@rebasepro/server-core 0.7.0 → 0.9.0

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 (300) hide show
  1. package/README.md +2 -2
  2. package/dist/api/ast-schema-editor.d.ts +21 -0
  3. package/dist/api/collections_for_test/callbacks_test_collection.d.ts +2 -0
  4. package/dist/api/errors.d.ts +53 -0
  5. package/dist/api/index.d.ts +7 -0
  6. package/dist/api/logs-routes.d.ts +37 -0
  7. package/dist/api/openapi-generator.d.ts +16 -0
  8. package/dist/api/rest/api-generator.d.ts +68 -0
  9. package/{src/api/rest/index.ts → dist/api/rest/index.d.ts} +0 -1
  10. package/dist/api/rest/query-parser.d.ts +6 -0
  11. package/dist/api/schema-editor-routes.d.ts +3 -0
  12. package/dist/api/types.d.ts +56 -0
  13. package/dist/auth/adapter-middleware.d.ts +43 -0
  14. package/dist/auth/admin-roles-route.d.ts +18 -0
  15. package/dist/auth/admin-user-ops.d.ts +79 -0
  16. package/dist/auth/admin-users-route.d.ts +28 -0
  17. package/dist/auth/api-keys/api-key-middleware.d.ts +39 -0
  18. package/{src/auth/api-keys/api-key-permission-guard.ts → dist/auth/api-keys/api-key-permission-guard.d.ts} +2 -34
  19. package/dist/auth/api-keys/api-key-routes.d.ts +20 -0
  20. package/dist/auth/api-keys/api-key-store.d.ts +35 -0
  21. package/{src/auth/api-keys/api-key-types.ts → dist/auth/api-keys/api-key-types.d.ts} +0 -6
  22. package/{src/auth/api-keys/index.ts → dist/auth/api-keys/index.d.ts} +2 -22
  23. package/dist/auth/apple-oauth.d.ts +30 -0
  24. package/{src/auth/auth-hooks.ts → dist/auth/auth-hooks.d.ts} +15 -73
  25. package/dist/auth/bitbucket-oauth.d.ts +11 -0
  26. package/dist/auth/builtin-auth-adapter.d.ts +55 -0
  27. package/dist/auth/cookie-utils.d.ts +32 -0
  28. package/{src/auth/crypto-utils.ts → dist/auth/crypto-utils.d.ts} +1 -16
  29. package/dist/auth/custom-auth-adapter.d.ts +39 -0
  30. package/dist/auth/discord-oauth.d.ts +14 -0
  31. package/dist/auth/facebook-oauth.d.ts +14 -0
  32. package/dist/auth/github-oauth.d.ts +15 -0
  33. package/dist/auth/gitlab-oauth.d.ts +13 -0
  34. package/dist/auth/google-oauth.d.ts +47 -0
  35. package/{src/auth/index.ts → dist/auth/index.d.ts} +4 -22
  36. package/{src/auth/interfaces.ts → dist/auth/interfaces.d.ts} +20 -89
  37. package/dist/auth/jwt.d.ts +67 -0
  38. package/dist/auth/linkedin-oauth.d.ts +18 -0
  39. package/dist/auth/magic-link-routes.d.ts +32 -0
  40. package/dist/auth/mfa-crypto.d.ts +23 -0
  41. package/dist/auth/mfa-routes.d.ts +7 -0
  42. package/dist/auth/mfa.d.ts +49 -0
  43. package/dist/auth/microsoft-oauth.d.ts +16 -0
  44. package/dist/auth/middleware.d.ts +158 -0
  45. package/dist/auth/password.d.ts +22 -0
  46. package/dist/auth/rate-limiter.d.ts +50 -0
  47. package/dist/auth/reset-password-admin.d.ts +29 -0
  48. package/dist/auth/rls-scope.d.ts +31 -0
  49. package/dist/auth/routes.d.ts +66 -0
  50. package/dist/auth/session-routes.d.ts +29 -0
  51. package/dist/auth/slack-oauth.d.ts +12 -0
  52. package/dist/auth/spotify-oauth.d.ts +12 -0
  53. package/dist/auth/twitter-oauth.d.ts +18 -0
  54. package/dist/collections/BackendCollectionRegistry.d.ts +13 -0
  55. package/dist/collections/loader.d.ts +5 -0
  56. package/dist/cron/cron-loader.d.ts +18 -0
  57. package/dist/cron/cron-routes.d.ts +14 -0
  58. package/dist/cron/cron-scheduler.d.ts +106 -0
  59. package/dist/cron/cron-store.d.ts +32 -0
  60. package/dist/cron/define-cron.d.ts +28 -0
  61. package/{src/cron/index.ts → dist/cron/index.d.ts} +1 -0
  62. package/dist/db/interfaces.d.ts +18 -0
  63. package/dist/dynamic-import-Dvh-K5fl.js +22 -0
  64. package/dist/dynamic-import-Dvh-K5fl.js.map +1 -0
  65. package/dist/email/index.d.ts +6 -0
  66. package/dist/email/smtp-email-service.d.ts +30 -0
  67. package/dist/email/templates.d.ts +50 -0
  68. package/{src/email/types.ts → dist/email/types.d.ts} +40 -36
  69. package/dist/env.d.ts +102 -0
  70. package/dist/functions/define-function.d.ts +55 -0
  71. package/dist/functions/function-loader.d.ts +18 -0
  72. package/dist/functions/function-routes.d.ts +10 -0
  73. package/{src/functions/index.ts → dist/functions/index.d.ts} +2 -0
  74. package/dist/history/history-routes.d.ts +23 -0
  75. package/{src/history/index.ts → dist/history/index.d.ts} +0 -1
  76. package/dist/index.d.ts +35 -0
  77. package/dist/index.es.js +18184 -0
  78. package/dist/index.es.js.map +1 -0
  79. package/dist/index.umd.js +48629 -0
  80. package/dist/index.umd.js.map +1 -0
  81. package/dist/init/docs.d.ts +4 -0
  82. package/dist/init/health.d.ts +2 -0
  83. package/dist/init/middlewares.d.ts +10 -0
  84. package/dist/init/shutdown.d.ts +65 -0
  85. package/dist/init/storage.d.ts +5 -0
  86. package/dist/init.d.ts +344 -0
  87. package/dist/jwt-BwIn8xmk.js +4200 -0
  88. package/dist/jwt-BwIn8xmk.js.map +1 -0
  89. package/dist/logger-BYU66ENZ.js +94 -0
  90. package/dist/logger-BYU66ENZ.js.map +1 -0
  91. package/dist/ms-DnYXB-Wd.js +162 -0
  92. package/dist/ms-DnYXB-Wd.js.map +1 -0
  93. package/dist/openapi-generator-Z9oYWLf_.js +586 -0
  94. package/dist/openapi-generator-Z9oYWLf_.js.map +1 -0
  95. package/dist/schema-editor-routes-D3ef8zu1.js +219 -0
  96. package/dist/schema-editor-routes-D3ef8zu1.js.map +1 -0
  97. package/dist/serve-spa.d.ts +36 -0
  98. package/dist/services/driver-registry.d.ts +78 -0
  99. package/dist/services/routed-realtime-service.d.ts +43 -0
  100. package/dist/services/webhook-service.d.ts +29 -0
  101. package/dist/singleton.d.ts +51 -0
  102. package/dist/src-B4OLmNVa.js +437 -0
  103. package/dist/src-B4OLmNVa.js.map +1 -0
  104. package/dist/src-B5WkP1Rv.js +24778 -0
  105. package/dist/src-B5WkP1Rv.js.map +1 -0
  106. package/dist/storage/GCSStorageController.d.ts +43 -0
  107. package/dist/storage/LocalStorageController.d.ts +46 -0
  108. package/dist/storage/S3StorageController.d.ts +40 -0
  109. package/dist/storage/image-transform.d.ts +50 -0
  110. package/{src/storage/index.ts → dist/storage/index.d.ts} +6 -21
  111. package/dist/storage/routes.d.ts +70 -0
  112. package/dist/storage/storage-registry.d.ts +78 -0
  113. package/dist/storage/tus-handler.d.ts +53 -0
  114. package/{src/storage/types.ts → dist/storage/types.d.ts} +32 -38
  115. package/dist/types/index.d.ts +11 -0
  116. package/dist/utils/dev-port.d.ts +45 -0
  117. package/dist/utils/dynamic-import.d.ts +25 -0
  118. package/dist/utils/logger.d.ts +31 -0
  119. package/dist/utils/logging.d.ts +9 -0
  120. package/dist/utils/request-id.d.ts +4 -0
  121. package/dist/utils/request-logger.d.ts +19 -0
  122. package/{src/utils/sql.ts → dist/utils/sql.d.ts} +5 -16
  123. package/package.json +49 -22
  124. package/coverage/clover.xml +0 -3739
  125. package/coverage/coverage-final.json +0 -31
  126. package/coverage/lcov-report/base.css +0 -224
  127. package/coverage/lcov-report/block-navigation.js +0 -87
  128. package/coverage/lcov-report/favicon.png +0 -0
  129. package/coverage/lcov-report/index.html +0 -266
  130. package/coverage/lcov-report/prettify.css +0 -1
  131. package/coverage/lcov-report/prettify.js +0 -2
  132. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  133. package/coverage/lcov-report/sorter.js +0 -210
  134. package/coverage/lcov-report/src/api/ast-schema-editor.ts.html +0 -952
  135. package/coverage/lcov-report/src/api/errors.ts.html +0 -472
  136. package/coverage/lcov-report/src/api/graphql/graphql-schema-generator.ts.html +0 -1069
  137. package/coverage/lcov-report/src/api/graphql/index.html +0 -116
  138. package/coverage/lcov-report/src/api/index.html +0 -176
  139. package/coverage/lcov-report/src/api/openapi-generator.ts.html +0 -565
  140. package/coverage/lcov-report/src/api/rest/api-generator.ts.html +0 -994
  141. package/coverage/lcov-report/src/api/rest/index.html +0 -131
  142. package/coverage/lcov-report/src/api/rest/query-parser.ts.html +0 -550
  143. package/coverage/lcov-report/src/api/schema-editor-routes.ts.html +0 -202
  144. package/coverage/lcov-report/src/api/server.ts.html +0 -823
  145. package/coverage/lcov-report/src/auth/admin-routes.ts.html +0 -973
  146. package/coverage/lcov-report/src/auth/index.html +0 -176
  147. package/coverage/lcov-report/src/auth/jwt.ts.html +0 -574
  148. package/coverage/lcov-report/src/auth/middleware.ts.html +0 -745
  149. package/coverage/lcov-report/src/auth/password.ts.html +0 -310
  150. package/coverage/lcov-report/src/auth/services.ts.html +0 -2074
  151. package/coverage/lcov-report/src/collections/index.html +0 -116
  152. package/coverage/lcov-report/src/collections/loader.ts.html +0 -232
  153. package/coverage/lcov-report/src/db/auth-schema.ts.html +0 -523
  154. package/coverage/lcov-report/src/db/data-transformer.ts.html +0 -1753
  155. package/coverage/lcov-report/src/db/entityService.ts.html +0 -700
  156. package/coverage/lcov-report/src/db/index.html +0 -146
  157. package/coverage/lcov-report/src/db/services/EntityFetchService.ts.html +0 -4048
  158. package/coverage/lcov-report/src/db/services/EntityPersistService.ts.html +0 -883
  159. package/coverage/lcov-report/src/db/services/RelationService.ts.html +0 -3121
  160. package/coverage/lcov-report/src/db/services/entity-helpers.ts.html +0 -442
  161. package/coverage/lcov-report/src/db/services/index.html +0 -176
  162. package/coverage/lcov-report/src/db/services/index.ts.html +0 -124
  163. package/coverage/lcov-report/src/generate-drizzle-schema-logic.ts.html +0 -1960
  164. package/coverage/lcov-report/src/index.html +0 -116
  165. package/coverage/lcov-report/src/services/driver-registry.ts.html +0 -631
  166. package/coverage/lcov-report/src/services/index.html +0 -131
  167. package/coverage/lcov-report/src/services/postgresDataDriver.ts.html +0 -3025
  168. package/coverage/lcov-report/src/storage/LocalStorageController.ts.html +0 -1189
  169. package/coverage/lcov-report/src/storage/S3StorageController.ts.html +0 -970
  170. package/coverage/lcov-report/src/storage/index.html +0 -161
  171. package/coverage/lcov-report/src/storage/storage-registry.ts.html +0 -646
  172. package/coverage/lcov-report/src/storage/types.ts.html +0 -451
  173. package/coverage/lcov-report/src/utils/drizzle-conditions.ts.html +0 -3082
  174. package/coverage/lcov-report/src/utils/index.html +0 -116
  175. package/coverage/lcov.info +0 -7179
  176. package/jest.config.cjs +0 -19
  177. package/src/api/ast-schema-editor.ts +0 -289
  178. package/src/api/collections_for_test/callbacks_test_collection.ts +0 -61
  179. package/src/api/errors.ts +0 -278
  180. package/src/api/graphql/graphql-schema-generator.ts +0 -383
  181. package/src/api/graphql/index.ts +0 -2
  182. package/src/api/index.ts +0 -11
  183. package/src/api/logs-routes.ts +0 -132
  184. package/src/api/openapi-generator.ts +0 -727
  185. package/src/api/rest/api-generator-count.test.ts +0 -126
  186. package/src/api/rest/api-generator.ts +0 -747
  187. package/src/api/rest/query-parser.ts +0 -300
  188. package/src/api/schema-editor-routes.ts +0 -41
  189. package/src/api/server.ts +0 -271
  190. package/src/api/types.ts +0 -104
  191. package/src/auth/adapter-middleware.ts +0 -114
  192. package/src/auth/admin-roles-route.ts +0 -36
  193. package/src/auth/admin-user-ops.ts +0 -236
  194. package/src/auth/admin-users-route.ts +0 -302
  195. package/src/auth/api-keys/api-key-middleware.ts +0 -133
  196. package/src/auth/api-keys/api-key-routes.ts +0 -193
  197. package/src/auth/api-keys/api-key-store.ts +0 -340
  198. package/src/auth/apple-oauth.ts +0 -122
  199. package/src/auth/bitbucket-oauth.ts +0 -84
  200. package/src/auth/builtin-auth-adapter.ts +0 -380
  201. package/src/auth/custom-auth-adapter.ts +0 -86
  202. package/src/auth/discord-oauth.ts +0 -85
  203. package/src/auth/facebook-oauth.ts +0 -74
  204. package/src/auth/github-oauth.ts +0 -112
  205. package/src/auth/gitlab-oauth.ts +0 -72
  206. package/src/auth/google-oauth.ts +0 -223
  207. package/src/auth/jwt.ts +0 -208
  208. package/src/auth/linkedin-oauth.ts +0 -83
  209. package/src/auth/magic-link-routes.ts +0 -167
  210. package/src/auth/mfa-crypto.ts +0 -91
  211. package/src/auth/mfa-routes.ts +0 -323
  212. package/src/auth/mfa.ts +0 -161
  213. package/src/auth/microsoft-oauth.ts +0 -90
  214. package/src/auth/middleware.ts +0 -369
  215. package/src/auth/password.ts +0 -77
  216. package/src/auth/rate-limiter.ts +0 -225
  217. package/src/auth/reset-password-admin.ts +0 -160
  218. package/src/auth/rls-scope.ts +0 -58
  219. package/src/auth/routes.ts +0 -802
  220. package/src/auth/session-routes.ts +0 -353
  221. package/src/auth/slack-oauth.ts +0 -73
  222. package/src/auth/spotify-oauth.ts +0 -69
  223. package/src/auth/twitter-oauth.ts +0 -128
  224. package/src/collections/BackendCollectionRegistry.ts +0 -20
  225. package/src/collections/loader.ts +0 -50
  226. package/src/cron/cron-loader.ts +0 -84
  227. package/src/cron/cron-routes.test.ts +0 -265
  228. package/src/cron/cron-routes.ts +0 -85
  229. package/src/cron/cron-scheduler.test.ts +0 -559
  230. package/src/cron/cron-scheduler.ts +0 -581
  231. package/src/cron/cron-store.ts +0 -166
  232. package/src/db/interfaces.ts +0 -60
  233. package/src/email/index.ts +0 -19
  234. package/src/email/smtp-email-service.ts +0 -123
  235. package/src/email/templates.ts +0 -470
  236. package/src/env.ts +0 -227
  237. package/src/functions/function-loader.ts +0 -116
  238. package/src/functions/function-routes.ts +0 -31
  239. package/src/history/history-routes.ts +0 -129
  240. package/src/index.ts +0 -70
  241. package/src/init/docs.ts +0 -47
  242. package/src/init/health.ts +0 -37
  243. package/src/init/middlewares.ts +0 -61
  244. package/src/init/shutdown.ts +0 -56
  245. package/src/init/storage.ts +0 -57
  246. package/src/init.ts +0 -1041
  247. package/src/serve-spa.ts +0 -89
  248. package/src/services/driver-registry.ts +0 -183
  249. package/src/services/routed-realtime-service.ts +0 -113
  250. package/src/services/webhook-service.ts +0 -155
  251. package/src/singleton.ts +0 -70
  252. package/src/storage/LocalStorageController.ts +0 -389
  253. package/src/storage/S3StorageController.ts +0 -300
  254. package/src/storage/image-transform.ts +0 -218
  255. package/src/storage/routes.ts +0 -368
  256. package/src/storage/storage-registry.ts +0 -188
  257. package/src/storage/tus-handler.ts +0 -315
  258. package/src/types/index.ts +0 -27
  259. package/src/utils/dev-port.ts +0 -196
  260. package/src/utils/logger.ts +0 -143
  261. package/src/utils/logging.ts +0 -40
  262. package/src/utils/request-id.ts +0 -40
  263. package/src/utils/request-logger.ts +0 -72
  264. package/test/api-generator.test.ts +0 -588
  265. package/test/api-key-permission-guard.test.ts +0 -144
  266. package/test/ast-schema-editor.test.ts +0 -89
  267. package/test/auth-middleware-hono.test.ts +0 -556
  268. package/test/auth-routes.test.ts +0 -1098
  269. package/test/backend-hooks-data.test.ts +0 -477
  270. package/test/custom-auth-adapter.test.ts +0 -189
  271. package/test/driver-registry.test.ts +0 -282
  272. package/test/email-templates.test.ts +0 -174
  273. package/test/env.test.ts +0 -128
  274. package/test/error-propagation.test.ts +0 -226
  275. package/test/errors-hono.test.ts +0 -133
  276. package/test/errors.test.ts +0 -155
  277. package/test/function-loader.test.ts +0 -127
  278. package/test/graphql-schema-generator.test.ts +0 -554
  279. package/test/jwt-security.test.ts +0 -182
  280. package/test/jwt.test.ts +0 -326
  281. package/test/mfa.test.ts +0 -197
  282. package/test/middleware.test.ts +0 -305
  283. package/test/multi-datasource-routing.test.ts +0 -113
  284. package/test/password.test.ts +0 -165
  285. package/test/query-parser.test.ts +0 -233
  286. package/test/rate-limiter.test.ts +0 -102
  287. package/test/reset-password-admin.test.ts +0 -113
  288. package/test/routed-realtime-service.test.ts +0 -86
  289. package/test/safe-compare.test.ts +0 -66
  290. package/test/singleton.test.ts +0 -59
  291. package/test/smtp-email-service.test.ts +0 -169
  292. package/test/storage-local.test.ts +0 -271
  293. package/test/storage-registry.test.ts +0 -282
  294. package/test/storage-routes.test.ts +0 -222
  295. package/test/storage-s3.test.ts +0 -304
  296. package/test/transform-auth-response.test.ts +0 -305
  297. package/test/webhook-service.test.ts +0 -260
  298. package/tsconfig.json +0 -54
  299. package/tsconfig.prod.json +0 -23
  300. package/vite.config.ts +0 -86
@@ -1,116 +0,0 @@
1
- import * as fs from "fs";
2
- import * as path from "path";
3
- import { pathToFileURL } from "url";
4
- import { Hono } from "hono";
5
- import { logger } from "../utils/logger.js";
6
-
7
- export interface LoadedFunction {
8
- /** Endpoint name derived from filename (e.g., "send-invoice") */
9
- name: string;
10
- /** The Hono sub-app to mount */
11
- app: Hono<import("hono").Env>;
12
- }
13
-
14
- /**
15
- * Auto-discover Hono route files from a directory.
16
- *
17
- * Each file should default-export a Hono app (or router).
18
- * The filename (without extension) becomes the mount path:
19
- * `functions/send-invoice.ts` → mounted at `/send-invoice`
20
- *
21
- * This mirrors how `loadCollectionsFromDirectory` works for collections.
22
- */
23
- export async function loadFunctionsFromDirectory(
24
- directory: string
25
- ): Promise<LoadedFunction[]> {
26
- const functions: LoadedFunction[] = [];
27
-
28
- if (!fs.existsSync(directory)) {
29
- return functions;
30
- }
31
-
32
- const files = fs.readdirSync(directory);
33
- for (const file of files) {
34
- if (
35
- (file.endsWith(".ts") || file.endsWith(".js")) &&
36
- !file.includes(".test.") &&
37
- !file.endsWith(".d.ts") &&
38
- file !== "index.ts" &&
39
- file !== "index.js"
40
- ) {
41
- const filePath = path.join(directory, file);
42
- try {
43
- const fileUrl = pathToFileURL(filePath).href;
44
-
45
- // Use new Function to compile dynamic import natively and bypass
46
- // tsc converting import() to require() — same pattern as collection loader
47
- const dynamicImport = new Function("url", "return import(url)");
48
- const mod = await dynamicImport(fileUrl);
49
-
50
- const exported = mod.default;
51
-
52
- if (!exported) {
53
- logger.warn(`[functions] ${file}: no default export. Skipping.`);
54
- continue;
55
- }
56
-
57
- // Accept a Hono instance — use duck-typing to handle different
58
- // Hono versions which may not share the same prototype.
59
- if (isHonoLike(exported)) {
60
- const name = path.basename(file, path.extname(file));
61
- functions.push({ name,
62
- app: exported as Hono });
63
- logger.info(`⚡ Loaded function route: ${name}`);
64
- continue;
65
- }
66
-
67
- // Also accept a factory function that returns a Hono instance
68
- if (typeof exported === "function") {
69
- const result = exported();
70
- if (isHonoLike(result)) {
71
- const name = path.basename(file, path.extname(file));
72
- functions.push({ name,
73
- app: result as Hono });
74
- logger.info(`⚡ Loaded function route: ${name}`);
75
- continue;
76
- }
77
- }
78
-
79
- // Provide actionable diagnostics
80
- const exportType = typeof exported;
81
- const keys = exported && typeof exported === "object"
82
- ? Object.getOwnPropertyNames(Object.getPrototypeOf(exported)).slice(0, 10).join(", ")
83
- : "N/A";
84
- logger.warn(
85
- `[functions] ${file}: default export is not a Hono app or factory. Skipping.\n` +
86
- ` export type: ${exportType}${exported?.constructor?.name ? ` (${exported.constructor.name})` : ""}\n` +
87
- ` prototype methods: ${keys}\n` +
88
- " Hint: ensure the function exports a Hono app created with the same hono version as the server.\n" +
89
- " The loader checks for .fetch() and .routes — any Hono-compatible app will work."
90
- );
91
- } catch (err: unknown) {
92
- const message =
93
- err instanceof Error ? err.message : String(err);
94
- logger.error(`[functions] Failed to load ${file}: ${message}`);
95
- }
96
- }
97
- }
98
-
99
- return functions;
100
- }
101
-
102
- /**
103
- * Duck-type check for Hono apps.
104
- * We avoid `instanceof Hono` because different Hono versions
105
- * installed in the user's project vs. our dependencies will
106
- * not share the same prototype, causing false negatives.
107
- */
108
- function isHonoLike(obj: unknown): boolean {
109
- if (!obj || typeof obj !== "object") return false;
110
- // Hono instances always have .fetch() and .routes
111
- const record = obj as Record<string, unknown>;
112
- return (
113
- typeof record.fetch === "function" &&
114
- Array.isArray(record.routes)
115
- );
116
- }
@@ -1,31 +0,0 @@
1
- import { Hono } from "hono";
2
- import { HonoEnv } from "../api/types";
3
- import { LoadedFunction } from "./function-loader";
4
-
5
- /**
6
- * Mount all loaded function routes under a single Hono router.
7
- *
8
- * Each function is mounted at `/<function-name>`, preserving
9
- * whatever HTTP methods and middleware the Hono sub-app defines.
10
- */
11
- export function createFunctionRoutes(
12
- functions: LoadedFunction[]
13
- ): Hono<HonoEnv> {
14
- const router = new Hono<HonoEnv>();
15
-
16
- // Listing endpoint: GET / → list available functions
17
- router.get("/", (c) => {
18
- return c.json({
19
- functions: functions.map((fn) => ({
20
- name: fn.name,
21
- endpoint: `/functions/${fn.name}`
22
- }))
23
- });
24
- });
25
-
26
- for (const fn of functions) {
27
- router.route(`/${fn.name}`, fn.app);
28
- }
29
-
30
- return router;
31
- }
@@ -1,129 +0,0 @@
1
- import { Hono } from "hono";
2
- import { HonoEnv } from "../api/types";
3
- import { BackendCollectionRegistry } from "../collections/BackendCollectionRegistry";
4
- import { ApiError, errorHandler } from "../api/errors";
5
- import { DataDriver } from "@rebasepro/types";
6
- /**
7
- * Create Hono routes for entity history.
8
- * Mounted at `{basePath}/data/:slug/:entityId/history`.
9
- */
10
- export interface HistoryService {
11
- fetchHistory(tableName: string, entityId: string, options: { limit: number, offset: number }): Promise<{ data: Record<string, unknown>[], total: number }>;
12
- fetchHistoryEntry(historyId: string): Promise<Record<string, unknown> | null>;
13
- }
14
-
15
- export function createHistoryRoutes(params: {
16
- historyService: HistoryService;
17
- registry: BackendCollectionRegistry;
18
- driver: DataDriver;
19
- }): Hono<HonoEnv> {
20
- const { historyService, registry, driver } = params;
21
- const router = new Hono<HonoEnv>();
22
- router.onError(errorHandler);
23
-
24
- /**
25
- * GET /:slug/:entityId/history - List history entries for an entity
26
- *
27
- * Query params:
28
- * limit (default 20)
29
- * offset (default 0)
30
- */
31
- router.get("/:slug/:entityId/history", async (c) => {
32
- const slug = c.req.param("slug");
33
- const entityId = c.req.param("entityId");
34
- const parsedLimit = parseInt(c.req.query("limit") ?? "20", 10);
35
- const parsedOffset = parseInt(c.req.query("offset") ?? "0", 10);
36
- const limit = Number.isNaN(parsedLimit) ? 20 : parsedLimit;
37
- const offset = Number.isNaN(parsedOffset) ? 0 : parsedOffset;
38
-
39
- // Resolve the collection to get the actual table name
40
- const collection = registry.getCollections().find(
41
- col => col.slug === slug || false
42
- );
43
-
44
- if (!collection) {
45
- throw ApiError.notFound(`Collection '${slug}' not found`);
46
- }
47
-
48
- if (!collection.history) {
49
- throw ApiError.badRequest(`History is not enabled for collection '${slug}'`);
50
- }
51
-
52
- const tableName = collection.slug;
53
-
54
- const result = await historyService.fetchHistory(tableName, entityId, {
55
- limit: Math.min(limit, 100),
56
- offset: Math.max(offset, 0)
57
- });
58
-
59
- return c.json({
60
- data: result.data,
61
- meta: {
62
- total: result.total,
63
- limit,
64
- offset,
65
- hasMore: offset + result.data.length < result.total
66
- }
67
- });
68
- });
69
-
70
- /**
71
- * POST /:slug/:entityId/history/:historyId/revert - Revert entity to a historical version
72
- *
73
- * This goes through the normal save path, so it creates its own history entry.
74
- */
75
- router.post("/:slug/:entityId/history/:historyId/revert", async (c) => {
76
- const slug = c.req.param("slug");
77
- const entityId = c.req.param("entityId");
78
- const historyId = c.req.param("historyId");
79
-
80
- const collection = registry.getCollections().find(
81
- col => col.slug === slug || false
82
- );
83
-
84
- if (!collection) {
85
- throw ApiError.notFound(`Collection '${slug}' not found`);
86
- }
87
-
88
- if (!collection.history) {
89
- throw ApiError.badRequest(`History is not enabled for collection '${slug}'`);
90
- }
91
-
92
- // Fetch the history entry
93
- const historyEntry = await historyService.fetchHistoryEntry(historyId);
94
-
95
- if (!historyEntry) {
96
- throw ApiError.notFound(`History entry '${historyId}' not found`);
97
- }
98
-
99
- // Verify the history entry belongs to this entity (prevent cross-entity revert)
100
- const tableName = collection.slug;
101
- if (historyEntry.entity_id !== String(entityId) || historyEntry.table_name !== tableName) {
102
- throw ApiError.badRequest("History entry does not belong to this entity");
103
- }
104
-
105
- if (!historyEntry.values) {
106
- throw ApiError.badRequest("Cannot revert: history entry has no stored values");
107
- }
108
-
109
- // Revert by saving through the normal driver path — this will
110
- // itself create another history entry, giving a full audit trail.
111
- const authDriver = c.get("driver") || driver;
112
- const path = collection.slug;
113
-
114
- const savedEntity = await authDriver.saveEntity({
115
- path,
116
- entityId: String(entityId),
117
- values: historyEntry.values,
118
- collection,
119
- status: "existing"
120
- });
121
-
122
- return c.json({
123
- data: savedEntity,
124
- meta: { reverted_from: historyId }
125
- });
126
- });
127
-
128
- return router;
129
- }
package/src/index.ts DELETED
@@ -1,70 +0,0 @@
1
- /**
2
- * @rebasepro/server-core
3
- *
4
- * Database-Agnostic Backend Core for Rebase.
5
- * This package provides the core backend services, generic driver routing,
6
- * and API layers. Database implementations (e.g., PostgreSQL) are provided
7
- * by specialized driver packages like `@rebasepro/server-postgresql`.
8
- */
9
-
10
- // =============================================================================
11
- // Abstract Interfaces (for database abstraction)
12
- // =============================================================================
13
- export * from "./db/interfaces";
14
- export * from "./auth/interfaces";
15
-
16
- // Core functionality
17
- export * from "./init";
18
-
19
- // Server-side singleton (import { rebase } from "@rebasepro/server-core")
20
- export { rebase, _setRebaseMock, _resetRebaseMock } from "./singleton";
21
-
22
- // Services
23
- export * from "./services/driver-registry";
24
-
25
- // API types (HonoEnv, ApiConfig, etc.)
26
- export * from "./api/types";
27
-
28
- // API Generation
29
- export * from "./api";
30
-
31
- // Types
32
- export * from "./types";
33
- export * from "./types/index";
34
-
35
- // Auth module
36
- export * from "./auth";
37
-
38
- // Email module
39
- export * from "./email";
40
-
41
- // Storage module
42
- export * from "./storage";
43
-
44
- export * from "./utils/logging";
45
- export * from "./utils/logger";
46
- export * from "./utils/request-logger";
47
- export * from "./utils/request-id";
48
- export * from "./utils/sql";
49
-
50
- // Entity history
51
- export * from "./history";
52
-
53
- // Custom Functions (auto-discovered Hono routes)
54
- export * from "./functions";
55
-
56
- // Cron Jobs (auto-discovered scheduled tasks)
57
- export * from "./cron";
58
-
59
-
60
- // SPA serving helper
61
- export * from "./serve-spa";
62
-
63
- // Dev-mode port resolution (retry on EADDRINUSE)
64
- export * from "./utils/dev-port";
65
-
66
- // Environment validation
67
- export { loadEnv } from "./env";
68
- export type { RebaseEnv } from "./env";
69
- export { z } from "zod";
70
-
package/src/init/docs.ts DELETED
@@ -1,47 +0,0 @@
1
- import { Hono } from "hono";
2
- import { EntityCollection } from "@rebasepro/types";
3
- import { HonoEnv } from "../api/types";
4
- import { logger } from "../utils/logger";
5
-
6
- export async function mountOpenApiDocs(
7
- app: Hono<HonoEnv>,
8
- basePath: string,
9
- enableSwagger: boolean | undefined,
10
- activeCollections: EntityCollection[],
11
- requireAuth: boolean
12
- ): Promise<void> {
13
- if (enableSwagger === false || activeCollections.length === 0) {
14
- return;
15
- }
16
-
17
- const { generateOpenApiSpec } = await import("../api/openapi-generator");
18
-
19
- app.get(`${basePath}/docs`, (c) => {
20
- const spec = generateOpenApiSpec(activeCollections, {
21
- basePath,
22
- requireAuth
23
- });
24
- return c.json(spec);
25
- });
26
-
27
- if (process.env.NODE_ENV !== "production") {
28
- app.get(`${basePath}/swagger`, (c) => {
29
- return c.html(`<!DOCTYPE html>
30
- <html>
31
- <head>
32
- <title>Rebase API Documentation</title>
33
- <meta charset="utf-8"/>
34
- <meta name="viewport" content="width=device-width, initial-scale=1"/>
35
- <link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css"/>
36
- <style>body{margin:0;padding:0;}</style>
37
- </head>
38
- <body>
39
- <div id="swagger-ui"></div>
40
- <script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
41
- <script>SwaggerUIBundle({ url: '${basePath}/docs', dom_id: '#swagger-ui' });</script>
42
- </body>
43
- </html>`);
44
- });
45
- logger.info("Swagger UI available", { path: `${basePath}/swagger` });
46
- }
47
- }
@@ -1,37 +0,0 @@
1
- import { DataDriver, HealthCheckResult, isSQLAdmin } from "@rebasepro/types";
2
- import { logger } from "../utils/logger";
3
-
4
- export function createHealthCheck(defaultDriver: DataDriver): () => Promise<HealthCheckResult> {
5
- return async (): Promise<HealthCheckResult> => {
6
- const start = performance.now();
7
- try {
8
- const admin = defaultDriver.admin;
9
- if (isSQLAdmin(admin)) {
10
- await admin.executeSql("SELECT 1");
11
- } else {
12
- await defaultDriver.fetchCollection({
13
- path: "__health_check_nonexistent__",
14
- limit: 1
15
- });
16
- }
17
- const latencyMs = Math.round(performance.now() - start);
18
- return {
19
- healthy: true,
20
- latencyMs
21
- };
22
- } catch (error: unknown) {
23
- const latencyMs = Math.round(performance.now() - start);
24
- logger.error("Health check failed", {
25
- error: error instanceof Error ? error : new Error(String(error)),
26
- latencyMs
27
- });
28
- return {
29
- healthy: false,
30
- latencyMs,
31
- details: {
32
- error: error instanceof Error ? error.message : String(error)
33
- }
34
- };
35
- }
36
- };
37
- }
@@ -1,61 +0,0 @@
1
- import { Hono } from "hono";
2
- import { bodyLimit } from "hono/body-limit";
3
- import { csrf } from "hono/csrf";
4
- import { HonoEnv } from "../api/types";
5
- import { requestId } from "../utils/request-id";
6
- import { requestLogger } from "../utils/request-logger";
7
- import { logger } from "../utils/logger";
8
-
9
- interface MiddlewareConfig {
10
- maxBodySize?: number;
11
- csrf?: {
12
- origin: string | string[] | ((origin: string) => boolean);
13
- };
14
- }
15
-
16
- export function configureMiddlewares(
17
- app: Hono<HonoEnv>,
18
- basePath: string,
19
- isProduction: boolean,
20
- config: MiddlewareConfig
21
- ): void {
22
- // Request ID (correlation)
23
- app.use(`${basePath}/*`, requestId());
24
-
25
- // Request Body Size Limit
26
- const maxBodySize = config.maxBodySize ?? 10 * 1024 * 1024; // 10MB default
27
- if (maxBodySize > 0) {
28
- app.use(`${basePath}/*`, bodyLimit({
29
- maxSize: maxBodySize,
30
- onError: (c) => {
31
- return c.json({
32
- error: {
33
- message: `Request body too large. Maximum size is ${Math.round(maxBodySize / 1024 / 1024)}MB.`,
34
- code: "PAYLOAD_TOO_LARGE"
35
- }
36
- }, 413);
37
- }
38
- }));
39
- logger.info("Request body limit configured", { maxSizeMB: Math.round(maxBodySize / 1024 / 1024) });
40
- }
41
-
42
- // CSRF Protection (opt-in)
43
- if (config.csrf?.origin) {
44
- app.use(`${basePath}/*`, csrf({
45
- origin: config.csrf.origin
46
- }));
47
- logger.info("CSRF protection enabled");
48
- }
49
-
50
- // CORS Warning
51
- if (!isProduction && !process.env.CORS_ORIGINS && !process.env.FRONTEND_URL) {
52
- logger.warn(
53
- "No CORS configuration detected (CORS_ORIGINS / FRONTEND_URL not set). " +
54
- "The API will accept requests from any origin. " +
55
- "Set CORS_ORIGINS in your .env file to restrict access."
56
- );
57
- }
58
-
59
- // Request Logging
60
- app.use(`${basePath}/*`, requestLogger());
61
- }
@@ -1,56 +0,0 @@
1
- import { Server } from "http";
2
- import { RealtimeProvider } from "@rebasepro/types";
3
- import { logger } from "../utils/logger";
4
-
5
- interface ShutdownConfig {
6
- server: Server;
7
- cronScheduler?: { stop(): void };
8
- realtimeServices: Record<string, RealtimeProvider>;
9
- }
10
-
11
- export function createShutdown(config: ShutdownConfig): (timeoutMs?: number) => Promise<void> {
12
- return (timeoutMs = 15_000): Promise<void> => {
13
- return new Promise<void>((resolve) => {
14
- (async () => {
15
- logger.info("Shutting down Rebase Backend...");
16
-
17
- // 1. Stop cron scheduler
18
- if (config.cronScheduler) {
19
- config.cronScheduler.stop();
20
- logger.info("Cron scheduler stopped");
21
- }
22
-
23
- // 2. Tear down realtime services (LISTEN clients, debounce timers,
24
- // subscriptions). Must happen BEFORE pool.end() so that pending
25
- // timer callbacks don't fire against a closed pool.
26
- for (const [key, rt] of Object.entries(config.realtimeServices)) {
27
- try {
28
- if (typeof rt.destroy === "function") {
29
- await rt.destroy();
30
- logger.info(`Realtime service "${key}" destroyed`);
31
- } else if (typeof rt.stopListening === "function") {
32
- await rt.stopListening();
33
- logger.info(`Realtime service "${key}" LISTEN client stopped`);
34
- }
35
- } catch (err) {
36
- logger.warn(`Error destroying realtime service "${key}":`, { error: err });
37
- }
38
- }
39
-
40
- // 3. Close the HTTP server (stop accepting, drain in-flight)
41
- config.server.close(() => {
42
- logger.info("HTTP server closed");
43
- resolve();
44
- });
45
-
46
- // 4. Force-resolve after timeout (unless disabled with 0)
47
- if (timeoutMs > 0) {
48
- setTimeout(() => {
49
- logger.warn(`Forced shutdown after ${timeoutMs / 1000}s timeout`);
50
- resolve();
51
- }, timeoutMs).unref();
52
- }
53
- })();
54
- });
55
- };
56
- }
@@ -1,57 +0,0 @@
1
- import {
2
- BackendStorageConfig,
3
- createStorageController,
4
- DEFAULT_STORAGE_ID,
5
- DefaultStorageRegistry,
6
- StorageController,
7
- StorageRegistry
8
- } from "../storage";
9
- import { logger } from "../utils/logger";
10
-
11
- export function initializeStorage(
12
- storageConfig: BackendStorageConfig | StorageController | Record<string, BackendStorageConfig | StorageController> | undefined,
13
- isProduction: boolean
14
- ): { storageRegistry?: StorageRegistry; storageController?: StorageController } {
15
- if (!storageConfig) return {};
16
-
17
- logger.info("Configuring storage");
18
- const controllers: Record<string, StorageController> = {};
19
-
20
- const toController = (entry: BackendStorageConfig | StorageController, label: string): StorageController => {
21
- if (typeof (entry as StorageController).putObject === "function") {
22
- return entry as StorageController;
23
- }
24
- const conf = entry as BackendStorageConfig;
25
- if (isProduction && conf.type === "local") {
26
- logger.warn(`Storage backend "${label}" uses local filesystem in production. ` +
27
- "Files will be lost on container restart. " +
28
- "Configure S3-compatible storage or a custom StorageController.");
29
- }
30
- return createStorageController(conf);
31
- };
32
-
33
- if (
34
- typeof storageConfig === "object" &&
35
- ("type" in storageConfig || typeof (storageConfig as StorageController).putObject === "function")
36
- ) {
37
- controllers[DEFAULT_STORAGE_ID] = toController(
38
- storageConfig as BackendStorageConfig | StorageController,
39
- DEFAULT_STORAGE_ID
40
- );
41
- } else {
42
- for (const [storageId, entry] of Object.entries(
43
- storageConfig as Record<string, BackendStorageConfig | StorageController>
44
- )) {
45
- controllers[storageId] = toController(entry, storageId);
46
- }
47
- }
48
-
49
- if (Object.keys(controllers).length > 0) {
50
- const storageRegistry = DefaultStorageRegistry.create(controllers);
51
- const storageController = storageRegistry.getDefault();
52
- logger.info("Initialized storage backends", { count: Object.keys(controllers).length });
53
- return { storageRegistry, storageController };
54
- }
55
-
56
- return {};
57
- }