@rebasepro/server-core 0.7.0 → 0.9.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/README.md +2 -2
- 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/index.d.ts +7 -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 +68 -0
- package/{src/api/rest/index.ts → dist/api/rest/index.d.ts} +0 -1
- package/dist/api/rest/query-parser.d.ts +6 -0
- package/dist/api/schema-editor-routes.d.ts +3 -0
- package/dist/api/types.d.ts +56 -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/{src/auth/api-keys/api-key-permission-guard.ts → dist/auth/api-keys/api-key-permission-guard.d.ts} +2 -34
- 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/{src/auth/api-keys/api-key-types.ts → dist/auth/api-keys/api-key-types.d.ts} +0 -6
- package/{src/auth/api-keys/index.ts → dist/auth/api-keys/index.d.ts} +2 -22
- package/dist/auth/apple-oauth.d.ts +30 -0
- package/{src/auth/auth-hooks.ts → dist/auth/auth-hooks.d.ts} +15 -73
- package/dist/auth/bitbucket-oauth.d.ts +11 -0
- package/dist/auth/builtin-auth-adapter.d.ts +55 -0
- package/dist/auth/cookie-utils.d.ts +32 -0
- package/{src/auth/crypto-utils.ts → dist/auth/crypto-utils.d.ts} +1 -16
- 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/{src/auth/index.ts → dist/auth/index.d.ts} +4 -22
- package/{src/auth/interfaces.ts → dist/auth/interfaces.d.ts} +20 -89
- package/dist/auth/jwt.d.ts +67 -0
- package/dist/auth/linkedin-oauth.d.ts +18 -0
- package/dist/auth/magic-link-routes.d.ts +32 -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 +158 -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 +66 -0
- package/dist/auth/session-routes.d.ts +29 -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/collections/BackendCollectionRegistry.d.ts +13 -0
- package/dist/collections/loader.d.ts +5 -0
- package/dist/cron/cron-loader.d.ts +18 -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/define-cron.d.ts +28 -0
- package/{src/cron/index.ts → dist/cron/index.d.ts} +1 -0
- package/dist/db/interfaces.d.ts +18 -0
- package/dist/dynamic-import-Dvh-K5fl.js +22 -0
- package/dist/dynamic-import-Dvh-K5fl.js.map +1 -0
- package/dist/email/index.d.ts +6 -0
- package/dist/email/smtp-email-service.d.ts +30 -0
- package/dist/email/templates.d.ts +50 -0
- package/{src/email/types.ts → dist/email/types.d.ts} +40 -36
- package/dist/env.d.ts +102 -0
- package/dist/functions/define-function.d.ts +55 -0
- package/dist/functions/function-loader.d.ts +18 -0
- package/dist/functions/function-routes.d.ts +10 -0
- package/{src/functions/index.ts → dist/functions/index.d.ts} +2 -0
- package/dist/history/history-routes.d.ts +23 -0
- package/{src/history/index.ts → dist/history/index.d.ts} +0 -1
- package/dist/index.d.ts +35 -0
- package/dist/index.es.js +18184 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +48629 -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 +65 -0
- package/dist/init/storage.d.ts +5 -0
- package/dist/init.d.ts +344 -0
- package/dist/jwt-BwIn8xmk.js +4200 -0
- package/dist/jwt-BwIn8xmk.js.map +1 -0
- package/dist/logger-BYU66ENZ.js +94 -0
- package/dist/logger-BYU66ENZ.js.map +1 -0
- package/dist/ms-DnYXB-Wd.js +162 -0
- package/dist/ms-DnYXB-Wd.js.map +1 -0
- package/dist/openapi-generator-Z9oYWLf_.js +586 -0
- package/dist/openapi-generator-Z9oYWLf_.js.map +1 -0
- package/dist/schema-editor-routes-D3ef8zu1.js +219 -0
- package/dist/schema-editor-routes-D3ef8zu1.js.map +1 -0
- package/dist/serve-spa.d.ts +36 -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 +51 -0
- package/dist/src-B4OLmNVa.js +437 -0
- package/dist/src-B4OLmNVa.js.map +1 -0
- package/dist/src-B5WkP1Rv.js +24778 -0
- package/dist/src-B5WkP1Rv.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 +40 -0
- package/dist/storage/image-transform.d.ts +50 -0
- package/{src/storage/index.ts → dist/storage/index.d.ts} +6 -21
- 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/{src/storage/types.ts → dist/storage/types.d.ts} +32 -38
- package/dist/types/index.d.ts +11 -0
- package/dist/utils/dev-port.d.ts +45 -0
- package/dist/utils/dynamic-import.d.ts +25 -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/{src/utils/sql.ts → dist/utils/sql.d.ts} +5 -16
- package/package.json +49 -22
- package/coverage/clover.xml +0 -3739
- package/coverage/coverage-final.json +0 -31
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -266
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -210
- package/coverage/lcov-report/src/api/ast-schema-editor.ts.html +0 -952
- package/coverage/lcov-report/src/api/errors.ts.html +0 -472
- package/coverage/lcov-report/src/api/graphql/graphql-schema-generator.ts.html +0 -1069
- package/coverage/lcov-report/src/api/graphql/index.html +0 -116
- package/coverage/lcov-report/src/api/index.html +0 -176
- package/coverage/lcov-report/src/api/openapi-generator.ts.html +0 -565
- package/coverage/lcov-report/src/api/rest/api-generator.ts.html +0 -994
- package/coverage/lcov-report/src/api/rest/index.html +0 -131
- package/coverage/lcov-report/src/api/rest/query-parser.ts.html +0 -550
- package/coverage/lcov-report/src/api/schema-editor-routes.ts.html +0 -202
- package/coverage/lcov-report/src/api/server.ts.html +0 -823
- package/coverage/lcov-report/src/auth/admin-routes.ts.html +0 -973
- package/coverage/lcov-report/src/auth/index.html +0 -176
- package/coverage/lcov-report/src/auth/jwt.ts.html +0 -574
- package/coverage/lcov-report/src/auth/middleware.ts.html +0 -745
- package/coverage/lcov-report/src/auth/password.ts.html +0 -310
- package/coverage/lcov-report/src/auth/services.ts.html +0 -2074
- package/coverage/lcov-report/src/collections/index.html +0 -116
- package/coverage/lcov-report/src/collections/loader.ts.html +0 -232
- package/coverage/lcov-report/src/db/auth-schema.ts.html +0 -523
- package/coverage/lcov-report/src/db/data-transformer.ts.html +0 -1753
- package/coverage/lcov-report/src/db/entityService.ts.html +0 -700
- package/coverage/lcov-report/src/db/index.html +0 -146
- package/coverage/lcov-report/src/db/services/EntityFetchService.ts.html +0 -4048
- package/coverage/lcov-report/src/db/services/EntityPersistService.ts.html +0 -883
- package/coverage/lcov-report/src/db/services/RelationService.ts.html +0 -3121
- package/coverage/lcov-report/src/db/services/entity-helpers.ts.html +0 -442
- package/coverage/lcov-report/src/db/services/index.html +0 -176
- package/coverage/lcov-report/src/db/services/index.ts.html +0 -124
- package/coverage/lcov-report/src/generate-drizzle-schema-logic.ts.html +0 -1960
- package/coverage/lcov-report/src/index.html +0 -116
- package/coverage/lcov-report/src/services/driver-registry.ts.html +0 -631
- package/coverage/lcov-report/src/services/index.html +0 -131
- package/coverage/lcov-report/src/services/postgresDataDriver.ts.html +0 -3025
- package/coverage/lcov-report/src/storage/LocalStorageController.ts.html +0 -1189
- package/coverage/lcov-report/src/storage/S3StorageController.ts.html +0 -970
- package/coverage/lcov-report/src/storage/index.html +0 -161
- package/coverage/lcov-report/src/storage/storage-registry.ts.html +0 -646
- package/coverage/lcov-report/src/storage/types.ts.html +0 -451
- package/coverage/lcov-report/src/utils/drizzle-conditions.ts.html +0 -3082
- package/coverage/lcov-report/src/utils/index.html +0 -116
- package/coverage/lcov.info +0 -7179
- package/jest.config.cjs +0 -19
- package/src/api/ast-schema-editor.ts +0 -289
- package/src/api/collections_for_test/callbacks_test_collection.ts +0 -61
- package/src/api/errors.ts +0 -278
- package/src/api/graphql/graphql-schema-generator.ts +0 -383
- package/src/api/graphql/index.ts +0 -2
- package/src/api/index.ts +0 -11
- package/src/api/logs-routes.ts +0 -132
- package/src/api/openapi-generator.ts +0 -727
- package/src/api/rest/api-generator-count.test.ts +0 -126
- package/src/api/rest/api-generator.ts +0 -747
- package/src/api/rest/query-parser.ts +0 -300
- package/src/api/schema-editor-routes.ts +0 -41
- package/src/api/server.ts +0 -271
- package/src/api/types.ts +0 -104
- package/src/auth/adapter-middleware.ts +0 -114
- package/src/auth/admin-roles-route.ts +0 -36
- package/src/auth/admin-user-ops.ts +0 -236
- package/src/auth/admin-users-route.ts +0 -302
- package/src/auth/api-keys/api-key-middleware.ts +0 -133
- package/src/auth/api-keys/api-key-routes.ts +0 -193
- package/src/auth/api-keys/api-key-store.ts +0 -340
- package/src/auth/apple-oauth.ts +0 -122
- package/src/auth/bitbucket-oauth.ts +0 -84
- package/src/auth/builtin-auth-adapter.ts +0 -380
- package/src/auth/custom-auth-adapter.ts +0 -86
- package/src/auth/discord-oauth.ts +0 -85
- package/src/auth/facebook-oauth.ts +0 -74
- package/src/auth/github-oauth.ts +0 -112
- package/src/auth/gitlab-oauth.ts +0 -72
- package/src/auth/google-oauth.ts +0 -223
- package/src/auth/jwt.ts +0 -208
- package/src/auth/linkedin-oauth.ts +0 -83
- package/src/auth/magic-link-routes.ts +0 -167
- package/src/auth/mfa-crypto.ts +0 -91
- package/src/auth/mfa-routes.ts +0 -323
- package/src/auth/mfa.ts +0 -161
- package/src/auth/microsoft-oauth.ts +0 -90
- package/src/auth/middleware.ts +0 -369
- package/src/auth/password.ts +0 -77
- package/src/auth/rate-limiter.ts +0 -225
- package/src/auth/reset-password-admin.ts +0 -160
- package/src/auth/rls-scope.ts +0 -58
- package/src/auth/routes.ts +0 -802
- package/src/auth/session-routes.ts +0 -353
- package/src/auth/slack-oauth.ts +0 -73
- package/src/auth/spotify-oauth.ts +0 -69
- package/src/auth/twitter-oauth.ts +0 -128
- package/src/collections/BackendCollectionRegistry.ts +0 -20
- package/src/collections/loader.ts +0 -50
- package/src/cron/cron-loader.ts +0 -84
- package/src/cron/cron-routes.test.ts +0 -265
- package/src/cron/cron-routes.ts +0 -85
- package/src/cron/cron-scheduler.test.ts +0 -559
- package/src/cron/cron-scheduler.ts +0 -581
- package/src/cron/cron-store.ts +0 -166
- package/src/db/interfaces.ts +0 -60
- package/src/email/index.ts +0 -19
- package/src/email/smtp-email-service.ts +0 -123
- package/src/email/templates.ts +0 -470
- package/src/env.ts +0 -227
- package/src/functions/function-loader.ts +0 -116
- package/src/functions/function-routes.ts +0 -31
- package/src/history/history-routes.ts +0 -129
- package/src/index.ts +0 -70
- package/src/init/docs.ts +0 -47
- package/src/init/health.ts +0 -37
- package/src/init/middlewares.ts +0 -61
- package/src/init/shutdown.ts +0 -56
- package/src/init/storage.ts +0 -57
- package/src/init.ts +0 -1041
- package/src/serve-spa.ts +0 -89
- package/src/services/driver-registry.ts +0 -183
- package/src/services/routed-realtime-service.ts +0 -113
- package/src/services/webhook-service.ts +0 -155
- package/src/singleton.ts +0 -70
- package/src/storage/LocalStorageController.ts +0 -389
- package/src/storage/S3StorageController.ts +0 -300
- package/src/storage/image-transform.ts +0 -218
- package/src/storage/routes.ts +0 -368
- package/src/storage/storage-registry.ts +0 -188
- package/src/storage/tus-handler.ts +0 -315
- package/src/types/index.ts +0 -27
- package/src/utils/dev-port.ts +0 -196
- package/src/utils/logger.ts +0 -143
- package/src/utils/logging.ts +0 -40
- package/src/utils/request-id.ts +0 -40
- package/src/utils/request-logger.ts +0 -72
- package/test/api-generator.test.ts +0 -588
- package/test/api-key-permission-guard.test.ts +0 -144
- package/test/ast-schema-editor.test.ts +0 -89
- package/test/auth-middleware-hono.test.ts +0 -556
- package/test/auth-routes.test.ts +0 -1098
- package/test/backend-hooks-data.test.ts +0 -477
- package/test/custom-auth-adapter.test.ts +0 -189
- package/test/driver-registry.test.ts +0 -282
- package/test/email-templates.test.ts +0 -174
- package/test/env.test.ts +0 -128
- package/test/error-propagation.test.ts +0 -226
- package/test/errors-hono.test.ts +0 -133
- package/test/errors.test.ts +0 -155
- package/test/function-loader.test.ts +0 -127
- package/test/graphql-schema-generator.test.ts +0 -554
- package/test/jwt-security.test.ts +0 -182
- package/test/jwt.test.ts +0 -326
- package/test/mfa.test.ts +0 -197
- package/test/middleware.test.ts +0 -305
- package/test/multi-datasource-routing.test.ts +0 -113
- package/test/password.test.ts +0 -165
- package/test/query-parser.test.ts +0 -233
- package/test/rate-limiter.test.ts +0 -102
- package/test/reset-password-admin.test.ts +0 -113
- package/test/routed-realtime-service.test.ts +0 -86
- package/test/safe-compare.test.ts +0 -66
- package/test/singleton.test.ts +0 -59
- package/test/smtp-email-service.test.ts +0 -169
- package/test/storage-local.test.ts +0 -271
- package/test/storage-registry.test.ts +0 -282
- package/test/storage-routes.test.ts +0 -222
- package/test/storage-s3.test.ts +0 -304
- package/test/transform-auth-response.test.ts +0 -305
- package/test/webhook-service.test.ts +0 -260
- package/tsconfig.json +0 -54
- package/tsconfig.prod.json +0 -23
- package/vite.config.ts +0 -86
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
import { pathToFileURL } from "url";
|
|
4
|
-
import { Hono } from "hono";
|
|
5
|
-
import { logger } from "../utils/logger.js";
|
|
6
|
-
|
|
7
|
-
export interface LoadedFunction {
|
|
8
|
-
/** Endpoint name derived from filename (e.g., "send-invoice") */
|
|
9
|
-
name: string;
|
|
10
|
-
/** The Hono sub-app to mount */
|
|
11
|
-
app: Hono<import("hono").Env>;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Auto-discover Hono route files from a directory.
|
|
16
|
-
*
|
|
17
|
-
* Each file should default-export a Hono app (or router).
|
|
18
|
-
* The filename (without extension) becomes the mount path:
|
|
19
|
-
* `functions/send-invoice.ts` → mounted at `/send-invoice`
|
|
20
|
-
*
|
|
21
|
-
* This mirrors how `loadCollectionsFromDirectory` works for collections.
|
|
22
|
-
*/
|
|
23
|
-
export async function loadFunctionsFromDirectory(
|
|
24
|
-
directory: string
|
|
25
|
-
): Promise<LoadedFunction[]> {
|
|
26
|
-
const functions: LoadedFunction[] = [];
|
|
27
|
-
|
|
28
|
-
if (!fs.existsSync(directory)) {
|
|
29
|
-
return functions;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const files = fs.readdirSync(directory);
|
|
33
|
-
for (const file of files) {
|
|
34
|
-
if (
|
|
35
|
-
(file.endsWith(".ts") || file.endsWith(".js")) &&
|
|
36
|
-
!file.includes(".test.") &&
|
|
37
|
-
!file.endsWith(".d.ts") &&
|
|
38
|
-
file !== "index.ts" &&
|
|
39
|
-
file !== "index.js"
|
|
40
|
-
) {
|
|
41
|
-
const filePath = path.join(directory, file);
|
|
42
|
-
try {
|
|
43
|
-
const fileUrl = pathToFileURL(filePath).href;
|
|
44
|
-
|
|
45
|
-
// Use new Function to compile dynamic import natively and bypass
|
|
46
|
-
// tsc converting import() to require() — same pattern as collection loader
|
|
47
|
-
const dynamicImport = new Function("url", "return import(url)");
|
|
48
|
-
const mod = await dynamicImport(fileUrl);
|
|
49
|
-
|
|
50
|
-
const exported = mod.default;
|
|
51
|
-
|
|
52
|
-
if (!exported) {
|
|
53
|
-
logger.warn(`[functions] ${file}: no default export. Skipping.`);
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Accept a Hono instance — use duck-typing to handle different
|
|
58
|
-
// Hono versions which may not share the same prototype.
|
|
59
|
-
if (isHonoLike(exported)) {
|
|
60
|
-
const name = path.basename(file, path.extname(file));
|
|
61
|
-
functions.push({ name,
|
|
62
|
-
app: exported as Hono });
|
|
63
|
-
logger.info(`⚡ Loaded function route: ${name}`);
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Also accept a factory function that returns a Hono instance
|
|
68
|
-
if (typeof exported === "function") {
|
|
69
|
-
const result = exported();
|
|
70
|
-
if (isHonoLike(result)) {
|
|
71
|
-
const name = path.basename(file, path.extname(file));
|
|
72
|
-
functions.push({ name,
|
|
73
|
-
app: result as Hono });
|
|
74
|
-
logger.info(`⚡ Loaded function route: ${name}`);
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Provide actionable diagnostics
|
|
80
|
-
const exportType = typeof exported;
|
|
81
|
-
const keys = exported && typeof exported === "object"
|
|
82
|
-
? Object.getOwnPropertyNames(Object.getPrototypeOf(exported)).slice(0, 10).join(", ")
|
|
83
|
-
: "N/A";
|
|
84
|
-
logger.warn(
|
|
85
|
-
`[functions] ${file}: default export is not a Hono app or factory. Skipping.\n` +
|
|
86
|
-
` export type: ${exportType}${exported?.constructor?.name ? ` (${exported.constructor.name})` : ""}\n` +
|
|
87
|
-
` prototype methods: ${keys}\n` +
|
|
88
|
-
" Hint: ensure the function exports a Hono app created with the same hono version as the server.\n" +
|
|
89
|
-
" The loader checks for .fetch() and .routes — any Hono-compatible app will work."
|
|
90
|
-
);
|
|
91
|
-
} catch (err: unknown) {
|
|
92
|
-
const message =
|
|
93
|
-
err instanceof Error ? err.message : String(err);
|
|
94
|
-
logger.error(`[functions] Failed to load ${file}: ${message}`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return functions;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Duck-type check for Hono apps.
|
|
104
|
-
* We avoid `instanceof Hono` because different Hono versions
|
|
105
|
-
* installed in the user's project vs. our dependencies will
|
|
106
|
-
* not share the same prototype, causing false negatives.
|
|
107
|
-
*/
|
|
108
|
-
function isHonoLike(obj: unknown): boolean {
|
|
109
|
-
if (!obj || typeof obj !== "object") return false;
|
|
110
|
-
// Hono instances always have .fetch() and .routes
|
|
111
|
-
const record = obj as Record<string, unknown>;
|
|
112
|
-
return (
|
|
113
|
-
typeof record.fetch === "function" &&
|
|
114
|
-
Array.isArray(record.routes)
|
|
115
|
-
);
|
|
116
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Hono } from "hono";
|
|
2
|
-
import { HonoEnv } from "../api/types";
|
|
3
|
-
import { LoadedFunction } from "./function-loader";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Mount all loaded function routes under a single Hono router.
|
|
7
|
-
*
|
|
8
|
-
* Each function is mounted at `/<function-name>`, preserving
|
|
9
|
-
* whatever HTTP methods and middleware the Hono sub-app defines.
|
|
10
|
-
*/
|
|
11
|
-
export function createFunctionRoutes(
|
|
12
|
-
functions: LoadedFunction[]
|
|
13
|
-
): Hono<HonoEnv> {
|
|
14
|
-
const router = new Hono<HonoEnv>();
|
|
15
|
-
|
|
16
|
-
// Listing endpoint: GET / → list available functions
|
|
17
|
-
router.get("/", (c) => {
|
|
18
|
-
return c.json({
|
|
19
|
-
functions: functions.map((fn) => ({
|
|
20
|
-
name: fn.name,
|
|
21
|
-
endpoint: `/functions/${fn.name}`
|
|
22
|
-
}))
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
for (const fn of functions) {
|
|
27
|
-
router.route(`/${fn.name}`, fn.app);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return router;
|
|
31
|
-
}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { Hono } from "hono";
|
|
2
|
-
import { HonoEnv } from "../api/types";
|
|
3
|
-
import { BackendCollectionRegistry } from "../collections/BackendCollectionRegistry";
|
|
4
|
-
import { ApiError, errorHandler } from "../api/errors";
|
|
5
|
-
import { DataDriver } from "@rebasepro/types";
|
|
6
|
-
/**
|
|
7
|
-
* Create Hono routes for entity history.
|
|
8
|
-
* Mounted at `{basePath}/data/:slug/:entityId/history`.
|
|
9
|
-
*/
|
|
10
|
-
export interface HistoryService {
|
|
11
|
-
fetchHistory(tableName: string, entityId: string, options: { limit: number, offset: number }): Promise<{ data: Record<string, unknown>[], total: number }>;
|
|
12
|
-
fetchHistoryEntry(historyId: string): Promise<Record<string, unknown> | null>;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function createHistoryRoutes(params: {
|
|
16
|
-
historyService: HistoryService;
|
|
17
|
-
registry: BackendCollectionRegistry;
|
|
18
|
-
driver: DataDriver;
|
|
19
|
-
}): Hono<HonoEnv> {
|
|
20
|
-
const { historyService, registry, driver } = params;
|
|
21
|
-
const router = new Hono<HonoEnv>();
|
|
22
|
-
router.onError(errorHandler);
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* GET /:slug/:entityId/history - List history entries for an entity
|
|
26
|
-
*
|
|
27
|
-
* Query params:
|
|
28
|
-
* limit (default 20)
|
|
29
|
-
* offset (default 0)
|
|
30
|
-
*/
|
|
31
|
-
router.get("/:slug/:entityId/history", async (c) => {
|
|
32
|
-
const slug = c.req.param("slug");
|
|
33
|
-
const entityId = c.req.param("entityId");
|
|
34
|
-
const parsedLimit = parseInt(c.req.query("limit") ?? "20", 10);
|
|
35
|
-
const parsedOffset = parseInt(c.req.query("offset") ?? "0", 10);
|
|
36
|
-
const limit = Number.isNaN(parsedLimit) ? 20 : parsedLimit;
|
|
37
|
-
const offset = Number.isNaN(parsedOffset) ? 0 : parsedOffset;
|
|
38
|
-
|
|
39
|
-
// Resolve the collection to get the actual table name
|
|
40
|
-
const collection = registry.getCollections().find(
|
|
41
|
-
col => col.slug === slug || false
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
if (!collection) {
|
|
45
|
-
throw ApiError.notFound(`Collection '${slug}' not found`);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (!collection.history) {
|
|
49
|
-
throw ApiError.badRequest(`History is not enabled for collection '${slug}'`);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const tableName = collection.slug;
|
|
53
|
-
|
|
54
|
-
const result = await historyService.fetchHistory(tableName, entityId, {
|
|
55
|
-
limit: Math.min(limit, 100),
|
|
56
|
-
offset: Math.max(offset, 0)
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
return c.json({
|
|
60
|
-
data: result.data,
|
|
61
|
-
meta: {
|
|
62
|
-
total: result.total,
|
|
63
|
-
limit,
|
|
64
|
-
offset,
|
|
65
|
-
hasMore: offset + result.data.length < result.total
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* POST /:slug/:entityId/history/:historyId/revert - Revert entity to a historical version
|
|
72
|
-
*
|
|
73
|
-
* This goes through the normal save path, so it creates its own history entry.
|
|
74
|
-
*/
|
|
75
|
-
router.post("/:slug/:entityId/history/:historyId/revert", async (c) => {
|
|
76
|
-
const slug = c.req.param("slug");
|
|
77
|
-
const entityId = c.req.param("entityId");
|
|
78
|
-
const historyId = c.req.param("historyId");
|
|
79
|
-
|
|
80
|
-
const collection = registry.getCollections().find(
|
|
81
|
-
col => col.slug === slug || false
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
if (!collection) {
|
|
85
|
-
throw ApiError.notFound(`Collection '${slug}' not found`);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (!collection.history) {
|
|
89
|
-
throw ApiError.badRequest(`History is not enabled for collection '${slug}'`);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Fetch the history entry
|
|
93
|
-
const historyEntry = await historyService.fetchHistoryEntry(historyId);
|
|
94
|
-
|
|
95
|
-
if (!historyEntry) {
|
|
96
|
-
throw ApiError.notFound(`History entry '${historyId}' not found`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Verify the history entry belongs to this entity (prevent cross-entity revert)
|
|
100
|
-
const tableName = collection.slug;
|
|
101
|
-
if (historyEntry.entity_id !== String(entityId) || historyEntry.table_name !== tableName) {
|
|
102
|
-
throw ApiError.badRequest("History entry does not belong to this entity");
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (!historyEntry.values) {
|
|
106
|
-
throw ApiError.badRequest("Cannot revert: history entry has no stored values");
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Revert by saving through the normal driver path — this will
|
|
110
|
-
// itself create another history entry, giving a full audit trail.
|
|
111
|
-
const authDriver = c.get("driver") || driver;
|
|
112
|
-
const path = collection.slug;
|
|
113
|
-
|
|
114
|
-
const savedEntity = await authDriver.saveEntity({
|
|
115
|
-
path,
|
|
116
|
-
entityId: String(entityId),
|
|
117
|
-
values: historyEntry.values,
|
|
118
|
-
collection,
|
|
119
|
-
status: "existing"
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
return c.json({
|
|
123
|
-
data: savedEntity,
|
|
124
|
-
meta: { reverted_from: historyId }
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
return router;
|
|
129
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @rebasepro/server-core
|
|
3
|
-
*
|
|
4
|
-
* Database-Agnostic Backend Core for Rebase.
|
|
5
|
-
* This package provides the core backend services, generic driver routing,
|
|
6
|
-
* and API layers. Database implementations (e.g., PostgreSQL) are provided
|
|
7
|
-
* by specialized driver packages like `@rebasepro/server-postgresql`.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
// =============================================================================
|
|
11
|
-
// Abstract Interfaces (for database abstraction)
|
|
12
|
-
// =============================================================================
|
|
13
|
-
export * from "./db/interfaces";
|
|
14
|
-
export * from "./auth/interfaces";
|
|
15
|
-
|
|
16
|
-
// Core functionality
|
|
17
|
-
export * from "./init";
|
|
18
|
-
|
|
19
|
-
// Server-side singleton (import { rebase } from "@rebasepro/server-core")
|
|
20
|
-
export { rebase, _setRebaseMock, _resetRebaseMock } from "./singleton";
|
|
21
|
-
|
|
22
|
-
// Services
|
|
23
|
-
export * from "./services/driver-registry";
|
|
24
|
-
|
|
25
|
-
// API types (HonoEnv, ApiConfig, etc.)
|
|
26
|
-
export * from "./api/types";
|
|
27
|
-
|
|
28
|
-
// API Generation
|
|
29
|
-
export * from "./api";
|
|
30
|
-
|
|
31
|
-
// Types
|
|
32
|
-
export * from "./types";
|
|
33
|
-
export * from "./types/index";
|
|
34
|
-
|
|
35
|
-
// Auth module
|
|
36
|
-
export * from "./auth";
|
|
37
|
-
|
|
38
|
-
// Email module
|
|
39
|
-
export * from "./email";
|
|
40
|
-
|
|
41
|
-
// Storage module
|
|
42
|
-
export * from "./storage";
|
|
43
|
-
|
|
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";
|
|
52
|
-
|
|
53
|
-
// Custom Functions (auto-discovered Hono routes)
|
|
54
|
-
export * from "./functions";
|
|
55
|
-
|
|
56
|
-
// Cron Jobs (auto-discovered scheduled tasks)
|
|
57
|
-
export * from "./cron";
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// SPA serving helper
|
|
61
|
-
export * from "./serve-spa";
|
|
62
|
-
|
|
63
|
-
// Dev-mode port resolution (retry on EADDRINUSE)
|
|
64
|
-
export * from "./utils/dev-port";
|
|
65
|
-
|
|
66
|
-
// Environment validation
|
|
67
|
-
export { loadEnv } from "./env";
|
|
68
|
-
export type { RebaseEnv } from "./env";
|
|
69
|
-
export { z } from "zod";
|
|
70
|
-
|
package/src/init/docs.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { Hono } from "hono";
|
|
2
|
-
import { EntityCollection } from "@rebasepro/types";
|
|
3
|
-
import { HonoEnv } from "../api/types";
|
|
4
|
-
import { logger } from "../utils/logger";
|
|
5
|
-
|
|
6
|
-
export async function mountOpenApiDocs(
|
|
7
|
-
app: Hono<HonoEnv>,
|
|
8
|
-
basePath: string,
|
|
9
|
-
enableSwagger: boolean | undefined,
|
|
10
|
-
activeCollections: EntityCollection[],
|
|
11
|
-
requireAuth: boolean
|
|
12
|
-
): Promise<void> {
|
|
13
|
-
if (enableSwagger === false || activeCollections.length === 0) {
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const { generateOpenApiSpec } = await import("../api/openapi-generator");
|
|
18
|
-
|
|
19
|
-
app.get(`${basePath}/docs`, (c) => {
|
|
20
|
-
const spec = generateOpenApiSpec(activeCollections, {
|
|
21
|
-
basePath,
|
|
22
|
-
requireAuth
|
|
23
|
-
});
|
|
24
|
-
return c.json(spec);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
if (process.env.NODE_ENV !== "production") {
|
|
28
|
-
app.get(`${basePath}/swagger`, (c) => {
|
|
29
|
-
return c.html(`<!DOCTYPE html>
|
|
30
|
-
<html>
|
|
31
|
-
<head>
|
|
32
|
-
<title>Rebase API Documentation</title>
|
|
33
|
-
<meta charset="utf-8"/>
|
|
34
|
-
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
35
|
-
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css"/>
|
|
36
|
-
<style>body{margin:0;padding:0;}</style>
|
|
37
|
-
</head>
|
|
38
|
-
<body>
|
|
39
|
-
<div id="swagger-ui"></div>
|
|
40
|
-
<script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
|
|
41
|
-
<script>SwaggerUIBundle({ url: '${basePath}/docs', dom_id: '#swagger-ui' });</script>
|
|
42
|
-
</body>
|
|
43
|
-
</html>`);
|
|
44
|
-
});
|
|
45
|
-
logger.info("Swagger UI available", { path: `${basePath}/swagger` });
|
|
46
|
-
}
|
|
47
|
-
}
|
package/src/init/health.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { DataDriver, HealthCheckResult, isSQLAdmin } from "@rebasepro/types";
|
|
2
|
-
import { logger } from "../utils/logger";
|
|
3
|
-
|
|
4
|
-
export function createHealthCheck(defaultDriver: DataDriver): () => Promise<HealthCheckResult> {
|
|
5
|
-
return async (): Promise<HealthCheckResult> => {
|
|
6
|
-
const start = performance.now();
|
|
7
|
-
try {
|
|
8
|
-
const admin = defaultDriver.admin;
|
|
9
|
-
if (isSQLAdmin(admin)) {
|
|
10
|
-
await admin.executeSql("SELECT 1");
|
|
11
|
-
} else {
|
|
12
|
-
await defaultDriver.fetchCollection({
|
|
13
|
-
path: "__health_check_nonexistent__",
|
|
14
|
-
limit: 1
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
const latencyMs = Math.round(performance.now() - start);
|
|
18
|
-
return {
|
|
19
|
-
healthy: true,
|
|
20
|
-
latencyMs
|
|
21
|
-
};
|
|
22
|
-
} catch (error: unknown) {
|
|
23
|
-
const latencyMs = Math.round(performance.now() - start);
|
|
24
|
-
logger.error("Health check failed", {
|
|
25
|
-
error: error instanceof Error ? error : new Error(String(error)),
|
|
26
|
-
latencyMs
|
|
27
|
-
});
|
|
28
|
-
return {
|
|
29
|
-
healthy: false,
|
|
30
|
-
latencyMs,
|
|
31
|
-
details: {
|
|
32
|
-
error: error instanceof Error ? error.message : String(error)
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
}
|
package/src/init/middlewares.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { Hono } from "hono";
|
|
2
|
-
import { bodyLimit } from "hono/body-limit";
|
|
3
|
-
import { csrf } from "hono/csrf";
|
|
4
|
-
import { HonoEnv } from "../api/types";
|
|
5
|
-
import { requestId } from "../utils/request-id";
|
|
6
|
-
import { requestLogger } from "../utils/request-logger";
|
|
7
|
-
import { logger } from "../utils/logger";
|
|
8
|
-
|
|
9
|
-
interface MiddlewareConfig {
|
|
10
|
-
maxBodySize?: number;
|
|
11
|
-
csrf?: {
|
|
12
|
-
origin: string | string[] | ((origin: string) => boolean);
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function configureMiddlewares(
|
|
17
|
-
app: Hono<HonoEnv>,
|
|
18
|
-
basePath: string,
|
|
19
|
-
isProduction: boolean,
|
|
20
|
-
config: MiddlewareConfig
|
|
21
|
-
): void {
|
|
22
|
-
// Request ID (correlation)
|
|
23
|
-
app.use(`${basePath}/*`, requestId());
|
|
24
|
-
|
|
25
|
-
// Request Body Size Limit
|
|
26
|
-
const maxBodySize = config.maxBodySize ?? 10 * 1024 * 1024; // 10MB default
|
|
27
|
-
if (maxBodySize > 0) {
|
|
28
|
-
app.use(`${basePath}/*`, bodyLimit({
|
|
29
|
-
maxSize: maxBodySize,
|
|
30
|
-
onError: (c) => {
|
|
31
|
-
return c.json({
|
|
32
|
-
error: {
|
|
33
|
-
message: `Request body too large. Maximum size is ${Math.round(maxBodySize / 1024 / 1024)}MB.`,
|
|
34
|
-
code: "PAYLOAD_TOO_LARGE"
|
|
35
|
-
}
|
|
36
|
-
}, 413);
|
|
37
|
-
}
|
|
38
|
-
}));
|
|
39
|
-
logger.info("Request body limit configured", { maxSizeMB: Math.round(maxBodySize / 1024 / 1024) });
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// CSRF Protection (opt-in)
|
|
43
|
-
if (config.csrf?.origin) {
|
|
44
|
-
app.use(`${basePath}/*`, csrf({
|
|
45
|
-
origin: config.csrf.origin
|
|
46
|
-
}));
|
|
47
|
-
logger.info("CSRF protection enabled");
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// CORS Warning
|
|
51
|
-
if (!isProduction && !process.env.CORS_ORIGINS && !process.env.FRONTEND_URL) {
|
|
52
|
-
logger.warn(
|
|
53
|
-
"No CORS configuration detected (CORS_ORIGINS / FRONTEND_URL not set). " +
|
|
54
|
-
"The API will accept requests from any origin. " +
|
|
55
|
-
"Set CORS_ORIGINS in your .env file to restrict access."
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Request Logging
|
|
60
|
-
app.use(`${basePath}/*`, requestLogger());
|
|
61
|
-
}
|
package/src/init/shutdown.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { Server } from "http";
|
|
2
|
-
import { RealtimeProvider } from "@rebasepro/types";
|
|
3
|
-
import { logger } from "../utils/logger";
|
|
4
|
-
|
|
5
|
-
interface ShutdownConfig {
|
|
6
|
-
server: Server;
|
|
7
|
-
cronScheduler?: { stop(): void };
|
|
8
|
-
realtimeServices: Record<string, RealtimeProvider>;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function createShutdown(config: ShutdownConfig): (timeoutMs?: number) => Promise<void> {
|
|
12
|
-
return (timeoutMs = 15_000): Promise<void> => {
|
|
13
|
-
return new Promise<void>((resolve) => {
|
|
14
|
-
(async () => {
|
|
15
|
-
logger.info("Shutting down Rebase Backend...");
|
|
16
|
-
|
|
17
|
-
// 1. Stop cron scheduler
|
|
18
|
-
if (config.cronScheduler) {
|
|
19
|
-
config.cronScheduler.stop();
|
|
20
|
-
logger.info("Cron scheduler stopped");
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// 2. Tear down realtime services (LISTEN clients, debounce timers,
|
|
24
|
-
// subscriptions). Must happen BEFORE pool.end() so that pending
|
|
25
|
-
// timer callbacks don't fire against a closed pool.
|
|
26
|
-
for (const [key, rt] of Object.entries(config.realtimeServices)) {
|
|
27
|
-
try {
|
|
28
|
-
if (typeof rt.destroy === "function") {
|
|
29
|
-
await rt.destroy();
|
|
30
|
-
logger.info(`Realtime service "${key}" destroyed`);
|
|
31
|
-
} else if (typeof rt.stopListening === "function") {
|
|
32
|
-
await rt.stopListening();
|
|
33
|
-
logger.info(`Realtime service "${key}" LISTEN client stopped`);
|
|
34
|
-
}
|
|
35
|
-
} catch (err) {
|
|
36
|
-
logger.warn(`Error destroying realtime service "${key}":`, { error: err });
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// 3. Close the HTTP server (stop accepting, drain in-flight)
|
|
41
|
-
config.server.close(() => {
|
|
42
|
-
logger.info("HTTP server closed");
|
|
43
|
-
resolve();
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
// 4. Force-resolve after timeout (unless disabled with 0)
|
|
47
|
-
if (timeoutMs > 0) {
|
|
48
|
-
setTimeout(() => {
|
|
49
|
-
logger.warn(`Forced shutdown after ${timeoutMs / 1000}s timeout`);
|
|
50
|
-
resolve();
|
|
51
|
-
}, timeoutMs).unref();
|
|
52
|
-
}
|
|
53
|
-
})();
|
|
54
|
-
});
|
|
55
|
-
};
|
|
56
|
-
}
|
package/src/init/storage.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BackendStorageConfig,
|
|
3
|
-
createStorageController,
|
|
4
|
-
DEFAULT_STORAGE_ID,
|
|
5
|
-
DefaultStorageRegistry,
|
|
6
|
-
StorageController,
|
|
7
|
-
StorageRegistry
|
|
8
|
-
} from "../storage";
|
|
9
|
-
import { logger } from "../utils/logger";
|
|
10
|
-
|
|
11
|
-
export function initializeStorage(
|
|
12
|
-
storageConfig: BackendStorageConfig | StorageController | Record<string, BackendStorageConfig | StorageController> | undefined,
|
|
13
|
-
isProduction: boolean
|
|
14
|
-
): { storageRegistry?: StorageRegistry; storageController?: StorageController } {
|
|
15
|
-
if (!storageConfig) return {};
|
|
16
|
-
|
|
17
|
-
logger.info("Configuring storage");
|
|
18
|
-
const controllers: Record<string, StorageController> = {};
|
|
19
|
-
|
|
20
|
-
const toController = (entry: BackendStorageConfig | StorageController, label: string): StorageController => {
|
|
21
|
-
if (typeof (entry as StorageController).putObject === "function") {
|
|
22
|
-
return entry as StorageController;
|
|
23
|
-
}
|
|
24
|
-
const conf = entry as BackendStorageConfig;
|
|
25
|
-
if (isProduction && conf.type === "local") {
|
|
26
|
-
logger.warn(`Storage backend "${label}" uses local filesystem in production. ` +
|
|
27
|
-
"Files will be lost on container restart. " +
|
|
28
|
-
"Configure S3-compatible storage or a custom StorageController.");
|
|
29
|
-
}
|
|
30
|
-
return createStorageController(conf);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
if (
|
|
34
|
-
typeof storageConfig === "object" &&
|
|
35
|
-
("type" in storageConfig || typeof (storageConfig as StorageController).putObject === "function")
|
|
36
|
-
) {
|
|
37
|
-
controllers[DEFAULT_STORAGE_ID] = toController(
|
|
38
|
-
storageConfig as BackendStorageConfig | StorageController,
|
|
39
|
-
DEFAULT_STORAGE_ID
|
|
40
|
-
);
|
|
41
|
-
} else {
|
|
42
|
-
for (const [storageId, entry] of Object.entries(
|
|
43
|
-
storageConfig as Record<string, BackendStorageConfig | StorageController>
|
|
44
|
-
)) {
|
|
45
|
-
controllers[storageId] = toController(entry, storageId);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (Object.keys(controllers).length > 0) {
|
|
50
|
-
const storageRegistry = DefaultStorageRegistry.create(controllers);
|
|
51
|
-
const storageController = storageRegistry.getDefault();
|
|
52
|
-
logger.info("Initialized storage backends", { count: Object.keys(controllers).length });
|
|
53
|
-
return { storageRegistry, storageController };
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return {};
|
|
57
|
-
}
|