@slowcook-ai/cli 0.19.0-alpha.18 → 0.19.0-alpha.40
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/dist/cli.js +28 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/brand/index.d.ts +58 -0
- package/dist/commands/brand/index.d.ts.map +1 -0
- package/dist/commands/brand/index.js +257 -0
- package/dist/commands/brand/index.js.map +1 -0
- package/dist/commands/budget/index.d.ts +2 -0
- package/dist/commands/budget/index.d.ts.map +1 -0
- package/dist/commands/budget/index.js +252 -0
- package/dist/commands/budget/index.js.map +1 -0
- package/dist/commands/dev-env/config.d.ts +136 -0
- package/dist/commands/dev-env/config.d.ts.map +1 -0
- package/dist/commands/dev-env/config.js +96 -0
- package/dist/commands/dev-env/config.js.map +1 -0
- package/dist/commands/dev-env/index.d.ts +27 -0
- package/dist/commands/dev-env/index.d.ts.map +1 -0
- package/dist/commands/dev-env/index.js +226 -0
- package/dist/commands/dev-env/index.js.map +1 -0
- package/dist/commands/dev-env/init.d.ts +28 -0
- package/dist/commands/dev-env/init.d.ts.map +1 -0
- package/dist/commands/dev-env/init.js +135 -0
- package/dist/commands/dev-env/init.js.map +1 -0
- package/dist/commands/eval/index.d.ts.map +1 -1
- package/dist/commands/eval/index.js +15 -1
- package/dist/commands/eval/index.js.map +1 -1
- package/dist/commands/init/mock-vite.d.ts +54 -0
- package/dist/commands/init/mock-vite.d.ts.map +1 -0
- package/dist/commands/init/mock-vite.js +611 -0
- package/dist/commands/init/mock-vite.js.map +1 -0
- package/dist/commands/init/mock.d.ts +6 -0
- package/dist/commands/init/mock.d.ts.map +1 -1
- package/dist/commands/init/mock.js +20 -4
- package/dist/commands/init/mock.js.map +1 -1
- package/dist/commands/plate/agent.d.ts +7 -0
- package/dist/commands/plate/agent.d.ts.map +1 -1
- package/dist/commands/plate/agent.js +1 -1
- package/dist/commands/plate/agent.js.map +1 -1
- package/dist/commands/plate/index.d.ts.map +1 -1
- package/dist/commands/plate/index.js +6 -0
- package/dist/commands/plate/index.js.map +1 -1
- package/dist/commands/refine/agent.d.ts +12 -0
- package/dist/commands/refine/agent.d.ts.map +1 -1
- package/dist/commands/refine/agent.js +173 -13
- package/dist/commands/refine/agent.js.map +1 -1
- package/dist/commands/refine/brownfield-answer.d.ts +81 -0
- package/dist/commands/refine/brownfield-answer.d.ts.map +1 -0
- package/dist/commands/refine/brownfield-answer.js +231 -0
- package/dist/commands/refine/brownfield-answer.js.map +1 -0
- package/dist/commands/refine/context.d.ts.map +1 -1
- package/dist/commands/refine/context.js +18 -0
- package/dist/commands/refine/context.js.map +1 -1
- package/dist/commands/refine/history-index.d.ts +29 -0
- package/dist/commands/refine/history-index.d.ts.map +1 -1
- package/dist/commands/refine/history-index.js +63 -0
- package/dist/commands/refine/history-index.js.map +1 -1
- package/dist/commands/refine/index.d.ts.map +1 -1
- package/dist/commands/refine/index.js +32 -1
- package/dist/commands/refine/index.js.map +1 -1
- package/dist/commands/refine/proposals-synth.d.ts +50 -1
- package/dist/commands/refine/proposals-synth.d.ts.map +1 -1
- package/dist/commands/refine/proposals-synth.js +199 -35
- package/dist/commands/refine/proposals-synth.js.map +1 -1
- package/dist/commands/refine/spec-yaml.d.ts +274 -250
- package/dist/commands/refine/spec-yaml.d.ts.map +1 -1
- package/dist/commands/refine/spec-yaml.js +10 -0
- package/dist/commands/refine/spec-yaml.js.map +1 -1
- package/dist/commands/run-mock/index.d.ts.map +1 -1
- package/dist/commands/run-mock/index.js +7 -1
- package/dist/commands/run-mock/index.js.map +1 -1
- package/dist/commands/testgen/agent.d.ts.map +1 -1
- package/dist/commands/testgen/agent.js +34 -9
- package/dist/commands/testgen/agent.js.map +1 -1
- package/dist/commands/vibe/agent.d.ts +7 -0
- package/dist/commands/vibe/agent.d.ts.map +1 -1
- package/dist/commands/vibe/agent.js +2 -2
- package/dist/commands/vibe/agent.js.map +1 -1
- package/dist/commands/vibe/index.d.ts.map +1 -1
- package/dist/commands/vibe/index.js +7 -1
- package/dist/commands/vibe/index.js.map +1 -1
- package/dist/cost-store.d.ts +52 -0
- package/dist/cost-store.d.ts.map +1 -0
- package/dist/cost-store.js +108 -0
- package/dist/cost-store.js.map +1 -0
- package/dist/lib/budget.d.ts +123 -0
- package/dist/lib/budget.d.ts.map +1 -0
- package/dist/lib/budget.js +225 -0
- package/dist/lib/budget.js.map +1 -0
- package/dist/lib/mock-shape.d.ts +44 -0
- package/dist/lib/mock-shape.d.ts.map +1 -0
- package/dist/lib/mock-shape.js +77 -0
- package/dist/lib/mock-shape.js.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0.19.0-α.35 (sc#66 follow-up) — `slowcook budget` subcommand.
|
|
3
|
+
*
|
|
4
|
+
* slowcook budget # show config + month-to-date spend
|
|
5
|
+
* slowcook budget set --monthly 50 # set monthly_budget_usd
|
|
6
|
+
* slowcook budget set --monthly 50 --start-day 15 --story 10
|
|
7
|
+
* slowcook budget rm # delete config (disables gauge)
|
|
8
|
+
*
|
|
9
|
+
* Writes/reads `.brewing/budget.yaml`. Idempotent: `set` merges into
|
|
10
|
+
* existing config; absent flags keep their current values; missing
|
|
11
|
+
* monthly_budget_usd on a brand-new config defaults nothing (must be
|
|
12
|
+
* supplied at least once).
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import YAML from "yaml";
|
|
17
|
+
import { loadBudgetConfig, aggregateMonthSpend, aggregateSpendSince, currentPeriodStart, classifyBudgetStatus, } from "../../lib/budget.js";
|
|
18
|
+
function parseArgs(argv) {
|
|
19
|
+
const args = { cwd: process.cwd(), action: "show" };
|
|
20
|
+
const positional = [];
|
|
21
|
+
for (let i = 0; i < argv.length; i++) {
|
|
22
|
+
const arg = argv[i];
|
|
23
|
+
const next = argv[i + 1];
|
|
24
|
+
if (arg === "--cwd" && next) {
|
|
25
|
+
args.cwd = next;
|
|
26
|
+
i++;
|
|
27
|
+
}
|
|
28
|
+
else if (arg === "--monthly" && next) {
|
|
29
|
+
args.monthly = Number(next);
|
|
30
|
+
i++;
|
|
31
|
+
}
|
|
32
|
+
else if (arg === "--start-day" && next) {
|
|
33
|
+
args.startDay = Number(next);
|
|
34
|
+
i++;
|
|
35
|
+
}
|
|
36
|
+
else if (arg === "--story" && next) {
|
|
37
|
+
args.story = Number(next);
|
|
38
|
+
i++;
|
|
39
|
+
}
|
|
40
|
+
else if (arg === "--credit" && next) {
|
|
41
|
+
args.credit = Number(next);
|
|
42
|
+
i++;
|
|
43
|
+
}
|
|
44
|
+
else if (arg === "--credit-baseline" && next) {
|
|
45
|
+
args.creditBaselineAt = next;
|
|
46
|
+
i++;
|
|
47
|
+
}
|
|
48
|
+
else if (arg === "--help" || arg === "-h") {
|
|
49
|
+
printHelp();
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
else if (arg && !arg.startsWith("--")) {
|
|
53
|
+
positional.push(arg);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const verb = positional[0];
|
|
57
|
+
if (verb === "set" || verb === "rm")
|
|
58
|
+
args.action = verb;
|
|
59
|
+
else if (verb && verb !== "show") {
|
|
60
|
+
throw new Error(`Unknown budget action: ${verb}. Use show | set | rm.`);
|
|
61
|
+
}
|
|
62
|
+
return args;
|
|
63
|
+
}
|
|
64
|
+
function printHelp() {
|
|
65
|
+
console.log(`
|
|
66
|
+
slowcook budget — manage the project budget(s) for the fuel gauge
|
|
67
|
+
|
|
68
|
+
Two independent gauges, both optional, both opt-in:
|
|
69
|
+
|
|
70
|
+
monthly_budget_usd A per-period cap that resets each month.
|
|
71
|
+
credit_balance_usd A non-recurring credit deposit (e.g. you topped
|
|
72
|
+
up $25 on Anthropic and DON'T have auto-recharge);
|
|
73
|
+
the gauge subtracts ALL-TIME spend from this.
|
|
74
|
+
|
|
75
|
+
Usage:
|
|
76
|
+
slowcook budget Show current config + spend
|
|
77
|
+
slowcook budget set --monthly <usd> Set the monthly cap
|
|
78
|
+
slowcook budget set --monthly 50 --start-day 15 Non-1st reset day
|
|
79
|
+
slowcook budget set --credit <usd> Track a one-shot deposit
|
|
80
|
+
slowcook budget set --story <usd> Optional per-story ceiling
|
|
81
|
+
slowcook budget rm Delete .brewing/budget.yaml
|
|
82
|
+
|
|
83
|
+
Flags:
|
|
84
|
+
--monthly <usd> Monthly budget in USD. Resets each period.
|
|
85
|
+
--start-day <1-31> Calendar day the monthly budget resets. Default 1.
|
|
86
|
+
--credit <usd> One-shot credit deposit. Captures the date of set as
|
|
87
|
+
a baseline; spend tracked from there. Re-run to top up.
|
|
88
|
+
--story <usd> Optional per-story informational ceiling.
|
|
89
|
+
--cwd <path> Project root. Defaults to current working dir.
|
|
90
|
+
|
|
91
|
+
When set, every refine comment appends:
|
|
92
|
+
⛽ Project this month: $X of $Y (monthly cap)
|
|
93
|
+
🪙 Anthropic credit: $X of $Y (credit balance)
|
|
94
|
+
|
|
95
|
+
Both fire ⚠️ at 80% and 🛑 at 95%.
|
|
96
|
+
|
|
97
|
+
Top-up workflow (no auto-recharge):
|
|
98
|
+
$ slowcook budget set --credit 25 # at the start of $25 deposit
|
|
99
|
+
... burn through credit ...
|
|
100
|
+
$ slowcook budget set --credit 50 # after topping up to $50 (new baseline)
|
|
101
|
+
`);
|
|
102
|
+
}
|
|
103
|
+
function configPath(cwd) {
|
|
104
|
+
return join(cwd, ".brewing", "budget.yaml");
|
|
105
|
+
}
|
|
106
|
+
function fmtUsd(n) {
|
|
107
|
+
return `$${n.toFixed(2)}`;
|
|
108
|
+
}
|
|
109
|
+
export async function budget(argv) {
|
|
110
|
+
let parsed;
|
|
111
|
+
try {
|
|
112
|
+
parsed = parseArgs(argv);
|
|
113
|
+
}
|
|
114
|
+
catch (e) {
|
|
115
|
+
console.error(e.message);
|
|
116
|
+
process.exit(2);
|
|
117
|
+
}
|
|
118
|
+
if (parsed.action === "rm") {
|
|
119
|
+
const p = configPath(parsed.cwd);
|
|
120
|
+
if (!existsSync(p)) {
|
|
121
|
+
console.log(`No .brewing/budget.yaml — nothing to remove.`);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
unlinkSync(p);
|
|
125
|
+
console.log(`Removed ${p}. Fuel gauge now disabled.`);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (parsed.action === "set") {
|
|
129
|
+
// Merge into existing config; allow updating individual fields.
|
|
130
|
+
let existing = null;
|
|
131
|
+
try {
|
|
132
|
+
existing = loadBudgetConfig(parsed.cwd);
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
console.error(`Existing config is invalid — fix or rm first: ${e.message}`);
|
|
136
|
+
process.exit(2);
|
|
137
|
+
}
|
|
138
|
+
const monthly = parsed.monthly ?? existing?.monthly_budget_usd;
|
|
139
|
+
if (monthly !== undefined && (!Number.isFinite(monthly) || monthly <= 0)) {
|
|
140
|
+
console.error(`--monthly must be a positive number, got ${parsed.monthly}`);
|
|
141
|
+
process.exit(2);
|
|
142
|
+
}
|
|
143
|
+
const startDay = parsed.startDay ?? existing?.monthly_start_day ?? 1;
|
|
144
|
+
if (!Number.isInteger(startDay) || startDay < 1 || startDay > 31) {
|
|
145
|
+
console.error(`--start-day must be an integer 1-31, got ${parsed.startDay}`);
|
|
146
|
+
process.exit(2);
|
|
147
|
+
}
|
|
148
|
+
const story = parsed.story ?? existing?.story_budget_usd;
|
|
149
|
+
if (story !== undefined && (!Number.isFinite(story) || story <= 0)) {
|
|
150
|
+
console.error(`--story must be a positive number, got ${parsed.story}`);
|
|
151
|
+
process.exit(2);
|
|
152
|
+
}
|
|
153
|
+
// Credit handling — a fresh --credit captures "now" as the
|
|
154
|
+
// baseline. Re-running --credit (top-up) refreshes the baseline so
|
|
155
|
+
// the gauge tracks ONLY spend from the new deposit forward.
|
|
156
|
+
let credit = existing?.credit_balance_usd;
|
|
157
|
+
let creditBaselineAt = existing?.credit_baseline_at;
|
|
158
|
+
if (parsed.credit !== undefined) {
|
|
159
|
+
if (!Number.isFinite(parsed.credit) || parsed.credit <= 0) {
|
|
160
|
+
console.error(`--credit must be a positive number, got ${parsed.credit}`);
|
|
161
|
+
process.exit(2);
|
|
162
|
+
}
|
|
163
|
+
credit = parsed.credit;
|
|
164
|
+
creditBaselineAt = parsed.creditBaselineAt ?? new Date().toISOString();
|
|
165
|
+
}
|
|
166
|
+
if (monthly === undefined && credit === undefined) {
|
|
167
|
+
console.error(`Set at least one of --monthly or --credit. Try: slowcook budget set --credit 25`);
|
|
168
|
+
process.exit(2);
|
|
169
|
+
}
|
|
170
|
+
const next = {
|
|
171
|
+
schema_version: 1,
|
|
172
|
+
monthly_start_day: startDay,
|
|
173
|
+
...(monthly !== undefined ? { monthly_budget_usd: monthly } : {}),
|
|
174
|
+
...(story !== undefined ? { story_budget_usd: story } : {}),
|
|
175
|
+
...(credit !== undefined ? { credit_balance_usd: credit } : {}),
|
|
176
|
+
...(creditBaselineAt !== undefined ? { credit_baseline_at: creditBaselineAt } : {}),
|
|
177
|
+
};
|
|
178
|
+
const p = configPath(parsed.cwd);
|
|
179
|
+
mkdirSync(join(parsed.cwd, ".brewing"), { recursive: true });
|
|
180
|
+
writeFileSync(p, YAML.stringify(next, { lineWidth: 0 }), "utf8");
|
|
181
|
+
const verb = existing ? "Updated" : "Wrote";
|
|
182
|
+
console.log(`${verb} ${p}`);
|
|
183
|
+
console.log(readFileSync(p, "utf8"));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
// show
|
|
187
|
+
let config;
|
|
188
|
+
try {
|
|
189
|
+
config = loadBudgetConfig(parsed.cwd);
|
|
190
|
+
}
|
|
191
|
+
catch (e) {
|
|
192
|
+
console.error(`Config at ${configPath(parsed.cwd)} is invalid: ${e.message}`);
|
|
193
|
+
process.exit(2);
|
|
194
|
+
}
|
|
195
|
+
if (!config) {
|
|
196
|
+
console.log(`No .brewing/budget.yaml — fuel gauge disabled.`);
|
|
197
|
+
console.log(`Set one with: slowcook budget set --credit 25 (one-shot deposit)`);
|
|
198
|
+
console.log(` or: slowcook budget set --monthly 50 (recurring cap)`);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const now = new Date();
|
|
202
|
+
console.log(`Config: ${configPath(parsed.cwd)}`);
|
|
203
|
+
if (config.monthly_budget_usd !== undefined) {
|
|
204
|
+
console.log(` monthly_budget_usd: ${fmtUsd(config.monthly_budget_usd)}`);
|
|
205
|
+
console.log(` monthly_start_day: ${config.monthly_start_day}`);
|
|
206
|
+
}
|
|
207
|
+
if (config.story_budget_usd !== undefined) {
|
|
208
|
+
console.log(` story_budget_usd: ${fmtUsd(config.story_budget_usd)}`);
|
|
209
|
+
}
|
|
210
|
+
if (config.credit_balance_usd !== undefined) {
|
|
211
|
+
console.log(` credit_balance_usd: ${fmtUsd(config.credit_balance_usd)}`);
|
|
212
|
+
console.log(` credit_baseline_at: ${config.credit_baseline_at ?? "(unset)"}`);
|
|
213
|
+
}
|
|
214
|
+
console.log(``);
|
|
215
|
+
if (config.monthly_budget_usd !== undefined) {
|
|
216
|
+
const period = currentPeriodStart(config, now);
|
|
217
|
+
const spend = aggregateMonthSpend(parsed.cwd, config, now);
|
|
218
|
+
const status = classifyBudgetStatus(spend.usd, config.monthly_budget_usd);
|
|
219
|
+
const pct = Math.round((spend.usd / config.monthly_budget_usd) * 100);
|
|
220
|
+
const icon = status === "halt" ? "🛑" : status === "warn" ? "⚠️" : "⛽";
|
|
221
|
+
console.log(`Period start: ${period.toISOString().slice(0, 10)}`);
|
|
222
|
+
console.log(`${icon} Spent this period: ${fmtUsd(spend.usd)} of ${fmtUsd(config.monthly_budget_usd)} (${pct}%)`);
|
|
223
|
+
console.log(` ${spend.entryCount} entr${spend.entryCount === 1 ? "y" : "ies"} across ${spend.storyCount} stor${spend.storyCount === 1 ? "y" : "ies"}.`);
|
|
224
|
+
if (status === "warn") {
|
|
225
|
+
console.log(` ⚠️ approaching monthly budget — consider topping up.`);
|
|
226
|
+
}
|
|
227
|
+
else if (status === "halt") {
|
|
228
|
+
console.log(` 🛑 over budget — agents will halt without the override-budget label.`);
|
|
229
|
+
}
|
|
230
|
+
console.log(``);
|
|
231
|
+
}
|
|
232
|
+
if (config.credit_balance_usd !== undefined && config.credit_baseline_at) {
|
|
233
|
+
const baseline = new Date(config.credit_baseline_at);
|
|
234
|
+
const spend = aggregateSpendSince(parsed.cwd, baseline);
|
|
235
|
+
const status = classifyBudgetStatus(spend.usd, config.credit_balance_usd);
|
|
236
|
+
const remaining = Math.max(0, config.credit_balance_usd - spend.usd);
|
|
237
|
+
const pctLeft = Math.max(0, 100 - Math.round((spend.usd / config.credit_balance_usd) * 100));
|
|
238
|
+
const icon = status === "halt" ? "🛑" : status === "warn" ? "⚠️" : "🪙";
|
|
239
|
+
console.log(`Credit baseline: ${config.credit_baseline_at.slice(0, 10)}`);
|
|
240
|
+
console.log(`${icon} Anthropic credit: ${fmtUsd(remaining)} of ${fmtUsd(config.credit_balance_usd)} remaining (${pctLeft}%)`);
|
|
241
|
+
console.log(` Spent ${fmtUsd(spend.usd)} since baseline. ${spend.entryCount} entr${spend.entryCount === 1 ? "y" : "ies"}.`);
|
|
242
|
+
if (status === "warn") {
|
|
243
|
+
console.log(` ⚠️ approaching empty — top up at https://console.anthropic.com/settings/billing.`);
|
|
244
|
+
console.log(` Then: slowcook budget set --credit <new-total> # captures fresh baseline`);
|
|
245
|
+
}
|
|
246
|
+
else if (status === "halt") {
|
|
247
|
+
console.log(` 🛑 credit nearly exhausted — pipeline will halt on 402 imminently.`);
|
|
248
|
+
console.log(` Top up + re-run: slowcook budget set --credit <new-total>`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/budget/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACzF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,GAErB,MAAM,qBAAqB,CAAC;AAa7B,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,IAAI,GAAe,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAChE,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzB,IAAI,GAAG,KAAK,OAAO,IAAI,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;YAChB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,WAAW,IAAI,IAAI,EAAE,CAAC;YACvC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,aAAa,IAAI,IAAI,EAAE,CAAC;YACzC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,IAAI,IAAI,EAAE,CAAC;YACrC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,UAAU,IAAI,IAAI,EAAE,CAAC;YACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC3B,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,mBAAmB,IAAI,IAAI,EAAE,CAAC;YAC/C,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAC7B,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YAC5C,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;aAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI;QAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;SACnD,IAAI,IAAI,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,wBAAwB,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCb,CAAC,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,MAAM,CAAC,CAAS;IACvB,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAc;IACzC,IAAI,MAAkB,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAE,CAAW,CAAC,OAAO,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QACD,UAAU,CAAC,CAAC,CAAC,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC;QACtD,OAAO;IACT,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC5B,gEAAgE;QAChE,IAAI,QAAQ,GAAwB,IAAI,CAAC;QACzC,IAAI,CAAC;YACH,QAAQ,GAAG,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,iDAAkD,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YACvF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,QAAQ,EAAE,kBAAkB,CAAC;QAC/D,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC;YACzE,OAAO,CAAC,KAAK,CAAC,4CAA4C,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,QAAQ,EAAE,iBAAiB,IAAI,CAAC,CAAC;QACrE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,IAAI,QAAQ,GAAG,EAAE,EAAE,CAAC;YACjE,OAAO,CAAC,KAAK,CAAC,4CAA4C,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,QAAQ,EAAE,gBAAgB,CAAC;QACzD,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC;YACnE,OAAO,CAAC,KAAK,CAAC,0CAA0C,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,2DAA2D;QAC3D,mEAAmE;QACnE,4DAA4D;QAC5D,IAAI,MAAM,GAAuB,QAAQ,EAAE,kBAAkB,CAAC;QAC9D,IAAI,gBAAgB,GAAuB,QAAQ,EAAE,kBAAkB,CAAC;QACxE,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBAC1D,OAAO,CAAC,KAAK,CAAC,2CAA2C,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;gBAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YACvB,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACzE,CAAC;QAED,IAAI,OAAO,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAClD,OAAO,CAAC,KAAK,CACX,iFAAiF,CAClF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,GAAiB;YACzB,cAAc,EAAE,CAAC;YACjB,iBAAiB,EAAE,QAAQ;YAC3B,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjE,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,GAAG,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpF,CAAC;QAEF,MAAM,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,OAAO;IACP,IAAI,MAA2B,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,aAAa,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,gBAAiB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAC;QACtF,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC;QAClF,OAAO;IACT,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,OAAO,CAAC,GAAG,CAAC,WAAW,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjD,IAAI,MAAM,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAC3E,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,MAAM,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,MAAM,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAC3E,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,kBAAkB,IAAI,SAAS,EAAE,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,IAAI,MAAM,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,mBAAmB,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC1E,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,GAAG,MAAM,CAAC,kBAAkB,CAAC,GAAG,GAAG,CAAC,CAAC;QACtE,MAAM,IAAI,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QAClE,OAAO,CAAC,GAAG,CACT,GAAG,IAAI,uBAAuB,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,GAAG,IAAI,CACpG,CAAC;QACF,OAAO,CAAC,GAAG,CACT,MAAM,KAAK,CAAC,UAAU,QAAQ,KAAK,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,WAAW,KAAK,CAAC,UAAU,QAAQ,KAAK,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAC7I,CAAC;QACF,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QAC1E,CAAC;aAAM,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,MAAM,CAAC,kBAAkB,KAAK,SAAS,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;QACzE,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,mBAAmB,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC1E,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,kBAAkB,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACrE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CACtB,CAAC,EACD,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,GAAG,MAAM,CAAC,kBAAkB,CAAC,GAAG,GAAG,CAAC,CAChE,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QACxE,OAAO,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CACT,GAAG,IAAI,sBAAsB,MAAM,CAAC,SAAS,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,eAAe,OAAO,IAAI,CACjH,CAAC;QACF,OAAO,CAAC,GAAG,CACT,YAAY,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,oBAAoB,KAAK,CAAC,UAAU,QAAQ,KAAK,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CACjH,CAAC;QACF,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CACT,sFAAsF,CACvF,CAAC;YACF,OAAO,CAAC,GAAG,CACT,qFAAqF,CACtF,CAAC;QACJ,CAAC;aAAM,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;YACrF,OAAO,CAAC,GAAG,CACT,kEAAkE,CACnE,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `.brewing/dev-env.yaml` config schema — Phase 2 of the dev-env
|
|
3
|
+
* upstreaming (delgoosh-first proof in Phase 1, generalised here).
|
|
4
|
+
*
|
|
5
|
+
* Consumers describe their dev env once: which apps run, in what
|
|
6
|
+
* mode (hot-reload vs production-shaped), which git branch the env
|
|
7
|
+
* mirrors (default `dev`), how seed data flows, and the optional SSH
|
|
8
|
+
* target if the env runs on a remote box.
|
|
9
|
+
*
|
|
10
|
+
* Then `slowcook dev-env <subcmd>` reads the file and acts. Today
|
|
11
|
+
* this Phase 2 cut ships only `push` end-to-end (the load-bearing
|
|
12
|
+
* operation for Phase 3 brew/plate wiring); `up`, `sync`, `switch`,
|
|
13
|
+
* `reset` ship as stubs that emit the canonical command shell for
|
|
14
|
+
* the consumer to wire into their workflow.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
export declare const DEV_ENV_CONFIG_PATH = ".brewing/dev-env.yaml";
|
|
18
|
+
declare const AppModeSchema: z.ZodEnum<["dev", "start", "nest-watch", "static", "none"]>;
|
|
19
|
+
export declare const DevEnvConfigSchema: z.ZodObject<{
|
|
20
|
+
$schema: z.ZodOptional<z.ZodString>;
|
|
21
|
+
schema_version: z.ZodLiteral<1>;
|
|
22
|
+
/**
|
|
23
|
+
* The git branch the dev env always reads from. Force-pushable —
|
|
24
|
+
* agents shove story-branch heads here to preview them. Default:
|
|
25
|
+
* `dev`.
|
|
26
|
+
*/
|
|
27
|
+
source_branch: z.ZodDefault<z.ZodString>;
|
|
28
|
+
/**
|
|
29
|
+
* Path (repo-relative) to the seed script. Run by `dev-env up` and
|
|
30
|
+
* `dev-env reset`. Must be idempotent on already-seeded data.
|
|
31
|
+
*/
|
|
32
|
+
seed_script: z.ZodOptional<z.ZodString>;
|
|
33
|
+
/**
|
|
34
|
+
* Where the dev env physically runs. Omit for "local docker compose
|
|
35
|
+
* on the runner" semantics (rare); set for SSH-to-box deploys.
|
|
36
|
+
*/
|
|
37
|
+
ssh_target: z.ZodOptional<z.ZodObject<{
|
|
38
|
+
host: z.ZodString;
|
|
39
|
+
user: z.ZodString;
|
|
40
|
+
/** Absolute path on the box where the consumer's checkout lives. */
|
|
41
|
+
checkout_dir: z.ZodString;
|
|
42
|
+
/** Repo secret name holding the SSH private key. */
|
|
43
|
+
key_secret: z.ZodDefault<z.ZodString>;
|
|
44
|
+
}, "strip", z.ZodTypeAny, {
|
|
45
|
+
host: string;
|
|
46
|
+
user: string;
|
|
47
|
+
checkout_dir: string;
|
|
48
|
+
key_secret: string;
|
|
49
|
+
}, {
|
|
50
|
+
host: string;
|
|
51
|
+
user: string;
|
|
52
|
+
checkout_dir: string;
|
|
53
|
+
key_secret?: string | undefined;
|
|
54
|
+
}>>;
|
|
55
|
+
persistence: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
56
|
+
/**
|
|
57
|
+
* Named docker volume that survives `dev-env reset`. PM-added DB
|
|
58
|
+
* rows persist across redeploys; only the seed-owned rows are
|
|
59
|
+
* touched by reset.
|
|
60
|
+
*/
|
|
61
|
+
db_volume: z.ZodOptional<z.ZodString>;
|
|
62
|
+
/** Named volume for uploaded user files / object storage. */
|
|
63
|
+
uploads_volume: z.ZodOptional<z.ZodString>;
|
|
64
|
+
}, "strip", z.ZodTypeAny, {
|
|
65
|
+
db_volume?: string | undefined;
|
|
66
|
+
uploads_volume?: string | undefined;
|
|
67
|
+
}, {
|
|
68
|
+
db_volume?: string | undefined;
|
|
69
|
+
uploads_volume?: string | undefined;
|
|
70
|
+
}>>>;
|
|
71
|
+
apps: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
72
|
+
mode: z.ZodEnum<["dev", "start", "nest-watch", "static", "none"]>;
|
|
73
|
+
port: z.ZodNumber;
|
|
74
|
+
/** Restart on crash. Defaults to true. */
|
|
75
|
+
autoheal: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
76
|
+
/** Optional: explicit container/process name override (otherwise the key). */
|
|
77
|
+
container: z.ZodOptional<z.ZodString>;
|
|
78
|
+
}, "strip", z.ZodTypeAny, {
|
|
79
|
+
mode: "dev" | "start" | "nest-watch" | "static" | "none";
|
|
80
|
+
port: number;
|
|
81
|
+
autoheal: boolean;
|
|
82
|
+
container?: string | undefined;
|
|
83
|
+
}, {
|
|
84
|
+
mode: "dev" | "start" | "nest-watch" | "static" | "none";
|
|
85
|
+
port: number;
|
|
86
|
+
autoheal?: boolean | undefined;
|
|
87
|
+
container?: string | undefined;
|
|
88
|
+
}>>;
|
|
89
|
+
}, "strip", z.ZodTypeAny, {
|
|
90
|
+
schema_version: 1;
|
|
91
|
+
source_branch: string;
|
|
92
|
+
persistence: {
|
|
93
|
+
db_volume?: string | undefined;
|
|
94
|
+
uploads_volume?: string | undefined;
|
|
95
|
+
};
|
|
96
|
+
apps: Record<string, {
|
|
97
|
+
mode: "dev" | "start" | "nest-watch" | "static" | "none";
|
|
98
|
+
port: number;
|
|
99
|
+
autoheal: boolean;
|
|
100
|
+
container?: string | undefined;
|
|
101
|
+
}>;
|
|
102
|
+
$schema?: string | undefined;
|
|
103
|
+
seed_script?: string | undefined;
|
|
104
|
+
ssh_target?: {
|
|
105
|
+
host: string;
|
|
106
|
+
user: string;
|
|
107
|
+
checkout_dir: string;
|
|
108
|
+
key_secret: string;
|
|
109
|
+
} | undefined;
|
|
110
|
+
}, {
|
|
111
|
+
schema_version: 1;
|
|
112
|
+
apps: Record<string, {
|
|
113
|
+
mode: "dev" | "start" | "nest-watch" | "static" | "none";
|
|
114
|
+
port: number;
|
|
115
|
+
autoheal?: boolean | undefined;
|
|
116
|
+
container?: string | undefined;
|
|
117
|
+
}>;
|
|
118
|
+
$schema?: string | undefined;
|
|
119
|
+
source_branch?: string | undefined;
|
|
120
|
+
seed_script?: string | undefined;
|
|
121
|
+
ssh_target?: {
|
|
122
|
+
host: string;
|
|
123
|
+
user: string;
|
|
124
|
+
checkout_dir: string;
|
|
125
|
+
key_secret?: string | undefined;
|
|
126
|
+
} | undefined;
|
|
127
|
+
persistence?: {
|
|
128
|
+
db_volume?: string | undefined;
|
|
129
|
+
uploads_volume?: string | undefined;
|
|
130
|
+
} | undefined;
|
|
131
|
+
}>;
|
|
132
|
+
export type DevEnvConfig = z.infer<typeof DevEnvConfigSchema>;
|
|
133
|
+
export type AppMode = z.infer<typeof AppModeSchema>;
|
|
134
|
+
export declare function loadDevEnvConfig(repoRoot: string): DevEnvConfig;
|
|
135
|
+
export {};
|
|
136
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/commands/dev-env/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,mBAAmB,0BAA0B,CAAC;AAE3D,QAAA,MAAM,aAAa,6DAMjB,CAAC;AA+BH,eAAO,MAAM,kBAAkB;;;IAG7B;;;;OAIG;;IAEH;;;OAGG;;IAEH;;;OAGG;;;;QAvBH,oEAAoE;;QAEpE,oDAAoD;;;;;;;;;;;;;;QAfpD;;;;WAIG;;QAEH,6DAA6D;;;;;;;;;;;;QAb7D,0CAA0C;;QAE1C,8EAA8E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6C9E,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAwB/D"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `.brewing/dev-env.yaml` config schema — Phase 2 of the dev-env
|
|
3
|
+
* upstreaming (delgoosh-first proof in Phase 1, generalised here).
|
|
4
|
+
*
|
|
5
|
+
* Consumers describe their dev env once: which apps run, in what
|
|
6
|
+
* mode (hot-reload vs production-shaped), which git branch the env
|
|
7
|
+
* mirrors (default `dev`), how seed data flows, and the optional SSH
|
|
8
|
+
* target if the env runs on a remote box.
|
|
9
|
+
*
|
|
10
|
+
* Then `slowcook dev-env <subcmd>` reads the file and acts. Today
|
|
11
|
+
* this Phase 2 cut ships only `push` end-to-end (the load-bearing
|
|
12
|
+
* operation for Phase 3 brew/plate wiring); `up`, `sync`, `switch`,
|
|
13
|
+
* `reset` ship as stubs that emit the canonical command shell for
|
|
14
|
+
* the consumer to wire into their workflow.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
import YAML from "yaml";
|
|
20
|
+
export const DEV_ENV_CONFIG_PATH = ".brewing/dev-env.yaml";
|
|
21
|
+
const AppModeSchema = z.enum([
|
|
22
|
+
"dev", // Next dev (hot reload) — for apps under active story development
|
|
23
|
+
"start", // next build + next start — production-shaped, slower restart
|
|
24
|
+
"nest-watch", // ts-node-dev / nest start --watch — backend hot reload
|
|
25
|
+
"static", // serve a built static export, never re-run
|
|
26
|
+
"none", // entry exists but isn't started by `dev-env up` (e.g. cron)
|
|
27
|
+
]);
|
|
28
|
+
const AppSchema = z.object({
|
|
29
|
+
mode: AppModeSchema,
|
|
30
|
+
port: z.number().int().positive(),
|
|
31
|
+
/** Restart on crash. Defaults to true. */
|
|
32
|
+
autoheal: z.boolean().optional().default(true),
|
|
33
|
+
/** Optional: explicit container/process name override (otherwise the key). */
|
|
34
|
+
container: z.string().optional(),
|
|
35
|
+
});
|
|
36
|
+
const PersistenceSchema = z.object({
|
|
37
|
+
/**
|
|
38
|
+
* Named docker volume that survives `dev-env reset`. PM-added DB
|
|
39
|
+
* rows persist across redeploys; only the seed-owned rows are
|
|
40
|
+
* touched by reset.
|
|
41
|
+
*/
|
|
42
|
+
db_volume: z.string().optional(),
|
|
43
|
+
/** Named volume for uploaded user files / object storage. */
|
|
44
|
+
uploads_volume: z.string().optional(),
|
|
45
|
+
});
|
|
46
|
+
const SshTargetSchema = z.object({
|
|
47
|
+
host: z.string(),
|
|
48
|
+
user: z.string(),
|
|
49
|
+
/** Absolute path on the box where the consumer's checkout lives. */
|
|
50
|
+
checkout_dir: z.string(),
|
|
51
|
+
/** Repo secret name holding the SSH private key. */
|
|
52
|
+
key_secret: z.string().default("DEV_DEPLOY_SSH_KEY"),
|
|
53
|
+
});
|
|
54
|
+
export const DevEnvConfigSchema = z.object({
|
|
55
|
+
$schema: z.string().optional(),
|
|
56
|
+
schema_version: z.literal(1),
|
|
57
|
+
/**
|
|
58
|
+
* The git branch the dev env always reads from. Force-pushable —
|
|
59
|
+
* agents shove story-branch heads here to preview them. Default:
|
|
60
|
+
* `dev`.
|
|
61
|
+
*/
|
|
62
|
+
source_branch: z.string().default("dev"),
|
|
63
|
+
/**
|
|
64
|
+
* Path (repo-relative) to the seed script. Run by `dev-env up` and
|
|
65
|
+
* `dev-env reset`. Must be idempotent on already-seeded data.
|
|
66
|
+
*/
|
|
67
|
+
seed_script: z.string().optional(),
|
|
68
|
+
/**
|
|
69
|
+
* Where the dev env physically runs. Omit for "local docker compose
|
|
70
|
+
* on the runner" semantics (rare); set for SSH-to-box deploys.
|
|
71
|
+
*/
|
|
72
|
+
ssh_target: SshTargetSchema.optional(),
|
|
73
|
+
persistence: PersistenceSchema.optional().default({}),
|
|
74
|
+
apps: z.record(z.string(), AppSchema),
|
|
75
|
+
});
|
|
76
|
+
export function loadDevEnvConfig(repoRoot) {
|
|
77
|
+
const path = join(repoRoot, DEV_ENV_CONFIG_PATH);
|
|
78
|
+
if (!existsSync(path)) {
|
|
79
|
+
throw new Error(`${DEV_ENV_CONFIG_PATH} not found. Run \`slowcook dev-env init\` to scaffold.`);
|
|
80
|
+
}
|
|
81
|
+
let raw;
|
|
82
|
+
try {
|
|
83
|
+
raw = YAML.parse(readFileSync(path, "utf8"));
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
throw new Error(`${DEV_ENV_CONFIG_PATH} is not valid YAML: ${e.message}`);
|
|
87
|
+
}
|
|
88
|
+
const parsed = DevEnvConfigSchema.safeParse(raw);
|
|
89
|
+
if (!parsed.success) {
|
|
90
|
+
throw new Error(`${DEV_ENV_CONFIG_PATH} failed validation: ${parsed.error.issues
|
|
91
|
+
.map((i) => `${i.path.join(".")}: ${i.message}`)
|
|
92
|
+
.join("; ")}`);
|
|
93
|
+
}
|
|
94
|
+
return parsed.data;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/commands/dev-env/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `slowcook dev-env <subcmd>` — manages the consumer's long-lived
|
|
3
|
+
* dev/preview environment. Phase 2 of the dev-env design.
|
|
4
|
+
*
|
|
5
|
+
* Subcommands:
|
|
6
|
+
*
|
|
7
|
+
* push --story <id> [--branch <name>]
|
|
8
|
+
* Force-push the current branch (or --branch) to the configured
|
|
9
|
+
* `source_branch` (default: `dev`). Agents (brew, plate) invoke
|
|
10
|
+
* this to preview their story-branch on the shared dev URL.
|
|
11
|
+
* Phase 3 wires this into brew/plate workflows automatically.
|
|
12
|
+
*
|
|
13
|
+
* switch --story <id>
|
|
14
|
+
* Locate the PR for story <id>, force-push its HEAD to
|
|
15
|
+
* `source_branch`. Operator-driven version of `push`.
|
|
16
|
+
*
|
|
17
|
+
* up | sync | reset
|
|
18
|
+
* Phase 2 stubs — print the canonical shell-out for the consumer
|
|
19
|
+
* to wire into their dev-deploy workflow. Phase 2.1 fills in the
|
|
20
|
+
* SSH-driven runtime path.
|
|
21
|
+
*
|
|
22
|
+
* init
|
|
23
|
+
* Phase 2.1 stub — scaffold `.brewing/dev-env.yaml` from detected
|
|
24
|
+
* apps. Not implemented yet; consumers hand-author for now.
|
|
25
|
+
*/
|
|
26
|
+
export declare function devEnv(argv: string[]): Promise<void>;
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/dev-env/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAuEH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyC1D"}
|