@askdb/config
v1.0.0-beta.11
Published
AskDB configuration helpers: Prisma-style env() and askdb.config file discovery for first-party apps.
Readme
@askdb/config
Prisma-style helpers for AskDB: env(), defineConfig(), plus discovery and loading of askdb.config.* / .config/askdb.* files used by first-party apps (askdb CLI, @askdb/http-api, @askdb/studio).
@askdb/config is the single package that reads process.env directly (during dotenv load, while askdb.config.* evaluates, and for a tiny bootstrap-time overlay allowlist). All other packages obtain configuration through getAskDbRuntimeConfig().
Install
pnpm add @askdb/configConfig file discovery
AskDB searches the working directory (cwd, usually process.cwd()) in this order:
askdb.config.<ext>— extension precedence:ts→mts→cts→js→mjs→cjs(first existing file wins)..config/askdb.<ext>— same extension precedence.
This mirrors the layout described in Prisma's config reference, but uses .config/askdb.* so it does not collide with Prisma's own .config/prisma.* files.
Example askdb.config.ts
import "dotenv/config";
import { defineConfig, env, type AskDbConfig } from "@askdb/config";
export default defineConfig({
ai: {
provider: "openai",
providerConfig: {
openai: {
apiKey: env("MY_OPENAI_API_KEY"),
model: env("MY_CHAT_MODEL"),
},
},
},
database: {
provider: "postgres",
providerConfig: { postgres: { databaseUrl: env("MY_DATABASE_URL") } },
},
introspection: {
provider: "postgres",
providerConfig: { postgres: {} },
outputDir: env("MY_INTROSPECT_OUTPUT_DIR"),
},
rag: {
embedder: "mock",
embedderConfig: {},
store: "memory",
storeConfig: { memory: {} },
},
} satisfies AskDbConfig);Your .env can use friendly names (MY_OPENAI_API_KEY, …). defineConfig runs flattenAskDbConfig, which maps the nested object onto the canonical environment variable names used in the runtime flat map (and in aiEnv for @askdb/ai). Unset optional fields get defaults inside flattenAskDbConfig (chat model, introspection output dir, database URL fallbacks, RAG embedding dimensions, file-store base path, pgvector index strategy, etc. — see packages/config/src/defaults.ts).
Architectural rule — @askdb/config is the sole process.env reader
Only @askdb/config reads process.env directly. All AskDB library packages obtain their
configuration through a single typed gateway:
import { getAskDbRuntimeConfig } from "@askdb/config";
const config = getAskDbRuntimeConfig();
const apiKey = opts.apiKey ?? config.rag.embedder.apiKey;
const level = config.logging.level;
// For @askdb/ai registry methods that accept an env-map argument:
const model = await aiRegistry.createLanguageModelFromEnv(config.ai.aiEnv, { ... });Rules:
- Library packages (
@askdb/rag,@askdb/enrich, …) must callgetAskDbRuntimeConfig()and use the returned typed fields. They must not callenv(),requiredEnv(), or accessprocess.envdirectly. env(name)is only for use insideaskdb.config.*files authored by end users — it maps friendly.envnames onto values that become part of the structured config and flat map.- First-party app entry points call
bootstrapAskDbEnv()at start-up. That loads dotenv, evaluatesaskdb.config.*, and installs an in-memory runtime snapshot (structured config + flat map + derivedaiEnv). It does not copy AskDB settings intoprocess.env.
Migration from legacy flat config
export default { OPENAI_API_KEY: "…" } is no longer supported. Use nested defineConfig({ ... satisfies AskDbConfig }) and export default defineConfig({ … }).
API
getAskDbRuntimeConfig()— primary API for library packages. Returns a typedAskDbRuntimeConfigfrom the bootstrapped snapshot (structured,flat-derived fields, andai.aiEnvfor@askdb/core).env(name)/requiredEnv(name)— readprocess.envwhile authoringaskdb.config.*only.defineConfig(config)— returns anAskDbEnvProjectionwithconfig(structured) andentries(flattened canonical map).flattenAskDbConfig(config)— nested config → flat canonical map (applies defaults for optional values).bootstrapAskDbEnv(options?)/bootstrapAskDbRuntime— load dotenv, load config, install the runtime snapshot.loadAskDbConfigProjection(cwd)/loadAskDbConfigProjectionSync(cwd)— load projection without installing the singleton (advanced / tests).discoverAskDbConfigPath(cwd)— returns the resolved config path, if any.mergeAskDbFlatIntoEnvMap(base, flat)— merge AskDB flat entries into an env map for child processes (does not readprocess.envitself). UsegetAskDbRuntimeConfig().flatasflatafter bootstrap.setAskDbRuntimeForTests/resetAskDbRuntimeForTests— test helpers for the runtime snapshot.
License
Apache-2.0 © Yahya Gilany. See LICENSE and NOTICE.
