@openmrs/esm-emr-api 8.0.1-pre.3605 → 8.0.1-pre.3614
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/.turbo/turbo-build.log +1 -1
- package/dist/events/index.d.ts +11 -0
- package/dist/events/index.js +29 -0
- package/dist/events/types.d.ts +51 -0
- package/dist/events/types.js +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/public.d.ts +1 -0
- package/dist/public.js +1 -0
- package/package.json +4 -4
- package/src/events/events.test.ts +136 -0
- package/src/events/index.ts +37 -0
- package/src/events/types.ts +55 -0
- package/src/index.ts +1 -0
- package/src/public.ts +1 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type EventsWithPayload, type OpenmrsEvent, type EventsWithoutPayload, type EventTypes } from './types';
|
|
2
|
+
export { type OpenmrsEvent, type EventTypes as OpenmrsEventTypes } from './types';
|
|
3
|
+
export declare function fireOpenmrsEvent<T extends EventsWithoutPayload>(event: T, payload?: never): boolean;
|
|
4
|
+
export declare function fireOpenmrsEvent<T extends EventsWithPayload>(event: T, payload: EventTypes[T]): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Subscribes to a custom OpenMRS event
|
|
7
|
+
*
|
|
8
|
+
* @param event The name of the event to listen to
|
|
9
|
+
* @param handler The callback to be called when the event fires
|
|
10
|
+
*/
|
|
11
|
+
export declare function subscribeOpenmrsEvent<T extends OpenmrsEvent>(event: T, handler: (payload?: EventTypes[T]) => boolean | void): () => void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fires an OpenMRS custom event
|
|
3
|
+
*
|
|
4
|
+
* @param event The custom event to fire
|
|
5
|
+
* @param payload The payload associated with this type of event
|
|
6
|
+
* @returns true if the event was not cancelled and false, i.e., the result of `dispatchEvent()`
|
|
7
|
+
*/ export function fireOpenmrsEvent(event, payload) {
|
|
8
|
+
const evt = new CustomEvent(`openmrs:${event}`, {
|
|
9
|
+
detail: payload ?? undefined,
|
|
10
|
+
cancelable: true,
|
|
11
|
+
bubbles: true
|
|
12
|
+
});
|
|
13
|
+
return window.dispatchEvent(evt);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Subscribes to a custom OpenMRS event
|
|
17
|
+
*
|
|
18
|
+
* @param event The name of the event to listen to
|
|
19
|
+
* @param handler The callback to be called when the event fires
|
|
20
|
+
*/ export function subscribeOpenmrsEvent(event, handler) {
|
|
21
|
+
const internalHandler = (event)=>{
|
|
22
|
+
const detail = 'detail' in event && event.detail !== null ? event.detail : undefined;
|
|
23
|
+
handler(detail);
|
|
24
|
+
};
|
|
25
|
+
window.addEventListener(`openmrs:${event}`, internalHandler);
|
|
26
|
+
return ()=>{
|
|
27
|
+
window.removeEventListener(`openmrs:${event}`, internalHandler);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload returned from the "page-change" event
|
|
3
|
+
*/
|
|
4
|
+
export interface PageChanged {
|
|
5
|
+
/**
|
|
6
|
+
* This function controls whether or not the page change goes ahead.
|
|
7
|
+
* Call this to interrupt the page navigation, e.g., if a user requested
|
|
8
|
+
* not to change the page.
|
|
9
|
+
*
|
|
10
|
+
* @param val If this is a value that ultimately results as "true", then navigation
|
|
11
|
+
* is cancelled, which is the default value.
|
|
12
|
+
*/
|
|
13
|
+
cancelNavigation(val?: boolean | Promise<boolean> | (() => boolean | Promise<boolean>)): void;
|
|
14
|
+
/**
|
|
15
|
+
* The name of the main content page that will be displayed, e.g., "@openmrs/esm-my-app-page-0".
|
|
16
|
+
* May be undefined if the navigation will not result in a main content page.
|
|
17
|
+
*/
|
|
18
|
+
newPage: string | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* The URL currently used by single-spa to determine the layout
|
|
21
|
+
*/
|
|
22
|
+
oldUrl: string;
|
|
23
|
+
/**
|
|
24
|
+
* The URL that will be in effect once this update cycle is complete
|
|
25
|
+
*/
|
|
26
|
+
newUrl: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* This is the set of events supported by the custom event system
|
|
30
|
+
*/
|
|
31
|
+
export interface EventTypes {
|
|
32
|
+
/**
|
|
33
|
+
* The started event is fired once when the app started.
|
|
34
|
+
* Listeners should use this as an opportunity to do any initialization required.
|
|
35
|
+
*/
|
|
36
|
+
started: never;
|
|
37
|
+
/**
|
|
38
|
+
* The before-page-changed event is fired before the active page in the application changes
|
|
39
|
+
*/
|
|
40
|
+
'before-page-changed': PageChanged;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* This type is the union of all supported events
|
|
44
|
+
*/
|
|
45
|
+
export type OpenmrsEvent = keyof EventTypes;
|
|
46
|
+
export type EventsWithoutPayload = {
|
|
47
|
+
[K in OpenmrsEvent]: EventTypes[K] extends undefined ? K : never;
|
|
48
|
+
}[OpenmrsEvent];
|
|
49
|
+
export type EventsWithPayload = {
|
|
50
|
+
[K in OpenmrsEvent]: EventTypes[K] extends undefined ? never : K;
|
|
51
|
+
}[OpenmrsEvent];
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/public.d.ts
CHANGED
package/dist/public.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmrs/esm-emr-api",
|
|
3
|
-
"version": "8.0.1-pre.
|
|
3
|
+
"version": "8.0.1-pre.3614",
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
5
|
"description": "The javascript module for interacting with the OpenMRS API",
|
|
6
6
|
"type": "module",
|
|
@@ -62,9 +62,9 @@
|
|
|
62
62
|
"@openmrs/esm-state": "6.x"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@openmrs/esm-api": "8.0.1-pre.
|
|
66
|
-
"@openmrs/esm-offline": "8.0.1-pre.
|
|
67
|
-
"@openmrs/esm-state": "8.0.1-pre.
|
|
65
|
+
"@openmrs/esm-api": "8.0.1-pre.3614",
|
|
66
|
+
"@openmrs/esm-offline": "8.0.1-pre.3614",
|
|
67
|
+
"@openmrs/esm-state": "8.0.1-pre.3614",
|
|
68
68
|
"@swc/cli": "^0.7.7",
|
|
69
69
|
"@swc/core": "^1.11.29",
|
|
70
70
|
"@vitest/coverage-v8": "^4.0.7",
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { fireOpenmrsEvent, subscribeOpenmrsEvent } from './index';
|
|
3
|
+
|
|
4
|
+
describe('Event system', () => {
|
|
5
|
+
describe('fireOpenmrsEvent', () => {
|
|
6
|
+
it('dispatches an event on window by default', () => {
|
|
7
|
+
const handler = vi.fn();
|
|
8
|
+
window.addEventListener('openmrs:started', handler);
|
|
9
|
+
|
|
10
|
+
fireOpenmrsEvent('started');
|
|
11
|
+
|
|
12
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
13
|
+
window.removeEventListener('openmrs:started', handler);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('dispatches an event with payload', () => {
|
|
17
|
+
const handler = vi.fn();
|
|
18
|
+
window.addEventListener('openmrs:before-page-changed', handler);
|
|
19
|
+
|
|
20
|
+
const payload = {
|
|
21
|
+
cancelNavigation: vi.fn(),
|
|
22
|
+
newPage: '/home',
|
|
23
|
+
oldUrl: 'http://localhost/old',
|
|
24
|
+
newUrl: 'http://localhost/new',
|
|
25
|
+
};
|
|
26
|
+
fireOpenmrsEvent('before-page-changed', payload);
|
|
27
|
+
|
|
28
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
29
|
+
const event = handler.mock.calls[0][0] as CustomEvent;
|
|
30
|
+
expect(event.detail).toEqual(payload);
|
|
31
|
+
window.removeEventListener('openmrs:before-page-changed', handler);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('returns true when event is not cancelled', () => {
|
|
35
|
+
const result = fireOpenmrsEvent('started');
|
|
36
|
+
expect(result).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('returns false when event is cancelled', () => {
|
|
40
|
+
const handler = (e: Event) => e.preventDefault();
|
|
41
|
+
window.addEventListener('openmrs:started', handler);
|
|
42
|
+
|
|
43
|
+
const result = fireOpenmrsEvent('started');
|
|
44
|
+
|
|
45
|
+
expect(result).toBe(false);
|
|
46
|
+
window.removeEventListener('openmrs:started', handler);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('subscribeOpenmrsEvent', () => {
|
|
51
|
+
it('subscribes to an event on window by default', () => {
|
|
52
|
+
const handler = vi.fn();
|
|
53
|
+
const unsubscribe = subscribeOpenmrsEvent('started', handler);
|
|
54
|
+
|
|
55
|
+
fireOpenmrsEvent('started');
|
|
56
|
+
|
|
57
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
58
|
+
unsubscribe();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('receives the event payload', () => {
|
|
62
|
+
const handler = vi.fn();
|
|
63
|
+
const unsubscribe = subscribeOpenmrsEvent('before-page-changed', handler);
|
|
64
|
+
|
|
65
|
+
const payload = {
|
|
66
|
+
cancelNavigation: vi.fn(),
|
|
67
|
+
newPage: '/home',
|
|
68
|
+
oldUrl: 'http://localhost/old',
|
|
69
|
+
newUrl: 'http://localhost/new',
|
|
70
|
+
};
|
|
71
|
+
fireOpenmrsEvent('before-page-changed', payload);
|
|
72
|
+
|
|
73
|
+
expect(handler).toHaveBeenCalledWith(payload);
|
|
74
|
+
unsubscribe();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('receives undefined for events without payload', () => {
|
|
78
|
+
const handler = vi.fn();
|
|
79
|
+
const unsubscribe = subscribeOpenmrsEvent('started', handler);
|
|
80
|
+
|
|
81
|
+
fireOpenmrsEvent('started');
|
|
82
|
+
|
|
83
|
+
expect(handler).toHaveBeenCalledWith(undefined);
|
|
84
|
+
unsubscribe();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('unsubscribes correctly', () => {
|
|
88
|
+
const handler = vi.fn();
|
|
89
|
+
const unsubscribe = subscribeOpenmrsEvent('started', handler);
|
|
90
|
+
|
|
91
|
+
fireOpenmrsEvent('started');
|
|
92
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
93
|
+
|
|
94
|
+
unsubscribe();
|
|
95
|
+
|
|
96
|
+
fireOpenmrsEvent('started');
|
|
97
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('allows multiple subscribers to the same event', () => {
|
|
101
|
+
const handler1 = vi.fn();
|
|
102
|
+
const handler2 = vi.fn();
|
|
103
|
+
const unsubscribe1 = subscribeOpenmrsEvent('started', handler1);
|
|
104
|
+
const unsubscribe2 = subscribeOpenmrsEvent('started', handler2);
|
|
105
|
+
|
|
106
|
+
fireOpenmrsEvent('started');
|
|
107
|
+
|
|
108
|
+
expect(handler1).toHaveBeenCalledOnce();
|
|
109
|
+
expect(handler2).toHaveBeenCalledOnce();
|
|
110
|
+
unsubscribe1();
|
|
111
|
+
unsubscribe2();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('calling unsubscribe multiple times is safe', () => {
|
|
115
|
+
const handler = vi.fn();
|
|
116
|
+
const unsubscribe = subscribeOpenmrsEvent('started', handler);
|
|
117
|
+
|
|
118
|
+
unsubscribe();
|
|
119
|
+
expect(() => unsubscribe()).not.toThrow();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('unsubscribing one handler does not affect others', () => {
|
|
123
|
+
const handler1 = vi.fn();
|
|
124
|
+
const handler2 = vi.fn();
|
|
125
|
+
const unsubscribe1 = subscribeOpenmrsEvent('started', handler1);
|
|
126
|
+
const unsubscribe2 = subscribeOpenmrsEvent('started', handler2);
|
|
127
|
+
|
|
128
|
+
unsubscribe1();
|
|
129
|
+
fireOpenmrsEvent('started');
|
|
130
|
+
|
|
131
|
+
expect(handler1).not.toHaveBeenCalled();
|
|
132
|
+
expect(handler2).toHaveBeenCalledOnce();
|
|
133
|
+
unsubscribe2();
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type EventsWithPayload, type OpenmrsEvent, type EventsWithoutPayload, type EventTypes } from './types';
|
|
2
|
+
export { type OpenmrsEvent, type EventTypes as OpenmrsEventTypes } from './types';
|
|
3
|
+
|
|
4
|
+
export function fireOpenmrsEvent<T extends EventsWithoutPayload>(event: T, payload?: never): boolean;
|
|
5
|
+
export function fireOpenmrsEvent<T extends EventsWithPayload>(event: T, payload: EventTypes[T]): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Fires an OpenMRS custom event
|
|
8
|
+
*
|
|
9
|
+
* @param event The custom event to fire
|
|
10
|
+
* @param payload The payload associated with this type of event
|
|
11
|
+
* @returns true if the event was not cancelled and false, i.e., the result of `dispatchEvent()`
|
|
12
|
+
*/
|
|
13
|
+
export function fireOpenmrsEvent<T extends OpenmrsEvent>(event: T, payload?: EventTypes[T]): boolean {
|
|
14
|
+
const evt = new CustomEvent(`openmrs:${event}`, { detail: payload ?? undefined, cancelable: true, bubbles: true });
|
|
15
|
+
return window.dispatchEvent(evt);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Subscribes to a custom OpenMRS event
|
|
20
|
+
*
|
|
21
|
+
* @param event The name of the event to listen to
|
|
22
|
+
* @param handler The callback to be called when the event fires
|
|
23
|
+
*/
|
|
24
|
+
export function subscribeOpenmrsEvent<T extends OpenmrsEvent>(
|
|
25
|
+
event: T,
|
|
26
|
+
handler: (payload?: EventTypes[T]) => boolean | void,
|
|
27
|
+
): () => void {
|
|
28
|
+
const internalHandler = (event: Event) => {
|
|
29
|
+
const detail = 'detail' in event && event.detail !== null ? event.detail : undefined;
|
|
30
|
+
handler(detail as EventTypes[T]);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
window.addEventListener(`openmrs:${event}`, internalHandler);
|
|
34
|
+
return () => {
|
|
35
|
+
window.removeEventListener(`openmrs:${event}`, internalHandler);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload returned from the "page-change" event
|
|
3
|
+
*/
|
|
4
|
+
export interface PageChanged {
|
|
5
|
+
/**
|
|
6
|
+
* This function controls whether or not the page change goes ahead.
|
|
7
|
+
* Call this to interrupt the page navigation, e.g., if a user requested
|
|
8
|
+
* not to change the page.
|
|
9
|
+
*
|
|
10
|
+
* @param val If this is a value that ultimately results as "true", then navigation
|
|
11
|
+
* is cancelled, which is the default value.
|
|
12
|
+
*/
|
|
13
|
+
cancelNavigation(val?: boolean | Promise<boolean> | (() => boolean | Promise<boolean>)): void;
|
|
14
|
+
/**
|
|
15
|
+
* The name of the main content page that will be displayed, e.g., "@openmrs/esm-my-app-page-0".
|
|
16
|
+
* May be undefined if the navigation will not result in a main content page.
|
|
17
|
+
*/
|
|
18
|
+
newPage: string | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* The URL currently used by single-spa to determine the layout
|
|
21
|
+
*/
|
|
22
|
+
oldUrl: string;
|
|
23
|
+
/**
|
|
24
|
+
* The URL that will be in effect once this update cycle is complete
|
|
25
|
+
*/
|
|
26
|
+
newUrl: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* This is the set of events supported by the custom event system
|
|
31
|
+
*/
|
|
32
|
+
export interface EventTypes {
|
|
33
|
+
/**
|
|
34
|
+
* The started event is fired once when the app started.
|
|
35
|
+
* Listeners should use this as an opportunity to do any initialization required.
|
|
36
|
+
*/
|
|
37
|
+
started: never;
|
|
38
|
+
/**
|
|
39
|
+
* The before-page-changed event is fired before the active page in the application changes
|
|
40
|
+
*/
|
|
41
|
+
'before-page-changed': PageChanged;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* This type is the union of all supported events
|
|
46
|
+
*/
|
|
47
|
+
export type OpenmrsEvent = keyof EventTypes;
|
|
48
|
+
|
|
49
|
+
export type EventsWithoutPayload = {
|
|
50
|
+
[K in OpenmrsEvent]: EventTypes[K] extends undefined ? K : never;
|
|
51
|
+
}[OpenmrsEvent];
|
|
52
|
+
|
|
53
|
+
export type EventsWithPayload = {
|
|
54
|
+
[K in OpenmrsEvent]: EventTypes[K] extends undefined ? never : K;
|
|
55
|
+
}[OpenmrsEvent];
|
package/src/index.ts
CHANGED
package/src/public.ts
CHANGED