@rebasepro/server-core 0.5.0 → 0.6.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 (279) hide show
  1. package/dist/{server-core/src/api → api}/errors.d.ts +5 -2
  2. package/dist/{server-core/src/api → api}/rest/api-generator.d.ts +8 -2
  3. package/dist/{server-core/src/api → api}/types.d.ts +2 -0
  4. package/dist/auth/admin-user-ops.d.ts +79 -0
  5. package/dist/{server-core/src/auth → auth}/api-keys/index.d.ts +2 -2
  6. package/dist/{server-core/src/auth → auth}/auth-hooks.d.ts +37 -9
  7. package/dist/{server-core/src/auth → auth}/builtin-auth-adapter.d.ts +4 -4
  8. package/dist/{server-core/src/auth → auth}/index.d.ts +5 -2
  9. package/dist/auth/mfa-routes.d.ts +6 -0
  10. package/dist/auth/reset-password-admin.d.ts +29 -0
  11. package/dist/auth/session-routes.d.ts +25 -0
  12. package/dist/backend-CIxN4FVm.js +15 -0
  13. package/dist/backend-CIxN4FVm.js.map +1 -0
  14. package/dist/chunk-Dze3rakg.js +42 -0
  15. package/dist/{server-core/src/cron → cron}/cron-scheduler.d.ts +1 -1
  16. package/dist/dist-CZKP-Xz4.js +832 -0
  17. package/dist/dist-CZKP-Xz4.js.map +1 -0
  18. package/dist/env.d.ts +102 -0
  19. package/dist/from-VbwD7xRf.js +3849 -0
  20. package/dist/from-VbwD7xRf.js.map +1 -0
  21. package/dist/{server-core/src/index.d.ts → index.d.ts} +1 -0
  22. package/dist/index.es.js +60867 -50462
  23. package/dist/index.es.js.map +1 -1
  24. package/dist/index.umd.js +73151 -51298
  25. package/dist/index.umd.js.map +1 -1
  26. package/dist/init/docs.d.ts +4 -0
  27. package/dist/init/health.d.ts +2 -0
  28. package/dist/init/middlewares.d.ts +10 -0
  29. package/dist/init/shutdown.d.ts +11 -0
  30. package/dist/init/storage.d.ts +5 -0
  31. package/dist/{server-core/src/init.d.ts → init.d.ts} +4 -4
  32. package/dist/jwt-DHcQRGC3.js +4168 -0
  33. package/dist/jwt-DHcQRGC3.js.map +1 -0
  34. package/dist/logger-BYU66ENZ.js +94 -0
  35. package/dist/logger-BYU66ENZ.js.map +1 -0
  36. package/dist/ms-BeBSuOXN.js +125 -0
  37. package/dist/ms-BeBSuOXN.js.map +1 -0
  38. package/dist/multipart-parser-CedBDOeC.js +299 -0
  39. package/dist/multipart-parser-CedBDOeC.js.map +1 -0
  40. package/dist/src-COaj0G3P.js +1182 -0
  41. package/dist/src-COaj0G3P.js.map +1 -0
  42. package/dist/{server-core/src/storage → storage}/image-transform.d.ts +3 -1
  43. package/dist/utils/request-id.d.ts +4 -0
  44. package/package.json +29 -29
  45. package/src/api/collections_for_test/callbacks_test_collection.ts +7 -6
  46. package/src/api/errors.ts +75 -19
  47. package/src/api/graphql/graphql-schema-generator.ts +15 -10
  48. package/src/api/logs-routes.ts +5 -2
  49. package/src/api/rest/api-generator-count.test.ts +21 -10
  50. package/src/api/rest/api-generator.ts +83 -24
  51. package/src/api/rest/query-parser.ts +18 -12
  52. package/src/api/server.ts +12 -1
  53. package/src/api/types.ts +2 -0
  54. package/src/auth/adapter-middleware.ts +17 -10
  55. package/src/auth/admin-user-ops.ts +236 -0
  56. package/src/auth/api-keys/api-key-middleware.ts +15 -9
  57. package/src/auth/api-keys/api-key-permission-guard.ts +1 -1
  58. package/src/auth/api-keys/api-key-routes.ts +3 -3
  59. package/src/auth/api-keys/api-key-store.ts +14 -8
  60. package/src/auth/api-keys/index.ts +2 -2
  61. package/src/auth/apple-oauth.ts +4 -3
  62. package/src/auth/auth-hooks.ts +50 -10
  63. package/src/auth/bitbucket-oauth.ts +5 -4
  64. package/src/auth/builtin-auth-adapter.ts +60 -39
  65. package/src/auth/custom-auth-adapter.ts +4 -5
  66. package/src/auth/discord-oauth.ts +5 -4
  67. package/src/auth/facebook-oauth.ts +5 -4
  68. package/src/auth/github-oauth.ts +6 -5
  69. package/src/auth/gitlab-oauth.ts +5 -4
  70. package/src/auth/google-oauth.ts +2 -1
  71. package/src/auth/index.ts +6 -2
  72. package/src/auth/jwt.ts +5 -4
  73. package/src/auth/linkedin-oauth.ts +4 -3
  74. package/src/auth/mfa-routes.ts +299 -0
  75. package/src/auth/mfa.ts +2 -1
  76. package/src/auth/microsoft-oauth.ts +5 -4
  77. package/src/auth/middleware.ts +5 -4
  78. package/src/auth/rate-limiter.ts +1 -1
  79. package/src/auth/reset-password-admin.ts +144 -0
  80. package/src/auth/rls-scope.ts +1 -1
  81. package/src/auth/routes.ts +52 -596
  82. package/src/auth/session-routes.ts +341 -0
  83. package/src/auth/slack-oauth.ts +6 -5
  84. package/src/auth/spotify-oauth.ts +5 -4
  85. package/src/auth/twitter-oauth.ts +4 -3
  86. package/src/collections/loader.ts +5 -4
  87. package/src/cron/cron-scheduler.test.ts +23 -11
  88. package/src/cron/cron-scheduler.ts +14 -8
  89. package/src/cron/cron-store.ts +1 -1
  90. package/src/email/smtp-email-service.ts +3 -2
  91. package/src/env.ts +11 -10
  92. package/src/index.ts +1 -0
  93. package/src/init/docs.ts +47 -0
  94. package/src/init/health.ts +37 -0
  95. package/src/init/middlewares.ts +61 -0
  96. package/src/init/shutdown.ts +56 -0
  97. package/src/init/storage.ts +57 -0
  98. package/src/init.ts +85 -279
  99. package/src/serve-spa.ts +12 -5
  100. package/src/services/driver-registry.ts +4 -3
  101. package/src/storage/S3StorageController.ts +1 -2
  102. package/src/storage/image-transform.ts +25 -10
  103. package/src/storage/routes.ts +30 -11
  104. package/src/storage/storage-registry.ts +4 -3
  105. package/src/storage/tus-handler.ts +12 -12
  106. package/src/utils/request-id.ts +40 -0
  107. package/src/utils/request-logger.ts +6 -0
  108. package/test/api-generator.test.ts +90 -2
  109. package/test/api-key-permission-guard.test.ts +24 -12
  110. package/test/auth-routes.test.ts +5 -3
  111. package/test/backend-hooks-data.test.ts +99 -30
  112. package/test/custom-auth-adapter.test.ts +16 -15
  113. package/test/email-templates.test.ts +10 -5
  114. package/test/env.test.ts +10 -10
  115. package/test/function-loader.test.ts +7 -4
  116. package/test/graphql-schema-generator.test.ts +554 -0
  117. package/test/jwt-security.test.ts +1 -1
  118. package/test/query-parser.test.ts +0 -1
  119. package/test/reset-password-admin.test.ts +113 -0
  120. package/test/singleton.test.ts +5 -5
  121. package/test/smtp-email-service.test.ts +21 -21
  122. package/test/webhook-service.test.ts +22 -11
  123. package/tsconfig.json +2 -0
  124. package/tsconfig.prod.json +3 -0
  125. package/vite.config.ts +5 -5
  126. package/dist/common/src/collections/CollectionRegistry.d.ts +0 -56
  127. package/dist/common/src/collections/default-collections.d.ts +0 -9
  128. package/dist/common/src/collections/index.d.ts +0 -2
  129. package/dist/common/src/data/buildRebaseData.d.ts +0 -14
  130. package/dist/common/src/data/query_builder.d.ts +0 -55
  131. package/dist/common/src/index.d.ts +0 -4
  132. package/dist/common/src/util/builders.d.ts +0 -57
  133. package/dist/common/src/util/callbacks.d.ts +0 -6
  134. package/dist/common/src/util/collections.d.ts +0 -11
  135. package/dist/common/src/util/common.d.ts +0 -2
  136. package/dist/common/src/util/conditions.d.ts +0 -26
  137. package/dist/common/src/util/entities.d.ts +0 -58
  138. package/dist/common/src/util/enums.d.ts +0 -3
  139. package/dist/common/src/util/index.d.ts +0 -16
  140. package/dist/common/src/util/navigation_from_path.d.ts +0 -34
  141. package/dist/common/src/util/navigation_utils.d.ts +0 -20
  142. package/dist/common/src/util/parent_references_from_path.d.ts +0 -6
  143. package/dist/common/src/util/paths.d.ts +0 -14
  144. package/dist/common/src/util/permissions.d.ts +0 -14
  145. package/dist/common/src/util/references.d.ts +0 -2
  146. package/dist/common/src/util/relations.d.ts +0 -22
  147. package/dist/common/src/util/resolutions.d.ts +0 -72
  148. package/dist/common/src/util/storage.d.ts +0 -24
  149. package/dist/index-Cr1D21av.js +0 -49
  150. package/dist/index-Cr1D21av.js.map +0 -1
  151. package/dist/server-core/src/auth/admin-routes.d.ts +0 -27
  152. package/dist/server-core/src/env.d.ts +0 -137
  153. package/dist/types/src/controllers/analytics_controller.d.ts +0 -7
  154. package/dist/types/src/controllers/auth.d.ts +0 -104
  155. package/dist/types/src/controllers/client.d.ts +0 -168
  156. package/dist/types/src/controllers/collection_registry.d.ts +0 -46
  157. package/dist/types/src/controllers/customization_controller.d.ts +0 -60
  158. package/dist/types/src/controllers/data.d.ts +0 -207
  159. package/dist/types/src/controllers/data_driver.d.ts +0 -218
  160. package/dist/types/src/controllers/database_admin.d.ts +0 -11
  161. package/dist/types/src/controllers/dialogs_controller.d.ts +0 -36
  162. package/dist/types/src/controllers/effective_role.d.ts +0 -4
  163. package/dist/types/src/controllers/email.d.ts +0 -36
  164. package/dist/types/src/controllers/index.d.ts +0 -18
  165. package/dist/types/src/controllers/local_config_persistence.d.ts +0 -20
  166. package/dist/types/src/controllers/navigation.d.ts +0 -225
  167. package/dist/types/src/controllers/registry.d.ts +0 -63
  168. package/dist/types/src/controllers/side_dialogs_controller.d.ts +0 -67
  169. package/dist/types/src/controllers/side_entity_controller.d.ts +0 -97
  170. package/dist/types/src/controllers/snackbar.d.ts +0 -24
  171. package/dist/types/src/controllers/storage.d.ts +0 -171
  172. package/dist/types/src/index.d.ts +0 -4
  173. package/dist/types/src/rebase_context.d.ts +0 -122
  174. package/dist/types/src/types/auth_adapter.d.ts +0 -301
  175. package/dist/types/src/types/backend.d.ts +0 -571
  176. package/dist/types/src/types/backend_hooks.d.ts +0 -172
  177. package/dist/types/src/types/builders.d.ts +0 -15
  178. package/dist/types/src/types/chips.d.ts +0 -5
  179. package/dist/types/src/types/collections.d.ts +0 -961
  180. package/dist/types/src/types/component_ref.d.ts +0 -47
  181. package/dist/types/src/types/cron.d.ts +0 -102
  182. package/dist/types/src/types/data_source.d.ts +0 -64
  183. package/dist/types/src/types/database_adapter.d.ts +0 -94
  184. package/dist/types/src/types/entities.d.ts +0 -145
  185. package/dist/types/src/types/entity_actions.d.ts +0 -104
  186. package/dist/types/src/types/entity_callbacks.d.ts +0 -173
  187. package/dist/types/src/types/entity_link_builder.d.ts +0 -7
  188. package/dist/types/src/types/entity_overrides.d.ts +0 -10
  189. package/dist/types/src/types/entity_views.d.ts +0 -87
  190. package/dist/types/src/types/export_import.d.ts +0 -21
  191. package/dist/types/src/types/formex.d.ts +0 -40
  192. package/dist/types/src/types/index.d.ts +0 -28
  193. package/dist/types/src/types/locales.d.ts +0 -4
  194. package/dist/types/src/types/modify_collections.d.ts +0 -5
  195. package/dist/types/src/types/plugins.d.ts +0 -282
  196. package/dist/types/src/types/properties.d.ts +0 -1173
  197. package/dist/types/src/types/property_config.d.ts +0 -74
  198. package/dist/types/src/types/relations.d.ts +0 -336
  199. package/dist/types/src/types/slots.d.ts +0 -262
  200. package/dist/types/src/types/translations.d.ts +0 -900
  201. package/dist/types/src/types/user_management_delegate.d.ts +0 -86
  202. package/dist/types/src/types/websockets.d.ts +0 -78
  203. package/dist/types/src/users/index.d.ts +0 -1
  204. package/dist/types/src/users/user.d.ts +0 -50
  205. package/src/auth/admin-routes.ts +0 -534
  206. package/test/admin-routes.test.ts +0 -544
  207. package/test/backend-hooks-admin.test.ts +0 -388
  208. /package/dist/{server-core/src/api → api}/ast-schema-editor.d.ts +0 -0
  209. /package/dist/{server-core/src/api → api}/collections_for_test/callbacks_test_collection.d.ts +0 -0
  210. /package/dist/{server-core/src/api → api}/graphql/graphql-schema-generator.d.ts +0 -0
  211. /package/dist/{server-core/src/api → api}/graphql/index.d.ts +0 -0
  212. /package/dist/{server-core/src/api → api}/index.d.ts +0 -0
  213. /package/dist/{server-core/src/api → api}/logs-routes.d.ts +0 -0
  214. /package/dist/{server-core/src/api → api}/openapi-generator.d.ts +0 -0
  215. /package/dist/{server-core/src/api → api}/rest/index.d.ts +0 -0
  216. /package/dist/{server-core/src/api → api}/rest/query-parser.d.ts +0 -0
  217. /package/dist/{server-core/src/api → api}/schema-editor-routes.d.ts +0 -0
  218. /package/dist/{server-core/src/api → api}/server.d.ts +0 -0
  219. /package/dist/{server-core/src/auth → auth}/adapter-middleware.d.ts +0 -0
  220. /package/dist/{server-core/src/auth → auth}/api-keys/api-key-middleware.d.ts +0 -0
  221. /package/dist/{server-core/src/auth → auth}/api-keys/api-key-permission-guard.d.ts +0 -0
  222. /package/dist/{server-core/src/auth → auth}/api-keys/api-key-routes.d.ts +0 -0
  223. /package/dist/{server-core/src/auth → auth}/api-keys/api-key-store.d.ts +0 -0
  224. /package/dist/{server-core/src/auth → auth}/api-keys/api-key-types.d.ts +0 -0
  225. /package/dist/{server-core/src/auth → auth}/apple-oauth.d.ts +0 -0
  226. /package/dist/{server-core/src/auth → auth}/bitbucket-oauth.d.ts +0 -0
  227. /package/dist/{server-core/src/auth → auth}/crypto-utils.d.ts +0 -0
  228. /package/dist/{server-core/src/auth → auth}/custom-auth-adapter.d.ts +0 -0
  229. /package/dist/{server-core/src/auth → auth}/discord-oauth.d.ts +0 -0
  230. /package/dist/{server-core/src/auth → auth}/facebook-oauth.d.ts +0 -0
  231. /package/dist/{server-core/src/auth → auth}/github-oauth.d.ts +0 -0
  232. /package/dist/{server-core/src/auth → auth}/gitlab-oauth.d.ts +0 -0
  233. /package/dist/{server-core/src/auth → auth}/google-oauth.d.ts +0 -0
  234. /package/dist/{server-core/src/auth → auth}/interfaces.d.ts +0 -0
  235. /package/dist/{server-core/src/auth → auth}/jwt.d.ts +0 -0
  236. /package/dist/{server-core/src/auth → auth}/linkedin-oauth.d.ts +0 -0
  237. /package/dist/{server-core/src/auth → auth}/mfa.d.ts +0 -0
  238. /package/dist/{server-core/src/auth → auth}/microsoft-oauth.d.ts +0 -0
  239. /package/dist/{server-core/src/auth → auth}/middleware.d.ts +0 -0
  240. /package/dist/{server-core/src/auth → auth}/password.d.ts +0 -0
  241. /package/dist/{server-core/src/auth → auth}/rate-limiter.d.ts +0 -0
  242. /package/dist/{server-core/src/auth → auth}/rls-scope.d.ts +0 -0
  243. /package/dist/{server-core/src/auth → auth}/routes.d.ts +0 -0
  244. /package/dist/{server-core/src/auth → auth}/slack-oauth.d.ts +0 -0
  245. /package/dist/{server-core/src/auth → auth}/spotify-oauth.d.ts +0 -0
  246. /package/dist/{server-core/src/auth → auth}/twitter-oauth.d.ts +0 -0
  247. /package/dist/{server-core/src/collections → collections}/BackendCollectionRegistry.d.ts +0 -0
  248. /package/dist/{server-core/src/collections → collections}/loader.d.ts +0 -0
  249. /package/dist/{server-core/src/cron → cron}/cron-loader.d.ts +0 -0
  250. /package/dist/{server-core/src/cron → cron}/cron-routes.d.ts +0 -0
  251. /package/dist/{server-core/src/cron → cron}/cron-store.d.ts +0 -0
  252. /package/dist/{server-core/src/cron → cron}/index.d.ts +0 -0
  253. /package/dist/{server-core/src/db → db}/interfaces.d.ts +0 -0
  254. /package/dist/{server-core/src/email → email}/index.d.ts +0 -0
  255. /package/dist/{server-core/src/email → email}/smtp-email-service.d.ts +0 -0
  256. /package/dist/{server-core/src/email → email}/templates.d.ts +0 -0
  257. /package/dist/{server-core/src/email → email}/types.d.ts +0 -0
  258. /package/dist/{server-core/src/functions → functions}/function-loader.d.ts +0 -0
  259. /package/dist/{server-core/src/functions → functions}/function-routes.d.ts +0 -0
  260. /package/dist/{server-core/src/functions → functions}/index.d.ts +0 -0
  261. /package/dist/{server-core/src/history → history}/history-routes.d.ts +0 -0
  262. /package/dist/{server-core/src/history → history}/index.d.ts +0 -0
  263. /package/dist/{server-core/src/serve-spa.d.ts → serve-spa.d.ts} +0 -0
  264. /package/dist/{server-core/src/services → services}/driver-registry.d.ts +0 -0
  265. /package/dist/{server-core/src/services → services}/webhook-service.d.ts +0 -0
  266. /package/dist/{server-core/src/singleton.d.ts → singleton.d.ts} +0 -0
  267. /package/dist/{server-core/src/storage → storage}/LocalStorageController.d.ts +0 -0
  268. /package/dist/{server-core/src/storage → storage}/S3StorageController.d.ts +0 -0
  269. /package/dist/{server-core/src/storage → storage}/index.d.ts +0 -0
  270. /package/dist/{server-core/src/storage → storage}/routes.d.ts +0 -0
  271. /package/dist/{server-core/src/storage → storage}/storage-registry.d.ts +0 -0
  272. /package/dist/{server-core/src/storage → storage}/tus-handler.d.ts +0 -0
  273. /package/dist/{server-core/src/storage → storage}/types.d.ts +0 -0
  274. /package/dist/{server-core/src/types → types}/index.d.ts +0 -0
  275. /package/dist/{server-core/src/utils → utils}/dev-port.d.ts +0 -0
  276. /package/dist/{server-core/src/utils → utils}/logger.d.ts +0 -0
  277. /package/dist/{server-core/src/utils → utils}/logging.d.ts +0 -0
  278. /package/dist/{server-core/src/utils → utils}/request-logger.d.ts +0 -0
  279. /package/dist/{server-core/src/utils → utils}/sql.d.ts +0 -0
@@ -184,8 +184,9 @@ export class GraphQLSchemaGenerator {
184
184
  id: { type: new GraphQLNonNull(GraphQLString) }
185
185
  },
186
186
  resolve: async (_, args, context: unknown) => {
187
- const ctx = context as { driver: DataDriver };
188
- const ds = ctx.driver || this.driver;
187
+ const ctx = context as { driver?: DataDriver } | undefined;
188
+ const ds = ctx?.driver;
189
+ if (!ds) throw new Error("Scoped driver not available");
189
190
  const entity = await ds.fetchEntity({
190
191
  path: collection.slug,
191
192
  entityId: args.id,
@@ -207,8 +208,9 @@ defaultValue: 0 },
207
208
  orderBy: { type: GraphQLString }
208
209
  },
209
210
  resolve: async (_, args, context: unknown) => {
210
- const ctx = context as { driver: DataDriver };
211
- const ds = ctx.driver || this.driver;
211
+ const ctx = context as { driver?: DataDriver } | undefined;
212
+ const ds = ctx?.driver;
213
+ if (!ds) throw new Error("Scoped driver not available");
212
214
  let filter: FetchCollectionProps["filter"] | undefined;
213
215
  if (args.where) {
214
216
  try {
@@ -259,8 +261,9 @@ defaultValue: 0 },
259
261
  input: { type: new GraphQLNonNull(inputType) }
260
262
  },
261
263
  resolve: async (_, args, context: unknown) => {
262
- const ctx = context as { driver: DataDriver };
263
- const ds = ctx.driver || this.driver;
264
+ const ctx = context as { driver?: DataDriver } | undefined;
265
+ const ds = ctx?.driver;
266
+ if (!ds) throw new Error("Scoped driver not available");
264
267
  const path = collection.slug;
265
268
  const entity = await ds.saveEntity({
266
269
  path,
@@ -280,8 +283,9 @@ defaultValue: 0 },
280
283
  input: { type: new GraphQLNonNull(inputType) }
281
284
  },
282
285
  resolve: async (_, args, context: unknown) => {
283
- const ctx = context as { driver: DataDriver };
284
- const ds = ctx.driver || this.driver;
286
+ const ctx = context as { driver?: DataDriver } | undefined;
287
+ const ds = ctx?.driver;
288
+ if (!ds) throw new Error("Scoped driver not available");
285
289
  const entity = await ds.saveEntity({
286
290
  path: collection.slug,
287
291
  entityId: args.id,
@@ -301,8 +305,9 @@ defaultValue: 0 },
301
305
  },
302
306
  resolve: async (_, args, context: unknown) => {
303
307
  try {
304
- const ctx = context as { driver: DataDriver };
305
- const ds = ctx.driver || this.driver;
308
+ const ctx = context as { driver?: DataDriver } | undefined;
309
+ const ds = ctx?.driver;
310
+ if (!ds) throw new Error("Scoped driver not available");
306
311
  const existingEntity = await ds.fetchEntity({
307
312
  path: collection.slug,
308
313
  entityId: args.id,
@@ -22,7 +22,8 @@ class LogRingBuffer {
22
22
 
23
23
  push(entry: Omit<LogEntry, "id">): void {
24
24
  const id = `log_${++this.idCounter}`;
25
- this.buffer.push({ ...entry, id });
25
+ this.buffer.push({ ...entry,
26
+ id });
26
27
  if (this.buffer.length > this.maxSize) {
27
28
  this.buffer.shift();
28
29
  }
@@ -95,11 +96,13 @@ export function logMiddleware(): MiddlewareHandler<HonoEnv> {
95
96
  const start = Date.now();
96
97
  await next();
97
98
  const duration = Date.now() - start;
99
+ const reqId = c.get("requestId");
98
100
  addLog("info", "api", `${c.req.method} ${c.req.path} ${c.res.status} ${duration}ms`, {
99
101
  method: c.req.method,
100
102
  path: c.req.path,
101
103
  status: c.res.status,
102
- duration
104
+ duration,
105
+ ...(reqId && { requestId: reqId })
103
106
  });
104
107
  };
105
108
  }
@@ -1,4 +1,5 @@
1
1
  import { jest } from "@jest/globals";
2
+ import { Hono } from "hono";
2
3
  import { RestApiGenerator } from "./api-generator";
3
4
  import type { DataDriver, Entity, EntityCollection, FetchCollectionProps } from "@rebasepro/types";
4
5
 
@@ -27,6 +28,21 @@ function createTestCollection(slug: string): EntityCollection {
27
28
  } as unknown as EntityCollection;
28
29
  }
29
30
 
31
+ /**
32
+ * Wraps generated routes in a parent Hono app that injects the driver
33
+ * into context — replicating what auth middleware does in production.
34
+ */
35
+ function createApp(collections: EntityCollection[], driver: DataDriver): Hono {
36
+ const parent = new Hono();
37
+ parent.use("/*", async (c, next) => {
38
+ c.set("driver", driver);
39
+ await next();
40
+ });
41
+ const generator = new RestApiGenerator(collections, driver);
42
+ parent.route("/", generator.generateRoutes());
43
+ return parent;
44
+ }
45
+
30
46
  describe("RestApiGenerator - Count Endpoint", () => {
31
47
  let driver: DataDriver;
32
48
  let collection: EntityCollection;
@@ -39,8 +55,7 @@ describe("RestApiGenerator - Count Endpoint", () => {
39
55
  });
40
56
 
41
57
  it("GET /products/count should return a count object", async () => {
42
- const generator = new RestApiGenerator([collection], driver);
43
- const app = generator.generateRoutes();
58
+ const app = createApp([collection], driver);
44
59
 
45
60
  const res = await app.request("/products/count");
46
61
  expect(res.status).toBe(200);
@@ -50,8 +65,7 @@ describe("RestApiGenerator - Count Endpoint", () => {
50
65
  });
51
66
 
52
67
  it("should pass filters to countEntities driver", async () => {
53
- const generator = new RestApiGenerator([collection], driver);
54
- const app = generator.generateRoutes();
68
+ const app = createApp([collection], driver);
55
69
 
56
70
  const res = await app.request("/products/count?status=eq.active");
57
71
  expect(res.status).toBe(200);
@@ -67,8 +81,7 @@ describe("RestApiGenerator - Count Endpoint", () => {
67
81
  });
68
82
 
69
83
  it("should pass searchString to countEntities driver", async () => {
70
- const generator = new RestApiGenerator([collection], driver);
71
- const app = generator.generateRoutes();
84
+ const app = createApp([collection], driver);
72
85
 
73
86
  const res = await app.request("/products/count?searchString=widget");
74
87
  expect(res.status).toBe(200);
@@ -83,8 +96,7 @@ describe("RestApiGenerator - Count Endpoint", () => {
83
96
 
84
97
  it("should return 0 when countEntities is not available on driver", async () => {
85
98
  const driverWithoutCount = createMockDriver({ countEntities: undefined });
86
- const generator = new RestApiGenerator([collection], driverWithoutCount);
87
- const app = generator.generateRoutes();
99
+ const app = createApp([collection], driverWithoutCount);
88
100
 
89
101
  const res = await app.request("/products/count");
90
102
  expect(res.status).toBe(200);
@@ -100,8 +112,7 @@ describe("RestApiGenerator - Count Endpoint", () => {
100
112
  countEntities: jest.fn<NonNullable<DataDriver["countEntities"]>>().mockResolvedValue(99),
101
113
  fetchEntity: fetchEntity as unknown as DataDriver["fetchEntity"]
102
114
  });
103
- const generator = new RestApiGenerator([collection], driverCustom);
104
- const app = generator.generateRoutes();
115
+ const app = createApp([collection], driverCustom);
105
116
 
106
117
  const res = await app.request("/products/count");
107
118
  expect(res.status).toBe(200);
@@ -1,10 +1,11 @@
1
1
  import { Hono } from "hono";
2
- import { DataDriver, Entity, EntityCollection, FetchCollectionProps, DataHooks, BackendHookContext, RestFetchService } from "@rebasepro/types";
2
+ import { AuthAdapter, DataDriver, Entity, EntityCollection, FetchCollectionProps, DataHooks, BackendHookContext, RestFetchService } from "@rebasepro/types";
3
3
  import { QueryOptions, HonoEnv } from "../types";
4
4
  import { ApiError, isRebaseApiError } from "../errors";
5
5
  import { parseQueryOptions } from "./query-parser";
6
6
  import { httpMethodToOperation, isOperationAllowed } from "../../auth/api-keys/api-key-permission-guard";
7
7
  import type { ApiKeyMasked } from "../../auth/api-keys/api-key-types";
8
+ import { logger } from "../../utils/logger";
8
9
 
9
10
 
10
11
  /**
@@ -16,11 +17,18 @@ export class RestApiGenerator {
16
17
  private router: Hono<HonoEnv>;
17
18
  private driver: DataDriver;
18
19
  private dataHooks?: DataHooks;
19
-
20
- constructor(collections: EntityCollection[], driver: DataDriver, dataHooks?: DataHooks) {
20
+ private authAdapter?: AuthAdapter;
21
+
22
+ constructor(
23
+ collections: EntityCollection[],
24
+ driver: DataDriver,
25
+ dataHooks?: DataHooks,
26
+ authAdapter?: AuthAdapter
27
+ ) {
21
28
  this.collections = collections;
22
29
  this.driver = driver;
23
30
  this.dataHooks = dataHooks;
31
+ this.authAdapter = authAdapter;
24
32
  this.router = new Hono<HonoEnv>();
25
33
  }
26
34
 
@@ -28,7 +36,8 @@ export class RestApiGenerator {
28
36
  private buildHookContext(c: { get: (key: string) => unknown }, method: BackendHookContext["method"]): BackendHookContext {
29
37
  const user = c.get("user") as { userId: string; roles?: string[] } | undefined;
30
38
  return {
31
- requestUser: user ? { userId: user.userId, roles: user.roles ?? [] } : undefined,
39
+ requestUser: user ? { userId: user.userId,
40
+ roles: user.roles ?? [] } : undefined,
32
41
  method
33
42
  };
34
43
  }
@@ -56,7 +65,7 @@ export class RestApiGenerator {
56
65
  */
57
66
  private enforceApiKeyPermission(
58
67
  c: { get: (key: string) => unknown; req: { method: string } },
59
- collectionSlug: string,
68
+ collectionSlug: string
60
69
  ): void {
61
70
  const apiKey = c.get("apiKey") as ApiKeyMasked | undefined;
62
71
  if (!apiKey) return; // Not an API key request — skip
@@ -65,11 +74,21 @@ export class RestApiGenerator {
65
74
  if (!isOperationAllowed(apiKey.permissions, collectionSlug, operation)) {
66
75
  throw ApiError.forbidden(
67
76
  `API key does not have "${operation}" permission for collection "${collectionSlug}"`,
68
- "API_KEY_FORBIDDEN",
77
+ "API_KEY_FORBIDDEN"
69
78
  );
70
79
  }
71
80
  }
72
81
 
82
+ /**
83
+ * Get the request-scoped driver. Throws if none is set — never falls
84
+ * back to the unscoped `this.driver` to avoid bypassing RLS/auth.
85
+ */
86
+ private getScopedDriver(c: { get: (key: string) => unknown }): DataDriver {
87
+ const driver = c.get("driver") as DataDriver | undefined;
88
+ if (!driver) throw ApiError.internal("Scoped driver not available");
89
+ return driver;
90
+ }
91
+
73
92
  /**
74
93
  * Get the typed RestFetchService from a driver if it exposes one (for include support).
75
94
  */
@@ -90,7 +109,7 @@ export class RestApiGenerator {
90
109
  const queryDict = c.req.queries();
91
110
  const queryOptions = parseQueryOptions(queryDict);
92
111
  const searchString = Array.isArray(queryDict.searchString) ? queryDict.searchString[queryDict.searchString.length - 1] : undefined;
93
- const driver = c.get("driver") || this.driver;
112
+ const driver = this.getScopedDriver(c);
94
113
 
95
114
  const total = await this.countRawEntities(driver, resolvedCollection, queryOptions, searchString);
96
115
  return c.json({ count: total });
@@ -103,7 +122,7 @@ export class RestApiGenerator {
103
122
  const queryOptions = parseQueryOptions(queryDict);
104
123
  const searchString = Array.isArray(queryDict.searchString) ? queryDict.searchString[queryDict.searchString.length - 1] : undefined;
105
124
 
106
- const driver = c.get("driver") || this.driver;
125
+ const driver = this.getScopedDriver(c);
107
126
  const fetchService = this.getFetchService(driver);
108
127
  const hookCtx = this.buildHookContext(c, "GET");
109
128
 
@@ -163,7 +182,7 @@ export class RestApiGenerator {
163
182
  const id = c.req.param("id");
164
183
  const queryDict = c.req.queries();
165
184
  const queryOptions = parseQueryOptions(queryDict);
166
- const driver = c.get("driver") || this.driver;
185
+ const driver = this.getScopedDriver(c);
167
186
  const fetchService = this.getFetchService(driver);
168
187
  const hookCtx = this.buildHookContext(c, "GET");
169
188
 
@@ -207,7 +226,7 @@ export class RestApiGenerator {
207
226
  this.router.post(basePath, async (c) => {
208
227
  try {
209
228
  this.enforceApiKeyPermission(c, collection.slug);
210
- const driver = c.get("driver") || this.driver;
229
+ const driver = this.getScopedDriver(c);
211
230
  const path = collection.slug;
212
231
  const hookCtx = this.buildHookContext(c, "POST");
213
232
 
@@ -217,6 +236,46 @@ export class RestApiGenerator {
217
236
  body = await this.dataHooks.beforeSave(path, body, undefined, hookCtx);
218
237
  }
219
238
 
239
+ const isAuth = collection.auth;
240
+ const isAuthCollection = isAuth === true || (isAuth && typeof isAuth === "object" && isAuth.enabled === true);
241
+
242
+ if (isAuthCollection && this.authAdapter?.prepareUserCreation) {
243
+ const collectionAuthConfig = typeof isAuth === "object" ? isAuth : undefined;
244
+ const prepared = await this.authAdapter.prepareUserCreation(body, collectionAuthConfig);
245
+
246
+ const entity = await driver.saveEntity({
247
+ path,
248
+ values: prepared.values,
249
+ collection: resolvedCollection,
250
+ status: "new"
251
+ });
252
+
253
+ const result = prepared.hookHandledEmail
254
+ ? { temporaryPassword: prepared.clearPassword,
255
+ invitationSent: prepared.invitationSent }
256
+ : this.authAdapter.finalizeUserCreation
257
+ ? await this.authAdapter.finalizeUserCreation(
258
+ { id: entity.id as string,
259
+ values: entity.values as Record<string, unknown> },
260
+ prepared.clearPassword
261
+ )
262
+ : { invitationSent: false };
263
+
264
+ const response = this.formatResponse(entity) as Record<string, unknown>;
265
+
266
+ if (this.dataHooks?.afterSave) {
267
+ Promise.resolve(this.dataHooks.afterSave(path, response, hookCtx)).catch(err => {
268
+ logger.error("[BackendHooks] data.afterSave error", { error: err instanceof Error ? err.message : err });
269
+ });
270
+ }
271
+
272
+ return c.json({
273
+ ...response,
274
+ invitationSent: result.invitationSent,
275
+ ...(result.temporaryPassword ? { temporaryPassword: result.temporaryPassword } : {})
276
+ }, 201);
277
+ }
278
+
220
279
  const entity = await driver.saveEntity({
221
280
  path,
222
281
  values: body,
@@ -228,7 +287,7 @@ export class RestApiGenerator {
228
287
 
229
288
  if (this.dataHooks?.afterSave) {
230
289
  Promise.resolve(this.dataHooks.afterSave(path, response as Record<string, unknown>, hookCtx)).catch(err => {
231
- console.error("[BackendHooks] data.afterSave error:", err instanceof Error ? err.message : err);
290
+ logger.error("[BackendHooks] data.afterSave error", { error: err instanceof Error ? err.message : err });
232
291
  });
233
292
  }
234
293
 
@@ -246,7 +305,7 @@ export class RestApiGenerator {
246
305
  try {
247
306
  this.enforceApiKeyPermission(c, collection.slug);
248
307
  const id = c.req.param("id");
249
- const driver = c.get("driver") || this.driver;
308
+ const driver = this.getScopedDriver(c);
250
309
  const hookCtx = this.buildHookContext(c, "PUT");
251
310
 
252
311
  const existingEntity = await driver.fetchEntity({
@@ -277,7 +336,7 @@ export class RestApiGenerator {
277
336
 
278
337
  if (this.dataHooks?.afterSave) {
279
338
  Promise.resolve(this.dataHooks.afterSave(collection.slug, response as Record<string, unknown>, hookCtx)).catch(err => {
280
- console.error("[BackendHooks] data.afterSave error:", err instanceof Error ? err.message : err);
339
+ logger.error("[BackendHooks] data.afterSave error", { error: err instanceof Error ? err.message : err });
281
340
  });
282
341
  }
283
342
 
@@ -294,7 +353,7 @@ export class RestApiGenerator {
294
353
  this.router.delete(`${basePath}/:id`, async (c) => {
295
354
  this.enforceApiKeyPermission(c, collection.slug);
296
355
  const id = c.req.param("id");
297
- const driver = c.get("driver") || this.driver;
356
+ const driver = this.getScopedDriver(c);
298
357
  const hookCtx = this.buildHookContext(c, "DELETE");
299
358
 
300
359
  const existingEntity = await driver.fetchEntity({
@@ -318,7 +377,7 @@ export class RestApiGenerator {
318
377
 
319
378
  if (this.dataHooks?.afterDelete) {
320
379
  Promise.resolve(this.dataHooks.afterDelete(collection.slug, String(id), hookCtx)).catch(err => {
321
- console.error("[BackendHooks] data.afterDelete error:", err instanceof Error ? err.message : err);
380
+ logger.error("[BackendHooks] data.afterDelete error", { error: err instanceof Error ? err.message : err });
322
381
  });
323
382
  }
324
383
 
@@ -384,7 +443,7 @@ entityId };
384
443
  const parsed = parseSubPath(rawPath);
385
444
  if (!parsed) return next();
386
445
 
387
- const driver = c.get("driver") || this.driver;
446
+ const driver = this.getScopedDriver(c);
388
447
 
389
448
  this.enforceApiKeyPermission(c, c.req.param("parent"));
390
449
 
@@ -395,13 +454,13 @@ entityId };
395
454
  const queryDict = c.req.queries();
396
455
  const queryOptions = parseQueryOptions(queryDict);
397
456
  const searchString = Array.isArray(queryDict.searchString) ? queryDict.searchString[queryDict.searchString.length - 1] : undefined;
398
-
457
+
399
458
  const total = driver.countEntities ? await driver.countEntities({
400
459
  path: parsed.collectionPath,
401
460
  filter: queryOptions.where as FetchCollectionProps["filter"],
402
461
  searchString
403
462
  }) : 0;
404
-
463
+
405
464
  return c.json({ count: total });
406
465
  } else if (parsed.entityId) {
407
466
  // GET /parent/:parentId/child/:id — single entity
@@ -459,7 +518,7 @@ entityId };
459
518
  const parsed = parseSubPath(rawPath);
460
519
  if (!parsed || parsed.entityId) return next();
461
520
 
462
- const driver = c.get("driver") || this.driver;
521
+ const driver = this.getScopedDriver(c);
463
522
  const hookCtx = this.buildHookContext(c, "POST");
464
523
 
465
524
  this.enforceApiKeyPermission(c, c.req.param("parent"));
@@ -479,7 +538,7 @@ entityId };
479
538
 
480
539
  if (this.dataHooks?.afterSave) {
481
540
  Promise.resolve(this.dataHooks.afterSave(parsed.collectionPath, response as Record<string, unknown>, hookCtx)).catch(err => {
482
- console.error("[BackendHooks] data.afterSave error:", err instanceof Error ? err.message : err);
541
+ logger.error("[BackendHooks] data.afterSave error", { error: err instanceof Error ? err.message : err });
483
542
  });
484
543
  }
485
544
 
@@ -494,7 +553,7 @@ entityId };
494
553
  const parsed = parseSubPath(rawPath);
495
554
  if (!parsed || !parsed.entityId) return next();
496
555
 
497
- const driver = c.get("driver") || this.driver;
556
+ const driver = this.getScopedDriver(c);
498
557
  const hookCtx = this.buildHookContext(c, "PUT");
499
558
 
500
559
  this.enforceApiKeyPermission(c, c.req.param("parent"));
@@ -516,7 +575,7 @@ entityId };
516
575
 
517
576
  if (this.dataHooks?.afterSave) {
518
577
  Promise.resolve(this.dataHooks.afterSave(parsed.collectionPath, response as Record<string, unknown>, hookCtx)).catch(err => {
519
- console.error("[BackendHooks] data.afterSave error:", err instanceof Error ? err.message : err);
578
+ logger.error("[BackendHooks] data.afterSave error", { error: err instanceof Error ? err.message : err });
520
579
  });
521
580
  }
522
581
 
@@ -531,7 +590,7 @@ entityId };
531
590
  const parsed = parseSubPath(rawPath);
532
591
  if (!parsed || !parsed.entityId) return next();
533
592
 
534
- const driver = c.get("driver") || this.driver;
593
+ const driver = this.getScopedDriver(c);
535
594
  const hookCtx = this.buildHookContext(c, "DELETE");
536
595
 
537
596
  this.enforceApiKeyPermission(c, c.req.param("parent"));
@@ -551,7 +610,7 @@ entityId };
551
610
 
552
611
  if (this.dataHooks?.afterDelete) {
553
612
  Promise.resolve(this.dataHooks.afterDelete(parsed.collectionPath, parsed.entityId, hookCtx)).catch(err => {
554
- console.error("[BackendHooks] data.afterDelete error:", err instanceof Error ? err.message : err);
613
+ logger.error("[BackendHooks] data.afterDelete error", { error: err instanceof Error ? err.message : err });
555
614
  });
556
615
  }
557
616
 
@@ -31,17 +31,21 @@ export function parseLogicalString(str: string): FilterCondition | LogicalCondit
31
31
  str = str.trim();
32
32
  if (str.startsWith("or(") && str.endsWith(")")) {
33
33
  const inner = str.slice(3, -1);
34
- return { type: "or", conditions: parseLogicalList(inner) };
34
+ return { type: "or",
35
+ conditions: parseLogicalList(inner) };
35
36
  }
36
37
  if (str.startsWith("and(") && str.endsWith(")")) {
37
38
  const inner = str.slice(4, -1);
38
- return { type: "and", conditions: parseLogicalList(inner) };
39
+ return { type: "and",
40
+ conditions: parseLogicalList(inner) };
39
41
  }
40
-
42
+
41
43
  // It's a leaf condition: field.op.val
42
44
  const firstDot = str.indexOf(".");
43
45
  if (firstDot === -1) {
44
- return { column: str, operator: "==", value: true };
46
+ return { column: str,
47
+ operator: "==",
48
+ value: true };
45
49
  }
46
50
  const field = str.substring(0, firstDot);
47
51
  const rest = str.substring(firstDot + 1);
@@ -55,7 +59,7 @@ export function parseLogicalString(str: string): FilterCondition | LogicalCondit
55
59
  op = "eq";
56
60
  valStr = rest;
57
61
  }
58
-
62
+
59
63
  const rebaseOp = (mapOperator(op) || "==") as FilterCondition["operator"];
60
64
  let parsedVal: unknown = valStr;
61
65
  if (valStr === "true") parsedVal = true;
@@ -73,20 +77,22 @@ export function parseLogicalString(str: string): FilterCondition | LogicalCondit
73
77
  return trimmed;
74
78
  });
75
79
  }
76
-
77
- return { column: field, operator: rebaseOp, value: parsedVal };
80
+
81
+ return { column: field,
82
+ operator: rebaseOp,
83
+ value: parsedVal };
78
84
  }
79
85
 
80
86
  function parseLogicalList(str: string): (FilterCondition | LogicalCondition)[] {
81
87
  const list: (FilterCondition | LogicalCondition)[] = [];
82
88
  let depth = 0;
83
89
  let current = "";
84
-
90
+
85
91
  for (let i = 0; i < str.length; i++) {
86
92
  const char = str[i];
87
93
  if (char === "(") depth++;
88
94
  if (char === ")") depth--;
89
-
95
+
90
96
  if (char === "," && depth === 0) {
91
97
  list.push(parseLogicalString(current));
92
98
  current = "";
@@ -109,10 +115,10 @@ export function parseQueryOptions(query: Record<string, unknown>): QueryOptions
109
115
  // Pagination
110
116
  const limitVal = getLastValue(query.limit);
111
117
  if (limitVal) options.limit = parseInt(String(limitVal));
112
-
118
+
113
119
  const offsetVal = getLastValue(query.offset);
114
120
  if (offsetVal) options.offset = parseInt(String(offsetVal));
115
-
121
+
116
122
  const pageVal = getLastValue(query.page);
117
123
  if (pageVal) {
118
124
  const page = parseInt(String(pageVal));
@@ -275,7 +281,7 @@ export function parseQueryOptions(query: Record<string, unknown>): QueryOptions
275
281
  const vectorSearch: VectorSearchParams = {
276
282
  property: String(vectorSearchVal),
277
283
  vector: queryVector,
278
- distance: distanceParam,
284
+ distance: distanceParam
279
285
  };
280
286
 
281
287
  const thresholdVal = getLastValue(query.vector_threshold);
package/src/api/server.ts CHANGED
@@ -12,6 +12,8 @@ import { createSchemaEditorRoutes } from "./schema-editor-routes";
12
12
  import { createAuthMiddleware, requireAuth, requireAdmin } from "../auth/middleware";
13
13
  import { errorHandler } from "./errors";
14
14
  import { generateOpenApiSpec } from "./openapi-generator";
15
+ import { requestId } from "../utils/request-id";
16
+ import { logger } from "../utils/logger";
15
17
 
16
18
  /**
17
19
  * Simplified API server that leverages existing Rebase infrastructure
@@ -69,6 +71,9 @@ export class RebaseApiServer {
69
71
  * Setup Hono middleware
70
72
  */
71
73
  private setupMiddleware(): void {
74
+ // Request ID — must be first so all downstream middleware can access it
75
+ this.router.use("/*", requestId());
76
+
72
77
  // Security headers — use same-origin-allow-popups for COOP so that
73
78
  // OAuth popup flows (Google, etc.) can postMessage back to the opener.
74
79
  this.router.use("/*", secureHeaders({
@@ -86,6 +91,12 @@ export class RebaseApiServer {
86
91
  : (origin ?? "*"),
87
92
  credentials: this.config.cors.credentials ?? false
88
93
  }));
94
+ } else if (process.env.NODE_ENV !== "production") {
95
+ logger.warn(
96
+ "⚠️ [RebaseApiServer] No CORS configuration provided. " +
97
+ "The API will accept requests from any origin. " +
98
+ "Pass a `cors` option or configure CORS on your Hono app."
99
+ );
89
100
  }
90
101
 
91
102
  // Auth middleware
@@ -179,7 +190,7 @@ export class RebaseApiServer {
179
190
  // Schema Editor endpoints
180
191
  if (this.config.collectionsDir) {
181
192
  if (process.env.NODE_ENV === "production") {
182
- console.warn("[RebaseApiServer] Schema Editor is disabled in production environments for security.");
193
+ logger.warn("[RebaseApiServer] Schema Editor is disabled in production environments for security.");
183
194
  } else {
184
195
  // Auth middlewares applied to schema-editor via the router prefix
185
196
  // MUST be declared before .route() so they execute first
package/src/api/types.ts CHANGED
@@ -14,6 +14,8 @@ export type HonoEnv = {
14
14
  driver?: DataDriver;
15
15
  /** Set when the request is authenticated via a Service API Key. */
16
16
  apiKey?: ApiKeyMasked;
17
+ /** Unique request correlation ID (generated or propagated from X-Request-ID header). */
18
+ requestId?: string;
17
19
  }
18
20
  };
19
21
 
@@ -21,6 +21,7 @@ import type { HonoEnv } from "../api/types";
21
21
  import type { ApiKeyStore } from "./api-keys/api-key-store";
22
22
  import { scopeDataDriver } from "./rls-scope";
23
23
  import { validateApiKey } from "./api-keys/api-key-middleware";
24
+ import { logger } from "../utils/logger";
24
25
 
25
26
  export interface AdapterAuthMiddlewareOptions {
26
27
  /** The auth adapter to delegate verification to. */
@@ -48,7 +49,8 @@ export function createAdapterAuthMiddleware(options: AdapterAuthMiddlewareOption
48
49
  const authHeader = c.req.header("authorization") || "";
49
50
  const token = authHeader.startsWith("Bearer ") ? authHeader.slice(7) : "";
50
51
  if (token.startsWith("rk_")) {
51
- const result = await validateApiKey(c, token, { store: apiKeyStore, driver });
52
+ const result = await validateApiKey(c, token, { store: apiKeyStore,
53
+ driver });
52
54
  if (result === true) return next();
53
55
  return result;
54
56
  }
@@ -60,7 +62,8 @@ export function createAdapterAuthMiddleware(options: AdapterAuthMiddlewareOption
60
62
  authenticatedUser = await adapter.verifyRequest(c.req.raw);
61
63
  } catch (error) {
62
64
  // adapter.verifyRequest() threw — reject the request (fail closed)
63
- return c.json({ error: { message: "Unauthorized", code: "UNAUTHORIZED" } }, 401);
65
+ return c.json({ error: { message: "Unauthorized",
66
+ code: "UNAUTHORIZED" } }, 401);
64
67
  }
65
68
 
66
69
  if (authenticatedUser) {
@@ -68,30 +71,34 @@ export function createAdapterAuthMiddleware(options: AdapterAuthMiddlewareOption
68
71
  c.set("user", {
69
72
  userId: authenticatedUser.uid,
70
73
  email: authenticatedUser.email,
71
- roles: authenticatedUser.roles,
74
+ roles: authenticatedUser.roles
72
75
  });
73
76
  try {
74
77
  c.set("driver", await scopeDataDriver(driver, {
75
78
  uid: authenticatedUser.uid,
76
- roles: authenticatedUser.roles,
79
+ roles: authenticatedUser.roles
77
80
  }));
78
81
  } catch (error) {
79
- console.error("[AUTH-ADAPTER] RLS scoping failed for authenticated user:", error);
80
- return c.json({ error: { message: "Internal authentication error", code: "INTERNAL_ERROR" } }, 500);
82
+ logger.error("[AUTH-ADAPTER] RLS scoping failed for authenticated user", { error: error });
83
+ return c.json({ error: { message: "Internal authentication error",
84
+ code: "INTERNAL_ERROR" } }, 500);
81
85
  }
82
86
  } else {
83
87
  // Not authenticated — scope as anon for RLS evaluation
84
88
  try {
85
- c.set("driver", await scopeDataDriver(driver, { uid: "anon", roles: ["anon"] }));
89
+ c.set("driver", await scopeDataDriver(driver, { uid: "anon",
90
+ roles: ["anon"] }));
86
91
  } catch (error) {
87
- console.error("[AUTH-ADAPTER] Failed to create anon-scoped driver:", error);
88
- return c.json({ error: { message: "Server configuration error", code: "INTERNAL_ERROR" } }, 500);
92
+ logger.error("[AUTH-ADAPTER] Failed to create anon-scoped driver", { error: error });
93
+ return c.json({ error: { message: "Server configuration error",
94
+ code: "INTERNAL_ERROR" } }, 500);
89
95
  }
90
96
  }
91
97
 
92
98
  // Enforce auth if required
93
99
  if (enforceAuth && !c.get("user")) {
94
- return c.json({ error: { message: "Unauthorized: Authentication required", code: "UNAUTHORIZED" } }, 401);
100
+ return c.json({ error: { message: "Unauthorized: Authentication required",
101
+ code: "UNAUTHORIZED" } }, 401);
95
102
  }
96
103
 
97
104
  return next();