@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,196 +0,0 @@
1
- /**
2
- * Dev-mode port resolution utilities.
3
- *
4
- * Provides a `listen` wrapper that automatically retries the next port when
5
- * the requested one is already in use, and writes the resolved port to a
6
- * well-known temp file so the CLI / frontend can discover it.
7
- *
8
- * Port affinity: when a port file already exists (e.g. after a tsx watch
9
- * restart), the saved port is tried FIRST so the backend stays on the same
10
- * port the frontend was configured with.
11
- *
12
- * This module is dev-only and should never run in production.
13
- */
14
- import type { Server } from "http";
15
- import path from "path";
16
- import fs from "fs";
17
-
18
- const MAX_PORT_ATTEMPTS = 20;
19
-
20
- /** Filename written next to the project `.env` so the CLI can read it. */
21
- export const DEV_PORT_FILENAME = ".rebase-dev-port";
22
-
23
- /**
24
- * Try to `listen` on `startPort`. If the port is busy (`EADDRINUSE`), increment
25
- * and retry up to `maxAttempts` times.
26
- *
27
- * When a port file already exists (written by a previous run), the saved port
28
- * is tried first to maintain port affinity across tsx watch restarts.
29
- *
30
- * Resolves with the port that was actually bound.
31
- */
32
- export function listenWithPortRetry(
33
- server: Server,
34
- startPort: number,
35
- options?: {
36
- host?: string;
37
- maxAttempts?: number;
38
- /** Absolute path to write the resolved port file into. Defaults to `process.cwd()`. */
39
- portFileDir?: string;
40
- /** Service key to include in the state file for MCP server auto-discovery. */
41
- serviceKey?: string;
42
- }
43
- ): Promise<number> {
44
- const host = options?.host ?? "0.0.0.0";
45
- const maxAttempts = options?.maxAttempts ?? MAX_PORT_ATTEMPTS;
46
- const portFileDir = options?.portFileDir;
47
-
48
- const isProd = process.env.NODE_ENV === "production";
49
- if (isProd) {
50
- return new Promise<number>((resolve, reject) => {
51
- const onError = (err: Error) => {
52
- reject(err);
53
- };
54
- server.once("error", onError);
55
- server.listen(startPort, host, () => {
56
- server.removeListener("error", onError);
57
- resolve(startPort);
58
- });
59
- });
60
- }
61
-
62
- // Read affinity port from a previous run's port file.
63
- // This ensures tsx watch restarts land on the same port the frontend was
64
- // configured with, even if the CLI-computed port was different.
65
- let affinityPort: number | null = null;
66
- if (portFileDir) {
67
- try {
68
- const portFile = path.join(portFileDir, DEV_PORT_FILENAME);
69
- if (fs.existsSync(portFile)) {
70
- const saved = parseInt(fs.readFileSync(portFile, "utf-8").trim(), 10);
71
- if (saved > 0 && saved < 65536 && saved !== startPort) {
72
- affinityPort = saved;
73
- }
74
- }
75
- } catch { /* ignore */ }
76
- }
77
-
78
- return new Promise<number>((resolve, reject) => {
79
- let attempt = 0;
80
- // Build the ordered list of ports to try:
81
- // 1. The affinity port (if different from startPort)
82
- // 2. startPort, startPort+1, startPort+2, ...
83
- const portsToTry: number[] = [];
84
- if (affinityPort) portsToTry.push(affinityPort);
85
- for (let i = 0; i < maxAttempts; i++) {
86
- const p = startPort + i;
87
- if (p !== affinityPort) portsToTry.push(p);
88
- }
89
-
90
- function tryNext(index: number) {
91
- if (index >= portsToTry.length) {
92
- reject(new Error(
93
- "All attempted ports are in use. " +
94
- "Stop other Rebase instances or specify a different port with --port."
95
- ));
96
- return;
97
- }
98
-
99
- const port = portsToTry[index];
100
- attempt++;
101
-
102
- const onError = (err: NodeJS.ErrnoException) => {
103
- if (err.code === "EADDRINUSE") {
104
- server.removeListener("error", onError);
105
- tryNext(index + 1);
106
- } else {
107
- reject(err);
108
- }
109
- };
110
-
111
- server.once("error", onError);
112
-
113
- server.listen(port, host, () => {
114
- server.removeListener("error", onError);
115
-
116
- // Write the port file so the CLI can pick it up
117
- if (portFileDir) {
118
- try {
119
- const portFile = path.join(portFileDir, DEV_PORT_FILENAME);
120
- fs.writeFileSync(portFile, String(port), "utf-8");
121
- } catch {
122
- // Non-fatal — the CLI will fall back to parsing stdout
123
- }
124
-
125
- // Write .rebase/state.json so external scripts can discover
126
- // the running server port, URL, etc.
127
- writeStateFile(portFileDir, port, options?.serviceKey);
128
- }
129
-
130
- resolve(port);
131
- });
132
- }
133
-
134
- tryNext(0);
135
- });
136
- }
137
-
138
- /**
139
- * Clean up the dev port file and state file (call on graceful shutdown).
140
- */
141
- export function cleanupDevPortFile(dir: string): void {
142
- try {
143
- const portFile = path.join(dir, DEV_PORT_FILENAME);
144
- if (fs.existsSync(portFile)) {
145
- fs.unlinkSync(portFile);
146
- }
147
- } catch {
148
- // ignore
149
- }
150
- try {
151
- const stateFile = path.join(dir, ".rebase", "state.json");
152
- if (fs.existsSync(stateFile)) {
153
- fs.unlinkSync(stateFile);
154
- }
155
- } catch {
156
- // ignore
157
- }
158
- }
159
-
160
- /**
161
- * Write `.rebase/state.json` with runtime info for external scripts.
162
- *
163
- * Scripts can read this file to discover:
164
- * - `port` — the actual port the backend is listening on
165
- * - `baseUrl` — full URL including protocol and port
166
- * - `pid` — the backend process ID
167
- * - `startedAt` — ISO timestamp of when the server started
168
- * - `serviceKey` — (dev only) the REBASE_SERVICE_KEY for MCP auto-discovery
169
- *
170
- * @example Reading from a script:
171
- * ```ts
172
- * const state = JSON.parse(fs.readFileSync('.rebase/state.json', 'utf-8'));
173
- * const apiUrl = state.baseUrl; // "http://localhost:3519"
174
- * ```
175
- */
176
- function writeStateFile(projectRoot: string, port: number, serviceKey?: string): void {
177
- try {
178
- const rebaseDir = path.join(projectRoot, ".rebase");
179
- if (!fs.existsSync(rebaseDir)) {
180
- fs.mkdirSync(rebaseDir, { recursive: true });
181
- }
182
- const stateFile = path.join(rebaseDir, "state.json");
183
- const state: Record<string, unknown> = {
184
- port,
185
- baseUrl: `http://localhost:${port}`,
186
- pid: process.pid,
187
- startedAt: new Date().toISOString()
188
- };
189
- if (serviceKey) {
190
- state.serviceKey = serviceKey;
191
- }
192
- fs.writeFileSync(stateFile, JSON.stringify(state, null, 2), "utf-8");
193
- } catch {
194
- // Non-fatal
195
- }
196
- }
@@ -1,143 +0,0 @@
1
- /**
2
- * Structured Logger for Rebase Backend
3
- *
4
- * Outputs JSON lines when `NODE_ENV=production`, human-readable prefixed
5
- * lines otherwise. Designed to work with Google Cloud Logging severity levels.
6
- *
7
- * Usage:
8
- * import { logger } from "./utils/logger";
9
- * logger.info("Server started", { port: 3001 });
10
- * logger.error("Request failed", { path: "/api/test", error: err });
11
- */
12
-
13
- export type LogLevel = "debug" | "info" | "warn" | "error";
14
-
15
- /** Google Cloud Logging severity strings. */
16
- const GCP_SEVERITY: Record<LogLevel, string> = {
17
- debug: "DEBUG",
18
- info: "INFO",
19
- warn: "WARNING",
20
- error: "ERROR"
21
- };
22
-
23
- const LOG_PRIORITY: Record<LogLevel, number> = {
24
- debug: 0,
25
- info: 1,
26
- warn: 2,
27
- error: 3
28
- };
29
-
30
- export interface LogEntry {
31
- severity: string;
32
- message: string;
33
- timestamp: string;
34
- [key: string]: unknown;
35
- }
36
-
37
- export interface Logger {
38
- debug(message: string, data?: Record<string, unknown>): void;
39
- info(message: string, data?: Record<string, unknown>): void;
40
- warn(message: string, data?: Record<string, unknown>): void;
41
- error(message: string, data?: Record<string, unknown>): void;
42
- child(defaultFields: Record<string, unknown>): Logger;
43
- }
44
-
45
- function isProduction(): boolean {
46
- return process.env.NODE_ENV === "production";
47
- }
48
-
49
- function getMinLevel(): LogLevel {
50
- const env = (process.env.LOG_LEVEL || "info").toLowerCase();
51
- if (env in LOG_PRIORITY) return env as LogLevel;
52
- return "info";
53
- }
54
-
55
- /**
56
- * Serialise an Error into a plain object (stack + message).
57
- * Handles non-Error values gracefully.
58
- */
59
- function serialiseError(value: unknown): Record<string, unknown> {
60
- if (value instanceof Error) {
61
- return {
62
- name: value.name,
63
- message: value.message,
64
- stack: value.stack
65
- };
66
- }
67
- return { value: String(value) };
68
- }
69
-
70
- function formatData(data?: Record<string, unknown>): Record<string, unknown> | undefined {
71
- if (!data) return undefined;
72
- const out: Record<string, unknown> = {};
73
- for (const [key, val] of Object.entries(data)) {
74
- if (val instanceof Error) {
75
- out[key] = serialiseError(val);
76
- } else {
77
- out[key] = val;
78
- }
79
- }
80
- return out;
81
- }
82
-
83
- function createLogger(defaultFields: Record<string, unknown> = {}): Logger {
84
- const minLevel = getMinLevel();
85
-
86
- function emit(level: LogLevel, message: string, data?: Record<string, unknown>): void {
87
- if (LOG_PRIORITY[level] < LOG_PRIORITY[minLevel]) return;
88
-
89
- const merged = { ...defaultFields,
90
- ...formatData(data) };
91
-
92
- if (isProduction()) {
93
- // Structured JSON for Cloud Logging
94
- const entry: LogEntry = {
95
- severity: GCP_SEVERITY[level],
96
- message,
97
- timestamp: new Date().toISOString(),
98
- ...merged
99
- };
100
- const line = JSON.stringify(entry);
101
-
102
- if (level === "error") {
103
- process.stderr.write(line + "\n");
104
- } else {
105
- process.stdout.write(line + "\n");
106
- }
107
- } else {
108
- // Human-readable for development
109
- const prefix = level === "error" ? "❌"
110
- : level === "warn" ? "⚠️"
111
- : level === "info" ? "ℹ️"
112
- : "🐛";
113
- const extra = Object.keys(merged).length > 0 ? ` ${JSON.stringify(merged)}` : "";
114
- const out = `${prefix} [${level.toUpperCase()}] ${message}${extra}`;
115
-
116
- if (level === "error") {
117
- console.error(out);
118
- } else if (level === "warn") {
119
- console.warn(out);
120
- } else {
121
- console.log(out);
122
- }
123
- }
124
- }
125
-
126
- return {
127
- debug: (msg, data) => emit("debug", msg, data),
128
- info: (msg, data) => emit("info", msg, data),
129
- warn: (msg, data) => emit("warn", msg, data),
130
- error: (msg, data) => emit("error", msg, data),
131
- child(fields: Record<string, unknown>): Logger {
132
- return createLogger({ ...defaultFields,
133
- ...fields });
134
- }
135
- };
136
- }
137
-
138
- /**
139
- * Singleton logger instance.
140
- * In production: emits JSON lines with `severity`, `message`, `timestamp`.
141
- * In development: emits human-readable prefixed lines.
142
- */
143
- export const logger: Logger = createLogger();
@@ -1,40 +0,0 @@
1
- /**
2
- * Configure console log levels based on environment variable
3
- * Call this early in your application to set up proper logging levels
4
- */
5
- export function configureLogLevel(logLevel?: string) {
6
- const LOG_LEVEL = logLevel || process.env.LOG_LEVEL || "info";
7
- const logLevels = { error: 0,
8
- warn: 1,
9
- info: 2,
10
- debug: 3 };
11
- const currentLevel = logLevels[LOG_LEVEL as keyof typeof logLevels] ?? 2;
12
-
13
- if (currentLevel < 3) console.debug = () => { };
14
- if (currentLevel < 2) console.log = () => { };
15
- if (currentLevel < 1) console.warn = () => { };
16
- if (currentLevel < 0) console.error = () => { };
17
- }
18
-
19
- /** Module-scoped backup of the original console methods. */
20
- let originalConsole: Pick<Console, "log" | "warn" | "error" | "debug"> | undefined;
21
-
22
- /**
23
- * Reset console methods to their original state
24
- */
25
- export function resetConsole() {
26
- // Store original methods if not already stored
27
- if (!originalConsole) {
28
- originalConsole = {
29
- log: console.log,
30
- warn: console.warn,
31
- error: console.error,
32
- debug: console.debug
33
- };
34
- }
35
-
36
- console.log = originalConsole.log;
37
- console.warn = originalConsole.warn;
38
- console.error = originalConsole.error;
39
- console.debug = originalConsole.debug;
40
- }
@@ -1,40 +0,0 @@
1
- /**
2
- * X-Request-ID Middleware for Hono.
3
- *
4
- * Generates a unique request identifier (UUID v4) for every inbound
5
- * request, or propagates an existing `X-Request-ID` header from the
6
- * caller. The ID is:
7
- *
8
- * 1. Stored in the Hono context (`c.get("requestId")`)
9
- * 2. Echoed back on the response as `X-Request-ID`
10
- *
11
- * Downstream middleware and handlers (request logger, error handler,
12
- * etc.) read the ID from context to include it in log entries and
13
- * error responses, enabling end-to-end request tracing across services.
14
- *
15
- * @example
16
- * ```ts
17
- * import { requestId } from "@rebasepro/server-core";
18
- * app.use("/*", requestId());
19
- * ```
20
- */
21
- import { randomUUID } from "node:crypto";
22
- import type { MiddlewareHandler } from "hono";
23
- import type { HonoEnv } from "../api/types";
24
-
25
- export const REQUEST_ID_HEADER = "X-Request-ID";
26
-
27
- const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
28
-
29
- export function requestId(): MiddlewareHandler<HonoEnv> {
30
- return async (c, next) => {
31
- const incoming = c.req.header(REQUEST_ID_HEADER);
32
- const id = incoming && UUID_RE.test(incoming) ? incoming : randomUUID();
33
-
34
- c.set("requestId", id);
35
-
36
- await next();
37
-
38
- c.header(REQUEST_ID_HEADER, id);
39
- };
40
- }
@@ -1,72 +0,0 @@
1
- /**
2
- * Structured HTTP request logging middleware for Hono.
3
- *
4
- * Logs every request with method, path, status code, latency, and
5
- * content-length. In production, outputs JSON for Cloud Logging; in
6
- * development, emits a coloured one-liner.
7
- *
8
- * @example
9
- * ```ts
10
- * import { requestLogger } from "@rebasepro/server-core";
11
- * app.use("/*", requestLogger());
12
- * ```
13
- */
14
- import type { MiddlewareHandler } from "hono";
15
- import { logger as log } from "./logger";
16
-
17
- export interface RequestLoggerOptions {
18
- /** Paths to skip logging (e.g. "/health"). Supports exact match. */
19
- skip?: string[];
20
- }
21
-
22
- export function requestLogger(options?: RequestLoggerOptions): MiddlewareHandler {
23
- const skipPaths = new Set(options?.skip ?? ["/health", "/favicon.ico"]);
24
-
25
- return async (c, next) => {
26
- const start = performance.now();
27
- const method = c.req.method;
28
- const path = c.req.path;
29
-
30
- // Skip noisy endpoints
31
- if (skipPaths.has(path)) {
32
- return next();
33
- }
34
-
35
- await next();
36
-
37
- const latencyMs = Math.round(performance.now() - start);
38
- const status = c.res.status;
39
- const contentLength = c.res.headers.get("content-length");
40
-
41
- const data: Record<string, unknown> = {
42
- method,
43
- path,
44
- status,
45
- latencyMs
46
- };
47
-
48
- // Include request correlation ID if available
49
- const reqId = c.get("requestId");
50
- if (reqId) {
51
- data.requestId = reqId;
52
- }
53
-
54
- if (contentLength) {
55
- data.contentLength = parseInt(contentLength, 10);
56
- }
57
-
58
- // Extract user ID from context if auth middleware ran
59
- const userId = c.get("userId" as never) as string | undefined;
60
- if (userId) {
61
- data.userId = userId;
62
- }
63
-
64
- if (status >= 500) {
65
- log.error("request", data);
66
- } else if (status >= 400) {
67
- log.warn("request", data);
68
- } else {
69
- log.info("request", data);
70
- }
71
- };
72
- }