@rebasepro/server-core 0.6.1 → 0.8.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 (116) hide show
  1. package/dist/api/graphql/graphql-schema-generator.d.ts +9 -0
  2. package/dist/api/rest/api-generator.d.ts +2 -14
  3. package/dist/api/rest/query-parser.d.ts +2 -5
  4. package/dist/api/types.d.ts +8 -2
  5. package/dist/auth/adapter-middleware.d.ts +7 -1
  6. package/dist/auth/admin-roles-route.d.ts +18 -0
  7. package/dist/auth/admin-users-route.d.ts +28 -0
  8. package/dist/auth/api-keys/api-key-types.d.ts +8 -0
  9. package/dist/auth/auth-hooks.d.ts +17 -0
  10. package/dist/auth/builtin-auth-adapter.d.ts +3 -1
  11. package/dist/auth/index.d.ts +1 -0
  12. package/dist/auth/interfaces.d.ts +32 -2
  13. package/dist/auth/magic-link-routes.d.ts +30 -0
  14. package/dist/auth/mfa-crypto.d.ts +23 -0
  15. package/dist/auth/mfa-routes.d.ts +2 -1
  16. package/dist/auth/middleware.d.ts +9 -2
  17. package/dist/auth/routes.d.ts +3 -1
  18. package/dist/auth/session-routes.d.ts +2 -0
  19. package/dist/backend-CIxN4FVm.js.map +1 -1
  20. package/dist/base64-js-C_frYBkI.js +1687 -0
  21. package/dist/base64-js-C_frYBkI.js.map +1 -0
  22. package/dist/{dist-CZKP-Xz4.js → dist-DMO-zF6D.js} +2 -2
  23. package/dist/{dist-CZKP-Xz4.js.map → dist-DMO-zF6D.js.map} +1 -1
  24. package/dist/email/index.d.ts +2 -2
  25. package/dist/email/templates.d.ts +8 -0
  26. package/dist/email/types.d.ts +18 -0
  27. package/dist/functions/define-function.d.ts +50 -0
  28. package/dist/functions/index.d.ts +2 -0
  29. package/dist/index.d.ts +16 -18
  30. package/dist/index.es.js +1947 -2356
  31. package/dist/index.es.js.map +1 -1
  32. package/dist/index.umd.js +40615 -10203
  33. package/dist/index.umd.js.map +1 -1
  34. package/dist/init.d.ts +68 -12
  35. package/dist/jws-BqRRaK11.js +616 -0
  36. package/dist/jws-BqRRaK11.js.map +1 -0
  37. package/dist/{jwt-DHcQRGC3.js → jwt-BETC8a1J.js} +3 -611
  38. package/dist/jwt-BETC8a1J.js.map +1 -0
  39. package/dist/services/routed-realtime-service.d.ts +43 -0
  40. package/dist/{src-COaj0G3P.js → src-CB2PIpBe.js} +2 -2
  41. package/dist/{src-COaj0G3P.js.map → src-CB2PIpBe.js.map} +1 -1
  42. package/dist/src-DjzOT1kG.js +29746 -0
  43. package/dist/src-DjzOT1kG.js.map +1 -0
  44. package/dist/storage/GCSStorageController.d.ts +43 -0
  45. package/dist/storage/index.d.ts +5 -2
  46. package/dist/storage/routes.d.ts +33 -1
  47. package/dist/storage/tus-handler.d.ts +3 -1
  48. package/dist/storage/types.d.ts +28 -3
  49. package/dist/utils/dev-port.d.ts +2 -0
  50. package/package.json +13 -5
  51. package/src/api/errors.ts +16 -2
  52. package/src/api/graphql/graphql-schema-generator.ts +50 -15
  53. package/src/api/openapi-generator.ts +2 -2
  54. package/src/api/rest/api-generator.ts +44 -123
  55. package/src/api/rest/query-parser.ts +6 -23
  56. package/src/api/server.ts +10 -2
  57. package/src/api/types.ts +8 -2
  58. package/src/auth/adapter-middleware.ts +10 -2
  59. package/src/auth/admin-roles-route.ts +36 -0
  60. package/src/auth/admin-users-route.ts +302 -0
  61. package/src/auth/api-keys/api-key-middleware.ts +4 -3
  62. package/src/auth/api-keys/api-key-routes.ts +12 -2
  63. package/src/auth/api-keys/api-key-store.ts +83 -66
  64. package/src/auth/api-keys/api-key-types.ts +8 -0
  65. package/src/auth/apple-oauth.ts +2 -1
  66. package/src/auth/auth-hooks.ts +21 -0
  67. package/src/auth/bitbucket-oauth.ts +2 -1
  68. package/src/auth/builtin-auth-adapter.ts +29 -6
  69. package/src/auth/custom-auth-adapter.ts +2 -0
  70. package/src/auth/discord-oauth.ts +2 -1
  71. package/src/auth/facebook-oauth.ts +2 -1
  72. package/src/auth/github-oauth.ts +2 -1
  73. package/src/auth/gitlab-oauth.ts +2 -1
  74. package/src/auth/google-oauth.ts +8 -4
  75. package/src/auth/index.ts +2 -0
  76. package/src/auth/interfaces.ts +38 -2
  77. package/src/auth/linkedin-oauth.ts +2 -1
  78. package/src/auth/magic-link-routes.ts +167 -0
  79. package/src/auth/mfa-crypto.ts +91 -0
  80. package/src/auth/mfa-routes.ts +34 -10
  81. package/src/auth/microsoft-oauth.ts +2 -1
  82. package/src/auth/middleware.ts +14 -5
  83. package/src/auth/reset-password-admin.ts +17 -1
  84. package/src/auth/routes.ts +78 -10
  85. package/src/auth/session-routes.ts +15 -3
  86. package/src/auth/slack-oauth.ts +2 -1
  87. package/src/auth/spotify-oauth.ts +2 -1
  88. package/src/auth/twitter-oauth.ts +8 -1
  89. package/src/cron/cron-store.ts +25 -23
  90. package/src/email/index.ts +3 -2
  91. package/src/email/templates.ts +82 -0
  92. package/src/email/types.ts +16 -0
  93. package/src/functions/define-function.ts +59 -0
  94. package/src/functions/function-loader.ts +16 -0
  95. package/src/functions/index.ts +2 -0
  96. package/src/index.ts +70 -37
  97. package/src/init.ts +214 -25
  98. package/src/services/routed-realtime-service.ts +113 -0
  99. package/src/storage/GCSStorageController.ts +334 -0
  100. package/src/storage/index.ts +9 -3
  101. package/src/storage/routes.ts +191 -23
  102. package/src/storage/tus-handler.ts +16 -4
  103. package/src/storage/types.ts +25 -3
  104. package/src/utils/dev-port.ts +13 -7
  105. package/test/api-generator.test.ts +1 -1
  106. package/test/auth-config-types.test.ts +40 -0
  107. package/test/auth-routes.test.ts +54 -4
  108. package/test/custom-auth-adapter.test.ts +20 -1
  109. package/test/define-function.test.ts +45 -0
  110. package/test/env.test.ts +9 -19
  111. package/test/multi-datasource-routing.test.ts +113 -0
  112. package/test/routed-realtime-service.test.ts +86 -0
  113. package/test/storage-routes.test.ts +160 -0
  114. package/test/transform-auth-response.test.ts +305 -0
  115. package/dist/jwt-DHcQRGC3.js.map +0 -1
  116. package/test/backend-hooks-data.test.ts +0 -477
@@ -57,6 +57,14 @@ export type WelcomeEmailTemplateFunction = (
57
57
  appName: string
58
58
  ) => { subject: string; html: string; text?: string };
59
59
 
60
+ /**
61
+ * Template function for magic link emails
62
+ */
63
+ export type MagicLinkTemplateFunction = (
64
+ magicLinkUrl: string,
65
+ user: { email: string; displayName?: string | null }
66
+ ) => { subject: string; html: string; text?: string };
67
+
60
68
  /**
61
69
  * Complete email configuration
62
70
  */
@@ -89,6 +97,13 @@ export interface EmailConfig {
89
97
  */
90
98
  verifyEmailUrl?: string;
91
99
 
100
+ /**
101
+ * Base URL for magic link login (e.g., "https://myapp.com")
102
+ * The magic link will be: {baseUrl}/auth/magic-link?token={token}
103
+ * Falls back to `resetPasswordUrl` if not set.
104
+ */
105
+ magicLinkUrl?: string;
106
+
92
107
  /**
93
108
  * Application name to use in email templates
94
109
  */
@@ -102,5 +117,6 @@ export interface EmailConfig {
102
117
  emailVerification?: EmailVerificationTemplateFunction;
103
118
  userInvitation?: UserInvitationTemplateFunction;
104
119
  welcomeEmail?: WelcomeEmailTemplateFunction;
120
+ magicLink?: MagicLinkTemplateFunction;
105
121
  };
106
122
  }
@@ -0,0 +1,59 @@
1
+ import { Hono } from "hono";
2
+ import type { RebaseClient } from "@rebasepro/types";
3
+ import type { HonoEnv } from "../api/types";
4
+ import { rebase } from "../singleton";
5
+
6
+ /**
7
+ * Typed context injected into a function authored with {@link defineFunction}.
8
+ *
9
+ * Surfaces the app-scoped Rebase singleton so handlers don't need to reach
10
+ * for the global `rebase` import. Request-scoped values (the authenticated
11
+ * `user`, the RLS-scoped `driver`, the `apiKey`, the `requestId`) are typed
12
+ * on the Hono context via {@link HonoEnv} — read them with `c.get("user")`
13
+ * / `c.var.driver` inside a handler.
14
+ */
15
+ export interface RebaseFunctionContext {
16
+ /**
17
+ * The server-side Rebase singleton (`data`, `auth`, `storage`, `email`,
18
+ * `sql`). `rebase.data` runs with **admin privileges** (no RLS) — use the
19
+ * request `driver` (`c.var.driver`) for user-scoped queries.
20
+ */
21
+ rebase: RebaseClient;
22
+ }
23
+
24
+ /**
25
+ * Typed authoring contract for a custom backend function.
26
+ *
27
+ * A custom function is a file in the `functionsDir` that default-exports a
28
+ * Hono app; the loader mounts it at `/<filename>`. `defineFunction` is the
29
+ * typed opt-in for that contract: it hands you a pre-typed `Hono<HonoEnv>`
30
+ * app (so `c.var.user` / `c.var.driver` are typed) plus a
31
+ * {@link RebaseFunctionContext}, and returns exactly the Hono app the loader
32
+ * already accepts — so it is fully interchangeable with a plain
33
+ * `export default new Hono()`.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * import { defineFunction, requireAuth } from "@rebasepro/server-core";
38
+ *
39
+ * export default defineFunction((app, { rebase }) => {
40
+ * app.use("/*", requireAuth);
41
+ * app.get("/home", async (c) => {
42
+ * const [stats] = await rebase.sql!(`SELECT count(*) AS n FROM orders`);
43
+ * return c.json({ orders: Number(stats.n) });
44
+ * });
45
+ * });
46
+ * ```
47
+ *
48
+ * @param definition Receives the function's Hono app and the typed context.
49
+ * Register routes on the provided `app` and return nothing, or return your
50
+ * own `Hono<HonoEnv>` app to use instead.
51
+ * @returns The Hono app to default-export from the function file.
52
+ */
53
+ export function defineFunction(
54
+ definition: (app: Hono<HonoEnv>, ctx: RebaseFunctionContext) => void | Hono<HonoEnv>
55
+ ): Hono<HonoEnv> {
56
+ const app = new Hono<HonoEnv>();
57
+ const returned = definition(app, { rebase });
58
+ return returned instanceof Hono ? returned : app;
59
+ }
@@ -24,6 +24,10 @@ export async function loadFunctionsFromDirectory(
24
24
  directory: string
25
25
  ): Promise<LoadedFunction[]> {
26
26
  const functions: LoadedFunction[] = [];
27
+ // Aggregate problem files so a broken function surfaces as one loud
28
+ // summary line, not just a warning buried per-file. We still don't throw:
29
+ // a single malformed function must not crash server boot.
30
+ const problems: string[] = [];
27
31
 
28
32
  if (!fs.existsSync(directory)) {
29
33
  return functions;
@@ -51,6 +55,7 @@ export async function loadFunctionsFromDirectory(
51
55
 
52
56
  if (!exported) {
53
57
  logger.warn(`[functions] ${file}: no default export. Skipping.`);
58
+ problems.push(`${file} (no default export)`);
54
59
  continue;
55
60
  }
56
61
 
@@ -86,16 +91,27 @@ app: result as Hono });
86
91
  ` export type: ${exportType}${exported?.constructor?.name ? ` (${exported.constructor.name})` : ""}\n` +
87
92
  ` prototype methods: ${keys}\n` +
88
93
  " Hint: ensure the function exports a Hono app created with the same hono version as the server.\n" +
94
+ " Author with `defineFunction(...)` from @rebasepro/server-core for a typed, checked contract.\n" +
89
95
  " The loader checks for .fetch() and .routes — any Hono-compatible app will work."
90
96
  );
97
+ problems.push(`${file} (not a Hono app or factory)`);
91
98
  } catch (err: unknown) {
92
99
  const message =
93
100
  err instanceof Error ? err.message : String(err);
94
101
  logger.error(`[functions] Failed to load ${file}: ${message}`);
102
+ problems.push(`${file} (threw: ${message})`);
95
103
  }
96
104
  }
97
105
  }
98
106
 
107
+ if (problems.length > 0) {
108
+ logger.warn(
109
+ `[functions] ${problems.length} function file(s) were skipped and will NOT be served:\n` +
110
+ problems.map((p) => ` - ${p}`).join("\n") + "\n" +
111
+ " Fix these or author them with `defineFunction(...)` for a typed, compile-checked contract."
112
+ );
113
+ }
114
+
99
115
  return functions;
100
116
  }
101
117
 
@@ -1,3 +1,5 @@
1
1
  export { loadFunctionsFromDirectory } from "./function-loader";
2
2
  export type { LoadedFunction } from "./function-loader";
3
3
  export { createFunctionRoutes } from "./function-routes";
4
+ export { defineFunction } from "./define-function";
5
+ export type { RebaseFunctionContext } from "./define-function";
package/src/index.ts CHANGED
@@ -8,63 +8,96 @@
8
8
  */
9
9
 
10
10
  // =============================================================================
11
- // Abstract Interfaces (for database abstraction)
11
+ // Core Initialization
12
12
  // =============================================================================
13
- export * from "./db/interfaces";
14
- export * from "./auth/interfaces";
15
-
16
- // Core functionality
17
- export * from "./init";
13
+ export {
14
+ initializeRebaseBackend,
15
+ isAuthAdapter,
16
+ isDatabaseAdapter
17
+ } from "./init";
18
+ export type {
19
+ RebaseBackendConfig,
20
+ RebaseBackendInstance,
21
+ RebaseAuthConfig
22
+ } from "./init";
18
23
 
24
+ // =============================================================================
19
25
  // Server-side singleton (import { rebase } from "@rebasepro/server-core")
26
+ // =============================================================================
20
27
  export { rebase, _setRebaseMock, _resetRebaseMock } from "./singleton";
21
28
 
22
- // Services
23
- export * from "./services/driver-registry";
29
+ // =============================================================================
30
+ // DB Abstractions (for database driver implementations)
31
+ // =============================================================================
32
+ export * from "./db/interfaces";
24
33
 
25
- // API types (HonoEnv, ApiConfig, etc.)
26
- export * from "./api/types";
34
+ // =============================================================================
35
+ // Auth
36
+ // =============================================================================
37
+ export * from "./auth";
27
38
 
28
- // API Generation
39
+ // =============================================================================
40
+ // API Layer
41
+ // =============================================================================
29
42
  export * from "./api";
30
43
 
31
- // Types
32
- export * from "./types";
33
- export * from "./types/index";
34
-
35
- // Auth module
36
- export * from "./auth";
37
-
38
- // Email module
44
+ // =============================================================================
45
+ // Email
46
+ // =============================================================================
39
47
  export * from "./email";
40
48
 
41
- // Storage module
49
+ // =============================================================================
50
+ // Storage
51
+ // =============================================================================
42
52
  export * from "./storage";
43
53
 
44
- export * from "./utils/logging";
45
- export * from "./utils/logger";
46
- export * from "./utils/request-logger";
47
- export * from "./utils/request-id";
48
- export * from "./utils/sql";
49
-
50
- // Entity history
51
- export * from "./history";
54
+ // =============================================================================
55
+ // Entity History
56
+ // =============================================================================
57
+ export { createHistoryRoutes } from "./history";
52
58
 
59
+ // =============================================================================
53
60
  // Custom Functions (auto-discovered Hono routes)
54
- export * from "./functions";
61
+ // =============================================================================
62
+ export { loadFunctionsFromDirectory, createFunctionRoutes, defineFunction } from "./functions";
63
+ export type { LoadedFunction, RebaseFunctionContext } from "./functions";
55
64
 
65
+ // =============================================================================
56
66
  // Cron Jobs (auto-discovered scheduled tasks)
57
- export * from "./cron";
58
-
67
+ // =============================================================================
68
+ export { loadCronJobsFromDirectory, CronScheduler, validateCronExpression, createCronRoutes, createCronStore } from "./cron";
69
+ export type { LoadedCronJob, CronStore } from "./cron";
59
70
 
60
- // SPA serving helper
61
- export * from "./serve-spa";
71
+ // =============================================================================
72
+ // SQL Helpers (for RLS policies)
73
+ // =============================================================================
74
+ export { authUid, authRoles, authJwt } from "./utils/sql";
62
75
 
63
- // Dev-mode port resolution (retry on EADDRINUSE)
64
- export * from "./utils/dev-port";
76
+ // =============================================================================
77
+ // Logger
78
+ // =============================================================================
79
+ export { logger } from "./utils/logger";
80
+ export type { Logger } from "./utils/logger";
65
81
 
66
- // Environment validation
82
+ // =============================================================================
83
+ // Environment Validation
84
+ // =============================================================================
67
85
  export { loadEnv } from "./env";
68
86
  export type { RebaseEnv } from "./env";
69
- export { z } from "zod";
70
87
 
88
+ // =============================================================================
89
+ // Server-core specific types (subscription types)
90
+ // =============================================================================
91
+ export * from "./types";
92
+
93
+ // =============================================================================
94
+ // Driver Registry
95
+ // =============================================================================
96
+ export * from "./services/driver-registry";
97
+
98
+ // =============================================================================
99
+ // Internal plumbing exported for the official app/backend
100
+ // =============================================================================
101
+ export { cleanupDevPortFile, listenWithPortRetry } from "./utils/dev-port";
102
+ export { serveSPA } from "./serve-spa";
103
+ export { z } from "zod";