@rebasepro/server-core 0.7.0 → 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.
- package/build-errors.txt +52 -0
- package/dist/api/ast-schema-editor.d.ts +21 -0
- package/dist/api/collections_for_test/callbacks_test_collection.d.ts +2 -0
- package/dist/api/errors.d.ts +53 -0
- package/dist/api/graphql/graphql-schema-generator.d.ts +44 -0
- package/dist/api/graphql/index.d.ts +1 -0
- package/dist/api/index.d.ts +9 -0
- package/dist/api/logs-routes.d.ts +37 -0
- package/dist/api/openapi-generator.d.ts +16 -0
- package/dist/api/rest/api-generator.d.ts +76 -0
- package/dist/api/rest/index.d.ts +1 -0
- package/dist/api/rest/query-parser.d.ts +8 -0
- package/dist/api/schema-editor-routes.d.ts +3 -0
- package/dist/api/server.d.ts +40 -0
- package/dist/api/types.d.ts +104 -0
- package/dist/auth/adapter-middleware.d.ts +43 -0
- package/dist/auth/admin-roles-route.d.ts +18 -0
- package/dist/auth/admin-user-ops.d.ts +79 -0
- package/dist/auth/admin-users-route.d.ts +28 -0
- package/dist/auth/api-keys/api-key-middleware.d.ts +39 -0
- package/dist/auth/api-keys/api-key-permission-guard.d.ts +32 -0
- package/dist/auth/api-keys/api-key-routes.d.ts +20 -0
- package/dist/auth/api-keys/api-key-store.d.ts +35 -0
- package/dist/auth/api-keys/api-key-types.d.ts +96 -0
- package/dist/auth/api-keys/index.d.ts +17 -0
- package/dist/auth/apple-oauth.d.ts +30 -0
- package/dist/auth/auth-hooks.d.ts +242 -0
- package/dist/auth/bitbucket-oauth.d.ts +11 -0
- package/dist/auth/builtin-auth-adapter.d.ts +51 -0
- package/dist/auth/crypto-utils.d.ts +16 -0
- package/dist/auth/custom-auth-adapter.d.ts +39 -0
- package/dist/auth/discord-oauth.d.ts +14 -0
- package/dist/auth/facebook-oauth.d.ts +14 -0
- package/dist/auth/github-oauth.d.ts +15 -0
- package/dist/auth/gitlab-oauth.d.ts +13 -0
- package/dist/auth/google-oauth.d.ts +47 -0
- package/dist/auth/index.d.ts +37 -0
- package/dist/auth/interfaces.d.ts +431 -0
- package/dist/auth/jwt.d.ts +55 -0
- package/dist/auth/linkedin-oauth.d.ts +18 -0
- package/dist/auth/magic-link-routes.d.ts +30 -0
- package/dist/auth/mfa-crypto.d.ts +23 -0
- package/dist/auth/mfa-routes.d.ts +7 -0
- package/dist/auth/mfa.d.ts +49 -0
- package/dist/auth/microsoft-oauth.d.ts +16 -0
- package/dist/auth/middleware.d.ts +113 -0
- package/dist/auth/password.d.ts +22 -0
- package/dist/auth/rate-limiter.d.ts +50 -0
- package/dist/auth/reset-password-admin.d.ts +29 -0
- package/dist/auth/rls-scope.d.ts +31 -0
- package/dist/auth/routes.d.ts +35 -0
- package/dist/auth/session-routes.d.ts +27 -0
- package/dist/auth/slack-oauth.d.ts +12 -0
- package/dist/auth/spotify-oauth.d.ts +12 -0
- package/dist/auth/twitter-oauth.d.ts +18 -0
- package/dist/backend-CIxN4FVm.js +15 -0
- package/dist/backend-CIxN4FVm.js.map +1 -0
- package/dist/base64-js-C_frYBkI.js +1687 -0
- package/dist/base64-js-C_frYBkI.js.map +1 -0
- package/dist/chunk-Dze3rakg.js +42 -0
- package/dist/collections/BackendCollectionRegistry.d.ts +13 -0
- package/dist/collections/loader.d.ts +5 -0
- package/dist/cron/cron-loader.d.ts +17 -0
- package/dist/cron/cron-routes.d.ts +14 -0
- package/dist/cron/cron-scheduler.d.ts +106 -0
- package/dist/cron/cron-store.d.ts +32 -0
- package/dist/cron/index.d.ts +6 -0
- package/dist/db/interfaces.d.ts +18 -0
- package/dist/dist-DMO-zF6D.js +832 -0
- package/dist/dist-DMO-zF6D.js.map +1 -0
- package/dist/email/index.d.ts +6 -0
- package/dist/email/smtp-email-service.d.ts +25 -0
- package/dist/email/templates.d.ts +50 -0
- package/dist/email/types.d.ts +126 -0
- package/dist/env.d.ts +102 -0
- package/dist/from-VbwD7xRf.js +3849 -0
- package/dist/from-VbwD7xRf.js.map +1 -0
- package/dist/functions/define-function.d.ts +50 -0
- package/dist/functions/function-loader.d.ts +17 -0
- package/dist/functions/function-routes.d.ts +10 -0
- package/dist/functions/index.d.ts +5 -0
- package/dist/history/history-routes.d.ts +23 -0
- package/dist/history/index.d.ts +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.es.js +61322 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +103633 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/init/docs.d.ts +4 -0
- package/dist/init/health.d.ts +2 -0
- package/dist/init/middlewares.d.ts +10 -0
- package/dist/init/shutdown.d.ts +11 -0
- package/dist/init/storage.d.ts +5 -0
- package/dist/init.d.ts +314 -0
- package/dist/jws-BqRRaK11.js +616 -0
- package/dist/jws-BqRRaK11.js.map +1 -0
- package/dist/jwt-BETC8a1J.js +3560 -0
- package/dist/jwt-BETC8a1J.js.map +1 -0
- package/dist/logger-BYU66ENZ.js +94 -0
- package/dist/logger-BYU66ENZ.js.map +1 -0
- package/dist/ms-BeBSuOXN.js +125 -0
- package/dist/ms-BeBSuOXN.js.map +1 -0
- package/dist/multipart-parser-CedBDOeC.js +299 -0
- package/dist/multipart-parser-CedBDOeC.js.map +1 -0
- package/dist/serve-spa.d.ts +30 -0
- package/dist/services/driver-registry.d.ts +78 -0
- package/dist/services/routed-realtime-service.d.ts +43 -0
- package/dist/services/webhook-service.d.ts +29 -0
- package/dist/singleton.d.ts +35 -0
- package/dist/src-CB2PIpBe.js +1182 -0
- package/dist/src-CB2PIpBe.js.map +1 -0
- package/dist/src-DjzOT1kG.js +29746 -0
- package/dist/src-DjzOT1kG.js.map +1 -0
- package/dist/storage/GCSStorageController.d.ts +43 -0
- package/dist/storage/LocalStorageController.d.ts +46 -0
- package/dist/storage/S3StorageController.d.ts +36 -0
- package/dist/storage/image-transform.d.ts +50 -0
- package/dist/storage/index.d.ts +31 -0
- package/dist/storage/routes.d.ts +70 -0
- package/dist/storage/storage-registry.d.ts +78 -0
- package/dist/storage/tus-handler.d.ts +53 -0
- package/dist/storage/types.d.ts +128 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/utils/dev-port.d.ts +37 -0
- package/dist/utils/logger.d.ts +31 -0
- package/dist/utils/logging.d.ts +9 -0
- package/dist/utils/request-id.d.ts +4 -0
- package/dist/utils/request-logger.d.ts +19 -0
- package/dist/utils/sql.d.ts +27 -0
- package/package.json +22 -14
- package/src/api/graphql/graphql-schema-generator.ts +5 -5
- package/src/api/openapi-generator.ts +2 -2
- package/src/api/rest/api-generator.ts +44 -123
- package/src/api/rest/query-parser.ts +6 -23
- package/src/api/types.ts +2 -2
- package/src/auth/auth-hooks.ts +1 -1
- package/src/auth/builtin-auth-adapter.ts +1 -2
- package/src/auth/interfaces.ts +11 -2
- package/src/auth/middleware.ts +4 -4
- package/src/auth/routes.ts +1 -2
- package/src/functions/define-function.ts +59 -0
- package/src/functions/function-loader.ts +16 -0
- package/src/functions/index.ts +2 -0
- package/src/index.ts +70 -37
- package/src/init.ts +78 -21
- package/src/storage/GCSStorageController.ts +334 -0
- package/src/storage/index.ts +9 -3
- package/src/storage/routes.ts +191 -23
- package/src/storage/tus-handler.ts +16 -4
- package/src/storage/types.ts +25 -3
- package/test/api-generator.test.ts +1 -1
- package/test/auth-config-types.test.ts +40 -0
- package/test/define-function.test.ts +45 -0
- package/test/storage-routes.test.ts +160 -0
- package/test/backend-hooks-data.test.ts +0 -477
package/src/auth/interfaces.ts
CHANGED
|
@@ -74,8 +74,17 @@ export interface OAuthProvider<T = unknown> {
|
|
|
74
74
|
/** Zod schema validating the expected request payload (e.g. { code: string }) */
|
|
75
75
|
schema: z.ZodSchema<T>;
|
|
76
76
|
|
|
77
|
-
/**
|
|
78
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Verify external tokens/codes and return a standardized user profile.
|
|
79
|
+
*
|
|
80
|
+
* NOTE: Declared as method syntax (not arrow property) intentionally.
|
|
81
|
+
* This makes `OAuthProvider` bivariant in `T`, which is correct because
|
|
82
|
+
* each provider is self-contained — `schema` validates the request body
|
|
83
|
+
* and `verify` consumes the same `T`. Bivariance lets heterogeneous
|
|
84
|
+
* providers (`OAuthProvider<SpecificPayload>`) coexist in a single
|
|
85
|
+
* `OAuthProvider<unknown>[]` array without resorting to `any`.
|
|
86
|
+
*/
|
|
87
|
+
verify(payload: T): Promise<OAuthProviderProfile | null>;
|
|
79
88
|
}
|
|
80
89
|
|
|
81
90
|
/**
|
package/src/auth/middleware.ts
CHANGED
|
@@ -37,7 +37,7 @@ export interface AuthMiddlewareOptions {
|
|
|
37
37
|
* to Postgres Row-Level Security policies.
|
|
38
38
|
*/
|
|
39
39
|
requireAuth?: boolean;
|
|
40
|
-
/** Optional custom validator (for non-JWT auth, e.g.
|
|
40
|
+
/** Optional custom validator (for non-JWT auth, e.g. external auth providers) */
|
|
41
41
|
validator?: (c: Context<HonoEnv>) => Promise<AuthResult>;
|
|
42
42
|
/**
|
|
43
43
|
* A static secret key for server-to-server / script authentication.
|
|
@@ -47,7 +47,7 @@ export interface AuthMiddlewareOptions {
|
|
|
47
47
|
* roles: `["admin"]`) **without** JWT verification. The driver is scoped
|
|
48
48
|
* via `withAuth()` with the service identity.
|
|
49
49
|
*
|
|
50
|
-
* This is the Rebase equivalent of a
|
|
50
|
+
* This is the Rebase equivalent of a Service Account key.
|
|
51
51
|
* Set via `REBASE_SERVICE_KEY` in `.env` and pass through the backend config.
|
|
52
52
|
*
|
|
53
53
|
* **Security:** The comparison uses constant-time equality to prevent
|
|
@@ -245,7 +245,7 @@ export function createAuthMiddleware(options: AuthMiddlewareOptions): Middleware
|
|
|
245
245
|
// Pick the per-request delegate (multi-data-source) before scoping.
|
|
246
246
|
const driver = resolveDriver ? resolveDriver(c) : baseDriver;
|
|
247
247
|
if (validator) {
|
|
248
|
-
// Custom validator path (e.g.,
|
|
248
|
+
// Custom validator path (e.g., API keys, external auth)
|
|
249
249
|
try {
|
|
250
250
|
const authResult = await validator(c);
|
|
251
251
|
if (authResult && typeof authResult === "object") {
|
|
@@ -291,7 +291,7 @@ code: "UNAUTHORIZED" } }, 401);
|
|
|
291
291
|
|
|
292
292
|
// ── Service Key check ──────────────────────────────────
|
|
293
293
|
// Check BEFORE JWT verification. Service keys are static
|
|
294
|
-
// secrets (like
|
|
294
|
+
// secrets (like Service Account keys) that grant admin access
|
|
295
295
|
// for scripts, cron jobs, and server-to-server calls.
|
|
296
296
|
if (serviceKey && safeCompare(token, serviceKey)) {
|
|
297
297
|
const serviceUser: AccessTokenPayload = {
|
package/src/auth/routes.ts
CHANGED
|
@@ -30,8 +30,7 @@ export interface AuthModuleConfig {
|
|
|
30
30
|
/** Default role ID to assign to new users (default: none). Must NOT be "admin". */
|
|
31
31
|
defaultRole?: string;
|
|
32
32
|
/** Optional array of OAuth providers */
|
|
33
|
-
|
|
34
|
-
oauthProviders?: OAuthProvider<any>[];
|
|
33
|
+
oauthProviders?: OAuthProvider<unknown>[];
|
|
35
34
|
/** When true, blocks all self-registration regardless of `allowRegistration`. */
|
|
36
35
|
disableSelfRegistration?: boolean;
|
|
37
36
|
/**
|
|
@@ -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
|
|
package/src/functions/index.ts
CHANGED
|
@@ -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
|
-
//
|
|
11
|
+
// Core Initialization
|
|
12
12
|
// =============================================================================
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
//
|
|
23
|
-
|
|
29
|
+
// =============================================================================
|
|
30
|
+
// DB Abstractions (for database driver implementations)
|
|
31
|
+
// =============================================================================
|
|
32
|
+
export * from "./db/interfaces";
|
|
24
33
|
|
|
25
|
-
//
|
|
26
|
-
|
|
34
|
+
// =============================================================================
|
|
35
|
+
// Auth
|
|
36
|
+
// =============================================================================
|
|
37
|
+
export * from "./auth";
|
|
27
38
|
|
|
28
|
-
//
|
|
39
|
+
// =============================================================================
|
|
40
|
+
// API Layer
|
|
41
|
+
// =============================================================================
|
|
29
42
|
export * from "./api";
|
|
30
43
|
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
// Auth module
|
|
36
|
-
export * from "./auth";
|
|
37
|
-
|
|
38
|
-
// Email module
|
|
44
|
+
// =============================================================================
|
|
45
|
+
// Email
|
|
46
|
+
// =============================================================================
|
|
39
47
|
export * from "./email";
|
|
40
48
|
|
|
41
|
-
//
|
|
49
|
+
// =============================================================================
|
|
50
|
+
// Storage
|
|
51
|
+
// =============================================================================
|
|
42
52
|
export * from "./storage";
|
|
43
53
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
export
|
|
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
|
-
|
|
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
|
-
|
|
58
|
-
|
|
67
|
+
// =============================================================================
|
|
68
|
+
export { loadCronJobsFromDirectory, CronScheduler, validateCronExpression, createCronRoutes, createCronStore } from "./cron";
|
|
69
|
+
export type { LoadedCronJob, CronStore } from "./cron";
|
|
59
70
|
|
|
60
|
-
//
|
|
61
|
-
|
|
71
|
+
// =============================================================================
|
|
72
|
+
// SQL Helpers (for RLS policies)
|
|
73
|
+
// =============================================================================
|
|
74
|
+
export { authUid, authRoles, authJwt } from "./utils/sql";
|
|
62
75
|
|
|
63
|
-
//
|
|
64
|
-
|
|
76
|
+
// =============================================================================
|
|
77
|
+
// Logger
|
|
78
|
+
// =============================================================================
|
|
79
|
+
export { logger } from "./utils/logger";
|
|
80
|
+
export type { Logger } from "./utils/logger";
|
|
65
81
|
|
|
66
|
-
//
|
|
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";
|
package/src/init.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthAdapter,
|
|
3
3
|
BackendBootstrapper,
|
|
4
|
-
BackendHooks,
|
|
5
4
|
BootstrappedAuth,
|
|
6
5
|
DatabaseAdapter,
|
|
7
6
|
DataDriver,
|
|
8
7
|
DataSourceDefinition,
|
|
8
|
+
EntityCallbacks,
|
|
9
9
|
EntityCollection,
|
|
10
10
|
HealthCheckResult,
|
|
11
11
|
InitializedDriver,
|
|
@@ -83,7 +83,7 @@ export interface RebaseAuthConfig {
|
|
|
83
83
|
*
|
|
84
84
|
* When a request includes `Authorization: Bearer <serviceKey>`, it is
|
|
85
85
|
* granted admin-level access without JWT verification. This is the
|
|
86
|
-
* Rebase equivalent of a
|
|
86
|
+
* Rebase equivalent of a Service Account key.
|
|
87
87
|
*
|
|
88
88
|
* Generate with: `node -e "logger.info(require('crypto').randomBytes(48).toString('base64'))"`
|
|
89
89
|
*
|
|
@@ -92,6 +92,14 @@ export interface RebaseAuthConfig {
|
|
|
92
92
|
*/
|
|
93
93
|
serviceKey?: string;
|
|
94
94
|
email?: EmailConfig;
|
|
95
|
+
// ── Convenience shortcuts ─────────────────────────────────────────
|
|
96
|
+
// Each named field below is syntactic sugar that internally resolves
|
|
97
|
+
// to an `OAuthProvider` via the corresponding `create*Provider`
|
|
98
|
+
// factory at startup. They are equivalent to constructing the
|
|
99
|
+
// provider manually and passing it in the `providers` array.
|
|
100
|
+
//
|
|
101
|
+
// For providers not listed here, or for full control over the
|
|
102
|
+
// provider configuration, use the `providers` array directly.
|
|
95
103
|
google?: { clientId: string; clientSecret?: string };
|
|
96
104
|
linkedin?: { clientId: string; clientSecret: string };
|
|
97
105
|
github?: { clientId: string; clientSecret: string };
|
|
@@ -105,8 +113,31 @@ export interface RebaseAuthConfig {
|
|
|
105
113
|
slack?: { clientId: string; clientSecret: string };
|
|
106
114
|
spotify?: { clientId: string; clientSecret: string };
|
|
107
115
|
defaultRole?: string;
|
|
108
|
-
|
|
109
|
-
|
|
116
|
+
/**
|
|
117
|
+
* Canonical array of OAuth providers.
|
|
118
|
+
*
|
|
119
|
+
* This is the primary extension point for **all** OAuth integrations.
|
|
120
|
+
* Each entry is an `OAuthProvider<unknown>` constructed via one of
|
|
121
|
+
* the `create*Provider` factories exported from `@rebasepro/server-core`
|
|
122
|
+
* (e.g. `createGoogleProvider`, `createGitHubProvider`).
|
|
123
|
+
*
|
|
124
|
+
* The named convenience fields above (`google`, `github`, etc.) are
|
|
125
|
+
* automatically resolved into this array at startup. You can mix both
|
|
126
|
+
* approaches; named fields and explicit entries are merged (named
|
|
127
|
+
* fields are appended after explicit entries).
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* import { createGoogleProvider } from "@rebasepro/server-core";
|
|
132
|
+
*
|
|
133
|
+
* auth: {
|
|
134
|
+
* providers: [
|
|
135
|
+
* createGoogleProvider({ clientId: "…", clientSecret: "…" }),
|
|
136
|
+
* ],
|
|
137
|
+
* }
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
providers?: OAuthProvider<unknown>[];
|
|
110
141
|
/**
|
|
111
142
|
* Override specific parts of the built-in auth implementation.
|
|
112
143
|
*
|
|
@@ -131,8 +162,6 @@ export interface RebaseAuthConfig {
|
|
|
131
162
|
* Requires email to be configured.
|
|
132
163
|
*/
|
|
133
164
|
magicLink?: boolean;
|
|
134
|
-
|
|
135
|
-
[key: string]: unknown;
|
|
136
165
|
}
|
|
137
166
|
|
|
138
167
|
export interface RebaseBackendConfig {
|
|
@@ -188,11 +217,22 @@ export interface RebaseBackendConfig {
|
|
|
188
217
|
/**
|
|
189
218
|
* Storage configuration. Accepts:
|
|
190
219
|
*
|
|
191
|
-
* - A `BackendStorageConfig` object (`{ type: 'local' | 's3', ... }`)
|
|
192
|
-
* - A `StorageController` instance (for custom providers like
|
|
220
|
+
* - A `BackendStorageConfig` object (`{ type: 'local' | 's3' | 'gcs', ... }`)
|
|
221
|
+
* - A `StorageController` instance (for custom providers like Azure, etc.)
|
|
193
222
|
* - A `Record<string, ...>` of either, for multi-backend setups
|
|
194
223
|
*/
|
|
195
224
|
storage?: BackendStorageConfig | StorageController | Record<string, BackendStorageConfig | StorageController>;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Declared storage sources. Drives the client-side StorageSourceRegistry
|
|
228
|
+
* and the transport distinction (server vs direct).
|
|
229
|
+
*
|
|
230
|
+
* Server-backed sources are auto-derived from the `storage` map — you
|
|
231
|
+
* only need explicit entries for "direct" transport sources (e.g.
|
|
232
|
+
* external storage) that the backend does not proxy.
|
|
233
|
+
*/
|
|
234
|
+
storageSources?: import("@rebasepro/types").StorageSourceDefinition[];
|
|
235
|
+
|
|
196
236
|
history?: unknown;
|
|
197
237
|
/**
|
|
198
238
|
* Default security rules applied to any collection that does not define
|
|
@@ -242,14 +282,24 @@ export interface RebaseBackendConfig {
|
|
|
242
282
|
origin: string | string[] | ((origin: string) => boolean);
|
|
243
283
|
};
|
|
244
284
|
/**
|
|
245
|
-
*
|
|
246
|
-
* at the REST API boundary. These run server-side after database
|
|
247
|
-
* operations and before API responses are sent.
|
|
285
|
+
* Global lifecycle callbacks applied to every collection.
|
|
248
286
|
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
287
|
+
* Same type as per-collection `callbacks` — fires on **every** data path
|
|
288
|
+
* (REST API, WebSocket / realtime, server-side `rebase.data`).
|
|
289
|
+
*
|
|
290
|
+
* Execution order: global callbacks → collection callbacks → property callbacks.
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```ts
|
|
294
|
+
* callbacks: {
|
|
295
|
+
* afterRead({ entity, collection }) {
|
|
296
|
+
* console.log(`Read ${collection.slug}/${entity.id}`);
|
|
297
|
+
* return entity;
|
|
298
|
+
* }
|
|
299
|
+
* }
|
|
300
|
+
* ```
|
|
251
301
|
*/
|
|
252
|
-
|
|
302
|
+
callbacks?: EntityCallbacks;
|
|
253
303
|
}
|
|
254
304
|
|
|
255
305
|
/**
|
|
@@ -337,6 +387,11 @@ async function _initializeRebaseBackend(config: RebaseBackendConfig): Promise<Re
|
|
|
337
387
|
// so normalization can resolve each collection's engine.
|
|
338
388
|
const dataSourceRegistry = createDataSourceRegistry(config.dataSources);
|
|
339
389
|
collectionRegistry.setDataSources(dataSourceRegistry);
|
|
390
|
+
|
|
391
|
+
// Global lifecycle callbacks — applied to every collection, on all data paths.
|
|
392
|
+
if (config.callbacks) {
|
|
393
|
+
collectionRegistry.setGlobalCallbacks(config.callbacks);
|
|
394
|
+
}
|
|
340
395
|
let activeCollections = config.collections || [];
|
|
341
396
|
if (config.collectionsDir && activeCollections.length === 0) {
|
|
342
397
|
activeCollections = await loadCollectionsFromDirectory(config.collectionsDir);
|
|
@@ -607,8 +662,7 @@ async function _initializeRebaseBackend(config: RebaseBackendConfig): Promise<Re
|
|
|
607
662
|
|
|
608
663
|
if (!isAuthAdapter(config.auth)) {
|
|
609
664
|
const safeAuthConfig = config.auth as RebaseAuthConfig;
|
|
610
|
-
|
|
611
|
-
const oauthProviders: OAuthProvider<any>[] = [...(safeAuthConfig.providers || [])];
|
|
665
|
+
const oauthProviders: OAuthProvider<unknown>[] = [...(safeAuthConfig.providers || [])];
|
|
612
666
|
|
|
613
667
|
// Resolve configured OAuth providers via data-driven registration.
|
|
614
668
|
// Each entry maps a config key to its factory function name and required fields.
|
|
@@ -723,7 +777,10 @@ async function _initializeRebaseBackend(config: RebaseBackendConfig): Promise<Re
|
|
|
723
777
|
|
|
724
778
|
const storageRoutes = createStorageRoutes({
|
|
725
779
|
controller: storageController,
|
|
726
|
-
|
|
780
|
+
registry: storageRegistry,
|
|
781
|
+
sources: config.storageSources,
|
|
782
|
+
requireAuth: resolveRequireAuth(config.auth),
|
|
783
|
+
authAdapter
|
|
727
784
|
});
|
|
728
785
|
|
|
729
786
|
// Apply a permissive body limit specifically for the upload endpoint
|
|
@@ -825,7 +882,6 @@ async function _initializeRebaseBackend(config: RebaseBackendConfig): Promise<Re
|
|
|
825
882
|
const restGenerator = new RestApiGenerator(
|
|
826
883
|
serverCollections,
|
|
827
884
|
defaultDriver,
|
|
828
|
-
config.hooks?.data,
|
|
829
885
|
authAdapter
|
|
830
886
|
);
|
|
831
887
|
dataRouter.route("/", restGenerator.generateRoutes());
|
|
@@ -913,9 +969,10 @@ async function _initializeRebaseBackend(config: RebaseBackendConfig): Promise<Re
|
|
|
913
969
|
const functionsRouter = new Hono<HonoEnv>();
|
|
914
970
|
functionsRouter.onError(errorHandler);
|
|
915
971
|
|
|
916
|
-
// Custom functions
|
|
917
|
-
//
|
|
918
|
-
|
|
972
|
+
// Custom functions do NOT require authentication at the global level by default.
|
|
973
|
+
// This allows custom functions to define public endpoints (like webhooks).
|
|
974
|
+
// Per-route auth can be further refined inside individual functions using `requireAuth`.
|
|
975
|
+
const functionsRequireAuth = false;
|
|
919
976
|
|
|
920
977
|
// Use adapter middleware when available, fallback to built-in
|
|
921
978
|
if (authAdapter) {
|