@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
package/src/utils/dev-port.ts
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dev-mode port resolution utilities.
|
|
3
|
-
*
|
|
4
|
-
* Provides a `listen` wrapper that automatically retries the next port when
|
|
5
|
-
* the requested one is already in use, and writes the resolved port to a
|
|
6
|
-
* well-known temp file so the CLI / frontend can discover it.
|
|
7
|
-
*
|
|
8
|
-
* Port affinity: when a port file already exists (e.g. after a tsx watch
|
|
9
|
-
* restart), the saved port is tried FIRST so the backend stays on the same
|
|
10
|
-
* port the frontend was configured with.
|
|
11
|
-
*
|
|
12
|
-
* This module is dev-only and should never run in production.
|
|
13
|
-
*/
|
|
14
|
-
import type { Server } from "http";
|
|
15
|
-
import path from "path";
|
|
16
|
-
import fs from "fs";
|
|
17
|
-
|
|
18
|
-
const MAX_PORT_ATTEMPTS = 20;
|
|
19
|
-
|
|
20
|
-
/** Filename written next to the project `.env` so the CLI can read it. */
|
|
21
|
-
export const DEV_PORT_FILENAME = ".rebase-dev-port";
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Try to `listen` on `startPort`. If the port is busy (`EADDRINUSE`), increment
|
|
25
|
-
* and retry up to `maxAttempts` times.
|
|
26
|
-
*
|
|
27
|
-
* When a port file already exists (written by a previous run), the saved port
|
|
28
|
-
* is tried first to maintain port affinity across tsx watch restarts.
|
|
29
|
-
*
|
|
30
|
-
* Resolves with the port that was actually bound.
|
|
31
|
-
*/
|
|
32
|
-
export function listenWithPortRetry(
|
|
33
|
-
server: Server,
|
|
34
|
-
startPort: number,
|
|
35
|
-
options?: {
|
|
36
|
-
host?: string;
|
|
37
|
-
maxAttempts?: number;
|
|
38
|
-
/** Absolute path to write the resolved port file into. Defaults to `process.cwd()`. */
|
|
39
|
-
portFileDir?: string;
|
|
40
|
-
/** Service key to include in the state file for MCP server auto-discovery. */
|
|
41
|
-
serviceKey?: string;
|
|
42
|
-
}
|
|
43
|
-
): Promise<number> {
|
|
44
|
-
const host = options?.host ?? "0.0.0.0";
|
|
45
|
-
const maxAttempts = options?.maxAttempts ?? MAX_PORT_ATTEMPTS;
|
|
46
|
-
const portFileDir = options?.portFileDir;
|
|
47
|
-
|
|
48
|
-
const isProd = process.env.NODE_ENV === "production";
|
|
49
|
-
if (isProd) {
|
|
50
|
-
return new Promise<number>((resolve, reject) => {
|
|
51
|
-
const onError = (err: Error) => {
|
|
52
|
-
reject(err);
|
|
53
|
-
};
|
|
54
|
-
server.once("error", onError);
|
|
55
|
-
server.listen(startPort, host, () => {
|
|
56
|
-
server.removeListener("error", onError);
|
|
57
|
-
resolve(startPort);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Read affinity port from a previous run's port file.
|
|
63
|
-
// This ensures tsx watch restarts land on the same port the frontend was
|
|
64
|
-
// configured with, even if the CLI-computed port was different.
|
|
65
|
-
let affinityPort: number | null = null;
|
|
66
|
-
if (portFileDir) {
|
|
67
|
-
try {
|
|
68
|
-
const portFile = path.join(portFileDir, DEV_PORT_FILENAME);
|
|
69
|
-
if (fs.existsSync(portFile)) {
|
|
70
|
-
const saved = parseInt(fs.readFileSync(portFile, "utf-8").trim(), 10);
|
|
71
|
-
if (saved > 0 && saved < 65536 && saved !== startPort) {
|
|
72
|
-
affinityPort = saved;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
} catch { /* ignore */ }
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return new Promise<number>((resolve, reject) => {
|
|
79
|
-
let attempt = 0;
|
|
80
|
-
// Build the ordered list of ports to try:
|
|
81
|
-
// 1. The affinity port (if different from startPort)
|
|
82
|
-
// 2. startPort, startPort+1, startPort+2, ...
|
|
83
|
-
const portsToTry: number[] = [];
|
|
84
|
-
if (affinityPort) portsToTry.push(affinityPort);
|
|
85
|
-
for (let i = 0; i < maxAttempts; i++) {
|
|
86
|
-
const p = startPort + i;
|
|
87
|
-
if (p !== affinityPort) portsToTry.push(p);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function tryNext(index: number) {
|
|
91
|
-
if (index >= portsToTry.length) {
|
|
92
|
-
reject(new Error(
|
|
93
|
-
"All attempted ports are in use. " +
|
|
94
|
-
"Stop other Rebase instances or specify a different port with --port."
|
|
95
|
-
));
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const port = portsToTry[index];
|
|
100
|
-
attempt++;
|
|
101
|
-
|
|
102
|
-
const onError = (err: NodeJS.ErrnoException) => {
|
|
103
|
-
if (err.code === "EADDRINUSE") {
|
|
104
|
-
server.removeListener("error", onError);
|
|
105
|
-
tryNext(index + 1);
|
|
106
|
-
} else {
|
|
107
|
-
reject(err);
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
server.once("error", onError);
|
|
112
|
-
|
|
113
|
-
server.listen(port, host, () => {
|
|
114
|
-
server.removeListener("error", onError);
|
|
115
|
-
|
|
116
|
-
// Write the port file so the CLI can pick it up
|
|
117
|
-
if (portFileDir) {
|
|
118
|
-
try {
|
|
119
|
-
const portFile = path.join(portFileDir, DEV_PORT_FILENAME);
|
|
120
|
-
fs.writeFileSync(portFile, String(port), "utf-8");
|
|
121
|
-
} catch {
|
|
122
|
-
// Non-fatal — the CLI will fall back to parsing stdout
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Write .rebase/state.json so external scripts can discover
|
|
126
|
-
// the running server port, URL, etc.
|
|
127
|
-
writeStateFile(portFileDir, port, options?.serviceKey);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
resolve(port);
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
tryNext(0);
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Clean up the dev port file and state file (call on graceful shutdown).
|
|
140
|
-
*/
|
|
141
|
-
export function cleanupDevPortFile(dir: string): void {
|
|
142
|
-
try {
|
|
143
|
-
const portFile = path.join(dir, DEV_PORT_FILENAME);
|
|
144
|
-
if (fs.existsSync(portFile)) {
|
|
145
|
-
fs.unlinkSync(portFile);
|
|
146
|
-
}
|
|
147
|
-
} catch {
|
|
148
|
-
// ignore
|
|
149
|
-
}
|
|
150
|
-
try {
|
|
151
|
-
const stateFile = path.join(dir, ".rebase", "state.json");
|
|
152
|
-
if (fs.existsSync(stateFile)) {
|
|
153
|
-
fs.unlinkSync(stateFile);
|
|
154
|
-
}
|
|
155
|
-
} catch {
|
|
156
|
-
// ignore
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Write `.rebase/state.json` with runtime info for external scripts.
|
|
162
|
-
*
|
|
163
|
-
* Scripts can read this file to discover:
|
|
164
|
-
* - `port` — the actual port the backend is listening on
|
|
165
|
-
* - `baseUrl` — full URL including protocol and port
|
|
166
|
-
* - `pid` — the backend process ID
|
|
167
|
-
* - `startedAt` — ISO timestamp of when the server started
|
|
168
|
-
* - `serviceKey` — (dev only) the REBASE_SERVICE_KEY for MCP auto-discovery
|
|
169
|
-
*
|
|
170
|
-
* @example Reading from a script:
|
|
171
|
-
* ```ts
|
|
172
|
-
* const state = JSON.parse(fs.readFileSync('.rebase/state.json', 'utf-8'));
|
|
173
|
-
* const apiUrl = state.baseUrl; // "http://localhost:3519"
|
|
174
|
-
* ```
|
|
175
|
-
*/
|
|
176
|
-
function writeStateFile(projectRoot: string, port: number, serviceKey?: string): void {
|
|
177
|
-
try {
|
|
178
|
-
const rebaseDir = path.join(projectRoot, ".rebase");
|
|
179
|
-
if (!fs.existsSync(rebaseDir)) {
|
|
180
|
-
fs.mkdirSync(rebaseDir, { recursive: true });
|
|
181
|
-
}
|
|
182
|
-
const stateFile = path.join(rebaseDir, "state.json");
|
|
183
|
-
const state: Record<string, unknown> = {
|
|
184
|
-
port,
|
|
185
|
-
baseUrl: `http://localhost:${port}`,
|
|
186
|
-
pid: process.pid,
|
|
187
|
-
startedAt: new Date().toISOString()
|
|
188
|
-
};
|
|
189
|
-
if (serviceKey) {
|
|
190
|
-
state.serviceKey = serviceKey;
|
|
191
|
-
}
|
|
192
|
-
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2), "utf-8");
|
|
193
|
-
} catch {
|
|
194
|
-
// Non-fatal
|
|
195
|
-
}
|
|
196
|
-
}
|
package/src/utils/logger.ts
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Structured Logger for Rebase Backend
|
|
3
|
-
*
|
|
4
|
-
* Outputs JSON lines when `NODE_ENV=production`, human-readable prefixed
|
|
5
|
-
* lines otherwise. Designed to work with Google Cloud Logging severity levels.
|
|
6
|
-
*
|
|
7
|
-
* Usage:
|
|
8
|
-
* import { logger } from "./utils/logger";
|
|
9
|
-
* logger.info("Server started", { port: 3001 });
|
|
10
|
-
* logger.error("Request failed", { path: "/api/test", error: err });
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
14
|
-
|
|
15
|
-
/** Google Cloud Logging severity strings. */
|
|
16
|
-
const GCP_SEVERITY: Record<LogLevel, string> = {
|
|
17
|
-
debug: "DEBUG",
|
|
18
|
-
info: "INFO",
|
|
19
|
-
warn: "WARNING",
|
|
20
|
-
error: "ERROR"
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const LOG_PRIORITY: Record<LogLevel, number> = {
|
|
24
|
-
debug: 0,
|
|
25
|
-
info: 1,
|
|
26
|
-
warn: 2,
|
|
27
|
-
error: 3
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export interface LogEntry {
|
|
31
|
-
severity: string;
|
|
32
|
-
message: string;
|
|
33
|
-
timestamp: string;
|
|
34
|
-
[key: string]: unknown;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface Logger {
|
|
38
|
-
debug(message: string, data?: Record<string, unknown>): void;
|
|
39
|
-
info(message: string, data?: Record<string, unknown>): void;
|
|
40
|
-
warn(message: string, data?: Record<string, unknown>): void;
|
|
41
|
-
error(message: string, data?: Record<string, unknown>): void;
|
|
42
|
-
child(defaultFields: Record<string, unknown>): Logger;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function isProduction(): boolean {
|
|
46
|
-
return process.env.NODE_ENV === "production";
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function getMinLevel(): LogLevel {
|
|
50
|
-
const env = (process.env.LOG_LEVEL || "info").toLowerCase();
|
|
51
|
-
if (env in LOG_PRIORITY) return env as LogLevel;
|
|
52
|
-
return "info";
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Serialise an Error into a plain object (stack + message).
|
|
57
|
-
* Handles non-Error values gracefully.
|
|
58
|
-
*/
|
|
59
|
-
function serialiseError(value: unknown): Record<string, unknown> {
|
|
60
|
-
if (value instanceof Error) {
|
|
61
|
-
return {
|
|
62
|
-
name: value.name,
|
|
63
|
-
message: value.message,
|
|
64
|
-
stack: value.stack
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
return { value: String(value) };
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function formatData(data?: Record<string, unknown>): Record<string, unknown> | undefined {
|
|
71
|
-
if (!data) return undefined;
|
|
72
|
-
const out: Record<string, unknown> = {};
|
|
73
|
-
for (const [key, val] of Object.entries(data)) {
|
|
74
|
-
if (val instanceof Error) {
|
|
75
|
-
out[key] = serialiseError(val);
|
|
76
|
-
} else {
|
|
77
|
-
out[key] = val;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return out;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function createLogger(defaultFields: Record<string, unknown> = {}): Logger {
|
|
84
|
-
const minLevel = getMinLevel();
|
|
85
|
-
|
|
86
|
-
function emit(level: LogLevel, message: string, data?: Record<string, unknown>): void {
|
|
87
|
-
if (LOG_PRIORITY[level] < LOG_PRIORITY[minLevel]) return;
|
|
88
|
-
|
|
89
|
-
const merged = { ...defaultFields,
|
|
90
|
-
...formatData(data) };
|
|
91
|
-
|
|
92
|
-
if (isProduction()) {
|
|
93
|
-
// Structured JSON for Cloud Logging
|
|
94
|
-
const entry: LogEntry = {
|
|
95
|
-
severity: GCP_SEVERITY[level],
|
|
96
|
-
message,
|
|
97
|
-
timestamp: new Date().toISOString(),
|
|
98
|
-
...merged
|
|
99
|
-
};
|
|
100
|
-
const line = JSON.stringify(entry);
|
|
101
|
-
|
|
102
|
-
if (level === "error") {
|
|
103
|
-
process.stderr.write(line + "\n");
|
|
104
|
-
} else {
|
|
105
|
-
process.stdout.write(line + "\n");
|
|
106
|
-
}
|
|
107
|
-
} else {
|
|
108
|
-
// Human-readable for development
|
|
109
|
-
const prefix = level === "error" ? "❌"
|
|
110
|
-
: level === "warn" ? "⚠️"
|
|
111
|
-
: level === "info" ? "ℹ️"
|
|
112
|
-
: "🐛";
|
|
113
|
-
const extra = Object.keys(merged).length > 0 ? ` ${JSON.stringify(merged)}` : "";
|
|
114
|
-
const out = `${prefix} [${level.toUpperCase()}] ${message}${extra}`;
|
|
115
|
-
|
|
116
|
-
if (level === "error") {
|
|
117
|
-
console.error(out);
|
|
118
|
-
} else if (level === "warn") {
|
|
119
|
-
console.warn(out);
|
|
120
|
-
} else {
|
|
121
|
-
console.log(out);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
debug: (msg, data) => emit("debug", msg, data),
|
|
128
|
-
info: (msg, data) => emit("info", msg, data),
|
|
129
|
-
warn: (msg, data) => emit("warn", msg, data),
|
|
130
|
-
error: (msg, data) => emit("error", msg, data),
|
|
131
|
-
child(fields: Record<string, unknown>): Logger {
|
|
132
|
-
return createLogger({ ...defaultFields,
|
|
133
|
-
...fields });
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Singleton logger instance.
|
|
140
|
-
* In production: emits JSON lines with `severity`, `message`, `timestamp`.
|
|
141
|
-
* In development: emits human-readable prefixed lines.
|
|
142
|
-
*/
|
|
143
|
-
export const logger: Logger = createLogger();
|
package/src/utils/logging.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Configure console log levels based on environment variable
|
|
3
|
-
* Call this early in your application to set up proper logging levels
|
|
4
|
-
*/
|
|
5
|
-
export function configureLogLevel(logLevel?: string) {
|
|
6
|
-
const LOG_LEVEL = logLevel || process.env.LOG_LEVEL || "info";
|
|
7
|
-
const logLevels = { error: 0,
|
|
8
|
-
warn: 1,
|
|
9
|
-
info: 2,
|
|
10
|
-
debug: 3 };
|
|
11
|
-
const currentLevel = logLevels[LOG_LEVEL as keyof typeof logLevels] ?? 2;
|
|
12
|
-
|
|
13
|
-
if (currentLevel < 3) console.debug = () => { };
|
|
14
|
-
if (currentLevel < 2) console.log = () => { };
|
|
15
|
-
if (currentLevel < 1) console.warn = () => { };
|
|
16
|
-
if (currentLevel < 0) console.error = () => { };
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/** Module-scoped backup of the original console methods. */
|
|
20
|
-
let originalConsole: Pick<Console, "log" | "warn" | "error" | "debug"> | undefined;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Reset console methods to their original state
|
|
24
|
-
*/
|
|
25
|
-
export function resetConsole() {
|
|
26
|
-
// Store original methods if not already stored
|
|
27
|
-
if (!originalConsole) {
|
|
28
|
-
originalConsole = {
|
|
29
|
-
log: console.log,
|
|
30
|
-
warn: console.warn,
|
|
31
|
-
error: console.error,
|
|
32
|
-
debug: console.debug
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
console.log = originalConsole.log;
|
|
37
|
-
console.warn = originalConsole.warn;
|
|
38
|
-
console.error = originalConsole.error;
|
|
39
|
-
console.debug = originalConsole.debug;
|
|
40
|
-
}
|
package/src/utils/request-id.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* X-Request-ID Middleware for Hono.
|
|
3
|
-
*
|
|
4
|
-
* Generates a unique request identifier (UUID v4) for every inbound
|
|
5
|
-
* request, or propagates an existing `X-Request-ID` header from the
|
|
6
|
-
* caller. The ID is:
|
|
7
|
-
*
|
|
8
|
-
* 1. Stored in the Hono context (`c.get("requestId")`)
|
|
9
|
-
* 2. Echoed back on the response as `X-Request-ID`
|
|
10
|
-
*
|
|
11
|
-
* Downstream middleware and handlers (request logger, error handler,
|
|
12
|
-
* etc.) read the ID from context to include it in log entries and
|
|
13
|
-
* error responses, enabling end-to-end request tracing across services.
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```ts
|
|
17
|
-
* import { requestId } from "@rebasepro/server-core";
|
|
18
|
-
* app.use("/*", requestId());
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
|
-
import { randomUUID } from "node:crypto";
|
|
22
|
-
import type { MiddlewareHandler } from "hono";
|
|
23
|
-
import type { HonoEnv } from "../api/types";
|
|
24
|
-
|
|
25
|
-
export const REQUEST_ID_HEADER = "X-Request-ID";
|
|
26
|
-
|
|
27
|
-
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
28
|
-
|
|
29
|
-
export function requestId(): MiddlewareHandler<HonoEnv> {
|
|
30
|
-
return async (c, next) => {
|
|
31
|
-
const incoming = c.req.header(REQUEST_ID_HEADER);
|
|
32
|
-
const id = incoming && UUID_RE.test(incoming) ? incoming : randomUUID();
|
|
33
|
-
|
|
34
|
-
c.set("requestId", id);
|
|
35
|
-
|
|
36
|
-
await next();
|
|
37
|
-
|
|
38
|
-
c.header(REQUEST_ID_HEADER, id);
|
|
39
|
-
};
|
|
40
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Structured HTTP request logging middleware for Hono.
|
|
3
|
-
*
|
|
4
|
-
* Logs every request with method, path, status code, latency, and
|
|
5
|
-
* content-length. In production, outputs JSON for Cloud Logging; in
|
|
6
|
-
* development, emits a coloured one-liner.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```ts
|
|
10
|
-
* import { requestLogger } from "@rebasepro/server-core";
|
|
11
|
-
* app.use("/*", requestLogger());
|
|
12
|
-
* ```
|
|
13
|
-
*/
|
|
14
|
-
import type { MiddlewareHandler } from "hono";
|
|
15
|
-
import { logger as log } from "./logger";
|
|
16
|
-
|
|
17
|
-
export interface RequestLoggerOptions {
|
|
18
|
-
/** Paths to skip logging (e.g. "/health"). Supports exact match. */
|
|
19
|
-
skip?: string[];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function requestLogger(options?: RequestLoggerOptions): MiddlewareHandler {
|
|
23
|
-
const skipPaths = new Set(options?.skip ?? ["/health", "/favicon.ico"]);
|
|
24
|
-
|
|
25
|
-
return async (c, next) => {
|
|
26
|
-
const start = performance.now();
|
|
27
|
-
const method = c.req.method;
|
|
28
|
-
const path = c.req.path;
|
|
29
|
-
|
|
30
|
-
// Skip noisy endpoints
|
|
31
|
-
if (skipPaths.has(path)) {
|
|
32
|
-
return next();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
await next();
|
|
36
|
-
|
|
37
|
-
const latencyMs = Math.round(performance.now() - start);
|
|
38
|
-
const status = c.res.status;
|
|
39
|
-
const contentLength = c.res.headers.get("content-length");
|
|
40
|
-
|
|
41
|
-
const data: Record<string, unknown> = {
|
|
42
|
-
method,
|
|
43
|
-
path,
|
|
44
|
-
status,
|
|
45
|
-
latencyMs
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
// Include request correlation ID if available
|
|
49
|
-
const reqId = c.get("requestId");
|
|
50
|
-
if (reqId) {
|
|
51
|
-
data.requestId = reqId;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (contentLength) {
|
|
55
|
-
data.contentLength = parseInt(contentLength, 10);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Extract user ID from context if auth middleware ran
|
|
59
|
-
const userId = c.get("userId" as never) as string | undefined;
|
|
60
|
-
if (userId) {
|
|
61
|
-
data.userId = userId;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (status >= 500) {
|
|
65
|
-
log.error("request", data);
|
|
66
|
-
} else if (status >= 400) {
|
|
67
|
-
log.warn("request", data);
|
|
68
|
-
} else {
|
|
69
|
-
log.info("request", data);
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
}
|