@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
package/src/api/types.ts DELETED
@@ -1,104 +0,0 @@
1
- import { EntityCollection, VectorSearchParams, LogicalCondition } from "@rebasepro/types";
2
- import { AuthResult } from "../auth/middleware";
3
- import { NodePgDatabase } from "drizzle-orm/node-postgres";
4
- import { DataDriver } from "@rebasepro/types";
5
- import type { ApiKeyMasked } from "../auth/api-keys/api-key-types";
6
-
7
- /**
8
- * Hono Environment Variables
9
- * Passed to generic Hono<HonoEnv> to type `c.get()`
10
- */
11
- export type HonoEnv = {
12
- Variables: {
13
- user?: AuthResult | { userId?: string, roles?: string[] };
14
- driver?: DataDriver;
15
- /** Set when the request is authenticated via a Service API Key. */
16
- apiKey?: ApiKeyMasked;
17
- /** Unique request correlation ID (generated or propagated from X-Request-ID header). */
18
- requestId?: string;
19
- }
20
- };
21
-
22
- /**
23
- * Configuration for API generation
24
- */
25
- /**
26
- * Configuration for API generation
27
- */
28
- export interface ApiConfig {
29
- collections?: EntityCollection[];
30
- collectionsDir?: string;
31
- /**
32
- * Declared data sources. When provided, collections on a `direct`/`custom`
33
- * transport are treated as client-only and no server routes are generated
34
- * for them.
35
- */
36
- dataSources?: import("@rebasepro/types").DataSourceDefinition[];
37
- basePath?: string;
38
- enableGraphQL?: boolean;
39
- enableREST?: boolean;
40
- cors?: {
41
- origin?: string | string[] | boolean;
42
- credentials?: boolean;
43
- };
44
- /** Whether auth is required for API endpoints (default: true) */
45
- requireAuth?: boolean;
46
- /** Optional custom validator for authentication */
47
- authValidator?: (c: import("hono").Context<import("./types").HonoEnv>) => Promise<AuthResult>;
48
- pagination?: {
49
- defaultLimit: number;
50
- maxLimit: number;
51
- };
52
- }
53
-
54
- /**
55
- * Context passed to resolvers and handlers
56
- */
57
- export interface ApiContext {
58
- user?: AuthResult;
59
- collections: Map<string, EntityCollection>;
60
- db: NodePgDatabase; // Drizzle DB instance
61
- }
62
-
63
- /**
64
- * Standard API response format
65
- */
66
- export interface ApiResponse<T = unknown> {
67
- data?: T;
68
- error?: {
69
- message: string;
70
- code?: string;
71
- details?: unknown;
72
- };
73
- meta?: {
74
- total?: number;
75
- page?: number;
76
- limit?: number;
77
- hasMore?: boolean;
78
- };
79
- }
80
-
81
- /**
82
- * Query options for API endpoints
83
- */
84
- export interface QueryOptions {
85
- limit?: number;
86
- offset?: number;
87
- where?: Record<string, unknown>;
88
- logical?: LogicalCondition;
89
- orderBy?: Array<{ field: string; direction: "asc" | "desc" }>;
90
- include?: string[];
91
- /** Columns to return in the response (field-level selection) */
92
- fields?: string[];
93
- /** Vector similarity search configuration */
94
- vectorSearch?: VectorSearchParams;
95
- }
96
-
97
- /**
98
- * Relation resolution configuration
99
- */
100
- export interface RelationConfig {
101
- relationName: string;
102
- depth?: number;
103
- include?: string[];
104
- }
@@ -1,114 +0,0 @@
1
- /**
2
- * Adapter Auth Middleware
3
- *
4
- * Creates a Hono middleware that delegates authentication to an `AuthAdapter`
5
- * instead of hardcoded JWT verification. This is used when the user passes
6
- * an `AuthAdapter` to `initializeRebaseBackend()`.
7
- *
8
- * The middleware:
9
- * 1. Checks for API key tokens (`rk_` prefix) first — these are Rebase-level
10
- * 2. Falls back to `adapter.verifyRequest(request)` to resolve the user
11
- * 3. Scopes the DataDriver via `withAuth()` for RLS
12
- * 4. Enforces auth (401) when `requireAuth` is true and no user is found
13
- *
14
- * The behavior is identical to `createAuthMiddleware()` — only the
15
- * token verification strategy is pluggable.
16
- */
17
-
18
- import type { MiddlewareHandler, Context } from "hono";
19
- import type { DataDriver, AuthAdapter } from "@rebasepro/types";
20
- import type { HonoEnv } from "../api/types";
21
- import type { ApiKeyStore } from "./api-keys/api-key-store";
22
- import { scopeDataDriver } from "./rls-scope";
23
- import { validateApiKey } from "./api-keys/api-key-middleware";
24
- import { logger } from "../utils/logger";
25
-
26
- export interface AdapterAuthMiddlewareOptions {
27
- /** The auth adapter to delegate verification to. */
28
- adapter: AuthAdapter;
29
- /** The DataDriver to scope via withAuth() for RLS. */
30
- driver: DataDriver;
31
- /**
32
- * Optional per-request driver resolver for multi-data-source backends.
33
- * Returns the unscoped delegate to use for this request (e.g. Postgres vs
34
- * Mongo). When omitted, `driver` is used for every request.
35
- */
36
- resolveDriver?: (c: Context<HonoEnv>) => DataDriver;
37
- /**
38
- * If true, return 401 when no valid user is resolved.
39
- * Defaults to `true` (secure by default).
40
- */
41
- requireAuth?: boolean;
42
- /** Optional API key store — when provided, `rk_` bearer tokens are accepted. */
43
- apiKeyStore?: ApiKeyStore;
44
- }
45
-
46
- /**
47
- * Create a Hono middleware that uses an `AuthAdapter` for request verification.
48
- */
49
- export function createAdapterAuthMiddleware(options: AdapterAuthMiddlewareOptions): MiddlewareHandler<HonoEnv> {
50
- const { adapter, driver: baseDriver, resolveDriver, requireAuth: enforceAuth = true, apiKeyStore } = options;
51
-
52
- return async (c, next) => {
53
- // Pick the per-request delegate (multi-data-source) before scoping.
54
- const driver = resolveDriver ? resolveDriver(c) : baseDriver;
55
- // ── API Key check (Rebase-level, independent of auth adapter) ────
56
- if (apiKeyStore) {
57
- const authHeader = c.req.header("authorization") || "";
58
- const token = authHeader.startsWith("Bearer ") ? authHeader.slice(7) : "";
59
- if (token.startsWith("rk_")) {
60
- const result = await validateApiKey(c, token, { store: apiKeyStore,
61
- driver });
62
- if (result === true) return next();
63
- return result;
64
- }
65
- }
66
-
67
- let authenticatedUser = null;
68
-
69
- try {
70
- authenticatedUser = await adapter.verifyRequest(c.req.raw);
71
- } catch (error) {
72
- // adapter.verifyRequest() threw — reject the request (fail closed)
73
- return c.json({ error: { message: "Unauthorized",
74
- code: "UNAUTHORIZED" } }, 401);
75
- }
76
-
77
- if (authenticatedUser) {
78
- // Authenticated — set user context and scope driver
79
- c.set("user", {
80
- userId: authenticatedUser.uid,
81
- email: authenticatedUser.email,
82
- roles: authenticatedUser.roles
83
- });
84
- try {
85
- c.set("driver", await scopeDataDriver(driver, {
86
- uid: authenticatedUser.uid,
87
- roles: authenticatedUser.roles
88
- }));
89
- } catch (error) {
90
- logger.error("[AUTH-ADAPTER] RLS scoping failed for authenticated user", { error: error });
91
- return c.json({ error: { message: "Internal authentication error",
92
- code: "INTERNAL_ERROR" } }, 500);
93
- }
94
- } else {
95
- // Not authenticated — scope as anon for RLS evaluation
96
- try {
97
- c.set("driver", await scopeDataDriver(driver, { uid: "anon",
98
- roles: ["anon"] }));
99
- } catch (error) {
100
- logger.error("[AUTH-ADAPTER] Failed to create anon-scoped driver", { error: error });
101
- return c.json({ error: { message: "Server configuration error",
102
- code: "INTERNAL_ERROR" } }, 500);
103
- }
104
- }
105
-
106
- // Enforce auth if required
107
- if (enforceAuth && !c.get("user")) {
108
- return c.json({ error: { message: "Unauthorized: Authentication required",
109
- code: "UNAUTHORIZED" } }, 401);
110
- }
111
-
112
- return next();
113
- };
114
- }
@@ -1,36 +0,0 @@
1
- /**
2
- * Admin endpoint for listing all roles.
3
- *
4
- * Mounts: GET /roles
5
- */
6
-
7
- import { Hono } from "hono";
8
- import { errorHandler } from "../api/errors";
9
- import type { AuthRepository } from "./interfaces";
10
- import { createRequireAuth, requireAdmin } from "./middleware";
11
- import type { HonoEnv } from "../api/types";
12
-
13
- export interface AdminRolesRouteConfig {
14
- authRepo: AuthRepository;
15
- serviceKey?: string;
16
- }
17
-
18
- /**
19
- * Create a standalone admin route for listing roles.
20
- *
21
- * Mounts: GET /roles
22
- */
23
- export function createAdminRolesRoute(config: AdminRolesRouteConfig): Hono<HonoEnv> {
24
- const router = new Hono<HonoEnv>();
25
- const authRepo = config.authRepo;
26
-
27
- router.onError(errorHandler);
28
- router.use("/*", createRequireAuth({ serviceKey: config.serviceKey }));
29
-
30
- router.get("/roles", requireAdmin, async (c) => {
31
- const roles = await authRepo.listRoles();
32
- return c.json({ roles });
33
- });
34
-
35
- return router;
36
- }
@@ -1,236 +0,0 @@
1
- /**
2
- * Admin User Operations
3
- *
4
- * Shared utilities and orchestration for admin-initiated user management
5
- * (user creation via REST API, password reset via admin panel).
6
- *
7
- * Hook resolution order:
8
- * 1. Collection-level hook (`auth.onCreateUser` on the collection) — closest to the data
9
- * 2. Backend-level hook (`AuthHooks.onAdminCreateUser`) — global override
10
- * 3. Built-in default — framework fallback
11
- */
12
-
13
- import { randomBytes, createHash, randomInt } from "node:crypto";
14
- import type { AuthRepository } from "./interfaces";
15
- import type { EmailService, EmailConfig } from "../email";
16
- import type { ResolvedAuthHooks } from "./auth-hooks";
17
- import type { AuthCollectionConfig, AuthCollectionContext } from "@rebasepro/types";
18
- import { getPasswordResetTemplate } from "../email/templates";
19
- import { logger } from "../utils/logger";
20
-
21
- // ─── Shared Crypto Utilities ────────────────────────────────────────────────
22
-
23
- /**
24
- * Generate a cryptographically secure random password that meets strength requirements.
25
- *
26
- * 16 characters, guaranteed at least one uppercase, one lowercase, one digit.
27
- * Ambiguous characters (0, O, 1, l, I) are excluded.
28
- */
29
- export function generateSecurePassword(): string {
30
- const upper = "ABCDEFGHJKLMNPQRSTUVWXYZ";
31
- const lower = "abcdefghjkmnpqrstuvwxyz";
32
- const digits = "23456789";
33
- const all = upper + lower + digits;
34
-
35
- const pick = (chars: string) => chars[randomInt(chars.length)];
36
- const parts = [pick(upper), pick(lower), pick(digits)];
37
-
38
- for (let i = parts.length; i < 16; i++) {
39
- parts.push(pick(all));
40
- }
41
-
42
- // Shuffle
43
- for (let i = parts.length - 1; i > 0; i--) {
44
- const j = randomInt(i + 1);
45
- [parts[i], parts[j]] = [parts[j], parts[i]];
46
- }
47
- return parts.join("");
48
- }
49
-
50
- /**
51
- * Generate a cryptographically secure random token (80 hex characters).
52
- */
53
- export function generateSecureToken(): string {
54
- return randomBytes(40).toString("hex");
55
- }
56
-
57
- /**
58
- * Hash a token for database storage using SHA-256.
59
- */
60
- export function hashToken(token: string): string {
61
- return createHash("sha256").update(token).digest("hex");
62
- }
63
-
64
- // ─── Admin User Creation ────────────────────────────────────────────────────
65
-
66
- /**
67
- * Context needed by admin user creation / password reset operations.
68
- */
69
- export interface AdminUserContext {
70
- authRepo: AuthRepository;
71
- emailService?: EmailService;
72
- emailConfig?: EmailConfig;
73
- resolvedHooks: ResolvedAuthHooks;
74
- /** The parsed auth config from the collection (if `auth` is an object, not just `true`). */
75
- collectionAuthConfig?: AuthCollectionConfig;
76
- }
77
-
78
- /**
79
- * Result of preparing user values for admin-initiated creation.
80
- */
81
- export interface AdminUserPrepareResult {
82
- /** Values ready for `driver.saveEntity()`. */
83
- values: Record<string, unknown>;
84
- /** The cleartext password (for returning to admin or sending via email). */
85
- clearPassword?: string;
86
- /** Whether the hook already handled the invitation email. */
87
- hookHandledEmail: boolean;
88
- /** Whether an invitation was sent (only relevant when hookHandledEmail is true). */
89
- invitationSent: boolean;
90
- }
91
-
92
- /**
93
- * Build the `AuthCollectionContext` facade from server internals.
94
- *
95
- * This is the simplified context exposed to collection-level auth hooks,
96
- * keeping them decoupled from internal interfaces like `AuthRepository`.
97
- */
98
- function buildCollectionContext(ctx: AdminUserContext): AuthCollectionContext {
99
- const isEmailConfigured = !!(ctx.emailService && ctx.emailService.isConfigured());
100
-
101
- return {
102
- hashPassword: (password: string) => ctx.resolvedHooks.hashPassword(password),
103
- sendEmail: isEmailConfigured
104
- ? (options) => ctx.emailService!.send(options)
105
- : undefined,
106
- emailConfigured: isEmailConfigured,
107
- appName: ctx.emailConfig?.appName || "Rebase",
108
- resetPasswordUrl: ctx.emailConfig?.resetPasswordUrl || ""
109
- };
110
- }
111
-
112
- /**
113
- * Prepare user values for an admin-initiated user creation.
114
- *
115
- * Resolution order:
116
- * 1. Collection-level `auth.onCreateUser` — closest to the data
117
- * 2. Backend-level `AuthHooks.onAdminCreateUser` — global override
118
- * 3. Built-in default — generate password → hash → normalize email
119
- *
120
- * The caller is responsible for persisting (via `driver.saveEntity()`).
121
- */
122
- export async function prepareAdminUserValues(
123
- body: Record<string, unknown>,
124
- ctx: AdminUserContext
125
- ): Promise<AdminUserPrepareResult> {
126
- const { resolvedHooks, collectionAuthConfig } = ctx;
127
-
128
- // 1. Collection-level hook (closest to the data)
129
- if (collectionAuthConfig?.onCreateUser) {
130
- const collectionCtx = buildCollectionContext(ctx);
131
- const hookResult = await collectionAuthConfig.onCreateUser(body, collectionCtx);
132
- return {
133
- values: hookResult.values,
134
- clearPassword: hookResult.temporaryPassword,
135
- hookHandledEmail: true,
136
- invitationSent: hookResult.invitationSent ?? false
137
- };
138
- }
139
-
140
- // 2. Backend-level hook (global override)
141
- if (resolvedHooks.onAdminCreateUser) {
142
- const hookResult = await resolvedHooks.onAdminCreateUser(body, {
143
- authRepo: ctx.authRepo,
144
- emailService: ctx.emailService,
145
- emailConfig: ctx.emailConfig,
146
- hashPassword: (password: string) => resolvedHooks.hashPassword(password)
147
- });
148
- return {
149
- values: hookResult.values,
150
- clearPassword: hookResult.temporaryPassword,
151
- hookHandledEmail: true,
152
- invitationSent: hookResult.invitationSent ?? false
153
- };
154
- }
155
-
156
- // 3. Built-in default
157
- const password = body.password as string | undefined;
158
- const clearPassword = password || generateSecurePassword();
159
- const passwordHash = await resolvedHooks.hashPassword(clearPassword);
160
-
161
- const values = { ...body };
162
- values.passwordHash = passwordHash;
163
- if (values.email) {
164
- values.email = (values.email as string).toLowerCase();
165
- }
166
- values.emailVerified = true;
167
- delete values.password;
168
-
169
- return {
170
- values,
171
- clearPassword: password ? undefined : clearPassword,
172
- hookHandledEmail: false,
173
- invitationSent: false
174
- };
175
- }
176
-
177
- /**
178
- * Handle post-creation work for admin-created users.
179
- *
180
- * Sends an invitation email (password-reset link) if email is configured
181
- * and no explicit password was provided. Falls back to returning the
182
- * temporary password if email fails or is not configured.
183
- */
184
- export async function finalizeAdminUserCreation(
185
- entity: { id: string; values: Record<string, unknown> },
186
- clearPassword: string | undefined,
187
- ctx: AdminUserContext
188
- ): Promise<{
189
- temporaryPassword?: string;
190
- invitationSent: boolean;
191
- }> {
192
- // If an explicit password was provided (clearPassword is undefined), nothing to do
193
- if (!clearPassword) {
194
- return { invitationSent: false };
195
- }
196
-
197
- const isEmailConfigured = !!(ctx.emailService && ctx.emailService.isConfigured());
198
-
199
- if (isEmailConfigured) {
200
- try {
201
- const token = generateSecureToken();
202
- const tokenHash = hashToken(token);
203
- const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24 hours
204
-
205
- await ctx.authRepo.createPasswordResetToken(entity.id, tokenHash, expiresAt);
206
-
207
- const baseUrl = ctx.emailConfig?.resetPasswordUrl || "";
208
- const setPasswordUrl = `${baseUrl}/reset-password?token=${token}`;
209
-
210
- const appName = ctx.emailConfig?.appName || "Rebase";
211
- const templateFn = ctx.emailConfig?.templates?.passwordReset;
212
- const emailContent = templateFn
213
- ? templateFn(setPasswordUrl, { email: entity.values.email as string,
214
- displayName: entity.values.displayName as string })
215
- : getPasswordResetTemplate(setPasswordUrl, { email: entity.values.email as string,
216
- displayName: entity.values.displayName as string }, appName);
217
-
218
- await ctx.emailService!.send({
219
- to: entity.values.email as string,
220
- subject: emailContent.subject,
221
- html: emailContent.html,
222
- text: emailContent.text
223
- });
224
- return { invitationSent: true };
225
- } catch (emailError: unknown) {
226
- logger.error("Failed to send reset email", { error: emailError instanceof Error ? emailError.message : emailError });
227
- // Fall back to returning the temporary password
228
- return { temporaryPassword: clearPassword,
229
- invitationSent: false };
230
- }
231
- }
232
-
233
- // No email service — return the temporary password
234
- return { temporaryPassword: clearPassword,
235
- invitationSent: false };
236
- }