Workspace configuration
Workspace configuration has two ownership levels.
Root configuration
Section titled “Root configuration”The root owns discovery and repository-wide policy:
import { defineConfig } from "@formly-contract/workspace";
export default defineConfig({ projectConfigs: ["apps/**/formly-contracts.project.ts", "libs/**/formly-contracts.project.ts"], excludeProjectConfigs: ["apps/legacy/**"], tsconfigPath: "tsconfig.base.json", projectConfigOverrides: { "configs/claims.project.ts": { projectRoot: "apps/claims", runtimeResolutionBase: "apps/claims", tsconfigPath: "apps/claims/tsconfig.app.json", }, }, sourceUsage: { convention: "direct-root-call-v1", tsconfigPath: "apps/claims/tsconfig.app.json", }, output: { directory: "dist/formly-contracts" }, locators: { testIdAttributes: ["data-testid", "data-cy"] }, diagnostics: { failOn: ["error"] }, effects: { cyclePolicy: "error" },});projectConfigs is required. Other settings have validated defaults:
output.directorydefaults todist/formly-contractslocators.testIdAttributesdefaults to['data-testid', 'data-test-id', 'data-test', 'data-cy', 'data-pw']diagnostics.failOndefaults to['error']effects.cyclePolicydefaults to'error'
projectConfigOverrides handles centralized configs through exact discovered
config paths; glob keys and stale keys are rejected. projectRoot and
runtimeResolutionBase otherwise default independently to the project config
directory. tsconfigPath falls back to root tsconfigPath, then absence.
Parent and worker realpath-check every effective path inside the workspace.
sourceUsage is optional. When enabled, root tsconfigPath is required as the
source-usage authority and default project-config resolver configuration. The current direct-root-call-v1 pilot
uses those options for a project-config-only authority Program, compares its
traversed authority imports and re-exports with the exact Jiti config runtime,
and accepts one leaf application sourceUsage.tsconfigPath for direct call
and new references to explicitly registered form-root symbols. Exact linkage
requires both Programs and Jiti to resolve the same registered chain. It is intentionally incomplete:
it does not prove routes, rendering, wrapper control flow, or runtime
reachability.
All discovered project configs must use .ts, .mts, or .cts for this
pilot. .mjs and .cjs remain valid when source indexing is disabled, but an
opted-in run rejects them with
SOURCE_USAGE_PROJECT_CONFIG_UNSUPPORTED instead of changing the leaf
program’s allowJs boundary.
Configured paths and workspace-owned program roots and sources, including declaration files, must resolve inside the workspace. TypeScript-classified external-library declarations remain allowed. Output must not resolve through a symlink.
Project configuration
Section titled “Project configuration”A project owns local sources, field profiles, effects, and supported policy overrides:
import { defineFormContractProject } from "@formly-contract/workspace";import { CLAIMS_SOURCE } from "./src/contracts.js";
export default defineFormContractProject({ projectId: "claims/forms", sources: [CLAIMS_SOURCE],});Every project that owns an indexed source file needs a discovered project config. A feature library that only consumes a form may therefore use a source-empty config:
export default defineFormContractProject({ projectId: "claims/feature", sources: [],});This explicit ownership keeps source matches deterministic; it does not make the feature library a form source.
Project and source IDs are validated globally before form factories execute. Projects are ordered deterministically by normalized config path and ID.
Config loading
Section titled “Config loading”The loader uses Jiti for ESM, CommonJS, and TypeScript. TypeScript aliases are
disabled unless tsconfigPath is explicit. Imports resolve from the consuming
workspace, not from the linked Formly Contract checkout.
Stable loader errors are:
CONFIG_NOT_FOUNDCONFIG_LOAD_FAILEDCONFIG_EXPORT_INVALID
Start with formly-contracts list. If loading fails, confirm the TypeScript
config and move discovery exports out of Angular browser barrels. Preloading
the Angular compiler makes compatible partially compiled Angular libraries
loadable; it cannot repair arbitrary JavaScript initialization cycles or make
browser integrations safe under Node. Follow the
Node-safe Angular library setup when a
project owns reusable Angular/Formly components.
Project failure results retain a stable worker failure code, its
bootstrap/inventory/compile phase, and the workspace-relative config path.
Run list, generate, or check with --explain to request bounded local
cause summaries and workspace-only frames. Explanations are not generated by
default and are never part of the deterministic artifact set.
The worker wire protocol is strict and package-lockstep rather than an
independently compatible plugin API. Custom worker modules must use the exact
@formly-contract/workspace version as the parent because unknown optional
fields are rejected.
Programmatic worker execution defaults to trusted-local-v1: direct Node
spawn, no shell, scrubbed environment, strict IPC, bounded teardown, and
read-only filesystem permissions when the current Node runtime supports them.
Filesystem writes, child processes, and worker threads are not granted, but
network access is not blocked; this remains a trusted-code guardrail rather
than an untrusted-code sandbox. Selecting isolated-ci-v1 fails closed before
project import until its external provider is installed.
Use the workspace API reference for programmatic discovery, generation, checking, authoring inspection, and index parsing. Use the CLI reference for command options and refusal behavior.