buncargo 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin.ts +253 -0
- package/cli.ts +238 -0
- package/config.ts +194 -0
- package/core/docker.ts +384 -0
- package/core/index.ts +7 -0
- package/core/network.ts +152 -0
- package/core/ports.ts +253 -0
- package/core/process.ts +253 -0
- package/core/utils.ts +127 -0
- package/core/watchdog-runner.ts +111 -0
- package/core/watchdog.ts +196 -0
- package/dist/bin.d.ts +12 -0
- package/dist/cli.d.ts +22 -0
- package/dist/config.d.ts +72 -0
- package/dist/core/docker.d.ts +74 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/network.d.ts +30 -0
- package/dist/core/ports.d.ts +30 -0
- package/dist/core/process.d.ts +52 -0
- package/dist/core/utils.d.ts +60 -0
- package/dist/core/watchdog-runner.d.ts +14 -0
- package/dist/core/watchdog.d.ts +46 -0
- package/dist/environment.d.ts +23 -0
- package/dist/index.d.ts +12 -0
- package/dist/lint.d.ts +46 -0
- package/dist/loader.d.ts +39 -0
- package/dist/prisma.d.ts +29 -0
- package/dist/types.d.ts +391 -0
- package/environment.ts +604 -0
- package/index.ts +103 -0
- package/lint.ts +277 -0
- package/loader.ts +100 -0
- package/package.json +124 -0
- package/prisma.ts +138 -0
- package/readme.md +198 -0
- package/types.ts +538 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the heartbeat file path for a project.
|
|
3
|
+
*/
|
|
4
|
+
export declare function getHeartbeatFile(projectName: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Get the watchdog PID file path for a project.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getWatchdogPidFile(projectName: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Start writing heartbeat to file.
|
|
11
|
+
* The heartbeat is used by the watchdog to detect idle state.
|
|
12
|
+
*/
|
|
13
|
+
export declare function startHeartbeat(projectName: string, intervalMs?: number): void;
|
|
14
|
+
/**
|
|
15
|
+
* Stop writing heartbeat.
|
|
16
|
+
*/
|
|
17
|
+
export declare function stopHeartbeat(): void;
|
|
18
|
+
/**
|
|
19
|
+
* Read the last heartbeat timestamp.
|
|
20
|
+
*/
|
|
21
|
+
export declare function readHeartbeat(projectName: string): number | null;
|
|
22
|
+
/**
|
|
23
|
+
* Remove the heartbeat file.
|
|
24
|
+
*/
|
|
25
|
+
export declare function removeHeartbeatFile(projectName: string): void;
|
|
26
|
+
/**
|
|
27
|
+
* Check if watchdog is already running.
|
|
28
|
+
*/
|
|
29
|
+
export declare function isWatchdogRunning(projectName: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Get the watchdog PID if running.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getWatchdogPid(projectName: string): number | null;
|
|
34
|
+
/**
|
|
35
|
+
* Spawn watchdog as a detached process.
|
|
36
|
+
* The watchdog monitors the heartbeat file and shuts down containers after idle timeout.
|
|
37
|
+
*/
|
|
38
|
+
export declare function spawnWatchdog(projectName: string, root: string, options?: {
|
|
39
|
+
timeoutMinutes?: number;
|
|
40
|
+
verbose?: boolean;
|
|
41
|
+
composeFile?: string;
|
|
42
|
+
}): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Stop the watchdog process.
|
|
45
|
+
*/
|
|
46
|
+
export declare function stopWatchdog(projectName: string): void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AppConfig, DevConfig, DevEnvironment, ServiceConfig } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Create a dev environment from a configuration.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { defineDevConfig, createDevEnvironment } from 'buncargo'
|
|
8
|
+
*
|
|
9
|
+
* const config = defineDevConfig({
|
|
10
|
+
* projectPrefix: 'myapp',
|
|
11
|
+
* services: { postgres: { port: 5432 } },
|
|
12
|
+
* apps: { api: { port: 3000, devCommand: 'bun run dev' } }
|
|
13
|
+
* })
|
|
14
|
+
*
|
|
15
|
+
* export const dev = createDevEnvironment(config)
|
|
16
|
+
*
|
|
17
|
+
* // Usage
|
|
18
|
+
* await dev.start()
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function createDevEnvironment<TServices extends Record<string, ServiceConfig>, TApps extends Record<string, AppConfig>>(config: DevConfig<TServices, TApps>, options?: {
|
|
22
|
+
suffix?: string;
|
|
23
|
+
}): DevEnvironment<TServices, TApps>;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { getFlagValue, hasFlag, runCli } from "./cli";
|
|
2
|
+
export { assertValidConfig, defineDevConfig, mergeConfigs, validateConfig, } from "./config";
|
|
3
|
+
export { createDevEnvironment } from "./environment";
|
|
4
|
+
export { runWorkspaceTypecheck, type TypecheckResult, type WorkspaceTypecheckOptions, type WorkspaceTypecheckResult, } from "./lint";
|
|
5
|
+
export { clearDevEnvCache, getDevEnv, loadDevEnv } from "./loader";
|
|
6
|
+
export type { AppConfig, BuiltInHealthCheck, CliOptions, ComputedPorts, ComputedUrls, DevConfig, DevEnvironment, DevHooks, DevOptions, DevServerPids, EnvVarsBuilder, ExecOptions, HealthCheckFn, HookContext, MigrationConfig, PrismaConfig, PrismaRunner, SeedCheckContext, SeedCheckHelpers, SeedConfig, ServiceConfig, StartOptions, StopOptions, UrlBuilderContext, UrlBuilderFn, } from "./types";
|
|
7
|
+
export { areContainersRunning, isContainerRunning, MAX_ATTEMPTS, POLL_INTERVAL, } from "./core/docker";
|
|
8
|
+
export { getLocalIp, isPortAvailable, waitForServer } from "./core/network";
|
|
9
|
+
export { calculatePortOffset, findMonorepoRoot, getProjectName, getWorktreeName, isWorktree, } from "./core/ports";
|
|
10
|
+
export { isProcessAlive } from "./core/process";
|
|
11
|
+
export { getEnvVar, isCI, logApiUrl, logExpoApiUrl, logFrontendPort, sleep, } from "./core/utils";
|
|
12
|
+
export { getHeartbeatFile, getWatchdogPidFile, isWatchdogRunning, spawnWatchdog, startHeartbeat, stopHeartbeat, stopWatchdog, } from "./core/watchdog";
|
package/dist/lint.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for running workspace typechecks.
|
|
3
|
+
*/
|
|
4
|
+
export interface WorkspaceTypecheckOptions {
|
|
5
|
+
/** Root directory to search from (defaults to cwd) */
|
|
6
|
+
root?: string;
|
|
7
|
+
/** Glob patterns for workspaces to check (defaults to apps/*, packages/*, modules) */
|
|
8
|
+
patterns?: string[];
|
|
9
|
+
/** Maximum concurrent typecheck processes (defaults to 1) */
|
|
10
|
+
concurrency?: number;
|
|
11
|
+
/** Print output to console (defaults to true) */
|
|
12
|
+
verbose?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Result of a single workspace typecheck.
|
|
16
|
+
*/
|
|
17
|
+
export interface WorkspaceTypecheckResult {
|
|
18
|
+
workspace: string;
|
|
19
|
+
duration: number;
|
|
20
|
+
success: boolean;
|
|
21
|
+
fileCount: number;
|
|
22
|
+
errorOutput?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Overall result of running typechecks across all workspaces.
|
|
26
|
+
*/
|
|
27
|
+
export interface TypecheckResult {
|
|
28
|
+
success: boolean;
|
|
29
|
+
totalDuration: number;
|
|
30
|
+
totalFiles: number;
|
|
31
|
+
workspaceCount: number;
|
|
32
|
+
results: WorkspaceTypecheckResult[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Run TypeScript typechecks across all workspaces that have a `typecheck` script.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const result = await runWorkspaceTypecheck({ verbose: true })
|
|
40
|
+
* if (!result.success) {
|
|
41
|
+
* console.error('Typecheck failed')
|
|
42
|
+
* process.exit(1)
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function runWorkspaceTypecheck(options?: WorkspaceTypecheckOptions): Promise<TypecheckResult>;
|
package/dist/loader.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AppConfig, DevEnvironment, ServiceConfig } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Load the dev environment from the config file.
|
|
4
|
+
* Caches the result for subsequent calls.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { loadDevEnv } from 'buncargo'
|
|
9
|
+
*
|
|
10
|
+
* const env = await loadDevEnv()
|
|
11
|
+
* console.log(env.ports.postgres) // 5432 (or offset port)
|
|
12
|
+
* console.log(env.urls.api) // http://localhost:3000
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadDevEnv(options?: {
|
|
16
|
+
/** Directory to search for config file. Defaults to process.cwd() */
|
|
17
|
+
cwd?: string;
|
|
18
|
+
/** Skip cache and reload config */
|
|
19
|
+
reload?: boolean;
|
|
20
|
+
}): Promise<DevEnvironment<Record<string, ServiceConfig>, Record<string, AppConfig>>>;
|
|
21
|
+
/**
|
|
22
|
+
* Get the cached dev environment synchronously.
|
|
23
|
+
* Throws if loadDevEnv() hasn't been called yet.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* // First load async
|
|
28
|
+
* await loadDevEnv()
|
|
29
|
+
*
|
|
30
|
+
* // Then use sync getter anywhere
|
|
31
|
+
* import { getDevEnv } from 'buncargo'
|
|
32
|
+
* const env = getDevEnv()
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function getDevEnv(): DevEnvironment<Record<string, ServiceConfig>, Record<string, AppConfig>>;
|
|
36
|
+
/**
|
|
37
|
+
* Clear the cached environment.
|
|
38
|
+
*/
|
|
39
|
+
export declare function clearDevEnvCache(): void;
|
package/dist/prisma.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prisma integration for dev-tools-v2.
|
|
3
|
+
*
|
|
4
|
+
* When `prisma` is configured in defineDevConfig, `dev.prisma` becomes available
|
|
5
|
+
* with methods to run prisma commands against the Docker development database.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // In dev.config.ts
|
|
10
|
+
* const config = defineDevConfig({
|
|
11
|
+
* projectPrefix: 'myapp',
|
|
12
|
+
* services: { postgres: { port: 5432, healthCheck: 'pg_isready' } },
|
|
13
|
+
* prisma: { cwd: 'packages/prisma' } // Enable prisma integration
|
|
14
|
+
* })
|
|
15
|
+
*
|
|
16
|
+
* // Usage
|
|
17
|
+
* await dev.prisma.run(['migrate', 'dev'])
|
|
18
|
+
* await dev.prisma.ensureDatabase()
|
|
19
|
+
* const url = dev.prisma.getDatabaseUrl()
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @internal This module is used internally by createDevEnvironment.
|
|
23
|
+
*/
|
|
24
|
+
import type { AppConfig, DevEnvironment, PrismaConfig, PrismaRunner, ServiceConfig } from "./types";
|
|
25
|
+
/**
|
|
26
|
+
* Create a Prisma runner from config (used internally by createDevEnvironment).
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
export declare function createPrismaRunner<TServices extends Record<string, ServiceConfig>, TApps extends Record<string, AppConfig>>(env: DevEnvironment<TServices, TApps>, config: PrismaConfig): PrismaRunner;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health check function signature for custom health checks.
|
|
3
|
+
*/
|
|
4
|
+
export type HealthCheckFn = (port: number) => Promise<boolean>;
|
|
5
|
+
/**
|
|
6
|
+
* Built-in health check types that map to common patterns.
|
|
7
|
+
*/
|
|
8
|
+
export type BuiltInHealthCheck = "pg_isready" | "redis-cli" | "http" | "tcp";
|
|
9
|
+
/**
|
|
10
|
+
* URL builder context passed to urlTemplate function.
|
|
11
|
+
*/
|
|
12
|
+
export interface UrlBuilderContext {
|
|
13
|
+
port: number;
|
|
14
|
+
secondaryPort?: number;
|
|
15
|
+
host: string;
|
|
16
|
+
localIp: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* URL builder function receives port info and returns the connection URL.
|
|
20
|
+
*/
|
|
21
|
+
export type UrlBuilderFn = (ctx: UrlBuilderContext) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Configuration for a Docker Compose service (e.g., postgres, redis).
|
|
24
|
+
*/
|
|
25
|
+
export interface ServiceConfig {
|
|
26
|
+
/** Base port for the service (before offset is applied) */
|
|
27
|
+
port: number;
|
|
28
|
+
/** Optional secondary port (e.g., ClickHouse native protocol) */
|
|
29
|
+
secondaryPort?: number;
|
|
30
|
+
/** Health check: built-in name, custom function, or disabled (false) */
|
|
31
|
+
healthCheck?: BuiltInHealthCheck | HealthCheckFn | false;
|
|
32
|
+
/** URL builder function that returns the connection URL */
|
|
33
|
+
urlTemplate?: UrlBuilderFn;
|
|
34
|
+
/** Docker Compose service name (defaults to the key name) */
|
|
35
|
+
serviceName?: string;
|
|
36
|
+
/** Database name (for postgres, mysql, clickhouse). Enables built-in URL template. */
|
|
37
|
+
database?: string;
|
|
38
|
+
/** Username (default: 'postgres' for postgres, 'root' for mysql, 'default' for clickhouse) */
|
|
39
|
+
user?: string;
|
|
40
|
+
/** Password (default: 'postgres' for postgres, 'root' for mysql, 'clickhouse' for clickhouse) */
|
|
41
|
+
password?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Configuration for an application (e.g., api, web).
|
|
45
|
+
*/
|
|
46
|
+
export interface AppConfig {
|
|
47
|
+
/** Base port for the app (before offset is applied) */
|
|
48
|
+
port: number;
|
|
49
|
+
/** Command to start the dev server */
|
|
50
|
+
devCommand: string;
|
|
51
|
+
/** Command to start production server (optional) */
|
|
52
|
+
prodCommand?: string;
|
|
53
|
+
/** Command to build for production (optional) */
|
|
54
|
+
buildCommand?: string;
|
|
55
|
+
/** Working directory relative to monorepo root */
|
|
56
|
+
cwd?: string;
|
|
57
|
+
/** Health check endpoint path (e.g., '/api/health') */
|
|
58
|
+
healthEndpoint?: string;
|
|
59
|
+
/** Timeout for health check in milliseconds */
|
|
60
|
+
healthTimeout?: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Execution options for the exec helper.
|
|
64
|
+
*/
|
|
65
|
+
export interface ExecOptions {
|
|
66
|
+
/** Working directory relative to monorepo root */
|
|
67
|
+
cwd?: string;
|
|
68
|
+
/** Print output to console */
|
|
69
|
+
verbose?: boolean;
|
|
70
|
+
/** Environment variables to add */
|
|
71
|
+
env?: Record<string, string>;
|
|
72
|
+
/** Throw on non-zero exit code (default: true) */
|
|
73
|
+
throwOnError?: boolean;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Context passed to hooks for executing commands and accessing environment.
|
|
77
|
+
*/
|
|
78
|
+
export interface HookContext<TServices extends Record<string, ServiceConfig>, TApps extends Record<string, AppConfig>> {
|
|
79
|
+
/** Project name (with suffix if applicable) */
|
|
80
|
+
projectName: string;
|
|
81
|
+
/** Computed ports for all services and apps */
|
|
82
|
+
ports: ComputedPorts<TServices, TApps>;
|
|
83
|
+
/** Computed URLs for all services and apps */
|
|
84
|
+
urls: ComputedUrls<TServices, TApps>;
|
|
85
|
+
/** Execute a shell command with environment variables set */
|
|
86
|
+
exec: (cmd: string, options?: ExecOptions) => Promise<{
|
|
87
|
+
exitCode: number;
|
|
88
|
+
stdout: string;
|
|
89
|
+
stderr: string;
|
|
90
|
+
}>;
|
|
91
|
+
/** Path to monorepo root */
|
|
92
|
+
root: string;
|
|
93
|
+
/** Whether running in CI environment */
|
|
94
|
+
isCI: boolean;
|
|
95
|
+
/** Port offset applied to all ports */
|
|
96
|
+
portOffset: number;
|
|
97
|
+
/** Local IP address for mobile connectivity */
|
|
98
|
+
localIp: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Lifecycle hooks for customizing the dev environment.
|
|
102
|
+
*/
|
|
103
|
+
export interface DevHooks<TServices extends Record<string, ServiceConfig>, TApps extends Record<string, AppConfig>> {
|
|
104
|
+
/** Called after all containers are healthy */
|
|
105
|
+
afterContainersReady?: (ctx: HookContext<TServices, TApps>) => Promise<void>;
|
|
106
|
+
/** Called before starting dev servers */
|
|
107
|
+
beforeServers?: (ctx: HookContext<TServices, TApps>) => Promise<void>;
|
|
108
|
+
/** Called after dev servers are ready */
|
|
109
|
+
afterServers?: (ctx: HookContext<TServices, TApps>) => Promise<void>;
|
|
110
|
+
/** Called before stopping the environment */
|
|
111
|
+
beforeStop?: (ctx: HookContext<TServices, TApps>) => Promise<void>;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Configuration for Prisma integration.
|
|
115
|
+
*/
|
|
116
|
+
export interface PrismaConfig {
|
|
117
|
+
/** Working directory where prisma schema lives (relative to monorepo root). Default: 'packages/prisma' */
|
|
118
|
+
cwd?: string;
|
|
119
|
+
/** Docker Compose service name for the database. Default: 'postgres' */
|
|
120
|
+
service?: string;
|
|
121
|
+
/** Environment variable name for the database URL. Default: 'DATABASE_URL' */
|
|
122
|
+
urlEnvVar?: string;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Prisma runner interface available on dev.prisma when prisma is configured.
|
|
126
|
+
*/
|
|
127
|
+
export interface PrismaRunner {
|
|
128
|
+
/** Run a prisma command with the correct environment. Returns exit code. */
|
|
129
|
+
run(args: string[]): Promise<number>;
|
|
130
|
+
/** Get the database URL from the dev environment */
|
|
131
|
+
getDatabaseUrl(): string;
|
|
132
|
+
/** Ensure the database container is running and healthy */
|
|
133
|
+
ensureDatabase(): Promise<void>;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Configuration for a migration command to run after containers are ready.
|
|
137
|
+
*/
|
|
138
|
+
export interface MigrationConfig {
|
|
139
|
+
/** Display name for the migration (e.g., 'prisma', 'clickhouse') */
|
|
140
|
+
name: string;
|
|
141
|
+
/** Command to run the migration */
|
|
142
|
+
command: string;
|
|
143
|
+
/** Working directory relative to monorepo root */
|
|
144
|
+
cwd?: string;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Helper functions available in the seed check function.
|
|
148
|
+
*/
|
|
149
|
+
export interface SeedCheckHelpers<TServices extends Record<string, ServiceConfig>> {
|
|
150
|
+
/**
|
|
151
|
+
* Check if a database table is empty.
|
|
152
|
+
* Returns true if the table has 0 rows (needs seeding), false otherwise.
|
|
153
|
+
*
|
|
154
|
+
* @param tableName - The table name to check (e.g., 'User')
|
|
155
|
+
* @param service - The database service name. Default: 'postgres'
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```typescript
|
|
159
|
+
* seed: {
|
|
160
|
+
* command: 'bun run run:seeder',
|
|
161
|
+
* check: ({ checkTable }) => checkTable('User')
|
|
162
|
+
* }
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
checkTable: (tableName: string, service: keyof TServices) => Promise<boolean>;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Context passed to the seed check function.
|
|
169
|
+
*/
|
|
170
|
+
export type SeedCheckContext<TServices extends Record<string, ServiceConfig>, TApps extends Record<string, AppConfig>> = HookContext<TServices, TApps> & SeedCheckHelpers<TServices>;
|
|
171
|
+
/**
|
|
172
|
+
* Configuration for database seeding.
|
|
173
|
+
*/
|
|
174
|
+
export interface SeedConfig<TServices extends Record<string, ServiceConfig>, TApps extends Record<string, AppConfig>> {
|
|
175
|
+
/** Command to run the seeder */
|
|
176
|
+
command: string;
|
|
177
|
+
/** Working directory relative to monorepo root */
|
|
178
|
+
cwd?: string;
|
|
179
|
+
/**
|
|
180
|
+
* Check function to determine if seeding is needed.
|
|
181
|
+
* Return true to run the seed command, false to skip.
|
|
182
|
+
* If not provided, seeding always runs.
|
|
183
|
+
*
|
|
184
|
+
* Receives hook context plus helper functions like `checkTable`.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```typescript
|
|
188
|
+
* seed: {
|
|
189
|
+
* command: 'bun run run:seeder',
|
|
190
|
+
* check: ({ checkTable }) => checkTable('User')
|
|
191
|
+
* }
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
check?: (ctx: SeedCheckContext<TServices, TApps>) => Promise<boolean>;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Options for the dev environment.
|
|
198
|
+
*/
|
|
199
|
+
export interface DevOptions {
|
|
200
|
+
/** Enable worktree isolation (unique ports per worktree). Default: true */
|
|
201
|
+
worktreeIsolation?: boolean;
|
|
202
|
+
/** Auto-shutdown after idle time in ms. Set to false to disable. Default: false */
|
|
203
|
+
autoShutdown?: number | false;
|
|
204
|
+
/** Path to docker-compose.yml relative to root. Default: 'docker-compose.yml' */
|
|
205
|
+
composeFile?: string;
|
|
206
|
+
/** Default verbose setting for all operations. Default: true */
|
|
207
|
+
verbose?: boolean;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Environment variable builder function.
|
|
211
|
+
*/
|
|
212
|
+
export type EnvVarsBuilder<TServices extends Record<string, ServiceConfig>, TApps extends Record<string, AppConfig>> = (ports: ComputedPorts<TServices, TApps>, urls: ComputedUrls<TServices, TApps>, ctx: {
|
|
213
|
+
projectName: string;
|
|
214
|
+
localIp: string;
|
|
215
|
+
portOffset: number;
|
|
216
|
+
}) => Record<string, string | number>;
|
|
217
|
+
/**
|
|
218
|
+
* Main configuration for the dev environment.
|
|
219
|
+
*/
|
|
220
|
+
export interface DevConfig<TServices extends Record<string, ServiceConfig> = Record<string, ServiceConfig>, TApps extends Record<string, AppConfig> = Record<string, AppConfig>> {
|
|
221
|
+
/** Prefix for Docker project name (e.g., 'myapp' -> 'myapp-main') */
|
|
222
|
+
projectPrefix: string;
|
|
223
|
+
/** Docker Compose services to manage */
|
|
224
|
+
services: TServices;
|
|
225
|
+
/** Applications to start (optional) */
|
|
226
|
+
apps?: TApps;
|
|
227
|
+
/**
|
|
228
|
+
* Environment variables builder. Define all env vars here.
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* ```typescript
|
|
232
|
+
* envVars: (ports, urls, { localIp }) => ({
|
|
233
|
+
* DATABASE_URL: urls.postgres,
|
|
234
|
+
* BASE_URL: urls.api,
|
|
235
|
+
* VITE_PORT: ports.platform,
|
|
236
|
+
* EXPO_API_URL: `http://${localIp}:${ports.api}`
|
|
237
|
+
* })
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
envVars?: EnvVarsBuilder<TServices, TApps>;
|
|
241
|
+
/** Lifecycle hooks (optional) */
|
|
242
|
+
hooks?: DevHooks<TServices, TApps>;
|
|
243
|
+
/** Migrations to run after containers are ready (optional). Runs in parallel. */
|
|
244
|
+
migrations?: MigrationConfig[];
|
|
245
|
+
/** Seed configuration (optional). Runs after migrations, before servers. */
|
|
246
|
+
seed?: SeedConfig<TServices, TApps>;
|
|
247
|
+
/** Prisma configuration (optional). When set, dev.prisma is available. */
|
|
248
|
+
prisma?: PrismaConfig;
|
|
249
|
+
/** Additional options (optional) */
|
|
250
|
+
options?: DevOptions;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Computed ports object - maps service/app names to their port numbers.
|
|
254
|
+
*/
|
|
255
|
+
type ServicesWithSecondaryPort<TServices extends Record<string, ServiceConfig>> = {
|
|
256
|
+
[K in keyof TServices as TServices[K] extends {
|
|
257
|
+
secondaryPort: number;
|
|
258
|
+
} ? `${K & string}Secondary` : never]: number;
|
|
259
|
+
};
|
|
260
|
+
export type ComputedPorts<TServices extends Record<string, ServiceConfig>, TApps extends Record<string, AppConfig>> = {
|
|
261
|
+
[K in keyof TServices]: number;
|
|
262
|
+
} & {
|
|
263
|
+
[K in keyof TApps]: number;
|
|
264
|
+
} & ServicesWithSecondaryPort<TServices>;
|
|
265
|
+
/**
|
|
266
|
+
* Computed URLs object - maps service/app names to their URLs.
|
|
267
|
+
*/
|
|
268
|
+
export type ComputedUrls<TServices extends Record<string, ServiceConfig>, TApps extends Record<string, AppConfig>> = {
|
|
269
|
+
[K in keyof TServices]: string;
|
|
270
|
+
} & {
|
|
271
|
+
[K in keyof TApps]: string;
|
|
272
|
+
};
|
|
273
|
+
/**
|
|
274
|
+
* Options for starting the dev environment.
|
|
275
|
+
*/
|
|
276
|
+
export interface StartOptions {
|
|
277
|
+
/** Print output to console. Default: true */
|
|
278
|
+
verbose?: boolean;
|
|
279
|
+
/** Wait for containers to be healthy. Default: true */
|
|
280
|
+
wait?: boolean;
|
|
281
|
+
/** Start dev servers after containers. Default: true */
|
|
282
|
+
startServers?: boolean;
|
|
283
|
+
/** Use production build for servers. Default: false (true in CI) */
|
|
284
|
+
productionBuild?: boolean;
|
|
285
|
+
/** Environment suffix for isolation (e.g., 'test'). Default: undefined */
|
|
286
|
+
suffix?: string;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Options for stopping the dev environment.
|
|
290
|
+
*/
|
|
291
|
+
export interface StopOptions {
|
|
292
|
+
/** Print output to console. Default: true */
|
|
293
|
+
verbose?: boolean;
|
|
294
|
+
/** Remove Docker volumes (destroys data). Default: false */
|
|
295
|
+
removeVolumes?: boolean;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Process IDs for running dev servers.
|
|
299
|
+
*/
|
|
300
|
+
export interface DevServerPids {
|
|
301
|
+
[appName: string]: number;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* The main dev environment interface returned by createDevEnvironment().
|
|
305
|
+
*/
|
|
306
|
+
export interface DevEnvironment<TServices extends Record<string, ServiceConfig>, TApps extends Record<string, AppConfig>> {
|
|
307
|
+
/** Docker project name (includes suffix if set) */
|
|
308
|
+
readonly projectName: string;
|
|
309
|
+
/** Computed ports for all services and apps */
|
|
310
|
+
readonly ports: ComputedPorts<TServices, TApps>;
|
|
311
|
+
/** Computed URLs for all services and apps */
|
|
312
|
+
readonly urls: ComputedUrls<TServices, TApps>;
|
|
313
|
+
/** Apps configuration (for CLI to build commands) */
|
|
314
|
+
readonly apps: TApps;
|
|
315
|
+
/** Port offset applied (0 for main, > 0 for worktrees) */
|
|
316
|
+
readonly portOffset: number;
|
|
317
|
+
/** Whether running in a git worktree */
|
|
318
|
+
readonly isWorktree: boolean;
|
|
319
|
+
/** Local IP address for mobile connectivity */
|
|
320
|
+
readonly localIp: string;
|
|
321
|
+
/** Path to monorepo root */
|
|
322
|
+
readonly root: string;
|
|
323
|
+
/** Start the dev environment (containers + optional servers) */
|
|
324
|
+
start(options?: StartOptions): Promise<DevServerPids | null>;
|
|
325
|
+
/** Stop the dev environment */
|
|
326
|
+
stop(options?: StopOptions): Promise<void>;
|
|
327
|
+
/** Restart containers only */
|
|
328
|
+
restart(): Promise<void>;
|
|
329
|
+
/** Check if containers are running */
|
|
330
|
+
isRunning(): Promise<boolean>;
|
|
331
|
+
/** Start dev servers only (assumes containers are running) */
|
|
332
|
+
startServers(options?: {
|
|
333
|
+
productionBuild?: boolean;
|
|
334
|
+
verbose?: boolean;
|
|
335
|
+
}): Promise<DevServerPids>;
|
|
336
|
+
/** Stop a process by PID */
|
|
337
|
+
stopProcess(pid: number): void;
|
|
338
|
+
/** Wait for servers to be ready */
|
|
339
|
+
waitForServers(options?: {
|
|
340
|
+
timeout?: number;
|
|
341
|
+
productionBuild?: boolean;
|
|
342
|
+
}): Promise<void>;
|
|
343
|
+
/** Build environment variables for shell commands */
|
|
344
|
+
buildEnvVars(production?: boolean): Record<string, string>;
|
|
345
|
+
/** Execute a command with environment variables set */
|
|
346
|
+
exec(cmd: string, options?: ExecOptions): Promise<{
|
|
347
|
+
exitCode: number;
|
|
348
|
+
stdout: string;
|
|
349
|
+
stderr: string;
|
|
350
|
+
}>;
|
|
351
|
+
/** Wait for an HTTP server to respond */
|
|
352
|
+
waitForServer(url: string, timeout?: number): Promise<void>;
|
|
353
|
+
/** Log environment info to console */
|
|
354
|
+
logInfo(label?: string): void;
|
|
355
|
+
/**
|
|
356
|
+
* Get the Expo API URL (http://<local-ip>:<api-port>) and log it for detection.
|
|
357
|
+
* Used by tools like Vibe Kanban to find the API server for mobile testing.
|
|
358
|
+
*/
|
|
359
|
+
getExpoApiUrl(): string;
|
|
360
|
+
/**
|
|
361
|
+
* Get the frontend port and log it for detection.
|
|
362
|
+
* Used by tools like Vibe Kanban to find the dev server.
|
|
363
|
+
*/
|
|
364
|
+
getFrontendPort(): number | undefined;
|
|
365
|
+
/** Start writing heartbeat for watchdog */
|
|
366
|
+
startHeartbeat(intervalMs?: number): void;
|
|
367
|
+
/** Stop writing heartbeat */
|
|
368
|
+
stopHeartbeat(): void;
|
|
369
|
+
/** Spawn watchdog process for auto-shutdown */
|
|
370
|
+
spawnWatchdog(timeoutMinutes?: number): Promise<void>;
|
|
371
|
+
/** Stop the watchdog process */
|
|
372
|
+
stopWatchdog(): void;
|
|
373
|
+
/** Prisma runner (only available when prisma is configured) */
|
|
374
|
+
readonly prisma?: PrismaRunner;
|
|
375
|
+
/** Create a new environment with a different suffix (for test isolation) */
|
|
376
|
+
withSuffix(suffix: string): DevEnvironment<TServices, TApps>;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Options for the CLI runner.
|
|
380
|
+
*/
|
|
381
|
+
export interface CliOptions {
|
|
382
|
+
/** Custom args (defaults to process.argv.slice(2)) */
|
|
383
|
+
args?: string[];
|
|
384
|
+
/** Enable watchdog auto-shutdown (default: true) */
|
|
385
|
+
watchdog?: boolean;
|
|
386
|
+
/** Watchdog timeout in minutes (default: 10) */
|
|
387
|
+
watchdogTimeout?: number;
|
|
388
|
+
/** Command to run dev servers (e.g., 'bun concurrently ...') */
|
|
389
|
+
devServersCommand?: string;
|
|
390
|
+
}
|
|
391
|
+
export {};
|