Skip to content

dhis2: Implement http namespace, a generic request function, and remove all callbacks #1046

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 100 commits into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from 94 commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
bd72e80
feat: implement downloadNewRecord option when creating a resource
hunterachieng Mar 7, 2025
cde1ead
feat: add changeset
hunterachieng Mar 7, 2025
7fe8f07
feat: implement http namespace
hunterachieng Mar 10, 2025
1a422c0
feat: add changeset
hunterachieng Mar 10, 2025
d60a16b
fix: add tests and docs for create
hunterachieng Mar 11, 2025
be489ab
fix: change changeset from minor to major
hunterachieng Mar 11, 2025
5584b1f
fix: add test asserion
hunterachieng Mar 11, 2025
0bd6a99
fix: create function variables and logs
hunterachieng Mar 12, 2025
0009e40
fix create logs
hunterachieng Mar 12, 2025
11a8c01
fix odoo images
taylordowns2000 Mar 12, 2025
68eab3b
Merge branch 'main' into feature/1008-odoo-newRecord
josephjclark Mar 12, 2025
1710698
Merge pull request #1051 from OpenFn/fix-odoo-images
josephjclark Mar 12, 2025
aa496e2
version: [email protected]
josephjclark Mar 12, 2025
42f877f
Merge pull request #1042 from OpenFn/feature/1008-odoo-newRecord
hunterachieng Mar 12, 2025
64e0069
OpenMRS: support error maps (common: support errors:false) (#1056)
josephjclark Mar 14, 2025
9e92571
NHGH Varo adaptor (#1054)
decarteret Mar 19, 2025
4ff30f2
Fhir 4 typescript (#964)
josephjclark Mar 20, 2025
feeb955
Fix fhir4 docs (#1076)
josephjclark Mar 20, 2025
36a849c
update examples in AI adaptors
josephjclark Mar 20, 2025
d0373fe
release (#1078)
josephjclark Mar 20, 2025
03583c1
Releases: [email protected] redit @1.3.0 (#1082)
josephjclark Mar 20, 2025
6232a21
DIVOC adaptor
PiusKariuki Mar 21, 2025
513e55d
Changeset file
PiusKariuki Mar 21, 2025
2e22e67
typo
PiusKariuki Mar 21, 2025
4f7e857
Typo
PiusKariuki Mar 21, 2025
e5264d1
update template (#1086)
josephjclark Mar 21, 2025
e024a79
Fhir 4 deps (#1088)
josephjclark Mar 21, 2025
79d791f
package lock
josephjclark Mar 21, 2025
ce4f7a9
OpenBoxes adaptor
PiusKariuki Mar 24, 2025
9fdddbf
Edited the config schema
PiusKariuki Mar 24, 2025
715c01a
changeset file
PiusKariuki Mar 24, 2025
f06b3cf
remove example in README.md
PiusKariuki Mar 24, 2025
b9b969a
square logo
PiusKariuki Mar 24, 2025
a918505
down to 0.1.0
taylordowns2000 Mar 24, 2025
e1f000f
Merge pull request #1085 from OpenFn/divoc
taylordowns2000 Mar 24, 2025
5663815
new logo 225*225
PiusKariuki Mar 24, 2025
3ae83db
Transparent and right size logos
PiusKariuki Mar 24, 2025
414289b
Examples indentation
PiusKariuki Mar 24, 2025
014b0c8
Updates to CHANGELOG.md and deleted changest file
PiusKariuki Mar 24, 2025
baf684e
Merge pull request #1095 from OpenFn/openboxes
taylordowns2000 Mar 24, 2025
a629256
New Mpesa adaptor
PiusKariuki Mar 27, 2025
58559c6
Updated changelog file
PiusKariuki Mar 27, 2025
adb3c49
Config schema
PiusKariuki Mar 27, 2025
f017404
fallback baseUrl
PiusKariuki Mar 27, 2025
fdabddc
test update
PiusKariuki Mar 27, 2025
0359564
Body is not inclided in the response object
PiusKariuki Mar 27, 2025
33b267d
typos
PiusKariuki Mar 27, 2025
cc6b573
Added a logResponse
PiusKariuki Mar 27, 2025
8759e6a
Added logs for initating transactions and their responses
PiusKariuki Mar 27, 2025
b9a5713
Rework the requestOptions object
PiusKariuki Mar 27, 2025
262369f
Have the conditional early on before the `opts ` object
PiusKariuki Mar 27, 2025
c0153fb
Typos and guide text
PiusKariuki Mar 27, 2025
9155951
Log response is now in a .then
PiusKariuki Mar 28, 2025
b3a927f
Remove JSON.stringify
PiusKariuki Mar 28, 2025
82750f2
More detailed log on request
PiusKariuki Mar 28, 2025
69c7adb
Typo
PiusKariuki Mar 28, 2025
f3ab1ba
Update add-to-project.yml (#1104)
taylordowns2000 Mar 28, 2025
29a1c83
Merge branch 'epic/release-dhis2' of github.com:OpenFn/adaptors into …
hunterachieng Mar 31, 2025
7cd1d3e
feat: re-work http namespace file functions
hunterachieng Mar 31, 2025
1a24fb5
Merge branch 'epic/release-dhis2' of github.com:OpenFn/adaptors into …
hunterachieng Mar 31, 2025
587e783
primero: add generic http helpers (#1101)
hunterachieng Mar 31, 2025
c9c1e6f
comment removed
PiusKariuki Apr 2, 2025
83ea93c
Release: Salesforce 6.0 (#1090)
josephjclark Apr 2, 2025
1ca16f9
Merge pull request #1103 from OpenFn/mpesa
PiusKariuki Apr 2, 2025
3e4182a
http: add `POST` example to `request()` function (#1096)
hunterachieng Apr 4, 2025
f9b44d8
fix: make state docs private
hunterachieng Apr 4, 2025
f8dcae4
fix: switch from generic helper to http helper
hunterachieng Apr 4, 2025
6b79517
fix: switch from resourceType to path
hunterachieng Apr 4, 2025
ef16a4d
fix: reduce get examples
hunterachieng Apr 4, 2025
5e401a7
satusehat: export `util.uuid` from common (#1116)
hunterachieng Apr 4, 2025
826ca90
ast
josephjclark Apr 4, 2025
4bbcc29
template: add extra functions from common
josephjclark Apr 4, 2025
b96b775
release: [email protected]
hunterachieng Apr 10, 2025
a4f4e1b
Release: OpenMRS v5 (#1002)
josephjclark Apr 11, 2025
f9e3ef7
fix versions
josephjclark Apr 11, 2025
37cac8b
package lock
josephjclark Apr 11, 2025
36aa5b6
Msupply adaptor (#1131)
PiusKariuki Apr 11, 2025
755764b
transparency for pesapal
taylordowns2000 Apr 12, 2025
f6134a0
New senaite adaptor (#1135)
PiusKariuki Apr 14, 2025
300fe56
ast
josephjclark Apr 14, 2025
d2838c8
feat: implement support for `parseAs:'base64'`
hunterachieng Apr 15, 2025
b089c56
feat: add changeset
hunterachieng Apr 15, 2025
ed89459
Merge branch 'main' of github.com:OpenFn/adaptors into feature/1122-c…
hunterachieng Apr 15, 2025
78fe59f
fix: fix tests for common
hunterachieng Apr 15, 2025
1ee7f20
adaptor: automate release dates to adaptor changelogs (#1125)
hunterachieng Apr 15, 2025
1941f7c
fix: remove await in body
hunterachieng Apr 15, 2025
878a382
Merge branch 'main' of github.com:OpenFn/adaptors into feature/1122-c…
hunterachieng Apr 16, 2025
24d5dc3
bump versions
hunterachieng Apr 16, 2025
5586849
Merge pull request #1137 from OpenFn/feature/1122-common-images
hunterachieng Apr 16, 2025
fb42f41
New adaptor: Google Drive (#1098) (#1119)
josephjclark Apr 17, 2025
8fb0f57
Merge branch 'main' of github.com:OpenFn/adaptors into feature/978-dh…
hunterachieng Apr 22, 2025
92b5eb3
fix: return get and switch responses
hunterachieng Apr 22, 2025
8b3c3b2
Revert "Merge branch 'main' of github.com:OpenFn/adaptors into featur…
hunterachieng Apr 22, 2025
ee22f89
fix: export encode
hunterachieng Apr 22, 2025
efc36c2
fix: add tests and fix documentation
hunterachieng Apr 22, 2025
6cec6a7
fix: remove response from adaptor state typedef
hunterachieng Apr 22, 2025
d44e454
fix: assert for state.response
hunterachieng Apr 22, 2025
ebcae84
fix: update changeset example
hunterachieng Apr 24, 2025
dcaf575
fix: move http tests to a new file
hunterachieng Apr 24, 2025
b01ca26
fix: update tests hostUrl
hunterachieng Apr 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .changeset/silly-bulldogs-complain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
'@openfn/language-dhis2': major
---

- Added a new http namespace, containing HTTP helpers for `get()`, `post()` and `patch()`.
- Added a `request()` function in the `http` file.
- Remove all callbacks

### Migration Change

If you used to do this:

```
get('programs', { orgUnit: 'TSyzvBiovKh', fields: '*' });

```

Do this instead:

```
http.get('programs', { orgUnit: 'TSyzvBiovKh', fields: '*' });

```

370 changes: 68 additions & 302 deletions packages/dhis2/ast.json

Large diffs are not rendered by default.

279 changes: 79 additions & 200 deletions packages/dhis2/src/Adaptor.js

Large diffs are not rendered by default.

13 changes: 11 additions & 2 deletions packages/dhis2/src/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,23 @@ export function selectId(resourceType) {
}
}

export function handleResponse(result, state, callback) {
export function handleHttpResponse(result, state) {
const { body, ...responseWithoutBody } = result;

const nextState = {
...composeNextState(state, body),
response: responseWithoutBody,
};
return callback(nextState);
return nextState;
}

export function handleResponse(result, state) {
const { body } = result;

const nextState = {
...composeNextState(state, body),
};
return nextState;
}

export function prettyJson(data) {
Expand Down
235 changes: 235 additions & 0 deletions packages/dhis2/src/http.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
import { expandReferences, encode } from '@openfn/language-common/util';
import * as util from './Utils';

/**
* State object
* @typedef {Object} Dhis2State
* @private
* @property data - The response body (as JSON)
* @property response - The HTTP response from the Dhis2 server (excluding the body)
* @property references - An array of all previous data objects used in the Job
*/

/**
* Options object
* @typedef {Object} RequestOptions
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worried about these docs but they're not technically part of this PR. Let me think about it. Referenced here: #975 (comment)

* @property {object} query - An object of query parameters to be encoded into the URL
* @property {object} headers - An object of all request headers
* @property {string} [parseAs='json'] - The response format to parse (e.g., 'json', 'text', 'stream', or 'base64'. Defaults to `json`
* @property {string} [apiVersion=42] - The apiVersion of the request. Defaults to 42.
*/

/**
* Get data. HTTP helper method for getting data of any kind from DHIS2.
* - This can be used to get `DataValueSets`,`events`,`trackers`,`etc.`
* @public
* @function
* @param {string} path - Path to resource(use its `plural` name). E.g. `dataElements`, `tracker/trackedEntities`,`organisationUnits`, etc.
* @param {RequestOptions} [options] - An optional object containing query, parseAs,and headers for the request
* @state {Dhis2State}
* @returns {Operation}
* @example <caption>Get all data values for the 'pBOMPrpg1QX' dataset</caption>
* http.get('dataValueSets', {
* query:{
* dataSet: 'pBOMPrpg1QX',
* orgUnit: 'DiszpKrYNg8',
* period: '201401',
* fields: '*',
* }
* });
* @example <caption>Get the relationship between two tracker entities. The only required parameters are 'trackedEntity', 'enrollment' or 'event'. See [Relationships docs](https://docs.dhis2.org/en/develop/using-the-api/dhis-core-version-241/tracker.html#relationships-get-apitrackerrelationships)</caption>
* http.get('tracker/relationships', {
* query: { trackedEntity:['F8yKM85NbxW'] }
* });
* @example <caption>Get an image from a trackedEntityInstance.</caption>
* http.get('trackedEntityInstances/qHVDKszQmdx/BqaEWTBG3RB/image', {
* headers:{
* Accept: 'image/*'
* },
* parseAs: 'base64',
* });
*/
export function get(path, options = {}) {
return async state => {
console.log('Preparing get operation...');

const [resolvedPath, resolvedOptions] = expandReferences(
state,
path,
options
);

const { parseAs } = resolvedOptions;

const response = await util.request(state.configuration, {
method: 'GET',
path: util.prefixVersionToPath(
state.configuration,
resolvedOptions,
resolvedPath
),
options: resolvedOptions,
});

if (parseAs === 'base64') {
response.body = encode(response.body);
}
console.log(`Retrieved ${resolvedPath}`);

return util.handleHttpResponse(response, state);
};
}

/**
* Post data. HTTP helper method for posting data of any kind to DHIS2.
* This can be used to create `DataValueSets`,`events`,`trackers`,etc.
* @public
* @function
* @param {string} path - Path to resource. E.g. `trackedEntities`, `programs`, `events`, ...
* @magic path $.children.resourceTypes[*]
* @param {Dhis2Data} data - Object which defines data that will be used to create a given instance of resource. To create a single instance of a resource, `data` must be a javascript object, and to create multiple instances of a resources, `data` must be an array of javascript objects.
* @param {RequestOptions} [options] - An optional object containing query, parseAs,and headers for the request.
* @state {Dhis2State}
* @returns {Operation}
* @example <caption>Create an event</caption>
* http.post("tracker", {
* events: [
* {
* program: "eBAyeGv0exc",
* orgUnit: "DiszpKrYNg8",
* status: "COMPLETED",
* },
* ],
* });
*/
export function post(path, data, options = {}) {
return async state => {
console.log('Preparing post operation...');

const [resolvedPath, resolvedOptions, resolvedData] = expandReferences(
state,
path,
options,
data
);

const { configuration } = state;
let response;

response = await util.request(configuration, {
method: 'POST',
path: util.prefixVersionToPath(
configuration,
resolvedOptions,
resolvedPath
),
options: resolvedOptions,
data: resolvedData,
});

console.log(`Created ${resolvedPath}`);
return util.handleHttpResponse(response, state);
};
}

/**
* Patch a record. A HTTP helper function to send partial updates on one or more object properties.
* - You are not required to send the full body of object properties.
* - This is useful for cases where you don't want or need to update all properties on a object.
* @public
* @function
* @param {string} resourceType - The type of resource to be updated. E.g. `dataElements`, `organisationUnits`, etc.
* @param {string} path - The `id` or `path` to the `object` to be updated. E.g. `FTRrcoaog83` or `FTRrcoaog83/{collection-name}/{object-id}`
* @param {Object} data - Data to update. Include only the fields you want to update. E.g. `{name: "New Name"}`
* @param {RequestOptions} [options] - An optional object containing query, parseAs,and headers for the request.
* @state {Dhis2State}
* @returns {Operation}
* @example <caption>a dataElement</caption>
* patch('dataElements', 'FTRrcoaog83', { name: 'New Name' });
*/

export function patch(resourceType, path, data, options = {}) {
return async state => {
console.log('Preparing patch operation...');

const [resolvedResourceType, resolvedPath, resolvedData, resolvedOptions] =
expandReferences(state, resourceType, path, data, options);

const { configuration } = state;
let response;

response = await util.request(configuration, {
method: 'PATCH',
path: util.prefixVersionToPath(
configuration,
resolvedOptions,
resolvedResourceType,
resolvedPath
),
options: resolvedOptions,
data: resolvedData,
});

console.log(`Patched ${resolvedResourceType} at ${resolvedPath}`);
return util.handleHttpResponse(response, state);
};
}

/**
* Make a HTTP request to any dhis2 endpoint
* @example <caption>GET request with a URL params</caption>
* http.request("GET",
* "tracker/relationships", {
* query:{
* trackedEntity: ['F8yKM85NbxW']
* },
* });
* @example <caption>Upsert a tracker resource </caption>
* http.request('POST', 'tracker', {
* data: {
* orgUnit: 'TSyzvBiovKh',
* trackedEntityType: 'nEenWmSyUEp',
* attributes: [
* {
* attribute: 'w75KJ2mc4zz',
* value: 'Qassime',
* },
* ],
* },
* query:{
* importStrategy: 'CREATE_AND_UPDATE'
* }
* });
* @function
* @public
* @param {string} method - HTTP method to use
* @param {string} path - Path to resource
* @param {RequestOptions} [options] - An optional object containing query, requestConfig, and data for the request
* @returns {Operation}
*/
export function request(method, path, options = {}) {
return async state => {
console.log(`Preparing a ${method.toLowerCase()} operation...`);

const [resolvedMethod, resolvedPath, resolvedOptions = {}] =
expandReferences(state, method, path, options);

const { data } = resolvedOptions;
const { configuration } = state;
let response;

response = await util.request(configuration, {
method: resolvedMethod,
path: util.prefixVersionToPath(
configuration,
resolvedOptions,
resolvedPath
),
options: resolvedOptions,
data,
});

console.log(`Successful ${resolvedMethod.toLowerCase()} operation...`);
return util.handleHttpResponse(response, state);
};
}
1 change: 1 addition & 0 deletions packages/dhis2/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export { metadata };
import * as Adaptor from './Adaptor';
export default Adaptor;
export * from './Adaptor';
export * as http from './http';
export * as util from './util';
Loading