import type { ElementSet } from "../satellites/types.ts"; import type { ObjectKind } from "./kinds.ts"; /** * The radar size class Space-Track gives an object: small (under 0.1 square metres), medium or large (over 1). * * @example * ```ts * import type { RadarSize } from "@johnmorrisdotca/chikyu-earth/catalogue"; * * const size: RadarSize = "L"; * console.log(size); * ``` */ export type RadarSize = "S" | "M" | "L"; /** * One object of the catalogue: its element set (the OMM numbers every source serves), what kind of object it is, and what the catalogue says of its owner and launch. Anything the catalogue leaves blank is left out, never guessed. * * @example * ```ts * import type { CatalogueRecord } from "@johnmorrisdotca/chikyu-earth/catalogue"; * * const record: CatalogueRecord = { * set: { OBJECT_NAME: "MADE-UP 1", OBJECT_ID: "2026-001A", EPOCH: "2026-11-08T04:12:35.430048", MEAN_MOTION: 15.2, ECCENTRICITY: 0.0002, INCLINATION: 53, RA_OF_ASC_NODE: 10, ARG_OF_PERICENTER: 90, MEAN_ANOMALY: 20, NORAD_CAT_ID: 900001, BSTAR: 0.0001, MEAN_MOTION_DOT: 0.00001, MEAN_MOTION_DDOT: 0 }, * kind: "PAY", * owner: "US", * launch: "2026-01-05", * }; * console.log(record.set.NORAD_CAT_ID, record.kind); * ``` */ export interface CatalogueRecord { set: ElementSet; kind: ObjectKind; /** The owner's country or organisation code, as the catalogue writes it ("US", "PRC", "CIS"), up to 8 characters. */ owner?: string; /** The launch date, `yyyy-mm-dd`, or just the year. */ launch?: string; size?: RadarSize; } /** * The most records one packed file holds: the data door's own limit, 200,000. * * @example * ```ts * import { MAX_PACKED } from "@johnmorrisdotca/chikyu-earth/catalogue"; * * console.log(MAX_PACKED); * ``` */ export declare const MAX_PACKED = 200000; /** * The most bytes a packed file may unpack to (64 MB): a file that claims more is refused before it is read. * * @example * ```ts * import { MAX_PACKED_BYTES } from "@johnmorrisdotca/chikyu-earth/catalogue"; * * console.log(MAX_PACKED_BYTES / 1_048_576); * ``` */ export declare const MAX_PACKED_BYTES: number; /** * A packed file that cannot be read: it is not a packed file, it is cut short, it holds more than `MAX_PACKED` records, or it unpacks to more than `MAX_PACKED_BYTES`. * * @param message - What is wrong with the file, in a sentence. * @example * ```ts * import { PackError, unpackCatalogue } from "@johnmorrisdotca/chikyu-earth/catalogue"; * * try { * unpackCatalogue(new Uint8Array(4)); * } catch (error) { * console.log(error instanceof PackError); * } * ``` */ export declare class PackError extends Error { constructor(message: string); } /** * Pack catalogue records into one file: a small header (the format, how many records, and `meta`, a few words of text such as where the data is from and when it was retrieved), a column for each number and, last, the names. * The epoch is kept to the microsecond and the mean motion in full; the angles, the eccentricity and the drag terms are kept as 32-bit floats (an angle to about 0.00003 degrees, well inside what the elements are good to). * A record whose numbers are not finite, or whose catalogue number is not a whole number from 0 up to 4,294,967,295, is refused with a `PackError`. * * @param records - The records, in the order the file keeps them (at most `MAX_PACKED`). * @param meta - Words to keep with the file (read back as `meta`). * @returns The bytes. Gzip them with `gzipBytes` for a file a site hosts. * * @example * ```ts * import { packCatalogue, unpackCatalogue, type CatalogueRecord } from "@johnmorrisdotca/chikyu-earth/catalogue"; * * const record: CatalogueRecord = { * set: { OBJECT_NAME: "MADE-UP 1", OBJECT_ID: "2026-001A", EPOCH: "2026-11-08T04:12:35.430048", MEAN_MOTION: 15.2, ECCENTRICITY: 0.0002, INCLINATION: 53, RA_OF_ASC_NODE: 10, ARG_OF_PERICENTER: 90, MEAN_ANOMALY: 20, NORAD_CAT_ID: 1_000_001, BSTAR: 0.0001, MEAN_MOTION_DOT: 0.00001, MEAN_MOTION_DDOT: 0 }, * kind: "DEB", * }; * const bytes = packCatalogue([record], { group: "debris" }); * const back = unpackCatalogue(bytes); * console.log(bytes.length, back.count, back.setAt(0).NORAD_CAT_ID, back.meta["group"]); * ``` */ export declare function packCatalogue(records: readonly CatalogueRecord[], meta?: Readonly>): Uint8Array; /** * A packed file, read: the columns as typed arrays (nothing is copied into objects until you ask) and the names. * * @example * ```ts * import { packCatalogue, unpackCatalogue, type PackedCatalogue } from "@johnmorrisdotca/chikyu-earth/catalogue"; * * const empty: PackedCatalogue = unpackCatalogue(packCatalogue([], { group: "none" })); * console.log(empty.count, empty.sets().length); * ``` */ export interface PackedCatalogue { /** The words kept with the file. */ meta: Readonly>; count: number; /** The catalogue numbers, 32-bit. */ norad: Uint32Array; /** Mean motion, revolutions a day. */ meanMotion: Float64Array; eccentricity: Float32Array; /** Degrees. */ inclination: Float32Array; /** Degrees. */ raan: Float32Array; /** Degrees. */ argPerigee: Float32Array; /** Degrees. */ meanAnomaly: Float32Array; /** Index into `OBJECT_KINDS`: 0 payload, 1 rocket body, 2 debris, 3 unknown. */ kind: Uint8Array; /** The epoch of record `i`, milliseconds since 1970 (the file keeps microseconds). */ epochMs(i: number): number; /** The kind of record `i`. */ kindAt(i: number): ObjectKind; /** The name of record `i`. */ nameAt(i: number): string; /** Record `i` as an element set the satellites code reads. */ setAt(i: number): ElementSet; /** Record `i` with what the catalogue says of it. */ recordAt(i: number): CatalogueRecord; /** Every record as an element set. */ sets(): ElementSet[]; /** Every record. */ records(): CatalogueRecord[]; } /** * Read a packed file (not gzipped: see `unpackAny`). The header is checked against the length, so a cut or wrong file is a `PackError` and never a wrong number; a file of more than `MAX_PACKED` records is refused. * * @param bytes - What `packCatalogue` made. * @returns The records, by column. * * @example * ```ts * import { packCatalogue, unpackCatalogue } from "@johnmorrisdotca/chikyu-earth/catalogue"; * * const set = { OBJECT_NAME: "MADE-UP 2", EPOCH: "2026-11-08T00:00:00", MEAN_MOTION: 14.1, ECCENTRICITY: 0.001, INCLINATION: 98, RA_OF_ASC_NODE: 1, ARG_OF_PERICENTER: 2, MEAN_ANOMALY: 3, NORAD_CAT_ID: 123_456, BSTAR: 0, MEAN_MOTION_DOT: 0, MEAN_MOTION_DDOT: 0 }; * const file = unpackCatalogue(packCatalogue([{ set, kind: "RB", size: "M" }])); * console.log(file.nameAt(0), file.kindAt(0), file.norad[0], file.recordAt(0).size); * ``` */ export declare function unpackCatalogue(bytes: Uint8Array): PackedCatalogue; /** * Gzip bytes, with the web's own `CompressionStream`: the form a site hosts a packed file in. * * @param bytes - What `packCatalogue` made. * @returns The gzipped bytes. * * @example * ```ts * import { gzipBytes } from "@johnmorrisdotca/chikyu-earth/catalogue"; * * const small = await gzipBytes(new Uint8Array(10_000)); * console.log(small.length < 100, small[0], small[1]); * ``` */ export declare function gzipBytes(bytes: Uint8Array): Promise; /** * Read a packed file whether or not it is gzipped (gzip is found from its first two bytes). The unpacked size is capped at `MAX_PACKED_BYTES`, so a small file that unpacks to a huge one is refused. * * @param bytes - A packed file, or a gzipped one. * @returns The records, by column. * * @example * ```ts * import { gzipBytes, packCatalogue, unpackAny } from "@johnmorrisdotca/chikyu-earth/catalogue"; * * const file = await unpackAny(await gzipBytes(packCatalogue([], { group: "empty" }))); * console.log(file.count, file.meta["group"]); * ``` */ export declare function unpackAny(bytes: Uint8Array): Promise;