@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.
Files changed (180) hide show
  1. package/build/cjs/__tests__/integration.test.js +10 -16
  2. package/build/cjs/__tests__/mutations.test.js +5 -8
  3. package/build/cjs/index.js +16 -44
  4. package/build/cjs/react/components/CustomDataProvider.js +9 -11
  5. package/build/cjs/react/components/DataMutation.js +7 -8
  6. package/build/cjs/react/components/DataProvider.js +3 -4
  7. package/build/cjs/react/components/DataProvider.test.js +3 -4
  8. package/build/cjs/react/components/DataQuery.js +8 -9
  9. package/build/cjs/react/components/index.js +33 -0
  10. package/build/cjs/react/context/DataContext.js +2 -2
  11. package/build/cjs/react/context/defaultDataContext.js +13 -0
  12. package/build/cjs/react/context/{defaultContext.test.js → defaultDataContext.test.js} +3 -3
  13. package/build/cjs/react/hooks/index.js +26 -0
  14. package/build/cjs/react/hooks/useDataMutation.js +6 -7
  15. package/build/cjs/react/hooks/useDataMutation.test.js +44 -71
  16. package/build/cjs/react/hooks/useDataQuery.js +10 -14
  17. package/build/cjs/react/hooks/useDataQuery.test.js +172 -265
  18. package/build/cjs/react/hooks/useQueryExecutor.js +11 -13
  19. package/build/cjs/react/hooks/useQueryExecutor.test.js +12 -16
  20. package/build/cjs/react/hooks/useStaticInput.js +4 -5
  21. package/build/cjs/react/hooks/useStaticInput.test.js +24 -39
  22. package/build/cjs/react/index.js +22 -77
  23. package/build/es/__tests__/integration.test.js +10 -16
  24. package/build/es/__tests__/mutations.test.js +5 -8
  25. package/build/es/index.js +2 -3
  26. package/build/es/react/components/CustomDataProvider.js +7 -9
  27. package/build/es/react/components/DataMutation.js +7 -8
  28. package/build/es/react/components/DataProvider.js +1 -2
  29. package/build/es/react/components/DataProvider.test.js +1 -2
  30. package/build/es/react/components/DataQuery.js +8 -9
  31. package/build/es/react/components/index.js +4 -0
  32. package/build/es/react/context/DataContext.js +2 -2
  33. package/build/es/react/context/{defaultContext.js → defaultDataContext.js} +2 -3
  34. package/build/es/react/context/{defaultContext.test.js → defaultDataContext.test.js} +3 -3
  35. package/build/es/react/hooks/index.js +3 -0
  36. package/build/es/react/hooks/useDataMutation.js +6 -7
  37. package/build/es/react/hooks/useDataMutation.test.js +44 -71
  38. package/build/es/react/hooks/useDataQuery.js +10 -14
  39. package/build/es/react/hooks/useDataQuery.test.js +172 -265
  40. package/build/es/react/hooks/useQueryExecutor.js +10 -12
  41. package/build/es/react/hooks/useQueryExecutor.test.js +12 -16
  42. package/build/es/react/hooks/useStaticInput.js +4 -5
  43. package/build/es/react/hooks/useStaticInput.test.js +24 -39
  44. package/build/es/react/index.js +3 -11
  45. package/build/types/index.d.ts +2 -3
  46. package/build/types/react/components/CustomDataProvider.d.ts +1 -1
  47. package/build/types/react/components/DataMutation.d.ts +1 -1
  48. package/build/types/react/components/DataQuery.d.ts +1 -1
  49. package/build/types/react/components/index.d.ts +4 -0
  50. package/build/types/react/context/defaultDataContext.d.ts +4 -0
  51. package/build/types/react/hooks/index.d.ts +3 -0
  52. package/build/types/react/hooks/mergeAndCompareVariables.d.ts +1 -1
  53. package/build/types/react/hooks/useDataEngine.d.ts +1 -1
  54. package/build/types/react/hooks/useDataMutation.d.ts +1 -1
  55. package/build/types/react/hooks/useDataQuery.d.ts +1 -1
  56. package/build/types/react/index.d.ts +2 -11
  57. package/build/types/types.d.ts +2 -7
  58. package/package.json +4 -3
  59. package/build/cjs/engine/DataEngine.js +0 -73
  60. package/build/cjs/engine/DataEngine.test.js +0 -156
  61. package/build/cjs/engine/helpers/getMutationFetchType.js +0 -8
  62. package/build/cjs/engine/helpers/getMutationFetchType.test.js +0 -39
  63. package/build/cjs/engine/helpers/resolveDynamicQuery.js +0 -21
  64. package/build/cjs/engine/helpers/resolveDynamicQuery.test.js +0 -63
  65. package/build/cjs/engine/helpers/validate.js +0 -62
  66. package/build/cjs/engine/helpers/validate.test.js +0 -206
  67. package/build/cjs/engine/index.js +0 -104
  68. package/build/cjs/engine/types/DataEngineLink.js +0 -1
  69. package/build/cjs/engine/types/ExecuteOptions.js +0 -1
  70. package/build/cjs/engine/types/FetchError.js +0 -24
  71. package/build/cjs/engine/types/FetchError.test.js +0 -14
  72. package/build/cjs/engine/types/InvalidQueryError.js +0 -18
  73. package/build/cjs/engine/types/JsonValue.js +0 -1
  74. package/build/cjs/engine/types/Mutation.js +0 -1
  75. package/build/cjs/engine/types/PossiblyDynamic.js +0 -1
  76. package/build/cjs/engine/types/Query.js +0 -1
  77. package/build/cjs/engine/types/QueryParameters.js +0 -1
  78. package/build/cjs/links/CustomDataLink.js +0 -51
  79. package/build/cjs/links/CustomDataLink.test.js +0 -73
  80. package/build/cjs/links/ErrorLink.js +0 -20
  81. package/build/cjs/links/RestAPILink/fetchData.js +0 -80
  82. package/build/cjs/links/RestAPILink/fetchData.test.js +0 -132
  83. package/build/cjs/links/RestAPILink/metadataResources.js +0 -22
  84. package/build/cjs/links/RestAPILink/path.js +0 -14
  85. package/build/cjs/links/RestAPILink/path.test.js +0 -16
  86. package/build/cjs/links/RestAPILink/queryToRequestOptions/multipartFormDataMatchers.js +0 -58
  87. package/build/cjs/links/RestAPILink/queryToRequestOptions/multipartFormDataMatchers.test.js +0 -73
  88. package/build/cjs/links/RestAPILink/queryToRequestOptions/requestContentType.js +0 -80
  89. package/build/cjs/links/RestAPILink/queryToRequestOptions/requestContentType.test.js +0 -120
  90. package/build/cjs/links/RestAPILink/queryToRequestOptions/textPlainMatchers.js +0 -170
  91. package/build/cjs/links/RestAPILink/queryToRequestOptions/textPlainMatchers.test.js +0 -246
  92. package/build/cjs/links/RestAPILink/queryToRequestOptions/xWwwFormUrlencodedMatchers.js +0 -14
  93. package/build/cjs/links/RestAPILink/queryToRequestOptions/xWwwFormUrlencodedMatchers.test.js +0 -20
  94. package/build/cjs/links/RestAPILink/queryToRequestOptions.js +0 -34
  95. package/build/cjs/links/RestAPILink/queryToRequestOptions.test.js +0 -107
  96. package/build/cjs/links/RestAPILink/queryToResourcePath.js +0 -82
  97. package/build/cjs/links/RestAPILink/queryToResourcePath.test.js +0 -173
  98. package/build/cjs/links/RestAPILink/validateQuery.js +0 -59
  99. package/build/cjs/links/RestAPILink/validateQuery.test.js +0 -209
  100. package/build/cjs/links/RestAPILink.js +0 -33
  101. package/build/cjs/links/RestAPILink.test.js +0 -21
  102. package/build/cjs/links/index.js +0 -38
  103. package/build/cjs/locales/en/translations.json +0 -3
  104. package/build/cjs/locales/index.js +0 -21
  105. package/build/cjs/react/context/defaultContext.js +0 -14
  106. package/build/es/engine/DataEngine.js +0 -66
  107. package/build/es/engine/DataEngine.test.js +0 -154
  108. package/build/es/engine/helpers/getMutationFetchType.js +0 -1
  109. package/build/es/engine/helpers/getMutationFetchType.test.js +0 -37
  110. package/build/es/engine/helpers/resolveDynamicQuery.js +0 -14
  111. package/build/es/engine/helpers/resolveDynamicQuery.test.js +0 -61
  112. package/build/es/engine/helpers/validate.js +0 -53
  113. package/build/es/engine/helpers/validate.test.js +0 -204
  114. package/build/es/engine/index.js +0 -10
  115. package/build/es/engine/types/DataEngineLink.js +0 -1
  116. package/build/es/engine/types/ExecuteOptions.js +0 -1
  117. package/build/es/engine/types/FetchError.js +0 -17
  118. package/build/es/engine/types/FetchError.test.js +0 -12
  119. package/build/es/engine/types/InvalidQueryError.js +0 -11
  120. package/build/es/engine/types/JsonValue.js +0 -1
  121. package/build/es/engine/types/Mutation.js +0 -1
  122. package/build/es/engine/types/PossiblyDynamic.js +0 -1
  123. package/build/es/engine/types/Query.js +0 -1
  124. package/build/es/engine/types/QueryParameters.js +0 -1
  125. package/build/es/links/CustomDataLink.js +0 -44
  126. package/build/es/links/CustomDataLink.test.js +0 -71
  127. package/build/es/links/ErrorLink.js +0 -13
  128. package/build/es/links/RestAPILink/fetchData.js +0 -71
  129. package/build/es/links/RestAPILink/fetchData.test.js +0 -130
  130. package/build/es/links/RestAPILink/metadataResources.js +0 -16
  131. package/build/es/links/RestAPILink/path.js +0 -7
  132. package/build/es/links/RestAPILink/path.test.js +0 -14
  133. package/build/es/links/RestAPILink/queryToRequestOptions/multipartFormDataMatchers.js +0 -47
  134. package/build/es/links/RestAPILink/queryToRequestOptions/multipartFormDataMatchers.test.js +0 -71
  135. package/build/es/links/RestAPILink/queryToRequestOptions/requestContentType.js +0 -70
  136. package/build/es/links/RestAPILink/queryToRequestOptions/requestContentType.test.js +0 -118
  137. package/build/es/links/RestAPILink/queryToRequestOptions/textPlainMatchers.js +0 -151
  138. package/build/es/links/RestAPILink/queryToRequestOptions/textPlainMatchers.test.js +0 -244
  139. package/build/es/links/RestAPILink/queryToRequestOptions/xWwwFormUrlencodedMatchers.js +0 -7
  140. package/build/es/links/RestAPILink/queryToRequestOptions/xWwwFormUrlencodedMatchers.test.js +0 -18
  141. package/build/es/links/RestAPILink/queryToRequestOptions.js +0 -27
  142. package/build/es/links/RestAPILink/queryToRequestOptions.test.js +0 -105
  143. package/build/es/links/RestAPILink/queryToResourcePath.js +0 -75
  144. package/build/es/links/RestAPILink/queryToResourcePath.test.js +0 -171
  145. package/build/es/links/RestAPILink/validateQuery.js +0 -52
  146. package/build/es/links/RestAPILink/validateQuery.test.js +0 -207
  147. package/build/es/links/RestAPILink.js +0 -26
  148. package/build/es/links/RestAPILink.test.js +0 -19
  149. package/build/es/links/index.js +0 -4
  150. package/build/es/locales/en/translations.json +0 -3
  151. package/build/es/locales/index.js +0 -13
  152. package/build/types/engine/DataEngine.d.ts +0 -13
  153. package/build/types/engine/helpers/getMutationFetchType.d.ts +0 -3
  154. package/build/types/engine/helpers/resolveDynamicQuery.d.ts +0 -2
  155. package/build/types/engine/helpers/validate.d.ts +0 -4
  156. package/build/types/engine/index.d.ts +0 -9
  157. package/build/types/engine/types/DataEngineLink.d.ts +0 -9
  158. package/build/types/engine/types/ExecuteOptions.d.ts +0 -9
  159. package/build/types/engine/types/FetchError.d.ts +0 -19
  160. package/build/types/engine/types/InvalidQueryError.d.ts +0 -5
  161. package/build/types/engine/types/JsonValue.d.ts +0 -6
  162. package/build/types/engine/types/Mutation.d.ts +0 -29
  163. package/build/types/engine/types/PossiblyDynamic.d.ts +0 -1
  164. package/build/types/engine/types/Query.d.ts +0 -24
  165. package/build/types/engine/types/QueryParameters.d.ts +0 -12
  166. package/build/types/links/CustomDataLink.d.ts +0 -17
  167. package/build/types/links/ErrorLink.d.ts +0 -6
  168. package/build/types/links/RestAPILink/fetchData.d.ts +0 -4
  169. package/build/types/links/RestAPILink/metadataResources.d.ts +0 -2
  170. package/build/types/links/RestAPILink/path.d.ts +0 -1
  171. package/build/types/links/RestAPILink/queryToRequestOptions/multipartFormDataMatchers.d.ts +0 -6
  172. package/build/types/links/RestAPILink/queryToRequestOptions/requestContentType.d.ts +0 -6
  173. package/build/types/links/RestAPILink/queryToRequestOptions/textPlainMatchers.d.ts +0 -14
  174. package/build/types/links/RestAPILink/queryToRequestOptions/xWwwFormUrlencodedMatchers.d.ts +0 -2
  175. package/build/types/links/RestAPILink/queryToRequestOptions.d.ts +0 -2
  176. package/build/types/links/RestAPILink/queryToResourcePath.d.ts +0 -3
  177. package/build/types/links/RestAPILink/validateQuery.d.ts +0 -2
  178. package/build/types/links/RestAPILink.d.ts +0 -10
  179. package/build/types/links/index.d.ts +0 -3
  180. package/build/types/react/context/defaultContext.d.ts +0 -4
@@ -1,80 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.fetchData = fetchData;
7
- exports.parseStatus = exports.parseContentType = void 0;
8
- var _engine = require("../../engine");
9
- const parseContentType = contentType => contentType ? contentType.split(';')[0].trim().toLowerCase() : '';
10
- exports.parseContentType = parseContentType;
11
- const parseStatus = async response => {
12
- const accessError = response.status === 401 || response.status === 403 || response.status === 409;
13
- if (accessError) {
14
- let message;
15
- let details = {};
16
- try {
17
- details = await response.json();
18
- message = details.message;
19
- } catch (e) {
20
- // Do nothing
21
- }
22
-
23
- // Set a message in case of invalid json, or json without 'message' property
24
- if (!message) {
25
- message = response.status === 401 ? 'Unauthorized' : 'Forbidden';
26
- }
27
- throw new _engine.FetchError({
28
- type: 'access',
29
- message,
30
- details
31
- });
32
- }
33
- if (response.status < 200 || response.status >= 400) {
34
- const message = `An unknown error occurred - ${response.statusText} (${response.status})`;
35
- let details = {};
36
- try {
37
- details = await response.json();
38
- } catch (e) {
39
- // We can leave details as is if parsing fails
40
- }
41
- throw new _engine.FetchError({
42
- type: 'unknown',
43
- message,
44
- details
45
- });
46
- }
47
- return response;
48
- };
49
- exports.parseStatus = parseStatus;
50
- function fetchData(url) {
51
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
52
- return fetch(url, {
53
- ...options,
54
- credentials: 'include',
55
- headers: {
56
- 'X-Requested-With': 'XMLHttpRequest',
57
- Accept: 'application/json',
58
- ...options.headers
59
- }
60
- }).catch(err => {
61
- throw new _engine.FetchError({
62
- type: 'network',
63
- message: 'An unknown network error occurred',
64
- details: err
65
- });
66
- }).then(parseStatus).then(async response => {
67
- const contentType = parseContentType(response.headers.get('Content-Type'));
68
-
69
- // 'application/json'
70
- if (contentType === 'application/json') {
71
- return await response.json(); // Will throw if invalid JSON!
72
- }
73
-
74
- // 'text/*'
75
- if (/^text\/[a-z0-9.-]+$/.test(contentType)) {
76
- return await response.text();
77
- }
78
- return await response.blob();
79
- });
80
- }
@@ -1,132 +0,0 @@
1
- "use strict";
2
-
3
- var _engine = require("../../engine");
4
- var _fetchData = require("./fetchData");
5
- describe('networkFetch', () => {
6
- describe('parseContentType', () => {
7
- it('should pass through simple content-types', () => {
8
- expect((0, _fetchData.parseContentType)('text/html')).toBe('text/html');
9
- expect((0, _fetchData.parseContentType)('text/plain')).toBe('text/plain');
10
- expect((0, _fetchData.parseContentType)('application/vnd.api+json')).toBe('application/vnd.api+json');
11
- });
12
- it('should strip parameters', () => {
13
- expect((0, _fetchData.parseContentType)('text/svg+xml;charset=utf-8')).toBe('text/svg+xml');
14
- expect((0, _fetchData.parseContentType)('text/html;testing123')).toBe('text/html');
15
- });
16
- it('should trim type', () => {
17
- expect((0, _fetchData.parseContentType)(' text/xml ')).toBe('text/xml');
18
- expect((0, _fetchData.parseContentType)(' application/json ; charset = utf-8')).toBe('application/json');
19
- });
20
- it('should convert to lower-case', () => {
21
- expect((0, _fetchData.parseContentType)(' Text/XML ')).toBe('text/xml');
22
- expect((0, _fetchData.parseContentType)('application/JSON ; charset = UTF-8')).toBe('application/json');
23
- });
24
- it('should correctly parse application/json with charset param', () => {
25
- expect((0, _fetchData.parseContentType)('application/json;charset=UTF-8')).toBe('application/json');
26
- });
27
- });
28
- describe('parseStatus', () => {
29
- it('should pass through the response for a success status code', async () => {
30
- const response = {
31
- status: 200
32
- };
33
- await expect((0, _fetchData.parseStatus)(response)).resolves.toBe(response);
34
- });
35
- it('should throw an access error for 401, 403 and 409 errors', async () => {
36
- const response401 = {
37
- status: 401,
38
- json: async () => {
39
- throw new Error();
40
- }
41
- };
42
- const response403 = {
43
- status: 403,
44
- json: async () => {
45
- throw new Error();
46
- }
47
- };
48
- const response409 = {
49
- status: 409,
50
- json: async () => ({
51
- message: 'An error occurred'
52
- })
53
- };
54
- expect((0, _fetchData.parseStatus)(response401)).rejects.toMatchObject({
55
- type: 'access',
56
- message: 'Unauthorized',
57
- details: {}
58
- });
59
- expect((0, _fetchData.parseStatus)(response403)).rejects.toMatchObject({
60
- type: 'access',
61
- message: 'Forbidden',
62
- details: {}
63
- });
64
- expect((0, _fetchData.parseStatus)(response409)).rejects.toMatchObject({
65
- type: 'access',
66
- message: 'An error occurred',
67
- details: {
68
- message: 'An error occurred'
69
- }
70
- });
71
- });
72
- it('should throw if an unknown error occurs', () => {
73
- const response = {
74
- status: 500,
75
- statusText: 'Failed',
76
- json: async () => ({
77
- message: 'An error occurred'
78
- })
79
- };
80
- expect((0, _fetchData.parseStatus)(response)).rejects.toMatchObject({
81
- type: 'unknown',
82
- message: `An unknown error occurred - Failed (500)`,
83
- details: {
84
- message: 'An error occurred'
85
- }
86
- });
87
- });
88
- });
89
- describe('fetchData', () => {
90
- const headers = {
91
- 'Content-Type': type => type === 'json' ? 'application/json' : type === 'text' ? 'text/plain' : 'some/other-content-type'
92
- };
93
- const mockFetch = jest.fn(async url => ({
94
- status: 200,
95
- headers: {
96
- get: name => headers[name] && headers[name](url)
97
- },
98
- json: async () => ({
99
- foo: 'bar'
100
- }),
101
- text: async () => 'foobar',
102
- blob: async () => 'blob of foobar'
103
- }));
104
- beforeEach(() => {
105
- jest.clearAllMocks();
106
- });
107
- it('Should correctly parse a successful JSON response', () => {
108
- ;
109
- global.fetch = mockFetch;
110
- expect((0, _fetchData.fetchData)('json', {})).resolves.toMatchObject({
111
- foo: 'bar'
112
- });
113
- });
114
- it('Should correctly parse a successful TEXT response', () => {
115
- ;
116
- global.fetch = mockFetch;
117
- expect((0, _fetchData.fetchData)('text')).resolves.toBe('foobar');
118
- });
119
- it('Should correctly parse a successful BLOB response', () => {
120
- ;
121
- global.fetch = mockFetch;
122
- expect((0, _fetchData.fetchData)('something else')).resolves.toBe('blob of foobar');
123
- });
124
- it('Should throw a FetchError if fetch fails', () => {
125
- ;
126
- global.fetch = jest.fn(async () => {
127
- throw new Error();
128
- });
129
- expect((0, _fetchData.fetchData)('failure', {})).rejects.toBeInstanceOf(_engine.FetchError);
130
- });
131
- });
132
- });
@@ -1,22 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.normativeMetadataResources = exports.nonNormativeMetadataResources = void 0;
7
- /*
8
- * These are metadata resources (from /api/resources) which are known to support paging.
9
- * They should all also support fields declarations. Only plural resource names are supported.
10
- * This list may be incomplete, and may require updating for new DHIS2 major versions
11
- */
12
-
13
- const normativeMetadataResources = exports.normativeMetadataResources = ['programDataElements', 'indicatorTypes', 'programs', 'optionGroups', 'programRuleVariables', 'reports', 'users', 'constants', 'externalMapLayers', 'analyticsTableHooks', 'pushAnalysis', 'oAuth2Clients', 'validationRules', 'reportTables', 'userGroups', 'sqlViews', 'sections', 'validationNotificationTemplates', 'optionGroupSets', 'organisationUnitGroupSets', 'trackedEntityAttributes', 'dashboardItems', 'categoryCombos', 'programSections', 'trackedEntityTypes', 'dataSetNotificationTemplates', 'maps', 'dataApprovalWorkflows', 'programStages', 'categoryOptionGroups', 'relationshipTypes', 'validationRuleGroups', 'predictors', 'dataSets', 'options', 'organisationUnitLevels', 'dataEntryForms', 'predictorGroups', 'dataElementGroupSets', 'programIndicatorGroups', 'dataApprovalLevels', 'organisationUnits', 'programIndicators', 'dataElements', 'mapViews', 'categories', 'categoryOptionCombos', 'documents', 'indicators', 'optionSets', 'interpretations', 'programRuleActions', 'dataElementGroups', 'attributes', 'validationResults', 'categoryOptions', 'indicatorGroupSets', 'messageConversations', 'dashboards', 'programNotificationTemplates', 'programStageSections', 'legendSets', 'organisationUnitGroups', 'visualizations', 'indicatorGroups', 'programTrackedEntityAttributeGroups', 'programRules', 'categoryOptionGroupSets', 'userRoles', 'eventFilters', 'eventReports', 'eventCharts', 'smsCommands', 'jobConfigurations', 'minMaxDataElements', 'charts', 'dataElementOperands',
14
- // These exist and appear to accept field declarations, but have abnormal behavior when it comes to viewing collections and paging results
15
- 'trackedEntityInstance', 'relationships'];
16
-
17
- // Including non-normative resources listed under /api/resources for future follow-up
18
- const nonNormativeMetadataResources = exports.nonNormativeMetadataResources = ['trackedEntityAttributeValues', 'programInstances', 'expressions', 'programStageInstances', 'externalFileResources', 'icons', 'fileResources', 'metadataVersions', 'dataStores',
19
- // This doesn't exist, but is listed as the plural of 'dataStore' in /api/resources
20
-
21
- // Known but missing from /api/resources
22
- 'userDataStore', 'apps'];
@@ -1,14 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.joinPath = void 0;
7
- const joinPath = function () {
8
- for (var _len = arguments.length, parts = new Array(_len), _key = 0; _key < _len; _key++) {
9
- parts[_key] = arguments[_key];
10
- }
11
- const realParts = parts.filter(part => !!part);
12
- return realParts.map(part => part.replace(/^\/+|\/+$/g, '')).join('/');
13
- };
14
- exports.joinPath = joinPath;
@@ -1,16 +0,0 @@
1
- "use strict";
2
-
3
- var _path = require("./path");
4
- describe('Utils', () => {
5
- describe('pathJoin', () => {
6
- it('Should strip all leading and trailing slashes', () => {
7
- expect((0, _path.joinPath)('///test//')).toBe('test');
8
- });
9
- it('Should join path segments with slashes', () => {
10
- expect((0, _path.joinPath)('a', 'b', 'c', 'd')).toBe('a/b/c/d');
11
- });
12
- it('Should only include singular joining slashes', () => {
13
- expect((0, _path.joinPath)('//a/', 'b//', '///c////', '/d')).toBe('a/b/c/d');
14
- });
15
- });
16
- });
@@ -1,58 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.isStaticContentUpload = exports.isMessageConversationAttachment = exports.isFileResourceUpload = exports.isDataValue = exports.isAppInstall = void 0;
7
- /*
8
- * Requests that expect a "multipart/form-data" Content-Type have been collected by scanning
9
- * the developer documentation:
10
- * https://docs.dhis2.org/master/en/developer/html/dhis2_developer_manual_full.html
11
- */
12
-
13
- // Post to 'dataValues' (send/update a data value; endpoint doesn't support JSON)
14
- // For file-uploads too
15
- const isDataValue = (type, _ref) => {
16
- let {
17
- resource
18
- } = _ref;
19
- return type === 'create' && (resource === 'dataValues' || resource === 'dataValues/file');
20
- };
21
-
22
- // POST to 'fileResources' (upload a file resource)
23
- exports.isDataValue = isDataValue;
24
- const isFileResourceUpload = (type, _ref2) => {
25
- let {
26
- resource
27
- } = _ref2;
28
- return type === 'create' && resource === 'fileResources';
29
- };
30
-
31
- // POST to 'messageConversations/attachments' (upload a message conversation attachment)
32
- exports.isFileResourceUpload = isFileResourceUpload;
33
- const isMessageConversationAttachment = (type, _ref3) => {
34
- let {
35
- resource
36
- } = _ref3;
37
- return type === 'create' && resource === 'messageConversations/attachments';
38
- };
39
-
40
- // POST to `staticContent/${key}` (upload staticContent: logo_banner | logo_front)
41
- exports.isMessageConversationAttachment = isMessageConversationAttachment;
42
- const isStaticContentUpload = (type, _ref4) => {
43
- let {
44
- resource
45
- } = _ref4;
46
- const pattern = /^staticContent\/(?:logo_banner|logo_front)$/;
47
- return type === 'create' && pattern.test(resource);
48
- };
49
-
50
- // POST to 'apps' (install an app)
51
- exports.isStaticContentUpload = isStaticContentUpload;
52
- const isAppInstall = (type, _ref5) => {
53
- let {
54
- resource
55
- } = _ref5;
56
- return type === 'create' && resource === 'apps';
57
- };
58
- exports.isAppInstall = isAppInstall;
@@ -1,73 +0,0 @@
1
- "use strict";
2
-
3
- var _multipartFormDataMatchers = require("./multipartFormDataMatchers");
4
- describe('isDataValue', () => {
5
- it('returns true for a POST to "dataValues"', () => {
6
- expect((0, _multipartFormDataMatchers.isDataValue)('create', {
7
- resource: 'dataValues'
8
- })).toBe(true);
9
- });
10
- it('returns true for a POST to "dataValues/file"', () => {
11
- expect((0, _multipartFormDataMatchers.isDataValue)('create', {
12
- resource: 'dataValues/file'
13
- })).toBe(true);
14
- });
15
- it('returns false for a POST to a different resource', () => {
16
- expect((0, _multipartFormDataMatchers.isDataValue)('create', {
17
- resource: 'somethingElse'
18
- })).toBe(false);
19
- });
20
- });
21
- describe('isFileResourceUpload', () => {
22
- it('returns true for a POST to "fileResources"', () => {
23
- expect((0, _multipartFormDataMatchers.isFileResourceUpload)('create', {
24
- resource: 'fileResources'
25
- })).toBe(true);
26
- });
27
- it('retuns false for a POST to a different resource', () => {
28
- expect((0, _multipartFormDataMatchers.isFileResourceUpload)('create', {
29
- resource: 'notFileResources'
30
- })).toBe(false);
31
- });
32
- });
33
- describe('isMessageConversationAttachment', () => {
34
- it('returns true for a POST to "messageConversations/attachments"', () => {
35
- expect((0, _multipartFormDataMatchers.isMessageConversationAttachment)('create', {
36
- resource: 'messageConversations/attachments'
37
- })).toBe(true);
38
- });
39
- it('retuns false for a POST to a different resource', () => {
40
- expect((0, _multipartFormDataMatchers.isMessageConversationAttachment)('create', {
41
- resource: 'messageConversations/notAttachments'
42
- })).toBe(false);
43
- });
44
- });
45
- describe('isStaticContentUpload', () => {
46
- it('returns true for a POST to "staticContent/logo_banner"', () => {
47
- expect((0, _multipartFormDataMatchers.isStaticContentUpload)('create', {
48
- resource: 'staticContent/logo_banner'
49
- })).toBe(true);
50
- });
51
- it('returns true for a POST to "staticContent/logo_front"', () => {
52
- expect((0, _multipartFormDataMatchers.isStaticContentUpload)('create', {
53
- resource: 'staticContent/logo_front'
54
- })).toBe(true);
55
- });
56
- it('returns false for a request to a different resource', () => {
57
- expect((0, _multipartFormDataMatchers.isStaticContentUpload)('create', {
58
- resource: 'staticContent/no_logo'
59
- })).toBe(false);
60
- });
61
- });
62
- describe('isAppInstall', () => {
63
- it('returns true for a POST to "apps"', () => {
64
- expect((0, _multipartFormDataMatchers.isAppInstall)('create', {
65
- resource: 'apps'
66
- })).toBe(true);
67
- });
68
- it('retuns false for a POST to a different resource', () => {
69
- expect((0, _multipartFormDataMatchers.isAppInstall)('create', {
70
- resource: 'notApps'
71
- })).toBe(false);
72
- });
73
- });
@@ -1,80 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.requestHeadersForContentType = exports.requestContentType = exports.requestBodyForContentType = void 0;
7
- var multipartFormDataMatchers = _interopRequireWildcard(require("./multipartFormDataMatchers"));
8
- var textPlainMatchers = _interopRequireWildcard(require("./textPlainMatchers"));
9
- var xWwwFormUrlencodedMatchers = _interopRequireWildcard(require("./xWwwFormUrlencodedMatchers"));
10
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
11
- const resourceExpectsTextPlain = (type, query) => Object.values(textPlainMatchers).some(textPlainMatcher => textPlainMatcher(type, query));
12
- const resourceExpectsMultipartFormData = (type, query) => Object.values(multipartFormDataMatchers).some(multipartFormDataMatcher => multipartFormDataMatcher(type, query));
13
- const resourceExpectsXWwwFormUrlencoded = (type, query) => Object.values(xWwwFormUrlencodedMatchers).some(xWwwFormUrlencodedMatcher => xWwwFormUrlencodedMatcher(type, query));
14
- const convertData = (data, initialValue) => {
15
- const dataEntries = Object.entries(data);
16
- if (dataEntries.length === 0) {
17
- throw new Error(`Could not convert data to ${initialValue.constructor.name}: object does not have own enumerable string-keyed properties`);
18
- }
19
- return dataEntries.reduce((convertedData, _ref) => {
20
- let [key, value] = _ref;
21
- convertedData.append(key, value);
22
- return convertedData;
23
- }, initialValue);
24
- };
25
- const requestContentType = (type, query) => {
26
- if (!query.data) {
27
- return null;
28
- }
29
- if (type === 'json-patch') {
30
- return 'application/json-patch+json';
31
- }
32
- if (resourceExpectsTextPlain(type, query)) {
33
- return 'text/plain';
34
- }
35
- if (resourceExpectsMultipartFormData(type, query)) {
36
- return 'multipart/form-data';
37
- }
38
- if (resourceExpectsXWwwFormUrlencoded(type, query)) {
39
- return 'application/x-www-form-urlencoded';
40
- }
41
- return 'application/json';
42
- };
43
- exports.requestContentType = requestContentType;
44
- const requestHeadersForContentType = contentType => {
45
- /*
46
- * Explicitely setting Content-Type to 'multipart/form-data' produces
47
- * a "multipart boundary not found" error. By not setting a Content-Type
48
- * the browser will correctly set it for us and also apply multipart
49
- * boundaries if the request body is an instance of FormData
50
- * See https://stackoverflow.com/a/39281156/1143502
51
- */
52
- if (!contentType || contentType === 'multipart/form-data') {
53
- return undefined;
54
- }
55
- return {
56
- 'Content-Type': contentType
57
- };
58
- };
59
- exports.requestHeadersForContentType = requestHeadersForContentType;
60
- const requestBodyForContentType = (contentType, _ref2) => {
61
- let {
62
- data
63
- } = _ref2;
64
- if (typeof data === 'undefined') {
65
- return undefined;
66
- }
67
- if (contentType === 'application/json' || contentType === 'application/json-patch+json') {
68
- return JSON.stringify(data);
69
- }
70
- if (contentType === 'multipart/form-data') {
71
- return convertData(data, new FormData());
72
- }
73
- if (contentType === 'application/x-www-form-urlencoded') {
74
- return convertData(data, new URLSearchParams());
75
- }
76
-
77
- // 'text/plain'
78
- return data;
79
- };
80
- exports.requestBodyForContentType = requestBodyForContentType;
@@ -1,120 +0,0 @@
1
- "use strict";
2
-
3
- var _requestContentType = require("./requestContentType");
4
- describe('requestContentType', () => {
5
- it('returns "application/json" for a normal resource', () => {
6
- expect((0, _requestContentType.requestContentType)('create', {
7
- resource: 'test',
8
- data: 'test'
9
- })).toBe('application/json');
10
- });
11
- it('returns "application/json-patch+json" when the fetch type is "json-patch"', () => {
12
- expect((0, _requestContentType.requestContentType)('json-patch', {
13
- resource: 'test',
14
- data: 'test'
15
- })).toBe('application/json-patch+json');
16
- });
17
- it('returns "multipart/form-data" for a specific resource that expects it', () => {
18
- expect((0, _requestContentType.requestContentType)('create', {
19
- resource: 'fileResources',
20
- data: 'test'
21
- })).toBe('multipart/form-data');
22
- });
23
- it('returns "text/plain" for a specific resource that expects it', () => {
24
- expect((0, _requestContentType.requestContentType)('create', {
25
- resource: 'messageConversations/feedback',
26
- data: 'test'
27
- })).toBe('text/plain');
28
- });
29
- });
30
- describe('requestHeadersForContentType', () => {
31
- it('returns undefined if contentType is null', () => {
32
- expect((0, _requestContentType.requestHeadersForContentType)(null)).toBe(undefined);
33
- });
34
- it('returns undefined if contentType is "multipart/form-data"', () => {
35
- expect((0, _requestContentType.requestHeadersForContentType)('multipart/form-data')).toBe(undefined);
36
- });
37
- it('returns a headers object with the contentType for "application/json"', () => {
38
- expect((0, _requestContentType.requestHeadersForContentType)('application/json')).toEqual({
39
- 'Content-Type': 'application/json'
40
- });
41
- });
42
- it('returns a headers object with the contentType for "text/plain"', () => {
43
- expect((0, _requestContentType.requestHeadersForContentType)('text/plain')).toEqual({
44
- 'Content-Type': 'text/plain'
45
- });
46
- });
47
- });
48
- describe('requestBodyForContentType', () => {
49
- it('returns undefined if data is undefined', () => {
50
- expect((0, _requestContentType.requestBodyForContentType)('application/json', {
51
- resource: 'test'
52
- })).toBe(undefined);
53
- });
54
- it('JSON stringifies the data if contentType is "application/json"', () => {
55
- const dataIn = {
56
- a: 'AAAA',
57
- b: 1,
58
- c: true
59
- };
60
- const dataOut = JSON.stringify(dataIn);
61
- expect((0, _requestContentType.requestBodyForContentType)('application/json', {
62
- resource: 'test',
63
- data: dataIn
64
- })).toBe(dataOut);
65
- });
66
- it('converts to FormData if contentType is "multipart/form-data"', () => {
67
- const file = new File(['foo'], 'foo.txt', {
68
- type: 'text/plain'
69
- });
70
- const data = {
71
- a: 'AAA',
72
- file
73
- };
74
- const result = (0, _requestContentType.requestBodyForContentType)('multipart/form-data', {
75
- resource: 'test',
76
- data
77
- });
78
- expect(result instanceof FormData).toBe(true);
79
- expect(result.get('a')).toBe('AAA');
80
- expect(result.get('file')).toBe(file);
81
- });
82
- it('throws an error if contentType is "multipart/form-data" and data does have own string-keyd properties', () => {
83
- expect(() => {
84
- (0, _requestContentType.requestBodyForContentType)('multipart/form-data', {
85
- resource: 'test',
86
- data: new File(['foo'], 'foo.txt', {
87
- type: 'text/plain'
88
- })
89
- });
90
- }).toThrowErrorMatchingInlineSnapshot(`"Could not convert data to FormData: object does not have own enumerable string-keyed properties"`);
91
- });
92
- it('converts to URLSearchParams if contentType is "application/x-www-form-urlencoded"', () => {
93
- const data = {
94
- a: 'AAA'
95
- };
96
- const result = (0, _requestContentType.requestBodyForContentType)('application/x-www-form-urlencoded', {
97
- resource: 'test',
98
- data
99
- });
100
- expect(result instanceof URLSearchParams).toBe(true);
101
- expect(result.get('a')).toBe('AAA');
102
- });
103
- it('throws an error if contentType is "application/x-www-form-urlencoded" and data does have own string-keyd properties', () => {
104
- expect(() => {
105
- (0, _requestContentType.requestBodyForContentType)('application/x-www-form-urlencoded', {
106
- resource: 'test',
107
- data: new File(['foo'], 'foo.txt', {
108
- type: 'text/plain'
109
- })
110
- });
111
- }).toThrowErrorMatchingInlineSnapshot(`"Could not convert data to URLSearchParams: object does not have own enumerable string-keyed properties"`);
112
- });
113
- it('returns the data as received if contentType is "text/plain"', () => {
114
- const data = 'Something';
115
- expect((0, _requestContentType.requestBodyForContentType)('text/plain', {
116
- resource: 'messageConversations/feedback',
117
- data
118
- })).toBe(data);
119
- });
120
- });