/** * @copyright Sister Software * @license AGPL-3.0 * @author Teffen Ellis, et al. * * `gleif-lei`: the GLEIF Level 1 golden copy, read for the legal and headquarters addresses of the * legal entities that hold a Legal Entity Identifier. * * Input is the publisher's own LEI-CDF 3.1 CSV, one record per LEI, as * `https://goldencopy.gleif.org` serves it zipped. `opts.inputPath` is the `.csv.zip` archive, an * extracted `.csv`, or the directory `#tools/fetch/gleif` writes, in which case the newest archive * by its date-prefixed name is read. The CSV member is streamed out of the archive, so the several * gigabytes it decompresses to never sit on disk or in memory. * * ## License * * GLEIF's LEI Data Terms of Use, at {@linkcode GLEIF_LICENSE_URL}, read on 2026-10-03, state: "The * data available through the Access Service are provided under the CC0 licence, see CC0 1.0 * Universal (CC0 1.0)." The Access Service is defined there as the facility that lets users "look-up * and/or download individual LEIs and/or related LE-RD and/or the entire set or a subset of LEIs", * which is the golden copy. GLEIF's open-data page states the same: "The data on GLEIF's website is * provided under a Creative Commons (CC0) license." The same terms ask a user not to create the * impression that derived data or services are provided or endorsed by GLEIF, which is why * {@linkcode GLEIF_ATTRIBUTION} credits the source rather than the corpus. * * ## Organization addresses only * * The register carries legal entities, and three of its fields identify an entity that is a natural * person trading in their own name. {@linkcode readGLEIFEntity} refuses each: * * 1. `Entity.EntityCategory` = `SOLE_PROPRIETOR`. * 2. `Entity.LegalForm.EntityLegalFormCode` naming an ISO 20275 form that is a sole * proprietorship, from {@linkcode GLEIF_SOLE_PROPRIETOR_LEGAL_FORMS}. A registrant can file the * form without the category, and the form is the registrar's own statement of what the entity is. * 3. `Entity.LegalForm.OtherLegalForm`, the free-text form a registrant writes where no ELF code * fits, matching {@linkcode SOLE_PROPRIETOR_FORM_TEXT}: `SOLE TRADER`, `Ditta Individuale`, * `Entreprise Individuelle`, `empresario individual`. * * No check on the legal name is applied. The `Surname, Firstname` test `it-anac` uses matched * company names here (`Experity, Inc`, `Octante, Lda`, `Slovalco, a.s.`) on nearly every hit, and the * category and form fields above are the registrant's and the LOU's own statement. * * `MailRouting` is never read into a row. It holds the care-of line, and on Scandinavian records it * holds a person's name: `c/o Marius Vinje`. A street line that opens with a care-of marker refuses the * address for the same reason. * * ## The street line * * `FirstAddressLine` holds the street and the number together, and `AddressNumber` repeats the * number on a minority of records. The split follows the country's own street order. * {@linkcode houseNumberLeadsStreet} reads that order from the layout `formatAddressRow` renders with. * A number-first country then takes `splitStreetLine` and a number-last country `splitTrailingStreetLine`. * Where the publisher's `AddressNumber` is present, the split must agree with it. * * Three normalizations run first. A copy of the publisher's own `City` value at the start or the end * of the line is removed, because several LOUs write `WARSZAWA PUŁAWSKA 182` with `City` `Warszawa`. * A civic-number marker is removed, so Romania's `Piata Presei Libere, nr. 3-5` splits to the street * `Piata Presei Libere` rather than `Piata Presei Libere, nr.`. A period closing a trailing number, * as Hungary writes `Bagoly utca 23.`, is removed. A whole line of the form `PO BOX 309` then * becomes `po_box` rather than a street. * * **A line holding a digit the split could not place refuses the address**, and so does a line with * no digit at all: in this register a digitless first line is as often a building (`UGLAND HOUSE`, * `KYDD BUILDING`) as a street, and no field separates the two. An English ordinal inside a street name * (`5TH AVENUE`) is a name rather than a number. * * The value the split leaves as `street` must then read as a street. It is refused where it still holds * a comma (`CAVES CORPORATE CENTRE, BUILDING 2` under the Bahamas' number-last layout), where it holds * a building or in-building word (`1302 DOMINION CENTRE`, `903 PLATINUM TOWER`, `APTO 2`), and where it * is a generic word alone (`910 Street`). Each of those numbers a room, an office or a building, and * labeling it `house_number` beside a building name labeled `street` would teach the wrong boundary. * * `AdditionalAddressLine.1`–`3` mix building names, districts, floors and second street lines, and * no field states which, so they reach no row. The golden copy's "AddressNumberWithinBuilding" field becomes `unit` when it * holds a letter, as `Suite 4` does. A bare number there would render as a second house number. * * ## Region * * `Region` is an ISO 3166-2 code such as `SK-KI`, which is not how an address writes the region. * It reaches a row only where the code's suffix is the written form, which * `matchSubdivisionIn` answers for the United States, Canada and Australia. A code whose * country prefix differs from `Country` refuses the address as contradicting it. * * ## One row per address * * Registered agents give one address to thousands of entities. The adapter emits each rendered * address once per country: the key is the address rendered without its venue, and the first * entity read at that address keeps the venue. The headquarters address is read only where it * differs from the legal address in some field. * * Only a country for which `layoutForCountry` returns a layout is emitted. * * The adapter honors `opts.limit`, `opts.signal` and `opts.country`, and counts every refusal in * `opts.dropped`. */ import { type AddressScript } from "@mailwoman/codex/address/layouts"; import { type CanonicalRow, type CorpusAdapter } from "#types"; /** * Registry id for this adapter, stamped into every row it emits. */ export declare const GLEIF_ADAPTER_ID = "gleif-lei"; /** * Countries whose sampled rows show a labeling defect the street split cannot detect, * so none of their rows is emitted until the split handles them. * * - `AE`: the first address line is often an office or unit number before a building name, * as in `601 سويس تاور` and `501 LE SOLARIUM`, which the split reads as a house number and a street. * - `HK`: a floor such as `6F` comes out as the house number, as in `6F MANULIFE PLACE`. * - `BS`: codex records the Bahamas as number-last while its published lines are number-first * (`1 Montague Place`), and a `# 207` suite marker stays inside the street. */ export declare const GLEIF_UNREVIEWED_COUNTRIES: ReadonlySet; /** * The license GLEIF's LEI Data Terms of Use state for the golden copy. */ export declare const GLEIF_LICENSE = "CC0-1.0"; /** * The page that states {@linkcode GLEIF_LICENSE}. */ export declare const GLEIF_LICENSE_URL = "https://www.gleif.org/en/meta/lei-data-terms-of-use"; /** * The credit a model card carries. * * CC0 requires none. * The terms ask that no derived product imply GLEIF's endorsement, so the credit * states the source and claims no relationship with GLEIF. */ export declare const GLEIF_ATTRIBUTION = "Global Legal Entity Identifier Foundation (GLEIF), LEI golden copy (CC0 1.0)"; /** * The publisher's file name for a Level 1 golden copy in CSV, date- and time-prefixed. */ export declare const GLEIF_ARCHIVE_PATTERN: RegExp; /** * ISO 20275 Entity Legal Form codes whose form is a natural person trading in their own name. * * Each code is one the golden copy files under the `SOLE_PROPRIETOR` category, and each is kept * because its name in GLEIF's ELF code list v1.6 (2026-02-19) states that form: `4QIE` is India's * `Sole Proprietorship`, `ZVVM` Poland's `osoby fizyczne prowadzące działalność gospodarczą`, * `OL20` Germany's `Einzelunternehmen, eingetragener Kaufmann`, `RV48` China's `个体工商户`. * Two codes filed under the category are left out because the list describes each as a company: * `HA2W` (Oman, a one-person company) and `AL8W` (Brazil, `Sociedade Limitada Unipessoal`). */ export declare const GLEIF_SOLE_PROPRIETOR_LEGAL_FORMS: ReadonlySet; /** * Why an entity or one of its addresses did not become a row. */ export declare const GLEIFRefusal: { /** * The country is in {@link GLEIF_UNREVIEWED_COUNTRIES}. */ readonly CountryUnreviewed: "country-unreviewed"; /** * `Entity.EntityCategory` is `SOLE_PROPRIETOR`. */ readonly SoleProprietorCategory: "sole-proprietor-category"; /** * The ELF code is a sole-proprietorship form. */ readonly SoleProprietorLegalForm: "sole-proprietor-legal-form"; /** * The free-text legal form states a sole proprietorship. */ readonly SoleProprietorFormText: "sole-proprietor-form-text"; /** * The address states no country. */ readonly CountryAbsent: "country-absent"; /** * The country is not an ISO 3166-1 alpha-2 code. */ readonly CountryNotAlpha2: "country-not-alpha-2"; /** * The ISO 3166-2 region code's country prefix differs from `Country`. */ readonly RegionContradictsCountry: "region-contradicts-country"; /** * Codex holds no layout for the country, so no address line can be rendered. */ readonly CountryWithoutLayout: "country-without-layout"; /** * The address states no city. */ readonly LocalityAbsent: "locality-absent"; /** * The address states no first line. */ readonly StreetLineAbsent: "street-line-absent"; /** * The first line opens with a care-of marker, so it identifies the recipient rather than the place. */ readonly CareOfLine: "care-of-line"; /** * The first line holds no digit, so it cannot be told from a building name. */ readonly StreetLineWithoutNumber: "street-line-without-number"; /** * The first line holds a digit the split could not place as a house number. */ readonly StreetNumberUnplaced: "street-number-unplaced"; /** * The street the split left still holds a comma, so the line joins several parts * (a building, a district, a floor) and the split cannot say which part is the street. */ readonly StreetLineSegmented: "street-line-segmented"; /** * The street the split left is a building or a place inside one * (`PLATINUM TOWER`, `NINTH FLOOR`, `APTO`), so the number beside it numbers a room, * an office or a building rather than a premise on a street. */ readonly StreetHoldsPremiseWord: "street-holds-premise-word"; /** * The street the split left is a generic word alone, as Qatar's `910 Street` leaves `Street`. */ readonly StreetNameGenericOnly: "street-name-generic-only"; /** * The split's house number disagrees with the publisher's own `AddressNumber`. */ readonly StreetNumberDisagrees: "street-number-disagrees"; /** * The components do not render under the country's layout. */ readonly Unrenderable: "unrenderable"; /** * The rendered line carries fewer than two address components besides the venue. */ readonly ComponentsTooFew: "components-too-few"; }; /** * One of the {@link GLEIFRefusal} reasons. */ export type GLEIFRefusal = (typeof GLEIFRefusal)[keyof typeof GLEIFRefusal]; /** * The two address blocks a record carries for its entity. */ export declare const GLEIFAddressBlock: { readonly Legal: "LegalAddress"; readonly Headquarters: "HeadquartersAddress"; }; /** * One of the {@link GLEIFAddressBlock} values. */ export type GLEIFAddressBlock = (typeof GLEIFAddressBlock)[keyof typeof GLEIFAddressBlock]; /** * One CSV record, keyed by the publisher's own column names. */ export type GLEIFRecord = Readonly>; /** * What one address block yielded: a row, or the reason it yielded none. */ export type GLEIFAddressReading = { readonly admitted: CanonicalRow; } | { readonly refused: GLEIFRefusal; }; /** * Whether the entity is a natural person trading in their own name, or otherwise refused whole. * * @returns The refusal, or `null` for an entity whose addresses may be read. */ export declare function readGLEIFEntity(record: GLEIFRecord): GLEIFRefusal | null; /** * Whether the headquarters block states the same address as the legal block, field for field. */ export declare function headquartersRepeatsLegal(record: GLEIFRecord): boolean; /** * Whether the country's layout, in `script`, writes the house number before the street name. * * Read off the layout `formatAddressRow` renders with, so the split and the render cannot disagree. * * @returns `null` where the layout prints no street line. */ export declare function houseNumberLeadsStreet(country: string, script?: AddressScript): boolean | null; /** * The first line with a leading or trailing copy of the publisher's own city removed, * a civic-number marker removed, and a period closing a trailing number removed. * * The city copy is removed only where it equals the `City` field, folded for case, * so the publisher's record authorizes the removal rather than a place-name list. */ export declare function normalizeGLEIFStreetLine(line: string, city: string): string; /** * Read one address block into a row, or report why it yielded none. * * Exported because the refusal reasons are the measurement the adapter is checked by. * The entity-level refusals of {@linkcode readGLEIFEntity} are the caller's to apply first. */ export declare function readGLEIFAddress(record: GLEIFRecord, block: GLEIFAddressBlock): GLEIFAddressReading; export declare function createGLEIFAdapter(): CorpusAdapter; /** * The configured adapter instance registered with the corpus builder. */ export declare const gleifAdapter: CorpusAdapter; //# sourceMappingURL=adapter.d.ts.map