/** * Cross-brand retail store schema. See * `skills/site-reconnaissance/reference/retail-store-locator-schema.md` * for the principle and conventions. */ export interface RetailStoreAddress { readonly line1: string; readonly line2: string | null; readonly locality: string | null; readonly city: string; readonly state: string | null; readonly postalCode: string | null; readonly country: string; } export type RetailStoreStatus = "open" | "coming-soon" | "closed" | "unknown" | null; /** * What KIND of location this record represents. Different industries surface * different types — surfaced by the discovery agents who reconned banking, * FMCG, sales-distribution, and logistics: * * - store — consumer-facing retail (Westside, Zudio, McDonald's) * - dealer — authorized seller (Maruti dealer, LG service touchpoint) * - service-centre — repair / support (Apple service, LG service centre) * - branch — bank branch (SBI branch with IFSC code) * - atm — bank-branded or white-label ATM (Tata Indicash, Hitachi) * - bc-agent — banking correspondent (Airtel Payments Bank, IPPB at kirana) * - depot — warehouse / distribution hub (Asian Paints depot) * - stockist — wholesale distributor (UltraTech, agro-input stockist) * - post-office — postal facility (India Post) * - dark-store — instant-delivery hub (Blinkit, Swiggy Instamart) * - warehouse — 3PL facility (Mahindra Logistics, Allcargo) * - pickup-point — courier pickup / drop-off (Blue Dart pickup point) * - distributor — FMCG channel partner (HUL distributor, ITC dealer) * * The canonical schema is the same — what varies per type is which fields * are populated. ATMs have no hours but have lat/lng; dealers may have phone * but no email; bc-agents have nominal hours of the kirana host shop, etc. */ export type LocationType = "store" | "dealer" | "service-centre" | "branch" | "atm" | "bc-agent" | "depot" | "stockist" | "post-office" | "dark-store" | "warehouse" | "pickup-point" | "distributor"; export interface RetailStore { readonly brand: string; readonly storeId: string | null; readonly name: string; readonly status: RetailStoreStatus; readonly mallOrLocation: string | null; readonly address: RetailStoreAddress; readonly lat: number | null; readonly lng: number | null; readonly phone: string | null; readonly email: string | null; readonly url: string | null; readonly hours: Record | null; /** * What KIND of physical location this is — defaults to "store" for retail * but cross-industry scrapes use this discriminator. See `LocationType`. */ readonly locationType: LocationType; /** Free-text sub-type within `locationType` (e.g. "Flagship", "Express"). */ readonly storeType: string | null; readonly segments: readonly string[]; readonly features: readonly string[]; readonly sourceUrl: string; readonly scrapedAt: string; readonly _extra: Record; } /** * Build a fully-formed `RetailStore` from a partial, filling every canonical * slot with a safe default. Use this to construct records for `scoreCard()` / * `validateBrand()` without hand-writing all 18 fields — only `brand` + `name` * are required. */ export declare function makeRetailStore(partial: Partial & { readonly brand: string; readonly name: string; }): RetailStore; /** * Helper for extractors: build an `_extra` bag by stripping the keys * that already promoted to canonical slots. */ export declare function extraOf>(source: T, promotedKeys: readonly (keyof T)[]): Record; /** Convert a free-form opening-hours string to a normalised window. */ export declare function normaliseHours(input: string | null | undefined): string | null; /** ISO-3166 alpha-2 from common country strings. */ export declare function normaliseCountry(input: string | null | undefined): string;