Skip to content

Phase 1.3: Create Stub QueryBuilder (csapi/url_builder.ts) #3

@Sam-Bolling

Description

@Sam-Bolling

Task

Create the stub CSAPIQueryBuilder class in src/ogc-api/csapi/url_builder.ts with constructor, private helper methods, resource validation, and 1-2 proof-of-concept public methods, plus its test file src/ogc-api/csapi/url_builder.spec.ts.

ROADMAP Reference: Phase 1, Task 3 — Create Stub QueryBuilder (~3-4 hours, Low complexity)


Files to Create or Modify

File Action Est. Lines Purpose
src/ogc-api/csapi/url_builder.ts Create ~80-120 Stub QueryBuilder class with constructor, 3 private helpers, availableResources property, and 1-2 public methods
src/ogc-api/csapi/url_builder.spec.ts Create ~100-150 Tests for constructor, resource validation, and the 1-2 public methods

Blueprint Reference

Follow the EDR QueryBuilder pattern established in src/ogc-api/edr/url_builder.ts (562 lines). Key patterns to match:

  • Class structure: export default class with constructor accepting OgcApiCollectionInfo
  • Constructor: Extracts capabilities from collection info, stores as instance properties
  • Private fields: Use private collection_ trailing underscore convention (matches EDR's private collection)
  • Import style: Named imports from ../model.js and ./model.js with .js extensions
  • JSDoc: Class-level @see link to specification

EDR has no url_builder.spec.ts — this will be a new test file. Follow test structure from src/ogc-api/edr/helpers.spec.ts (46 lines) and src/ogc-api/edr/model.spec.ts (39 lines) for describe/it patterns.

Scope — What to Implement

Class Structure

export default class CSAPIQueryBuilder {
  public readonly availableResources: Set<string>;

  constructor(private collection_: OgcApiCollectionInfo) {
    this.availableResources = this.extractAvailableResources();
  }
}

Private Helper Methods (3 methods)

  1. private extractAvailableResources(): Set<string> — Resource discovery from collection links

    • Parse collection links array for CSAPI resource type indicators (e.g., rel matching ogc-cs:{resourceType})
    • Return a Set<string> of available resource type names (e.g., 'systems', 'datastreams')
    • Called once in constructor
  2. private buildResourceUrl(resourceType: string, id?: string, subPath?: string, options?: QueryOptions): string — Core URL construction using this.baseUrl

    • Canonical: {baseUrl}/{resourceType}/systems
    • By ID: {baseUrl}/{resourceType}/{id}/systems/abc123
    • Nested: {baseUrl}/{resourceType}/{id}/{subPath}/systems/abc123/subsystems
    • Appends query string via buildQueryString()
  3. private buildQueryString(options?: QueryOptions): string — Parameter serialization with encoding

    • Convert query options object to URL query string
    • Handle undefined/null values (skip them)
    • Handle array parameters (e.g., id=sys1,sys2,sys3 as comma-joined)
    • Return empty string when no options, ?key=val&... when options present

Public Property

  • public readonly availableResources: Set<string> — Exposes discovered resource types for user inspection

Resource Validation Pattern

All public methods validate resource availability before building URLs (~2 lines per method):

if (!this.availableResources.has('systems')) {
  throw new EndpointError(
    `Collection '${this.collection_.id}' does not support 'systems' resource. ` +
    `Available resources: ${Array.from(this.availableResources).join(', ')}`
  );
}

Proof-of-Concept Public Methods (1-2 methods)

Implement 1-2 simple public methods as proof of concept using the private helpers:

  1. getSystems(options?: SystemQueryOptions): string — Returns URL for listing systems
  2. getSystem(id: string, options?: QueryOptions): string — Returns URL for a single system by ID

These methods demonstrate the complete pattern: validate → build URL → return string. All 78 remaining methods (Phase 2, issues #5-#13) follow this exact pattern.

JSDoc Requirements

  • Class-level JSDoc with @see link to CSAPI Part 1 specification
  • Document constructor with parameter description
  • Document public availableResources property
  • Document each public method with parameter descriptions, return type, and usage example
  • Private helpers get internal JSDoc only (not part of public API docs)
  • Follow the JSDoc style in src/ogc-api/edr/url_builder.ts

Testing Requirements

  • Create src/ogc-api/csapi/url_builder.spec.ts (~100-150 lines)
  • Constructor tests:
    • Constructs successfully with valid collection info containing CSAPI links
    • Populates availableResources from collection links
    • Handles collection with no CSAPI links (empty availableResources)
  • Resource validation tests:
    • Public method throws EndpointError when resource type is unavailable
    • Error message includes collection ID and lists available resources
    • Public method succeeds when resource type is available
  • Public method tests:
    • getSystems() returns correct URL with no options
    • getSystems({ limit: 10 }) returns correct URL with query parameters
    • getSystem('abc123') returns correct URL with resource ID
    • getSystems({ bbox: [-180, -90, 180, 90] }) returns correct URL with bbox parameter
  • Query string tests:
    • Properly encodes special characters in parameter values
    • Skips undefined/null values
    • Joins array parameters with commas
  • Follow test patterns from src/ogc-api/edr/helpers.spec.ts and src/ogc-api/edr/model.spec.ts
  • Use globalThis.fetch = jest.fn() if HTTP mocking is needed (unlikely for this stub)

Scope — What NOT to Touch

Acceptance Criteria

  • src/ogc-api/csapi/url_builder.ts exists with the CSAPIQueryBuilder class
  • Class has constructor accepting OgcApiCollectionInfo parameter
  • Class has public readonly availableResources: Set<string> property
  • Class has 3 private helper methods: extractAvailableResources(), buildResourceUrl(), buildQueryString()
  • Class has 1-2 public proof-of-concept methods (getSystems, getSystem) with resource validation
  • All public API has complete JSDoc documentation
  • Imports from model.ts (issue Phase 1.1: Create Type System (csapi/model.ts) #1) use types defined there (e.g., SystemQueryOptions, QueryOptions)
  • Imports from helpers.ts (issue Phase 1.2: Create Helper Utilities (csapi/helpers.ts) #2) use utilities defined there if needed (e.g., temporal encoding)
  • src/ogc-api/csapi/url_builder.spec.ts exists with tests for constructor, resource validation, and public methods
  • Existing tests still pass (npm test)
  • No lint errors

Dependencies

Blocked by: #1 — Phase 1.1: Create Type System (QueryBuilder imports types from model.ts), #2 — Phase 1.2: Create Helper Utilities (QueryBuilder may use temporal encoding and validation utilities from helpers.ts)
Blocks: #4 — Phase 1.4: Integrate with OgcApiEndpoint (integration imports CSAPIQueryBuilder), #5-#13 — Phase 2: All resource method implementations build on this stub


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 §6: "Resource Validation Strategy" Lines 535-600 Complete constructor and validation pattern — exact code for constructor, availableResources, and per-method validation with EndpointError
2 docs/planning/csapi-implementation-guide.md §6: "Helper Methods" Lines 620-720 Complete private helper method specificationsbuildResourceUrl(), buildQueryString(), extractAvailableResources() with full code blocks showing signatures, implementation logic, and link-parsing pattern
3 src/ogc-api/edr/url_builder.ts Full file (562 lines) Upstream blueprint — the accepted pattern for a QueryBuilder class. Match class structure, constructor pattern, export default class, import style, and JSDoc format
4 src/ogc-api/edr/helpers.spec.ts Full file (46 lines) Test blueprint — the accepted describe/it structure and assertion style for test files

Upstream Type/Import References (files this task imports from)

# Document What to Import
5 src/ogc-api/csapi/model.ts (created in issue #1) SystemQueryOptions, QueryOptions, CSAPIResourceType
6 src/ogc-api/model.ts OgcApiCollectionInfo (collection metadata type passed to constructor)
7 src/ogc-api/csapi/helpers.ts (created in issue #2) Temporal encoding and validation utilities if needed by buildQueryString()
8 src/shared/models.ts EndpointError (for validation error messages)

Research References (context, not required reading)

# Document What It Provides
9 docs/research/upstream/querybuilder-pattern-analysis.md Analysis of QueryBuilder patterns — why single class with private helpers, not multi-class with inheritance
10 docs/research/upstream/url-building-analysis.md URL construction patterns across all upstream APIs — why buildResourceUrl uses this specific signature
11 docs/research/design/csapiquerybuilder/architecture-decision/results/DECISION-part1-structure.md Complete structural design with confidence ratings — why helper methods, why resource validation
12 docs/research/design/csapiquerybuilder/architecture-decision/results/DECISION-part2-implementation.md Implementation details — exact code patterns for constructor and helpers
13 docs/planning/ROADMAP.md Phase 1, Task 3 Lines 91-103 — task description with time estimates and implementation notes

Specification References (for @see links in JSDoc)

# Document Use
14 OGC API - Connected Systems Part 1 (23-001) Canonical resource endpoint paths (/systems, /deployments, etc.) for URL construction
15 OGC API - Connected Systems Part 2 (23-002) Part 2 resource endpoint paths (/datastreams, /observations, etc.)
16 docs/research/standards/ogcapi-connectedsystems-1.bundled.oas31.yaml Part 1 OpenAPI schema — canonical endpoint definitions
17 docs/research/standards/ogcapi-connectedsystems-2.bundled.oas31.yaml Part 2 OpenAPI schema — query parameter definitions

Convention Quick Reference

Rule Example
Use .js extension for relative imports import { OgcApiCollectionInfo } from '../model.js'
Use import type for interfaces/types import type { SystemQueryOptions } from './model.js'
export default class for QueryBuilder export default class CSAPIQueryBuilder { ... }
Trailing underscore for private constructor params constructor(private collection_: OgcApiCollectionInfo)
Named exports for types and utilities export interface QueryOptions { ... }
HTTP mocking: globalThis.fetch = jest.fn() Probably not needed for this stub (no HTTP calls)
Meaningful tests only Verify actual URL output, validation error messages — not just that code runs without throwing

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions