@tstdl/base 0.93.115 → 0.93.117

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,6 @@
1
1
  import { DataStream } from '../../sse/data-stream.js';
2
2
  import { InAppNotificationView } from '../models/in-app-notification.model.js';
3
+ import type { NotificationStreamItem } from '../types.js';
3
4
  export type NotificationApiDefinition = typeof notificationApiDefinition;
4
5
  export declare const notificationApiDefinition: {
5
6
  resource: string;
@@ -8,7 +9,7 @@ export declare const notificationApiDefinition: {
8
9
  resource: string;
9
10
  method: "GET";
10
11
  result: {
11
- new (): DataStream<InAppNotificationView<Record<string, import("../models/notification-log.model.js").NotificationDefinition<import("../../types/types.js").ObjectLiteral, import("../../types/types.js").ObjectLiteral>>>>;
12
+ new (): DataStream<NotificationStreamItem>;
12
13
  parse<T>(eventSource: import("../../sse/server-sent-events.js").ServerSentEvents): import("rxjs").Observable<T>;
13
14
  };
14
15
  credentials: true;
@@ -19,6 +20,7 @@ export declare const notificationApiDefinition: {
19
20
  parameters: import("../../schema/index.js").ObjectSchema<{
20
21
  offset?: number | undefined;
21
22
  limit?: number | undefined;
23
+ after?: string | undefined;
22
24
  unreadOnly?: boolean | undefined;
23
25
  includeArchived?: boolean | undefined;
24
26
  }>;
@@ -104,7 +106,7 @@ declare const _NotificationApiClient: import("../../api/client/index.js").ApiCli
104
106
  resource: string;
105
107
  method: "GET";
106
108
  result: {
107
- new (): DataStream<InAppNotificationView<Record<string, import("../models/notification-log.model.js").NotificationDefinition<import("../../types/types.js").ObjectLiteral, import("../../types/types.js").ObjectLiteral>>>>;
109
+ new (): DataStream<NotificationStreamItem>;
108
110
  parse<T>(eventSource: import("../../sse/server-sent-events.js").ServerSentEvents): import("rxjs").Observable<T>;
109
111
  };
110
112
  credentials: true;
@@ -115,6 +117,7 @@ declare const _NotificationApiClient: import("../../api/client/index.js").ApiCli
115
117
  parameters: import("../../schema/index.js").ObjectSchema<{
116
118
  offset?: number | undefined;
117
119
  limit?: number | undefined;
120
+ after?: string | undefined;
118
121
  unreadOnly?: boolean | undefined;
119
122
  includeArchived?: boolean | undefined;
120
123
  }>;
@@ -26,6 +26,7 @@ export const notificationApiDefinition = defineApi({
26
26
  parameters: object({
27
27
  limit: optional(number()),
28
28
  offset: optional(number()),
29
+ after: optional(string()),
29
30
  unreadOnly: optional(boolean()),
30
31
  includeArchived: optional(boolean()),
31
32
  }),
@@ -0,0 +1 @@
1
+ export * from './notification-client.js';
@@ -0,0 +1 @@
1
+ export * from './notification-client.js';
@@ -0,0 +1,18 @@
1
+ import { NotificationApiClient } from '../../notification/api/index.js';
2
+ import type { InAppNotificationView, NotificationDefinitionMap } from '../../notification/models/index.js';
3
+ type NotificationState<Definitions extends NotificationDefinitionMap = NotificationDefinitionMap> = {
4
+ notifications: InAppNotificationView<Definitions>[];
5
+ unreadCount: number;
6
+ };
7
+ export declare class NotificationClient<Definitions extends NotificationDefinitionMap = NotificationDefinitionMap> {
8
+ #private;
9
+ readonly api: NotificationApiClient;
10
+ readonly state$: import("rxjs").Observable<NotificationState<Definitions>>;
11
+ readonly notifications$: import("rxjs").Observable<InAppNotificationView<Definitions>[]>;
12
+ readonly unreadCount$: import("rxjs").Observable<number>;
13
+ readonly state: import("../../signals/api.js").Signal<NotificationState<Definitions>>;
14
+ readonly notifications: import("../../signals/api.js").Signal<InAppNotificationView<Definitions>[]>;
15
+ readonly unreadCount: import("../../signals/api.js").Signal<number>;
16
+ loadNext(count?: number): void;
17
+ }
18
+ export {};
@@ -0,0 +1,62 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { concatMap, defer, from, map, merge, of, scan, shareReplay, Subject, switchAll, switchMap } from 'rxjs';
8
+ import { AuthenticationClientService } from '../../authentication/client/authentication.service.js';
9
+ import { Singleton } from '../../injector/decorators.js';
10
+ import { inject } from '../../injector/inject.js';
11
+ import { NotificationApiClient } from '../../notification/api/index.js';
12
+ import { forceCast } from '../../rxjs-utils/cast.js';
13
+ import { computed, toSignal } from '../../signals/api.js';
14
+ import { isDefined, isUndefined } from '../../utils/type-guards.js';
15
+ let NotificationClient = class NotificationClient {
16
+ #pagination$ = new Subject();
17
+ #authenticationService = inject(AuthenticationClientService);
18
+ api = inject(NotificationApiClient);
19
+ state$ = this.#authenticationService.sessionId$.pipe(switchMap((sessionId) => {
20
+ if (isUndefined(sessionId)) {
21
+ return of({ notifications: [], unreadCount: 0 });
22
+ }
23
+ return merge(defer(() => from(this.api.listInApp({ limit: 20 }))).pipe(map((notifications) => ({ type: 'set-notifications', notifications: notifications }))), defer(() => from(this.api.unreadCount())).pipe(map((unreadCount) => ({ type: 'set-unread-count', unreadCount }))), defer(() => from(this.api.stream())).pipe(switchAll(), forceCast(), switchMap((item) => {
24
+ const actions = [{ type: 'set-unread-count', unreadCount: item.unreadCount }];
25
+ if (isDefined(item.notification)) {
26
+ actions.push({ type: 'prepend-notification', notification: item.notification });
27
+ }
28
+ return from(actions);
29
+ })), this.#pagination$.pipe(concatMap(({ count, after }) => from(this.api.listInApp({ limit: count, after }))), map((notifications) => ({ type: 'append-notifications', notifications: notifications })))).pipe(scan((acc, action) => {
30
+ switch (action.type) {
31
+ case 'set-notifications':
32
+ return { ...acc, notifications: action.notifications };
33
+ case 'prepend-notification':
34
+ if (acc.notifications.some((n) => n.id == action.notification.id)) {
35
+ return acc;
36
+ }
37
+ return { ...acc, notifications: [action.notification, ...acc.notifications] };
38
+ case 'append-notifications':
39
+ const filtered = action.notifications.filter((n) => !acc.notifications.some((c) => c.id == n.id));
40
+ return { ...acc, notifications: [...acc.notifications, ...filtered] };
41
+ case 'set-unread-count':
42
+ return { ...acc, unreadCount: action.unreadCount };
43
+ default:
44
+ return acc;
45
+ }
46
+ }, { notifications: [], unreadCount: 0 }));
47
+ }), shareReplay({ bufferSize: 1, refCount: true }));
48
+ notifications$ = this.state$.pipe(map((state) => state.notifications));
49
+ unreadCount$ = this.state$.pipe(map((state) => state.unreadCount));
50
+ state = toSignal(this.state$, { initialValue: { notifications: [], unreadCount: 0 } });
51
+ notifications = computed(() => this.state().notifications);
52
+ unreadCount = computed(() => this.state().unreadCount);
53
+ loadNext(count = 20) {
54
+ const current = this.notifications();
55
+ const after = current[current.length - 1]?.id;
56
+ this.#pagination$.next({ count, after });
57
+ }
58
+ };
59
+ NotificationClient = __decorate([
60
+ Singleton()
61
+ ], NotificationClient);
62
+ export { NotificationClient };
@@ -1,2 +1,4 @@
1
1
  export * from './api/index.js';
2
+ export * from './client/index.js';
2
3
  export * from './models/index.js';
4
+ export * from './types.js';
@@ -1,2 +1,4 @@
1
1
  export * from './api/index.js';
2
+ export * from './client/index.js';
2
3
  export * from './models/index.js';
4
+ export * from './types.js';
@@ -5,7 +5,7 @@ import { NotificationAncillaryService } from './services/notification-ancillary.
5
5
  export declare class NotificationConfiguration {
6
6
  database?: DatabaseConfig;
7
7
  defaultChannels?: NotificationChannel[];
8
- ancillaryService?: InjectionToken<NotificationAncillaryService>;
8
+ ancillaryService?: InjectionToken<NotificationAncillaryService<any>>;
9
9
  }
10
10
  export declare function configureNotification({ injector, ...config }: NotificationConfiguration & {
11
11
  injector?: Injector;
@@ -8,9 +8,11 @@ import { inject, Singleton } from '../../../injector/index.js';
8
8
  import { injectRepository } from '../../../orm/server/index.js';
9
9
  import { InAppNotification, toInAppNotificationView } from '../../models/index.js';
10
10
  import { NotificationSseService } from '../services/notification-sse.service.js';
11
+ import { NotificationService } from '../services/notification.service.js';
11
12
  import { ChannelProvider } from './channel-provider.js';
12
13
  let InAppChannelProvider = class InAppChannelProvider extends ChannelProvider {
13
14
  #inAppRepository = injectRepository(InAppNotification);
15
+ #notificationService = inject(NotificationService);
14
16
  #sseService = inject(NotificationSseService);
15
17
  async send(notification, tx) {
16
18
  const inApp = await this.#inAppRepository.withOptionalTransaction(tx).insert({
@@ -21,7 +23,8 @@ let InAppChannelProvider = class InAppChannelProvider extends ChannelProvider {
21
23
  archiveTimestamp: null,
22
24
  });
23
25
  const inAppNotificationView = toInAppNotificationView(inApp, notification);
24
- await this.#sseService.send(inAppNotificationView);
26
+ const unreadCount = await this.#notificationService.withOptionalTransaction(tx).unreadCount(notification.tenantId, notification.userId);
27
+ await this.#sseService.send(inAppNotificationView, unreadCount);
25
28
  }
26
29
  };
27
30
  InAppChannelProvider = __decorate([
@@ -1,11 +1,13 @@
1
1
  import { Subject } from 'rxjs';
2
2
  import { afterResolve } from '../../../injector/index.js';
3
3
  import type { InAppNotificationView } from '../../models/index.js';
4
+ import type { NotificationStreamItem } from '../../types.js';
4
5
  export declare class NotificationSseService {
5
6
  #private;
6
7
  [afterResolve](): void;
7
- register(tenantId: string, userId: string): Subject<InAppNotificationView>;
8
- unregister(tenantId: string, userId: string, source: Subject<InAppNotificationView>): void;
9
- send(notification: InAppNotificationView): Promise<void>;
8
+ register(tenantId: string, userId: string): Subject<NotificationStreamItem>;
9
+ unregister(tenantId: string, userId: string, source: Subject<NotificationStreamItem>): void;
10
+ send(notification: InAppNotificationView, unreadCount: number): Promise<void>;
11
+ dispatchUnreadCountUpdate(tenantId: string, userId: string, unreadCount: number): Promise<void>;
10
12
  private dispatchToLocal;
11
13
  }
@@ -10,7 +10,7 @@ import { MessageBusProvider } from '../../../message-bus/index.js';
10
10
  let NotificationSseService = class NotificationSseService {
11
11
  #messageBusProvider = inject(MessageBusProvider);
12
12
  #messageBus = this.#messageBusProvider.get('notification');
13
- #sources = new Map(); // tenantId -> userId -> Sources
13
+ #sources = new Map(); // tenantId -> userId -> sources
14
14
  [afterResolve]() {
15
15
  this.#messageBus.allMessages$.subscribe((message) => this.dispatchToLocal(message));
16
16
  }
@@ -43,15 +43,27 @@ let NotificationSseService = class NotificationSseService {
43
43
  }
44
44
  source.complete();
45
45
  }
46
- async send(notification) {
47
- await this.#messageBus.publish(notification);
46
+ async send(notification, unreadCount) {
47
+ await this.#messageBus.publish({
48
+ tenantId: notification.tenantId,
49
+ userId: notification.userId,
50
+ notification,
51
+ unreadCount,
52
+ });
48
53
  }
49
- dispatchToLocal(notification) {
50
- const tenantMap = this.#sources.get(notification.tenantId);
51
- const userSources = tenantMap?.get(notification.userId);
54
+ async dispatchUnreadCountUpdate(tenantId, userId, unreadCount) {
55
+ await this.#messageBus.publish({
56
+ tenantId,
57
+ userId,
58
+ unreadCount,
59
+ });
60
+ }
61
+ dispatchToLocal(message) {
62
+ const tenantMap = this.#sources.get(message.tenantId);
63
+ const userSources = tenantMap?.get(message.userId);
52
64
  if (userSources != null) {
53
65
  for (const source of userSources) {
54
- source.next(notification);
66
+ source.next({ notification: message.notification, unreadCount: message.unreadCount });
55
67
  }
56
68
  }
57
69
  }
@@ -11,6 +11,7 @@ export declare class NotificationService<Definitions extends NotificationDefinit
11
11
  listInApp(tenantId: string, userId: string, options?: {
12
12
  limit?: number;
13
13
  offset?: number;
14
+ after?: string;
14
15
  includeArchived?: boolean;
15
16
  unreadOnly?: boolean;
16
17
  }): Promise<InAppNotificationView[]>;
@@ -22,4 +23,5 @@ export declare class NotificationService<Definitions extends NotificationDefinit
22
23
  getPreferences(tenantId: string, userId: string): Promise<NotificationPreference[]>;
23
24
  updatePreference(tenantId: string, userId: string, type: string, channel: NotificationChannel, enabled: boolean): Promise<void>;
24
25
  registerWebPush(tenantId: string, userId: string, endpoint: string, p256dh: Uint8Array<ArrayBuffer>, auth: Uint8Array<ArrayBuffer>): Promise<void>;
26
+ private dispatchUnreadCountUpdate;
25
27
  }
@@ -4,22 +4,30 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { and, desc, eq, isNull } from 'drizzle-orm';
7
+ var _a;
8
+ var NotificationService_1;
9
+ import { and, desc, eq, isNull, lt, or } from 'drizzle-orm';
8
10
  import { BadRequestError } from '../../../errors/bad-request.error.js';
9
11
  import { inject, Singleton } from '../../../injector/index.js';
12
+ import { Logger } from '../../../logger/logger.js';
10
13
  import { TRANSACTION_TIMESTAMP } from '../../../orm/index.js';
11
14
  import { injectRepository, Transactional } from '../../../orm/server/index.js';
12
15
  import { TaskQueue } from '../../../task-queue/task-queue.js';
16
+ import { tryIgnoreLogAsync } from '../../../utils/try-ignore.js';
17
+ import { isDefined } from '../../../utils/type-guards.js';
13
18
  import { InAppNotification, NotificationLogEntity, NotificationPreference, NotificationPriority, NotificationStatus, toInAppNotificationView, WebPushSubscription } from '../../models/index.js';
14
19
  import { inAppNotification, notificationLog } from '../schemas.js';
15
20
  import { NotificationAncillaryService } from './notification-ancillary.service.js';
16
- let NotificationService = class NotificationService extends Transactional {
21
+ import { NotificationSseService } from './notification-sse.service.js';
22
+ let NotificationService = NotificationService_1 = class NotificationService extends Transactional {
17
23
  #notificationLogRepository = injectRepository(NotificationLogEntity);
18
24
  #inAppNotificationRepository = injectRepository(InAppNotification);
19
25
  #preferenceRepository = injectRepository(NotificationPreference);
20
26
  #webPushSubscriptionRepository = injectRepository(WebPushSubscription);
21
27
  #notificationAncillaryService = inject(NotificationAncillaryService);
22
28
  #taskQueue = inject((TaskQueue), 'notification');
29
+ #sseService = inject(NotificationSseService);
30
+ #logger = inject(Logger, NotificationService_1.name);
23
31
  async send(tenantId, userId, notification, options) {
24
32
  await this.useTransaction(options?.transaction, async (tx) => {
25
33
  const notificationToInsert = {
@@ -36,6 +44,11 @@ let NotificationService = class NotificationService extends Transactional {
36
44
  });
37
45
  }
38
46
  async listInApp(tenantId, userId, options = {}) {
47
+ let afterNotification;
48
+ if (options.after != null) {
49
+ const inApp = await this.#inAppNotificationRepository.loadByQuery({ tenantId, userId, id: options.after });
50
+ afterNotification = await this.#notificationLogRepository.loadByQuery({ tenantId, userId, id: inApp.logId });
51
+ }
39
52
  const rows = await this.#notificationLogRepository.session
40
53
  .select({
41
54
  notification: notificationLog,
@@ -43,10 +56,12 @@ let NotificationService = class NotificationService extends Transactional {
43
56
  })
44
57
  .from(notificationLog)
45
58
  .innerJoin(inAppNotification, and(eq(inAppNotification.tenantId, notificationLog.tenantId), eq(inAppNotification.userId, notificationLog.userId), eq(inAppNotification.logId, notificationLog.id)))
46
- .where(and(eq(notificationLog.tenantId, tenantId), eq(notificationLog.userId, userId), options.includeArchived ? undefined : isNull(inAppNotification.archiveTimestamp), options.unreadOnly ? isNull(inAppNotification.readTimestamp) : undefined))
59
+ .where(and(eq(notificationLog.tenantId, tenantId), eq(notificationLog.userId, userId), options.includeArchived ? undefined : isNull(inAppNotification.archiveTimestamp), options.unreadOnly ? isNull(inAppNotification.readTimestamp) : undefined, isDefined(afterNotification)
60
+ ? or(lt(notificationLog.timestamp, afterNotification.timestamp), and(eq(notificationLog.timestamp, afterNotification.timestamp), lt(notificationLog.id, afterNotification.id)))
61
+ : undefined))
47
62
  .limit(options.limit ?? 50)
48
63
  .offset(options.offset ?? 0)
49
- .orderBy(desc(notificationLog.timestamp));
64
+ .orderBy(desc(notificationLog.timestamp), desc(notificationLog.id));
50
65
  const inAppRows = rows.map((row) => row.inApp);
51
66
  const notificationRows = rows.map((row) => row.notification);
52
67
  const notificationEntities = await this.#notificationLogRepository.mapManyToEntity(notificationRows);
@@ -62,15 +77,19 @@ let NotificationService = class NotificationService extends Transactional {
62
77
  }
63
78
  async markRead(tenantId, userId, id) {
64
79
  await this.#inAppNotificationRepository.updateByQuery({ tenantId, id, userId }, { readTimestamp: TRANSACTION_TIMESTAMP });
80
+ await this.dispatchUnreadCountUpdate(tenantId, userId);
65
81
  }
66
82
  async markAllRead(tenantId, userId) {
67
83
  await this.#inAppNotificationRepository.updateByQuery({ tenantId, userId, readTimestamp: null }, { readTimestamp: TRANSACTION_TIMESTAMP });
84
+ await this.dispatchUnreadCountUpdate(tenantId, userId);
68
85
  }
69
86
  async archive(tenantId, userId, id) {
70
87
  await this.#inAppNotificationRepository.updateByQuery({ tenantId, id, userId }, { archiveTimestamp: TRANSACTION_TIMESTAMP });
88
+ await this.dispatchUnreadCountUpdate(tenantId, userId);
71
89
  }
72
90
  async archiveAll(tenantId, userId) {
73
91
  await this.#inAppNotificationRepository.updateByQuery({ tenantId, userId, archiveTimestamp: null }, { archiveTimestamp: TRANSACTION_TIMESTAMP });
92
+ await this.dispatchUnreadCountUpdate(tenantId, userId);
74
93
  }
75
94
  async unreadCount(tenantId, userId) {
76
95
  return await this.#inAppNotificationRepository.countByQuery({
@@ -113,8 +132,14 @@ let NotificationService = class NotificationService extends Transactional {
113
132
  auth,
114
133
  });
115
134
  }
135
+ async dispatchUnreadCountUpdate(tenantId, userId) {
136
+ await tryIgnoreLogAsync(this.#logger, async () => {
137
+ const unreadCount = await this.unreadCount(tenantId, userId);
138
+ this.#sseService.dispatchUnreadCountUpdate(tenantId, userId, unreadCount);
139
+ });
140
+ }
116
141
  };
117
- NotificationService = __decorate([
142
+ NotificationService = NotificationService_1 = __decorate([
118
143
  Singleton()
119
144
  ], NotificationService);
120
145
  export { NotificationService };
@@ -265,4 +265,32 @@ describe('Notification Flow (Integration)', () => {
265
265
  expect(prefs[0].enabled).toBe(true);
266
266
  });
267
267
  });
268
+ test('should support keyset pagination with after and orderBy', async () => {
269
+ await runInInjectionContext(injector, async () => {
270
+ const logRepo = injectRepository(NotificationLogEntity);
271
+ const user = await subjectService.createUser({ tenantId, email: 'pagination@example.com', firstName: 'Pagination', lastName: 'User' });
272
+ await typeService.initializeTypes({ test: { label: 'Pagination Test' } });
273
+ // Create 3 notifications
274
+ await notificationService.send(tenantId, user.id, { type: 'test', triggerSubjectId: user.id, payload: { index: 1 } });
275
+ await notificationService.send(tenantId, user.id, { type: 'test', triggerSubjectId: user.id, payload: { index: 2 } });
276
+ await notificationService.send(tenantId, user.id, { type: 'test', triggerSubjectId: user.id, payload: { index: 3 } });
277
+ const logs = await logRepo.loadManyByQuery({ tenantId });
278
+ for (const log of logs) {
279
+ await worker.deliver(log.id);
280
+ }
281
+ // Default list (desc timestamp, then desc id)
282
+ const list = await notificationService.listInApp(tenantId, user.id);
283
+ expect(list).toHaveLength(3);
284
+ const firstId = list[0].id;
285
+ const secondId = list[1].id;
286
+ // After first
287
+ const afterFirst = await notificationService.listInApp(tenantId, user.id, { after: firstId });
288
+ expect(afterFirst).toHaveLength(2);
289
+ expect(afterFirst[0].id).toBe(secondId);
290
+ // After second
291
+ const afterSecond = await notificationService.listInApp(tenantId, user.id, { after: secondId });
292
+ expect(afterSecond).toHaveLength(1);
293
+ expect(afterSecond[0].id).toBe(list[2].id);
294
+ });
295
+ });
268
296
  });
@@ -14,7 +14,7 @@ describe('NotificationSseService', () => {
14
14
  // We can't easily spy on the LocalMessageBus internals without more complex setup,
15
15
  // but we can verify that sending doesn't throw.
16
16
  const msg = { tenantId, userId, logId: 'l1' };
17
- await expect(service.send(msg)).resolves.not.toThrow();
17
+ await expect(service.send(msg, 1)).resolves.not.toThrow();
18
18
  });
19
19
  });
20
20
  });
@@ -0,0 +1,9 @@
1
+ import { InAppNotificationView, type NotificationDefinitionMap } from './models/index.js';
2
+ export declare const notificationStreamItemSchema: import("../schema/index.js").ObjectSchema<{
3
+ unreadCount: number;
4
+ notification?: InAppNotificationView<Record<string, import("./models/notification-log.model.js").NotificationDefinition<import("../types/types.js").ObjectLiteral, import("../types/types.js").ObjectLiteral>>> | undefined;
5
+ }>;
6
+ export type NotificationStreamItem<Definitions extends NotificationDefinitionMap = NotificationDefinitionMap> = {
7
+ notification?: InAppNotificationView<Definitions>;
8
+ unreadCount: number;
9
+ };
@@ -0,0 +1,6 @@
1
+ import { number, object, optional } from '../schema/index.js';
2
+ import { InAppNotificationView } from './models/index.js';
3
+ export const notificationStreamItemSchema = object({
4
+ notification: optional(InAppNotificationView),
5
+ unreadCount: number(),
6
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.93.115",
3
+ "version": "0.93.117",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -200,7 +200,7 @@
200
200
  "typedoc-plugin-markdown": "4.10",
201
201
  "typedoc-plugin-missing-exports": "4.1",
202
202
  "typescript": "5.9",
203
- "typescript-eslint": "8.54",
203
+ "typescript-eslint": "8.55",
204
204
  "vite-tsconfig-paths": "6.1",
205
205
  "vitest": "4.0"
206
206
  },
@@ -2,8 +2,8 @@ import type { Logger } from '../logger/logger.js';
2
2
  export declare function tryIgnore<R>(fn: () => R): R | undefined;
3
3
  export declare function tryIgnore<R, F>(fn: () => R, fallback: F): R | F;
4
4
  export declare function tryIgnoreAsync<R>(fn: () => Promise<R>): Promise<R | undefined>;
5
- export declare function tryIgnoreAsync<R, F>(fn: () => Promise<R>, fallback: F): Promise<F>;
5
+ export declare function tryIgnoreAsync<R, F>(fn: () => Promise<R>, fallback: F): Promise<R | F>;
6
6
  export declare function tryIgnoreLog<R>(logger: Logger, fn: () => R): R | undefined;
7
7
  export declare function tryIgnoreLog<R, F>(logger: Logger, fn: () => R, fallback: F): R | F;
8
8
  export declare function tryIgnoreLogAsync<R>(logger: Logger, fn: () => Promise<R>): Promise<R | undefined>;
9
- export declare function tryIgnoreLogAsync<R, F>(logger: Logger, fn: () => Promise<R>, fallback: F): Promise<F>;
9
+ export declare function tryIgnoreLogAsync<R, F>(logger: Logger, fn: () => Promise<R>, fallback: F): Promise<R | F>;