App API
primate/app validates application configuration and returns the
application facade exported by config/app.ts.
import app from "primate/app";
import type { AppFacade } from "primate/app";See the Configuration guide for deployment advice and examples, the Application guide for facade usage, and the Modules guide for writing extensions.
app()
function app<
P extends EnvSchema = EnvSchema,
const I extends I18NConfig | undefined = undefined,
const T extends Record<string, string> = Record<string, string>,
D extends DB = DB,
>(input?: ConfigInput<P, I, T, D>): AppFacade<P, I, D>;Parameters: input is optional and defaults to {}. Pema validates it,
applies defaults, and rejects invalid values. http.timeout is explicitly
closed and rejects unknown members.
Returns: An AppFacade<P, I, D> preserving the
inferred environment, localization, and migration-database types.
Throws: A Pema parse error for invalid configuration. Removed
db.migrations.autoapply, client.groups, and numeric http.timeout forms
produce migration diagnostics instead of being ignored.
// config/app.ts
import app from "primate/app";
export default app({
http: { port: 8080 },
});
ConfigInput
ConfigInput is an inferred supporting type, not a named export from
primate/app. The following expanded shape represents the current public
input contract; generic refinements preserve partition, environment, i18n, and
database inference.
primate/config remains a deprecated compatibility entrypoint. Calling its
factory emits a diagnostic directing applications to primate/app; it
otherwise uses the same implementation and validation behavior.
type ConfigInput<P, I, T, D> = {
build?: { external?: string[] };
conditions?: string[];
client?: {
partitions: T;
routes: Record<string, keyof NoInfer<T> & string>;
};
http?: {
csp?: Record<string, string[]>;
headers?: Record<string, string>;
host?: string;
port?: number;
timeout?: {
inactivity?: number;
request?: number;
headers?: number;
};
ssl?: { cert?: string; key?: string };
static?: { root?: string };
};
livereload?: {
exclude?: string[];
host?: string;
port?: number;
};
migrations?: { table: string; db: D };
env?: { schema?: ObjectType<P> };
i18n?: I;
loaders?: Record<string, "file">;
entrypoints?: Record<string, string>;
modules?: Module[];
};
input.build.external
build?: { external?: string[] };Packages or import paths excluded from the production server bundle. The
default is []; duplicate entries are rejected. External packages must be
available in the production installation.
input.conditions
conditions?: string[];Additional package export conditions used by client and server builds. The
default is []; duplicate entries are rejected.
input.client
client?: {
partitions: Record<string, string>;
routes: Record<string, string>;
};Defines isolated client bundles and maps route prefixes to partition names.
Both maps are required when client is present. Route values are constrained
to inferred partitions keys. The complete prefix and isolation rules are in
the Configuration guide.
input.http.csp
csp?: Record<string, string[]>;Content-Security-Policy directives. No policy is emitted by default.
input.http.headers
headers?: Record<string, string>;Default response headers added while rendering application views. The default is no additional headers.
input.http.host
host?: string;Server host. Defaults to HOST from the environment, then "localhost".
input.http.port
port?: number;Unsigned valid TCP port. Defaults to numeric PORT from the environment, then
6161.
input.http.timeout
timeout?: {
inactivity?: number;
request?: number;
headers?: number;
};Optional whole-millisecond network clocks. inactivity accepts 0 through
255000; request and headers accept 0 through 2147483647. Omitted
members preserve runtime defaults. Runtime support and interactions are listed
in the Configuration guide.
input.http.ssl
ssl?: { cert?: string; key?: string };Certificate and private-key paths. HTTPS is active only when both are defined.
Both values default to undefined.
input.http.static.root
static?: { root?: string };URL root under which files from the application static directory are served.
Defaults to "/".
input.livereload
livereload?: {
exclude?: string[];
host?: string;
port?: number;
};Development live-reload exclusions and endpoint overrides. host defaults to
the configured HTTP host and port defaults to one less than the configured
HTTP port when Primate resolves the live-reload endpoint.
input.migrations
migrations?: { table: string; db: DB };Configures the application migration ledger and preserves db in the returned
facade's migration declaration type. There is no default migration ledger;
migrations are applied explicitly rather than at server startup.
input.env.schema
env?: { schema?: ObjectType<EnvSchema> };Pema object schema for environment values. When present, values are parsed when
the server facade is attached and app.env()
becomes key- and result-typed. The default is no schema.
input.i18n
i18n?: I18NConfig;Localization configuration. The default is undefined, which installs the
missing-i18n facade. See the primate/i18n API and
Internationalization guide.
input.loaders
loaders?: Record<string, "file">;Maps file extensions to esbuild loaders. The only accepted value is "file".
The default is no additional loader mapping.
input.entrypoints
entrypoints?: Record<string, string>;Named files from client bundled for matching HTML template placeholders.
The default is no named entrypoints. app, head, and body are reserved.
input.modules
modules?: Module[];Extension modules initialized in array order. The default is []; module names
must be unique. See the Module API.
Returned application facade
The returned instance preserves the inferred environment, localization and
migration database types. Prefer importing your configured instance; use
AppFacade for annotations and helper signatures when appropriate.
For a configured facade, typeof configured retains the inferred types;
explicit AppFacade<P, I, D> type arguments can describe a helper's expected
environment, localization and migration database.
AppFacade
declare class AppFacade<
T extends EnvSchema = EnvSchema,
I extends I18NConfig | undefined = undefined,
D extends DB = DB,
> {
get i18n(): I18NRuntime<I>;
config<P extends string>(path: P): ConfigValue<P>;
migrate(value: MigrationDeclaration<D>): MigrationDeclaration<D>;
env<K extends keyof T>(key: K): T[K]["infer"];
get views(): ViewBag;
get root(): FileRef;
get log(): AppLogger;
}ConfigValue, ViewBag, and AppLogger are readable representations of
inferred supporting contracts; they are not exports from primate/app.
The constructor and framework attachment symbols are internal and are omitted.
app.i18n
get i18n(): I18NRuntime<I>;Localization facade inferred from input.i18n. This is the only facade member
available in browser builds. Without i18n configuration, accessing localization
operations uses the missing-i18n behavior. See the
primate/i18n API and
Internationalization guide.
app.config()
config<P extends string>(path: P): ConfigValue<P>;Reads the parsed configuration through a dot-separated path. TypeScript infers the result for valid paths, including applied defaults. This method is server-only and throws when called from a browser build.
import app from "@/config/app";
const port = app.config("http.port"); // number
app.migrate()
migrate(
value: MigrationDeclaration<D>,
): MigrationDeclaration<D>;Validates and normalizes an application migration declaration while preserving
the configured migration database type. It requires an eight-character
lowercase hexadecimal id, unique valid parent IDs, and an optional function
run. Invalid declarations throw migration diagnostics. This method is
server-only and throws in browser builds.
MigrationDeclaration
Supporting input/output type for app.migrate().
type MigrationDeclaration<D extends DB = DB> = {
id: string;
parents: readonly string[];
run?: (db: D) => MaybePromise<unknown>;
};
app.env()
env<K extends keyof T>(key: K): T[K]["infer"];With env.schema, returns the parsed value for
a declared key and throws when the key is missing from the parsed environment.
Without a schema, it reads the named environment value as unknown. Invalid
schema input fails when the server facade is attached. env() is server-only
and throws in browser builds.
app.views
get views(): ViewBag;The server's loaded view registry. It becomes available after the application facade is attached to the serving app; access before that point throws. This property is not available in browser builds.
const render = app.views.get<
(props: { title: string }) => string | Promise<string>
>("docs/home/index.md");
ViewBag
Framework-owned supporting shape returned by app.views. It is
not exported from primate/app.
type ViewBag = {
get<T>(name: string): T;
try(name: string): unknown | undefined;
has(name: string): boolean;
keys(): string[];
values(): unknown[];
entries(): [string, unknown][];
};get() resolves registered frontend extensions and throws when no view exists.
try() returns undefined instead. The collection methods return snapshots of
the current registry.
app.root
get root(): FileRef;Project-root filesystem reference from @rcompat/fs. It becomes available
after server attachment and throws when used too early. In browser builds the
getter always throws.
app.log
get log(): AppLogger;Application logger attached to the serving app. It throws before server attachment and in browser builds.
AppLogger
Supporting shape returned by app.log.
type AppLogger = {
readonly deprecations: readonly {
deprecated: string;
message: string;
replacement: string;
}[];
readonly level: string;
print(strings: TemplateStringsArray, ...params: unknown[]): void;
system(strings: TemplateStringsArray, ...params: unknown[]): void;
trace(strings: TemplateStringsArray, ...params: unknown[]): void;
info(strings: TemplateStringsArray, ...params: unknown[]): void;
warn(strings: TemplateStringsArray, ...params: unknown[]): void;
deprecate(deprecated: string, replacement: string): void;
error(error: unknown): void;
};trace, info, and warn are tagged-template methods and notify registered
module log hooks even when their level is below the console threshold. print
and system write unclassified output. error() accepts an unknown thrown
value.
deprecate() reports that an API was actually used and names its supported
replacement. It emits every time it is called, regardless of the configured log
level. Calls made while building are also retained as build diagnostics for
strict-build handling; runtime calls remain warnings and never become failures.
The deprecations snapshot contains only diagnostics attributed to the active
build. Deprecation log hooks receive the "deprecation" level.
Browser availability
The browser-conditioned AppFacade keeps the typed i18n getter. config(),
migrate(), env(), root, and log throw explicit server-only errors;
views is absent. Do not import server configuration or environment access
into frontend code.