/** * Data-pack loader. * * Recursively scans one or more root directories, parses every file as a * data pack (see parse.ts), and builds a registry mapping a dotted * address to its list of values. * * Addressing (docs/superpowers/specs/2026-07-14-data-packs-design.md): * - Default: derived from the file's path relative to its scan root — * `person/es/man/firstName.txt` -> `person.es.man.firstName` * (folder names become dotted segments, filename is the last segment, * extension ignored). * - Override: a `---`-fenced header may declare `address:` explicitly, * for files that sit loose in the root or need an address that does * not match their folder tree (e.g. `scifi.ship.color`). * * Two files resolving to the same address is an error — the loader does * not guess a winner. Loading never throws; problems are returned as * diagnostics for the caller (TDC / CLI) to surface. */ import type { Diagnostic } from '../errors/index.js'; import { type GeneratorBody } from './generator.js'; import { type LocaleManifest } from './locales.js'; export interface PackEntry { /** Dotted address the list is reachable by, e.g. `person.es.man.firstName`. */ readonly address: string; /** * Data-list entry: the values to uniform-pick from. Present iff this is * a data pack (not a generator). */ readonly values?: readonly string[] | undefined; /** * The file resolved but cannot be used — an empty list, an empty or broken * generator body — and this is the sentence saying why. An entry carrying it * has neither values nor a generator; the validator reports the sentence as * TDC170 at the `value="…"` that asked for the address, which is where the * four ports have always reported it. Registering the address (instead of * pushing an eager error at 1:1) is also what keeps TDC071 from calling a * path that plainly exists on disk "unknown". */ readonly unusable?: string | undefined; /** * Per-value share in percent, parallel to `values`, summing to 100. Present * only for a WEIGHTED data list (header `weighted: true`, or `file:` with a * `weight:` column). When set, the pack is drawn to an exact Hamilton quota * instead of uniformly — so `Smith` appears as often as it does in the Census, * not as often as `Zabrowski`. Absent → uniform, unchanged. */ readonly percents?: readonly number[] | undefined; /** * Generator entry: a parsed generator body (single primitive ``, * or composed local sequences + `` output), executed by the * engine to produce values. Present iff the pack file declared a * `generator:` header. Exactly one of `values` / `generator` is set. */ readonly generator?: GeneratorBody | undefined; /** Addresses this generator references (for load-time validation). */ readonly references?: readonly string[] | undefined; /** * The generator's value is only correct across a whole column, so it must not * be resolved a row at a time. * * Two ways to earn it. The generator may declare a share itself (`` / `percent=`), which `parseGeneratorSpec` sees in the body. Or it * may DRAW from a weighted list, which the body does not say and only the * loaded registry knows — see `propagateWholeColumn`. */ readonly needsWholeColumn?: boolean | undefined; /** Human-readable description from the header, if any. */ readonly description?: string | undefined; /** * The locale this pack belongs to, as a run finds it: the locale its address * starts with, or — for an address outside every locale (`common`, a country) * — the header's `locale:`, else `undefined`. * * It used to be the header alone. 498 of the bundled packs carry no `locale:` * line — `ru.person.lastName` among them — so the registry said they belonged * nowhere while every run found them in `ru`, and a tool asking "which * locales have this path?" advised installing packs that were already there. * And 55 Nepali files say `locale: en` while living, and being found, in `ne`. */ readonly locale?: string | undefined; /** Absolute path of the file that produced this entry (for diagnostics). */ readonly sourceFile: string; } export type PackRegistry = ReadonlyMap; export interface ScanResult { readonly registry: PackRegistry; readonly locales: ReadonlyMap; readonly diagnostics: readonly Diagnostic[]; } /** * Forget every cached scan. * * Needed by anything that installs packs and keeps running — `tdcv2 pack add` * inside a long-lived process, or a test that writes into a root it has already * scanned. A fresh process starts empty, so ordinary runs never call this. */ export declare function clearPackCache(): void; /** * Scan the given root directories and build a pack registry. Roots that * do not exist are skipped silently (so an absent bundled folder in a * published package is not an error). Directory entries are walked in * sorted order for deterministic diagnostics. * * The result is cached per root list for the life of the process; the returned * maps are shared, so callers must treat them as read-only. */ export declare function scanPacks(roots: readonly string[]): ScanResult; export declare function pathToAddress(root: string, file: string): string; /** * Where the packs a run starts from live — the same three questions, in the same * order, in all five implementations: * * 1. `TDCV2_PACKS`, if it names a directory. Written down by hand, so it wins. * 2. The TDC source checkout this build came from, if there is one — see * {@link sourceCheckoutPacks}. In a checkout that is the copy every * implementation reads and the one a contributor edits, so all five see the * same data rather than five drifting copies. * 3. The starter set shipped inside the package. * * Whatever `tdcv2.config.json` and `--data-path` name is layered on top of the * answer, not instead of it. * * For step 3 two layouts have to work, and checking only one is what once made an * installed package unable to generate a single name: * * - **installed** — `/data/packs`, copied in at pack time. From * `dist/data-pack` that is two levels up. * - **in the repo** — `/data/packs`, three levels up from * `typescript/dist/data-pack` (or `typescript/src/data-pack` under tsx). * * The installed layout is checked first so a stale copy left inside the package * cannot be shadowed by the repo copy, and so the common case costs one stat. */ export declare function bundledPacksDir(): string | undefined; /** * `/data/packs`, if this code is running out of a TDC source checkout. * * Walking up for a bare `data/packs` is not enough: that name is ordinary enough * that an unrelated folder above an installed package could answer, and then the * same config would read different data depending on where the user happened to * install it. A directory only counts when it ALSO holds `fixtures/cross-language` * — the folder that holds the contract all five implementations are tested * against, which exists in this repository and nowhere else. */ export declare function sourceCheckoutPacks(startFrom: string): string | undefined; /** * The bundled data packs, scanned once and cached. Used as the default pack * source for the public render/object entry points and the JS facade, so * `person.male.firstName` and friends resolve with zero configuration. Empty * map if the bundled directory is absent (a trimmed published package). */ export declare function bundledPacks(): PackRegistry; /** * Address → the parameter names each generator pack accepts. * * A pack's parameters ARE its local `` names: `tax_office="7712"` * replaces the sequence called `tax_office`. A single-`` pack has none, and * a data-list pack is not a generator at all, so neither appears here — passing * anything to those is always a no-op. Consumed by the validator. */ export declare function packParameterNames(packs: PackRegistry): ReadonlyMap>; /** * The addresses that name a GENERATOR rather than a value list. * * A generator composes each value when it is asked, so there is no list of * values to draw from without replacement — `uniq="true"` over one is refused * by the run, and the validator reads this set to refuse it in `check` first. */ export declare function generatorPacks(packs: PackRegistry): ReadonlySet; /** * Address → the widths its parameters always produce, where that is provable. * * Only composed packs have parameters, and only some of their sequences have a * width that can be read off the spec. An address absent from the inner map * simply has no proven width, and the caller must stay silent about it. */ export declare function packParameterWidths(packs: PackRegistry): ReadonlyMap>; //# sourceMappingURL=load.d.ts.map