@rebasepro/server-core 0.0.1-canary.000dc36

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 (305) hide show
  1. package/LICENSE +6 -0
  2. package/README.md +40 -0
  3. package/build-errors.txt +52 -0
  4. package/coverage/clover.xml +3739 -0
  5. package/coverage/coverage-final.json +31 -0
  6. package/coverage/lcov-report/base.css +224 -0
  7. package/coverage/lcov-report/block-navigation.js +87 -0
  8. package/coverage/lcov-report/favicon.png +0 -0
  9. package/coverage/lcov-report/index.html +266 -0
  10. package/coverage/lcov-report/prettify.css +1 -0
  11. package/coverage/lcov-report/prettify.js +2 -0
  12. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  13. package/coverage/lcov-report/sorter.js +210 -0
  14. package/coverage/lcov-report/src/api/ast-schema-editor.ts.html +952 -0
  15. package/coverage/lcov-report/src/api/errors.ts.html +472 -0
  16. package/coverage/lcov-report/src/api/graphql/graphql-schema-generator.ts.html +1069 -0
  17. package/coverage/lcov-report/src/api/graphql/index.html +116 -0
  18. package/coverage/lcov-report/src/api/index.html +176 -0
  19. package/coverage/lcov-report/src/api/openapi-generator.ts.html +565 -0
  20. package/coverage/lcov-report/src/api/rest/api-generator.ts.html +994 -0
  21. package/coverage/lcov-report/src/api/rest/index.html +131 -0
  22. package/coverage/lcov-report/src/api/rest/query-parser.ts.html +550 -0
  23. package/coverage/lcov-report/src/api/schema-editor-routes.ts.html +202 -0
  24. package/coverage/lcov-report/src/api/server.ts.html +823 -0
  25. package/coverage/lcov-report/src/auth/admin-routes.ts.html +973 -0
  26. package/coverage/lcov-report/src/auth/index.html +176 -0
  27. package/coverage/lcov-report/src/auth/jwt.ts.html +574 -0
  28. package/coverage/lcov-report/src/auth/middleware.ts.html +745 -0
  29. package/coverage/lcov-report/src/auth/password.ts.html +310 -0
  30. package/coverage/lcov-report/src/auth/services.ts.html +2074 -0
  31. package/coverage/lcov-report/src/collections/index.html +116 -0
  32. package/coverage/lcov-report/src/collections/loader.ts.html +232 -0
  33. package/coverage/lcov-report/src/db/auth-schema.ts.html +523 -0
  34. package/coverage/lcov-report/src/db/data-transformer.ts.html +1753 -0
  35. package/coverage/lcov-report/src/db/entityService.ts.html +700 -0
  36. package/coverage/lcov-report/src/db/index.html +146 -0
  37. package/coverage/lcov-report/src/db/services/EntityFetchService.ts.html +4048 -0
  38. package/coverage/lcov-report/src/db/services/EntityPersistService.ts.html +883 -0
  39. package/coverage/lcov-report/src/db/services/RelationService.ts.html +3121 -0
  40. package/coverage/lcov-report/src/db/services/entity-helpers.ts.html +442 -0
  41. package/coverage/lcov-report/src/db/services/index.html +176 -0
  42. package/coverage/lcov-report/src/db/services/index.ts.html +124 -0
  43. package/coverage/lcov-report/src/generate-drizzle-schema-logic.ts.html +1960 -0
  44. package/coverage/lcov-report/src/index.html +116 -0
  45. package/coverage/lcov-report/src/services/driver-registry.ts.html +631 -0
  46. package/coverage/lcov-report/src/services/index.html +131 -0
  47. package/coverage/lcov-report/src/services/postgresDataDriver.ts.html +3025 -0
  48. package/coverage/lcov-report/src/storage/LocalStorageController.ts.html +1189 -0
  49. package/coverage/lcov-report/src/storage/S3StorageController.ts.html +970 -0
  50. package/coverage/lcov-report/src/storage/index.html +161 -0
  51. package/coverage/lcov-report/src/storage/storage-registry.ts.html +646 -0
  52. package/coverage/lcov-report/src/storage/types.ts.html +451 -0
  53. package/coverage/lcov-report/src/utils/drizzle-conditions.ts.html +3082 -0
  54. package/coverage/lcov-report/src/utils/index.html +116 -0
  55. package/coverage/lcov.info +7179 -0
  56. package/dist/common/src/collections/CollectionRegistry.d.ts +56 -0
  57. package/dist/common/src/collections/index.d.ts +1 -0
  58. package/dist/common/src/data/buildRebaseData.d.ts +14 -0
  59. package/dist/common/src/index.d.ts +3 -0
  60. package/dist/common/src/util/builders.d.ts +57 -0
  61. package/dist/common/src/util/callbacks.d.ts +6 -0
  62. package/dist/common/src/util/collections.d.ts +11 -0
  63. package/dist/common/src/util/common.d.ts +2 -0
  64. package/dist/common/src/util/conditions.d.ts +26 -0
  65. package/dist/common/src/util/entities.d.ts +58 -0
  66. package/dist/common/src/util/enums.d.ts +3 -0
  67. package/dist/common/src/util/index.d.ts +16 -0
  68. package/dist/common/src/util/navigation_from_path.d.ts +34 -0
  69. package/dist/common/src/util/navigation_utils.d.ts +20 -0
  70. package/dist/common/src/util/parent_references_from_path.d.ts +6 -0
  71. package/dist/common/src/util/paths.d.ts +14 -0
  72. package/dist/common/src/util/permissions.d.ts +5 -0
  73. package/dist/common/src/util/references.d.ts +2 -0
  74. package/dist/common/src/util/relations.d.ts +22 -0
  75. package/dist/common/src/util/resolutions.d.ts +72 -0
  76. package/dist/common/src/util/storage.d.ts +24 -0
  77. package/dist/index-DXVBFp5V.js +37 -0
  78. package/dist/index-DXVBFp5V.js.map +1 -0
  79. package/dist/index.es.js +49249 -0
  80. package/dist/index.es.js.map +1 -0
  81. package/dist/index.umd.js +49283 -0
  82. package/dist/index.umd.js.map +1 -0
  83. package/dist/server-core/src/api/ast-schema-editor.d.ts +21 -0
  84. package/dist/server-core/src/api/collections_for_test/callbacks_test_collection.d.ts +2 -0
  85. package/dist/server-core/src/api/errors.d.ts +35 -0
  86. package/dist/server-core/src/api/graphql/graphql-schema-generator.d.ts +35 -0
  87. package/dist/server-core/src/api/graphql/index.d.ts +1 -0
  88. package/dist/server-core/src/api/index.d.ts +9 -0
  89. package/dist/server-core/src/api/openapi-generator.d.ts +16 -0
  90. package/dist/server-core/src/api/rest/api-generator.d.ts +76 -0
  91. package/dist/server-core/src/api/rest/index.d.ts +1 -0
  92. package/dist/server-core/src/api/rest/query-parser.d.ts +9 -0
  93. package/dist/server-core/src/api/schema-editor-routes.d.ts +3 -0
  94. package/dist/server-core/src/api/server.d.ts +40 -0
  95. package/dist/server-core/src/api/types.d.ts +90 -0
  96. package/dist/server-core/src/auth/admin-routes.d.ts +21 -0
  97. package/dist/server-core/src/auth/apple-oauth.d.ts +30 -0
  98. package/dist/server-core/src/auth/bitbucket-oauth.d.ts +11 -0
  99. package/dist/server-core/src/auth/discord-oauth.d.ts +14 -0
  100. package/dist/server-core/src/auth/facebook-oauth.d.ts +14 -0
  101. package/dist/server-core/src/auth/github-oauth.d.ts +15 -0
  102. package/dist/server-core/src/auth/gitlab-oauth.d.ts +13 -0
  103. package/dist/server-core/src/auth/google-oauth.d.ts +14 -0
  104. package/dist/server-core/src/auth/index.d.ts +23 -0
  105. package/dist/server-core/src/auth/interfaces.d.ts +309 -0
  106. package/dist/server-core/src/auth/jwt.d.ts +43 -0
  107. package/dist/server-core/src/auth/linkedin-oauth.d.ts +18 -0
  108. package/dist/server-core/src/auth/microsoft-oauth.d.ts +16 -0
  109. package/dist/server-core/src/auth/middleware.d.ts +81 -0
  110. package/dist/server-core/src/auth/password.d.ts +22 -0
  111. package/dist/server-core/src/auth/rate-limiter.d.ts +31 -0
  112. package/dist/server-core/src/auth/routes.d.ts +27 -0
  113. package/dist/server-core/src/auth/slack-oauth.d.ts +12 -0
  114. package/dist/server-core/src/auth/spotify-oauth.d.ts +12 -0
  115. package/dist/server-core/src/auth/twitter-oauth.d.ts +18 -0
  116. package/dist/server-core/src/bootstrappers/index.d.ts +0 -0
  117. package/dist/server-core/src/collections/BackendCollectionRegistry.d.ts +13 -0
  118. package/dist/server-core/src/collections/loader.d.ts +5 -0
  119. package/dist/server-core/src/cron/cron-loader.d.ts +17 -0
  120. package/dist/server-core/src/cron/cron-routes.d.ts +14 -0
  121. package/dist/server-core/src/cron/cron-scheduler.d.ts +106 -0
  122. package/dist/server-core/src/cron/cron-store.d.ts +32 -0
  123. package/dist/server-core/src/cron/index.d.ts +6 -0
  124. package/dist/server-core/src/db/interfaces.d.ts +18 -0
  125. package/dist/server-core/src/email/index.d.ts +6 -0
  126. package/dist/server-core/src/email/smtp-email-service.d.ts +25 -0
  127. package/dist/server-core/src/email/templates.d.ts +42 -0
  128. package/dist/server-core/src/email/types.d.ts +107 -0
  129. package/dist/server-core/src/functions/function-loader.d.ts +17 -0
  130. package/dist/server-core/src/functions/function-routes.d.ts +10 -0
  131. package/dist/server-core/src/functions/index.d.ts +3 -0
  132. package/dist/server-core/src/history/history-routes.d.ts +23 -0
  133. package/dist/server-core/src/history/index.d.ts +1 -0
  134. package/dist/server-core/src/index.d.ts +29 -0
  135. package/dist/server-core/src/init.d.ts +168 -0
  136. package/dist/server-core/src/serve-spa.d.ts +30 -0
  137. package/dist/server-core/src/services/driver-registry.d.ts +78 -0
  138. package/dist/server-core/src/singleton.d.ts +35 -0
  139. package/dist/server-core/src/storage/LocalStorageController.d.ts +46 -0
  140. package/dist/server-core/src/storage/S3StorageController.d.ts +36 -0
  141. package/dist/server-core/src/storage/index.d.ts +25 -0
  142. package/dist/server-core/src/storage/routes.d.ts +38 -0
  143. package/dist/server-core/src/storage/storage-registry.d.ts +78 -0
  144. package/dist/server-core/src/storage/types.d.ts +103 -0
  145. package/dist/server-core/src/types/index.d.ts +11 -0
  146. package/dist/server-core/src/utils/dev-port.d.ts +35 -0
  147. package/dist/server-core/src/utils/logger.d.ts +31 -0
  148. package/dist/server-core/src/utils/logging.d.ts +9 -0
  149. package/dist/server-core/src/utils/request-logger.d.ts +19 -0
  150. package/dist/server-core/src/utils/sql.d.ts +27 -0
  151. package/dist/types/src/controllers/analytics_controller.d.ts +7 -0
  152. package/dist/types/src/controllers/auth.d.ts +119 -0
  153. package/dist/types/src/controllers/client.d.ts +170 -0
  154. package/dist/types/src/controllers/collection_registry.d.ts +46 -0
  155. package/dist/types/src/controllers/customization_controller.d.ts +60 -0
  156. package/dist/types/src/controllers/data.d.ts +168 -0
  157. package/dist/types/src/controllers/data_driver.d.ts +195 -0
  158. package/dist/types/src/controllers/database_admin.d.ts +11 -0
  159. package/dist/types/src/controllers/dialogs_controller.d.ts +36 -0
  160. package/dist/types/src/controllers/effective_role.d.ts +4 -0
  161. package/dist/types/src/controllers/email.d.ts +34 -0
  162. package/dist/types/src/controllers/index.d.ts +18 -0
  163. package/dist/types/src/controllers/local_config_persistence.d.ts +20 -0
  164. package/dist/types/src/controllers/navigation.d.ts +213 -0
  165. package/dist/types/src/controllers/registry.d.ts +54 -0
  166. package/dist/types/src/controllers/side_dialogs_controller.d.ts +67 -0
  167. package/dist/types/src/controllers/side_entity_controller.d.ts +90 -0
  168. package/dist/types/src/controllers/snackbar.d.ts +24 -0
  169. package/dist/types/src/controllers/storage.d.ts +171 -0
  170. package/dist/types/src/index.d.ts +4 -0
  171. package/dist/types/src/rebase_context.d.ts +105 -0
  172. package/dist/types/src/types/backend.d.ts +536 -0
  173. package/dist/types/src/types/backend_hooks.d.ts +187 -0
  174. package/dist/types/src/types/builders.d.ts +15 -0
  175. package/dist/types/src/types/chips.d.ts +5 -0
  176. package/dist/types/src/types/collections.d.ts +857 -0
  177. package/dist/types/src/types/cron.d.ts +102 -0
  178. package/dist/types/src/types/data_source.d.ts +64 -0
  179. package/dist/types/src/types/entities.d.ts +145 -0
  180. package/dist/types/src/types/entity_actions.d.ts +98 -0
  181. package/dist/types/src/types/entity_callbacks.d.ts +173 -0
  182. package/dist/types/src/types/entity_link_builder.d.ts +7 -0
  183. package/dist/types/src/types/entity_overrides.d.ts +10 -0
  184. package/dist/types/src/types/entity_views.d.ts +59 -0
  185. package/dist/types/src/types/export_import.d.ts +21 -0
  186. package/dist/types/src/types/formex.d.ts +40 -0
  187. package/dist/types/src/types/index.d.ts +25 -0
  188. package/dist/types/src/types/locales.d.ts +4 -0
  189. package/dist/types/src/types/modify_collections.d.ts +5 -0
  190. package/dist/types/src/types/plugins.d.ts +282 -0
  191. package/dist/types/src/types/properties.d.ts +1148 -0
  192. package/dist/types/src/types/property_config.d.ts +70 -0
  193. package/dist/types/src/types/relations.d.ts +336 -0
  194. package/dist/types/src/types/slots.d.ts +262 -0
  195. package/dist/types/src/types/translations.d.ts +874 -0
  196. package/dist/types/src/types/user_management_delegate.d.ts +121 -0
  197. package/dist/types/src/types/websockets.d.ts +78 -0
  198. package/dist/types/src/users/index.d.ts +2 -0
  199. package/dist/types/src/users/roles.d.ts +22 -0
  200. package/dist/types/src/users/user.d.ts +46 -0
  201. package/history_diff.log +385 -0
  202. package/jest.config.cjs +16 -0
  203. package/package.json +86 -0
  204. package/scratch.ts +9 -0
  205. package/src/api/ast-schema-editor.ts +289 -0
  206. package/src/api/collections_for_test/callbacks_test_collection.ts +60 -0
  207. package/src/api/errors.ts +179 -0
  208. package/src/api/graphql/graphql-schema-generator.ts +336 -0
  209. package/src/api/graphql/index.ts +2 -0
  210. package/src/api/index.ts +11 -0
  211. package/src/api/openapi-generator.ts +715 -0
  212. package/src/api/rest/api-generator-count.test.ts +113 -0
  213. package/src/api/rest/api-generator.ts +573 -0
  214. package/src/api/rest/index.ts +2 -0
  215. package/src/api/rest/query-parser.ts +155 -0
  216. package/src/api/schema-editor-routes.ts +41 -0
  217. package/src/api/server.ts +249 -0
  218. package/src/api/types.ts +90 -0
  219. package/src/auth/admin-routes.ts +605 -0
  220. package/src/auth/apple-oauth.ts +120 -0
  221. package/src/auth/bitbucket-oauth.ts +82 -0
  222. package/src/auth/discord-oauth.ts +83 -0
  223. package/src/auth/facebook-oauth.ts +72 -0
  224. package/src/auth/github-oauth.ts +110 -0
  225. package/src/auth/gitlab-oauth.ts +70 -0
  226. package/src/auth/google-oauth.ts +48 -0
  227. package/src/auth/index.ts +34 -0
  228. package/src/auth/interfaces.ts +363 -0
  229. package/src/auth/jwt.ts +181 -0
  230. package/src/auth/linkedin-oauth.ts +81 -0
  231. package/src/auth/microsoft-oauth.ts +88 -0
  232. package/src/auth/middleware.ts +384 -0
  233. package/src/auth/password.ts +77 -0
  234. package/src/auth/rate-limiter.ts +133 -0
  235. package/src/auth/routes.ts +788 -0
  236. package/src/auth/slack-oauth.ts +71 -0
  237. package/src/auth/spotify-oauth.ts +67 -0
  238. package/src/auth/twitter-oauth.ts +120 -0
  239. package/src/bootstrappers/index.ts +1 -0
  240. package/src/collections/BackendCollectionRegistry.ts +20 -0
  241. package/src/collections/loader.ts +49 -0
  242. package/src/cron/cron-loader.ts +89 -0
  243. package/src/cron/cron-routes.test.ts +265 -0
  244. package/src/cron/cron-routes.ts +85 -0
  245. package/src/cron/cron-scheduler.test.ts +547 -0
  246. package/src/cron/cron-scheduler.ts +576 -0
  247. package/src/cron/cron-store.ts +163 -0
  248. package/src/cron/index.ts +6 -0
  249. package/src/db/interfaces.ts +60 -0
  250. package/src/email/index.ts +18 -0
  251. package/src/email/smtp-email-service.ts +91 -0
  252. package/src/email/templates.ts +388 -0
  253. package/src/email/types.ts +105 -0
  254. package/src/functions/function-loader.ts +119 -0
  255. package/src/functions/function-routes.ts +31 -0
  256. package/src/functions/index.ts +3 -0
  257. package/src/history/history-routes.ts +129 -0
  258. package/src/history/index.ts +2 -0
  259. package/src/index.ts +66 -0
  260. package/src/init.ts +737 -0
  261. package/src/serve-spa.ts +81 -0
  262. package/src/services/driver-registry.ts +182 -0
  263. package/src/singleton.test.ts +28 -0
  264. package/src/singleton.ts +70 -0
  265. package/src/storage/LocalStorageController.ts +365 -0
  266. package/src/storage/S3StorageController.ts +298 -0
  267. package/src/storage/index.ts +43 -0
  268. package/src/storage/routes.ts +264 -0
  269. package/src/storage/storage-registry.ts +187 -0
  270. package/src/storage/types.ts +134 -0
  271. package/src/types/index.ts +27 -0
  272. package/src/utils/dev-port.ts +176 -0
  273. package/src/utils/logger.ts +143 -0
  274. package/src/utils/logging.ts +38 -0
  275. package/src/utils/request-logger.ts +66 -0
  276. package/src/utils/sql.ts +38 -0
  277. package/test/admin-routes.test.ts +640 -0
  278. package/test/api-generator.test.ts +501 -0
  279. package/test/ast-schema-editor.test.ts +63 -0
  280. package/test/auth-middleware-hono.test.ts +556 -0
  281. package/test/auth-routes.test.ts +1047 -0
  282. package/test/backend-hooks-admin.test.ts +394 -0
  283. package/test/backend-hooks-data.test.ts +408 -0
  284. package/test/driver-registry.test.ts +282 -0
  285. package/test/error-propagation.test.ts +226 -0
  286. package/test/errors-hono.test.ts +133 -0
  287. package/test/errors.test.ts +155 -0
  288. package/test/jwt-security.test.ts +182 -0
  289. package/test/jwt.test.ts +324 -0
  290. package/test/middleware.test.ts +300 -0
  291. package/test/password.test.ts +165 -0
  292. package/test/query-parser.test.ts +263 -0
  293. package/test/rate-limiter.test.ts +102 -0
  294. package/test/safe-compare.test.ts +66 -0
  295. package/test/singleton.test.ts +59 -0
  296. package/test/storage-local.test.ts +271 -0
  297. package/test/storage-registry.test.ts +282 -0
  298. package/test/storage-routes.test.ts +222 -0
  299. package/test/storage-s3.test.ts +304 -0
  300. package/test-ast.ts +28 -0
  301. package/test.ts +6 -0
  302. package/test_output.txt +1133 -0
  303. package/tsconfig.json +49 -0
  304. package/tsconfig.prod.json +20 -0
  305. package/vite.config.ts +80 -0
@@ -0,0 +1,163 @@
1
+ import type { CronJobLogEntry } from "@rebasepro/types";
2
+ import type { DataDriver } from "@rebasepro/types";
3
+ import { isSQLAdmin } from "@rebasepro/types";
4
+
5
+ /**
6
+ * Persistence layer for cron job execution logs.
7
+ *
8
+ * Uses the DataDriver's `admin.executeSql` capability to store logs in a
9
+ * `rebase.cron_logs` table. Falls back gracefully if the driver doesn't
10
+ * support SQL (e.g. MongoDB) — in that case, no persistence occurs.
11
+ */
12
+ export interface CronStore {
13
+ /** Ensure the backing table exists. Called once on startup. */
14
+ ensureTable(): Promise<void>;
15
+
16
+ /** Persist a single log entry after execution. */
17
+ insertLog(entry: CronJobLogEntry): Promise<void>;
18
+
19
+ /**
20
+ * Fetch the most recent logs for a job.
21
+ * @param jobId The job identifier
22
+ * @param limit Max entries to return (default 50)
23
+ * @returns Logs sorted newest-first
24
+ */
25
+ fetchLogs(jobId: string, limit?: number): Promise<CronJobLogEntry[]>;
26
+
27
+ /**
28
+ * Fetch aggregate stats for all jobs (totalRuns, totalFailures, lastRunAt).
29
+ * Used to seed in-memory counters on startup.
30
+ */
31
+ fetchJobStats(): Promise<Map<string, { totalRuns: number; totalFailures: number; lastRunAt?: string }>>;
32
+ }
33
+
34
+ // ─── SQL-based implementation ────────────────────────────────────────
35
+
36
+ const TABLE = "rebase.cron_logs";
37
+
38
+ export function createCronStore(driver: DataDriver): CronStore | undefined {
39
+ const admin = driver.admin;
40
+ if (!isSQLAdmin(admin)) {
41
+ console.warn("⚠️ [cron-store] DataDriver does not support SQL admin — cron logs will not be persisted.");
42
+ return undefined;
43
+ }
44
+
45
+ const exec = admin.executeSql.bind(admin);
46
+
47
+ return {
48
+ async ensureTable(): Promise<void> {
49
+ try {
50
+ await exec("CREATE SCHEMA IF NOT EXISTS rebase");
51
+ await exec(`
52
+ CREATE TABLE IF NOT EXISTS ${TABLE} (
53
+ id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
54
+ job_id TEXT NOT NULL,
55
+ started_at TIMESTAMPTZ NOT NULL,
56
+ finished_at TIMESTAMPTZ NOT NULL,
57
+ duration_ms INTEGER NOT NULL,
58
+ success BOOLEAN NOT NULL DEFAULT true,
59
+ error TEXT,
60
+ result JSONB,
61
+ logs JSONB,
62
+ manual BOOLEAN NOT NULL DEFAULT false
63
+ )
64
+ `);
65
+
66
+ await exec(`
67
+ CREATE INDEX IF NOT EXISTS idx_cron_logs_job
68
+ ON ${TABLE}(job_id, started_at DESC)
69
+ `);
70
+
71
+ console.log("✅ Cron logs table ready");
72
+ } catch (err) {
73
+ console.error("❌ Failed to create cron logs table:", err);
74
+ console.warn("⚠️ Continuing without cron log persistence.");
75
+ }
76
+ },
77
+
78
+ async insertLog(entry: CronJobLogEntry): Promise<void> {
79
+ try {
80
+ const resultJson = entry.result !== undefined ? JSON.stringify(entry.result) : null;
81
+ const logsJson = entry.logs.length > 0 ? JSON.stringify(entry.logs) : null;
82
+ const errorEscaped = entry.error ? entry.error.replace(/'/g, "''") : null;
83
+
84
+ await exec(`
85
+ INSERT INTO ${TABLE} (job_id, started_at, finished_at, duration_ms, success, error, result, logs, manual)
86
+ VALUES (
87
+ '${entry.jobId}',
88
+ '${entry.startedAt}',
89
+ '${entry.finishedAt}',
90
+ ${entry.durationMs},
91
+ ${entry.success},
92
+ ${errorEscaped ? `'${errorEscaped}'` : "NULL"},
93
+ ${resultJson ? `'${resultJson.replace(/'/g, "''")}'::jsonb` : "NULL"},
94
+ ${logsJson ? `'${logsJson.replace(/'/g, "''")}'::jsonb` : "NULL"},
95
+ ${entry.manual}
96
+ )
97
+ `);
98
+ } catch (err) {
99
+ // Non-blocking — log persistence should never crash the scheduler
100
+ console.error(`[cron-store] Failed to persist log for "${entry.jobId}":`, err);
101
+ }
102
+ },
103
+
104
+ async fetchLogs(jobId: string, limit = 50): Promise<CronJobLogEntry[]> {
105
+ try {
106
+ const rows = await exec(`
107
+ SELECT job_id, started_at, finished_at, duration_ms, success, error, result, logs, manual
108
+ FROM ${TABLE}
109
+ WHERE job_id = '${jobId}'
110
+ ORDER BY started_at DESC
111
+ LIMIT ${limit}
112
+ `);
113
+
114
+ return rows.map(rowToLogEntry);
115
+ } catch (err) {
116
+ console.error(`[cron-store] Failed to fetch logs for "${jobId}":`, err);
117
+ return [];
118
+ }
119
+ },
120
+
121
+ async fetchJobStats(): Promise<Map<string, { totalRuns: number; totalFailures: number; lastRunAt?: string }>> {
122
+ const stats = new Map<string, { totalRuns: number; totalFailures: number; lastRunAt?: string }>();
123
+ try {
124
+ const rows = await exec(`
125
+ SELECT
126
+ job_id,
127
+ COUNT(*)::int AS total_runs,
128
+ COUNT(*) FILTER (WHERE NOT success)::int AS total_failures,
129
+ MAX(started_at) AS last_run_at
130
+ FROM ${TABLE}
131
+ GROUP BY job_id
132
+ `);
133
+
134
+ for (const row of rows) {
135
+ stats.set(row.job_id as string, {
136
+ totalRuns: row.total_runs as number,
137
+ totalFailures: row.total_failures as number,
138
+ lastRunAt: row.last_run_at ? new Date(row.last_run_at as string).toISOString() : undefined
139
+ });
140
+ }
141
+ } catch (err) {
142
+ console.error("[cron-store] Failed to fetch job stats:", err);
143
+ }
144
+ return stats;
145
+ }
146
+ };
147
+ }
148
+
149
+ // ─── Helpers ─────────────────────────────────────────────────────────
150
+
151
+ function rowToLogEntry(row: Record<string, unknown>): CronJobLogEntry {
152
+ return {
153
+ jobId: row.job_id as string,
154
+ startedAt: new Date(row.started_at as string).toISOString(),
155
+ finishedAt: new Date(row.finished_at as string).toISOString(),
156
+ durationMs: row.duration_ms as number,
157
+ success: row.success as boolean,
158
+ error: (row.error as string) ?? undefined,
159
+ result: row.result ?? undefined,
160
+ logs: Array.isArray(row.logs) ? row.logs : (row.logs ? JSON.parse(row.logs as string) : []),
161
+ manual: row.manual as boolean
162
+ };
163
+ }
@@ -0,0 +1,6 @@
1
+ export { loadCronJobsFromDirectory } from "./cron-loader";
2
+ export type { LoadedCronJob } from "./cron-loader";
3
+ export { CronScheduler, validateCronExpression } from "./cron-scheduler";
4
+ export { createCronRoutes } from "./cron-routes";
5
+ export { createCronStore } from "./cron-store";
6
+ export type { CronStore } from "./cron-store";
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Database Abstraction Interfaces
3
+ *
4
+ * These interfaces define the contracts that any database backend must implement
5
+ * to be used with Rebase. This allows for pluggable database backends like
6
+ * PostgreSQL, MongoDB, MySQL, etc.
7
+ */
8
+
9
+ import {
10
+ Entity,
11
+ EntityCollection,
12
+ FilterValues,
13
+ WhereFilterOp,
14
+ DatabaseConnection,
15
+ QueryFilter,
16
+ FetchCollectionOptions,
17
+ SearchOptions,
18
+ CountOptions,
19
+ ConditionBuilder,
20
+ ConditionBuilderStatic,
21
+ EntityRepository,
22
+ CollectionSubscriptionConfig,
23
+ EntitySubscriptionConfig,
24
+ RealtimeProvider,
25
+ CollectionRegistryInterface,
26
+ DataTransformer,
27
+ BackendConfig,
28
+ BackendInstance,
29
+ BackendFactory
30
+ } from "@rebasepro/types";
31
+ import { NodePgDatabase } from "drizzle-orm/node-postgres";
32
+ import { PgTransaction } from "drizzle-orm/pg-core";
33
+
34
+ /**
35
+ * Type representing either a direct database connection or a transaction.
36
+ * Used to allow services to operate within a transaction context.
37
+ * Note: `any` is intentional here — it represents a Drizzle client with
38
+ * a dynamic schema, enabling `db.query[tableName]` access without casts.
39
+ */
40
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
+ export type DrizzleClient = NodePgDatabase<Record<string, unknown>> | PgTransaction<any, any, any>;
42
+
43
+ export type {
44
+ DatabaseConnection,
45
+ QueryFilter,
46
+ FetchCollectionOptions,
47
+ SearchOptions,
48
+ CountOptions,
49
+ ConditionBuilder,
50
+ ConditionBuilderStatic,
51
+ EntityRepository,
52
+ CollectionSubscriptionConfig,
53
+ EntitySubscriptionConfig,
54
+ RealtimeProvider,
55
+ CollectionRegistryInterface,
56
+ DataTransformer,
57
+ BackendConfig,
58
+ BackendInstance,
59
+ BackendFactory
60
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Email module exports
3
+ */
4
+
5
+ export type {
6
+ EmailService,
7
+ EmailSendOptions,
8
+ SMTPConfig,
9
+ EmailConfig,
10
+ PasswordResetTemplateFunction,
11
+ EmailVerificationTemplateFunction,
12
+ UserInvitationTemplateFunction,
13
+ WelcomeEmailTemplateFunction
14
+ } from "./types";
15
+
16
+ export { SMTPEmailService, createEmailService } from "./smtp-email-service";
17
+
18
+ export { getPasswordResetTemplate, getEmailVerificationTemplate, getUserInvitationTemplate, getWelcomeEmailTemplate } from "./templates";
@@ -0,0 +1,91 @@
1
+ import { createTransport, Transporter } from "nodemailer";
2
+ import { EmailService, EmailSendOptions, EmailConfig } from "./types";
3
+
4
+ /**
5
+ * SMTP Email Service implementation using Nodemailer
6
+ */
7
+ export class SMTPEmailService implements EmailService {
8
+ private transporter: Transporter | null = null;
9
+ private config: EmailConfig;
10
+
11
+ constructor(config: EmailConfig) {
12
+ this.config = config;
13
+
14
+ if (config.smtp) {
15
+ this.transporter = createTransport({
16
+ host: config.smtp.host,
17
+ port: config.smtp.port,
18
+ secure: config.smtp.secure ?? (config.smtp.port === 465),
19
+ auth: config.smtp.auth ? {
20
+ user: config.smtp.auth.user,
21
+ pass: config.smtp.auth.pass
22
+ } : undefined
23
+ });
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Check if the email service is properly configured
29
+ */
30
+ isConfigured(): boolean {
31
+ return !!(this.transporter || this.config.sendEmail);
32
+ }
33
+
34
+ /**
35
+ * Send an email using SMTP or custom send function
36
+ */
37
+ async send(options: EmailSendOptions): Promise<void> {
38
+ // Use custom send function if provided
39
+ if (this.config.sendEmail) {
40
+ await this.config.sendEmail(options);
41
+ return;
42
+ }
43
+
44
+ // Use SMTP transporter
45
+ if (!this.transporter) {
46
+ throw new Error("Email service not configured. Provide SMTP config or sendEmail function.");
47
+ }
48
+
49
+ const to = Array.isArray(options.to) ? options.to.join(", ") : options.to;
50
+
51
+ try {
52
+ await this.transporter.sendMail({
53
+ from: this.config.from,
54
+ to,
55
+ subject: options.subject,
56
+ html: options.html,
57
+ text: options.text,
58
+ replyTo: options.replyTo
59
+ });
60
+ } catch (error: unknown) {
61
+ const message = error instanceof Error ? error.message : String(error);
62
+ console.error("Failed to send email:", message);
63
+ throw new Error(`Failed to send email: ${message}`);
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Verify SMTP connection (useful for startup checks)
69
+ */
70
+ async verifyConnection(): Promise<boolean> {
71
+ if (!this.transporter) {
72
+ return !!this.config.sendEmail;
73
+ }
74
+
75
+ try {
76
+ await this.transporter.verify();
77
+ return true;
78
+ } catch (error: unknown) {
79
+ const message = error instanceof Error ? error.message : String(error);
80
+ console.error("SMTP connection verification failed:", message);
81
+ return false;
82
+ }
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Create an email service from configuration
88
+ */
89
+ export function createEmailService(config: EmailConfig): EmailService {
90
+ return new SMTPEmailService(config);
91
+ }