@rebasepro/server-core 0.2.1 → 0.2.4
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/dist/common/src/collections/default-collections.d.ts +12 -0
- package/dist/common/src/collections/index.d.ts +1 -0
- package/dist/common/src/data/query_builder.d.ts +51 -0
- package/dist/common/src/index.d.ts +1 -0
- package/dist/common/src/util/permissions.d.ts +1 -0
- package/dist/{index-BZoAtuqi.js → index-Cr1D21av.js} +11 -3
- package/dist/index-Cr1D21av.js.map +1 -0
- package/dist/index.es.js +2340 -370
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +2329 -355
- package/dist/index.umd.js.map +1 -1
- package/dist/server-core/src/api/logs-routes.d.ts +37 -0
- package/dist/server-core/src/api/rest/api-generator.d.ts +6 -0
- package/dist/server-core/src/api/types.d.ts +6 -1
- package/dist/server-core/src/auth/adapter-middleware.d.ts +7 -3
- package/dist/server-core/src/auth/admin-routes.d.ts +3 -3
- package/dist/server-core/src/auth/api-keys/api-key-middleware.d.ts +39 -0
- package/dist/server-core/src/auth/api-keys/api-key-permission-guard.d.ts +32 -0
- package/dist/server-core/src/auth/api-keys/api-key-routes.d.ts +20 -0
- package/dist/server-core/src/auth/api-keys/api-key-store.d.ts +35 -0
- package/dist/server-core/src/auth/api-keys/api-key-types.d.ts +88 -0
- package/dist/server-core/src/auth/api-keys/index.d.ts +17 -0
- package/dist/server-core/src/auth/{auth-overrides.d.ts → auth-hooks.d.ts} +69 -11
- package/dist/server-core/src/auth/builtin-auth-adapter.d.ts +3 -3
- package/dist/server-core/src/auth/index.d.ts +5 -3
- package/dist/server-core/src/auth/interfaces.d.ts +93 -3
- package/dist/server-core/src/auth/jwt.d.ts +3 -1
- package/dist/server-core/src/auth/mfa.d.ts +49 -0
- package/dist/server-core/src/auth/middleware.d.ts +7 -0
- package/dist/server-core/src/auth/rate-limiter.d.ts +19 -0
- package/dist/server-core/src/auth/routes.d.ts +3 -3
- package/dist/server-core/src/env.d.ts +6 -0
- package/dist/server-core/src/index.d.ts +1 -0
- package/dist/server-core/src/init.d.ts +3 -3
- package/dist/server-core/src/services/webhook-service.d.ts +29 -0
- package/dist/server-core/src/storage/image-transform.d.ts +48 -0
- package/dist/server-core/src/storage/index.d.ts +3 -0
- package/dist/server-core/src/storage/tus-handler.d.ts +51 -0
- package/dist/types/src/controllers/auth.d.ts +2 -24
- package/dist/types/src/controllers/client.d.ts +0 -3
- package/dist/types/src/controllers/collection_registry.d.ts +1 -1
- package/dist/types/src/controllers/data.d.ts +21 -0
- package/dist/types/src/controllers/data_driver.d.ts +18 -0
- package/dist/types/src/controllers/registry.d.ts +5 -4
- package/dist/types/src/rebase_context.d.ts +1 -1
- package/dist/types/src/types/auth_adapter.d.ts +2 -4
- package/dist/types/src/types/collections.d.ts +0 -4
- package/dist/types/src/types/component_ref.d.ts +1 -1
- package/dist/types/src/types/cron.d.ts +1 -1
- package/dist/types/src/types/entity_views.d.ts +1 -0
- package/dist/types/src/types/export_import.d.ts +1 -1
- package/dist/types/src/types/formex.d.ts +2 -2
- package/dist/types/src/types/properties.d.ts +2 -2
- package/dist/types/src/types/translations.d.ts +28 -12
- package/dist/types/src/types/user_management_delegate.d.ts +6 -4
- package/dist/types/src/users/roles.d.ts +0 -8
- package/jest.config.cjs +4 -1
- package/package.json +9 -7
- package/src/api/ast-schema-editor.ts +4 -4
- package/src/api/errors.ts +16 -7
- package/src/api/logs-routes.ts +129 -0
- package/src/api/rest/api-generator.ts +42 -2
- package/src/api/rest/query-parser.ts +37 -1
- package/src/api/types.ts +6 -1
- package/src/auth/adapter-middleware.ts +20 -4
- package/src/auth/admin-routes.ts +39 -14
- package/src/auth/api-keys/api-key-middleware.ts +126 -0
- package/src/auth/api-keys/api-key-permission-guard.ts +64 -0
- package/src/auth/api-keys/api-key-routes.ts +183 -0
- package/src/auth/api-keys/api-key-store.ts +317 -0
- package/src/auth/api-keys/api-key-types.ts +94 -0
- package/src/auth/api-keys/index.ts +37 -0
- package/src/auth/{auth-overrides.ts → auth-hooks.ts} +81 -14
- package/src/auth/builtin-auth-adapter.ts +31 -19
- package/src/auth/index.ts +7 -3
- package/src/auth/interfaces.ts +111 -3
- package/src/auth/jwt.ts +19 -5
- package/src/auth/mfa.ts +160 -0
- package/src/auth/middleware.ts +20 -1
- package/src/auth/rate-limiter.ts +92 -0
- package/src/auth/routes.ts +455 -24
- package/src/cron/cron-loader.ts +5 -10
- package/src/cron/cron-scheduler.ts +11 -12
- package/src/cron/cron-store.ts +8 -7
- package/src/env.ts +2 -0
- package/src/functions/function-loader.ts +6 -9
- package/src/index.ts +1 -2
- package/src/init.ts +37 -7
- package/src/serve-spa.ts +5 -4
- package/src/services/webhook-service.ts +155 -0
- package/src/storage/image-transform.ts +202 -0
- package/src/storage/index.ts +3 -0
- package/src/storage/routes.ts +56 -3
- package/src/storage/tus-handler.ts +315 -0
- package/src/utils/dev-port.ts +14 -0
- package/src/utils/logging.ts +9 -7
- package/test/admin-routes.test.ts +74 -7
- package/test/api-generator.test.ts +0 -1
- package/test/api-key-permission-guard.test.ts +132 -0
- package/test/ast-schema-editor.test.ts +26 -0
- package/test/auth-routes.test.ts +1 -2
- package/test/backend-hooks-admin.test.ts +3 -4
- package/test/email-templates.test.ts +169 -0
- package/test/function-loader.test.ts +124 -0
- package/test/jwt.test.ts +4 -2
- package/test/mfa.test.ts +197 -0
- package/test/middleware.test.ts +10 -5
- package/test/webhook-service.test.ts +249 -0
- package/vite.config.ts +3 -2
- package/dist/index-BZoAtuqi.js.map +0 -1
- package/dist/server-core/src/bootstrappers/index.d.ts +0 -0
- package/src/bootstrappers/index.ts +0 -1
- package/src/singleton.test.ts +0 -28
|
@@ -7,6 +7,8 @@ export interface AccessTokenPayload {
|
|
|
7
7
|
userId: string;
|
|
8
8
|
roles: string[];
|
|
9
9
|
uid?: string;
|
|
10
|
+
/** Authentication Assurance Level: aal1 = password/oauth, aal2 = MFA verified */
|
|
11
|
+
aal?: "aal1" | "aal2";
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
12
14
|
* Configure JWT settings - call this during initialization.
|
|
@@ -16,7 +18,7 @@ export declare function configureJwt(config: JwtConfig): void;
|
|
|
16
18
|
/**
|
|
17
19
|
* Generate an access token (short-lived, 1 hour by default)
|
|
18
20
|
*/
|
|
19
|
-
export declare function generateAccessToken(userId: string, roles: string[]): string;
|
|
21
|
+
export declare function generateAccessToken(userId: string, roles: string[], aal?: "aal1" | "aal2", customClaims?: Record<string, unknown>): string;
|
|
20
22
|
/**
|
|
21
23
|
* Get the expiration time of an access token in milliseconds from now
|
|
22
24
|
*/
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TOTP (Time-based One-Time Password) implementation.
|
|
3
|
+
*
|
|
4
|
+
* Pure Node.js crypto implementation — no external dependencies required.
|
|
5
|
+
* Implements RFC 6238 (TOTP) and RFC 4226 (HOTP).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Encode a Buffer to Base32 string (RFC 4648)
|
|
9
|
+
*/
|
|
10
|
+
export declare function base32Encode(buffer: Buffer): string;
|
|
11
|
+
/**
|
|
12
|
+
* Decode a Base32 string to Buffer
|
|
13
|
+
*/
|
|
14
|
+
export declare function base32Decode(encoded: string): Buffer;
|
|
15
|
+
/**
|
|
16
|
+
* Generate a TOTP value for the current time step
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateTotp(secret: Buffer, timeStep?: number): string;
|
|
19
|
+
/**
|
|
20
|
+
* Verify a TOTP token with a configurable time window
|
|
21
|
+
*
|
|
22
|
+
* @param secret - The shared secret as a Buffer
|
|
23
|
+
* @param token - The 6-digit TOTP code to verify
|
|
24
|
+
* @param window - Number of time steps to check on each side (default: 1)
|
|
25
|
+
* @returns true if the token is valid within the window
|
|
26
|
+
*/
|
|
27
|
+
export declare function verifyTotp(secret: Buffer, token: string, window?: number): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Generate a new TOTP secret and return the setup information
|
|
30
|
+
*
|
|
31
|
+
* @param issuer - The issuer name (app name) for the QR code
|
|
32
|
+
* @param accountName - The account identifier (usually email)
|
|
33
|
+
* @returns Object with base32 secret and otpauth URI
|
|
34
|
+
*/
|
|
35
|
+
export declare function generateTotpSecret(issuer: string, accountName: string): {
|
|
36
|
+
secret: string;
|
|
37
|
+
uri: string;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Generate a set of one-time recovery codes
|
|
41
|
+
*
|
|
42
|
+
* @param count - Number of recovery codes to generate (default: 10)
|
|
43
|
+
* @returns Array of formatted recovery code strings (e.g. "A1B2C-D3E4F")
|
|
44
|
+
*/
|
|
45
|
+
export declare function generateRecoveryCodes(count?: number): string[];
|
|
46
|
+
/**
|
|
47
|
+
* Hash a recovery code for storage
|
|
48
|
+
*/
|
|
49
|
+
export declare function hashRecoveryCode(code: string): string;
|
|
@@ -2,6 +2,7 @@ import { MiddlewareHandler, Context } from "hono";
|
|
|
2
2
|
import { DataDriver } from "@rebasepro/types";
|
|
3
3
|
import { AccessTokenPayload } from "./jwt";
|
|
4
4
|
import { HonoEnv } from "../api/types";
|
|
5
|
+
import type { ApiKeyStore } from "./api-keys/api-key-store";
|
|
5
6
|
/**
|
|
6
7
|
* Result from a custom auth validator.
|
|
7
8
|
* - `false`/`null`/`undefined` = not authenticated
|
|
@@ -45,6 +46,12 @@ export interface AuthMiddlewareOptions {
|
|
|
45
46
|
* timing attacks. The key must be at least 32 characters.
|
|
46
47
|
*/
|
|
47
48
|
serviceKey?: string;
|
|
49
|
+
/**
|
|
50
|
+
* API key store for authenticating `rk_` prefixed tokens.
|
|
51
|
+
* When set, tokens starting with `rk_` are validated against the
|
|
52
|
+
* database instead of being treated as JWTs.
|
|
53
|
+
*/
|
|
54
|
+
apiKeyStore?: ApiKeyStore;
|
|
48
55
|
}
|
|
49
56
|
/**
|
|
50
57
|
* Hono middleware that requires a valid JWT token
|
|
@@ -28,4 +28,23 @@ export declare const defaultAuthLimiter: MiddlewareHandler<HonoEnv>;
|
|
|
28
28
|
* 50 requests per 15 minutes per IP.
|
|
29
29
|
*/
|
|
30
30
|
export declare const strictAuthLimiter: MiddlewareHandler<HonoEnv>;
|
|
31
|
+
/**
|
|
32
|
+
* Key generator for API-key-based rate limiting.
|
|
33
|
+
*
|
|
34
|
+
* Uses the API key ID (from `c.get("apiKey")`) as the rate limit key.
|
|
35
|
+
* Falls back to IP-based keying when the request is not authenticated
|
|
36
|
+
* via an API key.
|
|
37
|
+
*/
|
|
38
|
+
export declare function apiKeyKeyGenerator(c: Parameters<MiddlewareHandler<HonoEnv>>[0]): string;
|
|
39
|
+
/**
|
|
40
|
+
* Create a rate limiter specifically for API key requests.
|
|
41
|
+
*
|
|
42
|
+
* When a request is authenticated via an API key that has a `rate_limit`
|
|
43
|
+
* configured, this limiter enforces per-key limits using the key's ID
|
|
44
|
+
* as the rate limit bucket.
|
|
45
|
+
*
|
|
46
|
+
* @param defaultLimit - Fallback limit when the key has no `rate_limit` set.
|
|
47
|
+
* @param windowMs - Time window in milliseconds (default: 15 minutes).
|
|
48
|
+
*/
|
|
49
|
+
export declare function createApiKeyRateLimiter(defaultLimit?: number, windowMs?: number): MiddlewareHandler<HonoEnv>;
|
|
31
50
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
2
|
import type { AuthRepository, OAuthProvider } from "./interfaces";
|
|
3
|
-
import type {
|
|
3
|
+
import type { AuthHooks } from "./auth-hooks";
|
|
4
4
|
import { EmailService, EmailConfig } from "../email";
|
|
5
5
|
import { HonoEnv } from "../api/types";
|
|
6
6
|
/**
|
|
@@ -19,10 +19,10 @@ export interface AuthModuleConfig {
|
|
|
19
19
|
/** When true, blocks all self-registration regardless of `allowRegistration`. */
|
|
20
20
|
disableSelfRegistration?: boolean;
|
|
21
21
|
/**
|
|
22
|
-
* Auth
|
|
22
|
+
* Auth hooks for customizing password hashing, credential
|
|
23
23
|
* verification, lifecycle hooks, etc.
|
|
24
24
|
*/
|
|
25
|
-
|
|
25
|
+
authHooks?: AuthHooks;
|
|
26
26
|
/**
|
|
27
27
|
* Callback that checks if bootstrap has already been completed.
|
|
28
28
|
* Used by GET /auth/config to report `needsSetup` status.
|
|
@@ -20,6 +20,8 @@ declare const rebaseEnvSchema: z.ZodObject<{
|
|
|
20
20
|
DB_POOL_MAX: z.ZodEffects<z.ZodDefault<z.ZodString>, number, string | undefined>;
|
|
21
21
|
DB_POOL_IDLE_TIMEOUT: z.ZodEffects<z.ZodDefault<z.ZodString>, number, string | undefined>;
|
|
22
22
|
DB_POOL_CONNECT_TIMEOUT: z.ZodEffects<z.ZodDefault<z.ZodString>, number, string | undefined>;
|
|
23
|
+
DATABASE_DIRECT_URL: z.ZodOptional<z.ZodString>;
|
|
24
|
+
DATABASE_READ_URL: z.ZodOptional<z.ZodString>;
|
|
23
25
|
FORCE_LOCAL_STORAGE: z.ZodEffects<z.ZodOptional<z.ZodEnum<["true", "false", ""]>>, boolean, "" | "true" | "false" | undefined>;
|
|
24
26
|
STORAGE_TYPE: z.ZodDefault<z.ZodEnum<["local", "s3"]>>;
|
|
25
27
|
STORAGE_PATH: z.ZodOptional<z.ZodString>;
|
|
@@ -50,6 +52,8 @@ declare const rebaseEnvSchema: z.ZodObject<{
|
|
|
50
52
|
REBASE_SERVICE_KEY?: string | undefined;
|
|
51
53
|
CORS_ORIGINS?: string | undefined;
|
|
52
54
|
FRONTEND_URL?: string | undefined;
|
|
55
|
+
DATABASE_DIRECT_URL?: string | undefined;
|
|
56
|
+
DATABASE_READ_URL?: string | undefined;
|
|
53
57
|
STORAGE_PATH?: string | undefined;
|
|
54
58
|
S3_BUCKET?: string | undefined;
|
|
55
59
|
S3_REGION?: string | undefined;
|
|
@@ -74,6 +78,8 @@ declare const rebaseEnvSchema: z.ZodObject<{
|
|
|
74
78
|
DB_POOL_MAX?: string | undefined;
|
|
75
79
|
DB_POOL_IDLE_TIMEOUT?: string | undefined;
|
|
76
80
|
DB_POOL_CONNECT_TIMEOUT?: string | undefined;
|
|
81
|
+
DATABASE_DIRECT_URL?: string | undefined;
|
|
82
|
+
DATABASE_READ_URL?: string | undefined;
|
|
77
83
|
FORCE_LOCAL_STORAGE?: "" | "true" | "false" | undefined;
|
|
78
84
|
STORAGE_TYPE?: "local" | "s3" | undefined;
|
|
79
85
|
STORAGE_PATH?: string | undefined;
|
|
@@ -7,7 +7,7 @@ import { HonoEnv } from "./api/types";
|
|
|
7
7
|
import { BackendStorageConfig, StorageController, StorageRegistry } from "./storage";
|
|
8
8
|
import { EmailConfig } from "./email";
|
|
9
9
|
import type { OAuthProvider } from "./auth/interfaces";
|
|
10
|
-
import type {
|
|
10
|
+
import type { AuthHooks } from "./auth/auth-hooks";
|
|
11
11
|
export interface RebaseAuthConfig {
|
|
12
12
|
jwtSecret?: string;
|
|
13
13
|
accessExpiresIn?: string;
|
|
@@ -93,13 +93,13 @@ export interface RebaseAuthConfig {
|
|
|
93
93
|
* ```ts
|
|
94
94
|
* import bcrypt from "bcrypt";
|
|
95
95
|
*
|
|
96
|
-
*
|
|
96
|
+
* hooks: {
|
|
97
97
|
* hashPassword: (pw) => bcrypt.hash(pw, 12),
|
|
98
98
|
* verifyPassword: (pw, hash) => bcrypt.compare(pw, hash),
|
|
99
99
|
* }
|
|
100
100
|
* ```
|
|
101
101
|
*/
|
|
102
|
-
|
|
102
|
+
hooks?: AuthHooks;
|
|
103
103
|
[key: string]: unknown;
|
|
104
104
|
}
|
|
105
105
|
export interface RebaseBackendConfig {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface WebhookConfig {
|
|
2
|
+
id: string;
|
|
3
|
+
url: string;
|
|
4
|
+
secret?: string;
|
|
5
|
+
headers?: Record<string, string>;
|
|
6
|
+
events: string[];
|
|
7
|
+
table: string;
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface WebhookDeliveryResult {
|
|
11
|
+
webhookId: string;
|
|
12
|
+
event: string;
|
|
13
|
+
payload: Record<string, unknown>;
|
|
14
|
+
statusCode: number;
|
|
15
|
+
responseBody: string;
|
|
16
|
+
success: boolean;
|
|
17
|
+
attemptNumber: number;
|
|
18
|
+
}
|
|
19
|
+
export declare class WebhookDispatcher {
|
|
20
|
+
private webhooks;
|
|
21
|
+
private maxRetries;
|
|
22
|
+
private retryDelays;
|
|
23
|
+
/** Register webhooks to watch */
|
|
24
|
+
setWebhooks(webhooks: WebhookConfig[]): void;
|
|
25
|
+
/** Called when an entity changes — checks if any webhook matches */
|
|
26
|
+
onEntityChange(table: string, event: "INSERT" | "UPDATE" | "DELETE", entityId: string, entity: Record<string, unknown> | null, previousEntity?: Record<string, unknown> | null): Promise<WebhookDeliveryResult[]>;
|
|
27
|
+
private deliverWithRetry;
|
|
28
|
+
private deliver;
|
|
29
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image Transformation Service
|
|
3
|
+
*
|
|
4
|
+
* Provides on-the-fly image resize, crop, format conversion, and quality
|
|
5
|
+
* adjustment using the `sharp` library. Results are cached in an LRU
|
|
6
|
+
* in-memory cache to avoid redundant processing.
|
|
7
|
+
*/
|
|
8
|
+
/** Options that can be specified via query parameters. */
|
|
9
|
+
export interface ImageTransformOptions {
|
|
10
|
+
width?: number;
|
|
11
|
+
height?: number;
|
|
12
|
+
quality?: number;
|
|
13
|
+
format?: "webp" | "avif" | "jpeg" | "png";
|
|
14
|
+
fit?: "cover" | "contain" | "fill" | "inside" | "outside";
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Parse transform options from URL query parameters.
|
|
18
|
+
* Returns `null` when no transformation is requested.
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseTransformOptions(query: Record<string, string>): ImageTransformOptions | null;
|
|
21
|
+
/** Check whether a content type is a transformable image. */
|
|
22
|
+
export declare function isTransformableImage(contentType: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Apply image transformations and return the result buffer + content type.
|
|
25
|
+
*/
|
|
26
|
+
export declare function transformImage(buffer: Buffer | Uint8Array, options: ImageTransformOptions): Promise<{
|
|
27
|
+
data: Buffer;
|
|
28
|
+
contentType: string;
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Simple LRU cache for transformed images.
|
|
32
|
+
*
|
|
33
|
+
* Entries expire after `maxAgeMs` (default: 1 hour) and the cache
|
|
34
|
+
* evicts the oldest entry when `maxEntries` is exceeded.
|
|
35
|
+
*/
|
|
36
|
+
export declare class TransformCache {
|
|
37
|
+
private cache;
|
|
38
|
+
private readonly maxEntries;
|
|
39
|
+
private readonly maxAgeMs;
|
|
40
|
+
constructor(maxEntries?: number, maxAgeMs?: number);
|
|
41
|
+
/** Build a deterministic cache key from file key + transform options. */
|
|
42
|
+
buildKey(fileKey: string, options: ImageTransformOptions): string;
|
|
43
|
+
get(cacheKey: string): {
|
|
44
|
+
data: Buffer;
|
|
45
|
+
contentType: string;
|
|
46
|
+
} | null;
|
|
47
|
+
set(cacheKey: string, data: Buffer, contentType: string): void;
|
|
48
|
+
}
|
|
@@ -15,6 +15,9 @@ export { S3StorageController } from "./S3StorageController";
|
|
|
15
15
|
export { createStorageRoutes } from "./routes";
|
|
16
16
|
export type { StorageRoutesConfig } from "./routes";
|
|
17
17
|
export * from "./storage-registry";
|
|
18
|
+
export { parseTransformOptions, transformImage, isTransformableImage, TransformCache } from "./image-transform";
|
|
19
|
+
export type { ImageTransformOptions } from "./image-transform";
|
|
20
|
+
export { TusHandler } from "./tus-handler";
|
|
18
21
|
import { BackendStorageConfig, StorageController } from "./types";
|
|
19
22
|
/**
|
|
20
23
|
* Create a storage controller from a config object.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TUS Protocol Handler
|
|
3
|
+
*
|
|
4
|
+
* Implements the TUS v1.0.0 resumable upload protocol with the
|
|
5
|
+
* Creation and Termination extensions. Uploads are stored in a
|
|
6
|
+
* temporary directory and moved to final storage on completion.
|
|
7
|
+
*
|
|
8
|
+
* @see https://tus.io/protocols/resumable-upload
|
|
9
|
+
*/
|
|
10
|
+
import type { Context } from "hono";
|
|
11
|
+
import type { StorageController } from "./types";
|
|
12
|
+
/**
|
|
13
|
+
* TUS resumable upload handler.
|
|
14
|
+
*
|
|
15
|
+
* Each instance manages uploads for a single storage root. The
|
|
16
|
+
* `storageController` is used to finalize completed uploads by
|
|
17
|
+
* calling `putObject`.
|
|
18
|
+
*/
|
|
19
|
+
export declare class TusHandler {
|
|
20
|
+
private storageController?;
|
|
21
|
+
private uploads;
|
|
22
|
+
private tusDir;
|
|
23
|
+
private cleanupTimer?;
|
|
24
|
+
constructor(storageBaseDir: string, storageController?: StorageController | undefined);
|
|
25
|
+
/** Ensure the temp directory exists. */
|
|
26
|
+
private ensureDir;
|
|
27
|
+
/** Start periodic cleanup of stale uploads. */
|
|
28
|
+
startCleanup(): void;
|
|
29
|
+
/** Remove uploads that have been idle for longer than UPLOAD_EXPIRY_MS. */
|
|
30
|
+
private cleanupStale;
|
|
31
|
+
/**
|
|
32
|
+
* Parse the `Upload-Metadata` header.
|
|
33
|
+
*
|
|
34
|
+
* Format: `key base64value,key2 base64value2`
|
|
35
|
+
*/
|
|
36
|
+
private parseMetadata;
|
|
37
|
+
/** `OPTIONS /tus` — TUS capability discovery. */
|
|
38
|
+
options(): Response;
|
|
39
|
+
/** `POST /tus` — Create a new upload. */
|
|
40
|
+
create(c: Context): Promise<Response>;
|
|
41
|
+
/** `HEAD /tus/:id` — Query upload progress. */
|
|
42
|
+
head(c: Context, id: string): Response;
|
|
43
|
+
/** `PATCH /tus/:id` — Append data to an upload. */
|
|
44
|
+
patch(c: Context, id: string): Promise<Response>;
|
|
45
|
+
/** `DELETE /tus/:id` — Cancel and remove an upload. */
|
|
46
|
+
delete(c: Context, id: string): Promise<Response>;
|
|
47
|
+
/**
|
|
48
|
+
* Move a completed upload into the storage controller.
|
|
49
|
+
*/
|
|
50
|
+
private finalize;
|
|
51
|
+
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { StorageSource } from "./storage";
|
|
2
1
|
import { Role, User } from "../users";
|
|
3
|
-
import { RebaseData } from "./data";
|
|
4
2
|
/**
|
|
5
3
|
* Capabilities advertised by an auth provider.
|
|
6
4
|
* UI components use this to show/hide features dynamically
|
|
@@ -89,6 +87,8 @@ export interface AuthControllerExtended<USER extends User = User, ExtraData = un
|
|
|
89
87
|
code: string;
|
|
90
88
|
redirectUri: string;
|
|
91
89
|
}) => Promise<void>;
|
|
90
|
+
/** Generic OAuth login — works with any provider. Posts payload to /auth/{providerId}. */
|
|
91
|
+
oauthLogin?: (providerId: string, payload: Record<string, unknown>) => Promise<void>;
|
|
92
92
|
/** Register a new user */
|
|
93
93
|
register?(email: string, password: string, displayName?: string): Promise<void>;
|
|
94
94
|
/** Skip login (for anonymous access if enabled) */
|
|
@@ -102,25 +102,3 @@ export interface AuthControllerExtended<USER extends User = User, ExtraData = un
|
|
|
102
102
|
/** Update user profile */
|
|
103
103
|
updateProfile?(displayName?: string, photoURL?: string): Promise<USER>;
|
|
104
104
|
}
|
|
105
|
-
/**
|
|
106
|
-
* Implement this function to allow access to specific users.
|
|
107
|
-
* @group Hooks and utilities
|
|
108
|
-
*/
|
|
109
|
-
export type Authenticator<USER extends User = User> = (props: {
|
|
110
|
-
/**
|
|
111
|
-
* Logged-in user or null
|
|
112
|
-
*/
|
|
113
|
-
user: USER | null;
|
|
114
|
-
/**
|
|
115
|
-
* AuthController
|
|
116
|
-
*/
|
|
117
|
-
authController: AuthController<USER>;
|
|
118
|
-
/**
|
|
119
|
-
* Unified data access API
|
|
120
|
-
*/
|
|
121
|
-
data: RebaseData;
|
|
122
|
-
/**
|
|
123
|
-
* Used storage implementation
|
|
124
|
-
*/
|
|
125
|
-
storageSource: StorageSource;
|
|
126
|
-
}) => boolean | Promise<boolean>;
|
|
@@ -65,7 +65,6 @@ export interface AdminRole {
|
|
|
65
65
|
name: string;
|
|
66
66
|
isAdmin: boolean;
|
|
67
67
|
defaultPermissions: Record<string, unknown> | null;
|
|
68
|
-
config: Record<string, unknown> | null;
|
|
69
68
|
}
|
|
70
69
|
/**
|
|
71
70
|
* Client-side Admin API interface.
|
|
@@ -123,7 +122,6 @@ export interface AdminAPI {
|
|
|
123
122
|
name: string;
|
|
124
123
|
isAdmin?: boolean;
|
|
125
124
|
defaultPermissions?: Record<string, unknown>;
|
|
126
|
-
config?: Record<string, unknown>;
|
|
127
125
|
}): Promise<{
|
|
128
126
|
role: AdminRole;
|
|
129
127
|
}>;
|
|
@@ -131,7 +129,6 @@ export interface AdminAPI {
|
|
|
131
129
|
name?: string;
|
|
132
130
|
isAdmin?: boolean;
|
|
133
131
|
defaultPermissions?: Record<string, unknown>;
|
|
134
|
-
config?: Record<string, unknown>;
|
|
135
132
|
}): Promise<{
|
|
136
133
|
role: AdminRole;
|
|
137
134
|
}>;
|
|
@@ -4,7 +4,7 @@ import type { EntityReference } from "../types/entities";
|
|
|
4
4
|
* Controller that provides access to the registered entity collections.
|
|
5
5
|
* @group Models
|
|
6
6
|
*/
|
|
7
|
-
export type CollectionRegistryController<DB = Record<string, unknown>, EC extends EntityCollection = EntityCollection
|
|
7
|
+
export type CollectionRegistryController<DB = Record<string, unknown>, EC extends EntityCollection = EntityCollection> = {
|
|
8
8
|
/**
|
|
9
9
|
* List of the mapped collections in the CMS.
|
|
10
10
|
* Each entry relates to a collection in the root database.
|
|
@@ -76,6 +76,21 @@ export interface FindResponse<M extends Record<string, unknown> = Record<string,
|
|
|
76
76
|
hasMore: boolean;
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
|
+
export type FilterOperator = WhereFilterOpShort;
|
|
80
|
+
/**
|
|
81
|
+
* Fluent Query Builder Interface supported on both client and server accessors.
|
|
82
|
+
* @group Data
|
|
83
|
+
*/
|
|
84
|
+
export interface QueryBuilderInterface<M extends Record<string, unknown> = Record<string, unknown>> {
|
|
85
|
+
where(column: keyof M & string, operator: FilterOperator, value: unknown): this;
|
|
86
|
+
orderBy(column: keyof M & string, ascending?: "asc" | "desc"): this;
|
|
87
|
+
limit(count: number): this;
|
|
88
|
+
offset(count: number): this;
|
|
89
|
+
search(searchString: string): this;
|
|
90
|
+
include(...relations: string[]): this;
|
|
91
|
+
find(): Promise<FindResponse<M>>;
|
|
92
|
+
listen(onUpdate: (data: FindResponse<M>) => void, onError?: (error: Error) => void): () => void;
|
|
93
|
+
}
|
|
79
94
|
/**
|
|
80
95
|
* A single collection's CRUD accessor.
|
|
81
96
|
*
|
|
@@ -124,6 +139,12 @@ export interface CollectionAccessor<M extends Record<string, unknown> = Record<s
|
|
|
124
139
|
* Count the number of records matching the given filter.
|
|
125
140
|
*/
|
|
126
141
|
count?(params?: FindParams): Promise<number>;
|
|
142
|
+
where(column: keyof M & string, operator: FilterOperator, value: unknown): QueryBuilderInterface<M>;
|
|
143
|
+
orderBy(column: keyof M & string, ascending?: "asc" | "desc"): QueryBuilderInterface<M>;
|
|
144
|
+
limit(count: number): QueryBuilderInterface<M>;
|
|
145
|
+
offset(count: number): QueryBuilderInterface<M>;
|
|
146
|
+
search(searchString: string): QueryBuilderInterface<M>;
|
|
147
|
+
include(...relations: string[]): QueryBuilderInterface<M>;
|
|
127
148
|
}
|
|
128
149
|
/**
|
|
129
150
|
* The unified data access object.
|
|
@@ -17,6 +17,21 @@ export type ListenEntityProps<M extends Record<string, unknown> = Record<string,
|
|
|
17
17
|
onUpdate: (entity: Entity<M> | null) => void;
|
|
18
18
|
onError?: (error: Error) => void;
|
|
19
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* Configuration for vector similarity search queries.
|
|
22
|
+
* Vector search applies an ORDER BY distance expression and optionally
|
|
23
|
+
* filters results by a distance threshold.
|
|
24
|
+
*/
|
|
25
|
+
export interface VectorSearchParams {
|
|
26
|
+
/** Property name containing the vector column */
|
|
27
|
+
property: string;
|
|
28
|
+
/** Query vector to compare against */
|
|
29
|
+
vector: number[];
|
|
30
|
+
/** Distance function (default: "cosine") */
|
|
31
|
+
distance?: "cosine" | "l2" | "inner_product";
|
|
32
|
+
/** Only return results within this distance threshold */
|
|
33
|
+
threshold?: number;
|
|
34
|
+
}
|
|
20
35
|
/**
|
|
21
36
|
* @internal
|
|
22
37
|
*/
|
|
@@ -30,6 +45,8 @@ export interface FetchCollectionProps<M extends Record<string, unknown> = Record
|
|
|
30
45
|
orderBy?: string;
|
|
31
46
|
searchString?: string;
|
|
32
47
|
order?: "desc" | "asc";
|
|
48
|
+
/** Vector similarity search configuration */
|
|
49
|
+
vectorSearch?: VectorSearchParams;
|
|
33
50
|
}
|
|
34
51
|
/**
|
|
35
52
|
* @internal
|
|
@@ -187,6 +204,7 @@ export interface RestFetchService {
|
|
|
187
204
|
startAfter?: Record<string, unknown>;
|
|
188
205
|
searchString?: string;
|
|
189
206
|
databaseId?: string;
|
|
207
|
+
vectorSearch?: VectorSearchParams;
|
|
190
208
|
}, include?: string[]): Promise<Record<string, unknown>[]>;
|
|
191
209
|
/**
|
|
192
210
|
* Fetch a single flattened entity with optional relation includes.
|
|
@@ -4,6 +4,7 @@ import type { EntityCollectionsBuilder } from "../types/builders";
|
|
|
4
4
|
import type { EntityCustomView } from "../types/entity_views";
|
|
5
5
|
import type { EntityAction } from "../types/entity_actions";
|
|
6
6
|
import type { AppView, NavigationGroupMapping } from "./navigation";
|
|
7
|
+
import type { RebasePlugin } from "../types/plugins";
|
|
7
8
|
/**
|
|
8
9
|
* Options to enable the built-in collection editor.
|
|
9
10
|
* When provided to `<RebaseCMS>`, the editor is auto-wired as a native feature.
|
|
@@ -19,12 +20,12 @@ export interface CollectionEditorOptions {
|
|
|
19
20
|
/** Suggested base paths shown when creating new collections. */
|
|
20
21
|
pathSuggestions?: string[];
|
|
21
22
|
}
|
|
22
|
-
export interface RebaseCMSConfig<EC extends EntityCollection =
|
|
23
|
+
export interface RebaseCMSConfig<EC extends EntityCollection = EntityCollection> {
|
|
23
24
|
collections?: EC[] | EntityCollectionsBuilder<EC>;
|
|
24
25
|
homePage?: ReactNode;
|
|
25
|
-
entityViews?: EntityCustomView
|
|
26
|
+
entityViews?: EntityCustomView[];
|
|
26
27
|
entityActions?: EntityAction[];
|
|
27
|
-
plugins?:
|
|
28
|
+
plugins?: RebasePlugin[];
|
|
28
29
|
/**
|
|
29
30
|
* Centralized configuration for how collections and views are grouped
|
|
30
31
|
* in the navigation sidebar and home page.
|
|
@@ -42,7 +43,7 @@ export interface RebaseCMSConfig<EC extends EntityCollection = any> {
|
|
|
42
43
|
collectionEditor?: boolean | CollectionEditorOptions;
|
|
43
44
|
}
|
|
44
45
|
export interface RebaseStudioConfig {
|
|
45
|
-
tools?: ("sql" | "js" | "rls" | "schema" | "storage" | "cron" | "schema-visualizer" | "branches" | "api")[];
|
|
46
|
+
tools?: ("sql" | "js" | "rls" | "schema" | "storage" | "cron" | "schema-visualizer" | "branches" | "api" | "logs")[];
|
|
46
47
|
homePage?: ReactNode;
|
|
47
48
|
devViews?: AppView[];
|
|
48
49
|
}
|
|
@@ -28,7 +28,7 @@ export type RebaseCallContext<USER extends User = User> = {
|
|
|
28
28
|
* const { client } = props.context;
|
|
29
29
|
* const result = await client.functions.invoke('extract-job', { url });
|
|
30
30
|
*/
|
|
31
|
-
client: RebaseClient
|
|
31
|
+
client: RebaseClient;
|
|
32
32
|
/**
|
|
33
33
|
* Unified data access — `context.data.products.create(...)`.
|
|
34
34
|
* Access any collection as a dynamic property.
|
|
@@ -133,7 +133,7 @@ export interface AuthUserData {
|
|
|
133
133
|
displayName?: string | null;
|
|
134
134
|
photoUrl?: string | null;
|
|
135
135
|
emailVerified?: boolean;
|
|
136
|
-
metadata?: Record<string,
|
|
136
|
+
metadata?: Record<string, unknown>;
|
|
137
137
|
createdAt?: Date;
|
|
138
138
|
updatedAt?: Date;
|
|
139
139
|
}
|
|
@@ -146,7 +146,7 @@ export interface AuthCreateUserData {
|
|
|
146
146
|
password?: string;
|
|
147
147
|
displayName?: string;
|
|
148
148
|
photoUrl?: string;
|
|
149
|
-
metadata?: Record<string,
|
|
149
|
+
metadata?: Record<string, unknown>;
|
|
150
150
|
}
|
|
151
151
|
/**
|
|
152
152
|
* Role data exposed by the auth adapter.
|
|
@@ -168,7 +168,6 @@ export interface AuthRoleData {
|
|
|
168
168
|
edit?: boolean;
|
|
169
169
|
delete?: boolean;
|
|
170
170
|
}> | null;
|
|
171
|
-
config?: Record<string, unknown> | null;
|
|
172
171
|
}
|
|
173
172
|
/**
|
|
174
173
|
* Data for creating a role.
|
|
@@ -180,7 +179,6 @@ export interface AuthCreateRoleData {
|
|
|
180
179
|
isAdmin?: boolean;
|
|
181
180
|
defaultPermissions?: AuthRoleData["defaultPermissions"];
|
|
182
181
|
collectionPermissions?: AuthRoleData["collectionPermissions"];
|
|
183
|
-
config?: AuthRoleData["config"];
|
|
184
182
|
}
|
|
185
183
|
/**
|
|
186
184
|
* User management operations for the admin panel.
|
|
@@ -589,10 +589,6 @@ export interface FilterPreset<Key extends string = string> {
|
|
|
589
589
|
*/
|
|
590
590
|
sort?: [Key, "asc" | "desc"];
|
|
591
591
|
}
|
|
592
|
-
/**
|
|
593
|
-
* @deprecated Use {@link FilterPreset} instead.
|
|
594
|
-
*/
|
|
595
|
-
export type QuickFilter<Key extends string = string> = FilterPreset<Key>;
|
|
596
592
|
/**
|
|
597
593
|
* Used to indicate valid filter combinations (e.g. created in Firestore)
|
|
598
594
|
* If the user selects a specific filter/sort combination, the CMS checks if it's
|
|
@@ -37,7 +37,7 @@ export interface LazyComponentRef<P = unknown> {
|
|
|
37
37
|
*
|
|
38
38
|
* @group Types
|
|
39
39
|
*/
|
|
40
|
-
export type ComponentRef<P =
|
|
40
|
+
export type ComponentRef<P = any> = React.ComponentType<P> | LazyComponentRef<P> | (() => Promise<{
|
|
41
41
|
default: React.ComponentType<P>;
|
|
42
42
|
}>) | string;
|
|
43
43
|
/**
|
|
@@ -44,7 +44,7 @@ export interface CronJobContext {
|
|
|
44
44
|
/** A simple logger scoped to this job run. */
|
|
45
45
|
log: (...args: unknown[]) => void;
|
|
46
46
|
/** The RebaseClient instance to interact with the database. */
|
|
47
|
-
client: RebaseClient
|
|
47
|
+
client: RebaseClient;
|
|
48
48
|
}
|
|
49
49
|
export type CronJobRunState = "idle" | "running" | "success" | "error" | "disabled";
|
|
50
50
|
/**
|
|
@@ -50,6 +50,7 @@ export interface FormContext<M extends Record<string, unknown> = Record<string,
|
|
|
50
50
|
export type EntityCustomView<M extends Record<string, unknown> = Record<string, unknown>> = {
|
|
51
51
|
key: string;
|
|
52
52
|
name: string;
|
|
53
|
+
icon?: string | React.ReactNode;
|
|
53
54
|
tabComponent?: React.ReactNode;
|
|
54
55
|
includeActions?: boolean | "bottom";
|
|
55
56
|
Builder?: ComponentRef<EntityCustomViewParams<M>>;
|
|
@@ -15,7 +15,7 @@ export interface ExportConfig<USER extends User = User> {
|
|
|
15
15
|
export interface ExportMappingFunction<USER extends User = User> {
|
|
16
16
|
key: string;
|
|
17
17
|
builder: ({ entity, context }: {
|
|
18
|
-
entity: Entity
|
|
18
|
+
entity: Entity;
|
|
19
19
|
context: RebaseContext<USER>;
|
|
20
20
|
}) => Promise<string> | string;
|
|
21
21
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { FormEvent } from "react";
|
|
2
|
-
export type FormexController<T =
|
|
2
|
+
export type FormexController<T = unknown> = {
|
|
3
3
|
values: T;
|
|
4
4
|
initialValues: T;
|
|
5
5
|
setValues: (values: T) => void;
|
|
@@ -32,7 +32,7 @@ export type FormexController<T = any> = {
|
|
|
32
32
|
canUndo: boolean;
|
|
33
33
|
canRedo: boolean;
|
|
34
34
|
};
|
|
35
|
-
export type FormexResetProps<T =
|
|
35
|
+
export type FormexResetProps<T = unknown> = {
|
|
36
36
|
values?: T;
|
|
37
37
|
submitCount?: number;
|
|
38
38
|
errors?: Record<string, string>;
|
|
@@ -104,8 +104,8 @@ export interface BaseUIConfig<CustomProps = unknown> {
|
|
|
104
104
|
disabled?: boolean | PropertyDisabledConfig;
|
|
105
105
|
widthPercentage?: number;
|
|
106
106
|
customProps?: CustomProps;
|
|
107
|
-
Field?: ComponentRef
|
|
108
|
-
Preview?: ComponentRef
|
|
107
|
+
Field?: ComponentRef;
|
|
108
|
+
Preview?: ComponentRef;
|
|
109
109
|
}
|
|
110
110
|
export interface BaseProperty<CustomProps = unknown> {
|
|
111
111
|
ui?: BaseUIConfig<CustomProps>;
|