@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
@@ -32,13 +32,25 @@ function createMockDriver(): jest.Mocked<DataDriver> {
32
32
  }
33
33
 
34
34
  const mockCollections: EntityCollection[] = [
35
- { slug: "products", name: "Products", singularName: "Product", properties: {} } as any,
36
- { slug: "orders", name: "Orders", singularName: "Order", properties: {} } as any
35
+ { slug: "products",
36
+ name: "Products",
37
+ singularName: "Product",
38
+ properties: {} } as any,
39
+ { slug: "orders",
40
+ name: "Orders",
41
+ singularName: "Order",
42
+ properties: {} } as any
37
43
  ];
38
44
 
39
45
  function createApp(mockDriver: jest.Mocked<DataDriver>, hooks?: DataHooks) {
40
46
  const app = new Hono();
41
47
  app.onError(errorHandler);
48
+ // RestApiGenerator.getScopedDriver reads from c.get("driver") which is
49
+ // normally set by auth middleware. Replicate that here for tests.
50
+ app.use("/api/*", async (c, next) => {
51
+ c.set("driver", mockDriver);
52
+ await next();
53
+ });
42
54
  const generator = new RestApiGenerator(mockCollections, mockDriver, hooks);
43
55
  app.route("/api", generator.generateRoutes());
44
56
  return app;
@@ -62,7 +74,8 @@ describe("DataHooks — REST API", () => {
62
74
  afterRead(slug, entity) {
63
75
  // Mask price for non-premium entities
64
76
  if (slug === "products") {
65
- return { ...entity, price: "***" };
77
+ return { ...entity,
78
+ price: "***" };
66
79
  }
67
80
  return entity;
68
81
  }
@@ -70,8 +83,14 @@ describe("DataHooks — REST API", () => {
70
83
  const app = createApp(mockDriver, hooks);
71
84
 
72
85
  mockDriver.fetchCollection.mockResolvedValue([
73
- { id: "p1", path: "products", values: { name: "Widget", price: 99 } } as any,
74
- { id: "p2", path: "products", values: { name: "Gadget", price: 199 } } as any
86
+ { id: "p1",
87
+ path: "products",
88
+ values: { name: "Widget",
89
+ price: 99 } } as any,
90
+ { id: "p2",
91
+ path: "products",
92
+ values: { name: "Gadget",
93
+ price: 199 } } as any
75
94
  ]);
76
95
  mockDriver.countEntities!.mockResolvedValue(2);
77
96
 
@@ -97,9 +116,18 @@ describe("DataHooks — REST API", () => {
97
116
  const app = createApp(mockDriver, hooks);
98
117
 
99
118
  mockDriver.fetchCollection.mockResolvedValue([
100
- { id: "p1", path: "products", values: { name: "Published", status: "active" } } as any,
101
- { id: "p2", path: "products", values: { name: "Draft", status: "draft" } } as any,
102
- { id: "p3", path: "products", values: { name: "Also Published", status: "active" } } as any
119
+ { id: "p1",
120
+ path: "products",
121
+ values: { name: "Published",
122
+ status: "active" } } as any,
123
+ { id: "p2",
124
+ path: "products",
125
+ values: { name: "Draft",
126
+ status: "draft" } } as any,
127
+ { id: "p3",
128
+ path: "products",
129
+ values: { name: "Also Published",
130
+ status: "active" } } as any
103
131
  ]);
104
132
  mockDriver.countEntities!.mockResolvedValue(3);
105
133
 
@@ -112,13 +140,16 @@ describe("DataHooks — REST API", () => {
112
140
  it("transforms single entity GET response", async () => {
113
141
  const hooks: DataHooks = {
114
142
  afterRead(slug, entity) {
115
- return { ...entity, _readAt: "2024-01-01" };
143
+ return { ...entity,
144
+ _readAt: "2024-01-01" };
116
145
  }
117
146
  };
118
147
  const app = createApp(mockDriver, hooks);
119
148
 
120
149
  mockDriver.fetchEntity.mockResolvedValue(
121
- { id: "p1", path: "products", values: { name: "Widget" } } as any
150
+ { id: "p1",
151
+ path: "products",
152
+ values: { name: "Widget" } } as any
122
153
  );
123
154
 
124
155
  const res = await app.request("/api/products/p1");
@@ -139,7 +170,9 @@ describe("DataHooks — REST API", () => {
139
170
  const app = createApp(mockDriver, hooks);
140
171
 
141
172
  mockDriver.fetchEntity.mockResolvedValue(
142
- { id: "hidden", path: "products", values: { name: "Secret" } } as any
173
+ { id: "hidden",
174
+ path: "products",
175
+ values: { name: "Secret" } } as any
143
176
  );
144
177
 
145
178
  const res = await app.request("/api/products/hidden");
@@ -150,7 +183,8 @@ describe("DataHooks — REST API", () => {
150
183
  const hooks: DataHooks = {
151
184
  afterRead(slug, entity) {
152
185
  if (slug === "products") {
153
- return { ...entity, hooked: true };
186
+ return { ...entity,
187
+ hooked: true };
154
188
  }
155
189
  return entity;
156
190
  }
@@ -159,7 +193,9 @@ describe("DataHooks — REST API", () => {
159
193
 
160
194
  // Products should be hooked
161
195
  mockDriver.fetchEntity.mockResolvedValueOnce(
162
- { id: "p1", path: "products", values: { name: "Widget" } } as any
196
+ { id: "p1",
197
+ path: "products",
198
+ values: { name: "Widget" } } as any
163
199
  );
164
200
  const prodRes = await app.request("/api/products/p1");
165
201
  const prodBody = await prodRes.json() as any;
@@ -167,7 +203,9 @@ describe("DataHooks — REST API", () => {
167
203
 
168
204
  // Orders should NOT be hooked
169
205
  mockDriver.fetchEntity.mockResolvedValueOnce(
170
- { id: "o1", path: "orders", values: { total: 42 } } as any
206
+ { id: "o1",
207
+ path: "orders",
208
+ values: { total: 42 } } as any
171
209
  );
172
210
  const orderRes = await app.request("/api/orders/o1");
173
211
  const orderBody = await orderRes.json() as any;
@@ -180,13 +218,17 @@ describe("DataHooks — REST API", () => {
180
218
  it("transforms values before POST (create)", async () => {
181
219
  const hooks: DataHooks = {
182
220
  beforeSave(slug, values, entityId) {
183
- return { ...values, slug: values.name?.toString().toLowerCase().replace(/\s+/g, "-") };
221
+ return { ...values,
222
+ slug: values.name?.toString().toLowerCase().replace(/\s+/g, "-") };
184
223
  }
185
224
  };
186
225
  const app = createApp(mockDriver, hooks);
187
226
 
188
227
  mockDriver.saveEntity.mockResolvedValue(
189
- { id: "new-1", path: "products", values: { name: "Cool Widget", slug: "cool-widget" } } as any
228
+ { id: "new-1",
229
+ path: "products",
230
+ values: { name: "Cool Widget",
231
+ slug: "cool-widget" } } as any
190
232
  );
191
233
 
192
234
  const res = await app.request("/api/products", {
@@ -207,14 +249,20 @@ describe("DataHooks — REST API", () => {
207
249
  const hooks: DataHooks = {
208
250
  beforeSave(slug, values, entityId) {
209
251
  // Add an updatedBy field
210
- return { ...values, updatedBy: "hook" };
252
+ return { ...values,
253
+ updatedBy: "hook" };
211
254
  }
212
255
  };
213
256
  const app = createApp(mockDriver, hooks);
214
257
 
215
- mockDriver.fetchEntity.mockResolvedValue({ id: "p1", path: "products", values: {} } as any);
258
+ mockDriver.fetchEntity.mockResolvedValue({ id: "p1",
259
+ path: "products",
260
+ values: {} } as any);
216
261
  mockDriver.saveEntity.mockResolvedValue(
217
- { id: "p1", path: "products", values: { name: "Updated", updatedBy: "hook" } } as any
262
+ { id: "p1",
263
+ path: "products",
264
+ values: { name: "Updated",
265
+ updatedBy: "hook" } } as any
218
266
  );
219
267
 
220
268
  const res = await app.request("/api/products/p1", {
@@ -238,7 +286,9 @@ describe("DataHooks — REST API", () => {
238
286
 
239
287
  // POST
240
288
  mockDriver.saveEntity.mockResolvedValueOnce(
241
- { id: "new-1", path: "products", values: { name: "A" } } as any
289
+ { id: "new-1",
290
+ path: "products",
291
+ values: { name: "A" } } as any
242
292
  );
243
293
  await app.request("/api/products", {
244
294
  method: "POST",
@@ -248,9 +298,13 @@ describe("DataHooks — REST API", () => {
248
298
  expect(beforeSaveSpy.mock.calls[0][2]).toBeUndefined(); // entityId
249
299
 
250
300
  // PUT
251
- mockDriver.fetchEntity.mockResolvedValueOnce({ id: "p1", path: "products", values: {} } as any);
301
+ mockDriver.fetchEntity.mockResolvedValueOnce({ id: "p1",
302
+ path: "products",
303
+ values: {} } as any);
252
304
  mockDriver.saveEntity.mockResolvedValueOnce(
253
- { id: "p1", path: "products", values: { name: "B" } } as any
305
+ { id: "p1",
306
+ path: "products",
307
+ values: { name: "B" } } as any
254
308
  );
255
309
  await app.request("/api/products/p1", {
256
310
  method: "PUT",
@@ -289,7 +343,9 @@ describe("DataHooks — REST API", () => {
289
343
  const app = createApp(mockDriver, hooks);
290
344
 
291
345
  mockDriver.saveEntity.mockResolvedValue(
292
- { id: "new-1", path: "products", values: { name: "Widget" } } as any
346
+ { id: "new-1",
347
+ path: "products",
348
+ values: { name: "Widget" } } as any
293
349
  );
294
350
 
295
351
  const res = await app.request("/api/products", {
@@ -303,7 +359,8 @@ describe("DataHooks — REST API", () => {
303
359
  expect(afterSaveSpy).toHaveBeenCalledTimes(1);
304
360
  expect(afterSaveSpy).toHaveBeenCalledWith(
305
361
  "products",
306
- expect.objectContaining({ id: "new-1", name: "Widget" }),
362
+ expect.objectContaining({ id: "new-1",
363
+ name: "Widget" }),
307
364
  expect.objectContaining({ method: "POST" })
308
365
  );
309
366
  });
@@ -313,9 +370,13 @@ describe("DataHooks — REST API", () => {
313
370
  const hooks: DataHooks = { afterSave: afterSaveSpy };
314
371
  const app = createApp(mockDriver, hooks);
315
372
 
316
- mockDriver.fetchEntity.mockResolvedValue({ id: "p1", path: "products", values: {} } as any);
373
+ mockDriver.fetchEntity.mockResolvedValue({ id: "p1",
374
+ path: "products",
375
+ values: {} } as any);
317
376
  mockDriver.saveEntity.mockResolvedValue(
318
- { id: "p1", path: "products", values: { name: "Updated" } } as any
377
+ { id: "p1",
378
+ path: "products",
379
+ values: { name: "Updated" } } as any
319
380
  );
320
381
 
321
382
  await app.request("/api/products/p1", {
@@ -346,7 +407,9 @@ describe("DataHooks — REST API", () => {
346
407
  const app = createApp(mockDriver, hooks);
347
408
 
348
409
  mockDriver.fetchEntity.mockResolvedValue(
349
- { id: "protected", path: "products", values: {} } as any
410
+ { id: "protected",
411
+ path: "products",
412
+ values: {} } as any
350
413
  );
351
414
 
352
415
  const res = await app.request("/api/products/protected", { method: "DELETE" });
@@ -359,7 +422,9 @@ describe("DataHooks — REST API", () => {
359
422
  const hooks: DataHooks = { beforeDelete: beforeDeleteSpy };
360
423
  const app = createApp(mockDriver, hooks);
361
424
 
362
- const existingEntity = { id: "p1", path: "products", values: {} } as any;
425
+ const existingEntity = { id: "p1",
426
+ path: "products",
427
+ values: {} } as any;
363
428
  mockDriver.fetchEntity.mockResolvedValue(existingEntity);
364
429
  mockDriver.deleteEntity.mockResolvedValue();
365
430
 
@@ -376,7 +441,9 @@ describe("DataHooks — REST API", () => {
376
441
  const hooks: DataHooks = { afterDelete: afterDeleteSpy };
377
442
  const app = createApp(mockDriver, hooks);
378
443
 
379
- mockDriver.fetchEntity.mockResolvedValue({ id: "p1", path: "products", values: {} } as any);
444
+ mockDriver.fetchEntity.mockResolvedValue({ id: "p1",
445
+ path: "products",
446
+ values: {} } as any);
380
447
  mockDriver.deleteEntity.mockResolvedValue();
381
448
 
382
449
  await app.request("/api/products/p1", { method: "DELETE" });
@@ -393,7 +460,9 @@ describe("DataHooks — REST API", () => {
393
460
  it("returns data unchanged when no hooks are provided", async () => {
394
461
  const app = createApp(mockDriver); // no hooks
395
462
  mockDriver.fetchCollection.mockResolvedValue([
396
- { id: "p1", path: "products", values: { name: "Widget" } } as any
463
+ { id: "p1",
464
+ path: "products",
465
+ values: { name: "Widget" } } as any
397
466
  ]);
398
467
  mockDriver.countEntities!.mockResolvedValue(1);
399
468
 
@@ -7,20 +7,20 @@ const TEST_USER: AuthenticatedUser = {
7
7
  displayName: "Test User",
8
8
  roles: ["editor"],
9
9
  isAdmin: false,
10
- rawToken: "tok_abc",
10
+ rawToken: "tok_abc"
11
11
  };
12
12
 
13
13
  const ADMIN_USER: AuthenticatedUser = {
14
14
  uid: "admin-1",
15
15
  email: "admin@example.com",
16
16
  roles: ["admin"],
17
- isAdmin: true,
17
+ isAdmin: true
18
18
  };
19
19
 
20
20
  describe("createCustomAuthAdapter", () => {
21
21
  it("sets the adapter id to 'custom'", () => {
22
22
  const adapter = createCustomAuthAdapter({
23
- verifyRequest: async () => null,
23
+ verifyRequest: async () => null
24
24
  });
25
25
  expect(adapter.id).toBe("custom");
26
26
  });
@@ -29,7 +29,7 @@ describe("createCustomAuthAdapter", () => {
29
29
  const verifyRequest = jest.fn(async () => TEST_USER);
30
30
  const adapter = createCustomAuthAdapter({ verifyRequest });
31
31
  const req = new Request("http://localhost/api", {
32
- headers: { Authorization: "Bearer test-token" },
32
+ headers: { Authorization: "Bearer test-token" }
33
33
  });
34
34
  const result = await adapter.verifyRequest(req);
35
35
  expect(verifyRequest).toHaveBeenCalledWith(req);
@@ -38,7 +38,7 @@ describe("createCustomAuthAdapter", () => {
38
38
 
39
39
  it("returns null from verifyRequest when the user function returns null", async () => {
40
40
  const adapter = createCustomAuthAdapter({
41
- verifyRequest: async () => null,
41
+ verifyRequest: async () => null
42
42
  });
43
43
  const result = await adapter.verifyRequest(new Request("http://localhost/"));
44
44
  expect(result).toBeNull();
@@ -68,7 +68,7 @@ describe("createCustomAuthAdapter", () => {
68
68
 
69
69
  it("returns null from fallback verifyToken for invalid token", async () => {
70
70
  const adapter = createCustomAuthAdapter({
71
- verifyRequest: async () => null,
71
+ verifyRequest: async () => null
72
72
  });
73
73
  const result = await adapter.verifyToken!("bad-token");
74
74
  expect(result).toBeNull();
@@ -84,7 +84,7 @@ describe("createCustomAuthAdapter", () => {
84
84
  const verifyRequest = jest.fn(async () => null);
85
85
  const adapter = createCustomAuthAdapter({
86
86
  verifyRequest,
87
- verifyToken: customVerifyToken,
87
+ verifyToken: customVerifyToken
88
88
  });
89
89
 
90
90
  const result = await adapter.verifyToken!("direct-token");
@@ -97,7 +97,7 @@ describe("createCustomAuthAdapter", () => {
97
97
  it("returns null from user-provided verifyToken for unknown token", async () => {
98
98
  const adapter = createCustomAuthAdapter({
99
99
  verifyRequest: async () => null,
100
- verifyToken: async () => null,
100
+ verifyToken: async () => null
101
101
  });
102
102
  const result = await adapter.verifyToken!("unknown");
103
103
  expect(result).toBeNull();
@@ -107,7 +107,7 @@ describe("createCustomAuthAdapter", () => {
107
107
 
108
108
  it("returns default capabilities when none are overridden", async () => {
109
109
  const adapter = createCustomAuthAdapter({
110
- verifyRequest: async () => null,
110
+ verifyRequest: async () => null
111
111
  });
112
112
  const caps = await adapter.getCapabilities!();
113
113
  expect(caps).toEqual({
@@ -118,14 +118,15 @@ describe("createCustomAuthAdapter", () => {
118
118
  sessionManagement: false,
119
119
  profileUpdate: false,
120
120
  emailVerification: false,
121
- enabledProviders: [],
121
+ enabledProviders: []
122
122
  });
123
123
  });
124
124
 
125
125
  it("merges user-provided capabilities with defaults", async () => {
126
126
  const adapter = createCustomAuthAdapter({
127
127
  verifyRequest: async () => null,
128
- capabilities: { emailPasswordLogin: true, registration: true },
128
+ capabilities: { emailPasswordLogin: true,
129
+ registration: true }
129
130
  });
130
131
  const caps = await adapter.getCapabilities!();
131
132
  expect(caps.emailPasswordLogin).toBe(true);
@@ -138,7 +139,7 @@ describe("createCustomAuthAdapter", () => {
138
139
  it("passes through serviceKey", () => {
139
140
  const adapter = createCustomAuthAdapter({
140
141
  verifyRequest: async () => null,
141
- serviceKey: "sk_live_123",
142
+ serviceKey: "sk_live_123"
142
143
  });
143
144
  expect(adapter.serviceKey).toBe("sk_live_123");
144
145
  });
@@ -149,12 +150,12 @@ describe("createCustomAuthAdapter", () => {
149
150
  listUsers: jest.fn(),
150
151
  createUser: jest.fn(),
151
152
  updateUser: jest.fn(),
152
- deleteUser: jest.fn(),
153
+ deleteUser: jest.fn()
153
154
  };
154
155
 
155
156
  const adapter = createCustomAuthAdapter({
156
157
  verifyRequest: async () => null,
157
- userManagement: userMgmt as unknown as CustomAuthAdapterOptions["userManagement"],
158
+ userManagement: userMgmt as unknown as CustomAuthAdapterOptions["userManagement"]
158
159
  });
159
160
 
160
161
  expect(adapter.userManagement).toBe(userMgmt);
@@ -162,7 +163,7 @@ describe("createCustomAuthAdapter", () => {
162
163
 
163
164
  it("omits userManagement when not provided", () => {
164
165
  const adapter = createCustomAuthAdapter({
165
- verifyRequest: async () => null,
166
+ verifyRequest: async () => null
166
167
  });
167
168
  expect(adapter.userManagement).toBeUndefined();
168
169
  });
@@ -6,7 +6,8 @@ import {
6
6
  } from "../src/email/templates";
7
7
 
8
8
  describe("getPasswordResetTemplate", () => {
9
- const user = { email: "john@example.com", displayName: "John Doe" };
9
+ const user = { email: "john@example.com",
10
+ displayName: "John Doe" };
10
11
  const resetUrl = "https://example.com/reset?token=abc123";
11
12
 
12
13
  it("returns subject, html, and text", () => {
@@ -43,7 +44,8 @@ describe("getPasswordResetTemplate", () => {
43
44
  });
44
45
 
45
46
  it("falls back to email prefix when displayName is null", () => {
46
- const userNoName = { email: "jane@example.com", displayName: null };
47
+ const userNoName = { email: "jane@example.com",
48
+ displayName: null };
47
49
  const result = getPasswordResetTemplate(resetUrl, userNoName);
48
50
  expect(result.html).toContain("jane");
49
51
  expect(result.text).toContain("jane");
@@ -58,7 +60,8 @@ describe("getPasswordResetTemplate", () => {
58
60
  });
59
61
 
60
62
  describe("getEmailVerificationTemplate", () => {
61
- const user = { email: "alice@example.com", displayName: "Alice" };
63
+ const user = { email: "alice@example.com",
64
+ displayName: "Alice" };
62
65
  const verifyUrl = "https://example.com/verify?token=xyz789";
63
66
 
64
67
  it("returns subject, html, and text", () => {
@@ -96,7 +99,8 @@ describe("getEmailVerificationTemplate", () => {
96
99
  });
97
100
 
98
101
  describe("getUserInvitationTemplate", () => {
99
- const user = { email: "bob@example.com", displayName: "Bob" };
102
+ const user = { email: "bob@example.com",
103
+ displayName: "Bob" };
100
104
  const setPasswordUrl = "https://example.com/set-password?token=def456";
101
105
 
102
106
  it("returns subject, html, and text", () => {
@@ -129,7 +133,8 @@ describe("getUserInvitationTemplate", () => {
129
133
  });
130
134
 
131
135
  describe("getWelcomeEmailTemplate", () => {
132
- const user = { email: "dave@example.com", displayName: "Dave" };
136
+ const user = { email: "dave@example.com",
137
+ displayName: "Dave" };
133
138
 
134
139
  it("returns subject, html, and text", () => {
135
140
  const result = getWelcomeEmailTemplate(user);
package/test/env.test.ts CHANGED
@@ -38,7 +38,7 @@ describe("env configuration and localhost validation", () => {
38
38
  process.env.JWT_SECRET = "12345678901234567890123456789012";
39
39
  process.env.FRONTEND_URL = "https://my-app.com";
40
40
 
41
- expect(() => loadEnv()).toThrowError(/postgresql:\/\/localhost:5432\/rebase/);
41
+ expect(() => loadEnv()).toThrow(/postgresql:\/\/localhost:5432\/rebase/);
42
42
  });
43
43
 
44
44
  it("should fail validation in production if DATABASE_URL contains 127.0.0.1", () => {
@@ -47,7 +47,7 @@ describe("env configuration and localhost validation", () => {
47
47
  process.env.JWT_SECRET = "12345678901234567890123456789012";
48
48
  process.env.FRONTEND_URL = "https://my-app.com";
49
49
 
50
- expect(() => loadEnv()).toThrowError(/postgresql:\/\/127\.0\.0\.1:5432\/rebase/);
50
+ expect(() => loadEnv()).toThrow(/postgresql:\/\/127\.0\.0\.1:5432\/rebase/);
51
51
  });
52
52
 
53
53
  it("should fail validation in production if DATABASE_URL contains an IPv6 loopback [::1]", () => {
@@ -56,7 +56,7 @@ describe("env configuration and localhost validation", () => {
56
56
  process.env.JWT_SECRET = "12345678901234567890123456789012";
57
57
  process.env.FRONTEND_URL = "https://my-app.com";
58
58
 
59
- expect(() => loadEnv()).toThrowError(/postgresql:\/\/\[::1\]:5432\/rebase/);
59
+ expect(() => loadEnv()).toThrow(/postgresql:\/\/\[::1\]:5432\/rebase/);
60
60
  });
61
61
 
62
62
  it("should fail validation in production if DATABASE_URL contains a loopback in the 127.x.x.x range", () => {
@@ -65,7 +65,7 @@ describe("env configuration and localhost validation", () => {
65
65
  process.env.JWT_SECRET = "12345678901234567890123456789012";
66
66
  process.env.FRONTEND_URL = "https://my-app.com";
67
67
 
68
- expect(() => loadEnv()).toThrowError(/postgresql:\/\/127\.0\.0\.2:5432\/rebase/);
68
+ expect(() => loadEnv()).toThrow(/postgresql:\/\/127\.0\.0\.2:5432\/rebase/);
69
69
  });
70
70
 
71
71
  it("should succeed validation in production with a non-localhost DATABASE_URL", () => {
@@ -113,11 +113,11 @@ describe("env configuration and localhost validation", () => {
113
113
 
114
114
  const extension = {
115
115
  extend: z.object({
116
- EXTERNAL_SERVICE_URL: z.string().url(),
117
- }),
116
+ EXTERNAL_SERVICE_URL: z.string().url()
117
+ })
118
118
  };
119
119
 
120
- expect(() => loadEnv(extension)).toThrowError(/https:\/\/localhost:8080\/api/);
120
+ expect(() => loadEnv(extension)).toThrow(/https:\/\/localhost:8080\/api/);
121
121
  });
122
122
 
123
123
  it("should validate and block plain host string matching localhost", () => {
@@ -129,10 +129,10 @@ describe("env configuration and localhost validation", () => {
129
129
 
130
130
  const extension = {
131
131
  extend: z.object({
132
- DB_HOST: z.string(),
133
- }),
132
+ DB_HOST: z.string()
133
+ })
134
134
  };
135
135
 
136
- expect(() => loadEnv(extension)).toThrowError(/localhost/);
136
+ expect(() => loadEnv(extension)).toThrow(/localhost/);
137
137
  });
138
138
  });
@@ -62,7 +62,8 @@ describe("Function Loader & Routes", () => {
62
62
  afterAll(() => {
63
63
  // Clean up temp directory
64
64
  if (tempDir && fs.existsSync(tempDir)) {
65
- fs.rmSync(tempDir, { recursive: true, force: true });
65
+ fs.rmSync(tempDir, { recursive: true,
66
+ force: true });
66
67
  }
67
68
  });
68
69
 
@@ -101,12 +102,14 @@ describe("Function Loader & Routes", () => {
101
102
  // 1. Verify GET / lists loaded functions
102
103
  const listRes = await routes.request("/");
103
104
  expect(listRes.status).toBe(200);
104
-
105
+
105
106
  const listData = await listRes.json();
106
107
  expect(listData).toEqual({
107
108
  functions: [
108
- { name: "valid-app", endpoint: "/functions/valid-app" },
109
- { name: "valid-factory", endpoint: "/functions/valid-factory" }
109
+ { name: "valid-app",
110
+ endpoint: "/functions/valid-app" },
111
+ { name: "valid-factory",
112
+ endpoint: "/functions/valid-factory" }
110
113
  ]
111
114
  });
112
115