@molecule/api-bonds-default-express
Feature · bonds-default · API (Node) · v1.1.1 · Apache-2.0
Default API bond setup for Express apps — per-concern setup functions plus a consolidated setup, wiring the byte-identical bond configuration (config-env, database, jwt, middleware, password, secrets, device, two-factor, and more) shared across the molecule fleet.
npm install @molecule/api-bonds-default-expressHow it works
@molecule/api-bonds-default-express is a ready-made bonds-default feature for the API (Node) side. It composes the core interfaces it needs, so it works with whichever providers your app has bonded.
// api/src/bonds/index.ts — wire defaults at startup, then validate:
import { validateBonds } from '@molecule/api-bond'
import {
setupConfigEnv,
setupDatabasePostgresql,
setupEmailsMailgun,
setupJwtJsonwebtoken,
setupSecretsEnv,
} from '@molecule/api-bonds-default-express'
async function setupBonds(): Promise<void> {
setupConfigEnv()
setupSecretsEnv()
setupDatabasePostgresql()
setupJwtJsonwebtoken()
setupEmailsMailgun()
validateBonds()
}Works with: @molecule/api-analytics, @molecule/api-bond, @molecule/api-cache-memory, @molecule/api-config, @molecule/api-config-env, @molecule/api-database, @molecule/api-database-postgresql, @molecule/api-emails, @molecule/api-emails-capture, @molecule/api-emails-mailgun, @molecule/api-entitlements, @molecule/api-geolocation-nominatim, @molecule/api-i18n, @molecule/api-jwt, @molecule/api-jwt-jsonwebtoken, @molecule/api-logger, @molecule/api-middleware-body-parser, @molecule/api-middleware-body-parser-express, @molecule/api-middleware-cookie-parser, @molecule/api-middleware-cookie-parser-express, @molecule/api-middleware-cors, @molecule/api-middleware-cors-express, @molecule/api-middleware-validation, @molecule/api-password, @molecule/api-password-bcrypt, @molecule/api-payments, @molecule/api-payments-stripe, @molecule/api-push-capture, @molecule/api-queue, @molecule/api-queue-memory, @molecule/api-resource, @molecule/api-resource-device, @molecule/api-resource-payment, @molecule/api-resource-user, @molecule/api-search, @molecule/api-search-meilisearch, @molecule/api-search-postgres, @molecule/api-secrets, @molecule/api-secrets-env, @molecule/api-server-default-express, @molecule/api-two-factor, @molecule/api-two-factor-otplib, @molecule/api-uploads, @molecule/api-uploads-filesystem, @molecule/api-uploads-s3
Reference
@molecule/api-bonds-default-express — default API bond wirings and
shared route/handler plumbing for Express-based apps.
Two halves:
setup<Name>()bond wirings (40+): one function per default provider (setupConfigEnv,setupDatabasePostgresql,setupJwtJsonwebtoken,setupEmailsMailgun,setupUploadsS3,setupRealtimeSocketio,setupAiAnthropic, …) so per-appapi/src/bonds/<name>.tsfiles are 1-line re-exports andbonds/index.tsjust calls them in order.- Shared Express plumbing:
createBillingRouter(the fleet's Stripe billing endpoints), themountDefaultUserAuthRoutes/mountDefaultDeviceRoutes/ othermountDefault*Routeshelpers, handler guards (requireAuth,requireUser,requireOwnership,getUserId,validationError,internalError), zod param schemas,trackAuthEvent, and acreateMigratorre-export.
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
// api/src/bonds/index.ts — wire defaults at startup, then validate:
import { validateBonds } from '@molecule/api-bond'
import {
setupConfigEnv,
setupDatabasePostgresql,
setupEmailsMailgun,
setupJwtJsonwebtoken,
setupSecretsEnv,
} from '@molecule/api-bonds-default-express'
async function setupBonds(): Promise<void> {
setupConfigEnv()
setupSecretsEnv()
setupDatabasePostgresql()
setupJwtJsonwebtoken()
setupEmailsMailgun()
validateBonds()
}
// api/src/routes/billing.ts — the fleet-standard billing endpoints
// (POST /checkout, POST /cancel, GET /status, GET /tiers), mounted by
// the app router at /billing (the real file default-exports the router):
import { createBillingRouter } from '@molecule/api-bonds-default-express'
// Your app owns these (typically in api/src/tiers.ts):
interface AppLimits {
seats: number
}
const getPricingTiers = () => [] // your tiers, each with a stripePriceId + limits
const appPlanKeys = { free: 'free', pro: 'pro' }
const billingRouter = createBillingRouter<AppLimits>({
getPricingTiers,
planKeys: appPlanKeys,
})
Type
feature
Installation
npm install @molecule/api-bonds-default-express @molecule/api-ai-anthropic @molecule/api-ai-embeddings @molecule/api-ai-embeddings-openai @molecule/api-ai-openai @molecule/api-ai-speech @molecule/api-ai-speech-openai @molecule/api-ai-vector-store @molecule/api-ai-vector-store-pgvector @molecule/api-analytics @molecule/api-audit @molecule/api-audit-database @molecule/api-bond @molecule/api-cache @molecule/api-cache-memory @molecule/api-cache-redis @molecule/api-config @molecule/api-config-env @molecule/api-cron @molecule/api-cron-node-cron @molecule/api-database @molecule/api-database-pglite @molecule/api-database-postgresql @molecule/api-emails @molecule/api-emails-capture @molecule/api-emails-mailgun @molecule/api-encryption @molecule/api-encryption-aes @molecule/api-entitlements @molecule/api-error-tracking @molecule/api-error-tracking-console @molecule/api-error-tracking-sentry @molecule/api-geolocation @molecule/api-geolocation-google @molecule/api-geolocation-mapbox @molecule/api-geolocation-nominatim @molecule/api-http @molecule/api-http-fetch @molecule/api-i18n @molecule/api-image @molecule/api-image-sharp @molecule/api-import-export @molecule/api-import-export-csv @molecule/api-jwt @molecule/api-jwt-jsonwebtoken @molecule/api-logger @molecule/api-media-streaming @molecule/api-media-streaming-hls @molecule/api-middleware-body-parser @molecule/api-middleware-body-parser-express @molecule/api-middleware-cookie-parser @molecule/api-middleware-cookie-parser-express @molecule/api-middleware-cors @molecule/api-middleware-cors-express @molecule/api-middleware-validation @molecule/api-notifications-webhook @molecule/api-password @molecule/api-password-bcrypt @molecule/api-payments @molecule/api-payments-capture @molecule/api-payments-stripe @molecule/api-pdf @molecule/api-pdf-pdfkit @molecule/api-permissions @molecule/api-permissions-custom @molecule/api-push-capture @molecule/api-push-notifications @molecule/api-push-notifications-web-push @molecule/api-queue @molecule/api-queue-memory @molecule/api-queue-redis @molecule/api-rate-limit @molecule/api-rate-limit-memory @molecule/api-realtime @molecule/api-realtime-socketio @molecule/api-realtime-sse @molecule/api-realtime-ws @molecule/api-reporting @molecule/api-reporting-database @molecule/api-resource @molecule/api-resource-device @molecule/api-resource-payment @molecule/api-resource-user @molecule/api-search @molecule/api-search-meilisearch @molecule/api-search-postgres @molecule/api-secrets @molecule/api-secrets-env @molecule/api-server-default-express @molecule/api-two-factor @molecule/api-two-factor-otplib @molecule/api-uploads @molecule/api-uploads-filesystem @molecule/api-uploads-s3 @molecule/api-webhook @molecule/api-webhook-http @molecule/api-workflow @molecule/api-workflow-database express zod
npm install -D @types/express
API
Types
AuthzResult
Result of an ownership check. ok: true carries the resolved row;
ok: false carries the HTTP status the handler should return —
always 404 to avoid leaking row existence to non-owners (the
"no IDOR" rule).
type AuthzResult<T> = { ok: true; row: T } | { ok: false; status: 404 }
Functions
createMigrator(migrationsDir)
Returns a runMigrations() function bound to the given directory.
function createMigrator(migrationsDir: string): () => Promise<void>
migrationsDir— Absolute path to the directory containing ordered*.sqlmigration files. Resolve viajoin(new URL('.', import.meta.url).pathname, '../../migrations')from the app'sscripts/migrate.ts.
Returns: A no-arg runMigrations() that creates the database (if missing) and applies every migration file in lexical order.
createBillingRouter(opts)
Factory for the default billing router. The router exposes four
endpoints: POST /checkout, POST /cancel, GET /status, GET /tiers.
function createBillingRouter(opts: {
getPricingTiers: () => ReadonlyArray<PricingTier>
planKeys: { free: string } & Record<string, string>
}): Router
getUserId(res)
Read the JWT session userId off res.locals.session. Returns null
when there is no session (the auth middleware never ran, or the
request is unauthenticated).
function getUserId(res: Response<any, Record<string, any>>): string | null
requireUser(res)
Like getUserId but writes a 401 + returns null when there's no
session. Use at the top of handler bodies to bail early:
const userId = requireUser(res)
if (!userId) return
function requireUser(res: Response<any, Record<string, any>>): string | null
getParamId(req, name?)
Read a route param as a string, defending against the Express
type union string | string[] (multi-value when the same param
key appears more than once). Defaults to 'id'.
function getParamId(
req: Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>,
name?: string,
): string
requireOwnership(table, id, userId)
Look up a row by id and verify the caller owns it via owner_id.
Returns the row on success, 404 when missing OR owned by a different
user (so attackers can't probe row existence).
function requireOwnership(table: string, id: string, userId: string): Promise<AuthzResult<T>>
requireUserOwnership(table, id, userId)
Variant of requireOwnership for tables that scope by user_id
instead of owner_id (notifications, user-bound preferences, etc.).
function requireUserOwnership(table: string, id: string, userId: string): Promise<AuthzResult<T>>
requireAuth(_req, res, next)
Express middleware that 401s any request lacking res.locals.session.userId.
Drop-in for the fleet's 51 inline requireAuth copies.
function requireAuth(
_req: Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>,
res: Response<any, Record<string, any>>,
next: NextFunction,
): void
validationError(res, issues)
Standard 400 response for zod / schema validation failures.
Used by ~21 fleet apps' api/src/lib/authz.ts files.
function validationError(res: Response<any, Record<string, any>>, issues: unknown): void
internalError(res, error?)
Standard 500 response that logs the underlying cause before responding with a generic message. Always pass the original error so silent catches don't ship to prod under green tests.
function internalError(res: Response<any, Record<string, any>>, error?: unknown): void
trackAuthEvent(eventName)
Emits an analytics event AND a log entry for an auth-related mutation (signup, login, password reset, plan change, etc.). Logs at info on success and warn on auth failure (4xx) so security signal is captured.
Replaces the per-app api/src/middleware/auth-analytics.ts shipped
by 10 fleet apps.
function trackAuthEvent(
eventName: string,
): RequestHandler<ParamsDictionary, any, any, ParsedQs, Record<string, any>>
createMigratorPglite(migrationsDir, extraDirs)
Returns a runMigrations() that applies every *.sql file in
migrationsDir, in lexical order, to @molecule/api-database-pglite's
default pool — the pool setupDatabasePglite() bonds, so the schema
lands in the database the app queries (an in-memory PGlite database exists
only inside that one instance). Same files and same "already exists is a
warning, anything else fails the boot" contract as createMigrator; there
is no CREATE DATABASE step.
Further directories run after it, each in its own lexical order — e.g. a
scaffolded app's __setup__/ (resource-package DDL such as payments.sql)
after migrations/, the order the scaffolded Postgres runner uses. A
directory that does not exist counts as empty.
function createMigratorPglite(migrationsDir: string, extraDirs?: string[]): () => Promise<void>
migrationsDir— Absolute path to the app'smigrations/directory.extraDirs— Absolute paths of further*.sqldirectories to apply after it, in order.
Returns: A no-arg migration runner.
mountDefaultDeviceRoutes(router, device)
Mounts the standard device routes:
GET /devices/push/public-key(public — the VAPID public key browsers need forpushManager.subscribe({ applicationServerKey }); bond-gated 404/503 when no push provider is bonded/configured)GET /devices(auth+query)GET /devices/:id(authUser+read)PATCH /devices/:id(authUser+update)DELETE /devices/:id(authUser+del)
function mountDefaultDeviceRoutes(router: Router, device: DeviceRequestHandlerMap): void
mountDefaultUserAuthRoutes(router, user)
Mounts the public auth endpoints:
POST /users(create)POST /users/log-in(rateLimitAuth + logIn)POST /users/forgot-password(rateLimitAuth + forgotPassword)
The credential-bearing routes are fronted by user.rateLimitAuth — the
default IP+account brute-force throttle from @molecule/api-resource-user —
so generated apps are not left with unthrottled password / TOTP-via-login
guessing. The limiter degrades open (logs a warning) when no rate-limit
provider is bonded, so apps that opt out still boot.
function mountDefaultUserAuthRoutes(router: Router, user: UserRequestHandlerMap): void
mountDefaultUserOAuthLoginRoute(router, user)
Optional OAuth routes — BOTH halves of the flow:
GET /users/oauth/:provider(rateLimitAuth + oauthAuthorize) — initiation: sets the CSRFoauth_state+ PKCEoauth_verifierhttpOnly cookies and 302-redirects to the bonded provider's authorization URL. Without this half the state cookielogInOAuthvalidates is never set, so every callback fails 403 (this is exactly how the generated-app fleet shipped an exchange endpoint with no way to start the dance). The GET carries the samerateLimitAuththrottle as the POST: it has no body, so only the generous per-IP bucket applies — an abuse ceiling on cookie-mint/ redirect flooding that a legitimate login (one GET + one POST) never approaches. A trip is a 429 JSON on a top-level navigation, which is acceptable for that ceiling.POST /users/log-in/oauth(rateLimitAuth + logInOAuth) — callback exchange: verifies state + code with the bonded provider and logs the user in.
Only mount when the app wires an oauth bond. Handlers check the bond registry at request time, so an unbonded provider yields a clean 404.
function mountDefaultUserOAuthLoginRoute(router: Router, user: UserRequestHandlerMap): void
mountDefaultUserResetPasswordRoute(router, user)
Optional reset-password route: POST /users/reset-password (rateLimitAuth +
resetPassword). Only mount when the app uses the pkg's resetPassword handler
rather than a custom local handler.
function mountDefaultUserResetPasswordRoute(router: Router, user: UserRequestHandlerMap): void
mountDefaultUserCrudRoutes(router, user)
Mounts the authed-self user CRUD routes:
GET /users/me(auth+readSelf) — session restore; MUST precede/users/:idGET /users/:id(authSelf+read)PATCH /users/:id(authSelf+update)DELETE /users/:id(authSelf+del)
function mountDefaultUserCrudRoutes(router: Router, user: UserRequestHandlerMap): void
mountDefaultUserSecurityRoutes(router, user)
Mounts password + 2FA security routes:
PATCH /users/:id/password(authSelf+updatePassword)POST /users/:id/verify-two-factor(authSelf + rateLimitTwoFactor + verifyTwoFactor)
The 2FA verification route carries a stricter limiter (user.rateLimitTwoFactor)
that temp-locks the second factor per account after consecutive misses.
function mountDefaultUserSecurityRoutes(router: Router, user: UserRequestHandlerMap): void
mountDefaultUserBillingRoutes(router, user)
Mounts plan/billing routes:
PATCH /users/:id/plan(authSelf+updatePlan)POST /users/payment-notification/:provider(requireWebhookAuthenticity+handlePaymentNotification)
The notification route is public (providers POST to it), so it is gated by
requireWebhookAuthenticity: signature-verifying webhook providers (Stripe)
pass through, while unsigned server-to-server providers (Apple/Google) require
a shared secret — the endpoint is not open by default.
function mountDefaultUserBillingRoutes(router: Router, user: UserRequestHandlerMap): void
mountDefaultUserVerifyPaymentRoutes(router, user)
Optional payment-verification routes for apps that support client-driven payment confirmation (Apple/Google receipt verify).
Both verbs require authSelf ([M3-1]): the handler mutates and returns the
:id user, so an unauthenticated / cross-user call must not reach it. The
permissive global verifyMiddleware() never blocks, so per-route authSelf
is the gate. authSelf does NOT break the Stripe Checkout success_url
callback — that is a top-level browser navigation which carries the
sameSite:'lax' session cookie — and in-handler customer/checkout-session
binding remains as defense-in-depth. This mirrors the hardened declarative
route table (resources/user/src/routes.ts) and molecule-dev's live router;
the fix had not been propagated to this mounter, which the generated-app
fleet uses.
GET /users/:id/verify-payment/:provider(authSelf+verifyPayment)POST /users/:id/verify-payment/:provider(authSelf+verifyPayment)
function mountDefaultUserVerifyPaymentRoutes(router: Router, user: UserRequestHandlerMap): void
setupConfigEnv()
Wires @molecule/api-config-env to @molecule/api-config.
function setupConfigEnv(): void
setupDatabasePostgresql()
Wires @molecule/api-database-postgresql to @molecule/api-database.
function setupDatabasePostgresql(): void
setupDatabasePglite()
Wires @molecule/api-database-pglite (real Postgres compiled to
WebAssembly, in-process) to @molecule/api-database — the database half of
the zero-server "browser" profile. Same SQL, placeholders and error codes as
the postgresql bond, so app code and migrations do not change.
Binds the pglite package's DEFAULT pool, whose data directory comes from
PGLITE_DATA_DIR (memory://, idb://<name>, or a filesystem path; the
bond's Node default is ./data/pglite). Run migrations with
createMigratorPglite, which targets the same default pool — an
in-memory database exists only inside that one instance, so the migrator
and the app must share it.
@molecule/api-database-pglite is an OPTIONAL peer, imported lazily, so a
postgres-only app never needs it installed.
function setupDatabasePglite(): Promise<void>
setupJwtJsonwebtoken()
Wires @molecule/api-jwt-jsonwebtoken to @molecule/api-jwt.
function setupJwtJsonwebtoken(): void
setupMiddlewareBodyParserExpress()
Wires @molecule/api-middleware-body-parser-express to @molecule/api-middleware-body-parser.
function setupMiddlewareBodyParserExpress(): void
setupMiddlewareCookieParserExpress()
Wires @molecule/api-middleware-cookie-parser-express to @molecule/api-middleware-cookie-parser.
function setupMiddlewareCookieParserExpress(): void
setupMiddlewareCorsExpress()
Wires @molecule/api-middleware-cors-express to @molecule/api-middleware-cors.
function setupMiddlewareCorsExpress(): void
setupPasswordBcrypt()
Wires @molecule/api-password-bcrypt to @molecule/api-password.
function setupPasswordBcrypt(): void
setupSecretsEnv()
Wires @molecule/api-secrets-env to @molecule/api-secrets.
function setupSecretsEnv(): void
setupServiceDevice()
Registers the device service from @molecule/api-resource-device on the bond system.
function setupServiceDevice(): void
setupTwoFactorOtplib()
Wires @molecule/api-two-factor-otplib to @molecule/api-two-factor.
function setupTwoFactorOtplib(): void
setupEmailsMailgun()
Wires @molecule/api-emails-mailgun to @molecule/api-emails.
function setupEmailsMailgun(): void
setupEmailsCapture()
Wires @molecule/api-emails-capture to @molecule/api-emails
unconditionally — every message is captured in memory instead of sent.
Unlike setupEmailsMailgun's development fallback, this does not
depend on NODE_ENV or on which env vars are missing, so a profile that
selects it always gets it.
function setupEmailsCapture(): void
setupPaymentsStripe()
Registers @molecule/api-payments-stripe as a named 'stripe' payments provider.
function setupPaymentsStripe(): void
setupPaymentsCapture()
Registers @molecule/api-payments-capture (a payments vendor simulated in
memory: checkouts complete at once, signed local webhooks) under the name
'stripe' — the name setupPaymentsStripe uses — so the billing
router, the /users/:id/verify-payment/stripe and
/users/payment-notification/stripe routes, and the plan catalogue's
platformKey work unchanged. Grants plans without taking money: bond it in
a development / browser profile only, never in production.
@molecule/api-payments-capture is an OPTIONAL peer, imported lazily.
function setupPaymentsCapture(): Promise<void>
setupServicePayment()
Registers the plan + paymentRecord services from @molecule/api-resource-payment.
function setupServicePayment(): void
setupSearchMeilisearch()
Wires @molecule/api-search-meilisearch to @molecule/api-search.
function setupSearchMeilisearch(): void
setupUploadsS3()
Wires @molecule/api-uploads-s3 to @molecule/api-uploads.
function setupUploadsS3(): void
setupImageSharp()
Wires @molecule/api-image-sharp to @molecule/api-image.
function setupImageSharp(): Promise<void>
setupPermissionsCustom()
Wires @molecule/api-permissions-custom to @molecule/api-permissions.
function setupPermissionsCustom(): Promise<void>
setupReportingDatabase()
Wires @molecule/api-reporting-database to @molecule/api-reporting.
function setupReportingDatabase(): Promise<void>
setupRealtimeSocketio()
Wires @molecule/api-realtime-socketio to @molecule/api-realtime.
function setupRealtimeSocketio(): Promise<void>
setupRealtimeWs()
Wires @molecule/api-realtime-ws to @molecule/api-realtime.
function setupRealtimeWs(): Promise<void>
setupRealtimeSse()
Wires @molecule/api-realtime-sse to @molecule/api-realtime.
function setupRealtimeSse(): Promise<void>
setupCronNodeCron()
Wires @molecule/api-cron-node-cron to @molecule/api-cron.
function setupCronNodeCron(): Promise<void>
setupEncryptionAes()
Wires @molecule/api-encryption-aes to @molecule/api-encryption.
function setupEncryptionAes(): Promise<void>
setupPushNotificationsWebPush()
Wires @molecule/api-push-notifications-web-push to @molecule/api-push-notifications.
function setupPushNotificationsWebPush(): Promise<void>
setupImportExportCsv()
Wires @molecule/api-import-export-csv to @molecule/api-import-export.
function setupImportExportCsv(): Promise<void>
setupAiAnthropic()
Registers @molecule/api-ai-anthropic as a named 'anthropic' AI provider.
function setupAiAnthropic(): Promise<void>
setupAuditDatabase()
Wires @molecule/api-audit-database to @molecule/api-audit.
function setupAuditDatabase(): Promise<void>
setupPdfPdfkit()
Wires @molecule/api-pdf-pdfkit to @molecule/api-pdf.
function setupPdfPdfkit(): Promise<void>
setupApiAnalyticsDefault()
Wires a no-op default analytics provider so @molecule/api-analytics calls succeed.
function setupApiAnalyticsDefault(): Promise<void>
setupGeolocationMapbox()
Wires @molecule/api-geolocation-mapbox to @molecule/api-geolocation.
function setupGeolocationMapbox(): Promise<void>
setupErrorTrackingSentry()
Wires @molecule/api-error-tracking-sentry to @molecule/api-error-tracking.
Safe to wire unconditionally: without SENTRY_DSN the Sentry provider is a
documented no-op (the boot config report flags the missing key), so an app
that hasn't configured Sentry yet boots and runs untouched.
function setupErrorTrackingSentry(): Promise<void>
setupErrorTrackingConsole()
Wires @molecule/api-error-tracking-console to @molecule/api-error-tracking.
Zero-credential development default: captures are logged as structured lines through the bonded logger instead of being sent to a remote service.
function setupErrorTrackingConsole(): Promise<void>
setupCacheRedis()
Wires @molecule/api-cache-redis to @molecule/api-cache.
function setupCacheRedis(): Promise<void>
setupQueueMemory()
Wires @molecule/api-queue-memory to @molecule/api-queue — the
zero-credential in-process queue (single-process/dev; swap to
redis/rabbitmq/sqs for multi-instance production).
function setupQueueMemory(): Promise<void>
setupQueueRedis()
Wires @molecule/api-queue-redis to @molecule/api-queue. Outside
production, when REDIS_URL is absent, falls back to
@molecule/api-queue-memory — the zero-credential in-process queue — so
queue-backed features (background jobs, async delivery workers) run out of
the box, mirroring setupCacheRedis.
function setupQueueRedis(): Promise<void>
setupAiOpenai()
Registers @molecule/api-ai-openai as a named 'openai' AI provider.
function setupAiOpenai(): Promise<void>
setupAiEmbeddingsOpenai()
Wires @molecule/api-ai-embeddings-openai to @molecule/api-ai-embeddings.
function setupAiEmbeddingsOpenai(): Promise<void>
setupWebhookHttp()
Wires @molecule/api-webhook-http to @molecule/api-webhook.
function setupWebhookHttp(): Promise<void>
setupAiVectorStorePgvector()
Wires @molecule/api-ai-vector-store-pgvector to @molecule/api-ai-vector-store.
function setupAiVectorStorePgvector(): Promise<void>
setupAiSpeechOpenai()
Wires @molecule/api-ai-speech-openai to @molecule/api-ai-speech.
function setupAiSpeechOpenai(): Promise<void>
setupWorkflowDatabase()
Wires @molecule/api-workflow-database to @molecule/api-workflow.
function setupWorkflowDatabase(): Promise<void>
setupHttpFetch()
Wires @molecule/api-http-fetch to @molecule/api-http.
function setupHttpFetch(): Promise<void>
setupNotificationsWebhook()
Registers @molecule/api-notifications-webhook as a named 'webhook' notifications provider.
function setupNotificationsWebhook(): Promise<void>
setupGeolocationGoogle()
Wires @molecule/api-geolocation-google to @molecule/api-geolocation.
function setupGeolocationGoogle(): Promise<void>
setupMediaStreamingHls()
Wires @molecule/api-media-streaming-hls to @molecule/api-media-streaming.
function setupMediaStreamingHls(): Promise<void>
setupRateLimitMemory()
Wires @molecule/api-rate-limit-memory to @molecule/api-rate-limit.
This is the default brute-force-protection backend for mlcl-generated apps
(single-instance). Multi-instance deployments should swap in
@molecule/api-rate-limit-redis so the throttle is shared across replicas.
function setupRateLimitMemory(): Promise<void>
Constants
userRequestHandlerMap
Pre-wired request handler map for @molecule/api-resource-user.
const userRequestHandlerMap: UserRequestHandlerMap
deviceRequestHandlerMap
Pre-wired request handler map for @molecule/api-resource-device.
const deviceRequestHandlerMap: DeviceRequestHandlerMap
idParamSchema
Standard route-param schema for :id. Accepts any non-empty string.
Pair with validateParams(idParamSchema).
const idParamSchema: z.ZodObject<{ id: z.ZodString }, z.core.$strip>
uuidParamSchema
Strict variant of idParamSchema that requires a UUID. Use when the
underlying column is a uuid.
const uuidParamSchema: z.ZodObject<{ id: z.ZodString }, z.core.$strip>
deviceService
DeviceService implementation for the bond system.
Provides device CRUD operations that other resources
can use through get('device') / require('device').
const deviceService: DeviceService
Namespaces
userAuthorization
Injection Notes
Requirements
Peer dependencies:
@molecule/api-ai-anthropic^1.0.1@molecule/api-ai-embeddings^1.0.1@molecule/api-ai-embeddings-openai^1.0.1@molecule/api-ai-openai^1.0.1@molecule/api-ai-speech^1.0.1@molecule/api-ai-speech-openai^1.0.1@molecule/api-ai-vector-store^1.0.1@molecule/api-ai-vector-store-pgvector^1.0.1@molecule/api-analytics^1.0.1@molecule/api-audit^1.0.1@molecule/api-audit-database^1.0.1@molecule/api-bond^1.0.1@molecule/api-cache^1.0.1@molecule/api-cache-memory^1.0.1@molecule/api-cache-redis^1.0.1@molecule/api-config^1.0.1@molecule/api-config-env^1.0.1@molecule/api-cron^1.0.1@molecule/api-cron-node-cron^1.0.1@molecule/api-database^1.0.1@molecule/api-database-pglite^1.0.0@molecule/api-database-postgresql^1.0.1@molecule/api-emails^1.0.1@molecule/api-emails-capture^1.0.1@molecule/api-emails-mailgun^1.0.1@molecule/api-encryption^1.0.1@molecule/api-encryption-aes^1.0.1@molecule/api-entitlements^1.0.1@molecule/api-error-tracking^1.0.1@molecule/api-error-tracking-console^1.0.1@molecule/api-error-tracking-sentry^1.0.1@molecule/api-geolocation^1.0.1@molecule/api-geolocation-google^1.0.1@molecule/api-geolocation-mapbox^1.0.1@molecule/api-geolocation-nominatim^1.0.1@molecule/api-http^1.0.1@molecule/api-http-fetch^1.0.1@molecule/api-i18n^1.0.1@molecule/api-image^1.0.1@molecule/api-image-sharp^1.0.1@molecule/api-import-export^1.0.1@molecule/api-import-export-csv^1.0.1@molecule/api-jwt^1.0.1@molecule/api-jwt-jsonwebtoken^1.0.1@molecule/api-logger^1.0.1@molecule/api-media-streaming^1.0.1@molecule/api-media-streaming-hls^1.0.1@molecule/api-middleware-body-parser^1.0.1@molecule/api-middleware-body-parser-express^1.0.1@molecule/api-middleware-cookie-parser^1.0.1@molecule/api-middleware-cookie-parser-express^1.0.1@molecule/api-middleware-cors^1.0.1@molecule/api-middleware-cors-express^1.0.1@molecule/api-middleware-validation^1.0.1@molecule/api-notifications-webhook^1.0.1@molecule/api-password^1.0.1@molecule/api-password-bcrypt^1.0.1@molecule/api-payments^1.0.1@molecule/api-payments-capture^1.0.0@molecule/api-payments-stripe^1.0.1@molecule/api-pdf^1.0.1@molecule/api-pdf-pdfkit^1.0.1@molecule/api-permissions^1.0.1@molecule/api-permissions-custom^1.0.1@molecule/api-push-capture^1.0.1@molecule/api-push-notifications^1.0.1@molecule/api-push-notifications-web-push^1.0.1@molecule/api-queue^1.0.1@molecule/api-queue-memory^1.0.1@molecule/api-queue-redis^1.0.1@molecule/api-rate-limit^1.0.1@molecule/api-rate-limit-memory^1.0.1@molecule/api-realtime^1.0.1@molecule/api-realtime-socketio^1.0.1@molecule/api-realtime-sse^1.0.1@molecule/api-realtime-ws^1.0.1@molecule/api-reporting^1.0.1@molecule/api-reporting-database^1.0.1@molecule/api-resource^1.0.1@molecule/api-resource-device^1.0.1@molecule/api-resource-payment^1.0.1@molecule/api-resource-user^1.0.1@molecule/api-search^1.0.1@molecule/api-search-meilisearch^1.0.1@molecule/api-search-postgres^1.0.1@molecule/api-secrets^1.0.1@molecule/api-secrets-env^1.0.1@molecule/api-server-default-express^1.0.1@molecule/api-two-factor^1.0.1@molecule/api-two-factor-otplib^1.0.1@molecule/api-uploads^1.0.1@molecule/api-uploads-filesystem^1.0.1@molecule/api-uploads-s3^1.0.1@molecule/api-webhook^1.0.1@molecule/api-webhook-http^1.0.1@molecule/api-workflow^1.0.1@molecule/api-workflow-database^1.0.1express^4.0.0 || ^5.0.0
Runtime Dependencies
-
@molecule/api-ai-anthropic -
@molecule/api-ai-embeddings -
@molecule/api-ai-embeddings-openai -
@molecule/api-ai-openai -
@molecule/api-ai-speech -
@molecule/api-ai-speech-openai -
@molecule/api-ai-vector-store -
@molecule/api-ai-vector-store-pgvector -
@molecule/api-analytics -
@molecule/api-audit -
@molecule/api-audit-database -
@molecule/api-bond -
@molecule/api-cache -
@molecule/api-cache-memory -
@molecule/api-cache-redis -
@molecule/api-config -
@molecule/api-config-env -
@molecule/api-cron -
@molecule/api-cron-node-cron -
@molecule/api-database -
@molecule/api-database-pglite -
@molecule/api-database-postgresql -
@molecule/api-emails -
@molecule/api-emails-capture -
@molecule/api-emails-mailgun -
@molecule/api-encryption -
@molecule/api-encryption-aes -
@molecule/api-entitlements -
@molecule/api-error-tracking -
@molecule/api-error-tracking-console -
@molecule/api-error-tracking-sentry -
@molecule/api-geolocation -
@molecule/api-geolocation-google -
@molecule/api-geolocation-mapbox -
@molecule/api-geolocation-nominatim -
@molecule/api-http -
@molecule/api-http-fetch -
@molecule/api-i18n -
@molecule/api-image -
@molecule/api-image-sharp -
@molecule/api-import-export -
@molecule/api-import-export-csv -
@molecule/api-jwt -
@molecule/api-jwt-jsonwebtoken -
@molecule/api-logger -
@molecule/api-media-streaming -
@molecule/api-media-streaming-hls -
@molecule/api-middleware-body-parser -
@molecule/api-middleware-body-parser-express -
@molecule/api-middleware-cookie-parser -
@molecule/api-middleware-cookie-parser-express -
@molecule/api-middleware-cors -
@molecule/api-middleware-cors-express -
@molecule/api-middleware-validation -
@molecule/api-notifications-webhook -
@molecule/api-password -
@molecule/api-password-bcrypt -
@molecule/api-payments -
@molecule/api-payments-capture -
@molecule/api-payments-stripe -
@molecule/api-pdf -
@molecule/api-pdf-pdfkit -
@molecule/api-permissions -
@molecule/api-permissions-custom -
@molecule/api-push-capture -
@molecule/api-push-notifications -
@molecule/api-push-notifications-web-push -
@molecule/api-queue -
@molecule/api-queue-memory -
@molecule/api-queue-redis -
@molecule/api-rate-limit -
@molecule/api-rate-limit-memory -
@molecule/api-realtime -
@molecule/api-realtime-socketio -
@molecule/api-realtime-sse -
@molecule/api-realtime-ws -
@molecule/api-reporting -
@molecule/api-reporting-database -
@molecule/api-resource -
@molecule/api-resource-device -
@molecule/api-resource-payment -
@molecule/api-resource-user -
@molecule/api-search -
@molecule/api-search-meilisearch -
@molecule/api-search-postgres -
@molecule/api-secrets -
@molecule/api-secrets-env -
@molecule/api-server-default-express -
@molecule/api-two-factor -
@molecule/api-two-factor-otplib -
@molecule/api-uploads -
@molecule/api-uploads-filesystem -
@molecule/api-uploads-s3 -
@molecule/api-webhook -
@molecule/api-webhook-http -
@molecule/api-workflow -
@molecule/api-workflow-database -
express -
zod -
Development falls back to zero-credential providers; production never does. When
NODE_ENV !== 'production'and a provider's required env is missing, the setup wires the capture/local sibling instead and logs the swap: mailgun→emails-capture (MAILGUN_API_KEY/MAILGUN_DOMAIN), uploads-s3→uploads-filesystem (AWS_*), search-meilisearch→ search-postgres (MEILISEARCH_URL), web-push→push-capture (VAPID_*), geolocation-mapbox→nominatim (MAPBOX_ACCESS_TOKEN), cache-redis→cache-memory (REDIS_URL). In production the credentialed provider is wired regardless — missing env surfaces as loud, actionable 503s and boot-report entries, never a silent provider swap. So "emails don't arrive in dev" usually means they were CAPTURED (read them via the activity/capture tooling), not lost. -
Realtime setups (
setupRealtimeSocketio,setupRealtimeWs,setupRealtimeSse) all defer-attach. Each dynamic-imports its provider'screateProvider({ deferAttach: true }), callssetProvider(), thenregisterServerCreatedHook((server) => provider.attachHttpServer?.(server))from@molecule/api-server-default-express— so the realtime transport shares the API's HTTP server/port once it exists, instead of a standalone port a containerized sandbox / proxied deploy may not expose. Add new realtime bonds by mirroring this pattern exactly. -
createBillingRouterregisters the app's Stripe plan catalogue with@molecule/api-resource-paymentat construction AND re-registers per checkout (price-id env vars may resolve after startup); webhook handling stays with@molecule/api-resource-user'shandlePaymentNotification. A paid price whoseplanKeysentry is missing is skipped WITH a warning — that plan could never be granted. -
Only wire the setups whose packages your app actually installed — each one imports its provider package (several lazily via dynamic import), so calling a setup for an uninstalled bond fails at that import.