Integrate template listing with Voyage mock API #23

Closed
opened 2026-01-03 23:39:47 +00:00 by KofTwentyTwo · 1 comment
KofTwentyTwo commented 2026-01-03 23:39:47 +00:00 (Migrated from github.com)

Part of #12

User Story

As a qctl user, I want qctl qqq list to fetch templates from a mock Voyage API so that the command works like the production flow will, even before Voyage is ready.

Design

Current State

Templates are fetched directly from GitHub:

  • Clone QRun-IO/templates-hub repository
  • Read directories as available templates
  • No registry metadata

Target State

Templates listed from mock API (and later real Voyage):

$ qctl qqq list
Available templates:
  qqq-web-api      v1.2.0   Web API application with Javalin middleware
  qqq-cli-tool     v1.0.0   Command-line tool with Picocli
  qqq-batch        v1.1.0   Batch processing application
  qqq-full-stack   v0.9.0   Full-stack with React frontend

Mock API Design

Serve from static JSON or embedded response:

{
  "templates": [
    {
      "id": "qqq-web-api",
      "name": "QQQ Web API",
      "version": "1.2.0",
      "description": "Web API application with Javalin middleware",
      "downloadUrl": "https://github.com/QRun-IO/templates-hub/archive/refs/heads/main.zip"
    }
  ]
}

API Client Interface

public interface TemplateRegistry {
    List<TemplateInfo> listTemplates() throws IOException;
    TemplateInfo getTemplate(String id) throws IOException;
    Path downloadTemplate(String id, String version) throws IOException;
}

public class MockTemplateRegistry implements TemplateRegistry { }
public class VoyageTemplateRegistry implements TemplateRegistry { }  // Future

Files to Create/Modify

File Action Description
TemplateRegistry.java Create Interface for template listing/download
TemplateInfo.java Create DTO for template metadata
MockTemplateRegistry.java Create Mock implementation with embedded data
ListCommand.java Modify Use TemplateRegistry instead of GitHub
InitCommand.java Modify Use TemplateRegistry for template fetch
mock-templates.json Create Embedded mock template list

Implementation Tasks

  • Define TemplateRegistry interface
  • Create TemplateInfo record (id, name, version, description, downloadUrl)
  • Create MockTemplateRegistry with hardcoded templates
  • Embed mock data as resource file or constants
  • Refactor ListCommand to use TemplateRegistry
  • Refactor InitCommand to use TemplateRegistry.downloadTemplate()
  • Add configuration for registry URL (for future Voyage) - via QCTL_REGISTRY_TYPE env var
  • Add caching layer with TTL for template list - 15-minute TTL in GitHubTemplateRegistry
  • Add --refresh flag to bypass cache
  • Add unit tests for mock registry - 13 tests (MockTemplateRegistryTest + TemplateRegistryFactoryTest)
  • Document API contract for future Voyage integration - TemplateRegistry interface

Acceptance Criteria

  • qctl qqq list shows templates from mock registry
  • Template metadata includes version and description
  • qctl qqq init <template> downloads from registry
  • Registry interface ready for Voyage implementation
  • Cache prevents repeated API calls
  • --refresh bypasses cache
  • Offline fallback to cached data
Part of #12 ## User Story As a **qctl user**, I want `qctl qqq list` to fetch templates from a mock Voyage API so that the command works like the production flow will, even before Voyage is ready. ## Design ### Current State Templates are fetched directly from GitHub: - Clone `QRun-IO/templates-hub` repository - Read directories as available templates - No registry metadata ### Target State Templates listed from mock API (and later real Voyage): ```bash $ qctl qqq list Available templates: qqq-web-api v1.2.0 Web API application with Javalin middleware qqq-cli-tool v1.0.0 Command-line tool with Picocli qqq-batch v1.1.0 Batch processing application qqq-full-stack v0.9.0 Full-stack with React frontend ``` ### Mock API Design Serve from static JSON or embedded response: ```json { "templates": [ { "id": "qqq-web-api", "name": "QQQ Web API", "version": "1.2.0", "description": "Web API application with Javalin middleware", "downloadUrl": "https://github.com/QRun-IO/templates-hub/archive/refs/heads/main.zip" } ] } ``` ### API Client Interface ```java public interface TemplateRegistry { List<TemplateInfo> listTemplates() throws IOException; TemplateInfo getTemplate(String id) throws IOException; Path downloadTemplate(String id, String version) throws IOException; } public class MockTemplateRegistry implements TemplateRegistry { } public class VoyageTemplateRegistry implements TemplateRegistry { } // Future ``` ## Files to Create/Modify | File | Action | Description | |------|--------|-------------| | `TemplateRegistry.java` | Create | Interface for template listing/download | | `TemplateInfo.java` | Create | DTO for template metadata | | `MockTemplateRegistry.java` | Create | Mock implementation with embedded data | | `ListCommand.java` | Modify | Use TemplateRegistry instead of GitHub | | `InitCommand.java` | Modify | Use TemplateRegistry for template fetch | | `mock-templates.json` | Create | Embedded mock template list | ## Implementation Tasks - [x] Define `TemplateRegistry` interface - [x] Create `TemplateInfo` record (id, name, version, description, downloadUrl) - [x] Create `MockTemplateRegistry` with hardcoded templates - [x] Embed mock data as resource file or constants - [x] Refactor `ListCommand` to use `TemplateRegistry` - [x] Refactor `InitCommand` to use `TemplateRegistry.downloadTemplate()` - [x] Add configuration for registry URL (for future Voyage) - via QCTL_REGISTRY_TYPE env var - [x] Add caching layer with TTL for template list - 15-minute TTL in GitHubTemplateRegistry - [x] Add `--refresh` flag to bypass cache - [x] Add unit tests for mock registry - 13 tests (MockTemplateRegistryTest + TemplateRegistryFactoryTest) - [x] Document API contract for future Voyage integration - TemplateRegistry interface ## Acceptance Criteria - [x] `qctl qqq list` shows templates from mock registry - [x] Template metadata includes version and description - [x] `qctl qqq init <template>` downloads from registry - [x] Registry interface ready for Voyage implementation - [x] Cache prevents repeated API calls - [x] `--refresh` bypasses cache - [x] Offline fallback to cached data
KofTwentyTwo commented 2026-01-04 03:01:25 +00:00 (Migrated from github.com)

Implementation Complete

Files Created

  • TemplateRegistry.java - Interface with list/get/download/refresh methods
  • TemplateInfo.java - Record for template metadata with toManifest() conversion
  • MockTemplateRegistry.java - Embedded mock data for 3 templates
  • GitHubTemplateRegistry.java - Wraps TemplatesHub with 15-minute cache TTL
  • TemplateRegistryFactory.java - Factory using QCTL_REGISTRY_TYPE env var

Files Modified

  • ListCommand.java - Uses TemplateRegistry, added --refresh flag
  • InitCommand.java - Uses TemplateRegistry for template selection/download
  • reflect-config.json - Added TemplateInfo for native-image

Tests Added

  • MockTemplateRegistryTest.java - 10 tests
  • TemplateRegistryFactoryTest.java - 3 tests

Usage

# Default (GitHub registry)
qctl qqq list

# Force cache refresh
qctl qqq list --refresh

# Use mock registry for testing
QCTL_REGISTRY_TYPE=mock qctl qqq list

Commit: e14565a

## Implementation Complete ### Files Created - `TemplateRegistry.java` - Interface with list/get/download/refresh methods - `TemplateInfo.java` - Record for template metadata with toManifest() conversion - `MockTemplateRegistry.java` - Embedded mock data for 3 templates - `GitHubTemplateRegistry.java` - Wraps TemplatesHub with 15-minute cache TTL - `TemplateRegistryFactory.java` - Factory using QCTL_REGISTRY_TYPE env var ### Files Modified - `ListCommand.java` - Uses TemplateRegistry, added `--refresh` flag - `InitCommand.java` - Uses TemplateRegistry for template selection/download - `reflect-config.json` - Added TemplateInfo for native-image ### Tests Added - `MockTemplateRegistryTest.java` - 10 tests - `TemplateRegistryFactoryTest.java` - 3 tests ### Usage ```bash # Default (GitHub registry) qctl qqq list # Force cache refresh qctl qqq list --refresh # Use mock registry for testing QCTL_REGISTRY_TYPE=mock qctl qqq list ``` Commit: e14565a
Sign in to join this conversation.