@rebasepro/server 0.25.1 → 0.26.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/dist/{GCSStorageController-CRd9bFrc.js → GCSStorageController-40FyFeSx.js} +6 -2
- package/dist/GCSStorageController-40FyFeSx.js.map +1 -0
- package/dist/{S3StorageController-D00EFa5P.js → S3StorageController-Bl5shp94.js} +6 -2
- package/dist/S3StorageController-Bl5shp94.js.map +1 -0
- package/dist/access-BFAUvsSs.js +1897 -0
- package/dist/access-BFAUvsSs.js.map +1 -0
- package/dist/api/branch-routes.d.ts +25 -0
- package/dist/api/live-schema-routes.d.ts +10 -0
- package/dist/api/rest/api-generator.d.ts +9 -1
- package/dist/api/rest/idempotency.d.ts +15 -1
- package/dist/api/root-error-handler.d.ts +6 -5
- package/dist/api/types.d.ts +12 -0
- package/dist/{ast-schema-editor-mCeSC03x.js → ast-schema-editor-madTa9Hh.js} +2 -2
- package/dist/{ast-schema-editor-mCeSC03x.js.map → ast-schema-editor-madTa9Hh.js.map} +1 -1
- package/dist/auth/access.d.ts +10 -0
- package/dist/auth/adapter-middleware.d.ts +2 -1
- package/dist/auth/adapter-service-key.d.ts +24 -0
- package/dist/auth/api-keys/api-key-middleware.d.ts +21 -1
- package/dist/auth/api-keys/api-key-store.d.ts +8 -1
- package/dist/auth/api-keys/key-grant.d.ts +18 -1
- package/dist/auth/expired-token-sweep.d.ts +5 -0
- package/dist/auth/impersonation.d.ts +3 -1
- package/dist/auth/jwt.d.ts +8 -2
- package/dist/auth/oauth-signin-policy.d.ts +21 -35
- package/dist/auth/rls-scope.d.ts +17 -7
- package/dist/auth/rls-simulator-routes.d.ts +51 -0
- package/dist/auth/simulation-read-only.d.ts +28 -0
- package/dist/auth/simulation.d.ts +141 -0
- package/dist/auth/sql-rate-limit-store.d.ts +15 -1
- package/dist/{auth-Dkvo2tTJ.js → auth-izI7AEzC.js} +370 -1880
- package/dist/auth-izI7AEzC.js.map +1 -0
- package/dist/auth_adapter-B7RUMk6e.js +89 -0
- package/dist/auth_adapter-B7RUMk6e.js.map +1 -0
- package/dist/backend/create-backend.d.ts +6 -0
- package/dist/backend/options.d.ts +9 -4
- package/dist/{backend-DTAOsLQc.js → backend-CaG_Jyso.js} +9 -2
- package/dist/backend-CaG_Jyso.js.map +1 -0
- package/dist/{backup-B9m3cb3X.js → backup-BVbHoKo8.js} +6 -6
- package/dist/{backup-B9m3cb3X.js.map → backup-BVbHoKo8.js.map} +1 -1
- package/dist/boot/boot.d.ts +2 -15
- package/dist/boot/ddl-bootstrap.d.ts +34 -0
- package/dist/boot/env.d.ts +6 -0
- package/dist/boot/fetch-bundle.d.ts +5 -1
- package/dist/boot/provision-only.d.ts +23 -0
- package/dist/boot/provision.d.ts +53 -2
- package/dist/boot/role.d.ts +2 -0
- package/dist/boot/schema-change-recorder.d.ts +45 -0
- package/dist/boot/security-headers.d.ts +22 -0
- package/dist/branch-routes-B2vvEx53.js +84 -0
- package/dist/branch-routes-B2vvEx53.js.map +1 -0
- package/dist/{contract-routes-CsFXW7j4.js → contract-routes-CU2A3JnF.js} +2 -2
- package/dist/{contract-routes-CsFXW7j4.js.map → contract-routes-CU2A3JnF.js.map} +1 -1
- package/dist/cron/cron-store.d.ts +8 -1
- package/dist/{cron-loader-Dj6lA4HQ.js → cron-loader-mMhqbVsl.js} +2 -2
- package/dist/{cron-loader-Dj6lA4HQ.js.map → cron-loader-mMhqbVsl.js.map} +1 -1
- package/dist/{cron-routes-CwbLZguO.js → cron-routes-Cs33j_Kr.js} +3 -3
- package/dist/{cron-routes-CwbLZguO.js.map → cron-routes-Cs33j_Kr.js.map} +1 -1
- package/dist/{cron-scheduler-B04ACoUE.js → cron-scheduler-Be7CNghL.js} +2 -2
- package/dist/{cron-scheduler-B04ACoUE.js.map → cron-scheduler-Be7CNghL.js.map} +1 -1
- package/dist/{cron-store-DkyfuLOH.js → cron-store-DLn11M8H.js} +10 -9
- package/dist/cron-store-DLn11M8H.js.map +1 -0
- package/dist/{strings.es-BeZWAodn.js → data_driver-D0mg1Y_x.js} +2 -90
- package/dist/data_driver-D0mg1Y_x.js.map +1 -0
- package/dist/{ddl-bootstrap-Ck20GSIX.js → ddl-bootstrap-CjRrn12l.js} +91 -2
- package/dist/ddl-bootstrap-CjRrn12l.js.map +1 -0
- package/dist/deploy/pod-contract.d.ts +1 -1
- package/dist/email/dev-sink.d.ts +6 -0
- package/dist/email/index.d.ts +1 -1
- package/dist/{soft-delete-params-BmlVwecC.js → field-access-DYsvjI_P.js} +27 -57
- package/dist/field-access-DYsvjI_P.js.map +1 -0
- package/dist/{filter-dialect-O1HK6Nvr.js → filter-dialect-TrKFWLqT.js} +3 -3
- package/dist/{filter-dialect-O1HK6Nvr.js.map → filter-dialect-TrKFWLqT.js.map} +1 -1
- package/dist/{function-loader-KKDqTcIr.js → function-loader-B8YzXEsQ.js} +21 -14
- package/dist/function-loader-B8YzXEsQ.js.map +1 -0
- package/dist/functions/hono-like.d.ts +12 -0
- package/dist/functions/index.js +19 -1
- package/dist/functions/index.js.map +1 -1
- package/dist/functions/request-timeout.d.ts +3 -3
- package/dist/history/history-routes.d.ts +6 -0
- package/dist/history/retention-sweep.d.ts +5 -0
- package/dist/{history-recorder-B2rkuhuy.js → history-recorder-Bsau7h4X.js} +6 -6
- package/dist/history-recorder-Bsau7h4X.js.map +1 -0
- package/dist/{history-store-DPofGVDp.js → history-store-BQz5YCkW.js} +26 -2
- package/dist/history-store-BQz5YCkW.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.es.js +2449 -543
- package/dist/index.es.js.map +1 -1
- package/dist/init/process-safety.d.ts +4 -3
- package/dist/init/shutdown.d.ts +8 -0
- package/dist/init.d.ts +6 -1
- package/dist/jobs/job-store.d.ts +8 -1
- package/dist/{jobs-h1WRq3cp.js → jobs-Co6Ni5HP.js} +6 -6
- package/dist/jobs-Co6Ni5HP.js.map +1 -0
- package/dist/{jwt-D3oFauZI.js → jwt-rDS0884_.js} +4 -3
- package/dist/{jwt-D3oFauZI.js.map → jwt-rDS0884_.js.map} +1 -1
- package/dist/{keys-COzQ2aE8.js → keys-BXcdRNhJ.js} +2 -2
- package/dist/{keys-COzQ2aE8.js.map → keys-BXcdRNhJ.js.map} +1 -1
- package/dist/mcp/consent-page.d.ts +38 -1
- package/dist/mcp/mcp-routes.d.ts +9 -0
- package/dist/mcp/mcp-tools.d.ts +7 -1
- package/dist/mcp/oauth-store.d.ts +12 -5
- package/dist/metrics/history-recorder.d.ts +4 -1
- package/dist/metrics/history-store.d.ts +8 -0
- package/dist/{offline-BrqCRgih-BtDB1ecy.js → offline-AvuEcg7u-DFHL98OT.js} +127 -40
- package/dist/offline-AvuEcg7u-DFHL98OT.js.map +1 -0
- package/dist/{offline-store-BhYXViha-BW5j1We_.js → offline-store-BhYXViha-YTmjBpo2.js} +5 -5
- package/dist/{offline-store-BhYXViha-BW5j1We_.js.map → offline-store-BhYXViha-YTmjBpo2.js.map} +1 -1
- package/dist/{openapi-generator-BjHr6upl.js → openapi-generator-CyxEtYEX.js} +61 -22
- package/dist/openapi-generator-CyxEtYEX.js.map +1 -0
- package/dist/{proxy-CH8Jsovg.js → proxy-BYir8tWK.js} +4 -6
- package/dist/proxy-BYir8tWK.js.map +1 -0
- package/dist/{query-parser-otFZqJsC.js → query-parser-CDXWf2hH.js} +6 -5
- package/dist/{query-parser-otFZqJsC.js.map → query-parser-CDXWf2hH.js.map} +1 -1
- package/dist/{request-timeout-59crS-9u.js → request-timeout-DVjo-c_8.js} +4 -4
- package/dist/request-timeout-DVjo-c_8.js.map +1 -0
- package/dist/rls-simulator-routes-bEY7-5-u.js +190 -0
- package/dist/rls-simulator-routes-bEY7-5-u.js.map +1 -0
- package/dist/schema-edit/deployed-schema-guard.d.ts +47 -0
- package/dist/{schema-editor-routes-Bsut0bCC.js → schema-editor-routes-Dc3DU_jm.js} +3 -3
- package/dist/{schema-editor-routes-Bsut0bCC.js.map → schema-editor-routes-Dc3DU_jm.js.map} +1 -1
- package/dist/soft-delete-params-BRONCOA2.js +59 -0
- package/dist/soft-delete-params-BRONCOA2.js.map +1 -0
- package/dist/{sql-export-routes-DmB_uZ4l.js → sql-export-routes-QycX8W8S.js} +38 -4
- package/dist/sql-export-routes-QycX8W8S.js.map +1 -0
- package/dist/{src-D5Y3N-S4.js → src-Bh9LRPb9.js} +21 -2
- package/dist/{src-D5Y3N-S4.js.map → src-Bh9LRPb9.js.map} +1 -1
- package/dist/storage/GCSStorageController.d.ts +2 -0
- package/dist/storage/LocalStorageController.d.ts +8 -3
- package/dist/storage/S3StorageController.d.ts +2 -0
- package/dist/storage/maintenance-keys.d.ts +17 -0
- package/dist/storage/maintenance-routes.d.ts +28 -5
- package/dist/storage/maintenance.d.ts +136 -4
- package/dist/storage/orphan-scans.d.ts +120 -0
- package/dist/storage/types.d.ts +11 -0
- package/dist/strings.es-B7QLnHh2.js +96 -0
- package/dist/strings.es-B7QLnHh2.js.map +1 -0
- package/dist/upload-validation-Bgo626uY.js.map +1 -1
- package/package.json +5 -5
- package/dist/GCSStorageController-CRd9bFrc.js.map +0 -1
- package/dist/S3StorageController-D00EFa5P.js.map +0 -1
- package/dist/auth-Dkvo2tTJ.js.map +0 -1
- package/dist/auth_adapter-CIItCTc8.js +0 -21
- package/dist/auth_adapter-CIItCTc8.js.map +0 -1
- package/dist/backend-DTAOsLQc.js.map +0 -1
- package/dist/cron-store-DkyfuLOH.js.map +0 -1
- package/dist/ddl-bootstrap-Ck20GSIX.js.map +0 -1
- package/dist/function-loader-KKDqTcIr.js.map +0 -1
- package/dist/history-recorder-B2rkuhuy.js.map +0 -1
- package/dist/history-store-DPofGVDp.js.map +0 -1
- package/dist/jobs-h1WRq3cp.js.map +0 -1
- package/dist/offline-BrqCRgih-BtDB1ecy.js.map +0 -1
- package/dist/openapi-generator-BjHr6upl.js.map +0 -1
- package/dist/proxy-CH8Jsovg.js.map +0 -1
- package/dist/request-timeout-59crS-9u.js.map +0 -1
- package/dist/soft-delete-params-BmlVwecC.js.map +0 -1
- package/dist/sql-export-routes-DmB_uZ4l.js.map +0 -1
- package/dist/strings.es-BeZWAodn.js.map +0 -1
|
@@ -8,6 +8,24 @@ import { i as warnDeprecated, n as describeLoadFailure, r as nativeDynamicImport
|
|
|
8
8
|
import * as fs$1 from "fs";
|
|
9
9
|
import * as path$1 from "path";
|
|
10
10
|
import { pathToFileURL } from "url";
|
|
11
|
+
//#region src/functions/hono-like.ts
|
|
12
|
+
/**
|
|
13
|
+
* Duck-type check for Hono apps.
|
|
14
|
+
*
|
|
15
|
+
* Not `instanceof Hono`: a project's own `hono` and the copy this package
|
|
16
|
+
* resolves are often different installs, which do not share a prototype, so
|
|
17
|
+
* `instanceof` answers false for a perfectly good app. Every Hono instance has
|
|
18
|
+
* `.fetch()` and `.routes`.
|
|
19
|
+
*
|
|
20
|
+
* Node-free: `defineFunction` uses it, and it is exported from the portable
|
|
21
|
+
* `@rebasepro/server/functions` entry point.
|
|
22
|
+
*/
|
|
23
|
+
function isHonoLike(obj) {
|
|
24
|
+
if (!obj || typeof obj !== "object") return false;
|
|
25
|
+
const record = obj;
|
|
26
|
+
return typeof record.fetch === "function" && Array.isArray(record.routes);
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
11
29
|
//#region src/functions/function-loader.ts
|
|
12
30
|
var function_loader_exports = /* @__PURE__ */ __exportAll({
|
|
13
31
|
functionList: () => functionList,
|
|
@@ -136,7 +154,7 @@ async function readFunctionsDirectory(directory, importModule = nativeDynamicImp
|
|
|
136
154
|
const exportType = typeof exported;
|
|
137
155
|
const keys = exported && typeof exported === "object" ? Object.getOwnPropertyNames(Object.getPrototypeOf(exported)).slice(0, 10).join(", ") : "N/A";
|
|
138
156
|
logger.warn(`[functions] ${file}: default export is not a Hono app or factory. Skipping.\n export type: ${exportType}${exported?.constructor?.name ? ` (${exported.constructor.name})` : ""}\n prototype methods: ${keys}\n Hint: ensure the function exports a Hono app created with the same hono version as the server.
|
|
139
|
-
Author with \`defineFunction(...)\` from @rebasepro/server for a typed, checked contract.
|
|
157
|
+
Author with \`defineFunction(...)\` from @rebasepro/server/functions for a typed, checked contract.
|
|
140
158
|
The loader checks for .fetch() and .routes — any Hono-compatible app will work.`);
|
|
141
159
|
problems.push(`${file} (not a Hono app or factory)`);
|
|
142
160
|
} catch (err) {
|
|
@@ -159,18 +177,7 @@ async function readFunctionsDirectory(directory, importModule = nativeDynamicImp
|
|
|
159
177
|
problems
|
|
160
178
|
};
|
|
161
179
|
}
|
|
162
|
-
/**
|
|
163
|
-
* Duck-type check for Hono apps.
|
|
164
|
-
* We avoid `instanceof Hono` because different Hono versions
|
|
165
|
-
* installed in the user's project vs. our dependencies will
|
|
166
|
-
* not share the same prototype, causing false negatives.
|
|
167
|
-
*/
|
|
168
|
-
function isHonoLike(obj) {
|
|
169
|
-
if (!obj || typeof obj !== "object") return false;
|
|
170
|
-
const record = obj;
|
|
171
|
-
return typeof record.fetch === "function" && Array.isArray(record.routes);
|
|
172
|
-
}
|
|
173
180
|
//#endregion
|
|
174
|
-
export { loadFunctionsWithDiagnostics as i, loadFunctions as n, loadFunctionsFromDirectory as r, function_loader_exports as t };
|
|
181
|
+
export { isHonoLike as a, loadFunctionsWithDiagnostics as i, loadFunctions as n, loadFunctionsFromDirectory as r, function_loader_exports as t };
|
|
175
182
|
|
|
176
|
-
//# sourceMappingURL=function-loader-
|
|
183
|
+
//# sourceMappingURL=function-loader-B8YzXEsQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"function-loader-B8YzXEsQ.js","names":[],"sources":["../src/functions/hono-like.ts","../src/functions/function-loader.ts"],"sourcesContent":["/**\n * Duck-type check for Hono apps.\n *\n * Not `instanceof Hono`: a project's own `hono` and the copy this package\n * resolves are often different installs, which do not share a prototype, so\n * `instanceof` answers false for a perfectly good app. Every Hono instance has\n * `.fetch()` and `.routes`.\n *\n * Node-free: `defineFunction` uses it, and it is exported from the portable\n * `@rebasepro/server/functions` entry point.\n */\nexport function isHonoLike(obj: unknown): boolean {\n if (!obj || typeof obj !== \"object\") return false;\n const record = obj as Record<string, unknown>;\n return typeof record.fetch === \"function\" && Array.isArray(record.routes);\n}\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport { pathToFileURL } from \"url\";\nimport { Hono } from \"hono\";\nimport type { HonoEnv } from \"../api/types\";\nimport { logger } from \"../utils/logger.js\";\nimport { nativeDynamicImport, type ModuleImporter } from \"../utils/dynamic-import.js\";\nimport { describeLoadFailure, SYNTAX_ERROR_ADVICE } from \"../utils/load-failure.js\";\nimport { warnDeprecated } from \"@rebasepro/common\";\nimport { isHonoLike } from \"./hono-like\";\n\n/**\n * One custom function: a Hono app, served at `<functions mount>/<name>`.\n *\n * What `defineFunction(...)` returns, and what a function file default-exports:\n * a Hono app over {@link HonoEnv}, the environment a function runs in — build\n * one by hand as `new Hono<HonoEnv>()`. Any Hono-compatible app works at\n * runtime — the loader checks for `.fetch()` and `.routes` rather than an\n * `instanceof`, because a project and the server can hold two copies of hono.\n */\nexport type FunctionApp = Hono<HonoEnv>;\n\n/**\n * Functions as values: the URL segment each one answers at, to its app.\n *\n * `functions: { \"send-invoice\": sendInvoice }` serves `sendInvoice` at\n * `/api/functions/send-invoice` — the same thing a file named\n * `functions/send-invoice.ts` does. {@link loadFunctions} returns exactly this\n * shape, so `functions: await loadFunctions(dir)` and `functionsDir: dir` serve\n * the same routes.\n */\nexport type FunctionsRecord = Record<string, FunctionApp>;\n\n/** How a directory of modules is read. Shared by the function and cron loaders. */\nexport interface LoadDirectoryOptions {\n /**\n * How a module file is imported. Defaults to the runtime's own `import()`;\n * a caller with its own loader hooks (tsx, a test runner's sandbox) passes\n * `url => import(url)` so they apply.\n */\n importModule?: ModuleImporter;\n /**\n * Called once for every file the loader saw and did **not** load, as\n * `<file> (<reason>)`. The files are skipped either way — one malformed\n * file must not take the others with it — and logged; this is how a caller\n * reports them anywhere else.\n */\n onSkip?: (problem: string) => void;\n}\n\n/**\n * Load the custom functions in a directory, as values.\n *\n * Each file default-exports a Hono app — `defineFunction(...)` — or a factory\n * returning one. The filename without its extension is the record key, which\n * is the URL segment it is served at: `functions/send-invoice.ts` →\n * `{ \"send-invoice\": app }`. Only the top level is read.\n *\n * Never throws for a bad file: it is skipped, logged, and passed to\n * `options.onSkip`.\n *\n * @example\n * ```ts\n * const functions = await loadFunctions(path.resolve(\"functions\"));\n * const backend = await createRebaseBackend({ database, functions, provision: true });\n * ```\n */\nexport async function loadFunctions(directory: string, options: LoadDirectoryOptions = {}): Promise<FunctionsRecord> {\n const { functions, problems } = await readFunctionsDirectory(directory, options.importModule);\n if (options.onSkip) for (const problem of problems) options.onSkip(problem);\n return functions;\n}\n\n/** A loaded function, by name. The shape {@link createFunctionRoutes} mounts. */\nexport interface LoadedFunction {\n /** Endpoint name derived from filename (e.g., \"send-invoice\") */\n name: string;\n /** The Hono sub-app to mount */\n app: FunctionApp;\n}\n\n/** What a directory of function files produced: what mounted, and what did not. */\nexport interface LoadedFunctions {\n /** The functions that will be served. */\n functions: LoadedFunction[];\n /**\n * One entry per file the loader saw and did **not** mount, each already\n * phrased as `<name> (<reason>)`.\n */\n problems: string[];\n}\n\n/** A record of functions as the list {@link createFunctionRoutes} mounts, in record order. */\nexport function functionList(functions: FunctionsRecord): LoadedFunction[] {\n return Object.entries(functions).map(([name, app]) => ({ name, app }));\n}\n\n/**\n * Extensions the bundler compiles (or a developer might reasonably write) that\n * this loader cannot import. `rebase build` globs `functions/**\\/*.ts`, so the\n * build's idea of \"a function file\" is strictly wider than the runtime's — the\n * worst direction for a mismatch to go. Anything listed here is reported as a\n * problem instead of vanishing; non-code files (`.md`, `.json`, `.txt`) stay\n * silent, because a README next to your functions is not a mistake.\n */\nconst UNSUPPORTED_CODE_EXTENSIONS = [\".mts\", \".cts\", \".tsx\", \".jsx\", \".mjs\", \".cjs\"];\n\n/**\n * @deprecated Use `loadFunctions` instead, which returns the functions as a\n * record keyed by name. Will be removed in a future release.\n */\nexport async function loadFunctionsFromDirectory(\n directory: string,\n importModule: ModuleImporter = nativeDynamicImport\n): Promise<LoadedFunction[]> {\n warnDeprecated(\n \"server.loadFunctionsFromDirectory\",\n \"`loadFunctionsFromDirectory` is deprecated; use `loadFunctions(dir)`, which returns `{ [name]: app }`.\"\n );\n return functionList((await readFunctionsDirectory(directory, importModule)).functions);\n}\n\n/**\n * @deprecated Use `loadFunctions` instead, with `onSkip` to collect the files\n * it skipped. Will be removed in a future release.\n */\nexport async function loadFunctionsWithDiagnostics(\n directory: string,\n importModule: ModuleImporter = nativeDynamicImport\n): Promise<LoadedFunctions> {\n warnDeprecated(\n \"server.loadFunctionsWithDiagnostics\",\n \"`loadFunctionsWithDiagnostics` is deprecated; use `loadFunctions(dir, { onSkip })`, which returns `{ [name]: app }`.\"\n );\n const { functions, problems } = await readFunctionsDirectory(directory, importModule);\n return { functions: functionList(functions), problems };\n}\n\n/**\n * Read a directory of function files: what loaded, keyed by name, and one\n * `<file> (<reason>)` per file that did not.\n *\n * Never throws: a single malformed function must not crash server boot. The\n * backend mounts the router regardless and surfaces the count of skipped files\n * on the listing endpoint.\n */\nexport async function readFunctionsDirectory(\n directory: string,\n importModule: ModuleImporter = nativeDynamicImport\n): Promise<{ functions: FunctionsRecord; problems: string[] }> {\n const functions: FunctionsRecord = {};\n // Aggregate problem files so a broken function surfaces as one loud\n // summary line, not just a warning buried per-file. We still don't throw:\n // a single malformed function must not crash server boot.\n const problems: string[] = [];\n\n if (!fs.existsSync(directory)) {\n return { functions, problems };\n }\n\n // `withFileTypes` so a directory entry is a *reported* skip rather than a\n // filter miss. `readdirSync(dir)` returned bare names, and a subdirectory\n // simply failed the `.ts`/`.js` test — so `functions/admin/users.ts` was\n // compiled by `rebase build`, shipped in the bundle, and then dropped at\n // boot without a single log line.\n const entries = fs.readdirSync(directory, { withFileTypes: true });\n for (const entry of entries) {\n const file = entry.name;\n\n if (entry.isDirectory()) {\n // Dot-directories are tooling (`.git`, `.turbo`), not intent.\n if (file.startsWith(\".\") || file === \"node_modules\") continue;\n logger.warn(\n `[functions] ${file}/: subdirectory ignored. Functions are loaded from the top level of ` +\n `${directory} only, so nothing under ${file}/ is served. Move the file up (or flatten the ` +\n \"name: `admin/users.ts` → `admin-users.ts`).\"\n );\n problems.push(`${file}/ (subdirectory — functions are not loaded recursively)`);\n continue;\n }\n\n const extension = path.extname(file);\n if (\n !file.startsWith(\".\") &&\n !file.includes(\".test.\") &&\n UNSUPPORTED_CODE_EXTENSIONS.includes(extension)\n ) {\n logger.warn(\n `[functions] ${file}: ${extension} files are not loaded. Rename it to .ts (or .js) to serve it.`\n );\n problems.push(`${file} (unsupported extension ${extension})`);\n continue;\n }\n\n if (\n (file.endsWith(\".ts\") || file.endsWith(\".js\")) &&\n // Dotfiles: notably macOS bsdtar AppleDouble sidecars (`._foo.ts`),\n // binary blobs that cannot be imported.\n !file.startsWith(\".\") &&\n !file.includes(\".test.\") &&\n !file.endsWith(\".d.ts\") &&\n file !== \"index.ts\" &&\n file !== \"index.js\"\n ) {\n const filePath = path.join(directory, file);\n try {\n const fileUrl = pathToFileURL(filePath).href;\n\n const mod = await importModule(fileUrl);\n\n const exported = mod.default;\n\n if (!exported) {\n logger.warn(`[functions] ${file}: no default export. Skipping.`);\n problems.push(`${file} (no default export)`);\n continue;\n }\n\n // Accept a Hono instance — use duck-typing to handle different\n // Hono versions which may not share the same prototype.\n const app = isHonoLike(exported)\n ? exported as FunctionApp\n // Also accept a factory function that returns a Hono instance\n : typeof exported === \"function\" ? exported() : undefined;\n if (isHonoLike(app)) {\n const name = path.basename(file, path.extname(file));\n // `send.ts` and `send.js` side by side name one URL. A\n // record holds one app per name, so the second is reported\n // rather than silently replacing the first.\n if (Object.hasOwn(functions, name)) {\n logger.warn(`[functions] ${file}: another file is already served as '${name}'. Skipping.`);\n problems.push(`${file} (another file is already served as '${name}')`);\n continue;\n }\n functions[name] = app as FunctionApp;\n logger.debug(`⚡ Loaded function route: ${name}`);\n continue;\n }\n\n // Provide actionable diagnostics\n const exportType = typeof exported;\n const keys = exported && typeof exported === \"object\"\n ? Object.getOwnPropertyNames(Object.getPrototypeOf(exported)).slice(0, 10).join(\", \")\n : \"N/A\";\n logger.warn(\n `[functions] ${file}: default export is not a Hono app or factory. Skipping.\\n` +\n ` export type: ${exportType}${exported?.constructor?.name ? ` (${exported.constructor.name})` : \"\"}\\n` +\n ` prototype methods: ${keys}\\n` +\n \" Hint: ensure the function exports a Hono app created with the same hono version as the server.\\n\" +\n \" Author with `defineFunction(...)` from @rebasepro/server/functions for a typed, checked contract.\\n\" +\n \" The loader checks for .fetch() and .routes — any Hono-compatible app will work.\"\n );\n problems.push(`${file} (not a Hono app or factory)`);\n } catch (err: unknown) {\n const message =\n err instanceof Error ? err.message : String(err);\n logger.error(`[functions] Failed to load ${file}: ${message}`);\n problems.push(describeLoadFailure(file, err));\n }\n }\n }\n\n if (problems.length > 0) {\n // Advice keyed to what actually went wrong. The old line said\n // \"author them with `defineFunction(...)`\" for every failure — which is\n // the fix for a wrong export shape and no help at all for the commonest\n // one: a file that threw while being imported, usually a module-scope\n // `process.env.X` read that came back undefined. Told to reach for\n // `defineFunction`, an author rewrites a file whose export was already\n // correct and gets the same failure.\n const advice: string[] = [];\n if (problems.some(p => p.includes(\"(syntax error\"))) {\n advice.push(SYNTAX_ERROR_ADVICE);\n }\n if (problems.some(p => p.includes(\"(threw:\"))) {\n advice.push(\n \" A file that threw ran at import time. Read configuration *inside* a handler \" +\n \"(`requireEnv(c, \\\"STRIPE_KEY\\\")`, or a lazily-built client) rather than at module \" +\n \"scope, where one undefined variable takes the whole file down before any route exists.\"\n );\n }\n if (problems.some(p => p.includes(\"(no default export)\"))) {\n advice.push(\n \" A file with no default export exports nothing the loader can mount. \" +\n \"`export default defineFunction((app) => { … })`.\"\n );\n }\n if (problems.some(p => p.includes(\"(not a Hono app or factory)\"))) {\n advice.push(\n \" A default export the loader did not recognise is usually two copies of hono. \" +\n \"Author with `defineFunction(...)` from @rebasepro/server/functions, which uses the \" +\n \"server's own copy.\"\n );\n }\n logger.warn(\n `[functions] ${problems.length} function file(s) were skipped and will NOT be served:\\n` +\n problems.map((p) => ` - ${p}`).join(\"\\n\") + \"\\n\" +\n advice.join(\"\\n\")\n );\n }\n\n return { functions, problems };\n}\n\n"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Duck-type check for Hono apps.
|
|
3
|
+
*
|
|
4
|
+
* Not `instanceof Hono`: a project's own `hono` and the copy this package
|
|
5
|
+
* resolves are often different installs, which do not share a prototype, so
|
|
6
|
+
* `instanceof` answers false for a perfectly good app. Every Hono instance has
|
|
7
|
+
* `.fetch()` and `.routes`.
|
|
8
|
+
*
|
|
9
|
+
* Node-free: `defineFunction` uses it, and it is exported from the portable
|
|
10
|
+
* `@rebasepro/server/functions` entry point.
|
|
11
|
+
*/
|
|
12
|
+
export declare function isHonoLike(obj: unknown): boolean;
|
package/dist/functions/index.js
CHANGED
|
@@ -194,6 +194,24 @@ var rebase = new Proxy({}, {
|
|
|
194
194
|
}
|
|
195
195
|
});
|
|
196
196
|
//#endregion
|
|
197
|
+
//#region src/functions/hono-like.ts
|
|
198
|
+
/**
|
|
199
|
+
* Duck-type check for Hono apps.
|
|
200
|
+
*
|
|
201
|
+
* Not `instanceof Hono`: a project's own `hono` and the copy this package
|
|
202
|
+
* resolves are often different installs, which do not share a prototype, so
|
|
203
|
+
* `instanceof` answers false for a perfectly good app. Every Hono instance has
|
|
204
|
+
* `.fetch()` and `.routes`.
|
|
205
|
+
*
|
|
206
|
+
* Node-free: `defineFunction` uses it, and it is exported from the portable
|
|
207
|
+
* `@rebasepro/server/functions` entry point.
|
|
208
|
+
*/
|
|
209
|
+
function isHonoLike(obj) {
|
|
210
|
+
if (!obj || typeof obj !== "object") return false;
|
|
211
|
+
const record = obj;
|
|
212
|
+
return typeof record.fetch === "function" && Array.isArray(record.routes);
|
|
213
|
+
}
|
|
214
|
+
//#endregion
|
|
197
215
|
//#region src/functions/define-function.ts
|
|
198
216
|
/**
|
|
199
217
|
* The `rebase` handle, seen through the `Database` a function names.
|
|
@@ -246,7 +264,7 @@ function typedSingleton() {
|
|
|
246
264
|
function defineFunction(definition) {
|
|
247
265
|
const app = new Hono();
|
|
248
266
|
const returned = definition(app, { rebase: typedSingleton() });
|
|
249
|
-
return returned
|
|
267
|
+
return isHonoLike(returned) ? returned : app;
|
|
250
268
|
}
|
|
251
269
|
//#endregion
|
|
252
270
|
//#region src/auth/admin-roles.ts
|