@rpcbase/client 0.337.0 → 0.339.0

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,5 +1,5 @@
1
1
  import { Application } from 'express';
2
- type Ctx = any;
2
+ import { Ctx } from '../../../api/src';
3
3
  type ServerArgs = {
4
4
  app: Application;
5
5
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/apiClient/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAG1C,KAAK,GAAG,GAAG,GAAG,CAAA;AAGd,KAAK,UAAU,GAAG;IAChB,GAAG,EAAE,WAAW,CAAC;CAClB,CAAC;AAEF,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;KAC5C,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,EAAE,KAAK;CACzB,CAAC;AAEF,KAAK,eAAe,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,aAAa,EACtB,GAAG,CAAC,EAAE,GAAG,KACN,OAAO,CAAC,SAAS,CAAC,CAAC;AAExB,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;AAC3D,KAAK,YAAY,CAAC,CAAC,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;AAE7C,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;AAEtD,QAAA,IAAI,SAAS,EAAE,SAAS,CAAA;AAExB,eAAO,MAAM,aAAa,GAAU,OAAO,UAAU,kBAyDpD,CAAA;AAED,OAAO,EAAE,SAAS,EAAE,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/apiClient/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAGvC,KAAK,UAAU,GAAG;IAChB,GAAG,EAAE,WAAW,CAAC;CAClB,CAAC;AAEF,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;KAC5C,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,EAAE,KAAK;CACzB,CAAC;AAEF,KAAK,eAAe,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,aAAa,EACtB,GAAG,CAAC,EAAE,GAAG,KACN,OAAO,CAAC,SAAS,CAAC,CAAC;AAExB,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;AAC3D,KAAK,YAAY,CAAC,CAAC,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;AAE7C,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;AAEtD,QAAA,IAAI,SAAS,EAAE,SAAS,CAAA;AAExB,eAAO,MAAM,aAAa,GAAU,OAAO,UAAU,kBAyDpD,CAAA;AAED,OAAO,EAAE,SAAS,EAAE,CAAA"}
package/dist/index.d.ts CHANGED
@@ -7,5 +7,6 @@ export * from './hooks';
7
7
  export * from './ssrErrorState';
8
8
  export * from './components/SsrErrorFallback';
9
9
  export * from './components/RouteErrorBoundary';
10
+ export * from './notifications';
10
11
  export { toast } from 'sonner';
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,SAAS,CAAA;AACvB,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,+BAA+B,CAAA;AAC7C,cAAc,iCAAiC,CAAA;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,SAAS,CAAA;AACvB,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,+BAA+B,CAAA;AAC7C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA"}
package/dist/index.js CHANGED
@@ -112,17 +112,19 @@ const getWindowState = () => {
112
112
  const key = "__rpcbaseNavigationGuardWindowState";
113
113
  const globalAny = window;
114
114
  if (globalAny[key]) {
115
- return globalAny[key];
115
+ const existing = globalAny[key];
116
+ if (typeof existing.suppressBeforeUnloadFromKey === "undefined") {
117
+ existing.suppressBeforeUnloadFromKey = null;
118
+ }
119
+ return existing;
116
120
  }
117
121
  const created = {
118
- suppressBeforeUnloadUntil: 0,
119
- lastBeforeUnloadAt: 0
122
+ suppressBeforeUnloadFromKey: null,
123
+ nativePromptActive: false
120
124
  };
121
125
  globalAny[key] = created;
122
126
  return created;
123
127
  };
124
- const NATIVE_PROMPT_COOLDOWN_MS = 1e3;
125
- const SUPPRESS_BEFOREUNLOAD_MS = 1e3;
126
128
  const getGlobalGuardWeakSet = () => {
127
129
  const key = "__rpcbaseNavigationGuardInstalledRouters";
128
130
  const globalAny = globalThis;
@@ -146,9 +148,18 @@ const installGlobalNavigationGuard = (router) => {
146
148
  let lastPromptedLocationKey = null;
147
149
  router.getBlocker(blockerKey, (args) => {
148
150
  lastArgs = args;
151
+ if (windowState?.nativePromptActive && args.historyAction !== "POP") {
152
+ windowState.nativePromptActive = false;
153
+ }
149
154
  return pickNavigationGuard(args) !== null;
150
155
  });
151
156
  router.subscribe((state) => {
157
+ if (windowState?.suppressBeforeUnloadFromKey && state?.location) {
158
+ const currentKey = getLocationDedupKey(state.location);
159
+ if (currentKey !== windowState.suppressBeforeUnloadFromKey) {
160
+ windowState.suppressBeforeUnloadFromKey = null;
161
+ }
162
+ }
152
163
  const blocker = state.blockers.get(blockerKey);
153
164
  if (!blocker || blocker.state !== "blocked") {
154
165
  lastPromptedLocationKey = null;
@@ -160,12 +171,17 @@ const installGlobalNavigationGuard = (router) => {
160
171
  return;
161
172
  }
162
173
  lastPromptedLocationKey = dedupKey;
163
- if (windowState && Date.now() - windowState.lastBeforeUnloadAt < NATIVE_PROMPT_COOLDOWN_MS) {
174
+ if (windowState?.nativePromptActive && lastArgs?.historyAction === "POP") {
175
+ windowState.nativePromptActive = false;
164
176
  blocker.reset();
165
177
  return;
166
178
  }
167
179
  const args = lastArgs;
168
- const guard = args ? pickNavigationGuard(args) : null;
180
+ if (!args) {
181
+ blocker.proceed();
182
+ return;
183
+ }
184
+ const guard = pickNavigationGuard(args);
169
185
  if (!guard) {
170
186
  blocker.proceed();
171
187
  return;
@@ -173,7 +189,7 @@ const installGlobalNavigationGuard = (router) => {
173
189
  const ok = window.confirm(guard.message);
174
190
  if (ok) {
175
191
  if (windowState) {
176
- windowState.suppressBeforeUnloadUntil = Date.now() + SUPPRESS_BEFOREUNLOAD_MS;
192
+ windowState.suppressBeforeUnloadFromKey = getLocationDedupKey(args.currentLocation);
177
193
  }
178
194
  blocker.proceed();
179
195
  } else {
@@ -187,15 +203,15 @@ const installGlobalNavigationGuard = (router) => {
187
203
  globalAny[key] = true;
188
204
  window.addEventListener("beforeunload", (event) => {
189
205
  const state = getWindowState();
190
- if (state && state.suppressBeforeUnloadUntil > 0 && Date.now() < state.suppressBeforeUnloadUntil) {
191
- state.suppressBeforeUnloadUntil = 0;
206
+ if (state && state.suppressBeforeUnloadFromKey) {
207
+ state.suppressBeforeUnloadFromKey = null;
192
208
  return;
193
209
  }
194
210
  if (!hasUnloadBlockers()) {
195
211
  return;
196
212
  }
197
213
  if (state) {
198
- state.lastBeforeUnloadAt = Date.now();
214
+ state.nativePromptActive = true;
199
215
  }
200
216
  event.preventDefault();
201
217
  event.returnValue = "";
@@ -1850,19 +1866,89 @@ const RouteErrorBoundary = ({ renderErrorExtra }) => {
1850
1866
  }
1851
1867
  );
1852
1868
  };
1869
+ const listNotifications = async (input = {}) => {
1870
+ const result = await apiClient.post("/api/rb/notifications", input);
1871
+ if (!result?.ok) {
1872
+ throw new Error(result?.error || "Failed to load notifications");
1873
+ }
1874
+ return {
1875
+ notifications: Array.isArray(result.notifications) ? result.notifications : [],
1876
+ unreadCount: Number.isFinite(result.unreadCount) ? Math.max(0, Math.floor(result.unreadCount ?? 0)) : 0,
1877
+ unseenCount: Number.isFinite(result.unseenCount) ? Math.max(0, Math.floor(result.unseenCount ?? 0)) : 0
1878
+ };
1879
+ };
1880
+ const markNotificationRead = async (notificationId) => {
1881
+ const id = notificationId.trim();
1882
+ if (!id) throw new Error("notificationId is required");
1883
+ const result = await apiClient.post(
1884
+ `/api/rb/notifications/${encodeURIComponent(id)}/read`,
1885
+ {}
1886
+ );
1887
+ if (!result?.ok) {
1888
+ throw new Error(result?.error || "Failed to mark notification read");
1889
+ }
1890
+ };
1891
+ const archiveNotification = async (notificationId) => {
1892
+ const id = notificationId.trim();
1893
+ if (!id) throw new Error("notificationId is required");
1894
+ const result = await apiClient.post(
1895
+ `/api/rb/notifications/${encodeURIComponent(id)}/archive`,
1896
+ {}
1897
+ );
1898
+ if (!result?.ok) {
1899
+ throw new Error(result?.error || "Failed to archive notification");
1900
+ }
1901
+ };
1902
+ const markAllNotificationsRead = async () => {
1903
+ const result = await apiClient.post("/api/rb/notifications/mark-all-read", {});
1904
+ if (!result?.ok) {
1905
+ throw new Error(result?.error || "Failed to mark all notifications read");
1906
+ }
1907
+ };
1908
+ const getNotificationSettings = async () => {
1909
+ const result = await apiClient.get("/api/rb/notifications/settings", {});
1910
+ if (!result?.ok) {
1911
+ throw new Error(result?.error || "Failed to load notification settings");
1912
+ }
1913
+ return result.settings ?? { digestFrequency: "weekly", topicPreferences: [] };
1914
+ };
1915
+ const updateNotificationSettings = async (partial) => {
1916
+ const result = await apiClient.put("/api/rb/notifications/settings", partial);
1917
+ if (!result?.ok) {
1918
+ throw new Error(result?.error || "Failed to update notification settings");
1919
+ }
1920
+ return result.settings ?? { digestFrequency: "weekly", topicPreferences: [] };
1921
+ };
1922
+ const runNotificationDigest = async ({ force = false } = {}) => {
1923
+ const result = await apiClient.post(
1924
+ "/api/rb/notifications/digest/run",
1925
+ { force }
1926
+ );
1927
+ if (!result?.ok) {
1928
+ throw new Error(result?.error || "Failed to run digest");
1929
+ }
1930
+ return { sent: result.sent === true, skippedReason: result.skippedReason };
1931
+ };
1853
1932
  export {
1854
1933
  RootProvider,
1855
1934
  RouteErrorBoundary,
1856
1935
  SSR_ERROR_STATE_GLOBAL_KEY,
1857
1936
  SsrErrorFallback,
1858
1937
  apiClient,
1938
+ archiveNotification,
1859
1939
  consumeClientSsrErrorState,
1860
1940
  getFeatureFlag,
1941
+ getNotificationSettings,
1861
1942
  initApiClient,
1862
1943
  initWithRoutes,
1944
+ listNotifications,
1945
+ markAllNotificationsRead,
1946
+ markNotificationRead,
1863
1947
  peekClientSsrErrorState,
1948
+ runNotificationDigest,
1864
1949
  serializeSsrErrorState,
1865
1950
  toast,
1951
+ updateNotificationSettings,
1866
1952
  useMediaQuery,
1867
1953
  useThrottledMeasure
1868
1954
  };
@@ -1 +1 @@
1
- {"version":3,"file":"installGlobalNavigationGuard.d.ts","sourceRoot":"","sources":["../../src/navigationGuard/installGlobalNavigationGuard.ts"],"names":[],"mappings":"AAAA,OAAQ,EAAuB,KAAK,UAAU,EAAuB,MAAM,iBAAiB,CAAA;AA2F5F,eAAO,MAAM,4BAA4B,GAAI,QAAQ,UAAU,KAAG,IAoFjE,CAAA"}
1
+ {"version":3,"file":"installGlobalNavigationGuard.d.ts","sourceRoot":"","sources":["../../src/navigationGuard/installGlobalNavigationGuard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,UAAU,EAAwB,MAAM,iBAAiB,CAAA;AA4F5F,eAAO,MAAM,4BAA4B,GAAI,QAAQ,UAAU,KAAG,IAoGjE,CAAA"}
@@ -0,0 +1,54 @@
1
+ export type NotificationItem = {
2
+ id: string;
3
+ topic?: string;
4
+ title: string;
5
+ body?: string;
6
+ url?: string;
7
+ createdAt: string;
8
+ seenAt?: string;
9
+ readAt?: string;
10
+ archivedAt?: string;
11
+ metadata?: Record<string, unknown>;
12
+ };
13
+ export type NotificationDigestFrequency = "off" | "daily" | "weekly";
14
+ export type NotificationTopicPreference = {
15
+ topic: string;
16
+ inApp: boolean;
17
+ emailDigest: boolean;
18
+ push: boolean;
19
+ };
20
+ export type NotificationSettings = {
21
+ digestFrequency: NotificationDigestFrequency;
22
+ topicPreferences: NotificationTopicPreference[];
23
+ lastDigestSentAt?: string;
24
+ };
25
+ export type ListNotificationsInput = {
26
+ includeArchived?: boolean;
27
+ unreadOnly?: boolean;
28
+ limit?: number;
29
+ markSeen?: boolean;
30
+ };
31
+ export type ListNotificationsResponse = {
32
+ ok: boolean;
33
+ error?: string;
34
+ notifications?: NotificationItem[];
35
+ unreadCount?: number;
36
+ unseenCount?: number;
37
+ };
38
+ export declare const listNotifications: (input?: ListNotificationsInput) => Promise<{
39
+ notifications: NotificationItem[];
40
+ unreadCount: number;
41
+ unseenCount: number;
42
+ }>;
43
+ export declare const markNotificationRead: (notificationId: string) => Promise<void>;
44
+ export declare const archiveNotification: (notificationId: string) => Promise<void>;
45
+ export declare const markAllNotificationsRead: () => Promise<void>;
46
+ export declare const getNotificationSettings: () => Promise<NotificationSettings>;
47
+ export declare const updateNotificationSettings: (partial: Partial<Pick<NotificationSettings, "digestFrequency" | "topicPreferences">>) => Promise<NotificationSettings>;
48
+ export declare const runNotificationDigest: ({ force }?: {
49
+ force?: boolean;
50
+ }) => Promise<{
51
+ sent: boolean;
52
+ skippedReason: string | undefined;
53
+ }>;
54
+ //# sourceMappingURL=notifications.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEpE,MAAM,MAAM,2BAA2B,GAAG;IACxC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,OAAO,CAAA;IACd,WAAW,EAAE,OAAO,CAAA;IACpB,IAAI,EAAE,OAAO,CAAA;CACd,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,eAAe,EAAE,2BAA2B,CAAA;IAC5C,gBAAgB,EAAE,2BAA2B,EAAE,CAAA;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,EAAE,EAAE,OAAO,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAClC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAU,QAAO,sBAA2B;;;;EAUzE,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAU,gBAAgB,MAAM,kBAWhE,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAU,gBAAgB,MAAM,kBAW/D,CAAA;AAED,eAAO,MAAM,wBAAwB,qBAKpC,CAAA;AAQD,eAAO,MAAM,uBAAuB,QAAa,OAAO,CAAC,oBAAoB,CAO5E,CAAA;AAED,eAAO,MAAM,0BAA0B,GACrC,SAAS,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,iBAAiB,GAAG,kBAAkB,CAAC,CAAC,KACnF,OAAO,CAAC,oBAAoB,CAM9B,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAU,YAAmB;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO;;;EAStF,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpcbase/client",
3
- "version": "0.337.0",
3
+ "version": "0.339.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"