Skip to content

Implement comprehensive test suite with matrix-driven configuration validation#4

Open
eugenegraves wants to merge 34 commits into
mainfrom
test-suite
Open

Implement comprehensive test suite with matrix-driven configuration validation#4
eugenegraves wants to merge 34 commits into
mainfrom
test-suite

Conversation

@eugenegraves
Copy link
Copy Markdown
Collaborator

@eugenegraves eugenegraves commented Nov 8, 2025

Summary

  • Stabilized CLI scaffolds uncovered by the expanded test harness: added missing configuration templates, guarded generator logic, and enforced clean pre-run states so every supported combo boots without manual cleanup.
  • Elevated the functional testing stack: each framework, database, auth, and cloud runner now performs pre-run teardown, leverages dependency caching, and filters the matrix to only implemented options—eliminating false negatives from unsupported stacks (e.g., PlanetScale/MySQL).
  • Introduced auth validation atop the functional suite and documented the full battery of scripts in package.json, giving contributors a repeatable path to verify scaffolds end-to-end.
  • Hardened configuration generation in response to the latest issues: tsconfig scaffolding now guards reads/writes with clear error messaging, custom directory prompts fire interactively instead of silently defaulting, and Vue shims ensure their src/types directory exists before writing.

CLI Fixes Driven by Testing

  • Created src/templates/configurations/tsconfig.example.json, src/templates/configurations/eslint.config.mjs, and src/templates/configurations/.prettierignore to resolve TypeScript compile errors and lint failures during scaffolded project validation.
  • Added cleanupProjectDirectory and wired it into every runner to remove stale scaffold directories before each test, preventing “directory already exists” aborts.
  • Updated matrix filters across framework/database/cloud runners to exclude unimplemented engines/ORMs/providers (PlanetScale/MySQL, Prisma combos, etc.), preserving focus on supported permutations.
  • Extended dependency caching support so repeated installs across the 1k+ test cases reuse node_modules snapshots, stabilizing install steps and cutting runtime.
  • Wrapped tsconfig template processing in a try/catch, creating the project directory on demand and logging contextual errors when reads, parses, or writes fail.
  • Ensured getFrontendDirectoryConfigurations prompts for custom layouts instead of silently applying defaults, while non-custom flows retain automatic values for CI/--skip.
  • Created src/types/ automatically for Vue projects before emitting vue-shim.d.ts, eliminating intermittent ENOENT failures in validators.

Test Coverage & Results (Most Recent Full Runs)

Suite Scope Pass Count Total Success Rate Notes
Functional core Structure, build, dependency, server validators (test:functional, test:server, test:build, test:deps) 4 4 100% Baseline scaffold sanity.
React Validator + full matrix runner 96 96 100% All supported DB/ORM/auth combos; custom directory prompts verified.
Vue Validator + full matrix runner 88 96 91.7% Eight “none + none” permutations still fail during dependency install (expected).
Svelte Validator + full matrix runner 88 96 91.7% Same “none + none” dependency issue.
HTML Validator + full matrix runner 88 96 91.7% Minimal stacks without DB continue to fail install; no regressions.
HTMX Validator + full matrix runner 88 96 91.7% Follows the HTML pattern; known install gaps remain.
SQLite Validator + full matrix runner 320 320 100% Covers local + Turso scenarios across frameworks/ORMs/auth.
PostgreSQL Validator + full matrix runner 160 320 50.0% Neon (remote) passes; local Docker combos fail due to sandbox/docker credential limits.
MySQL Validator + full matrix runner 0 320 0% PlanetScale filtered out; remaining local Docker combos fail and local runs expose schema mismatch (uid) still pending fix.
MongoDB Validator + full matrix runner 0 80 0% Handlers fail on missing users/count_history collections; captured for follow-up.
Cloud providers Neon/PostgreSQL, Turso/SQLite combinations 320 320 100% PlanetScale/MySQL excluded until implementation lands.
Auth Validator + full matrix runner (absoluteAuth across frameworks/DBs) 200 200 100% Confirms handler/schema/env/server integration plus functional pass-through.

Totals reflect supported combinations after matrix filtering; Docker-dependent failures and template gaps remain documented but no longer bring down the suite.

Testing Commands

  • bun run test:functional
  • bun run test:server
  • bun run test:build
  • bun run test:deps
  • bun run test:react
  • bun run test:react:all
  • bun run test:vue
  • bun run test:vue:all
  • bun run test:svelte
  • bun run test:svelte:all
  • bun run test:html
  • bun run test:html:all
  • bun run test:htmx
  • bun run test:htmx:all
  • bun run test:sqlite
  • bun run test:sqlite:all
  • bun run test:postgresql
  • bun run test:postgresql:all
  • bun run test:mysql
  • bun run test:mysql:all
  • bun run test:mongodb
  • bun run test:mongodb:all
  • bun run test:cloud
  • bun run test:cloud:all
  • bun run test:auth
  • bun run test:auth:all

Summary by CodeRabbit

Release Notes

New Features

  • Comprehensive Test Infrastructure – Added functional and behavioral test suites for validating framework integrations, database configurations, and authentication setups across multiple combinations.
  • Prisma ORM Support – Added dependencies and configuration for Prisma, including cloud provider support (Neon, PlanetScale).
  • Database Validators – Introduced validators for PostgreSQL (local and remote), MySQL, MongoDB, and SQLite configurations.
  • Git Installation Detection – Added cross-platform Git availability checking with automated installation prompts.
  • Dependency Caching – Implemented caching system for faster test execution.

Bug Fixes

  • Improved error handling in project formatting.
  • Enhanced non-interactive mode defaults.

Chores

  • Updated ESLint and TypeScript configuration.
  • Removed deprecated Prettier configuration template.
  • Added test documentation and migration guides.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 8, 2025

Walkthrough

This pull request introduces a comprehensive test infrastructure overhaul for the AbsoluteJS project scaffolder. It adds 20+ new functional test validators for various frameworks and databases, implements a dependency caching system for test optimization, creates a matrix-based test execution CLI, establishes behavioral test suites with database hooks, and updates code generators to support Prisma ORM and enhanced PostgreSQL/Drizzle configurations alongside existing database support.

Changes

Cohort / File(s) Summary
Test Infrastructure - Core New test execution CLI, matrix configuration, and runner orchestration
scripts/functional-tests/test-cli.ts, scripts/functional-tests/matrix.ts, scripts/functional-tests/test-cli-registry.ts, scripts/functional-tests/functional-test-runner.ts CLI argument parsing, suite registry, matrix generation with skip/required-env annotation, and three-step functional test coordination (dependencies, build, server)
Test Infrastructure - Validators Framework and database-specific validators
scripts/functional-tests/auth-validator.ts, scripts/functional-tests/react-validator.ts, scripts/functional-tests/vue-validator.ts, scripts/functional-tests/svelte-validator.ts, scripts/functional-tests/htmx-validator.ts Framework validators delegating to functional test suites with framework-specific checks and error aggregation
scripts/functional-tests/mongodb-validator.ts, scripts/functional-tests/mysql-validator.ts, scripts/functional-tests/postgresql-validator.ts, scripts/functional-tests/sqlite-validator.ts, scripts/functional-tests/cloud-provider-validator.ts Database validators with local Docker orchestration, remote host support (Neon, PlanetScale, Turso), and connection verification
Test Infrastructure - Utilities Build, server, and dependency installation validators
scripts/functional-tests/build-validator.ts, scripts/functional-tests/server-startup-validator.ts, scripts/functional-tests/dependency-installer-tester.ts TypeScript compilation, server typecheck, and dependency installation validation with timeout handling
Dependency Caching Manifest hashing and per-configuration caching
scripts/functional-tests/dependency-cache.ts Fingerprint-based cache management with SHA-256 hashing, manifest comparison, and timed cleanup
Behavioral Tests Multi-database scenario tests with hooks
tests/behavioural/auth-matrix.test.ts, tests/behavioural/cloud-matrix.test.ts, tests/behavioural/database-matrix.test.ts, tests/behavioural/database-matrix.ts, tests/behavioural/database-matrix-definitions.ts, tests/behavioural/database-hooks.ts, tests/behavioural/utils.ts RESTful scenario runners for count/history and auth endpoints, database lifecycle hooks (PostgreSQL, MySQL, MongoDB), and environment isolation
Functional Tests Matrix-driven framework and database test suites
tests/functional/auth.test.ts, tests/functional/cloud.test.ts, tests/functional/frameworks/*, tests/functional/databases/* Framework/database matrix filtering, scaffolding, dependency installation, and validation orchestration with per-scenario timeouts
tests/functional/frameworks/test-utils.ts Matrix suite orchestration with configurable lifecycle hooks (beforeValidate, afterValidate) and error aggregation
Functional Test Support Test helpers for HTTP, Docker, filesystem, installation, scaffolding
tests/functional/support/assertions.ts, tests/functional/support/docker.ts, tests/functional/support/filesystem.ts, tests/functional/support/http.ts, tests/functional/support/install.ts, tests/functional/support/scaffold.ts, tests/functional/support/timing.ts, tests/functional/support/types.ts, tests/functional/support/index.ts Docker lifecycle (up/down/availability check), project scaffolding with timeout/env handling, dependency installation with caching, HTTP health checks, timing utilities
Harness - Shared Test Utilities Re-usable test infrastructure
tests/harness/cli.ts, tests/harness/http.ts, tests/harness/process.ts, tests/harness/project.ts, tests/harness/server.ts, tests/harness/types.ts, tests/harness/index.ts, tests/harness/harness.test.ts Scaffold argument building, HTTP polling, process spawning with timeout/cleanup, child process server management with graceful shutdown
Generators - Prisma & DB Support Prisma ORM integration and PostgreSQL adapter
src/generators/configurations/generatePackageJson.ts, src/generators/db/generateHandlers.ts, src/generators/db/generateDrizzleSchema.ts, src/generators/db/ensurePostgresSqlAdapter.ts, src/generators/db/handlerTemplates.ts, src/generators/db/generateDBBlock.ts, src/generators/db/generateImportsBlock.ts, src/generators/db/dockerInitTemplates.ts, src/generators/db/generateDockerContainer.ts, src/generators/db/scaffoldDocker.ts Prisma runtime/dev dependencies, PostgreSQL pg Pool wrapper (createPgSql), auth_sub-based user/session lookups, Neon/MongoDB connection updates, remote vs local Drizzle handling, MongoDB Docker init, shared container support via ABSOLUTE_TEST env var
Generators - Configuration & Routes Configuration file generation and routing
src/generators/configurations/generateEnv.ts, src/generators/configurations/scaffoldConfigurationFiles.ts, src/generators/project/generateServer.ts, src/generators/project/generateRoutesBlock.ts, src/generators/project/generateImportsBlock.ts, src/generators/project/generateUseBlock.ts Updated DB connection URLs (MongoDB 27018, PostgreSQL 5433), dynamic tsconfig JSX option per frontend, Vue type shims, PostgreSQL adapter initialization, databaseEngine thread-through, absoluteAuth config refactoring
CLI & Utils Command execution and argument parsing
src/commands/formatProject.ts, src/commands/initializeGit.ts, src/utils/parseCommandLineOptions.ts, src/utils/checkGitInstalled.ts, scripts/clean-tests.sh Non-throwing format errors with yellow messages, Git availability pre-flight check with platform-specific installers, non-interactive defaults when --skip provided, test artifact cleanup script
Configuration & Templates Template files and tooling config
src/templates/configurations/.prettierignore, src/templates/configurations/.prettierrc.json, src/templates/configurations/tsconfig.example.json, src/templates/configurations/eslint.config.mjs, src/templates/configurations/drizzle.config.ts, .gitignore, eslint.config.mjs, tsconfig.json Prettier ignore newline, Prettier config removal, streamlined tsconfig with JSX support, simplified ESLint rules + test directory globals, drizzle.config.ts removal, test-dependency-cache ignore, TypeScript paths expansion
Documentation Test infrastructure planning and usage
docs/test-cli-migration-phase0.md, docs/test-cli-migration-phase1.md, docs/test-cli-ux.md, docs/cloud-auth-test-verification.md, README.md Phase 0 baseline, Phase 1 shared utilities plan, Test CLI UX spec, cloud/auth verification guide, README removal
Package & Config Scripts and TypeScript config
package.json, tsconfig.json New scripts: test:behavioural, test:clean, test:cli; TypeScript includes for scripts/ and tests/

Sequence Diagram(s)

sequenceDiagram
    participant CLI as Test CLI
    participant Matrix as Matrix Generator
    participant Suite as Functional Suite
    participant Scaffold as Scaffold Project
    participant Deps as Install Dependencies
    participant Build as Build Validator
    participant Serve as Server Validator
    participant Validate as Framework/DB Validator

    CLI->>Matrix: createMatrix()
    Matrix-->>CLI: MatrixConfig[]
    
    CLI->>Matrix: annotateHostConstraints()
    Matrix-->>CLI: annotated configs with skip/required-env
    
    loop per suite
        CLI->>Suite: runFunctionalTests()
        
        rect rgb(200, 220, 255)
            Suite->>Scaffold: scaffoldProject()
            Scaffold-->>Suite: projectPath
            
            Suite->>Deps: testDependencyInstallation()
            Deps-->>Suite: DependencyInstallResult
        end
        
        rect rgb(200, 255, 220)
            Suite->>Build: validateBuild()
            Build-->>Suite: BuildResult
        end
        
        rect rgb(255, 220, 200)
            Suite->>Serve: validateServerStartup()
            Serve-->>Suite: ServerStartupResult
        end
        
        Suite-->>CLI: FunctionalTestResult
        
        CLI->>Validate: validateFramework/Database()
        Validate->>Validate: aggregate functional results
        Validate-->>CLI: ValidationResult
    end
Loading
sequenceDiagram
    participant Test as Behavioural Test
    participant Scenario as Scenario Runner
    participant Scaffold as Scaffold
    participant DB as Database Hooks
    participant Server as Server
    participant HTTP as HTTP Client

    Test->>Scenario: runCountHistoryScenario()
    
    Scenario->>Scaffold: scaffoldProject(config)
    Scaffold-->>Scenario: projectPath
    
    Scenario->>DB: beforeServerStart()
    
    rect rgb(200, 220, 255)
        DB->>DB: docker compose up
        DB->>DB: wait for readiness
    end
    
    Scenario->>Server: startServer()
    Server-->>Scenario: running server
    
    Scenario->>HTTP: POST /count
    HTTP-->>Scenario: { uid, count }
    
    Scenario->>HTTP: GET /count?uid=...
    HTTP-->>Scenario: history array
    
    Scenario->>Server: server.stop()
    
    Scenario->>DB: afterServerStop()
    DB->>DB: docker compose down
    
    Scenario-->>Test: result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • Dependency cache fingerprinting & hashing (scripts/functional-tests/dependency-cache.ts): Complex manifest hash computation with lock file merging and cache invalidation logic; verify SHA-256 correctness and edge cases with missing/unreadable files
  • Database validators (scripts/functional-tests/*-validator.ts): Each has distinct Docker orchestration, connection verification, and query patterns; PostgreSQL includes Docker state tracking and Neon-specific handling requiring careful review
  • Matrix generation & annotation (scripts/functional-tests/matrix.ts): Sophisticated cartesian product with host constraints, ORM compatibility rules, and skip reason logic; verify correctness of filtering and that all combinations are properly annotated
  • Functional test orchestration (scripts/functional-tests/functional-test-runner.ts): Three-step pipeline aggregating results across installation, build, and server validation; ensure error propagation and timing are correct
  • Behavioral test environment isolation (tests/behavioural/utils.ts, tests/behavioural/database-hooks.ts): Complex child process environment building with database-specific readiness checks and cleanup; verify robustness of Docker availability handling and timeout mechanics
  • Handler template auth_sub migration (src/generators/db/handlerTemplates.ts): Sweeping changes from insertId-based lookups to auth_sub-based; verify compatibility across all ORM/database combinations and that identity extraction fallbacks are correct
  • PostgreSQL Pool adapter (src/generators/db/ensurePostgresSqlAdapter.ts): New SQL templating and parameter normalization; verify parameter binding safety and type coercion correctness

Possibly related PRs

Suggested reviewers

  • absolutejs

Poem

🐰 Hops through the test matrix with glee,
Dependencies cached, validators run free,
Databases dockerized, handlers auth-signed,
A comprehensive harness—test infrastructure refined!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately captures the main objective: implementing a comprehensive test suite with matrix-driven configuration validation. It is concise and clearly conveys the primary change.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch test-suite

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 24

🧹 Nitpick comments (6)
src/commands/formatProject.ts (1)

6-6: Remove unused import.

The formatNoInstallCommands import is no longer used after the refactoring to always use formatCommands.

Apply this diff:

-import { formatCommands, formatNoInstallCommands } from '../utils/commandMaps';
+import { formatCommands } from '../utils/commandMaps';
scripts/functional-tests/database-connection-tester.ts (1)

11-11: Remove unused import.

The readFileSync import is not used anywhere in the file.

Apply this diff:

-import { existsSync, readFileSync } from 'fs';
+import { existsSync } from 'fs';
scripts/functional-tests/frontend-renderer-tester.ts (4)

18-24: Consider prefixing unused parameters with underscore.

The projectPath and config parameters are declared but never used in the function body. To signal intentionally unused parameters and avoid linting warnings, consider prefixing them with an underscore (e.g., _projectPath, _config) or add basic validation such as checking that the project path exists.

Apply this diff to prefix unused parameters:

 export async function testFrontendRendering(
-  projectPath: string,
+  _projectPath: string,
   serverUrl: string = 'http://localhost:3000',
-  config: {
+  _config: {
     frontends?: string[];
   } = {}
 ): Promise<FrontendRendererResult> {

47-47: Use the errors variable for consistency.

Line 47 returns an empty array literal errors: [] instead of the errors variable declared on line 25. For consistency with how warnings is returned, use the variable.

Apply this diff:

-  return { passed: true, errors: [], warnings };
+  return { passed: true, errors, warnings };

50-78: CLI usage is well-structured.

The CLI block properly validates input presence, handles errors, and uses appropriate exit codes. The error messages are clear and helpful.

Optionally, you could add validation that the project path exists to provide earlier feedback:

import { existsSync } from 'fs';

// ... after line 58
if (!existsSync(projectPath)) {
  console.error(`Error: Project path "${projectPath}" does not exist`);
  process.exit(1);
}

28-47: Placeholder always succeeds—consider test suite implications.

The function returns passed: true regardless of actual validation, which means any tests using this helper will pass until the implementation is complete. While the warnings alert users to the incomplete state, you might consider either:

  • Documenting this behavior in the function's JSDoc
  • Having it fail by default with an opt-in flag for placeholder mode
  • Ensuring the test suite explicitly filters out tests using this placeholder

This helps prevent false confidence in test coverage.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0177f83 and 017b8d6.

📒 Files selected for processing (54)
  • .gitignore (1 hunks)
  • package.json (1 hunks)
  • scripts/check-project-structure.ts (1 hunks)
  • scripts/functional-tests/api-endpoint-tester.ts (1 hunks)
  • scripts/functional-tests/auth-test-runner.ts (1 hunks)
  • scripts/functional-tests/auth-validator.ts (1 hunks)
  • scripts/functional-tests/build-validator.ts (1 hunks)
  • scripts/functional-tests/cloud-provider-test-runner.ts (1 hunks)
  • scripts/functional-tests/cloud-provider-validator.ts (1 hunks)
  • scripts/functional-tests/database-connection-tester.ts (1 hunks)
  • scripts/functional-tests/dependency-cache.ts (1 hunks)
  • scripts/functional-tests/dependency-installer-tester.ts (1 hunks)
  • scripts/functional-tests/frontend-renderer-tester.ts (1 hunks)
  • scripts/functional-tests/functional-test-runner.ts (1 hunks)
  • scripts/functional-tests/html-test-runner.ts (1 hunks)
  • scripts/functional-tests/html-validator.ts (1 hunks)
  • scripts/functional-tests/htmx-test-runner.ts (1 hunks)
  • scripts/functional-tests/htmx-validator.ts (1 hunks)
  • scripts/functional-tests/mongodb-test-runner.ts (1 hunks)
  • scripts/functional-tests/mongodb-validator.ts (1 hunks)
  • scripts/functional-tests/mysql-test-runner.ts (1 hunks)
  • scripts/functional-tests/mysql-validator.ts (1 hunks)
  • scripts/functional-tests/postgresql-test-runner.ts (1 hunks)
  • scripts/functional-tests/postgresql-validator.ts (1 hunks)
  • scripts/functional-tests/react-test-runner.ts (1 hunks)
  • scripts/functional-tests/react-validator.ts (1 hunks)
  • scripts/functional-tests/server-startup-validator.ts (1 hunks)
  • scripts/functional-tests/sqlite-test-runner.ts (1 hunks)
  • scripts/functional-tests/sqlite-validator.ts (1 hunks)
  • scripts/functional-tests/svelte-test-runner.ts (1 hunks)
  • scripts/functional-tests/svelte-validator.ts (1 hunks)
  • scripts/functional-tests/test-utils.ts (1 hunks)
  • scripts/functional-tests/vue-test-runner.ts (1 hunks)
  • scripts/functional-tests/vue-validator.ts (1 hunks)
  • scripts/generate-test-matrix.ts (1 hunks)
  • scripts/verify-test-matrix.ts (1 hunks)
  • src/commands/formatProject.ts (1 hunks)
  • src/generators/configurations/generatePackageJson.ts (2 hunks)
  • src/generators/configurations/scaffoldConfigurationFiles.ts (1 hunks)
  • src/generators/db/generateHandlers.ts (1 hunks)
  • src/generators/db/handlerTemplates.ts (2 hunks)
  • src/generators/project/generateDBBlock.ts (3 hunks)
  • src/generators/project/generateImportsBlock.ts (2 hunks)
  • src/generators/project/generateRoutesBlock.ts (4 hunks)
  • src/generators/project/generateServer.ts (1 hunks)
  • src/generators/project/generateUseBlock.ts (1 hunks)
  • src/questions/directoryConfiguration.ts (1 hunks)
  • src/questions/frontendDirectoryConfigurations.ts (3 hunks)
  • src/templates/configurations/.prettierignore (1 hunks)
  • src/templates/configurations/.prettierrc.json (0 hunks)
  • src/templates/configurations/drizzle.config.ts (0 hunks)
  • src/templates/configurations/eslint.config.mjs (2 hunks)
  • src/templates/configurations/tsconfig.example.json (1 hunks)
  • src/utils/parseCommandLineOptions.ts (3 hunks)
💤 Files with no reviewable changes (2)
  • src/templates/configurations/.prettierrc.json
  • src/templates/configurations/drizzle.config.ts
🧰 Additional context used
🧬 Code graph analysis (43)
src/generators/db/generateHandlers.ts (1)
src/questions/orm.ts (1)
  • databaseEngine (7-28)
src/generators/configurations/scaffoldConfigurationFiles.ts (2)
src/generators/vue/scaffoldVue.ts (1)
  • ScaffoldVueProps (8-27)
src/generators/project/scaffoldFrontends.ts (1)
  • ScaffoldFrontendsProps (19-106)
src/questions/frontendDirectoryConfigurations.ts (4)
src/data.ts (1)
  • frontendLabels (55-62)
src/generators/project/scaffoldFrontends.ts (1)
  • ScaffoldFrontendsProps (19-106)
src/questions/configurationType.ts (1)
  • directoryConfig (5-16)
src/prompt.ts (2)
  • frontend (34-34)
  • argumentConfiguration (18-123)
scripts/functional-tests/mongodb-validator.ts (3)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/db/generateDockerContainer.ts (1)
  • databaseEngine (84-114)
scripts/functional-tests/frontend-renderer-tester.ts (5)
src/generators/project/scaffoldFrontends.ts (1)
  • ScaffoldFrontendsProps (19-106)
src/generators/svelte/scaffoldSvelte.ts (1)
  • ScaffoldFrontendProps (6-33)
src/generators/htmx/scaffoldHTMX.ts (1)
  • ScaffoldFrontendProps (8-46)
src/generators/html/generateHTMLPage.ts (1)
  • frontends (4-75)
src/generators/react/scaffoldReact.ts (1)
  • ScaffoldFrontendProps (7-35)
scripts/functional-tests/api-endpoint-tester.ts (2)
src/generators/project/scaffoldFrontends.ts (1)
  • ScaffoldFrontendsProps (19-106)
src/generators/htmx/scaffoldHTMX.ts (1)
  • ScaffoldFrontendProps (8-46)
scripts/functional-tests/test-utils.ts (1)
src/generators/configurations/initializeRoot.ts (1)
  • projectName (4-44)
scripts/functional-tests/mongodb-test-runner.ts (5)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/functional-test-runner.ts (1)
  • runFunctionalTests (24-120)
scripts/functional-tests/mongodb-validator.ts (1)
  • validateMongoDBDatabase (22-170)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
scripts/functional-tests/database-connection-tester.ts (7)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
src/generators/db/generateDockerContainer.ts (1)
  • databaseEngine (84-114)
src/generators/configurations/generateEnv.ts (1)
  • GenerateEnvProps (23-44)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
src/questions/orm.ts (1)
  • databaseEngine (7-28)
scripts/functional-tests/cloud-provider-validator.ts (5)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (24-120)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
scripts/verify-test-matrix.ts (3)
src/types.ts (6)
  • DatabaseEngine (45-47)
  • ORM (52-52)
  • DatabaseHost (49-49)
  • Frontend (21-21)
  • AuthProvider (40-40)
  • CodeQualityTool (53-53)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
scripts/functional-tests/html-validator.ts (3)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (24-120)
src/generators/html/scaffoldHTML.ts (1)
  • ScaffoldHTMLProps (11-41)
src/generators/html/generateHTMLPage.ts (1)
  • frontends (4-75)
scripts/functional-tests/sqlite-test-runner.ts (4)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/functional-test-runner.ts (1)
  • runFunctionalTests (24-120)
scripts/functional-tests/sqlite-validator.ts (1)
  • validateSQLiteDatabase (23-157)
scripts/check-project-structure.ts (1)
src/generators/configurations/initializeRoot.ts (1)
  • projectName (4-44)
scripts/functional-tests/functional-test-runner.ts (4)
scripts/check-project-structure.ts (1)
  • checkProjectStructure (17-48)
scripts/functional-tests/dependency-installer-tester.ts (1)
  • testDependencyInstallation (18-105)
scripts/functional-tests/build-validator.ts (1)
  • validateBuild (18-109)
scripts/functional-tests/server-startup-validator.ts (1)
  • validateServerStartup (20-109)
scripts/functional-tests/svelte-test-runner.ts (3)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/svelte-validator.ts (1)
  • validateSvelteFramework (24-162)
scripts/functional-tests/svelte-validator.ts (4)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (24-120)
src/generators/svelte/scaffoldSvelte.ts (1)
  • ScaffoldFrontendProps (6-33)
src/generators/project/scaffoldFrontends.ts (1)
  • ScaffoldFrontendsProps (19-106)
src/generators/svelte/generateSveltePage.ts (1)
  • frontends (4-218)
scripts/functional-tests/mysql-validator.ts (4)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
src/generators/db/generateDockerContainer.ts (1)
  • databaseEngine (84-114)
scripts/functional-tests/mysql-test-runner.ts (6)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/functional-test-runner.ts (1)
  • runFunctionalTests (24-120)
scripts/functional-tests/mysql-validator.ts (1)
  • validateMySQLDatabase (23-198)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
scripts/functional-tests/react-validator.ts (3)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (24-120)
src/generators/react/scaffoldReact.ts (1)
  • ScaffoldFrontendProps (7-35)
src/templates/react/pages/ReactExample.tsx (1)
  • ReactExampleProps (7-18)
scripts/functional-tests/react-test-runner.ts (3)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/react-validator.ts (1)
  • validateReactFramework (24-140)
src/generators/db/handlerTemplates.ts (1)
src/questions/authProvider.ts (1)
  • authProvider (5-16)
src/generators/project/generateServer.ts (5)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/configurations/generateEnv.ts (1)
  • GenerateEnvProps (23-44)
src/generators/db/generateDockerContainer.ts (1)
  • databaseEngine (84-114)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
src/utils/parseCommandLineOptions.ts (1)
src/prompt.ts (1)
  • argumentConfiguration (18-123)
scripts/functional-tests/build-validator.ts (2)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
scripts/functional-tests/vue-validator.ts (2)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (24-120)
src/generators/vue/scaffoldVue.ts (1)
  • ScaffoldVueProps (8-27)
scripts/functional-tests/postgresql-test-runner.ts (4)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/functional-test-runner.ts (1)
  • runFunctionalTests (24-120)
scripts/functional-tests/postgresql-validator.ts (1)
  • validatePostgreSQLDatabase (23-198)
scripts/functional-tests/htmx-validator.ts (3)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (24-120)
src/generators/htmx/scaffoldHTMX.ts (1)
  • ScaffoldFrontendProps (8-46)
src/generators/project/scaffoldFrontends.ts (1)
  • ScaffoldFrontendsProps (19-106)
scripts/functional-tests/auth-validator.ts (4)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (24-120)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
scripts/functional-tests/htmx-test-runner.ts (5)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/htmx-validator.ts (1)
  • validateHTMXFramework (24-181)
src/generators/htmx/scaffoldHTMX.ts (1)
  • ScaffoldFrontendProps (8-46)
src/generators/project/scaffoldFrontends.ts (1)
  • ScaffoldFrontendsProps (19-106)
src/generators/project/generateRoutesBlock.ts (2)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/configurations/generateEnv.ts (1)
  • GenerateEnvProps (23-44)
scripts/functional-tests/dependency-installer-tester.ts (2)
src/utils/commandMaps.ts (1)
  • installCommands (17-22)
src/commands/installDependencies.ts (1)
  • packageManager (8-24)
src/questions/directoryConfiguration.ts (3)
src/prompt.ts (1)
  • argumentConfiguration (18-123)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/project/scaffoldFrontends.ts (1)
  • ScaffoldFrontendsProps (19-106)
scripts/generate-test-matrix.ts (6)
src/types.ts (6)
  • Frontend (21-21)
  • DatabaseEngine (45-47)
  • ORM (52-52)
  • DatabaseHost (49-49)
  • AuthProvider (40-40)
  • CodeQualityTool (53-53)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/configurations/generateEnv.ts (1)
  • GenerateEnvProps (23-44)
src/generators/project/scaffoldFrontends.ts (1)
  • ScaffoldFrontendsProps (19-106)
scripts/functional-tests/sqlite-validator.ts (4)
src/utils/checkSqliteInstalled.ts (7)
  • hasSqlite (137-159)
  • hasSqlite (112-117)
  • commandExists (80-110)
  • commandExists (119-135)
  • $ (34-35)
  • $ (27-32)
  • cmd (21-25)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
scripts/functional-tests/postgresql-validator.ts (5)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
src/generators/db/generateDockerContainer.ts (1)
  • databaseEngine (84-114)
scripts/functional-tests/dependency-cache.ts (2)
src/generators/project/collectDependencies.ts (2)
  • dependency (39-39)
  • CollectDependenciesProps (17-48)
src/commands/installDependencies.ts (1)
  • packageManager (8-24)
src/generators/configurations/generatePackageJson.ts (3)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/db/generateDockerContainer.ts (1)
  • databaseEngine (84-114)
scripts/functional-tests/html-test-runner.ts (3)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/html-validator.ts (1)
  • validateHTMLFramework (24-187)
scripts/functional-tests/vue-test-runner.ts (3)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/vue-validator.ts (1)
  • validateVueFramework (24-160)
scripts/functional-tests/auth-test-runner.ts (3)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/auth-validator.ts (1)
  • validateAuthConfiguration (43-178)
scripts/functional-tests/cloud-provider-test-runner.ts (3)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/cloud-provider-validator.ts (1)
  • validateCloudProvider (26-230)
src/commands/formatProject.ts (1)
src/utils/commandMaps.ts (1)
  • formatCommands (3-8)
🔇 Additional comments (12)
src/templates/configurations/.prettierignore (1)

1-5: Looks good.

Standard Prettier ignore patterns (dependencies, build artifacts, minified files) with proper trailing newline following POSIX convention. This template is ready for scaffolding.

src/commands/formatProject.ts (2)

19-23: LGTM: Early return guard prevents hanging in non-interactive mode.

The guard correctly skips formatting when dependencies aren't installed, preventing the command from hanging on bunx/npx prettier calls during non-interactive test runs.


28-28: LGTM: Command selection simplified correctly.

Since the early return ensures installDependenciesNow is true at this point, always using formatCommands[packageManager] is safe and removes unnecessary conditional logic.

scripts/functional-tests/database-connection-tester.ts (3)

1-9: Good documentation of current limitations.

The header clearly communicates that this is a placeholder implementation and outlines what's needed for full functionality.


14-62: Validation logic is appropriate for a placeholder.

The function correctly validates the basic project structure (db directory, schema files) and clearly communicates its limitations through warnings. The early-return pattern keeps the code readable.


64-97: CLI interface is well-structured.

The command-line interface properly validates inputs, provides clear usage instructions, and formats output in a user-friendly way with appropriate exit codes.

scripts/functional-tests/frontend-renderer-tester.ts (1)

1-16: Clear documentation and appropriate result type.

The header comment clearly communicates the placeholder status and outlines the future requirements. The FrontendRendererResult type follows a standard pattern for test results.

scripts/functional-tests/api-endpoint-tester.ts (2)

8-12: LGTM: Clean result type definition.

The APIEndpointResult type follows standard conventions for test result reporting with clear boolean pass/fail status and separate arrays for errors and warnings.


44-72: LGTM: Well-structured CLI entry point.

The CLI implementation properly handles argument parsing, validation, result reporting, and exit codes. Error handling is appropriate with both promise rejection and general error catching.

Minor note: The CLI currently doesn't expose the config parameter (auth provider, frontends) to command-line users, which is fine for this placeholder implementation but may need extension when the actual testing logic is implemented.

src/templates/configurations/tsconfig.example.json (2)

3-17: Modern, clean TypeScript configuration.

The simplified compilerOptions are well-chosen for a modern web project: strict type checking enabled, modern target/module settings, and sensible defaults like noUncheckedIndexedAccess. The configuration aligns with current TypeScript best practices.


10-10: No changes required—TypeScript version is compatible.

The project specifies TypeScript 5.8.3 in peerDependencies, which fully supports the "bundler" moduleResolution mode (available since TypeScript 5.0). The example configuration aligns with the root tsconfig.json, which also uses "bundler". No fallback or modification is necessary.

src/generators/project/generateUseBlock.ts (1)

34-43: Remove misleading comments and consider template literal refactoring.

Verification shows no actual template literal parsing issues exist:

  • useBlock is interpolated normally via ${} in generateServer.ts
  • The generated string contains no backticks or special characters
  • No eval() or Function() calls process this code
  • TypeScript compiles the output as standard source code

The string concatenation in lines 39-43 works but is less readable than template literals, which would work identically here. The comments citing "template literal nesting issues" and "parsing issues" describe a non-existent problem. Either remove the comments or refactor to use template literals:

return `.use(absoluteAuth${pluginGeneric}(${mergedConfig}))`;

Likely an incorrect or invalid review comment.

Comment thread scripts/check-project-structure.ts Outdated
Comment thread scripts/functional-tests/api-endpoint-tester.ts Outdated
Comment thread scripts/functional-tests/build-validator.ts Outdated
Comment thread scripts/functional-tests/cloud-provider-test-runner.ts Outdated
Comment thread scripts/functional-tests/cloud-provider-validator.ts Outdated
Comment thread src/generators/db/handlerTemplates.ts Outdated
Comment thread src/generators/project/generateUseBlock.ts Outdated
Comment thread src/questions/frontendDirectoryConfigurations.ts Outdated
Comment on lines +35 to 43
files: ['**/*.{js,mjs,cjs,ts,tsx,jsx,json}'],
rules: {
'absolute/explicit-object-types': 'error',
'absolute/localize-react-props': 'error',
'absolute/max-depth-extended': ['error', 1],
'absolute/max-jsxnesting': ['error', 5],
'absolute/min-var-length': [
'error',
{ allowedVars: ['_', 'id', 'db', 'OK'], minLength: 3 }
],
'absolute/no-button-navigation': 'error',
'absolute/no-explicit-return-type': 'error',
'absolute/no-inline-prop-types': 'error',
'absolute/no-multi-style-objects': 'error',
'absolute/no-nested-jsx-return': 'error',
'absolute/no-or-none-component': 'error',
'absolute/no-transition-cssproperties': 'error',
'absolute/no-type-cast': 'error',
'absolute/no-unnecessary-div': 'error',
'absolute/no-unnecessary-key': 'error',
'absolute/no-useless-function': 'error',
'absolute/seperate-style-files': 'error',
'absolute/sort-exports': [
'@typescript-eslint/no-unused-vars': [
'error',
{
caseSensitive: true,
natural: true,
order: 'asc',
variablesBeforeFunctions: true
}
{ argsIgnorePattern: '^_' }
],
'absolute/sort-keys-fixable': [
'error',
{
caseSensitive: true,
natural: true,
order: 'asc',
variablesBeforeFunctions: true
}
],
'arrow-body-style': ['error', 'as-needed'],
'consistent-return': 'error',
eqeqeq: 'error',
'func-style': [
'error',
'expression',
{ allowArrowFunctions: true }
],
'import/no-cycle': 'error',
'import/no-default-export': 'error',
'import/no-relative-packages': 'error',
'import/no-unused-modules': ['error', { missingExports: true }],
'import/order': ['error', { alphabetize: { order: 'asc' } }],
'no-await-in-loop': 'error',
'no-console': ['error', { allow: ['warn', 'error'] }],
'no-debugger': 'error',
'no-duplicate-case': 'error',
'no-duplicate-imports': 'error',
'no-else-return': 'error',
'no-empty-function': 'error',
'no-empty-pattern': 'error',
'no-empty-static-block': 'error',
'no-fallthrough': 'error',
'no-floating-decimal': 'error',
'no-global-assign': 'error',
'no-implicit-coercion': 'error',
'no-implicit-globals': 'error',
'no-loop-func': 'error',
'no-magic-numbers': [
'warn',
{ detectObjects: false, enforceConst: true, ignore: [0, 1] }
],
'no-misleading-character-class': 'error',
'no-nested-ternary': 'error',
'no-new-native-nonconstructor': 'error',
'no-new-wrappers': 'error',
'no-param-reassign': 'error',
'no-restricted-imports': [
'error',
{
paths: [
{
importNames: ['default'],
message:
'Import only named React exports for tree-shaking.',
name: 'react'
},
{
importNames: ['default'],
message: 'Import only the required Bun exports.',
name: 'bun'
}
]
}
],
'no-return-await': 'error',
'no-shadow': 'error',
'no-undef': 'error',
'no-unneeded-ternary': 'error',
'no-unreachable': 'error',
'no-useless-assignment': 'error',
'no-useless-concat': 'error',
'no-useless-return': 'error',
'no-var': 'error',
'prefer-arrow-callback': 'error',
'prefer-const': 'error',
'prefer-destructuring': [
'error',
{ array: true, object: true },
{ enforceForRenamedProperties: false }
],
'prefer-template': 'error',
'promise/always-return': 'warn',
'promise/avoid-new': 'warn',
'promise/catch-or-return': 'error',
'promise/no-callback-in-promise': 'warn',
'promise/no-nesting': 'warn',
'promise/no-promise-in-callback': 'warn',
'promise/no-return-wrap': 'error',
'promise/param-names': 'error'
}
},
{
files: ['example/**/*.{js,jsx,ts,tsx}'],
plugins: {
'jsx-a11y': jsxA11yPlugin,
react: reactPlugin,
'react-compiler': reactCompilerPlugin,
'react-hooks': reactHooksPlugin
},
rules: {
'jsx-a11y/prefer-tag-over-role': 'error',
'react-compiler/react-compiler': 'error',
'react-hooks/exhaustive-deps': 'warn',
'react-hooks/rules-of-hooks': 'error',
'react/checked-requires-onchange-or-readonly': 'error',
'react/destructuring-assignment': ['error', 'always'],
'react/jsx-filename-extension': ['error', { extensions: ['.tsx'] }],
'react/jsx-no-leaked-render': 'error',
'react/jsx-no-target-blank': 'error',
'react/jsx-no-useless-fragment': 'error',
'react/jsx-pascal-case': ['error', { allowAllCaps: true }],
'react/no-multi-comp': 'error',
'react/no-unknown-property': 'off',
'react/react-in-jsx-scope': 'off',
'react/self-closing-comp': 'error'
},
settings: {
react: { version: 'detect' }
}
},
{
files: [
'example/server.ts',
'example/indexes/*.tsx',
'example/db/migrate.ts'
],
rules: {
'import/no-unused-modules': 'off'
}
},
{
files: ['example/db/migrate.ts', 'example/utils/absoluteAuthConfig.ts'],
rules: {
'no-console': 'off'
}
},
{
files: ['eslint.config.mjs'],
rules: {
'no-magic-numbers': 'off'
}
},
{
files: ['eslint.config.mjs'],
rules: {
'import/no-default-export': 'off'
}
},
{
files: ['example/db/schema.ts'],
rules: {
'absolute/explicit-object-types': 'off'
'no-console': 'warn',
'prefer-const': 'error'
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Drop .json from the rules glob or add a JSON parser

With the flat config, ESLint will run this rule set on *.json files using the default parser (espree). JSON syntax is invalid JavaScript, so every run will now fail with Parsing error: Unexpected token. Either remove .json from the files glob or wire up a JSON-capable parser (e.g. eslint-plugin-jsonc) before shipping this config.

🤖 Prompt for AI Agents
In src/templates/configurations/eslint.config.mjs around lines 35 to 43, the
config applies JS/TS rules to .json files which causes "Parsing error:
Unexpected token" with the default parser; either remove ".json" from the files
glob so ESLint won't run this rule set on JSON, or add a JSON-capable
parser/plugin and an override for JSON files (e.g., install and enable
eslint-plugin-jsonc or similar, register its processor/parser, and set an
override for files: ['**/*.json'] to use that parser and appropriate rules).
Ensure you choose one approach (remove .json from the glob OR wire up the json
parser and add an override) and update the config accordingly.

Comment thread src/templates/configurations/tsconfig.example.json
@eugenegraves
Copy link
Copy Markdown
Collaborator Author

Summary after Testing Improvements

  • Hardened generator templates so every scaffolded project ships with TypeScript, ESLint, and Prettier baselines that the test harness expects.
  • Added resilient filesystem guards (statSync checks, cleanup helpers, managed child-process timeouts) so validators report structured failures instead of crashing on IO quirks.
  • Reworked every functional runner to spawn commands safely, pre-clean directories, honor dependency cache hits, and ignore unsupported matrix entries (PlanetScale/MySQL held back until real driver support).
  • Delivered a full auth validation stack on top of the functional suite and tuned the cloud runner to exercise only Neon/Postgres and Turso/SQLite, yielding reliable green runs.
  • Captured real-world gaps surfaced by local runs (e.g., Postgres Docker, MySQL Drizzle schema columns, MongoDB seed collections) to feed upcoming sprint fixes.

Testing

  • bun run test:html:all – 96 configs; 87 passed, 9 fail (dependency install on minimal none/none stacks, pre-existing).
  • bun run test:htmx:all – 96 configs; 88 passed, 8 fail (same minimal none/none dependency install issue).
  • bun run test:react:all – 96/96 pass.
  • bun run test:vue:all – 96 configs; 88 passed, 8 fail (minimal none/none dependency install).
  • bun run test:svelte:all – 96 configs; 88 passed, 8 fail (minimal none/none dependency install).
  • bun run test:sqlite:all – 320/320 pass (local + Turso permutations).
  • bun run test:postgresql:all – 160/160 pass for Neon remote; 160 local combos blocked by sandbox Docker (error getting credentials). ✅ Verified locally: Docker-capable host exposed real template bug (NodePgDatabase import + missing pg dependency) now logged for follow-up.
  • bun run test:mysql:all – PlanetScale filtered out; sandbox run still fails on local Docker. ✅ Local run highlighted Drizzle schema mismatch (users.uid) now queued for fixes.
  • bun run test:mongodb:all – sandbox failures (users/count_history collections undefined). ✅ Local run reproduced and captured for template/validator alignment.
  • bun run test:auth:all – 200/200 pass.
  • bun run test:cloud:all – 320/320 pass (Neon + Turso only; PlanetScale excluded).

Pending: integrate the discovered local Postgres/MySQL/MongoDB template fixes in upcoming tasks.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
scripts/functional-tests/server-startup-validator.ts (1)

69-76: Check for typecheck script existence before invoking it.

Line 76 runs ${packageManager} run typecheck without verifying that packageJson.scripts?.typecheck exists. If the scaffold omits this script (many provide only dev and build), the invocation will fail and incorrectly report the project as broken. Check for the script's presence and either skip with a warning or fall back to tsc --noEmit if absent.

Apply this diff to guard the typecheck invocation:

   // Check 4: TypeScript compilation (most important functional check)
   if (!existsSync(tsconfigPath)) {
     warnings.push(`tsconfig.json not found - skipping compilation check`);
+  } else if (!packageJson.scripts?.typecheck) {
+    warnings.push(`No 'typecheck' script found - skipping compilation check`);
   } else {
     try {
       const startTime = Date.now();
🧹 Nitpick comments (8)
scripts/functional-tests/mysql-test-runner.ts (6)

44-52: Remove redundant cleanup operation.

The cleanupProjectDirectory utility already performs rmSync with recursive: true and force: true (as shown in test-utils.ts). The additional rm -rf command is unnecessary.

Apply this diff to streamline the cleanup:

-  // Ensure cleanup before starting
-  cleanupProjectDirectory(projectPath);
-
-  try {
-    const { $ } = await import('bun');
-    await $`rm -rf ${projectPath}`.quiet().nothrow();
-  } catch {
-    // Ignore cleanup errors
-  }
+  // Ensure cleanup before starting
+  cleanupProjectDirectory(projectPath);

107-108: Remove redundant import.

The $ utility is already imported from 'bun' at line 48. This second import is unnecessary.

Apply this diff:

-    // Scaffold project
-    const { $ } = await import('bun');
-    process.stdout.write('  → Scaffolding project... ');
+    // Scaffold project
+    process.stdout.write('  → Scaffolding project... ');

168-191: Consider extracting duplicate dependency fingerprint.

The dependency fingerprint object is constructed twice (lines 168-176 and 179-189) with identical properties. Extracting this to a variable would reduce duplication and make the code more maintainable.

Apply this diff to extract the common fingerprint:

     process.stdout.write('  → Installing dependencies... ');
-    const hasCache = hasCachedDependencies({
+    const depFingerprint = {
       frontend: config.frontend,
       databaseEngine: config.databaseEngine,
       orm: config.orm,
       databaseHost: config.databaseHost,
       authProvider: config.authProvider,
       useTailwind: config.useTailwind,
       codeQualityTool: config.codeQualityTool
-    });
+    };
+    const hasCache = hasCachedDependencies(depFingerprint);
 
     try {
-      const { cached, installTime } = await getOrInstallDependencies(
-        projectPath,
-        {
-          frontend: config.frontend,
-          databaseEngine: config.databaseEngine,
-          orm: config.orm,
-          databaseHost: config.databaseHost,
-          authProvider: config.authProvider,
-          useTailwind: config.useTailwind,
-          codeQualityTool: config.codeQualityTool
-        },
-        packageJsonPath
-      );
+      const { cached, installTime } = await getOrInstallDependencies(
+        projectPath,
+        depFingerprint,
+        packageJsonPath
+      );

259-259: Verify the null-check logic for functionalTestResults.

The variable functionalTestResults is declared at line 213 and will always be defined (though it may be undefined if the try-catch assigns nothing). The condition !functionalTestResults should explicitly check for undefined to clarify intent.

Apply this diff:

-    const passed = validationResult.passed && (!functionalTestResults || functionalTestResults.passed);
+    const passed = validationResult.passed && (functionalTestResults === undefined || functionalTestResults.passed);

288-292: Remove unused parameter.

The maxConcurrent parameter is defined but never used—tests run sequentially at line 312. Either implement concurrent execution or remove the parameter.

Apply this diff to remove the unused parameter:

 async function runMySQLTests(
   matrixFile: string = 'test-matrix.json',
-  maxConcurrent: number = 2,
   testSubset?: number
 ): Promise<void> {

And update the CLI usage:

   const matrixFile = process.argv[2] || 'test-matrix.json';
-  const maxConcurrent = parseInt(process.argv[3] || '2', 10);
-  const testSubset = process.argv[4] ? parseInt(process.argv[4], 10) : undefined;
+  const testSubset = process.argv[3] ? parseInt(process.argv[3], 10) : undefined;
 
-  runMySQLTests(matrixFile, maxConcurrent, testSubset).catch((e) => {
+  runMySQLTests(matrixFile, testSubset).catch((e) => {

316-318: Extract project name generation to avoid duplication.

The project name generation logic is duplicated from lines 40-42. Consider extracting this to a helper function to maintain consistency and reduce code duplication.

Add a helper function at the top of the file:

function getProjectName(config: TestMatrixEntry): string {
  return `test-mysql-${config.frontend}-${config.orm}-${config.authProvider === 'none' ? 'noauth' : 'auth'}-${config.databaseHost === 'none' ? 'local' : config.databaseHost}-${config.useTailwind ? 'tw' : 'notw'}`.replace(/[^a-z0-9-]/g, '-');
}

Then use it at lines 41 and 317:

-  const projectName = `test-mysql-${config.frontend}-${config.orm}-${config.authProvider === 'none' ? 'noauth' : 'auth'}-${config.databaseHost === 'none' ? 'local' : config.databaseHost}-${config.useTailwind ? 'tw' : 'notw'}`.replace(/[^a-z0-9-]/g, '-');
+  const projectName = getProjectName(config);
scripts/functional-tests/server-startup-validator.ts (1)

136-143: Consider an ESM-native entrypoint check.

The file uses ESM imports but checks require.main === module (CommonJS). While Bun likely supports this, an ESM-native approach would be more consistent. You can use import.meta.url comparison or Bun's specific entrypoint detection if available.

scripts/functional-tests/html-test-runner.ts (1)

293-318: Consider documenting or removing the unused maxConcurrent parameter.

The maxConcurrent parameter is defined and parsed from CLI args but never used to control concurrency. Tests always run sequentially (line 318). While the comment on line 317 acknowledges this, the parameter is misleading to callers.

Either remove the parameter for now and add it back when implementing parallelization, or document it as reserved for future use:

 async function runHTMLTests(
   matrixFile: string = 'test-matrix.json',
-  maxConcurrent: number = 2,
+  maxConcurrent: number = 2, // Reserved for future parallel execution
   testSubset?: number
 ): Promise<void> {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 017b8d6 and 8ee5b5a.

📒 Files selected for processing (11)
  • scripts/check-project-structure.ts (1 hunks)
  • scripts/functional-tests/api-endpoint-tester.ts (1 hunks)
  • scripts/functional-tests/build-validator.ts (1 hunks)
  • scripts/functional-tests/cloud-provider-test-runner.ts (1 hunks)
  • scripts/functional-tests/cloud-provider-validator.ts (1 hunks)
  • scripts/functional-tests/dependency-installer-tester.ts (1 hunks)
  • scripts/functional-tests/html-test-runner.ts (1 hunks)
  • scripts/functional-tests/htmx-validator.ts (1 hunks)
  • scripts/functional-tests/mongodb-test-runner.ts (1 hunks)
  • scripts/functional-tests/mysql-test-runner.ts (1 hunks)
  • scripts/functional-tests/server-startup-validator.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • scripts/functional-tests/build-validator.ts
  • scripts/functional-tests/mongodb-test-runner.ts
  • scripts/functional-tests/api-endpoint-tester.ts
🧰 Additional context used
🧬 Code graph analysis (6)
scripts/functional-tests/dependency-installer-tester.ts (1)
src/utils/commandMaps.ts (1)
  • installCommands (17-22)
scripts/functional-tests/mysql-test-runner.ts (4)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/functional-test-runner.ts (1)
  • runFunctionalTests (24-120)
scripts/functional-tests/mysql-validator.ts (1)
  • validateMySQLDatabase (23-198)
scripts/functional-tests/cloud-provider-test-runner.ts (3)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/cloud-provider-validator.ts (1)
  • validateCloudProvider (26-231)
scripts/functional-tests/htmx-validator.ts (1)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (24-120)
scripts/functional-tests/cloud-provider-validator.ts (1)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (24-120)
scripts/functional-tests/html-test-runner.ts (3)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/html-validator.ts (1)
  • validateHTMLFramework (24-187)
🔇 Additional comments (4)
scripts/functional-tests/mysql-test-runner.ts (2)

1-31: LGTM! Clean setup and well-structured types.

The imports and type definitions align with other test runners in the suite, maintaining consistency across the functional testing infrastructure.


362-372: Verify CLI entry point works in Bun/ESM context.

The require.main === module pattern is CommonJS-specific, but this file uses ES module syntax (import statements). While Bun may support this pattern, you should verify that the CLI entry point is properly invoked when running the script directly.

If this doesn't work, consider using an alternative ESM-compatible approach or ensure Bun's CommonJS compatibility is sufficient for your use case.

scripts/functional-tests/server-startup-validator.ts (1)

76-108: Timeout logic correctly kills the compiler process.

The timeout mechanism now properly terminates the typecheck subprocess when the deadline expires (lines 82-85: SIGTERM → SIGKILL fallback) and clears the timeout when the process completes first (lines 97-100, 105-107). This addresses the past review concern about hung compilers clogging the test matrix.

scripts/check-project-structure.ts (1)

27-53: Good call on guarding the filesystem stat path.

Wrapping both statSync calls in try/catch ensures the checker returns structured failures instead of crashing on IO issues. Solid hardening.

Comment thread scripts/functional-tests/cloud-provider-test-runner.ts Outdated
Comment thread scripts/functional-tests/html-test-runner.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (7)
scripts/functional-tests/cloud-provider-test-runner.ts (5)

44-53: Remove redundant cleanup operations.

The cleanup at line 45 (cleanupProjectDirectory) already performs a recursive, forced removal using rmSync. The subsequent rm -rf command (lines 48-53) and 100ms wait are redundant and suggest a workaround for a non-existent filesystem sync issue.

Apply this diff to remove the redundancy:

   // Ensure cleanup before starting
   cleanupProjectDirectory(projectPath);
 
-  try {
-    const { $ } = await import('bun');
-    await $`rm -rf ${projectPath}`.quiet().nothrow();
-    await new Promise(resolve => setTimeout(resolve, 100));
-  } catch {
-    // Ignore cleanup errors
-  }
-
   try {

262-266: Remove unnecessary await on synchronous function.

cleanupProjectDirectory is synchronous (returns void), so the await has no effect.

Apply this diff:

     try {
-      await cleanupProjectDirectory(projectPath);
+      cleanupProjectDirectory(projectPath);
     } catch {

277-281: Remove unnecessary await on synchronous function.

Same issue as line 263 - cleanupProjectDirectory doesn't return a Promise.

Apply this diff:

     try {
-      await cleanupProjectDirectory(projectPath);
+      cleanupProjectDirectory(projectPath);
     } catch {

330-338: Remove redundant pre-cleanup in orchestrator.

scaffoldAndTestCloudProvider already performs pre-cleanup at line 45, so this additional cleanup is redundant and adds unnecessary overhead to each test run.

Apply this diff:

     console.log(`[${i + 1}/${configsToTest.length}] Testing ${providerName} + ${config.databaseEngine} + ${config.orm} + ${config.authProvider === 'none' ? 'no auth' : 'auth'}...`);
     
-    // Cleanup any leftover directories before starting
-    const projectName = `test-cloud-${config.databaseHost}-${config.databaseEngine}-${config.orm}-${config.frontend}-${config.authProvider === 'none' ? 'noauth' : 'auth'}-${config.useTailwind ? 'tw' : 'notw'}`.replace(/[^a-z0-9-]/g, '-');
-    try {
-      const { $ } = await import('bun');
-      await $`rm -rf ${projectName}`.quiet().nothrow();
-      await new Promise(resolve => setTimeout(resolve, 100));
-    } catch {
-      // Ignore cleanup errors
-    }
-    
     const result = await scaffoldAndTestCloudProvider(config);

399-401: Use Bun-native module detection.

require.main === module is a CommonJS pattern that may not work reliably in Bun's ESM context.

Apply this diff to use Bun's native detection:

 // CLI usage
-if (require.main === module) {
+if (import.meta.main) {
   runCloudProviderTests().catch(console.error);
 }
scripts/functional-tests/html-test-runner.ts (2)

262-267: Consider using cleanupProjectDirectory for consistency.

The code uses cleanupProjectDirectory at line 47 (pre-scaffold cleanup) but direct shell rm -rf commands at lines 264 and 280 (post-test cleanup). Using cleanupProjectDirectory consistently would improve maintainability and provides better error handling (existence checks, structured warnings).

Apply this diff:

     // Cleanup
     try {
-      await $`rm -rf ${projectPath}`.quiet();
+      cleanupProjectDirectory(projectPath);
     } catch {
       // Ignore cleanup errors
     }
     // Cleanup on error
     try {
-      await $`rm -rf ${projectPath}`.quiet();
+      cleanupProjectDirectory(projectPath);
     } catch {
       // Ignore cleanup errors
     }

Also applies to: 279-283


294-298: Unused parameter: maxConcurrent is defined but not used.

The maxConcurrent parameter is defined at line 296 and parsed from CLI arguments at line 361, but is never used—the loop at line 319 runs sequentially. The comment indicates parallelization is planned, but until then the parameter serves no purpose and may confuse readers.

Consider either:

  1. Removing the parameter until parallelization is implemented, or
  2. Adding a TODO comment explaining it's reserved for future parallel execution
 async function runHTMLTests(
   matrixFile: string = 'test-matrix.json',
-  maxConcurrent: number = 2,
   testSubset?: number
 ): Promise<void> {
 if (require.main === module) {
   const matrixFile = process.argv[2] || 'test-matrix.json';
-  const maxConcurrent = parseInt(process.argv[3] || '2', 10);
-  const testSubset = process.argv[4] ? parseInt(process.argv[4], 10) : undefined;
+  const testSubset = process.argv[3] ? parseInt(process.argv[3], 10) : undefined;

-  runHTMLTests(matrixFile, maxConcurrent, testSubset).catch((e) => {
+  runHTMLTests(matrixFile, testSubset).catch((e) => {

Also applies to: 318-319

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ee5b5a and 0f4f98f.

📒 Files selected for processing (2)
  • scripts/functional-tests/cloud-provider-test-runner.ts (1 hunks)
  • scripts/functional-tests/html-test-runner.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
scripts/functional-tests/html-test-runner.ts (3)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/html-validator.ts (1)
  • validateHTMLFramework (24-187)
scripts/functional-tests/cloud-provider-test-runner.ts (3)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (7-19)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (53-59)
  • getOrInstallDependencies (64-126)
scripts/functional-tests/cloud-provider-validator.ts (1)
  • validateCloudProvider (26-231)
🔇 Additional comments (3)
scripts/functional-tests/cloud-provider-test-runner.ts (1)

105-183: LGTM - Scaffold execution properly fixed.

The spawn implementation correctly addresses the previous issue by passing the executable and arguments separately (spawn(cmd[0], cmd.slice(1))). Timeout handling and error propagation are properly implemented.

scripts/functional-tests/html-test-runner.ts (2)

36-50: LGTM: $ utility is correctly imported at function scope.

The import at line 49 ensures $ is available for cleanup operations in both the try block (line 264) and catch block (line 280), addressing the scope concern raised in previous reviews.


104-150: LGTM: Scaffold execution properly uses spawn() with timeout.

The use of spawn(cmd[0], cmd.slice(1), ...) correctly passes the command and arguments separately, avoiding the array interpolation issue mentioned in previous reviews. Timeout and error handling are well-structured.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f4f98f and 0c85f01.

📒 Files selected for processing (1)
  • src/generators/configurations/scaffoldConfigurationFiles.ts (3 hunks)

Comment thread src/generators/configurations/scaffoldConfigurationFiles.ts Outdated
Comment thread src/generators/configurations/scaffoldConfigurationFiles.ts
@eugenegraves eugenegraves changed the title Test Suite (Minus Unimplemented Items) Implement comprehensive test suite with matrix-driven configuration validation Nov 9, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 9, 2025

Note

Docstrings generation - SUCCESS
Generated docstrings for this pull request at #5

Docstrings generation was requested by @eugenegraves.

* #4 (comment)

The following files were modified:

* `scripts/check-project-structure.ts`
* `scripts/functional-tests/api-endpoint-tester.ts`
* `scripts/functional-tests/auth-test-runner.ts`
* `scripts/functional-tests/auth-validator.ts`
* `scripts/functional-tests/build-validator.ts`
* `scripts/functional-tests/cloud-provider-test-runner.ts`
* `scripts/functional-tests/cloud-provider-validator.ts`
* `scripts/functional-tests/database-connection-tester.ts`
* `scripts/functional-tests/dependency-cache.ts`
* `scripts/functional-tests/dependency-installer-tester.ts`
* `scripts/functional-tests/frontend-renderer-tester.ts`
* `scripts/functional-tests/functional-test-runner.ts`
* `scripts/functional-tests/html-test-runner.ts`
* `scripts/functional-tests/html-validator.ts`
* `scripts/functional-tests/htmx-test-runner.ts`
* `scripts/functional-tests/htmx-validator.ts`
* `scripts/functional-tests/mongodb-test-runner.ts`
* `scripts/functional-tests/mongodb-validator.ts`
* `scripts/functional-tests/mysql-test-runner.ts`
* `scripts/functional-tests/mysql-validator.ts`
* `scripts/functional-tests/postgresql-test-runner.ts`
* `scripts/functional-tests/postgresql-validator.ts`
* `scripts/functional-tests/react-test-runner.ts`
* `scripts/functional-tests/react-validator.ts`
* `scripts/functional-tests/server-startup-validator.ts`
* `scripts/functional-tests/sqlite-test-runner.ts`
* `scripts/functional-tests/sqlite-validator.ts`
* `scripts/functional-tests/svelte-test-runner.ts`
* `scripts/functional-tests/svelte-validator.ts`
* `scripts/functional-tests/test-utils.ts`
* `scripts/functional-tests/vue-test-runner.ts`
* `scripts/functional-tests/vue-validator.ts`
* `scripts/generate-test-matrix.ts`
* `scripts/verify-test-matrix.ts`
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

♻️ Duplicate comments (4)
scripts/functional-tests/postgresql-test-runner.ts (1)

116-125: Restore structured Bun command invocation

Passing the cmd array straight into the tagged template coerces it to bun,run,src/index.ts,…, recreating the scaffold failure I flagged earlier. Use the object form so Bun receives discrete arguments.

-    const scaffoldPromise = $`${cmd}`.quiet().nothrow();
+    const scaffoldPromise = $({ cmd }).quiet().nothrow();
scripts/functional-tests/sqlite-validator.ts (1)

104-133: Stop short-circuiting connectionWorks when the query returns nothing.

Because testQuery.includes('users') / 'count_history' is always true, any zero-exit sqlite3 call marks the connection (and subsequently the entire validator) as passing even when the table is absent. That recreates the false-positive highlighted earlier. Capture actual output instead.

-      if (result.exitCode === 0) {
-        const output = result.stdout?.toString() || '';
-        if (output.trim() || testQuery.includes('users') || testQuery.includes('count_history')) {
-          sqliteSpecific.connectionWorks = true;
+      if (result.exitCode === 0) {
+        sqliteSpecific.connectionWorks = true;
+        const output = (result.stdout?.toString() ?? '').trim();
+        if (output.length > 0) {
           // Try a more comprehensive query to verify tables exist
scripts/functional-tests/react-test-runner.ts (1)

99-145: Scaffold command never executes because ${cmd} stringifies to commas.

Interpolating the array directly ($${cmd}``) renders bun,run,src/index.ts,…, so Bun looks for a binary literally named `bun,run,src/index.ts` and the scaffold fails outright. Join/escape the arguments or switch to `$.spawn({ cmd })` so each token is passed separately.

Minimal fix:

-    const scaffoldPromise = $`${cmd}`.quiet().nothrow();
+    const scaffoldCommand = cmd.join(' ');
+    const scaffoldPromise = $`${scaffoldCommand}`.quiet().nothrow();

(Or adopt $.spawn for stronger quoting.)

scripts/functional-tests/react-validator.ts (1)

67-88: Support both single- and multi-frontend React directories.

Still hard-coding src/frontend/* causes every multi-frontend scaffold (which places React under src/frontend/react) to fail this validator even when files exist. Check both candidate roots and only evaluate required files when a valid root is found.

-  const reactComponentsPath = join(projectPath, 'src', 'frontend', 'components');
-  const reactPagesPath = join(projectPath, 'src', 'frontend', 'pages');
-  const reactStylesPath = join(projectPath, 'src', 'frontend', 'styles');
-  const reactAssetsPath = join(projectPath, 'src', 'backend', 'assets', 'svg', 'react.svg');
-
-  const requiredFiles = [
-    join(reactComponentsPath, 'App.tsx'),
-    join(reactComponentsPath, 'Head.tsx'),
-    join(reactComponentsPath, 'Dropdown.tsx'),
-    join(reactPagesPath, 'ReactExample.tsx'),
-    join(reactStylesPath, 'react-example.css'),
-    reactAssetsPath
-  ];
-
-  const missingFiles = requiredFiles.filter((file) => !existsSync(file));
-
-  if (missingFiles.length > 0) {
-    errors.push(`Missing React files: ${missingFiles.join(', ')}`);
-  } else {
-    reactSpecific.filesExist = true;
-  }
+  const reactAssetsPath = join(projectPath, 'src', 'backend', 'assets', 'svg', 'react.svg');
+  const candidateReactDirs = [
+    join(projectPath, 'src', 'frontend', 'react'),
+    join(projectPath, 'src', 'frontend')
+  ];
+  const reactRoot = candidateReactDirs.find((dir) =>
+    ['components', 'pages', 'styles'].every((sub) => existsSync(join(dir, sub)))
+  );
+
+  if (!reactRoot) {
+    errors.push('React frontend directory not found (checked src/frontend/react and src/frontend)');
+  } else {
+    const requiredFiles = [
+      join(reactRoot, 'components', 'App.tsx'),
+      join(reactRoot, 'components', 'Head.tsx'),
+      join(reactRoot, 'components', 'Dropdown.tsx'),
+      join(reactRoot, 'pages', 'ReactExample.tsx'),
+      join(reactRoot, 'styles', 'react-example.css'),
+      reactAssetsPath
+    ];
+    const missingFiles = requiredFiles.filter((file) => !existsSync(file));
+    if (missingFiles.length > 0) {
+      errors.push(`Missing React files: ${missingFiles.join(', ')}`);
+    } else {
+      reactSpecific.filesExist = true;
+    }
+  }
🧹 Nitpick comments (7)
scripts/functional-tests/build-validator.ts (2)

16-22: Fix JSDoc comment formatting.

The JSDoc comment for validateBuild incorrectly starts on the same line as the COMPILE_TIMEOUT constant declaration. Move the JSDoc to a separate line above the function for clarity and to avoid confusing documentation parsers.

Apply this diff:

-const COMPILE_TIMEOUT = 60000; /**
+const COMPILE_TIMEOUT = 60000;
+
+/**
  * Validates that a scaffolded project compiles by checking for tsconfig.json, ensuring package.json has a `typecheck` script, and running that script.
  *
  * @param projectPath - Path to the project directory to validate
  * @param packageManager - Package manager to run the `typecheck` script with (`'bun' | 'npm' | 'pnpm' | 'yarn'`); defaults to `'bun'`
  * @returns A BuildResult where `passed` is `true` when compilation succeeds, `errors` contains failure messages when present, and `compileTime` (milliseconds) is included when a compilation attempt was performed
  */
-
 export async function validateBuild(

119-120: Validate package manager argument instead of casting to any.

The as any cast bypasses type safety. Consider validating that process.argv[3] is one of the allowed package managers or falls back to 'bun'.

Apply this diff:

   const projectPath = process.argv[2];
-  const packageManager = (process.argv[3] as any) || 'bun';
+  const allowedManagers = ['bun', 'npm', 'pnpm', 'yarn'] as const;
+  const packageManager = allowedManagers.includes(process.argv[3] as any)
+    ? (process.argv[3] as 'bun' | 'npm' | 'pnpm' | 'yarn')
+    : 'bun';
scripts/functional-tests/database-connection-tester.ts (1)

11-11: Remove unused import.

readFileSync is imported but never used in this file.

Apply this diff to remove the unused import:

-import { existsSync, readFileSync } from 'fs';
+import { existsSync } from 'fs';
scripts/functional-tests/mysql-validator.ts (4)

7-7: Remove unused import.

readFileSync is imported but never used in this file.

-import { existsSync, readFileSync } from 'fs';
+import { existsSync } from 'fs';

67-77: Add explicit validation for databaseHost values.

The code only checks for 'none'/falsy and 'planetscale', but doesn't validate against unexpected values. If an invalid host like 'neon' or 'turso' is passed, both conditions fail silently, potentially causing confusing validation failures later.

Consider adding explicit validation at the start of the function:

// After line 59
const validHosts = ['none', 'planetscale', undefined];
if (config.databaseHost && !validHosts.includes(config.databaseHost)) {
  errors.push(`Invalid databaseHost for MySQL: ${config.databaseHost}. Expected 'none', 'planetscale', or undefined`);
  return { passed: false, errors, warnings, mysqlSpecific };
}

87-91: Clarify schema validation for non-ORM case.

Setting schemaFileExists = true without checking any file is misleading. For non-ORM MySQL, tables are created via Docker exec during scaffolding, so no persistent schema file exists. Consider either:

  1. Checking for evidence of successful table creation instead
  2. Renaming the field to schemaReady to better reflect what's being validated

115-115: Consider making timeout configurable.

The fixed 2-second wait may be insufficient in slower environments (e.g., resource-constrained CI runners, cold container starts). While the subsequent polling loop (lines 120-127) provides additional resilience, the initial delay could be made configurable or adaptive.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05fee6c and 74eb0bf.

📒 Files selected for processing (34)
  • scripts/check-project-structure.ts (1 hunks)
  • scripts/functional-tests/api-endpoint-tester.ts (1 hunks)
  • scripts/functional-tests/auth-test-runner.ts (1 hunks)
  • scripts/functional-tests/auth-validator.ts (1 hunks)
  • scripts/functional-tests/build-validator.ts (1 hunks)
  • scripts/functional-tests/cloud-provider-test-runner.ts (1 hunks)
  • scripts/functional-tests/cloud-provider-validator.ts (1 hunks)
  • scripts/functional-tests/database-connection-tester.ts (1 hunks)
  • scripts/functional-tests/dependency-cache.ts (1 hunks)
  • scripts/functional-tests/dependency-installer-tester.ts (1 hunks)
  • scripts/functional-tests/frontend-renderer-tester.ts (1 hunks)
  • scripts/functional-tests/functional-test-runner.ts (1 hunks)
  • scripts/functional-tests/html-test-runner.ts (1 hunks)
  • scripts/functional-tests/html-validator.ts (1 hunks)
  • scripts/functional-tests/htmx-test-runner.ts (1 hunks)
  • scripts/functional-tests/htmx-validator.ts (1 hunks)
  • scripts/functional-tests/mongodb-test-runner.ts (1 hunks)
  • scripts/functional-tests/mongodb-validator.ts (1 hunks)
  • scripts/functional-tests/mysql-test-runner.ts (1 hunks)
  • scripts/functional-tests/mysql-validator.ts (1 hunks)
  • scripts/functional-tests/postgresql-test-runner.ts (1 hunks)
  • scripts/functional-tests/postgresql-validator.ts (1 hunks)
  • scripts/functional-tests/react-test-runner.ts (1 hunks)
  • scripts/functional-tests/react-validator.ts (1 hunks)
  • scripts/functional-tests/server-startup-validator.ts (1 hunks)
  • scripts/functional-tests/sqlite-test-runner.ts (1 hunks)
  • scripts/functional-tests/sqlite-validator.ts (1 hunks)
  • scripts/functional-tests/svelte-test-runner.ts (1 hunks)
  • scripts/functional-tests/svelte-validator.ts (1 hunks)
  • scripts/functional-tests/test-utils.ts (1 hunks)
  • scripts/functional-tests/vue-test-runner.ts (1 hunks)
  • scripts/functional-tests/vue-validator.ts (1 hunks)
  • scripts/generate-test-matrix.ts (1 hunks)
  • scripts/verify-test-matrix.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (10)
  • scripts/functional-tests/functional-test-runner.ts
  • scripts/functional-tests/frontend-renderer-tester.ts
  • scripts/functional-tests/api-endpoint-tester.ts
  • scripts/generate-test-matrix.ts
  • scripts/functional-tests/sqlite-test-runner.ts
  • scripts/functional-tests/auth-test-runner.ts
  • scripts/functional-tests/vue-test-runner.ts
  • scripts/functional-tests/mongodb-test-runner.ts
  • scripts/functional-tests/test-utils.ts
  • scripts/verify-test-matrix.ts
🧰 Additional context used
🧬 Code graph analysis (24)
scripts/check-project-structure.ts (2)
src/generators/configurations/initializeRoot.ts (1)
  • projectName (4-44)
src/generators/configurations/generatePackageJson.ts (1)
  • CreatePackageJsonProps (31-226)
scripts/functional-tests/sqlite-validator.ts (3)
src/utils/checkSqliteInstalled.ts (7)
  • hasSqlite (137-159)
  • commandExists (80-110)
  • hasSqlite (112-117)
  • ensureSudo (37-49)
  • commandExists (119-135)
  • $ (27-32)
  • $ (34-35)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
scripts/functional-tests/dependency-installer-tester.ts (2)
src/utils/commandMaps.ts (1)
  • installCommands (17-22)
src/commands/installDependencies.ts (1)
  • packageManager (8-24)
scripts/functional-tests/mysql-validator.ts (4)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
src/generators/configurations/generatePackageJson.ts (1)
  • CreatePackageJsonProps (31-226)
scripts/functional-tests/htmx-validator.ts (2)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (41-137)
src/generators/htmx/scaffoldHTMX.ts (1)
  • ScaffoldFrontendProps (8-46)
scripts/functional-tests/htmx-test-runner.ts (5)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (11-23)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (61-67)
  • getOrInstallDependencies (79-141)
scripts/functional-tests/htmx-validator.ts (1)
  • validateHTMXFramework (33-190)
src/generators/htmx/scaffoldHTMX.ts (1)
  • ScaffoldFrontendProps (8-46)
src/generators/project/scaffoldFrontends.ts (1)
  • ScaffoldFrontendsProps (19-106)
scripts/functional-tests/dependency-cache.ts (1)
src/commands/installDependencies.ts (1)
  • packageManager (8-24)
scripts/functional-tests/react-test-runner.ts (3)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (11-23)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (61-67)
  • getOrInstallDependencies (79-141)
scripts/functional-tests/react-validator.ts (1)
  • validateReactFramework (41-157)
scripts/functional-tests/mysql-test-runner.ts (7)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (11-23)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (61-67)
  • getOrInstallDependencies (79-141)
scripts/functional-tests/functional-test-runner.ts (1)
  • runFunctionalTests (41-137)
scripts/functional-tests/mysql-validator.ts (1)
  • validateMySQLDatabase (41-216)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
scripts/functional-tests/cloud-provider-validator.ts (4)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (41-137)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
scripts/functional-tests/html-validator.ts (5)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (41-137)
src/generators/html/scaffoldHTML.ts (1)
  • ScaffoldHTMLProps (11-41)
src/generators/htmx/scaffoldHTMX.ts (1)
  • ScaffoldFrontendProps (8-46)
src/generators/html/generateHTMLPage.ts (1)
  • frontends (4-75)
src/generators/project/scaffoldFrontends.ts (1)
  • ScaffoldFrontendsProps (19-106)
scripts/functional-tests/build-validator.ts (2)
src/generators/configurations/scaffoldConfigurationFiles.ts (1)
  • AddConfigurationProps (22-77)
src/generators/configurations/generatePackageJson.ts (1)
  • CreatePackageJsonProps (31-226)
scripts/functional-tests/postgresql-test-runner.ts (4)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (11-23)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (61-67)
  • getOrInstallDependencies (79-141)
scripts/functional-tests/functional-test-runner.ts (1)
  • runFunctionalTests (41-137)
scripts/functional-tests/postgresql-validator.ts (1)
  • validatePostgreSQLDatabase (33-208)
scripts/functional-tests/svelte-validator.ts (3)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (41-137)
src/generators/svelte/scaffoldSvelte.ts (1)
  • ScaffoldFrontendProps (6-33)
src/generators/svelte/generateSveltePage.ts (1)
  • frontends (4-218)
scripts/functional-tests/database-connection-tester.ts (5)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
src/generators/configurations/generateEnv.ts (1)
  • GenerateEnvProps (23-44)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
scripts/functional-tests/html-test-runner.ts (5)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (11-23)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (61-67)
  • getOrInstallDependencies (79-141)
scripts/functional-tests/html-validator.ts (1)
  • validateHTMLFramework (43-206)
src/generators/html/scaffoldHTML.ts (1)
  • ScaffoldHTMLProps (11-41)
src/generators/html/generateHTMLPage.ts (1)
  • frontends (4-75)
scripts/functional-tests/cloud-provider-test-runner.ts (3)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (11-23)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (61-67)
  • getOrInstallDependencies (79-141)
scripts/functional-tests/cloud-provider-validator.ts (1)
  • validateCloudProvider (46-251)
scripts/functional-tests/postgresql-validator.ts (6)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
src/generators/db/generateDockerContainer.ts (1)
  • databaseEngine (84-114)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
src/generators/project/generateDBBlock.ts (1)
  • GenerateDBBlockProps (54-103)
src/generators/configurations/generatePackageJson.ts (1)
  • CreatePackageJsonProps (31-226)
scripts/functional-tests/svelte-test-runner.ts (3)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (11-23)
scripts/functional-tests/dependency-cache.ts (2)
  • hasCachedDependencies (61-67)
  • getOrInstallDependencies (79-141)
scripts/functional-tests/svelte-validator.ts (1)
  • validateSvelteFramework (35-173)
scripts/functional-tests/react-validator.ts (3)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (41-137)
src/generators/react/scaffoldReact.ts (1)
  • ScaffoldFrontendProps (7-35)
src/templates/react/pages/ReactExample.tsx (1)
  • ReactExampleProps (7-18)
scripts/functional-tests/mongodb-validator.ts (3)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/db/generateDockerContainer.ts (1)
  • databaseEngine (84-114)
scripts/functional-tests/server-startup-validator.ts (3)
src/generators/project/generateServer.ts (1)
  • CreateServerFileProps (27-94)
src/generators/configurations/scaffoldConfigurationFiles.ts (1)
  • AddConfigurationProps (22-77)
src/generators/configurations/generatePackageJson.ts (1)
  • CreatePackageJsonProps (31-226)
scripts/functional-tests/vue-validator.ts (2)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (41-137)
src/generators/vue/scaffoldVue.ts (1)
  • ScaffoldVueProps (8-27)
scripts/functional-tests/auth-validator.ts (1)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (11-22)
  • runFunctionalTests (41-137)
🔇 Additional comments (12)
scripts/functional-tests/build-validator.ts (2)

24-56: LGTM on validation checks.

The initial validation logic correctly checks for tsconfig.json, package.json, and the typecheck script with appropriate error handling and early returns.


58-114: Compilation and timeout logic works correctly.

The timeout is correctly handled via the catch block when timeoutPromise rejects. The error extraction logic appropriately filters TypeScript errors and limits output. The type assertion on line 69 is slightly misleading (implies result could be from timeout path) but functionally correct since timeout rejection jumps to the catch block.

scripts/functional-tests/database-connection-tester.ts (2)

14-18: LGTM!

The DatabaseConnectionResult type is well-structured and follows the pattern used by other validators in the test suite.


37-79: LGTM!

The function implementation correctly performs basic filesystem checks, handles early returns appropriately, and accumulates warnings as documented. The placeholder nature is clearly communicated through inline comments and warnings.

scripts/functional-tests/mysql-validator.ts (7)

23-48: LGTM!

The function signature and documentation are clear and comprehensive.


49-65: LGTM!

Proper initialization and early validation with clear error handling.


136-170: LGTM!

The query construction correctly handles auth vs. non-auth cases, and the table verification logic is thorough.


187-192: LGTM!

The PlanetScale handling is appropriate—optimistically passing with clear warnings when live testing isn't feasible.


194-202: LGTM!

Handler file validation correctly matches the scaffolding logic from scaffoldDatabase.ts.


204-216: LGTM!

The result computation correctly evaluates all checks and handles both local Docker and PlanetScale remote cases.


218-258: LGTM!

The CLI interface is well-structured with clear usage messages, proper error handling, and readable output formatting.

scripts/functional-tests/dependency-installer-tester.ts (1)

16-28: Close the doc comment so TypeScript can parse the module.

The /** after INSTALL_TIMEOUT never terminates, so everything that follows is commented out and the file won’t compile. Please close the block before the JSDoc.

-const INSTALL_TIMEOUT = 120000; /**
+const INSTALL_TIMEOUT = 120000;
+
+/**

Likely an incorrect or invalid review comment.

Comment thread scripts/functional-tests/auth-validator.ts Outdated
Comment thread scripts/functional-tests/dependency-cache.ts Outdated
Comment thread scripts/functional-tests/htmx-test-runner.ts Outdated
Comment thread scripts/functional-tests/mongodb-validator.ts Outdated
Comment thread scripts/functional-tests/mysql-test-runner.ts Outdated
Comment thread scripts/functional-tests/mysql-validator.ts Outdated
Comment thread scripts/functional-tests/postgresql-test-runner.ts Outdated
Comment thread scripts/functional-tests/postgresql-validator.ts Outdated
Comment thread scripts/functional-tests/postgresql-validator.ts Outdated
Comment thread scripts/functional-tests/svelte-test-runner.ts Outdated
@eugenegraves
Copy link
Copy Markdown
Collaborator Author

Summary

  • Unified the testing workflow behind bun run test:cli, removing legacy matrix scripts and aligning every runner with the new flag-driven UX (use -h or --help to view menu)
  • Hardened dependency caching (manifest hashing, cache invalidation) and non-interactive scaffolding so CI/test runs no longer hang on prompts or stale node_modules.
  • Fixed functional regressions exposed by the suites (PostgreSQL SQL adapter now wraps pg.Pool; MySQL Drizzle handlers now fetch insert IDs correctly; Tsconfig/vue shim guardrails, auth handler typing, directory prompts, config scaffolding safety, etc.).

Testing

Suite Result Notes
Functional core (build + server + deps) ✅ 100% Unified runner exercised via test:cli
Framework: React ✅ 100% Includes non-interactive scaffolding guard
Framework: Vue ✅ 100% tsconfig JSX + vue shim fixes validated
Framework: Svelte ✅ 100%
Framework: HTML ✅ 100%
Framework: HTMX ✅ 100%
Database: SQLite ✅ 100% Local + Turso matrix
Database: PostgreSQL ✅ 100% createPgSql adapter + Drizzle schema verified
Database: MySQL ✅ 100% Drizzle insert handler now uses insertId
Database: MongoDB ✅ 100%
Auth (absoluteAuth matrix) ✅ 100% Handler casting + dependency guards
Cloud providers (Neon, Turso) ✅ 100% Uses manifest-aware dependency cache

Structural Changes

  • scripts/functional-tests/test-cli.ts is the single entry-point (framework/database/auth/cloud flags auto-include matching suites; --all, --list, --clean, --dry-run supported).
  • Test matrices filter incompatible options (e.g., skip custom directory configs, unsupported providers) directly inside the runners—no separate generation/verification scripts.
  • Dependency cache fingerprints now hash manifests (package.json, bun.lockb, package-lock.json) so updated templates invalidate cached installs automatically.
  • All Bun process spawns replaced with child_process.spawn where we need timeout control or .kill() handles; stdout/stderr collected for error previews.
  • Every runner ensures the scaffolded CLI runs non-interactively (--skip defaults) by pushing unresolved frontends into prompts instead of defaulting silently.

Functional Fixes

  • Introduced backend/database/createPgSql.ts (generated only for PostgreSQL SQL templates) plus type-safe handlers, eliminating Pool vs SQL mismatches.
  • Drizzle schema/handler updates: MySQL count-history insert now reads insertId; auth handlers cast userIdentity defensively; Frontend directory prompt respects custom config without defaulting.
  • Config scaffolding hardened: tsconfig writes wrapped in try/catch, Vue shims only emitted when relevant, ensures src/types/ exists.
  • Template adjustments: tsconfig JSX option respects the chosen frontend; Vue shim suppressed for non-Vue; React/Vue/Svelte validators refactored for clearer error reporting.
  • Dependency/cache guards: parseCommandLineOptions forces non-interactive defaults under --skip; server/build validators ported to ESM with robust timeout/error extraction; server startup validator kills subprocesses on timeout.
  • Test harness reliability: API/Frontend placeholders converted to ESM; installers/typecheckers capture outputs with bounded previews; cloud runner uses child_process.spawn for strict argument handling; MongoDB and SQLite validators rely on native CLIs with timeout protection.

All suites above were re-run after these changes, completing at 100%.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/generators/db/scaffoldDocker.ts (1)

48-62: MongoDB initialization is completely skipped—critical issue.

The condition on line 48 (if (databaseEngine !== 'mongodb')) excludes MongoDB entirely from the initialization block. While PostgreSQL, MySQL, and MariaDB execute initialization commands (lines 53–61) that populate users and count_history collections via userTables and countHistoryTables, MongoDB gets no equivalent initialization.

MongoDB is fundamentally designed for "create on first use", so if you do not insert data, then no database is created. Without the initialization commands that other engines receive, MongoDB will have empty or missing collections. This directly aligns with the PR objective noting "MongoDB: sandbox failures due to undefined users/count_history collections."

MongoDB initialization must be added. The initTemplates[mongodb], userTables[mongodb], and countHistoryTables[mongodb] are imported but never used. Either:

  • Add MongoDB initialization logic in an else block (lines 62+), or
  • Verify MongoDB initialization happens elsewhere and update logic accordingly.
♻️ Duplicate comments (6)
src/generators/configurations/generatePackageJson.ts (1)

229-230: Fix mongosh readiness loop authentication.

The db:mongosh readiness check calls mongosh --eval without credentials, but the MongoDB container requires authentication (-u user -p password --authenticationDatabase admin database). The ping will fail with exit code 18, causing the until loop to hang indefinitely. Both the readiness probe and the interactive shell need credentials.

Apply this diff to fix the authentication:

-		scripts['db:mongosh'] =
-			"docker compose -p mongodb -f db/docker-compose.db.yml exec db bash -lc 'until mongosh --eval \"db.runCommand({ ping: 1 })\" --quiet; do sleep 1; done; exec mongosh'";
+		scripts['db:mongosh'] =
+			"docker compose -p mongodb -f db/docker-compose.db.yml exec db bash -lc 'until mongosh -u user -p password --authenticationDatabase admin database --eval \"db.runCommand({ ping: 1 })\" --quiet; do sleep 1; done; exec mongosh -u user -p password --authenticationDatabase admin database'";
scripts/functional-tests/server-startup-validator.ts (1)

92-155: Still running typecheck even when the script isn't defined.

We continue to spawn ${packageManager} run typecheck without first verifying the script exists. Several generated packages (for example the minimal HTML/HTMX scaffolds) only expose dev and build, so this exits with “Missing script: typecheck” and the validator reports a failure despite the server scaffold being fine. Please reuse the package.json probing logic so we skip or fall back when the script is absent instead of treating it as an error.

scripts/functional-tests/htmx-test-runner.ts (1)

103-132: Timeout branch still fires after a successful scaffold

We’re still racing the scaffold promise against an uncancellable bun.sleep. When the scaffold finishes under the deadline, the race resolves immediately, but sleep keeps running and eventually invokes onTimeout(), killing the already-finished process and throwing an unhandled rejection minutes later—the same dangling-timer problem from the earlier review. Please switch back to an explicit setTimeout that you clear in a finally block so the timeout path can’t execute once the scaffold promise settles.

-const raceWithTimeout = async <T>(
-  promise: Promise<T>,
-  timeoutMs: number,
-  onTimeout: () => void
-) => {
-  const bunModule = await loadBunModule();
-  const timeoutPromise = bunModule.sleep(timeoutMs).then(() => {
-    onTimeout();
-    throw new Error('TIMEOUT');
-  });
-
-  return Promise.race([promise, timeoutPromise]) as Promise<T>;
-};
+const raceWithTimeout = async <T>(
+  promise: Promise<T>,
+  timeoutMs: number,
+  onTimeout: () => void
+) => {
+  let timeoutId: ReturnType<typeof setTimeout> | undefined;
+  try {
+    return await Promise.race([
+      promise,
+      new Promise<never>((_, reject) => {
+        timeoutId = setTimeout(() => {
+          try {
+            onTimeout();
+          } finally {
+            reject(new Error('TIMEOUT'));
+          }
+        }, timeoutMs);
+      })
+    ]);
+  } finally {
+    if (timeoutId !== undefined) {
+      clearTimeout(timeoutId);
+    }
+  }
+};
scripts/functional-tests/mysql-validator.ts (1)

105-160: Docker skips still report success

When bun db:up fails because Docker needs sudo/is absent, handleDockerUnavailable marks connectionWorks/queriesWork true and getDockerStartErrors returns an empty list. The call at Line 208 therefore leaves errors empty, so the validator ends up reporting passed: true even though no MySQL checks ran and the container never started. That’s the same false-positive scenario I called out earlier. Please fail (or require an explicit skip flag) rather than assuming success so CI can catch real MySQL regressions. Suggested fix:

 const handleDockerUnavailable = (
   stderr: string,
   warnings: string[],
   mysqlSpecific: MySQLValidationResult['mysqlSpecific']
 ) => {
   warnings.push(
     `Docker not available or requires sudo - skipping local MySQL connection test: ${stderr.slice(0, DOCKER_WARNING_SNIPPET_LENGTH)}`
   );
-  mysqlSpecific.connectionWorks = true;
-  mysqlSpecific.queriesWork = true;
+  mysqlSpecific.connectionWorks = false;
+  mysqlSpecific.queriesWork = false;
 };
 
 const getDockerStartErrors = (
   stderr: string,
   warnings: string[],
   mysqlSpecific: MySQLValidationResult['mysqlSpecific']
 ) => {
   const lowerStderr = stderr.toLowerCase();
   const requiresDockerAccess = stderr.includes('sudo') || lowerStderr.includes('docker');
 
   if (requiresDockerAccess) {
-    handleDockerUnavailable(stderr, warnings, mysqlSpecific);
-
-    return [];
+    handleDockerUnavailable(stderr, warnings, mysqlSpecific);
+
+    return [
+      'Docker not available or requires sudo - cannot execute local MySQL validation'
+    ];
   }
scripts/functional-tests/mongodb-validator.ts (1)

97-151: Remote Docker skip still yields a pass

If bun db:up fails because Docker needs sudo/is absent, handleDockerUnavailable flips connectionWorks/queriesWork to true and getDockerStartErrors returns an empty array. The early return at Line 209 then hands back no errors, so the top-level validator happily marks the run as passed even though no MongoDB checks ran. This keeps masking real regressions—the exact issue from the previous review. Please treat this as a failure (or gate it behind an explicit skip flag). For example:

 const handleDockerUnavailable = (
   stderr: string,
   warnings: string[],
   mongodbSpecific: MongoDBValidationResult['mongodbSpecific']
 ) => {
   warnings.push(
     `Docker not available or requires sudo - skipping local MongoDB connection test: ${stderr.slice(0, DOCKER_WARNING_SNIPPET_LENGTH)}`
   );
-  mongodbSpecific.connectionWorks = true;
-  mongodbSpecific.queriesWork = true;
+  mongodbSpecific.connectionWorks = false;
+  mongodbSpecific.queriesWork = false;
 };
 
 ...
   if (requiresDockerAccess) {
-    handleDockerUnavailable(stderr, warnings, mongodbSpecific);
-
-    return [];
+    handleDockerUnavailable(stderr, warnings, mongodbSpecific);
+
+    return [
+      'Docker not available or requires sudo - cannot execute local MongoDB validation'
+    ];
   }
scripts/functional-tests/react-validator.ts (1)

48-72: Handle multi-frontend React directories

When scaffoldFrontends provisions multiple frontends, React assets live under src/frontend/react/... instead of src/frontend. Hard-coding the single-front paths makes every multi-front scaffold look broken even though the files exist, so the validator produces false failures. Please detect the React root first (e.g. probe both src/frontend/react and src/frontend) and only assert the file list inside the directory that actually exists; fall back to an error if neither is present. Reusing _config.isMultiFrontend or a helper similar to the HTMX validator would solve it.

Apply this diff as a starting point:

-const REQUIRED_COMPONENT_FILES = [
-  ['src', 'frontend', 'components', 'App.tsx'],
-  ['src', 'frontend', 'components', 'Head.tsx'],
-  ['src', 'frontend', 'components', 'Dropdown.tsx'],
-  ['src', 'frontend', 'pages', 'ReactExample.tsx'],
-  ['src', 'frontend', 'styles', 'react-example.css'],
-  ['src', 'backend', 'assets', 'svg', 'react.svg']
-];
+const REACT_DIRECTORY_CANDIDATES = ['src/frontend/react', 'src/frontend'] as const;
+const REACT_REQUIRED_SUBPATHS = {
+  components: ['components', 'App.tsx', 'Head.tsx', 'Dropdown.tsx'],
+  pages: ['pages', 'ReactExample.tsx'],
+  styles: ['styles', 'react-example.css']
+};
+
+const resolveReactDirectory = (projectPath: string) =>
+  REACT_DIRECTORY_CANDIDATES.map((relative) => join(projectPath, relative)).find((candidate) =>
+    existsSync(join(candidate, 'components'))
+  );

Then join the resolved directory with the required subpaths before validating and keep the backend asset check separate.

🧹 Nitpick comments (6)
src/generators/db/scaffoldDocker.ts (2)

38-42: Add explanatory comment for test-specific behavior.

The shared container logic is not immediately obvious without context. Consider adding a brief comment explaining that this optimization allows test runners to reuse containers across test permutations.

+	// In test mode, PostgreSQL/MySQL/MariaDB can share a single container
+	// across multiple test permutations to reduce overhead
 	const useSharedContainer =
 		process.env.ABSOLUTE_TEST === 'true' &&
 		(databaseEngine === 'postgresql' ||
 			databaseEngine === 'mysql' ||
 			databaseEngine === 'mariadb');

45-46: Consider error handling for file write operation.

The writeFileSync call could fail if projectDatabaseDirectory doesn't exist or has permission issues. While the directory may be created earlier in the call chain, adding error handling here would provide clearer feedback.

-	const composePath = join(projectDatabaseDirectory, 'docker-compose.db.yml');
-	writeFileSync(composePath, dbContainer, 'utf-8');
+	const composePath = join(projectDatabaseDirectory, 'docker-compose.db.yml');
+	try {
+		writeFileSync(composePath, dbContainer, 'utf-8');
+	} catch (error) {
+		throw new Error(
+			`Failed to write docker-compose file to ${composePath}: ${error instanceof Error ? error.message : String(error)}`
+		);
+	}
src/generators/project/generateDBBlock.ts (1)

96-101: Clarify the fallback logic in expression selection.

The expression selection logic has fallbacks that may be confusing:

const isRemoteHost = hostKey !== 'none' && hostKey in remoteDrizzleInit;
const expr = isRemoteHost 
  ? (remoteDrizzleInit[hostKey] ?? engineGroup[hostKey]?.expr)
  : (engineGroup[hostKey]?.expr ?? remoteDrizzleInit[hostKey]);

For remote hosts: Falls back from remoteDrizzleInit[hostKey]engineGroup[hostKey]?.expr
For local hosts: Falls back from engineGroup[hostKey]?.exprremoteDrizzleInit[hostKey]

The local-host fallback to remoteDrizzleInit seems unexpected. If engineGroup[hostKey]?.expr is undefined for a local host, falling back to a remote initialization expression could cause runtime issues.

Consider simplifying without the fallback, or adding a guard:

 const isRemoteHost = hostKey !== 'none' && hostKey in remoteDrizzleInit;
-const expr = isRemoteHost 
-  ? (remoteDrizzleInit[hostKey] ?? engineGroup[hostKey]?.expr)
-  : (engineGroup[hostKey]?.expr ?? remoteDrizzleInit[hostKey]);
+const expr = isRemoteHost 
+  ? remoteDrizzleInit[hostKey]
+  : engineGroup[hostKey]?.expr;
 if (!expr) return '';

This relies on the existing if (!expr) guard at Line 101 to catch missing configurations.

src/generators/db/ensurePostgresSqlAdapter.ts (1)

40-66: Consider documenting the object serialization behavior.

The normaliseValue function JSON-stringifies all objects (Line 59), with a fallback to String(value) on error. This is a reasonable default, but developers might expect different behavior depending on the column type (e.g., JSONB vs TEXT vs custom types).

Add a comment documenting this behavior:

   if (typeof value === 'object') {
+    // Objects are JSON-stringified by default. Use explicit JSON.stringify()
+    // or custom type handlers for precise control over serialization.
     try {
       return JSON.stringify(value)
     } catch {
       return String(value)
     }
   }
scripts/functional-tests/cloud-provider-test-runner.ts (2)

408-454: Consider renaming sortedResults to avoid confusion.

The variable sortedResults creates a deep copy of the results but performs no sorting, making the name misleading.

If sorting isn't needed, consider either:

  1. Renaming to processedResults or simply using results directly, or
  2. Adding actual sorting if needed (e.g., by databaseHost or pass/fail status)
-  const sortedResults = results.map((result) => ({
+  const processedResults = results.map((result) => ({
     config: {

and update references accordingly. If the deep copy serves a specific purpose, a brief comment would clarify the intent.


491-540: LGTM with a minor inconsistency note.

The main orchestration correctly loads, filters, executes, and summarizes tests with proper exit codes.

Consider using a consistent error display limit or documenting the distinction:

  • Line 521: Inline errors limited to 2
  • Line 450: Summary errors limited to MAX_ERRORS_TO_DISPLAY (3)

If the difference is intentional (inline brevity vs. summary detail), a brief comment would clarify. Otherwise, consider:

-      console.log(`    Errors: ${outcome.errors.slice(0, 2).join('; ')}`);
+      console.log(`    Errors: ${outcome.errors.slice(0, MAX_ERRORS_TO_DISPLAY).join('; ')}`);

or introduce a separate constant like MAX_INLINE_ERRORS = 2.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 74eb0bf and 78b7a1e.

📒 Files selected for processing (41)
  • package.json (1 hunks)
  • scripts/functional-tests/api-endpoint-tester.ts (1 hunks)
  • scripts/functional-tests/auth-test-runner.ts (1 hunks)
  • scripts/functional-tests/auth-validator.ts (1 hunks)
  • scripts/functional-tests/build-validator.ts (1 hunks)
  • scripts/functional-tests/cloud-provider-test-runner.ts (1 hunks)
  • scripts/functional-tests/cloud-provider-validator.ts (1 hunks)
  • scripts/functional-tests/database-connection-tester.ts (1 hunks)
  • scripts/functional-tests/dependency-cache.ts (1 hunks)
  • scripts/functional-tests/dependency-installer-tester.ts (1 hunks)
  • scripts/functional-tests/frontend-renderer-tester.ts (1 hunks)
  • scripts/functional-tests/functional-test-runner.ts (1 hunks)
  • scripts/functional-tests/html-test-runner.ts (1 hunks)
  • scripts/functional-tests/htmx-test-runner.ts (1 hunks)
  • scripts/functional-tests/htmx-validator.ts (1 hunks)
  • scripts/functional-tests/matrix.ts (1 hunks)
  • scripts/functional-tests/mongodb-test-runner.ts (1 hunks)
  • scripts/functional-tests/mongodb-validator.ts (1 hunks)
  • scripts/functional-tests/mysql-test-runner.ts (1 hunks)
  • scripts/functional-tests/mysql-validator.ts (1 hunks)
  • scripts/functional-tests/postgresql-test-runner.ts (1 hunks)
  • scripts/functional-tests/postgresql-validator.ts (1 hunks)
  • scripts/functional-tests/react-test-runner.ts (1 hunks)
  • scripts/functional-tests/react-validator.ts (1 hunks)
  • scripts/functional-tests/server-startup-validator.ts (1 hunks)
  • scripts/functional-tests/sqlite-test-runner.ts (1 hunks)
  • scripts/functional-tests/sqlite-validator.ts (1 hunks)
  • scripts/functional-tests/svelte-test-runner.ts (1 hunks)
  • scripts/functional-tests/svelte-validator.ts (1 hunks)
  • scripts/functional-tests/test-cli.ts (1 hunks)
  • scripts/functional-tests/test-utils.ts (1 hunks)
  • scripts/functional-tests/vue-validator.ts (1 hunks)
  • src/generators/configurations/generatePackageJson.ts (3 hunks)
  • src/generators/db/ensurePostgresSqlAdapter.ts (1 hunks)
  • src/generators/db/generateDrizzleSchema.ts (1 hunks)
  • src/generators/db/handlerTemplates.ts (6 hunks)
  • src/generators/db/scaffoldDocker.ts (2 hunks)
  • src/generators/project/generateDBBlock.ts (3 hunks)
  • src/generators/project/generateImportsBlock.ts (2 hunks)
  • src/generators/project/generateServer.ts (3 hunks)
  • tsconfig.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • scripts/functional-tests/database-connection-tester.ts
  • src/generators/db/handlerTemplates.ts
  • scripts/functional-tests/sqlite-test-runner.ts
  • scripts/functional-tests/svelte-test-runner.ts
  • scripts/functional-tests/mysql-test-runner.ts
  • package.json
🧰 Additional context used
🧬 Code graph analysis (29)
tsconfig.json (1)
src/generators/configurations/scaffoldConfigurationFiles.ts (1)
  • AddConfigurationProps (22-77)
src/generators/project/generateServer.ts (1)
src/generators/db/ensurePostgresSqlAdapter.ts (1)
  • ensurePostgresSqlAdapter (98-104)
src/generators/db/generateDrizzleSchema.ts (2)
src/questions/databaseHost.ts (1)
  • databaseEngine (6-35)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/db/scaffoldDocker.ts (1)
src/generators/db/generateDockerContainer.ts (1)
  • generateDockerContainer (84-114)
scripts/functional-tests/svelte-validator.ts (4)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (24-34)
  • runFunctionalTests (116-170)
src/generators/svelte/scaffoldSvelte.ts (1)
  • ScaffoldFrontendProps (6-33)
src/generators/project/scaffoldFrontends.ts (1)
  • ScaffoldFrontendsProps (19-106)
src/generators/svelte/generateSveltePage.ts (1)
  • frontends (4-218)
scripts/functional-tests/test-cli.ts (2)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (9-20)
scripts/functional-tests/dependency-cache.ts (1)
  • cleanupCache (282-313)
scripts/functional-tests/auth-validator.ts (2)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (24-34)
  • runFunctionalTests (116-170)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
scripts/functional-tests/react-test-runner.ts (4)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (9-20)
scripts/functional-tests/dependency-cache.ts (3)
  • computeManifestHash (80-106)
  • hasCachedDependencies (224-248)
  • getOrInstallDependencies (250-280)
scripts/functional-tests/react-validator.ts (1)
  • validateReactFramework (210-249)
scripts/functional-tests/matrix.ts (1)
  • createMatrix (82-93)
scripts/functional-tests/build-validator.ts (1)
src/generators/configurations/scaffoldConfigurationFiles.ts (1)
  • AddConfigurationProps (22-77)
src/generators/db/ensurePostgresSqlAdapter.ts (1)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/project/generateDBBlock.ts (3)
src/questions/databaseHost.ts (1)
  • databaseEngine (6-35)
src/generators/configurations/generateEnv.ts (1)
  • GenerateEnvProps (23-44)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
scripts/functional-tests/dependency-installer-tester.ts (1)
src/commands/installDependencies.ts (1)
  • packageManager (8-24)
scripts/functional-tests/server-startup-validator.ts (1)
src/generators/configurations/scaffoldConfigurationFiles.ts (1)
  • AddConfigurationProps (22-77)
scripts/functional-tests/dependency-cache.ts (1)
src/commands/installDependencies.ts (1)
  • installDependencies (8-24)
scripts/functional-tests/vue-validator.ts (2)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (24-34)
  • runFunctionalTests (116-170)
src/generators/vue/scaffoldVue.ts (1)
  • ScaffoldVueProps (8-27)
scripts/functional-tests/mysql-validator.ts (4)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
src/generators/db/generateDockerContainer.ts (1)
  • databaseEngine (84-114)
src/utils/parseCommandLineOptions.ts (1)
  • parseArgs (32-332)
scripts/functional-tests/cloud-provider-test-runner.ts (4)
scripts/functional-tests/matrix.ts (2)
  • MatrixConfig (33-42)
  • createMatrix (82-93)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (9-20)
scripts/functional-tests/dependency-cache.ts (3)
  • computeManifestHash (80-106)
  • hasCachedDependencies (224-248)
  • getOrInstallDependencies (250-280)
scripts/functional-tests/cloud-provider-validator.ts (1)
  • validateCloudProvider (247-320)
scripts/functional-tests/htmx-test-runner.ts (4)
scripts/functional-tests/matrix.ts (2)
  • MatrixConfig (33-42)
  • createMatrix (82-93)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (9-20)
scripts/functional-tests/dependency-cache.ts (3)
  • computeManifestHash (80-106)
  • hasCachedDependencies (224-248)
  • getOrInstallDependencies (250-280)
scripts/functional-tests/htmx-validator.ts (1)
  • validateHTMXFramework (230-269)
scripts/functional-tests/sqlite-validator.ts (2)
src/utils/checkSqliteInstalled.ts (8)
  • hasSqlite (137-159)
  • commandExists (80-110)
  • ensureSudo (37-49)
  • commandExists (119-135)
  • hasSqlite (112-117)
  • cmd (21-25)
  • $ (34-35)
  • $ (27-32)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
scripts/functional-tests/postgresql-validator.ts (2)
src/generators/db/dockerInitTemplates.ts (3)
  • initTemplates (111-140)
  • userTables (91-99)
  • countHistoryTables (101-109)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
scripts/functional-tests/mongodb-validator.ts (2)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/db/generateDockerContainer.ts (1)
  • databaseEngine (84-114)
scripts/functional-tests/functional-test-runner.ts (3)
scripts/functional-tests/dependency-installer-tester.ts (1)
  • testDependencyInstallation (117-163)
scripts/functional-tests/build-validator.ts (1)
  • validateBuild (107-158)
scripts/functional-tests/server-startup-validator.ts (1)
  • validateServerStartup (157-198)
scripts/functional-tests/html-test-runner.ts (3)
scripts/functional-tests/matrix.ts (2)
  • MatrixConfig (33-42)
  • createMatrix (82-93)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (9-20)
scripts/functional-tests/dependency-cache.ts (3)
  • computeManifestHash (80-106)
  • hasCachedDependencies (224-248)
  • getOrInstallDependencies (250-280)
scripts/functional-tests/cloud-provider-validator.ts (1)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (24-34)
  • runFunctionalTests (116-170)
scripts/functional-tests/mongodb-test-runner.ts (5)
scripts/functional-tests/matrix.ts (2)
  • MatrixConfig (33-42)
  • createMatrix (82-93)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (9-20)
scripts/functional-tests/dependency-cache.ts (3)
  • computeManifestHash (80-106)
  • hasCachedDependencies (224-248)
  • getOrInstallDependencies (250-280)
scripts/functional-tests/functional-test-runner.ts (1)
  • runFunctionalTests (116-170)
scripts/functional-tests/mongodb-validator.ts (1)
  • validateMongoDBDatabase (262-334)
scripts/functional-tests/auth-test-runner.ts (4)
scripts/functional-tests/matrix.ts (2)
  • MatrixConfig (33-42)
  • createMatrix (82-93)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (9-20)
scripts/functional-tests/dependency-cache.ts (3)
  • computeManifestHash (80-106)
  • hasCachedDependencies (224-248)
  • getOrInstallDependencies (250-280)
scripts/functional-tests/auth-validator.ts (1)
  • validateAuthConfiguration (222-290)
scripts/functional-tests/react-validator.ts (1)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (24-34)
  • runFunctionalTests (116-170)
scripts/functional-tests/htmx-validator.ts (1)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (24-34)
  • runFunctionalTests (116-170)
scripts/functional-tests/postgresql-test-runner.ts (5)
scripts/functional-tests/matrix.ts (2)
  • MatrixConfig (33-42)
  • createMatrix (82-93)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (9-20)
scripts/functional-tests/dependency-cache.ts (3)
  • computeManifestHash (80-106)
  • hasCachedDependencies (224-248)
  • getOrInstallDependencies (250-280)
scripts/functional-tests/functional-test-runner.ts (1)
  • runFunctionalTests (116-170)
scripts/functional-tests/postgresql-validator.ts (3)
  • validatePostgreSQLDatabase (398-482)
  • isPostgresDockerManaged (288-288)
  • stopManagedPostgresDocker (284-286)
🔇 Additional comments (26)
src/generators/configurations/generatePackageJson.ts (2)

169-170: LGTM!

The PostgreSQL native driver and types are correctly added only for local Docker setups, aligning with the pattern where cloud providers (Neon) use their own packages.


189-191: MongoDB dependency pattern is consistent with MySQL.

The mongodb package is added unconditionally, matching the mysql2 pattern (line 186). This works for the current implementation since no cloud MongoDB provider is configured in the databaseHost switch. When cloud MongoDB support is added, verify whether it uses the native mongodb package or requires a provider-specific package like Neon/PlanetScale.

src/generators/db/scaffoldDocker.ts (1)

2-2: LGTM: Modern import syntax.

Using the node: prefix for built-in modules is a best practice.

src/generators/project/generateImportsBlock.ts (3)

82-91: LGTM! Dynamic Neon import selection is well-designed.

The getNeonImport() helper correctly handles the different import requirements:

  • Drizzle ORM needs Pool from @neondatabase/serverless for connection pooling
  • Non-Drizzle scenarios use the neon serverless function

This centralizes the logic and makes the connector imports maintainable.


169-174: LGTM! MongoDB import path is now explicit and correct.

The refactored MongoDB path clearly imports MongoClient and getEnv, removing the previous conditional complexity. This aligns with the MongoDB connection handling added in generateDBBlock.ts.


153-167: Verification confirmed: adapter creation is guaranteed before import generation.

The conditions in generateServer.ts:47 (where ensurePostgresSqlAdapter is called) and generateImportsBlock.ts:153-167 (where the import is generated) are perfectly aligned. Both require databaseEngine === 'postgresql', no ORM, and local host (not remote). Since generateImportsBlock is only called from generateServerFile immediately after the adapter is created, all codepaths that generate this import also ensure the adapter file exists.

src/generators/project/generateServer.ts (2)

42-48: LGTM! Adapter scaffolding is properly gated.

The conditions correctly identify when the PostgreSQL adapter is needed:

  • PostgreSQL database engine
  • No ORM (undefined or 'none')
  • Local host (undefined or 'none')

This ensures createPgSql.ts is available before generateImportsBlock tries to import it at Line 162.


85-86: LGTM! Passing databaseEngine to route generation.

This change enables route generation logic to adapt based on the database engine, which is necessary for the expanded test coverage across different database configurations mentioned in the PR objectives.

src/generators/project/generateDBBlock.ts (3)

17-17: Good fix! Removed syntax error in MongoDB connection string.

The extra closing brace } has been correctly removed from the MongoDB none expression.


28-28: LGTM! Neon expression updated for non-Drizzle usage.

Changed from new Pool({ connectionString: getEnv("DATABASE_URL") }) to neon(getEnv("DATABASE_URL")). This is correct for non-Drizzle + Neon scenarios where you use the serverless neon() function instead of a connection pool.


73-91: LGTM! Special handling for MongoDB and PostgreSQL is correct.

The non-Drizzle paths now have engine-specific initialization:

  • MongoDB (lines 74-80): Creates client, connects, and gets database handle - necessary for MongoDB's connection model
  • PostgreSQL + local (lines 82-87): Creates pool and wraps it with createPgSql adapter - aligns with the scaffolded adapter
  • Fallback (lines 89-91): Generic const db = ${expr} for other engines

This handles the connection lifecycle differences across database engines correctly.

src/generators/db/ensurePostgresSqlAdapter.ts (3)

21-38: LGTM! Standard PostgreSQL parameterization.

The buildQuery function correctly constructs parameterized queries by:

  • Interleaving template string parts
  • Replacing parameters with $1, $2, etc. placeholders
  • Accumulating parameter values

This follows PostgreSQL's parameterized query conventions.


73-95: LGTM! Clean template literal API with raw query support.

The createPgSql function provides:

  • Template literal interface: sql<T>\SELECT * FROM users WHERE id = ${id}``
  • Raw query method: sql.query<T>(text, params)
  • Cleanup: sql.end() terminates the pool

The type safety with QueryResultRow generics is well-designed.


98-104: LGTM! Adapter scaffolding is straightforward.

The ensurePostgresSqlAdapter function creates the necessary directory structure and writes the adapter file to backend/database/createPgSql.ts. This integrates cleanly with the import added in generateImportsBlock.ts at Line 162.

scripts/functional-tests/cloud-provider-test-runner.ts (12)

1-46: LGTM! Clean imports and well-structured types.

The type definitions properly model the test execution flow, and the dependency configuration structure correctly matches the cache fingerprinting requirements.


47-56: LGTM! Constants properly scope the test matrix.

The supported sets correctly limit testing to stable combinations (Neon/Turso with SQLite/PostgreSQL), aligning with the PR's approach to exclude failing MySQL/MongoDB and PlanetScale configurations.


57-65: LGTM! Efficient module caching pattern.

Lazy-loading the Bun module with caching avoids repeated dynamic imports across multiple test executions.


67-117: LGTM! Deterministic command construction.

The helper functions correctly build scaffold commands with appropriate flags for each configuration. Project naming ensures valid, predictable identifiers.


119-162: LGTM! Robust command execution with timeout handling.

The command spawning correctly uses the cmd array format, and the timeout mechanism properly kills hung processes. Previous command interpolation issues have been addressed.


164-212: LGTM! Clean scaffolding orchestration.

Pre-run cleanup, timeout handling, and exit code validation are properly implemented with clear user feedback.


214-267: LGTM! Proper dependency cache integration.

The dependency installation correctly leverages the cache mechanism, with proper error handling and timing feedback.


269-303: LGTM! Correct validation integration.

The validation correctly skips dependency installation (already performed) while running build and server checks, properly propagating errors and warnings.


305-379: LGTM! Comprehensive test orchestration.

The pipeline properly sequences scaffolding, dependency installation, and validation with appropriate early exits and guaranteed cleanup in all paths.


381-392: LGTM! Matrix filtering aligns with supported configurations.

The filter correctly limits testing to stable cloud provider combinations and default directory configurations.


394-406: LGTM! Standard sequential execution pattern.

The reduce-based sequential runner correctly chains test executions and accumulates results.


456-489: LGTM! Backward-compatible argument parsing.

The parser gracefully handles legacy two-argument format while supporting the new single-argument subset parameter, with appropriate warnings.

Comment thread scripts/functional-tests/build-validator.ts Outdated
Comment on lines +34 to +105
const LOCK_FILES = ['bun.lockb', 'package-lock.json'];
const MINUTES_PER_INSTALL_TIMEOUT = 5;
const SECONDS_PER_MINUTE = 60;
const MILLISECONDS_PER_SECOND = 1_000;
const INSTALL_TIMEOUT_MS = MINUTES_PER_INSTALL_TIMEOUT * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND;
const DEFAULT_CACHE_MAX_AGE_DAYS = 7;
const HOURS_PER_DAY = 24;
const MINUTES_PER_HOUR = 60;
const FORCE_KILL_DELAY_MS = 100;

const createFingerprintKey = (config: DependencyFingerprint, manifestHash: string) =>
JSON.stringify({
authProvider: config.authProvider,
codeQualityTool: config.codeQualityTool ?? 'none',
databaseEngine: config.databaseEngine,
databaseHost: config.databaseHost,
frontend: config.frontend,
manifestHash,
orm: config.orm,
useTailwind: config.useTailwind
});

const FINGERPRINT_LENGTH = 16;

const getDependencyFingerprint = (config: DependencyFingerprint, manifestHash: string) =>
createHash('sha256')
.update(createFingerprintKey(config, manifestHash))
.digest('hex')
.slice(0, FINGERPRINT_LENGTH);

const getCachePath = (fingerprint: string) => join(CACHE_DIR, fingerprint);

const safeRead = (path: string) => {
try {
return readFileSync(path);
} catch {
return null;
}
};

const ensureCacheDir = () => {
if (!existsSync(CACHE_DIR)) {
mkdirSync(CACHE_DIR, { recursive: true });
}
};

export const computeManifestHash = (packageJsonPath: string) => {
if (!existsSync(packageJsonPath)) {
return 'missing';
}

const hash = createHash('sha256');
const packageJsonContents = safeRead(packageJsonPath);

if (!packageJsonContents) {
return 'error:package-json-unreadable';
}

hash.update(packageJsonContents);

const packageDir = dirname(packageJsonPath);

LOCK_FILES.forEach((lockFile) => {
const lockPath = join(packageDir, lockFile);
const contents = safeRead(lockPath);

if (contents) {
hash.update(contents);
}
});

return hash.digest('hex');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Include pnpm/yarn lockfiles in the cache key

The manifest hash (and therefore the cache fingerprint) ignores pnpm-lock.yaml and yarn.lock. Any matrix run using pnpm or yarn can update its lockfile without ever invalidating the cached node_modules, leading to stale dependency trees and spurious build/runtime failures. Please add both lockfiles to LOCK_FILES (and copy them alongside package.json) so cache hits stay valid.

-const LOCK_FILES = ['bun.lockb', 'package-lock.json'];
+const LOCK_FILES = ['bun.lockb', 'package-lock.json', 'pnpm-lock.yaml', 'yarn.lock'];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const LOCK_FILES = ['bun.lockb', 'package-lock.json'];
const MINUTES_PER_INSTALL_TIMEOUT = 5;
const SECONDS_PER_MINUTE = 60;
const MILLISECONDS_PER_SECOND = 1_000;
const INSTALL_TIMEOUT_MS = MINUTES_PER_INSTALL_TIMEOUT * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND;
const DEFAULT_CACHE_MAX_AGE_DAYS = 7;
const HOURS_PER_DAY = 24;
const MINUTES_PER_HOUR = 60;
const FORCE_KILL_DELAY_MS = 100;
const createFingerprintKey = (config: DependencyFingerprint, manifestHash: string) =>
JSON.stringify({
authProvider: config.authProvider,
codeQualityTool: config.codeQualityTool ?? 'none',
databaseEngine: config.databaseEngine,
databaseHost: config.databaseHost,
frontend: config.frontend,
manifestHash,
orm: config.orm,
useTailwind: config.useTailwind
});
const FINGERPRINT_LENGTH = 16;
const getDependencyFingerprint = (config: DependencyFingerprint, manifestHash: string) =>
createHash('sha256')
.update(createFingerprintKey(config, manifestHash))
.digest('hex')
.slice(0, FINGERPRINT_LENGTH);
const getCachePath = (fingerprint: string) => join(CACHE_DIR, fingerprint);
const safeRead = (path: string) => {
try {
return readFileSync(path);
} catch {
return null;
}
};
const ensureCacheDir = () => {
if (!existsSync(CACHE_DIR)) {
mkdirSync(CACHE_DIR, { recursive: true });
}
};
export const computeManifestHash = (packageJsonPath: string) => {
if (!existsSync(packageJsonPath)) {
return 'missing';
}
const hash = createHash('sha256');
const packageJsonContents = safeRead(packageJsonPath);
if (!packageJsonContents) {
return 'error:package-json-unreadable';
}
hash.update(packageJsonContents);
const packageDir = dirname(packageJsonPath);
LOCK_FILES.forEach((lockFile) => {
const lockPath = join(packageDir, lockFile);
const contents = safeRead(lockPath);
if (contents) {
hash.update(contents);
}
});
return hash.digest('hex');
const LOCK_FILES = ['bun.lockb', 'package-lock.json', 'pnpm-lock.yaml', 'yarn.lock'];
const MINUTES_PER_INSTALL_TIMEOUT = 5;
const SECONDS_PER_MINUTE = 60;
const MILLISECONDS_PER_SECOND = 1_000;
const INSTALL_TIMEOUT_MS = MINUTES_PER_INSTALL_TIMEOUT * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND;
const DEFAULT_CACHE_MAX_AGE_DAYS = 7;
const HOURS_PER_DAY = 24;
const MINUTES_PER_HOUR = 60;
const FORCE_KILL_DELAY_MS = 100;
const createFingerprintKey = (config: DependencyFingerprint, manifestHash: string) =>
JSON.stringify({
authProvider: config.authProvider,
codeQualityTool: config.codeQualityTool ?? 'none',
databaseEngine: config.databaseEngine,
databaseHost: config.databaseHost,
frontend: config.frontend,
manifestHash,
orm: config.orm,
useTailwind: config.useTailwind
});
const FINGERPRINT_LENGTH = 16;
const getDependencyFingerprint = (config: DependencyFingerprint, manifestHash: string) =>
createHash('sha256')
.update(createFingerprintKey(config, manifestHash))
.digest('hex')
.slice(0, FINGERPRINT_LENGTH);
const getCachePath = (fingerprint: string) => join(CACHE_DIR, fingerprint);
const safeRead = (path: string) => {
try {
return readFileSync(path);
} catch {
return null;
}
};
const ensureCacheDir = () => {
if (!existsSync(CACHE_DIR)) {
mkdirSync(CACHE_DIR, { recursive: true });
}
};
export const computeManifestHash = (packageJsonPath: string) => {
if (!existsSync(packageJsonPath)) {
return 'missing';
}
const hash = createHash('sha256');
const packageJsonContents = safeRead(packageJsonPath);
if (!packageJsonContents) {
return 'error:package-json-unreadable';
}
hash.update(packageJsonContents);
const packageDir = dirname(packageJsonPath);
LOCK_FILES.forEach((lockFile) => {
const lockPath = join(packageDir, lockFile);
const contents = safeRead(lockPath);
if (contents) {
hash.update(contents);
}
});
return hash.digest('hex');
🤖 Prompt for AI Agents
In scripts/functional-tests/dependency-cache.ts around lines 34 to 105, the
manifest hash currently ignores pnpm and yarn lockfiles; add 'pnpm-lock.yaml'
and 'yarn.lock' to the LOCK_FILES array so computeManifestHash incorporates
them, and update any cache copy logic that copies package.json to also copy
these lockfiles from the package directory when present to ensure cache
invalidation on lockfile changes.

Comment thread scripts/functional-tests/functional-test-runner.ts Outdated
Comment thread scripts/functional-tests/htmx-test-runner.ts Outdated
Comment thread scripts/functional-tests/postgresql-validator.ts Outdated
Comment thread scripts/functional-tests/sqlite-validator.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (8)
scripts/functional-tests/htmx-test-runner.ts (2)

211-227: Consider removing the redundant cache check.

The hasCachedDependencies call on lines 211-215 duplicates the cache-hit logic already performed inside getOrInstallDependencies (which calls restoreCache internally). The returned cached flag is sufficient for the console message.

Apply this diff to simplify the logic:

   process.stdout.write('  → Installing dependencies... ');
 
   const manifestHash = computeManifestHash(packageJsonPath);
   const dependencyConfig: DependencyConfig = {
     authProvider: config.authProvider,
     codeQualityTool: config.codeQualityTool,
     databaseEngine: config.databaseEngine,
     databaseHost: config.databaseHost,
     frontend: config.frontend,
     orm: config.orm,
     useTailwind: config.useTailwind
   };
 
-  const cachedDependency = hasCachedDependencies(
-    dependencyConfig,
-    packageJsonPath,
-    manifestHash
-  );
-
   try {
     const { cached, installTime } = await getOrInstallDependencies(
       projectPath,
       dependencyConfig,
       packageJsonPath,
       manifestHash
     );
 
     console.log(
-      cached || cachedDependency ? `✓ (cached, ${installTime}ms)` : `✓ (${installTime}ms)`
+      cached ? `✓ (cached, ${installTime}ms)` : `✓ (${installTime}ms)`
     );

49-468: Significant code duplication with vue-test-runner.ts.

This file shares ~400 lines of identical or near-identical code with vue-test-runner.ts, including loadBunModule, raceWithTimeout, runCommand, recordFailure, scaffoldProject, installDependencies, runSequentially, printSummary, and parseSubsetFromArgs. Consider extracting these shared utilities into a common test-runner-utils module to improve maintainability and reduce duplication.

scripts/functional-tests/dependency-cache.ts (1)

158-166: Consider confirming SIGTERM completion before SIGKILL.

The current code sends SIGKILL after a fixed 100ms delay without checking whether SIGTERM succeeded. While this works for stuck processes, consider either increasing the delay or checking process state before escalating to SIGKILL for a more graceful shutdown sequence.

scripts/functional-tests/vue-test-runner.ts (2)

233-249: Consider removing the redundant cache check.

The hasCachedDependencies call on lines 233-237 duplicates the cache-hit logic already performed inside getOrInstallDependencies. The returned cached flag is sufficient for the console message. This is the same pattern as in htmx-test-runner.ts lines 211-227.

Apply this diff:

   const manifestHash = computeManifestHash(packageJsonPath);
   const dependencyConfig: DependencyConfig = {
     authProvider: config.authProvider,
     codeQualityTool: config.codeQualityTool,
     databaseEngine: config.databaseEngine,
     databaseHost: config.databaseHost,
     frontend: config.frontend,
     orm: config.orm,
     useTailwind: config.useTailwind
   };
 
-  const cachedDependency = hasCachedDependencies(
-    dependencyConfig,
-    packageJsonPath,
-    manifestHash
-  );
-
   try {
     const { cached, installTime } = await getOrInstallDependencies(
       projectPath,
       dependencyConfig,
       packageJsonPath,
       manifestHash
     );
 
     console.log(
-      cached || cachedDependency ? `✓ (cached, ${installTime}ms)` : `✓ (${installTime}ms)`
+      cached ? `✓ (cached, ${installTime}ms)` : `✓ (${installTime}ms)`
     );

55-478: Significant code duplication with htmx-test-runner.ts.

This file duplicates ~400 lines from htmx-test-runner.ts, including loadBunModule, raceWithTimeout, runCommand, recordFailure, scaffoldProject, installDependencies, runSequentially, printSummary, and parseSubsetFromArgs. Both files would benefit from extracting these shared utilities into a common module. (Same issue flagged in htmx-test-runner.ts review.)

scripts/functional-tests/functional-test-runner.ts (1)

257-263: Remove unreachable return statement.

Line 262's return undefined is unreachable because process.exit() on line 260 terminates the process. Remove the dead code for clarity.

Apply this diff:

   runFunctionalTests(projectPath, packageManager, options)
     .then((result) => {
       printCliSummary(result);
       process.exit(result.passed ? 0 : 1);
-
-      return undefined;
     })
     .catch((error) => {
       console.error('✗ Functional test runner error:', extractErrorMessage(error));
       process.exit(1);
     });
src/generators/db/scaffoldDocker.ts (1)

45-46: Add error handling or ensure directory exists.

The writeFileSync call lacks error handling and will throw if projectDatabaseDirectory doesn't exist. Consider wrapping this in a try-catch or ensuring the directory is created beforehand.

Apply this pattern to add basic error handling:

 const composePath = join(projectDatabaseDirectory, 'docker-compose.db.yml');
-writeFileSync(composePath, dbContainer, 'utf-8');
+try {
+	writeFileSync(composePath, dbContainer, 'utf-8');
+} catch (error) {
+	throw new Error(`Failed to write docker-compose file to ${composePath}: ${error}`);
+}
scripts/functional-tests/postgresql-validator.ts (1)

286-290: Consider removing unused parameter for clarity.

The _projectPath parameter is prefixed with an underscore to indicate it's intentionally unused. If it's not needed for API consistency with other validators, consider removing it to simplify the signature.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 78b7a1e and 92d14e9.

📒 Files selected for processing (9)
  • scripts/functional-tests/build-validator.ts (1 hunks)
  • scripts/functional-tests/dependency-cache.ts (1 hunks)
  • scripts/functional-tests/functional-test-runner.ts (1 hunks)
  • scripts/functional-tests/htmx-test-runner.ts (1 hunks)
  • scripts/functional-tests/postgresql-validator.ts (1 hunks)
  • scripts/functional-tests/sqlite-validator.ts (1 hunks)
  • scripts/functional-tests/vue-test-runner.ts (1 hunks)
  • src/generators/db/dockerInitTemplates.ts (4 hunks)
  • src/generators/db/scaffoldDocker.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • scripts/functional-tests/sqlite-validator.ts
  • scripts/functional-tests/build-validator.ts
🧰 Additional context used
🧬 Code graph analysis (6)
scripts/functional-tests/postgresql-validator.ts (3)
src/generators/db/dockerInitTemplates.ts (3)
  • initTemplates (119-152)
  • userTables (97-106)
  • countHistoryTables (108-117)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
scripts/functional-tests/functional-test-runner.ts (3)
scripts/functional-tests/dependency-installer-tester.ts (1)
  • testDependencyInstallation (117-163)
scripts/functional-tests/build-validator.ts (1)
  • validateBuild (260-295)
scripts/functional-tests/server-startup-validator.ts (1)
  • validateServerStartup (157-198)
scripts/functional-tests/vue-test-runner.ts (4)
scripts/functional-tests/matrix.ts (2)
  • MatrixConfig (33-42)
  • createMatrix (82-93)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (9-20)
scripts/functional-tests/dependency-cache.ts (3)
  • computeManifestHash (80-106)
  • hasCachedDependencies (224-248)
  • getOrInstallDependencies (250-280)
scripts/functional-tests/vue-validator.ts (1)
  • validateVueFramework (231-270)
scripts/functional-tests/dependency-cache.ts (2)
src/commands/installDependencies.ts (1)
  • installDependencies (8-24)
src/generators/configurations/generatePackageJson.ts (1)
  • dep (79-84)
src/generators/db/scaffoldDocker.ts (2)
src/generators/db/generateDockerContainer.ts (1)
  • generateDockerContainer (84-114)
src/generators/db/dockerInitTemplates.ts (3)
  • initTemplates (119-152)
  • userTables (97-106)
  • countHistoryTables (108-117)
scripts/functional-tests/htmx-test-runner.ts (4)
scripts/functional-tests/matrix.ts (2)
  • MatrixConfig (33-42)
  • createMatrix (82-93)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (9-20)
scripts/functional-tests/dependency-cache.ts (3)
  • computeManifestHash (80-106)
  • hasCachedDependencies (224-248)
  • getOrInstallDependencies (250-280)
scripts/functional-tests/htmx-validator.ts (1)
  • validateHTMXFramework (230-269)
🔇 Additional comments (21)
scripts/functional-tests/dependency-cache.ts (1)

250-280: LGTM - Manifest hash recomputation after install is correct.

The code correctly recomputes the manifest hash after installation (line 273) and stores the cache with the updated fingerprint. This handles the case where installation modifies package.json or generates lockfiles, ensuring the cache key reflects the actual installed state rather than the requested state.

scripts/functional-tests/functional-test-runner.ts (1)

215-229: LGTM - Package manager normalization correctly handles flags.

The normalizePackageManager function properly addresses the previous review concern by detecting when the argument is a flag (starts with '-') or an invalid package manager, defaulting to 'bun' and preserving the argument in the remaining array.

src/generators/db/dockerInitTemplates.ts (1)

103-103: MongoDB initialization template structure looks correct.

The additions to userTables, countHistoryTables, and initTemplates are structurally sound and follow the established patterns for other database engines. The mongosh CLI commands and ping-based readiness check are appropriate for MongoDB.

Note: Plain-text credentials in the connection string are consistent with other database templates in this file (lines 129, 141, 149), suggesting this is acceptable for local Docker development scenarios.

Also applies to: 114-114, 136-139

src/generators/db/scaffoldDocker.ts (4)

2-2: LGTM!

The import is necessary for accessing process.env.ABSOLUTE_TEST in the shared container logic.


52-61: LGTM!

The database initialization logic is preserved correctly for non-shared-container scenarios. The code properly:

  • Selects the appropriate SQL/NoSQL commands based on authProvider
  • Executes container startup, initialization, and shutdown
  • Uses the initTemplates to handle engine-specific CLI syntax

38-42: Shared containers are properly initialized in the validator before scaffolding runs.

Verification confirms that validatePostgreSQLDatabase (called before scaffolding) creates and seeds shared containers using userTables or countHistoryTables based on the auth configuration. The docker-compose.db.yml file is copied to a persistent cache directory via ensureSharedComposeFile, allowing containers to be reused across test runs. When scaffolding executes with ABSOLUTE_TEST=true, the early return at line 49 correctly skips redundant initialization since the validator has already completed seeding.


48-50: Shared container workflow verified—but confirm state isolation between test matrix runs.

The shared container is correctly pre-initialized: when useSharedContainer returns early (lines 48-50), the database has already been started and seeded by validatePostgreSQLDatabasestartDockerContainer (postgresql-validator.ts:208-245). The schema and seed data are established before test execution.

However, the container persists across all test matrix entries without data cleanup between projects:

  • Schema init uses CREATE TABLE IF NOT EXISTS (existing tables are skipped)
  • Data inserted by Project N remains when Project N+1 runs
  • Container only stops after the entire test matrix completes (postgresql-test-runner.ts:615)

Verify that test isolation doesn't depend on stale data cleanup, or add TRUNCATE calls after each project's test execution.

scripts/functional-tests/postgresql-validator.ts (14)

1-30: LGTM! Well-organized imports and constants.

The constants are appropriately scoped and the timeout values are reasonable for database operations.


31-39: LGTM! Clean dynamic import caching.

The pattern correctly caches the Bun module to avoid repeated dynamic imports.


49-100: LGTM! Robust command execution with proper timeout handling.

The escalation from SIGTERM to SIGKILL and comprehensive error handling are well-implemented.


102-111: LGTM! Path helpers correctly implement expected logic.

The conditional path selection based on ORM and auth configuration is appropriate.


123-140: LGTM! Docker unavailability is now handled correctly.

The implementation no longer short-circuits or marks skipped Docker checks as passed. When Docker is unavailable, a warning is pushed but validation continues with remaining structural checks, allowing the final pass/fail decision to be based on all available signals.


142-160: LGTM! Solid retry pattern for database readiness.

The recursive approach with bounded attempts and appropriate delays is well-implemented.


162-176: LGTM! Clean type definitions and state management.

The module-level state enables efficient container reuse across validations.


178-190: LGTM! Shared compose file management is well-implemented.

Centralizing the compose file enables efficient container reuse across multiple validations.


192-206: LGTM! Container status check is correctly implemented.

The command and output parsing appropriately verify the 'db' service is running.


254-274: LGTM! Clean container lifecycle management.

The teardown functions properly reset state and handle errors gracefully, which is appropriate for cleanup operations.


276-284: LGTM! SQL is now passed safely without shell quoting issues.

The query is passed as a separate command argument to psql -c, avoiding bash string interpolation issues that would occur with embedded single or double quotes. The PGPASSWORD environment variable is the standard secure method for non-interactive authentication.


291-370: LGTM! Local validation logic is comprehensive and correct.

The validation properly handles all failure scenarios, and the flags correctly reflect the actual state rather than assuming success when checks are skipped.


449-453: Neon configurations always pass connection checks without testing.

Since Neon is a remote service requiring credentials, the validator skips actual connection tests and marks connectionWorks and queriesWork as true. This means Neon configurations cannot detect connection issues during validation, which could mask problems. However, this is a reasonable trade-off given the credentials constraint.

Document this limitation so that Neon validation failures in production are understood to not be caught by the validator.


384-468: LGTM! Main validation function handles local and remote configurations appropriately.

The logic correctly differentiates between Docker-based local setups and Neon remote configurations, with appropriate checks for each.

Comment thread scripts/functional-tests/postgresql-validator.ts
Comment on lines +25 to +26
const mongodbUsers =
"const admin = db.getSiblingDB('admin'); admin.auth('user', 'password'); const database = db.getSiblingDB('database'); database.users.updateOne({ auth_sub: 'seed-user' }, { \\$setOnInsert: { auth_sub: 'seed-user', created_at: new Date(), metadata: {} } }, { upsert: true });";
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify the MongoDB operator escaping.

The double backslash in \\$setOnInsert will produce a literal backslash character when evaluated by mongosh, breaking the MongoDB operator syntax (should be $setOnInsert). Please verify whether these strings undergo additional processing that requires this escaping, or if this is a bug.

Run the following script to check how these templates are consumed:


🏁 Script executed:

#!/bin/bash
# Description: Find usages of mongodbUsers to verify string processing context

# Search for references to userTables or mongodbUsers
rg -n -A5 -B5 'userTables\[|mongodbUsers' --type=ts

Length of output: 2797






🏁 Script executed:

#!/bin/bash
# Search for other MongoDB shell/mongosh commands in the codebase to see if the escaping pattern is consistent
rg -n 'mongosh|mongo\s' --type=ts --type=js -B2 -A2

Length of output: 2273


🏁 Script executed:

#!/bin/bash
# Search for the pattern of $set, $update, etc. to see if escaping is used elsewhere
rg -n '\$setOnInsert|\$set|\$update' --type=ts --type=js -B1 -A1

Length of output: 844


🏁 Script executed:

#!/bin/bash
# Check if there are any test files or documentation about database initialization
fd -e test.ts -e spec.ts -e '.md' | xargs rg -l 'mongodb|mongosh|updateOne' 2>/dev/null | head -10

Length of output: 9


🌐 Web query:

MongoDB mongosh updateOne $setOnInsert operator syntax correct format

💡 Result:

Use $setOnInsert inside the update document and pass { upsert: true } to updateOne. Example (mongosh):

db.collection.updateOne(
{ _id: 1 }, // filter
{
$set: { item: "apple" }, // applied on match or insert
$setOnInsert: { defaultQty: 100, createdAt: new Date() } // only when inserted
},
{ upsert: true } // must be true for $setOnInsert to run
)

Notes:

  • $setOnInsert does nothing when a matching document is found; it only applies when the operation inserts a new document via upsert. [1][2]

Sources:
[1] MongoDB docs — $setOnInsert operator.
[2] MongoDB docs — db.collection.updateOne() syntax.


Fix MongoDB operator escaping syntax.

The double backslash in \\$setOnInsert produces a literal backslash when passed to mongosh, breaking the MongoDB operator syntax. MongoDB mongosh requires $setOnInsert directly without escape characters.

  • Line 26: Change \\$setOnInsert to $setOnInsert in mongodbUsers
  • Line 29: Change \\$setOnInsert to $setOnInsert in mongodbCountHistory
🤖 Prompt for AI Agents
In src/generators/db/dockerInitTemplates.ts around lines 25-29 the MongoDB
operator is incorrectly escaped: the string uses "\\$setOnInsert" which yields a
literal backslash and breaks mongosh; replace the escaped token with the plain
"$setOnInsert" in both mongodbUsers (line ~26) and mongodbCountHistory (line
~29) so the generated script contains the correct MongoDB operator syntax.

Comment thread src/generators/db/dockerInitTemplates.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 92d14e9 and 4348df6.

📒 Files selected for processing (2)
  • scripts/functional-tests/postgresql-validator.ts (1 hunks)
  • src/generators/db/dockerInitTemplates.ts (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
scripts/functional-tests/postgresql-validator.ts (2)
src/generators/db/dockerInitTemplates.ts (3)
  • initTemplates (119-152)
  • userTables (97-106)
  • countHistoryTables (108-117)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
🔇 Additional comments (1)
src/generators/db/dockerInitTemplates.ts (1)

136-139: LGTM: MongoDB initialization configuration is correct.

The mongosh CLI commands and wait logic are properly configured. Authentication credentials ('user'/'password') match those used in the MongoDB template scripts (lines 26, 29), ensuring consistency across the initialization flow.

Comment thread scripts/functional-tests/postgresql-validator.ts
Comment thread src/generators/db/dockerInitTemplates.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
scripts/functional-tests/postgresql-validator.ts (2)

206-234: Consider simplifying the promise pattern for clarity.

The sequential promise chaining using forEach and promise reassignment works correctly but is harder to follow than a standard for-of loop with await. This pattern is functionally correct but less idiomatic.

Consider this refactor for improved readability:

 const runPostgresSeedScripts = async (
   seeds: readonly string[],
   executeSeed: (seed: string) => Promise<CommandResult>,
   errors: string[]
 ) => {
-  let resultPromise = Promise.resolve(true);
-
-  seeds.forEach((seed) => {
-    resultPromise = resultPromise.then(async (previousSucceeded) => {
-      if (!previousSucceeded) {
-        return false;
-      }
-
-      const seedResult = await executeSeed(seed);
-
-      if (seedResult.exitCode !== 0) {
-        errors.push(
-          `Failed to initialise PostgreSQL schema: ${seedResult.stderr.slice(0, DOCKER_ERROR_SNIPPET_LENGTH) || 'Unknown error'}`
-        );
-
-        return false;
-      }
-
-      return true;
-    });
-  });
-
-  return resultPromise;
+  for (const seed of seeds) {
+    const seedResult = await executeSeed(seed);
+
+    if (seedResult.exitCode !== 0) {
+      errors.push(
+        `Failed to initialise PostgreSQL schema: ${seedResult.stderr.slice(0, DOCKER_ERROR_SNIPPET_LENGTH) || 'Unknown error'}`
+      );
+      return false;
+    }
+  }
+
+  return true;
 };

236-242: Consider removing the unused parameter.

The _authProvider parameter is prefixed with an underscore to indicate it's intentionally unused, which is correct since both tables are now seeded unconditionally (line 255). However, removing the parameter entirely would further simplify the function signature.

Apply this diff:

 const startDockerContainer = async (
   composePath: string,
-  _authProvider: string | undefined,
   warnings: string[],
   postgresqlSpecific: PostgreSQLValidationResult['postgresqlSpecific'],
   errors: string[]
 ) => {

And update the call site at line 339:

   if (
     !usingExistingContainer &&
-    !(await startDockerContainer(sharedComposePath, authProvider, warnings, postgresqlSpecific, errors))
+    !(await startDockerContainer(sharedComposePath, warnings, postgresqlSpecific, errors))
   ) {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4348df6 and fd17082.

📒 Files selected for processing (3)
  • scripts/functional-tests/postgresql-validator.ts (1 hunks)
  • src/generators/db/dockerInitTemplates.ts (4 hunks)
  • src/generators/db/scaffoldDocker.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/generators/db/scaffoldDocker.ts (3)
src/generators/db/generateDockerContainer.ts (1)
  • generateDockerContainer (84-114)
src/generators/db/dockerInitTemplates.ts (3)
  • initTemplates (119-152)
  • userTables (97-106)
  • countHistoryTables (108-117)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
scripts/functional-tests/postgresql-validator.ts (1)
src/generators/db/dockerInitTemplates.ts (3)
  • initTemplates (119-152)
  • userTables (97-106)
  • countHistoryTables (108-117)
🔇 Additional comments (7)
src/generators/db/dockerInitTemplates.ts (3)

25-29: MongoDB templates look correct; verify handler alignment with singleton pattern.

The templates correctly use $setOnInsert (escaping issue from past review resolved) and include the uid field in count_history (schema mismatch resolved). The escaping will work correctly: line 57 of scaffoldDocker.ts escapes $ to \$, which bash interprets as literal $ for mongosh.

However, the mongodbCountHistory template creates a singleton document with uid: 1 using an if-check + insertOne pattern, while SQL variants use AUTO_INCREMENT to create multiple records. Past review comments indicated this was addressed in commit 4348df6, but please verify that the current handler logic matches this singleton pattern (e.g., using updateOne({uid: 1}) rather than insertOne() for new history entries).


103-103: LGTM!

MongoDB entries correctly added to userTables and countHistoryTables exports, consistent with other database engines.

Also applies to: 114-114


136-139: LGTM!

MongoDB initTemplates entry correctly configured with mongosh CLI and readiness wait command using db.runCommand({ ping: 1 }).

src/generators/db/scaffoldDocker.ts (3)

2-2: Verify MongoDB exclusion from shared container logic.

The useSharedContainer logic enables test efficiency for PostgreSQL, MySQL, and MariaDB by skipping initialization when ABSOLUTE_TEST=true. However, MongoDB is excluded from this optimization.

Is this intentional? The PR objectives mention "MongoDB: sandbox failures due to missing users/count_history collections," which may explain why shared containers aren't enabled for MongoDB yet. If this is temporary while MongoDB issues are resolved, consider adding a TODO comment. If intentional for other reasons, the current implementation is fine.

Also applies to: 38-50


57-57: LGTM!

The escaping logic correctly handles MongoDB operators like $setOnInsert. When passed through bash double quotes in the command template (lines 60-61), \$ is interpreted as literal $, allowing mongosh to receive the correct operator syntax.


52-62: LGTM!

The Docker initialization flow correctly:

  1. Selects the appropriate table template based on auth configuration
  2. Escapes special characters for shell execution
  3. Ensures database readiness with the wait command before executing initialization
  4. Properly uses Bun template literal interpolation
scripts/functional-tests/postgresql-validator.ts (1)

1-492: Excellent implementation with robust error handling and proper resource cleanup.

The validator successfully addresses all previously flagged issues:

  • ✅ No early returns that skip structural validation when Docker is unavailable
  • ✅ Proper SQL command escaping via separate -c arguments
  • ✅ Docker unavailability warnings don't falsely mark tests as passed
  • ✅ Both users and count_history tables are seeded to support container reuse across different auth configurations (line 255)
  • ✅ Docker Compose cache is refreshed on every run to catch template regressions (lines 182-183)

The implementation demonstrates solid engineering practices:

  • Robust timeout handling with graceful SIGTERM followed by SIGKILL
  • Proper process lifecycle management with cleanup on failures
  • Structured error collection with bounded log snippets to prevent spam
  • Clear separation between local Docker validation and Neon remote flows
  • Comprehensive validation of schema files, handler files, and Docker artifacts

The Neon handling (lines 473-477) correctly bypasses connection tests with warnings, which aligns with the PR objectives stating that credentials aren't available in CI.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 18

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/generators/project/generateDBBlock.ts (1)

41-45: Fix Neon remote Drizzle initializer to use neon()

Drizzle remote hosts route through remoteDrizzleInit, so for databaseHost: "neon" we still emit const pool = new Pool(...). After the connection-map change, the import generator now pulls in neon instead of Pool, leaving the scaffolded project referencing an undefined Pool and blowing up the first time it runs. Please update the Neon entry here to use the same neon(getEnv("DATABASE_URL")) initializer so the emitted code matches the imports.

Apply this diff:

-	neon: 'new Pool({ connectionString: getEnv("DATABASE_URL") })',
+	neon: 'neon(getEnv("DATABASE_URL"))',
♻️ Duplicate comments (1)
src/generators/db/handlerTemplates.ts (1)

43-54: Same TypeScript typing issue as getUser.

The subject derivation logic here has the same incomplete type cast. See the fix proposed for getUser above.

🧹 Nitpick comments (10)
test-cli-project/src/frontend/styles/colors.ts (1)

1-11: LGTM! Color constants are well-defined and consistent.

The color palette is valid and the primary colors correctly match those used in the generated CSS (seen in generateMarkupCSS.ts). The naming convention is clear and consistent.

For improved type safety, consider adding as const assertions to enable literal type inference:

-export const primaryColor = '#5FBEEB';
-export const secondaryColor = '#35d5a2';
-export const tertiaryColor = '#ff4b91';
+export const primaryColor = '#5FBEEB' as const;
+export const secondaryColor = '#35d5a2' as const;
+export const tertiaryColor = '#ff4b91' as const;

-export const lightPrimaryColor = '#ffffff';
-export const lightSecondaryColor = '#f5f5f5';
-export const lightTertiaryColor = '#e0e0e0';
+export const lightPrimaryColor = '#ffffff' as const;
+export const lightSecondaryColor = '#f5f5f5' as const;
+export const lightTertiaryColor = '#e0e0e0' as const;

-export const darkPrimaryColor = '#1a1a1a';
-export const darkSecondaryColor = '#2c2c2c';
-export const darkTertiaryColor = '#3c3c3c';
+export const darkPrimaryColor = '#1a1a1a' as const;
+export const darkSecondaryColor = '#2c2c2c' as const;
+export const darkTertiaryColor = '#3c3c3c' as const;

Alternatively, for better organization, you could structure these as a theme object:

export const theme = {
  colors: {
    primary: '#5FBEEB',
    secondary: '#35d5a2',
    tertiary: '#ff4b91',
  },
  light: {
    primary: '#ffffff',
    secondary: '#f5f5f5',
    tertiary: '#e0e0e0',
  },
  dark: {
    primary: '#1a1a1a',
    secondary: '#2c2c2c',
    tertiary: '#3c3c3c',
  },
} as const;
src/generators/db/generateDockerContainer.ts (1)

30-30: Consider non-standard host ports for other database engines.

For consistency and to avoid conflicts with local installations, consider mapping other database engines to non-standard host ports as well. Currently, MariaDB, MySQL, and SingleStore all use the standard port 3306:3306, which could conflict with local installations or with each other if multiple services are run simultaneously.

Example approach:

  • MariaDB: 3307:3306
  • MySQL: 3308:3306
  • SingleStore: 3309:3306

Also applies to: 61-61, 79-79

docs/test-cli-migration-phase0.md (1)

46-46: Track acknowledged cleanup debt.

Line 46 notes that "Several suites still list behavioural tests even though the corresponding tests/behavioural/*.test.ts files were deleted earlier" and calls for "cleanup in later phases." This is a known inconsistency worth tracking as a follow-up issue.

Would you like me to open a follow-up issue to track this cleanup task, or is it already captured in your tracking system?

tests/behavioural/cloud-matrix.test.ts (1)

43-71: Consider validating that environment variables are non-empty strings.

The current check at line 47 (!process.env[source]) correctly filters out undefined values, but an environment variable set to an empty string would pass this check and potentially cause connection failures later in the test flow. While the current behavior may be acceptable, explicitly checking for non-empty strings would provide clearer, earlier error messages.

If you'd like to add this validation, apply this diff:

 const resolveScenario = (
   definition: CloudScenarioDefinition
 ): BehaviouralScenario | null => {
   const missing = definition.requiredEnv.filter(
-    ({ source }) => !process.env[source]
+    ({ source }) => !process.env[source] || process.env[source]?.trim() === ''
   );
tests/behavioural/auth-matrix.test.ts (1)

8-28: Consider expanding AUTH_SCENARIOS for comprehensive coverage.

The current matrix only covers React + SQLite (with and without Drizzle). Based on the PR objectives mentioning Vue/Svelte/HTML/HTMX frameworks and PostgreSQL/MySQL/MongoDB databases, consider whether additional scenarios should be included here or if this is intentionally a focused subset for smoke testing.

test-cli-project/src/backend/server.ts (2)

27-36: Remove duplicate route definition.

The '/' and '/react' routes have identical implementations. Consider removing one or extracting the handler to a shared function if both routes are intentionally needed.

+const renderReactExample = () => handleReactPageRequest(
+  ReactExample,
+  asset(manifest, 'ReactExampleIndex'),
+  { initialCount: 0, cssPath: asset(manifest, 'ReactExampleCSS') }
+);
+
 .use(networking)
 .use(staticPlugin({"assets":"./build","prefix":""}))
-  .get('/', () => handleReactPageRequest(
-        ReactExample,
-        asset(manifest, 'ReactExampleIndex'),
-        { initialCount: 0, cssPath: asset(manifest, 'ReactExampleCSS') }
-      ))
-  .get('/react', () => handleReactPageRequest(
-        ReactExample,
-        asset(manifest, 'ReactExampleIndex'),
-        { initialCount: 0, cssPath: asset(manifest, 'ReactExampleCSS') }
-      ))
+  .get('/', renderReactExample)
+  .get('/react', renderReactExample)

15-22: Add connection error handling for PostgreSQL pool.

The Pool is created without error handling. If the connection string is invalid or the database is unavailable, the error will only surface when queries are attempted, making debugging harder.

 const connectionString = getEnv("DATABASE_URL")
 if (process.env.ABSOLUTE_TEST_VERBOSE === '1') {
   console.log('Server runtime env: DATABASE_URL=' + connectionString)
   console.log('Server runtime env: PGHOST=' + (process.env.PGHOST ?? 'undefined'))
   console.log('Server runtime env: PGPORT=' + (process.env.PGPORT ?? 'undefined'))
 }
-const pool = new Pool({ connectionString })
+
+const pool = new Pool({ connectionString })
+
+pool.on('error', (err) => {
+  console.error('Unexpected PostgreSQL pool error:', err)
+})
+
 const db = createPgSql(pool)
scripts/functional-tests/cloud-provider-validator.ts (1)

108-124: Validate CLI arguments to prevent runtime errors.

The parseCliArguments function destructures 8 positional arguments without validation and casts packageManager without checking. Invalid inputs could cause runtime failures.

 const parseCliArguments = (argv: string[]) => {
   const [, , projectPath, packageManager, databaseEngine, databaseHost, orm, authProvider] = argv;
+
+  const validPackageManagers = ['bun', 'npm', 'pnpm', 'yarn'];
+  const pm = packageManager ?? DEFAULT_PACKAGE_MANAGER;
+  
+  if (!validPackageManagers.includes(pm)) {
+    throw new Error(`Invalid package manager: ${pm}. Expected: ${validPackageManagers.join(', ')}`);
+  }

   return {
     authProvider: authProvider ?? 'none',
     databaseEngine: databaseEngine ?? 'none',
     databaseHost: databaseHost ?? 'none',
     options: {
       skipBuild: argv.includes('--skip-build'),
       skipDependencies: argv.includes('--skip-deps'),
       skipServer: argv.includes('--skip-server')
     },
     orm: orm ?? 'none',
-    packageManager: (packageManager as 'bun' | 'npm' | 'pnpm' | 'yarn') ?? DEFAULT_PACKAGE_MANAGER,
+    packageManager: pm as 'bun' | 'npm' | 'pnpm' | 'yarn',
     projectPath
   };
 };
tests/functional/frameworks/svelte.test.ts (1)

10-15: Make project slug host/tool aware to avoid collisions.

Multiple matrix entries differ only by databaseHost or codeQualityTool, so the current slug reuses the same directory, which risks cross-scenario residue if cleanup ever skips or tests run in parallel. Folding those fields into the slug keeps each scenario isolated.

-const createProjectName = (config: SvelteMatrixEntry) =>
-  `test-svelte-${config.databaseEngine}-${config.orm}-${config.authProvider === 'none' ? 'noauth' : 'auth'}-${
-    config.useTailwind ? 'tw' : 'notw'
-  }`
-    .replace(/[^a-z0-9-]/g, '-')
-    .toLowerCase();
+const createProjectName = (config: SvelteMatrixEntry) =>
+  [
+    'test-svelte',
+    config.databaseEngine,
+    config.databaseHost,
+    config.orm,
+    config.authProvider === 'none' ? 'noauth' : 'auth',
+    config.useTailwind ? 'tw' : 'notw',
+    config.codeQualityTool ?? null
+  ]
+    .filter(Boolean)
+    .join('-')
+    .replace(/[^a-z0-9-]/g, '-')
+    .toLowerCase();
tests/functional/frameworks/html.test.ts (1)

10-15: Mirror the slug fix for HTML scenarios.

HTML matrix entries also differ by host/code-quality, so keeping those in the slug prevents different runs from sharing the same project directory.

-const createProjectName = (config: HtmlMatrixEntry) =>
-  `test-html-${config.databaseEngine}-${config.orm}-${config.authProvider === 'none' ? 'noauth' : 'auth'}-${
-    config.useTailwind ? 'tw' : 'notw'
-  }`
-    .replace(/[^a-z0-9-]/g, '-')
-    .toLowerCase();
+const createProjectName = (config: HtmlMatrixEntry) =>
+  [
+    'test-html',
+    config.databaseEngine,
+    config.databaseHost,
+    config.orm,
+    config.authProvider === 'none' ? 'noauth' : 'auth',
+    config.useTailwind ? 'tw' : 'notw',
+    config.codeQualityTool ?? null
+  ]
+    .filter(Boolean)
+    .join('-')
+    .replace(/[^a-z0-9-]/g, '-')
+    .toLowerCase();
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd17082 and 55227a0.

⛔ Files ignored due to path filters (4)
  • bun.lock is excluded by !**/*.lock
  • test-cli-project/src/backend/assets/ico/favicon.ico is excluded by !**/*.ico
  • test-cli-project/src/backend/assets/png/absolutejs-temp.png is excluded by !**/*.png
  • test-cli-project/src/backend/assets/svg/react.svg is excluded by !**/*.svg
📒 Files selected for processing (82)
  • README.md (0 hunks)
  • docs/test-cli-migration-phase0.md (1 hunks)
  • docs/test-cli-migration-phase1.md (1 hunks)
  • docs/test-cli-ux.md (1 hunks)
  • eslint.config.mjs (1 hunks)
  • package.json (1 hunks)
  • scripts/functional-tests/auth-validator.ts (1 hunks)
  • scripts/functional-tests/build-validator.ts (1 hunks)
  • scripts/functional-tests/cloud-provider-validator.ts (1 hunks)
  • scripts/functional-tests/dependency-cache.ts (1 hunks)
  • scripts/functional-tests/dependency-installer-tester.ts (1 hunks)
  • scripts/functional-tests/htmx-validator.ts (1 hunks)
  • scripts/functional-tests/mongodb-validator.ts (1 hunks)
  • scripts/functional-tests/mysql-validator.ts (1 hunks)
  • scripts/functional-tests/postgresql-validator.ts (1 hunks)
  • scripts/functional-tests/react-validator.ts (1 hunks)
  • scripts/functional-tests/server-startup-validator.ts (1 hunks)
  • scripts/functional-tests/sqlite-validator.ts (1 hunks)
  • scripts/functional-tests/svelte-validator.ts (1 hunks)
  • scripts/functional-tests/test-cli-registry.ts (1 hunks)
  • scripts/functional-tests/test-cli.ts (1 hunks)
  • scripts/functional-tests/vue-validator.ts (1 hunks)
  • src/generators/configurations/generateEnv.ts (1 hunks)
  • src/generators/db/dockerInitTemplates.ts (4 hunks)
  • src/generators/db/generateDockerContainer.ts (2 hunks)
  • src/generators/db/handlerTemplates.ts (7 hunks)
  • src/generators/project/generateDBBlock.ts (3 hunks)
  • test-cli-project/.prettierignore (1 hunks)
  • test-cli-project/.prettierrc.json (1 hunks)
  • test-cli-project/README.md (1 hunks)
  • test-cli-project/db/docker-compose.db.yml (1 hunks)
  • test-cli-project/eslint.config.mjs (1 hunks)
  • test-cli-project/package.json (1 hunks)
  • test-cli-project/src/backend/database/createPgSql.ts (1 hunks)
  • test-cli-project/src/backend/handlers/countHistoryHandlers.ts (1 hunks)
  • test-cli-project/src/backend/server.ts (1 hunks)
  • test-cli-project/src/constants.ts (1 hunks)
  • test-cli-project/src/frontend/components/App.tsx (1 hunks)
  • test-cli-project/src/frontend/components/Dropdown.tsx (1 hunks)
  • test-cli-project/src/frontend/components/Head.tsx (1 hunks)
  • test-cli-project/src/frontend/pages/ReactExample.tsx (1 hunks)
  • test-cli-project/src/frontend/styles/colors.ts (1 hunks)
  • test-cli-project/src/frontend/styles/react-example.css (1 hunks)
  • test-cli-project/src/frontend/styles/reset.css (1 hunks)
  • test-cli-project/tsconfig.json (1 hunks)
  • tests/behavioural/auth-matrix.test.ts (1 hunks)
  • tests/behavioural/cloud-matrix.test.ts (1 hunks)
  • tests/behavioural/database-hooks.ts (1 hunks)
  • tests/behavioural/database-matrix-definitions.ts (1 hunks)
  • tests/behavioural/database-matrix.test.ts (1 hunks)
  • tests/behavioural/database-matrix.ts (1 hunks)
  • tests/behavioural/utils.ts (1 hunks)
  • tests/functional/auth.test.ts (1 hunks)
  • tests/functional/cloud.test.ts (1 hunks)
  • tests/functional/databases/mongodb.test.ts (1 hunks)
  • tests/functional/databases/mysql.test.ts (1 hunks)
  • tests/functional/databases/postgresql.test.ts (1 hunks)
  • tests/functional/databases/sqlite.test.ts (1 hunks)
  • tests/functional/frameworks/html.test.ts (1 hunks)
  • tests/functional/frameworks/htmx.test.ts (1 hunks)
  • tests/functional/frameworks/react.test.ts (1 hunks)
  • tests/functional/frameworks/svelte.test.ts (1 hunks)
  • tests/functional/frameworks/test-utils.ts (1 hunks)
  • tests/functional/frameworks/vue.test.ts (1 hunks)
  • tests/functional/support/assertions.ts (1 hunks)
  • tests/functional/support/docker.ts (1 hunks)
  • tests/functional/support/filesystem.ts (1 hunks)
  • tests/functional/support/http.ts (1 hunks)
  • tests/functional/support/index.ts (1 hunks)
  • tests/functional/support/install.ts (1 hunks)
  • tests/functional/support/scaffold.ts (1 hunks)
  • tests/functional/support/timing.ts (1 hunks)
  • tests/functional/support/types.ts (1 hunks)
  • tests/harness/cli.ts (1 hunks)
  • tests/harness/harness.test.ts (1 hunks)
  • tests/harness/http.ts (1 hunks)
  • tests/harness/index.ts (1 hunks)
  • tests/harness/process.ts (1 hunks)
  • tests/harness/project.ts (1 hunks)
  • tests/harness/server.ts (1 hunks)
  • tests/harness/types.ts (1 hunks)
  • tsconfig.json (1 hunks)
💤 Files with no reviewable changes (1)
  • README.md
✅ Files skipped from review due to trivial changes (5)
  • docs/test-cli-migration-phase1.md
  • test-cli-project/src/frontend/styles/reset.css
  • test-cli-project/README.md
  • test-cli-project/.prettierrc.json
  • test-cli-project/.prettierignore
🚧 Files skipped from review as they are similar to previous changes (5)
  • tsconfig.json
  • scripts/functional-tests/sqlite-validator.ts
  • package.json
  • scripts/functional-tests/react-validator.ts
  • src/generators/db/dockerInitTemplates.ts
🧰 Additional context used
🧬 Code graph analysis (56)
test-cli-project/src/frontend/pages/ReactExample.tsx (3)
test-cli-project/src/frontend/components/Head.tsx (1)
  • Head (9-34)
test-cli-project/src/frontend/components/Dropdown.tsx (1)
  • Dropdown (3-18)
test-cli-project/src/frontend/components/App.tsx (1)
  • App (5-52)
test-cli-project/src/frontend/components/Head.tsx (2)
src/templates/react/components/Head.tsx (1)
  • HeadProps (9-34)
src/templates/react/pages/ReactExample.tsx (1)
  • ReactExampleProps (7-18)
test-cli-project/src/frontend/styles/react-example.css (4)
src/generators/project/generateMarkupCSS.ts (1)
  • frontend (3-157)
src/templates/react/pages/ReactExample.tsx (1)
  • ReactExampleProps (7-18)
src/templates/react/components/Head.tsx (1)
  • HeadProps (9-34)
src/generators/react/generateReactPage.ts (1)
  • frontends (4-26)
test-cli-project/db/docker-compose.db.yml (1)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
tests/functional/frameworks/vue.test.ts (3)
scripts/functional-tests/matrix.ts (1)
  • MatrixConfig (33-42)
tests/functional/frameworks/test-utils.ts (1)
  • runFrameworkMatrix (77-165)
scripts/functional-tests/vue-validator.ts (1)
  • validateVueFramework (61-87)
tests/functional/support/scaffold.ts (4)
tests/functional/support/timing.ts (2)
  • minutesToMilliseconds (22-22)
  • MILLISECONDS_PER_SECOND (1-1)
tests/functional/support/types.ts (3)
  • StepResult (1-6)
  • createFailure (8-13)
  • createSuccess (15-23)
tests/harness/project.ts (2)
  • scaffoldProject (26-58)
  • cleanupProject (139-143)
tests/functional/support/filesystem.ts (1)
  • removeDirectoryIfExists (3-14)
scripts/functional-tests/cloud-provider-validator.ts (2)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (24-34)
  • runFunctionalTests (116-170)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (58-155)
test-cli-project/package.json (3)
src/generators/configurations/generatePackageJson.ts (2)
  • CreatePackageJsonProps (31-226)
  • dep (79-84)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
scripts/functional-tests/postgresql-validator.ts (2)
tests/harness/process.ts (1)
  • runCommand (14-66)
src/generators/db/dockerInitTemplates.ts (3)
  • initTemplates (119-152)
  • userTables (97-106)
  • countHistoryTables (108-117)
tests/functional/frameworks/htmx.test.ts (2)
scripts/functional-tests/matrix.ts (1)
  • MatrixConfig (33-42)
tests/functional/frameworks/test-utils.ts (1)
  • runFrameworkMatrix (77-165)
test-cli-project/src/frontend/components/Dropdown.tsx (3)
src/generators/react/generateReactPage.ts (1)
  • frontends (4-26)
src/templates/react/pages/ReactExample.tsx (1)
  • ReactExampleProps (7-18)
src/generators/react/scaffoldReact.ts (1)
  • ScaffoldFrontendProps (7-35)
tests/functional/databases/sqlite.test.ts (4)
scripts/functional-tests/matrix.ts (1)
  • MatrixConfig (33-42)
scripts/functional-tests/functional-test-runner.ts (1)
  • runFunctionalTests (116-170)
tests/functional/frameworks/test-utils.ts (1)
  • runMatrixSuite (167-167)
scripts/functional-tests/sqlite-validator.ts (1)
  • validateSQLiteDatabase (148-183)
tests/harness/server.ts (2)
tests/harness/types.ts (2)
  • StartServerOptions (54-61)
  • RunningServer (63-66)
tests/harness/http.ts (1)
  • waitForHttpOk (6-32)
tests/functional/frameworks/react.test.ts (3)
scripts/functional-tests/matrix.ts (1)
  • MatrixConfig (33-42)
tests/functional/frameworks/test-utils.ts (1)
  • runFrameworkMatrix (77-165)
scripts/functional-tests/react-validator.ts (1)
  • validateReactFramework (62-88)
tests/functional/frameworks/html.test.ts (2)
scripts/functional-tests/matrix.ts (1)
  • MatrixConfig (33-42)
tests/functional/frameworks/test-utils.ts (1)
  • runFrameworkMatrix (77-165)
tests/behavioural/database-matrix.ts (2)
tests/harness/types.ts (3)
  • Frontend (1-7)
  • Orm (15-15)
  • DatabaseEngine (9-9)
tests/behavioural/utils.ts (3)
  • BehaviouralScenario (13-16)
  • ScenarioHooks (18-27)
  • runCountHistoryScenario (257-484)
test-cli-project/src/frontend/styles/colors.ts (1)
src/generators/project/generateMarkupCSS.ts (1)
  • frontend (3-157)
tests/functional/cloud.test.ts (3)
scripts/functional-tests/matrix.ts (1)
  • MatrixConfig (33-42)
tests/functional/frameworks/test-utils.ts (1)
  • runMatrixSuite (167-167)
scripts/functional-tests/cloud-provider-validator.ts (1)
  • validateCloudProvider (62-99)
test-cli-project/src/frontend/components/App.tsx (3)
src/templates/react/components/App.tsx (2)
  • AppProps (5-52)
  • setCount (27-27)
src/templates/react/pages/ReactExample.tsx (1)
  • ReactExampleProps (7-18)
src/templates/react/components/Head.tsx (1)
  • HeadProps (9-34)
tests/behavioural/auth-matrix.test.ts (1)
tests/behavioural/utils.ts (2)
  • BehaviouralScenario (13-16)
  • runAuthScenario (496-593)
test-cli-project/src/backend/server.ts (3)
test-cli-project/src/backend/database/createPgSql.ts (1)
  • createPgSql (70-92)
test-cli-project/src/frontend/pages/ReactExample.tsx (1)
  • ReactExample (7-18)
test-cli-project/src/backend/handlers/countHistoryHandlers.ts (2)
  • getCountHistory (4-11)
  • createCountHistory (13-20)
tests/harness/project.ts (4)
tests/harness/types.ts (2)
  • ScaffoldOptions (21-33)
  • ScaffoldResult (35-38)
tests/harness/cli.ts (1)
  • buildScaffoldArguments (11-59)
tests/harness/process.ts (1)
  • runCommand (14-66)
scripts/functional-tests/dependency-cache.ts (4)
  • DependencyFingerprint (23-31)
  • computeManifestHash (80-106)
  • hasCachedDependencies (225-249)
  • getOrInstallDependencies (251-282)
scripts/functional-tests/auth-validator.ts (1)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (24-34)
  • runFunctionalTests (116-170)
tests/behavioural/cloud-matrix.test.ts (1)
tests/behavioural/utils.ts (2)
  • BehaviouralScenario (13-16)
  • runCountHistoryScenario (257-484)
tests/harness/cli.ts (2)
tests/harness/types.ts (1)
  • ScaffoldOptions (21-33)
src/utils/parseCommandLineOptions.ts (1)
  • parseArgs (32-332)
tests/functional/auth.test.ts (3)
scripts/functional-tests/matrix.ts (1)
  • MatrixConfig (33-42)
tests/functional/frameworks/test-utils.ts (1)
  • runMatrixSuite (167-167)
scripts/functional-tests/auth-validator.ts (1)
  • validateAuthConfiguration (61-95)
tests/functional/frameworks/test-utils.ts (6)
scripts/functional-tests/matrix.ts (1)
  • MatrixConfig (33-42)
tests/functional/support/scaffold.ts (3)
  • ScaffoldOptions (18-33)
  • scaffoldProject (99-211)
  • cleanupProject (213-215)
scripts/functional-tests/dependency-cache.ts (1)
  • DependencyFingerprint (23-31)
tests/functional/support/timing.ts (1)
  • minutesToMilliseconds (22-22)
tests/functional/support/assertions.ts (1)
  • assertStepSuccess (3-15)
tests/functional/support/install.ts (1)
  • installDependencies (25-62)
src/generators/db/handlerTemplates.ts (1)
src/generators/db/generateSqliteSchema.ts (1)
  • authProvider (3-14)
tests/functional/support/assertions.ts (1)
tests/functional/support/types.ts (1)
  • StepResult (1-6)
tests/functional/support/docker.ts (3)
tests/functional/support/timing.ts (2)
  • minutesToMilliseconds (22-22)
  • MILLISECONDS_PER_SECOND (1-1)
tests/functional/support/types.ts (2)
  • createFailure (8-13)
  • createSuccess (15-23)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
scripts/functional-tests/dependency-cache.ts (2)
tests/functional/support/install.ts (1)
  • installDependencies (25-62)
tests/harness/project.ts (1)
  • installDependencies (62-137)
src/generators/configurations/generateEnv.ts (1)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
tests/functional/databases/mongodb.test.ts (5)
scripts/functional-tests/matrix.ts (1)
  • MatrixConfig (33-42)
scripts/functional-tests/functional-test-runner.ts (1)
  • runFunctionalTests (116-170)
tests/functional/frameworks/test-utils.ts (1)
  • runMatrixSuite (167-167)
tests/functional/support/docker.ts (1)
  • ensureDockerAvailable (79-100)
scripts/functional-tests/mongodb-validator.ts (1)
  • validateMongoDBDatabase (255-307)
eslint.config.mjs (1)
src/generators/configurations/scaffoldConfigurationFiles.ts (1)
  • AddConfigurationProps (22-77)
scripts/functional-tests/mongodb-validator.ts (4)
tests/functional/support/timing.ts (2)
  • MILLISECONDS_PER_SECOND (1-1)
  • SECONDS_PER_MINUTE (2-2)
tests/harness/process.ts (1)
  • runCommand (14-66)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
tests/harness/process.ts (2)
tests/functional/support/timing.ts (2)
  • MILLISECONDS_PER_SECOND (1-1)
  • SECONDS_PER_MINUTE (2-2)
tests/harness/types.ts (2)
  • RunCommandOptions (40-45)
  • RunCommandResult (47-52)
scripts/functional-tests/mysql-validator.ts (5)
tests/functional/support/timing.ts (2)
  • MILLISECONDS_PER_SECOND (1-1)
  • SECONDS_PER_MINUTE (2-2)
tests/harness/process.ts (1)
  • runCommand (14-66)
tests/functional/support/assertions.ts (1)
  • logWarnings (17-19)
src/generators/db/scaffoldDatabase.ts (1)
  • ScaffoldDatabaseProps (27-107)
src/generators/db/scaffoldDocker.ts (1)
  • ScaffoldDockerProps (20-56)
tests/functional/databases/postgresql.test.ts (5)
scripts/functional-tests/matrix.ts (1)
  • MatrixConfig (33-42)
scripts/functional-tests/functional-test-runner.ts (1)
  • runFunctionalTests (116-170)
tests/functional/frameworks/test-utils.ts (1)
  • runMatrixSuite (167-167)
tests/functional/support/docker.ts (1)
  • ensureDockerAvailable (79-100)
scripts/functional-tests/postgresql-validator.ts (1)
  • validatePostgreSQLDatabase (388-433)
tests/harness/harness.test.ts (4)
tests/harness/project.ts (3)
  • scaffoldProject (26-58)
  • installDependencies (62-137)
  • cleanupProject (139-143)
tests/harness/server.ts (1)
  • startServer (14-156)
tests/harness/process.ts (1)
  • runCommand (14-66)
tests/harness/cli.ts (1)
  • buildScaffoldArguments (11-59)
test-cli-project/eslint.config.mjs (2)
src/generators/configurations/scaffoldConfigurationFiles.ts (1)
  • AddConfigurationProps (22-77)
src/generators/configurations/generatePackageJson.ts (1)
  • CreatePackageJsonProps (31-226)
tests/functional/support/install.ts (3)
scripts/functional-tests/dependency-cache.ts (4)
  • DependencyFingerprint (23-31)
  • getOrInstallDependencies (251-282)
  • hasCachedDependencies (225-249)
  • computeManifestHash (80-106)
tests/functional/support/types.ts (3)
  • StepResult (1-6)
  • createSuccess (15-23)
  • createFailure (8-13)
tests/harness/project.ts (1)
  • installDependencies (62-137)
tests/behavioural/utils.ts (4)
tests/harness/project.ts (3)
  • scaffoldProject (26-58)
  • installDependencies (62-137)
  • cleanupProject (139-143)
tests/harness/process.ts (1)
  • runCommand (14-66)
tests/harness/types.ts (1)
  • RunningServer (63-66)
tests/harness/server.ts (1)
  • startServer (14-156)
test-cli-project/src/backend/handlers/countHistoryHandlers.ts (2)
test-cli-project/src/backend/database/createPgSql.ts (1)
  • PgSql (68-68)
src/generators/db/generateSqliteSchema.ts (1)
  • authProvider (3-14)
tests/behavioural/database-matrix.test.ts (2)
tests/behavioural/database-matrix-definitions.ts (1)
  • DATABASE_MATRIX_DEFINITIONS (17-79)
tests/behavioural/database-matrix.ts (1)
  • describeDatabaseMatrix (75-98)
tests/functional/databases/mysql.test.ts (5)
scripts/functional-tests/matrix.ts (1)
  • MatrixConfig (33-42)
scripts/functional-tests/functional-test-runner.ts (1)
  • runFunctionalTests (116-170)
tests/functional/frameworks/test-utils.ts (1)
  • runMatrixSuite (167-167)
tests/functional/support/docker.ts (1)
  • ensureDockerAvailable (79-100)
scripts/functional-tests/mysql-validator.ts (1)
  • validateMySQLDatabase (270-325)
scripts/functional-tests/dependency-installer-tester.ts (2)
src/commands/installDependencies.ts (1)
  • packageManager (8-24)
src/generators/configurations/generatePackageJson.ts (1)
  • CreatePackageJsonProps (31-226)
tests/harness/types.ts (1)
tests/functional/support/scaffold.ts (2)
  • ScaffoldOptions (18-33)
  • ScaffoldResult (35-40)
tests/behavioural/database-matrix-definitions.ts (3)
tests/behavioural/database-matrix.ts (1)
  • DatabaseMatrixDefinition (18-26)
tests/behavioural/database-hooks.ts (3)
  • createPostgresHooks (4-45)
  • createMysqlHooks (47-90)
  • createMongoHooks (92-239)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
test-cli-project/tsconfig.json (2)
src/generators/configurations/generatePackageJson.ts (1)
  • CreatePackageJsonProps (31-226)
src/generators/configurations/scaffoldConfigurationFiles.ts (1)
  • AddConfigurationProps (22-77)
tests/behavioural/database-hooks.ts (2)
tests/behavioural/utils.ts (1)
  • ScenarioHooks (18-27)
tests/harness/process.ts (1)
  • runCommand (14-66)
tests/functional/frameworks/svelte.test.ts (3)
scripts/functional-tests/matrix.ts (1)
  • MatrixConfig (33-42)
tests/functional/frameworks/test-utils.ts (1)
  • runFrameworkMatrix (77-165)
scripts/functional-tests/svelte-validator.ts (1)
  • validateSvelteFramework (61-87)
scripts/functional-tests/vue-validator.ts (1)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (24-34)
  • runFunctionalTests (116-170)
scripts/functional-tests/test-cli.ts (3)
scripts/functional-tests/test-cli-registry.ts (6)
  • SuiteDefinition (13-25)
  • SUITE_REGISTRY (29-235)
  • KNOWN_PROVIDERS (248-248)
  • SUITE_MAP (237-239)
  • KNOWN_FRAMEWORKS (246-246)
  • KNOWN_DATABASES (247-247)
scripts/functional-tests/test-utils.ts (1)
  • cleanupProjectDirectory (9-20)
scripts/functional-tests/dependency-cache.ts (1)
  • cleanupCache (284-315)
scripts/functional-tests/svelte-validator.ts (1)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (24-34)
  • runFunctionalTests (116-170)
src/generators/project/generateDBBlock.ts (1)
src/generators/configurations/generateDrizzleConfig.ts (1)
  • CreateDrizzleConfigProps (11-34)
scripts/functional-tests/htmx-validator.ts (2)
scripts/functional-tests/functional-test-runner.ts (2)
  • FunctionalTestResult (24-34)
  • runFunctionalTests (116-170)
tests/functional/support/assertions.ts (1)
  • logWarnings (17-19)
🪛 Biome (2.1.2)
test-cli-project/src/frontend/components/App.tsx

[error] 11-11: Avoid using target="_blank" without rel="noopener" or rel="noreferrer".

Opening external links in new tabs without rel="noopener" is a security risk. See the explanation for more details.
Safe fix: Add the rel="noopener" attribute.

(lint/security/noBlankTarget)

🪛 LanguageTool
docs/test-cli-ux.md

[grammar] ~6-~6: Use a hyphen to join words.
Context: ...he legacy runner: intuitive flags, human friendly progress, concise summary, pred...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.18.1)
docs/test-cli-ux.md

45-45: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (33)
test-cli-project/tsconfig.json (1)

27-29: Verify that the include pattern covers all required TypeScript files.

The current include pattern covers only src/**/*, but the AI summary and PR objectives indicate that TypeScript files from scripts/functional-tests/ and test-cli-project are expected to be compiled under this configuration (e.g., scripts/functional-tests/test-cli.ts). If this is the project-wide TypeScript configuration, the include pattern may be incomplete.

Please confirm:

  1. Is this tsconfig intended to cover only source files under src/, or should it also include test and functional-test files?
  2. If test files need compilation, add them to the include array:
   "include": [
-    "src/**/*"
+    "src/**/*",
+    "scripts/functional-tests/**/*.ts",
+    "test-cli-project/**/*.ts"
   ]

Alternatively, if separate TypeScript configurations are preferred for tests (e.g., tsconfig.test.json), confirm that arrangement and ensure the test runner uses the appropriate config.

test-cli-project/src/constants.ts (1)

1-2: These constants are unused dead code and should be removed or their purpose clarified.

Verification confirms that HOURS_IN_DAY and TWO_THIRDS are never imported or used anywhere in the codebase—they are only defined. While unused code in test projects may sometimes be intentional for validation purposes, exported constants that serve no function should be removed to keep the test project clean and focused.

src/generators/configurations/generateEnv.ts (3)

15-15: Verify the intentional password inconsistency.

MariaDB and MySQL now use userpassword while other databases retain password. This inconsistency may confuse maintainers or lead to test setup errors if not clearly documented.

If this aligns with your Docker Compose or test fixture credentials, consider adding a comment explaining the variance. Otherwise, standardize the passwords across all engines.

Also applies to: 18-18


16-16: Good addition of authSource parameter.

Including authSource=admin in the MongoDB connection string is a standard practice when authentication is enabled and aligns with common MongoDB Docker image configurations.


16-16: Verify MongoDB port configuration and normalize host values to 127.0.0.1 for consistency.

The review observations are accurate. Verification confirms:

  1. Non-standard ports confirmed: PostgreSQL port 5433 is configured in test-cli-project/db/docker-compose.db.yml (line 10: 5433:5432). MongoDB port 27018 is referenced in the code but no corresponding docker-compose port mapping was found.

  2. Host inconsistency verified: MongoDB (line 16) and PostgreSQL (line 19) use 127.0.0.1, while other database entries (lines 13–15, 17–18, 20) use localhost. This mixed approach creates maintenance inconsistency.

  3. Missing MongoDB setup: Unlike PostgreSQL, no Docker Compose or test configuration explicitly configures port 27018. Ensure this is set up in your test environment.

Action: Verify that MongoDB docker-compose maps 27018:27017 and consider normalizing all database URLs to use 127.0.0.1 for consistency.

docs/test-cli-migration-phase0.md (2)

3-3: Clarify the Phase 3 reference and tense.

Line 3 states "Phase 3 replaced the legacy…" but this is Phase 0 documentation. This creates ambiguity about whether Phase 3 is already complete or a future milestone. Please clarify the intended meaning and correct the tense if necessary.

If Phase 3 is a future phase, rephrase to "Phase 3 will replace…" or document the actual state of the transition.


40-40: Documentation is accurate; no changes needed.

The verification confirms that line 40's description is correct:

  • test-cli-registry.ts exists and exports KNOWN_FRAMEWORKS, KNOWN_DATABASES, and KNOWN_PROVIDERS
  • These constants are used directly for CLI flag validation in test-cli.ts (lines 251, 307, 323 check .has() against user input and throw errors for unknown values)
  • The parity requirement is valid: these sets must remain synchronized when testing frameworks change
docs/test-cli-ux.md (2)

68-96: Both documented behaviors are correctly implemented; no issues found.

The verification confirms:

  • Skip exit codes (line 73): Skip paths (lines 510–522, 524–539) correctly return exitCode: 0 and skipped: true. The summary displays skipped suites with symbol and reason text (lines 482–485, 511). ✓

  • ABSOLUTE_BEHAVIOURAL_MODE (line 89): The environment variable is explicitly set to '1' when chaining functional runners (line 561) and defaults to '0' for downstream processes that may not have it set (line 565). ✓

The documentation accurately reflects the implementation.


12-41: All runner files exist and environment variable checks are properly implemented.

Verification complete:

  1. ✓ All 10 runner files listed in the Suite Taxonomy table exist
  2. ✓ Environment variable checks for cloud credentials (ABSOLUTE_BEHAVIOURAL_NEON_DATABASE_URL, ABSOLUTE_BEHAVIOURAL_TURSO_DATABASE_URL) are implemented in tests/behavioural/cloud-matrix.test.ts
  3. ✓ Skip logic works correctly: missing credentials cause resolveScenario() to return null, which triggers an early return in the test (lines 68–71), effectively skipping the test with a warning message

The documentation accurately reflects the implementation. No corrections needed.

tests/functional/databases/sqlite.test.ts (2)

85-93: Fingerprint excludes directoryConfig — verify this is intentional.

The createFingerprint function omits directoryConfig, while buildScaffoldOptions includes it (line 81). Since the filter constrains all entries to directoryConfig === 'default', this field is constant and doesn't affect cache validity. However, if future changes relax the filter to allow other directory configurations, the fingerprint could produce incorrect cache hits across different directoryConfig values.

Consider explicitly documenting this design choice or including directoryConfig in the fingerprint for future-proofing:

  createFingerprint: (config) => ({
    authProvider: config.authProvider,
    codeQualityTool: config.codeQualityTool,
    databaseEngine: config.databaseEngine,
    databaseHost: config.databaseHost,
+   directoryConfig: config.directoryConfig,
    frontend: config.frontend,
    orm: config.orm,
    useTailwind: config.useTailwind
  }),

1-107: Well-structured test suite with comprehensive coverage.

The implementation follows the repository's matrix-driven validation pattern effectively:

  • Proper type constraints via SqliteMatrixEntry ensure type safety throughout the pipeline
  • Error handling in runFunctionalSuite (lines 51-55, 59-67) is defensive and provides clear diagnostics
  • The three-phase validation (functional tests → database-specific checks) aligns with the comprehensive testing approach described in the PR objectives
  • Configuration mapping correctly handles edge cases (e.g., framework: undefined when frontend === 'none')

The test structure is consistent with other database validators referenced in the PR and should reliably validate SQLite configurations across the supported matrix.

src/generators/db/handlerTemplates.ts (3)

171-188: Good use of upsert for idempotency.

The updateOne with { upsert: true } ensures that repeated calls with the same auth_sub are idempotent, and the projection correctly excludes MongoDB's internal _id.


343-362: Verify MySQL RETURNING support before production.

The manual insertId extraction (lines 348-355) with array/object fallbacks suggests the result shape is inconsistent across MySQL2 or Drizzle versions. This workaround is brittle.

Please confirm whether Drizzle ORM's .returning() is unsupported for MySQL in this configuration. If it is supported, refactor to match the simpler pattern used for PostgreSQL/SQLite:

const [newHistory] = await db
  .insert(schema.countHistory)
  .values({ count })
  .returning()

return newHistory

Otherwise, document why the fallback is necessary (e.g., "MySQL <8.0.1 / MariaDB does not support RETURNING").


420-440: LGTM! PostgreSQL configuration updates are consistent.

The import path changes for NodePgDatabase and the new PgSql type abstraction align well with the stated PR objective to introduce backend/database/createPgSql.ts. The query operations remain unchanged and correct.

tests/behavioural/cloud-matrix.test.ts (3)

1-6: LGTM!

Imports are clean and appropriate for the test infrastructure.


8-12: LGTM!

Type definition clearly expresses the structure for cloud scenario configurations with environment variable mapping.


14-41: Well-structured scenario definitions.

The consistent structure and use of as const ensures type safety and immutability for the test matrix.

eslint.config.mjs (1)

223-231: LGTM! Test-specific ESLint configuration is appropriate.

The configuration correctly:

  • Provides Node.js globals for test files
  • Disables import/no-unused-modules since test files are entry points

This aligns with the existing pattern of file-specific rule overrides in the configuration.

test-cli-project/db/docker-compose.db.yml (1)

1-15: Configuration is appropriate for test infrastructure.

The Docker Compose setup uses standard PostgreSQL 15 with hardcoded credentials (database/password/user), which is acceptable for test scenarios. Port mapping to 5433 avoids conflicts with default PostgreSQL instances running on 5432.

tests/functional/support/filesystem.ts (1)

3-14: LGTM! Robust cleanup implementation.

The function appropriately:

  • Guards against non-existent paths
  • Catches and logs errors without throwing, allowing cleanup to continue
  • Uses force: true and recursive: true for thorough removal

This is well-suited for test cleanup scenarios where failures shouldn't halt execution.

tests/functional/support/http.ts (1)

1-19: LGTM! Clean HTTP test utilities.

Both functions are well-implemented with:

  • Clear, descriptive error messages
  • Type safety through generics
  • Appropriate error handling for test scenarios

These provide useful building blocks for HTTP assertions in functional tests.

tests/functional/support/types.ts (1)

1-23: LGTM! Well-structured result types.

The StepResult type and factory functions provide:

  • Immutability through readonly fields
  • Consistent structure via factory functions
  • Sensible defaults (empty arrays for optional warnings)

This pattern ensures test results are correctly structured across the functional test suite.

scripts/functional-tests/cloud-provider-validator.ts (1)

62-99: Validation logic is sound and well-structured.

The function appropriately:

  • Validates provider against VALID_PROVIDERS with early return
  • Wraps functional tests in try/catch
  • Aggregates errors and warnings from test results
  • Computes passed based on both zero errors AND successful functional tests

This defensive approach ensures robust validation reporting.

tests/functional/databases/mysql.test.ts (1)

40-71: Preflight functional run reads well.

Running the full functional suite up front and echoing elapsed timing plus warnings keeps the MySQL matrix failures actionable without duplicating logic. Nicely structured.

tests/functional/support/scaffold.ts (1)

99-205: Timeout-aware scaffolding helper looks great.

I like how this helper removes any stale directory, streams output for postmortems, and reports timeouts with captured logs—makes diagnosing scaffold failures much easier.

tests/functional/auth.test.ts (1)

62-84: Auth matrix filtering is on point.

Restricting to the supported engines and enforcing an auth provider keeps the validator focused on the combinations we can genuinely verify right now. Looks good.

tests/harness/index.ts (1)

1-7: LGTM: Clean barrel export pattern.

The barrel file consolidates test harness utilities into a single entry point, following standard TypeScript conventions.

tests/harness/harness.test.ts (1)

12-24: LGTM: Appropriate smoke tests for harness validation.

The test suite correctly validates that the harness exports the expected helpers as functions and that buildScaffoldArguments returns an array.

tests/functional/support/index.ts (1)

1-9: LGTM: Functional support utilities consolidated.

Standard barrel export pattern for functional test support modules.

test-cli-project/src/frontend/components/App.tsx (1)

5-52: Component logic is sound.

The React component correctly manages state and renders the UI as expected.

tests/harness/cli.ts (1)

11-59: LGTM: Scaffold argument builder is well-structured.

The function correctly translates ScaffoldOptions into CLI arguments, handling default values and 'none' options appropriately. The conditional logic aligns with the CLI parser expectations.

test-cli-project/src/frontend/components/Head.tsx (1)

1-34: LGTM: Well-structured Head component.

The component provides a clean abstraction for HTML head elements with sensible defaults and optional CSS path injection.

tests/harness/http.ts (1)

6-32: LGTM: Robust HTTP polling implementation.

The recursive polling approach with async/await is safe from stack overflow, and the error handling correctly allows the server time to boot before succeeding.

Comment thread docs/test-cli-ux.md
## Goals

- Provide a single entry point (`bun run test:cli`) for every validation path (functional harness + behavioural specs).
- Preserve the stakeholder‑approved experience from the legacy runner: intuitive flags, human friendly progress, concise summary, predictable exit codes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Apply hyphen to compound adjective.

Line 6: "human friendly progress" should be "human-friendly progress" to maintain proper grammar for compound modifiers preceding a noun.

Apply this diff:

- Preserve the stakeholder‑approved experience from the legacy runner: intuitive flags, human friendly progress, concise summary, predictable exit codes.
+ Preserve the stakeholder‑approved experience from the legacy runner: intuitive flags, human-friendly progress, concise summary, predictable exit codes.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- Preserve the stakeholder‑approved experience from the legacy runner: intuitive flags, human friendly progress, concise summary, predictable exit codes.
- Preserve the stakeholder‑approved experience from the legacy runner: intuitive flags, human-friendly progress, concise summary, predictable exit codes.
🧰 Tools
🪛 LanguageTool

[grammar] ~6-~6: Use a hyphen to join words.
Context: ...he legacy runner: intuitive flags, human friendly progress, concise summary, pred...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
In docs/test-cli-ux.md around line 6, the phrase "human friendly progress"
should be corrected to the compound adjective "human-friendly progress"; update
that line to insert the hyphen so the sentence reads "...intuitive flags,
human-friendly progress, concise summary, predictable exit codes."

Comment thread docs/test-cli-ux.md
Comment on lines +45 to +47
```
bun run test:cli [options]
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Specify language for fenced code block.

The code block lacks a language identifier, which violates Markdown best practices and prevents proper syntax highlighting.

Apply this diff:

-\`\`\`
+\`\`\`bash
 bun run test:cli [options]
-\`\`\`
+\`\`\`
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

45-45: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In docs/test-cli-ux.md around lines 45 to 47, the fenced code block lacks a
language identifier; update the block opener to include a shell language (e.g.,
```bash or ```sh) so the snippet reads as a fenced code block with a language
specifier to enable proper syntax highlighting and adhere to Markdown best
practices.

Comment on lines +90 to +104
const [, , projectPath, packageManagerArg, ...flags] = process.argv;
const packageManager = (packageManagerArg as 'bun' | 'npm' | 'pnpm' | 'yarn' | undefined) ?? 'bun';

const skipDependencies = flags.includes('--skip-deps');
const skipBuild = flags.includes('--skip-build');
const skipServer = flags.includes('--skip-server');

return {
packageManager,
projectPath,
skipBuild,
skipDependencies,
skipServer
} as const;
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard the optional package-manager argument from CLI flags

Line 90 currently assumes the third CLI argument is always a package manager, so a call such as bun run scripts/functional-tests/htmx-validator.ts ./tmp --skip-deps ends up setting packageManager to "--skip-deps". We then try to spawn that string as the package manager and the validator crashes, even though the usage banner says the package manager is optional. Please treat the third argument as a package manager only when it matches the supported binaries and otherwise push it back into the flags list. Based on PR objectives

Apply this diff to fix the parsing:

-const parseCliArguments = () => {
-  const [, , projectPath, packageManagerArg, ...flags] = process.argv;
-  const packageManager = (packageManagerArg as 'bun' | 'npm' | 'pnpm' | 'yarn' | undefined) ?? 'bun';
-
-  const skipDependencies = flags.includes('--skip-deps');
-  const skipBuild = flags.includes('--skip-build');
-  const skipServer = flags.includes('--skip-server');
-
-  return {
-    packageManager,
-    projectPath,
-    skipBuild,
-    skipDependencies,
-    skipServer
-  } as const;
-};
+const parseCliArguments = () => {
+  const [, , projectPath, packageManagerCandidate, ...flagArgs] = process.argv;
+
+  const isKnownPackageManager = (
+    value: string | undefined
+  ): value is 'bun' | 'npm' | 'pnpm' | 'yarn' =>
+    value === 'bun' || value === 'npm' || value === 'pnpm' || value === 'yarn';
+
+  const flags = [...flagArgs];
+  const packageManager = isKnownPackageManager(packageManagerCandidate) ? packageManagerCandidate : 'bun';
+
+  if (!isKnownPackageManager(packageManagerCandidate) && packageManagerCandidate) {
+    flags.unshift(packageManagerCandidate);
+  }
+
+  const skipDependencies = flags.includes('--skip-deps');
+  const skipBuild = flags.includes('--skip-build');
+  const skipServer = flags.includes('--skip-server');
+
+  return {
+    packageManager,
+    projectPath,
+    skipBuild,
+    skipDependencies,
+    skipServer
+  } as const;
+};
🤖 Prompt for AI Agents
In scripts/functional-tests/htmx-validator.ts around lines 90 to 104, the CLI
parsing assumes the third argv entry is always a package manager which allows
flags (e.g. --skip-deps) to be misinterpreted as the package manager; change the
logic to first inspect the third arg and only treat it as packageManager if it
exactly matches one of the supported binaries ('bun','npm','pnpm','yarn'),
otherwise leave packageManager undefined/default to 'bun' and push the original
third arg back into the flags array (so flags includes any provided options),
then compute skipDependencies/skipBuild/skipServer from the corrected flags and
return the typed result as before.

},
image: 'mongo:7.0',
port: '27017:27017',
port: '27018:27017',
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify connection strings use the updated host ports.

The port mappings correctly avoid conflicts with local database installations by using non-standard host ports (27018 for MongoDB, 5433 for PostgreSQL). The PR objectives mention that generateEnv.ts was updated to reflect these changes.

Verify that all connection strings, environment variables, and test configurations consistently reference the new host ports:

Also applies to: 71-71


🏁 Script executed:

#!/bin/bash
# Description: Verify all MongoDB and PostgreSQL connection references use the new ports.

# Search for hardcoded port references to old ports
echo "=== Checking for hardcoded old port references ==="
rg -n '\b27017\b' --type ts --type js -g '!*.lock*' -C2
rg -n '\b5432\b' --type ts --type js -g '!*.lock*' -C2

# Search for new port references to confirm they're being used
echo "=== Confirming new port references exist ==="
rg -n '\b27018\b' --type ts --type js -g '!*.lock*' -C2
rg -n '\b5433\b' --type ts --type js -g '!*.lock*' -C2

# Check environment generation for port consistency
echo "=== Checking generateEnv.ts for port mappings ==="
fd -e ts -e js 'generateEnv' --exec cat {}

Length of output: 5919


Critical port configuration mismatches detected—update these hardcoded connection strings to use the new host ports.

The port mapping changes in generateDockerContainer.ts are correct, and most connection strings have been updated in generateEnv.ts and test configurations. However, three files still contain hardcoded references to the old ports, which will cause connection failures:

  1. src/generators/db/dockerInitTemplates.ts (lines 133-134): MongoDB CLI and wait commands reference old port 27017—update both to 27018
  2. tests/behavioural/database-hooks.ts (line 146): MongoDB connection string uses old port 27017—update to 27018
  3. src/generators/configurations/generateEnv.ts (line 14): PostgreSQL "gel" database URL uses old port 5432—update to 5433
🤖 Prompt for AI Agents
In src/generators/db/dockerInitTemplates.ts around lines 133-134,
tests/behavioural/database-hooks.ts line 146, and
src/generators/configurations/generateEnv.ts line 14, update the hardcoded DB
ports to match the new Docker mappings: change both MongoDB CLI/wait command
port references from 27017 to 27018 in dockerInitTemplates.ts, change the
MongoDB connection string port from 27017 to 27018 in
tests/behavioural/database-hooks.ts, and change the PostgreSQL "gel" database
URL port from 5432 to 5433 in generateEnv.ts; ensure only the port numbers are
adjusted and connection string syntax remains valid.

Comment on lines 30 to 41
export const getUser = async ({ authProvider, db, userIdentity }: UserHandlerProps) => {
if (!isValidProviderOption(authProvider)) throw new Error(\`Invalid auth provider: \${authProvider}\`)
const subject = providers[authProvider].extractSubjectFromIdentity(userIdentity)
const provider = providers[authProvider as keyof typeof providers]
const identity = userIdentity as Record<string, unknown>
const subject =
(provider as any).extractSubjectFromIdentity?.(identity) ??
(identity.sub as string | undefined) ??
(identity.id as string | undefined) ??
String(identity.sub || identity.id || 'unknown')
const authSub = \`\${authProvider.toUpperCase()}|\${subject}\`
${queries.selectUser}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

TypeScript typing fix is still incomplete.

The cast to Record<string, unknown> on line 33 does not resolve the TypeScript compilation error flagged in the past review. Record<string, unknown> has an index signature but no explicit sub or id properties, so accessing identity.sub or identity.id with dot notation will still fail tsc.

Use either bracket notation or an intersection type:

Option 1 (bracket notation):

  const identity = userIdentity as Record<string, unknown>
  const subject =
    (provider as any).extractSubjectFromIdentity?.(identity) ??
-   (identity.sub as string | undefined) ??
-   (identity.id as string | undefined) ??
-   String(identity.sub || identity.id || 'unknown')
+   (identity['sub'] as string | undefined) ??
+   (identity['id'] as string | undefined) ??
+   String(identity['sub'] ?? identity['id'] ?? 'unknown')

Option 2 (intersection type):

- const identity = userIdentity as Record<string, unknown>
+ const identity = userIdentity as Record<string, unknown> & { sub?: unknown; id?: unknown }
  const subject =
    (provider as any).extractSubjectFromIdentity?.(identity) ??
    (identity.sub as string | undefined) ??
    (identity.id as string | undefined) ??
-   String(identity.sub || identity.id || 'unknown')
+   String(identity.sub ?? identity.id ?? 'unknown')

Also applies to createUser on lines 43-54.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const getUser = async ({ authProvider, db, userIdentity }: UserHandlerProps) => {
if (!isValidProviderOption(authProvider)) throw new Error(\`Invalid auth provider: \${authProvider}\`)
const subject = providers[authProvider].extractSubjectFromIdentity(userIdentity)
const provider = providers[authProvider as keyof typeof providers]
const identity = userIdentity as Record<string, unknown>
const subject =
(provider as any).extractSubjectFromIdentity?.(identity) ??
(identity.sub as string | undefined) ??
(identity.id as string | undefined) ??
String(identity.sub || identity.id || 'unknown')
const authSub = \`\${authProvider.toUpperCase()}|\${subject}\`
${queries.selectUser}
}
export const getUser = async ({ authProvider, db, userIdentity }: UserHandlerProps) => {
if (!isValidProviderOption(authProvider)) throw new Error(`Invalid auth provider: ${authProvider}`)
const provider = providers[authProvider as keyof typeof providers]
const identity = userIdentity as Record<string, unknown> & { sub?: unknown; id?: unknown }
const subject =
(provider as any).extractSubjectFromIdentity?.(identity) ??
(identity.sub as string | undefined) ??
(identity.id as string | undefined) ??
String(identity.sub ?? identity.id ?? 'unknown')
const authSub = `${authProvider.toUpperCase()}|${subject}`
${queries.selectUser}
}
🤖 Prompt for AI Agents
In src/generators/db/handlerTemplates.ts around lines 30 to 41 (and also apply
the same fix to createUser on lines 43 to 54), the current cast to
Record<string, unknown> still triggers TypeScript errors when accessing
identity.sub or identity.id with dot notation; change the typing or access to
satisfy the compiler: either cast identity to an intersection type that includes
optional sub and id properties (e.g., Record<string, unknown> & { sub?: string;
id?: string }) so dot access is valid, or keep Record<string, unknown> but use
safe bracket notation (identity['sub'] / identity['id']) and coerce to string
where needed; apply the same approach in createUser so both handlers compile
cleanly.

Comment on lines +62 to +67
filterMatrix: (config): config is CloudMatrixEntry =>
config.databaseHost !== 'none' &&
SUPPORTED_DATABASE_ENGINES.has(config.databaseEngine) &&
SUPPORTED_ORMS.has(config.orm) &&
SUPPORTED_FRONTENDS.has(config.frontend) &&
config.directoryConfig === 'default',
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Exclude local hosts from the cloud provider matrix.

Right now filterMatrix only checks that databaseHost !== 'none'. Matrix entries with databaseHost === 'docker' (or other non-cloud hosts) therefore slip through, yet validateCloudProvider only accepts neon, planetscale, or turso. Every such entry fails with Invalid cloud provider: docker, and the type guard claims these configs are CloudMatrixEntry even though the runtime value disagrees. Please tighten the host filter so only the supported cloud hosts make it into this suite.

 const SUPPORTED_DATABASE_ENGINES = new Set(['sqlite', 'postgresql']);
 const SUPPORTED_ORMS = new Set(['none', 'drizzle']);
 const SUPPORTED_FRONTENDS = new Set(['html', 'react', 'vue', 'svelte']);
+const SUPPORTED_DATABASE_HOSTS = new Set(['neon', 'turso']);
 ...
-  filterMatrix: (config): config is CloudMatrixEntry =>
-    config.databaseHost !== 'none' &&
+  filterMatrix: (config): config is CloudMatrixEntry =>
+    SUPPORTED_DATABASE_HOSTS.has(config.databaseHost) &&
     SUPPORTED_DATABASE_ENGINES.has(config.databaseEngine) &&

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In tests/functional/cloud.test.ts around lines 62–67, the filterMatrix type
guard currently only excludes 'none' hosts, allowing non-cloud hosts like
'docker' to pass and later fail validateCloudProvider; update the predicate so
it only accepts known cloud hosts (e.g. neon, planetscale, turso) by either
checking a SUPPORTED_CLOUD_PROVIDERS set/array or invoking the existing
validateCloudProvider logic in the filter, replacing the databaseHost !== 'none'
check with a membership check
(SUPPORTED_CLOUD_PROVIDERS.has(config.databaseHost) or equivalent) so the guard
accurately reflects CloudMatrixEntry at runtime.

Comment on lines +72 to +81
createProjectName, describeBlock: 'MongoDB database matrix', describeConfig, beforeValidate: async ({ config, projectPath }) => {
await runFunctionalSuite(projectPath);

if (config.databaseHost === 'none') {
const dockerStatus = ensureDockerAvailable();

if (!dockerStatus.available) {
throw new Error(`Docker unavailable: ${dockerStatus.message}`);
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Remove redundant Docker availability check.

The beforeValidate hook checks Docker availability and throws if unavailable, but validateMongoDBDatabase already handles Docker unavailability gracefully by detecting the condition and returning warnings instead of errors (see mongodb-validator.ts lines 195-200 and handleDockerUnavailable). This redundant check prevents the validator from applying its own detection logic and causes unnecessary test failures in environments where Docker is unavailable.

Remove the Docker check from beforeValidate:

  beforeValidate: async ({ config, projectPath }) => {
    await runFunctionalSuite(projectPath);
-
-    if (config.databaseHost === 'none') {
-      const dockerStatus = ensureDockerAvailable();
-
-      if (!dockerStatus.available) {
-        throw new Error(`Docker unavailable: ${dockerStatus.message}`);
-      }
-    }
  },
🤖 Prompt for AI Agents
In tests/functional/databases/mongodb.test.ts around lines 72 to 81, remove the
redundant Docker availability check inside the beforeValidate hook: delete the
conditional block that calls ensureDockerAvailable() and throws when
dockerStatus.available is false (the if (config.databaseHost === 'none') { ... }
block), leaving only the await runFunctionalSuite(projectPath); so that
validateMongoDBDatabase can handle Docker-unavailable cases and emit warnings
instead of forcing test failures.

Comment on lines +58 to +62
}), filterMatrix: (config): config is HtmxMatrixEntry =>
config.frontend === 'htmx' &&
config.directoryConfig === 'default' &&
SUPPORTED_DATABASE_ENGINES.has(config.databaseEngine) &&
SUPPORTED_ORMS.has(config.orm), validate: async ({ config, projectPath }) => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Exclude unsupported Drizzle/MongoDB combinations.

The current filter lets databaseEngine === 'mongodb' pair with orm === 'drizzle'. Our scaffolder immediately throws (isDrizzleDialect rejects MongoDB), so every such matrix entry fails before validation begins. Tighten the predicate so Drizzle only runs with the supported SQL engine (sqlite in this filtered set).

Apply this diff to fix the issue:

-    SUPPORTED_DATABASE_ENGINES.has(config.databaseEngine) &&
-    SUPPORTED_ORMS.has(config.orm), validate: async ({ config, projectPath }) => {
+    SUPPORTED_DATABASE_ENGINES.has(config.databaseEngine) &&
+    SUPPORTED_ORMS.has(config.orm) &&
+    (config.orm !== 'drizzle' || config.databaseEngine === 'sqlite'), validate: async ({ config, projectPath }) => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
}), filterMatrix: (config): config is HtmxMatrixEntry =>
config.frontend === 'htmx' &&
config.directoryConfig === 'default' &&
SUPPORTED_DATABASE_ENGINES.has(config.databaseEngine) &&
SUPPORTED_ORMS.has(config.orm), validate: async ({ config, projectPath }) => {
}), filterMatrix: (config): config is HtmxMatrixEntry =>
config.frontend === 'htmx' &&
config.directoryConfig === 'default' &&
SUPPORTED_DATABASE_ENGINES.has(config.databaseEngine) &&
SUPPORTED_ORMS.has(config.orm) &&
(config.orm !== 'drizzle' || config.databaseEngine === 'sqlite'), validate: async ({ config, projectPath }) => {
🤖 Prompt for AI Agents
In tests/functional/frameworks/htmx.test.ts around lines 58 to 62, the
filterMatrix predicate currently allows orm === 'drizzle' to pair with
databaseEngine === 'mongodb', which the scaffolder rejects; tighten the
predicate so Drizzle only runs with the supported SQL engine by adding a clause
that excludes Drizzle+MongoDB combos (e.g. require config.orm !== 'drizzle' ||
config.databaseEngine === 'sqlite' or explicitly disallow config.orm ===
'drizzle' && config.databaseEngine === 'mongodb'), ensuring the filter only
yields valid matrix entries.

Comment thread tests/harness/process.ts
Comment on lines +45 to +46
const [exitCode] = (await once(child, 'close')) as [number | null];
clearTimeout(timeoutHandle);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Handle child-process spawn errors to avoid hangs.

When spawn fails before the process starts (missing executable, permission issues, etc.), Node emits an 'error' event without ever firing 'close'. Because we only await 'close', runCommand never resolves and the harness deadlocks. Please race the 'close' event with 'error' and clear the timeout in both paths.

-  const [exitCode] = (await once(child, 'close')) as [number | null];
-  clearTimeout(timeoutHandle);
+  const closePromise = once(child, 'close') as Promise<[number | null, NodeJS.Signals | null]>;
+  const errorPromise = once(child, 'error').then((error) => {
+    throw error;
+  });
+
+  let exitCode: number | null = null;
+  try {
+    [exitCode] = await Promise.race([closePromise, errorPromise]);
+  } finally {
+    clearTimeout(timeoutHandle);
+  }
🤖 Prompt for AI Agents
In tests/harness/process.ts around lines 45-46, the current await only listens
for the child's 'close' event so if spawn emits an 'error' (e.g., missing
executable) the promise never resolves and the test harness hangs; update the
logic to race/listen for both 'close' and 'error' (e.g., Promise.race or once
for both events), handle the 'error' path by rejecting or returning an
appropriate non-null exit/error result, and ensure clearTimeout(timeoutHandle)
is called in both the 'close' and 'error' handlers so the timeout is always
cleared.

Comment thread tests/harness/server.ts
Comment on lines +39 to +138
const child = spawn(command[0], command.slice(1), {
cwd: projectPath,
env: childEnv,
stdio: [
'ignore',
options.forwardStdout ? 'inherit' : 'pipe',
options.forwardStderr ? 'inherit' : 'pipe'
]
});

let exited = false;
let exitCode: number | null = null;

const exitWatcher = once(child, 'exit').then(([code, signal]) => {
exited = true;
exitCode = code ?? 0;

if (!options.forwardStdout && child.stdout) {
child.stdout.removeAllListeners('data');
}
if (!options.forwardStderr && child.stderr) {
child.stderr.removeAllListeners('data');
}

const terminatedBySignal =
typeof signal === 'string' && signal.length > 0;

if (!terminatedBySignal && exitCode !== 0) {
console.warn(`Server process exited prematurely with code ${code}`);
}

return exitCode ?? 0;
});

if (!options.forwardStdout && child.stdout) {
child.stdout.on('data', (chunk: Buffer) => {
const text = chunk.toString();
stdoutBuffer.push(text);
if (captureOutput) {
process.stdout.write(text);
}
});
}

if (!options.forwardStderr && child.stderr) {
child.stderr.on('data', (chunk: Buffer) => {
const text = chunk.toString();
stderrBuffer.push(text);
if (captureOutput) {
process.stderr.write(text);
}
});
}

const buildDiagnosticMessage = (base: string, cause?: unknown) => {
const tail = (lines: string[], maxLines: number) =>
lines.join('').split('\n').filter(Boolean).slice(-maxLines).join('\n');

const stdoutTail = tail(stdoutBuffer, OUTPUT_TAIL_LINES);
const stderrTail = tail(stderrBuffer, OUTPUT_TAIL_LINES);

const details: string[] = [base];

if (stdoutTail.length > 0) {
details.push(`stdout:\n${stdoutTail}`);
}

if (stderrTail.length > 0) {
details.push(`stderr:\n${stderrTail}`);
}

if (cause) {
const message = cause instanceof Error ? cause.message : String(cause);
details.push(`cause: ${message}`);
}

return details.join('\n\n');
};

try {
await waitForHttpOk(readyUrl, readyTimeoutMs);
} catch (error) {
child.kill('SIGTERM');
await exitWatcher;
if (exitCode && exitCode !== 0) {
throw new Error(
buildDiagnosticMessage(
`Server process exited with code ${exitCode} while waiting for readiness (${readyUrl}).`,
error
)
);
}

throw new Error(
buildDiagnosticMessage(
`Server did not become ready within ${readyTimeoutMs}ms (${readyUrl}).`,
error
)
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Handle spawn failures so the harness doesn’t crash.

Line 39 spawns the dev server without attaching an 'error' listener. When the executable is missing (e.g., bun not installed) or cannot start, Node emits an 'error' event; without a listener the process throws and the entire test harness crashes before we can surface diagnostics. We need to race readiness with that 'error' event and convert it into a controlled failure, while avoiding SIGTERM/exitWatcher waits when the child never spawned.

@@
-  const exitWatcher = once(child, 'exit').then(([code, signal]) => {
+  const exitWatcher = once(child, 'exit').then(([code, signal]) => {
     exited = true;
     exitCode = code ?? 0;
@@
-  try {
-    await waitForHttpOk(readyUrl, readyTimeoutMs);
+  const spawnErrorWatcher = once(child, 'error');
+
+  try {
+    await Promise.race([
+      waitForHttpOk(readyUrl, readyTimeoutMs),
+      spawnErrorWatcher
+    ]);
   } catch (error) {
-    child.kill('SIGTERM');
-    await exitWatcher;
-    if (exitCode && exitCode !== 0) {
-      throw new Error(
-        buildDiagnosticMessage(
-          `Server process exited with code ${exitCode} while waiting for readiness (${readyUrl}).`,
-          error
-        )
-      );
-    }
-
-    throw new Error(
-      buildDiagnosticMessage(
-        `Server did not become ready within ${readyTimeoutMs}ms (${readyUrl}).`,
-        error
-      )
-    );
+    const processStarted = typeof child.pid === 'number' && child.pid > 0;
+
+    if (processStarted && !exited) {
+      child.kill('SIGTERM');
+      await Promise.race([exitWatcher, delay(STOP_TIMEOUT_MS)]);
+
+      if (!exited) {
+        child.kill('SIGKILL');
+        await exitWatcher.catch(() => undefined);
+      }
+    }
+
+    if (exitCode !== null && exitCode !== 0) {
+      throw new Error(
+        buildDiagnosticMessage(
+          `Server process exited with code ${exitCode} while waiting for readiness (${readyUrl}).`,
+          error
+        )
+      );
+    }
+
+    throw new Error(
+      buildDiagnosticMessage(
+        processStarted
+          ? `Server did not become ready within ${readyTimeoutMs}ms (${readyUrl}).`
+          : `Failed to start server process (${command.join(' ')})`,
+        error
+      )
+    );
   }

Committable suggestion skipped: line range outside the PR's diff.

- Simplify cloud env var names (NEON_DATABASE_URL, TURSO_DB_URL)
- Broaden auth filter to include postgresql for proper matrix skip handling
- Expand auth behavioural coverage to Vue and Svelte frontends
- Document functional vs behavioural env var behavior in guide
Fixed all remaining ESLint violations to achieve zero-error lint status:

ESLint Fixes:
- Remove unused 'config' parameter from isValidMatrixConfig in matrix.ts
- Remove explicit return type annotations to rely on TypeScript inference
  - extractProvidersArray, getRedirectWarning, buildAuthConfig in generateUseBlock.ts
  - annotateMatrixEntry in matrix.ts
- Flatten deeply nested blocks to comply with max-depth-extended rule
  - Extract writeTsconfigFile helper in scaffoldConfigurationFiles.ts
  - Simplify PostgreSQL imports logic in generateImportsBlock.ts
  - Extract processFrontend helper in frontendDirectoryConfigurations.ts
  - Flatten --skip section conditionals in parseCommandLineOptions.ts
  - Simplify environment variable check in test-utils.ts

Test Cleanup:
- Remove test-cli-project directory and all generated artifacts
- Clean up behavioural test temporary directories
- Remove test-auth-* project directories from functional testing

All changes maintain existing functionality while improving code quality.
Verified with: bun lint (zero errors), bun test ./tests/harness/harness.test.ts (passing)
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

♻️ Duplicate comments (3)
docs/test-cli-ux.md (2)

6-6: Fix compound adjective with hyphen.

This was already flagged in a prior review: the phrase "human friendly progress" should be "human-friendly progress" to properly form the compound adjective.

Apply this diff:

-Preserve the stakeholder‑approved experience from the legacy runner: intuitive flags, human friendly progress, concise summary, predictable exit codes.
+Preserve the stakeholder‑approved experience from the legacy runner: intuitive flags, human-friendly progress, concise summary, predictable exit codes.

64-66: Add language identifier to fenced code block.

This was already flagged in a prior review: the fenced code block lacks a language specifier for syntax highlighting.

Apply this diff:

-\`\`\`
+\`\`\`bash
 bun run test:cli [options]
-\`\`\`
+\`\`\`
src/generators/project/generateUseBlock.ts (1)

49-51: Fix getUser argument shape and reconsider broad callback casting

Two concerns in the callback construction:

  1. Inconsistent userIdentity property name
    Previously, both createUser and getUser were called with { userIdentity }. The new code keeps createUser({ …, userIdentity }) but changes getUser to getUser({ authProvider, db, user_identity: userIdentity }). Unless getUser’s signature was explicitly changed to expect user_identity, this is likely a breaking change and will pass undefined into the handler.

    Suggested fix to keep the handlers consistent:

  •   createUser: (userIdentity: Record<string, unknown>) => createUser({ authProvider, db, userIdentity }), getUser: (userIdentity: Record<string, unknown>) => getUser({ authProvider, db, user_identity: userIdentity }) } as Record<string, unknown>)`
    
  •   createUser: (userIdentity: Record<string, unknown>) => createUser({ authProvider, db, userIdentity }), getUser: (userIdentity: Record<string, unknown>) => getUser({ authProvider, db, userIdentity }) } as Record<string, unknown>)`
    
    
    
  1. Outer as Record<string, unknown> cast on the callback
    mergedConfig wraps the whole function in as Record<string, unknown>:

    onCallbackSuccess: (${callback}) as Record<string, unknown>

    This largely sidesteps the function’s actual type, similar to the earlier concern about heavy any usage in this callback. If absoluteAuth exposes a concrete callback type, prefer casting to that or letting inference work instead of forcing a generic record type.

    A lighter option (if types permit) would be to drop the outer cast:

  • mergedConfig += ${routesString} onCallbackSuccess: (${callback}) as Record<string, unknown> ${redirectWarning} };
  • mergedConfig += ${routesString} onCallbackSuccess: (${callback})${redirectWarning} };





To double‑check the handler contract, you can search how `getUser` is declared:

```shell
#!/bin/bash
# Inspect getUser/createUser handler signatures to confirm expected payload keys.
rg -n "function getUser|const getUser|export const getUser" -C3
rg -n "function createUser|const createUser|export const createUser" -C3

Also applies to: 63-63

🧹 Nitpick comments (10)
docs/test-cli-ux.md (1)

26-35: Replace hard tabs with spaces for list indentation.

The nested list items (lines 29, 31, 33) use hard tabs for indentation; Markdown linting requires 2 spaces per nesting level.

Apply this diff:

 Usage:

-- Dry run (list directories found):
-	- `bash scripts/clean-tests.sh`
+- Dry run (list directories found):
+  - `bash scripts/clean-tests.sh`
 - Delete test projects (standard):
-	- `bash scripts/clean-tests.sh --confirm`
+  - `bash scripts/clean-tests.sh --confirm`
 - Full cleanup (also removes `.test-dependency-cache`):
-	- `bash scripts/clean-tests.sh --full --confirm`
+  - `bash scripts/clean-tests.sh --full --confirm`
scripts/clean-tests.sh (1)

35-35: Note potential portability limitation with find -printf on BSD/macOS.

The find -printf '%f\n' option is a GNU find extension and may not be available on macOS (BSD find). While the || true fallback prevents script failure, TEST_DIRS would be empty unexpectedly on systems without GNU find, silently skipping the cleanup. If macOS support is required, consider using a more portable approach.

For portability, consider:

# Option 1: Use -print with basename extraction (more portable)
mapfile -t TEST_DIRS < <(find "$ROOT_DIR" -maxdepth 1 -type d -name 'test-*' ! -name 'test-cli-project' -print | xargs -I {} basename {} || true)

# Option 2: Use find with -type d and -exec basename
mapfile -t TEST_DIRS < <(find "$ROOT_DIR" -maxdepth 1 -type d -name 'test-*' ! -name 'test-cli-project' -exec basename {} \;)
src/generators/configurations/scaffoldConfigurationFiles.ts (1)

47-67: Refactor to eliminate code duplication in directory creation and file writing.

Lines 58-59 and 65-66 duplicate the mkdirSync and writeFileSync calls. The early return at line 61 forces this repetition, but the operations are identical in both branches.

Apply this diff to consolidate the duplicated logic:

 const writeTsconfigFile = () => {
 	const tsconfigContent = readFileSync(tsconfigTemplatePath, 'utf-8');
 	const tsconfig = JSON.parse(tsconfigContent);
 
 	if (!tsconfig.compilerOptions) {
 		tsconfig.compilerOptions = {};
 	}
 
 	const jsxOption = getJsxOption();
-	if (!jsxOption) {
+	if (jsxOption) {
+		tsconfig.compilerOptions.jsx = jsxOption;
+	} else {
 		delete tsconfig.compilerOptions.jsx;
-		mkdirSync(projectName, { recursive: true });
-		writeFileSync(tsconfigTargetPath, `${JSON.stringify(tsconfig, null, 2)}\n`);
-
-		return;
 	}
 
-	tsconfig.compilerOptions.jsx = jsxOption;
 	mkdirSync(projectName, { recursive: true });
 	writeFileSync(tsconfigTargetPath, `${JSON.stringify(tsconfig, null, 2)}\n`);
 };
eslint.config.mjs (1)

223-231: Configuration for test files looks good.

The test-specific block correctly:

  • Overrides browser globals with Node globals for the test environment
  • Disables import/no-unused-modules for test utilities
  • Relies on earlier TypeScript parser configuration (which will merge correctly in flat config)

Consider also relaxing no-magic-numbers for test files, as tests commonly use literal values for test data and assertions:

 {
   files: ['tests/**/*.{ts,tsx}'],
   languageOptions: {
     globals: globals.node
   },
   rules: {
-    'import/no-unused-modules': 'off'
+    'import/no-unused-modules': 'off',
+    'no-magic-numbers': 'off'
   }
 },

This mirrors the existing override for configuration files (lines 184-194).

tests/behavioural/database-matrix.ts (1)

39-74: Env merge and options construction are correct; consider tightening baseOptions typing

The env merge and override order (baseOptions → per‑scenario options → fixed database/frontend → optional orm) look correct and predictable, and only attaching options.env when there’s at least one key avoids spurious empty env blocks.

One optional refinement: baseOptions currently allows frontend (but it’s always overridden by config.frontend). To avoid any confusion for callers, you could exclude frontend there as well:

-  baseOptions?: Partial<Omit<BehaviouralScenario['options'], 'database'>>;
+  baseOptions?: Partial<
+    Omit<BehaviouralScenario['options'], 'database' | 'frontend'>
+  >;

Not mandatory, but it would better express the actual behavior of buildScenario.

src/generators/project/generateImportsBlock.ts (2)

163-168: Consider adding explicit validation for remote PostgreSQL host.

The code safely handles invalid databaseHost values with the conditional check at line 166, but silently skipping imports could mask configuration errors. Since PostgreSQL remote hosting is effectively limited to Neon in the current connectorImports map, consider adding an explicit type constraint or runtime assertion to ensure databaseHost is 'neon' in this path.

Example:

 if (shouldAddPostgresqlImports && isRemoteHost) {
-	const connectorKey = databaseHost;
+	if (databaseHost !== 'neon') {
+		throw new Error(`Unsupported PostgreSQL remote host: ${databaseHost}`);
+	}
+	const connectorKey = databaseHost as 'neon';
 	const connectorImportsList = connectorImports[connectorKey];
 	if (connectorImportsList) rawImports.push(...connectorImportsList);
 	rawImports.push(`import { getEnv } from '@absolutejs/absolute'`);
 }

216-231: Enhance parseImportClause to handle mixed default and named imports.

The current implementation assumes import clauses are either default-only or named-only, but doesn't handle the mixed pattern (e.g., React, { useState }). While the existing code doesn't generate mixed imports, this is a latent bug that could surface if the import generation logic changes.

Apply this diff to handle mixed imports:

 const parseImportClause = (
 	importClause: string,
 	entry: { defaultImport: string | null; namedImports: Set<string> }
 ) => {
-	if (importClause.startsWith('{')) {
+	const parts = importClause.split(',').map((s) => s.trim());
+	
+	for (const part of parts) {
+		if (part.startsWith('{')) {
+			// Named imports
-		importClause
-			.slice(1, -1)
+			part
+				.slice(1, part.endsWith('}') ? -1 : part.length)
 				.split(',')
 				.map((segment) => segment.trim())
 				.filter(Boolean)
 				.forEach((name) => entry.namedImports.add(name));
-	} else {
+		} else if (!part.endsWith('}')) {
+			// Default import
-		entry.defaultImport = importClause.trim();
+			entry.defaultImport = part;
+		}
 	}
 };
docs/cloud-auth-test-verification.md (1)

26-45: Add language specifications to code blocks for better readability.

The code blocks at lines 26-29, 32-34, 37-39, and 42-45 lack language specifications. Adding bash or shell identifiers will enable syntax highlighting.

Apply this pattern to the affected blocks:

-```
+```bash
 bun run typecheck
 npm run lint

</blockquote></details>
<details>
<summary>src/commands/initializeGit.ts (1)</summary><blockquote>

`21-27`: **Stop the spinner before calling checkGitInstalled().**

The spinner "Checking git availability..." continues running while `checkGitInstalled()` may display interactive prompts and start its own spinners for package installation. This creates overlapping UI elements and confusing UX.



Apply this diff to stop the spinner before the interactive check:

```diff
-	spin.start('Checking git availability...');
+	spin.start('Checking git availability...');
 	const isGitInstalled = await checkGitInstalled();
+	spin.stop();
 	
 	if (!isGitInstalled) {
-		spin.stop(red('Git is not installed. Please install git before proceeding.'), 1);
+		console.log(red('✖ Git is not installed. Please install git before proceeding.'));
 		abort();
 	}

Alternatively, remove the spinner entirely since checkGitInstalled() manages its own progress indicators:

-	spin.start('Checking git availability...');
 	const isGitInstalled = await checkGitInstalled();
 	
 	if (!isGitInstalled) {
-		spin.stop(red('Git is not installed. Please install git before proceeding.'), 1);
+		console.log(red('✖ Git is not installed. Please install git before proceeding.'));
 		abort();
 	}
src/questions/frontendDirectoryConfigurations.ts (1)

55-91: Logic is correct with minor harmless redundancy.

The processFrontend helper properly implements the custom directory flow: prefilled values are used directly, custom configurations trigger prompts, and defaults are applied otherwise.

Note: Line 88 passes passedFrontendDirectories?.[name], but this will always be undefined for items in frontendsToPrompt (since prefilled values are filtered out earlier). This redundancy is harmless as getDirectoryForFrontend already handles undefined providedValue.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 55227a0 and 4bb793c.

📒 Files selected for processing (27)
  • docs/cloud-auth-test-verification.md (1 hunks)
  • docs/test-cli-ux.md (1 hunks)
  • eslint.config.mjs (2 hunks)
  • package.json (1 hunks)
  • scripts/clean-tests.sh (1 hunks)
  • scripts/functional-tests/matrix.ts (1 hunks)
  • src/commands/formatProject.ts (2 hunks)
  • src/commands/initializeGit.ts (1 hunks)
  • src/data.ts (2 hunks)
  • src/generators/configurations/generatePackageJson.ts (4 hunks)
  • src/generators/configurations/scaffoldConfigurationFiles.ts (3 hunks)
  • src/generators/db/generateHandlers.ts (2 hunks)
  • src/generators/project/generateImportsBlock.ts (4 hunks)
  • src/generators/project/generateServer.ts (3 hunks)
  • src/generators/project/generateUseBlock.ts (2 hunks)
  • src/questions/directoryConfiguration.ts (1 hunks)
  • src/questions/frontendDirectoryConfigurations.ts (3 hunks)
  • src/utils/checkGitInstalled.ts (1 hunks)
  • src/utils/parseCommandLineOptions.ts (2 hunks)
  • tests/behavioural/auth-matrix.test.ts (1 hunks)
  • tests/behavioural/cloud-matrix.test.ts (1 hunks)
  • tests/behavioural/database-matrix-definitions.ts (1 hunks)
  • tests/behavioural/database-matrix.test.ts (1 hunks)
  • tests/behavioural/database-matrix.ts (1 hunks)
  • tests/behavioural/utils.ts (1 hunks)
  • tests/functional/auth.test.ts (1 hunks)
  • tests/functional/frameworks/test-utils.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (10)
  • package.json
  • tests/behavioural/auth-matrix.test.ts
  • src/commands/formatProject.ts
  • tests/functional/frameworks/test-utils.ts
  • src/utils/parseCommandLineOptions.ts
  • tests/behavioural/cloud-matrix.test.ts
  • tests/behavioural/database-matrix-definitions.ts
  • src/generators/project/generateServer.ts
  • tests/behavioural/utils.ts
  • src/generators/db/generateHandlers.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-23T22:49:50.485Z
Learnt from: absolutejs
Repo: absolutejs/create-absolutejs PR: 15
File: src/data.ts:138-156
Timestamp: 2025-11-23T22:49:50.485Z
Learning: In the create-absolutejs repository, React-specific ESLint plugins (eslint-plugin-jsx-a11y, eslint-plugin-react, eslint-plugin-react-compiler, eslint-plugin-react-hooks) should only be installed conditionally when the project uses React (flags.requiresReact is true), not for all projects using eslint+prettier.

Applied to files:

  • eslint.config.mjs
🧬 Code graph analysis (9)
src/utils/checkGitInstalled.ts (2)
src/utils/checkDockerInstalled.ts (6)
  • $ (114-134)
  • commandExists (80-112)
  • commandExists (136-190)
  • spin (71-78)
  • cmd (21-25)
  • env (9-10)
src/utils/checkSqliteInstalled.ts (2)
  • hasSqlite (137-159)
  • hasSqlite (112-117)
src/questions/directoryConfiguration.ts (2)
src/prompt.ts (1)
  • argumentConfiguration (18-123)
src/questions/configurationType.ts (1)
  • directoryConfig (5-16)
src/generators/project/generateUseBlock.ts (1)
src/types.ts (1)
  • ORM (52-52)
src/generators/configurations/generatePackageJson.ts (1)
src/data.ts (2)
  • prismaRuntimeDependencies (140-149)
  • prismaDevDependencies (151-156)
src/data.ts (2)
src/types.ts (1)
  • AvailableDependency (31-36)
src/generators/project/collectDependencies.ts (2)
  • dependency (39-39)
  • CollectDependenciesProps (17-48)
src/generators/configurations/scaffoldConfigurationFiles.ts (3)
src/generators/project/scaffoldFrontends.ts (1)
  • ScaffoldFrontendsProps (19-106)
src/generators/project/generateRoutesBlock.ts (1)
  • frontend (20-70)
src/generators/vue/generateVuePage.ts (1)
  • frontends (4-269)
tests/functional/auth.test.ts (3)
scripts/functional-tests/matrix.ts (1)
  • MatrixConfig (33-46)
tests/functional/frameworks/test-utils.ts (1)
  • runMatrixSuite (183-183)
scripts/functional-tests/auth-validator.ts (1)
  • validateAuthConfiguration (61-95)
tests/behavioural/database-matrix.test.ts (3)
tests/behavioural/database-matrix-definitions.ts (1)
  • DATABASE_MATRIX_DEFINITIONS (17-62)
tests/behavioural/database-matrix.ts (1)
  • describeDatabaseMatrix (76-99)
src/generators/db/generateDrizzleSchema.ts (1)
  • GenerateSchemaProps (66-163)
src/commands/initializeGit.ts (3)
src/utils/checkGitInstalled.ts (1)
  • checkGitInstalled (261-301)
src/utils/abort.ts (1)
  • abort (5-8)
src/questions/initializeGitNow.ts (1)
  • initializeGitNow (4-11)
🪛 LanguageTool
docs/test-cli-ux.md

[grammar] ~6-~6: Use a hyphen to join words.
Context: ...he legacy runner: intuitive flags, human friendly progress, concise summary, pred...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.18.1)
docs/cloud-auth-test-verification.md

26-26: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


32-32: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


37-37: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


42-42: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

docs/test-cli-ux.md

29-29: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


29-29: Hard tabs
Column: 1

(MD010, no-hard-tabs)


31-31: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


31-31: Hard tabs
Column: 1

(MD010, no-hard-tabs)


33-33: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


33-33: Hard tabs
Column: 1

(MD010, no-hard-tabs)


64-64: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 Shellcheck (0.11.0)
scripts/clean-tests.sh

[warning] 52-52: Use "${var:?}" to ensure this never expands to / .

(SC2115)

🔇 Additional comments (33)
docs/test-cli-ux.md (1)

1-117: Excellent documentation structure and content clarity.

The specification comprehensively covers the Test CLI UX with well-organized sections, clear tables, and actionable command examples. The suite taxonomy, execution semantics, and behavioral integration details are all clearly explained. Once the formatting issues above are resolved, this will serve as strong reference documentation for developers and CI workflows.

scripts/clean-tests.sh (1)

4-68: Solid cleanup utility with clear dry-run safety and modular flags.

The overall design is well-structured: argument parsing is explicit, the dry-run default prevents accidental deletion, and separation of test-directory cleanup from cache cleanup allows flexible workflows. The conditional logic correctly enforces --confirm for destructive operations and handles edge cases (e.g., no test dirs but cache removal still allowed in full mode).

src/generators/configurations/scaffoldConfigurationFiles.ts (1)

119-130: LGTM! Vue type declarations properly implemented.

The directory is created with { recursive: true } before writing the Vue shim file, eliminating the ENOENT risk flagged in the previous review. The module declaration correctly types .vue file imports for TypeScript.

eslint.config.mjs (1)

19-19: LGTM!

Adding test-cli-project/** to the ignore list is appropriate for excluding scaffolded test projects from linting, consistent with the existing absolutejs-project/** pattern.

tests/behavioural/database-matrix.test.ts (1)

1-4: Simple, correct wiring for database behavioural matrix

The test file cleanly delegates all behavior to describeDatabaseMatrix for each entry in DATABASE_MATRIX_DEFINITIONS; registration is synchronous and top-level, which is what bun:test expects. No issues here.

tests/behavioural/database-matrix.ts (2)

5-25: Type-driven matrix definition looks solid and future‑proof

Deriving Frontend, Orm, and DatabaseEngine from BehaviouralScenario['options'] keeps the matrix types in sync with the underlying scenario options, and ScenarioConfig / DatabaseMatrixDefinition give a clear, constrained shape for callers. This is a good balance between flexibility (partial options) and type safety.


76-99: Remove review comment; auth and cloud matrices don't follow the database-matrix filtering pattern.

The review assumes other behavioural matrices (auth/cloud) use similar ABSOLUTE_BEHAVIOURAL_*_FILTER env var patterns. Verification shows this is not the case: auth-matrix.test.ts uses hardcoded scenarios with direct describe/it calls, while cloud-matrix.test.ts uses a requiredEnv mapping pattern for environment variables. Only database-matrix.ts implements the filtering approach. No consistency issue exists because the implementation patterns are fundamentally different across these test files. Additionally, no documentation references the ABSOLUTE_BEHAVIOURAL_DATABASE_FILTER env var.

Likely an incorrect or invalid review comment.

src/generators/project/generateImportsBlock.ts (3)

82-92: LGTM! Dynamic Neon import resolution is correct.

The function correctly returns Pool imports for Drizzle ORM and neon imports for no-ORM scenarios. The logic properly ensures that the appropriate import is selected based on the ORM value, and since the mutually exclusive execution paths (Drizzle at line 110 vs. no-ORM at line 163) consume this value appropriately, the behavior is sound.


170-175: LGTM! MongoDB no-ORM imports are correct.

The explicit import of MongoClient and getEnv for no-ORM MongoDB paths is appropriate and aligns with the broader pattern of ORM-aware import resolution in this PR.


238-251: LGTM! Import consolidation logic is clean and correct.

The refactoring to use parseImportClause consolidates duplicate imports effectively (leveraging Set for deduplication), and the overall flow is more maintainable than inline parsing.

scripts/functional-tests/matrix.ts (3)

70-96: LGTM!

The host constraint annotation logic correctly handles environment variable requirements for cloud providers and appropriately skips PlanetScale flows per the documented test strategy.


124-146: LGTM!

The matrix creation using reduce/flatMap correctly generates the cartesian product of all configuration dimensions, and the file I/O operations are implemented appropriately.


27-31: No changes needed—the code is accurate.

PlanetScale supports both PostgreSQL and MySQL. PlanetScale offers a managed PostgreSQL product called "PlanetScale for Postgres" (GA announced July 1, 2025), making the HOST_CONSTRAINTS declaration on line 29 correct.

Likely an incorrect or invalid review comment.

tests/functional/auth.test.ts (3)

5-10: LGTM!

The type definition appropriately extends MatrixConfig to ensure authProvider is required and directoryConfig is locked to 'default'. The limited database engine support aligns with the documented test scope.


12-37: LGTM!

The helper functions correctly transform matrix configurations into project names and test descriptions. The sanitization in createProjectName (lines 17-19) properly handles special characters.


39-85: LGTM!

The matrix suite configuration correctly maps configurations to scaffold options, applies appropriate filters for auth-enabled scenarios, and integrates with the auth validator. The hardcoded 'bun' package manager (line 69) is acceptable for this test suite scope.

src/data.ts (1)

90-99: LGTM!

The GitHub credentials configuration structure is appropriate for scaffolding templates, with clear placeholder values for test purposes.

src/generators/configurations/generatePackageJson.ts (2)

10-12: LGTM!

The new Prisma dependency imports are correctly added and align with the exports from src/data.ts.


153-154: LGTM!

The clarifying comment accurately describes the purpose of the cloud provider dependencies.

src/utils/checkGitInstalled.ts (6)

1-31: LGTM: Environment detection is comprehensive.

The platform detection logic correctly handles Windows, macOS, WSL, and Linux environments. The isWSL check covers both WSL_DISTRO_NAME and kernel release patterns.


33-55: LGTM: Helper functions follow established patterns.

The implementation matches the patterns used in similar utilities like checkDockerInstalled.ts and checkSqliteInstalled.ts.


63-148: LGTM: Package manager installers are well-structured.

All installers follow a consistent pattern with appropriate non-interactive flags. The use of DEBIAN_FRONTEND=noninteractive for apt is correct.


156-186: LGTM: Platform-specific installers handle their constraints appropriately.

The macOS installer correctly omits sudo for Homebrew. The Windows installer reasonably directs users to manual installation rather than attempting automated installation with winget/choco.


194-244: LGTM: Platform wrappers prioritize package managers appropriately.

The fallback sequence makes sense: apt (most common), yum, dnf, pacman. Manual installation guidance is clear.


251-252: LGTM: Git detection is straightforward and correct.

src/commands/initializeGit.ts (3)

4-5: LGTM: New imports support the Git availability check.


7-16: LGTM: Good refactor extracting initialization logic.

The helper function improves code organization and makes the main flow easier to follow.


29-34: LGTM: Error handling for repository initialization is appropriate.

src/generators/project/generateUseBlock.ts (3)

3-31: Auth config helpers are defensive and read clearly

extractProvidersArray and getRedirectWarning safely handle missing/ill‑shaped providersConfiguration, defaulting to [] and omitting the warning rather than throwing. That’s appropriate for generator code that must not crash on partially specified configs.


65-68: Auth use chain and providers/session routes look consistent

The .use(absoluteAuth…) chain with the /auth/providers and /auth/session routes is built in one place now, and the providers route correctly reuses the derived providersArray (or [] when unspecified). This centralization should make future auth route tweaks easier.


87-89: Delegating auth plugin handling to buildAuthConfig simplifies generateUseBlock

Conditionally routing absoluteAuth through buildAuthConfig(pluginImport, databaseEngine, orm) keeps the main generateUseBlock flow straightforward while leaving other plugins’ behavior unchanged. This refactor improves readability without altering external behavior.

src/questions/frontendDirectoryConfigurations.ts (2)

1-2: LGTM!

The process import is correctly added to support non-interactive environment detection.


12-44: Well-designed non-interactive handling!

The function correctly prioritizes provided values, detects non-interactive environments to prevent hangs, and only prompts when running interactively. The TTY checks are comprehensive.

Comment thread scripts/clean-tests.sh
Comment on lines +50 to +54
for d in "${TEST_DIRS[@]}"; do
echo "Removing: $d"
rm -rf "$ROOT_DIR/$d"
done
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use parameter expansion to guard against unsafe rm -rf expansion.

Line 52 uses variables in a destructive rm -rf operation without the Bash best practice of parameter expansion checks. While $ROOT_DIR is set to $(pwd) and $d comes from find output, using "${var:?message}" syntax explicitly prevents accidental expansion to unsafe paths.

Apply this diff to add safety guards:

  for d in "${TEST_DIRS[@]}"; do
    echo "Removing: $d"
-   rm -rf "$ROOT_DIR/$d"
+   rm -rf "${ROOT_DIR:?ROOT_DIR not set}/${d:?d is empty}"
  done

Alternatively, validate ROOT_DIR once at initialization:

-ROOT_DIR="$(pwd)"
+ROOT_DIR="${ROOT_DIR:-.}"
+ROOT_DIR="${ROOT_DIR:?ROOT_DIR not set}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for d in "${TEST_DIRS[@]}"; do
echo "Removing: $d"
rm -rf "$ROOT_DIR/$d"
done
fi
for d in "${TEST_DIRS[@]}"; do
echo "Removing: $d"
rm -rf "${ROOT_DIR:?ROOT_DIR not set}/${d:?d is empty}"
done
fi
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 52-52: Use "${var:?}" to ensure this never expands to / .

(SC2115)

🤖 Prompt for AI Agents
In scripts/clean-tests.sh around lines 50 to 54, the rm -rf call uses unguarded
variables which can expand to unsafe paths; change the destructive command to
use Bash parameter-expansion guards and validate variables by replacing rm -rf
"$ROOT_DIR/$d" with rm -rf "${ROOT_DIR:?}/$d" (or more strictly rm -rf
"${ROOT_DIR:?}/${d:?}") and/or validate ROOT_DIR once at script initialization
(e.g., ensure ROOT_DIR is set and non-empty using : "${ROOT_DIR:?ROOT_DIR is not
set}" ) so the script will fail fast instead of accidentally running rm -rf /.

Comment on lines +48 to +53
export const isValidMatrixConfig = () =>
// Keep validation permissive here; skip/invalid combinations are annotated
// and handled by the test harness so they appear in generated matrix with
// an explicit skip reason. This helps produce transparent reports.
true
;type MatrixField = {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix syntax error: misplaced semicolon.

The semicolon is incorrectly placed at the start of line 53 instead of at the end of line 52. This will cause a compilation error.

Apply this diff:

 export const isValidMatrixConfig = () => 
 	// Keep validation permissive here; skip/invalid combinations are annotated
 	// and handled by the test harness so they appear in generated matrix with
 	// an explicit skip reason. This helps produce transparent reports.
-	 true
-;type MatrixField = {
+	 true;
+
+type MatrixField = {
   key: keyof MatrixConfig;
   values: ReadonlyArray<MatrixConfig[keyof MatrixConfig]>;
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const isValidMatrixConfig = () =>
// Keep validation permissive here; skip/invalid combinations are annotated
// and handled by the test harness so they appear in generated matrix with
// an explicit skip reason. This helps produce transparent reports.
true
;type MatrixField = {
export const isValidMatrixConfig = () =>
// Keep validation permissive here; skip/invalid combinations are annotated
// and handled by the test harness so they appear in generated matrix with
// an explicit skip reason. This helps produce transparent reports.
true;
type MatrixField = {
key: keyof MatrixConfig;
values: ReadonlyArray<MatrixConfig[keyof MatrixConfig]>;
};
🤖 Prompt for AI Agents
In scripts/functional-tests/matrix.ts around lines 48 to 53, there's a misplaced
semicolon beginning line 53 which causes a syntax error before the type
declaration; move the semicolon so it terminates the previous statement (place
it at the end of the line that returns true for isValidMatrixConfig) or remove
the extraneous newline so the export const line ends with a semicolon and the
type declaration starts cleanly.

Comment thread src/data.ts
Comment on lines +140 to +156
export const prismaRuntimeDependencies: AvailableDependency[] = [
{
latestVersion: '6.2.1',
value: '@prisma/client'
},
{
latestVersion: '5.23.0',
value: '@prisma/extension-accelerate'
}
];

export const prismaDevDependencies: AvailableDependency[] = [
{
latestVersion: '6.2.1',
value: 'prisma'
}
];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Verify Prisma package versions are current and secure.

Ensure the specified versions are valid and check for any security advisories or updates since my knowledge cutoff.


🌐 Web query:

What are the latest versions of @prisma/client, @prisma/extension-accelerate, and prisma npm packages?

💡 Result:

  • @prisma/client — 6.19.0. [1]
  • prisma — 6.19.0. [1]
  • @prisma/extension-accelerate — 2.0.2. [2]

Sources:
[1] Prisma releases (GitHub) — 6.19.0 release.
[2] @prisma/extension-accelerate package on npm (v2.0.2).


Update Prisma dependency versions to latest stable releases.

The latest versions are @prisma/client 6.19.0, prisma 6.19.0, and @prisma/extension-accelerate 2.0.2. The code specifies outdated versions:

  • @prisma/client: 6.2.1 → 6.19.0
  • prisma: 6.2.1 → 6.19.0
  • @prisma/extension-accelerate: 5.23.0 → 2.0.2

Update lines 141, 147, and 151 in src/data.ts with the latest stable versions to ensure security patches and bug fixes are included.

🤖 Prompt for AI Agents
In src/data.ts around lines 140 to 156, the pinned Prisma package versions are
outdated; update the version strings for the three entries: change
@prisma/client at line ~141 from "6.2.1" to "6.19.0", change
@prisma/extension-accelerate at line ~147 from "5.23.0" to "2.0.2", and change
prisma in prismaDevDependencies at line ~151 from "6.2.1" to "6.19.0"; keep the
object structure unchanged and ensure versions are exact strings.

Comment on lines +139 to 151
if (orm === 'prisma') {
prismaRuntimeDependencies.forEach((dep) => {
dependencies[dep.value] = resolveVersion(dep.value, dep.latestVersion);
});

prismaDevDependencies.forEach((dep) => {
if (dep.value === '@prisma/extension-accelerate' && !usesAccelerate) return;
devDependencies[dep.value] = resolveVersion(
dep.value,
dep.latestVersion
);
});
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix misplaced conditional check for @prisma/extension-accelerate.

The condition on line 145 checks if dep.value === '@prisma/extension-accelerate' within the prismaDevDependencies.forEach loop, but @prisma/extension-accelerate is defined in prismaRuntimeDependencies (see lines 145-148 in src/data.ts), not in prismaDevDependencies. This means the condition will never match, and the Accelerate extension will always be added to dependencies even when usesAccelerate is false.

Apply this diff to move the check to the correct loop:

 if (orm === 'prisma') {
 	prismaRuntimeDependencies.forEach((dep) => {
+		if (dep.value === '@prisma/extension-accelerate' && !usesAccelerate) return;
 		dependencies[dep.value] = resolveVersion(dep.value, dep.latestVersion);
 	});
 
 	prismaDevDependencies.forEach((dep) => {
-		if (dep.value === '@prisma/extension-accelerate' && !usesAccelerate) return;
 		devDependencies[dep.value] = resolveVersion(
 			dep.value,
 			dep.latestVersion
 		);
 	});
 }
🤖 Prompt for AI Agents
In src/generators/configurations/generatePackageJson.ts around lines 139 to 151,
the check for '@prisma/extension-accelerate' is placed inside the
prismaDevDependencies.forEach loop but that package lives in
prismaRuntimeDependencies, so the condition never matches and the accelerate
runtime package is always added; move the conditional into the
prismaRuntimeDependencies.forEach loop so that when iterating runtime deps you
skip adding dep.value === '@prisma/extension-accelerate' if !usesAccelerate,
leaving the devDependencies loop unchanged and continue to resolve and assign
versions for all other deps as before.

Comment on lines +234 to +243
if (orm === 'prisma') {
scripts['postinstall'] = 'prisma generate';
scripts['db:generate'] = 'prisma generate';
scripts['db:push'] = 'prisma db push';
scripts['db:studio'] = 'prisma studio';
scripts['db:migrate'] = 'prisma migrate dev';
scripts['db:migrate:deploy'] = 'prisma migrate deploy';
scripts['db:migrate:reset'] = 'prisma migrate reset';

}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix indentation in Prisma scripts block.

The script definitions (lines 235-241) have inconsistent indentation with excessive leading whitespace.

Apply this diff to normalize the indentation:

 if (orm === 'prisma') {
-  			scripts['postinstall'] = 'prisma generate';
-  			scripts['db:generate'] = 'prisma generate';
-  			scripts['db:push'] = 'prisma db push';
-  			scripts['db:studio'] = 'prisma studio';
-  			scripts['db:migrate'] = 'prisma migrate dev';
-  			scripts['db:migrate:deploy'] = 'prisma migrate deploy';
-  			scripts['db:migrate:reset'] = 'prisma migrate reset';
-
+	scripts['postinstall'] = 'prisma generate';
+	scripts['db:generate'] = 'prisma generate';
+	scripts['db:push'] = 'prisma db push';
+	scripts['db:studio'] = 'prisma studio';
+	scripts['db:migrate'] = 'prisma migrate dev';
+	scripts['db:migrate:deploy'] = 'prisma migrate deploy';
+	scripts['db:migrate:reset'] = 'prisma migrate reset';
 }
🤖 Prompt for AI Agents
In src/generators/configurations/generatePackageJson.ts around lines 234 to 243,
the block adding Prisma scripts has inconsistent/excessive leading indentation;
normalize the indentation so each scripts[...] assignment aligns with the
surrounding code (remove extra leading spaces before scripts['postinstall']
through scripts['db:migrate:reset']), keeping the same statements and spacing
style as other script entries in the file.

Comment on lines +39 to +43
const baseConfigString =
pluginImport.config !== null
? JSON.stringify(pluginImport.config).slice(1, -1)
: '';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Guard against undefined configs to avoid runtime crash in baseConfigString

When pluginImport.config is undefined, the condition pluginImport.config !== null is true, so JSON.stringify(pluginImport.config) returns undefined and .slice(1, -1) will throw at generation time. This is a hard failure if absoluteAuth is registered without an explicit config.

You can fix this by treating both null and undefined as “no base config” and normalizing config before passing to helpers:

- const baseConfigString =
- 	pluginImport.config !== null
- 		? JSON.stringify(pluginImport.config).slice(1, -1)
- 		: '';
+ const baseConfigString =
+ 	pluginImport.config != null
+ 		? JSON.stringify(pluginImport.config).slice(1, -1)
+ 		: '';

- const config = pluginImport.config as Record<string, unknown> | null;
+ const config = (pluginImport.config ?? null) as Record<string, unknown> | null;

This preserves existing behavior for null while avoiding the JSON.stringify(undefined) edge case and aligning the runtime value with the declared helper parameter type.

Also applies to: 55-57

🤖 Prompt for AI Agents
In src/generators/project/generateUseBlock.ts around lines 39-43 (and similarly
at 55-57), the code treats only null as “no config” but not undefined, causing
JSON.stringify(undefined) and .slice to throw; normalize pluginImport.config to
treat both null and undefined as absent (e.g., coalesce undefined to null or to
an empty object/string) before calling JSON.stringify and slicing, or check for
both null and undefined in the conditional so you only call JSON.stringify when
config is a real value; update both places to use the same normalized guard to
preserve existing null behavior while avoiding the undefined crash.

Comment on lines +38 to 67
// Build directory - use default if not provided (non-interactive mode)
const buildDirectory =
argumentConfiguration.buildDirectory ??
(await text({
message: 'Build directory:',
placeholder: 'build'
}));
if (isCancel(buildDirectory)) abort();
argumentConfiguration.buildDirectory ?? 'build';

// Assets directory
// Assets directory - use default if not provided (non-interactive mode)
const assetsDirectory =
argumentConfiguration.assetsDirectory ??
(await text({
message: 'Assets directory:',
placeholder: 'src/backend/assets'
}));
if (isCancel(assetsDirectory)) abort();
argumentConfiguration.assetsDirectory ?? 'src/backend/assets';

// Tailwind directory
// Tailwind directory - use defaults if not provided (non-interactive mode)
let tailwind;
if (useTailwind) {
const input =
argumentConfiguration.tailwind?.input ??
(await text({
message: 'Tailwind input CSS file:',
placeholder: './src/frontend/styles/tailwind.css'
}));
if (isCancel(input)) abort();
'./src/frontend/styles/tailwind.css';

const output =
argumentConfiguration.tailwind?.output ??
(await text({
message: 'Tailwind output CSS file:',
placeholder: '/assets/css/tailwind.generated.css'
}));
if (isCancel(output)) abort();
'/assets/css/tailwind.generated.css';

tailwind = { input, output };
} else {
tailwind = undefined;
}

// Database
// Database - use default if not provided (non-interactive mode)
let databaseDirectory;
if (databaseEngine !== undefined && databaseEngine !== 'none') {
databaseDirectory =
argumentConfiguration.databaseDirectory ??
(await text({
message: 'Database directory:',
placeholder: 'db'
}));
if (isCancel(databaseDirectory)) abort();
argumentConfiguration.databaseDirectory ?? 'db';
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Clarify intended behavior for custom directory configuration.

The non-default (custom) branch always uses defaults from argumentConfiguration or hardcoded fallbacks, with no interactive prompting—even when a user explicitly chooses "custom" configuration. This differs from frontendDirectoryConfigurations.ts, which detects non-interactive mode and prompts appropriately in interactive contexts.

Current behavior:

  • User selects "custom" configuration interactively
  • Expects to be prompted for custom directories (build, assets, tailwind, database)
  • Actually receives default values identical to "default" configuration
  • Custom values only work if passed via CLI arguments

Questions:

  1. Is this intentional? Should build/assets/tailwind/database directories support custom prompts in interactive mode?
  2. If not, should the "custom" option in getConfigurationType() clarify it only affects frontend directories?
  3. Should this function check isNonInteractive (like line 31 in frontendDirectoryConfigurations.ts) and prompt only when interactive?

If custom prompts are intended here, apply a pattern similar to frontendDirectoryConfigurations.ts:

+import process from 'node:process';
+import { isCancel, text } from '@clack/prompts';
+import { abort } from '../utils/abort';
+
 export const getDirectoryConfiguration = async ({
 	directoryConfig,
 	useTailwind,
 	databaseEngine,
 	argumentConfiguration
 }: GetDirectoryConfigurationProps) => {
 	if (directoryConfig === 'default') {
 		return {
 			assetsDirectory:
 				argumentConfiguration.assetsDirectory ?? 'src/backend/assets',
 			buildDirectory: argumentConfiguration.buildDirectory ?? 'build',
 			databaseDirectory:
 				databaseEngine !== undefined && databaseEngine !== 'none'
 					? (argumentConfiguration.databaseDirectory ?? 'db')
 					: undefined,
 			tailwind: useTailwind
 				? {
 						input:
 							argumentConfiguration.tailwind?.input ??
 							'./src/frontend/styles/tailwind.css',
 						output:
 							argumentConfiguration.tailwind?.output ??
 							'/assets/css/tailwind.generated.css'
 					}
 				: undefined
 		};
 	}

-	// Build directory - use default if not provided (non-interactive mode)
-	const buildDirectory =
-		argumentConfiguration.buildDirectory ?? 'build';
+	// Detect non-interactive environment
+	const isNonInteractive = !process.stdin.isTTY || !process.stdout.isTTY || !process.stdin.readable;
+
+	// Build directory
+	let buildDirectory = argumentConfiguration.buildDirectory;
+	if (buildDirectory === undefined) {
+		if (isNonInteractive) {
+			buildDirectory = 'build';
+		} else {
+			const response = await text({
+				message: 'Build directory:',
+				placeholder: 'build'
+			});
+			if (isCancel(response)) abort();
+			buildDirectory = response;
+		}
+	}

-	// Assets directory - use default if not provided (non-interactive mode)
-	const assetsDirectory =
-		argumentConfiguration.assetsDirectory ?? 'src/backend/assets';
+	// Assets directory
+	let assetsDirectory = argumentConfiguration.assetsDirectory;
+	if (assetsDirectory === undefined) {
+		if (isNonInteractive) {
+			assetsDirectory = 'src/backend/assets';
+		} else {
+			const response = await text({
+				message: 'Assets directory:',
+				placeholder: 'src/backend/assets'
+			});
+			if (isCancel(response)) abort();
+			assetsDirectory = response;
+		}
+	}

-	// Tailwind directory - use defaults if not provided (non-interactive mode)
 	let tailwind;
 	if (useTailwind) {
-		const input =
-			argumentConfiguration.tailwind?.input ??
-			'./src/frontend/styles/tailwind.css';
+		let input = argumentConfiguration.tailwind?.input;
+		if (input === undefined) {
+			if (isNonInteractive) {
+				input = './src/frontend/styles/tailwind.css';
+			} else {
+				const response = await text({
+					message: 'Tailwind input file:',
+					placeholder: './src/frontend/styles/tailwind.css'
+				});
+				if (isCancel(response)) abort();
+				input = response;
+			}
+		}

-		const output =
-			argumentConfiguration.tailwind?.output ??
-			'/assets/css/tailwind.generated.css';
+		let output = argumentConfiguration.tailwind?.output;
+		if (output === undefined) {
+			if (isNonInteractive) {
+				output = '/assets/css/tailwind.generated.css';
+			} else {
+				const response = await text({
+					message: 'Tailwind output file:',
+					placeholder: '/assets/css/tailwind.generated.css'
+				});
+				if (isCancel(response)) abort();
+				output = response;
+			}
+		}

 		tailwind = { input, output };
 	} else {
 		tailwind = undefined;
 	}

-	// Database - use default if not provided (non-interactive mode)
 	let databaseDirectory;
 	if (databaseEngine !== undefined && databaseEngine !== 'none') {
-		databaseDirectory =
-			argumentConfiguration.databaseDirectory ?? 'db';
+		databaseDirectory = argumentConfiguration.databaseDirectory;
+		if (databaseDirectory === undefined) {
+			if (isNonInteractive) {
+				databaseDirectory = 'db';
+			} else {
+				const response = await text({
+					message: 'Database directory:',
+					placeholder: 'db'
+				});
+				if (isCancel(response)) abort();
+				databaseDirectory = response;
+			}
+		}
 	}

 	return {
 		assetsDirectory,
 		buildDirectory,
 		databaseDirectory,
 		tailwind
 	};
 };

🏁 Script executed:

#!/bin/bash
# Find and examine frontendDirectoryConfigurations.ts to verify the pattern
fd -t f 'frontendDirectoryConfigurations' -x cat {}

Length of output: 2688


🏁 Script executed:

#!/bin/bash
# Find getConfigurationType to understand available configuration types
rg -n 'getConfigurationType' --type=ts -A 20

Length of output: 3332


🏁 Script executed:

#!/bin/bash
# Examine full directoryConfiguration.ts file to understand both branches
fd -t f 'directoryConfiguration.ts' -x cat {}

Length of output: 2078


🏁 Script executed:

#!/bin/bash
# Search for isNonInteractive pattern and usage
rg -n 'isNonInteractive' --type=ts -B 2 -A 2

Length of output: 610


🏁 Script executed:

#!/bin/bash
# Look for tests related to directory configuration
fd -t f -e 'test.ts' -e 'test.js' -e 'spec.ts' | xargs grep -l 'directoryConfiguration\|getDirectoryConfiguration' 2>/dev/null || echo "No test files found with this pattern"

Length of output: 37


🏁 Script executed:

#!/bin/bash
# Check recent git history/PR info if available
if [ -f '.git/config' ]; then
  git log --oneline -20 -- 'src/questions/directoryConfiguration.ts' 2>/dev/null || echo "No git history available"
fi

Length of output: 958


Add interactive mode prompting to custom directory configuration to match frontend behavior.

The custom branch (lines 38-67) never prompts for custom values, always using argumentConfiguration or hardcoded defaults—even when selected interactively. This differs from frontendDirectoryConfigurations.ts, which detects non-interactive environments (line 31) and prompts only when interactive.

Issue:

  • User selects "custom" configuration interactively → expects prompts for build, assets, tailwind, and database directories
  • Function ignores this and applies defaults regardless
  • Custom values only take effect via CLI arguments, making the UI selection non-functional

Fix:
Add isNonInteractive detection (process.stdin/stdout checks) and prompt only when interactive, mirroring the pattern already established in frontendDirectoryConfigurations.ts. Use defaults in non-interactive mode (CI/--skip).

+import process from 'node:process';
+import { isCancel, text } from '@clack/prompts';
+import { abort } from '../utils/abort';
+
 export const getDirectoryConfiguration = async ({
 	directoryConfig,
 	useTailwind,
 	databaseEngine,
 	argumentConfiguration
 }: GetDirectoryConfigurationProps) => {
 	if (directoryConfig === 'default') {
 		return {
 			assetsDirectory:
 				argumentConfiguration.assetsDirectory ?? 'src/backend/assets',
 			buildDirectory: argumentConfiguration.buildDirectory ?? 'build',
 			databaseDirectory:
 				databaseEngine !== undefined && databaseEngine !== 'none'
 					? (argumentConfiguration.databaseDirectory ?? 'db')
 					: undefined,
 			tailwind: useTailwind
 				? {
 						input:
 							argumentConfiguration.tailwind?.input ??
 							'./src/frontend/styles/tailwind.css',
 						output:
 							argumentConfiguration.tailwind?.output ??
 							'/assets/css/tailwind.generated.css'
 					}
 				: undefined
 		};
 	}

+	const isNonInteractive = !process.stdin.isTTY || !process.stdout.isTTY || !process.stdin.readable;
+
-	// Build directory - use default if not provided (non-interactive mode)
-	const buildDirectory =
-		argumentConfiguration.buildDirectory ?? 'build';
+	let buildDirectory = argumentConfiguration.buildDirectory;
+	if (buildDirectory === undefined) {
+		if (isNonInteractive) {
+			buildDirectory = 'build';
+		} else {
+			const response = await text({
+				message: 'Build directory:',
+				placeholder: 'build'
+			});
+			if (isCancel(response)) abort();
+			buildDirectory = response;
+		}
+	}

-	// Assets directory - use default if not provided (non-interactive mode)
-	const assetsDirectory =
-		argumentConfiguration.assetsDirectory ?? 'src/backend/assets';
+	let assetsDirectory = argumentConfiguration.assetsDirectory;
+	if (assetsDirectory === undefined) {
+		if (isNonInteractive) {
+			assetsDirectory = 'src/backend/assets';
+		} else {
+			const response = await text({
+				message: 'Assets directory:',
+				placeholder: 'src/backend/assets'
+			});
+			if (isCancel(response)) abort();
+			assetsDirectory = response;
+		}
+	}

-	// Tailwind directory - use defaults if not provided (non-interactive mode)
 	let tailwind;
 	if (useTailwind) {
-		const input =
-			argumentConfiguration.tailwind?.input ??
-			'./src/frontend/styles/tailwind.css';
+		let input = argumentConfiguration.tailwind?.input;
+		if (input === undefined) {
+			if (isNonInteractive) {
+				input = './src/frontend/styles/tailwind.css';
+			} else {
+				const response = await text({
+					message: 'Tailwind input file:',
+					placeholder: './src/frontend/styles/tailwind.css'
+				});
+				if (isCancel(response)) abort();
+				input = response;
+			}
+		}

-		const output =
-			argumentConfiguration.tailwind?.output ??
-			'/assets/css/tailwind.generated.css';
+		let output = argumentConfiguration.tailwind?.output;
+		if (output === undefined) {
+			if (isNonInteractive) {
+				output = '/assets/css/tailwind.generated.css';
+			} else {
+				const response = await text({
+					message: 'Tailwind output file:',
+					placeholder: '/assets/css/tailwind.generated.css'
+				});
+				if (isCancel(response)) abort();
+				output = response;
+			}
+		}

 		tailwind = { input, output };
 	} else {
 		tailwind = undefined;
 	}

-	// Database - use default if not provided (non-interactive mode)
 	let databaseDirectory;
 	if (databaseEngine !== undefined && databaseEngine !== 'none') {
-		databaseDirectory =
-			argumentConfiguration.databaseDirectory ?? 'db';
+		databaseDirectory = argumentConfiguration.databaseDirectory;
+		if (databaseDirectory === undefined) {
+			if (isNonInteractive) {
+				databaseDirectory = 'db';
+			} else {
+				const response = await text({
+					message: 'Database directory:',
+					placeholder: 'db'
+				});
+				if (isCancel(response)) abort();
+				databaseDirectory = response;
+			}
+		}
 	}

 	return {
 		assetsDirectory,
 		buildDirectory,
 		databaseDirectory,
 		tailwind
 	};
 };

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/questions/directoryConfiguration.ts around lines 38-67, the "custom"
branch always pulls values from argumentConfiguration or hardcoded defaults and
never prompts the user; update it to detect interactive mode (mirror
frontendDirectoryConfigurations.ts — e.g., check process.stdin.isTTY &&
process.stdout.isTTY or reuse the existing isNonInteractive helper) and only
apply non-interactive defaults when non-interactive; when interactive, prompt
for buildDirectory, assetsDirectory, tailwind (input and output) and
databaseDirectory (using argumentConfiguration values as the prompt defaults),
and keep using the hardcoded defaults when neither arguments nor interactive
input are provided so the behavior matches the frontend implementation.

Comment on lines +261 to +301
export const checkGitInstalled = async () => {
// Git is already installed
if (await hasGit()) return true;

// Prompt user to install Git
const proceed = await confirm({
initialValue: true,
message: 'Git is required for project initialization. Install it now?'
});

if (!proceed) return false;

// Attempt platform-specific installation
switch (hostEnv) {
case 'windows':
await installWindows();
break;
case 'darwin':
if (await commandExists('brew')) {
if (await brewInstall()) return hasGit();
}
console.log(
`${dim('│')}\n${yellow('▲')} Please install Git from: ${GIT_URL}`
);
break;
case 'wsl':
if (await installWSL()) return hasGit();
break;
case 'linux':
if (await installLinux()) return hasGit();
break;
}

// Installation failed or not automated - direct user to manual installation
console.log(
`${dim('│')}\n${yellow('▲')} Couldn't install Git automatically. Please download it from: ${GIT_URL}`
);
console.log(`${dim('│')} After installation, restart your terminal and try again.`);

return hasGit();
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Duplicate error messages due to inconsistent control flow.

The function prints redundant failure messages because platform-specific installers print their own messages before falling through to the generic fallback at lines 295-298. This results in duplicate messages in several scenarios:

  • Windows: Always prints both the Windows-specific message (lines 180-183 via installWindows) and the generic message (lines 295-298)
  • macOS: Prints duplicate messages when brew is unavailable or installation fails
  • WSL/Linux: When installation fails, platform wrappers print their own messages (lines 205-207, 239-241), then fall through to the generic message

Apply this diff to add early returns and eliminate duplicates:

 	// Attempt platform-specific installation
 	switch (hostEnv) {
 		case 'windows':
 			await installWindows();
+			return hasGit();
 		case 'darwin':
 			if (await commandExists('brew')) {
 				if (await brewInstall()) return hasGit();
+			} else {
+				console.log(
+					`${dim('│')}\n${yellow('▲')}  Please install Git from: ${GIT_URL}`
+				);
 			}
-			console.log(
-				`${dim('│')}\n${yellow('▲')}  Please install Git from: ${GIT_URL}`
-			);
-			break;
+			return hasGit();
 		case 'wsl':
 			if (await installWSL()) return hasGit();
-			break;
+			return hasGit();
 		case 'linux':
 			if (await installLinux()) return hasGit();
-			break;
+			return hasGit();
 	}
-	
-	// Installation failed or not automated - direct user to manual installation
-	console.log(
-		`${dim('│')}\n${yellow('▲')}  Couldn't install Git automatically. Please download it from: ${GIT_URL}`
-	);
-	console.log(`${dim('│')}   After installation, restart your terminal and try again.`);
-
-	return hasGit();
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const checkGitInstalled = async () => {
// Git is already installed
if (await hasGit()) return true;
// Prompt user to install Git
const proceed = await confirm({
initialValue: true,
message: 'Git is required for project initialization. Install it now?'
});
if (!proceed) return false;
// Attempt platform-specific installation
switch (hostEnv) {
case 'windows':
await installWindows();
break;
case 'darwin':
if (await commandExists('brew')) {
if (await brewInstall()) return hasGit();
}
console.log(
`${dim('│')}\n${yellow('▲')} Please install Git from: ${GIT_URL}`
);
break;
case 'wsl':
if (await installWSL()) return hasGit();
break;
case 'linux':
if (await installLinux()) return hasGit();
break;
}
// Installation failed or not automated - direct user to manual installation
console.log(
`${dim('│')}\n${yellow('▲')} Couldn't install Git automatically. Please download it from: ${GIT_URL}`
);
console.log(`${dim('│')} After installation, restart your terminal and try again.`);
return hasGit();
};
export const checkGitInstalled = async () => {
// Git is already installed
if (await hasGit()) return true;
// Prompt user to install Git
const proceed = await confirm({
initialValue: true,
message: 'Git is required for project initialization. Install it now?'
});
if (!proceed) return false;
// Attempt platform-specific installation
switch (hostEnv) {
case 'windows':
await installWindows();
return hasGit();
case 'darwin':
if (await commandExists('brew')) {
if (await brewInstall()) return hasGit();
} else {
console.log(
`${dim('│')}\n${yellow('▲')} Please install Git from: ${GIT_URL}`
);
}
return hasGit();
case 'wsl':
if (await installWSL()) return hasGit();
return hasGit();
case 'linux':
if (await installLinux()) return hasGit();
return hasGit();
}
};
🤖 Prompt for AI Agents
In src/utils/checkGitInstalled.ts around lines 261 to 301, the generic fallback
messages are printed even when platform-specific installers already printed
failure/success messages, causing duplicates; update the switch to return
immediately after any platform-specific install that either succeeds (return
hasGit()) or already displayed a failure message (return false) so the generic
"Couldn't install Git automatically" block is only reached when no platform
branch handled the outcome; specifically add early returns after
installWindows(), after the brew branch when brewInstall() is false or brew is
missing (return false), after installWSL() and installLinux() when they report
failure (return false), and keep the final generic fallback only for unhandled
paths, then return hasGit() only where appropriate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants