@timothyw/pat-common 1.0.121 → 1.0.122

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.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './enums';
2
2
  export * from './types';
3
3
  export * from './utils';
4
+ export * from './notification-entity-registry';
package/dist/index.js CHANGED
@@ -17,3 +17,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./enums"), exports);
18
18
  __exportStar(require("./types"), exports);
19
19
  __exportStar(require("./utils"), exports);
20
+ __exportStar(require("./notification-entity-registry"), exports);
@@ -0,0 +1,77 @@
1
+ import { NotificationEntityConfig, ParentResolutionResult } from './types/notification-entity-config';
2
+ /**
3
+ * Registry for managing notification entity configurations and parent resolution
4
+ */
5
+ export declare class NotificationEntityRegistry {
6
+ private static instance;
7
+ private entityConfigs;
8
+ private constructor();
9
+ /**
10
+ * Get the singleton instance
11
+ */
12
+ static getInstance(): NotificationEntityRegistry;
13
+ /**
14
+ * Register a new entity configuration
15
+ */
16
+ registerEntity(config: NotificationEntityConfig): void;
17
+ /**
18
+ * Get configuration for an entity type
19
+ */
20
+ getEntityConfig(entityType: string): NotificationEntityConfig | null;
21
+ /**
22
+ * Get all registered entity types
23
+ */
24
+ getEntityTypes(): string[];
25
+ /**
26
+ * Get all entity configurations
27
+ */
28
+ getAllConfigs(): NotificationEntityConfig[];
29
+ /**
30
+ * Resolve the parent type for a specific entity instance
31
+ */
32
+ resolveParent(entityType: string, entityData: any): ParentResolutionResult | null;
33
+ /**
34
+ * Check if an entity type supports dynamic parent resolution
35
+ */
36
+ isDynamicParentType(entityType: string): boolean;
37
+ /**
38
+ * Get the parent property name for dynamic resolution
39
+ */
40
+ getParentProperty(entityType: string): string | null;
41
+ /**
42
+ * Get display name for an entity type
43
+ */
44
+ getDisplayName(entityType: string): string;
45
+ /**
46
+ * Get icon for an entity type
47
+ */
48
+ getIcon(entityType: string): string | null;
49
+ /**
50
+ * Check if entity type exists
51
+ */
52
+ hasEntityType(entityType: string): boolean;
53
+ /**
54
+ * Remove an entity configuration
55
+ */
56
+ unregisterEntity(entityType: string): boolean;
57
+ /**
58
+ * Clear all configurations
59
+ */
60
+ clear(): void;
61
+ /**
62
+ * Resolve static parent type
63
+ */
64
+ private resolveStaticParent;
65
+ /**
66
+ * Resolve dynamic parent type based on entity data
67
+ */
68
+ private resolveDynamicParent;
69
+ /**
70
+ * Register default entity configurations
71
+ */
72
+ private registerDefaultEntities;
73
+ }
74
+ /**
75
+ * Convenience function to get the singleton instance
76
+ */
77
+ export declare function getNotificationEntityRegistry(): NotificationEntityRegistry;
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NotificationEntityRegistry = void 0;
4
+ exports.getNotificationEntityRegistry = getNotificationEntityRegistry;
5
+ /**
6
+ * Registry for managing notification entity configurations and parent resolution
7
+ */
8
+ class NotificationEntityRegistry {
9
+ constructor() {
10
+ this.entityConfigs = new Map();
11
+ // Initialize with default configurations
12
+ this.registerDefaultEntities();
13
+ }
14
+ /**
15
+ * Get the singleton instance
16
+ */
17
+ static getInstance() {
18
+ if (!NotificationEntityRegistry.instance) {
19
+ NotificationEntityRegistry.instance = new NotificationEntityRegistry();
20
+ }
21
+ return NotificationEntityRegistry.instance;
22
+ }
23
+ /**
24
+ * Register a new entity configuration
25
+ */
26
+ registerEntity(config) {
27
+ this.entityConfigs.set(config.entityType, config);
28
+ }
29
+ /**
30
+ * Get configuration for an entity type
31
+ */
32
+ getEntityConfig(entityType) {
33
+ return this.entityConfigs.get(entityType) || null;
34
+ }
35
+ /**
36
+ * Get all registered entity types
37
+ */
38
+ getEntityTypes() {
39
+ return Array.from(this.entityConfigs.keys());
40
+ }
41
+ /**
42
+ * Get all entity configurations
43
+ */
44
+ getAllConfigs() {
45
+ return Array.from(this.entityConfigs.values());
46
+ }
47
+ /**
48
+ * Resolve the parent type for a specific entity instance
49
+ */
50
+ resolveParent(entityType, entityData) {
51
+ const config = this.entityConfigs.get(entityType);
52
+ if (!config) {
53
+ return null;
54
+ }
55
+ const resolver = config.parentResolver;
56
+ if (resolver.type === 'static') {
57
+ return this.resolveStaticParent(resolver);
58
+ }
59
+ else {
60
+ return this.resolveDynamicParent(resolver, entityData);
61
+ }
62
+ }
63
+ /**
64
+ * Check if an entity type supports dynamic parent resolution
65
+ */
66
+ isDynamicParentType(entityType) {
67
+ const config = this.entityConfigs.get(entityType);
68
+ return config?.parentResolver.type === 'dynamic' || false;
69
+ }
70
+ /**
71
+ * Get the parent property name for dynamic resolution
72
+ */
73
+ getParentProperty(entityType) {
74
+ const config = this.entityConfigs.get(entityType);
75
+ if (config?.parentResolver.type === 'dynamic') {
76
+ return config.parentResolver.parentProperty;
77
+ }
78
+ return null;
79
+ }
80
+ /**
81
+ * Get display name for an entity type
82
+ */
83
+ getDisplayName(entityType) {
84
+ const config = this.entityConfigs.get(entityType);
85
+ return config?.displayName || entityType;
86
+ }
87
+ /**
88
+ * Get icon for an entity type
89
+ */
90
+ getIcon(entityType) {
91
+ const config = this.entityConfigs.get(entityType);
92
+ return config?.icon || null;
93
+ }
94
+ /**
95
+ * Check if entity type exists
96
+ */
97
+ hasEntityType(entityType) {
98
+ return this.entityConfigs.has(entityType);
99
+ }
100
+ /**
101
+ * Remove an entity configuration
102
+ */
103
+ unregisterEntity(entityType) {
104
+ return this.entityConfigs.delete(entityType);
105
+ }
106
+ /**
107
+ * Clear all configurations
108
+ */
109
+ clear() {
110
+ this.entityConfigs.clear();
111
+ }
112
+ /**
113
+ * Resolve static parent type
114
+ */
115
+ resolveStaticParent(resolver) {
116
+ return {
117
+ parentType: resolver.parentType,
118
+ isDynamic: false
119
+ };
120
+ }
121
+ /**
122
+ * Resolve dynamic parent type based on entity data
123
+ */
124
+ resolveDynamicParent(resolver, entityData) {
125
+ const propertyValue = entityData?.[resolver.parentProperty];
126
+ if (propertyValue && typeof propertyValue === 'string' && propertyValue.trim()) {
127
+ // Use the property value to construct the parent type
128
+ const parentType = resolver.parentTypePrefix + propertyValue.trim();
129
+ return {
130
+ parentType,
131
+ isDynamic: true,
132
+ resolvedProperty: propertyValue.trim(),
133
+ usedFallback: false
134
+ };
135
+ }
136
+ // Fall back to default parent
137
+ return {
138
+ parentType: resolver.fallbackParent,
139
+ isDynamic: true,
140
+ usedFallback: true
141
+ };
142
+ }
143
+ /**
144
+ * Register default entity configurations
145
+ */
146
+ registerDefaultEntities() {
147
+ // Agenda Panel (static parent of agenda items)
148
+ this.registerEntity({
149
+ entityType: 'agenda_panel',
150
+ parentResolver: {
151
+ type: 'static',
152
+ parentType: 'agenda_panel' // Self-referencing for panel level
153
+ },
154
+ displayName: 'Agenda Panel',
155
+ icon: 'calendar',
156
+ description: 'Default notification templates for all agenda items'
157
+ });
158
+ // Agenda Item (can have dynamic parent based on category)
159
+ this.registerEntity({
160
+ entityType: 'agenda_item',
161
+ parentResolver: {
162
+ type: 'dynamic',
163
+ parentProperty: 'category',
164
+ parentTypePrefix: 'agenda_category_',
165
+ fallbackParent: 'agenda_panel'
166
+ },
167
+ displayName: 'Agenda Item',
168
+ icon: 'calendar',
169
+ description: 'Individual agenda item notifications'
170
+ });
171
+ // Inbox Panel
172
+ this.registerEntity({
173
+ entityType: 'inbox_panel',
174
+ parentResolver: {
175
+ type: 'static',
176
+ parentType: 'inbox_panel' // Self-referencing for panel level
177
+ },
178
+ displayName: 'Inbox Panel',
179
+ icon: 'mail',
180
+ description: 'Inbox notification templates'
181
+ });
182
+ }
183
+ }
184
+ exports.NotificationEntityRegistry = NotificationEntityRegistry;
185
+ /**
186
+ * Convenience function to get the singleton instance
187
+ */
188
+ function getNotificationEntityRegistry() {
189
+ return NotificationEntityRegistry.getInstance();
190
+ }
@@ -6,7 +6,7 @@ export * from './id-types';
6
6
  export * from './people-types';
7
7
  export * from './lists-types';
8
8
  export * from './notifications-types';
9
+ export * from './notification-entity-config';
9
10
  export * from './auth-types';
10
11
  export * from './user-types';
11
12
  export * from './program-config-types';
12
- export * from './misc';
@@ -22,7 +22,7 @@ __exportStar(require("./id-types"), exports);
22
22
  __exportStar(require("./people-types"), exports);
23
23
  __exportStar(require("./lists-types"), exports);
24
24
  __exportStar(require("./notifications-types"), exports);
25
+ __exportStar(require("./notification-entity-config"), exports);
25
26
  __exportStar(require("./auth-types"), exports);
26
27
  __exportStar(require("./user-types"), exports);
27
28
  __exportStar(require("./program-config-types"), exports);
28
- __exportStar(require("./misc"), exports);
@@ -0,0 +1,157 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Static parent resolver - entity always inherits from the same parent type
4
+ */
5
+ export interface StaticParentResolver {
6
+ type: 'static';
7
+ parentType: string;
8
+ }
9
+ /**
10
+ * Dynamic parent resolver - parent determined by entity properties
11
+ */
12
+ export interface DynamicParentResolver {
13
+ type: 'dynamic';
14
+ parentProperty: string;
15
+ parentTypePrefix: string;
16
+ fallbackParent: string;
17
+ }
18
+ export type ParentResolver = StaticParentResolver | DynamicParentResolver;
19
+ /**
20
+ * Configuration for a notification entity type
21
+ */
22
+ export interface NotificationEntityConfig {
23
+ entityType: string;
24
+ parentResolver: ParentResolver;
25
+ displayName: string;
26
+ icon?: string;
27
+ description?: string;
28
+ }
29
+ /**
30
+ * Result of parent resolution for a specific entity instance
31
+ */
32
+ export interface ParentResolutionResult {
33
+ parentType: string;
34
+ isDynamic: boolean;
35
+ resolvedProperty?: string;
36
+ usedFallback?: boolean;
37
+ }
38
+ /**
39
+ * Zod schemas for validation
40
+ */
41
+ export declare const staticParentResolverSchema: z.ZodObject<{
42
+ type: z.ZodLiteral<"static">;
43
+ parentType: z.ZodString;
44
+ }, "strip", z.ZodTypeAny, {
45
+ type: "static";
46
+ parentType: string;
47
+ }, {
48
+ type: "static";
49
+ parentType: string;
50
+ }>;
51
+ export declare const dynamicParentResolverSchema: z.ZodObject<{
52
+ type: z.ZodLiteral<"dynamic">;
53
+ parentProperty: z.ZodString;
54
+ parentTypePrefix: z.ZodString;
55
+ fallbackParent: z.ZodString;
56
+ }, "strip", z.ZodTypeAny, {
57
+ type: "dynamic";
58
+ parentProperty: string;
59
+ parentTypePrefix: string;
60
+ fallbackParent: string;
61
+ }, {
62
+ type: "dynamic";
63
+ parentProperty: string;
64
+ parentTypePrefix: string;
65
+ fallbackParent: string;
66
+ }>;
67
+ export declare const parentResolverSchema: z.ZodUnion<[z.ZodObject<{
68
+ type: z.ZodLiteral<"static">;
69
+ parentType: z.ZodString;
70
+ }, "strip", z.ZodTypeAny, {
71
+ type: "static";
72
+ parentType: string;
73
+ }, {
74
+ type: "static";
75
+ parentType: string;
76
+ }>, z.ZodObject<{
77
+ type: z.ZodLiteral<"dynamic">;
78
+ parentProperty: z.ZodString;
79
+ parentTypePrefix: z.ZodString;
80
+ fallbackParent: z.ZodString;
81
+ }, "strip", z.ZodTypeAny, {
82
+ type: "dynamic";
83
+ parentProperty: string;
84
+ parentTypePrefix: string;
85
+ fallbackParent: string;
86
+ }, {
87
+ type: "dynamic";
88
+ parentProperty: string;
89
+ parentTypePrefix: string;
90
+ fallbackParent: string;
91
+ }>]>;
92
+ export declare const notificationEntityConfigSchema: z.ZodObject<{
93
+ entityType: z.ZodString;
94
+ parentResolver: z.ZodUnion<[z.ZodObject<{
95
+ type: z.ZodLiteral<"static">;
96
+ parentType: z.ZodString;
97
+ }, "strip", z.ZodTypeAny, {
98
+ type: "static";
99
+ parentType: string;
100
+ }, {
101
+ type: "static";
102
+ parentType: string;
103
+ }>, z.ZodObject<{
104
+ type: z.ZodLiteral<"dynamic">;
105
+ parentProperty: z.ZodString;
106
+ parentTypePrefix: z.ZodString;
107
+ fallbackParent: z.ZodString;
108
+ }, "strip", z.ZodTypeAny, {
109
+ type: "dynamic";
110
+ parentProperty: string;
111
+ parentTypePrefix: string;
112
+ fallbackParent: string;
113
+ }, {
114
+ type: "dynamic";
115
+ parentProperty: string;
116
+ parentTypePrefix: string;
117
+ fallbackParent: string;
118
+ }>]>;
119
+ displayName: z.ZodString;
120
+ icon: z.ZodOptional<z.ZodString>;
121
+ description: z.ZodOptional<z.ZodString>;
122
+ }, "strip", z.ZodTypeAny, {
123
+ entityType: string;
124
+ parentResolver: {
125
+ type: "static";
126
+ parentType: string;
127
+ } | {
128
+ type: "dynamic";
129
+ parentProperty: string;
130
+ parentTypePrefix: string;
131
+ fallbackParent: string;
132
+ };
133
+ displayName: string;
134
+ description?: string | undefined;
135
+ icon?: string | undefined;
136
+ }, {
137
+ entityType: string;
138
+ parentResolver: {
139
+ type: "static";
140
+ parentType: string;
141
+ } | {
142
+ type: "dynamic";
143
+ parentProperty: string;
144
+ parentTypePrefix: string;
145
+ fallbackParent: string;
146
+ };
147
+ displayName: string;
148
+ description?: string | undefined;
149
+ icon?: string | undefined;
150
+ }>;
151
+ /**
152
+ * Type exports
153
+ */
154
+ export type StaticParentResolverData = z.infer<typeof staticParentResolverSchema>;
155
+ export type DynamicParentResolverData = z.infer<typeof dynamicParentResolverSchema>;
156
+ export type ParentResolverData = z.infer<typeof parentResolverSchema>;
157
+ export type NotificationEntityConfigData = z.infer<typeof notificationEntityConfigSchema>;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.notificationEntityConfigSchema = exports.parentResolverSchema = exports.dynamicParentResolverSchema = exports.staticParentResolverSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ /**
6
+ * Zod schemas for validation
7
+ */
8
+ exports.staticParentResolverSchema = zod_1.z.object({
9
+ type: zod_1.z.literal('static'),
10
+ parentType: zod_1.z.string()
11
+ });
12
+ exports.dynamicParentResolverSchema = zod_1.z.object({
13
+ type: zod_1.z.literal('dynamic'),
14
+ parentProperty: zod_1.z.string(),
15
+ parentTypePrefix: zod_1.z.string(),
16
+ fallbackParent: zod_1.z.string()
17
+ });
18
+ exports.parentResolverSchema = zod_1.z.union([
19
+ exports.staticParentResolverSchema,
20
+ exports.dynamicParentResolverSchema
21
+ ]);
22
+ exports.notificationEntityConfigSchema = zod_1.z.object({
23
+ entityType: zod_1.z.string(),
24
+ parentResolver: exports.parentResolverSchema,
25
+ displayName: zod_1.z.string(),
26
+ icon: zod_1.z.string().optional(),
27
+ description: zod_1.z.string().optional()
28
+ });
@@ -2,20 +2,28 @@ import { z } from 'zod';
2
2
  import { Serialized } from '../utils';
3
3
  export interface NotificationContext<T = any> {
4
4
  entityId: string;
5
- entityType: NotificationEntityType;
5
+ entityType: string;
6
6
  entityData: T;
7
7
  userId: string;
8
8
  variables: Record<string, any>;
9
9
  }
10
+ /**
11
+ * @deprecated Use string types with NotificationEntityRegistry instead
12
+ * These enums are kept for backward compatibility during migration
13
+ */
10
14
  export declare enum NotificationParentType {
11
15
  AGENDA_PANEL = "agenda_panel"
12
16
  }
17
+ /**
18
+ * @deprecated Use string types with NotificationEntityRegistry instead
19
+ * These enums are kept for backward compatibility during migration
20
+ */
13
21
  export declare enum NotificationEntityType {
14
22
  INBOX_PANEL = "inbox_panel",
15
- AGENDA_PANEL = "agenda_item",
23
+ AGENDA_PANEL = "agenda_panel",
16
24
  AGENDA_ITEM = "agenda_item"
17
25
  }
18
- export declare const notificationEntityTypeSchema: z.ZodNativeEnum<typeof NotificationEntityType>;
26
+ export declare const notificationEntityTypeSchema: z.ZodString;
19
27
  export declare enum NotificationStatus {
20
28
  SCHEDULED = "scheduled",
21
29
  SENT = "sent",
@@ -58,7 +66,7 @@ export declare const notificationContentSchema: z.ZodObject<{
58
66
  export declare const notificationTemplateSchema: z.ZodObject<{
59
67
  _id: z.ZodEffects<z.ZodString, import("./id-types").NotificationTemplateId, string>;
60
68
  userId: z.ZodEffects<z.ZodString, import("./id-types").UserId, string>;
61
- entityType: z.ZodNativeEnum<typeof NotificationEntityType>;
69
+ entityType: z.ZodString;
62
70
  entityId: z.ZodOptional<z.ZodString>;
63
71
  name: z.ZodString;
64
72
  description: z.ZodOptional<z.ZodString>;
@@ -108,7 +116,7 @@ export declare const notificationTemplateSchema: z.ZodObject<{
108
116
  body: string;
109
117
  variables?: Record<string, string> | undefined;
110
118
  };
111
- entityType: NotificationEntityType;
119
+ entityType: string;
112
120
  trigger: {
113
121
  type: NotificationTriggerType;
114
122
  conditions: Record<string, any>;
@@ -130,7 +138,7 @@ export declare const notificationTemplateSchema: z.ZodObject<{
130
138
  body: string;
131
139
  variables?: Record<string, string> | undefined;
132
140
  };
133
- entityType: NotificationEntityType;
141
+ entityType: string;
134
142
  trigger: {
135
143
  type: NotificationTriggerType;
136
144
  conditions: Record<string, any>;
@@ -145,7 +153,7 @@ export declare const notificationTemplateSchema: z.ZodObject<{
145
153
  export declare const createNotificationTemplateSchema: z.ZodObject<Omit<{
146
154
  _id: z.ZodEffects<z.ZodString, import("./id-types").NotificationTemplateId, string>;
147
155
  userId: z.ZodEffects<z.ZodString, import("./id-types").UserId, string>;
148
- entityType: z.ZodNativeEnum<typeof NotificationEntityType>;
156
+ entityType: z.ZodString;
149
157
  entityId: z.ZodOptional<z.ZodString>;
150
158
  name: z.ZodString;
151
159
  description: z.ZodOptional<z.ZodString>;
@@ -190,7 +198,7 @@ export declare const createNotificationTemplateSchema: z.ZodObject<Omit<{
190
198
  body: string;
191
199
  variables?: Record<string, string> | undefined;
192
200
  };
193
- entityType: NotificationEntityType;
201
+ entityType: string;
194
202
  trigger: {
195
203
  type: NotificationTriggerType;
196
204
  conditions: Record<string, any>;
@@ -209,7 +217,7 @@ export declare const createNotificationTemplateSchema: z.ZodObject<Omit<{
209
217
  body: string;
210
218
  variables?: Record<string, string> | undefined;
211
219
  };
212
- entityType: NotificationEntityType;
220
+ entityType: string;
213
221
  trigger: {
214
222
  type: NotificationTriggerType;
215
223
  conditions: Record<string, any>;
@@ -223,7 +231,7 @@ export declare const createNotificationTemplateSchema: z.ZodObject<Omit<{
223
231
  }>;
224
232
  export declare const entitySyncStateSchema: z.ZodObject<{
225
233
  userId: z.ZodEffects<z.ZodString, import("./id-types").UserId, string>;
226
- entityType: z.ZodNativeEnum<typeof NotificationEntityType>;
234
+ entityType: z.ZodString;
227
235
  entityId: z.ZodString;
228
236
  synced: z.ZodBoolean;
229
237
  updatedAt: z.ZodDate;
@@ -232,13 +240,13 @@ export declare const entitySyncStateSchema: z.ZodObject<{
232
240
  userId: string & {
233
241
  readonly __brand: "UserId";
234
242
  };
235
- entityType: NotificationEntityType;
243
+ entityType: string;
236
244
  entityId: string;
237
245
  synced: boolean;
238
246
  }, {
239
247
  updatedAt: Date;
240
248
  userId: string;
241
- entityType: NotificationEntityType;
249
+ entityType: string;
242
250
  entityId: string;
243
251
  synced: boolean;
244
252
  }>;
@@ -309,7 +317,7 @@ export declare const notificationInstanceSchema: z.ZodObject<{
309
317
  error?: string | undefined;
310
318
  }>;
311
319
  export declare const createNotificationTemplateRequestSchema: z.ZodObject<{
312
- entityType: z.ZodNativeEnum<typeof NotificationEntityType>;
320
+ entityType: z.ZodString;
313
321
  entityId: z.ZodOptional<z.ZodString>;
314
322
  name: z.ZodString;
315
323
  description: z.ZodOptional<z.ZodString>;
@@ -349,7 +357,7 @@ export declare const createNotificationTemplateRequestSchema: z.ZodObject<{
349
357
  body: string;
350
358
  variables?: Record<string, string> | undefined;
351
359
  };
352
- entityType: NotificationEntityType;
360
+ entityType: string;
353
361
  trigger: {
354
362
  type: NotificationTriggerType;
355
363
  conditions: Record<string, any>;
@@ -367,7 +375,7 @@ export declare const createNotificationTemplateRequestSchema: z.ZodObject<{
367
375
  body: string;
368
376
  variables?: Record<string, string> | undefined;
369
377
  };
370
- entityType: NotificationEntityType;
378
+ entityType: string;
371
379
  trigger: {
372
380
  type: NotificationTriggerType;
373
381
  conditions: Record<string, any>;
@@ -3,17 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getEntitySyncRequestSchema = exports.entitySyncRequestSchema = exports.getNotificationInstancesRequestSchema = exports.previewNotificationTemplateRequestSchema = exports.syncNotificationTemplateRequestSchema = exports.updateNotificationTemplateRequestSchema = exports.createNotificationTemplateRequestSchema = exports.notificationInstanceSchema = exports.entitySyncStateSchema = exports.createNotificationTemplateSchema = exports.notificationTemplateSchema = exports.notificationContentSchema = exports.notificationTriggerSchema = exports.notificationTriggerTypeSchema = exports.notificationStatusSchema = exports.NotificationTriggerType = exports.NotificationStatus = exports.notificationEntityTypeSchema = exports.NotificationEntityType = exports.NotificationParentType = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const id_types_1 = require("./id-types");
6
+ /**
7
+ * @deprecated Use string types with NotificationEntityRegistry instead
8
+ * These enums are kept for backward compatibility during migration
9
+ */
6
10
  var NotificationParentType;
7
11
  (function (NotificationParentType) {
8
12
  NotificationParentType["AGENDA_PANEL"] = "agenda_panel";
9
13
  })(NotificationParentType || (exports.NotificationParentType = NotificationParentType = {}));
14
+ /**
15
+ * @deprecated Use string types with NotificationEntityRegistry instead
16
+ * These enums are kept for backward compatibility during migration
17
+ */
10
18
  var NotificationEntityType;
11
19
  (function (NotificationEntityType) {
12
20
  NotificationEntityType["INBOX_PANEL"] = "inbox_panel";
13
- NotificationEntityType["AGENDA_PANEL"] = "agenda_item";
21
+ NotificationEntityType["AGENDA_PANEL"] = "agenda_panel";
14
22
  NotificationEntityType["AGENDA_ITEM"] = "agenda_item";
15
23
  })(NotificationEntityType || (exports.NotificationEntityType = NotificationEntityType = {}));
16
- exports.notificationEntityTypeSchema = zod_1.z.nativeEnum(NotificationEntityType);
24
+ // Updated to use string instead of enum
25
+ exports.notificationEntityTypeSchema = zod_1.z.string();
17
26
  var NotificationStatus;
18
27
  (function (NotificationStatus) {
19
28
  NotificationStatus["SCHEDULED"] = "scheduled";
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@timothyw/pat-common",
3
3
  "description": "",
4
4
  "author": "Timothy Washburn",
5
- "version": "1.0.121",
5
+ "version": "1.0.122",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "scripts": {
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './enums'
2
2
  export * from './types'
3
- export * from './utils'
3
+ export * from './utils'
4
+ export * from './notification-entity-registry'
@@ -0,0 +1,217 @@
1
+ import {
2
+ NotificationEntityConfig,
3
+ ParentResolver,
4
+ ParentResolutionResult,
5
+ StaticParentResolver,
6
+ DynamicParentResolver
7
+ } from './types/notification-entity-config';
8
+
9
+ /**
10
+ * Registry for managing notification entity configurations and parent resolution
11
+ */
12
+ export class NotificationEntityRegistry {
13
+ private static instance: NotificationEntityRegistry;
14
+ private entityConfigs: Map<string, NotificationEntityConfig> = new Map();
15
+
16
+ private constructor() {
17
+ // Initialize with default configurations
18
+ this.registerDefaultEntities();
19
+ }
20
+
21
+ /**
22
+ * Get the singleton instance
23
+ */
24
+ static getInstance(): NotificationEntityRegistry {
25
+ if (!NotificationEntityRegistry.instance) {
26
+ NotificationEntityRegistry.instance = new NotificationEntityRegistry();
27
+ }
28
+ return NotificationEntityRegistry.instance;
29
+ }
30
+
31
+ /**
32
+ * Register a new entity configuration
33
+ */
34
+ registerEntity(config: NotificationEntityConfig): void {
35
+ this.entityConfigs.set(config.entityType, config);
36
+ }
37
+
38
+ /**
39
+ * Get configuration for an entity type
40
+ */
41
+ getEntityConfig(entityType: string): NotificationEntityConfig | null {
42
+ return this.entityConfigs.get(entityType) || null;
43
+ }
44
+
45
+ /**
46
+ * Get all registered entity types
47
+ */
48
+ getEntityTypes(): string[] {
49
+ return Array.from(this.entityConfigs.keys());
50
+ }
51
+
52
+ /**
53
+ * Get all entity configurations
54
+ */
55
+ getAllConfigs(): NotificationEntityConfig[] {
56
+ return Array.from(this.entityConfigs.values());
57
+ }
58
+
59
+ /**
60
+ * Resolve the parent type for a specific entity instance
61
+ */
62
+ resolveParent(entityType: string, entityData: any): ParentResolutionResult | null {
63
+ const config = this.entityConfigs.get(entityType);
64
+ if (!config) {
65
+ return null;
66
+ }
67
+
68
+ const resolver = config.parentResolver;
69
+
70
+ if (resolver.type === 'static') {
71
+ return this.resolveStaticParent(resolver);
72
+ } else {
73
+ return this.resolveDynamicParent(resolver, entityData);
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Check if an entity type supports dynamic parent resolution
79
+ */
80
+ isDynamicParentType(entityType: string): boolean {
81
+ const config = this.entityConfigs.get(entityType);
82
+ return config?.parentResolver.type === 'dynamic' || false;
83
+ }
84
+
85
+ /**
86
+ * Get the parent property name for dynamic resolution
87
+ */
88
+ getParentProperty(entityType: string): string | null {
89
+ const config = this.entityConfigs.get(entityType);
90
+ if (config?.parentResolver.type === 'dynamic') {
91
+ return config.parentResolver.parentProperty;
92
+ }
93
+ return null;
94
+ }
95
+
96
+ /**
97
+ * Get display name for an entity type
98
+ */
99
+ getDisplayName(entityType: string): string {
100
+ const config = this.entityConfigs.get(entityType);
101
+ return config?.displayName || entityType;
102
+ }
103
+
104
+ /**
105
+ * Get icon for an entity type
106
+ */
107
+ getIcon(entityType: string): string | null {
108
+ const config = this.entityConfigs.get(entityType);
109
+ return config?.icon || null;
110
+ }
111
+
112
+ /**
113
+ * Check if entity type exists
114
+ */
115
+ hasEntityType(entityType: string): boolean {
116
+ return this.entityConfigs.has(entityType);
117
+ }
118
+
119
+ /**
120
+ * Remove an entity configuration
121
+ */
122
+ unregisterEntity(entityType: string): boolean {
123
+ return this.entityConfigs.delete(entityType);
124
+ }
125
+
126
+ /**
127
+ * Clear all configurations
128
+ */
129
+ clear(): void {
130
+ this.entityConfigs.clear();
131
+ }
132
+
133
+ /**
134
+ * Resolve static parent type
135
+ */
136
+ private resolveStaticParent(resolver: StaticParentResolver): ParentResolutionResult {
137
+ return {
138
+ parentType: resolver.parentType,
139
+ isDynamic: false
140
+ };
141
+ }
142
+
143
+ /**
144
+ * Resolve dynamic parent type based on entity data
145
+ */
146
+ private resolveDynamicParent(resolver: DynamicParentResolver, entityData: any): ParentResolutionResult {
147
+ const propertyValue = entityData?.[resolver.parentProperty];
148
+
149
+ if (propertyValue && typeof propertyValue === 'string' && propertyValue.trim()) {
150
+ // Use the property value to construct the parent type
151
+ const parentType = resolver.parentTypePrefix + propertyValue.trim();
152
+ return {
153
+ parentType,
154
+ isDynamic: true,
155
+ resolvedProperty: propertyValue.trim(),
156
+ usedFallback: false
157
+ };
158
+ }
159
+
160
+ // Fall back to default parent
161
+ return {
162
+ parentType: resolver.fallbackParent,
163
+ isDynamic: true,
164
+ usedFallback: true
165
+ };
166
+ }
167
+
168
+ /**
169
+ * Register default entity configurations
170
+ */
171
+ private registerDefaultEntities(): void {
172
+ // Agenda Panel (static parent of agenda items)
173
+ this.registerEntity({
174
+ entityType: 'agenda_panel',
175
+ parentResolver: {
176
+ type: 'static',
177
+ parentType: 'agenda_panel' // Self-referencing for panel level
178
+ },
179
+ displayName: 'Agenda Panel',
180
+ icon: 'calendar',
181
+ description: 'Default notification templates for all agenda items'
182
+ });
183
+
184
+ // Agenda Item (can have dynamic parent based on category)
185
+ this.registerEntity({
186
+ entityType: 'agenda_item',
187
+ parentResolver: {
188
+ type: 'dynamic',
189
+ parentProperty: 'category',
190
+ parentTypePrefix: 'agenda_category_',
191
+ fallbackParent: 'agenda_panel'
192
+ },
193
+ displayName: 'Agenda Item',
194
+ icon: 'calendar',
195
+ description: 'Individual agenda item notifications'
196
+ });
197
+
198
+ // Inbox Panel
199
+ this.registerEntity({
200
+ entityType: 'inbox_panel',
201
+ parentResolver: {
202
+ type: 'static',
203
+ parentType: 'inbox_panel' // Self-referencing for panel level
204
+ },
205
+ displayName: 'Inbox Panel',
206
+ icon: 'mail',
207
+ description: 'Inbox notification templates'
208
+ });
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Convenience function to get the singleton instance
214
+ */
215
+ export function getNotificationEntityRegistry(): NotificationEntityRegistry {
216
+ return NotificationEntityRegistry.getInstance();
217
+ }
@@ -6,7 +6,7 @@ export * from './id-types';
6
6
  export * from './people-types';
7
7
  export * from './lists-types';
8
8
  export * from './notifications-types';
9
+ export * from './notification-entity-config';
9
10
  export * from './auth-types';
10
11
  export * from './user-types';
11
- export * from './program-config-types';
12
- export * from './misc';
12
+ export * from './program-config-types';
@@ -0,0 +1,78 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Static parent resolver - entity always inherits from the same parent type
5
+ */
6
+ export interface StaticParentResolver {
7
+ type: 'static';
8
+ parentType: string;
9
+ }
10
+
11
+ /**
12
+ * Dynamic parent resolver - parent determined by entity properties
13
+ */
14
+ export interface DynamicParentResolver {
15
+ type: 'dynamic';
16
+ parentProperty: string; // Property name on entity (e.g., 'category')
17
+ parentTypePrefix: string; // Prefix for parent type (e.g., 'agenda_category_')
18
+ fallbackParent: string; // Default parent if property is missing/empty
19
+ }
20
+
21
+ export type ParentResolver = StaticParentResolver | DynamicParentResolver;
22
+
23
+ /**
24
+ * Configuration for a notification entity type
25
+ */
26
+ export interface NotificationEntityConfig {
27
+ entityType: string;
28
+ parentResolver: ParentResolver;
29
+ displayName: string;
30
+ icon?: string;
31
+ description?: string;
32
+ }
33
+
34
+ /**
35
+ * Result of parent resolution for a specific entity instance
36
+ */
37
+ export interface ParentResolutionResult {
38
+ parentType: string;
39
+ isDynamic: boolean;
40
+ resolvedProperty?: string;
41
+ usedFallback?: boolean;
42
+ }
43
+
44
+ /**
45
+ * Zod schemas for validation
46
+ */
47
+ export const staticParentResolverSchema = z.object({
48
+ type: z.literal('static'),
49
+ parentType: z.string()
50
+ });
51
+
52
+ export const dynamicParentResolverSchema = z.object({
53
+ type: z.literal('dynamic'),
54
+ parentProperty: z.string(),
55
+ parentTypePrefix: z.string(),
56
+ fallbackParent: z.string()
57
+ });
58
+
59
+ export const parentResolverSchema = z.union([
60
+ staticParentResolverSchema,
61
+ dynamicParentResolverSchema
62
+ ]);
63
+
64
+ export const notificationEntityConfigSchema = z.object({
65
+ entityType: z.string(),
66
+ parentResolver: parentResolverSchema,
67
+ displayName: z.string(),
68
+ icon: z.string().optional(),
69
+ description: z.string().optional()
70
+ });
71
+
72
+ /**
73
+ * Type exports
74
+ */
75
+ export type StaticParentResolverData = z.infer<typeof staticParentResolverSchema>;
76
+ export type DynamicParentResolverData = z.infer<typeof dynamicParentResolverSchema>;
77
+ export type ParentResolverData = z.infer<typeof parentResolverSchema>;
78
+ export type NotificationEntityConfigData = z.infer<typeof notificationEntityConfigSchema>;
@@ -4,23 +4,32 @@ import { Serialized } from '../utils';
4
4
 
5
5
  export interface NotificationContext<T = any> {
6
6
  entityId: string;
7
- entityType: NotificationEntityType;
7
+ entityType: string;
8
8
  entityData: T;
9
9
  userId: string;
10
10
  variables: Record<string, any>;
11
11
  }
12
12
 
13
+ /**
14
+ * @deprecated Use string types with NotificationEntityRegistry instead
15
+ * These enums are kept for backward compatibility during migration
16
+ */
13
17
  export enum NotificationParentType {
14
18
  AGENDA_PANEL = 'agenda_panel',
15
19
  }
16
20
 
21
+ /**
22
+ * @deprecated Use string types with NotificationEntityRegistry instead
23
+ * These enums are kept for backward compatibility during migration
24
+ */
17
25
  export enum NotificationEntityType {
18
26
  INBOX_PANEL = 'inbox_panel',
19
- AGENDA_PANEL = 'agenda_item',
27
+ AGENDA_PANEL = 'agenda_panel',
20
28
  AGENDA_ITEM = 'agenda_item',
21
29
  }
22
30
 
23
- export const notificationEntityTypeSchema = z.nativeEnum(NotificationEntityType);
31
+ // Updated to use string instead of enum
32
+ export const notificationEntityTypeSchema = z.string();
24
33
 
25
34
  export enum NotificationStatus {
26
35
  SCHEDULED = 'scheduled',