@rebasepro/server-mongodb 0.0.1-canary.09e5ec5

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 (286) hide show
  1. package/LICENSE +6 -0
  2. package/dist/ensure-collections-CNrcwVgY.js +74 -0
  3. package/dist/ensure-collections-CNrcwVgY.js.map +1 -0
  4. package/dist/ensure-history-collection-DBIiwmCm.js +15 -0
  5. package/dist/ensure-history-collection-DBIiwmCm.js.map +1 -0
  6. package/dist/index.es.js +1734 -0
  7. package/dist/index.es.js.map +1 -0
  8. package/dist/index.umd.js +2043 -0
  9. package/dist/index.umd.js.map +1 -0
  10. package/dist/server-core/src/api/ast-schema-editor.d.ts +22 -0
  11. package/dist/server-core/src/api/ast-schema-editor.d.ts.map +1 -0
  12. package/dist/server-core/src/api/errors.d.ts +36 -0
  13. package/dist/server-core/src/api/errors.d.ts.map +1 -0
  14. package/dist/server-core/src/api/graphql/graphql-schema-generator.d.ts +36 -0
  15. package/dist/server-core/src/api/graphql/graphql-schema-generator.d.ts.map +1 -0
  16. package/dist/server-core/src/api/graphql/index.d.ts +2 -0
  17. package/dist/server-core/src/api/graphql/index.d.ts.map +1 -0
  18. package/dist/server-core/src/api/index.d.ts +10 -0
  19. package/dist/server-core/src/api/index.d.ts.map +1 -0
  20. package/dist/server-core/src/api/openapi-generator.d.ts +17 -0
  21. package/dist/server-core/src/api/openapi-generator.d.ts.map +1 -0
  22. package/dist/server-core/src/api/rest/api-generator.d.ts +65 -0
  23. package/dist/server-core/src/api/rest/api-generator.d.ts.map +1 -0
  24. package/dist/server-core/src/api/rest/index.d.ts +2 -0
  25. package/dist/server-core/src/api/rest/index.d.ts.map +1 -0
  26. package/dist/server-core/src/api/rest/query-parser.d.ts +10 -0
  27. package/dist/server-core/src/api/rest/query-parser.d.ts.map +1 -0
  28. package/dist/server-core/src/api/schema-editor-routes.d.ts +4 -0
  29. package/dist/server-core/src/api/schema-editor-routes.d.ts.map +1 -0
  30. package/dist/server-core/src/api/server.d.ts +41 -0
  31. package/dist/server-core/src/api/server.d.ts.map +1 -0
  32. package/dist/server-core/src/api/types.d.ts +91 -0
  33. package/dist/server-core/src/api/types.d.ts.map +1 -0
  34. package/dist/server-core/src/auth/admin-routes.d.ts +17 -0
  35. package/dist/server-core/src/auth/admin-routes.d.ts.map +1 -0
  36. package/dist/server-core/src/auth/apple-oauth.d.ts +31 -0
  37. package/dist/server-core/src/auth/apple-oauth.d.ts.map +1 -0
  38. package/dist/server-core/src/auth/bitbucket-oauth.d.ts +12 -0
  39. package/dist/server-core/src/auth/bitbucket-oauth.d.ts.map +1 -0
  40. package/dist/server-core/src/auth/discord-oauth.d.ts +15 -0
  41. package/dist/server-core/src/auth/discord-oauth.d.ts.map +1 -0
  42. package/dist/server-core/src/auth/facebook-oauth.d.ts +15 -0
  43. package/dist/server-core/src/auth/facebook-oauth.d.ts.map +1 -0
  44. package/dist/server-core/src/auth/github-oauth.d.ts +16 -0
  45. package/dist/server-core/src/auth/github-oauth.d.ts.map +1 -0
  46. package/dist/server-core/src/auth/gitlab-oauth.d.ts +14 -0
  47. package/dist/server-core/src/auth/gitlab-oauth.d.ts.map +1 -0
  48. package/dist/server-core/src/auth/google-oauth.d.ts +15 -0
  49. package/dist/server-core/src/auth/google-oauth.d.ts.map +1 -0
  50. package/dist/server-core/src/auth/index.d.ts +24 -0
  51. package/dist/server-core/src/auth/index.d.ts.map +1 -0
  52. package/dist/server-core/src/auth/interfaces.d.ts +310 -0
  53. package/dist/server-core/src/auth/interfaces.d.ts.map +1 -0
  54. package/dist/server-core/src/auth/jwt.d.ts +44 -0
  55. package/dist/server-core/src/auth/jwt.d.ts.map +1 -0
  56. package/dist/server-core/src/auth/linkedin-oauth.d.ts +19 -0
  57. package/dist/server-core/src/auth/linkedin-oauth.d.ts.map +1 -0
  58. package/dist/server-core/src/auth/microsoft-oauth.d.ts +17 -0
  59. package/dist/server-core/src/auth/microsoft-oauth.d.ts.map +1 -0
  60. package/dist/server-core/src/auth/middleware.d.ts +82 -0
  61. package/dist/server-core/src/auth/middleware.d.ts.map +1 -0
  62. package/dist/server-core/src/auth/password.d.ts +23 -0
  63. package/dist/server-core/src/auth/password.d.ts.map +1 -0
  64. package/dist/server-core/src/auth/rate-limiter.d.ts +32 -0
  65. package/dist/server-core/src/auth/rate-limiter.d.ts.map +1 -0
  66. package/dist/server-core/src/auth/routes.d.ts +28 -0
  67. package/dist/server-core/src/auth/routes.d.ts.map +1 -0
  68. package/dist/server-core/src/auth/slack-oauth.d.ts +13 -0
  69. package/dist/server-core/src/auth/slack-oauth.d.ts.map +1 -0
  70. package/dist/server-core/src/auth/spotify-oauth.d.ts +13 -0
  71. package/dist/server-core/src/auth/spotify-oauth.d.ts.map +1 -0
  72. package/dist/server-core/src/auth/twitter-oauth.d.ts +19 -0
  73. package/dist/server-core/src/auth/twitter-oauth.d.ts.map +1 -0
  74. package/dist/server-core/src/collections/BackendCollectionRegistry.d.ts +14 -0
  75. package/dist/server-core/src/collections/BackendCollectionRegistry.d.ts.map +1 -0
  76. package/dist/server-core/src/collections/loader.d.ts +6 -0
  77. package/dist/server-core/src/collections/loader.d.ts.map +1 -0
  78. package/dist/server-core/src/cron/cron-loader.d.ts +18 -0
  79. package/dist/server-core/src/cron/cron-loader.d.ts.map +1 -0
  80. package/dist/server-core/src/cron/cron-routes.d.ts +15 -0
  81. package/dist/server-core/src/cron/cron-routes.d.ts.map +1 -0
  82. package/dist/server-core/src/cron/cron-scheduler.d.ts +62 -0
  83. package/dist/server-core/src/cron/cron-scheduler.d.ts.map +1 -0
  84. package/dist/server-core/src/cron/cron-store.d.ts +33 -0
  85. package/dist/server-core/src/cron/cron-store.d.ts.map +1 -0
  86. package/dist/server-core/src/cron/index.d.ts +7 -0
  87. package/dist/server-core/src/cron/index.d.ts.map +1 -0
  88. package/dist/server-core/src/db/interfaces.d.ts +19 -0
  89. package/dist/server-core/src/db/interfaces.d.ts.map +1 -0
  90. package/dist/server-core/src/email/index.d.ts +7 -0
  91. package/dist/server-core/src/email/index.d.ts.map +1 -0
  92. package/dist/server-core/src/email/smtp-email-service.d.ts +26 -0
  93. package/dist/server-core/src/email/smtp-email-service.d.ts.map +1 -0
  94. package/dist/server-core/src/email/templates.d.ts +43 -0
  95. package/dist/server-core/src/email/templates.d.ts.map +1 -0
  96. package/dist/server-core/src/email/types.d.ts +108 -0
  97. package/dist/server-core/src/email/types.d.ts.map +1 -0
  98. package/dist/server-core/src/functions/function-loader.d.ts +18 -0
  99. package/dist/server-core/src/functions/function-loader.d.ts.map +1 -0
  100. package/dist/server-core/src/functions/function-routes.d.ts +11 -0
  101. package/dist/server-core/src/functions/function-routes.d.ts.map +1 -0
  102. package/dist/server-core/src/functions/index.d.ts +4 -0
  103. package/dist/server-core/src/functions/index.d.ts.map +1 -0
  104. package/dist/server-core/src/history/history-routes.d.ts +24 -0
  105. package/dist/server-core/src/history/history-routes.d.ts.map +1 -0
  106. package/dist/server-core/src/history/index.d.ts +2 -0
  107. package/dist/server-core/src/history/index.d.ts.map +1 -0
  108. package/dist/server-core/src/index.d.ts +30 -0
  109. package/dist/server-core/src/index.d.ts.map +1 -0
  110. package/dist/server-core/src/init.d.ts +160 -0
  111. package/dist/server-core/src/init.d.ts.map +1 -0
  112. package/dist/server-core/src/serve-spa.d.ts +31 -0
  113. package/dist/server-core/src/serve-spa.d.ts.map +1 -0
  114. package/dist/server-core/src/services/driver-registry.d.ts +79 -0
  115. package/dist/server-core/src/services/driver-registry.d.ts.map +1 -0
  116. package/dist/server-core/src/singleton.d.ts +36 -0
  117. package/dist/server-core/src/singleton.d.ts.map +1 -0
  118. package/dist/server-core/src/storage/LocalStorageController.d.ts +47 -0
  119. package/dist/server-core/src/storage/LocalStorageController.d.ts.map +1 -0
  120. package/dist/server-core/src/storage/S3StorageController.d.ts +37 -0
  121. package/dist/server-core/src/storage/S3StorageController.d.ts.map +1 -0
  122. package/dist/server-core/src/storage/index.d.ts +26 -0
  123. package/dist/server-core/src/storage/index.d.ts.map +1 -0
  124. package/dist/server-core/src/storage/routes.d.ts +39 -0
  125. package/dist/server-core/src/storage/routes.d.ts.map +1 -0
  126. package/dist/server-core/src/storage/storage-registry.d.ts +79 -0
  127. package/dist/server-core/src/storage/storage-registry.d.ts.map +1 -0
  128. package/dist/server-core/src/storage/types.d.ts +104 -0
  129. package/dist/server-core/src/storage/types.d.ts.map +1 -0
  130. package/dist/server-core/src/types/index.d.ts +12 -0
  131. package/dist/server-core/src/types/index.d.ts.map +1 -0
  132. package/dist/server-core/src/utils/dev-port.d.ts +36 -0
  133. package/dist/server-core/src/utils/dev-port.d.ts.map +1 -0
  134. package/dist/server-core/src/utils/logger.d.ts +32 -0
  135. package/dist/server-core/src/utils/logger.d.ts.map +1 -0
  136. package/dist/server-core/src/utils/logging.d.ts +10 -0
  137. package/dist/server-core/src/utils/logging.d.ts.map +1 -0
  138. package/dist/server-core/src/utils/request-logger.d.ts +20 -0
  139. package/dist/server-core/src/utils/request-logger.d.ts.map +1 -0
  140. package/dist/server-core/src/utils/sql.d.ts +28 -0
  141. package/dist/server-core/src/utils/sql.d.ts.map +1 -0
  142. package/dist/server-mongodb/src/MongoBootstrapper.d.ts +18 -0
  143. package/dist/server-mongodb/src/MongoBootstrapper.d.ts.map +1 -0
  144. package/dist/server-mongodb/src/auth/ensure-collections.d.ts +3 -0
  145. package/dist/server-mongodb/src/auth/ensure-collections.d.ts.map +1 -0
  146. package/dist/server-mongodb/src/auth/services.d.ts +135 -0
  147. package/dist/server-mongodb/src/auth/services.d.ts.map +1 -0
  148. package/dist/server-mongodb/src/connection.d.ts +35 -0
  149. package/dist/server-mongodb/src/connection.d.ts.map +1 -0
  150. package/dist/server-mongodb/src/db/MongoConditionBuilder.d.ts +64 -0
  151. package/dist/server-mongodb/src/db/MongoConditionBuilder.d.ts.map +1 -0
  152. package/dist/server-mongodb/src/db/MongoEntityService.d.ts +98 -0
  153. package/dist/server-mongodb/src/db/MongoEntityService.d.ts.map +1 -0
  154. package/dist/server-mongodb/src/factory.d.ts +142 -0
  155. package/dist/server-mongodb/src/factory.d.ts.map +1 -0
  156. package/dist/server-mongodb/src/history/ensure-history-collection.d.ts +3 -0
  157. package/dist/server-mongodb/src/history/ensure-history-collection.d.ts.map +1 -0
  158. package/dist/server-mongodb/src/index.d.ts +18 -0
  159. package/dist/server-mongodb/src/index.d.ts.map +1 -0
  160. package/dist/server-mongodb/src/services/MongoDriver.d.ts +83 -0
  161. package/dist/server-mongodb/src/services/MongoDriver.d.ts.map +1 -0
  162. package/dist/server-mongodb/src/services/MongoHistoryService.d.ts +37 -0
  163. package/dist/server-mongodb/src/services/MongoHistoryService.d.ts.map +1 -0
  164. package/dist/server-mongodb/src/services/MongoRealtimeService.d.ts +86 -0
  165. package/dist/server-mongodb/src/services/MongoRealtimeService.d.ts.map +1 -0
  166. package/dist/server-mongodb/src/useMongoDriver.d.ts +18 -0
  167. package/dist/server-mongodb/src/useMongoDriver.d.ts.map +1 -0
  168. package/dist/server-mongodb/src/utils.d.ts +10 -0
  169. package/dist/server-mongodb/src/utils.d.ts.map +1 -0
  170. package/dist/server-mongodb/src/websocket.d.ts +7 -0
  171. package/dist/server-mongodb/src/websocket.d.ts.map +1 -0
  172. package/dist/types/src/controllers/analytics_controller.d.ts +8 -0
  173. package/dist/types/src/controllers/analytics_controller.d.ts.map +1 -0
  174. package/dist/types/src/controllers/auth.d.ts +120 -0
  175. package/dist/types/src/controllers/auth.d.ts.map +1 -0
  176. package/dist/types/src/controllers/client.d.ts +171 -0
  177. package/dist/types/src/controllers/client.d.ts.map +1 -0
  178. package/dist/types/src/controllers/collection_registry.d.ts +46 -0
  179. package/dist/types/src/controllers/collection_registry.d.ts.map +1 -0
  180. package/dist/types/src/controllers/customization_controller.d.ts +61 -0
  181. package/dist/types/src/controllers/customization_controller.d.ts.map +1 -0
  182. package/dist/types/src/controllers/data.d.ts +169 -0
  183. package/dist/types/src/controllers/data.d.ts.map +1 -0
  184. package/dist/types/src/controllers/data_driver.d.ts +161 -0
  185. package/dist/types/src/controllers/data_driver.d.ts.map +1 -0
  186. package/dist/types/src/controllers/database_admin.d.ts +12 -0
  187. package/dist/types/src/controllers/database_admin.d.ts.map +1 -0
  188. package/dist/types/src/controllers/dialogs_controller.d.ts +37 -0
  189. package/dist/types/src/controllers/dialogs_controller.d.ts.map +1 -0
  190. package/dist/types/src/controllers/effective_role.d.ts +5 -0
  191. package/dist/types/src/controllers/effective_role.d.ts.map +1 -0
  192. package/dist/types/src/controllers/email.d.ts +35 -0
  193. package/dist/types/src/controllers/email.d.ts.map +1 -0
  194. package/dist/types/src/controllers/index.d.ts +19 -0
  195. package/dist/types/src/controllers/index.d.ts.map +1 -0
  196. package/dist/types/src/controllers/local_config_persistence.d.ts +21 -0
  197. package/dist/types/src/controllers/local_config_persistence.d.ts.map +1 -0
  198. package/dist/types/src/controllers/navigation.d.ts +214 -0
  199. package/dist/types/src/controllers/navigation.d.ts.map +1 -0
  200. package/dist/types/src/controllers/registry.d.ts +55 -0
  201. package/dist/types/src/controllers/registry.d.ts.map +1 -0
  202. package/dist/types/src/controllers/side_dialogs_controller.d.ts +68 -0
  203. package/dist/types/src/controllers/side_dialogs_controller.d.ts.map +1 -0
  204. package/dist/types/src/controllers/side_entity_controller.d.ts +91 -0
  205. package/dist/types/src/controllers/side_entity_controller.d.ts.map +1 -0
  206. package/dist/types/src/controllers/snackbar.d.ts +25 -0
  207. package/dist/types/src/controllers/snackbar.d.ts.map +1 -0
  208. package/dist/types/src/controllers/storage.d.ts +172 -0
  209. package/dist/types/src/controllers/storage.d.ts.map +1 -0
  210. package/dist/types/src/index.d.ts +5 -0
  211. package/dist/types/src/index.d.ts.map +1 -0
  212. package/dist/types/src/rebase_context.d.ts +106 -0
  213. package/dist/types/src/rebase_context.d.ts.map +1 -0
  214. package/dist/types/src/types/backend.d.ts +537 -0
  215. package/dist/types/src/types/backend.d.ts.map +1 -0
  216. package/dist/types/src/types/builders.d.ts +16 -0
  217. package/dist/types/src/types/builders.d.ts.map +1 -0
  218. package/dist/types/src/types/chips.d.ts +6 -0
  219. package/dist/types/src/types/chips.d.ts.map +1 -0
  220. package/dist/types/src/types/collections.d.ts +857 -0
  221. package/dist/types/src/types/collections.d.ts.map +1 -0
  222. package/dist/types/src/types/cron.d.ts +103 -0
  223. package/dist/types/src/types/cron.d.ts.map +1 -0
  224. package/dist/types/src/types/data_source.d.ts +65 -0
  225. package/dist/types/src/types/data_source.d.ts.map +1 -0
  226. package/dist/types/src/types/entities.d.ts +146 -0
  227. package/dist/types/src/types/entities.d.ts.map +1 -0
  228. package/dist/types/src/types/entity_actions.d.ts +99 -0
  229. package/dist/types/src/types/entity_actions.d.ts.map +1 -0
  230. package/dist/types/src/types/entity_callbacks.d.ts +174 -0
  231. package/dist/types/src/types/entity_callbacks.d.ts.map +1 -0
  232. package/dist/types/src/types/entity_link_builder.d.ts +8 -0
  233. package/dist/types/src/types/entity_link_builder.d.ts.map +1 -0
  234. package/dist/types/src/types/entity_overrides.d.ts +11 -0
  235. package/dist/types/src/types/entity_overrides.d.ts.map +1 -0
  236. package/dist/types/src/types/entity_views.d.ts +62 -0
  237. package/dist/types/src/types/entity_views.d.ts.map +1 -0
  238. package/dist/types/src/types/export_import.d.ts +22 -0
  239. package/dist/types/src/types/export_import.d.ts.map +1 -0
  240. package/dist/types/src/types/index.d.ts +24 -0
  241. package/dist/types/src/types/index.d.ts.map +1 -0
  242. package/dist/types/src/types/locales.d.ts +5 -0
  243. package/dist/types/src/types/locales.d.ts.map +1 -0
  244. package/dist/types/src/types/modify_collections.d.ts +6 -0
  245. package/dist/types/src/types/modify_collections.d.ts.map +1 -0
  246. package/dist/types/src/types/plugins.d.ts +280 -0
  247. package/dist/types/src/types/plugins.d.ts.map +1 -0
  248. package/dist/types/src/types/properties.d.ts +1177 -0
  249. package/dist/types/src/types/properties.d.ts.map +1 -0
  250. package/dist/types/src/types/property_config.d.ts +71 -0
  251. package/dist/types/src/types/property_config.d.ts.map +1 -0
  252. package/dist/types/src/types/relations.d.ts +337 -0
  253. package/dist/types/src/types/relations.d.ts.map +1 -0
  254. package/dist/types/src/types/slots.d.ts +253 -0
  255. package/dist/types/src/types/slots.d.ts.map +1 -0
  256. package/dist/types/src/types/translations.d.ts +871 -0
  257. package/dist/types/src/types/translations.d.ts.map +1 -0
  258. package/dist/types/src/types/user_management_delegate.d.ts +122 -0
  259. package/dist/types/src/types/user_management_delegate.d.ts.map +1 -0
  260. package/dist/types/src/types/websockets.d.ts +79 -0
  261. package/dist/types/src/types/websockets.d.ts.map +1 -0
  262. package/dist/types/src/users/index.d.ts +3 -0
  263. package/dist/types/src/users/index.d.ts.map +1 -0
  264. package/dist/types/src/users/roles.d.ts +23 -0
  265. package/dist/types/src/users/roles.d.ts.map +1 -0
  266. package/dist/types/src/users/user.d.ts +47 -0
  267. package/dist/types/src/users/user.d.ts.map +1 -0
  268. package/dist/websocket-BZlPuJrt.js +220 -0
  269. package/dist/websocket-BZlPuJrt.js.map +1 -0
  270. package/package.json +79 -0
  271. package/src/MongoBootstrapper.ts +177 -0
  272. package/src/auth/ensure-collections.ts +94 -0
  273. package/src/auth/services.ts +638 -0
  274. package/src/connection.ts +60 -0
  275. package/src/db/MongoConditionBuilder.ts +181 -0
  276. package/src/db/MongoEntityService.ts +350 -0
  277. package/src/factory.ts +289 -0
  278. package/src/history/ensure-history-collection.ts +19 -0
  279. package/src/index.ts +25 -0
  280. package/src/services/MongoDriver.ts +297 -0
  281. package/src/services/MongoDriver.ts.backup +266 -0
  282. package/src/services/MongoHistoryService.ts +154 -0
  283. package/src/services/MongoRealtimeService.ts +394 -0
  284. package/src/useMongoDriver.ts +519 -0
  285. package/src/utils.ts +28 -0
  286. package/src/websocket.ts +257 -0
@@ -0,0 +1,266 @@
1
+ /**
2
+ * MongoDB DataDriver Delegate
3
+ *
4
+ * Implements the DataDriver interface for Rebase frontend integration.
5
+ * This is the main entry point for Rebase to interact with MongoDB.
6
+ */
7
+
8
+ import { Db, ObjectId } from "mongodb";
9
+ import {
10
+ DataDriver,
11
+ DeleteEntityProps,
12
+ Entity,
13
+ EntityCollection,
14
+ FetchCollectionProps,
15
+ FetchEntityProps,
16
+ ListenCollectionProps,
17
+ ListenEntityProps,
18
+ SaveEntityProps
19
+ } from "@rebasepro/types";
20
+ import { MongoEntityService } from "../db/MongoEntityService";
21
+ import { MongoRealtimeService } from "./MongoRealtimeService";
22
+
23
+ /**
24
+ * MongoDB DataDriver Delegate
25
+ *
26
+ * Implements the DataDriver interface for Rebase.
27
+ * Provides all data operations needed by the Rebase frontend.
28
+ */
29
+ export class MongoDriver implements DataDriver {
30
+ key = "mongodb";
31
+ initialised = true;
32
+
33
+ private entityService: MongoEntityService;
34
+ private realtimeService: MongoRealtimeService;
35
+
36
+
37
+ constructor(
38
+ private db: Db,
39
+ realtimeService?: MongoRealtimeService
40
+ ) {
41
+ this.entityService = new MongoEntityService(db);
42
+ this.realtimeService = realtimeService ?? new MongoRealtimeService(db);
43
+ }
44
+
45
+
46
+ /**
47
+ * Get the current timestamp
48
+ */
49
+ currentTime(): Date {
50
+ return new Date();
51
+ }
52
+
53
+ /**
54
+ * Fetch a collection of entities
55
+ */
56
+ async fetchCollection<M extends Record<string, any>>({
57
+ path,
58
+ collection,
59
+ filter,
60
+ limit,
61
+ startAfter,
62
+ orderBy,
63
+ searchString,
64
+ order
65
+ }: FetchCollectionProps<M>): Promise<Entity<M>[]> {
66
+ return this.entityService.fetchCollection<M>(path, {
67
+ filter,
68
+ limit,
69
+ startAfter,
70
+ orderBy,
71
+ order,
72
+ searchString,
73
+ collection: collection as unknown as EntityCollection
74
+ });
75
+ }
76
+
77
+ /**
78
+ * Listen to collection changes
79
+ */
80
+ listenCollection<M extends Record<string, any>>({
81
+ path,
82
+ collection,
83
+ filter,
84
+ limit,
85
+ startAfter,
86
+ orderBy,
87
+ searchString,
88
+ order,
89
+ onUpdate,
90
+ onError
91
+ }: ListenCollectionProps<M>): () => void {
92
+ const subscriptionId = this.generateSubscriptionId();
93
+
94
+ const callback = (entities: Entity<any>[]) => {
95
+ try {
96
+ onUpdate(entities as Entity<M>[]);
97
+ } catch (error) {
98
+ console.error("Error in collection update callback:", error);
99
+ if (onError) {
100
+ onError(error instanceof Error ? error : new Error(String(error)));
101
+ }
102
+ }
103
+ };
104
+
105
+ this.realtimeService.subscribeToCollection(
106
+ subscriptionId,
107
+ {
108
+ clientId: "driver",
109
+ path,
110
+ filter,
111
+ orderBy,
112
+ order,
113
+ limit,
114
+ startAfter,
115
+ searchString
116
+ },
117
+ callback
118
+ );
119
+
120
+ // Return unsubscribe function
121
+ return () => {
122
+ this.realtimeService.unsubscribe(subscriptionId);
123
+ };
124
+ }
125
+
126
+ /**
127
+ * Fetch a single entity
128
+ */
129
+ async fetchEntity<M extends Record<string, any>>({
130
+ path,
131
+ entityId,
132
+ databaseId,
133
+ collection
134
+ }: FetchEntityProps<M>): Promise<Entity<M> | undefined> {
135
+ return this.entityService.fetchEntity<M>(path, entityId, databaseId);
136
+ }
137
+
138
+ /**
139
+ * Listen to entity changes
140
+ */
141
+ listenEntity<M extends Record<string, any>>({
142
+ path,
143
+ entityId,
144
+ collection,
145
+ onUpdate,
146
+ onError
147
+ }: ListenEntityProps<M>): () => void {
148
+ const subscriptionId = this.generateSubscriptionId();
149
+
150
+ const callback = (entity: Entity<any> | null) => {
151
+ try {
152
+ onUpdate(entity as Entity<M>);
153
+ } catch (error) {
154
+ console.error("Error in entity update callback:", error);
155
+ if (onError) {
156
+ onError(error instanceof Error ? error : new Error(String(error)));
157
+ }
158
+ }
159
+ };
160
+
161
+ this.realtimeService.subscribeToEntity(
162
+ subscriptionId,
163
+ {
164
+ clientId: "driver",
165
+ path,
166
+ entityId
167
+ },
168
+ callback
169
+ );
170
+
171
+ // Return unsubscribe function
172
+ return () => {
173
+ this.realtimeService.unsubscribe(subscriptionId);
174
+ };
175
+ }
176
+
177
+ /**
178
+ * Save an entity (create or update)
179
+ */
180
+ async saveEntity<M extends Record<string, any>>({
181
+ path,
182
+ entityId,
183
+ values,
184
+ collection,
185
+ status
186
+ }: SaveEntityProps<M>): Promise<Entity<M>> {
187
+ const entity = await this.entityService.saveEntity<M>(path, values, entityId);
188
+
189
+ // Notify subscribers of the update
190
+ await this.realtimeService.notifyEntityUpdate(path, String(entity.id), entity);
191
+
192
+ return entity;
193
+ }
194
+
195
+ /**
196
+ * Delete an entity
197
+ */
198
+ async deleteEntity<M extends Record<string, any>>({
199
+ entity,
200
+ collection
201
+ }: DeleteEntityProps<M>): Promise<void> {
202
+ await this.entityService.deleteEntity(entity.path, entity.id);
203
+
204
+ // Notify subscribers of the deletion
205
+ await this.realtimeService.notifyEntityUpdate(entity.path, String(entity.id), null);
206
+ }
207
+
208
+ /**
209
+ * Check if a field value is unique
210
+ */
211
+ async checkUniqueField(
212
+ path: string,
213
+ name: string,
214
+ value: any,
215
+ entityId?: string,
216
+ collection?: EntityCollection
217
+ ): Promise<boolean> {
218
+ return this.entityService.checkUniqueField(path, name, value, entityId);
219
+ }
220
+
221
+ /**
222
+ * Generate a new entity ID
223
+ */
224
+ generateEntityId(path: string, collection?: EntityCollection): string {
225
+ return this.entityService.generateEntityId();
226
+ }
227
+
228
+ /**
229
+ * Count entities in a collection
230
+ */
231
+ async countEntities<M extends Record<string, any>>({
232
+ path,
233
+ collection,
234
+ filter
235
+ }: FetchCollectionProps<M>): Promise<number> {
236
+ return this.entityService.countEntities<M>(path, { filter });
237
+ }
238
+
239
+ /**
240
+ * Generate a unique subscription ID
241
+ */
242
+ private generateSubscriptionId(): string {
243
+ return `mongo_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
244
+ }
245
+
246
+ /**
247
+ * Check if the delegate is ready
248
+ */
249
+ isReady(): boolean {
250
+ return this.initialised;
251
+ }
252
+
253
+ /**
254
+ * Get the underlying entity service for direct access
255
+ */
256
+ getEntityService(): MongoEntityService {
257
+ return this.entityService;
258
+ }
259
+
260
+ /**
261
+ * Get the underlying realtime service for direct access
262
+ */
263
+ getRealtimeService(): MongoRealtimeService {
264
+ return this.realtimeService;
265
+ }
266
+ }
@@ -0,0 +1,154 @@
1
+ import { Db, ObjectId } from "mongodb";
2
+
3
+ /**
4
+ * Shallow comparison to find top-level keys that changed between two objects.
5
+ */
6
+ export function findChangedFields(
7
+ oldValues: Record<string, unknown>,
8
+ newValues: Record<string, unknown>
9
+ ): string[] | null {
10
+ const changed: string[] = [];
11
+ const allKeys = new Set([
12
+ ...Object.keys(oldValues),
13
+ ...Object.keys(newValues)
14
+ ]);
15
+
16
+ for (const key of allKeys) {
17
+ const oldVal = oldValues[key];
18
+ const newVal = newValues[key];
19
+
20
+ // Skip internal metadata
21
+ if (key.startsWith("__")) continue;
22
+
23
+ if (oldVal !== newVal) {
24
+ // For objects/arrays, use JSON comparison
25
+ if (
26
+ typeof oldVal === "object" && oldVal !== null &&
27
+ typeof newVal === "object" && newVal !== null
28
+ ) {
29
+ if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
30
+ changed.push(key);
31
+ }
32
+ } else {
33
+ changed.push(key);
34
+ }
35
+ }
36
+ }
37
+
38
+ return changed.length > 0 ? changed : null;
39
+ }
40
+
41
+ export interface HistoryEntry {
42
+ _id?: ObjectId;
43
+ id: string;
44
+ table_name: string;
45
+ entity_id: string;
46
+ action: "create" | "update" | "delete";
47
+ changed_fields: string[] | null;
48
+ values: Record<string, unknown> | null;
49
+ previous_values: Record<string, unknown> | null;
50
+ updated_by: string | null;
51
+ updated_at: Date;
52
+ }
53
+
54
+ export interface RecordHistoryParams {
55
+ tableName: string;
56
+ entityId: string;
57
+ action: "create" | "update" | "delete";
58
+ values?: Record<string, unknown> | null;
59
+ previousValues?: Record<string, unknown> | null;
60
+ updatedBy?: string | null;
61
+ }
62
+
63
+ export interface HistoryRetentionConfig {
64
+ maxEntries: number;
65
+ ttlDays: number;
66
+ }
67
+
68
+ const DEFAULT_RETENTION: HistoryRetentionConfig = {
69
+ maxEntries: 200,
70
+ ttlDays: 90
71
+ };
72
+
73
+ export class MongoHistoryService {
74
+ public retention: HistoryRetentionConfig;
75
+
76
+ constructor(
77
+ private db: Db,
78
+ retention?: Partial<HistoryRetentionConfig>
79
+ ) {
80
+ this.retention = { ...DEFAULT_RETENTION, ...retention };
81
+ }
82
+
83
+ async recordHistory(params: RecordHistoryParams): Promise<void> {
84
+ const {
85
+ tableName,
86
+ entityId,
87
+ action,
88
+ values,
89
+ previousValues,
90
+ updatedBy
91
+ } = params;
92
+
93
+ const changedFields = previousValues && values
94
+ ? findChangedFields(previousValues, values)
95
+ : null;
96
+
97
+ if (action === "update" && (!changedFields || changedFields.length === 0)) {
98
+ return;
99
+ }
100
+
101
+ try {
102
+ const entry: HistoryEntry = {
103
+ id: new ObjectId().toString(),
104
+ table_name: tableName,
105
+ entity_id: String(entityId),
106
+ action,
107
+ changed_fields: changedFields,
108
+ values: values || null,
109
+ previous_values: previousValues || null,
110
+ updated_by: updatedBy || null,
111
+ updated_at: new Date()
112
+ };
113
+
114
+ await this.db.collection("__rebase_history").insertOne(entry);
115
+
116
+ // Non-blocking prune for this specific entity
117
+ this.pruneHistory(String(entityId), tableName).catch(e => {
118
+ console.error(`[HistoryService] Failed to prune history for ${tableName}/${entityId}:`, e);
119
+ });
120
+ } catch (error) {
121
+ console.error(`[HistoryService] Failed to record history for ${tableName}/${entityId}:`, error);
122
+ }
123
+ }
124
+
125
+ private async pruneHistory(entityId: string, tableName: string): Promise<void> {
126
+ const collection = this.db.collection("__rebase_history");
127
+
128
+ // 1. Enforce maxEntries
129
+ const count = await collection.countDocuments({ entity_id: entityId, table_name: tableName });
130
+ if (count > this.retention.maxEntries) {
131
+ const toDelete = count - this.retention.maxEntries;
132
+ const oldestEntries = await collection
133
+ .find({ entity_id: entityId, table_name: tableName })
134
+ .sort({ updated_at: 1 })
135
+ .limit(toDelete)
136
+ .toArray();
137
+
138
+ if (oldestEntries.length > 0) {
139
+ const idsToDelete = oldestEntries.map(entry => entry._id);
140
+ await collection.deleteMany({ _id: { $in: idsToDelete } });
141
+ }
142
+ }
143
+
144
+ // 2. Enforce ttlDays
145
+ const cutoffDate = new Date();
146
+ cutoffDate.setDate(cutoffDate.getDate() - this.retention.ttlDays);
147
+
148
+ await collection.deleteMany({
149
+ entity_id: entityId,
150
+ table_name: tableName,
151
+ updated_at: { $lt: cutoffDate }
152
+ });
153
+ }
154
+ }