@timothyw/pat-common 1.0.100 → 1.0.102

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 (58) hide show
  1. package/dist/enums/module-type.d.ts +1 -0
  2. package/dist/enums/module-type.js +1 -0
  3. package/dist/types/api/account/update-user-types.d.ts +3 -3
  4. package/dist/types/api/auth/create-account-types.d.ts +2 -1
  5. package/dist/types/api/habits/create-habit-types.d.ts +2 -2
  6. package/dist/types/api/habits/update-habit-types.d.ts +2 -2
  7. package/dist/types/api/index.d.ts +1 -0
  8. package/dist/types/api/index.js +1 -0
  9. package/dist/types/api/notifications/create-notification-template-types.d.ts +93 -0
  10. package/dist/types/api/notifications/create-notification-template-types.js +31 -0
  11. package/dist/types/api/notifications/delete-notification-template-types.d.ts +14 -0
  12. package/dist/types/api/notifications/delete-notification-template-types.js +11 -0
  13. package/dist/types/api/notifications/get-notification-instances-types.d.ts +45 -0
  14. package/dist/types/api/notifications/get-notification-instances-types.js +19 -0
  15. package/dist/types/api/notifications/get-notification-templates-types.d.ts +23 -0
  16. package/dist/types/api/notifications/get-notification-templates-types.js +12 -0
  17. package/dist/types/api/notifications/index.d.ts +7 -0
  18. package/dist/types/api/notifications/index.js +23 -0
  19. package/dist/types/api/notifications/preview-notification-template-types.d.ts +58 -0
  20. package/dist/types/api/notifications/preview-notification-template-types.js +23 -0
  21. package/dist/types/api/notifications/sync-notification-template-types.d.ts +29 -0
  22. package/dist/types/api/notifications/sync-notification-template-types.js +14 -0
  23. package/dist/types/api/notifications/update-notification-template-types.d.ts +84 -0
  24. package/dist/types/api/notifications/update-notification-template-types.js +28 -0
  25. package/dist/types/api/people/create-person-note-types.d.ts +2 -2
  26. package/dist/types/api/tasks/get-tasks-types.d.ts +1 -1
  27. package/dist/types/id-types.d.ts +8 -0
  28. package/dist/types/id-types.js +3 -1
  29. package/dist/types/models/index.d.ts +3 -0
  30. package/dist/types/models/index.js +3 -0
  31. package/dist/types/models/notifiable.d.ts +42 -0
  32. package/dist/types/models/notifiable.js +2 -0
  33. package/dist/types/models/notification-instance-data.d.ts +128 -0
  34. package/dist/types/models/notification-instance-data.js +34 -0
  35. package/dist/types/models/notification-template-data.d.ts +202 -0
  36. package/dist/types/models/notification-template-data.js +38 -0
  37. package/dist/types/models/user-data.d.ts +2 -2
  38. package/dist/utils/serializing-utils.d.ts +5 -1
  39. package/dist/utils/serializing-utils.js +12 -0
  40. package/package.json +1 -1
  41. package/src/enums/module-type.ts +1 -0
  42. package/src/types/api/auth/create-account-types.ts +2 -1
  43. package/src/types/api/index.ts +1 -0
  44. package/src/types/api/notifications/create-notification-template-types.ts +39 -0
  45. package/src/types/api/notifications/delete-notification-template-types.ts +14 -0
  46. package/src/types/api/notifications/get-notification-instances-types.ts +29 -0
  47. package/src/types/api/notifications/get-notification-templates-types.ts +21 -0
  48. package/src/types/api/notifications/index.ts +7 -0
  49. package/src/types/api/notifications/preview-notification-template-types.ts +26 -0
  50. package/src/types/api/notifications/sync-notification-template-types.ts +23 -0
  51. package/src/types/api/notifications/update-notification-template-types.ts +36 -0
  52. package/src/types/api/tasks/get-tasks-types.ts +1 -1
  53. package/src/types/id-types.ts +7 -1
  54. package/src/types/models/index.ts +3 -0
  55. package/src/types/models/notifiable.ts +52 -0
  56. package/src/types/models/notification-instance-data.ts +40 -0
  57. package/src/types/models/notification-template-data.ts +50 -0
  58. package/src/utils/serializing-utils.ts +18 -0
@@ -0,0 +1,39 @@
1
+ import { z } from "zod";
2
+ import { Serialized } from "../../../utils";
3
+ import { NotificationTemplateData, CreateNotificationTemplateData, notificationEntityTypeSchema, notificationTriggerTypeSchema } from "../../models/notification-template-data";
4
+
5
+ // Request schema
6
+ export const createNotificationTemplateRequestSchema = z.object({
7
+ entityType: notificationEntityTypeSchema,
8
+ entityId: z.string().optional(),
9
+ name: z.string().min(1).max(100),
10
+ description: z.string().max(500).optional(),
11
+ trigger: z.object({
12
+ type: notificationTriggerTypeSchema,
13
+ conditions: z.record(z.any()),
14
+ timing: z.record(z.any())
15
+ }),
16
+ content: z.object({
17
+ title: z.string().min(1).max(200),
18
+ body: z.string().min(1).max(1000),
19
+ variables: z.record(z.string()).optional()
20
+ }),
21
+ active: z.boolean().default(true),
22
+ inheritedFrom: z.string().optional(),
23
+ customized: z.boolean().default(false)
24
+ });
25
+
26
+ export type CreateNotificationTemplateRequest = z.infer<typeof createNotificationTemplateRequestSchema>;
27
+
28
+ // Response schema
29
+ export const createNotificationTemplateResponseSchema = z.object({
30
+ success: z.boolean(),
31
+ template: z.any().optional(), // Will be Serialized<NotificationTemplateData>
32
+ error: z.string().optional()
33
+ });
34
+
35
+ export type CreateNotificationTemplateResponse = {
36
+ success: boolean;
37
+ template?: Serialized<NotificationTemplateData>;
38
+ error?: string;
39
+ };
@@ -0,0 +1,14 @@
1
+ import { z } from "zod";
2
+
3
+ // Request schema - no body needed for DELETE
4
+ export const deleteNotificationTemplateRequestSchema = z.object({});
5
+
6
+ export type DeleteNotificationTemplateRequest = z.infer<typeof deleteNotificationTemplateRequestSchema>;
7
+
8
+ // Response schema
9
+ export const deleteNotificationTemplateResponseSchema = z.object({
10
+ success: z.boolean(),
11
+ error: z.string().optional()
12
+ });
13
+
14
+ export type DeleteNotificationTemplateResponse = z.infer<typeof deleteNotificationTemplateResponseSchema>;
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ import { Serialized } from "../../../utils";
3
+ import { NotificationInstanceData } from "../../models/notification-instance-data";
4
+
5
+ // Request schema - query parameters
6
+ export const getNotificationInstancesRequestSchema = z.object({
7
+ status: z.string().optional(), // filter by status
8
+ templateId: z.string().optional(), // filter by template
9
+ entityId: z.string().optional(), // filter by entity
10
+ limit: z.number().optional(), // pagination
11
+ offset: z.number().optional() // pagination
12
+ });
13
+
14
+ export type GetNotificationInstancesRequest = z.infer<typeof getNotificationInstancesRequestSchema>;
15
+
16
+ // Response schema
17
+ export const getNotificationInstancesResponseSchema = z.object({
18
+ success: z.boolean(),
19
+ instances: z.array(z.any()).optional(), // Will be Serialized<NotificationInstanceData>[]
20
+ total: z.number().optional(),
21
+ error: z.string().optional()
22
+ });
23
+
24
+ export type GetNotificationInstancesResponse = {
25
+ success: boolean;
26
+ instances?: Serialized<NotificationInstanceData>[];
27
+ total?: number;
28
+ error?: string;
29
+ };
@@ -0,0 +1,21 @@
1
+ import { z } from "zod";
2
+ import { Serialized } from "../../../utils";
3
+ import { NotificationTemplateData } from "../../models/notification-template-data";
4
+
5
+ // Request schema - no body needed for GET
6
+ export const getNotificationTemplatesRequestSchema = z.object({});
7
+
8
+ export type GetNotificationTemplatesRequest = z.infer<typeof getNotificationTemplatesRequestSchema>;
9
+
10
+ // Response schema
11
+ export const getNotificationTemplatesResponseSchema = z.object({
12
+ success: z.boolean(),
13
+ templates: z.array(z.any()).optional(), // Will be Serialized<NotificationTemplateData>[]
14
+ error: z.string().optional()
15
+ });
16
+
17
+ export type GetNotificationTemplatesResponse = {
18
+ success: boolean;
19
+ templates?: Serialized<NotificationTemplateData>[];
20
+ error?: string;
21
+ };
@@ -0,0 +1,7 @@
1
+ export * from './get-notification-templates-types';
2
+ export * from './create-notification-template-types';
3
+ export * from './update-notification-template-types';
4
+ export * from './delete-notification-template-types';
5
+ export * from './get-notification-instances-types';
6
+ export * from './preview-notification-template-types';
7
+ export * from './sync-notification-template-types';
@@ -0,0 +1,26 @@
1
+ import { z } from "zod";
2
+
3
+ // Request schema
4
+ export const previewNotificationTemplateRequestSchema = z.object({
5
+ templateTitle: z.string(),
6
+ templateBody: z.string(),
7
+ entityType: z.string(),
8
+ entityId: z.string(),
9
+ variables: z.record(z.any()).optional()
10
+ });
11
+
12
+ export type PreviewNotificationTemplateRequest = z.infer<typeof previewNotificationTemplateRequestSchema>;
13
+
14
+ // Response schema
15
+ export const previewNotificationTemplateResponseSchema = z.object({
16
+ success: z.boolean(),
17
+ preview: z.object({
18
+ title: z.string(),
19
+ body: z.string(),
20
+ variables: z.record(z.any())
21
+ }).optional(),
22
+ missingVariables: z.array(z.string()).optional(),
23
+ error: z.string().optional()
24
+ });
25
+
26
+ export type PreviewNotificationTemplateResponse = z.infer<typeof previewNotificationTemplateResponseSchema>;
@@ -0,0 +1,23 @@
1
+ import { z } from "zod";
2
+ import { Serialized } from "../../../utils";
3
+ import { NotificationTemplateData } from "../../models/notification-template-data";
4
+
5
+ // Request schema
6
+ export const syncNotificationTemplateRequestSchema = z.object({
7
+ sync: z.boolean() // true to sync with parent, false to unsync
8
+ });
9
+
10
+ export type SyncNotificationTemplateRequest = z.infer<typeof syncNotificationTemplateRequestSchema>;
11
+
12
+ // Response schema
13
+ export const syncNotificationTemplateResponseSchema = z.object({
14
+ success: z.boolean(),
15
+ template: z.any().optional(), // Will be Serialized<NotificationTemplateData>
16
+ error: z.string().optional()
17
+ });
18
+
19
+ export type SyncNotificationTemplateResponse = {
20
+ success: boolean;
21
+ template?: Serialized<NotificationTemplateData>;
22
+ error?: string;
23
+ };
@@ -0,0 +1,36 @@
1
+ import { z } from "zod";
2
+ import { Serialized } from "../../../utils";
3
+ import { NotificationTemplateData, notificationEntityTypeSchema, notificationTriggerTypeSchema } from "../../models/notification-template-data";
4
+
5
+ // Request schema
6
+ export const updateNotificationTemplateRequestSchema = z.object({
7
+ name: z.string().min(1).max(100).optional(),
8
+ description: z.string().max(500).optional(),
9
+ trigger: z.object({
10
+ type: notificationTriggerTypeSchema,
11
+ conditions: z.record(z.any()),
12
+ timing: z.record(z.any())
13
+ }).optional(),
14
+ content: z.object({
15
+ title: z.string().min(1).max(200),
16
+ body: z.string().min(1).max(1000),
17
+ variables: z.record(z.string()).optional()
18
+ }).optional(),
19
+ active: z.boolean().optional(),
20
+ customized: z.boolean().optional()
21
+ });
22
+
23
+ export type UpdateNotificationTemplateRequest = z.infer<typeof updateNotificationTemplateRequestSchema>;
24
+
25
+ // Response schema
26
+ export const updateNotificationTemplateResponseSchema = z.object({
27
+ success: z.boolean(),
28
+ template: z.any().optional(), // Will be Serialized<NotificationTemplateData>
29
+ error: z.string().optional()
30
+ });
31
+
32
+ export type UpdateNotificationTemplateResponse = {
33
+ success: boolean;
34
+ template?: Serialized<NotificationTemplateData>;
35
+ error?: string;
36
+ };
@@ -2,5 +2,5 @@ import { Serialized } from "../../../utils";
2
2
  import { TaskData } from "../../models";
3
3
 
4
4
  export interface GetTasksResponse {
5
- tasks: Serialized<TaskData>;
5
+ tasks: Serialized<TaskData>[];
6
6
  }
@@ -28,4 +28,10 @@ export const habitIdSchema = z.string().transform((val): TaskListId => val as Ta
28
28
  export type HabitId = string & { readonly __brand: "HabitId" };
29
29
 
30
30
  export const habitEntryIdSchema = z.string().transform((val): TaskListId => val as TaskListId);
31
- export type HabitEntryId = string & { readonly __brand: "HabitEntryId" };
31
+ export type HabitEntryId = string & { readonly __brand: "HabitEntryId" };
32
+
33
+ export const notificationTemplateIdSchema = z.string().transform((val): NotificationTemplateId => val as NotificationTemplateId);
34
+ export type NotificationTemplateId = string & { readonly __brand: "NotificationTemplateId" };
35
+
36
+ export const notificationInstanceIdSchema = z.string().transform((val): NotificationInstanceId => val as NotificationInstanceId);
37
+ export type NotificationInstanceId = string & { readonly __brand: "NotificationInstanceId" };
@@ -1,6 +1,9 @@
1
1
  export * from './auth-data';
2
2
  export * from './habit-data';
3
3
  export * from './item-data';
4
+ export * from './notification-template-data';
5
+ export * from './notification-instance-data';
6
+ export * from './notifiable';
4
7
  export * from './person-data';
5
8
  export * from './program-config';
6
9
  export * from './task-data';
@@ -0,0 +1,52 @@
1
+ import { NotificationTemplateData, NotificationEntityType } from "./notification-template-data";
2
+
3
+ export interface NotificationContext<T = any> {
4
+ entityId: string;
5
+ entityType: NotificationEntityType;
6
+ entityData: T;
7
+ userId: string;
8
+ // Additional context for template variable replacement
9
+ variables: Record<string, any>;
10
+ }
11
+
12
+ export interface INotifiable<T = any> {
13
+ /**
14
+ * Get the ID of this notifiable entity
15
+ */
16
+ getId(): string;
17
+
18
+ /**
19
+ * Get the entity type for notification purposes
20
+ */
21
+ getNotificationEntityType(): NotificationEntityType;
22
+
23
+ /**
24
+ * Get context data for notification template variables
25
+ */
26
+ getNotificationContext(): NotificationContext<T>;
27
+
28
+ /**
29
+ * Get inherited notification templates from parent entities
30
+ */
31
+ getInheritedNotificationTemplates(): Promise<NotificationTemplateData[]>;
32
+
33
+ /**
34
+ * Get custom notification templates specific to this entity
35
+ */
36
+ getCustomNotificationTemplates(): Promise<NotificationTemplateData[]>;
37
+
38
+ /**
39
+ * Get all effective notification templates (inherited + custom)
40
+ */
41
+ getAllNotificationTemplates(): Promise<NotificationTemplateData[]>;
42
+
43
+ /**
44
+ * Register notification triggers when entity is created/updated
45
+ */
46
+ registerNotificationTriggers(): Promise<void>;
47
+
48
+ /**
49
+ * Remove notification triggers when entity is deleted
50
+ */
51
+ removeNotificationTriggers(): Promise<void>;
52
+ }
@@ -0,0 +1,40 @@
1
+ import { z } from "zod";
2
+ import { NotificationInstanceId, NotificationTemplateId, UserId } from "../id-types";
3
+
4
+ export const notificationStatusSchema = z.enum(['scheduled', 'sent', 'failed', 'cancelled']);
5
+ export type NotificationStatus = z.infer<typeof notificationStatusSchema>;
6
+
7
+ export const notificationInstanceDataSchema = z.object({
8
+ _id: z.string().transform((val): NotificationInstanceId => val as NotificationInstanceId),
9
+ templateId: z.string().transform((val): NotificationTemplateId => val as NotificationTemplateId),
10
+ userId: z.string().transform((val): UserId => val as UserId),
11
+ entityId: z.string(), // ID of the specific entity this notification is for
12
+ scheduledFor: z.date(),
13
+ status: notificationStatusSchema,
14
+ sentAt: z.date().optional(),
15
+ content: z.object({
16
+ title: z.string(),
17
+ body: z.string(),
18
+ data: z.record(z.any()).optional() // additional data for the notification
19
+ }),
20
+ redisId: z.string(), // link to Redis scheduled notification for coordination
21
+ error: z.string().optional(), // error message if status is 'failed'
22
+ createdAt: z.date(),
23
+ updatedAt: z.date()
24
+ });
25
+
26
+ export type NotificationInstanceData = z.infer<typeof notificationInstanceDataSchema>;
27
+
28
+ // Helper type for creating new instances (without _id, dates, status)
29
+ export const createNotificationInstanceSchema = notificationInstanceDataSchema.omit({
30
+ _id: true,
31
+ status: true,
32
+ sentAt: true,
33
+ error: true,
34
+ createdAt: true,
35
+ updatedAt: true
36
+ }).extend({
37
+ status: notificationStatusSchema.default('scheduled')
38
+ });
39
+
40
+ export type CreateNotificationInstanceData = z.infer<typeof createNotificationInstanceSchema>;
@@ -0,0 +1,50 @@
1
+ import { z } from "zod";
2
+ import { NotificationTemplateId, UserId } from "../id-types";
3
+
4
+ export const notificationEntityTypeSchema = z.enum(['agenda', 'tasks', 'habits', 'agenda_item', 'task_list', 'task', 'habit']);
5
+ export type NotificationEntityType = z.infer<typeof notificationEntityTypeSchema>;
6
+
7
+ export const notificationTriggerTypeSchema = z.enum(['time_based', 'event_based', 'recurring']);
8
+ export type NotificationTriggerType = z.infer<typeof notificationTriggerTypeSchema>;
9
+
10
+ export const notificationTriggerSchema = z.object({
11
+ type: notificationTriggerTypeSchema,
12
+ conditions: z.record(z.any()), // flexible conditions object
13
+ timing: z.record(z.any()) // timing configuration like "5 minutes before due"
14
+ });
15
+ export type NotificationTrigger = z.infer<typeof notificationTriggerSchema>;
16
+
17
+ export const notificationContentSchema = z.object({
18
+ title: z.string(),
19
+ body: z.string(),
20
+ // Support for template variables like {{entity.name}}
21
+ variables: z.record(z.string()).optional()
22
+ });
23
+ export type NotificationContent = z.infer<typeof notificationContentSchema>;
24
+
25
+ export const notificationTemplateDataSchema = z.object({
26
+ _id: z.string().transform((val): NotificationTemplateId => val as NotificationTemplateId),
27
+ userId: z.string().transform((val): UserId => val as UserId),
28
+ entityType: notificationEntityTypeSchema,
29
+ entityId: z.string().optional(), // null/undefined for panel-level templates
30
+ name: z.string(),
31
+ description: z.string().optional(),
32
+ trigger: notificationTriggerSchema,
33
+ content: notificationContentSchema,
34
+ active: z.boolean().default(true),
35
+ inheritedFrom: z.string().transform((val): NotificationTemplateId => val as NotificationTemplateId).optional(),
36
+ customized: z.boolean().default(false), // true if user modified inherited template
37
+ createdAt: z.date(),
38
+ updatedAt: z.date()
39
+ });
40
+
41
+ export type NotificationTemplateData = z.infer<typeof notificationTemplateDataSchema>;
42
+
43
+ // Helper type for creating new templates (without _id, dates)
44
+ export const createNotificationTemplateSchema = notificationTemplateDataSchema.omit({
45
+ _id: true,
46
+ createdAt: true,
47
+ updatedAt: true
48
+ });
49
+
50
+ export type CreateNotificationTemplateData = z.infer<typeof createNotificationTemplateSchema>;
@@ -5,6 +5,8 @@ import {
5
5
  ItemData, Person,
6
6
  PersonData,
7
7
  PersonNoteData,
8
+ NotificationTemplateData,
9
+ NotificationInstanceData,
8
10
  TaskData, TaskListData,
9
11
  ThoughtData,
10
12
  UserData
@@ -126,6 +128,22 @@ export class Serializer {
126
128
  static deserializeUserData(data: Serialized<UserData>): UserData {
127
129
  return this.deserialize(data) as unknown as UserData;
128
130
  }
131
+
132
+ static serializeNotificationTemplateData(data: NotificationTemplateData): Serialized<NotificationTemplateData> {
133
+ return this.serialize(data);
134
+ }
135
+
136
+ static deserializeNotificationTemplateData(data: Serialized<NotificationTemplateData>): NotificationTemplateData {
137
+ return this.deserialize(data) as unknown as NotificationTemplateData;
138
+ }
139
+
140
+ static serializeNotificationInstanceData(data: NotificationInstanceData): Serialized<NotificationInstanceData> {
141
+ return this.serialize(data);
142
+ }
143
+
144
+ static deserializeNotificationInstanceData(data: Serialized<NotificationInstanceData>): NotificationInstanceData {
145
+ return this.deserialize(data) as unknown as NotificationInstanceData;
146
+ }
129
147
  }
130
148
 
131
149
  function serializeRecursive(obj: any): any {