9.6 KiB
Implementation Plan: Config Wizard
Overview
Implement configure.js as a single-file interactive CLI wizard at the project root. The implementation follows the design's module structure: constants/registry, parsing, validation, display/prompt, file writing, and main flow orchestration. Property-based tests use fast-check in backend/__tests__/.
Tasks
-
1. Set up project structure and install test dependencies
-
1.1 Create
configure.jswith shebang, constants, and variable descriptor registry- Add
#!/usr/bin/env nodeheader - Define
VARIABLE_DESCRIPTORSarray with all 32 managed variables and their metadata (name, group, required, default, description, docUrl, sensitive, validator) - Define
GROUP_ORDERarray,GROUP_DESCRIPTIONSobject, andSENSITIVE_VARSlist - Export constants for testability using
module.exportsat the bottom (conditionally, so the file still runs as a script) - Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 3.1, 3.2, 3.3, 3.4
- Add
-
1.2 Install fast-check as a dev dependency in backend
- Run
npm install --save-dev fast-checkinbackend/ - Requirements: N/A (test infrastructure)
- Run
-
-
2. Implement parsing functions
-
2.1 Implement
resolveShellDefault(str)function- Extract default value from
${VAR:-default}pattern - Return original string if pattern not found
- Requirements: 4.1
- Extract default value from
-
2.2 Implement
parseDockerCompose(filePath)function- Line-by-line state machine parser for docker-compose.yml
- Extract POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB, and host port
- Resolve shell variable substitution via
resolveShellDefault - Return
nullif file missing or unparseable - Requirements: 4.1, 4.2, 4.3, 4.4
-
2.3 Implement
parseEnvFile(filePath)function- Read file line by line, split on first
= - Separate managed variables from unmanaged lines (including preceding comments)
- Handle quoted values (strip surrounding double quotes)
- Return
{ managed: Map, unmanaged: String[] } - Return empty maps if file doesn't exist or is unreadable
- Requirements: 9.1, 9.2, 9.4, 9.6
- Read file line by line, split on first
-
* 2.4 Write property test for shell default resolution
- Property 5: Shell variable default resolution
- Validates: Requirements 4.1
-
* 2.5 Write property test for DATABASE_URL construction
- Property 6: DATABASE_URL construction
- Validates: Requirements 4.2
-
* 2.6 Write property test for env file round-trip parsing
- Property 16: Env file round-trip parsing
- Validates: Requirements 9.1, 9.2
-
-
3. Implement validation functions
-
3.1 Implement all validation functions
validatePort(value)— integer in [1, 65535]validateCorsOrigins(value)— each comma-separated entry starts with http:// or https://validateDatabaseUrl(value)— starts withpostgresql://or equalssqlitevalidateSessionSecret(value)— at least 16 charactersvalidateRequired(value)— non-empty, non-whitespace-only- Requirements: 5.1, 5.2, 5.3, 5.4, 5.6
-
* 3.2 Write property tests for validation functions
- Property 8: Port validation
- Property 9: CORS origins validation
- Property 10: DATABASE_URL validation
- Property 11: SESSION_SECRET validation
- Property 12: Required variable rejection of whitespace
- Validates: Requirements 5.1, 5.2, 5.3, 5.4, 5.6
-
-
4. Implement display and prompt functions
-
4.1 Implement display functions
printWelcome()— purpose and instructionsprintGroupHeader(group)— group name and descriptionprintSummary(config, skippedGroups)— table with masked sensitive values, target file paths, overwrite indicatorsmaskSensitive(name, value)— first 4 + last 4 with asterisks for strings > 8 chars, full value otherwise- Requirements: 1.2, 2.3, 3.4, 8.1, 8.2, 8.3
-
4.2 Implement prompt functions
promptVariable(rl, descriptor, currentValue)— display label, description, default/current, docUrl; validate input; re-prompt on failurepromptYesNo(rl, question, defaultNo)— yes/no with configurable defaultpromptOverwrite(rl, filePath)— confirm overwrite, offer backup- Requirements: 3.1, 3.2, 3.3, 3.5, 5.5, 6.5, 7.1, 9.3
-
* 4.3 Write property test for sensitive value masking
- Property 4: Sensitive value masking
- Validates: Requirements 3.4
-
* 4.4 Write property test for derived URL defaults from PORT
- Property 7: Derived URL defaults from PORT
- Validates: Requirements 4.6
-
-
5. Checkpoint
- Ensure all tests pass, ask the user if questions arise.
-
6. Implement file writing functions
-
6.1 Implement
generateEnvContent(variables, groupOrder, groupDescriptions, unmanagedLines)function- Group header comments (
# --- Group Name ---) KEY=valuelines with conditional double-quote wrapping (spaces,#, quotes)- Omit optional variables with no value and no default
- Append unmanaged variables in
# --- Custom Variables ---section - Requirements: 6.1, 6.2, 6.3, 6.4, 9.4, 9.5
- Group header comments (
-
6.2 Implement
writeEnvFile(filePath, content)andcreateBackup(filePath)functions- Write content to file path using
fs.writeFileSync createBackupcopies existing file to{filename}.backup.{YYYYMMDD_HHmmss}- Handle filesystem errors with descriptive messages
- Requirements: 6.5, 6.6
- Write content to file path using
-
* 6.3 Write property test for env value quoting
- Property 13: Env value quoting
- Validates: Requirements 6.3
-
* 6.4 Write property test for optional variable omission
- Property 14: Optional variable omission
- Validates: Requirements 6.4
-
* 6.5 Write property test for skipped group exclusion
- Property 15: Skipped group exclusion
- Validates: Requirements 7.2, 7.3
-
* 6.6 Write property test for unmanaged variable preservation
- Property 17: Unmanaged variable preservation
- Validates: Requirements 9.4
-
* 6.7 Write property test for managed key deduplication
- Property 18: Managed key deduplication
- Validates: Requirements 9.5
-
-
7. Implement main flow orchestration
- 7.1 Implement
main()function and wire all components together- Validate project root (check
backend/andfrontend/exist) - Parse existing env files for pre-fill defaults
- Parse docker-compose.yml for derived defaults
- Set up readline interface and SIGINT handler
- Group loop: iterate GROUP_ORDER, prompt skip for optional groups, prompt each variable
- Derive REACT_APP_API_BASE, REACT_APP_API_HOST, CORS_ORIGINS from confirmed PORT
- Display summary, prompt confirmation (approve / restart / exit)
- Handle overwrite prompts and write both env files
- Display success message with next steps
- Exit code 0 on success, 1 on error/cancel
- Requirements: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 4.5, 4.6, 7.1, 7.2, 7.3, 7.4, 8.1, 8.2, 8.3, 8.4, 8.5
- Validate project root (check
- 7.1 Implement
-
8. Checkpoint
- Ensure all tests pass, ask the user if questions arise.
-
9. Write descriptor registry property tests
-
* 9.1 Write property test for descriptor registry invariants
- Property 1: Descriptor registry invariants
- Validates: Requirements 2.3, 2.5
-
* 9.2 Write property test for variable ordering within groups
- Property 2: Variable ordering within groups
- Validates: Requirements 2.4
-
* 9.3 Write property test for group presentation order
- Property 3: Group presentation order
- Validates: Requirements 2.1
-
-
10. Write integration and unit tests
-
* 10.1 Write unit tests for parseDockerCompose
- Test valid compose files, missing files, malformed content
- Requirements: 4.1, 4.2, 4.3, 4.4
-
* 10.2 Write unit tests for parseEnvFile
- Test standard files, quoted values, comments, empty lines, malformed lines
- Requirements: 9.1, 9.2, 9.4, 9.6
-
* 10.3 Write unit tests for generateEnvContent
- Test group headers, quoting rules, omission of empty optionals, custom variables section
- Requirements: 6.1, 6.2, 6.3, 6.4, 9.4, 9.5
-
* 10.4 Write integration tests for full wizard flow
- Test full run with defaults accepted, existing env pre-fill, skipped groups, SIGINT handling, missing project structure error
- Use temporary directories and mock readline input
- Requirements: 1.1, 1.4, 1.5, 7.1, 7.2, 7.3, 8.4, 8.5, 9.1
-
-
11. Final checkpoint
- Ensure all tests pass, ask the user if questions arise.
Notes
- Tasks marked with
*are optional and can be skipped for faster MVP - Each task references specific requirements for traceability
- Checkpoints ensure incremental validation
- Property tests validate universal correctness properties from the design document
- Unit tests validate specific examples and edge cases
- All code goes in a single
configure.jsfile at the project root - Tests go in
backend/__tests__/using Jest + fast-check - The file uses
module.exportsconditionally (only whenrequire.main !== module) so it can be both a runnable script and importable for testing
Task Dependency Graph
{
"waves": [
{ "id": 0, "tasks": ["1.1", "1.2"] },
{ "id": 1, "tasks": ["2.1", "2.2", "2.3", "3.1"] },
{ "id": 2, "tasks": ["2.4", "2.5", "2.6", "3.2", "4.1", "4.2"] },
{ "id": 3, "tasks": ["4.3", "4.4", "6.1", "6.2"] },
{ "id": 4, "tasks": ["6.3", "6.4", "6.5", "6.6", "6.7", "7.1"] },
{ "id": 5, "tasks": ["9.1", "9.2", "9.3", "10.1", "10.2", "10.3"] },
{ "id": 6, "tasks": ["10.4"] }
]
}