2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  core  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"bytes" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"encoding/json" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"errors" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"maps" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"slices" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"sort" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									validation  "github.com/go-ozzo/ozzo-validation/v4" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/pocketbase/dbx" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/pocketbase/pocketbase/core/validators" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/pocketbase/pocketbase/tools/filesystem" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/pocketbase/pocketbase/tools/hook" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/pocketbase/pocketbase/tools/inflector" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/pocketbase/pocketbase/tools/list" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/pocketbase/pocketbase/tools/store" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/pocketbase/pocketbase/tools/types" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/spf13/cast" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// used as a workaround by some fields for persisting local state between various events  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// (for now is kept private and cannot be changed or cloned outside of the core package)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  internalCustomFieldKeyPrefix  =  "@pbInternal"  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_  Model         =  ( * Record ) ( nil ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_  HookTagger    =  ( * Record ) ( nil ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_  DBExporter    =  ( * Record ) ( nil ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_  FilesManager  =  ( * Record ) ( nil ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  Record  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									collection        * Collection 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									originalData      map [ string ] any 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									customVisibility  * store . Store [ bool ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									data              * store . Store [ any ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									expand            * store . Store [ any ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BaseModel 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									exportCustomData       bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ignoreEmailVisibility  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ignoreUnchangedFields  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  systemHookIdRecord  =  "__pbRecordSystemHook__"  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( app  * BaseApp )  registerRecordHooks ( )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnModelValidate ( ) . Bind ( & hook . Handler [ * ModelEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( me  * ModelEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  re ,  ok  :=  newRecordEventFromModelEvent ( me ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  me . App . OnRecordValidate ( ) . Trigger ( re ,  func ( re  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													syncModelEventWithRecordEvent ( me ,  re ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnModelCreate ( ) . Bind ( & hook . Handler [ * ModelEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( me  * ModelEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  re ,  ok  :=  newRecordEventFromModelEvent ( me ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  me . App . OnRecordCreate ( ) . Trigger ( re ,  func ( re  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													syncModelEventWithRecordEvent ( me ,  re ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnModelCreateExecute ( ) . Bind ( & hook . Handler [ * ModelEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( me  * ModelEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  re ,  ok  :=  newRecordEventFromModelEvent ( me ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  me . App . OnRecordCreateExecute ( ) . Trigger ( re ,  func ( re  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													syncModelEventWithRecordEvent ( me ,  re ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnModelAfterCreateSuccess ( ) . Bind ( & hook . Handler [ * ModelEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( me  * ModelEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  re ,  ok  :=  newRecordEventFromModelEvent ( me ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  me . App . OnRecordAfterCreateSuccess ( ) . Trigger ( re ,  func ( re  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													syncModelEventWithRecordEvent ( me ,  re ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnModelAfterCreateError ( ) . Bind ( & hook . Handler [ * ModelErrorEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( me  * ModelErrorEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  re ,  ok  :=  newRecordErrorEventFromModelErrorEvent ( me ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  me . App . OnRecordAfterCreateError ( ) . Trigger ( re ,  func ( re  * RecordErrorEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													syncModelErrorEventWithRecordErrorEvent ( me ,  re ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnModelUpdate ( ) . Bind ( & hook . Handler [ * ModelEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( me  * ModelEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  re ,  ok  :=  newRecordEventFromModelEvent ( me ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  me . App . OnRecordUpdate ( ) . Trigger ( re ,  func ( re  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													syncModelEventWithRecordEvent ( me ,  re ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnModelUpdateExecute ( ) . Bind ( & hook . Handler [ * ModelEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( me  * ModelEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  re ,  ok  :=  newRecordEventFromModelEvent ( me ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  me . App . OnRecordUpdateExecute ( ) . Trigger ( re ,  func ( re  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													syncModelEventWithRecordEvent ( me ,  re ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnModelAfterUpdateSuccess ( ) . Bind ( & hook . Handler [ * ModelEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( me  * ModelEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  re ,  ok  :=  newRecordEventFromModelEvent ( me ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  me . App . OnRecordAfterUpdateSuccess ( ) . Trigger ( re ,  func ( re  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													syncModelEventWithRecordEvent ( me ,  re ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnModelAfterUpdateError ( ) . Bind ( & hook . Handler [ * ModelErrorEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( me  * ModelErrorEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  re ,  ok  :=  newRecordErrorEventFromModelErrorEvent ( me ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  me . App . OnRecordAfterUpdateError ( ) . Trigger ( re ,  func ( re  * RecordErrorEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													syncModelErrorEventWithRecordErrorEvent ( me ,  re ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnModelDelete ( ) . Bind ( & hook . Handler [ * ModelEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( me  * ModelEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  re ,  ok  :=  newRecordEventFromModelEvent ( me ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  me . App . OnRecordDelete ( ) . Trigger ( re ,  func ( re  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													syncModelEventWithRecordEvent ( me ,  re ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnModelDeleteExecute ( ) . Bind ( & hook . Handler [ * ModelEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( me  * ModelEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  re ,  ok  :=  newRecordEventFromModelEvent ( me ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  me . App . OnRecordDeleteExecute ( ) . Trigger ( re ,  func ( re  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													syncModelEventWithRecordEvent ( me ,  re ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnModelAfterDeleteSuccess ( ) . Bind ( & hook . Handler [ * ModelEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( me  * ModelEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  re ,  ok  :=  newRecordEventFromModelEvent ( me ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  me . App . OnRecordAfterDeleteSuccess ( ) . Trigger ( re ,  func ( re  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													syncModelEventWithRecordEvent ( me ,  re ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnModelAfterDeleteError ( ) . Bind ( & hook . Handler [ * ModelErrorEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( me  * ModelErrorEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  re ,  ok  :=  newRecordErrorEventFromModelErrorEvent ( me ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  me . App . OnRecordAfterDeleteError ( ) . Trigger ( re ,  func ( re  * RecordErrorEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													syncModelErrorEventWithRecordErrorEvent ( me ,  re ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  me . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// --------------------------------------------------------------- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnRecordValidate ( ) . Bind ( & hook . Handler [ * RecordEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( e  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  e . Record . callFieldInterceptors ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												InterceptorActionValidate , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												func ( )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  onRecordValidate ( e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnRecordCreate ( ) . Bind ( & hook . Handler [ * RecordEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( e  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  e . Record . callFieldInterceptors ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												InterceptorActionCreate , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Next , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnRecordCreateExecute ( ) . Bind ( & hook . Handler [ * RecordEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( e  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  e . Record . callFieldInterceptors ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												InterceptorActionCreateExecute , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												func ( )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  onRecordSaveExecute ( e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnRecordAfterCreateSuccess ( ) . Bind ( & hook . Handler [ * RecordEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( e  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  e . Record . callFieldInterceptors ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												InterceptorActionAfterCreate , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Next , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnRecordAfterCreateError ( ) . Bind ( & hook . Handler [ * RecordErrorEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( e  * RecordErrorEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  e . Record . callFieldInterceptors ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												InterceptorActionAfterCreateError , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Next , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnRecordUpdate ( ) . Bind ( & hook . Handler [ * RecordEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( e  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  e . Record . callFieldInterceptors ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												InterceptorActionUpdate , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Next , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnRecordUpdateExecute ( ) . Bind ( & hook . Handler [ * RecordEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( e  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  e . Record . callFieldInterceptors ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												InterceptorActionUpdateExecute , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												func ( )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  onRecordSaveExecute ( e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnRecordAfterUpdateSuccess ( ) . Bind ( & hook . Handler [ * RecordEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( e  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  e . Record . callFieldInterceptors ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												InterceptorActionAfterUpdate , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Next , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnRecordAfterUpdateError ( ) . Bind ( & hook . Handler [ * RecordErrorEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( e  * RecordErrorEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  e . Record . callFieldInterceptors ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												InterceptorActionAfterUpdateError , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Next , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnRecordDelete ( ) . Bind ( & hook . Handler [ * RecordEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( e  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  e . Record . callFieldInterceptors ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												InterceptorActionDelete , 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-09 11:51:03 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												func ( )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  e . Record . Collection ( ) . IsView ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														return  errors . New ( "view records cannot be deleted" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  e . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} , 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnRecordDeleteExecute ( ) . Bind ( & hook . Handler [ * RecordEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( e  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  e . Record . callFieldInterceptors ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												InterceptorActionDeleteExecute , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												func ( )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  onRecordDeleteExecute ( e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnRecordAfterDeleteSuccess ( ) . Bind ( & hook . Handler [ * RecordEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( e  * RecordEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  e . Record . callFieldInterceptors ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												InterceptorActionAfterDelete , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Next , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app . OnRecordAfterDeleteError ( ) . Bind ( & hook . Handler [ * RecordErrorEvent ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Id :  systemHookIdRecord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Func :  func ( e  * RecordErrorEvent )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  e . Record . callFieldInterceptors ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												InterceptorActionAfterDeleteError , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												e . Next , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Priority :  - 99 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// -------------------------------------------------------------------  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// newRecordFromNullStringMap initializes a single new Record model  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// with data loaded from the provided NullStringMap.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Note that this method is intended to load and Scan data from a database row result.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  newRecordFromNullStringMap ( collection  * Collection ,  data  dbx . NullStringMap )  ( * Record ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									record  :=  NewRecord ( collection ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  fieldName  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  field  :=  range  collection . Fields  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fieldName  =  field . GetName ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										nullString ,  ok  :=  data [ fieldName ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  value  any 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  err  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ok  &&  nullString . Valid  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											value ,  err  =  field . PrepareValue ( record ,  nullString . String ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											value ,  err  =  field . PrepareValue ( record ,  nil ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// we load only the original data to avoid unnecessary copying the same data into the record.data store 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// (it is also the reason why we don't invoke PostScan on the record itself) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										record . originalData [ fieldName ]  =  value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  fieldName  ==  FieldNameId  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											record . Id  =  cast . ToString ( value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									record . BaseModel . PostScan ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  record ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// newRecordsFromNullStringMaps initializes a new Record model for  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// each row in the provided NullStringMap slice.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Note that this method is intended to load and Scan data from a database rows result.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  newRecordsFromNullStringMaps ( collection  * Collection ,  rows  [ ] dbx . NullStringMap )  ( [ ] * Record ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									result  :=  make ( [ ] * Record ,  len ( rows ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  err  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i ,  row  :=  range  rows  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										result [ i ] ,  err  =  newRecordFromNullStringMap ( collection ,  row ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  result ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// -------------------------------------------------------------------  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// NewRecord initializes a new empty Record model.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  NewRecord ( collection  * Collection )  * Record  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									record  :=  & Record { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										collection :        collection , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data :              store . New [ any ] ( nil ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										customVisibility :  store . New [ bool ] ( nil ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										originalData :      make ( map [ string ] any ,  len ( collection . Fields ) ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// initialize default field values 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  fieldName  string 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  _ ,  field  :=  range  collection . Fields  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										fieldName  =  field . GetName ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  fieldName  ==  FieldNameId  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										value ,  _  :=  field . PrepareValue ( record ,  nil ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										record . originalData [ fieldName ]  =  value 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  record 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Collection returns the Collection model associated with the current Record model.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// NB! The returned collection is only for read purposes and it shouldn't be modified  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// because it could have unintended side-effects on other Record models from the same collection.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  Collection ( )  * Collection  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  m . collection 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// TableName returns the table name associated with the current Record model.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  TableName ( )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  m . collection . Name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// PostScan implements the [dbx.PostScanner] interface.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// It essentially refreshes/updates the current Record original state  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// as if the model was fetched from the databases for the first time.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Or in other words, it means that m.Original().FieldsData() will have  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the same values as m.Record().FieldsData().  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  PostScan ( )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  m . Id  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  errors . New ( "missing record primary key" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  m . BaseModel . PostScan ( ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m . originalData  =  m . FieldsData ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// HookTags returns the hook tags associated with the current record.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  HookTags ( )  [ ] string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  [ ] string { m . collection . Name ,  m . collection . Id } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// BaseFilesPath returns the storage dir path used by the record.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  BaseFilesPath ( )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									id  :=  cast . ToString ( m . LastSavedPK ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  id  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										id  =  m . Id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  m . collection . BaseFilesPath ( )  +  "/"  +  id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Original returns a shallow copy of the current record model populated  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// with its ORIGINAL db data state (aka. right after PostScan())  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// and everything else reset to the defaults.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// If record was created using NewRecord() the original will be always  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// a blank record (until PostScan() is invoked).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  Original ( )  * Record  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									newRecord  :=  NewRecord ( m . collection ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									newRecord . originalData  =  maps . Clone ( m . originalData ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  newRecord . originalData [ FieldNameId ]  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										newRecord . lastSavedPK  =  cast . ToString ( newRecord . originalData [ FieldNameId ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										newRecord . Id  =  newRecord . lastSavedPK 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  newRecord 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Fresh returns a shallow copy of the current record model populated  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// with its LATEST data state and everything else reset to the defaults  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// (aka. no expand, no unknown fields and with default visibility flags).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  Fresh ( )  * Record  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									newRecord  :=  m . Original ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-28 23:06:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// note: this will also load the Id field through m.GetRaw 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  fieldName  string 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-28 23:06:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  _ ,  field  :=  range  m . collection . Fields  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										fieldName  =  field . GetName ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										newRecord . SetRaw ( fieldName ,  m . GetRaw ( fieldName ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-28 23:06:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  newRecord 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Clone returns a shallow copy of the current record model with all of  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// its collection and unknown fields data, expand and flags copied.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// use [Record.Fresh()] instead if you want a copy with only the latest  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// collection fields data and everything else reset to the defaults.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  Clone ( )  * Record  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									newRecord  :=  m . Original ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									newRecord . Id  =  m . Id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									newRecord . exportCustomData  =  m . exportCustomData 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									newRecord . ignoreEmailVisibility  =  m . ignoreEmailVisibility 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									newRecord . ignoreUnchangedFields  =  m . ignoreUnchangedFields 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									newRecord . customVisibility . Reset ( m . customVisibility . GetAll ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-28 23:06:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									data  :=  m . data . GetAll ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  k ,  v  :=  range  data  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										newRecord . SetRaw ( k ,  v ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  m . expand  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										newRecord . SetExpand ( m . expand . GetAll ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  newRecord 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Expand returns a shallow copy of the current Record model expand data (if any).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  Expand ( )  map [ string ] any  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  m . expand  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// return a dummy initialized map to avoid assignment to nil map errors 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  map [ string ] any { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  m . expand . GetAll ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// SetExpand replaces the current Record's expand with the provided expand arg data (shallow copied).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  SetExpand ( expand  map [ string ] any )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  m . expand  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										m . expand  =  store . New [ any ] ( nil ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m . expand . Reset ( expand ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// MergeExpand merges recursively the provided expand data into  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the current model's expand (if any).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Note that if an expanded prop with the same key is a slice (old or new expand)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// then both old and new records will be merged into a new slice (aka. a :merge: [b,c] => [a,b,c]).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Otherwise the "old" expanded record will be replace with the "new" one (aka. a :merge: aNew => aNew).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  MergeExpand ( expand  map [ string ] any )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// nothing to merge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  len ( expand )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// no old expand 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  m . expand  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										m . expand  =  store . New ( expand ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									oldExpand  :=  m . expand . GetAll ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  key ,  new  :=  range  expand  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										old ,  ok  :=  oldExpand [ key ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											oldExpand [ key ]  =  new 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  wasOldSlice  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  oldSlice  [ ] * Record 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  v  :=  old . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  * Record : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											oldSlice  =  [ ] * Record { v } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  [ ] * Record : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											wasOldSlice  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											oldSlice  =  v 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// invalid old expand data -> assign directly the new 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// (no matter whether new is valid or not) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											oldExpand [ key ]  =  new 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  wasNewSlice  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  newSlice  [ ] * Record 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  v  :=  new . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  * Record : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											newSlice  =  [ ] * Record { v } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  [ ] * Record : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											wasNewSlice  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											newSlice  =  v 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// invalid new expand data -> skip 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										oldIndexed  :=  make ( map [ string ] * Record ,  len ( oldSlice ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  oldRecord  :=  range  oldSlice  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											oldIndexed [ oldRecord . Id ]  =  oldRecord 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  newRecord  :=  range  newSlice  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											oldRecord  :=  oldIndexed [ newRecord . Id ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  oldRecord  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// note: there is no need to update oldSlice since oldRecord is a reference 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												oldRecord . MergeExpand ( newRecord . Expand ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// missing new entry 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												oldSlice  =  append ( oldSlice ,  newRecord ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  wasOldSlice  ||  wasNewSlice  ||  len ( oldSlice )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											oldExpand [ key ]  =  oldSlice 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											oldExpand [ key ]  =  oldSlice [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m . expand . Reset ( oldExpand ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// FieldsData returns a shallow copy ONLY of the collection's fields record's data.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  FieldsData ( )  map [ string ] any  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									result  :=  make ( map [ string ] any ,  len ( m . collection . Fields ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  fieldName  string 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  _ ,  field  :=  range  m . collection . Fields  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										fieldName  =  field . GetName ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										result [ fieldName ]  =  m . Get ( fieldName ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  result 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// CustomData returns a shallow copy ONLY of the custom record fields data,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// aka. fields that are neither defined by the collection, nor special system ones.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Note that custom fields prefixed with "@pbInternal" are always skipped.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  CustomData ( )  map [ string ] any  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  m . data  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fields  :=  m . Collection ( ) . Fields 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									knownFields  :=  make ( map [ string ] struct { } ,  len ( fields ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  f  :=  range  fields  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										knownFields [ f . GetName ( ) ]  =  struct { } { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									result  :=  map [ string ] any { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rawData  :=  m . data . GetAll ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  k ,  v  :=  range  rawData  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  _ ,  ok  :=  knownFields [ k ] ;  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// skip internal custom fields 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  strings . HasPrefix ( k ,  internalCustomFieldKeyPrefix )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											result [ k ]  =  v 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  result 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// WithCustomData toggles the export/serialization of custom data fields  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// (false by default).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  WithCustomData ( state  bool )  * Record  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m . exportCustomData  =  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  m 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// IgnoreEmailVisibility toggles the flag to ignore the auth record email visibility check.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  IgnoreEmailVisibility ( state  bool )  * Record  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m . ignoreEmailVisibility  =  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  m 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// IgnoreUnchangedFields toggles the flag to ignore the unchanged fields  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// from the DB export for the UPDATE SQL query.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This could be used if you want to save only the record fields that you've changed  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// without overwrite other untouched fields in case of concurrent update.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  IgnoreUnchangedFields ( state  bool )  * Record  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m . ignoreUnchangedFields  =  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  m 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Set sets the provided key-value data pair into the current Record  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// model directly as it is WITHOUT NORMALIZATIONS.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// See also [Record.Set].  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  SetRaw ( key  string ,  value  any )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  key  ==  FieldNameId  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										m . Id  =  cast . ToString ( value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m . data . Set ( key ,  value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// SetIfFieldExists sets the provided key-value data pair into the current Record model  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ONLY if key is existing Collection field name/modifier.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This method does nothing if key is not a known Collection field name/modifier.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// On success returns the matched Field, otherwise - nil.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// To set any key-value, including custom/unknown fields, use the [Record.Set] method.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  SetIfFieldExists ( key  string ,  value  any )  Field  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  field  :=  range  m . Collection ( ) . Fields  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ff ,  ok  :=  field . ( SetterFinder ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											setter  :=  ff . FindSetter ( key ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  setter  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												setter ( m ,  value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  field 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// fallback to the default field PrepareValue method for direct match 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  key  ==  field . GetName ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											value ,  _  =  field . PrepareValue ( m ,  value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											m . SetRaw ( key ,  value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  field 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Set sets the provided key-value data pair into the current Record model.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// If the record collection has field with name matching the provided "key",  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the value will be further normalized according to the field setter(s).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  Set ( key  string ,  value  any )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  key  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  FieldNameExpand :  // for backward-compatibility with earlier versions 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										m . SetExpand ( cast . ToStringMap ( value ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										field  :=  m . SetIfFieldExists ( key ,  value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  field  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// custom key - set it without any transformations 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											m . SetRaw ( key ,  value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  GetRaw ( key  string )  any  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  key  ==  FieldNameId  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  m . Id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  v ,  ok  :=  m . data . GetOk ( key ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  v 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  m . originalData [ key ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Get returns a normalized single record model data value for "key".  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  Get ( key  string )  any  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  key  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  FieldNameExpand :  // for backward-compatibility with earlier versions 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  m . Expand ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  field  :=  range  m . Collection ( ) . Fields  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											gm ,  ok  :=  field . ( GetterFinder ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue  // no custom getters 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											getter  :=  gm . FindGetter ( key ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  getter  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  getter ( m ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  m . GetRaw ( key ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Load bulk loads the provided data into the current Record model.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  Load ( data  map [ string ] any )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  k ,  v  :=  range  data  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										m . Set ( k ,  v ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetBool returns the data value for "key" as a bool.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  GetBool ( key  string )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cast . ToBool ( m . Get ( key ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetString returns the data value for "key" as a string.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  GetString ( key  string )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cast . ToString ( m . Get ( key ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetInt returns the data value for "key" as an int.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  GetInt ( key  string )  int  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cast . ToInt ( m . Get ( key ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetFloat returns the data value for "key" as a float64.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  GetFloat ( key  string )  float64  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cast . ToFloat64 ( m . Get ( key ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetDateTime returns the data value for "key" as a DateTime instance.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  GetDateTime ( key  string )  types . DateTime  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									d ,  _  :=  types . ParseDateTime ( m . Get ( key ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  d 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetStringSlice returns the data value for "key" as a slice of non-zero unique strings.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  GetStringSlice ( key  string )  [ ] string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  list . ToUniqueStringSlice ( m . Get ( key ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetUploadedFiles returns the uploaded files for the provided "file" field key,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// (aka. the current [*filesytem.File] values) so that you can apply further  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// validations or modifications (including changing the file name or content before persisting).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Example:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	files := record.GetUploadedFiles("documents")  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	for _, f := range files {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	    f.Name = "doc_" + f.Name // add a prefix to each file name  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	app.Save(record) // the files are pointers so the applied changes will transparently reflect on the record value  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  GetUploadedFiles ( key  string )  [ ] * filesystem . File  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! strings . HasSuffix ( key ,  ":uploaded" )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										key  +=  ":uploaded" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									values ,  _  :=  m . Get ( key ) . ( [ ] * filesystem . File ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  values 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Retrieves the "key" json field value and unmarshals it into "result".  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Example  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	result := struct {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	    FirstName string `json:"first_name"`  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	}{}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	err := m.UnmarshalJSONField("my_field_name", &result)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  UnmarshalJSONField ( key  string ,  result  any )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  json . Unmarshal ( [ ] byte ( m . GetString ( key ) ) ,  & result ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ExpandedOne retrieves a single relation Record from the already  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// loaded expand data of the current model.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// If the requested expand relation is multiple, this method returns  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// only first available Record from the expanded relation.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Returns nil if there is no such expand relation loaded.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  ExpandedOne ( relField  string )  * Record  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  m . expand  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rel  :=  m . expand . Get ( relField ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  v  :=  rel . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  * Record : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  v 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] * Record : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( v )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  v [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ExpandedAll retrieves a slice of relation Records from the already  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// loaded expand data of the current model.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// If the requested expand relation is single, this method normalizes  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the return result and will wrap the single model as a slice.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Returns nil slice if there is no such expand relation loaded.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  ExpandedAll ( relField  string )  [ ] * Record  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  m . expand  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rel  :=  m . expand . Get ( relField ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  v  :=  rel . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  * Record : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  [ ] * Record { v } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] * Record : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  v 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// FindFileFieldByFile returns the first file type field for which  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// any of the record's data contains the provided filename.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  FindFileFieldByFile ( filename  string )  * FileField  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  field  :=  range  m . Collection ( ) . Fields  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  field . Type ( )  !=  FieldTypeFile  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										f ,  ok  :=  field . ( * FileField ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										filenames  :=  m . GetStringSlice ( f . GetName ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  slices . Contains ( filenames ,  filename )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  f 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// DBExport implements the [DBExporter] interface and returns a key-value  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// map with the data to be persisted when saving the Record in the database.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  DBExport ( app  App )  ( map [ string ] any ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									result ,  err  :=  m . dbExport ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// remove exported fields that haven't changed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// (with exception of the id column) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! m . IsNew ( )  &&  m . ignoreUnchangedFields  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										oldResult ,  err  :=  m . Original ( ) . dbExport ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  oldK ,  oldV  :=  range  oldResult  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  oldK  ==  idColumn  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											newV ,  ok  :=  result [ oldK ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ok  &&  areValuesEqual ( newV ,  oldV )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												delete ( result ,  oldK ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  result ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  dbExport ( )  ( map [ string ] any ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fields  :=  m . Collection ( ) . Fields 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									result  :=  make ( map [ string ] any ,  len ( fields ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  fieldName  string 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  _ ,  field  :=  range  fields  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										fieldName  =  field . GetName ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  f ,  ok  :=  field . ( DriverValuer ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											v ,  err  :=  f . DriverValue ( m ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											result [ fieldName ]  =  v 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											result [ fieldName ]  =  m . GetRaw ( fieldName ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  result ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  areValuesEqual ( a  any ,  b  any )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  av  :=  a . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  string : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( string ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  bool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( bool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  float32 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( float32 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  float64 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( float64 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  uint : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( uint ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  uint8 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( uint8 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  uint16 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( uint16 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  uint32 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( uint32 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  uint64 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( uint64 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  int : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  int8 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( int8 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  int16 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( int16 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  int32 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( int32 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  int64 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( int64 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bv  ==  av 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] byte : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( [ ] byte ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bytes . Equal ( av ,  bv ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] string : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( [ ] string ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  slices . Equal ( av ,  bv ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] int : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( [ ] int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  slices . Equal ( av ,  bv ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] int32 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( [ ] int32 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  slices . Equal ( av ,  bv ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] int64 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( [ ] int64 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  slices . Equal ( av ,  bv ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] float32 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( [ ] float32 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  slices . Equal ( av ,  bv ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] float64 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( [ ] float64 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  slices . Equal ( av ,  bv ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  types . JSONArray [ string ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( types . JSONArray [ string ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  slices . Equal ( av ,  bv ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  types . JSONRaw : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bv ,  ok  :=  b . ( types . JSONRaw ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ok  &&  bytes . Equal ( av ,  bv ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aRaw ,  err  :=  json . Marshal ( a ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bRaw ,  err  :=  json . Marshal ( b ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  bytes . Equal ( aRaw ,  bRaw ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Hide hides the specified fields from the public safe serialization of the record.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( record  * Record )  Hide ( fieldNames  ... string )  * Record  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  name  :=  range  fieldNames  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										record . customVisibility . Set ( name ,  false ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  record 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Unhide forces to unhide the specified fields from the public safe serialization  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// of the record (even when the collection field itself is marked as hidden).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( record  * Record )  Unhide ( fieldNames  ... string )  * Record  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  name  :=  range  fieldNames  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										record . customVisibility . Set ( name ,  true ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  record 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// PublicExport exports only the record fields that are safe to be public.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// To export unknown data fields you need to set record.WithCustomData(true).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// For auth records, to force the export of the email field you need to set  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// record.IgnoreEmailVisibility(true).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( record  * Record )  PublicExport ( )  map [ string ] any  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									export  :=  make ( map [ string ] any ,  len ( record . collection . Fields ) + 3 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  isVisible ,  hasCustomVisibility  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									customVisibility  :=  record . customVisibility . GetAll ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// export schema fields 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  fieldName  string 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  _ ,  f  :=  range  record . collection . Fields  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										fieldName  =  f . GetName ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										isVisible ,  hasCustomVisibility  =  customVisibility [ fieldName ] 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  ! hasCustomVisibility  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											isVisible  =  ! f . GetHidden ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! isVisible  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 11:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										export [ fieldName ]  =  record . Get ( fieldName ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-29 19:23:19 +03:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// export custom fields 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  record . exportCustomData  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  k ,  v  :=  range  record . CustomData ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											isVisible ,  hasCustomVisibility  =  customVisibility [ k ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ! hasCustomVisibility  ||  isVisible  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												export [ k ]  =  v 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  record . Collection ( ) . IsAuth ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// always hide the password and tokenKey fields 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										delete ( export ,  FieldNamePassword ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										delete ( export ,  FieldNameTokenKey ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! record . ignoreEmailVisibility  &&  ! record . GetBool ( FieldNameEmailVisibility )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											delete ( export ,  FieldNameEmail ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// add helper collection reference fields 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									isVisible ,  hasCustomVisibility  =  customVisibility [ FieldNameCollectionId ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! hasCustomVisibility  ||  isVisible  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										export [ FieldNameCollectionId ]  =  record . collection . Id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									isVisible ,  hasCustomVisibility  =  customVisibility [ FieldNameCollectionName ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! hasCustomVisibility  ||  isVisible  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										export [ FieldNameCollectionName ]  =  record . collection . Name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// add expand (if non-nil) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									isVisible ,  hasCustomVisibility  =  customVisibility [ FieldNameExpand ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! hasCustomVisibility  ||  isVisible )  &&  record . expand  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										export [ FieldNameExpand ]  =  record . expand . GetAll ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  export 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// MarshalJSON implements the [json.Marshaler] interface.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Only the data exported by `PublicExport()` will be serialized.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  Record )  MarshalJSON ( )  ( [ ] byte ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  json . Marshal ( m . PublicExport ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// UnmarshalJSON implements the [json.Unmarshaler] interface.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  UnmarshalJSON ( data  [ ] byte )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									result  :=  map [ string ] any { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  json . Unmarshal ( data ,  & result ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m . Load ( result ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ReplaceModifiers returns a new map with applied modifier  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// values based on the current record and the specified data.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The resolved modifier keys will be removed.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Multiple modifiers will be applied one after another,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// while reusing the previous base key value result (ex. 1; -5; +2 => -2).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Note that because Go doesn't guaranteed the iteration order of maps,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// we would explicitly apply shorter keys first for a more consistent and reproducible behavior.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Example usage:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	 newData := record.ReplaceModifiers(data)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		// record: {"field": 10}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		// data:   {"field+": 5}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		// result: {"field": 15}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  ReplaceModifiers ( data  map [ string ] any )  map [ string ] any  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  len ( data )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dataCopy  :=  maps . Clone ( data ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									recordCopy  :=  m . Fresh ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// key orders is not guaranteed so 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sortedDataKeys  :=  make ( [ ] string ,  0 ,  len ( data ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  k  :=  range  data  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sortedDataKeys  =  append ( sortedDataKeys ,  k ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sort . SliceStable ( sortedDataKeys ,  func ( i  int ,  j  int )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  len ( sortedDataKeys [ i ] )  <  len ( sortedDataKeys [ j ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  k  :=  range  sortedDataKeys  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										field  :=  recordCopy . SetIfFieldExists ( k ,  data [ k ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  field  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// delete the original key in case it is with a modifer (ex. "items+") 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											delete ( dataCopy ,  k ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// store the transformed value under the field name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dataCopy [ field . GetName ( ) ]  =  recordCopy . Get ( field . GetName ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  dataCopy 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// -------------------------------------------------------------------  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Record )  callFieldInterceptors (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  context . Context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app  App , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									actionName  string , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									actionFunc  func ( )  error , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// the firing order of the fields doesn't matter 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  field  :=  range  m . Collection ( ) . Fields  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  f ,  ok  :=  field . ( RecordInterceptor ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											oldfn  :=  actionFunc 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											actionFunc  =  func ( )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  f . Intercept ( ctx ,  app ,  m ,  actionName ,  oldfn ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  actionFunc ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  onRecordValidate ( e  * RecordEvent )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									errs  :=  validation . Errors { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  f  :=  range  e . Record . Collection ( ) . Fields  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  f . ValidateValue ( e . Context ,  e . App ,  e . Record ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											errs [ f . GetName ( ) ]  =  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  len ( errs )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  errs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  e . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  onRecordSaveExecute ( e  * RecordEvent )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  e . Record . Collection ( ) . IsAuth ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// ensure that the token key is different on password change 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										old  :=  e . Record . Original ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! e . Record . IsNew ( )  && 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											old . TokenKey ( )  ==  e . Record . TokenKey ( )  && 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											old . Get ( FieldNamePassword )  !=  e . Record . Get ( FieldNamePassword )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											e . Record . RefreshTokenKey ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// cross-check that the auth record id is unique across all auth collections. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										authCollections ,  err  :=  e . App . FindAllCollections ( CollectionTypeAuth ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  fmt . Errorf ( "unable to fetch the auth collections for cross-id unique check: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  collection  :=  range  authCollections  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  e . Record . Collection ( ) . Id  ==  collection . Id  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue  // skip current collection (sqlite will do the check for us) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											record ,  _  :=  e . App . FindRecordById ( collection ,  e . Record . Id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  record  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  validation . Errors { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													FieldNameId :  validation . NewError ( "validation_invalid_auth_id" ,  "Invalid or duplicated auth record id." ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  :=  e . Next ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  validators . NormalizeUniqueIndexError ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e . Record . Collection ( ) . Name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e . Record . Collection ( ) . Fields . FieldNames ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  onRecordDeleteExecute ( e  * RecordEvent )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// fetch rel references (if any) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// note: the select is outside of the transaction to minimize 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// SQLITE_BUSY errors when mixing read&write in a single transaction 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									refs ,  err  :=  e . App . FindCollectionReferences ( e . Record . Collection ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									originalApp  :=  e . App 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									txErr  :=  e . App . RunInTransaction ( func ( txApp  App )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e . App  =  txApp 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// delete the record before the relation references to ensure that there 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// will be no "A<->B" relations to prevent deadlock when calling DeleteRecord recursively 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  e . Next ( ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  cascadeRecordDelete ( txApp ,  e . Record ,  refs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									e . App  =  originalApp 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  txErr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// cascadeRecordDelete triggers cascade deletion for the provided references.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// NB! This method is expected to be called from inside of a transaction.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  cascadeRecordDelete ( app  App ,  mainRecord  * Record ,  refs  map [ * Collection ] [ ] Field )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Sort the refs keys to ensure that the cascade events firing order is always the same. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// This is not necessary for the operation to function correctly but it helps having deterministic output during testing. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sortedRefKeys  :=  make ( [ ] * Collection ,  0 ,  len ( refs ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  k  :=  range  refs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sortedRefKeys  =  append ( sortedRefKeys ,  k ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sort . Slice ( sortedRefKeys ,  func ( i ,  j  int )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  sortedRefKeys [ i ] . Name  <  sortedRefKeys [ j ] . Name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  refCollection  :=  range  sortedRefKeys  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fields ,  ok  :=  refs [ refCollection ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  refCollection . IsView ( )  ||  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue  // skip missing or view collections 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  field  :=  range  fields  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											recordTableName  :=  inflector . Columnify ( refCollection . Name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											prefixedFieldName  :=  recordTableName  +  "."  +  inflector . Columnify ( field . GetName ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											query  :=  app . RecordQuery ( refCollection ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  opt ,  ok  :=  field . ( MultiValuer ) ;  ! ok  ||  ! opt . IsMultiple ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												query . AndWhere ( dbx . HashExp { prefixedFieldName :  mainRecord . Id } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												query . AndWhere ( dbx . Exists ( dbx . NewExp ( fmt . Sprintf ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													` SELECT 1 FROM json_each(CASE WHEN json_valid([[%s]]) THEN [[%s]] ELSE json_array([[%s]]) END)  {{ __je__ }}  WHERE [[__je__.value]]= { :jevalue} ` , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													prefixedFieldName ,  prefixedFieldName ,  prefixedFieldName , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												) ,  dbx . Params { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													"jevalue" :  mainRecord . Id , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  refCollection . Id  ==  mainRecord . Collection ( ) . Id  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												query . AndWhere ( dbx . Not ( dbx . HashExp { recordTableName  +  ".id" :  mainRecord . Id } ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// trigger cascade for each batchSize rel items until there is none 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											batchSize  :=  4000 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											rows  :=  make ( [ ] * Record ,  0 ,  batchSize ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err  :=  query . Limit ( int64 ( batchSize ) ) . All ( & rows ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												total  :=  len ( rows ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  total  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												err  :=  deleteRefRecords ( app ,  mainRecord ,  rows ,  field ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  total  <  batchSize  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break  // no more items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												rows  =  rows [ : 0 ]  // keep allocated memory 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// deleteRefRecords checks if related records has to be deleted (if `CascadeDelete` is set)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// OR  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// just unset the record id from any relation field values (if they are not required).  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// NB! This method is expected to be called from inside of a transaction.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  deleteRefRecords ( app  App ,  mainRecord  * Record ,  refRecords  [ ] * Record ,  field  Field )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									relField ,  _  :=  field . ( * RelationField ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  relField  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  errors . New ( "only RelationField is supported at the moment, got "  +  field . Type ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  refRecord  :=  range  refRecords  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ids  :=  refRecord . GetStringSlice ( relField . Name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// unset the record id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  i  :=  len ( ids )  -  1 ;  i  >=  0 ;  i --  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ids [ i ]  ==  mainRecord . Id  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ids  =  append ( ids [ : i ] ,  ids [ i + 1 : ] ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// cascade delete the reference 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// (only if there are no other active references in case of multiple select) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  relField . CascadeDelete  &&  len ( ids )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  :=  app . Delete ( refRecord ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// no further actions are needed (the reference is deleted) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  relField . Required  &&  len ( ids )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  fmt . Errorf ( "the record cannot be deleted because it is part of a required reference in record %s (%s collection)" ,  refRecord . Id ,  refRecord . Collection ( ) . Name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// save the reference changes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// (without validation because it is possible that another relation field to have a reference to a previous deleted record) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										refRecord . Set ( relField . Name ,  ids ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  app . SaveNoValidate ( refRecord ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}