← All @molecule/* packages · App templates

@molecule/api-bonds-default-express

Feature · bonds-default · API (Node) · v1.0.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-express

npm · Source on GitHub

How 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-two-factor, @molecule/api-two-factor-otplib, @molecule/api-uploads, @molecule/api-uploads-filesystem, @molecule/api-uploads-s3

Reference

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.ts JSDoc, not this file.

@molecule/api-bonds-default-express — default API bond wirings and shared route/handler plumbing for Express-based apps.

Two halves:

  1. setup<Name>() bond wirings (40+): one function per default provider (setupConfigEnv, setupDatabasePostgresql, setupJwtJsonwebtoken, setupEmailsMailgun, setupUploadsS3, setupRealtimeSocketio, setupAiAnthropic, …) so per-app api/src/bonds/<name>.ts files are 1-line re-exports and bonds/index.ts just calls them in order.
  2. Shared Express plumbing: createBillingRouter (the fleet's Stripe billing endpoints), the mountDefaultUserAuthRoutes / mountDefaultDeviceRoutes / other mountDefault*Routes helpers, handler guards (requireAuth, requireUser, requireOwnership, getUserId, validationError, internalError), zod param schemas, trackAuthEvent, and a createMigrator re-export.

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-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-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-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

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

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

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 *.sql migration files. Resolve via join(new URL('.', import.meta.url).pathname, '../../migrations') from the app's scripts/migrate.ts.

Returns: A no-arg runMigrations() that creates the database (if missing) and applies every migration file in lexical order.

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

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

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

mountDefaultDeviceRoutes(router, device)

Mounts the standard device routes:

  • GET /devices/push/public-key (public — the VAPID public key browsers need for pushManager.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

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

mountDefaultUserCrudRoutes(router, user)

Mounts the authed-self user CRUD routes:

  • GET /users/me (auth+readSelf) — session restore; MUST precede /users/:id
  • GET /users/:id (authSelf+read)
  • PATCH /users/:id (authSelf+update)
  • DELETE /users/:id (authSelf+del)
function mountDefaultUserCrudRoutes(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 CSRF oauth_state + PKCE oauth_verifier httpOnly cookies and 302-redirects to the bonded provider's authorization URL. Without this half the state cookie logInOAuth validates 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 same rateLimitAuth throttle 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

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

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

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

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>>

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

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>>

setupAiAnthropic()

Registers @molecule/api-ai-anthropic as a named 'anthropic' AI provider.

function setupAiAnthropic(): Promise<void>

setupAiEmbeddingsOpenai()

Wires @molecule/api-ai-embeddings-openai to @molecule/api-ai-embeddings.

function setupAiEmbeddingsOpenai(): Promise<void>

setupAiOpenai()

Registers @molecule/api-ai-openai as a named 'openai' AI provider.

function setupAiOpenai(): Promise<void>

setupAiSpeechOpenai()

Wires @molecule/api-ai-speech-openai to @molecule/api-ai-speech.

function setupAiSpeechOpenai(): Promise<void>

setupAiVectorStorePgvector()

Wires @molecule/api-ai-vector-store-pgvector to @molecule/api-ai-vector-store.

function setupAiVectorStorePgvector(): Promise<void>

setupApiAnalyticsDefault()

Wires a no-op default analytics provider so @molecule/api-analytics calls succeed.

function setupApiAnalyticsDefault(): Promise<void>

setupAuditDatabase()

Wires @molecule/api-audit-database to @molecule/api-audit.

function setupAuditDatabase(): Promise<void>

setupCacheRedis()

Wires @molecule/api-cache-redis to @molecule/api-cache.

function setupCacheRedis(): Promise<void>

setupConfigEnv()

Wires @molecule/api-config-env to @molecule/api-config.

function setupConfigEnv(): void

setupCronNodeCron()

Wires @molecule/api-cron-node-cron to @molecule/api-cron.

function setupCronNodeCron(): Promise<void>

setupDatabasePostgresql()

Wires @molecule/api-database-postgresql to @molecule/api-database.

function setupDatabasePostgresql(): void

setupEmailsMailgun()

Wires @molecule/api-emails-mailgun to @molecule/api-emails.

function setupEmailsMailgun(): void

setupEncryptionAes()

Wires @molecule/api-encryption-aes to @molecule/api-encryption.

function setupEncryptionAes(): 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>

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>

setupGeolocationGoogle()

Wires @molecule/api-geolocation-google to @molecule/api-geolocation.

function setupGeolocationGoogle(): Promise<void>

setupGeolocationMapbox()

Wires @molecule/api-geolocation-mapbox to @molecule/api-geolocation.

function setupGeolocationMapbox(): Promise<void>

setupHttpFetch()

Wires @molecule/api-http-fetch to @molecule/api-http.

function setupHttpFetch(): Promise<void>

setupImageSharp()

Wires @molecule/api-image-sharp to @molecule/api-image.

function setupImageSharp(): Promise<void>

setupImportExportCsv()

Wires @molecule/api-import-export-csv to @molecule/api-import-export.

function setupImportExportCsv(): Promise<void>

setupJwtJsonwebtoken()

Wires @molecule/api-jwt-jsonwebtoken to @molecule/api-jwt.

function setupJwtJsonwebtoken(): void

setupMediaStreamingHls()

Wires @molecule/api-media-streaming-hls to @molecule/api-media-streaming.

function setupMediaStreamingHls(): Promise<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

setupNotificationsWebhook()

Registers @molecule/api-notifications-webhook as a named 'webhook' notifications provider.

function setupNotificationsWebhook(): Promise<void>

setupPasswordBcrypt()

Wires @molecule/api-password-bcrypt to @molecule/api-password.

function setupPasswordBcrypt(): void

setupPaymentsStripe()

Registers @molecule/api-payments-stripe as a named 'stripe' payments provider.

function setupPaymentsStripe(): void

setupPdfPdfkit()

Wires @molecule/api-pdf-pdfkit to @molecule/api-pdf.

function setupPdfPdfkit(): Promise<void>

setupPermissionsCustom()

Wires @molecule/api-permissions-custom to @molecule/api-permissions.

function setupPermissionsCustom(): Promise<void>

setupPushNotificationsWebPush()

Wires @molecule/api-push-notifications-web-push to @molecule/api-push-notifications.

function setupPushNotificationsWebPush(): 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>

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>

setupRealtimeSocketio()

Wires @molecule/api-realtime-socketio to @molecule/api-realtime.

function setupRealtimeSocketio(): Promise<void>

setupRealtimeSse()

Wires @molecule/api-realtime-sse to @molecule/api-realtime.

function setupRealtimeSse(): Promise<void>

setupRealtimeWs()

Wires @molecule/api-realtime-ws to @molecule/api-realtime.

function setupRealtimeWs(): Promise<void>

setupReportingDatabase()

Wires @molecule/api-reporting-database to @molecule/api-reporting.

function setupReportingDatabase(): Promise<void>

setupSearchMeilisearch()

Wires @molecule/api-search-meilisearch to @molecule/api-search.

function setupSearchMeilisearch(): 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

setupServicePayment()

Registers the plan + paymentRecord services from @molecule/api-resource-payment.

function setupServicePayment(): void

setupTwoFactorOtplib()

Wires @molecule/api-two-factor-otplib to @molecule/api-two-factor.

function setupTwoFactorOtplib(): void

setupUploadsS3()

Wires @molecule/api-uploads-s3 to @molecule/api-uploads.

function setupUploadsS3(): void

setupWebhookHttp()

Wires @molecule/api-webhook-http to @molecule/api-webhook.

function setupWebhookHttp(): Promise<void>

setupWorkflowDatabase()

Wires @molecule/api-workflow-database to @molecule/api-workflow.

function setupWorkflowDatabase(): Promise<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>>

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

Constants

deviceRequestHandlerMap

Pre-wired request handler map for @molecule/api-resource-device.

const deviceRequestHandlerMap: DeviceRequestHandlerMap

deviceService

DeviceService implementation for the bond system.

Provides device CRUD operations that other resources can use through get('device') / require('device').

const deviceService: DeviceService

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>

userRequestHandlerMap

Pre-wired request handler map for @molecule/api-resource-user.

const userRequestHandlerMap: UserRequestHandlerMap

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>

Namespaces

userAuthorization

Members:

  • userAuthorization.getAuthCookieName — const: Resolve the actual cookie name for an auth cookie.
  • userAuthorization.getAuthCookieOptions — const: Base cookie attributes shared by EVERY auth cookie this resource sets and
  • userAuthorization.invalidateDeviceExistsCache — const: Evict a single device's positive entry from the device-exists cache so the
  • userAuthorization.invalidateAllDeviceExistsCache — const: Evict ALL positive entries from the device-exists cache.
  • userAuthorization.set — const: Set authorization headers and cookie for a session.
  • userAuthorization.VerifyMiddlewareOptions — interface: Options for {@link verifyMiddleware}.
  • userAuthorization.verifyMiddleware — const: Middleware that verifies the JWT token from the Authorization header and sets res.locals.session.

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-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-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-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.1

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-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-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-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

  • 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's createProvider({ deferAttach: true }), calls setProvider(), then registerServerCreatedHook((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.

  • createBillingRouter registers the app's Stripe plan catalogue with @molecule/api-resource-payment at construction AND re-registers per checkout (price-id env vars may resolve after startup); webhook handling stays with @molecule/api-resource-user's handlePaymentNotification. A paid price whose planKeys entry 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.