Task
Create the SWE Common Main Parser (parser.ts) — the central orchestrator that discriminates component types, detects encodings, delegates to sub-parsers (simple components, DataRecord, DataArray), and validates parsed structures against DataComponent schema definitions.
ROADMAP Reference: Phase 3, Task 14 — SWE Common Main Parser (~2-3 hours, High complexity)
Files to Create or Modify
File
Action
Est. Lines
Purpose
src/ogc-api/csapi/formats/swecommon/parser.ts
Create
~500-700
Main SWE Common 3.0 parser with type discrimination, encoding detection, schema validation
src/ogc-api/csapi/formats/swecommon/parser.spec.ts
Create
~200-300
Main parser tests — type discrimination, encoding detection, schema validation, error handling
Blueprint Reference
Follow the EDR pattern in src/ogc-api/edr/model.ts (126 lines) for file structure and src/ogc-api/edr/model.spec.ts (42 lines) for test patterns.
Scope — What to Implement
Main Parser Entry Point
parseSWEComponent(json: unknown): SWEDataComponent
Parse any SWE Common 3.0 DataComponent by discriminating on the type property. This is the primary entry point for all SWE Common parsing. It reads the type discriminator from the input JSON and delegates to the appropriate sub-parser.
Type discrimination table:
type value
Delegate to
Source
'Quantity'
parseSimpleComponent() (Issue #24 )
Simple scalar
'Count'
parseSimpleComponent() (Issue #24 )
Simple scalar
'Boolean'
parseSimpleComponent() (Issue #24 )
Simple scalar
'Text'
parseSimpleComponent() (Issue #24 )
Simple scalar
'Time'
parseSimpleComponent() (Issue #24 )
Simple scalar
'Category'
parseSimpleComponent() (Issue #24 )
Simple scalar
'QuantityRange'
parseSimpleComponent() (Issue #24 )
Range component
'CountRange'
parseSimpleComponent() (Issue #24 )
Range component
'TimeRange'
parseSimpleComponent() (Issue #24 )
Range component
'CategoryRange'
parseSimpleComponent() (Issue #24 )
Range component
'DataRecord'
parseDataRecord() (Issue #25 )
Complex aggregate
'DataArray'
parseDataArray() (Issue #26 )
Complex aggregate
'Vector'
parseVector() (this file)
Complex aggregate
'Matrix'
parseMatrix() (this file)
Complex aggregate
'DataChoice'
parseDataChoice() (this file)
Complex aggregate
'Geometry'
parseGeometry() (this file)
Complex aggregate
Error handling: Unknown type values should produce a meaningful error naming the unrecognized type.
Complex Component Parsers (in this file)
The main parser file contains parsers for the complex components not covered by dedicated sub-parser files (Issues #24 -#26 ):
parseVector(json: unknown): Vector
Parse a Vector component: positional vector with coordinate reference system
Properties: type: 'Vector', referenceFrame: string (required URI — the CRS), localFrame?: string, coordinates: DataField[] (named coordinate fields, same SoftNamedProperty wrapper as DataRecord fields)
Required per spec: type, referenceFrame, label, coordinates
parseMatrix(json: unknown): Matrix
Parse a Matrix component: extends DataArray with reference frame
Properties: inherits all DataArray properties plus referenceFrame: string (required URI), localFrame?: string
Required per spec: type, referenceFrame, elementType
parseDataChoice(json: unknown): DataChoice
Parse a DataChoice component: choice of two or more alternative data components (disjoint union)
Properties: type: 'DataChoice', choiceValue?: object, items: DataField[] (named alternative components, same SoftNamedProperty wrapper)
Required per spec: type, items
parseGeometry(json: unknown): Geometry
Parse a Geometry component: geometric data using GeoJSON geometry types
Properties: type: 'Geometry', srs?: string (spatial reference system URI), value?: GeoJSON.Geometry
Required per spec: type
Encoding Detection
detectEncoding(json: unknown): DataEncoding | undefined
Detect the encoding type from a DataArray or observation result structure. Reads the encoding.type discriminator:
'JSONEncoding' → JSON encoding with recordsAsArrays and vectorsAsArrays options
'TextEncoding' → Text/CSV encoding with separator configuration
'BinaryEncoding' → Binary encoding with byte order and member specifications
'XMLEncoding' → XML encoding (recognized but low priority, preserve structure)
No encoding present → return undefined
This delegates to parseEncoding() from Issue #26 (data-array.ts) for the actual parsing.
Schema Validation
validateAgainstSchema(value: unknown, schema: SWEDataComponent): ValidationResult
Validate a parsed observation result value against a DataStream's SWE Common schema (DataComponent definition). Returns a validation result indicating success or failure with error details.
Validation checks:
Structure match: Value structure matches schema structure (e.g., DataRecord with matching field names)
Type match: Value types match component types (number for Quantity, integer for Count, boolean for Boolean, string for Text/Category/Time)
Range validation: Numeric values within constraint.values AllowedValues ranges
Token validation: Category/Text values match constraint.values AllowedTokens list
Array dimensions: Array value count consistent with elementCount when specified
Required fields: All required schema fields present in values
Unit consistency: UoM codes present when schema specifies them
ValidationResult structure:
interface ValidationResult {
valid : boolean ;
errors : ValidationError [ ] ;
}
interface ValidationError {
path : string ; // JSON path to the problematic value (e.g., "fields[0].value")
message : string ; // Human-readable error description
code : string ; // Machine-readable error code (e.g., "RANGE_VIOLATION", "TYPE_MISMATCH")
}
Error Handling
Missing type property → error with guidance about expected discriminator values
Unknown type value → error naming the unrecognized type and listing valid types
Sub-parser delegation failures → wrap with context (which component type, which field)
Validation failures → return ValidationResult with structured errors (not thrown exceptions)
Null/undefined input → error
Non-object input → error
JSDoc Requirements
Document parseSWEComponent with @param, @returns, full type discrimination table, and usage example
Document each complex component parser (parseVector, parseMatrix, parseDataChoice, parseGeometry)
Document detectEncoding with examples of each encoding type
Document validateAgainstSchema with example schema and value validation
Add @see links to OGC SWE Common 3.0 (24-014) for each component type
Follow the JSDoc style in src/ogc-api/edr/model.ts
Testing Requirements
Create src/ogc-api/csapi/formats/swecommon/parser.spec.ts (~200-300 lines)
Type discrimination tests:
Each simple component type dispatched correctly (Quantity, Count, Boolean, Text, Time, Category)
Each range type dispatched correctly (QuantityRange, CountRange, TimeRange, CategoryRange)
DataRecord dispatched to parseDataRecord
DataArray dispatched to parseDataArray
Vector, Matrix, DataChoice, Geometry parsed correctly
Unknown type → meaningful error
Encoding detection tests:
JSON encoding detected and parsed
Text encoding detected and parsed
Binary encoding detected and parsed
XMLEncoding recognized
Missing encoding → undefined
Schema validation tests:
Valid DataRecord value against DataRecord schema → passes
Type mismatch (string where number expected) → validation error
Range violation (value outside AllowedValues) → validation error
Missing required field → validation error
Array dimension mismatch → validation error
Error handling tests:
Null/undefined input → error
Non-object input → error
Missing type → error
Nested errors include context path
Follow test patterns from src/ogc-api/edr/model.spec.ts
Scope — What NOT to Touch
Acceptance Criteria
parser.ts exists with parseSWEComponent() as the main entry point
Type discrimination correctly dispatches all 16 component types
parseVector(), parseMatrix(), parseDataChoice(), parseGeometry() implemented
detectEncoding() recognizes JSON, Text, Binary, and XML encoding types
validateAgainstSchema() returns structured ValidationResult with error details
Validation covers structure match, type match, range, tokens, array dimensions, required fields
Unknown types produce meaningful errors listing valid options
All new code has complete JSDoc documentation with @see spec references
parser.spec.ts exists with tests for type discrimination, encoding detection, schema validation, and error handling
Existing tests still pass (npm test)
No lint errors
Dependencies
Blocked by: Issue #17 — SWE Common Types (all interfaces), Issue #24 — Simple Components Parser, Issue #25 — DataRecord Parser, Issue #26 — DataArray Parser
Blocks: Issue #28 — SWE Common Index (re-exports parser functions)
Operational Constraints
⚠️ MANDATORY: Before starting work on this issue, review docs/governance/AI_OPERATIONAL_CONSTRAINTS.md .
Key constraints for this task:
Precedence: OGC specifications → AI Collaboration Agreement → This issue description → Existing code → Conversational context
No scope expansion: Do not infer unstated requirements or add unrequested features
No refactoring: Do not rename, restructure, or "improve" code outside this issue's scope
Minimal diffs: Prefer the smallest change that satisfies the acceptance criteria
Ask when unclear: If intent is ambiguous, stop and ask for clarification
References
Read these documents before starting implementation. They are ordered by priority.
Primary References (must read)
#
Document
Section/Lines
What It Provides
1
docs/planning/csapi-implementation-guide.md
Lines 3043-3130 (SWE Common Handler)
Full specification of all data components, encodings, schema validation requirements, and advanced features
2
docs/planning/csapi-implementation-guide.md
Lines 2098-2120 (File Structure)
File organization showing parser.ts (~500-700 lines)
3
docs/planning/csapi-implementation-guide.md
Lines 2804-2821 (SWEDataComponent union)
All 16 component types in the discriminated union
4
src/ogc-api/edr/model.ts
Full file (126 lines)
Blueprint — file structure, JSDoc style, export conventions
5
src/ogc-api/edr/model.spec.ts
Full file (42 lines)
Blueprint — test structure and patterns
Upstream Type/Import References (files this task imports from)
#
Document
What to Import
1
src/ogc-api/csapi/formats/swecommon/types.ts
SWEDataComponent, DataRecord, DataArray, Vector, Matrix, DataChoice, Geometry, DataEncoding, ValidationResult, ValidationError, and all component interfaces
2
src/ogc-api/csapi/formats/swecommon/components.ts
parseSimpleComponent — for simple/range type delegation
3
src/ogc-api/csapi/formats/swecommon/data-record.ts
parseDataRecord — for DataRecord delegation
4
src/ogc-api/csapi/formats/swecommon/data-array.ts
parseDataArray, parseEncoding — for DataArray delegation and encoding detection
Research References (context, not required reading)
#
Document
What It Provides
1
docs/research/requirements/csapi-datatype-schema-requirements.md
Complete analysis of SWE Common data types
2
docs/research/testing/findings/04-implementation-guide-testing-requirements.md
Testing requirements and fixture definitions
Specification References (for @see links and field accuracy)
#
Document
Use
1
OGC SWE Common 3.0 (24-014)
Normative specification for all data components, encoding methods, and validation rules
2
OGC API - Connected Systems Part 2 (23-002)
DataStream schema and Observation result usage context
3
docs/research/standards/ogcapi-connectedsystems-2.bundled.oas31.yaml
OpenAPI schema — AnyComponent (L7606, oneOf *ref_36), Vector (L1061, required: type, referenceFrame, label, coordinates), Matrix (L1329), DataChoice (L1351), Geometry (L1384), encoding types (L7620-7633)
Convention Quick Reference
Rule
Example
Use .js extension for relative imports
import { X } from './file.js'
Use import type for interfaces/types
import type { Y } from './model.js'
Three-tier hierarchy: import from lower tiers only
shared → ogc-api → csapi
Named exports for types and utilities
export interface Z { ... }
as const arrays for enum-like values
export const XTypes = [...] as const
HTTP mocking: globalThis.fetch = jest.fn()
Never use nock, msw, or other libraries
Meaningful tests only
Verify behavior, not that code runs without throwing
Task
Create the SWE Common Main Parser (
parser.ts) — the central orchestrator that discriminates component types, detects encodings, delegates to sub-parsers (simple components, DataRecord, DataArray), and validates parsed structures against DataComponent schema definitions.ROADMAP Reference: Phase 3, Task 14 — SWE Common Main Parser (~2-3 hours, High complexity)
Files to Create or Modify
src/ogc-api/csapi/formats/swecommon/parser.tssrc/ogc-api/csapi/formats/swecommon/parser.spec.tsBlueprint Reference
Follow the EDR pattern in
src/ogc-api/edr/model.ts(126 lines) for file structure andsrc/ogc-api/edr/model.spec.ts(42 lines) for test patterns.Scope — What to Implement
Main Parser Entry Point
parseSWEComponent(json: unknown): SWEDataComponentParse any SWE Common 3.0 DataComponent by discriminating on the
typeproperty. This is the primary entry point for all SWE Common parsing. It reads thetypediscriminator from the input JSON and delegates to the appropriate sub-parser.Type discrimination table:
typevalue'Quantity'parseSimpleComponent()(Issue #24)'Count'parseSimpleComponent()(Issue #24)'Boolean'parseSimpleComponent()(Issue #24)'Text'parseSimpleComponent()(Issue #24)'Time'parseSimpleComponent()(Issue #24)'Category'parseSimpleComponent()(Issue #24)'QuantityRange'parseSimpleComponent()(Issue #24)'CountRange'parseSimpleComponent()(Issue #24)'TimeRange'parseSimpleComponent()(Issue #24)'CategoryRange'parseSimpleComponent()(Issue #24)'DataRecord'parseDataRecord()(Issue #25)'DataArray'parseDataArray()(Issue #26)'Vector'parseVector()(this file)'Matrix'parseMatrix()(this file)'DataChoice'parseDataChoice()(this file)'Geometry'parseGeometry()(this file)Error handling: Unknown
typevalues should produce a meaningful error naming the unrecognized type.Complex Component Parsers (in this file)
The main parser file contains parsers for the complex components not covered by dedicated sub-parser files (Issues #24-#26):
parseVector(json: unknown): Vectortype: 'Vector',referenceFrame: string(required URI — the CRS),localFrame?: string,coordinates: DataField[](named coordinate fields, same SoftNamedProperty wrapper as DataRecord fields)type,referenceFrame,label,coordinatesparseMatrix(json: unknown): MatrixreferenceFrame: string(required URI),localFrame?: stringtype,referenceFrame,elementTypeparseDataChoice(json: unknown): DataChoicetype: 'DataChoice',choiceValue?: object,items: DataField[](named alternative components, same SoftNamedProperty wrapper)type,itemsparseGeometry(json: unknown): Geometrytype: 'Geometry',srs?: string(spatial reference system URI),value?: GeoJSON.GeometrytypeEncoding Detection
detectEncoding(json: unknown): DataEncoding | undefinedDetect the encoding type from a DataArray or observation result structure. Reads the
encoding.typediscriminator:'JSONEncoding'→ JSON encoding withrecordsAsArraysandvectorsAsArraysoptions'TextEncoding'→ Text/CSV encoding with separator configuration'BinaryEncoding'→ Binary encoding with byte order and member specifications'XMLEncoding'→ XML encoding (recognized but low priority, preserve structure)undefinedThis delegates to
parseEncoding()from Issue #26 (data-array.ts) for the actual parsing.Schema Validation
validateAgainstSchema(value: unknown, schema: SWEDataComponent): ValidationResultValidate a parsed observation result value against a DataStream's SWE Common schema (DataComponent definition). Returns a validation result indicating success or failure with error details.
Validation checks:
constraint.valuesAllowedValues rangesconstraint.valuesAllowedTokens listelementCountwhen specifiedValidationResultstructure:Error Handling
typeproperty → error with guidance about expected discriminator valuestypevalue → error naming the unrecognized type and listing valid typesValidationResultwith structured errors (not thrown exceptions)JSDoc Requirements
parseSWEComponentwith@param,@returns, full type discrimination table, and usage exampleparseVector,parseMatrix,parseDataChoice,parseGeometry)detectEncodingwith examples of each encoding typevalidateAgainstSchemawith example schema and value validation@seelinks to OGC SWE Common 3.0 (24-014) for each component typesrc/ogc-api/edr/model.tsTesting Requirements
src/ogc-api/csapi/formats/swecommon/parser.spec.ts(~200-300 lines)parseDataRecordparseDataArraysrc/ogc-api/edr/model.spec.tsScope — What NOT to Touch
types.ts— that belongs to Issue Phase 3.4: SWE Common Types #17 (SWE Common Types)components.ts— that belongs to Issue Phase 3, Task 11: SWE Common Simple Components Parser #24 (SWE Common Simple Components Parser)data-record.ts— that belongs to Issue Phase 3, Task 12: SWE Common DataRecord Parser #25 (SWE Common DataRecord Parser)data-array.ts— that belongs to Issue Phase 3, Task 13: SWE Common DataArray Parser #26 (SWE Common DataArray Parser)index.ts— that belongs to Issue Phase 3, Task 15: SWE Common Index #28 (SWE Common Index)Acceptance Criteria
parser.tsexists withparseSWEComponent()as the main entry pointparseVector(),parseMatrix(),parseDataChoice(),parseGeometry()implementeddetectEncoding()recognizes JSON, Text, Binary, and XML encoding typesvalidateAgainstSchema()returns structuredValidationResultwith error details@seespec referencesparser.spec.tsexists with tests for type discrimination, encoding detection, schema validation, and error handlingnpm test)Dependencies
Blocked by: Issue #17 — SWE Common Types (all interfaces), Issue #24 — Simple Components Parser, Issue #25 — DataRecord Parser, Issue #26 — DataArray Parser
Blocks: Issue #28 — SWE Common Index (re-exports parser functions)
Operational Constraints
Key constraints for this task:
References
Read these documents before starting implementation. They are ordered by priority.
Primary References (must read)
docs/planning/csapi-implementation-guide.mddocs/planning/csapi-implementation-guide.mdparser.ts(~500-700 lines)docs/planning/csapi-implementation-guide.mdsrc/ogc-api/edr/model.tssrc/ogc-api/edr/model.spec.tsUpstream Type/Import References (files this task imports from)
src/ogc-api/csapi/formats/swecommon/types.tsSWEDataComponent,DataRecord,DataArray,Vector,Matrix,DataChoice,Geometry,DataEncoding,ValidationResult,ValidationError, and all component interfacessrc/ogc-api/csapi/formats/swecommon/components.tsparseSimpleComponent— for simple/range type delegationsrc/ogc-api/csapi/formats/swecommon/data-record.tsparseDataRecord— for DataRecord delegationsrc/ogc-api/csapi/formats/swecommon/data-array.tsparseDataArray,parseEncoding— for DataArray delegation and encoding detectionResearch References (context, not required reading)
docs/research/requirements/csapi-datatype-schema-requirements.mddocs/research/testing/findings/04-implementation-guide-testing-requirements.mdSpecification References (for
@seelinks and field accuracy)docs/research/standards/ogcapi-connectedsystems-2.bundled.oas31.yamlAnyComponent(L7606, oneOf*ref_36),Vector(L1061, required: type, referenceFrame, label, coordinates),Matrix(L1329),DataChoice(L1351),Geometry(L1384), encoding types (L7620-7633)Convention Quick Reference
.jsextension for relative importsimport { X } from './file.js'import typefor interfaces/typesimport type { Y } from './model.js'export interface Z { ... }as constarrays for enum-like valuesexport const XTypes = [...] as constglobalThis.fetch = jest.fn()