@dhis2/app-service-data 3.17.0-beta.4 → 3.18.0-beta.1

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/README.md CHANGED
@@ -9,3 +9,107 @@ This library is intended for use with the [DHIS2 Application Platform](https://g
9
9
  This package is internal to `@dhis2/app-runtime` and generally should not be installed independently.
10
10
 
11
11
  See [the docs](https://developers.dhis2.org/docs/app-runtime/getting-started) for more.
12
+
13
+ ## TypeScript — typed query responses
14
+
15
+ `useDataQuery` infers the response type automatically from the query object. The default map covers all DHIS2 v43 metadata endpoints. Three patterns are supported:
16
+
17
+ ### 1. Default — v43 types, fully inferred
18
+
19
+ Pass the query `as const` so TypeScript can see the literal resource name and field list. No type annotation needed.
20
+
21
+ ```ts
22
+ import { useDataQuery } from '@dhis2/app-runtime'
23
+
24
+ const { data } = useDataQuery({
25
+ dataElements: {
26
+ resource: 'dataElements',
27
+ params: { fields: ['id', 'name', 'valueType'] as const },
28
+ },
29
+ } as const)
30
+
31
+ // data?.dataElements.pager.page → number
32
+ // data?.dataElements.dataElements[0].id → string | undefined
33
+ // data?.dataElements.dataElements[0].valueType → ValueType (enum, not just string)
34
+ ```
35
+
36
+ `as const` on the fields array is what allows TypeScript to narrow the element type. Without it the response type is broader but still valid. Without `as const` on the outer object, resource names are not captured as literals and field narrowing is skipped entirely.
37
+
38
+ ### 2. Targeting a specific DHIS2 API version
39
+
40
+ If the target instance runs an older DHIS2 version, build the result type from that version's paths. `paths` comes from the version-specific entry point; `DeriveResourceTypeMap` and `InferQueryResult` are version-agnostic and always come from `@dhis2/api-types/utils`:
41
+
42
+ ```ts
43
+ import { useDataQuery } from '@dhis2/app-runtime'
44
+ import type { paths } from '@dhis2/api-types/v42'
45
+ import type {
46
+ DeriveResourceTypeMap,
47
+ InferQueryResult,
48
+ } from '@dhis2/api-types/utils'
49
+
50
+ const query = {
51
+ dataElements: {
52
+ resource: 'dataElements',
53
+ params: { fields: ['id', 'name', 'valueType'] as const },
54
+ },
55
+ } as const
56
+
57
+ type Result = InferQueryResult<typeof query, DeriveResourceTypeMap<paths>>
58
+
59
+ const { data } = useDataQuery<typeof query, Result>(query)
60
+ // data?.dataElements.dataElements[0].valueType → v42's ValueType
61
+ ```
62
+
63
+ `@dhis2/api-types/v40`, `/v41`, `/v42`, and `/v43` are all available.
64
+
65
+ ### 3. Overriding the inferred type
66
+
67
+ Pass an explicit result type as the second generic to opt out of inference entirely — useful for custom endpoints or when the inferred type needs to be shaped differently:
68
+
69
+ ```ts
70
+ import { useDataQuery } from '@dhis2/app-runtime'
71
+
72
+ type MyResult = {
73
+ dataElements: {
74
+ pager: {
75
+ page: number
76
+ pageCount: number
77
+ total: number
78
+ pageSize: number
79
+ }
80
+ dataElements: Array<{ id: string; name: string; valueType: string }>
81
+ }
82
+ }
83
+
84
+ const { data } = useDataQuery<typeof query, MyResult>(query)
85
+ // data?.dataElements.dataElements[0] → { id: string; name: string; valueType: string }
86
+ ```
87
+
88
+ ### Tracker resources
89
+
90
+ Tracker endpoints (`tracker/enrollments`, `tracker/trackedEntities`, etc.) resolve to `unknown` with the default map because the spec types their responses opaquely. Extend the map manually to cover them:
91
+
92
+ ```ts
93
+ import { useDataQuery } from '@dhis2/app-runtime'
94
+ import type { paths, TrackerEnrollment } from '@dhis2/api-types'
95
+ import type {
96
+ DeriveResourceTypeMap,
97
+ InferQueryResult,
98
+ } from '@dhis2/api-types/utils'
99
+
100
+ type TrackerMap = DeriveResourceTypeMap<paths> & {
101
+ 'tracker/enrollments': TrackerEnrollment
102
+ }
103
+
104
+ const query = {
105
+ enrollments: {
106
+ resource: 'tracker/enrollments',
107
+ params: { fields: ['enrollment', 'status'] as const },
108
+ },
109
+ } as const
110
+
111
+ type Result = InferQueryResult<typeof query, TrackerMap>
112
+
113
+ const { data } = useDataQuery<typeof query, Result>(query)
114
+ // data?.enrollments.enrollments[0].status → EnrollmentStatus
115
+ ```
@@ -9,6 +9,10 @@ var _react = require("react");
9
9
  var _mergeAndCompareVariables = require("./mergeAndCompareVariables");
10
10
  var _useDataEngine = require("./useDataEngine");
11
11
  var _useStaticInput = require("./useStaticInput");
12
+ // Pre-compute the default resource→item map once from the latest API version's paths type.
13
+ // Consumers targeting an older DHIS2 version can pass an explicit TResult built with
14
+ // InferQueryResult<typeof query, DeriveResourceTypeMap<v4xPaths>> as the second generic.
15
+
12
16
  const useDataQuery = (query, {
13
17
  onComplete: userOnSuccess,
14
18
  onError: userOnError,
@@ -3,6 +3,11 @@ import { useState, useRef, useCallback, useDebugValue } from 'react';
3
3
  import { mergeAndCompareVariables } from './mergeAndCompareVariables';
4
4
  import { useDataEngine } from './useDataEngine';
5
5
  import { useStaticInput } from './useStaticInput';
6
+
7
+ // Pre-compute the default resource→item map once from the latest API version's paths type.
8
+ // Consumers targeting an older DHIS2 version can pass an explicit TResult built with
9
+ // InferQueryResult<typeof query, DeriveResourceTypeMap<v4xPaths>> as the second generic.
10
+
6
11
  export const useDataQuery = (query, {
7
12
  onComplete: userOnSuccess,
8
13
  onError: userOnError,
@@ -1,3 +1,7 @@
1
- import type { Query, QueryOptions, QueryResult } from '@dhis2/data-engine';
1
+ import type { paths } from '@dhis2/api-types';
2
+ import type { DeriveResourceTypeMap, InferQueryResult } from '@dhis2/api-types/utils';
3
+ import type { Query, QueryOptions } from '@dhis2/data-engine';
2
4
  import type { QueryRenderInput } from '../../types';
3
- export declare const useDataQuery: <TQueryResult = QueryResult>(query: Query, { onComplete: userOnSuccess, onError: userOnError, variables: initialVariables, lazy: initialLazy, }?: QueryOptions<TQueryResult>) => QueryRenderInput<TQueryResult>;
5
+ type DefaultMap = DeriveResourceTypeMap<paths>;
6
+ export declare const useDataQuery: <Q extends Query, TResult = InferQueryResult<Q, DefaultMap>>(query: Q, { onComplete: userOnSuccess, onError: userOnError, variables: initialVariables, lazy: initialLazy, }?: QueryOptions<TResult>) => QueryRenderInput<TResult>;
7
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhis2/app-service-data",
3
- "version": "3.17.0-beta.4",
3
+ "version": "3.18.0-beta.1",
4
4
  "main": "./build/cjs/index.js",
5
5
  "module": "./build/es/index.js",
6
6
  "types": "./build/types/index.d.ts",
@@ -33,12 +33,13 @@
33
33
  "coverage": "yarn test --coverage"
34
34
  },
35
35
  "dependencies": {
36
+ "@dhis2/api-types": "^43.0.0-beta.a48b417",
36
37
  "@tanstack/react-query": "^4.36.1",
37
38
  "prop-types": "^15.7.2"
38
39
  },
39
40
  "peerDependencies": {
40
- "@dhis2/app-service-config": "3.17.0-beta.4",
41
- "@dhis2/data-engine": "3.17.0-beta.4",
41
+ "@dhis2/app-service-config": "3.18.0-beta.1",
42
+ "@dhis2/data-engine": "3.18.0-beta.1",
42
43
  "react": "^16.8.6 || ^18",
43
44
  "react-dom": "^16.8.6 || ^18"
44
45
  }