identity-admin 1.28.28 → 1.28.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/README.md +148 -148
  2. package/lib/Dashboard.d.ts +14 -14
  3. package/lib/Dashboard.js +95 -95
  4. package/lib/container/helpers/HelperInversify.d.ts +6 -6
  5. package/lib/container/helpers/HelperInversify.js +10 -10
  6. package/lib/container/helpers/HelperTypes.d.ts +5 -5
  7. package/lib/container/helpers/HelperTypes.js +7 -7
  8. package/lib/container/index.d.ts +1 -1
  9. package/lib/container/index.js +14 -14
  10. package/lib/container/repositories/RepositoryInversify.d.ts +4 -4
  11. package/lib/container/repositories/RepositoryInversify.js +13 -13
  12. package/lib/container/repositories/RepositoryTypes.d.ts +4 -4
  13. package/lib/container/repositories/RepositoryTypes.js +6 -6
  14. package/lib/container/types.d.ts +8 -8
  15. package/lib/container/types.js +9 -9
  16. package/lib/controllers/ActionController.d.ts +9 -9
  17. package/lib/controllers/ActionController.js +141 -141
  18. package/lib/controllers/AdminNotificationController.d.ts +8 -8
  19. package/lib/controllers/AdminNotificationController.js +69 -69
  20. package/lib/controllers/DashboardController.d.ts +45 -45
  21. package/lib/controllers/DashboardController.js +827 -827
  22. package/lib/controllers/PermissionController.d.ts +6 -6
  23. package/lib/controllers/PermissionController.js +52 -52
  24. package/lib/controllers/ResourceController.d.ts +15 -15
  25. package/lib/controllers/ResourceController.js +128 -128
  26. package/lib/helpers/ActionsGenerator.d.ts +11 -11
  27. package/lib/helpers/ActionsGenerator.js +168 -168
  28. package/lib/helpers/AdminNotifications/AdminNotificationCreation.d.ts +54 -54
  29. package/lib/helpers/AdminNotifications/AdminNotificationCreation.js +66 -66
  30. package/lib/helpers/AdminNotifications/AdminNotificationFetcher.d.ts +63 -63
  31. package/lib/helpers/AdminNotifications/AdminNotificationFetcher.js +45 -45
  32. package/lib/helpers/FilterQueryHelper.d.ts +9 -9
  33. package/lib/helpers/FilterQueryHelper.js +83 -83
  34. package/lib/helpers/FiltersHelper.d.ts +9 -9
  35. package/lib/helpers/FiltersHelper.js +126 -126
  36. package/lib/helpers/JsonRichText/DraftRawToUniversalConverter.d.ts +3 -3
  37. package/lib/helpers/JsonRichText/DraftRawToUniversalConverter.js +144 -144
  38. package/lib/helpers/JsonRichText/IDraftRawType.d.ts +18 -18
  39. package/lib/helpers/JsonRichText/IDraftRawType.js +2 -2
  40. package/lib/helpers/JsonRichText/IUniversalJsonType.d.ts +24 -24
  41. package/lib/helpers/JsonRichText/IUniversalJsonType.js +10 -10
  42. package/lib/helpers/LocalesHelper.d.ts +4 -4
  43. package/lib/helpers/LocalesHelper.js +73 -73
  44. package/lib/helpers/LocalizedStringHelper.d.ts +11 -11
  45. package/lib/helpers/LocalizedStringHelper.js +76 -76
  46. package/lib/helpers/Permissions/PermissionFetcher.d.ts +8 -8
  47. package/lib/helpers/Permissions/PermissionFetcher.js +95 -95
  48. package/lib/helpers/Permissions/PermissionLabel.d.ts +2 -2
  49. package/lib/helpers/Permissions/PermissionLabel.js +42 -42
  50. package/lib/helpers/Permissions/PermissionMapper.d.ts +13 -13
  51. package/lib/helpers/Permissions/PermissionMapper.js +35 -35
  52. package/lib/helpers/Permissions/PermissionResource.d.ts +6 -6
  53. package/lib/helpers/Permissions/PermissionResource.js +62 -62
  54. package/lib/helpers/Permissions/PermissionSavingService.d.ts +13 -13
  55. package/lib/helpers/Permissions/PermissionSavingService.js +32 -32
  56. package/lib/helpers/Permissions/SavePermissionGroup.d.ts +6 -6
  57. package/lib/helpers/Permissions/SavePermissionGroup.js +32 -32
  58. package/lib/helpers/Permissions/UpdatePermissionGroup.d.ts +6 -6
  59. package/lib/helpers/Permissions/UpdatePermissionGroup.js +50 -50
  60. package/lib/helpers/Permissions/types.d.ts +17 -17
  61. package/lib/helpers/Permissions/types.js +2 -2
  62. package/lib/helpers/PopulationHelper.d.ts +12 -12
  63. package/lib/helpers/PopulationHelper.js +50 -50
  64. package/lib/helpers/RecordsCounter.d.ts +10 -10
  65. package/lib/helpers/RecordsCounter.js +33 -33
  66. package/lib/helpers/ReportsGenerator.d.ts +26 -26
  67. package/lib/helpers/ReportsGenerator.js +163 -162
  68. package/lib/helpers/ResourceGenerator.d.ts +9 -9
  69. package/lib/helpers/ResourceGenerator.js +172 -172
  70. package/lib/helpers/ResourceHelper.d.ts +28 -28
  71. package/lib/helpers/ResourceHelper.js +397 -397
  72. package/lib/helpers/RportsGenerator.d.ts +10 -10
  73. package/lib/helpers/RportsGenerator.js +21 -21
  74. package/lib/helpers/SchemaGenerator.d.ts +7 -7
  75. package/lib/helpers/SchemaGenerator.js +137 -137
  76. package/lib/helpers/SchemaHelper.d.ts +5 -5
  77. package/lib/helpers/SchemaHelper.js +21 -21
  78. package/lib/helpers/UserActionsLog/UserActionsLogHelper.d.ts +2 -2
  79. package/lib/helpers/UserActionsLog/UserActionsLogHelper.js +49 -49
  80. package/lib/locales/en.json +54 -54
  81. package/lib/middlewares/cache/decorator.d.ts +3 -3
  82. package/lib/middlewares/cache/decorator.js +60 -60
  83. package/lib/middlewares/cache/deletionMethods.d.ts +3 -3
  84. package/lib/middlewares/cache/deletionMethods.js +23 -23
  85. package/lib/middlewares/isAuth.d.ts +13 -13
  86. package/lib/middlewares/isAuth.js +43 -43
  87. package/lib/models/ModelNames.d.ts +10 -10
  88. package/lib/models/ModelNames.js +13 -13
  89. package/lib/models/adminNotification/AdminNotification.d.ts +5 -5
  90. package/lib/models/adminNotification/AdminNotification.js +70 -70
  91. package/lib/models/adminNotification/IAdminNotification.d.ts +35 -35
  92. package/lib/models/adminNotification/IAdminNotification.js +15 -15
  93. package/lib/models/adminpermission/AdminPermission.d.ts +6 -6
  94. package/lib/models/adminpermission/AdminPermission.js +27 -27
  95. package/lib/models/adminpermission/IAdminPermission.d.ts +13 -13
  96. package/lib/models/adminpermission/IAdminPermission.js +2 -2
  97. package/lib/models/customPage/CustomPage.d.ts +2 -2
  98. package/lib/models/customPage/CustomPage.js +38 -38
  99. package/lib/models/customPage/ICustomPage.d.ts +17 -17
  100. package/lib/models/customPage/ICustomPage.js +2 -2
  101. package/lib/models/file/File.d.ts +2 -2
  102. package/lib/models/file/File.js +23 -23
  103. package/lib/models/file/IFile.d.ts +15 -15
  104. package/lib/models/file/IFile.js +2 -2
  105. package/lib/models/language/ILanguage.d.ts +8 -8
  106. package/lib/models/language/ILanguage.js +8 -8
  107. package/lib/models/language/LanguageSchema.d.ts +9 -9
  108. package/lib/models/language/LanguageSchema.js +17 -17
  109. package/lib/models/location/ILocation.d.ts +16 -16
  110. package/lib/models/location/ILocation.js +2 -2
  111. package/lib/models/location/Location.d.ts +2 -2
  112. package/lib/models/location/Location.js +29 -29
  113. package/lib/models/mailLog/IMailLog.d.ts +14 -14
  114. package/lib/models/mailLog/IMailLog.js +2 -2
  115. package/lib/models/mailLog/MailLog.d.ts +3 -3
  116. package/lib/models/mailLog/MailLog.js +23 -23
  117. package/lib/models/modelConfiguration/IModelConfigurations.d.ts +31 -31
  118. package/lib/models/modelConfiguration/IModelConfigurations.js +2 -2
  119. package/lib/models/modelConfiguration/ModelConfiguration.d.ts +13 -13
  120. package/lib/models/modelConfiguration/ModelConfiguration.js +103 -103
  121. package/lib/models/permission/IPermission.d.ts +14 -14
  122. package/lib/models/permission/IPermission.js +2 -2
  123. package/lib/models/permission/Permission.d.ts +6 -6
  124. package/lib/models/permission/Permission.js +28 -28
  125. package/lib/models/permissiongroup/IPermissionGroup.d.ts +15 -15
  126. package/lib/models/permissiongroup/IPermissionGroup.js +2 -2
  127. package/lib/models/permissiongroup/PermissionGroup.d.ts +6 -6
  128. package/lib/models/permissiongroup/PermissionGroup.js +23 -23
  129. package/lib/models/request-log/IRequestLog.d.ts +22 -22
  130. package/lib/models/request-log/IRequestLog.js +2 -2
  131. package/lib/models/request-log/RequestLog.d.ts +3 -3
  132. package/lib/models/request-log/RequestLog.js +51 -51
  133. package/lib/models/userActionsLog/IUserActionsLog.d.ts +26 -26
  134. package/lib/models/userActionsLog/IUserActionsLog.js +11 -11
  135. package/lib/models/userActionsLog/UserActionsLog.d.ts +3 -3
  136. package/lib/models/userActionsLog/UserActionsLog.js +41 -41
  137. package/lib/pdf/ReportTemplate.d.ts +71 -71
  138. package/lib/pdf/ReportTemplate.js +94 -94
  139. package/lib/repositories/AdminNotificationRepository.d.ts +7 -7
  140. package/lib/repositories/AdminNotificationRepository.js +23 -23
  141. package/lib/repositories/AdminPermissionRepository.d.ts +7 -7
  142. package/lib/repositories/AdminPermissionRepository.js +23 -23
  143. package/lib/repositories/DashboardRepository.d.ts +5 -5
  144. package/lib/repositories/DashboardRepository.js +12 -12
  145. package/lib/repositories/PermissionGroupRepository.d.ts +7 -7
  146. package/lib/repositories/PermissionGroupRepository.js +23 -23
  147. package/lib/repositories/PermissionRepository.d.ts +7 -7
  148. package/lib/repositories/PermissionRepository.js +23 -23
  149. package/lib/repositories/Repository.d.ts +68 -68
  150. package/lib/repositories/Repository.js +215 -215
  151. package/lib/repositories/RequestLogRepository.d.ts +10 -10
  152. package/lib/repositories/RequestLogRepository.js +54 -54
  153. package/lib/repositories/SaveResult.d.ts +14 -14
  154. package/lib/repositories/SaveResult.js +18 -18
  155. package/lib/resources/AdminNotificationsResource.d.ts +3 -3
  156. package/lib/resources/AdminNotificationsResource.js +23 -23
  157. package/lib/resources/AdminPermissionResource.d.ts +5 -5
  158. package/lib/resources/AdminPermissionResource.js +36 -36
  159. package/lib/resources/PermissionGroupResource.d.ts +5 -5
  160. package/lib/resources/PermissionGroupResource.js +60 -60
  161. package/lib/resources/PermissionsResource.d.ts +5 -5
  162. package/lib/resources/PermissionsResource.js +23 -23
  163. package/lib/resources/parents.d.ts +12 -12
  164. package/lib/resources/parents.js +15 -15
  165. package/lib/router/index.d.ts +8 -8
  166. package/lib/router/index.js +104 -104
  167. package/lib/seeds/PermissionSeeder.d.ts +4 -4
  168. package/lib/seeds/PermissionSeeder.js +56 -56
  169. package/lib/types/DashbordConfig.d.ts +21 -21
  170. package/lib/types/DashbordConfig.js +2 -2
  171. package/lib/types/IConfigurationFile.d.ts +14 -14
  172. package/lib/types/IConfigurationFile.js +2 -2
  173. package/lib/types/IResourceFile.d.ts +738 -736
  174. package/lib/types/IResourceFile.js +2 -2
  175. package/lib/types/IResourceResponse.d.ts +96 -96
  176. package/lib/types/IResourceResponse.js +2 -2
  177. package/lib/types/helpers.d.ts +72 -71
  178. package/lib/types/helpers.js +84 -83
  179. package/lib/utils/DateUtils.d.ts +7 -7
  180. package/lib/utils/DateUtils.js +45 -45
  181. package/lib/utils/ResourceUtils.d.ts +2 -2
  182. package/lib/utils/ResourceUtils.js +7 -7
  183. package/lib/utils/ResponseUtils.d.ts +11 -11
  184. package/lib/utils/ResponseUtils.js +41 -41
  185. package/lib/utils/StringUtils.d.ts +9 -9
  186. package/lib/utils/StringUtils.js +46 -46
  187. package/lib/view/asset-manifest.json +18 -18
  188. package/lib/view/assets/icons/delete_icon.svg +3 -3
  189. package/lib/view/assets/icons/flags/ic_flag_cn.svg +9 -9
  190. package/lib/view/assets/icons/flags/ic_flag_sa.svg +9 -9
  191. package/lib/view/assets/icons/flags/ic_flag_vn.svg +9 -9
  192. package/lib/view/assets/icons/info_icon.svg +3 -3
  193. package/lib/view/assets/icons/navbar/ic_banking.svg +5 -5
  194. package/lib/view/assets/icons/navbar/ic_invoice.svg +4 -4
  195. package/lib/view/assets/icons/navbar/ic_kanban.svg +7 -7
  196. package/lib/view/assets/icons/navbar/ic_menu_item.svg +8 -8
  197. package/lib/view/assets/icons/small_info_icon.svg +3 -3
  198. package/lib/view/assets/illustrations/Group 16.svg +4 -4
  199. package/lib/view/assets/illustrations/logo.svg +5 -5
  200. package/lib/view/favicon/browserconfig.xml +9 -9
  201. package/lib/view/favicon/safari-pinned-tab.svg +182 -182
  202. package/lib/view/favicon/site.webmanifest +19 -19
  203. package/lib/view/fonts/index.css +18 -18
  204. package/lib/view/index.html +52 -52
  205. package/lib/view/manifest.json +20 -20
  206. package/lib/view/robots.txt +3 -3
  207. package/lib/view/static/css/main.54de06ef.css +1 -1
  208. package/lib/view/static/js/574.778b5963.chunk.js +1 -1
  209. package/lib/view/static/js/678.521704a3.chunk.js +1 -1
  210. package/lib/view/static/js/798.54856416.chunk.js +1 -1
  211. package/lib/view/static/js/main.4687f255.js +2 -2
  212. package/lib/view/static/js/main.4687f255.js.LICENSE.txt +214 -214
  213. package/package.json +65 -64
  214. package/skills/identity-admin/SKILL.md +272 -0
  215. package/skills/identity-admin/resource-file.md +654 -0
@@ -0,0 +1,654 @@
1
+ # Resource File Reference (`IResourceFile`)
2
+
3
+ This is the companion reference for the **identity-admin** skill. It documents every property of the `IResourceFile` interface that defines how a Mongoose model appears and behaves in the admin dashboard.
4
+
5
+ ```typescript
6
+ export interface IResourceFile {
7
+ properties: { /* see below */ };
8
+ listProperties?: string[];
9
+ showProperties?: string[];
10
+ formProperties?: string[];
11
+ filterProperties?: string[];
12
+ quickFilterProperties?: string[];
13
+ }
14
+ ```
15
+
16
+ ---
17
+
18
+ ## Required Properties
19
+
20
+ ```typescript
21
+ properties: {
22
+ resource: Model<any, any>; // the compiled Mongoose model
23
+ modelName: string; // database collection name
24
+ }
25
+ ```
26
+
27
+ - `resource` — The Mongoose model instance (e.g., `User` from `mongoose.model('User', schema)`)
28
+ - `modelName` — The collection name in MongoDB (e.g., `'users'`). Used for API route generation and permission lookups.
29
+
30
+ ---
31
+
32
+ ## Identity & Display
33
+
34
+ | Property | Type | Default | Description |
35
+ |----------|------|---------|-------------|
36
+ | `properties.name` | `string` | `modelName` | Display name in nav bar, page titles, and breadcrumbs |
37
+ | `properties.title` | `string` | Auto-detected | Field used as the clickable record link. Auto-detects `name`, `title`, or `email` on the schema; falls back to `_id`. Also used as the search bar target. |
38
+ | `properties.defaultOrderBy` | `string` | Schema title field | Sort field for the list view |
39
+ | `properties.defaultOrder` | `'asc' \| 'desc'` | `'asc'` | Sort direction |
40
+ | `properties.defaultrowsPerPage` | `number` | `10` | Default pagination size |
41
+
42
+ ## Navigation
43
+
44
+ ```typescript
45
+ properties: {
46
+ parent?: {
47
+ name: string; // nav group label (e.g., "Content", "Users")
48
+ icon: string; // MUI icon name (e.g., "People", "Settings")
49
+ };
50
+ }
51
+ ```
52
+
53
+ Resources with the same `parent.name` are grouped under one nav section. Icons come from [Material UI icons](https://mui.com/material-ui/material-icons/).
54
+
55
+ ## Visibility & Access Control
56
+
57
+ | Property | Type | Default | Description |
58
+ |----------|------|---------|-------------|
59
+ | `properties.isAllowed` | `(currentUser) => Promise<boolean>` | `true` | Whether the user can access this resource at all |
60
+ | `properties.isVisible` | `(currentUser) => Promise<boolean>` | `true` | Whether the resource appears in the nav bar |
61
+ | `properties.enableLog` | `(currentUser) => Promise<boolean>` | `false` | Whether to log changes to this resource |
62
+ | `properties.hiddenProperties` | `string[]` | `[]` | Fields completely hidden from all pages |
63
+
64
+ ## Display Property Arrays
65
+
66
+ Control exactly which fields appear on each view:
67
+
68
+ | Array | Purpose |
69
+ |-------|---------|
70
+ | `listProperties` | Table columns in the list/index view. Shows first 4 by default. |
71
+ | `showProperties` | Read-only fields in the detail view |
72
+ | `formProperties` | Editable fields in create/edit forms |
73
+ | `filterProperties` | Fields available in the advanced filter panel |
74
+ | `quickFilterProperties` | Fields shown as quick filter chips above the table |
75
+
76
+ If not specified, **all schema fields** (`list/show/form/filter`) or **none** (`quickFilter`) are shown.
77
+
78
+ ## Field Overrides (`properties.model`)
79
+
80
+ ```typescript
81
+ properties: {
82
+ model?: { [fieldName: string]: IFieldValue } | IModel;
83
+ }
84
+ ```
85
+
86
+ Override any schema field's behavior, or add virtual fields. Each key is a field name from the Mongoose schema.
87
+
88
+ ### `IFieldValue` Reference
89
+
90
+ | Property | Type | Default | Description |
91
+ |----------|------|---------|-------------|
92
+ | `type` | `FieldTypes` | Same as schema | Override the field type. See enums below. |
93
+ | `required` | `boolean` | Same as schema | Override whether the field is required in forms |
94
+ | `isEditable` | `boolean` | `true` | Whether the field can be edited |
95
+ | `enumValues` | `string[] \| { [key]: { label, color?, labelColor? } }` | Same as schema | Custom enum labels and chip colors |
96
+ | `countryCodes` | `string[]` | — | Allowed country codes for phone number fields (e.g., `['sa', 'eg']`) |
97
+ | `defaultCountryCode` | `string` | First country or `'sa'` | Default selected country for phone fields |
98
+ | `mediaUploader` | `boolean` | — | Enable media upload for reference fields pointing to the Image collection |
99
+ | `fileType` | `FileTypes` | `'IMAGE'` | Restrict media uploader to specific file types |
100
+ | `imageOptimizingCategory` | `ImageOptimizingCategories` | `'NORMAL'` | Image compression level (`'NORMAL'` or `'BANNERS'`) |
101
+ | `disableImageOptimization` | `boolean` | `false` | Skip image optimization |
102
+ | `imageBackgroundHexColor` | `string` | — | Background color for image display |
103
+ | `withTime` | `boolean` | `false` | Show time picker alongside date picker |
104
+ | `apiRoute` | `string` | — | API endpoint for fetching reference options |
105
+ | `valuePath` | `string` | — | Path to the value inside a referenced document |
106
+ | `isClickable` | `boolean` | — | Whether the field value is clickable in the list |
107
+ | `path` | `string` | — | Resource path to navigate to on click |
108
+ | `keys` | `string[]` | — | Keys to show within a nested schema field |
109
+ | `schema` | `IModel \| { [key]: IFieldValue }` | — | Define nested schema structure |
110
+ | `multipleInFilter` | `boolean` | — | Enable multi-value selection for this quick filter |
111
+ | `yupValidationSchema` | `Yup.Schema` | Same as schema | Custom Yup validation |
112
+ | `enableCreateNewButtonOnReference` | `boolean` | `false` | Show "Create New" button inside reference selector |
113
+ | `textArea` | `boolean` | `false` | Render text field as a multi-line textarea |
114
+ | `relatedFields` | `string[]` | — | Show related fields from a referenced document |
115
+ | `minWidth` | `number` | — | Minimum column width in the list view |
116
+ | `filter` | `{ formList?, filterList? }` | — | Filter options for reference selectors (`Record<string, any>`) |
117
+ | `arrayType` | `FieldTypes` | Same as schema | Element type for array fields |
118
+ | `isDraggable` | `boolean` | `true` | Whether array items are reorderable by drag-and-drop |
119
+
120
+ ### Virtual Fields (`IModel.virtuals`)
121
+
122
+ Add fields that don't exist in the database but are needed in the UI:
123
+
124
+ ```typescript
125
+ model?: {
126
+ virtuals?: {
127
+ [virtualName: string]: IVirtualValue;
128
+ };
129
+ }
130
+ ```
131
+
132
+ ### `IVirtualValue` Reference
133
+
134
+ | Property | Type | Description |
135
+ |----------|------|-------------|
136
+ | `type` | `'password' \| 'ref' \| 'Array'` | Virtual field type |
137
+ | `filterBy` | `string` | For `ref` type: the foreign key field for one-to-many relations |
138
+ | `arrayType` | `string` | For `Array` type: the element type |
139
+ | `showIn` | `Virtuals` | Where to display: `'SHOW'`, `'LIST'`, `'FORM'`, or `'FILTER'` |
140
+ | `required` | `boolean` | Whether the virtual is required in forms |
141
+ | `resource` | `Model` | For `ref`/`Array` type: the related Mongoose model |
142
+ | `handler` | `(filterQuery, value) => filterQuery` | Custom filter query logic when used in filters |
143
+
144
+ **Use cases:**
145
+
146
+ - `password` — Add a password field to the creation form without storing it in the model
147
+ - `ref` — Display related child records (e.g., all posts by a user) in the show page
148
+ - `Array` — Display an array of related items
149
+
150
+ ## Actions (`properties.actions`)
151
+
152
+ ```typescript
153
+ properties: {
154
+ actions?: ActionOptions;
155
+ }
156
+ ```
157
+
158
+ Control built-in CRUD actions and add custom extra actions:
159
+
160
+ ```typescript
161
+ interface ActionOptions {
162
+ show?: Action;
163
+ new?: Action;
164
+ edit?: Action;
165
+ delete?: Action;
166
+ import?: Action;
167
+ bulkDelete?: Action;
168
+ duplicate?: Action;
169
+ extras?: ExtraAction[];
170
+ }
171
+ ```
172
+
173
+ ### `Action` Interface (for built-in actions)
174
+
175
+ | Property | Type | Default | Description |
176
+ |----------|------|---------|-------------|
177
+ | `isAccessible` | `boolean` | `true` (except bulkDelete/import: `false`) | Whether the action is available |
178
+ | `reloadAfterAction` | `boolean` | `false` | Reload page after action execution |
179
+ | `isAllowed` | `(currentUser) => boolean` | Same as `isAccessible` | Role-based permission check |
180
+ | `isMainAction` | `boolean` | `true` for show/edit, `false` for others | Whether action appears as a primary button vs. menu item |
181
+ | `isVisible` | `(data: ActionData) => Promise<boolean>` | Same as `isAccessible` | Per-record visibility check |
182
+
183
+ ### `ExtraAction` Interface (custom actions)
184
+
185
+ | Property | Type | Default | Description |
186
+ |----------|------|---------|-------------|
187
+ | `key` | `string` | — | Unique identifier within the resource |
188
+ | `name` | `string` | — | Button label |
189
+ | `icon` | `string` | — | MUI icon name |
190
+ | `color` | `string \| ButtonColors` | `'inherit'` (bulk) / `'black'` (record) | Button color |
191
+ | `size` | `ButtonSizes` | `'small'` | Button size (bulk actions only) |
192
+ | `variant` | `ButtonVariants` | `'contained'` | Button variant (bulk actions only) |
193
+ | `actionType` | `'record' \| 'resource'` | — | `'record'` = per-row action, `'resource'` = top-level button |
194
+ | `guardTitle` | `string` | — | Confirmation dialog title |
195
+ | `guard` | `string` | — | Confirmation dialog message |
196
+ | `message` | `string` | `'Action was executed successfully'` | Success alert message |
197
+ | `showAlertMessage` | `boolean` | `true` | Whether to show the success alert |
198
+ | `severity` | `'success' \| 'info' \| 'warning' \| 'error'` | `'success'` | Alert severity/color |
199
+ | `fullScreen` | `boolean` | `false` | Whether the custom component dialog is full screen |
200
+ | `isVisible` | `(data: ActionData) => Promise<boolean>` | Always visible | Per-record visibility |
201
+ | `isMainAction` | `boolean` | `true` for show/edit | Whether it's a primary button vs. menu item |
202
+ | `handler` | `(req, res, data) => Promise<IActionHandlerResponse>` | — | The action logic |
203
+ | `handlerStrategy` | `HandlerStrategy` | — | `'NORMAL'`, `'FILE_DOWNLOAD'`, or `'CUSTOM_COMPONENT'` |
204
+
205
+ ### `IActionHandlerResponse`
206
+
207
+ ```typescript
208
+ interface IActionHandlerResponse {
209
+ action: ActionNames; // 'SHOW' | 'LIST' | 'NEW' | 'EDIT'
210
+ path: string; // resource.path to redirect to
211
+ recordId?: string; // for SHOW/EDIT redirections
212
+ filePath?: string; // for FILE_DOWNLOAD strategy
213
+ }
214
+ ```
215
+
216
+ ### `ActionData` (passed to `isVisible` and `handler`)
217
+
218
+ ```typescript
219
+ interface ActionData {
220
+ record: any; // the document
221
+ currentUser: Document; // authenticated user
222
+ resource: {
223
+ name: string; // modelName
224
+ path: string; // resource route path
225
+ repository: IRepository<Document>; // the repository instance
226
+ };
227
+ }
228
+ ```
229
+
230
+ ## Filters (`properties.filters`)
231
+
232
+ ```typescript
233
+ properties: {
234
+ filters?: IFilters;
235
+ }
236
+ ```
237
+
238
+ ### Scopes
239
+
240
+ Scope filters add tabs above the list view:
241
+
242
+ ```typescript
243
+ scopes?: {
244
+ isAccessible: boolean; // default false
245
+ showAll?: boolean; // show "All" tab (default true)
246
+
247
+ // Auto scope — filters by a schema key with predefined values
248
+ auto?: {
249
+ key: string; // schema field name (e.g., 'status')
250
+ options: string[]; // values that become tabs
251
+ };
252
+
253
+ // Manual scope — full control with a handler
254
+ manual?: {
255
+ options: string[]; // tab labels
256
+ handler: (filter, scope, currentUser) => Promise<filter>;
257
+ };
258
+ }
259
+ ```
260
+
261
+ **Auto scope example** — creates tabs for each `status` value:
262
+ ```typescript
263
+ scopes: { isAccessible: true, auto: { key: 'status', options: ['active', 'inactive', 'pending'] } }
264
+ ```
265
+
266
+ **Manual scope example** — custom logic per tab:
267
+ ```typescript
268
+ scopes: {
269
+ isAccessible: true,
270
+ manual: {
271
+ options: ['Today', 'This Week', 'This Month'],
272
+ handler: async (filter, scope) => {
273
+ const now = new Date();
274
+ switch (scope) {
275
+ case 'Today':
276
+ filter.createdAt = { $gte: new Date(now.setHours(0,0,0,0)) };
277
+ break;
278
+ case 'This Week':
279
+ filter.createdAt = { $gte: new Date(now.setDate(now.getDate() - now.getDay())) };
280
+ break;
281
+ }
282
+ return filter;
283
+ },
284
+ },
285
+ }
286
+ ```
287
+
288
+ ### Search Bar
289
+
290
+ ```typescript
291
+ searchBar?: {
292
+ isAccessible: boolean; // default true
293
+ }
294
+ ```
295
+
296
+ ## CRUD Operations (`properties.crudOperations`)
297
+
298
+ Intercept any CRUD lifecycle stage. Each hook receives different arguments and must return a specific type — pay close attention to parameter order and return types.
299
+
300
+ ```typescript
301
+ properties: {
302
+ crudOperations?: ICrudOperations;
303
+ }
304
+ ```
305
+
306
+ ---
307
+
308
+ ### `index` — List view
309
+
310
+ #### `index.before`
311
+ ```typescript
312
+ before?: (
313
+ req: IRequest,
314
+ filter: { [key: string]: any },
315
+ currentUser: Document
316
+ ) => Promise<{ [key: string]: any }>
317
+ ```
318
+ Modify the MongoDB filter object before the query runs. Return the (possibly modified) filter.
319
+
320
+ #### `index.after`
321
+ ```typescript
322
+ after?: (
323
+ req: IRequest,
324
+ documents: Document[],
325
+ currentUser: Document
326
+ ) => Promise<Document[]>
327
+ ```
328
+ Transform the result array after the query completes. Return the modified documents array.
329
+
330
+ #### `index.index` (custom query)
331
+ ```typescript
332
+ index?: (
333
+ req: IRequest,
334
+ filter: { [key: string]: any },
335
+ sortQuery: { [key: string]: any },
336
+ paginateParams: PaginateParams | undefined,
337
+ populate: any,
338
+ currentUser: Document
339
+ ) => Promise<{ records: Document[]; pageInfo?: PageInfo }>
340
+ ```
341
+ Replace the entire list query with custom logic. You receive the raw filter, sort, pagination, and populate params. Return `{ records, pageInfo? }`.
342
+
343
+ ---
344
+
345
+ ### `create` — Create record
346
+
347
+ #### `create.before`
348
+ ```typescript
349
+ before?: (
350
+ req: IRequest,
351
+ params: any,
352
+ currentUser: Document
353
+ ) => Promise<any>
354
+ ```
355
+ Modify the request body params before the document is saved. Return the (possibly modified) params. Common use: inject `createdBy` from `currentUser._id`.
356
+
357
+ #### `create.after`
358
+ ```typescript
359
+ after?: (
360
+ req: IRequest,
361
+ document: Document,
362
+ currentUser: Document,
363
+ params: any
364
+ ) => Promise<Document>
365
+ ```
366
+ Called after the document is saved. Receives both the saved document and the original params. Return the (possibly modified) document.
367
+
368
+ **Argument order:** `req, document, currentUser, params` — note `currentUser` comes before `params`.
369
+
370
+ #### `create.validators`
371
+ ```typescript
372
+ validators?: ValidationChain[]
373
+ ```
374
+ Array of [express-validator](https://express-validator.github.io) chains run before the save query.
375
+
376
+ ---
377
+
378
+ ### `update` — Update record
379
+
380
+ #### `update.before`
381
+ ```typescript
382
+ before?: (
383
+ req: IRequest,
384
+ params: any,
385
+ currentUser: Document
386
+ ) => Promise<any>
387
+ ```
388
+ Modify the request body params before the document is updated. Return the (possibly modified) params.
389
+
390
+ #### `update.after`
391
+ ```typescript
392
+ after?: (
393
+ req: IRequest,
394
+ document: Document,
395
+ params: any,
396
+ currentUser: Document
397
+ ) => Promise<Document>
398
+ ```
399
+ Called after the document is updated. Receives the updated document, the submitted params, and the current user.
400
+
401
+ **Argument order:** `req, document, params, currentUser` — different from `create.after` where `currentUser` comes before `params`.
402
+
403
+ #### `update.update` (custom update)
404
+ ```typescript
405
+ update?: (
406
+ req: IRequest,
407
+ record: Document,
408
+ recordParams: any,
409
+ currentUser: Document
410
+ ) => Promise<SaveResult<any>>
411
+ ```
412
+ Replace the entire update logic. Receives the existing `record`, the `recordParams` from the request, and the current user. Return a `SaveResult<any>`.
413
+
414
+ #### `update.validators`
415
+ ```typescript
416
+ validators?: ValidationChain[]
417
+ ```
418
+ Array of express-validator chains run before the update query.
419
+
420
+ ---
421
+
422
+ ### `show` — Detail view
423
+
424
+ #### `show.before`
425
+ ```typescript
426
+ before?: (
427
+ req: IRequest,
428
+ filter: { [key: string]: any },
429
+ currentUser: Document
430
+ ) => Promise<{ [key: string]: any }>
431
+ ```
432
+ Modify the lookup filter before the record is fetched. Return the (possibly modified) filter.
433
+
434
+ #### `show.after`
435
+ ```typescript
436
+ after?: (
437
+ req: IRequest,
438
+ record: Document
439
+ ) => Promise<{ record: Document; [key: string]: any }>
440
+ ```
441
+ Add extra data to the show response. **Note:** this hook does NOT receive `currentUser`. Return an object containing the `record` plus any additional fields.
442
+
443
+ ```typescript
444
+ // Example: attach related data to the response
445
+ show: {
446
+ after: async (req, record) => {
447
+ const stats = await Stats.findOne({ userId: record._id });
448
+ return { record, stats };
449
+ },
450
+ },
451
+ ```
452
+
453
+ #### `show.nextPreviousButtonHandler`
454
+ ```typescript
455
+ nextPreviousButtonHandler?: (
456
+ req: IRequest,
457
+ filter: { [key: string]: any },
458
+ currentUser: Document,
459
+ direction: NeighborTypes // 'NEXT' | 'PREVIOUS'
460
+ ) => Promise<{ [key: string]: any }>
461
+ ```
462
+ Custom logic for navigating to the next or previous record. Modify the filter to scope which records are eligible for neighbor navigation. Return the filter.
463
+
464
+ ## Population (`properties.populate`)
465
+
466
+ Control how referenced fields are populated:
467
+
468
+ ```typescript
469
+ populate?: {
470
+ all?: PopulateFunction; // applied to all endpoints
471
+ list?: PopulateFunction; // applied only to list endpoint
472
+ show?: PopulateFunction; // applied to show, create, update
473
+ }
474
+
475
+ // PopulateFunction = (populatedString: any) => Promise<any>
476
+ ```
477
+
478
+ The function receives the current populate string and can modify it before execution.
479
+
480
+ ## Localization
481
+
482
+ ```typescript
483
+ keysTranslations?: { [key: string]: any }; // field label translations
484
+ actionsTranslations?: { [key: string]: any }; // action button translations
485
+ ```
486
+
487
+ Structure mirrors the locale JSON (see `src/locales/en.json`). Used when `enableLocalization: true` is set in the app configuration.
488
+
489
+ ## Additional Options
490
+
491
+ | Property | Type | Default | Description |
492
+ |----------|------|---------|-------------|
493
+ | `disableNextPreviousButtonsInShowPage` | `boolean` | `false` | Hide prev/next navigation in show |
494
+ | `disableNextPreviousButtonsInEditPage` | `boolean` | `false` | Hide prev/next navigation in edit |
495
+ | `displayEditPageInShowPage` | `boolean` | `false` | Open edit form instead of show view |
496
+ | `imageOnReferencePath` | `string` | — | Field path for thumbnail image in reference selectors |
497
+ | `disableImageOnReference` | `boolean` | `false` | Hide thumbnail images in reference selectors |
498
+ | `extras` | `{ [key]: any }` | — | Arbitrary extra data passed to the frontend |
499
+ | `sendDraftMail` | `(data: { to, subject, html }) => Promise<void>` | — | Handler for sending draft emails from mail log |
500
+ | `afterImport` | `(req, currentUser, data) => Promise<any>` | — | Post-import processing hook |
501
+
502
+ ---
503
+
504
+ ## Enums
505
+
506
+ ### `FieldTypes`
507
+
508
+ | Value | Description |
509
+ |-------|-------------|
510
+ | `'String'` | Text input |
511
+ | `'Number'` | Number input |
512
+ | `'enum'` | Dropdown / chips |
513
+ | `'ref'` | Reference to another model |
514
+ | `'Date'` | Date picker |
515
+ | `'password'` | Masked password input |
516
+ | `'Boolean'` | Toggle switch |
517
+ | `'ObjectID'` | Object ID display |
518
+ | `'nestedSchema'` | Embedded sub-document |
519
+ | `'Array'` | Array of values |
520
+ | `'image'` | Image upload with preview |
521
+ | `'localizedString'` | Multi-language string |
522
+ | `'phoneNumber'` | Phone input with country code |
523
+ | `'color'` | Color picker |
524
+ | `'timePicker'` | Time selector |
525
+ | `'File'` | File upload |
526
+ | `'LOCATION'` | Map location picker |
527
+ | `'HTML'` | HTML rich text editor |
528
+ | `'RICH_TEXT_I'` | Rich text editor (type I) |
529
+ | `'RICH_TEXT_II'` | Rich text editor (type II) |
530
+ | `'JSON_RICH_TEXT'` | JSON-based rich text |
531
+ | `'EXTERNAL_LINK'` | External URL input |
532
+ | `'MULTIPLE_TEXT'` | Multiple text values |
533
+
534
+ ### `ActionTypes`
535
+
536
+ - `'record'` — Per-row action in the list
537
+ - `'resource'` — Top-level action button
538
+
539
+ ### `ActionNames`
540
+
541
+ - `'SHOW'`, `'LIST'`, `'NEW'`, `'EDIT'` — Redirection targets
542
+
543
+ ### `Virtuals`
544
+
545
+ - `'SHOW'`, `'LIST'`, `'FORM'`, `'FILTER'` — Where a virtual field appears
546
+
547
+ ### `HandlerStrategy`
548
+
549
+ - `'NORMAL'` — Standard handler execution
550
+ - `'FILE_DOWNLOAD'` — Returns a file for download
551
+ - `'CUSTOM_COMPONENT'` — Opens a custom React component dialog
552
+
553
+ ### `FileTypes`
554
+
555
+ `'ALL'`, `'IMAGE'`, `'3D'`, `'PDF'`, `'EXCEL'`, `'WORD'`, `'VIDEO'`, `'TEXT'`, `'ZIP'`, `'POWER_POINT'`, `'AUDIO'`
556
+
557
+ ### `ImageOptimizingCategories`
558
+
559
+ - `'NORMAL'` — Standard compression
560
+ - `'BANNERS'` — Banner-level compression
561
+
562
+ ---
563
+
564
+ ## Complete Example
565
+
566
+ ```typescript
567
+ import { Model, Schema } from 'mongoose';
568
+ import { IResourceFile } from 'identity-admin/lib/types/IResourceFile';
569
+ import { FieldTypes, Virtuals, ActionTypes } from 'identity-admin/lib/types/helpers';
570
+
571
+ const UserResource: IResourceFile = {
572
+ properties: {
573
+ resource: User,
574
+ modelName: 'users',
575
+ name: 'Users',
576
+ title: 'fullName',
577
+ parent: { name: 'Access Control', icon: 'People' },
578
+ defaultOrderBy: 'createdAt',
579
+ defaultOrder: 'desc',
580
+ defaultrowsPerPage: 25,
581
+ isAllowed: async (user) => user.role === 'admin',
582
+ isVisible: async (user) => user.role !== 'viewer',
583
+ hiddenProperties: ['__v', 'encryptedPassword'],
584
+ model: {
585
+ fullName: { type: 'String' as FieldTypes, required: true },
586
+ email: { type: 'String' as FieldTypes, isEditable: false },
587
+ role: {
588
+ type: 'enum' as FieldTypes,
589
+ enumValues: {
590
+ admin: { label: 'Admin', color: '#FF6B6B', labelColor: '#FFF' },
591
+ editor: { label: 'Editor', color: '#4ECDC4', labelColor: '#FFF' },
592
+ viewer: { label: 'Viewer', color: '#95E1D3', labelColor: '#333' },
593
+ },
594
+ },
595
+ avatar: { type: 'image' as FieldTypes, mediaUploader: true, imageOptimizingCategory: 'NORMAL' as any },
596
+ phone: { type: 'phoneNumber' as FieldTypes, countryCodes: ['sa', 'eg', 'us'] },
597
+ bio: { type: 'HTML' as FieldTypes },
598
+ virtuals: {
599
+ password: { type: 'password', showIn: Virtuals.FORM, required: true },
600
+ posts: { type: 'ref', filterBy: 'author', showIn: Virtuals.SHOW, resource: Post },
601
+ },
602
+ },
603
+ actions: {
604
+ delete: { isAccessible: false },
605
+ bulkDelete: { isAccessible: true },
606
+ extras: [
607
+ {
608
+ key: 'sendWelcomeEmail',
609
+ name: 'Send Welcome',
610
+ icon: 'Email',
611
+ actionType: 'record' as ActionTypes,
612
+ handler: async (req, res, data) => {
613
+ await sendEmail(data.record.email, 'Welcome!');
614
+ return { action: 'LIST', path: data.resource.path };
615
+ },
616
+ },
617
+ ],
618
+ },
619
+ filters: {
620
+ scopes: {
621
+ isAccessible: true,
622
+ auto: { key: 'role', options: ['admin', 'editor', 'viewer'] },
623
+ },
624
+ },
625
+ crudOperations: {
626
+ create: {
627
+ before: async (req, params, currentUser) => {
628
+ params.createdBy = currentUser._id;
629
+ return params;
630
+ },
631
+ },
632
+ index: {
633
+ before: async (req, filter) => {
634
+ if (req.query.search) filter.$text = { $search: req.query.search };
635
+ return filter;
636
+ },
637
+ },
638
+ },
639
+ populate: {
640
+ all: async (populateStr) => `${populateStr} createdBy`,
641
+ },
642
+ keysTranslations: {
643
+ fullName: { en: 'Full Name', ar: 'الاسم الكامل' },
644
+ email: { en: 'Email', ar: 'البريد الإلكتروني' },
645
+ },
646
+ disableNextPreviousButtonsInShowPage: true,
647
+ },
648
+ listProperties: ['fullName', 'email', 'role', 'createdAt'],
649
+ showProperties: ['fullName', 'email', 'role', 'avatar', 'bio', 'createdAt'],
650
+ formProperties: ['fullName', 'email', 'role', 'avatar', 'phone', 'bio', 'password'],
651
+ filterProperties: ['role', 'createdAt'],
652
+ quickFilterProperties: ['role'],
653
+ };
654
+ ```