/** * @copyright Sister Software * @license AGPL-3.0 * @author Teffen Ellis, et al. * * Downloads the INSPIRE Addresses theme Paradigm publishes for the Brussels-Capital Region. * * ## What the publisher offers * * One archive at a bare HTTPS URL, `URBIS_ADM_Adresses.zip`, holding a single member * `UrbAdm_Adresses.gml`. Paradigm publishes no INSPIRE ATOM feed for this theme, so there is no * `` element to poll and no dataset feed to resolve: the URL is the whole acquisition * path. `last-modified` is the one freshness signal the service offers, and this fetcher records it * in the manifest so a later run can tell a refreshed archive from the one it already holds. * * ## Why the archive stays compressed * * `#be/adapters/brussels/adapter` reads the member through `inspireGMLChunks`, which inflates it * through the zip reader rather than from disk. The member is 474,245,978 bytes against the * archive's 11,521,182, so unpacking it here would cost 41 times the disk for no reader that wants * it. * * ## Two hostnames that do not serve it * * `urbis.brussels` and `urbisonline.brussels` both fail TLS with `ERR_TLS_CERT_ALTNAME_INVALID`, * because the certificate's altnames are `*.irisnet.be` and `irisnet.be`. The services live on * `irisnet.be` and the download lives on `datastore.brussels`. */ import { APIClient } from "@mailwoman/core/api"; import { type PathBuilderLike } from "path-ts"; import type { BaseFetchOptions, FetchSummary, SourceManifest } from "#tools/fetch/download"; /** * The archive's URL, which is the whole acquisition path for this theme. */ export declare const BE_BRUSSELS_ARCHIVE_URL = "https://urbisdownload.datastore.brussels/INSPIRE/URBIS_ADM_Adresses.zip"; /** * The name the archive is written under, which is what the adapter's `inputPath` states. */ export declare const BE_BRUSSELS_ARCHIVE_FILENAME = "URBIS_ADM_Adresses.zip"; /** * The attribution CC BY 4.0 ยง3(a)(1) requires on a publication derived from these rows. */ export declare const BE_BRUSSELS_ATTRIBUTION = "Paradigm"; /** * What one run recorded, so a later run can tell a refreshed archive from the one on disk. * * `lastModified` is the publisher's own header. * With no ATOM feed for this theme it is the only freshness signal, and a changed * value is the one reason to download again. */ export interface BrusselsManifest extends SourceManifest { last_modified: string | null; attribution: string; } /** * Per-invocation options. */ export interface DownloadBrusselsOptions { outputDir: PathBuilderLike; /** * Downloads the archive even where the manifest's `lastModified` and byte count still match. */ force?: boolean; retries?: number; retryDelayMs?: number; signal?: AbortSignal; report?: (line: string) => void; } /** * What the publisher's HEAD response states about the archive it holds. * * Both fields read `null` where the header is absent, rather than an empty string or zero. * An absent `last-modified` is the service declining to state a version, which is a * different fact from a version that happens to match the one on disk. */ export interface BrusselsPublication { lastModified: string | null; reportedBytes: number | null; } /** * Reads the publisher's HEAD response. * * Separate from {@linkcode downloadBrussels} because this one request carries the whole freshness * decision, and the download itself runs on global `fetch`, which a unit test cannot intercept. */ export declare function readBrusselsPublication(client: Pick, options?: { signal?: AbortSignal; }): Promise; /** * Whether the archive on disk is the one the publisher currently serves. * * A skip requires the publisher to state a `last-modified` value. * Where it states none, both sides read `null` and an equality test would hold, * which would keep an archive of unknown age for as long as the service stayed silent. * Downloading 11 MiB again is the cheaper error. */ export declare function brusselsPublicationIsRecorded(recorded: BrusselsManifest, bytesOnDisk: number, publication: BrusselsPublication): boolean; /** * Downloads the archive unless the manifest and the file on disk already agree with the publisher. */ export declare function downloadBrussels(client: Pick, options: DownloadBrusselsOptions): Promise; /** * The path `#be/adapters/brussels/adapter` reads, given the root a fetch wrote under. */ export declare function brusselsInputPath(outRoot: BaseFetchOptions["outRoot"]): PathBuilderLike; /** * Per-invocation options for the registry entry. */ export interface FetchBrusselsOptions extends BaseFetchOptions { force?: boolean; retries?: number; retryDelayMs?: number; signal?: AbortSignal; } /** * The registry entry. */ export declare function fetchBrussels(options: FetchBrusselsOptions, report?: (line: string) => void): Promise; //# sourceMappingURL=brussels.d.ts.map