New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@dhis2/app-service-offline

Package Overview
Dependencies
Maintainers
14
Versions
76
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@dhis2/app-service-offline - npm Package Compare versions

Comparing version 2.10.0-pwa.1 to 2.10.0-pwa.2

build/cjs/types.js

60

build/cjs/__tests__/integration.test.js

@@ -55,3 +55,4 @@ "use strict";

const TestSection = ({
id
id,
children
}) => /*#__PURE__*/_react2.default.createElement(_cacheableSection.CacheableSection, {

@@ -65,3 +66,3 @@ id: id,

countsObj: renderCounts
}));
}), children);

@@ -95,3 +96,4 @@ const TestSingleSection = props => {

afterEach(() => {
jest.clearAllMocks();
jest.clearAllMocks() // This syntax appeases typescript:
;
console.error.mockRestore();

@@ -286,2 +288,54 @@ (0, _renderCounter.resetRenderCounts)(renderCounts);

});
});
describe('useCacheableSection can be used inside a child of CacheableSection', () => {
const ChildTest = props => {
// Props are spread so they can be overwritten
return /*#__PURE__*/_react2.default.createElement(_offlineProvider.OfflineProvider, _extends({
offlineInterface: _testMocks.mockOfflineInterface
}, props), /*#__PURE__*/_react2.default.createElement(TestSection, _extends({
id: '1'
}, props), /*#__PURE__*/_react2.default.createElement(TestControls, _extends({
id: '1'
}, props))));
};
it('handles a successful recording', async done => {
const {
getByTestId,
queryByTestId
} = _react.screen;
const onStarted = () => {
expect(getByTestId(/recording-state/)).toHaveTextContent('recording');
expect(getByTestId(/loading-mask/)).toBeInTheDocument();
expect(getByTestId(/section-rc/)).toBeInTheDocument();
};
const onCompleted = () => {
expect(getByTestId(/recording-state/)).toHaveTextContent('default');
expect(queryByTestId(/loading-mask/)).not.toBeInTheDocument();
done();
};
const recordingOptions = {
onStarted,
onCompleted
};
const makeRecordingHandler = startRecording => {
return () => startRecording(recordingOptions);
};
(0, _react.render)( /*#__PURE__*/_react2.default.createElement(ChildTest, {
makeRecordingHandler: makeRecordingHandler
}));
await (0, _react.act)(async () => {
_react.fireEvent.click(getByTestId(/start-recording/));
}); // At this stage, should be pending
// - In this test case, 'controls' should not be rendered
expect(queryByTestId(/recording-state/)).not.toBeInTheDocument();
expect(queryByTestId(/section-rc/)).not.toBeInTheDocument();
expect.assertions(7);
});
});

6

build/cjs/lib/__tests__/offline-provider.test.js

@@ -31,3 +31,4 @@ "use strict";

afterEach(() => {
jest.clearAllMocks();
jest.clearAllMocks() // syntax needed to appease typescript
;
console.error.mockRestore();

@@ -82,3 +83,3 @@ });

await (0, _react.waitFor)(() => getByTestId('sections').textContent !== '{}');
const textContent = JSON.parse(getByTestId('sections').textContent);
const textContent = JSON.parse(getByTestId('sections').textContent || '');
expect(textContent).toEqual({

@@ -97,2 +98,3 @@ 1: {

return /*#__PURE__*/_react2.default.createElement(_cacheableSection.CacheableSection, {
loadingMask: /*#__PURE__*/_react2.default.createElement("div", null),
id: 'id'

@@ -99,0 +101,0 @@ }, /*#__PURE__*/_react2.default.createElement("div", {

@@ -15,3 +15,3 @@ "use strict";

result
} = (0, _reactHooks.renderHook)((...args) => (0, _onlineStatus.useOnlineStatus)(...args));
} = (0, _reactHooks.renderHook)(() => (0, _onlineStatus.useOnlineStatus)());
expect(result.current.online).toBe(true);

@@ -24,3 +24,3 @@ expect(result.current.offline).toBe(false);

result
} = (0, _reactHooks.renderHook)((...args) => (0, _onlineStatus.useOnlineStatus)(...args));
} = (0, _reactHooks.renderHook)(() => (0, _onlineStatus.useOnlineStatus)());
expect(result.current.online).toBe(false);

@@ -39,8 +39,6 @@ expect(result.current.offline).toBe(true);

waitForNextUpdate
} = (0, _reactHooks.renderHook)((...args) => (0, _onlineStatus.useOnlineStatus)(...args));
} = (0, _reactHooks.renderHook)(() => (0, _onlineStatus.useOnlineStatus)());
(0, _reactHooks.act)(() => {
// Trigger callback captured by addEventListener mock
events.offline({
type: 'offline'
});
events.offline(new Event('offline'));
}); // Wait for debounce

@@ -61,7 +59,5 @@

waitForNextUpdate
} = (0, _reactHooks.renderHook)((...args) => (0, _onlineStatus.useOnlineStatus)(...args));
} = (0, _reactHooks.renderHook)(() => (0, _onlineStatus.useOnlineStatus)());
(0, _reactHooks.act)(() => {
events.online({
type: 'online'
});
events.online(new Event('online'));
}); // Wait for debounce

@@ -85,14 +81,8 @@

waitForNextUpdate
} = (0, _reactHooks.renderHook)((...args) => (0, _onlineStatus.useOnlineStatus)(...args));
} = (0, _reactHooks.renderHook)(() => (0, _onlineStatus.useOnlineStatus)());
await (0, _reactHooks.act)(async () => {
// Multiple events in succession
events.offline({
type: 'offline'
});
events.online({
type: 'online'
});
events.offline({
type: 'offline'
});
events.offline(new Event('offline'));
events.online(new Event('online'));
events.offline(new Event('offline'));
}); // Immediately, nothing should happen

@@ -122,11 +112,5 @@

// Multiple events in succession
events.offline({
type: 'offline'
});
events.online({
type: 'online'
});
events.offline({
type: 'offline'
});
events.offline(new Event('offline'));
events.online(new Event('online'));
events.offline(new Event('offline'));
}); // Immediately, nothing should happen

@@ -133,0 +117,0 @@

@@ -30,3 +30,4 @@ "use strict";

afterEach(() => {
jest.clearAllMocks();
jest.clearAllMocks() // This syntax appeases typescript:
;
console.error.mockRestore();

@@ -33,0 +34,0 @@ });

@@ -22,5 +22,2 @@ "use strict";

// Functions in here use the global state service to manage cacheable section
// state in a performant way
/**

@@ -87,7 +84,9 @@ * Helper that transforms an array of cached section objects from the IndexedDB

_react.default.useEffect(() => {
offlineInterface.getCachedSections().then(sections => {
store.mutate(state => ({ ...state,
cachedSections: getSectionsById(sections)
}));
});
if (offlineInterface) {
offlineInterface.getCachedSections().then(sections => {
store.mutate(state => ({ ...state,
cachedSections: getSectionsById(sections)
}));
});
}
}, [store, offlineInterface]);

@@ -103,2 +102,3 @@

};
/**

@@ -111,3 +111,2 @@ * Uses an optimized global state to manage 'recording state' values without

*/
function useRecordingState(id) {

@@ -152,2 +151,3 @@ const [recordingState] = (0, _globalStateService.useGlobalState)(state => state.recordingStates[id]);

}
/**

@@ -158,4 +158,2 @@ * Uses global state to manage an object of cached sections' statuses

*/
function useCachedSections() {

@@ -189,2 +187,3 @@ const [cachedSections] = (0, _globalStateService.useGlobalState)(state => state.cachedSections);

}
/**

@@ -197,4 +196,2 @@ * Uses global state to manage the cached status of just one section, which

*/
function useCachedSection(id) {

@@ -201,0 +198,0 @@ const [status] = (0, _globalStateService.useGlobalState)(state => state.cachedSections[id]);

@@ -29,2 +29,3 @@ "use strict";

};
/**

@@ -39,3 +40,2 @@ * Returns the main controls for a cacheable section and manages recording

*/
function useCacheableSection(id) {

@@ -55,6 +55,13 @@ const offlineInterface = (0, _offlineInterface.useOfflineInterface)();

(0, _react.useEffect)(() => {
// On mount, add recording state for this ID to context
setRecordingState(recordingStates.default); // On unnmount, remove recording state
// On mount, add recording state for this ID to context if needed
if (!recordingState) {
setRecordingState(recordingStates.default);
} // On unnmount, remove recording state if not recording
return removeRecordingState;
return () => {
if (recordingState && recordingState !== recordingStates.recording && recordingState !== recordingStates.pending) {
removeRecordingState();
}
};
}, []); // eslint-disable-line react-hooks/exhaustive-deps

@@ -74,13 +81,13 @@

recordingTimeoutDelay,
onStarted: (...args) => {
onRecordingStarted(...args);
onStarted && onStarted(...args);
onStarted: () => {
onRecordingStarted();
onStarted && onStarted();
},
onCompleted: (...args) => {
onRecordingCompleted(...args);
onCompleted && onCompleted(...args);
onCompleted: () => {
onRecordingCompleted();
onCompleted && onCompleted();
},
onError: (...args) => {
onRecordingError(...args);
onError && onError(...args);
onError: error => {
onRecordingError(error);
onError && onError(error);
}

@@ -114,2 +121,3 @@ }).then(() => setRecordingState(recordingStates.pending));

}
/**

@@ -126,4 +134,2 @@ * Used to wrap the relevant component to be recorded and saved offline.

*/
function CacheableSection({

@@ -143,5 +149,8 @@ id,

if (recordingState === recordingStates.error) return children; // Handling rendering with the following conditions prevents an unncessary
if (recordingState === recordingStates.error) {
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, children);
} // Handling rendering with the following conditions prevents an unncessary
// rerender after successful recording
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, recordingState === recordingStates.recording && loadingMask, recordingState !== recordingStates.pending && children);

@@ -148,0 +157,0 @@ }

@@ -6,3 +6,4 @@ "use strict";

});
exports.useGlobalStateMutation = exports.useGlobalState = exports.GlobalStateProvider = exports.createStore = void 0;
exports.useGlobalStateMutation = useGlobalStateMutation;
exports.useGlobalState = exports.GlobalStateProvider = exports.createStore = void 0;

@@ -88,3 +89,3 @@ var _isEqual = _interopRequireDefault(require("lodash/isEqual"));

const useGlobalStateMutation = mutationCreator => {
function useGlobalStateMutation(mutationCreator) {
const store = useGlobalStateStore();

@@ -94,4 +95,2 @@ return (0, _react.useCallback)((...args) => {

}, [mutationCreator, store]);
};
exports.useGlobalStateMutation = useGlobalStateMutation;
}

@@ -21,3 +21,12 @@ "use strict";

const OfflineContext = /*#__PURE__*/(0, _react.createContext)();
// This is to prevent 'offlineInterface could be null' type-checking errors
const noopOfflineInterface = {
pwaEnabled: false,
init: () => () => null,
startRecording: async () => undefined,
getCachedSections: async () => [],
removeSection: async () => false
};
const OfflineInterfaceContext = /*#__PURE__*/(0, _react.createContext)(noopOfflineInterface);
/**

@@ -31,3 +40,2 @@ * Receives an OfflineInterface instance as a prop (presumably from the app

*/
function OfflineInterfaceProvider({

@@ -60,3 +68,3 @@ offlineInterface,

return /*#__PURE__*/_react.default.createElement(OfflineContext.Provider, {
return /*#__PURE__*/_react.default.createElement(OfflineInterfaceContext.Provider, {
value: offlineInterface

@@ -74,6 +82,6 @@ }, children);

function useOfflineInterface() {
const offlineInterface = (0, _react.useContext)(OfflineContext);
const offlineInterface = (0, _react.useContext)(OfflineInterfaceContext);
if (offlineInterface === undefined) {
throw new Error('useOfflineInterface must be used within an OfflineInterfaceProvider. Make sure `pwa: { enabled: true }` in `d2.config.js`.');
throw new Error('Offline interface context not found. If this app is using the app platform, make sure `pwa: { enabled: true }` is in d2.config.js. If this is not a platform app, make sure your app is wrapped with an app-runtime <Provider> or an <OfflineProvider> from app-service-offline.');
}

@@ -80,0 +88,0 @@

@@ -26,3 +26,3 @@ "use strict";

if (!offlineInterface) {
return children;
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, children);
} // If PWA is not enabled, just init interface to make sure new SW gets

@@ -40,3 +40,3 @@ // activated with code that unregisters SW. Not technically necessary if a

});
return children;
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, children);
}

@@ -43,0 +43,0 @@

@@ -12,3 +12,2 @@ "use strict";

// eslint-disable-next-line react/prop-types
const RenderCounter = ({

@@ -15,0 +14,0 @@ id,

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
/* eslint-disable react/prop-types */
import { act, fireEvent, render, screen } from '@testing-library/react';

@@ -46,3 +45,4 @@ import React from 'react';

const TestSection = ({
id
id,
children
}) => /*#__PURE__*/React.createElement(CacheableSection, {

@@ -56,3 +56,3 @@ id: id,

countsObj: renderCounts
}));
}), children);

@@ -86,3 +86,4 @@ const TestSingleSection = props => {

afterEach(() => {
jest.clearAllMocks();
jest.clearAllMocks() // This syntax appeases typescript:
;
console.error.mockRestore();

@@ -277,2 +278,54 @@ resetRenderCounts(renderCounts);

});
});
describe('useCacheableSection can be used inside a child of CacheableSection', () => {
const ChildTest = props => {
// Props are spread so they can be overwritten
return /*#__PURE__*/React.createElement(OfflineProvider, _extends({
offlineInterface: mockOfflineInterface
}, props), /*#__PURE__*/React.createElement(TestSection, _extends({
id: '1'
}, props), /*#__PURE__*/React.createElement(TestControls, _extends({
id: '1'
}, props))));
};
it('handles a successful recording', async done => {
const {
getByTestId,
queryByTestId
} = screen;
const onStarted = () => {
expect(getByTestId(/recording-state/)).toHaveTextContent('recording');
expect(getByTestId(/loading-mask/)).toBeInTheDocument();
expect(getByTestId(/section-rc/)).toBeInTheDocument();
};
const onCompleted = () => {
expect(getByTestId(/recording-state/)).toHaveTextContent('default');
expect(queryByTestId(/loading-mask/)).not.toBeInTheDocument();
done();
};
const recordingOptions = {
onStarted,
onCompleted
};
const makeRecordingHandler = startRecording => {
return () => startRecording(recordingOptions);
};
render( /*#__PURE__*/React.createElement(ChildTest, {
makeRecordingHandler: makeRecordingHandler
}));
await act(async () => {
fireEvent.click(getByTestId(/start-recording/));
}); // At this stage, should be pending
// - In this test case, 'controls' should not be rendered
expect(queryByTestId(/recording-state/)).not.toBeInTheDocument();
expect(queryByTestId(/section-rc/)).not.toBeInTheDocument();
expect.assertions(7);
});
});

@@ -21,3 +21,4 @@ import { render, screen, waitFor } from '@testing-library/react';

afterEach(() => {
jest.clearAllMocks();
jest.clearAllMocks() // syntax needed to appease typescript
;
console.error.mockRestore();

@@ -72,3 +73,3 @@ });

await waitFor(() => getByTestId('sections').textContent !== '{}');
const textContent = JSON.parse(getByTestId('sections').textContent);
const textContent = JSON.parse(getByTestId('sections').textContent || '');
expect(textContent).toEqual({

@@ -87,2 +88,3 @@ 1: {

return /*#__PURE__*/React.createElement(CacheableSection, {
loadingMask: /*#__PURE__*/React.createElement("div", null),
id: 'id'

@@ -89,0 +91,0 @@ }, /*#__PURE__*/React.createElement("div", {

@@ -11,3 +11,3 @@ import { act, renderHook } from '@testing-library/react-hooks';

result
} = renderHook((...args) => useOnlineStatus(...args));
} = renderHook(() => useOnlineStatus());
expect(result.current.online).toBe(true);

@@ -20,3 +20,3 @@ expect(result.current.offline).toBe(false);

result
} = renderHook((...args) => useOnlineStatus(...args));
} = renderHook(() => useOnlineStatus());
expect(result.current.online).toBe(false);

@@ -35,8 +35,6 @@ expect(result.current.offline).toBe(true);

waitForNextUpdate
} = renderHook((...args) => useOnlineStatus(...args));
} = renderHook(() => useOnlineStatus());
act(() => {
// Trigger callback captured by addEventListener mock
events.offline({
type: 'offline'
});
events.offline(new Event('offline'));
}); // Wait for debounce

@@ -57,7 +55,5 @@

waitForNextUpdate
} = renderHook((...args) => useOnlineStatus(...args));
} = renderHook(() => useOnlineStatus());
act(() => {
events.online({
type: 'online'
});
events.online(new Event('online'));
}); // Wait for debounce

@@ -81,14 +77,8 @@

waitForNextUpdate
} = renderHook((...args) => useOnlineStatus(...args));
} = renderHook(() => useOnlineStatus());
await act(async () => {
// Multiple events in succession
events.offline({
type: 'offline'
});
events.online({
type: 'online'
});
events.offline({
type: 'offline'
});
events.offline(new Event('offline'));
events.online(new Event('online'));
events.offline(new Event('offline'));
}); // Immediately, nothing should happen

@@ -118,11 +108,5 @@

// Multiple events in succession
events.offline({
type: 'offline'
});
events.online({
type: 'online'
});
events.offline({
type: 'offline'
});
events.offline(new Event('offline'));
events.online(new Event('online'));
events.offline(new Event('offline'));
}); // Immediately, nothing should happen

@@ -129,0 +113,0 @@

@@ -21,3 +21,4 @@ /* eslint-disable react/display-name, react/prop-types */

afterEach(() => {
jest.clearAllMocks();
jest.clearAllMocks() // This syntax appeases typescript:
;
console.error.mockRestore();

@@ -24,0 +25,0 @@ });

@@ -14,3 +14,2 @@ import PropTypes from 'prop-types';

*/
function getSectionsById(sectionsArray) {

@@ -69,7 +68,9 @@ return sectionsArray.reduce((result, {

React.useEffect(() => {
offlineInterface.getCachedSections().then(sections => {
store.mutate(state => ({ ...state,
cachedSections: getSectionsById(sections)
}));
});
if (offlineInterface) {
offlineInterface.getCachedSections().then(sections => {
store.mutate(state => ({ ...state,
cachedSections: getSectionsById(sections)
}));
});
}
}, [store, offlineInterface]);

@@ -83,2 +84,3 @@ return /*#__PURE__*/React.createElement(GlobalStateProvider, {

};
/**

@@ -91,3 +93,2 @@ * Uses an optimized global state to manage 'recording state' values without

*/
export function useRecordingState(id) {

@@ -131,2 +132,3 @@ const [recordingState] = useGlobalState(state => state.recordingStates[id]);

}
/**

@@ -137,4 +139,2 @@ * Uses global state to manage an object of cached sections' statuses

*/
export function useCachedSections() {

@@ -168,2 +168,3 @@ const [cachedSections] = useGlobalState(state => state.cachedSections);

}
/**

@@ -176,3 +177,2 @@ * Uses global state to manage the cached status of just one section, which

*/
export function useCachedSection(id) {

@@ -179,0 +179,0 @@ const [status] = useGlobalState(state => state.cachedSections[id]);

@@ -11,2 +11,3 @@ import PropTypes from 'prop-types';

};
/**

@@ -21,3 +22,2 @@ * Returns the main controls for a cacheable section and manages recording

*/
export function useCacheableSection(id) {

@@ -37,6 +37,13 @@ const offlineInterface = useOfflineInterface();

useEffect(() => {
// On mount, add recording state for this ID to context
setRecordingState(recordingStates.default); // On unnmount, remove recording state
// On mount, add recording state for this ID to context if needed
if (!recordingState) {
setRecordingState(recordingStates.default);
} // On unnmount, remove recording state if not recording
return removeRecordingState;
return () => {
if (recordingState && recordingState !== recordingStates.recording && recordingState !== recordingStates.pending) {
removeRecordingState();
}
};
}, []); // eslint-disable-line react-hooks/exhaustive-deps

@@ -56,13 +63,13 @@

recordingTimeoutDelay,
onStarted: (...args) => {
onRecordingStarted(...args);
onStarted && onStarted(...args);
onStarted: () => {
onRecordingStarted();
onStarted && onStarted();
},
onCompleted: (...args) => {
onRecordingCompleted(...args);
onCompleted && onCompleted(...args);
onCompleted: () => {
onRecordingCompleted();
onCompleted && onCompleted();
},
onError: (...args) => {
onRecordingError(...args);
onError && onError(...args);
onError: error => {
onRecordingError(error);
onError && onError(error);
}

@@ -96,2 +103,3 @@ }).then(() => setRecordingState(recordingStates.pending));

}
/**

@@ -108,3 +116,2 @@ * Used to wrap the relevant component to be recorded and saved offline.

*/
export function CacheableSection({

@@ -124,5 +131,8 @@ id,

if (recordingState === recordingStates.error) return children; // Handling rendering with the following conditions prevents an unncessary
if (recordingState === recordingStates.error) {
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
} // Handling rendering with the following conditions prevents an unncessary
// rerender after successful recording
return /*#__PURE__*/React.createElement(React.Fragment, null, recordingState === recordingStates.recording && loadingMask, recordingState !== recordingStates.pending && children);

@@ -129,0 +139,0 @@ }

import isEqual from 'lodash/isEqual';
import PropTypes from 'prop-types';
import React, { useEffect, useCallback, useContext, useState } from 'react'; // This file creates a redux-like state management service using React context
import React, { useEffect, useCallback, useContext, useState } from 'react';
// This file creates a redux-like state management service using React context
// that minimizes unnecessary rerenders that consume the context.
// See more at https://github.com/amcgee/state-service-poc
const identity = state => state;

@@ -62,3 +63,3 @@

};
export const useGlobalStateMutation = mutationCreator => {
export function useGlobalStateMutation(mutationCreator) {
const store = useGlobalStateStore();

@@ -68,2 +69,2 @@ return useCallback((...args) => {

}, [mutationCreator, store]);
};
}
import { useAlert } from '@dhis2/app-service-alerts';
import PropTypes from 'prop-types';
import React, { createContext, useContext } from 'react';
const OfflineContext = /*#__PURE__*/createContext();
// This is to prevent 'offlineInterface could be null' type-checking errors
const noopOfflineInterface = {
pwaEnabled: false,
init: () => () => null,
startRecording: async () => undefined,
getCachedSections: async () => [],
removeSection: async () => false
};
const OfflineInterfaceContext = /*#__PURE__*/createContext(noopOfflineInterface);
/**

@@ -13,3 +22,2 @@ * Receives an OfflineInterface instance as a prop (presumably from the app

*/
export function OfflineInterfaceProvider({

@@ -40,3 +48,3 @@ offlineInterface,

return /*#__PURE__*/React.createElement(OfflineContext.Provider, {
return /*#__PURE__*/React.createElement(OfflineInterfaceContext.Provider, {
value: offlineInterface

@@ -52,6 +60,6 @@ }, children);

export function useOfflineInterface() {
const offlineInterface = useContext(OfflineContext);
const offlineInterface = useContext(OfflineInterfaceContext);
if (offlineInterface === undefined) {
throw new Error('useOfflineInterface must be used within an OfflineInterfaceProvider. Make sure `pwa: { enabled: true }` in `d2.config.js`.');
throw new Error('Offline interface context not found. If this app is using the app platform, make sure `pwa: { enabled: true }` is in d2.config.js. If this is not a platform app, make sure your app is wrapped with an app-runtime <Provider> or an <OfflineProvider> from app-service-offline.');
}

@@ -58,0 +66,0 @@

@@ -5,4 +5,4 @@ import PropTypes from 'prop-types';

import { OfflineInterfaceProvider } from './offline-interface';
/** A context provider for all the relevant offline contexts */
export function OfflineProvider({

@@ -15,3 +15,3 @@ offlineInterface,

if (!offlineInterface) {
return children;
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
} // If PWA is not enabled, just init interface to make sure new SW gets

@@ -29,3 +29,3 @@ // activated with code that unregisters SW. Not technically necessary if a

});
return children;
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
}

@@ -32,0 +32,0 @@

import debounce from 'lodash/debounce';
import { useState, useEffect, useCallback } from 'react';
/**

@@ -16,3 +17,2 @@ * Returns the browser's online status. Updates in response to 'online' and

*/
export function useOnlineStatus(options) {

@@ -19,0 +19,0 @@ // initialize state to `navigator.onLine` value

@@ -1,3 +0,2 @@

import React from 'react'; // eslint-disable-next-line react/prop-types
import React from 'react';
export const RenderCounter = ({

@@ -4,0 +3,0 @@ id,

{
"name": "@dhis2/app-service-offline",
"description": "A runtime service for online/offline detection and offline caching",
"version": "2.10.0-pwa.1",
"version": "2.10.0-pwa.2",
"main": "./build/cjs/index.js",
"module": "./build/es/index.js",
"types": "build/types/index.d.ts",
"exports": {

@@ -25,9 +26,13 @@ "import": "./build/es/index.js",

"scripts": {
"build": "d2-app-scripts build",
"start": "d2-app-scripts start",
"build:types": "tsc --emitDeclarationOnly --outDir ./build/types",
"build:package": "d2-app-scripts build",
"build": "concurrently -n build,types \"yarn build:package\" \"yarn build:types\"",
"watch": "NODE_ENV=development concurrently -n build,types \"yarn build:package --watch\" \"yarn build:types --watch\"",
"type-check": "tsc --noEmit --allowJs --checkJs",
"type-check:watch": "yarn type-check --watch",
"test": "d2-app-scripts test",
"deploy": "d2-app-scripts deploy"
"coverage": "yarn test --coverage"
},
"peerDependencies": {
"@dhis2/app-service-alerts": "^2.10.0-pwa.1",
"@dhis2/app-service-alerts": "^2.10.0-pwa.2",
"prop-types": "^15.7.2",

@@ -34,0 +39,0 @@ "react": "^16.8.6",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc