mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
feat(cli): add programmatic api (#494)
This commit is contained in:
@@ -22,6 +22,8 @@ create-better-t-stack [project-directory] [options]
|
||||
### Key Options
|
||||
|
||||
- `--yes, -y`: Use default configuration (skips prompts)
|
||||
- `--verbose`: Show detailed result information as JSON
|
||||
- `--yolo`: Bypass validations and compatibility checks
|
||||
- `--package-manager <pm>`: `npm`, `pnpm`, `bun`
|
||||
- `--install / --no-install`: Install dependencies after creation
|
||||
- `--git / --no-git`: Initialize Git repository
|
||||
@@ -34,6 +36,8 @@ create-better-t-stack [project-directory] [options]
|
||||
- `--db-setup <setup>`: `none`, `turso`, `d1`, `neon`, `supabase`, `prisma-postgres`, `mongodb-atlas`, `docker`
|
||||
- `--examples <types...>`: `none`, `todo`, `ai`
|
||||
- `--web-deploy <setup>`: `none`, `workers`
|
||||
- `--directory-conflict <strategy>`: `merge`, `overwrite`, `increment`, `error`
|
||||
- `--render-title / --no-render-title`: Show/hide ASCII art title
|
||||
|
||||
See the full reference in [Options](/docs/cli/options).
|
||||
|
||||
@@ -147,3 +151,35 @@ create-better-t-stack api-server \
|
||||
cd my-existing-project
|
||||
create-better-t-stack add --addons tauri starlight --install
|
||||
```
|
||||
|
||||
## Programmatic Usage
|
||||
|
||||
For advanced use cases, automation, or integration with other tools, you can use the [Programmatic API](/docs/cli/programmatic-api) to create projects from Node.js code:
|
||||
|
||||
```typescript
|
||||
import { init } from "create-better-t-stack";
|
||||
|
||||
// Create multiple projects programmatically
|
||||
const projects = [
|
||||
{ name: "api", config: { frontend: ["none"], backend: "hono" } },
|
||||
{ name: "web", config: { frontend: ["next"], backend: "none" } }
|
||||
];
|
||||
|
||||
for (const { name, config } of projects) {
|
||||
const result = await init(name, {
|
||||
yes: true,
|
||||
...config,
|
||||
directoryConflict: "increment"
|
||||
});
|
||||
|
||||
console.log(result.success ? `✅ ${name}` : `❌ ${name}: ${result.error}`);
|
||||
}
|
||||
```
|
||||
|
||||
This is useful for:
|
||||
- **Build tools and generators** - Create projects from templates
|
||||
- **CI/CD pipelines** - Generate test projects automatically
|
||||
- **Development workflows** - Batch create related projects
|
||||
- **Custom tooling** - Integrate with your existing development setup
|
||||
|
||||
See the [Programmatic API documentation](/docs/cli/programmatic-api) for complete examples and API reference.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"title": "CLI",
|
||||
"defaultOpen": true,
|
||||
"pages": ["index", "options", "compatibility"]
|
||||
"pages": ["index", "programmatic-api", "options", "compatibility"]
|
||||
}
|
||||
|
||||
@@ -37,6 +37,48 @@ Control Git repository initialization.
|
||||
create-better-t-stack --no-git
|
||||
```
|
||||
|
||||
### `--yolo`
|
||||
|
||||
Bypass validations and compatibility checks. Not recommended for normal use.
|
||||
|
||||
```bash
|
||||
create-better-t-stack --yolo
|
||||
```
|
||||
|
||||
### `--verbose`
|
||||
|
||||
Show detailed result information in JSON format after project creation.
|
||||
|
||||
```bash
|
||||
create-better-t-stack --verbose
|
||||
```
|
||||
|
||||
### `--render-title / --no-render-title`
|
||||
|
||||
Control whether the ASCII art title is shown. Enabled by default.
|
||||
|
||||
```bash
|
||||
# Hide the title (useful in CI)
|
||||
create-better-t-stack --no-render-title
|
||||
```
|
||||
|
||||
### `--directory-conflict <strategy>`
|
||||
|
||||
How to handle existing, non-empty target directories:
|
||||
|
||||
- `merge`: Keep existing files and merge new ones
|
||||
- `overwrite`: Clear the directory before scaffolding
|
||||
- `increment`: Create a suffixed directory (e.g., `my-app-1`)
|
||||
- `error`: Fail instead of prompting
|
||||
|
||||
```bash
|
||||
# Overwrite an existing directory without prompting
|
||||
create-better-t-stack my-app --yes --directory-conflict overwrite
|
||||
|
||||
# Safely create a new directory name if it exists
|
||||
create-better-t-stack my-app --yes --directory-conflict increment
|
||||
```
|
||||
|
||||
## Database Options
|
||||
|
||||
### `--database <type>`
|
||||
|
||||
276
apps/web/content/docs/cli/programmatic-api.mdx
Normal file
276
apps/web/content/docs/cli/programmatic-api.mdx
Normal file
@@ -0,0 +1,276 @@
|
||||
---
|
||||
title: Programmatic API
|
||||
description: Use Better-T Stack programmatically in your Node.js applications
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The Better-T Stack CLI can be used programmatically in your Node.js applications, allowing you to create projects, add features, and manage configurations through JavaScript/TypeScript code instead of shell commands.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the package in your Node.js project:
|
||||
|
||||
```bash
|
||||
npm install create-better-t-stack
|
||||
# or
|
||||
pnpm add create-better-t-stack
|
||||
# or
|
||||
bun add create-better-t-stack
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Basic Project Creation
|
||||
|
||||
```typescript
|
||||
import { init } from "create-better-t-stack";
|
||||
|
||||
async function createProject() {
|
||||
const result = await init("my-app", {
|
||||
yes: true, // Use defaults, no prompts
|
||||
frontend: ["tanstack-router"],
|
||||
backend: "hono",
|
||||
database: "sqlite",
|
||||
orm: "drizzle",
|
||||
auth: true,
|
||||
packageManager: "bun",
|
||||
install: false, // Don't install deps automatically
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
console.log(`✅ Project created at: ${result.projectDirectory}`);
|
||||
console.log(`📝 Reproducible command: ${result.reproducibleCommand}`);
|
||||
console.log(`⏱️ Time taken: ${result.elapsedTimeMs}ms`);
|
||||
} else {
|
||||
console.error(`❌ Failed: ${result.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
createProject();
|
||||
```
|
||||
|
||||
### Directory Conflict Handling
|
||||
|
||||
```typescript
|
||||
import { init } from "create-better-t-stack";
|
||||
|
||||
const result = await init("existing-folder", {
|
||||
yes: true,
|
||||
directoryConflict: "increment", // Creates "existing-folder-1"
|
||||
renderTitle: false, // Hide ASCII art
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `init(projectName?, options?)`
|
||||
|
||||
Creates a new Better-T Stack project.
|
||||
|
||||
**Parameters:**
|
||||
- `projectName` (string, optional): Project name or directory path
|
||||
- `options` (CreateInput, optional): Configuration options
|
||||
|
||||
**Returns:** `Promise<InitResult>`
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
const result = await init("my-project", {
|
||||
frontend: ["next"],
|
||||
backend: "hono",
|
||||
database: "postgres",
|
||||
orm: "drizzle"
|
||||
});
|
||||
```
|
||||
|
||||
### `sponsors()`
|
||||
|
||||
Display Better-T Stack sponsors (same as CLI).
|
||||
|
||||
**Returns:** `Promise<void>`
|
||||
|
||||
### `docs()`
|
||||
|
||||
Open documentation in browser (same as CLI).
|
||||
|
||||
**Returns:** `Promise<void>`
|
||||
|
||||
### `builder()`
|
||||
|
||||
Open web-based stack builder (same as CLI).
|
||||
|
||||
**Returns:** `Promise<void>`
|
||||
|
||||
## Type Definitions
|
||||
|
||||
### `CreateInput`
|
||||
|
||||
Configuration options for project creation:
|
||||
|
||||
```typescript
|
||||
interface CreateInput {
|
||||
projectName?: string;
|
||||
yes?: boolean; // Skip prompts, use defaults
|
||||
yolo?: boolean; // Bypass validations (not recommended)
|
||||
verbose?: boolean; // Show JSON result (CLI only, programmatic always returns result)
|
||||
database?: Database; // "none" | "sqlite" | "postgres" | "mysql" | "mongodb"
|
||||
orm?: ORM; // "none" | "drizzle" | "prisma" | "mongoose"
|
||||
auth?: boolean; // Include authentication
|
||||
frontend?: Frontend[]; // Array of frontend frameworks
|
||||
addons?: Addons[]; // Array of addons
|
||||
examples?: Examples[]; // Array of examples
|
||||
git?: boolean; // Initialize git repo
|
||||
packageManager?: PackageManager; // "npm" | "pnpm" | "bun"
|
||||
install?: boolean; // Install dependencies
|
||||
dbSetup?: DatabaseSetup; // Database hosting setup
|
||||
backend?: Backend; // Backend framework
|
||||
runtime?: Runtime; // Runtime environment
|
||||
api?: API; // API type
|
||||
webDeploy?: WebDeploy; // Web deployment setup
|
||||
directoryConflict?: DirectoryConflict; // "merge" | "overwrite" | "increment" | "error"
|
||||
renderTitle?: boolean; // Show ASCII art title
|
||||
}
|
||||
```
|
||||
|
||||
### `InitResult`
|
||||
|
||||
Result object returned by `init()`:
|
||||
|
||||
```typescript
|
||||
interface InitResult {
|
||||
success: boolean; // Whether operation succeeded
|
||||
projectConfig: ProjectConfig; // Final project configuration
|
||||
reproducibleCommand: string; // CLI command to recreate project
|
||||
timeScaffolded: string; // ISO timestamp of creation
|
||||
elapsedTimeMs: number; // Time taken in milliseconds
|
||||
projectDirectory: string; // Absolute path to project
|
||||
relativePath: string; // Relative path to project
|
||||
error?: string; // Error message if failed
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### Directory Conflict Resolution
|
||||
|
||||
Control how existing directories are handled:
|
||||
|
||||
```typescript
|
||||
// Merge with existing files (careful with conflicts)
|
||||
directoryConflict: "merge"
|
||||
|
||||
// Completely overwrite existing directory
|
||||
directoryConflict: "overwrite"
|
||||
|
||||
// Create new directory with incremented name (my-app-1)
|
||||
directoryConflict: "increment"
|
||||
|
||||
// Throw error if directory exists
|
||||
directoryConflict: "error"
|
||||
```
|
||||
|
||||
### Title Rendering
|
||||
|
||||
Control CLI output appearance:
|
||||
|
||||
```typescript
|
||||
// Hide ASCII art title (useful for automated scripts)
|
||||
renderTitle: false
|
||||
|
||||
// Show ASCII art title (default)
|
||||
renderTitle: true
|
||||
```
|
||||
|
||||
### YOLO Mode
|
||||
|
||||
Bypass validation checks (not recommended):
|
||||
|
||||
```typescript
|
||||
// Skip compatibility validations
|
||||
yolo: true
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The programmatic API uses different error handling than the CLI:
|
||||
|
||||
### Directory Conflicts
|
||||
|
||||
Directory conflict errors return structured results instead of throwing:
|
||||
|
||||
```typescript
|
||||
const result = await init("existing-dir", {
|
||||
directoryConflict: "error"
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
console.log(result.error); // "Directory exists and is not empty..."
|
||||
// Handle gracefully instead of process exit
|
||||
}
|
||||
```
|
||||
|
||||
### Validation Errors
|
||||
|
||||
Validation errors still throw exceptions (maintains CLI compatibility):
|
||||
|
||||
```typescript
|
||||
try {
|
||||
await init("test", {
|
||||
database: "mongodb",
|
||||
orm: "drizzle" // Invalid combination
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error.message); // "MongoDB requires Mongoose or Prisma ORM"
|
||||
}
|
||||
```
|
||||
|
||||
## Migration from CLI
|
||||
|
||||
### CLI Command to Programmatic API
|
||||
|
||||
Convert CLI commands to programmatic calls:
|
||||
|
||||
```bash
|
||||
# CLI Command
|
||||
create-better-t-stack my-app \
|
||||
--frontend tanstack-router \
|
||||
--backend hono \
|
||||
--database postgres \
|
||||
--orm drizzle \
|
||||
--auth \
|
||||
--yes
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Programmatic Equivalent
|
||||
const result = await init("my-app", {
|
||||
frontend: ["tanstack-router"],
|
||||
backend: "hono",
|
||||
database: "postgres",
|
||||
orm: "drizzle",
|
||||
auth: true,
|
||||
yes: true
|
||||
});
|
||||
```
|
||||
|
||||
### Handling Prompts
|
||||
|
||||
CLI prompts become explicit options:
|
||||
|
||||
```typescript
|
||||
// Instead of interactive prompts, specify all options
|
||||
const result = await init("my-app", {
|
||||
yes: true, // Skip all prompts
|
||||
frontend: ["tanstack-router"],
|
||||
backend: "hono",
|
||||
database: "postgres",
|
||||
orm: "drizzle",
|
||||
auth: true,
|
||||
addons: ["biome", "turborepo"],
|
||||
examples: ["todo"],
|
||||
packageManager: "bun",
|
||||
install: false,
|
||||
git: true
|
||||
});
|
||||
```
|
||||
Reference in New Issue
Block a user