/** * Find every relative module specifier in a declaration source: static `import`/`export … from`, * `import("…")` type nodes, and `/// `. Pure parsing — no I/O. * * A non-empty result means the file is NOT self-contained and would break when copied verbatim to a * flattened output location, so the ambient-copy step rejects it. * @public */ import { CatalogAssemblyError, DependencyResolutionError, ManifestDecodeError, UnresolvedDependencyError } from "@effected/npm"; import { Plugin } from "rolldown"; import { Context, Effect, Layer, Schema } from "effect"; import { BundleManifest, ManifestSource, OpenGraphImage, RegistryRef } from "@tsdoctor/manifest"; //#region src/manifest/transform.d.ts /** @public */ type Json = Record; /** * Which exports get a CJS `require` condition. `true`/`false` apply uniformly to every * TS export; a Set marks ONLY the listed export keys (e.g. "./changesets/markdownlint") * as dual — used by per-entry format overrides. * @public */ type DualExports = boolean | ReadonlySet; /** * The default `transform` applied to every package's manifest when its * `savvy.build.ts` does not provide one of its own. Strips the build/dev-only * fields in `NON_PUBLISHED_FIELDS` from the emitted package.json. * * This is the pattern nearly every package repeated by hand (inherited from * rslib-builder); `defineBuild` now applies it automatically so a package needs a * `transform` only when it has genuinely custom manifest work to do (e.g. silk * promoting workspace deps to peerDependencies). A custom transform REPLACES this * default — re-export it and call it from a custom transform to keep the stripping. * * `targetGroup` is accepted (so this is assignable wherever the full transform * signature is expected) but unused; the strip is identical for every group. * * Pure: the supplied `pkg` is NOT mutated — a shallow copy with the fields removed * is returned, so external callers invoking this from a custom transform keep their * input intact. * @public */ export declare function defaultManifestTransform({ pkg }: { pkg: Json; }): Json; /** * Describes a SEA binary the bundler compiled for this package. When present, * {@link transformManifest} rewrites every `exports`/`bin` value equal to `source` * to the emitted binary path and adds it to `files` so it ships in the tarball. * @public */ interface ExeRewrite { /** The exe entry source path (matches exports/bin values to rewrite). */ readonly source: string; /** The emitted SEA filename (already suffixed, incl. .exe on win). */ readonly fileName: string; /** Relative dir the binary is emitted into (e.g. "bin"). */ readonly dir: string; } /** * Rewrite an exports map: TS string targets become a types/import conditions object. * Each TS condition also gets a `require` entry when `dual` is `true` (uniform) or when * the export key is in the `dual` Set (per-entry). * * The output path is derived from the export KEY via the shared entry-name function, * never from the source path, so the manifest target always matches the emitted file. * * Export keys in `subdirExports` are built into an isolated `/index.*` subdir (e.g. an * RSPress `./runtime`), so their conditions gain an `/index` segment. * * `emitDts` gates the `types` condition on every GENERATED (non-ambient) TS export: pass `false` * when the build's dts pass was skipped (issue #198) so the manifest does not point at a `.d.ts` * that was never written. Defaults to `true`. Ambient `.d.ts` exports (hand-authored, copied * verbatim regardless of the dts pass) are unaffected — their `types` condition is always kept. * @public */ export declare function transformExports(exports: unknown, dual?: DualExports, subdirExports?: ReadonlySet, emitDts?: boolean): unknown; /** * Rewrite bin: TS targets to bin/[command].js (string to bin/cli.js); strip leading ./ otherwise. * * @public */ export declare function transformBin(bin: unknown): unknown; /** * FINAL guard: strip leading ./ from bin paths (npm 11.x drops ./-prefixed bins). * * @public */ export declare function normalizeBinPaths(bin: unknown): unknown; /** @public */ interface TransformManifestOptions { /** Run after the standard transforms, before the bin final-guard + sort. */ readonly transform?: ((pkg: Json) => Json) | undefined; /** Which exports emit dual import/require conditions. boolean = uniform; Set = per-export-key. */ readonly dual?: DualExports | undefined; /** Export keys built into a `/index.*` subdir (e.g. an RSPress `./runtime`). */ readonly subdirExports?: ReadonlySet | undefined; /** When set, rewrite exports/bin values equal to `source` to the SEA path and add it to `files`. */ readonly exeRewrite?: ExeRewrite | undefined; /** * Whether the build's dts pass ran. `false` omits the `types` condition from generated (non- * ambient) TS exports — the manifest must not point at a `.d.ts` that was never written * (issue #198). Defaults to `true`. */ readonly emitDts?: boolean | undefined; } /** * Apply the full standard manifest transform (excluding catalog resolution, done upstream). * * @public */ export declare function transformManifest(pkg: Json, options?: TransformManifestOptions): Json; //#endregion //#region src/manifest/emit-manifest.d.ts /** @public */ interface TargetGroupRef { readonly id: string; /** The package.json name this group's manifest carries (the declarative rename). */ readonly name: string; readonly isProd: boolean; } /** @public */ interface BuildEmittedManifestOptions { readonly pkg: Json; readonly targetGroup: TargetGroupRef; readonly devManifest: "preserve" | "resolve"; readonly transform?: ((args: { pkg: Json; targetGroup: TargetGroupRef; }) => Json) | undefined; /** Which exports emit dual import/require conditions. boolean (uniform) or a Set of export keys (per-entry). */ readonly dual?: DualExports | undefined; /** Export keys built into a `/index.*` subdir (e.g. an RSPress `./runtime`). */ readonly subdirExports?: ReadonlySet | undefined; /** When set, rewrite exports/bin values equal to the exe source to the SEA path and add it to `files`. */ readonly exeRewrite?: ExeRewrite | undefined; /** Whether the dts pass ran; `false` omits `types` conditions from the emitted manifest (issue #198). Defaults to `true`. */ readonly emitDts?: boolean | undefined; } /** * Compute the final manifest bytes for a TargetGroup (catalog resolution + standard transforms). * * @public */ export declare function buildEmittedManifest(options: BuildEmittedManifestOptions): Promise; /** @public */ interface EmitManifestOptions { readonly targetGroup: TargetGroupRef; readonly devManifest?: "preserve" | "resolve" | undefined; readonly transform?: ((args: { pkg: Json; targetGroup: TargetGroupRef; }) => Json) | undefined; /** Source package dir to read package.json/LICENSE/README from. */ readonly sourceDir: string; /** Which exports emit dual import/require conditions. boolean (uniform) or a Set of export keys (per-entry). */ readonly dual?: DualExports | undefined; /** Export keys built into a `/index.*` subdir (e.g. an RSPress `./runtime`). */ readonly subdirExports?: ReadonlySet | undefined; /** When set, rewrite exports/bin values equal to the exe source to the SEA path and add it to `files`. */ readonly exeRewrite?: ExeRewrite | undefined; /** Whether the dts pass ran; `false` omits `types` conditions from the emitted manifest (issue #198). Defaults to `true`. */ readonly emitDts?: boolean | undefined; } /** * Rolldown plugin: emit the transformed package.json + LICENSE/README into the output pkg/ root. * * @public */ export declare function emitManifest(options: EmitManifestOptions): Plugin; //#endregion //#region src/report/schema.d.ts declare const ReportTimings_base: Schema.Class, {}>; /** @public */ export declare class ReportTimings extends ReportTimings_base {} declare const DiagnosticEntry_base: Schema.Class; readonly level: Schema.Literals; readonly text: Schema.String; /** * Diagnostic identifier — an API Extractor messageId (e.g. "ae-forgotten-export") or a * rolldown warning code (e.g. "MIXED_EXPORTS"); used to group suppressed messages by type. */ readonly code: Schema.optional; /** True when shown as `warn` locally but a hard error in CI (drives the "[fails CI]" nudge). */ readonly ciFatal: Schema.optional; readonly file: Schema.optional; readonly line: Schema.optional; readonly column: Schema.optional; }>, {}>; /** * A captured warning or error, from tsdown's logger, rolldown's onLog, API Extractor, or the meta * pass's own sidecar work (`tsdoctor.json` sources, Open Graph generation). * * @public */ declare class DiagnosticEntry extends DiagnosticEntry_base {} declare const EmittedFile_base: Schema.Class; }>, {}>; /** * One emitted output file with its in-memory byte size (gzip only when --verbose). * * @public */ declare class EmittedFile extends EmittedFile_base {} declare const PassReport_base: Schema.Class; readonly files: Schema.$Array; readonly ms: Schema.Number; }>, {}>; /** * One build pass within a target group (js / dts / loose / exe / meta). * * @public */ declare class PassReport extends PassReport_base {} declare const TargetGroupReport_base: Schema.Class; readonly passes: Schema.$Array; readonly warnings: Schema.$Array; readonly errors: Schema.$Array; /** Messages matched by `suppressWarnings`, kept for accounting and `--verbose` expansion. */ readonly suppressed: Schema.$Array; readonly timings: typeof ReportTimings; }>, {}>; /** @public */ declare class TargetGroupReport extends TargetGroupReport_base {} declare const BuildReport_base: Schema.Class; }>, {}>; /** @public */ declare class BuildReport extends BuildReport_base {} //#endregion //#region src/report/collector.d.ts /** @public */ type PassKind = PassReport["id"]; /** @public */ interface DiagnosticInput { readonly source: DiagnosticEntry["source"]; readonly level: DiagnosticEntry["level"]; readonly text: string; readonly code?: string; readonly ciFatal?: boolean; readonly file?: string; readonly line?: number; readonly column?: number; } /** * Stateful build-event accumulator. The write surface is synchronous so it can be called directly * from tsdown's customLogger and API Extractor's messageCallback (both invoked synchronously). * `snapshot` builds the immutable BuildReport the Effect render pipeline consumes. * @public */ export declare class BuildCollector { private readonly groups; private group; private pass; registerGroup(groupId: string, entries: ReadonlyArray): void; recordEmitted(groupId: string, pass: PassKind, file: EmittedFile): void; recordPassTiming(groupId: string, pass: PassKind, ms: number): void; recordWarning(groupId: string, entry: DiagnosticInput): void; recordError(groupId: string, entry: DiagnosticInput): void; recordSuppressed(groupId: string, entry: DiagnosticInput): void; snapshot(packageName: string): ReadonlyArray; } declare const BuildCollectorTag_base: Context.ServiceClass; /** @public */ export declare class BuildCollectorTag extends BuildCollectorTag_base {} //#endregion //#region src/build/target-groups.d.ts /** * A build group id: "dev" or any prod byte-variant id (e.g. "npm", "github", a custom key). * * @public */ type TargetGroupId = string; /** * An output module format the build can emit. * * @public */ type BuildFormat = "esm" | "cjs"; /** * Bundling platform for the JS pass. Defaults to "node". Use "browser" for web runtime partitions. * * @public */ type BuildPlatform = "node" | "browser" | "neutral"; /** * A prod/dev group to build: its folder id and the resolved package name its manifest carries. * * @public */ interface BuildGroupSpec { readonly id: TargetGroupId; readonly name: string; } /** @public */ interface DeriveOptions { readonly group: TargetGroupId; readonly cwd: string; readonly version: string; readonly entry: Record; readonly tsconfigPath: string; readonly devManifest: "preserve" | "resolve"; readonly externals?: ReadonlyArray; /** JS-pass platform. Defaults to "node"; set "browser" for an RSPress runtime partition. */ readonly platform?: BuildPlatform | undefined; /** Output formats to emit. Defaults to esm-only when unset. */ readonly format?: ReadonlyArray | undefined; /** Minify prod output (prod groups only; dev is never minified). Defaults to false. */ readonly minify?: boolean | undefined; /** * Compile-time global replacements forwarded to the build `define`. Merged AFTER the * auto-injected `process.env.__PACKAGE_VERSION__` so a user key of the same name wins. * Values are inserted verbatim (string literals must already be quoted). */ readonly define?: Record | undefined; /** * External packages whose declarations should be INLINED into the bundled dts * (the rslib `dtsBundledPackages` equivalent). Maps to tsdown's `deps.onlyBundle` * in the dts pass, so ONLY these node_modules packages are rolled into the * `.d.ts` and every other dependency stays an external `import`. dts-pass-only: * runtime JS bundling is unaffected. */ readonly bundledPackages?: ReadonlyArray | undefined; /** * Force-bundle node_modules (and workspace) JS dependencies into the JS pass. * Consumed here ONLY to decide the JS pass's `unbundle` posture — see * {@link DerivedTsdownOptions.unbundle} — which is the whole of its effect: tsdown * already bundles anything the manifest does not declare as a production dependency, * so no `deps` flag is needed to force it. */ readonly bundleNodeModules?: boolean | undefined; } /** * The JS pass: per-module JavaScript, no declarations. * * The build runs TWO tsdown passes per TargetGroup to the SAME outDir: * - pass 1 (this) emits per-module JS (`unbundle: true`) with `dts: false` and the * default `clean: true`, so it starts from a fresh outDir; * - pass 2 (`DerivedDtsPassOptions`) emits ONLY bundled declarations (`unbundle: false`, * `dts: { emitDtsOnly: true }`) with `clean: false`, so it must NOT wipe pass 1. * * We cannot do this in a single pass: tsdown's `unbundle` maps to rolldown * `output.preserveModules` for the WHOLE build, and the dts plugin shares it — so one pass * gives EITHER per-module JS + per-module dts OR bundled JS + bundled dts. Per-module dts * breaks type portability (TS2883) when a package exports only its root entry, and bundling * the JS re-bundles workspace consumers (e.g. silk re-bundling silk-effects crashes at * runtime). The split keeps per-module JS (no re-bundle hazard) AND bundled, self-contained * declarations (no TS2883). * * **`unbundle` flips to `false` when `bundleNodeModules` is set.** `bundleNodeModules: true` * exists to produce a genuinely self-contained artifact (its own TSDoc already promises this), * but `preserveModules` (the per-module JS pass) writes every inlined node_modules dependency * out to its OWN sibling file, mirroring its `node_modules/.pnpm/...` (or workspace) path * relative to the package root — for BOTH esm and cjs. `npm pack` unconditionally strips any * directory literally named `node_modules` from the published tarball, so an esm entry built * this way throws `Cannot find module '.../node_modules/.pnpm/.../foo.js'` once packed and * installed (the cjs sibling accidentally escapes this: tsdown's own dts pass, which always * runs `unbundle: false`, re-emits and overwrites a dual-format build's `.cjs` JS chunk as a * side effect of emitting `.d.cts` — see the dts-pass rebuild note in `buildTargetGroups` — so * only the esm artifact keeps the broken preserveModules layout). Turning `unbundle` off for * the JS pass whenever `bundleNodeModules` is requested makes BOTH formats bundle into one * self-contained file, matching what the flag already promises and what the cjs side already * does by accident. Scoped to `bundleNodeModules` alone: every other build keeps the default * per-module dev-friendly layout unchanged. * @public */ interface DerivedTsdownOptions { readonly outDir: string; readonly sourcemap: boolean; readonly minify: boolean; readonly format: ReadonlyArray; /** `false` only when `bundleNodeModules` is set — see the interface TSDoc above. */ readonly unbundle: boolean; /** JS pass starts fresh; it owns the outDir before the dts pass appends to it. */ readonly clean: true; readonly platform: BuildPlatform; /** * Controls output file extensions. Always false for this builder. * * tsdown 0.22.2 finding (verified by running a real esm+cjs build of a type:module package): * - With fixedExtension: false, tsdown emits ESM index.js plus CJS index.cjs for a * type:module package in the JS pass. There is no collision: tsdown derives the .js * extension for ESM and the .cjs extension for CJS automatically. An earlier M1.1 note * claimed the two formats collide on ambient .js under fixedExtension: false; that claim * was wrong and is corrected here. * - This .js plus .cjs scheme is the one we want. It matches the rslib parity target, where * silk's dual-format output uses import: .js, require: .cjs, and a single types: .d.ts, and * it matches the flat manifest the emit-manifest transform writes. * - Setting fixedExtension: true would instead yield .mjs plus .cjs (and .d.mts plus .d.cts), * which is NOT wanted, so dual-format needs no fixedExtension change and we leave it false. * - The matching `.d.ts` / `.d.cts` declarations are emitted by the SEPARATE dts pass (see * `DerivedDtsPassOptions`), which keeps `unbundle: false` so the declarations are rolled up. */ readonly fixedExtension: false; readonly entry: Record; /** JS pass emits no declarations; the dts pass owns them. */ readonly dts: false; readonly define: Record; readonly isProd: boolean; /** * CJS named-export interop, the equivalent of rslib's cjsInterop: true. This is the real * tsdown option name, so it threads straight to the build with no rename. * * tsdown 0.22.2 finding (verified against the dist Options dts plus the build source): * - cjsDefault is a top-level boolean, default true. The build maps it to rolldown's * output.exports: cjsDefault ? "auto" : "named", and also silences the MIXED_EXPORT * warning. With "auto", a module whose only default-style export is a single default * becomes module.exports = value, while named exports stay attached, so a require() call * returns the value directly and named exports survive, the interop rslib gives with * cjsInterop: true. * - We only set it (to true) when cjs is in the format, so esm-only builds leave the tsdown * default untouched and stay byte-identical to before. */ readonly cjsDefault?: boolean | undefined; } /** * Derive the JS-pass tsdown options for one TargetGroup (per-module JS, no dts). * * @public */ export declare function deriveTargetGroupOptions(options: DeriveOptions): DerivedTsdownOptions; //#endregion //#region src/build/loose-files.d.ts /** * One standalone bundled output file, declared by its literal output filename. * * @public */ interface LooseFileSpec { /** Source module to bundle into the file. */ readonly source: string; /** Module format. Required only for an ambiguous `.js` key; inferred from `.mjs`/`.cjs`. */ readonly format?: BuildFormat | undefined; } /** * Map of literal output filename to its source (bare string) or a `{ source, format }` spec. * * @public */ type LooseFiles = Record; /** * A loose file resolved to a concrete build descriptor. * * @public */ interface NormalizedLooseFile { /** Literal output filename written into the package dir, e.g. `pnpmfile.mjs`. */ readonly outFile: string; /** tsdown entry name (outFile without its extension), e.g. `pnpmfile`. */ readonly entryName: string; /** Source module to bundle. */ readonly source: string; /** Resolved module format. */ readonly format: BuildFormat; /** * Whether tsdown should use fixed extensions. `.mjs`/`.cjs` need `true` (tsdown derives * `.mjs` for esm and `.cjs` for cjs); a `.js` + esm output needs `false` (tsdown derives `.js`). */ readonly fixedExtension: boolean; } /** * Resolve a `looseFiles` map into normalized build descriptors. Pure (no filesystem): * a missing `source` is surfaced later by tsdown's entry resolution. Throws * {@link ConfigValidationError} on any structural problem so the bundler's ConfigValidator * surfaces it as a typed, fast-fail config error. * @public */ export declare function normalizeLooseFiles(files: LooseFiles): ReadonlyArray; //#endregion //#region src/build/build-target-groups.d.ts /** * Signature compatible with tsdown's `build(inlineConfig)`. * * @public */ type TsdownBuild = (config: Record) => Promise; /** * CSS handling for a partition's JS pass, forwarded VERBATIM to tsdown's `css` option (consumed * by `@tsdown/css`). Structurally typed so tsdown-plugins takes no dependency on `@tsdown/css`. * The package whose runtime is built must install `@tsdown/css`; tsdown loads it lazily. * @public */ interface CssOptions { readonly modules?: boolean | { readonly localsConvention?: string; readonly namedExport?: boolean; readonly [k: string]: unknown; }; readonly [k: string]: unknown; } /** * One entry partition built with its own format + bundling posture, layered into the * SAME outDir as the base build (clean:false). Each partition is built from ITS OWN values * only — an option this override omits is simply absent for this partition, not inherited * from the base build (partition 0 in `buildTargetGroups`). Callers that want a base-build * value to also apply to an override must pass it again explicitly. This is relied upon * deliberately by at least one consumer: `packages/silk/savvy.build.ts` has an override that * depends on NOT inheriting the base build's externals. `entry` is a subset of the package's * entries (`entryName -> source path`). * @public */ interface EntryOverride { readonly entry: Record; readonly format?: ReadonlyArray | undefined; readonly externals?: ReadonlyArray | undefined; readonly bundle?: ReadonlyArray | undefined; readonly bundleNodeModules?: boolean | undefined; readonly bundledPackages?: ReadonlyArray | undefined; readonly dtsExternals?: ReadonlyArray | undefined; /** JS-pass platform for this partition. Defaults to the base "node". Use "browser" for a web runtime. */ readonly platform?: BuildPlatform | undefined; /** CSS handling forwarded to tsdown's `css` option (JS pass only). Enables `@tsdown/css`. */ readonly css?: CssOptions | undefined; /** * Build this partition into `//` instead of the shared group root. * Isolates a sub-package (e.g. an RSPress `./runtime`) so its bundleless per-file output cannot * collide with the base partition's output and its barrel path is deterministic. The partition's * entry should be `{ index: }` so it emits `/index.js` + `/index.d.ts`. */ readonly outSubdir?: string | undefined; } /** @public */ interface BuildTargetGroupsOptions { readonly cwd: string; readonly version: string; readonly entry: Record; readonly tsconfigPath: string; readonly groups: ReadonlyArray; readonly devManifest: "preserve" | "resolve"; readonly externals?: ReadonlyArray; /** * Packages externalized in the dts pass ONLY — emitted as `import ... from "..."` * references in the `.d.ts` rather than inlined — while the JS pass still bundles * them per `bundleNodeModules`. The dts pass `neverBundle` becomes the union of * `externals` and `dtsExternals`. Use when a dependency's types cannot be safely * inlined into a single bundled declaration file (e.g. effect's cross-module * `declare module` augmentations, which inline into conflicting interface * extensions in consumers). The JS pass is unaffected. */ readonly dtsExternals?: ReadonlyArray | undefined; /** * External packages whose declarations are inlined into the bundled dts * (rslib `dtsBundledPackages` equivalent). Forwarded to the dts pass as * `deps.dts.alwaysBundle` alongside `deps.neverBundle: true`; unlike * `deps.onlyBundle` this does not enable tsdown's strict-mode check that * errors on every unlisted transitive dependency. The JS pass is unaffected. */ readonly bundledPackages?: ReadonlyArray | undefined; /** * Force-bundle node_modules (and workspace) JS dependencies that are not * externalized, restoring the rslib bundle-everything-except-externals * behavior. Acts through the JS pass's `unbundle: false` posture, NOT through a * `deps` flag: bundling node_modules is already tsdown's default for anything the * manifest does not declare as a production dependency. The dts pass mirrors it by * likewise leaving that default in place, so the bundled declarations are also * self-contained. Defaults to false (current behavior). */ readonly bundleNodeModules?: boolean | undefined; /** * Force-bundle (inline) these packages into the JS output (tsdown `deps.alwaysBundle`), * even declared deps that would otherwise be auto-externalized. The inverse of * `externals`. Forwarded to the JS pass AND, identically, to the dts pass and the * prod-only per-module declarations pass — the dts pass RE-EMITS the dual-format `.cjs` * chunk (see `buildTargetGroups`'s class doc), so a force-bundled dependency must stay * inlined there too, or the re-emitted `.cjs` re-externalizes it. */ readonly bundle?: ReadonlyArray | undefined; /** Output formats to emit. Defaults to esm-only when unset. */ readonly format?: ReadonlyArray | undefined; /** * Minify the JS output of PROD groups only (dev is never minified). Defaults to * false — this builder targets Node libraries where readable output is preferred. */ readonly minify?: boolean | undefined; readonly transform?: (args: { pkg: Json; targetGroup: TargetGroupRef; }) => Json; /** * Extra rolldown plugins, forwarded to BOTH the JS pass and the dts-only pass. A plugin * with JS-lifecycle side effects (asset emitters, banner injectors) runs in both passes; * the dts pass uses `emitDtsOnly`, so for esm-only builds it produces no JS chunks and most * rolldown hooks are no-ops there. For DUAL (esm+cjs) builds, however, tsdown's dts pass * still RE-EMITS the `.cjs` JS chunk and overwrites the JS pass's `.cjs` output — so a * `renderChunk`/`generateBundle` plugin that must persist onto the final `.cjs` (e.g. the * built-in cjs-default-interop) has to run in the dts pass too. A caller relying on a hook * firing exactly once should guard the second invocation. */ readonly extraPlugins?: ReadonlyArray; /** * Compile-time global replacements forwarded to BOTH the JS and dts passes' `define`. * Build-wide (shared by every entry partition); merged after the auto-injected * `process.env.__PACKAGE_VERSION__` so a user key of the same name wins. */ readonly define?: Record | undefined; /** * Entry partitions with their own format/bundling, built into the same outDir after * the base entries. Used for per-entry format overrides (e.g. one CJS entry in an * otherwise ESM-only package). The base `entry` must already EXCLUDE these entries. */ readonly overrides?: ReadonlyArray | undefined; /** * Standalone bundled output files emitted at literal paths into each group's pkg/ dir, * outside the exports/dts/meta graph (e.g. pnpm config-dependency pnpmfiles). Each runs as * one extra single-entry, bundled (unbundle:false), no-dts, no-manifest pass per group, * inheriting the group's bundleNodeModules/bundle/externals posture so the file is * self-contained. Caller passes the normalized form (see normalizeLooseFiles). */ readonly looseFiles?: ReadonlyArray | undefined; /** * Which export keys get a CJS `require` condition in the emitted manifest. Pass a Set * when overrides give different entries different formats; omit for the uniform * `format`-includes-cjs behavior. */ readonly dualExports?: DualExports | undefined; /** Export keys built into a `/index.*` subdir (e.g. an RSPress `./runtime`). */ readonly subdirExports?: ReadonlySet | undefined; /** When set, rewrite the emitted manifest's exports/bin values equal to the exe source to the SEA path and add it to `files`. */ readonly exeRewrite?: ExeRewrite | undefined; /** Injectable for tests; defaults to tsdown's build. */ readonly build?: TsdownBuild; /** When set, muzzle tsdown (silent + customLogger) and capture metrics/timing into this collector. */ readonly collector?: BuildCollector | undefined; /** Compute gzip sizes for emitted files (verbose render). Forwarded to the metrics plugin. */ readonly verbose?: boolean | undefined; /** * Emit a per-module (`unbundle: true`) declaration tree into `dist/prod//declarations/` per * group, in addition to the bundled dts in `pkg/`. API Extractor's diagnostics-run input for the * meta pass. Prod-only; the bundler sets it for `--target prod`. Absent → no third pass * (byte-identical to the two-pass default). Not captured by the collector. Has no effect when * `emitDts` is `false` — the declarations pass exists only to feed the dts-derived meta pass. */ readonly emitDeclarations?: boolean | undefined; /** * When `false`, skip BOTH the bundled per-entry dts pass (Pass 2) and the prod per-module * declarations pass (Pass 3) — no TypeScript compiler load. The JS pass (Pass 1) and * `copyPublicDir` still run. Defaults to `true` (current two/three-pass behavior). */ readonly emitDts?: boolean | undefined; } /** * Run tsdown.build() per TargetGroup. Composable so the escape hatch gets multi-group too. * * Each group runs TWO passes to the SAME outDir: * 1. JS pass — per-module JS (`unbundle: true`, `dts: false`), with the `emitManifest` plugin * and the `public/` copy. Default `clean: true` gives it a fresh outDir. * 2. dts pass — bundled declarations only (`unbundle: false`, `dts: { emitDtsOnly: true }`, * `clean: false`). No manifest plugin, no copy, no sourcemaps. `clean: false` is load-bearing: * it must NOT wipe the JS the first pass just wrote. * * Why two passes: tsdown's `unbundle` maps to rolldown `output.preserveModules` for the whole * build (JS and the dts plugin share it), so a single pass cannot give per-module JS + bundled * dts. Per-module dts breaks type portability (TS2883); bundling the JS re-bundles workspace * consumers. The split keeps per-module JS AND rolled-up, self-contained declarations. * * **The JS pass's `unbundle` flips to `false` for a `bundleNodeModules` partition** (see * `DerivedTsdownOptions` in `target-groups.ts`), so that partition's JS pass ALSO bundles * instead of preserving modules — a per-module preserveModules JS pass writes every inlined * node_modules dependency to its own sibling file (mirroring its `node_modules/...` path), * which `npm pack` then strips, breaking the "self-contained" promise `bundleNodeModules` * already makes. Scoped to that flag alone; every other build's JS pass is unaffected. * @public */ export declare function buildTargetGroups(options: BuildTargetGroupsOptions): Promise; //#endregion //#region src/build/cjs-default-interop.d.ts /** * Rolldown plugin: append the CJS default-interop footer to ENTRY chunks of the * `cjs` format that export a default alongside named exports. * * Gated tightly so it never touches the wrong chunk: * - format must be `cjs` (ESM is untouched; `import().default` on ESM is already correct); * - the chunk must be an ENTRY chunk — never a SHARED chunk. Shared chunks are required by * entry chunks via their named bindings (e.g. `require_changesets.changesets_exports.X`); * reassigning a shared chunk's `module.exports` to its own default would break those reads * (many bundled vendor chunks carry an `exports.default`); * - the chunk must export a `default` AND at least one named export. A default-only chunk * already gets `module.exports = ` from rolldown, and a named-only chunk has no * default to promote. * * The emitted footer is also self-guarded (`module.exports.default !== void 0`), so it is a * runtime no-op whenever the static gate is ever too generous. * @public */ export declare function cjsDefaultInterop(): Plugin; //#endregion //#region src/build/node-builtin-default-interop.d.ts /** * Rewrite a default import / default re-export of a Node built-in into the * equivalent NAMESPACE form, so rolldown's CJS codegen produces correct interop. * * Why this exists — a rolldown 1.1.0 codegen defect (verified against the latest * published rolldown 1.1.0 / tsdown 0.22.2, with no newer release to upgrade to): * * ```ts * // SOURCE (e.g. vfile's lib/minproc.js) * export {default as minproc} from 'node:process' * // ...consumed as minproc.cwd() * * // rolldown CJS OUTPUT (BROKEN) * let node_process = require("node:process"); * node_process.default.cwd() // <- require("node:process").default is undefined * ``` * * For a default import of an EXTERNAL Node builtin, rolldown emits a bare * `require("node:x")` WITHOUT its `__toESM` interop wrapper, yet still accesses * `.default` — which is `undefined` on a builtin's CJS export object, so the call * throws `Cannot read properties of undefined (reading 'cwd')` at runtime. NAMED * imports are unaffected (`(0, node_process.cwd)()` reads a real property), and a * NAMESPACE import is handled correctly: rolldown wraps it as * `node_process = __toESM(require("node:process"), 1)`, which synthesizes `.default` * and copies every own property, so member access works. This transform converts the * broken default form into the working namespace form BEFORE codegen, so it is immune * to minification and applies identically to per-module and bundled output. * * rolldown exposes no Rollup-style `output.interop` knob to fix this at the output * layer, which is why the correction happens here on the source. * * Rewrites (the two static forms that occur in practice, anchored to statement start): * * ```ts * import NAME from "node:x" -> import * as NAME from "node:x" * export { default as NAME } from "node:x" -> export * as NAME from "node:x" * import NAME, { a, b } from "node:x" -> import * as NAME from "node:x"; import { a, b } from "node:x" * ``` * * The namespace binding NAME carries the builtin's named exports (`NAME.cwd`, * `NAME.join`, ...), which is exactly how a default import of a builtin is consumed * in practice. ESM output is unaffected at runtime (a namespace import of a builtin * resolves to the same members), so the plugin is safe to attach to dual builds. * @public */ export declare function nodeBuiltinDefaultInterop(): Plugin; //#endregion //#region src/build/strip-maps.d.ts /** * Remove declaration source-map files (`.d.ts.map` / `.d.cts.map`) from a built `pkg` * directory, returning the removed paths. * * The dts pass emits these next to each `.d.ts` (the resolved dts tsconfig sets * `declarationMap: true`) because API Extractor reads them during meta generation to * resolve original-source positions. But they are dead weight in a PUBLISHED package — * they reference `.ts` sources the tarball does not ship — and they leak local source * paths, so the prod build strips them AFTER meta generation has consumed them. The dev * build keeps them (it is never published, and `savvy build --target meta` reads them). * * Recurses, but skips `node_modules` so it does not traverse a self-contained bundle's * vendored tree — only the package's own emitted declarations carry maps worth stripping. * @public */ export declare function removeDeclarationMaps(pkgDir: string): string[]; //#endregion //#region src/errors.d.ts declare const MetaGenerationError_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & { readonly _tag: "MetaGenerationError"; } & Readonly; /** * API Extractor meta generation failed for an entry. * * @public */ export declare class MetaGenerationError extends MetaGenerationError_base<{ readonly entry: string; readonly reason: string; }> { get message(): string; } declare const ConfigValidationError_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & { readonly _tag: "ConfigValidationError"; } & Readonly; /** * A savvy.build.ts or publishConfig.targets config is structurally invalid; raised before any build work. * * @public */ export declare class ConfigValidationError extends ConfigValidationError_base<{ readonly path: string; readonly reason: string; }> { get message(): string; } declare const TsdoctorEmitError_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & { readonly _tag: "TsdoctorEmitError"; } & Readonly; /** * Writing the `tsdoctor.json` sidecar failed — the composed manifest did not encode, or the file * could not be written (a read-only or full disk). Recorded in `issues.json` as a `meta` error. * * @public */ export declare class TsdoctorEmitError extends TsdoctorEmitError_base<{ readonly packageName: string; readonly path: string; readonly cause: unknown; }> { get message(): string; } //#endregion //#region src/entry/extract.d.ts /** @public */ interface PackageJsonLike { readonly exports?: unknown; readonly bin?: unknown; } /** @public */ interface ExtractOptions { readonly exportsAsIndexes?: boolean | undefined; /** Source paths to NOT turn into JS build entries (e.g. an exe entry compiled as a SEA). */ readonly excludeSources?: ReadonlyArray | undefined; } /** @public */ interface ExtractResult { /** entry name to TS source path */ readonly entries: Record; /** entry name to original export key (for downstream output-map alignment) */ readonly exportPaths: Record; } /** * Map an export key to the tsdown entry name (the emitted output basename). * * `.` becomes `index`; otherwise the leading `./` is stripped and, unless * `exportsAsIndexes` is set, nested slashes are flattened to dashes * (e.g. `./changesets/markdownlint` to `changesets-markdownlint`). The manifest * transform reuses this so the declared output path always matches the emitted file. * * @internal */ export declare const createEntryName: (exportKey: string, exportsAsIndexes: boolean) => string; /** @public */ export declare function extractEntries(pkg: PackageJsonLike, options?: ExtractOptions): ExtractResult; //#endregion //#region src/entry/ambient-dts.d.ts /** The declaration-file extension of a path, or undefined when it is not a declaration file. @public */ export declare function declarationExt(p: string): ".d.ts" | ".d.cts" | ".d.mts" | undefined; /** Classification of a single export value for ambient-.d.ts handling. @public */ type DtsExportClass = { readonly kind: "ambient"; readonly source: string; } | { readonly kind: "mixed"; } | { readonly kind: "none"; }; /** * Classify an export value: * - `ambient` — a types-only declaration source (bare `.d.ts` string, or `{ types: "*.d.ts" }` with no runtime source). * - `mixed` — a declaration `types` AND a compilable runtime source (`import`/`require`/`default` → `.ts`/`.tsx`). * - `none` — anything else (normal runtime export, json, etc.). * @public */ export declare function classifyDtsExport(value: unknown): DtsExportClass; /** * Output basename (including the preserved declaration extension) for an ambient export, derived * from the export KEY — consistent with how JS entries are named. @public */ export declare function ambientOutName(exportKey: string, source: string, exportsAsIndexes?: boolean): string; /** The shared mixed-export error (Decision 2), used by both the extractor and the manifest transform. @public */ export declare function mixedDtsExportError(exportKey: string): ConfigValidationError; /** One ambient `.d.ts` export resolved for copy + manifest. @public */ interface AmbientDtsEntry { readonly exportKey: string; readonly source: string; readonly outName: string; } /** @public */ interface ExtractAmbientOptions { readonly exportsAsIndexes?: boolean | undefined; } /** * Extract the types-only `.d.ts` exports from a package's `exports` map. Pure. * Throws {@link ConfigValidationError} on a mixed export (Decision 2) or an ambient-vs-ambient * output-name collision. @public */ export declare function extractAmbientDts(pkg: PackageJsonLike, options?: ExtractAmbientOptions): ReadonlyArray; /** * Throw {@link ConfigValidationError} if any ambient output name collides with a JS build-entry name. * The JS entry names carry no extension, so each ambient `outName` is compared with its declaration * extension stripped. @public */ export declare function assertNoEntryCollisions(jsEntryNames: ReadonlyArray, ambient: ReadonlyArray): void; //#endregion //#region src/build/sync-public.d.ts /** * Copy the CONTENTS of `sourceDir` into `outDir`, additively. * * Each `sourceDir/` copies to `outDir/` — only the `public/` directory itself is dropped; * the substructure under it is preserved (`public/tsconfig/ecma.json` becomes `/tsconfig/ecma.json`, * NOT `/ecma.json`). The published manifest mirrors this drop via `transformExports`, which strips * a leading `public/` from export values. This function NEVER deletes: `outDir` is the shared package * root that the JS/dts passes own, so deleting "files not in source" would wipe the build product. * Stale-asset pruning on a non-clean rebuild is therefore out of scope (a full build's `clean: true` handles it). * * Collision guard: when a destination already exists, identical bytes mean a prior copy of the same * asset (skipped); anything else — differing bytes, a directory where a file is needed, or a file * where a parent directory is needed — means a built output occupies that path, so it throws * {@link ConfigValidationError} rather than clobbering it or surfacing a raw fs error. * @public */ export declare function copyPublicDir(sourceDir: string, outDir: string): void; /** @public */ interface CopyAmbientDtsOptions { /** The ambient exports to copy (from `extractAmbientDts`). */ readonly ambient: ReadonlyArray; /** Package root the `source` paths are relative to. */ readonly srcCwd: string; /** The built package dir to copy into (e.g. `dist/dev/pkg`). */ readonly outDir: string; } /** * Copy each ambient `.d.ts` export's source verbatim into `outDir/`, byte-stable (an * unchanged file keeps its timestamp). The copy is NOT compiled or bundled, so the build owns two * fast-fail checks: the source must exist, and it must be self-contained — a relative * import/export/reference would not resolve once the file is flattened to the package root. * * Throws {@link ConfigValidationError} on a missing source or any relative specifier. * @public */ export declare function copyAmbientDts(options: CopyAmbientDtsOptions): void; //#endregion //#region src/catalog/resolve-catalogs.d.ts /** * Minimal shape of a `package.json` manifest needed to resolve catalog and * workspace specifiers. * * @public */ interface ManifestLike { readonly name: string; readonly version: string; dependencies?: Record; devDependencies?: Record; peerDependencies?: Record; optionalDependencies?: Record; [k: string]: unknown; } /** * Resolve every `catalog:`/`workspace:` specifier in a manifest to a concrete spec, * delegating to `@effected/workspaces`' one-shot `Workspaces.resolveManifest`. The * resolver re-discovers the workspace root from `process.cwd()` on every call (run * this from inside the target workspace) and assembles catalogs durably (inline + * config-dependency hook-replay + lockfile), so no transient * `.pnpm-workspace-state-v1.json` is required. * * Rejects with `ManifestDecodeError` when a dependency field is not a string-to-string * record, `UnresolvedDependencyError` on a specifier the workspace cannot answer, or * `CatalogAssemblyError`/`DependencyResolutionError` when catalog assembly or the * resolution mechanism itself fails. * @public */ export declare function resolveManifest(pkg: ManifestLike): Promise; //#endregion //#region src/changesets/next-versions.d.ts /** * Result of resolving next release versions for a workspace. * * @public */ interface NextVersions { /** Monorepo root containing `.changeset/` (or `cwd` when no workspace was found). */ readonly root: string; /** Canonical package name `->` next release version (current version when unbumped). */ readonly versions: ReadonlyMap; } /** * Resolve the next release version of every workspace package from pending changesets. * * Walks up from `cwd` to the monorepo root via `@effected/workspaces`' `WorkspaceDiscovery`, * seeds the map with each package's CURRENT version, then overlays `newVersion` for * changeset-affected packages via `@changesets/get-release-plan`. Never rejects: any failure * (not a workspace, missing `.changeset/config.json`, parse error) degrades to current * versions (or an empty map). * @public */ export declare function resolveNextVersions(cwd: string): Promise; //#endregion //#region src/exe/config.d.ts /** * Default Node runtime embedded in the SEA (parity with the vitest-agent reference). * * @public */ export declare const DEFAULT_EXE_NODE_VERSION = "25.9.0"; /** * A resolved per-platform SEA target. `platform` uses the tsdown/\@tsdown/exe token (win, not win32). * * @public */ interface ExeTarget { readonly platform: "darwin" | "linux" | "win"; readonly arch: "arm64" | "x64"; readonly nodeVersion: string; } /** * A target before nodeVersion defaulting (platform/arch only). * * @public */ interface ExeTargetInput { readonly platform: "darwin" | "linux" | "win"; readonly arch: "arm64" | "x64"; } /** * SEA seaConfig overrides (subset; the rest are defaulted). * * @public */ interface ExeSeaConfig { readonly disableExperimentalSEAWarning?: boolean | undefined; readonly useCodeCache?: boolean | undefined; readonly useSnapshot?: boolean | undefined; } /** * One SEA binary to compile. * * @public */ interface ExeConfig { /** Output binary basename (no extension/suffix). */ readonly fileName: string; /** Bin entry; defaults to ./src/bin.ts. */ readonly entry?: string | undefined; /** Node runtime to embed; defaults to DEFAULT_EXE_NODE_VERSION. */ readonly nodeVersion?: string | undefined; /** seaConfig overrides merged over the defaults. */ readonly seaConfig?: ExeSeaConfig | undefined; /** Explicit targets; default inferred from the package os/cpu. */ readonly targets?: ReadonlyArray | undefined; } /** * Fully-resolved SEA binary spec (no optionals). * * @public */ interface NormalizedExe { readonly fileName: string; readonly entry: string; readonly targets: ReadonlyArray; readonly seaConfig: { readonly disableExperimentalSEAWarning: boolean; readonly useCodeCache: boolean; readonly useSnapshot: boolean; }; } /** * The package's own os/cpu fields, used to infer a single platform target. * * @public */ interface PkgOsCpu { readonly os: ReadonlyArray; readonly cpu: ReadonlyArray; } /** * Normalize `exe` (object or array) into one fully-resolved spec per binary. * * Pure function; structural validation (missing fileName, empty targets) lives in the * config-validation layer. * @public */ export declare function normalizeExeOptions(exe: ExeConfig | ReadonlyArray, pkg: PkgOsCpu): ReadonlyArray; //#endregion //#region src/meta/tsdoctor-config.d.ts /** * What an Open Graph image generator receives: the merged identity of the * package being built, after the config, leaf and project tiers resolved. * * @public */ interface OgImageInfo { /** Display name — the merged `name`, falling back to the npm name. */ readonly name: string; /** The npm package name. */ readonly packageName: string; /** The emitted version (the optimistic next version when enabled). */ readonly version: string; readonly tagline?: string | undefined; readonly description?: string | undefined; /** The inherited project tier, when the workspace root declares one. */ readonly project?: { readonly name?: string | undefined; readonly tagline?: string | undefined; } | undefined; } /** * The `meta.tsdoctor` block: the CONFIG tier of the emitted `tsdoctor.json`, * ranked over the package's `tsdoctor.json` (leaf) and the workspace root's * (project). * * @public */ interface TsdoctorMetaOptions { readonly name?: string | undefined; readonly tagline?: string | undefined; readonly description?: string | undefined; readonly openGraph?: { /** Static images, path (bundle-relative) or url. Listed after a generated image. */ readonly images?: ReadonlyArray | undefined; readonly themeColor?: string | undefined; /** Render an image at build time; the bytes are written to `meta/og/.png` and listed first. */ readonly generate?: ((info: OgImageInfo) => Promise) | undefined; } | undefined; /** Registries; `false` disables the default derived from `targets.json`. */ readonly registries?: ReadonlyArray | false | undefined; } //#endregion //#region src/meta/config.d.ts /** * A single TSDoc tag definition (parity with api-extractor's TSDoc config). * * @public */ interface TsdocTagDefinition { readonly tagName: string; readonly syntaxKind: "block" | "inline" | "modifier"; readonly allowMultiple?: boolean | undefined; } /** * An api-extractor message-suppression rule. messageId is exact-matched; pattern (regex or substring) is AND-matched against the text. * * @public */ interface WarningSuppressionRule { readonly messageId: string; readonly pattern?: string | undefined; } /** * TSDoc / doc-warning configuration. suppressWarnings is doc functionality, so it lives here. * * @public */ interface TsdocOptions { readonly suppressWarnings?: ReadonlyArray | undefined; readonly tagDefinitions?: ReadonlyArray | undefined; } /** * The `meta` field on defineBuild. Absent means no api-model generation. * * @public */ interface MetaOptions { /** Directories to copy the canonical group's api-model into after `savvy build --target prod`. */ readonly localPaths?: ReadonlyArray | undefined; /** * Forward-look the meta bundle's own `version` and workspace-sibling dep versions to their * NEXT release version from pending changesets. `"auto"` (default) is `false` under CI * (`CI`/`GITHUB_ACTIONS` set) and `true` locally, so a local bundle matches the CI release build. */ readonly optimistic?: "auto" | boolean | undefined; readonly tsdoc?: TsdocOptions | undefined; /** * The CONFIG tier of the emitted `tsdoctor.json` sidecar (ranked over the package's and the * workspace root's `tsdoctor.json` source files) and the optional build-time Open Graph image. * The project tier is found through workspace discovery, which requires the workspace root's * `package.json` to declare a `version`; without one, discovery fails silently and no `project` * tier is emitted. */ readonly tsdoctor?: TsdoctorMetaOptions | undefined; } /** * Fully-resolved meta options (no optionals). * * @public */ interface NormalizedMeta { readonly localPaths: ReadonlyArray; readonly optimistic: boolean; readonly tsdoc: { readonly suppressWarnings: ReadonlyArray; readonly tagDefinitions: ReadonlyArray; }; /** Passed through verbatim; `undefined` means no config tier (the source tiers still apply). */ readonly tsdoctor: TsdoctorMetaOptions | undefined; } /** * Fill defaults so downstream code never branches on undefined. * * @public */ export declare function normalizeMetaOptions(meta: MetaOptions, env?: { CI?: string | undefined; GITHUB_ACTIONS?: string | undefined; }): NormalizedMeta; //#endregion //#region src/targets/config.d.ts /** * A single object-form publish target. Uses `from` XOR `name` (never both). * * @public */ interface PublishTargetObject { /** Registry endpoint. Required for custom keys; defaulted for `npm`/`github`. */ readonly registry?: string | undefined; /** Name override for this target's own group. Mutually exclusive with `from`. */ readonly name?: string | undefined; /** Reuse another target's group bytes (deploy them to this registry). Mutually exclusive with `name`. */ readonly from?: string | undefined; } /** * A `publishConfig.targets` value: `true` (well-known registry, base name), a string (name override), or an object. * * @public */ type PublishTargetValue = true | string | PublishTargetObject; /** * The `publishConfig.targets` map, keyed by target id (`npm`, `github`, or a custom key). * * @public */ type PublishTargets = Record; /** * A distinct byte-variant build group (one per distinct resolved name). * * @public */ interface ResolvedGroup { /** Folder id; the group's output dir nests this id under dist/prod, with a pkg subfolder. */ readonly id: string; /** The `package.json.name` this group's manifest carries. */ readonly name: string; /** The group's pkg output dir, relative to the package root. */ readonly dir: string; } /** * A resolved registry target (one per `publishConfig.targets` key). * * @public */ interface ResolvedTarget { /** The `publishConfig.targets` key. */ readonly id: string; /** The group id whose bytes this target deploys. */ readonly group: string; /** The resolved name for that group. */ readonly name: string; /** The resolved registry endpoint. */ readonly registry: string; } /** * The full resolution of `publishConfig.targets`: the distinct groups to build, and every target bound to one. * * @public */ interface TargetResolution { readonly groups: ReadonlyArray; readonly targets: ReadonlyArray; } /** * True when a target value is the object form (carries registry/name/from). * * @public */ export declare function isTargetObject(value: PublishTargetValue): value is PublishTargetObject; //#endregion //#region src/config-validation/ConfigValidator.d.ts /** * The normalized facts the validator checks, assembled by the bundler before any build work. * * @public */ interface ValidationInput { readonly baseName: string; /** Whether the package declares an exports map (for the model-without-exports cross-field rule). */ readonly hasExports: boolean; readonly targets?: PublishTargets | undefined; readonly exe?: ExeConfig | ReadonlyArray | undefined; readonly osCpu?: { readonly os: ReadonlyArray; readonly cpu: ReadonlyArray; } | undefined; readonly meta?: MetaOptions | undefined; /** Standalone bundled output files; validated structurally (extension/format) before any build. */ readonly looseFiles?: LooseFiles | undefined; } declare const ConfigValidator_base: Context.ServiceClass Effect.Effect; }>; /** * Fast-fail config validator; runs first in the bundler over the resolved config. * * @public */ export declare class ConfigValidator extends ConfigValidator_base { static readonly layer: Layer.Layer; } //#endregion //#region src/dts/reexport-stub.d.ts /** * The analysis of an entry source treated as a candidate re-export barrel. * * @public */ interface ReexportBarrelAnalysis { /** Value (non-type-only) names the module re-exports, after `as` aliasing. */ readonly valueNames: ReadonlyArray; /** Type-only names the module re-exports (`export type { … }`), after `as` aliasing. */ readonly typeNames: ReadonlyArray; /** * True iff EVERY top-level statement is a NAMED re-export `from` another module * (`export { … } from "…"` / `export type { … } from "…"`). A module that declares anything * locally, re-exports a namespace (`export * as NS from`), star-re-exports (`export * from`), or * has a bare `export { … }` without `from` is NOT a pure named barrel and cannot be expressed as * a thin re-export stub of another entry. */ readonly isPureNamedReexportBarrel: boolean; } /** * The set of names a module exports, plus whether that set is fully known. * * @public */ interface ModuleExportNames { readonly names: ReadonlySet; /** * False when the module contains a star re-export (`export * from "…"`) whose target exports * cannot be enumerated from this source alone — the name set is then a lower bound, not complete, * so callers must not use it for a strict subset decision. */ readonly complete: boolean; } /** * Analyze an entry source as a candidate pure re-export barrel: classify its re-exported names into * value vs type-only and report whether it is expressible as a thin stub. Pure parsing — no I/O. * * @public */ export declare function analyzeReexportBarrel(source: string, fileName?: string): ReexportBarrelAnalysis; /** * Collect every name a module exports (named re-exports, namespace re-exports, and local `export` * declarations). Used to test whether a barrel's re-exports are a strict subset of a base entry, so * a stub re-exporting from that base resolves every symbol. Pure parsing — no I/O. * * @public */ export declare function collectExportNames(source: string, fileName?: string): ModuleExportNames; /** * Render a thin re-export-stub `.d.ts`/`.d.cts` body: named re-exports of `valueNames` and * `typeNames` from `baseSpecifier` (the published file of the base entry, e.g. `./index.js` for the * ESM `.d.ts` or `./index.cjs` for the CJS `.d.cts`). Names are sorted so the output is * deterministic. Returns the empty string when there is nothing to re-export. * * @public */ export declare function renderReexportStub(options: { readonly valueNames: ReadonlyArray; readonly typeNames: ReadonlyArray; readonly baseSpecifier: string; }): string; //#endregion //#region src/dts/relative-imports.d.ts export declare function findRelativeSpecifiers(source: string, fileName?: string): string[]; //#endregion //#region src/dts/resolved-tsconfig.d.ts /** @public */ interface ResolvedTsconfigOptions { /** Absolute package root. */ readonly cwd: string; /** TS `compilerOptions.jsx` override (e.g. "react-jsx"); wins over the resolved config. */ readonly jsx?: string | undefined; /** TS `compilerOptions.jsxImportSource` override (e.g. "react"); wins over the resolved config. */ readonly jsxImportSource?: string | undefined; } /** @public */ interface ResolvedTsconfig { readonly compilerOptions: Record; readonly include: ReadonlyArray; readonly exclude: ReadonlyArray; } /** * Build the portable absolute-path tsconfig object for the dts pass. * * @remarks * Resolves the package's own `/tsconfig.json` (which extends the shared * `ecma.json` base) through `@effected/tsconfig-json`'s `TsconfigLoaderSync`, so the * result carries the package's real effective options — target, module, lib, strict, * jsx — with `${configDir}` already substituted to absolute paths. Only the dts-pass * overlay (composite/incremental/tsBuildInfoFile forced off, declarationMap forced on) * and an explicit jsx override are layered on top. * * `include`/`exclude` are NOT taken from the resolved config. The shared base includes * `__test__` and `lib` sources, which have no business in a declaration program; the * narrow list below is dts-pass-specific and deliberately held fixed. * * @public */ export declare function buildResolvedTsconfig(options: ResolvedTsconfigOptions): ResolvedTsconfig; /** * Write the resolved tsconfig to a temp file and return its absolute path. * * @public */ export declare function writeResolvedTsconfig(options: ResolvedTsconfigOptions): string; /** * Derive a dts-EMIT variant of an already-written resolved tsconfig that adds * `stableTypeOrdering: true`, and return its path. This makes the TypeScript declaration emitter * (rolldown-plugin-dts on `typescript@6`) order union/type members deterministically, so a * multi-union `.d.ts` (e.g. an Effect `Layer.Layer<…>` requirement channel) does not flip member * order across otherwise-identical builds (#156). It is kept in a SEPARATE file from the * api-extractor tsconfig on purpose: `@microsoft/api-extractor` pins `typescript ~5.9`, which * predates the flag and hard-errors on the unknown compiler option — so only the emit passes * (which run on TS6) ever see it, while the api-extractor compile reads the original clean config. * * Best-effort: if the base tsconfig cannot be read or parsed (e.g. a synthetic test path that was * never written), the original path is returned unchanged — the emit then simply keeps TS's * default ordering rather than aborting the build at this layer. * * @public */ export declare function writeDtsEmitTsconfig(resolvedTsconfigPath: string): string; //#endregion //#region src/entry/package-json-entries.d.ts /** @public */ interface PackageJsonEntriesOptions extends ExtractOptions { /** In-memory package.json. If omitted, reads `/package.json`. */ readonly pkg?: PackageJsonLike; /** Working directory for reading package.json. Defaults to process.cwd(). */ readonly cwd?: string; } /** * Derive a tsdown `entry` record (name to source path) from a package.json. * * @public */ export declare function packageJsonEntries(options?: PackageJsonEntriesOptions): Record; //#endregion //#region src/exe/build.d.ts /** * A minimal structural type for tsdown's build, kept loose so this package keeps no tsdown runtime dep (interface-only). * * @public */ type ExeBuild = (config: unknown) => Promise; /** * Options for compiling SEA binaries. * * @public */ interface RunExeBuildOptions { readonly cwd: string; /** Directory the binaries are emitted into (e.g. dist/dev/pkg/bin). */ readonly outDir: string; /** One fully-resolved spec per binary. */ readonly specs: ReadonlyArray; /** Injectable tsdown build (defaults to tsdown's build function). */ readonly build?: ExeBuild | undefined; /** When set with groupId, muzzle tsdown and record an "exe" pass into this collector. */ readonly collector?: BuildCollector | undefined; /** Target-group id the exe pass belongs to (required to record into the collector). */ readonly groupId?: string | undefined; /** Compute gzip sizes (verbose render). */ readonly verbose?: boolean | undefined; } /** * Compile each SEA binary via tsdown's exe mode. One tsdown build per spec. * * @public */ export declare function runExeBuild(options: RunExeBuildOptions): Promise; //#endregion //#region src/exe/filename.d.ts /** * The exact filename `@tsdown/exe` emits for a SEA target, mirroring tsdown's * `resolveOutputFileName`: base fileName + `--` + `.exe` on win. * Single source of truth so the manifest value never drifts from the on-disk file. * @public */ export declare function computeExeFileName(fileName: string, target: ExeTarget): string; //#endregion //#region src/jsx/config.d.ts /** * Resolved JSX transform settings. The shape mirrors the subset of rolldown's JsxOptions, but the * bundler consumes it to populate the generated dts tsconfig's `jsx`/`jsxImportSource`, not by * forwarding it into rolldown's input options. * * @public */ interface JsxConfig { /** "automatic" auto-imports the JSX factories (react-jsx); "classic" does not (React.createElement). */ readonly runtime?: "classic" | "automatic" | undefined; /** The JSX import source for the automatic runtime (e.g. "react", "preact"). */ readonly importSource?: string | undefined; } /** * The jsx-relevant slice of a tsconfig's compilerOptions. * * @public */ interface TsconfigJsx { readonly jsx?: string | undefined; readonly jsxImportSource?: string | undefined; } /** * Resolve the effective JSX config: an explicit override wins; otherwise infer from the tsconfig * values via `@effected/tsconfig-json`'s `JsxConfig.fromCompilerOptions`. Returns undefined when * no JSX transform is needed (preserve/none). * @public */ export declare function resolveJsxConfig(tsconfig: TsconfigJsx, override: JsxConfig | undefined): JsxConfig | undefined; /** * Read the jsx-relevant compilerOptions from a package's own tsconfig.json (best-effort; * returns empty on absence or parse error). Resolved through `@effected/tsconfig-json`'s * sync loader, so JSONC syntax and `extends` chains are honored. * @public */ export declare function readTsconfigJsx(cwd: string): TsconfigJsx; //#endregion //#region src/meta/tsdoctor-manifest.d.ts /** * A `targets.json` target as the manifest composer sees it: the human label and the registry endpoint. * * @public */ interface ManifestTarget { readonly name: string; readonly registry: string; } /** * Everything {@link composeTsdoctorManifest} needs: the three authoring tiers plus the build facts * that derive the rest. * * @public */ interface ComposeManifestInput { readonly config: TsdoctorMetaOptions | undefined; readonly leaf: ManifestSource | undefined; readonly project: ManifestSource | undefined; readonly packageName: string; readonly isPrivate: boolean; /** `targets.json` targets for the group being emitted. */ readonly targets: ReadonlyArray; /** The image `og-image.ts` wrote, already sized. */ readonly generatedImage: OpenGraphImage | undefined; /** The emitted manifest's `repository` field; a GitHub Packages target derives its page URL from it. */ readonly repository?: ManifestRepository | undefined; } /** * The `repository` field of the emitted `package.json`, as far as the manifest composer reads it. * * @public */ interface ManifestRepository { readonly url: string; readonly directory?: string | undefined; } /** * `owner/repo` from any of the GitHub URL spellings a `repository.url` carries (https, `git+https`, * `git@`, `ssh://`, `git://`, the `github:` shorthand), or `undefined` for anything else. * * @public */ export declare function githubOwnerRepo(url: string): { readonly owner: string; readonly repo: string; } | undefined; /** * Derive the registries block from the build's targets. Only for a public * package: a private one is published nowhere. * * @public */ export declare function registriesFromTargets(input: Pick): ReadonlyArray; /** * Flatten the three authoring tiers into the emitted manifest. Pure. * * @remarks * Config beats leaf beats project per FIELD; the project tier is emitted * nested, never flattened, because the consumer's provenance ranking depends * on telling the tiers apart. Returns `undefined` when there is nothing to * say, so a package with no metadata emits no file. An `sbom` pointer is * never written here — the release action upserts it at publish. * * @public */ export declare function composeTsdoctorManifest(input: ComposeManifestInput): BundleManifest | undefined; /** * What the generator sees. Built from the same tiers as the manifest. * * @public */ export declare function ogImageInfoOf(input: ComposeManifestInput & { readonly version: string; }): OgImageInfo; //#endregion //#region src/meta/generate.d.ts /** @public */ interface GenerateMetaOptions { readonly cwd: string; readonly packageName: string; /** Resolved tsconfig (from writeResolvedTsconfig) for the api-extractor compiler. */ readonly tsconfigPath: string; /** Directory holding the tsdown-emitted per-file .d.ts (e.g. dist/dev/pkg). */ readonly dtsDir: string; /** * Per-module declarations dir used ONLY for a second, diagnostics-only API Extractor run that * resolves accurate per-file source locations. The shipped api-model is still produced from * `dtsDir` (the bundled dts), so it is unchanged. When omitted or equal to `dtsDir`, a single * run over `dtsDir` produces both model and diagnostics (legacy behavior). */ readonly aeInputDir?: string | undefined; /** Map of entry name to the .d.ts basename (without extension) inside dtsDir. */ readonly entries: Record; /** Map of entry name to its export path (".", "./sub"). */ readonly exportPaths: Record; /** Where to write the meta bundle (.api.json + package.json + tsconfig.json). */ readonly outMetaDir: string; /** Directories (relative to cwd) to copy the meta bundle into. */ readonly localPaths: ReadonlyArray; readonly tsdoc: NormalizedMeta["tsdoc"]; /** * Optional transform applied to the bundle `package.json` (read from `dtsDir`) before it is * written to `outMetaDir` and copied into `localPaths`. Used for the optimistic next-version * rewrite. When omitted, the package.json is copied verbatim. */ readonly manifestTransform?: ((pkg: Record) => Record) | undefined; /** When set, API Extractor warnings/errors are routed here (and suppressed from console). */ readonly onMessage?: ((entry: DiagnosticInput) => void) | undefined; /** When true (CI), forgotten exports become a hard build error. */ readonly ci?: boolean | undefined; /** When set, messages matched by `suppressWarnings` are routed here for accounting. */ readonly onSuppressed?: ((entry: DiagnosticInput) => void) | undefined; /** * The `tsdoctor.json` sidecar inputs: the config tier, the two source tiers, and the targets bound * to this group (registries derive from them). Omitted means no sidecar and no Open Graph image. */ readonly tsdoctor?: { readonly config: TsdoctorMetaOptions | undefined; readonly leaf: ManifestSource | undefined; readonly project: ManifestSource | undefined; readonly targets: ReadonlyArray; } | undefined; } /** @public */ interface MetaResult { readonly apiJsonPath: string; readonly apiJsonFilename: string; } /** * Generate the api-model meta bundle from already-emitted .d.ts. Writes tsdoc.json (idempotent), * runs the extractor per entry, merges if needed, and writes the "virtual TS env" trio to * outMetaDir (`.api.json` + the final `package.json` + a portable `tsconfig.json`), * copying that trio into each localPaths dir. The api-extractor `tsdoc-metadata.json` is a * published-package artifact and is written into `dtsDir` (the built pkg/), not the meta bundle. * @public */ export declare function generateMeta(options: GenerateMetaOptions): Promise; //#endregion //#region src/meta/og-image.d.ts declare const OgGenerateError_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & { readonly _tag: "OgGenerateError"; } & Readonly; /** * A configured `openGraph.generate` renderer threw, returned no bytes, or returned bytes that are * not an image. Fails the build: a half-written OG image is worse than none. * * @public */ export declare class OgGenerateError extends OgGenerateError_base<{ readonly packageName: string; readonly cause: unknown; }> { get message(): string; } /** * Options for {@link writeGeneratedOgImage}. * * @public */ interface WriteGeneratedOgImageOptions { readonly generate: (info: OgImageInfo) => Promise; readonly info: OgImageInfo; /** The meta bundle dir; the image lands at `og/.` beneath it. */ readonly outMetaDir: string; readonly unscopedName: string; } /** * Run the generator, size the bytes, and write `og/.` under the meta dir. Returns the * manifest image entry (bundle-relative path, MIME type, dimensions). * * @public */ export declare function writeGeneratedOgImage(options: WriteGeneratedOgImageOptions): Promise; //#endregion //#region src/meta/optimistic.d.ts /** * Rewrite a meta `package.json` so the package's own `version` and any workspace-sibling * dependency version reflect their NEXT release version from `versions`. Pure: returns a new * object, never mutates the input. External/catalog-resolved deps (names absent from `versions`) * are left as-is. * @public */ export declare function rewriteMetaVersions(pkg: Record, versions: ReadonlyMap, selfName: string): Record; //#endregion //#region src/meta/tsdoctor-source.d.ts declare const TsdoctorSourceError_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & { readonly _tag: "TsdoctorSourceError"; } & Readonly; /** * A present `tsdoctor.json` source file that could not be parsed or decoded. Absence is never * this error — a missing source tier is the normal case. * * @public */ export declare class TsdoctorSourceError extends TsdoctorSourceError_base<{ readonly path: string; readonly cause: unknown; }> { get message(): string; } /** * The two source tiers a build reads: the package's own file and the workspace root's. * * @public */ interface TsdoctorSources { readonly leaf: ManifestSource | undefined; readonly project: ManifestSource | undefined; /** * Why workspace discovery failed, when it did. The project tier is then unknown rather than * absent; `runMetaPass` records it as a `meta` warning so the degradation is visible in `issues.json`. */ readonly discoveryFailure?: string | undefined; } /** * Read the leaf (`/tsdoctor.json`) and project (`/tsdoctor.json`) * source tiers. Absence is normal; a present file that does not decode throws * {@link TsdoctorSourceError}. A package that IS the workspace root reads its file once, as the * leaf, and has no project tier. * * @public */ export declare function loadTsdoctorSources(cwd: string): Promise; //#endregion //#region src/meta/run-pass.d.ts /** * Options for the meta-pass orchestrator. * * @public */ interface RunMetaPassOptions { readonly cwd: string; readonly packageName: string; readonly tsconfigPath: string; readonly groups: ReadonlyArray<{ id: string; name: string; }>; readonly entries: Record; readonly exportsMap: Record | undefined; readonly overrides?: ReadonlyArray<{ entries: ReadonlyArray; outSubdir?: string | undefined; }> | undefined; readonly meta: MetaOptions; readonly collector: BuildCollector; readonly ci: boolean; /** Injectable for tests; defaults to the real generateMeta. */ readonly generateMeta?: (o: GenerateMetaOptions) => Promise; /** Injectable for tests; defaults to the real resolveNextVersions. Only called when optimistic. */ readonly resolveNextVersions?: (cwd: string) => Promise<{ versions: ReadonlyMap; }>; /** * The resolved `targets.json` targets; each group's `tsdoctor.json` derives its registries from the * targets bound to that group. Omitted (an escape-hatch build with no resolution) means none. */ readonly targets?: ReadonlyArray<{ group: string; id: string; registry: string; }> | undefined; /** Injectable for tests; defaults to the real loadTsdoctorSources. */ readonly loadTsdoctorSources?: (cwd: string) => Promise; } /** * Meta-pass orchestrator: derives export paths, filters bin/ entries, resolves optimistic * next-versions, and calls generateMeta once per publish group. * @public */ export declare function runMetaPass(o: RunMetaPassOptions): Promise; /** * Map entry names to export paths using the package exports map. index maps to ".". * * @public */ export declare function deriveExportPaths(entries: Record, exportsMap: Record | undefined): Record; /** * For each `outSubdir` override, point its meta entry at the isolated sub-package barrel. * * @public */ export declare function applySubdirMetaEntries(overrides: ReadonlyArray<{ entries: ReadonlyArray; outSubdir?: string | undefined; }> | undefined, dtsBasenames: Record, exportPaths: Record): void; //#endregion //#region src/meta/tsconfig-resolver.d.ts /** * Compiler options with enum values converted to their string equivalents. * * @remarks * Open-ended record because TypeScript compiler options vary by version. * * @public */ interface ResolvedCompilerOptions { [key: string]: unknown; } /** * Portable, JSON-serializable tsconfig.json (compilerOptions-only). * * @remarks * Designed for virtual TypeScript environments (shiki/Twoslash, API Extractor) * where file paths and emit settings are controlled externally. Holds no * machine-specific absolute paths and no emit/path/file-selection options. * * @public */ interface PortableTsconfig { /** JSON schema for IDE support. */ $schema: string; /** Compiler options with enum values converted to strings. */ compilerOptions: ResolvedCompilerOptions; } /** * Resolves the package's effective compiler options (following `extends`) into a * portable, JSON-serializable tsconfig for the meta release bundle. * * @remarks * Resolves the package's own `/tsconfig.json` (which extends the shared * `@savvy-web/bundler/ecma.json` base) via `@effected/tsconfig-json`'s * synchronous `TsconfigLoaderSync` (tsc-parity `extends` resolution) so the * result carries the full effective options (target/module/strict/jsx/lib), * then projects them through the kit's `PortableTsconfig.make` allow-list * filter to a portable, compilerOptions-only shape with no absolute paths or * emit/file-selection options. * * When the package has no own `tsconfig.json` (e.g. a minimal test fixture), * falls back to `fallbackConfigPath` — the build's already-resolved dts tsconfig, * which always exists during a build. If neither is present, returns a minimal * portable config carrying only the virtual-environment flags. * * @param cwd - Absolute package root. * @param fallbackConfigPath - Optional resolved tsconfig to use when the package has no own one. * @returns The portable tsconfig object. * * @public */ export declare function resolvePortableTsconfig(cwd: string, fallbackConfigPath?: string): PortableTsconfig; //#endregion //#region src/report/formatters/types.d.ts /** @public */ interface RenderedOutput { readonly target: "stdout" | "file" | "github-summary"; readonly content: string; readonly contentType: string; } /** @public */ interface FormatterContext { readonly noColor: boolean; readonly verbose: boolean; } /** @public */ interface Formatter { readonly format: string; readonly render: (reports: ReadonlyArray, ctx: FormatterContext) => ReadonlyArray; } //#endregion //#region src/report/formatters/ci-annotations.d.ts /** @public */ export declare const CiAnnotationsFormatter: Formatter; //#endregion //#region src/report/formatters/json.d.ts /** @public */ export declare const JsonFormatter: Formatter; //#endregion //#region src/report/formatters/markdown.d.ts /** @public */ export declare const MarkdownFormatter: Formatter; //#endregion //#region src/report/formatters/silent.d.ts /** @public */ export declare const SilentFormatter: Formatter; //#endregion //#region src/report/formatters/terminal.d.ts /** @public */ export declare const TerminalFormatter: Formatter; //#endregion //#region src/report/issues-artifact.d.ts /** * A diagnostic flattened to a plain JSON object (only defined fields are present). * * @public */ interface PlainDiagnostic { source: DiagnosticEntry["source"]; level: DiagnosticEntry["level"]; text: string; code?: string; ciFatal?: boolean; file?: string; line?: number; column?: number; } /** * The aggregated build-issues artifact written to `dist//issues.json`. * * @public */ interface BuildIssues { generatedAt: string; package: string; target: "dev" | "prod"; /** * Whether the build that produced this artifact reached its end without a terminal failure. * * The artifact is written on EVERY terminal path — success and failure alike — so a reader must * gate on this flag, not on `errors.length`. A crashed build (API Extractor blowing up, a racing * `rm -rf dist`) can leave all three diagnostic buckets empty; without this stamp that file is * byte-identical to a perfectly clean gate. Absent on artifacts written before this field existed; * treat a missing value as unknown rather than as a pass. */ buildOk: boolean; /** The terminal error that ended the build. Present only when `buildOk` is false. */ failure?: { /** The error's `name` (e.g. `"Error"`, `"ConfigValidationError"`), when it has one. */ name?: string; /** The error message, truncated to 2000 characters. */ message: string; }; warnings: PlainDiagnostic[]; errors: PlainDiagnostic[]; suppressed: PlainDiagnostic[]; } /** * Flatten a build snapshot into the aggregated, de-duplicated issues artifact. Pure. * * `buildOk` defaults to `true`, so an existing caller that never fails keeps its current output plus * the stamp; a caller that also writes on a failure path MUST pass `buildOk: false` (and ideally the * `failure`), otherwise the artifact reads as a clean gate. * * @public */ export declare function flattenIssues(reports: ReadonlyArray, opts: { target: "dev" | "prod"; generatedAt: string; buildOk?: boolean | undefined; failure?: { name?: string | undefined; message: string; } | undefined; }): BuildIssues; /** * Serialize the issues artifact to pretty JSON with a trailing newline. * * @public */ export declare function serializeIssues(issues: BuildIssues): string; /** * Write the aggregated issues artifact to `/dist//issues.json`. Returns the path written. * * The write is atomic: the JSON lands in a sibling temp file which is then `rename`d over the * destination, so a concurrent reader observes either the previous artifact or the complete new one, * never a torn or half-written file. Pass `buildOk: false` (plus `failure`, when there is an error to * report) on a failure path — see the `buildOk` field of `BuildIssues`. * * @public */ export declare function writeIssuesArtifact(opts: { cwd: string; target: "dev" | "prod"; reports: ReadonlyArray; now?: () => Date; buildOk?: boolean | undefined; failure?: { name?: string | undefined; message: string; } | undefined; }): string; //#endregion //#region src/report/metrics-plugin.d.ts /** * Rolldown plugin that records emitted-file metrics into the BuildCollector via writeBundle (which * fires for the JS pass AND the emitDtsOnly dts pass — verified against tsdown 0.22.3), plus a * defensive onLog for rolldown-level diagnostics that bypass tsdown's logger. Append it to each * build pass's `plugins` array. `bytes` is taken from the in-memory chunk/asset content (no fs); * `gzip` is computed only when `verbose`. * * Set `suppressMixedExports` for a pass whose emitted CJS carries the `cjsDefaultInterop()` * footer — see the onLog comment below for why rolldown's MIXED_EXPORTS advice does not apply * there. * @public */ export declare function buildMetricsPlugin(collector: BuildCollector, groupId: string, pass: PassKind, verbose: boolean, suppressMixedExports?: boolean): Plugin; //#endregion //#region src/report/services/EnvironmentDetector.d.ts /** @public */ type Environment = "agent-shell" | "terminal" | "ci-github" | "ci-generic"; declare const EnvironmentDetector_base: Context.ServiceClass Effect.Effect; }>; /** @public */ export declare class EnvironmentDetector extends EnvironmentDetector_base { static readonly layer: Layer.Layer; } //#endregion //#region src/report/services/ExecutorResolver.d.ts /** @public */ type Executor = "human" | "agent" | "ci"; declare const ExecutorResolver_base: Context.ServiceClass Effect.Effect; }>; /** @public */ export declare class ExecutorResolver extends ExecutorResolver_base { static readonly layer: Layer.Layer; } //#endregion //#region src/report/services/FormatSelector.d.ts /** @public */ type OutputFormat = "terminal" | "json" | "markdown" | "ci-annotations" | "silent"; declare const FormatSelector_base: Context.ServiceClass Effect.Effect; }>; /** @public */ export declare class FormatSelector extends FormatSelector_base { static readonly layer: Layer.Layer; } //#endregion //#region src/report/services/OutputRenderer.d.ts declare const OutputRenderer_base: Context.ServiceClass, format: OutputFormat, ctx: FormatterContext) => Effect.Effect>; }>; /** @public */ export declare class OutputRenderer extends OutputRenderer_base { static readonly layer: Layer.Layer; } //#endregion //#region src/report/pipeline.d.ts /** @public */ export declare const ReportPipeline: Layer.Layer; /** @public */ interface RenderReportOptions { readonly explicitFormat?: OutputFormat; /** Override env detection (mainly for tests). */ readonly env?: Environment; readonly noColor: boolean; readonly verbose?: boolean; } /** @public */ export declare const renderReport: (reports: ReadonlyArray, options: RenderReportOptions) => Effect.Effect, never, EnvironmentDetector | ExecutorResolver | FormatSelector | OutputRenderer>; //#endregion //#region src/report/timer.d.ts /** @public */ export declare function formatTime(ms: number): string; /** @public */ interface Timer { readonly elapsed: () => number; readonly format: () => string; } /** * Create a wall-clock timer. (Date.now is fine in runtime build code.) * * @public */ export declare function createTimer(now?: () => number): Timer; //#endregion //#region src/report/tsdown-logger.d.ts /** * Structural match for tsdown's Logger interface (tsdown 0.22.x). * * @public */ interface TsdownLogger { level: "info"; info: (...args: unknown[]) => void; warn: (...args: unknown[]) => void; warnOnce: (...args: unknown[]) => void; error: (...args: unknown[]) => void; success: (...args: unknown[]) => void; clearScreen: () => void; } /** * A tsdown `customLogger` that routes warnings/errors into the BuildCollector instead of the * console. Paired with `logLevel: "silent"` in the same build config: silent suppresses tsdown's * own console output while this logger still receives every message (verified against tsdown 0.22.3). * info/success are dropped — file metrics come from the writeBundle plugin and timing from our timer. * @public */ export declare function createTsdownLogger(collector: BuildCollector, groupId: string): TsdownLogger; //#endregion //#region src/targets/binding.d.ts /** * Write the target-to-group binding to dist/prod/targets.json for the release action to consume. Returns the path. * * @public */ export declare function writeTargetsBinding(cwd: string, resolution: TargetResolution): string; //#endregion //#region src/targets/resolve-targets.d.ts /** * Resolve a `publishConfig.targets` map into the distinct groups to build and every target bound to one. Pure; throws ConfigValidationError on structurally-invalid config. * * @public */ export declare function resolveTargets(options: { targets: PublishTargets; baseName: string; }): TargetResolution; //#endregion export { type AmbientDtsEntry, type BuildEmittedManifestOptions, type BuildFormat, type BuildGroupSpec, type BuildIssues, type BuildPlatform, type BuildReport, BuildReport as BuildReportSchema, type BuildTargetGroupsOptions, CatalogAssemblyError, type ComposeManifestInput, type CopyAmbientDtsOptions, type CssOptions, DependencyResolutionError, type DeriveOptions, type DerivedTsdownOptions, type DiagnosticEntry, type DiagnosticInput, type DtsExportClass, type DualExports, type EmitManifestOptions, type EmittedFile, type EntryOverride, type Environment, type ExeBuild, type ExeConfig, type ExeRewrite, type ExeSeaConfig, type ExeTarget, type ExeTargetInput, type Executor, type ExtractAmbientOptions, type ExtractOptions, type ExtractResult, type Formatter, type FormatterContext, type GenerateMetaOptions, type Json, type JsxConfig, type LooseFileSpec, type LooseFiles, ManifestDecodeError, type ManifestLike, type ManifestRepository, type ManifestTarget, type MetaOptions, type MetaResult, type ModuleExportNames, type NextVersions, type NormalizedExe, type NormalizedLooseFile, type NormalizedMeta, type OgImageInfo, type OutputFormat, type PackageJsonEntriesOptions, type PackageJsonLike, type PassKind, type PassReport, type PkgOsCpu, type PlainDiagnostic, type PortableTsconfig, type PublishTargetObject, type PublishTargetValue, type PublishTargets, type ReexportBarrelAnalysis, type RenderReportOptions, type RenderedOutput, type ResolvedCompilerOptions, type ResolvedGroup, type ResolvedTarget, type ResolvedTsconfig, type ResolvedTsconfigOptions, type RunExeBuildOptions, type RunMetaPassOptions, type TargetGroupId, type TargetGroupRef, type TargetGroupReport, TargetGroupReport as TargetGroupReportSchema, type TargetResolution, type Timer, type TransformManifestOptions, type TsconfigJsx, type TsdocOptions, type TsdocTagDefinition, type TsdoctorMetaOptions, type TsdoctorSources, type TsdownBuild, type TsdownLogger, UnresolvedDependencyError, type ValidationInput, type WarningSuppressionRule, type WriteGeneratedOgImageOptions }; //# sourceMappingURL=index.d.ts.map