Skip to content

Latest commit

 

History

History
205 lines (153 loc) · 4.55 KB

File metadata and controls

205 lines (153 loc) · 4.55 KB

dotcat-parser Library Spec

This document defines the first usable version of the library.

v0.0.1 Goal

Parse Spanish Cadastre .CAT fixed-width files into typed JavaScript objects without losing the raw source data.

This version should be useful for scripts, tests, and exploratory data work. It does not need full domain modeling, GeoJSON export, reprojection, or database integration yet.

Non-Goals

  • No coordinate reprojection.
  • No GeoJSON export.
  • No CSV writer.
  • No high-level parcel/property graph.
  • No automatic downloading or unzipping of CAT files.
  • No guarantee that every CAT field has a final semantic TypeScript name.

Input Model

CAT files are plain text files made of fixed-width records.

  • Every record is expected to be 1000 characters long, excluding line endings.
  • Record type is stored at positions 1-2.
  • Field positions from the official spec are 1-indexed.
  • Internal slices use start = position - 1 and end = start + length.

Supported Record Types

v0.0.1 should recognize:

  • 01: header
  • 11: parcel/finca
  • 13: construction unit
  • 14: construction
  • 15: property/bien inmueble
  • 16: common element share
  • 17: crop
  • 90: trailer

Unknown record type handling can be added later. The current parser throws for unknown record types.

Public API

parseLine(line: string): ParsedRecord

parseText(text: string): ParsedRecord[]

parseFile(path: string): Promise<ParsedRecord[]>

parseStream(
  stream: NodeJS.ReadableStream
): AsyncIterable<ParsedRecord>

validateLine(line: string): ValidationIssue[]

validateFile(records: ParsedRecord[]): ValidationIssue[]

Data Structures

type RecordType = "01" | "11" | "13" | "14" | "15" | "16" | "17" | "90"

interface ParsedRecord {
  type: RecordType
  name: string
  raw: string
  lineNumber?: number
  fields: Record<string, ParsedField>
}

interface ParsedField {
  spec: FieldSpec
  raw: string
  value: string | number | null
}

interface ValidationIssue {
  level: "warning" | "error"
  code: string
  message: string
  lineNumber?: number
  recordType?: string
  fieldName?: string
}

Schema Model

The parser should be schema-driven.

Record specs are explicit per record type. Shared-looking fields should still be encoded from the official table for that specific record unless we have tests proving a helper preserves the same documented position, length, and format.

interface FieldSpec {
  name: string
  position: number
  length: number
  format: "X" | "N"
  description?: string
}

interface RecordSpec {
  type: RecordType
  name: string
  length: 1000
  officialName: string
  fields: FieldSpec[]
}

v0.0.1 only needs enough field specs to prove the parser shape:

  • common recordType field for all supported records;
  • key identity fields for records 01, 11, 15, and 90;
  • raw fallback access for everything else.

Full field coverage can grow incrementally from the official spec.

Validation

v0.0.1 validation should check:

  • line length is exactly 1000 when strictLineLength is true;
  • record type exists or is reported as unknown;
  • file has at most one header record;
  • file has at most one trailer record;
  • header, if present, is first non-empty record;
  • trailer, if present, is last non-empty record.

Trailer count validation can come later once the relevant fields are modeled.

Error Strategy

Parsing should be tolerant by default:

  • v0.0.1 parseLine throws for unknown record types.
  • recoverable problems are exposed as ValidationIssues.
  • hard failures should be reserved for invalid API inputs, unreadable files, or strict parsing modes added later.

Package Shape

Initial package exports:

export { parseLine, parseText, parseFile, parseStream }
export { validateLine, validateFile }
export { getRecordSpec, recordSpecs }
export type {
  FieldSpec,
  ParsedField,
  ParsedRecord,
  RecordSpec,
  RecordType,
  ValidationIssue,
}

Next To Implement

Parse options are not implemented yet. A later version should add:

interface ParseOptions {
  trimText?: boolean
  emptyTextAsNull?: boolean
  parseNumbers?: boolean
  zeroNumbersAsNull?: boolean
  strictLineLength?: boolean
}

Likely defaults:

{
  trimText: true,
  emptyTextAsNull: true,
  parseNumbers: false,
  zeroNumbersAsNull: false,
  strictLineLength: true
}

parseNumbers should default to false because many CAT fields are identifiers that look numeric but should remain strings.

CLI Later

The CLI is not required for v0.0.1, but the API should make this easy later:

dotcat parse file.CAT --json
dotcat validate file.CAT