@rebasepro/server 0.23.0 → 0.24.1-canary.g19596ef
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 +28 -3
- package/bin/rebase-server.js +4 -2
- package/dist/GCSStorageController-DEga1ULx.js +402 -0
- package/dist/GCSStorageController-DEga1ULx.js.map +1 -0
- package/dist/S3StorageController-Btx-6bJ5.js +480 -0
- package/dist/S3StorageController-Btx-6bJ5.js.map +1 -0
- package/dist/api/ast-schema-editor.d.ts +92 -1
- package/dist/api/errors.d.ts +41 -0
- package/dist/api/live-schema-routes.d.ts +64 -10
- package/dist/api/logs-routes.d.ts +39 -1
- package/dist/api/mount-path.d.ts +30 -0
- package/dist/api/mount.d.ts +6 -13
- package/dist/api/openapi-generator.d.ts +17 -0
- package/dist/api/rest/api-generator.d.ts +97 -11
- package/dist/api/rest/auth-collection-writes.d.ts +28 -21
- package/dist/api/rest/field-access-query.d.ts +28 -8
- package/dist/api/rest/field-ops.d.ts +19 -7
- package/dist/api/rest/query-body.d.ts +10 -0
- package/dist/api/rest/write-validation.d.ts +9 -7
- package/dist/api/schema-editor-routes.d.ts +10 -1
- package/dist/api/sql-export-routes.d.ts +8 -0
- package/dist/api/types.d.ts +52 -1
- package/dist/{ast-schema-editor-Mvr50v_S.js → ast-schema-editor-mCeSC03x.js} +310 -12
- package/dist/ast-schema-editor-mCeSC03x.js.map +1 -0
- package/dist/auth/access.d.ts +156 -0
- package/dist/auth/adapter-middleware.d.ts +2 -1
- package/dist/auth/address-ownership.d.ts +16 -1
- package/dist/auth/admin-roles-route.d.ts +4 -2
- package/dist/auth/admin-roles.d.ts +17 -20
- package/dist/auth/admin-user-ops.d.ts +24 -2
- package/dist/auth/admin-users-route.d.ts +2 -0
- package/dist/auth/api-keys/api-key-middleware.d.ts +64 -56
- package/dist/auth/api-keys/api-key-routes.d.ts +44 -11
- package/dist/auth/api-keys/api-key-store.d.ts +31 -8
- package/dist/auth/api-keys/api-key-types.d.ts +14 -16
- package/dist/auth/api-keys/http-operation.d.ts +19 -0
- package/dist/auth/api-keys/index.d.ts +11 -11
- package/dist/auth/api-keys/key-grant.d.ts +41 -0
- package/dist/auth/api-keys/legacy-permissions.d.ts +33 -0
- package/dist/auth/auth-hooks.d.ts +46 -7
- package/dist/auth/builtin-auth-adapter.d.ts +21 -0
- package/dist/auth/cookie-utils.d.ts +7 -0
- package/dist/auth/deliverable-address.d.ts +6 -0
- package/dist/auth/email-change-routes.d.ts +44 -0
- package/dist/auth/expired-token-sweep.d.ts +71 -0
- package/dist/auth/impersonation.d.ts +110 -0
- package/dist/auth/index.d.ts +4 -2
- package/dist/auth/interfaces.d.ts +120 -59
- package/dist/auth/jwks-routes.d.ts +5 -1
- package/dist/auth/jwt-crypto.d.ts +7 -0
- package/dist/auth/jwt-keys.d.ts +4 -0
- package/dist/auth/jwt.d.ts +319 -157
- package/dist/auth/magic-link-routes.d.ts +5 -6
- package/dist/auth/mfa-crypto.d.ts +9 -3
- package/dist/auth/mfa-gate.d.ts +4 -2
- package/dist/auth/mfa-routes.d.ts +8 -9
- package/dist/auth/middleware.d.ts +26 -7
- package/dist/auth/otp-routes.d.ts +5 -6
- package/dist/auth/passwordless-signup.d.ts +27 -0
- package/dist/auth/platform-token.d.ts +122 -0
- package/dist/auth/rate-limiter.d.ts +99 -31
- package/dist/auth/registration-policy.d.ts +17 -0
- package/dist/auth/require-auth.d.ts +1 -1
- package/dist/auth/routes.d.ts +61 -0
- package/dist/auth/scope-routes.d.ts +22 -0
- package/dist/auth/session-routes.d.ts +17 -6
- package/dist/auth/token-revocation.d.ts +56 -1
- package/dist/auth/user-picking.d.ts +37 -0
- package/dist/auth/verify-credential.d.ts +49 -0
- package/dist/{auth-B-GIMpDG.js → auth-CSBky1mt.js} +4564 -1929
- package/dist/auth-CSBky1mt.js.map +1 -0
- package/dist/auth_adapter-CIItCTc8.js +21 -0
- package/dist/auth_adapter-CIItCTc8.js.map +1 -0
- package/dist/backend/create-backend.d.ts +281 -0
- package/dist/backend/default-backend.d.ts +35 -0
- package/dist/backend/no-collections.d.ts +19 -0
- package/dist/backend/options.d.ts +912 -0
- package/dist/backend/scope.d.ts +23 -0
- package/dist/backend/services.d.ts +54 -0
- package/dist/backend-DTAOsLQc.js.map +1 -1
- package/dist/backup/backup-common.d.ts +24 -3
- package/dist/backup/backup-routes.d.ts +46 -5
- package/dist/backup/backup-schedule.d.ts +33 -0
- package/dist/backup/backup-storage.d.ts +16 -0
- package/dist/backup/index.d.ts +5 -1
- package/dist/backup-DBGRUVTS.js +585 -0
- package/dist/backup-DBGRUVTS.js.map +1 -0
- package/dist/boot/boot.d.ts +2 -2
- package/dist/boot/bundle.d.ts +19 -0
- package/dist/boot/driver.d.ts +3 -0
- package/dist/boot/env.d.ts +58 -6
- package/dist/boot/http-server.d.ts +22 -0
- package/dist/boot/options.d.ts +16 -1
- package/dist/boot/provision.d.ts +4 -2
- package/dist/boot/resource-adapters.d.ts +11 -14
- package/dist/boot/runtime-cors.d.ts +17 -0
- package/dist/boot/security-headers.d.ts +26 -0
- package/dist/boot/sources.d.ts +9 -0
- package/dist/boot/static-routing.d.ts +65 -0
- package/dist/collection_patch-BRu-BvDv.js +472 -0
- package/dist/collection_patch-BRu-BvDv.js.map +1 -0
- package/dist/{contract-routes-CbFjuBwa.js → contract-routes-DiFwiLg2.js} +5 -8
- package/dist/contract-routes-DiFwiLg2.js.map +1 -0
- package/dist/cron/cron-loader.d.ts +77 -18
- package/dist/cron/cron-routes.d.ts +1 -1
- package/dist/cron/cron-scheduler.d.ts +94 -23
- package/dist/cron/cron-store.d.ts +37 -5
- package/dist/cron/define-cron.d.ts +6 -2
- package/dist/cron/index.d.ts +3 -3
- package/dist/cron-loader-NHqRfKF0.js +202 -0
- package/dist/cron-loader-NHqRfKF0.js.map +1 -0
- package/dist/{cron-routes-eE8nif_b.js → cron-routes-DsH8Jwn5.js} +34 -8
- package/dist/cron-routes-DsH8Jwn5.js.map +1 -0
- package/dist/{cron-scheduler-B0pLfAix.js → cron-scheduler-D1DT0nw5.js} +349 -65
- package/dist/cron-scheduler-D1DT0nw5.js.map +1 -0
- package/dist/cron-store-DEpVstUU.js +577 -0
- package/dist/cron-store-DEpVstUU.js.map +1 -0
- package/dist/{ddl-bootstrap-C6mo0Kmz.js → ddl-bootstrap-BNqi2NZe.js} +2 -2
- package/dist/{ddl-bootstrap-C6mo0Kmz.js.map → ddl-bootstrap-BNqi2NZe.js.map} +1 -1
- package/dist/email/index.d.ts +2 -2
- package/dist/email/smtp-email-service.d.ts +23 -0
- package/dist/email/templates.d.ts +22 -0
- package/dist/email/types.d.ts +44 -0
- package/dist/env.d.ts +1 -39
- package/dist/{errors-DWsX4yTd.js → errors-Cqp86KnA.js} +263 -10
- package/dist/errors-Cqp86KnA.js.map +1 -0
- package/dist/filter-dialect-O1HK6Nvr.js +1628 -0
- package/dist/filter-dialect-O1HK6Nvr.js.map +1 -0
- package/dist/{function-loader-xnbDAPfa.js → function-loader-DbCSoNJj.js} +69 -39
- package/dist/function-loader-DbCSoNJj.js.map +1 -0
- package/dist/{function-routes-Chet4-lB.js → function-routes-BSTClQNa.js} +28 -15
- package/dist/function-routes-BSTClQNa.js.map +1 -0
- package/dist/functions/context.d.ts +26 -6
- package/dist/functions/define-function.d.ts +10 -6
- package/dist/functions/function-loader.d.ts +75 -18
- package/dist/functions/function-routes.d.ts +2 -1
- package/dist/functions/guards.d.ts +22 -5
- package/dist/functions/index.d.ts +6 -5
- package/dist/functions/index.js +148 -50
- package/dist/functions/index.js.map +1 -1
- package/dist/functions/internal.d.ts +2 -2
- package/dist/functions/proxy.d.ts +6 -2
- package/dist/functions/request-timeout.d.ts +7 -5
- package/dist/history/history-routes.d.ts +9 -0
- package/dist/history/retention-sweep.d.ts +81 -0
- package/dist/{history-recorder-B4MpJfJK.js → history-recorder-RZ1Ow4YY.js} +4 -4
- package/dist/{history-recorder-B4MpJfJK.js.map → history-recorder-RZ1Ow4YY.js.map} +1 -1
- package/dist/{history-store-BhxWOuz9.js → history-store-DPofGVDp.js} +2 -2
- package/dist/{history-store-BhxWOuz9.js.map → history-store-DPofGVDp.js.map} +1 -1
- package/dist/index.d.ts +32 -13
- package/dist/index.es.js +25329 -18393
- package/dist/index.es.js.map +1 -1
- package/dist/init/docs.d.ts +35 -10
- package/dist/init/health.d.ts +17 -2
- package/dist/init/process-safety.d.ts +7 -2
- package/dist/init/shutdown.d.ts +26 -1
- package/dist/init.d.ts +49 -811
- package/dist/internal-tables-L2t39RdT.js +136 -0
- package/dist/internal-tables-L2t39RdT.js.map +1 -0
- package/dist/jobs/job-queue.d.ts +8 -0
- package/dist/jobs/job-store.d.ts +24 -0
- package/dist/jobs/types.d.ts +25 -4
- package/dist/{jobs-CazMYhyy.js → jobs-8G-_agld.js} +235 -25
- package/dist/jobs-8G-_agld.js.map +1 -0
- package/dist/{jwt-DnQHNFCl.js → jwt-CBaFc34Y.js} +546 -447
- package/dist/jwt-CBaFc34Y.js.map +1 -0
- package/dist/{keys-CogCQpxG.js → keys-COzQ2aE8.js} +3 -17
- package/dist/{keys-CogCQpxG.js.map → keys-COzQ2aE8.js.map} +1 -1
- package/dist/load-failure-L5hvfDoG.js +80 -0
- package/dist/load-failure-L5hvfDoG.js.map +1 -0
- package/dist/{logger-DO2PZc4i.js → logger-Bt32sHFw.js} +41 -5
- package/dist/logger-Bt32sHFw.js.map +1 -0
- package/dist/{logs-routes-Bj4TYYUl.js → logs-routes-DQJhrf-b.js} +48 -8
- package/dist/logs-routes-DQJhrf-b.js.map +1 -0
- package/dist/mcp/consent-page.d.ts +1 -1
- package/dist/mcp/mcp-routes.d.ts +13 -0
- package/dist/mcp/mcp-tools.d.ts +23 -9
- package/dist/mcp/oauth-metadata.d.ts +21 -16
- package/dist/mcp/oauth-routes.d.ts +14 -1
- package/dist/metrics/index.d.ts +18 -0
- package/dist/metrics/pool-wait.d.ts +50 -0
- package/dist/offline-QNQgsPOq-B2yGeXkn.js +3305 -0
- package/dist/offline-QNQgsPOq-B2yGeXkn.js.map +1 -0
- package/dist/offline-store-Cm5sAX81-CALiO4Gn.js +1915 -0
- package/dist/offline-store-Cm5sAX81-CALiO4Gn.js.map +1 -0
- package/dist/{openapi-generator-O_O24MAT.js → openapi-generator-CeGW2dLC.js} +455 -80
- package/dist/openapi-generator-CeGW2dLC.js.map +1 -0
- package/dist/policy-PdzX-Opd.js +121 -0
- package/dist/policy-PdzX-Opd.js.map +1 -0
- package/dist/project_manifest-R6y_KHms.js +59 -0
- package/dist/project_manifest-R6y_KHms.js.map +1 -0
- package/dist/{proxy-Czngl3p9.js → proxy-BEKbsil6.js} +5 -4
- package/dist/proxy-BEKbsil6.js.map +1 -0
- package/dist/{query-parser-DGRVFNM3.js → query-parser-ECxP0nDw.js} +497 -52
- package/dist/query-parser-ECxP0nDw.js.map +1 -0
- package/dist/{request-timeout-C_4C2BeR.js → request-timeout-BiRelY-U.js} +17 -10
- package/dist/request-timeout-BiRelY-U.js.map +1 -0
- package/dist/resumable-upload-threshold-CKv-Ry0l.js +24 -0
- package/dist/resumable-upload-threshold-CKv-Ry0l.js.map +1 -0
- package/dist/schema-edit/apply-schema-change.d.ts +73 -3
- package/dist/schema-edit/local-source.d.ts +29 -0
- package/dist/schema-edit/project-root.d.ts +3 -2
- package/dist/schema-edit/remote-source.d.ts +20 -5
- package/dist/schema-edit/source-editor.d.ts +28 -0
- package/dist/schema-editor-routes-DRXBAbZy.js +136 -0
- package/dist/schema-editor-routes-DRXBAbZy.js.map +1 -0
- package/dist/serve-spa.d.ts +58 -0
- package/dist/services/outbound-post.d.ts +50 -0
- package/dist/services/outbound-url-guard.d.ts +34 -5
- package/dist/services/routed-realtime-service.d.ts +16 -0
- package/dist/services/webhook-service.d.ts +66 -14
- package/dist/singleton.d.ts +9 -5
- package/dist/soft-delete-params-CBryZXMq.js +668 -0
- package/dist/soft-delete-params-CBryZXMq.js.map +1 -0
- package/dist/sql-export-routes-D8ZaRvoR.js +240 -0
- package/dist/sql-export-routes-D8ZaRvoR.js.map +1 -0
- package/dist/{src-vkcwKXbT.js → src-D5Y3N-S4.js} +440 -20
- package/dist/src-D5Y3N-S4.js.map +1 -0
- package/dist/storage/GCSStorageController.d.ts +48 -2
- package/dist/storage/LocalStorageController.d.ts +69 -2
- package/dist/storage/S3StorageController.d.ts +39 -3
- package/dist/storage/image-transform.d.ts +15 -0
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/maintenance-routes.d.ts +23 -0
- package/dist/storage/maintenance.d.ts +126 -0
- package/dist/storage/property-limits.d.ts +41 -6
- package/dist/storage/rendition-cache.d.ts +9 -11
- package/dist/storage/request-keys.d.ts +15 -0
- package/dist/storage/request-principals.d.ts +30 -0
- package/dist/storage/requested-object.d.ts +74 -0
- package/dist/storage/routes.d.ts +52 -14
- package/dist/storage/source-variables.d.ts +10 -0
- package/dist/storage/streams.d.ts +42 -0
- package/dist/storage/tus-handler.d.ts +76 -7
- package/dist/storage/types.d.ts +101 -7
- package/dist/storage/upload-validation.d.ts +13 -0
- package/dist/storage-resumable-VO-cMpse-C_YX71pO.js +125 -0
- package/dist/storage-resumable-VO-cMpse-C_YX71pO.js.map +1 -0
- package/dist/strings.es-BeZWAodn.js +256 -0
- package/dist/strings.es-BeZWAodn.js.map +1 -0
- package/dist/upload-validation-CVobI5xO.js +172 -0
- package/dist/upload-validation-CVobI5xO.js.map +1 -0
- package/dist/utils/byte-size.d.ts +10 -0
- package/dist/utils/compression.d.ts +6 -0
- package/dist/utils/load-failure.d.ts +14 -0
- package/dist/utils/logger.d.ts +21 -0
- package/package.json +5 -5
- package/dist/GCSStorageController-CjrA4PMo.js +0 -242
- package/dist/GCSStorageController-CjrA4PMo.js.map +0 -1
- package/dist/S3StorageController-B6pKDNVj.js +0 -264
- package/dist/S3StorageController-B6pKDNVj.js.map +0 -1
- package/dist/admin-roles-vYdp_Pil.js +0 -36
- package/dist/admin-roles-vYdp_Pil.js.map +0 -1
- package/dist/admin_block-DxKLmdiv.js +0 -206
- package/dist/admin_block-DxKLmdiv.js.map +0 -1
- package/dist/ast-schema-editor-Mvr50v_S.js.map +0 -1
- package/dist/auth/api-keys/api-key-permission-guard.d.ts +0 -65
- package/dist/auth-B-GIMpDG.js.map +0 -1
- package/dist/backup-D7YR94N3.js +0 -253
- package/dist/backup-D7YR94N3.js.map +0 -1
- package/dist/contract-routes-CbFjuBwa.js.map +0 -1
- package/dist/cron-loader-DfTj2Hbi.js +0 -118
- package/dist/cron-loader-DfTj2Hbi.js.map +0 -1
- package/dist/cron-routes-eE8nif_b.js.map +0 -1
- package/dist/cron-scheduler-B0pLfAix.js.map +0 -1
- package/dist/cron-store-TcoGz-xS.js +0 -305
- package/dist/cron-store-TcoGz-xS.js.map +0 -1
- package/dist/dynamic-import-X40pTZUQ.js +0 -23
- package/dist/dynamic-import-X40pTZUQ.js.map +0 -1
- package/dist/errors-DWsX4yTd.js.map +0 -1
- package/dist/function-loader-xnbDAPfa.js.map +0 -1
- package/dist/function-routes-Chet4-lB.js.map +0 -1
- package/dist/jobs-CazMYhyy.js.map +0 -1
- package/dist/jwt-DnQHNFCl.js.map +0 -1
- package/dist/logger-DO2PZc4i.js.map +0 -1
- package/dist/logs-routes-Bj4TYYUl.js.map +0 -1
- package/dist/openapi-generator-O_O24MAT.js.map +0 -1
- package/dist/proxy-Czngl3p9.js.map +0 -1
- package/dist/query-parser-DGRVFNM3.js.map +0 -1
- package/dist/request-timeout-C_4C2BeR.js.map +0 -1
- package/dist/schema-editor-routes-C5-lh_jO.js +0 -87
- package/dist/schema-editor-routes-C5-lh_jO.js.map +0 -1
- package/dist/src-pmvW7BFx.js +0 -6688
- package/dist/src-pmvW7BFx.js.map +0 -1
- package/dist/src-vkcwKXbT.js.map +0 -1
- package/dist/types-BfKcm9do.js +0 -39
- package/dist/types-BfKcm9do.js.map +0 -1
|
@@ -67,14 +67,15 @@ export type { RebaseFunctionContext } from "./define-function.js";
|
|
|
67
67
|
*
|
|
68
68
|
* It is safe to hold at module scope, unlike a configuration value, because it
|
|
69
69
|
* is a lazy Proxy: nothing is resolved until a property is read, which happens
|
|
70
|
-
* inside a request
|
|
71
|
-
*
|
|
72
|
-
*
|
|
70
|
+
* inside a request — and it resolves to the backend serving that request, so
|
|
71
|
+
* with two backends in one process each one's functions see their own. That
|
|
72
|
+
* indirection is the whole of what a host hooks — the Node server per request,
|
|
73
|
+
* an isolate host per isolate — see `_setRebaseResolver` in `../singleton.ts`.
|
|
73
74
|
*/
|
|
74
75
|
export { rebase } from "../singleton.js";
|
|
75
|
-
export { getUser, getUserId, getRoles, hasRole, isAdmin, isAuthenticated, getDriver, requireDriver, getApiKey, getRequestId, identityResolved } from "./context.js";
|
|
76
|
+
export { getUser, getUserId, getRoles, hasRole, isAdmin, getScopes, hasScope, isAuthenticated, getDriver, requireDriver, getApiKey, getRequestId, getSignal, identityResolved } from "./context.js";
|
|
76
77
|
export type { FunctionUser } from "./context.js";
|
|
77
|
-
export { requireAuth, requireAdmin, requireRole } from "./guards.js";
|
|
78
|
+
export { requireAuth, requireAdmin, requireRole, requireScope } from "./guards.js";
|
|
78
79
|
export { getEnv, env, requireEnv, runtimeKey, isNodeRuntime, lazyResource } from "./runtime-env.js";
|
|
79
80
|
export { waitUntil } from "./wait-until.js";
|
|
80
81
|
/**
|
package/dist/functions/index.js
CHANGED
|
@@ -96,13 +96,15 @@ var INSTANCE_SLOT = Symbol.for("@rebasepro/server:singleton-instance");
|
|
|
96
96
|
* A *function* that answers "which client is this call for", for hosts where
|
|
97
97
|
* one answer per process is the wrong shape.
|
|
98
98
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* request
|
|
99
|
+
* {@link INSTANCE_SLOT} is one answer per process: the default backend's. A
|
|
100
|
+
* Node process can hold several backends, and the code each one runs — a
|
|
101
|
+
* function, a cron job, a hook — must see that one, so the server registers a
|
|
102
|
+
* resolver reading the backend scope it enters per request (an
|
|
103
|
+
* `AsyncLocalStorage`, host-side, in `backend/scope.ts`). An isolate-based
|
|
104
|
+
* host is different in the same way: the environment arrives attached to the
|
|
105
|
+
* **request**, not to the module, so there is nothing to publish at import
|
|
106
|
+
* time, and an isolate can be reused across requests that must not share
|
|
107
|
+
* state. The resolver is consulted first.
|
|
106
108
|
*
|
|
107
109
|
* This exists now, before there is a host that needs it, because of what it
|
|
108
110
|
* protects: `rebase` is a lazy Proxy, so every property access already goes
|
|
@@ -123,10 +125,13 @@ function getInstance() {
|
|
|
123
125
|
return global[INSTANCE_SLOT] ?? null;
|
|
124
126
|
}
|
|
125
127
|
/**
|
|
126
|
-
* The server-side Rebase
|
|
128
|
+
* The server-side Rebase client, as a module-level handle.
|
|
127
129
|
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
+
* Inside a request, cron run or job a backend serves, it is that backend's
|
|
131
|
+
* client (`backend.rebase`) — so with two backends in one process, each one's
|
|
132
|
+
* functions see their own. Anywhere else it is the process default's, which
|
|
133
|
+
* `initializeRebaseBackend` (or `setDefaultBackend`) installs. Provides access
|
|
134
|
+
* to all app-scoped services: **data**, **auth**, **storage**, and **email**.
|
|
130
135
|
*
|
|
131
136
|
* **Admin data plane** (`rebase.dataAsAdmin`):
|
|
132
137
|
* Backed by the native DataDriver — calls go directly to the database without
|
|
@@ -185,12 +190,25 @@ var rebase = new Proxy({}, {
|
|
|
185
190
|
return instance[prop];
|
|
186
191
|
},
|
|
187
192
|
set(_, prop) {
|
|
188
|
-
throw new Error(`Cannot set rebase.${String(prop)} directly. The singleton is read-only.
|
|
193
|
+
throw new Error(`Cannot set rebase.${String(prop)} directly. The singleton is read-only. Install a backend with setDefaultBackend(backend), or use backend.rebase.`);
|
|
189
194
|
}
|
|
190
195
|
});
|
|
191
196
|
//#endregion
|
|
192
197
|
//#region src/functions/define-function.ts
|
|
193
198
|
/**
|
|
199
|
+
* The `rebase` handle, seen through the `Database` a function names.
|
|
200
|
+
*
|
|
201
|
+
* One object serves every function; `DB` only describes it. It resolves, per
|
|
202
|
+
* call, to the backend serving the request — the same answer the imported
|
|
203
|
+
* `rebase` gives. Each collection accessor on `dataAsAdmin` is resolved by
|
|
204
|
+
* name at call time, so a generated `Database` adds compile-time checks and
|
|
205
|
+
* changes nothing the object does — the same reason the browser client's
|
|
206
|
+
* `createRebaseClient<Database>()` is one implementation for every `Database`.
|
|
207
|
+
*/
|
|
208
|
+
function typedSingleton() {
|
|
209
|
+
return rebase;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
194
212
|
* Typed authoring contract for a custom backend function.
|
|
195
213
|
*
|
|
196
214
|
* A custom function is a file in the `functionsDir` that default-exports a
|
|
@@ -227,37 +245,39 @@ var rebase = new Proxy({}, {
|
|
|
227
245
|
*/
|
|
228
246
|
function defineFunction(definition) {
|
|
229
247
|
const app = new Hono();
|
|
230
|
-
const returned = definition(app, { rebase });
|
|
248
|
+
const returned = definition(app, { rebase: typedSingleton() });
|
|
231
249
|
return returned instanceof Hono ? returned : app;
|
|
232
250
|
}
|
|
233
251
|
//#endregion
|
|
234
252
|
//#region src/auth/admin-roles.ts
|
|
235
253
|
/**
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
* a
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* neither of them owns it.
|
|
247
|
-
*
|
|
248
|
-
* `schema-admin` is here deliberately: it can reach the schema editor and the
|
|
249
|
-
* SQL surfaces, which is administrative by any definition that matters. If a
|
|
250
|
-
* genuinely lesser role is added later, it does not belong in this list — it
|
|
251
|
-
* belongs in a capability check of its own.
|
|
254
|
+
* The admin role and scope matching, for code that may not import
|
|
255
|
+
* `@rebasepro/types`.
|
|
256
|
+
*
|
|
257
|
+
* The custom-functions surface (`@rebasepro/server/functions`) must bundle for
|
|
258
|
+
* a runtime with no Node built-ins and imports nothing but `hono`, so its
|
|
259
|
+
* guards cannot reach the canonical definitions in `@rebasepro/types`
|
|
260
|
+
* (`ADMIN_ROLE`, `hasAdminRole`, `scopeGrants`). These are the same rules,
|
|
261
|
+
* restated, and `test/admin-roles.test.ts` holds them equal.
|
|
262
|
+
*
|
|
263
|
+
* Everything else imports the `@rebasepro/types` versions.
|
|
252
264
|
*/
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
265
|
+
/** The one built-in role. It holds every scope. */
|
|
266
|
+
var ADMIN_ROLE_NAME = "admin";
|
|
267
|
+
/** Does this list of roles include the admin role? */
|
|
268
|
+
function holdsAdminRole(roles) {
|
|
269
|
+
return !!roles?.includes(ADMIN_ROLE_NAME);
|
|
257
270
|
}
|
|
258
|
-
/**
|
|
259
|
-
|
|
260
|
-
|
|
271
|
+
/**
|
|
272
|
+
* Does a set of held scopes grant `scope`, optionally on one `target`? The
|
|
273
|
+
* unqualified grant covers every target; `scope:target` covers its own.
|
|
274
|
+
*/
|
|
275
|
+
function heldScopesGrant(held, scope, target) {
|
|
276
|
+
for (const entry of held) {
|
|
277
|
+
if (entry === scope) return true;
|
|
278
|
+
if (target !== void 0 && entry === `${scope}:${target}`) return true;
|
|
279
|
+
}
|
|
280
|
+
return false;
|
|
261
281
|
}
|
|
262
282
|
//#endregion
|
|
263
283
|
//#region src/functions/context.ts
|
|
@@ -310,16 +330,31 @@ function hasRole(c, ...roles) {
|
|
|
310
330
|
const held = new Set(getRoles(c));
|
|
311
331
|
return roles.some((role) => held.has(role));
|
|
312
332
|
}
|
|
333
|
+
/** Whether the caller holds the `admin` role, which holds every scope. */
|
|
334
|
+
function isAdmin(c) {
|
|
335
|
+
return holdsAdminRole(getRoles(c));
|
|
336
|
+
}
|
|
313
337
|
/**
|
|
314
|
-
*
|
|
338
|
+
* Everything the caller may do, as `resource:action[:target]` scope strings —
|
|
339
|
+
* the data plane, the app's own `auth.scopes`, and whatever their roles (or
|
|
340
|
+
* their API key) hold. Empty for an anonymous request.
|
|
315
341
|
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
* Those two lists disagreed once, and the gap made every public registrant an
|
|
319
|
-
* administrator; see that file.
|
|
342
|
+
* Resolved by the framework before the handler runs; `undefined` only when no
|
|
343
|
+
* Rebase auth middleware ran (see {@link identityResolved}).
|
|
320
344
|
*/
|
|
321
|
-
function
|
|
322
|
-
return
|
|
345
|
+
function getScopes(c) {
|
|
346
|
+
return read(c, "scopes");
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Whether the caller holds `scope`, on `target` when one is given.
|
|
350
|
+
*
|
|
351
|
+
* For an app scope declared under `auth.scopes` — `project:deploy` — a
|
|
352
|
+
* signed-in person always holds it, so this narrows only API keys and tokens.
|
|
353
|
+
* Whether the *person* may deploy *this* project is still the handler's to
|
|
354
|
+
* decide.
|
|
355
|
+
*/
|
|
356
|
+
function hasScope(c, scope, target) {
|
|
357
|
+
return heldScopesGrant(getScopes(c) ?? [], scope, target);
|
|
323
358
|
}
|
|
324
359
|
/** Whether the request carries an identity at all. */
|
|
325
360
|
function isAuthenticated(c) {
|
|
@@ -376,6 +411,17 @@ function getRequestId(c) {
|
|
|
376
411
|
return read(c, "requestId");
|
|
377
412
|
}
|
|
378
413
|
/**
|
|
414
|
+
* The signal aborted when this request outlasts the functions timeout and is
|
|
415
|
+
* answered `504 FUNCTION_TIMEOUT`. Pass it to `fetch` and anything else that
|
|
416
|
+
* takes one, so the work stops with the request instead of running on after
|
|
417
|
+
* the caller was told it failed.
|
|
418
|
+
*
|
|
419
|
+
* Never aborts when the timeout is off, or outside the functions router.
|
|
420
|
+
*/
|
|
421
|
+
function getSignal(c) {
|
|
422
|
+
return read(c, "functionSignal") ?? new AbortController().signal;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
379
425
|
* Whether a Rebase auth middleware has run on this request.
|
|
380
426
|
*
|
|
381
427
|
* Both middlewares populate `driver` for *every* outcome, anonymous included,
|
|
@@ -428,15 +474,14 @@ var requireAuth = async (c, next) => {
|
|
|
428
474
|
} }, 401);
|
|
429
475
|
};
|
|
430
476
|
/**
|
|
431
|
-
* Reject callers without
|
|
477
|
+
* Reject callers without the `admin` role with 403.
|
|
432
478
|
*
|
|
433
479
|
* Must come **after** {@link requireAuth}: on its own it answers 401 for an
|
|
434
480
|
* anonymous caller, which is right, but pairing them keeps the two failures
|
|
435
481
|
* distinguishable — 401 "who are you", 403 "not you".
|
|
436
482
|
*
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
* divergence that list exists to prevent.
|
|
483
|
+
* Prefer {@link requireScope} for anything an app declares a scope for: a
|
|
484
|
+
* scope can be granted to a narrower role and to a key, and `admin` cannot.
|
|
440
485
|
*/
|
|
441
486
|
var requireAdmin = async (c, next) => {
|
|
442
487
|
if (!getUser(c)) {
|
|
@@ -483,6 +528,44 @@ function requireRole(...roles) {
|
|
|
483
528
|
return next();
|
|
484
529
|
};
|
|
485
530
|
}
|
|
531
|
+
/**
|
|
532
|
+
* Reject callers who do not hold `scope` with 403.
|
|
533
|
+
*
|
|
534
|
+
* `scope` is a built-in scope or one the app declares under `auth.scopes` on
|
|
535
|
+
* the users collection. `target` narrows it to one resource — a key holding
|
|
536
|
+
* `project:deploy:p1` passes `requireScope("project:deploy", c => c.req.param("project"))`
|
|
537
|
+
* for `p1` only — and may be read from the request.
|
|
538
|
+
*
|
|
539
|
+
* A signed-in person holds every app scope, so for a person this is no
|
|
540
|
+
* authorization at all: it narrows API keys and tokens. Decide whether the
|
|
541
|
+
* person may act in the handler, as you would without it.
|
|
542
|
+
*
|
|
543
|
+
* @example
|
|
544
|
+
* ```ts
|
|
545
|
+
* app.post("/deploy/:project", requireAuth, requireScope("project:deploy", c => c.req.param("project")), handler);
|
|
546
|
+
* ```
|
|
547
|
+
*/
|
|
548
|
+
function requireScope(scope, target) {
|
|
549
|
+
return async (c, next) => {
|
|
550
|
+
if (!getUser(c)) {
|
|
551
|
+
if (!identityResolved(c)) return c.json(unresolvedIdentity(), 500);
|
|
552
|
+
return c.json({ error: {
|
|
553
|
+
message: "Authentication required",
|
|
554
|
+
code: "UNAUTHORIZED"
|
|
555
|
+
} }, 401);
|
|
556
|
+
}
|
|
557
|
+
const resolvedTarget = typeof target === "function" ? target(c) : target;
|
|
558
|
+
if (!hasScope(c, scope, resolvedTarget)) {
|
|
559
|
+
const wanted = resolvedTarget !== void 0 ? `${scope}:${resolvedTarget}` : scope;
|
|
560
|
+
return c.json({ error: {
|
|
561
|
+
message: `This credential does not hold the "${wanted}" scope.`,
|
|
562
|
+
code: "SCOPE_MISSING",
|
|
563
|
+
details: { requiredScope: wanted }
|
|
564
|
+
} }, 403);
|
|
565
|
+
}
|
|
566
|
+
return next();
|
|
567
|
+
};
|
|
568
|
+
}
|
|
486
569
|
//#endregion
|
|
487
570
|
//#region src/functions/runtime-env.ts
|
|
488
571
|
/**
|
|
@@ -632,9 +715,11 @@ function isProduction() {
|
|
|
632
715
|
* not be undone, because the originals were gone.
|
|
633
716
|
*/
|
|
634
717
|
var configuredLevel;
|
|
718
|
+
/** Every line to stderr, when a command's stdout is its result. See {@link setLogOutput}. */
|
|
719
|
+
var everyLineToStderr = false;
|
|
635
720
|
function getMinLevel() {
|
|
636
721
|
if (configuredLevel) return configuredLevel;
|
|
637
|
-
const env = (hostEnv().LOG_LEVEL || "info").toLowerCase();
|
|
722
|
+
const env = (hostEnv().LOG_LEVEL || "info").trim().toLowerCase();
|
|
638
723
|
if (env in LOG_PRIORITY) return env;
|
|
639
724
|
return "info";
|
|
640
725
|
}
|
|
@@ -853,13 +938,13 @@ function createLogger(rawDefaultFields = {}) {
|
|
|
853
938
|
...merged
|
|
854
939
|
};
|
|
855
940
|
const line = JSON.stringify(entry);
|
|
856
|
-
if (level === "error") writeLine("err", line);
|
|
941
|
+
if (level === "error" || everyLineToStderr) writeLine("err", line);
|
|
857
942
|
else writeLine("out", line);
|
|
858
943
|
} else {
|
|
859
944
|
const prefix = level === "error" ? "❌" : level === "warn" ? "⚠️" : level === "info" ? "ℹ️" : "🐛";
|
|
860
945
|
const extra = Object.keys(merged).length > 0 ? ` ${JSON.stringify(merged)}` : "";
|
|
861
946
|
const out = `${prefix} [${level.toUpperCase()}] ${safeMessage}${extra}`;
|
|
862
|
-
if (level === "error") console.error(out);
|
|
947
|
+
if (level === "error" || everyLineToStderr) console.error(out);
|
|
863
948
|
else if (level === "warn") console.warn(out);
|
|
864
949
|
else console.log(out);
|
|
865
950
|
}
|
|
@@ -950,6 +1035,8 @@ function logBackgroundFailure(c, error) {
|
|
|
950
1035
|
}
|
|
951
1036
|
//#endregion
|
|
952
1037
|
//#region src/api/errors.ts
|
|
1038
|
+
/** What a caller is told when the database cannot be reached. Retryable, and not about them. */
|
|
1039
|
+
var DATABASE_UNAVAILABLE_MESSAGE = "The database could not be reached, so this request was not served. Retry shortly; if it keeps happening, the server's database is down or unreachable from it.";
|
|
953
1040
|
/**
|
|
954
1041
|
* Standardized API error class.
|
|
955
1042
|
* Throw this from any route handler — the errorHandler middleware
|
|
@@ -1022,8 +1109,19 @@ var ApiError = class ApiError extends Error {
|
|
|
1022
1109
|
static serviceUnavailable(message, code = "SERVICE_UNAVAILABLE") {
|
|
1023
1110
|
return new ApiError(503, code, message);
|
|
1024
1111
|
}
|
|
1112
|
+
/**
|
|
1113
|
+
* `503 DATABASE_UNAVAILABLE`: the database could not be reached. What
|
|
1114
|
+
* every door answers then — the data API, sign-in, the admin routes and
|
|
1115
|
+
* the realtime socket — so a client sees one retryable answer, sent with
|
|
1116
|
+
* `Retry-After`, rather than a permission failure or a crash.
|
|
1117
|
+
*
|
|
1118
|
+
* @see isDatabaseUnreachable
|
|
1119
|
+
*/
|
|
1120
|
+
static databaseUnavailable(message = DATABASE_UNAVAILABLE_MESSAGE) {
|
|
1121
|
+
return new ApiError(503, "DATABASE_UNAVAILABLE", message);
|
|
1122
|
+
}
|
|
1025
1123
|
};
|
|
1026
1124
|
//#endregion
|
|
1027
|
-
export { ApiError, defineFunction, env, getApiKey, getDriver, getEnv, getRequestId, getRoles, getUser, getUserId, hasRole, identityResolved, isAdmin, isAuthenticated, isNodeRuntime, lazyResource, rebase, requireAdmin, requireAuth, requireDriver, requireEnv, requireRole, runtimeKey, waitUntil };
|
|
1125
|
+
export { ApiError, defineFunction, env, getApiKey, getDriver, getEnv, getRequestId, getRoles, getScopes, getSignal, getUser, getUserId, hasRole, hasScope, identityResolved, isAdmin, isAuthenticated, isNodeRuntime, lazyResource, rebase, requireAdmin, requireAuth, requireDriver, requireEnv, requireRole, requireScope, runtimeKey, waitUntil };
|
|
1028
1126
|
|
|
1029
1127
|
//# sourceMappingURL=index.js.map
|