-
-
Notifications
You must be signed in to change notification settings - Fork 149
feat: Add SingleStore Helios database support #518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: Add SingleStore Helios database support #518
Conversation
🦋 Changeset detectedLatest commit: 9943774 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughAdds SingleStore as a database option and SingleStore Helios as a specialized db-setup across CLI, templates, validation, web UI, docs, and tests. Implements Drizzle-specific templates, a Helios env writer helper, runtime/UI compatibility guards, and expanded smoke and programmatic tests. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI
participant Validator
participant Installer
participant FS
User->>CLI: init --database singlestore --db-setup singlestore-helios --orm drizzle
CLI->>Validator: processAndValidateFlags (includes SingleStore checks)
Validator-->>CLI: validation OK
CLI->>Installer: db-setup dispatch -> setupSingleStoreHelios
Installer->>FS: ensure apps/server directory, write apps/server/.env (DATABASE_URL)
Installer-->>CLI: success + manual instructions
CLI-->>User: scaffolding complete
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Assessment against linked issues
Out-of-scope changes
Possibly related PRs
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. 📜 Recent review detailsConfiguration used: CodeRabbit UI 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (1)
🔇 Additional comments (4)
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
commit: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Nitpick comments (28)
apps/web/content/docs/index.mdx (1)
257-259
: Duplicate--addons
bullets — keep the extended list onlyThere are two
--addons
bullets; suggest removing the older list to avoid confusion and keep the extended list with new options.Apply this diff to deduplicate:
- - `--addons`: turborepo, pwa, tauri, biome, husky, starlight, none
apps/web/content/docs/cli/options.mdx (1)
123-124
: Tighten wording for Helios provider descriptionMinor clarity/grammar tweak: make the provider description explicit about being a managed/cloud setup.
Apply this diff:
- - `singlestore-helios`: SingleStore Helios (SingleStore) + - `singlestore-helios`: SingleStore Helios (cloud-hosted SingleStore)apps/web/content/docs/cli/compatibility.mdx (1)
132-133
: Minor wording polish for provider descriptionConsider clarifying the Helios provider note to be explicit about hosted nature.
Apply this diff:
-| `singlestore-helios` | `singlestore` | Cloud SingleStore database | +| `singlestore-helios` | `singlestore` | Cloud-hosted SingleStore database |apps/web/content/docs/cli/programmatic-api.mdx (1)
135-135
: Docs updated to include "singlestore" — consider adding a short compatibility noteThe addition is correct. To reduce misuse in programmatic usage, consider appending a brief note that SingleStore currently requires Drizzle and that the recommended dbSetup is "singlestore-helios" when using the managed cloud.
apps/cli/src/prompts/database-setup.ts (1)
94-102
: Default to Helios when SingleStore is selected?To mirror the “auto-selection of Helios for SingleStore” experience mentioned elsewhere, consider defaulting the select’s initialValue to Helios when databaseType is "singlestore" (keeps it consistent across channels). If you prefer not to change CLI behavior, feel free to ignore.
You could implement this by tweaking the select call:
const response = await select<DatabaseSetup>({ message: `Select ${databaseType} setup option`, options, initialValue: databaseType === "singlestore" ? "singlestore-helios" : "none", });apps/cli/src/helpers/project-generation/env-setup.ts (1)
188-188
: Manual SingleStore path results in empty DATABASE_URL — consider a helpful placeholderWhen database is "singlestore" and dbSetup is "none", databaseUrl remains null and we write a blank
DATABASE_URL=
. Consider adding a placeholder DSN to guide users doing manual/self-hosted setup.For example, in the switch that sets
databaseUrl
, add:case "singlestore": // Example DSN; adjust host/db to user environment. For Helios, add SSL params as required. databaseUrl = "mysql://user:password@localhost:3306/mydb"; // For Helios-like SSL: append ?ssl={\"rejectUnauthorized\":true} break;apps/cli/src/prompts/database.ts (1)
42-46
: Hide SingleStore when runtime is "workers"SingleStore (mysql2/Drizzle) targets Node/Bun; Workers are not supported. To reduce invalid selections later caught by validation, hide this option when
runtime === "workers"
.Apply this diff to remove the unconditional entry:
- { - value: "singlestore", - label: "SingleStore", - hint: "high-performance distributed SQL database for real-time analytics", - },Then, push it conditionally alongside MongoDB:
if (runtime !== "workers") { databaseOptions.push({ value: "singlestore", label: "SingleStore", hint: "high-performance distributed SQL database for real-time analytics", }); databaseOptions.push({ value: "mongodb", label: "MongoDB", hint: "open-source NoSQL database that stores data in JSON-like documents called BSON", }); }apps/cli/templates/examples/todo/server/drizzle/singlestore/src/db/schema/todo.ts (1)
1-7
: Schema LGTM; consider adding timestamps as a convenienceThe table definition is correct and idiomatic for Drizzle + SingleStore. Optionally, add createdAt/updatedAt columns for common patterns.
Example:
createdAt: timestamp("created_at").defaultNow().notNull(), updatedAt: timestamp("updated_at").onUpdateNow().defaultNow().notNull(),apps/cli/README.md (1)
176-181
: Example command is clear and accurateGood inclusion of Node runtime, Drizzle ORM, and singlestore-helios setup. Consider adding a brief note that Helios requires TLS and that DATABASE_URL will be written by the setup.
apps/cli/src/helpers/setup/db-setup.ts (1)
72-77
: Deduplicate dependency logic for MySQL-like backends (mysql & singlestore).Both branches install identical packages. Merge them to reduce drift and future maintenance.
- } else if (database === "mysql") { + } else if (database === "mysql" || database === "singlestore") { await addPackageDependency({ dependencies: ["drizzle-orm", "mysql2"], devDependencies: ["drizzle-kit"], projectDir: serverDir, }); - } else if (database === "singlestore") { - await addPackageDependency({ - dependencies: ["drizzle-orm", "mysql2"], - devDependencies: ["drizzle-kit"], - projectDir: serverDir, - }); }apps/cli/test/programmatic-api.test.ts (1)
175-191
: Strengthen the SingleStore + Drizzle test by asserting .env creation.Since Helios setup writes apps/server/.env with DATABASE_URL, add assertions to catch regressions in setup.
expect(result.success).toBe(true); assertBtsConfig(result.projectDirectory, { database: "singlestore", orm: "drizzle", }); + // Optional: verify Helios .env was created with DATABASE_URL + const envPath = join(result.projectDirectory, "apps/server", ".env"); + expect(existsSync(envPath)).toBe(true); + const envContent = readFileSync(envPath, "utf-8"); + expect(envContent).toMatch(/^\s*DATABASE_URL=/m);apps/cli/src/utils/compatibility-rules.ts (1)
134-170
: Centralize SingleStore validation and unify error text.Good addition. Two improvements:
- Align the wording to “requires Drizzle ORM” to be consistent with other checks/tests.
- Remove duplicated checks in validation.ts and rely on this function as the single source of truth.
if ( providedFlags.has("database") && options.database === "singlestore" && config.orm && config.orm !== "drizzle" ) { exitWithError( - `SingleStore database is only compatible with Drizzle ORM. Current ORM: ${config.orm}. Please use '--orm drizzle' or choose a different database.`, + `SingleStore database requires Drizzle ORM. Current ORM: ${config.orm}. Please use '--orm drizzle' or choose a different database.`, ); } if ( providedFlags.has("orm") && config.orm && config.orm !== "drizzle" && config.database === "singlestore" ) { exitWithError( - `ORM '${config.orm}' is not compatible with SingleStore database. SingleStore only supports Drizzle ORM. Please use '--orm drizzle' or choose a different database.`, + `ORM '${config.orm}' is not compatible with SingleStore database. SingleStore requires Drizzle ORM. Please use '--orm drizzle' or choose a different database.`, ); } if ( providedFlags.has("dbSetup") && options.dbSetup === "singlestore-helios" && config.database !== "singlestore" ) { exitWithError( `SingleStore Helios setup (--db-setup singlestore-helios) requires SingleStore database. Current database: ${config.database}. Please use '--database singlestore' or choose a different database setup.`, ); }apps/cli/src/validation.ts (2)
251-261
: Remove duplicated SingleStore ORM compatibility check; rely on compatibility-rules.ts.This block duplicates validateSingleStoreCompatibility and risks message drift.
- if ( - providedFlags.has("database") && - providedFlags.has("orm") && - config.database === "singlestore" && - config.orm && - config.orm !== "drizzle" - ) { - exitWithError( - "SingleStore database requires Drizzle ORM. Please use '--orm drizzle' or choose a different database.", - ); - }
365-374
: Remove duplicated Helios setup check; rely on compatibility-rules.ts.Avoid duplication; keep validation rules in one place.
- if ( - providedFlags.has("dbSetup") && - (config.database ? providedFlags.has("database") : true) && - config.dbSetup === "singlestore-helios" && - config.database !== "singlestore" - ) { - exitWithError( - "SingleStore Helios setup requires SingleStore database. Please use '--database singlestore' or choose a different setup.", - ); - }apps/cli/src/helpers/database-providers/singlestore-helios-setup.ts (3)
11-14
: Remove unused SingleStoreHeliosConfig type.It’s not used and suggests a non-existent config.connectionString property on ProjectConfig.
-type SingleStoreHeliosConfig = { - connectionString: string; -};
15-34
: Simplify writeEnvFile signature and fix placeholder value.
- The config param is unused; drop it.
- Placeholder uses ssl=require, but below instructions say ssl={}. Pick one format and keep it consistent.
-async function writeEnvFile( - projectDir: string, - config?: SingleStoreHeliosConfig, -) { +async function writeEnvFile(projectDir: string) { try { const envPath = path.join(projectDir, "apps/server", ".env"); const variables: EnvVariable[] = [ { key: "DATABASE_URL", - value: - config?.connectionString ?? - "singlestore://username:password@host:port/database?ssl=require", + value: "mysql://USERNAME:PASSWORD@HOST:PORT/DATABASE?ssl={\"rejectUnauthorized\":true}", condition: true, }, ]; await addEnvVariablesToFile(envPath, variables); } catch (_error) { log.error("Failed to update environment configuration"); } }
68-73
: Nit: Clarify which .env file was written.Improve UX by pointing to apps/server/.env explicitly in the success message.
- "SingleStore Helios setup complete! Please update the connection string in .env file.", + "SingleStore Helios setup complete! Please update the connection string in apps/server/.env.",apps/cli/test/cli.smoke.test.ts (9)
1150-1194
: Solid baseline SingleStore + Drizzle scaffold test. Consider asserting dbSetup.This covers the happy-path scaffold and config assertions for SingleStore + Drizzle. One improvement: assert that the selected db-setup (“singlestore-helios”) is also reflected in bts.jsonc to guard against regressions in config writing.
1196-1250
: Good coverage of drizzle dialect and mysql2 driver.
- Asserting drizzle.config.ts includes
dialect: "singlestore"
anddrizzle-orm/singlestore
imports is on point.- Checking
mysql2/promise
and dependency inclusion is also appropriate.Optional: also assert the drizzle config references
process.env.DATABASE_URL
to ensure environment plumbing is intact.
1252-1303
: Schema assertion is a bit brittle; iterate through schema files.Picking the first .ts file may miss the intended table if another file happens to be first. Iterate through all .ts files in the schema directory and assert at least one contains
singlestoreTable
.Apply within this test body:
- const schemaFiles = require("node:fs").readdirSync(schemaDir); - const schemaFile = schemaFiles.find((file: string) => - file.endsWith(".ts"), - ); - - if (schemaFile) { - const schemaPath = join(schemaDir, schemaFile); - const schemaContent = readFileSync(schemaPath, "utf8"); - expect(schemaContent).toContain("singlestoreTable"); - } + const schemaFiles = require("node:fs").readdirSync(schemaDir).filter((f: string) => f.endsWith(".ts")); + expect(schemaFiles.length).toBeGreaterThan(0); + const anyUsesSingleStore = schemaFiles.some((file: string) => { + const schemaPath = join(schemaDir, file); + const schemaContent = readFileSync(schemaPath, "utf8"); + return schemaContent.includes("singlestoreTable"); + }); + expect(anyUsesSingleStore).toBe(true);
1305-1362
: Env checks are OK; consider tightening the SSL assertion to catch malformed values.The regex and
?ssl=
checks are adequate. If you want to make it a bit stricter without overfitting, assert?ssl=true
or?ssl=%7B
(JSON-encoded) or?ssl={
(quoted) to catch accidental empties:- expect(databaseUrl).toMatch(/singlestore:\/\/.*\?ssl/); + expect(databaseUrl).toMatch(/singlestore:\/\/.+\?ssl(=|%3D)(true|%7B|{|%22|\S+)/i);
1412-1471
: Great TODO-schema assertions; consider also checking a bigint primary key.You’re already checking
singlestoreTable
andbigint(
for the TODO example. Optionally add a more specific assertion that id is bigint primary key (if template guarantees it) to further reduce false positives.
1717-1748
: Negative case: Prisma + SingleStore rejection. Consider asserting the error message.The failure path is verified, but we don’t validate the error content. Asserting a helpful, explicit error message will protect UX and prevent regressions.
- await runCliExpectingError( + await runCliExpectingError( [ // ... ], workdir, ); + // Optionally, read stderr captured by a wrapped runner and assert: + // expect(stderr).toMatch(/SingleStore.*requires Drizzle/i);
1750-1781
: Negative case: Mongoose + SingleStore rejection. Mirror error-message assertion.Same recommendation as above—assert a meaningful error string like “SingleStore requires Drizzle ORM.”
1783-1814
: Negative case: Helios with non-SingleStore DB. Mirror error-message assertion.Good guard. Suggest also asserting the error mentions Helios requires SingleStore to keep user feedback crisp.
2885-2886
: “singlestore-hono-node” appears in build list but isn’t scaffolded above.The build loop will skip it if the directory is absent, but it’s confusing. Either add a matching scaffold test for this project or drop it from the build set to avoid noise.
apps/web/src/app/(home)/_components/stack-builder.tsx (2)
1708-1721
: Tighten ORM options when SingleStore is selected (hide 'none').You currently show 'drizzle' and 'none' for SingleStore, but the rules require Drizzle. Hiding 'none' reduces user confusion and churn in the auto-adjust toast.
- if (stack.database === "singlestore") { - return option.id === "drizzle" || option.id === "none"; - } + if (stack.database === "singlestore") { + return option.id === "drizzle"; + }
1708-1756
: Avoid duplication: centralize compatibility constraints for filtering and analysis.Filtering logic and analyzeStackCompatibility encode similar rules (allowed ORMs, allowed setups). Consider extracting a small config map (e.g., allowedOrmsByDb, allowedSetupsByDb, requiredDbBySetup, requiredOrmBySetup) and using it in both places to prevent drift.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
bun.lock
is excluded by!**/*.lock
📒 Files selected for processing (22)
apps/cli/README.md
(5 hunks)apps/cli/src/helpers/database-providers/singlestore-helios-setup.ts
(1 hunks)apps/cli/src/helpers/project-generation/env-setup.ts
(1 hunks)apps/cli/src/helpers/setup/db-setup.ts
(3 hunks)apps/cli/src/prompts/database-setup.ts
(1 hunks)apps/cli/src/prompts/database.ts
(1 hunks)apps/cli/src/types.ts
(2 hunks)apps/cli/src/utils/compatibility-rules.ts
(1 hunks)apps/cli/src/validation.ts
(4 hunks)apps/cli/templates/db/drizzle/singlestore/drizzle.config.ts.hbs
(1 hunks)apps/cli/templates/db/drizzle/singlestore/src/db/index.ts.hbs
(1 hunks)apps/cli/templates/examples/todo/server/drizzle/singlestore/src/db/schema/todo.ts
(1 hunks)apps/cli/test/cli.smoke.test.ts
(4 hunks)apps/cli/test/programmatic-api.test.ts
(2 hunks)apps/web/content/docs/cli/compatibility.mdx
(4 hunks)apps/web/content/docs/cli/index.mdx
(1 hunks)apps/web/content/docs/cli/options.mdx
(2 hunks)apps/web/content/docs/cli/programmatic-api.mdx
(1 hunks)apps/web/content/docs/compatibility.mdx
(1 hunks)apps/web/content/docs/index.mdx
(1 hunks)apps/web/src/app/(home)/_components/stack-builder.tsx
(4 hunks)apps/web/src/lib/constant.ts
(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (5)
apps/cli/src/utils/compatibility-rules.ts (2)
apps/cli/src/types.ts (2)
CLIInput
(149-151)ProjectConfig
(153-171)apps/cli/src/utils/errors.ts (1)
exitWithError
(9-15)
apps/cli/src/helpers/database-providers/singlestore-helios-setup.ts (1)
apps/cli/src/helpers/project-generation/env-setup.ts (2)
EnvVariable
(6-10)addEnvVariablesToFile
(12-85)
apps/cli/test/programmatic-api.test.ts (1)
apps/cli/src/index.ts (1)
init
(216-228)
apps/cli/src/helpers/setup/db-setup.ts (2)
apps/cli/src/utils/add-package-deps.ts (1)
addPackageDependency
(6-43)apps/cli/src/helpers/database-providers/singlestore-helios-setup.ts (1)
setupSingleStoreHelios
(57-86)
apps/cli/src/validation.ts (2)
apps/cli/src/utils/errors.ts (1)
exitWithError
(9-15)apps/cli/src/utils/compatibility-rules.ts (1)
validateSingleStoreCompatibility
(134-170)
🪛 LanguageTool
apps/web/content/docs/cli/options.mdx
[grammar] ~123-~123: There might be a mistake here.
Context: ...elios: SingleStore Helios (SingleStore) -
docker`: Local Docker containers ```bash creat...
(QB_NEW_EN)
apps/web/content/docs/index.mdx
[grammar] ~254-~254: There might be a mistake here.
Context: ...tgres, mysql, mongodb, singlestore, none - --orm
: drizzle, prisma, mongoose, none - `--a...
(QB_NEW_EN)
apps/web/content/docs/cli/compatibility.mdx
[grammar] ~20-~20: There might be a mistake here.
Context: ...h-performance distributed SQL database | | none
| none
| No database setup | ...
(QB_NEW_EN)
[grammar] ~109-~109: There might be a mistake here.
Context: ...s**: ❌ Only one native framework allowed - Web + Native: ✅ One web and one native...
(QB_NEW_EN)
[grammar] ~132-~132: There might be a mistake here.
Context: ...glestore| Cloud SingleStore database | |
docker|
postgres,
mysql,
mongo...
(QB_NEW_EN)
[grammar] ~183-~183: There might be a mistake here.
Context: ...eand
--database none ### AI Example - Not compatible with
--backend elysia` -...
(QB_NEW_EN)
🔇 Additional comments (30)
apps/web/content/docs/index.mdx (1)
254-254
: Add SingleStore to database flags — looks goodThe new
singlestore
entry in the flags cheat sheet is accurate and consistent with the PR scope.apps/web/content/docs/cli/options.mdx (1)
93-94
: Add SingleStore to database types — looks correctThe new
singlestore
option under database types aligns with compatibility and templates added in this PR.apps/web/content/docs/compatibility.mdx (1)
14-15
: Compatibility rule for SingleStore + Drizzle — approvedClear rule; matches CLI validation and UI auto-selection behavior introduced in this PR.
apps/web/content/docs/cli/index.mdx (2)
33-34
: Exposesinglestore
in--database
options — approvedAccurate reflection of new support.
36-37
: Exposesinglestore-helios
in--db-setup
options — approvedMatches the new setup handler and templates.
apps/web/content/docs/cli/compatibility.mdx (3)
20-21
: Add SingleStore + Drizzle to compatibility matrix — approvedRow content and note are accurate.
26-27
: Restrict SingleStore to Drizzle — approvedThe restriction text is clear and consistent with CLI validation.
183-186
: AI Example section update — approvedSection header and notes read clearly and match other docs.
apps/cli/src/types.ts (1)
4-4
: Enums extended with "singlestore" and "singlestore-helios" — LGTMThe schema updates are consistent and align with the new prompts and setup flows.
Also applies to: 73-73
apps/cli/src/prompts/database-setup.ts (1)
94-102
: SingleStore setup prompt options — LGTMThe Helios and manual setup options for SingleStore are clear and correctly wired to the DatabaseSetup schema.
apps/cli/src/helpers/project-generation/env-setup.ts (1)
188-188
: Skipping generic DATABASE_URL for "singlestore-helios" — LGTMThis prevents duplicate or conflicting values and delegates DATABASE_URL creation to the specialized Helios setup helper as intended.
apps/cli/src/prompts/database.ts (1)
42-46
: Add SingleStore option — LGTMClear label and hint; integrates well with the existing prompt.
apps/cli/templates/db/drizzle/singlestore/src/db/index.ts.hbs (2)
2-3
: Correct driver and dialect importsmysql2/promise with drizzle-orm/singlestore is the right pairing for SingleStore + Drizzle.
7-7
: Confirm drizzle({ client }) signature support for singlestore driverRecent Drizzle versions generally accept drizzle({ client }) across drivers, but older patterns use drizzle(pool) for mysql2. Given you’ve pinned drizzle-orm to ^0.44.2, this should be fine—please confirm compile/runtime behavior.
If you see type errors, switch to the positional form:
-export const db = drizzle({ client: pool }); +export const db = drizzle(pool);Also applies to: 17-17
apps/web/src/lib/constant.ts (2)
249-255
: New “SingleStore” database option looks consistentIcon, color, naming, and placement align with existing entries. No conflicts with existing defaults (SQLite remains default).
338-344
: Auto-selection logic for SingleStore Helios is in placeBoth the UI filter and the setup auto-select behavior exist in
stack-builder.tsx
:
- In the options renderer (≈ lines 1724–1730), when
stack.database === "singlestore"
, only"singlestore-helios"
and"none"
are shown.- In the stack initialization (≈ lines 402–411), if
nextStack.database === "singlestore"
andnextStack.dbSetup === "none"
,nextStack.dbSetup
is automatically set to"singlestore-helios"
with accompanying notes/changes.No further changes required.
apps/cli/README.md (4)
39-39
: Docs: SingleStore correctly added to Database matrixMatches the new option id and naming used in code.
56-56
: CLI flag docs: database types now include singlestoreConsistent with code and tests; no issues.
68-68
: CLI flag docs: db-setup includes singlestore-heliosAccurate and aligned with the new setup flow.
199-199
: Compatibility note aligns with implementationStates Drizzle-only and auto-Helios selection, which matches the codebase intent and validation.
apps/cli/src/helpers/setup/db-setup.ts (1)
103-105
: LGTM: Helios setup is correctly dispatched.The condition correctly scopes Helios setup to the SingleStore database.
apps/cli/test/programmatic-api.test.ts (1)
281-292
: LGTM: Incompatible SingleStore + Prisma path is properly asserted.Regex is resilient to minor message changes.
apps/cli/src/validation.ts (2)
23-26
: LGTM: New SingleStore validation imported and integrated.
423-424
: LGTM: Centralized SingleStore validation is invoked after core validations.apps/cli/test/cli.smoke.test.ts (2)
1366-1410
: Auth + SingleStore scenario: good end-to-end assertion.Asserts for auth + DB + server presence and config flags look good.
2862-2863
: Including app-singlestore-drizzle in the build list aligns with earlier scaffolding.This name is scaffolded above, so the build step will process it if WITH_BUILD=1. LGTM.
apps/web/src/app/(home)/_components/stack-builder.tsx (4)
385-401
: Correctly enforcing Drizzle for SingleStore.This auto-correction aligns with the compatibility rules. Good handling of notes/changes too.
553-587
: Helios setup cross-checks are spot on.Enforcing
database='singlestore'
andorm='drizzle'
whendbSetup='singlestore-helios'
keeps the state consistent. Nice.
1011-1019
: Command generation: correct to require explicit --database when Helios is chosen.Including 'singlestore-helios' in the explicit-database set ensures CLI reproducibility. LGTM.
1723-1756
: DB Setup filtering for SingleStore looks correct.Limiting to 'singlestore-helios' and 'none' matches the documented support. Good.
function displayManualSetupInstructions() { | ||
log.info(` | ||
${pc.green("SingleStore Helios Manual Setup Instructions:")} | ||
|
||
1. Sign up for SingleStore Cloud at: | ||
${pc.blue("https://www.singlestore.com/cloud")} | ||
|
||
2. Create a new workspace from the dashboard | ||
|
||
3. Get your connection string from the workspace details: | ||
Format: ${pc.dim("singlestore://USERNAME:PASSWORD@HOST:PORT/DATABASE?ssl={}")} | ||
|
||
4. Add the connection string to your .env file: | ||
${pc.dim('DATABASE_URL="your_connection_string"')} | ||
|
||
${pc.yellow("Important:")} | ||
- The connection string MUST include ${pc.bold("ssl={}")} at the end | ||
- Use the singlestore:// protocol for SingleStore connections | ||
- SingleStore requires SSL connections for cloud deployments`); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Inconsistent connection string scheme and SSL parameter.
Instructions say “singlestore://... ssl={}” while the placeholder used “...ssl=require”. For mysql2, a common pattern is mysql:// with ssl={"rejectUnauthorized":true}. Standardize both the placeholder and the docs to the same, tested format.
Please confirm the correct scheme and SSL parameter expected by mysql2 and Drizzle for SingleStore Helios:
Proposed update (pending confirmation):
- Format: ${pc.dim("singlestore://USERNAME:PASSWORD@HOST:PORT/DATABASE?ssl={}")}
+ Format: ${pc.dim('mysql://USERNAME:PASSWORD@HOST:PORT/DATABASE?ssl={"rejectUnauthorized":true}')}
@@
-${pc.yellow("Important:")}
-- The connection string MUST include ${pc.bold("ssl={}")} at the end
-- Use the singlestore:// protocol for SingleStore connections
-- SingleStore requires SSL connections for cloud deployments`);
+${pc.yellow("Important:")}
+- The connection string MUST include a valid ${pc.bold("ssl")} parameter
+- Use the ${pc.bold("mysql://")} protocol (mysql2 driver)
+- SingleStore Helios requires SSL connections`);
🌐 Web query:
What is the correct connection string format (scheme and SSL parameter) for connecting to SingleStore Helios using the mysql2 driver (and Drizzle ORM)? Does mysql2 accept a singlestore:// scheme, or should we use mysql:// with an SSL JSON object (e.g., ssl={"rejectUnauthorized":true})?
💡 Result:
To connect to SingleStore Helios using the mysql2 driver (and Drizzle ORM), you should use the mysql:// scheme in your connection string, not singlestore://. The mysql2 driver does not natively support singlestore:// URIs, and SingleStore is specifically designed to be MySQL wire-compatible for maximum tooling compatibility[1][4][5][8].
For SSL/TLS, you must specify an ssl
parameter in the connection options. This can be either as part of a connection URI with SSL query parameters or, more commonly, as a JSON object when using programmatic connection:
- With URI/connection string:
mysql://user:password@host:port/database?ssl={"rejectUnauthorized":true}
- As a configuration object (recommended):
{ host: '<endpoint>', port: 3306, user: '<username>', password: '<password>', database: '<database>', ssl: { rejectUnauthorized: true } }
Key points:
- Use mysql://, not singlestore:// with mysql2.
- Set the endpoint as provided in the SingleStore Cloud Portal.
- Port is typically 3306.
- For SSL, set
ssl: { rejectUnauthorized: true }
(you can further provide a CA if needed). - Drizzle ORM will pass options to mysql2, so use the same approach as mysql2 expects[5][1][4].
While some documentation examples (including [5]) show a singlestore:// URI, this is for SingleStore’s own native drivers or wrappers. The mysql2 NPM package (and most node/mysql libraries) will not recognize singlestore://—they only support mysql:// as the URI scheme[5][4].
Reference connection:
const connection = mysql.createConnection({
host: "<endpoint>.svc.singlestore.com",
port: 3306,
user: "<user>",
password: "<password>",
database: "<database>",
ssl: {
rejectUnauthorized: true
// Optionally: ca: fs.readFileSync('path/to/cert.pem')
}
});
Summary Table
Parameter/Option | Value/Notes |
---|---|
Scheme/Protocol | mysql:// (not singlestore://) |
Host | SingleStore Helios endpoint |
Port | 3306 |
User | Your database username |
Password | Your database password |
Database | Your database name |
SSL | ssl: { rejectUnauthorized: true } (pass as object) |
CA bundle (Optional) | ssl: { ca: fs.readFileSync('path/to/bundle.pem') } if required |
Conclusion:
Use the mysql://
scheme and provide the SSL object as specified for secure connections to SingleStore Helios via the mysql2 driver. Do not use singlestore://
URIs with mysql2, including with Drizzle ORM[5][4][1].
Citations:
- 1: https://docs.singlestore.com/cloud/connect-to-singlestore/connect-with-mysql/connect-with-mysql-client/
- 2: https://docs.singlestore.com/cloud/connect-to-singlestore/connect-with-mysql/connect-with-mysql-client/connect-to-singlestore-helios-using-tls-ssl/
- 3: https://docs.singlestore.com/cloud/connect-to-singlestore/
- 4: https://docs.singlestore.com/cloud/connect-to-singlestore/connect-with-mysql/connect-with-any-mysql-compatible-tool-to-singlestore-helios/
- 5: https://www.singlestore.com/developers/build/nodejs/mysql2/
- 6: https://docs.singlestore.com/cloud/developer-resources/connect-with-application-development-tools/connect-with-java-jdbc/the-singlestore-jdbc-driver/
- 7: https://docs.singlestore.com/cloud/developer-resources/connect-with-application-development-tools/connect-with-odbc/the-singlestore-odbc-driver/
- 8: https://docs.singlestore.com/cloud/connect-to-singlestore/connect-with-sql-workbench/
- 9: https://docs.singlestore.com/cloud/developer-resources/connect-with-application-development-tools/connect-with-odbc/
- 10: https://docs.singlestore.com/cloud/connect-to-singlestore/client-and-driver-downloads/
Update SingleStore Helios Manual Setup Instructions
The mysql2 driver (and Drizzle ORM) requires a mysql:// URI and an SSL JSON object (ssl={"rejectUnauthorized":true}
), not singlestore:// or an empty ssl={}
.
File: apps/cli/src/helpers/database-providers/singlestore-helios-setup.ts (lines 36–55)
- Change the connection-string scheme from
singlestore://
tomysql://
. - Replace the empty
ssl={}
placeholder withssl={"rejectUnauthorized":true}
. - Update the “Important” notes accordingly.
function displayManualSetupInstructions() {
log.info(`
${pc.green("SingleStore Helios Manual Setup Instructions:")}
1. Sign up for SingleStore Cloud at:
${pc.blue("https://www.singlestore.com/cloud")}
2. Create a new workspace from the dashboard
3. Get your connection string from the workspace details:
- Format: ${pc.dim("singlestore://USERNAME:PASSWORD@HOST:PORT/DATABASE?ssl={}")}
+ Format: ${pc.dim('mysql://USERNAME:PASSWORD@HOST:PORT/DATABASE?ssl={"rejectUnauthorized":true}')}
4. Add the connection string to your .env file:
${pc.dim('DATABASE_URL="your_connection_string"')}
${pc.yellow("Important:")}
- - The connection string MUST include ${pc.bold("ssl={}")} at the end
- - Use the ${pc.bold("singlestore://")} protocol for SingleStore connections
+ - The connection string MUST include a valid ${pc.bold("ssl")} parameter (e.g., {"rejectUnauthorized":true})
+ - Use the ${pc.bold("mysql://")} protocol (mysql2 driver)
- SingleStore Helios requires SSL connections for cloud deployments`);
}
📝 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.
function displayManualSetupInstructions() { | |
log.info(` | |
${pc.green("SingleStore Helios Manual Setup Instructions:")} | |
1. Sign up for SingleStore Cloud at: | |
${pc.blue("https://www.singlestore.com/cloud")} | |
2. Create a new workspace from the dashboard | |
3. Get your connection string from the workspace details: | |
Format: ${pc.dim("singlestore://USERNAME:PASSWORD@HOST:PORT/DATABASE?ssl={}")} | |
4. Add the connection string to your .env file: | |
${pc.dim('DATABASE_URL="your_connection_string"')} | |
${pc.yellow("Important:")} | |
- The connection string MUST include ${pc.bold("ssl={}")} at the end | |
- Use the singlestore:// protocol for SingleStore connections | |
- SingleStore requires SSL connections for cloud deployments`); | |
} | |
function displayManualSetupInstructions() { | |
log.info(` | |
${pc.green("SingleStore Helios Manual Setup Instructions:")} | |
1. Sign up for SingleStore Cloud at: | |
${pc.blue("https://www.singlestore.com/cloud")} | |
2. Create a new workspace from the dashboard | |
3. Get your connection string from the workspace details: | |
Format: ${pc.dim('mysql://USERNAME:PASSWORD@HOST:PORT/DATABASE?ssl={"rejectUnauthorized":true}')} | |
4. Add the connection string to your .env file: | |
${pc.dim('DATABASE_URL="your_connection_string"')} | |
${pc.yellow("Important:")} | |
- The connection string MUST include a valid ${pc.bold("ssl")} parameter (e.g., {"rejectUnauthorized":true}) | |
- Use the ${pc.bold("mysql://")} protocol (mysql2 driver) | |
- SingleStore Helios requires SSL connections for cloud deployments`); | |
} |
🤖 Prompt for AI Agents
In apps/cli/src/helpers/database-providers/singlestore-helios-setup.ts around
lines 36 to 55, update the manual setup text to use the mysql driver URI and
correct SSL JSON: change the example connection scheme from singlestore:// to
mysql://, replace the placeholder ssl={} with ssl={"rejectUnauthorized":true} in
the Format and .env examples, and adjust the “Important” notes to state use the
mysql:// protocol and include ssl={"rejectUnauthorized":true} (not an empty
object) for SSL configuration required by mysql2/Drizzle.
import { defineConfig } from "drizzle-kit"; | ||
|
||
export default defineConfig({ | ||
schema: "./src/db/schema", | ||
out: "./src/db/migrations", | ||
dialect: "singlestore", | ||
dbCredentials: { | ||
url: process.env.DATABASE_URL || "", | ||
}, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Load .env early and fail fast when DATABASE_URL is missing
drizzle-kit runs this file directly; without importing dotenv, DATABASE_URL often won’t be present. Falling back to "" hides config mistakes.
Apply this diff:
+import "dotenv/config";
import { defineConfig } from "drizzle-kit";
-export default defineConfig({
- schema: "./src/db/schema",
- out: "./src/db/migrations",
- dialect: "singlestore",
- dbCredentials: {
- url: process.env.DATABASE_URL || "",
- },
-});
+const url = process.env.DATABASE_URL;
+if (!url) {
+ throw new Error("DATABASE_URL is not set. Please set it (SingleStore Helios requires TLS).");
+}
+
+export default defineConfig({
+ schema: "./src/db/schema",
+ out: "./src/db/migrations",
+ dialect: "singlestore",
+ dbCredentials: {
+ url,
+ },
+});
📝 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.
import { defineConfig } from "drizzle-kit"; | |
export default defineConfig({ | |
schema: "./src/db/schema", | |
out: "./src/db/migrations", | |
dialect: "singlestore", | |
dbCredentials: { | |
url: process.env.DATABASE_URL || "", | |
}, | |
}); | |
import "dotenv/config"; | |
import { defineConfig } from "drizzle-kit"; | |
const url = process.env.DATABASE_URL; | |
if (!url) { | |
throw new Error("DATABASE_URL is not set. Please set it (SingleStore Helios requires TLS)."); | |
} | |
export default defineConfig({ | |
schema: "./src/db/schema", | |
out: "./src/db/migrations", | |
dialect: "singlestore", | |
dbCredentials: { | |
url, | |
}, | |
}); |
🤖 Prompt for AI Agents
In apps/cli/templates/db/drizzle/singlestore/drizzle.config.ts.hbs around lines
1 to 10, dotenv is not loaded before reading DATABASE_URL and the code silently
falls back to an empty string; load environment variables early (e.g., require
or import and call dotenv.config() at top of the file) and then validate
process.env.DATABASE_URL exists, throwing an error or exiting with a non-zero
status if it's missing so the process fails fast; finally set dbCredentials.url
to process.env.DATABASE_URL (no empty fallback).
const pool = mysql.createPool(process.env.DATABASE_URL || ""); | ||
|
||
export const db = drizzle({ client: pool }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fail fast on missing DATABASE_URL and avoid empty-string fallback
Silently passing "" to createPool will defer failures to runtime and make debugging harder. Also, Helios requires TLS; ensure the env-provided URL includes ssl params or configure ssl in code.
Apply this diff to validate the env and add basic pool options (keeps URL-driven SSL; if you prefer code-driven SSL, I can provide that too):
-const pool = mysql.createPool(process.env.DATABASE_URL || "");
+const url = process.env.DATABASE_URL;
+if (!url) {
+ throw new Error("DATABASE_URL is not set. SingleStore Helios requires a valid TLS connection string.");
+}
+const pool = mysql.createPool({
+ uri: url,
+ waitForConnections: true,
+ connectionLimit: 10,
+ maxIdle: 10,
+ queueLimit: 0,
+ enableKeepAlive: true,
+});
📝 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.
const pool = mysql.createPool(process.env.DATABASE_URL || ""); | |
export const db = drizzle({ client: pool }); | |
const url = process.env.DATABASE_URL; | |
if (!url) { | |
throw new Error("DATABASE_URL is not set. SingleStore Helios requires a valid TLS connection string."); | |
} | |
const pool = mysql.createPool({ | |
uri: url, | |
waitForConnections: true, | |
connectionLimit: 10, | |
maxIdle: 10, | |
queueLimit: 0, | |
enableKeepAlive: true, | |
}); | |
export const db = drizzle({ client: pool }); |
{{#if (eq runtime "workers")}} | ||
import mysql from "mysql2/promise"; | ||
import { drizzle } from "drizzle-orm/singlestore"; | ||
import { env } from "cloudflare:workers"; | ||
|
||
const pool = mysql.createPool(env.DATABASE_URL || ""); | ||
|
||
export const db = drizzle({ client: pool }); | ||
{{/if}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Cloudflare Workers block will not work with mysql2 (TCP sockets not supported)
Workers don’t support Node TCP sockets used by mysql2; this will fail to bundle/run. Your README also states Workers is only compatible with SQLite/D1 and not SingleStore.
Replace the Workers block with an explicit error to avoid generating broken code (or remove it entirely):
-{{#if (eq runtime "workers")}}
-import mysql from "mysql2/promise";
-import { drizzle } from "drizzle-orm/singlestore";
-import { env } from "cloudflare:workers";
-
-const pool = mysql.createPool(env.DATABASE_URL || "");
-
-export const db = drizzle({ client: pool });
-{{/if}}
+{{#if (eq runtime "workers")}}
+// SingleStore is not supported on Cloudflare Workers (mysql2 requires TCP sockets).
+// Choose Bun or Node.js runtime for SingleStore.
+throw new Error("SingleStore is not supported on Cloudflare Workers. Use Bun or Node.js.");
+{{/if}}
Run this quick check to ensure no other SingleStore Workers templates slipped in:
🏁 Script executed:
#!/bin/bash
rg -n -C2 -i 'singlestore' apps | rg -n -C2 -i 'workers'
Length of output: 5590
Avoid generating broken SingleStore code for Workers
Cloudflare Workers do not support Node TCP sockets required by mysql2, so the existing template will fail at build/runtime. Replace the workers
branch with an explicit error to prevent generating unusable code.
Files to update:
- apps/cli/templates/db/drizzle/singlestore/src/db/index.ts.hbs (lines 10–18)
Suggested diff:
-{{#if (eq runtime "workers")}}
-import mysql from "mysql2/promise";
-import { drizzle } from "drizzle-orm/singlestore";
-import { env } from "cloudflare:workers";
-
-const pool = mysql.createPool(env.DATABASE_URL || "");
-
-export const db = drizzle({ client: pool });
-{{/if}}
+{{#if (eq runtime "workers")}}
+ // SingleStore (mysql2) is not supported on Cloudflare Workers (no TCP sockets).
+ throw new Error(
+ "SingleStore is not supported on Cloudflare Workers. Use Bun or Node.js runtimes."
+ );
+{{/if}}
📝 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.
{{#if (eq runtime "workers")}} | |
import mysql from "mysql2/promise"; | |
import { drizzle } from "drizzle-orm/singlestore"; | |
import { env } from "cloudflare:workers"; | |
const pool = mysql.createPool(env.DATABASE_URL || ""); | |
export const db = drizzle({ client: pool }); | |
{{/if}} | |
{{#if (eq runtime "workers")}} | |
// SingleStore (mysql2) is not supported on Cloudflare Workers (no TCP sockets). | |
throw new Error( | |
"SingleStore is not supported on Cloudflare Workers. Use Bun or Node.js runtimes." | |
); | |
{{/if}} |
if (nextStack.dbSetup === "none") { | ||
notes.database.notes.push( | ||
"SingleStore database selected: DB Setup will be set to 'SingleStore Helios'.", | ||
); | ||
notes.dbSetup.notes.push( | ||
"SingleStore works best with cloud setup. SingleStore Helios will be selected.", | ||
); | ||
notes.database.hasIssue = true; | ||
notes.dbSetup.hasIssue = true; | ||
nextStack.dbSetup = "singlestore-helios"; | ||
changed = true; | ||
changes.push({ | ||
category: "database", | ||
message: | ||
"DB Setup set to 'SingleStore Helios' (recommended for SingleStore)", | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Handle all incompatible dbSetup values for SingleStore, not just 'none'.
Right now, for database='singlestore' you only override dbSetup when it is 'none'. If a user lands here via a URL or saved state with dbSetup='docker' (or anything except 'singlestore-helios'/'none'), it won’t be corrected, and generateCommand could emit an invalid combination. Normalize any non-allowed dbSetup to 'singlestore-helios'.
Apply this diff in this block:
- if (nextStack.dbSetup === "none") {
+ const allowedSetups = new Set(["singlestore-helios", "none"]);
+ if (!allowedSetups.has(nextStack.dbSetup)) {
+ notes.database.notes.push(
+ "SingleStore database selected: DB Setup will be set to 'SingleStore Helios'.",
+ );
+ notes.dbSetup.notes.push(
+ "SingleStore works best with cloud setup. SingleStore Helios will be selected.",
+ );
+ notes.database.hasIssue = true;
+ notes.dbSetup.hasIssue = true;
+ nextStack.dbSetup = "singlestore-helios";
+ changed = true;
+ changes.push({
+ category: "database",
+ message:
+ "DB Setup set to 'SingleStore Helios' (recommended for SingleStore)",
+ });
+ } else if (nextStack.dbSetup === "none") {
notes.database.notes.push(
"SingleStore database selected: DB Setup will be set to 'SingleStore Helios'.",
);
notes.dbSetup.notes.push(
"SingleStore works best with cloud setup. SingleStore Helios will be selected.",
);
notes.database.hasIssue = true;
notes.dbSetup.hasIssue = true;
nextStack.dbSetup = "singlestore-helios";
changed = true;
changes.push({
category: "database",
message:
"DB Setup set to 'SingleStore Helios' (recommended for SingleStore)",
});
}
📝 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.
if (nextStack.dbSetup === "none") { | |
notes.database.notes.push( | |
"SingleStore database selected: DB Setup will be set to 'SingleStore Helios'.", | |
); | |
notes.dbSetup.notes.push( | |
"SingleStore works best with cloud setup. SingleStore Helios will be selected.", | |
); | |
notes.database.hasIssue = true; | |
notes.dbSetup.hasIssue = true; | |
nextStack.dbSetup = "singlestore-helios"; | |
changed = true; | |
changes.push({ | |
category: "database", | |
message: | |
"DB Setup set to 'SingleStore Helios' (recommended for SingleStore)", | |
}); | |
} | |
const allowedSetups = new Set(["singlestore-helios", "none"]); | |
if (!allowedSetups.has(nextStack.dbSetup)) { | |
notes.database.notes.push( | |
"SingleStore database selected: DB Setup will be set to 'SingleStore Helios'.", | |
); | |
notes.dbSetup.notes.push( | |
"SingleStore works best with cloud setup. SingleStore Helios will be selected.", | |
); | |
notes.database.hasIssue = true; | |
notes.dbSetup.hasIssue = true; | |
nextStack.dbSetup = "singlestore-helios"; | |
changed = true; | |
changes.push({ | |
category: "database", | |
message: | |
"DB Setup set to 'SingleStore Helios' (recommended for SingleStore)", | |
}); | |
} else if (nextStack.dbSetup === "none") { | |
notes.database.notes.push( | |
"SingleStore database selected: DB Setup will be set to 'SingleStore Helios'.", | |
); | |
notes.dbSetup.notes.push( | |
"SingleStore works best with cloud setup. SingleStore Helios will be selected.", | |
); | |
notes.database.hasIssue = true; | |
notes.dbSetup.hasIssue = true; | |
nextStack.dbSetup = "singlestore-helios"; | |
changed = true; | |
changes.push({ | |
category: "database", | |
message: | |
"DB Setup set to 'SingleStore Helios' (recommended for SingleStore)", | |
}); | |
} |
🤖 Prompt for AI Agents
In apps/web/src/app/(home)/_components/stack-builder.tsx around lines 402 to
418, the current logic only normalizes nextStack.dbSetup when it equals "none"
for database === "singlestore"; update it so any value other than
"singlestore-helios" (i.e., if dbSetup !== "singlestore-helios") is treated as
incompatible and reset to "singlestore-helios". Keep the same notes/dbSetup
flags, changed=true, and push the same changes entry, but apply them whenever
dbSetup is not "singlestore-helios" (including "docker" or any other value),
ensuring generateCommand won't receive invalid combinations.
…e tests for clarity
… Workers and update documentation
…ibility notes in documentation
…ated documentation to omit None
There was a problem hiding this 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
♻️ Duplicate comments (2)
apps/cli/templates/db/drizzle/singlestore/src/db/index.ts.hbs (1)
1-6
: Fail fast on missing DATABASE_URL and avoid empty-string fallbackPassing an empty string to createPool defers errors to runtime and obscures TLS requirements. Throw early and use the provided URL. This also aligns with Helios’s TLS mandate (URL should contain ssl params).
-const pool = mysql.createPool(process.env.DATABASE_URL || ""); +const url = process.env.DATABASE_URL; +if (!url) { + throw new Error( + "DATABASE_URL is not set. SingleStore Helios requires a TLS-enabled connection string.", + ); +} +const pool = mysql.createPool(url);Follow-up: if you want pool tuning (waitForConnections, connectionLimit, keep-alive), we can switch to an options object, but the above keeps it minimal and safe.
apps/web/src/app/(home)/_components/stack-builder.tsx (1)
402-418
: Normalize dbSetup for SingleStore for any non-Helios values (not just 'none').If state is loaded with an incompatible dbSetup (e.g., docker), it won’t be corrected and can leak into generateCommand. Normalize any dbSetup that isn’t 'singlestore-helios' to 'singlestore-helios'.
Apply this diff to generalize the normalization:
- if (nextStack.dbSetup === "none") { + if (nextStack.dbSetup !== "singlestore-helios") { notes.database.notes.push( "SingleStore database selected: DB Setup will be set to 'SingleStore Helios'.", ); notes.dbSetup.notes.push( "SingleStore works best with cloud setup. SingleStore Helios will be selected.", ); notes.database.hasIssue = true; notes.dbSetup.hasIssue = true; nextStack.dbSetup = "singlestore-helios"; changed = true; changes.push({ category: "database", message: "DB Setup set to 'SingleStore Helios' (recommended for SingleStore)", }); }
🧹 Nitpick comments (6)
apps/web/content/docs/cli/options.mdx (2)
88-94
: Add quick Drizzle-only note and cross-link for SingleStoreTo reduce surprises, note that SingleStore is Drizzle-only and link to the compatibility page.
- `singlestore`: SingleStore database + - `singlestore`: SingleStore database (Drizzle-only; see [Compatibility](/docs/cli/compatibility))
116-124
: Clarify Helios requirements (TLS) and Drizzle-only pairingHelios mandates TLS and SingleStore pairs only with Drizzle. Small wording tweak helps users get it right upfront.
- `singlestore-helios`: SingleStore Helios (cloud-hosted SingleStore) + `singlestore-helios`: SingleStore Helios (cloud-hosted SingleStore; TLS required; Drizzle-only)apps/web/content/docs/compatibility.mdx (1)
14-15
: “Requires Helios” is too strict; basic/manual setup is allowedPer PR objectives, Helios is recommended, but a basic/self-hosted (“none”) path is also supported. Adjust wording to avoid blocking valid use.
- **SingleStore database**: Only compatible with Drizzle ORM; requires SingleStore Helios setup + **SingleStore database**: Only compatible with Drizzle ORM; use SingleStore Helios (recommended) or basic/manual setupCan you confirm the CLI permits
--database singlestore --db-setup none
with Drizzle? If yes, the above change keeps docs aligned.apps/cli/src/utils/compatibility-rules.ts (1)
154-190
: Centralizing SingleStore validations here is good; avoid duplicating the same checks in validation.ts.The Drizzle requirement and Helios-setup coupling (when selected) are properly enforced here. Let’s remove duplicates in validation.ts to keep a single source of truth.
apps/cli/src/validation.ts (2)
251-261
: Remove duplicate SingleStore+ORM check; defer to validateSingleStoreCompatibility.This logic duplicates the dedicated helper’s check. Consolidate to avoid drift.
- if ( - providedFlags.has("database") && - providedFlags.has("orm") && - config.database === "singlestore" && - config.orm && - config.orm !== "drizzle" - ) { - exitWithError( - "SingleStore database requires Drizzle ORM. Please use '--orm drizzle' or choose a different database.", - ); - }
365-374
: Duplicate: Helios setup requires SingleStore database.This is already enforced in validateSingleStoreCompatibility. Recommend removing here to keep rules centralized.
- if ( - providedFlags.has("dbSetup") && - (config.database ? providedFlags.has("database") : true) && - config.dbSetup === "singlestore-helios" && - config.database !== "singlestore" - ) { - exitWithError( - "SingleStore Helios setup requires SingleStore database. Please use '--database singlestore' or choose a different setup.", - ); - }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (14)
apps/cli/README.md
(5 hunks)apps/cli/src/helpers/database-providers/singlestore-helios-setup.ts
(1 hunks)apps/cli/src/prompts/database-setup.ts
(1 hunks)apps/cli/src/prompts/database.ts
(1 hunks)apps/cli/src/utils/compatibility-rules.ts
(1 hunks)apps/cli/src/validation.ts
(4 hunks)apps/cli/templates/db/drizzle/singlestore/src/db/index.ts.hbs
(1 hunks)apps/cli/templates/examples/todo/server/drizzle/singlestore/src/db/schema/todo.ts
(1 hunks)apps/cli/test/cli.smoke.test.ts
(4 hunks)apps/web/content/docs/cli/compatibility.mdx
(4 hunks)apps/web/content/docs/cli/options.mdx
(2 hunks)apps/web/content/docs/compatibility.mdx
(1 hunks)apps/web/src/app/(home)/_components/stack-builder.tsx
(5 hunks)apps/web/src/lib/constant.ts
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
- apps/cli/src/prompts/database-setup.ts
- apps/cli/templates/examples/todo/server/drizzle/singlestore/src/db/schema/todo.ts
- apps/cli/src/helpers/database-providers/singlestore-helios-setup.ts
- apps/cli/README.md
- apps/cli/src/prompts/database.ts
- apps/cli/test/cli.smoke.test.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
apps/cli/src/utils/compatibility-rules.ts (2)
apps/cli/src/utils/errors.ts (1)
exitWithError
(9-15)apps/cli/src/types.ts (2)
CLIInput
(149-151)ProjectConfig
(153-171)
apps/cli/src/validation.ts (2)
apps/cli/src/utils/errors.ts (1)
exitWithError
(9-15)apps/cli/src/utils/compatibility-rules.ts (1)
validateSingleStoreCompatibility
(154-190)
🪛 LanguageTool
apps/web/content/docs/cli/compatibility.mdx
[grammar] ~20-~20: There might be a mistake here.
Context: ...h-performance distributed SQL database | | none
| none
| No database setup | ...
(QB_NEW_EN)
[grammar] ~109-~109: There might be a mistake here.
Context: ...s**: ❌ Only one native framework allowed - Web + Native: ✅ One web and one native...
(QB_NEW_EN)
[grammar] ~132-~132: There might be a mistake here.
Context: ...e| Cloud-hosted SingleStore database | |
docker|
postgres,
mysql,
mongo...
(QB_NEW_EN)
[grammar] ~183-~183: There might be a mistake here.
Context: ...eand
--database none ### AI Example - Not compatible with
--backend elysia` -...
(QB_NEW_EN)
apps/web/content/docs/cli/options.mdx
[grammar] ~90-~90: There might be a mistake here.
Context: ...tabase - postgres
: PostgreSQL database - mysql
: MySQL database - mongodb
: MongoDB da...
(QB_NEW_EN)
[grammar] ~91-~91: There might be a mistake here.
Context: ...reSQL database - mysql
: MySQL database - mongodb
: MongoDB database - singlestore
: Sing...
(QB_NEW_EN)
[grammar] ~92-~92: There might be a mistake here.
Context: ...L database - mongodb
: MongoDB database - singlestore
: SingleStore database ```bash create-b...
(QB_NEW_EN)
[grammar] ~123-~123: There might be a mistake here.
Context: ...eStore Helios (cloud-hosted SingleStore) - docker
: Local Docker containers ```bash creat...
(QB_NEW_EN)
apps/web/content/docs/compatibility.mdx
[grammar] ~19-~19: There might be a mistake here.
Context: ...oudflare Workers - Backend: hono
only - Database: sqlite
with Cloudflare D1 - ...
(QB_NEW_EN)
[grammar] ~20-~20: There might be a mistake here.
Context: ... - Database: sqlite
with Cloudflare D1 - ORM: drizzle
(or none) - Not compatibl...
(QB_NEW_EN)
[grammar] ~21-~21: There might be a mistake here.
Context: ...Cloudflare D1 - ORM: drizzle
(or none) - Not compatible with MongoDB, SingleStore...
(QB_NEW_EN)
[style] ~22-~22: Consider using “incompatible” to avoid wordiness.
Context: ...udflare D1 - ORM: drizzle
(or none) - Not compatible with MongoDB, SingleStore ## Framework...
(NOT_ABLE_PREMIUM)
🔇 Additional comments (12)
apps/web/content/docs/compatibility.mdx (1)
22-23
: Good call-out: Workers is incompatible with SingleStoreThis aligns with mysql2’s TCP socket requirement and avoids generating broken Workers stacks for SingleStore.
apps/web/content/docs/cli/compatibility.mdx (3)
20-21
: LGTM: Adds SingleStore ↔ Drizzle pairing to the matrixThis clearly communicates the Drizzle-only constraint for SingleStore.
26-27
: Explicit SingleStore restriction with Prisma/Mongoose is helpfulKeeps users on the supported path and prevents invalid scaffolds.
132-133
: Provider matrix entry for singlestore-helios looks correctAccurate mapping between provider and required database.
apps/web/src/lib/constant.ts (1)
249-255
: LGTM: Added SingleStore database optionAccurate name, description, and icon path. This aligns with the new CLI choices.
apps/web/src/app/(home)/_components/stack-builder.tsx (4)
386-401
: SingleStore → enforce Drizzle ORM: LGTMThe Drizzle-only enforcement for SingleStore is correct and consistent with the new dialect/driver integration.
553-587
: Helios dbSetup backfills SingleStore + Drizzle: LGTMEnsuring database 'singlestore' and ORM 'drizzle' when dbSetup is 'singlestore-helios' keeps state coherent.
1035-1036
: Command generation: treating 'singlestore-helios' as requiring explicit database is correct.This ensures the database flag is emitted alongside the setup flag.
1726-1771
: Confirm intention: UI excludes 'none' dbSetup when database='singlestore'.PR objectives mention allowing a basic/self-hosted 'none' option, but the UI filters only 'singlestore-helios'. If this is intentional (cloud-first in UI; 'none' allowed via CLI/programmatic only), consider adding a small note in UI to reduce confusion. If not intentional, include 'none' in the filter.
Would you like me to update the UI to:
- keep showing only Helios (status quo, plus a note), or
- include 'none' as an advanced option (while analyzeStackCompatibility continues to prefer Helios)?
apps/cli/src/utils/compatibility-rules.ts (1)
132-152
: Workers + SingleStore guardrails: LGTMClear error messages and parity with existing Workers checks for other databases.
apps/cli/src/validation.ts (2)
23-26
: Import and invocation of validateSingleStoreCompatibility: LGTMHooking SingleStore checks into the main validation pipeline keeps rules coherent.
433-435
: Good: SingleStore validations are invoked alongside Workers checks.This keeps the CLI’s cross-field constraints consistent with the new database.
if ( | ||
providedFlags.has("database") && | ||
providedFlags.has("dbSetup") && | ||
config.database === "singlestore" && | ||
config.dbSetup === "none" | ||
) { | ||
exitWithError( | ||
"SingleStore database requires SingleStore Helios setup. Please use '--db-setup singlestore-helios' or omit the --db-setup flag.", | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not force Helios when database='singlestore' — conflicts with PR objective to allow 'none'.
The PR explicitly allows a basic/self-hosted 'none' option. This block prohibits it by erroring when dbSetup==='none'. Remove this constraint.
- if (
- providedFlags.has("database") &&
- providedFlags.has("dbSetup") &&
- config.database === "singlestore" &&
- config.dbSetup === "none"
- ) {
- exitWithError(
- "SingleStore database requires SingleStore Helios setup. Please use '--db-setup singlestore-helios' or omit the --db-setup flag.",
- );
- }
📝 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.
if ( | |
providedFlags.has("database") && | |
providedFlags.has("dbSetup") && | |
config.database === "singlestore" && | |
config.dbSetup === "none" | |
) { | |
exitWithError( | |
"SingleStore database requires SingleStore Helios setup. Please use '--db-setup singlestore-helios' or omit the --db-setup flag.", | |
); | |
} |
🤖 Prompt for AI Agents
In apps/cli/src/validation.ts around lines 376 to 385 the code currently rejects
the combination database==='singlestore' && dbSetup==='none', which contradicts
the PR goal to allow a basic/self-hosted "none" option; remove this constraint
by deleting the entire if-block that checks for providedFlags.has("database") &&
providedFlags.has("dbSetup") && config.database === "singlestore" &&
config.dbSetup === "none" (or change the condition so it no longer treats
dbSetup==='none' as an error), leaving no special-case error for SingleStore
when dbSetup is "none".
id: "singlestore-helios", | ||
name: "SingleStore Helios", | ||
description: "Cloud-hosted SingleStore database on Helios", | ||
icon: `${ICON_BASE_URL}/singlestore.svg`, | ||
color: "from-purple-500 to-purple-700", | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
LGTM: Added SingleStore Helios provider
Entry is consistent with the provider naming elsewhere. One minor check: ensure the icon asset exists at the R2 path.
Run this to verify the remote asset is available:
🏁 Script executed:
#!/bin/bash
# Verify that the icon is accessible
set -euo pipefail
url="https://r2.better-t-stack.dev/icons/singlestore.svg"
echo "HEAD $url"
curl -sI "$url" | awk 'NR<=1 {print}'
Length of output: 297
Missing R2 Icon for SingleStore Helios
The URL https://r2.better-t-stack.dev/icons/singlestore.svg returns HTTP 404, so the singlestore.svg
asset isn’t available. Please add singlestore.svg
to R2 (at /icons/singlestore.svg
) or update the icon
field to reference an existing asset.
• File: apps/web/src/lib/constant.ts (lines 339–344)
• Section:
id: "singlestore-helios",
name: "SingleStore Helios",
description: "Cloud-hosted SingleStore database on Helios",
icon: `${ICON_BASE_URL}/singlestore.svg`,
color: "from-purple-500 to-purple-700",
🤖 Prompt for AI Agents
In apps/web/src/lib/constant.ts around lines 339 to 344, the icon URL
`${ICON_BASE_URL}/singlestore.svg` points to a missing asset (404); either
upload a valid singlestore.svg to R2 at /icons/singlestore.svg or change the
icon field to an existing asset path (e.g., reuse an existing database icon in
/icons/) and update the icon string accordingly so the referenced URL resolves.
… provider and update database selection logic
@AmanVarshney01 Please add the singlestore.svg icon to the R2 bucket. |
This PR adds complete SingleStore Helios database support to Better-T-Stack, implementing a comprehensive integration across all CLI, programmatic API, and web app interfaces. SingleStore is a distributed SQL database designed for data-intensive applications that require real-time analytics and high-performance transactions.
Key Features Added
singlestore
database option with Drizzle ORM integrationImplementation Details
Core Integration
singlestore
to database type system with proper TypeScript typessinglestore-helios
database setup option for cloud deploymentsTemplate System
singlestore
dialectsinglestoreTable
andbigint
primary keysWeb App Integration
Environment & Setup
.env
file generationTechnical Specifications
Database Configuration
singlestore
(Drizzle)mysql2
with connection poolingsinglestoreTable
,bigint
primary keys, no foreign keysDependencies
drizzle-orm
: ^0.44.2 (SingleStore support)drizzle-kit
: ^0.31.2 (migration tools)mysql2
: Latest (connection driver)Compatibility Matrix
Testing Coverage
Smoke Tests (9 new tests)
Validation Tests
Integration Tests
Documentation Updates
CLI Documentation
Web Documentation
Breaking Changes
None. This is a purely additive feature that doesn't modify existing functionality.
Migration Guide
For users wanting to use SingleStore:
--database singlestore --db-setup singlestore-helios
database: "singlestore"
anddatabaseSetup: "singlestore-helios"
Related Issues
Closes #517
Testing Instructions
create-better-t-stack my-app --database singlestore --db-setup singlestore-helios
cd apps/cli && bun test
WITH_BUILD=1 bun test
Summary by CodeRabbit
New Features
Documentation
Tests