Skip to content

Master Plan: Complete CSAPI ogc-client Implementation - v2 #15

@Sam-Bolling

Description

@Sam-Bolling

Master Plan: Complete OGC API - Connected Systems Implementation

Overview

This issue tracks the complete implementation of OGC API – Connected Systems (CSAPI) support for the ogc-client library. This is a fresh start based on lessons learned from initial exploratory work.

Implementation Repository: OS4CSAPI/ogc-client-CSAPI


Background & Context

Previous Work

Feedback Received

Initial implementation was assessed as ~5% complete. Key gaps identified:

  • ❌ Read-only (needs full CRUD support)
  • ❌ Tests are server-oriented, not client-oriented
  • ❌ No deep end-to-end testing
  • ❌ Missing advanced query parameters/filtering
  • ❌ Only supports GeoJSON (needs SensorML support)
  • ❌ No pagination support

Reference Resources

OGC Standards:

Reference Implementations:

  • oscar-viewer - TypeScript webapp client
  • osh-viewer - JavaScript webapp client
  • osh-js library - Critical reference for implementation patterns

Upstream Patterns:


Strategy: One Perfect Resource, Then Scale

Instead of implementing all resources partially, we'll:

  1. ✅ Build Systems resource with 100% completeness
  2. ✅ Use Systems as the template for all other resources
  3. ✅ Ensure production-ready quality at each step

PHASE 1: Setup & Research 🔍

Duration: 1 week
Goal: Understand what "complete" means

Tasks

  • Create this tracking issue
  • Study camptocamp/ogc-client patterns:
    • How WFS implements CRUD operations
    • How STAC handles query parameters
    • How pagination is implemented
    • How format negotiation works
  • Deep dive into osh-js library:
    • CRUD operation patterns
    • Query building architecture
    • Format handling (GeoJSON vs SensorML)
    • Pagination mechanisms
    • Error handling patterns
  • Analyze oscar-viewer and osh-viewer:
    • How clients actually use CSAPI
    • Common use cases
    • Error scenarios
  • Document findings in this issue

Deliverable: Research summary comment with key patterns identified

Status:COMPLETE - See research comments below


PHASE 2: Systems Resource - Complete Implementation 🚀

Duration: 3 weeks
Goal: One perfect, production-ready resource implementation

2.1: READ Operations

  • listSystems(options) - list with comprehensive filtering
  • getSystem(id, options) - get single system
  • Format negotiation (GeoJSON vs SensorML)

2.2: CREATE Operations

  • createSystem() - URL builder for POST operations
  • Validation before sending
  • Handle conflicts (409)

2.3: UPDATE Operations

  • updateSystem(id) - URL builder for full update (PUT)
  • patchSystem(id) - URL builder for partial update (PATCH)
  • Support GeoJSON format
  • Support SensorML format

2.4: DELETE Operations

  • deleteSystem(id) - URL builder for DELETE

2.5: Format Support

  • Format negotiation utilities via Accept headers
  • Content-Type and Accept header handling

2.6: URL & Query Building

  • Proper URL construction
  • Query parameter encoding
  • Handle arrays in parameters
  • Support for custom parameters

2.7: Testing (Client-Oriented)

  • Unit Tests (186 tests)
  • Integration Tests (10 tests)
  • All CRUD operations
  • Both formats (GeoJSON + SensorML)
  • All query parameters
  • Pagination scenarios
  • Test Coverage: 100% for CSAPI code

2.8: Documentation

  • JSDoc for all public methods
  • Usage examples
  • Error handling guide

Deliverable: Fully functional, tested, documented Systems resource

Status:COMPLETE - All systems methods implemented with full test coverage


PHASE 3: Template Other Resources 📋

Duration: 6 weeks (planned) → 3 days (actual) 🚀
Goal: Apply Systems pattern to all other resource types

Priority Order (Part 2 - Dynamic Data)

  • Datastreams - Critical for observations (11 methods)
  • Observations - Core dynamic data functionality (9 methods)

Part 1 - Feature Resources

  • Deployments - System deployment context (8 methods)
  • Procedures - Method descriptions (8 methods)
  • Sampling Features - Spatial sampling (8 methods)
  • Properties - Observable/controllable properties (6 methods)

Part 2 - Control & Events

  • Control Streams - Command channels (8 methods)
  • Commands - Control messages (8 methods)

Status:COMPLETE - All 9 resource types implemented (70+ URL builder methods total)

Actual Timeline: 3 days (significantly faster than planned 6 weeks due to consistent templating pattern)


PHASE 4: Integration & Polish 🎨

Duration: 2 weeks
Goal: Production-ready contribution

4.1: Cross-Cutting Concerns

  • Consistent error handling across all resources
  • Unified pagination approach
  • Format negotiation framework
  • Performance optimization (caching)
  • Memory efficiency

4.2: Examples & Documentation

  • Complete README update (posted to issue for reference)
  • Usage examples for each resource
  • API reference documentation (JSDoc)

4.3: Quality Assurance

  • Code review checklist
  • Linting and formatting
  • Performance benchmarks
  • Browser compatibility testing
  • Node.js compatibility testing

4.4: Commit History

  • Clean, logical commit sequence (11 commits)
  • Meaningful commit messages
  • Each commit builds and passes tests

Status:COMPLETE - All integration work finished


PHASE 5: Pre-Submission Quality & Test Coverage 🧪

Duration: 1-2 weeks
Goal: Comprehensive test coverage for parsers and validators before upstream submission

Rationale

Based on PR #114 (EDR) and discussion with maintainers, we need to ensure production-ready quality with comprehensive test coverage before submitting the PR. This phase focuses on parsers and validators that handle GeoJSON and SWE Common format validation and type safety.

5.1: Navigator & Core Infrastructure Tests

  • Expand navigator.spec.ts with query parameter tests
    • Coverage: 92.7% (target 95%, achieved very close)
    • Added 19 tests for individual query parameters
  • Create formats.spec.ts for format detection utilities
  • Create request-builders.spec.ts (97.5% coverage) ✅
  • Create typed-navigator.spec.ts (96.66% coverage) ✅
  • Module Coverage: csapi/ main module at 94.41% ✅

Status:COMPLETE - Commit 0f8e7cb (4 files, 1738 insertions)

5.2: GeoJSON Validator Tests

  • Create geojson-validator.spec.ts with comprehensive tests
    • Coverage: 56.47% → 97.4% (+40.93%) ✅
    • Added 61 tests for all 7 CSAPI feature types
    • validateSystemFeature, validateDeploymentFeature, etc. (7 tests each)
    • validateSystemFeatureCollection, etc. (3 tests each)
    • validateCSAPIFeature switch dispatcher tests (7 tests)
    • Required property validation (system, definition, etc.)
    • Bug fixes: Added missing required properties, corrected error messages

Status:COMPLETE - Commit fd90630 (included in validator commit)

5.3: SWE Common Validator Tests

  • Create swe-validator.spec.ts with comprehensive tests
    • Coverage: 75.43% → 100% (+24.57%) ✅
    • Added 50 tests for SWE Common data components
    • validateObservationResult tests (5 tests): null/undefined, simple values, SWE components
    • Individual validator tests (45 tests): Quantity, DataRecord, DataArray, Vector, Category, Text, Boolean, Count, Time
    • Error path tests (9 tests): Missing DataComponent properties, type mismatches, missing required fields
    • Bug fix: Discovered hasDataComponentProperties only validates type field
  • Module Coverage: validation/ module at 98.01% ✅

Status:COMPLETE - Commit fd90630 (4 files, 1625 insertions)

5.4: Parser Tests

  • Create parsers/base.spec.ts for base parser class
    • Coverage: 60.23% → 96.62% (+36.39%) ✅
    • Tests for parseGeoJSON, parseSensorML, parseSWE
    • Format detection and validation integration tests
    • Error handling for unsupported formats
    • All base parser code paths covered
  • Create parsers/resources.spec.ts for resource-specific parsers
    • Coverage: 29.57% → 70.41% (+40.84%)
    • Added 29 tests for 6 CSAPI resource types
    • DeploymentParser (6 tests): GeoJSON, SensorML, location, platform/links, validation, SWE error
    • ProcedureParser (6 tests): GeoJSON, SimpleProcess, inputs/outputs/parameters, AggregateProcess, position, SWE error
    • SamplingFeatureParser, PropertyParser, DatastreamParser (3-4 tests each)
    • ControlStreamParser (3 tests): GeoJSON, error handling
    • Common tests (4 tests): Property extraction, FeatureCollection errors, validation
    • Bug fixes: SensorML contentType header handling
  • Module Coverage: parsers/ module at 78.43% (base 96.62% ✅, resources 70.41%)

Status:COMPLETE - Commit b29df89 (4 files, 877 insertions)

5.5: Final Coverage Push

  • Add remaining tests for resources.ts (70% → 85%+ target)
    • Add tests for extractGeometry helper function
    • More SensorML parsing edge cases
    • More validation integration tests
    • Property extraction edge cases
    • Estimated: 10-15 more tests
  • Final verification: Run full test suite
  • Confirm overall coverage 83-85%+

Status: 🔄 IN PROGRESS - ~90% complete

Phase 5 Summary

Overall Metrics:

  • Test Coverage: 68.49% → 81.46% (+12.97%)
  • Test Count: 364 → 499 (+135 tests)
  • Test Files: 1 → 9 (+8 files)
  • Lines of Test Code: ~400 → ~4,640 (+4,240 lines)

Module Breakdown:

  • csapi/ (main): 94.41%
  • validation/: 98.01%
  • parsers/base.ts: 96.62%
  • parsers/resources.ts: 70.41% (target 85%+)

Commits:

  • 0f8e7cb: Navigator & core infrastructure tests (4 files, 1738 insertions)
  • fd90630: Validator tests achieving 95%+ coverage (4 files, 1625 insertions)
  • b29df89: Parser tests with comprehensive coverage (4 files, 877 insertions)
  • be3846f: Gitignore for test output files (1 file, 3 insertions)

Deliverable: Production-ready test coverage demonstrating quality before upstream PR

Status: 🔄 ~90% COMPLETE - Final resources.ts coverage push pending (see detailed progress comment)


PHASE 6: Upstream Contribution 🎯

Duration: Ongoing
Goal: Successful merge to camptocamp/ogc-client

Tasks

  • Create new PR from OS4CSAPI/ogc-client-CSAPI
  • Address all feedback promptly
  • Be responsive to maintainer requests
  • Iterate based on code review

Status:PENDING - Awaiting Phase 5 completion


Success Criteria ✅

A complete implementation means:

  • Full CRUD for all 11+ resource types - URL builders for all operations
  • ⚠️ Both formats: GeoJSON and SensorML - Format negotiation via headers (parsing not in scope per PR #114 pattern)
  • Complete query support: All parameters from spec - bbox, datetime, filters, etc.
  • Pagination: Offset-based - limit/offset parameters supported
  • Client-oriented tests: Real-world usage scenarios - 499 tests passing (was 196)
  • >90% test coverage - 81.46% overall (was 100% CSAPI, now includes parsers/validators)
  • Production-ready quality - All tests passing, clean architecture
  • Comprehensive documentation - JSDoc + examples posted to issue
  • Maintainer approval - Pending Phase 5 completion → PR submission

Progress Tracking

Current Phase: PHASE 5 - Pre-Submission Quality & Test Coverage 🧪 (~90% complete)

Completed:

Phase 1: Research complete (see comments below)
Phase 2: Systems resource fully implemented
Phase 3: All 9 resources implemented (70+ methods)
Phase 4: Integration & polish complete
🔄 Phase 5: Test coverage expansion (~90% complete)

  • ✅ Step 1: Navigator & core infrastructure (94.41%)
  • ✅ Step 2: GeoJSON validator (97.4%)
  • ✅ Step 3: SWE validator (100%)
  • ✅ Step 4: Parser tests (78.43%)
  • 🔄 Step 5: Final resources.ts push (70% → 85%+ target)

Current Stats:

  • 499/499 CSAPI tests passing (186 unit + 10 integration + 303 validator/parser tests)
  • 81.46% overall coverage (was 68.49%, +12.97% gain)
  • 9 test files (was 1, +8 new files)
  • 70+ URL builder methods across all resources
  • 14 clean commits pushed to main branch (was 11, +3 test commits)
  • 4,240+ lines of test code added in Phase 5

Next Up:

  • Complete Phase 5 Step 5: Final resources.ts coverage push (10-15 tests)
  • Verify 83-85% overall coverage target
  • Create PR to camptocamp/ogc-client
  • Address maintainer feedback
  • Iterate to approval

Implementation Summary

Architecture Decision

Following PR #114 (EDR), we implemented URL building pattern rather than full CRUD client:

Pattern: Library provides URL strings, users handle fetch()

Example:

const navigator = await endpoint.csapi('sensors');
const url = navigator.getSystemsUrl({ limit: 10 });
const response = await fetch(url);
const systems = await response.json();

Rationale:

  • Matches maintainer's established pattern
  • Users control auth, headers, retries
  • Simpler, more flexible implementation
  • No HTTP abstraction needed

Files Created

Core Implementation:

  • src/ogc-api/csapi/navigator.ts (~1,400 lines) - Main navigator with 70+ methods
  • src/ogc-api/csapi/model.ts (168 lines) - TypeScript interfaces for all query options
  • src/ogc-api/csapi/navigator.spec.ts (~900 lines) - 186 unit tests
  • src/ogc-api/csapi/endpoint.integration.spec.ts (485 lines) - 10 integration tests

Phase 5 Additions:

  • src/ogc-api/csapi/formats.spec.ts - Format detection tests
  • src/ogc-api/csapi/request-builders.spec.ts - URL builder utility tests
  • src/ogc-api/csapi/typed-navigator.spec.ts - Type-safe navigator tests
  • src/ogc-api/csapi/parsers/base.spec.ts - Base parser tests
  • src/ogc-api/csapi/parsers/resources.spec.ts - Resource parser tests (29 tests)
  • src/ogc-api/csapi/validation/geojson-validator.spec.ts - GeoJSON validator tests (61 tests)
  • src/ogc-api/csapi/validation/swe-validator.spec.ts - SWE validator tests (50 tests)

Modified Files:

  • src/ogc-api/endpoint.ts - Added hasConnectedSystems, csapiCollections, csapi() method
  • src/ogc-api/info.ts - Added CSAPI conformance checking, preserved links in parseBaseCollectionInfo
  • src/index.ts - Exported CSAPINavigator and CSAPI types

Test Fixtures:

  • Created mock CSAPI server responses in fixtures/ogc-api/csapi/

All Implemented Resources

  1. Systems (12 methods) - CRUD + history + sub-resources
  2. Procedures (8 methods) - CRUD + history
  3. Deployments (8 methods) - CRUD + history
  4. Sampling Features (8 methods) - CRUD + history
  5. Properties (6 methods) - CRUD
  6. Datastreams (11 methods) - CRUD + observations + schema
  7. Observations (9 methods) - Read/create + result time filters
  8. Commands (8 methods) - CRUD + status
  9. Control Streams (8 methods) - CRUD + issue/execution time

Notes & Decisions

Key Architectural Choices

  1. Composition Pattern: endpoint.csapi(collectionId) returns navigator instance (matches PR #114)
  2. Per-Collection Navigators: Different collections may support different resources
  3. URL Building Only: Library doesn't handle HTTP - users control fetch()
  4. Caching: Navigator instances cached per collection for efficiency
  5. Early Validation: Check resource availability before constructing URLs
  6. Native Types: Use Date, BoundingBox from shared models
  7. Links Preservation: Fixed bug where collection.links was being dropped
  8. Test Coverage First: Phase 5 ensures production quality before PR submission

Divergences from Original Plan

Planned: Full CRUD client with data handling, format parsing, pagination abstractions
Implemented: URL building following PR #114 pattern
Impact: Simpler, matches maintainer preferences, higher approval likelihood

Added: Phase 5 (Pre-Submission Quality & Test Coverage)
Rationale: Ensure production-ready quality with comprehensive test coverage for parsers/validators before upstream submission


Related Issues

  • Systems: ✅ Complete
  • Datastreams: ✅ Complete
  • Observations: ✅ Complete
  • All other resources: ✅ Complete
  • Phase 5 Test Coverage: 🔄 ~90% Complete

Team

  • @Sam-Bolling - Implementation lead
  • GitHub Copilot - Development assistant

Last Updated: 2026-01-25 (Phase 5 progress)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions