/** * Lexicon API surface snapshot and diff. * * Extracts a stable, serializable representation of a lexicon's public API * surface from the generated lexicon JSON. Diffs a fresh snapshot against a * committed baseline and classifies each change as additive or breaking. * * The surface is derived from the lexicon registry JSON that every lexicon's * `generate` step writes to `src/generated/.json`. Resource and * property-type names, together with their structural metadata (attrs, props, * kind), form the baseline. The generated .d.ts is not used for diffing * because: (a) it is not self-describing without parsing TypeScript, and * (b) the registry JSON already encodes everything a consumer needs. */ /** * A single entry in the surface snapshot. * "resource" entries carry attrs and props; "property" entries are lightweight. */ export interface SurfaceEntry { kind: "resource" | "property"; /** The cloud-provider resource type string (e.g. "AWS::S3::Bucket"). */ resourceType: string; /** Readonly attribute names (resource entries only). */ attrs?: string[]; /** * Property names with their required flag. Stored as * `name:required` strings (e.g. "BucketName:false", "Tags:false"). * Sorting is stable so the snapshot is deterministic. */ props?: string[]; /** Names that are create-only / immutable after creation. */ createOnly?: string[]; /** * Whether the resource supports tagging. * Present when known; absent means not known or not applicable. */ taggable?: boolean; } /** * The complete surface snapshot for one lexicon. */ export interface SurfaceSnapshot { /** * Schema version for forward-compatibility. Bump when the shape changes * in a way that makes old snapshots unreadable by newer tooling. */ schemaVersion: 1; /** When this snapshot was generated (ISO 8601 UTC). */ generatedAt: string; /** * Per-entry map keyed by the TS export name (e.g. "Bucket", * "Bucket_Tag"). Sorted alphabetically for stable diffs. */ entries: Record; } export type ChangeSeverity = "additive" | "breaking" | "none"; export interface AddedEntry { name: string; entry: SurfaceEntry; } export interface RemovedEntry { name: string; entry: SurfaceEntry; } /** Structural differences between two versions of one entry. */ export interface EntryChanges { /** New resourceType (breaking). */ resourceTypeChanged?: { before: string; after: string; }; /** kind changed from resource to property or vice-versa (breaking). */ kindChanged?: { before: string; after: string; }; /** Props that were removed (breaking). */ removedProps?: string[]; /** Props that switched from optional to required (breaking). */ nowRequired?: string[]; /** Attrs that were removed (breaking). */ removedAttrs?: string[]; /** Props that were newly added. */ addedProps?: string[]; /** Props that switched from required to optional (additive). */ nowOptional?: string[]; /** Attrs that were newly added. */ addedAttrs?: string[]; /** createOnly set changed. */ createOnlyChanged?: { before: string[]; after: string[]; }; /** taggable flag changed. */ taggableChanged?: { before?: boolean; after?: boolean; }; } export interface ChangedEntry extends EntryChanges { name: string; } /** * An entry whose TS export name changed while its kind and resourceType * stayed the same (#1460). Paired from one removal and one addition. */ export interface RenamedEntry { /** TS export name in the baseline. */ from: string; /** TS export name in the fresh surface. */ to: string; /** The entry as it now appears. */ entry: SurfaceEntry; /** Structural differences between the two, when any. */ changes?: EntryChanges; } export interface SurfaceDelta { added: AddedEntry[]; changed: ChangedEntry[]; removed: RemovedEntry[]; /** * Removals and additions paired by kind + resourceType. A rename still * breaks the old import, so it counts as breaking; it is reported apart * from removals so a reader can tell the two kinds of break apart. */ renamed: RenamedEntry[]; /** * Rolled-up severity. "none" means no surface changes at all. * "additive" means only new resources / new optional props / new attrs. * "breaking" means any removal, rename, or change that could break * existing consumers. */ severity: ChangeSeverity; } /** * Extract a surface snapshot from the lexicon JSON and the generated index.d.ts. * * The lexicon JSON contains the resource/property registry (names, kinds, * attrs, createOnly, tagging). The .d.ts provides per-prop names and their * required flags for resource constructor shapes. * * @param lexiconJSON Contents of `src/generated/.json` * @param typesDTS Contents of `src/generated/index.d.ts` */ export declare function extractSurface(lexiconJSON: string, typesDTS: string): SurfaceSnapshot; /** * Lightweight extractor: pull constructor prop names and required flags * from a `.d.ts` string. * * Handles the pattern generated by writeConstructor: * ``` * export declare class Bucket { * constructor(props: { * BucketName?: string; * Tags: Bucket_Tag[]; * }, attributes?: CFResourceAttributes); * } * ``` * * Returns a Map * where each entry is sorted alphabetically. */ export declare function extractPropsFromDts(dts: string): Map; /** * Diff a fresh snapshot against a committed baseline. * * Classification rules: * - Added entry → additive * - Removed entry → breaking * - Changed entry: * - resourceType changed → breaking * - kind changed → breaking * - prop removed → breaking * - prop now required (was optional) → breaking * - attr removed → breaking * - createOnly changed → breaking (changes immutability contract) * - taggable: false→undefined or true→false → breaking * - prop added (optional) → additive * - prop now optional (was required) → additive * - attr added → additive * - taggable: false→true or undefined→true → additive */ export declare function diffSurface(baseline: SurfaceSnapshot, fresh: SurfaceSnapshot): SurfaceDelta; /** * Serialize a snapshot to stable JSON. Suitable for writing to * `surface.snapshot.json` at the lexicon root. */ export declare function serializeSnapshot(snapshot: SurfaceSnapshot): string; /** * Parse a snapshot from JSON. */ export declare function parseSnapshot(json: string): SurfaceSnapshot; /** * Render a surface delta as human-readable text. */ export declare function formatDelta(delta: SurfaceDelta): string; //# sourceMappingURL=surface-snapshot.d.ts.map