quidproquo-web-react 0.0.263 → 0.1.1

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.
Files changed (83) hide show
  1. package/lib/commonjs/api/hooks/index.d.ts +1 -0
  2. package/lib/commonjs/api/hooks/index.js +1 -0
  3. package/lib/commonjs/api/hooks/useApiRequestActionProcessor.d.ts +5 -0
  4. package/lib/commonjs/api/hooks/useApiRequestActionProcessor.js +22 -0
  5. package/lib/commonjs/api/hooks/useAuthenticatedNetworkRequest.js +2 -2
  6. package/lib/commonjs/api/hooks/useNetworkRequest.js +2 -2
  7. package/lib/commonjs/auth/hooks/useRefreshTokens.js +11 -3
  8. package/lib/commonjs/dateTime/DateTime.d.ts +28 -0
  9. package/lib/commonjs/dateTime/DateTime.js +57 -0
  10. package/lib/commonjs/dateTime/hooks/index.d.ts +1 -0
  11. package/lib/commonjs/dateTime/hooks/index.js +17 -0
  12. package/lib/commonjs/dateTime/hooks/useTimeAgo.d.ts +6 -0
  13. package/lib/commonjs/dateTime/hooks/useTimeAgo.js +26 -0
  14. package/lib/commonjs/dateTime/index.d.ts +2 -0
  15. package/lib/commonjs/dateTime/index.js +18 -0
  16. package/lib/commonjs/dateTime/logic/formatTimeAgo.d.ts +11 -0
  17. package/lib/commonjs/dateTime/logic/formatTimeAgo.js +49 -0
  18. package/lib/commonjs/dateTime/logic/index.d.ts +1 -0
  19. package/lib/commonjs/dateTime/logic/index.js +17 -0
  20. package/lib/commonjs/hooks/asmj/QpqContextProvider.d.ts +2 -1
  21. package/lib/commonjs/hooks/asmj/QpqContextProvider.js +6 -1
  22. package/lib/commonjs/hooks/asmj/QpqRuntimeEffectCatcher.d.ts +2 -2
  23. package/lib/commonjs/hooks/index.d.ts +1 -0
  24. package/lib/commonjs/hooks/index.js +1 -0
  25. package/lib/commonjs/hooks/useComputed.d.ts +1 -0
  26. package/lib/commonjs/hooks/useComputed.js +7 -0
  27. package/lib/commonjs/index.d.ts +1 -0
  28. package/lib/commonjs/index.js +1 -0
  29. package/lib/commonjs/websocket/WebSocketAuthSync/WebSocketAuthContext.d.ts +1 -0
  30. package/lib/commonjs/websocket/WebSocketAuthSync/WebSocketAuthContext.js +5 -0
  31. package/lib/commonjs/websocket/WebSocketAuthSync/WebSocketAuthSync.js +3 -3
  32. package/lib/commonjs/websocket/WebSocketAuthSync/hooks/index.d.ts +1 -0
  33. package/lib/commonjs/websocket/WebSocketAuthSync/hooks/index.js +1 -0
  34. package/lib/commonjs/websocket/WebSocketAuthSync/hooks/useWebSocketIsAuthenticated.d.ts +1 -0
  35. package/lib/commonjs/websocket/WebSocketAuthSync/hooks/useWebSocketIsAuthenticated.js +9 -0
  36. package/lib/commonjs/websocket/WebSocketAuthSync/hooks/useWebsocketAuthSync.d.ts +1 -1
  37. package/lib/commonjs/websocket/WebSocketAuthSync/hooks/useWebsocketAuthSync.js +11 -8
  38. package/lib/commonjs/websocket/WebSocketAuthSync/index.d.ts +1 -0
  39. package/lib/commonjs/websocket/WebSocketAuthSync/index.js +1 -0
  40. package/lib/commonjs/websocket/hooks/useSubscribeToWebSocketEvent.js +4 -2
  41. package/lib/commonjs/websocket/hooks/useSubscribeToWebsocket.js +4 -2
  42. package/lib/esm/api/hooks/index.d.ts +1 -0
  43. package/lib/esm/api/hooks/index.js +1 -0
  44. package/lib/esm/api/hooks/useApiRequestActionProcessor.d.ts +5 -0
  45. package/lib/esm/api/hooks/useApiRequestActionProcessor.js +15 -0
  46. package/lib/esm/api/hooks/useAuthenticatedNetworkRequest.js +1 -1
  47. package/lib/esm/api/hooks/useNetworkRequest.js +1 -1
  48. package/lib/esm/auth/hooks/useRefreshTokens.js +11 -3
  49. package/lib/esm/dateTime/DateTime.d.ts +28 -0
  50. package/lib/esm/dateTime/DateTime.js +54 -0
  51. package/lib/esm/dateTime/hooks/index.d.ts +1 -0
  52. package/lib/esm/dateTime/hooks/index.js +1 -0
  53. package/lib/esm/dateTime/hooks/useTimeAgo.d.ts +6 -0
  54. package/lib/esm/dateTime/hooks/useTimeAgo.js +22 -0
  55. package/lib/esm/dateTime/index.d.ts +2 -0
  56. package/lib/esm/dateTime/index.js +2 -0
  57. package/lib/esm/dateTime/logic/formatTimeAgo.d.ts +11 -0
  58. package/lib/esm/dateTime/logic/formatTimeAgo.js +44 -0
  59. package/lib/esm/dateTime/logic/index.d.ts +1 -0
  60. package/lib/esm/dateTime/logic/index.js +1 -0
  61. package/lib/esm/hooks/asmj/QpqContextProvider.d.ts +2 -1
  62. package/lib/esm/hooks/asmj/QpqContextProvider.js +4 -0
  63. package/lib/esm/hooks/asmj/QpqRuntimeEffectCatcher.d.ts +2 -2
  64. package/lib/esm/hooks/index.d.ts +1 -0
  65. package/lib/esm/hooks/index.js +1 -0
  66. package/lib/esm/hooks/useComputed.d.ts +1 -0
  67. package/lib/esm/hooks/useComputed.js +4 -0
  68. package/lib/esm/index.d.ts +1 -0
  69. package/lib/esm/index.js +1 -0
  70. package/lib/esm/websocket/WebSocketAuthSync/WebSocketAuthContext.d.ts +1 -0
  71. package/lib/esm/websocket/WebSocketAuthSync/WebSocketAuthContext.js +2 -0
  72. package/lib/esm/websocket/WebSocketAuthSync/WebSocketAuthSync.js +4 -4
  73. package/lib/esm/websocket/WebSocketAuthSync/hooks/index.d.ts +1 -0
  74. package/lib/esm/websocket/WebSocketAuthSync/hooks/index.js +1 -0
  75. package/lib/esm/websocket/WebSocketAuthSync/hooks/useWebSocketIsAuthenticated.d.ts +1 -0
  76. package/lib/esm/websocket/WebSocketAuthSync/hooks/useWebSocketIsAuthenticated.js +5 -0
  77. package/lib/esm/websocket/WebSocketAuthSync/hooks/useWebsocketAuthSync.d.ts +1 -1
  78. package/lib/esm/websocket/WebSocketAuthSync/hooks/useWebsocketAuthSync.js +14 -11
  79. package/lib/esm/websocket/WebSocketAuthSync/index.d.ts +1 -0
  80. package/lib/esm/websocket/WebSocketAuthSync/index.js +1 -0
  81. package/lib/esm/websocket/hooks/useSubscribeToWebSocketEvent.js +4 -2
  82. package/lib/esm/websocket/hooks/useSubscribeToWebsocket.js +4 -2
  83. package/package.json +10 -8
@@ -1,2 +1,3 @@
1
+ export * from './useApiRequestActionProcessor';
1
2
  export * from './useAuthenticatedNetworkRequest';
2
3
  export * from './useNetworkRequest';
@@ -14,5 +14,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./useApiRequestActionProcessor"), exports);
17
18
  __exportStar(require("./useAuthenticatedNetworkRequest"), exports);
18
19
  __exportStar(require("./useNetworkRequest"), exports);
@@ -0,0 +1,5 @@
1
+ import { ActionProcessorListResolver } from 'quidproquo-core';
2
+ export type UseApiRequestActionProcessorOptions = {
3
+ resolveServiceBaseUrl?: (service: string) => string;
4
+ };
5
+ export declare const useApiRequestActionProcessor: (options?: UseApiRequestActionProcessorOptions) => ActionProcessorListResolver;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useApiRequestActionProcessor = void 0;
4
+ const quidproquo_actionprocessor_web_1 = require("quidproquo-actionprocessor-web");
5
+ const react_1 = require("react");
6
+ const hooks_1 = require("../../auth/hooks");
7
+ const hooks_2 = require("../../baseUrl/hooks");
8
+ const useApiRequestActionProcessor = (options) => {
9
+ const accessToken = (0, hooks_1.useAuthAccessToken)();
10
+ const { getApiUrl } = (0, hooks_2.useBaseUrlResolvers)();
11
+ // Hold the token in a ref so the processor closure always reads the current value.
12
+ const tokenRef = (0, react_1.useRef)(accessToken);
13
+ tokenRef.current = accessToken;
14
+ return (0, react_1.useMemo)(() => {
15
+ var _a;
16
+ return (0, quidproquo_actionprocessor_web_1.createApiRequestActionProcessor)({
17
+ getHeaders: () => (tokenRef.current ? { Authorization: `Bearer ${tokenRef.current}` } : {}),
18
+ resolveServiceBaseUrl: (_a = options === null || options === void 0 ? void 0 : options.resolveServiceBaseUrl) !== null && _a !== void 0 ? _a : (() => getApiUrl()),
19
+ });
20
+ }, [options === null || options === void 0 ? void 0 : options.resolveServiceBaseUrl, getApiUrl]);
21
+ };
22
+ exports.useApiRequestActionProcessor = useApiRequestActionProcessor;
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useAuthenticatedNetworkRequest = void 0;
4
- const quidproquo_web_1 = require("quidproquo-web");
4
+ const quidproquo_webserver_1 = require("quidproquo-webserver");
5
5
  const auth_1 = require("../../auth");
6
6
  const hooks_1 = require("../../hooks");
7
7
  const useAuthenticatedNetworkRequest = (payload) => {
8
8
  const authToken = (0, auth_1.useAuthAccessToken)();
9
9
  const payloadWithAuthHeaders = authToken
10
10
  ? Object.assign(Object.assign({}, payload), { headers: Object.assign(Object.assign({}, (payload.headers || {})), { Authorization: `Bearer ${authToken}` }) }) : payload;
11
- const requeser = (0, hooks_1.useFastCallback)(() => (0, quidproquo_web_1.preformNetworkRequest)(payloadWithAuthHeaders));
11
+ const requeser = (0, hooks_1.useFastCallback)(() => (0, quidproquo_webserver_1.preformNetworkRequest)(payloadWithAuthHeaders));
12
12
  return requeser;
13
13
  };
14
14
  exports.useAuthenticatedNetworkRequest = useAuthenticatedNetworkRequest;
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useNetworkRequest = void 0;
4
- const quidproquo_web_1 = require("quidproquo-web");
4
+ const quidproquo_webserver_1 = require("quidproquo-webserver");
5
5
  const hooks_1 = require("../../hooks");
6
6
  const useNetworkRequest = (payload) => {
7
- const requeser = (0, hooks_1.useFastCallback)(() => (0, quidproquo_web_1.preformNetworkRequest)(payload));
7
+ const requeser = (0, hooks_1.useFastCallback)(() => (0, quidproquo_webserver_1.preformNetworkRequest)(payload));
8
8
  return requeser;
9
9
  };
10
10
  exports.useNetworkRequest = useNetworkRequest;
@@ -2,7 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useRefreshTokens = void 0;
4
4
  const react_1 = require("react");
5
+ const useFastCallback_1 = require("../../hooks/useFastCallback");
5
6
  const useRefreshTokens = (authenticationInfo, refreshTokens) => {
7
+ const stableRefreshTokens = (0, useFastCallback_1.useFastCallback)(refreshTokens);
6
8
  const refresh = () => {
7
9
  if (authenticationInfo && authenticationInfo.refreshToken && authenticationInfo.expiresAt) {
8
10
  const now = new Date().toISOString();
@@ -12,12 +14,12 @@ const useRefreshTokens = (authenticationInfo, refreshTokens) => {
12
14
  const refreshTime = timeToExpire - bufferTime;
13
15
  if (refreshTime > 0) {
14
16
  return setTimeout(() => {
15
- refreshTokens(authenticationInfo);
17
+ stableRefreshTokens(authenticationInfo);
16
18
  }, refreshTime);
17
19
  }
18
20
  else {
19
21
  // If the token is already expired or very close to expiration, refresh immediately
20
- refreshTokens(authenticationInfo);
22
+ stableRefreshTokens(authenticationInfo);
21
23
  }
22
24
  }
23
25
  return null;
@@ -30,6 +32,12 @@ const useRefreshTokens = (authenticationInfo, refreshTokens) => {
30
32
  clearTimeout(timerId);
31
33
  }
32
34
  };
33
- }, [authenticationInfo, refreshTokens]);
35
+ // Key on the stable primitives that actually drive a refresh, not the
36
+ // authenticationInfo object itself. Callers commonly derive that object
37
+ // fresh on every render (e.g. an unmemoized selector), so depending on its
38
+ // reference would re-run this effect every render — and when the token is
39
+ // expired/near-expiry the "refresh immediately" branch would then fire a
40
+ // network refresh on every render, an unbounded loop.
41
+ }, [authenticationInfo === null || authenticationInfo === void 0 ? void 0 : authenticationInfo.expiresAt, authenticationInfo === null || authenticationInfo === void 0 ? void 0 : authenticationInfo.refreshToken]);
34
42
  };
35
43
  exports.useRefreshTokens = useRefreshTokens;
@@ -0,0 +1,28 @@
1
+ type DateInput = {
2
+ isoDateTime: string;
3
+ } | {
4
+ unixTimestampMs: number;
5
+ } | {
6
+ date: Date;
7
+ };
8
+ export type DateTimeProps = DateInput & {
9
+ /** Locale(s) for both the absolute and relative formatting. Defaults to the runtime locale. */
10
+ locale?: string | string[];
11
+ /** Options for the absolute date/time. Defaults to a short date + time. */
12
+ dateTimeFormatOptions?: Intl.DateTimeFormatOptions;
13
+ /** Show the "x minutes ago" label alongside the absolute time. Defaults to true. */
14
+ showTimeAgo?: boolean;
15
+ /** Hide the date portion of the absolute time. Defaults to false. */
16
+ hideDate?: boolean;
17
+ /** Hide the time portion of the absolute time. Defaults to false. */
18
+ hideTime?: boolean;
19
+ /** Hide the "x minutes ago" label. Takes precedence over showTimeAgo. Defaults to false. */
20
+ hideTimeAgo?: boolean;
21
+ /** Render each part on its own line instead of inline. Defaults to true. */
22
+ isMultiline?: boolean;
23
+ /** What to render when the date is missing/invalid (e.g. an empty isoDateTime). Defaults to "—". */
24
+ placeholder?: React.ReactNode;
25
+ className?: string;
26
+ };
27
+ export declare const DateTime: import("react").NamedExoticComponent<DateTimeProps>;
28
+ export {};
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DateTime = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const hooks_1 = require("./hooks");
7
+ const DEFAULT_DATE_OPTIONS = {
8
+ day: '2-digit',
9
+ month: '2-digit',
10
+ year: '2-digit',
11
+ };
12
+ const DEFAULT_TIME_OPTIONS = {
13
+ hour: '2-digit',
14
+ minute: '2-digit',
15
+ };
16
+ const DATE_OPTION_KEYS = ['weekday', 'era', 'year', 'month', 'day'];
17
+ const TIME_OPTION_KEYS = ['hour', 'minute', 'second', 'dayPeriod', 'timeZoneName'];
18
+ const pickOptions = (options, keys) => {
19
+ if (!options) {
20
+ return undefined;
21
+ }
22
+ const picked = keys.reduce((acc, key) => {
23
+ if (options[key] !== undefined) {
24
+ acc[key] = options[key];
25
+ }
26
+ return acc;
27
+ }, {});
28
+ return Object.keys(picked).length > 0 ? picked : undefined;
29
+ };
30
+ const toDate = (props) => {
31
+ if ('isoDateTime' in props) {
32
+ return new Date(props.isoDateTime);
33
+ }
34
+ if ('unixTimestampMs' in props) {
35
+ return new Date(props.unixTimestampMs);
36
+ }
37
+ return props.date;
38
+ };
39
+ const component = (props) => {
40
+ const { locale, dateTimeFormatOptions, showTimeAgo = true, hideDate = false, hideTime = false, hideTimeAgo = false, isMultiline = true, placeholder = '—', className } = props;
41
+ // Stable primitive key so a fresh props object doesn't churn the memo.
42
+ const dateKey = 'isoDateTime' in props ? props.isoDateTime : 'unixTimestampMs' in props ? props.unixTimestampMs : props.date.getTime();
43
+ const date = (0, react_1.useMemo)(() => toDate(props), [dateKey]);
44
+ const isValidDate = !Number.isNaN(date.getTime());
45
+ const formattedDate = (0, react_1.useMemo)(() => { var _a; return (hideDate ? '' : date.toLocaleDateString(locale, (_a = pickOptions(dateTimeFormatOptions, DATE_OPTION_KEYS)) !== null && _a !== void 0 ? _a : DEFAULT_DATE_OPTIONS)); }, [date, locale, dateTimeFormatOptions, hideDate]);
46
+ const formattedTime = (0, react_1.useMemo)(() => { var _a; return (hideTime ? '' : date.toLocaleTimeString(locale, (_a = pickOptions(dateTimeFormatOptions, TIME_OPTION_KEYS)) !== null && _a !== void 0 ? _a : DEFAULT_TIME_OPTIONS)); }, [date, locale, dateTimeFormatOptions, hideTime]);
47
+ const timeAgo = (0, hooks_1.useTimeAgo)(date, locale);
48
+ const formattedDateTime = [formattedDate, formattedTime].filter(Boolean).join(' ');
49
+ const displayTimeAgo = showTimeAgo && !hideTimeAgo;
50
+ // A missing/invalid date (e.g. an empty isoDateTime) renders the placeholder instead of
51
+ // an "Invalid Date" string or crashing the relative-time formatter.
52
+ if (!isValidDate) {
53
+ return (0, jsx_runtime_1.jsx)("time", { className: className, children: placeholder });
54
+ }
55
+ return ((0, jsx_runtime_1.jsx)("time", { dateTime: date.toISOString(), title: date.toLocaleString(locale), className: className, children: isMultiline ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [formattedDateTime ? (0, jsx_runtime_1.jsx)("div", { children: formattedDateTime }) : null, displayTimeAgo ? (0, jsx_runtime_1.jsx)("div", { children: timeAgo }) : null] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [formattedDateTime, displayTimeAgo ? ` (${timeAgo})` : ''] })) }));
56
+ };
57
+ exports.DateTime = (0, react_1.memo)(component);
@@ -0,0 +1 @@
1
+ export * from './useTimeAgo';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./useTimeAgo"), exports);
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Returns a relative time phrase for `date` (e.g. "5 minutes ago") that
3
+ * updates itself over time. The re-render cadence adapts to the age of the
4
+ * date, so recent times tick every second and older ones only update hourly.
5
+ */
6
+ export declare const useTimeAgo: (date: Date, locale?: string | string[]) => string;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useTimeAgo = void 0;
4
+ const quidproquo_web_1 = require("quidproquo-web");
5
+ const react_1 = require("react");
6
+ /**
7
+ * Returns a relative time phrase for `date` (e.g. "5 minutes ago") that
8
+ * updates itself over time. The re-render cadence adapts to the age of the
9
+ * date, so recent times tick every second and older ones only update hourly.
10
+ */
11
+ const useTimeAgo = (date, locale) => {
12
+ const [now, setNow] = (0, react_1.useState)(() => new Date());
13
+ (0, react_1.useEffect)(() => {
14
+ let timeoutId;
15
+ const schedule = () => {
16
+ timeoutId = setTimeout(() => {
17
+ setNow(new Date());
18
+ schedule();
19
+ }, (0, quidproquo_web_1.getTimeAgoUpdateIntervalMs)(date, new Date()));
20
+ };
21
+ schedule();
22
+ return () => clearTimeout(timeoutId);
23
+ }, [date]);
24
+ return (0, react_1.useMemo)(() => (0, quidproquo_web_1.formatTimeAgo)(date, now, locale), [date, now, locale]);
25
+ };
26
+ exports.useTimeAgo = useTimeAgo;
@@ -0,0 +1,2 @@
1
+ export * from './DateTime';
2
+ export * from './hooks';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./DateTime"), exports);
18
+ __exportStar(require("./hooks"), exports);
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Formats the distance between `date` and `now` as a relative phrase
3
+ * (e.g. "5 minutes ago", "in 2 hours") using the native Intl.RelativeTimeFormat.
4
+ * Past dates are negative, future dates are positive.
5
+ */
6
+ export declare const formatTimeAgo: (date: Date, now?: Date, locale?: string | string[]) => string;
7
+ /**
8
+ * How long until the relative phrase could next change, so callers can
9
+ * re-render no more often than necessary.
10
+ */
11
+ export declare const getTimeAgoUpdateIntervalMs: (date: Date, now?: Date) => number;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTimeAgoUpdateIntervalMs = exports.formatTimeAgo = void 0;
4
+ // Each amount is "how many of this unit make up one of the next unit".
5
+ const DIVISIONS = [
6
+ { amount: 60, unit: 'seconds' },
7
+ { amount: 60, unit: 'minutes' },
8
+ { amount: 24, unit: 'hours' },
9
+ { amount: 7, unit: 'days' },
10
+ { amount: 4.34524, unit: 'weeks' },
11
+ { amount: 12, unit: 'months' },
12
+ { amount: Number.POSITIVE_INFINITY, unit: 'years' },
13
+ ];
14
+ /**
15
+ * Formats the distance between `date` and `now` as a relative phrase
16
+ * (e.g. "5 minutes ago", "in 2 hours") using the native Intl.RelativeTimeFormat.
17
+ * Past dates are negative, future dates are positive.
18
+ */
19
+ const formatTimeAgo = (date, now = new Date(), locale) => {
20
+ const formatter = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
21
+ // Seconds between the two dates; negative for the past.
22
+ let duration = (date.getTime() - now.getTime()) / 1000;
23
+ for (const division of DIVISIONS) {
24
+ if (Math.abs(duration) < division.amount) {
25
+ return formatter.format(Math.round(duration), division.unit);
26
+ }
27
+ duration /= division.amount;
28
+ }
29
+ return formatter.format(Math.round(duration), 'years');
30
+ };
31
+ exports.formatTimeAgo = formatTimeAgo;
32
+ /**
33
+ * How long until the relative phrase could next change, so callers can
34
+ * re-render no more often than necessary.
35
+ */
36
+ const getTimeAgoUpdateIntervalMs = (date, now = new Date()) => {
37
+ const seconds = Math.abs((date.getTime() - now.getTime()) / 1000);
38
+ if (seconds < 60) {
39
+ return 1000; // seconds tick over
40
+ }
41
+ if (seconds < 60 * 60) {
42
+ return 60 * 1000; // minutes tick over
43
+ }
44
+ if (seconds < 60 * 60 * 24) {
45
+ return 60 * 60 * 1000; // hours tick over
46
+ }
47
+ return 60 * 60 * 24 * 1000; // days or coarser
48
+ };
49
+ exports.getTimeAgoUpdateIntervalMs = getTimeAgoUpdateIntervalMs;
@@ -0,0 +1 @@
1
+ export * from './formatTimeAgo';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./formatTimeAgo"), exports);
@@ -6,5 +6,6 @@ interface QpqContextProviderProps<T> {
6
6
  children: ReactNode;
7
7
  }
8
8
  export declare const useQpqContextValues: () => QpqContext<any>;
9
- export declare const QpqContextProvider: <T>({ contextIdentifier, value, children }: QpqContextProviderProps<T>) => import("react/jsx-runtime").JSX.Element;
9
+ export declare const useQpqContextValue: <T>(contextIdentifier: QpqContextIdentifier<T>) => T;
10
+ export declare const QpqContextProvider: <T>({ contextIdentifier, value, children }: QpqContextProviderProps<T>) => import("react").JSX.Element;
10
11
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.QpqContextProvider = exports.useQpqContextValues = void 0;
3
+ exports.QpqContextProvider = exports.useQpqContextValue = exports.useQpqContextValues = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  // Define a generic type for the React Context
@@ -9,6 +9,11 @@ const useQpqContextValues = () => {
9
9
  return (0, react_1.useContext)(qpqReactContext);
10
10
  };
11
11
  exports.useQpqContextValues = useQpqContextValues;
12
+ const useQpqContextValue = (contextIdentifier) => {
13
+ const context = (0, exports.useQpqContextValues)();
14
+ return contextIdentifier.uniqueName in context ? context[contextIdentifier.uniqueName] : contextIdentifier.defaultValue;
15
+ };
16
+ exports.useQpqContextValue = useQpqContextValue;
12
17
  const QpqContextProvider = ({ contextIdentifier, value, children }) => {
13
18
  // Get the parent context value
14
19
  const parentContext = (0, react_1.useContext)(qpqReactContext);
@@ -7,8 +7,8 @@ type QpqRuntimeEffectCatcher = {
7
7
  };
8
8
  export declare const QpqRuntimeEffectCatcherComponent: <TState, TAction, TApi extends QpqApi>({ children, runtime, name, }: QpqRuntimeEffectCatcher & {
9
9
  children: ReactNode;
10
- }) => import("react/jsx-runtime").JSX.Element;
10
+ }) => import("react").JSX.Element;
11
11
  export declare const QpqRuntimeEffectCatcher: import("react").MemoExoticComponent<(<TState, TAction, TApi extends QpqApi>({ children, runtime, name, }: QpqRuntimeEffectCatcher & {
12
12
  children: ReactNode;
13
- }) => import("react/jsx-runtime").JSX.Element)>;
13
+ }) => import("react").JSX.Element)>;
14
14
  export {};
@@ -1,5 +1,6 @@
1
1
  export * from './asmj';
2
2
  export * from './useAsyncEffect';
3
+ export * from './useComputed';
3
4
  export * from './useEffectCallback';
4
5
  export * from './useFastCallback';
5
6
  export * from './useMetadata';
@@ -16,6 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./asmj"), exports);
18
18
  __exportStar(require("./useAsyncEffect"), exports);
19
+ __exportStar(require("./useComputed"), exports);
19
20
  __exportStar(require("./useEffectCallback"), exports);
20
21
  __exportStar(require("./useFastCallback"), exports);
21
22
  __exportStar(require("./useMetadata"), exports);
@@ -0,0 +1 @@
1
+ export declare function useComputed<TState extends object, T>(state: TState, selector: (state: TState) => T): T;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useComputed = useComputed;
4
+ function useComputed(state, selector) {
5
+ // TODO: use proxies to resolve deps and only return updated values when the deps change.
6
+ return selector(state);
7
+ }
@@ -3,6 +3,7 @@ export * from './actionProcessor';
3
3
  export * from './api';
4
4
  export * from './auth';
5
5
  export * from './baseUrl';
6
+ export * from './dateTime';
6
7
  export * from './hooks';
7
8
  export * from './state';
8
9
  export * from './useFieldBinding';
@@ -19,6 +19,7 @@ __exportStar(require("./actionProcessor"), exports);
19
19
  __exportStar(require("./api"), exports);
20
20
  __exportStar(require("./auth"), exports);
21
21
  __exportStar(require("./baseUrl"), exports);
22
+ __exportStar(require("./dateTime"), exports);
22
23
  __exportStar(require("./hooks"), exports);
23
24
  __exportStar(require("./state"), exports);
24
25
  __exportStar(require("./useFieldBinding"), exports);
@@ -0,0 +1 @@
1
+ export declare const WebSocketAuthContext: import("react").Context<boolean>;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebSocketAuthContext = void 0;
4
+ const react_1 = require("react");
5
+ exports.WebSocketAuthContext = (0, react_1.createContext)(false);
@@ -4,11 +4,11 @@ exports.WebSocketAuthSync = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const hooks_1 = require("./hooks");
7
+ const WebSocketAuthContext_1 = require("./WebSocketAuthContext");
7
8
  const component = ({ children, accessToken }) => {
8
- (0, hooks_1.useWebsocketAuthSync)(accessToken);
9
+ const isAuthenticated = (0, hooks_1.useWebsocketAuthSync)(accessToken);
9
10
  // Keep the active websocket alive
10
11
  (0, hooks_1.useWebsocketPingPong)();
11
- // This fragment is not useless!
12
- return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
12
+ return ((0, jsx_runtime_1.jsx)(WebSocketAuthContext_1.WebSocketAuthContext.Provider, { value: isAuthenticated, children: children }));
13
13
  };
14
14
  exports.WebSocketAuthSync = (0, react_1.memo)(component);
@@ -1,2 +1,3 @@
1
1
  export * from './useWebsocketAuthSync';
2
+ export * from './useWebSocketIsAuthenticated';
2
3
  export * from './useWebsocketPingPong';
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./useWebsocketAuthSync"), exports);
18
+ __exportStar(require("./useWebSocketIsAuthenticated"), exports);
18
19
  __exportStar(require("./useWebsocketPingPong"), exports);
@@ -0,0 +1 @@
1
+ export declare const useWebSocketIsAuthenticated: () => boolean;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useWebSocketIsAuthenticated = void 0;
4
+ const react_1 = require("react");
5
+ const WebSocketAuthContext_1 = require("../WebSocketAuthContext");
6
+ const useWebSocketIsAuthenticated = () => {
7
+ return (0, react_1.useContext)(WebSocketAuthContext_1.WebSocketAuthContext);
8
+ };
9
+ exports.useWebSocketIsAuthenticated = useWebSocketIsAuthenticated;
@@ -1,2 +1,2 @@
1
1
  import { AuthenticationInfo } from 'quidproquo-core';
2
- export declare const useWebsocketAuthSync: (accessToken: AuthenticationInfo["accessToken"]) => void;
2
+ export declare const useWebsocketAuthSync: (accessToken: AuthenticationInfo["accessToken"]) => boolean;
@@ -9,29 +9,32 @@ const hooks_2 = require("../../hooks");
9
9
  const useWebsocketAuthSync = (accessToken) => {
10
10
  const sendMessage = (0, hooks_2.useWebsocketSendEvent)();
11
11
  const websocketApi = (0, hooks_2.useWebsocketApi)();
12
+ const [isAuthenticated, setIsAuthenticated] = (0, react_1.useState)(false);
12
13
  const updateAuthTokens = (0, hooks_1.useFastCallback)(() => {
13
14
  if (!(websocketApi === null || websocketApi === void 0 ? void 0 : websocketApi.isConnected())) {
14
15
  return;
15
16
  }
16
17
  if (accessToken) {
17
- const authMessage = {
18
+ sendMessage({
18
19
  type: quidproquo_webserver_1.WebSocketQueueClientMessageEventType.Authenticate,
19
20
  payload: {
20
21
  accessToken: accessToken,
21
22
  },
22
- };
23
- sendMessage(authMessage);
23
+ });
24
24
  }
25
- else {
26
- const authMessage = {
25
+ else if (isAuthenticated) {
26
+ sendMessage({
27
27
  type: quidproquo_webserver_1.WebSocketQueueClientMessageEventType.Unauthenticate,
28
- };
29
- sendMessage(authMessage);
28
+ });
30
29
  }
31
30
  });
31
+ (0, hooks_2.useSubscribeToWebSocketEvent)(quidproquo_webserver_1.WebSocketQueueServerMessageEventType.Authenticated, () => setIsAuthenticated(true));
32
+ (0, hooks_2.useSubscribeToWebSocketEvent)(quidproquo_webserver_1.WebSocketQueueServerMessageEventType.Unauthenticated, () => setIsAuthenticated(false));
32
33
  // Sync the tokens in on open
33
34
  (0, hooks_2.useSubscribeToWebsocket)(quidproquo_web_1.WebsocketServiceEvent.OPEN, updateAuthTokens);
35
+ (0, hooks_2.useSubscribeToWebsocket)(quidproquo_web_1.WebsocketServiceEvent.CLOSE, () => setIsAuthenticated(false));
34
36
  // Sync the tokens when they change
35
- (0, react_1.useEffect)(updateAuthTokens, [accessToken, websocketApi]);
37
+ (0, react_1.useEffect)(updateAuthTokens, [accessToken, websocketApi, isAuthenticated]);
38
+ return isAuthenticated;
36
39
  };
37
40
  exports.useWebsocketAuthSync = useWebsocketAuthSync;
@@ -1 +1,2 @@
1
+ export * from './hooks/useWebSocketIsAuthenticated';
1
2
  export * from './WebSocketAuthSync';
@@ -14,4 +14,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./hooks/useWebSocketIsAuthenticated"), exports);
17
18
  __exportStar(require("./WebSocketAuthSync"), exports);
@@ -2,16 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useSubscribeToWebSocketEvent = void 0;
4
4
  const react_1 = require("react");
5
+ const hooks_1 = require("../../hooks");
5
6
  const useWebsocketApi_1 = require("./useWebsocketApi");
6
7
  const useSubscribeToWebSocketEvent = (subscriptionType, callback) => {
8
+ const stableCallback = (0, hooks_1.useFastCallback)(callback);
7
9
  const websocketService = (0, useWebsocketApi_1.useWebsocketApi)();
8
10
  (0, react_1.useEffect)(() => {
9
- const subscriptionHandle = websocketService === null || websocketService === void 0 ? void 0 : websocketService.subscribeToEvent(subscriptionType, callback);
11
+ const subscriptionHandle = websocketService === null || websocketService === void 0 ? void 0 : websocketService.subscribeToEvent(subscriptionType, stableCallback);
10
12
  return () => {
11
13
  if (subscriptionHandle) {
12
14
  websocketService === null || websocketService === void 0 ? void 0 : websocketService.unsubscribe(subscriptionHandle);
13
15
  }
14
16
  };
15
- }, [websocketService, subscriptionType, callback]);
17
+ }, [websocketService, subscriptionType, stableCallback]);
16
18
  };
17
19
  exports.useSubscribeToWebSocketEvent = useSubscribeToWebSocketEvent;
@@ -2,16 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useSubscribeToWebsocket = void 0;
4
4
  const react_1 = require("react");
5
+ const hooks_1 = require("../../hooks");
5
6
  const useWebsocketApi_1 = require("./useWebsocketApi");
6
7
  const useSubscribeToWebsocket = (subscriptionType, callback) => {
8
+ const stableCallback = (0, hooks_1.useFastCallback)(callback);
7
9
  const websocketService = (0, useWebsocketApi_1.useWebsocketApi)();
8
10
  (0, react_1.useEffect)(() => {
9
- const handle = websocketService === null || websocketService === void 0 ? void 0 : websocketService.subscribe(subscriptionType, callback);
11
+ const handle = websocketService === null || websocketService === void 0 ? void 0 : websocketService.subscribe(subscriptionType, stableCallback);
10
12
  return () => {
11
13
  if (handle) {
12
14
  websocketService === null || websocketService === void 0 ? void 0 : websocketService.unsubscribe(handle);
13
15
  }
14
16
  };
15
- }, [websocketService, subscriptionType, callback]);
17
+ }, [websocketService, subscriptionType, stableCallback]);
16
18
  };
17
19
  exports.useSubscribeToWebsocket = useSubscribeToWebsocket;
@@ -1,2 +1,3 @@
1
+ export * from './useApiRequestActionProcessor';
1
2
  export * from './useAuthenticatedNetworkRequest';
2
3
  export * from './useNetworkRequest';
@@ -1,2 +1,3 @@
1
+ export * from './useApiRequestActionProcessor';
1
2
  export * from './useAuthenticatedNetworkRequest';
2
3
  export * from './useNetworkRequest';