Configuration
There's both codegen and runtime configuration of the ent framework.
codegen
codegen can be configured in a yml file in order of precedence (from the root of the project):
- a
ent.ymlfile - a
src/ent.ymlfile - a
src/graphql/ent.ymlfile
The root of codegen configuration is the codegen key in the file.
The following properties can be configured:
defaultEntPolicyconfigures the Privacy Policy in base class of generated Ents. Overrides the default privacy policy. See PrivacyConfig for the expected format.defaultActionPolicyconfigures the Privacy Policy in base class of generated Actions. Overrides the default privacy policy. See PrivacyConfig for the expected format.- Biome is the default formatter for generated TypeScript. Codegen will use the project's
biome.jsonorbiome.jsoncwhen present, and otherwise fall back to ent's bundled Biome config. prettierconfigures legacy Prettier formatting and makes codegen use Prettier instead of Biome. See PrettierConfig for the expected format.relativeImportsconfigures where to use relative imports in generated files instead ofsrc/ent/useretc. needed for legacy scenarios or situations where the custom compiler has issues.disableGraphQLRoot: the default graphql root is src/graphql/index.ts. if integrating into an existing project (with an existing root) or just want to do something different, set this to truegeneratedHeader: add header to each generated file in addition to "Generated by github.com/lolopinto/ent, DO NOT EDIT."disableBase64Encoding: disable base64encoding of id fields. When set to true, id fields aren't resolved with nodeIDEncoder and the actual uuid or integer is sent to the clientgenerateRootResolvers: for each type exposed to GraphQL instead of node(). Should be used in combination withdefaultGraphQLMutationName: default names for graphql actions|mutations is nounVerb e.g. userCreate. If you wanna change it to verbNoun e.g. createUser, set this field toVERB_NOUNdefaultGraphQLFieldFormat: default format for fields is lowerCamelCase e.g. firstName. If you wanna change it to snake_case e.g. first_name, set this field to snake_caseschemaSQLFilePath: if we should generate schema.sql file and path to generate itglobalImportPath: path to add to src/ent/internal.ts so that it's included everywhere. Where things like global augmentation can be doneuserOverridenFiles: list of files to not override during codegen i.e. because there's a bug in codegen and the user has decided to override it.transformLoadMethod: if set, overrides the loadNoTransform(X) methods to be this instead of the default loadNoTransform(X)transformDeleteMethod: if set, overrides the saveWithoutTransform(X) methods to be this instead of the default saveWithoutTransform(X)disableDefaultExportForActions: by default, actions are exported withexport default. This changes that to named defaults.
PrivacyConfig
Following fields supported:
policyName(string. required). name of default privacy policypath(string. required). path to import to get the policyclass(boolean. optional). indicates if the policy is a class as opposed to a constant.
PrettierConfig
Following fields supported:
custom(boolean. optional). indicates there's already a custom prettier configuration that should be used.glob(string. optional). glob to pass to prettier instead of defaultsrc/**/*.ts
Formatting
Generated TypeScript is formatted with Biome during codegen unless codegen.prettier is configured or --force_prettier is passed.
Codegen looks for biome.json or biome.jsonc at the project root and lets Biome apply that configuration directly. If neither file exists, ent falls back to its bundled Biome config. Formatter options are no longer copied into .ent/schema.json; the Biome config file is the source of truth.
To preserve single quotes or other project formatting preferences, add a project-root biome.json or biome.jsonc:
{
"javascript": {
"formatter": {
"quoteStyle": "single",
"jsxQuoteStyle": "single"
}
}
}
runtime
Because there could be so many possible entrypoints into the framework e.g. GraphQL endpoint, REST API endpoint, tests, migration script, etc, there's no way to automatically configure runtime behavior so it has to be done manually via calling loadConfig.
loadConfig
loadConfig takes an optional file, Buffer or Config. If nothing is passed, it assumes local ent.yml file, if string is passed, it assumes yml file and attempts to read and parse it.
loadConfig(file?: string | Buffer | Config | ConfigWithCodegen): void;
type logType = "query" | "warn" | "info" | "error" | "debug";
export interface Database {
database?: string;
user?: string;
password?: string;
host?: string;
port?: number;
ssl?: boolean;
sslmode?: string;
}
export type env = "production" | "test" | "development";
export declare type DBDict = Partial<Record<env, Database>>;
export interface Config {
dbConnectionString?: string; // raw db connection string
dbFile?: string; // config/database.yml is default
db?: Database | DBDict;
log?: logType | logType[]; // logging levels.
// dev branch schemas (postgres only)
devSchema?: RuntimeDevSchemaConfig;
// optional runtime extension validation / schema overrides
extensions?: RuntimeDBExtension[];
}
export interface ConfigWithCodegen extends Config {
// config for codegen. not relevant when loadConfig is called but accepted when reading ent.yml
codegen?: CodegenConfig;
// codegen/tooling extends the runtime config with prune support
devSchema?: DevSchemaConfig;
}
interface CodegenConfig {
defaultEntPolicy?: PrivacyConfig;
defaultActionPolicy?: PrivacyConfig;
// legacy Prettier formatting. prefer biome.json or biome.jsonc at the project root
prettier?: PrettierConfig;
}
interface PrettierConfig {
custom?: boolean;
// default glob is 'src/**/*.ts', can override this
glob?: string;
}
interface PrivacyConfig {
path: string; // e.g. "@snowtop/ent"
policyName: string; // e.g. "AlwaysAllowPrivacyPolicy";
class?: boolean;
}
interface RuntimeDevSchemaConfig {
enabled?: boolean;
schemaName?: string; // optional explicit schema name
includePublic?: boolean;
ignoreBranches?: string[];
}
interface RuntimeDBExtension {
name: string;
provisionedBy?: "ent" | "external";
version?: string;
installSchema?: string;
runtimeSchemas?: string[];
dropCascade?: boolean;
}
interface DevSchemaConfig extends RuntimeDevSchemaConfig {
prune?: {
enabled?: boolean;
days?: number; // default 30
};
}
Example
log:
- query
- error
- warn
- info
codegen:
defaultEntPolicy:
path: "@snowtop/ent"
policyName: "AlwaysAllowPrivacyPolicy"
defaultActionPolicy:
path: "@snowtop/ent"
policyName: "AlwaysAllowPrivacyPolicy"
prettier:
custom: true
devSchema:
enabled: true
# includePublic: false
# ignoreBranches:
# - main
# - master
prune:
enabled: true
days: 30
Dev branch schemas (postgres only)
When devSchema.enabled is true (and NODE_ENV is not production), ent will derive a per-branch
postgres schema and set search_path automatically. The schema name is based on the git branch name
unless schemaName is explicitly provided (explicit names are sanitized and will be prefixed with
schema_ if they start with a digit). Note that schemaName does not enable dev schemas by itself;
devSchema.enabled must be set to true. This feature is not supported for sqlite and will error if
enabled with a sqlite connection.
If you pass devSchema to runtime loadConfig, that config is self-sufficient: ent derives the
schema directly from the current git branch unless schemaName is explicitly provided. It does not
require src/schema/.ent/dev_schema.json.
If runtime config is not provided, ent falls back to src/schema/.ent/dev_schema.json, which is
written by Go codegen. In that state-file mode, ent fails closed if the current branch cannot be
determined or does not match the stored branchName. After switching branches, rerun tsent codegen
before using the generated state again.
By default, the dev schema is isolated (includePublic defaults to false). Set includePublic: true
to add public to the search_path for reads while still keeping reflection/compare limited to the
dev schema.
If you want to disable dev schemas on certain branches (e.g. main/master), set
devSchema.ignoreBranches. This applies unless you force-enable via ENT_DEV_SCHEMA_ENABLED=true.
devSchema.prune is a codegen/tooling setting, not a TS runtime setting. It is used when writing the
generated state file and by tsent prune_schemas. Runtime
loadConfig does not prune schemas on connection open.
You can force-enable or disable this behavior with ENT_DEV_SCHEMA_ENABLED (useful for tests).
DB extensions at runtime
Extension packages such as @snowtop/ent-postgis and @snowtop/ent-pgvector register their type parsers and default runtime schemas when they are imported. Ent batches those registrations into a single type lookup query at startup, so multiple extensions do not each issue their own pg_type query.
If you want fail-fast runtime validation, version checks, or non-default runtime schemas, pass extensions to loadConfig:
import { loadConfig } from "@snowtop/ent";
import { PostGISExtension } from "@snowtop/ent-postgis";
loadConfig({
dbConnectionString: process.env.DB_CONNECTION_STRING,
extensions: [
PostGISExtension(),
],
});
provisionedBy has the same meaning here as in dbExtensions:
"ent"is the default. It means Ent owns the extension lifecycle in migrations."external"means the database service or DBA owns the extension lifecycle and Ent should only validate that it already exists.
Runtime config is optional when the package defaults are enough. It is recommended when:
- you want startup to fail if a required extension is missing or at the wrong version
- the extension is installed outside
public - dev-schema mode needs extra schemas added to
search_path