@openmrs/esm-offline 3.2.1-pre.986 → 3.3.1-pre.1173

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/jest.config.js CHANGED
@@ -1,5 +1,8 @@
1
1
  module.exports = {
2
2
  transform: {
3
- "^.+\\.tsx?$": "babel-jest",
3
+ "^.+\\.tsx?$": ["@swc/jest"],
4
+ },
5
+ moduleNameMapper: {
6
+ "lodash-es": "lodash",
4
7
  },
5
8
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmrs/esm-offline",
3
- "version": "3.2.1-pre.986",
3
+ "version": "3.3.1-pre.1173",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Helper utilities for OpenMRS",
6
6
  "browser": "dist/openmrs-esm-offline.js",
@@ -36,10 +36,10 @@
36
36
  "access": "public"
37
37
  },
38
38
  "devDependencies": {
39
- "@openmrs/esm-api": "^3.2.1-pre.986",
40
- "@openmrs/esm-globals": "^3.2.1-pre.986",
41
- "@openmrs/esm-state": "^3.2.1-pre.986",
42
- "@openmrs/esm-styleguide": "^3.2.1-pre.986",
39
+ "@openmrs/esm-api": "^3.3.1-pre.1173",
40
+ "@openmrs/esm-globals": "^3.3.1-pre.1173",
41
+ "@openmrs/esm-state": "^3.3.1-pre.1173",
42
+ "@openmrs/esm-styleguide": "^3.3.1-pre.1173",
43
43
  "@types/uuid": "^8.3.0",
44
44
  "rxjs": "^6.5.3"
45
45
  },
@@ -56,5 +56,5 @@
56
56
  "uuid": "^8.3.2",
57
57
  "workbox-window": "^6.1.5"
58
58
  },
59
- "gitHead": "970eb8ac9493a64af6d84c3f8a9620f96f01a1a3"
59
+ "gitHead": "957c0c36b8f754808127269f6e50b90992a60559"
60
60
  }
package/src/index.ts CHANGED
@@ -1,10 +1,7 @@
1
1
  export * from "./service-worker";
2
2
  export * from "./service-worker-http-headers";
3
3
  export * from "./service-worker-messaging";
4
- export * from "./service-worker-events";
5
- export * from "./events";
6
4
  export * from "./mode";
7
- export * from "./patches";
8
5
  export * from "./sync";
9
6
  export * from "./uuid";
10
7
  export * from "./offline-patient-data";
package/src/mode.ts CHANGED
@@ -1,3 +1,5 @@
1
+ /** @module @category Offline */
2
+
1
3
  async function isSafariPrivateBrowsing() {
2
4
  const storage = window.sessionStorage;
3
5
 
@@ -1,3 +1,4 @@
1
+ /** @module @category Offline */
1
2
  import Dexie, { Table } from "dexie";
2
3
  import { createGlobalStore } from "@openmrs/esm-state";
3
4
 
package/src/public.ts ADDED
@@ -0,0 +1,20 @@
1
+ export { OfflineMode, OfflineModeResult, getCurrentOfflineMode } from "./mode";
2
+ export * from "./offline-patient-data";
3
+ export * from "./service-worker-messaging";
4
+ export * from "./service-worker-http-headers";
5
+ export * from "./uuid";
6
+ export {
7
+ QueueItemDescriptor,
8
+ SyncItem,
9
+ SyncProcessOptions,
10
+ queueSynchronizationItem,
11
+ getSynchronizationItem,
12
+ getSynchronizationItems,
13
+ getFullSynchronizationItems,
14
+ getFullSynchronizationItemsFor,
15
+ getOfflineDb,
16
+ canBeginEditSynchronizationItemsOfType,
17
+ beginEditSynchronizationItem,
18
+ deleteSynchronizationItem,
19
+ setupOfflineSync,
20
+ } from "./sync";
@@ -1,3 +1,5 @@
1
+ /** @module @category Offline */
2
+
1
3
  export const omrsOfflineResponseBodyHttpHeaderName =
2
4
  "x-omrs-offline-response-body";
3
5
  export const omrsOfflineResponseStatusHttpHeaderName =
@@ -1,3 +1,4 @@
1
+ /** @module @category Offline */
1
2
  import type { ImportMap } from "@openmrs/esm-globals";
2
3
  import { OmrsOfflineCachingStrategy } from "./service-worker-http-headers";
3
4
  import { getOmrsServiceWorker } from "./service-worker";
@@ -0,0 +1,153 @@
1
+ import "fake-indexeddb/auto";
2
+ import { getLoggedInUser, LoggedInUser } from "@openmrs/esm-api";
3
+ import {
4
+ getFullSynchronizationItems,
5
+ getFullSynchronizationItemsFor,
6
+ getOfflineDb,
7
+ getSynchronizationItems,
8
+ getSynchronizationItemsFor,
9
+ QueueItemDescriptor,
10
+ queueSynchronizationItem,
11
+ queueSynchronizationItemFor,
12
+ deleteSynchronizationItem,
13
+ getSynchronizationItem,
14
+ } from "./sync";
15
+
16
+ interface MockSyncItem {
17
+ value: number;
18
+ }
19
+
20
+ const systemTime = new Date();
21
+ const mockUserId = "00000000-0000-0000-0000-000000000000";
22
+ const mockSyncItemType = "mock-sync-item";
23
+ const defaultMockSyncItem: MockSyncItem = {
24
+ value: 123,
25
+ };
26
+ const defaultMockSyncItemDescriptor: QueueItemDescriptor = {
27
+ dependencies: [],
28
+ id: "123",
29
+ displayName: "Mock Sync Item",
30
+ patientUuid: "00000000-0000-0000-0000-000000000001",
31
+ };
32
+
33
+ jest.mock("@openmrs/esm-api", () => ({
34
+ getLoggedInUser: jest.fn(async () => ({ uuid: mockUserId })),
35
+ }));
36
+
37
+ afterEach(async () => {
38
+ // We want each test case to start fresh with a clean sync queue.
39
+ await getOfflineDb().syncQueue.clear();
40
+ });
41
+
42
+ describe("Sync Queue", () => {
43
+ beforeAll(() => {
44
+ // We want to control the timers to ensure that we can test the `createdOn` attribute
45
+ // of the sync item (which is created using `new Date()`).
46
+ jest.useFakeTimers("modern");
47
+ jest.setSystemTime(systemTime);
48
+ });
49
+
50
+ afterAll(() => {
51
+ jest.useRealTimers();
52
+ });
53
+
54
+ it("enqueues sync item with expected attributes", async () => {
55
+ const id = await queueSynchronizationItemFor(
56
+ mockUserId,
57
+ mockSyncItemType,
58
+ defaultMockSyncItem,
59
+ defaultMockSyncItemDescriptor
60
+ );
61
+ const queuedItems = await getFullSynchronizationItemsFor<MockSyncItem>(
62
+ mockUserId,
63
+ mockSyncItemType
64
+ );
65
+
66
+ expect(queuedItems).toHaveLength(1);
67
+ expect(queuedItems[0].id).toBe(id);
68
+ expect(queuedItems[0].type).toBe(mockSyncItemType);
69
+ expect(queuedItems[0].userId).toBe(mockUserId);
70
+ expect(queuedItems[0].createdOn).toStrictEqual(systemTime);
71
+ expect(queuedItems[0].content).toStrictEqual(defaultMockSyncItem);
72
+ expect(queuedItems[0].descriptor).toStrictEqual(
73
+ defaultMockSyncItemDescriptor
74
+ );
75
+ });
76
+ });
77
+
78
+ describe("Logged-in user specific functions", () => {
79
+ it("enqueue and return sync items of currently logged-in user", async () => {
80
+ const loggedInUserId = (await getLoggedInUser()).uuid;
81
+ await queueSynchronizationItem(mockSyncItemType, defaultMockSyncItem);
82
+ const queuedItems = await getFullSynchronizationItems(mockSyncItemType);
83
+
84
+ expect(queuedItems).toHaveLength(1);
85
+ expect(queuedItems[0].userId).toBe(loggedInUserId);
86
+ });
87
+ });
88
+
89
+ describe("getSynchronizationItems", () => {
90
+ it("returns `content` of corresponding `getFullSynchronizationItems` call", async () => {
91
+ await queueSynchronizationItem(mockSyncItemType, defaultMockSyncItem);
92
+ const items = await getSynchronizationItems(mockSyncItemType);
93
+ const fullItems = await getFullSynchronizationItems(mockSyncItemType);
94
+ expect(items).toHaveLength(1);
95
+ expect(fullItems).toHaveLength(1);
96
+ expect(items[0]).toStrictEqual(fullItems[0].content);
97
+ });
98
+ });
99
+
100
+ describe("getSynchronizationItemsFor", () => {
101
+ it("returns `content` of corresponding `getFullSynchronizationItemsFor` call", async () => {
102
+ await queueSynchronizationItemFor(
103
+ mockUserId,
104
+ mockSyncItemType,
105
+ defaultMockSyncItem
106
+ );
107
+ const items = await getSynchronizationItemsFor(
108
+ mockUserId,
109
+ mockSyncItemType
110
+ );
111
+ const fullItems = await getFullSynchronizationItemsFor(
112
+ mockUserId,
113
+ mockSyncItemType
114
+ );
115
+
116
+ expect(items).toHaveLength(1);
117
+ expect(fullItems).toHaveLength(1);
118
+ expect(items[0]).toStrictEqual(fullItems[0].content);
119
+ });
120
+ });
121
+
122
+ describe("getSynchronizationItem", () => {
123
+ it("returns the specific sync item with given ID", async () => {
124
+ const id = await queueSynchronizationItem(
125
+ mockSyncItemType,
126
+ defaultMockSyncItem
127
+ );
128
+ const items = await getFullSynchronizationItems(mockSyncItemType);
129
+ const item = await getSynchronizationItem(id);
130
+ expect(item).toStrictEqual(items[0]);
131
+ });
132
+
133
+ it("returns undefined when no item with given ID exists", async () => {
134
+ const item = await getSynchronizationItem(404);
135
+ expect(item).toBeUndefined();
136
+ });
137
+ });
138
+
139
+ describe("deleteSynchronizationItem", () => {
140
+ it("deletes sync item with given ID", async () => {
141
+ const id = await queueSynchronizationItem(
142
+ mockSyncItemType,
143
+ defaultMockSyncItem
144
+ );
145
+ await deleteSynchronizationItem(id);
146
+ const items = await getSynchronizationItems(mockSyncItemType);
147
+ expect(items).toHaveLength(0);
148
+ });
149
+
150
+ it("does not throw when no item with given ID exists", async () => {
151
+ await deleteSynchronizationItem(404);
152
+ });
153
+ });
package/src/sync.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /** @module @category Offline */
1
2
  import Dexie, { Table } from "dexie";
2
3
  import { getLoggedInUser } from "@openmrs/esm-api";
3
4
  import { createGlobalStore } from "@openmrs/esm-state";
@@ -299,26 +300,39 @@ export async function queueSynchronizationItem<T>(
299
300
  }
300
301
 
301
302
  /**
302
- * Returns all currently queued up sync items of a given user.
303
+ * Returns the content of all currently queued up sync items of a given user.
303
304
  * @param userId The ID of the user whose synchronization items should be returned.
304
305
  * @param type The identifying type of the synchronization items to be returned..
305
306
  */
306
307
  export async function getSynchronizationItemsFor<T>(
307
308
  userId: string,
308
309
  type: string
310
+ ) {
311
+ const fullItems = await getFullSynchronizationItemsFor<T>(userId, type);
312
+ return fullItems.map((item) => item.content);
313
+ }
314
+
315
+ /**
316
+ * Returns all currently queued up sync items of a given user.
317
+ * @param userId The ID of the user whose synchronization items should be returned.
318
+ * @param type The identifying type of the synchronization items to be returned..
319
+ */
320
+ export async function getFullSynchronizationItemsFor<T>(
321
+ userId: string,
322
+ type: string
309
323
  ) {
310
324
  const table = db.syncQueue;
311
- const items: Array<T> = [];
325
+ const items: Array<SyncItem<T>> = [];
312
326
 
313
327
  await table.where({ type, userId }).each((item) => {
314
- items.push(item.content);
328
+ items.push(item);
315
329
  });
316
330
 
317
331
  return items;
318
332
  }
319
333
 
320
334
  /**
321
- * Returns all currently queued up sync items of the currently signed in user.
335
+ * Returns the content of all currently queued up sync items of the currently signed in user.
322
336
  * @param type The identifying type of the synchronization items to be returned.
323
337
  */
324
338
  export async function getSynchronizationItems<T>(type: string) {
@@ -326,6 +340,15 @@ export async function getSynchronizationItems<T>(type: string) {
326
340
  return await getSynchronizationItemsFor<T>(userId, type);
327
341
  }
328
342
 
343
+ /**
344
+ * Returns all currently queued up sync items of the currently signed in user.
345
+ * @param type The identifying type of the synchronization items to be returned.
346
+ */
347
+ export async function getFullSynchronizationItems<T>(type: string) {
348
+ const userId = await getUserId();
349
+ return await getFullSynchronizationItemsFor<T>(userId, type);
350
+ }
351
+
329
352
  /**
330
353
  * Returns a queued sync item with the given ID or `undefined` if no such item exists.
331
354
  * @param id The ID of the requested sync item.
package/src/uuid.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /** @module @category Offline */
1
2
  import { v4 } from "uuid";
2
3
 
3
4
  export const offlineUuidPrefix = "OFFLINE+";
package/webpack.config.js CHANGED
@@ -19,7 +19,7 @@ module.exports = (env) => ({
19
19
  {
20
20
  test: /\.m?(js|ts|tsx)$/,
21
21
  exclude: /(node_modules|bower_components)/,
22
- use: "babel-loader",
22
+ use: "swc-loader",
23
23
  },
24
24
  ],
25
25
  },
package/.babelrc DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "presets": [
3
- "@babel/preset-env",
4
- "@babel/preset-typescript",
5
- "@babel/preset-react"
6
- ]
7
- }
package/src/events.ts DELETED
@@ -1,18 +0,0 @@
1
- import { NetworkRequestFailedEvent } from "./service-worker-events";
2
-
3
- const networkRequestFailedEventName = "openmrs:network-request-failed";
4
-
5
- export function dispatchNetworkRequestFailed(data: NetworkRequestFailedEvent) {
6
- window.dispatchEvent(
7
- new CustomEvent(networkRequestFailedEventName, { detail: data })
8
- );
9
- }
10
-
11
- export function subscribeNetworkRequestFailed(
12
- cb: (data: NetworkRequestFailedEvent) => void
13
- ) {
14
- const handler = (ev: CustomEvent) => cb(ev.detail);
15
- window.addEventListener(networkRequestFailedEventName, handler);
16
- return () =>
17
- window.removeEventListener(networkRequestFailedEventName, handler);
18
- }
package/src/patches.ts DELETED
@@ -1,7 +0,0 @@
1
- export function patchXMLHttpRequest() {
2
- const send = XMLHttpRequest.prototype.send;
3
-
4
- XMLHttpRequest.prototype.send = function (...args) {
5
- return send.apply(this, args);
6
- };
7
- }
@@ -1,15 +0,0 @@
1
- export interface OmrsServiceWorkerEvent<TypeIdentifier extends string> {
2
- type: TypeIdentifier;
3
- }
4
-
5
- export interface NetworkRequestFailedEvent
6
- extends OmrsServiceWorkerEvent<"networkRequestFailed"> {
7
- request: {
8
- url: string;
9
- method: string;
10
- headers: Record<string, string>;
11
- body: string;
12
- };
13
- }
14
-
15
- export type KnownOmrsServiceWorkerEvents = NetworkRequestFailedEvent;