Skip to content

Configuration

The root configuration object passed to defineConfig().

import { defineConfig } from "@porulle/core";
export default defineConfig({ /* CommerceConfig */ });
FieldTypeDefaultDescription
storeNamestringDisplay name of the store
versionstring"0.0.1"Semantic version of the store configuration
databaseDatabaseConfigrequiredPrimary database connection
databaseAdapterDatabaseAdapterPre-built database adapter. When provided, bypasses database config.
authAuthConfigSee defaultsAuthentication and authorization settings
entitiesRecord<string, EntityConfig>Custom entity type definitions keyed by entity slug
cartCartConfigSee defaultsCart behavior and hooks
checkoutCheckoutConfigSee defaultsCheckout hooks
ordersOrdersConfigSee defaultsOrder lifecycle hooks
inventoryInventoryConfigSee defaultsInventory hooks
shippingShippingConfigShipping calculation strategy
paymentsPaymentAdapter[]Payment gateway adapters
storageStorageAdapterFile/media storage adapter
emailEmailAdapterTransactional email sender
taxTaxConfigTax calculation adapter and origin address
analyticsAnalyticsConfigAnalytics and reporting settings
searchSearchConfigSearch adapter and facet defaults
jobsJobsConfigBackground job processing
schemaArray<Record<string, unknown>>App-level Drizzle table definitions merged at boot. Must also add file paths to drizzle.config.ts.
hooksRecord<string, Array<Function>>Global hook functions keyed by hook name (e.g., "orders.afterCreate")
pluginsCommercePlugin[]Plugin config-transform functions, applied in array order
logLevel"fatal" | "error" | "warn" | "info" | "debug" | "trace""info"Pino log level
rateLimitsRateLimitsConfigSee defaultsPer-tier rate limiting thresholds (requests per minute)
middlewareMiddlewareHandler[]Hono middleware applied to all routes
routes(app: Hono, kernel: unknown) => voidCallback to register custom Hono routes. Cast kernel to Kernel to access services and database.

database: {
provider: "postgresql";
options?: Record<string, unknown>;
}
FieldTypeDefaultDescription
provider"postgresql"requiredDatabase provider. PostgreSQL is the only supported database.
optionsRecord<string, unknown>Provider-specific connection options

rateLimits: {
api?: number;
auth?: number;
checkout?: number;
}
FieldTypeDefaultDescription
apinumber100Max requests per minute for general API routes
authnumber10Max requests per minute for authentication endpoints
checkoutnumber5Max requests per minute for checkout creation

When a client exceeds the limit, the server responds with 429 Too Many Requests.


interface AuthConfig {
defaultOrganizationId?: string;
strictOrgResolution?: boolean;
storeResolver?: (request: Request) => string | null | Promise<string | null>;
requireEmailVerification?: boolean;
sessionDuration?: number;
socialProviders?: Record<string, { clientId: string; clientSecret: string }>;
twoFactor?: { enabled: boolean; requiredForRoles?: string[] };
apiKeys?: { enabled: boolean; defaultPermissions?: string[] };
roles?: Record<string, RoleDefinition>;
trustedOrigins?: string[];
enableDevKey?: boolean;
}
FieldTypeDefaultDescription
defaultOrganizationIdstringOrganization ID for single-store deployments. See Identity and Store Resolution.
strictOrgResolutionbooleanfalseWhen true, requests where storeResolver returns null are rejected with HTTP 503.
storeResolver(request: Request) => string | null | Promise<string | null>Resolves which organization a request belongs to in multi-store SaaS deployments.
requireEmailVerificationbooleantrueRequire email verification before account activation
sessionDurationnumber604800 (7 days, in seconds)Session lifetime in seconds
socialProvidersRecord<string, { clientId: string; clientSecret: string }>OAuth provider credentials keyed by provider name
twoFactor{ enabled: boolean; requiredForRoles?: string[] }{ enabled: false }Two-factor authentication settings
apiKeys{ enabled: boolean; defaultPermissions?: string[] }{ enabled: false }Enable API key authentication
rolesRecord<string, RoleDefinition>See belowRole definitions mapping role names to permission sets
trustedOriginsstring[]Origins allowed for CSRF protection
enableDevKeybooleantrue in dev, false in prodEnable the dev-staff-key API key. Set to false in production.
RolePermissions
owner*:*
admin*:*
managercatalog CRUD, inventory, orders, cart
customercatalog:read, cart, orders:read:own, customers:read:self, customers:update:self
interface RoleDefinition {
permissions: string[];
}

Permissions use "module:action" or "module:action:scope" format. "*:*" grants all.


interface EntityConfig {
fields: EntityFieldDefinition[];
variants: EntityVariantConfig;
fulfillment: string;
hooks?: EntityHooks;
}
FieldTypeDescription
fieldsEntityFieldDefinition[]Custom field definitions. The catalog service validates entity metadata against these on create/update.
variantsEntityVariantConfigVariant support configuration
fulfillmentstringFulfillment strategy: "physical", "digital", "digital-download", "digital-access"
hooksEntityHooksLifecycle hooks scoped to this entity type
FieldTypeDescription
namestringField identifier
type"text" | "number" | "boolean" | "date" | "json" | "relation" | "select"Data type
unitstringUnit of measurement (for "number" fields, e.g., "g", "ml")
schemaunknownValidation schema for the field value
targetstringTarget entity slug (for "relation" fields)
optionsstring[]Allowed values (for "select" fields)
FieldTypeDescription
enabledbooleanWhether this entity supports variants
optionTypesstring[]Variant option type names (e.g., ["size", "color"])

FieldTypeDefaultDescription
ttlMinutesnumber10080 (7 days)Cart time-to-live in minutes
hooks.beforeAddItemBeforeHook[][]Before adding an item
hooks.afterAddItemAfterHook[][]After adding an item
hooks.beforeRemoveItemBeforeHook[][]Before removing an item
hooks.afterRemoveItemAfterHook[][]After removing an item
hooks.beforeUpdateQuantityBeforeHook[][]Before updating item quantity
hooks.afterUpdateQuantityAfterHook[][]After updating item quantity

FieldTypeDefaultDescription
hooks.beforeCreateBeforeHook[][]Before checkout is created. May mutate checkout data.
hooks.afterCreateAfterHook[][]After checkout completes and order is created

FieldTypeDefaultDescription
hooks.beforeCreateBeforeHook[][]Before order creation
hooks.afterCreateAfterHook[][]After order creation
hooks.beforeStatusChangeBeforeHook[][]Before order status transition
hooks.afterStatusChangeAfterHook[][]After order status transition
hooks.beforeDeleteBeforeHook[][]Before order deletion

FieldTypeDefaultDescription
hooks.afterAdjustAfterHook[][]After an inventory level adjustment

interface ShippingConfig {
type: "flat" | "weight_based";
flatRate: number;
freeShippingThreshold?: number;
brackets: Array<{ upToGrams: number; cost: number }>;
fallbackCost: number;
}
FieldTypeDescription
type"flat" | "weight_based"Shipping calculation strategy
flatRatenumberFixed shipping cost. Used when type is "flat".
freeShippingThresholdnumberOrder subtotal above which shipping is free
bracketsArray<{ upToGrams: number; cost: number }>Weight-based cost brackets. Used when type is "weight_based".
fallbackCostnumberShipping cost when no bracket matches

FieldTypeDescription
adapterTaxAdapterTax calculation adapter instance
defaultFromAddress.countrystringISO country code
defaultFromAddress.postalCodestringPostal/ZIP code
defaultFromAddress.statestringState or province code
defaultFromAddress.citystringCity name
defaultFromAddress.line1stringStreet address

FieldTypeDescription
modelsAnalyticsModel[]Plugin-contributed analytics model definitions
customSchemaPathstringPath to a directory containing custom .js analytics model files

FieldTypeDescription
adapterSearchAdapterSearch engine adapter instance
defaultFacetsstring[]Facet field names returned by default in search results

FieldTypeDefaultDescription
adapterJobsAdapterBackground job queue adapter. When omitted, uses in-memory queue (dev only).
tasksTaskDefinition[]Task definitions registered at startup. Each specifies a slug and handler.
autorun.enabledbooleanEnable automatic job polling
autorun.intervalMsnumber5000Polling interval in milliseconds