/** * @copyright Sister Software * @license AGPL-3.0 * @author Teffen Ellis, et al. * * Derive the committed address-source register from a research pass's two CSVs. * * The second input is mostly not input: the eight global discovery lookups repeat once per jurisdiction and are dropped, because they name a lookup rather than a national source. */ import type { PathBuilderLike } from "path-ts"; import { JurisdictionResearchState, SourceStatus, type AddressSourceRecord, type ElectedLicense, type LicenseDecision, type RefusedLicense } from "#source-register"; /** * What the build produced, for a caller that wants to print it rather than re-read the file. */ export interface SourceRegisterBuildResult { outPath: string; jurisdictions: number; sources: number; licenses: number; /** * Rows dropped because their source identifies a global discovery lookup rather than a national source. */ discoveryRailRowsDropped: number; researchStates: Readonly>; statuses: Readonly>; } export interface BuildSourceRegisterOptions { /** * The 250-row jurisdiction inventory CSV. */ inventoryPath: PathBuilderLike; /** * The functional-authority CSV, discovery lookups included. * * This build drops them. */ sourcesPath: PathBuilderLike; outPath: PathBuilderLike; /** * License decisions somebody made by reading a publisher's terms, applied over the * `unchecked` defaults this build derives from the research pass's access labels. * * An input rather than an edit of the output, because the register is generated * and {@linkcode buildSourceRegister} rewrites it whole. * A path that does not exist is read as no decisions recorded. */ decisionsPath?: PathBuilderLike; /** * Source fields a review resolved, applied over the rows this build derives from the research CSV. * * An input rather than an edit of the output, for the same reason as {@linkcode * BuildSourceRegisterOptions.decisionsPath}: this build rewrites the register whole. * A path that does not exist is read as no resolutions recorded. */ resolutionsPath?: PathBuilderLike; version: string; /** * ISO 8601 calendar date the research pass was taken, `yyyy-MM-DD`. */ authoredAt: string; /** * The research document the pass was written against, recorded in the register's provenance. */ sourceVersion?: string; } /** * Replace every retired word in one string. */ export declare function rewriteRetiredVocabulary(text: string): string; /** * A column's value, or `undefined` when the research pass left it unresolved. * * Every value outside the placeholder set is returned, so a value somebody fills in * later reaches the register or fails the build rather than being lost. */ export declare function readUnresolvedColumn(value: string | undefined, column: string, row: number): string | undefined; /** * Build the register and write it, refusing to write one that fails the audit. * * The output is tab-indented JSON. * `oxfmt` applies additional formatting. * * @throws When an input row contains a vocabulary this build has no mapping for, when a declared * rewrite never fires, or when the finished register fails {@linkcode auditAddressSourceRegister}. */ /** * The shape of `license-decisions.json`: license id to the decision minus its own id, * keyed by id so each license has one decision. */ /** * A decision body without its own id, as `license-decisions.json` records one. */ type RecordedDecision = Omit | Omit; /** * A decision that reuses a body declared once under `sharedReadings`. * * One publisher can hold a license over several jurisdictions, and the register * scopes a decision to one publisher in one jurisdiction, so reading that publisher's * terms once produces several decisions with the same body. * Naming the shared body keeps each license id's own decision while the prose behind * it has one home, so nine copies cannot drift apart under later editing. */ interface SharedDecisionReference { sameAs: string; } /** * The shape of `license-decisions.json`. */ export interface LicenseDecisionsFile { decisions?: Record; /** * Decision bodies that several license ids reuse, keyed by a name the ids refer to. */ sharedReadings?: Record; } /** * The source fields a review resolves, which the research CSV records as placeholders. * * The CSV holds the research pass's findings and is a working document of that pass, * so a later review records its own findings here rather than by editing the pass's record. */ type SourceResolution = Pick; /** * Merges each recorded resolution onto the source whose id it holds. * * @throws When a resolution's source id is absent from the register. * Such an entry is a typo or a source that has been removed. * Keeping it silently would leave a review whose fields reach no row, which reads as work already done. */ export declare function applySourceResolutions(sources: readonly AddressSourceRecord[], recorded: ReadonlyMap): AddressSourceRecord[]; /** * Turns a decisions file into decisions keyed by license id, resolving every `sameAs` reference. * * The id comes from the key, so a record cannot disagree with the license it is filed under. * `auditAddressSourceRegister` decides whether the resolved fields form a well-formed decision, so this * function checks only that the file declares a reading for each reference. * * @throws When a `sameAs` reads a reading absent from `sharedReadings`. * Such a reference would otherwise produce a decision carrying no terms, which the audit * would report as an unknown review state rather than as the typo it is. */ export declare function resolveRecordedDecisions(file: LicenseDecisionsFile): Map; export declare function buildSourceRegister(options: BuildSourceRegisterOptions): Promise; export {}; //# sourceMappingURL=build.d.ts.map