Atlas API Reference#
@atlas/config#
env(name, opts?) → EnvRef<T> opts: { parse: (s)=>T, default: string }
defineConfig(schema) → Readonly<T> resolves all EnvRef values, freezes
@atlas/db#
from(schema, alias?) → Chainable<RowOf<schema>> typed Ecto-style chain
from(table: string, alias?) → Chainable<any> dynamic / cross-table chain
.select(...keys) narrows row to Pick<Row, K>
.where(cb) .join(t, on) .leftJoin(t, on) .innerJoin(t, on)
.orderBy(col, dir?, nulls?) .groupBy(...cols) .having(cb)
.limit(n) .offset(n) .distinct(...cols)
.insert(data) .insertMany(data[]) .update(data) .del() .truncate(cascade?)
.returning(...keys) .onConflict(spec) .cte(name, sub) .recursiveCte(name, sub)
.toSql(dialect?) → SqlResult<Selected>
raw(sql, ...values) → Fragment
defineSchema(table, columns) → Schema<T>
column.serial() → number .text() → string .integer() → number
.bigint() → bigint .real() → number .boolean() → boolean
.timestamp() → Date .json<T>() → T .uuid() → string
modifiers: .primaryKey() .unique() .nullable() (widens to T|null)
.default(val) .defaultRaw(sql) .ref(table, col)
RowOf<typeof schema> extract row TS type
changeset(schema, { cast, required?, validate? }) → (data) => ChangesetResult
connect({ driver, path|url, pool? }) → Connection
Connection: .execute<Row>(q) → Row[]
.one<Row>(q) → Row | null
.all<Row>(q) → Row[]
.transaction(fn) .close()
row type is inferred from the chain when from(schema) is used
@atlas/migrate#
migrate.create(dir, name) creates timestamped up.sql/down.sql
migrate.up(db, dir) runs pending migrations
migrate.down(db, dir) rolls back last migration
migrate.status(db, dir) lists migration status
migrate.plan(db, schemas) → DiffPlan compute up/down SQL (read-only)
migrate.diff(db, schemas, { name?, dir? }) → DiffWriteResult
introspect live DB, write a new migration
folder with up/down SQL — { noop: true }
when in sync. Type/nullability mismatches
emit `-- ALTER` comments for review.
@atlas/server#
createConn(req, params?) → Conn immutable connection from Request
assign(conn, data) → Conn merge into conn.assigns
putHeader(conn, key, val) → Conn add response header
halt(conn, status, body?) → Conn stop pipeline
setStatus(conn, status) → Conn
pipe(fn) → PipeFn type-inference wrapper
pipeline(...pipes)(handler) → PipeFn compose pipes, halt short-circuits
get|post|put|patch|del|head|options(path, handler) → Route
router(...routes) → fetch handler
serve({ port, routes, hostname?, websocket? })
json(conn, status, data) → Conn
text(conn, status, body) → Conn
redirect(conn, location, status?) → Conn
stream(conn, status, readable) → Conn
parseJson | parseForm | parseMultipart built-in parser pipes
onError(handler) → error pipe
createAdapter(name, start) → ServerAdapter
compose(adapters) → ComposedServer
route(method, path, schemas, handler) → Route validated, typed route
getR | postR | putR | patchR | delR(path, schemas, handler) → Route
schemas: { params?, body?, query?, before?, assigns? }
- params/body/query: Validator<T> = (input) => T | { parse(input): T }
(Zod, plain functions, or any Standard-Schema-shape qualify)
- before: PipeFn[] (run ahead of validation; e.g., requireAuth)
- assigns: phantom — `{} as MyClaims` types c.assigns for the handler
body schema auto-parses JSON; rejects non-application/json content-types.
validation failures → unprocessable("Invalid <where>", VALIDATION_FAILED)
httpError(status, message, { code?, details?, headers? }) → HttpError
isHttpError(value) → bool type guard
haltWith(conn, error) → Conn halt with HttpError
notFound | unauthorized | forbidden | badRequest | conflict | gone |
unprocessable | tooManyRequests | methodNotAllowed | internal |
serviceUnavailable(message?, opts?) → HttpError
router catches `throw httpError(...)` and renders { error, code?, details? }
@atlas/edge#
defineEdge(config) → { ...config, listen() → Promise<RunningEdge> }
runEdge(config) → Promise<RunningEdge> { mode: "tls"|"plain", stop() }
proxy(upstream, { preserveHost? }) → EdgeHandler reverse proxy with X-Forwarded-*
forward(req, options, ctx) → Promise<Response> low-level proxy primitive
files({ root, index?, stripPrefix? }) → EdgeHandler static file serving via Bun.file
compressResponse(res, accept, allow) → Response apply gzip/zstd
matchHost(host, pattern) → bool literal or "*.x.com"
matchRoute(req, url, matcher?) → bool path (regex|string|*) + method
isLocalHost(host) → bool localhost / 127.0.0.1 / ::1 / *.localhost
provisionCertificate({ directoryUrl, accountKey, contactEmail, hosts, challenge }) → { certPem, keyPem }
generateKeyPair() → AcmeKeyPair ECDSA P-256 via Web Crypto
importKeyPair(jwk) | jwkThumbprint(jwk)
LETSENCRYPT_PROD | LETSENCRYPT_STAGING directory URLs
issueCert({ directoryUrl, contactEmail, hosts, store, challenge }) → CertRecord
loadOrCreateAccount(store) → AcmeKeyPair
fileStore(root) | memoryStore() → CertStore .load .save .loadAccountJwk .saveAccountJwk
certKey(hosts) → string stable map key for a host list
createRenewalScheduler(onRenew) → { schedule, cancel, stop }
renewAt(record) → number unix ms; 30 days before expiry, clamped
EdgeConfig: { acme?, sites: Site[], insecure?, httpPort?, httpsPort? }
Site: { host, routes: Route[], compress?: ("gzip"|"zstd")[] }
Route: { match?: { path?, method? }, handler: (req, ctx) => Promise<Response> }
ForwardContext: { remoteIp, tls, host }
@atlas/server/ws#
ws(config) → { websocket, rooms, upgrade }
channel(name, handlers) → Channel
createRooms() → { join, leave, leaveAll, broadcast, members }
WsConn<T>: wrapped ws with auto-JSON send
@atlas/server/sse#
createSseChannel() → { broadcast, pipe, clients }
eventStream(conn, generator) → SSE response
SseClient: { id, send, close }
@atlas/auth#
hash(password) → Promise<string> Argon2id via Bun.password
verify(password, hashed) → Promise<bool>
token.sign(payload, secret, opts?) → Promise<string> opts: { expiresIn: seconds }
token.verify(jwt, secret) → Promise<TokenPayload>
createMemoryStore({ ttl? }) → SessionStore dev/testing session store; ttl seconds expires entries
signup({ db, table, fields, onSuccess }) → PipeFn
login({ db, table, identity, password, onSuccess }) → PipeFn
requireAuth({ secret }) → PipeFn reads Bearer token, sets conn.assigns.auth
passwordReset({ db, table, secret, transport, expiresIn? }) → PipeFn
@atlas/auth/social#
socialAuth({ secret, providers, cookie? }) → SocialAuth
SocialAuth: { providers,
authorize(name, { scopes?, returnTo?, extraParams? }?) → { url, cookie },
complete(name, conn) → { provider, tokens, profile, returnTo? },
start(name, opts?) → PipeFn, 302s + sets state cookie
callback(name, { onSuccess, onError? }) → PipeFn validates state, exchanges code, clears cookie }
Provider factories — each returns a `SocialProvider`:
google({ clientId, clientSecret, redirectUri, hostedDomain?, prompt? })
github({ clientId, clientSecret, redirectUri, allowSignup? })
apple({ clientId, teamId, keyId, privateKey, redirectUri, responseMode? })
mints ES256 client_secret JWT per exchange; default response_mode=form_post
microsoft({ clientId, clientSecret, redirectUri, tenant?, prompt? }) tenant defaults to "common"
facebook({ clientId, clientSecret, redirectUri, apiVersion?, profileFields? })
twitter({ clientId, clientSecret?, redirectUri, userFields? }) Basic auth for confidential clients
tiktok({ clientKey, clientSecret, redirectUri, userFields? }) uses `client_key`, comma-joined scopes, id is open_id
SocialProfile: { provider, id, email?, emailVerified?, name?, picture?, username?, raw }
TokenSet: { accessToken, tokenType?, expiresIn?, refreshToken?, idToken?, scope?, raw }
State + PKCE verifier live in a signed, HttpOnly, SameSite=lax cookie
(`_atlas_oauth_state`, 10 min TTL). Override via cookie: { name?, path?, secure?, sameSite? }.
@atlas/share#
shareUrl(channel, content) → string throws on unknown channel or missing url
share(content) → Record<ShareChannel, string> all eight URLs at once
listChannels() → { channel, label }[] ordered list with display labels
channels readonly ShareChannel[]
ShareChannel = "twitter" | "facebook" | "linkedin" | "reddit" | "whatsapp" | "telegram" | "sms" | "email"
ShareContent: { url, title?, text?, hashtags?, via?, phone?, to?, cc?, bcc? }
url required; unknown fields ignored per channel.
Provider re-exports (each is a `ShareProvider { channel, label, build }`):
twitter, facebook, linkedin, reddit, whatsapp, telegram, sms, email
shareEmail({ emailer, to, from?, replyTo?, sharerName?, product?, message?, content, brand?, accent? })
→ Promise<SendResult> dispatches a branded HTML email through @atlas/email
renderShareEmailMessage(opts) → { subject, html, text } pure preview/render
@atlas/email#
createEmailer({ apiKey?, from? }) → Emailer auto-picks Resend if both set, else console
createResendEmailer({ apiKey, from }) → Emailer
createConsoleEmailer() → Emailer dev fallback; logs and returns ok:true
Emailer: { enabled, send(msg) → Promise<SendResult> }
EmailMessage: { to, subject, html, text?, replyTo?, from? }
SendResult: { ok: true, id?, logged? } | { ok: false, error }
inviteEmail(opts) | passwordResetEmail(opts) → { subject, html, text }
layout({ title, body, brand?, footer?, accent? }) → string
escapeHtml(s) → string always wrap untrusted input
@atlas/oauth#
oauthRoutes(cfg, { basePath?, adminBasePath? }) → Route[] all OAuth endpoints
oauthAuthorizeRoutes(cfg, base) | oauthTokenRoutes | oauthRevokeRoutes
oauthDeviceRoutes | oauthDiscoveryRoutes | oauthClientRoutes(cfg, adminBase)
findClient(db, id) | verifyClientCredentials(db, id, secret)
sweepExpired(cfg) | sweepExpiredAuthCodes | sweepExpiredRefreshTokens | sweepExpiredDeviceCodes(cfg)
helpers: parseScope, formatScope, includesScopes, isAllowedRedirect,
verifyPkceS256, randomId, shortId, sha256, newUserCode, normalizeUserCode
constants: ACCESS_TOKEN_TTL_SECONDS, REFRESH_TOKEN_TTL_SECONDS,
AUTH_CODE_TTL_SECONDS, DEVICE_CODE_TTL_SECONDS, DEVICE_POLL_INTERVAL_SECONDS
types: OAuthConfig, OAuthUser, ClientRow, AuthCodeRow, RefreshTokenRow,
DeviceCodeRow, OAuthAuditEvent, RequestContext
@atlas/sso#
mountSso(cfg: SsoConfig) → readonly Route[] mount /login + /callback + /backchannel-logout
ensureSsoStateTable(db, table?) idempotent CREATE TABLE IF NOT EXISTS
sweepExpiredSsoState(db, table?) prune expired state rows (10m TTL)
clearDiscoveryCache() for tests / hot-reload
SsoConfig: { db, issuerUrl, clientId, clientSecret,
onAuthenticated(db, claims) → { localUserId, displayName? },
issueSession(conn, user, claims) → Conn,
redirectUri?, scopes?, basePath?, defaultPostLoginPath?, stateTable?,
findLocalUserBySub?(db, sub), invalidateSessions?(db, { sub, localUserId }) }
IdTokenClaims: { sub, iss, aud, email?, email_verified?, name?, preferred_username?, picture?, ... }
DiscoveryDoc: { issuer, authorization_endpoint, token_endpoint, jwks_uri, userinfo_endpoint?, end_session_endpoint? }
@atlas/security#
withSecurityHeaders(fetch, { dev?, csp?, disableCsp? }) → fetch HSTS/CSP/COOP/CORP + req.peerIp shim
developmentCsp | productionCsp string CSP presets
decideInline(mime, name, wantInline) → { contentType, disposition } safe-MIME allowlist for inline
createDbRateLimit({ db }) | createMemoryRateLimit() → RateLimit .check(bucket, max, windowSec) .reset(bucket) .sweep(olderThanSec)
clientIp(req, { trustedProxies? }) → string honors X-Forwarded-For only via trusted proxy
userAgent(req) → string | undefined
parseTrustedProxies(env) → string[]
createAuditLogger({ db }) → { log(event), ... } fire-and-forget; never throws
createSessionStore<U>({ db, secret, ttlSeconds }) → SessionStore DB-backed JWT sessions
.issue(user, ctx) .isActive(jti) .touch(jti) .revoke(jti, userId) .revokeAll(userId, keep?) .sweepExpired()
newJti() → string
generateSecret() → string TOTP base32 secret
totpAt(secret, epochSec) → string 6-digit code at time
verifyTotp(secret, code, { window? }) → bool window=1 accepts ±30s
otpauthUrl({ secret, account, issuer }) → string
generateBackupCodes(n?) → string[] store hashed
base32Encode(bytes) | base32Decode(str)
@atlas/storage#
createStore({ endpoint, bucket, region, accessKey, secretKey }) → Store
upload(store, { key, body, contentType }) → Promise
download(store, key) → Promise<Response>
list(store, prefix?) → Promise<ListResult>
remove(store, key) → Promise
presign(store, key, { expires?, method? }) → string
@atlas/cache#
createCache({ url }) → Cache Redis-backed
createMemoryCache() → Cache in-memory for dev
cached(cache, prefix, fn, { ttl? }) → cached function
invalidate(cache, prefix, ...args) → Promise
@atlas/request#
request(url, opts?) → Promise<Response> opts: { json, headers, method, body, retry, timeout (ms) }
createClient({ baseUrl, headers?, retry?, interceptors?, timeout? }) → Client
Client: .get .post .put .patch .del .request — all return Promise<Response>
withRetry(fn, { attempts?, delay?, backoff?, retryOn? })
github({ token }) | stripe({ key }) | openai({ key }) | resend({ key })
preconfigured clients — import from @atlas/request/providers
@atlas/cli#
cli(name, commands) run CLI with command definitions
command(name, { flags?, run }) define a command
flag(short, { type, default? }) define a flag
parseArgs(argv, flags) → ParsedArgs
foreman(procs) | parseProcfile(str) process manager
initCommand | addCommand | docsCommand built-in atlas commands
questions | applyDefaults | generateProject scaffolding
CLI surface:
atlas init [-y] [-n name] scaffold a new project
atlas add <pkg>... install @atlas/* packages
atlas dev foreman → Procfile
atlas mcp start MCP server
atlas docs [<pkg>|<doc>|<root>] print canonical documentation to stdout
@atlas/ui#
@atlas/ui/provider: AtlasProvider, AppShell
@atlas/ui/forms: createForm, TextField, SelectField, SubmitButton
@atlas/ui/table: createTable, TextColumn, DateColumn, ActionColumn
@atlas/ui/auth: LoginPage, SignupPage, ResetPasswordPage
@atlas/ui/storage: FileUpload, ImagePreview
@atlas/ui/nav: Sidebar, NavLink, Breadcrumb
@atlas/ui/cache: CacheInspector, CacheStatus
@atlas/ui/ai: ChatWindow, MessageBubble, PromptInput, AiSearch, GenerateButton
@atlas/admin#
admin({ db, models, basePath?, auth? }) → { mount, routes }
model({ schema, listFields?, searchFields?, filterFields?, relations?, actions?, bulkActions?, readOnly? }) → ModelConfig
Components: AdminApp, AdminSidebar, Dashboard, ModelList, Detail, Create, FilterBuilder, QueryBuilder, BulkBar
@atlas/mcp#
createContext(opts?) → AtlasMcpContext opts: { db?, cache?, routes?, config?, storage?, migrationsDir?, logBuffer? }
collectTools(ctx) → Tool[] tools auto-register from what's in ctx
createMcpServer(tools, ctx) → McpServer
defineTool({ name, description, inputSchema, handler }) → Tool
McpServer: .start() .stop()
Always-on tools (independent of context):
docs.list list package, guide, and root documentation sources
docs.read({ package?, doc?, root? }) read one canonical source; docs/agents.md is the grounding guide
@atlas/ai#
createProvider({ provider, key?, baseUrl? }) → AiProvider provider: "openai"|"anthropic"|"ollama"
createConversation(system?) → Conversation
addMessage(conv, msg) → Conversation
send(provider, conv, content, opts?) → { conversation, response }
userMessage|assistantMessage|systemMessage(content) → Message
toolMessage(toolCallId, content) → Message
chatStream: provider.chatStream(opts) → AsyncIterable
collectStream(stream) → ChatResponse
streamToSse(stream) → ReadableStream
parseSSE(text) → events
embed(provider, input) → number[][] input: string | string[]
cosineSimilarity(a, b) → number
createVectorStore() → { add, search, size }
generateJson<T>(provider, prompt, opts?) → T
tool(name, desc, parameters) → ToolDef
index(rag, id, text, metadata?) → Promise rag: { ai, store, topK? }
query(rag, question) → { answer, sources }
runAgent({ ai, system?, tools, maxIterations? }, prompt) → { response, messages, iterations }
withAi(provider) → PipeFn adds ai to conn.assigns