interaqt 0.6.2 → 0.6.4

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.
@@ -2799,6 +2799,137 @@ new Controller({
2799
2799
 
2800
2800
  ⚠️ **IMPORTANT**: Controller does NOT accept a computations parameter. All computations should be defined within the `computation` field of Entity/Relation/Property definitions. The 6th parameter `dict` is for global dictionary definitions (Dictionary.create), not for computation definitions.
2801
2801
 
2802
+ ### RecordMutationSideEffect
2803
+
2804
+ RecordMutationSideEffect allows you to execute custom logic when records are created, updated, or deleted within interaction contexts. It's useful for triggering external operations, logging, or custom business logic in response to data changes.
2805
+
2806
+ **Syntax**
2807
+ ```typescript
2808
+ RecordMutationSideEffect.create(config: RecordMutationSideEffectConfig): RecordMutationSideEffectInstance
2809
+ ```
2810
+
2811
+ **Parameters**
2812
+ - `config.name` (string, required): Unique name for the side effect
2813
+ - `config.record` (object, required): Target record configuration
2814
+ - `record.name` (string, required): Entity or relation name to monitor
2815
+ - `config.content` (function, required): Async function executed when mutation occurs
2816
+ ```typescript
2817
+ async (event: RecordMutationEvent) => Promise<any>
2818
+ ```
2819
+
2820
+ **RecordMutationEvent Structure**
2821
+ ```typescript
2822
+ type RecordMutationEvent = {
2823
+ recordName: string // Entity/relation name
2824
+ type: 'create' | 'update' | 'delete' // Mutation type
2825
+ record?: { id: string, ... } // New/current record (for create/update)
2826
+ oldRecord?: { id: string, ... } // Previous record (for update/delete)
2827
+ keys?: string[] // Changed fields (for update)
2828
+ }
2829
+ ```
2830
+
2831
+ **Important Notes**
2832
+ - RecordMutationSideEffect **only** triggers within interaction execution context
2833
+ - Direct storage operations (e.g., `controller.system.storage.create()`) do **NOT** trigger side effects
2834
+ - All side effects registered for an entity are called on any mutation of that entity
2835
+ - Side effects run after the storage operation completes
2836
+ - Side effect errors are captured but don't fail the interaction
2837
+
2838
+ **Examples**
2839
+
2840
+ ```typescript
2841
+ // Log user creation events
2842
+ const userCreatedLogger = RecordMutationSideEffect.create({
2843
+ name: 'userCreatedLogger',
2844
+ record: { name: 'User' },
2845
+ content: async (event) => {
2846
+ if (event.type === 'create') {
2847
+ console.log('New user created:', event.record?.id);
2848
+ // Send welcome email, update analytics, etc.
2849
+ return { logged: true, userId: event.record?.id };
2850
+ }
2851
+ return null;
2852
+ }
2853
+ });
2854
+
2855
+ // Audit trail for data changes
2856
+ const auditLogger = RecordMutationSideEffect.create({
2857
+ name: 'auditLogger',
2858
+ record: { name: 'Order' },
2859
+ content: async (event) => {
2860
+ const audit = {
2861
+ action: event.type,
2862
+ entityId: event.record?.id || event.oldRecord?.id,
2863
+ timestamp: new Date().toISOString(),
2864
+ changes: event.type === 'update' ? {
2865
+ before: event.oldRecord,
2866
+ after: event.record,
2867
+ fields: event.keys
2868
+ } : null
2869
+ };
2870
+
2871
+ // Store audit log (pseudo-code)
2872
+ await auditService.log(audit);
2873
+ return { audited: true };
2874
+ }
2875
+ });
2876
+
2877
+ // Cache invalidation on updates
2878
+ const cacheInvalidator = RecordMutationSideEffect.create({
2879
+ name: 'cacheInvalidator',
2880
+ record: { name: 'Product' },
2881
+ content: async (event) => {
2882
+ if (event.type === 'update' || event.type === 'delete') {
2883
+ const productId = event.record?.id || event.oldRecord?.id;
2884
+ await cacheService.invalidate(`product:${productId}`);
2885
+ return { invalidated: true, productId };
2886
+ }
2887
+ return null;
2888
+ }
2889
+ });
2890
+
2891
+ // Using in Controller
2892
+ const controller = new Controller({
2893
+ system: system,
2894
+ entities: [User, Order, Product],
2895
+ relations: [],
2896
+ interactions: [CreateUserInteraction, UpdateOrderInteraction],
2897
+ recordMutationSideEffects: [
2898
+ userCreatedLogger,
2899
+ auditLogger,
2900
+ cacheInvalidator
2901
+ ]
2902
+ });
2903
+
2904
+ // When interaction is called, side effects are triggered
2905
+ const result = await controller.callInteraction('createUser', {
2906
+ user: { id: 'admin' },
2907
+ payload: { name: 'John', email: 'john@example.com' }
2908
+ });
2909
+
2910
+ // Access side effect results
2911
+ if (result.sideEffects?.userCreatedLogger?.error) {
2912
+ console.warn('Logger failed:', result.sideEffects.userCreatedLogger.error);
2913
+ } else {
2914
+ console.log('Logger result:', result.sideEffects.userCreatedLogger.result);
2915
+ }
2916
+ ```
2917
+
2918
+ **Common Use Cases**
2919
+ 1. **Audit Logging**: Track all changes to sensitive data
2920
+ 2. **External System Sync**: Update external systems when data changes
2921
+ 3. **Cache Management**: Invalidate caches on data mutations
2922
+ 4. **Notifications**: Send notifications when specific events occur
2923
+ 5. **Analytics**: Track user actions and data changes
2924
+ 6. **Cleanup Tasks**: Perform cleanup when records are deleted
2925
+
2926
+ **Best Practices**
2927
+ 1. Filter by event type within the content function if needed
2928
+ 2. Handle errors gracefully - side effect failures shouldn't break the main operation
2929
+ 3. Keep side effects lightweight to avoid impacting performance
2930
+ 4. Use descriptive names for debugging
2931
+ 5. Return meaningful results for monitoring
2932
+
2802
2933
  **Main Methods**
2803
2934
 
2804
2935
  #### setup(install?: boolean)