chore: added bun dw enable / disable

This commit is contained in:
johnyeo
2026-05-19 18:01:48 +01:00
parent 36e530dee7
commit f46bdad307
8 changed files with 102 additions and 3 deletions

View File

@@ -85,6 +85,8 @@
"dw:identify": "ENV_FILE=.env infisical run --env=dev --recursive -- bun scripts/dw/index.ts identify",
"dw:setup": "ENV_FILE=.env infisical run --env=dev --recursive -- bun scripts/dw/index.ts setup",
"dw:run": "ENV_FILE=.env infisical run --env=dev --recursive -- bun scripts/dw/index.ts run",
"dw:enable": "bun scripts/dw/index.ts enable",
"dw:disable": "bun scripts/dw/index.ts disable",
"d": "ENV_FILE=.env infisical run --env=dev --recursive -- bun scripts/dev.ts",
"d:prod": "ENV_FILE=.env infisical run --env=dev --recursive -- bun scripts/dev.ts --production",
"dx": "bun scripts/dx.ts",

View File

@@ -34,6 +34,8 @@ bun dw logs # tail last 2000 lines without attaching
bun dw reset # nuke DB branch + containers → re-provision
bun dw teardown # full cleanup of this worktree
bun dw teardown --all # full cleanup of every agent worktree
bun dw disable # rename .env.local -> .env.local.disabled (fall back to canonical env)
bun dw enable # rename .env.local.disabled -> .env.local
```
## Subcommands
@@ -113,6 +115,20 @@ Attaches your terminal to the worktree's tmux session. Detach with `Ctrl+B` then
bun dw attach
```
### `bun dw disable`
Renames each managed `.env.local` to `.env.local.disabled` so tooling falls back to the canonical (infisical-injected) env. Useful when a test or script needs the canonical env without nuking your worktree provisioning.
```sh
bun dw disable
```
### `bun dw enable`
Inverse of `disable` — restores each `.env.local.disabled` to `.env.local`.
```sh
bun dw enable
```
### `bun dw teardown`
Full cleanup of the current worktree: deletes Neon branch, unregisters portless aliases, kills tmux session, removes Docker compose stack, removes `.env.local` files, and deletes the registry entry. If no other agent worktrees remain, also stops emulate + portless daemons.

View File

@@ -0,0 +1,9 @@
import { log } from "../helpers/shell.ts";
import { disableEnvLocalFiles } from "../helpers/env-files.ts";
export function cmdDisable(): void {
const { moved, missing, alreadyDisabled } = disableEnvLocalFiles();
log(
`disable: ${moved} renamed, ${alreadyDisabled} already disabled, ${missing} not present`,
);
}

View File

@@ -0,0 +1,9 @@
import { log } from "../helpers/shell.ts";
import { enableEnvLocalFiles } from "../helpers/env-files.ts";
export function cmdEnable(): void {
const { moved, missing, alreadyEnabled } = enableEnvLocalFiles();
log(
`enable: ${moved} restored, ${alreadyEnabled} already enabled, ${missing} not present`,
);
}

View File

@@ -25,3 +25,5 @@ export const ENV_LOCAL_TARGETS = [
"vite/.env.local",
"apps/checkout/.env.local",
] as const;
export const ENV_LOCAL_DISABLED_SUFFIX = ".disabled";

View File

@@ -1,10 +1,10 @@
import { existsSync, readFileSync, writeFileSync, rmSync } from "node:fs";
import { existsSync, readFileSync, renameSync, writeFileSync, rmSync } from "node:fs";
import { dirname, join } from "node:path";
import { homedir } from "node:os";
import { log } from "./shell.ts";
import { forceSslVerifyFull } from "./url.ts";
import { aliasesFor, dragonflyPortFor, elasticMqPortFor } from "./ports.ts";
import { PROJECT_ROOT, ENV_LOCAL_TARGETS } from "../constants.ts";
import { PROJECT_ROOT, ENV_LOCAL_TARGETS, ENV_LOCAL_DISABLED_SUFFIX } from "../constants.ts";
import type { RegistryEntry } from "../types.ts";
// Simple KEY=VALUE parse (no quoting/multiline). Sufficient for .env.local
@@ -121,5 +121,52 @@ export function removeEnvLocalFiles(): void {
rmSync(abs, { force: true });
log(`removed ${rel}`);
}
const disabled = `${abs}${ENV_LOCAL_DISABLED_SUFFIX}`;
if (existsSync(disabled)) {
rmSync(disabled, { force: true });
log(`removed ${rel}${ENV_LOCAL_DISABLED_SUFFIX}`);
}
}
}
export function disableEnvLocalFiles(): { moved: number; missing: number; alreadyDisabled: number } {
let moved = 0;
let missing = 0;
let alreadyDisabled = 0;
for (const rel of ENV_LOCAL_TARGETS) {
const abs = join(PROJECT_ROOT, rel);
const disabled = `${abs}${ENV_LOCAL_DISABLED_SUFFIX}`;
if (existsSync(abs)) {
if (existsSync(disabled)) rmSync(disabled, { force: true });
renameSync(abs, disabled);
log(`disabled ${rel} -> ${rel}${ENV_LOCAL_DISABLED_SUFFIX}`);
moved++;
} else if (existsSync(disabled)) {
alreadyDisabled++;
} else {
missing++;
}
}
return { moved, missing, alreadyDisabled };
}
export function enableEnvLocalFiles(): { moved: number; missing: number; alreadyEnabled: number } {
let moved = 0;
let missing = 0;
let alreadyEnabled = 0;
for (const rel of ENV_LOCAL_TARGETS) {
const abs = join(PROJECT_ROOT, rel);
const disabled = `${abs}${ENV_LOCAL_DISABLED_SUFFIX}`;
if (existsSync(disabled)) {
if (existsSync(abs)) rmSync(abs, { force: true });
renameSync(disabled, abs);
log(`enabled ${rel}`);
moved++;
} else if (existsSync(abs)) {
alreadyEnabled++;
} else {
missing++;
}
}
return { moved, missing, alreadyEnabled };
}

View File

@@ -8,6 +8,8 @@ import { cmdReset } from "./commands/reset.ts";
import { cmdLogs } from "./commands/logs.ts";
import { cmdAttach } from "./commands/attach.ts";
import { cmdIdentify } from "./commands/identify.ts";
import { cmdEnable } from "./commands/enable.ts";
import { cmdDisable } from "./commands/disable.ts";
async function main(): Promise<void> {
const sub = process.argv[2];
@@ -40,9 +42,15 @@ async function main(): Promise<void> {
case "identify":
cmdIdentify();
break;
case "enable":
cmdEnable();
break;
case "disable":
cmdDisable();
break;
default:
fatal(
`unknown subcommand: ${sub} (use: setup | run | teardown | list | reset | logs | attach | identify)`,
`unknown subcommand: ${sub} (use: setup | run | teardown | list | reset | logs | attach | identify | enable | disable)`,
);
}
}

View File

@@ -5,6 +5,12 @@ import react from "@vitejs/plugin-react";
import { defineConfig, type Plugin } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
// Defaults so the app works when no .env.local is present
// (e.g. after `bun dw disable`). Real values from .env / infisical /
// process.env still take precedence.
process.env.VITE_BACKEND_URL ||= "http://localhost:8080";
process.env.VITE_FRONTEND_URL ||= "http://localhost:3000";
function printPortlessUrl(): Plugin {
return {
name: "print-portless-url",