@openmrs/esm-react-utils 10.0.1-pre.5434 → 10.0.1-pre.5452

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.
@@ -1,3 +1,3 @@
1
- [0] Successfully compiled: 55 files with swc (157.5ms)
1
+ [0] Successfully compiled: 55 files with swc (132.12ms)
2
2
  [0] swc --strip-leading-paths src -d dist exited with code 0
3
3
  [1] tsc --project tsconfig.build.json exited with code 0
@@ -5,8 +5,12 @@ import { type AttachmentResponse } from '@openmrs/esm-emr-api';
5
5
  * and automatic revalidation.
6
6
  *
7
7
  * @param patientUuid The UUID of the patient whose attachments should be fetched.
8
+ * Nothing is fetched while this is empty, so callers can defer the request.
8
9
  * @param includeEncounterless Whether to include attachments that are not
9
- * associated with any encounter.
10
+ * associated with any encounter. Ignored when `encounterUuid` is set.
11
+ * @param encounterUuid When set, only attachments recorded on this encounter are
12
+ * returned. An unknown encounter UUID makes the server fall back to every attachment
13
+ * of the patient, so only pass a UUID you have loaded.
10
14
  * @returns An object containing:
11
15
  * - `data`: Array of attachment objects (empty array while loading)
12
16
  * - `isLoading`: Whether the initial fetch is in progress
@@ -23,9 +27,12 @@ import { type AttachmentResponse } from '@openmrs/esm-emr-api';
23
27
  * if (error) return <span>Error loading attachments</span>;
24
28
  * return <AttachmentList attachments={data} />;
25
29
  * }
30
+ *
31
+ * // Only the attachments recorded on one encounter
32
+ * const { data } = useAttachments(patientUuid, false, encounterUuid);
26
33
  * ```
27
34
  */
28
- export declare function useAttachments(patientUuid: string, includeEncounterless: boolean): {
35
+ export declare function useAttachments(patientUuid: string | null | undefined, includeEncounterless: boolean, encounterUuid?: string): {
29
36
  isLoading: boolean;
30
37
  data: AttachmentResponse[];
31
38
  error: any;
@@ -1 +1 @@
1
- {"version":3,"file":"useAttachments.d.ts","sourceRoot":"","sources":["../src/useAttachments.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,oBAAoB,EAAE,OAAO;;;;;iBAEpD,KAAK,CAAC,kBAAkB,CAAC;;;EAerD"}
1
+ {"version":3,"file":"useAttachments.d.ts","sourceRoot":"","sources":["../src/useAttachments.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAElF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACtC,oBAAoB,EAAE,OAAO,EAC7B,aAAa,CAAC,EAAE,MAAM;;;;;iBAGK,KAAK,CAAC,kBAAkB,CAAC;;;EAerD"}
@@ -1,14 +1,18 @@
1
1
  /** @module @category API */ import { useMemo } from "react";
2
2
  import useSWR from "swr";
3
3
  import { openmrsFetch } from "@openmrs/esm-api";
4
- import { attachmentUrl } from "@openmrs/esm-emr-api";
4
+ import { getAttachmentsUrl } from "@openmrs/esm-emr-api";
5
5
  /**
6
6
  * A React hook that fetches attachments for a patient using SWR for caching
7
7
  * and automatic revalidation.
8
8
  *
9
9
  * @param patientUuid The UUID of the patient whose attachments should be fetched.
10
+ * Nothing is fetched while this is empty, so callers can defer the request.
10
11
  * @param includeEncounterless Whether to include attachments that are not
11
- * associated with any encounter.
12
+ * associated with any encounter. Ignored when `encounterUuid` is set.
13
+ * @param encounterUuid When set, only attachments recorded on this encounter are
14
+ * returned. An unknown encounter UUID makes the server fall back to every attachment
15
+ * of the patient, so only pass a UUID you have loaded.
12
16
  * @returns An object containing:
13
17
  * - `data`: Array of attachment objects (empty array while loading)
14
18
  * - `isLoading`: Whether the initial fetch is in progress
@@ -25,9 +29,12 @@ import { attachmentUrl } from "@openmrs/esm-emr-api";
25
29
  * if (error) return <span>Error loading attachments</span>;
26
30
  * return <AttachmentList attachments={data} />;
27
31
  * }
32
+ *
33
+ * // Only the attachments recorded on one encounter
34
+ * const { data } = useAttachments(patientUuid, false, encounterUuid);
28
35
  * ```
29
- */ export function useAttachments(patientUuid, includeEncounterless) {
30
- const { data, error, mutate, isLoading, isValidating } = useSWR(`${attachmentUrl}?patient=${patientUuid}&includeEncounterless=${includeEncounterless}`, openmrsFetch);
36
+ */ export function useAttachments(patientUuid, includeEncounterless, encounterUuid) {
37
+ const { data, error, mutate, isLoading, isValidating } = useSWR(patientUuid ? getAttachmentsUrl(patientUuid, includeEncounterless, encounterUuid) : null, openmrsFetch);
31
38
  const results = useMemo(()=>({
32
39
  isLoading,
33
40
  data: data?.data.results ?? [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmrs/esm-react-utils",
3
- "version": "10.0.1-pre.5434",
3
+ "version": "10.0.1-pre.5452",
4
4
  "license": "MPL-2.0",
5
5
  "description": "React utilities for OpenMRS.",
6
6
  "type": "module",
@@ -60,17 +60,17 @@
60
60
  "single-spa-react": "^6.0.2"
61
61
  },
62
62
  "peerDependencies": {
63
- "@openmrs/esm-api": "^10.0.1-pre.5434",
64
- "@openmrs/esm-config": "^10.0.1-pre.5434",
65
- "@openmrs/esm-context": "^10.0.1-pre.5434",
66
- "@openmrs/esm-emr-api": "^10.0.1-pre.5434",
67
- "@openmrs/esm-error-handling": "^10.0.1-pre.5434",
68
- "@openmrs/esm-extensions": "^10.0.1-pre.5434",
69
- "@openmrs/esm-feature-flags": "^10.0.1-pre.5434",
70
- "@openmrs/esm-globals": "^10.0.1-pre.5434",
71
- "@openmrs/esm-navigation": "^10.0.1-pre.5434",
72
- "@openmrs/esm-state": "^10.0.1-pre.5434",
73
- "@openmrs/esm-utils": "^10.0.1-pre.5434",
63
+ "@openmrs/esm-api": "^10.0.1-pre.5452",
64
+ "@openmrs/esm-config": "^10.0.1-pre.5452",
65
+ "@openmrs/esm-context": "^10.0.1-pre.5452",
66
+ "@openmrs/esm-emr-api": "^10.0.1-pre.5452",
67
+ "@openmrs/esm-error-handling": "^10.0.1-pre.5452",
68
+ "@openmrs/esm-extensions": "^10.0.1-pre.5452",
69
+ "@openmrs/esm-feature-flags": "^10.0.1-pre.5452",
70
+ "@openmrs/esm-globals": "^10.0.1-pre.5452",
71
+ "@openmrs/esm-navigation": "^10.0.1-pre.5452",
72
+ "@openmrs/esm-state": "^10.0.1-pre.5452",
73
+ "@openmrs/esm-utils": "^10.0.1-pre.5452",
74
74
  "dayjs": "1.x",
75
75
  "i18next": "25.x",
76
76
  "react": "18.x",
@@ -80,17 +80,17 @@
80
80
  "swr": "2.x"
81
81
  },
82
82
  "devDependencies": {
83
- "@openmrs/esm-api": "10.0.1-pre.5434",
84
- "@openmrs/esm-config": "10.0.1-pre.5434",
85
- "@openmrs/esm-context": "10.0.1-pre.5434",
86
- "@openmrs/esm-emr-api": "10.0.1-pre.5434",
87
- "@openmrs/esm-error-handling": "10.0.1-pre.5434",
88
- "@openmrs/esm-extensions": "10.0.1-pre.5434",
89
- "@openmrs/esm-feature-flags": "10.0.1-pre.5434",
90
- "@openmrs/esm-globals": "10.0.1-pre.5434",
91
- "@openmrs/esm-navigation": "10.0.1-pre.5434",
92
- "@openmrs/esm-state": "10.0.1-pre.5434",
93
- "@openmrs/esm-utils": "10.0.1-pre.5434",
83
+ "@openmrs/esm-api": "10.0.1-pre.5452",
84
+ "@openmrs/esm-config": "10.0.1-pre.5452",
85
+ "@openmrs/esm-context": "10.0.1-pre.5452",
86
+ "@openmrs/esm-emr-api": "10.0.1-pre.5452",
87
+ "@openmrs/esm-error-handling": "10.0.1-pre.5452",
88
+ "@openmrs/esm-extensions": "10.0.1-pre.5452",
89
+ "@openmrs/esm-feature-flags": "10.0.1-pre.5452",
90
+ "@openmrs/esm-globals": "10.0.1-pre.5452",
91
+ "@openmrs/esm-navigation": "10.0.1-pre.5452",
92
+ "@openmrs/esm-state": "10.0.1-pre.5452",
93
+ "@openmrs/esm-utils": "10.0.1-pre.5452",
94
94
  "@swc/cli": "0.8.1",
95
95
  "@swc/core": "1.15.21",
96
96
  "@vitest/coverage-v8": "^4.1.2",
@@ -0,0 +1,71 @@
1
+ import React from 'react';
2
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
3
+ import { renderHook, waitFor } from '@testing-library/react';
4
+ import { SWRConfig } from 'swr';
5
+ import { openmrsFetch, type FetchResponse } from '@openmrs/esm-api';
6
+ import { attachmentUrl, type AttachmentResponse } from '@openmrs/esm-emr-api';
7
+ import { useAttachments } from './useAttachments';
8
+
9
+ vi.mock('@openmrs/esm-api', async (importOriginal) => ({
10
+ ...(await importOriginal<typeof import('@openmrs/esm-api')>()),
11
+ openmrsFetch: vi.fn(),
12
+ }));
13
+
14
+ const mockOpenmrsFetch = vi.mocked(openmrsFetch);
15
+
16
+ const attachment: AttachmentResponse = {
17
+ uuid: 'attachment-uuid',
18
+ filename: 'photo.png',
19
+ comment: 'Wound photo',
20
+ dateTime: '2026-09-18T10:00:00.000+0000',
21
+ bytesMimeType: 'image/png',
22
+ bytesContentFamily: 'IMAGE',
23
+ };
24
+
25
+ // Each test gets its own SWR cache so keys requested in one test do not satisfy the next.
26
+ const wrapper = ({ children }: { children: React.ReactNode }) => (
27
+ <SWRConfig value={{ provider: () => new Map(), dedupingInterval: 0 }}>{children}</SWRConfig>
28
+ );
29
+
30
+ describe('useAttachments', () => {
31
+ beforeEach(() => {
32
+ mockOpenmrsFetch.mockReset();
33
+ mockOpenmrsFetch.mockResolvedValue({ data: { results: [attachment] } } as FetchResponse<{
34
+ results: Array<AttachmentResponse>;
35
+ }>);
36
+ });
37
+
38
+ it('fetches the patient attachments and unwraps the results', async () => {
39
+ const { result } = renderHook(() => useAttachments('patient-uuid', true), { wrapper });
40
+
41
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
42
+
43
+ expect(mockOpenmrsFetch).toHaveBeenCalledWith(`${attachmentUrl}?patient=patient-uuid&includeEncounterless=true`);
44
+ expect(result.current.data).toEqual([attachment]);
45
+ });
46
+
47
+ it('fetches only the attachments on an encounter when one is given', async () => {
48
+ const { result } = renderHook(() => useAttachments('patient-uuid', true, 'encounter-uuid'), { wrapper });
49
+
50
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
51
+
52
+ expect(mockOpenmrsFetch).toHaveBeenCalledWith(`${attachmentUrl}?patient=patient-uuid&encounter=encounter-uuid`);
53
+ expect(result.current.data).toEqual([attachment]);
54
+ });
55
+
56
+ it('does not fetch while the patient UUID is empty', () => {
57
+ const { result } = renderHook(() => useAttachments(null, true), { wrapper });
58
+
59
+ expect(mockOpenmrsFetch).not.toHaveBeenCalled();
60
+ expect(result.current.isLoading).toBe(false);
61
+ expect(result.current.data).toEqual([]);
62
+ });
63
+
64
+ it('returns an empty list while loading', () => {
65
+ mockOpenmrsFetch.mockReturnValue(new Promise(() => {}));
66
+ const { result } = renderHook(() => useAttachments('patient-uuid', true), { wrapper });
67
+
68
+ expect(result.current.isLoading).toBe(true);
69
+ expect(result.current.data).toEqual([]);
70
+ });
71
+ });
@@ -2,15 +2,19 @@
2
2
  import { useMemo } from 'react';
3
3
  import useSWR from 'swr';
4
4
  import { openmrsFetch, type FetchResponse } from '@openmrs/esm-api';
5
- import { attachmentUrl, type AttachmentResponse } from '@openmrs/esm-emr-api';
5
+ import { getAttachmentsUrl, type AttachmentResponse } from '@openmrs/esm-emr-api';
6
6
 
7
7
  /**
8
8
  * A React hook that fetches attachments for a patient using SWR for caching
9
9
  * and automatic revalidation.
10
10
  *
11
11
  * @param patientUuid The UUID of the patient whose attachments should be fetched.
12
+ * Nothing is fetched while this is empty, so callers can defer the request.
12
13
  * @param includeEncounterless Whether to include attachments that are not
13
- * associated with any encounter.
14
+ * associated with any encounter. Ignored when `encounterUuid` is set.
15
+ * @param encounterUuid When set, only attachments recorded on this encounter are
16
+ * returned. An unknown encounter UUID makes the server fall back to every attachment
17
+ * of the patient, so only pass a UUID you have loaded.
14
18
  * @returns An object containing:
15
19
  * - `data`: Array of attachment objects (empty array while loading)
16
20
  * - `isLoading`: Whether the initial fetch is in progress
@@ -27,12 +31,19 @@ import { attachmentUrl, type AttachmentResponse } from '@openmrs/esm-emr-api';
27
31
  * if (error) return <span>Error loading attachments</span>;
28
32
  * return <AttachmentList attachments={data} />;
29
33
  * }
34
+ *
35
+ * // Only the attachments recorded on one encounter
36
+ * const { data } = useAttachments(patientUuid, false, encounterUuid);
30
37
  * ```
31
38
  */
32
- export function useAttachments(patientUuid: string, includeEncounterless: boolean) {
39
+ export function useAttachments(
40
+ patientUuid: string | null | undefined,
41
+ includeEncounterless: boolean,
42
+ encounterUuid?: string,
43
+ ) {
33
44
  const { data, error, mutate, isLoading, isValidating } = useSWR<
34
45
  FetchResponse<{ results: Array<AttachmentResponse> }>
35
- >(`${attachmentUrl}?patient=${patientUuid}&includeEncounterless=${includeEncounterless}`, openmrsFetch);
46
+ >(patientUuid ? getAttachmentsUrl(patientUuid, includeEncounterless, encounterUuid) : null, openmrsFetch);
36
47
 
37
48
  const results = useMemo(
38
49
  () => ({