outfitter 0.2.6 → 0.3.2
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/README.md +53 -28
- package/dist/cli.js +3 -2
- package/dist/index.d.ts +95 -135
- package/dist/index.js +8 -15
- package/dist/shared/{chunk-k59f60cp.js → chunk-3pwh8ys4.js} +3092 -2625
- package/package.json +36 -22
- package/dist/actions.d.ts +0 -2
- package/dist/actions.js +0 -34
- package/dist/commands/add.d.ts +0 -54
- package/dist/commands/add.js +0 -16
- package/dist/commands/check.d.ts +0 -91
- package/dist/commands/check.js +0 -14
- package/dist/commands/demo.d.ts +0 -21
- package/dist/commands/demo.js +0 -8
- package/dist/commands/docs-module-loader.d.ts +0 -2
- package/dist/commands/docs-module-loader.js +0 -8
- package/dist/commands/doctor.d.ts +0 -2
- package/dist/commands/doctor.js +0 -13
- package/dist/commands/init.d.ts +0 -7
- package/dist/commands/init.js +0 -31
- package/dist/commands/migrate-kit.d.ts +0 -2
- package/dist/commands/migrate-kit.js +0 -15
- package/dist/commands/repo.d.ts +0 -3
- package/dist/commands/repo.js +0 -9
- package/dist/commands/scaffold.d.ts +0 -4
- package/dist/commands/scaffold.js +0 -31
- package/dist/commands/shared-deps.d.ts +0 -36
- package/dist/commands/shared-deps.js +0 -10
- package/dist/commands/upgrade-codemods.d.ts +0 -42
- package/dist/commands/upgrade-codemods.js +0 -15
- package/dist/commands/upgrade-planner.d.ts +0 -58
- package/dist/commands/upgrade-planner.js +0 -8
- package/dist/commands/upgrade-workspace.d.ts +0 -76
- package/dist/commands/upgrade-workspace.js +0 -16
- package/dist/commands/upgrade.d.ts +0 -214
- package/dist/commands/upgrade.js +0 -25
- package/dist/create/index.d.ts +0 -5
- package/dist/create/index.js +0 -29
- package/dist/create/planner.d.ts +0 -3
- package/dist/create/planner.js +0 -21
- package/dist/create/presets.d.ts +0 -3
- package/dist/create/presets.js +0 -12
- package/dist/create/types.d.ts +0 -2
- package/dist/create/types.js +0 -1
- package/dist/engine/blocks.d.ts +0 -3
- package/dist/engine/blocks.js +0 -12
- package/dist/engine/collector.d.ts +0 -2
- package/dist/engine/collector.js +0 -8
- package/dist/engine/config.d.ts +0 -3
- package/dist/engine/config.js +0 -12
- package/dist/engine/executor.d.ts +0 -3
- package/dist/engine/executor.js +0 -16
- package/dist/engine/index.d.ts +0 -8
- package/dist/engine/index.js +0 -59
- package/dist/engine/names.d.ts +0 -2
- package/dist/engine/names.js +0 -16
- package/dist/engine/post-scaffold.d.ts +0 -3
- package/dist/engine/post-scaffold.js +0 -8
- package/dist/engine/render-plan.d.ts +0 -7
- package/dist/engine/render-plan.js +0 -9
- package/dist/engine/template.d.ts +0 -3
- package/dist/engine/template.js +0 -17
- package/dist/engine/types.d.ts +0 -2
- package/dist/engine/types.js +0 -8
- package/dist/engine/workspace.d.ts +0 -3
- package/dist/engine/workspace.js +0 -13
- package/dist/manifest.d.ts +0 -71
- package/dist/manifest.js +0 -16
- package/dist/output-mode.d.ts +0 -2
- package/dist/output-mode.js +0 -10
- package/dist/shared/outfitter-193jvzg4.d.ts +0 -5
- package/dist/shared/outfitter-1dd0k853.js +0 -194
- package/dist/shared/outfitter-1dvma85c.js +0 -322
- package/dist/shared/outfitter-1h7k8xxt.js +0 -29
- package/dist/shared/outfitter-2ngep1h2.d.ts +0 -5
- package/dist/shared/outfitter-2np85etz.js +0 -95
- package/dist/shared/outfitter-33w361tc.d.ts +0 -18
- package/dist/shared/outfitter-344t1r38.js +0 -1
- package/dist/shared/outfitter-3weh61w7.d.ts +0 -25
- package/dist/shared/outfitter-4s9meh3j.js +0 -221
- package/dist/shared/outfitter-66b25bj8.js +0 -125
- package/dist/shared/outfitter-6bkqjk86.d.ts +0 -3
- package/dist/shared/outfitter-79vfxt6y.js +0 -269
- package/dist/shared/outfitter-7ha7p61k.d.ts +0 -6
- package/dist/shared/outfitter-7r12fj7f.js +0 -30
- package/dist/shared/outfitter-8y2dfx6n.js +0 -11
- package/dist/shared/outfitter-9x1brcmq.js +0 -184
- package/dist/shared/outfitter-9zqc2njf.js +0 -859
- package/dist/shared/outfitter-a79xrm12.d.ts +0 -17
- package/dist/shared/outfitter-amc4jbs1.d.ts +0 -50
- package/dist/shared/outfitter-ara3djt0.js +0 -73
- package/dist/shared/outfitter-avhm5z6w.js +0 -82
- package/dist/shared/outfitter-bkwpbkr9.d.ts +0 -63
- package/dist/shared/outfitter-bn9c8p2e.js +0 -204
- package/dist/shared/outfitter-bpr28y54.js +0 -70
- package/dist/shared/outfitter-cwq39bv4.d.ts +0 -48
- package/dist/shared/outfitter-d7pq7d0k.js +0 -196
- package/dist/shared/outfitter-dd0btgec.d.ts +0 -40
- package/dist/shared/outfitter-e2zz5wv7.d.ts +0 -51
- package/dist/shared/outfitter-ehp18x1n.js +0 -1
- package/dist/shared/outfitter-gdvm5c0b.d.ts +0 -4
- package/dist/shared/outfitter-h1mnzzd1.d.ts +0 -14
- package/dist/shared/outfitter-hvsaxgcp.js +0 -1
- package/dist/shared/outfitter-hws10ze7.js +0 -532
- package/dist/shared/outfitter-j833sxws.js +0 -61
- package/dist/shared/outfitter-j8yc7294.d.ts +0 -22
- package/dist/shared/outfitter-k112c427.js +0 -21
- package/dist/shared/outfitter-k56rmt24.d.ts +0 -30
- package/dist/shared/outfitter-ksa1pp4t.d.ts +0 -4
- package/dist/shared/outfitter-ksyvwmb5.js +0 -191
- package/dist/shared/outfitter-mdt37hqm.js +0 -4
- package/dist/shared/outfitter-mtbpabf3.js +0 -91
- package/dist/shared/outfitter-mxz69pgy.js +0 -713
- package/dist/shared/outfitter-npemy7ta.d.ts +0 -53
- package/dist/shared/outfitter-npyfbdmc.d.ts +0 -6
- package/dist/shared/outfitter-pyy1zkfh.d.ts +0 -133
- package/dist/shared/outfitter-q9agarmb.js +0 -42
- package/dist/shared/outfitter-qfh36ddg.d.ts +0 -66
- package/dist/shared/outfitter-qn864k6h.js +0 -581
- package/dist/shared/outfitter-rdc5v5ms.js +0 -746
- package/dist/shared/outfitter-sgtq57qr.d.ts +0 -5
- package/dist/shared/outfitter-ttjr95y9.js +0 -98
- package/dist/shared/outfitter-vh4xgb93.js +0 -35
- package/dist/shared/outfitter-yvksv5qb.js +0 -322
- package/dist/shared/outfitter-zwyvewr1.js +0 -36
- package/dist/targets/index.d.ts +0 -4
- package/dist/targets/index.js +0 -29
- package/dist/targets/registry.d.ts +0 -3
- package/dist/targets/registry.js +0 -28
- package/dist/targets/types.d.ts +0 -2
- package/dist/targets/types.js +0 -1
- package/templates/.gitkeep +0 -0
- package/templates/basic/.gitignore.template +0 -30
- package/templates/basic/.lefthook.yml.template +0 -26
- package/templates/basic/package.json.template +0 -46
- package/templates/basic/src/index.ts.template +0 -26
- package/templates/basic/tsconfig.json.template +0 -34
- package/templates/cli/.gitignore.template +0 -4
- package/templates/cli/.lefthook.yml.template +0 -26
- package/templates/cli/README.md.template +0 -35
- package/templates/cli/biome.json.template +0 -4
- package/templates/cli/package.json.template +0 -45
- package/templates/cli/src/cli.ts.template +0 -8
- package/templates/cli/src/index.ts.template +0 -7
- package/templates/cli/src/program.ts.template +0 -31
- package/templates/cli/tsconfig.json.template +0 -34
- package/templates/daemon/.gitignore.template +0 -4
- package/templates/daemon/.lefthook.yml.template +0 -26
- package/templates/daemon/README.md.template +0 -67
- package/templates/daemon/biome.json.template +0 -4
- package/templates/daemon/package.json.template +0 -48
- package/templates/daemon/src/cli.ts.template +0 -96
- package/templates/daemon/src/daemon-main.ts.template +0 -79
- package/templates/daemon/src/daemon.ts.template +0 -11
- package/templates/daemon/src/index.ts.template +0 -7
- package/templates/daemon/tsconfig.json.template +0 -23
- package/templates/mcp/.gitignore.template +0 -4
- package/templates/mcp/.lefthook.yml.template +0 -26
- package/templates/mcp/README.md.template +0 -54
- package/templates/mcp/biome.json.template +0 -4
- package/templates/mcp/package.json.template +0 -45
- package/templates/mcp/src/index.ts.template +0 -7
- package/templates/mcp/src/mcp.ts.template +0 -79
- package/templates/mcp/src/server.ts.template +0 -15
- package/templates/mcp/tsconfig.json.template +0 -23
- package/templates/minimal/.gitignore.template +0 -30
- package/templates/minimal/.lefthook.yml.template +0 -26
- package/templates/minimal/package.json.template +0 -46
- package/templates/minimal/src/index.ts.template +0 -26
- package/templates/minimal/tsconfig.json.template +0 -34
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
// apps/outfitter/src/engine/post-scaffold.ts
|
|
3
|
-
import { relative } from "path";
|
|
4
|
-
import { Result } from "@outfitter/contracts";
|
|
5
|
-
function detectGitState(cwd) {
|
|
6
|
-
try {
|
|
7
|
-
const result = Bun.spawnSync(["git", "rev-parse", "--show-toplevel"], {
|
|
8
|
-
cwd,
|
|
9
|
-
stdout: "pipe",
|
|
10
|
-
stderr: "ignore"
|
|
11
|
-
});
|
|
12
|
-
return { isRepo: result.exitCode === 0 };
|
|
13
|
-
} catch {
|
|
14
|
-
return { isRepo: false };
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
async function runBunInstall(cwd, timeoutMs) {
|
|
18
|
-
try {
|
|
19
|
-
const proc = Bun.spawn(["bun", "install"], {
|
|
20
|
-
cwd,
|
|
21
|
-
stdout: "pipe",
|
|
22
|
-
stderr: "pipe"
|
|
23
|
-
});
|
|
24
|
-
const timeoutPromise = new Promise((resolveTimeout) => {
|
|
25
|
-
const timer = setTimeout(() => resolveTimeout("timeout"), timeoutMs);
|
|
26
|
-
proc.exited.finally(() => clearTimeout(timer));
|
|
27
|
-
});
|
|
28
|
-
const race = await Promise.race([
|
|
29
|
-
proc.exited.then(() => "exit"),
|
|
30
|
-
timeoutPromise
|
|
31
|
-
]);
|
|
32
|
-
if (race === "timeout") {
|
|
33
|
-
proc.kill();
|
|
34
|
-
return Result.err(`bun install timed out after ${timeoutMs}ms`);
|
|
35
|
-
}
|
|
36
|
-
const exitCode = await proc.exited;
|
|
37
|
-
if (exitCode !== 0) {
|
|
38
|
-
const stderr = await new Response(proc.stderr).text();
|
|
39
|
-
return Result.err(stderr.trim() || `bun install exited with code ${exitCode}`);
|
|
40
|
-
}
|
|
41
|
-
return Result.ok(undefined);
|
|
42
|
-
} catch (error) {
|
|
43
|
-
return Result.err(error instanceof Error ? error.message : "Unknown error");
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
function runGitInit(cwd) {
|
|
47
|
-
try {
|
|
48
|
-
const result = Bun.spawnSync(["git", "init"], {
|
|
49
|
-
cwd,
|
|
50
|
-
stdout: "pipe",
|
|
51
|
-
stderr: "pipe"
|
|
52
|
-
});
|
|
53
|
-
if (result.exitCode !== 0) {
|
|
54
|
-
return Result.err(result.stderr.toString().trim());
|
|
55
|
-
}
|
|
56
|
-
return Result.ok(undefined);
|
|
57
|
-
} catch (error) {
|
|
58
|
-
return Result.err(error instanceof Error ? error.message : "Unknown error");
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
function hasGitUserConfig(cwd) {
|
|
62
|
-
try {
|
|
63
|
-
const name = Bun.spawnSync(["git", "config", "--get", "user.name"], {
|
|
64
|
-
cwd,
|
|
65
|
-
stdout: "pipe",
|
|
66
|
-
stderr: "ignore"
|
|
67
|
-
});
|
|
68
|
-
if (name.exitCode !== 0 || name.stdout.toString().trim().length === 0) {
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
const email = Bun.spawnSync(["git", "config", "--get", "user.email"], {
|
|
72
|
-
cwd,
|
|
73
|
-
stdout: "pipe",
|
|
74
|
-
stderr: "ignore"
|
|
75
|
-
});
|
|
76
|
-
return email.exitCode === 0 && email.stdout.toString().trim().length > 0;
|
|
77
|
-
} catch {
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function runGitCommit(cwd, message) {
|
|
82
|
-
try {
|
|
83
|
-
const addResult = Bun.spawnSync(["git", "add", "."], {
|
|
84
|
-
cwd,
|
|
85
|
-
stdout: "pipe",
|
|
86
|
-
stderr: "pipe"
|
|
87
|
-
});
|
|
88
|
-
if (addResult.exitCode !== 0) {
|
|
89
|
-
return Result.err(`git add failed: ${addResult.stderr.toString().trim()}`);
|
|
90
|
-
}
|
|
91
|
-
const commitResult = Bun.spawnSync(["git", "commit", "-m", message], {
|
|
92
|
-
cwd,
|
|
93
|
-
stdout: "pipe",
|
|
94
|
-
stderr: "pipe"
|
|
95
|
-
});
|
|
96
|
-
if (commitResult.exitCode !== 0) {
|
|
97
|
-
return Result.err(`git commit failed: ${commitResult.stderr.toString().trim()}`);
|
|
98
|
-
}
|
|
99
|
-
return Result.ok(undefined);
|
|
100
|
-
} catch (error) {
|
|
101
|
-
return Result.err(error instanceof Error ? error.message : "Unknown error");
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
function computeNextSteps(options, installResult) {
|
|
105
|
-
const steps = [];
|
|
106
|
-
if (options.origin === "init") {
|
|
107
|
-
steps.push(`cd ${JSON.stringify(options.rootDir)}`);
|
|
108
|
-
}
|
|
109
|
-
if (installResult !== "success") {
|
|
110
|
-
steps.push("bun install");
|
|
111
|
-
}
|
|
112
|
-
if (options.structure === "workspace") {
|
|
113
|
-
const relProject = relative(options.rootDir, options.projectDir) || ".";
|
|
114
|
-
steps.push(`bun run --cwd ${JSON.stringify(relProject)} dev`);
|
|
115
|
-
} else {
|
|
116
|
-
steps.push("bun run dev");
|
|
117
|
-
}
|
|
118
|
-
return steps;
|
|
119
|
-
}
|
|
120
|
-
async function runPostScaffold(options, collector) {
|
|
121
|
-
if (process.env["OUTFITTER_DISABLE_POST_SCAFFOLD"] === "1") {
|
|
122
|
-
return Result.ok({
|
|
123
|
-
installResult: "skipped",
|
|
124
|
-
gitInitResult: "skipped",
|
|
125
|
-
gitCommitResult: "skipped",
|
|
126
|
-
nextSteps: computeNextSteps(options, "skipped")
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
let installResult = "skipped";
|
|
130
|
-
let installError;
|
|
131
|
-
if (!options.skipInstall) {
|
|
132
|
-
if (options.dryRun) {
|
|
133
|
-
collector?.add({
|
|
134
|
-
type: "install",
|
|
135
|
-
command: "bun install",
|
|
136
|
-
cwd: options.rootDir
|
|
137
|
-
});
|
|
138
|
-
installResult = "skipped";
|
|
139
|
-
} else {
|
|
140
|
-
const result = await runBunInstall(options.rootDir, options.installTimeoutMs);
|
|
141
|
-
if (result.isErr()) {
|
|
142
|
-
installResult = "failed";
|
|
143
|
-
installError = result.error;
|
|
144
|
-
process.stderr.write(`Warning: bun install failed: ${result.error}
|
|
145
|
-
`);
|
|
146
|
-
} else {
|
|
147
|
-
installResult = "success";
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
let gitInitResult = "skipped";
|
|
152
|
-
let gitCommitResult = "skipped";
|
|
153
|
-
let gitError;
|
|
154
|
-
if (!options.skipGit && options.origin === "init") {
|
|
155
|
-
const gitState = detectGitState(options.rootDir);
|
|
156
|
-
if (options.dryRun) {
|
|
157
|
-
if (!gitState.isRepo) {
|
|
158
|
-
collector?.add({
|
|
159
|
-
type: "git",
|
|
160
|
-
action: "init",
|
|
161
|
-
cwd: options.rootDir
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
if (!options.skipCommit) {
|
|
165
|
-
collector?.add({
|
|
166
|
-
type: "git",
|
|
167
|
-
action: "add-all",
|
|
168
|
-
cwd: options.rootDir
|
|
169
|
-
});
|
|
170
|
-
collector?.add({
|
|
171
|
-
type: "git",
|
|
172
|
-
action: "commit",
|
|
173
|
-
cwd: options.rootDir,
|
|
174
|
-
message: "init: scaffold with outfitter"
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
gitInitResult = gitState.isRepo ? "already-repo" : "skipped";
|
|
178
|
-
} else {
|
|
179
|
-
if (gitState.isRepo) {
|
|
180
|
-
gitInitResult = "already-repo";
|
|
181
|
-
} else {
|
|
182
|
-
const result = runGitInit(options.rootDir);
|
|
183
|
-
if (result.isErr()) {
|
|
184
|
-
gitInitResult = "failed";
|
|
185
|
-
gitError = result.error;
|
|
186
|
-
process.stderr.write(`Warning: git init failed: ${result.error}
|
|
187
|
-
`);
|
|
188
|
-
} else {
|
|
189
|
-
gitInitResult = "success";
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
if (!options.skipCommit && (gitInitResult === "success" || gitInitResult === "already-repo")) {
|
|
193
|
-
if (hasGitUserConfig(options.rootDir)) {
|
|
194
|
-
const commitResult = runGitCommit(options.rootDir, "init: scaffold with outfitter");
|
|
195
|
-
if (commitResult.isErr()) {
|
|
196
|
-
gitCommitResult = "failed";
|
|
197
|
-
gitError = commitResult.error;
|
|
198
|
-
process.stderr.write(`Warning: ${commitResult.error}
|
|
199
|
-
`);
|
|
200
|
-
} else {
|
|
201
|
-
gitCommitResult = "success";
|
|
202
|
-
}
|
|
203
|
-
} else {
|
|
204
|
-
gitCommitResult = "skipped";
|
|
205
|
-
process.stderr.write(`Warning: git user.name/email not configured, skipping initial commit.
|
|
206
|
-
`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return Result.ok({
|
|
212
|
-
installResult,
|
|
213
|
-
installError,
|
|
214
|
-
gitInitResult,
|
|
215
|
-
gitCommitResult,
|
|
216
|
-
gitError,
|
|
217
|
-
nextSteps: computeNextSteps(options, installResult)
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export { runPostScaffold };
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import {
|
|
3
|
-
copyTemplateFiles,
|
|
4
|
-
getTemplatesDir
|
|
5
|
-
} from "./outfitter-9x1brcmq.js";
|
|
6
|
-
import {
|
|
7
|
-
addBlocks
|
|
8
|
-
} from "./outfitter-j833sxws.js";
|
|
9
|
-
import {
|
|
10
|
-
injectSharedConfig,
|
|
11
|
-
rewriteLocalDependencies
|
|
12
|
-
} from "./outfitter-ara3djt0.js";
|
|
13
|
-
import {
|
|
14
|
-
ScaffoldError
|
|
15
|
-
} from "./outfitter-8y2dfx6n.js";
|
|
16
|
-
|
|
17
|
-
// apps/outfitter/src/engine/executor.ts
|
|
18
|
-
import { existsSync, mkdirSync } from "fs";
|
|
19
|
-
import { join } from "path";
|
|
20
|
-
import { Result } from "@outfitter/contracts";
|
|
21
|
-
async function executePlan(plan, options) {
|
|
22
|
-
try {
|
|
23
|
-
const templatesDir = getTemplatesDir();
|
|
24
|
-
let projectDir;
|
|
25
|
-
let blocksAdded;
|
|
26
|
-
for (const change of plan.changes) {
|
|
27
|
-
switch (change.type) {
|
|
28
|
-
case "copy-template": {
|
|
29
|
-
projectDir = change.targetDir;
|
|
30
|
-
if (!(existsSync(projectDir) || options.collector)) {
|
|
31
|
-
mkdirSync(projectDir, { recursive: true });
|
|
32
|
-
}
|
|
33
|
-
const templatePath = join(templatesDir, change.template);
|
|
34
|
-
if (!existsSync(templatePath)) {
|
|
35
|
-
return Result.err(new ScaffoldError(`Template '${change.template}' not found in ${templatesDir}`));
|
|
36
|
-
}
|
|
37
|
-
if (change.overlayBaseTemplate) {
|
|
38
|
-
const basePath = join(templatesDir, "_base");
|
|
39
|
-
if (existsSync(basePath)) {
|
|
40
|
-
const baseWrittenPaths = new Set;
|
|
41
|
-
const baseResult = copyTemplateFiles(basePath, projectDir, plan.values, options, {
|
|
42
|
-
writtenPaths: baseWrittenPaths
|
|
43
|
-
});
|
|
44
|
-
if (baseResult.isErr()) {
|
|
45
|
-
return baseResult;
|
|
46
|
-
}
|
|
47
|
-
const templateResult2 = copyTemplateFiles(templatePath, projectDir, plan.values, options, {
|
|
48
|
-
allowOverwrite: true,
|
|
49
|
-
overwritablePaths: baseWrittenPaths
|
|
50
|
-
});
|
|
51
|
-
if (templateResult2.isErr()) {
|
|
52
|
-
return templateResult2;
|
|
53
|
-
}
|
|
54
|
-
break;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
const templateResult = copyTemplateFiles(templatePath, projectDir, plan.values, options);
|
|
58
|
-
if (templateResult.isErr()) {
|
|
59
|
-
return templateResult;
|
|
60
|
-
}
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
|
-
case "inject-shared-config": {
|
|
64
|
-
if (!projectDir) {
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
if (options.collector) {
|
|
68
|
-
options.collector.add({
|
|
69
|
-
type: "config-inject",
|
|
70
|
-
target: join(projectDir, "package.json"),
|
|
71
|
-
description: "Inject shared scripts/devDependencies"
|
|
72
|
-
});
|
|
73
|
-
} else {
|
|
74
|
-
const result = injectSharedConfig(projectDir);
|
|
75
|
-
if (result.isErr()) {
|
|
76
|
-
return result;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
case "rewrite-local-dependencies": {
|
|
82
|
-
if (!projectDir) {
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
if (options.collector) {
|
|
86
|
-
options.collector.add({
|
|
87
|
-
type: "config-inject",
|
|
88
|
-
target: join(projectDir, "package.json"),
|
|
89
|
-
description: "Rewrite local @outfitter/* dependencies to workspace:*"
|
|
90
|
-
});
|
|
91
|
-
} else {
|
|
92
|
-
const result = rewriteLocalDependencies(projectDir);
|
|
93
|
-
if (result.isErr()) {
|
|
94
|
-
return result;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
case "add-blocks": {
|
|
100
|
-
if (!projectDir) {
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
const result = await addBlocks(projectDir, change.blocks, options);
|
|
104
|
-
if (result.isErr()) {
|
|
105
|
-
return result;
|
|
106
|
-
}
|
|
107
|
-
blocksAdded = result.value;
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
default: {
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
if (!projectDir) {
|
|
116
|
-
return Result.err(new ScaffoldError("Plan contains no copy-template step"));
|
|
117
|
-
}
|
|
118
|
-
return Result.ok({ projectDir, blocksAdded });
|
|
119
|
-
} catch (error) {
|
|
120
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
121
|
-
return Result.err(new ScaffoldError(`Failed to execute scaffold plan: ${message}`));
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export { executePlan };
|
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import {
|
|
3
|
-
stampBlock
|
|
4
|
-
} from "./outfitter-mtbpabf3.js";
|
|
5
|
-
import {
|
|
6
|
-
resolveStructuredOutputMode
|
|
7
|
-
} from "./outfitter-7r12fj7f.js";
|
|
8
|
-
|
|
9
|
-
// apps/outfitter/src/commands/add.ts
|
|
10
|
-
import {
|
|
11
|
-
chmodSync,
|
|
12
|
-
existsSync,
|
|
13
|
-
mkdirSync,
|
|
14
|
-
readFileSync,
|
|
15
|
-
writeFileSync
|
|
16
|
-
} from "fs";
|
|
17
|
-
import { dirname, join, resolve } from "path";
|
|
18
|
-
import { fileURLToPath } from "url";
|
|
19
|
-
import { output } from "@outfitter/cli";
|
|
20
|
-
import { Result } from "@outfitter/contracts";
|
|
21
|
-
import { RegistrySchema } from "@outfitter/tooling";
|
|
22
|
-
class AddError extends Error {
|
|
23
|
-
_tag = "AddError";
|
|
24
|
-
constructor(message) {
|
|
25
|
-
super(message);
|
|
26
|
-
this.name = "AddError";
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
function getRegistryPath() {
|
|
30
|
-
let currentDir = dirname(fileURLToPath(import.meta.url));
|
|
31
|
-
for (let i = 0;i < 10; i++) {
|
|
32
|
-
const registryPath = join(currentDir, "node_modules/@outfitter/tooling/registry/registry.json");
|
|
33
|
-
if (existsSync(registryPath)) {
|
|
34
|
-
return registryPath;
|
|
35
|
-
}
|
|
36
|
-
const monoRepoPath = join(currentDir, "packages/tooling/registry/registry.json");
|
|
37
|
-
if (existsSync(monoRepoPath)) {
|
|
38
|
-
return monoRepoPath;
|
|
39
|
-
}
|
|
40
|
-
currentDir = dirname(currentDir);
|
|
41
|
-
}
|
|
42
|
-
throw new AddError("Could not find registry.json. Ensure @outfitter/tooling is installed.");
|
|
43
|
-
}
|
|
44
|
-
function readToolingVersion(registryPath) {
|
|
45
|
-
try {
|
|
46
|
-
const toolingRoot = dirname(dirname(registryPath));
|
|
47
|
-
const pkgPath = join(toolingRoot, "package.json");
|
|
48
|
-
const content = readFileSync(pkgPath, "utf-8");
|
|
49
|
-
const pkg = JSON.parse(content);
|
|
50
|
-
return pkg.version ?? "unknown";
|
|
51
|
-
} catch {
|
|
52
|
-
return "unknown";
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
function loadRegistry() {
|
|
56
|
-
try {
|
|
57
|
-
const registryPath = getRegistryPath();
|
|
58
|
-
const content = readFileSync(registryPath, "utf-8");
|
|
59
|
-
const parsed = JSON.parse(content);
|
|
60
|
-
const registry = RegistrySchema.parse(parsed);
|
|
61
|
-
const toolingVersion = readToolingVersion(registryPath);
|
|
62
|
-
return Result.ok({ registry, toolingVersion });
|
|
63
|
-
} catch (error) {
|
|
64
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
65
|
-
return Result.err(new AddError(`Failed to load registry: ${message}`));
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
function resolveBlock(registry, blockName, visited = new Set) {
|
|
69
|
-
if (visited.has(blockName)) {
|
|
70
|
-
return Result.err(new AddError(`Circular dependency detected for block: ${blockName}`));
|
|
71
|
-
}
|
|
72
|
-
visited.add(blockName);
|
|
73
|
-
const block = registry.blocks[blockName];
|
|
74
|
-
if (!block) {
|
|
75
|
-
const available = Object.keys(registry.blocks).join(", ");
|
|
76
|
-
return Result.err(new AddError(`Block '${blockName}' not found. Available blocks: ${available}`));
|
|
77
|
-
}
|
|
78
|
-
if (block.extends && block.extends.length > 0) {
|
|
79
|
-
const mergedFiles = [];
|
|
80
|
-
const mergedDeps = {};
|
|
81
|
-
const mergedDevDeps = {};
|
|
82
|
-
for (const extendedName of block.extends) {
|
|
83
|
-
const extendedResult = resolveBlock(registry, extendedName, visited);
|
|
84
|
-
if (extendedResult.isErr()) {
|
|
85
|
-
return extendedResult;
|
|
86
|
-
}
|
|
87
|
-
const extended = extendedResult.value;
|
|
88
|
-
if (extended.files) {
|
|
89
|
-
mergedFiles.push(...extended.files);
|
|
90
|
-
}
|
|
91
|
-
if (extended.dependencies) {
|
|
92
|
-
Object.assign(mergedDeps, extended.dependencies);
|
|
93
|
-
}
|
|
94
|
-
if (extended.devDependencies) {
|
|
95
|
-
Object.assign(mergedDevDeps, extended.devDependencies);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
if (block.files) {
|
|
99
|
-
mergedFiles.push(...block.files);
|
|
100
|
-
}
|
|
101
|
-
if (block.dependencies) {
|
|
102
|
-
Object.assign(mergedDeps, block.dependencies);
|
|
103
|
-
}
|
|
104
|
-
if (block.devDependencies) {
|
|
105
|
-
Object.assign(mergedDevDeps, block.devDependencies);
|
|
106
|
-
}
|
|
107
|
-
return Result.ok({
|
|
108
|
-
name: block.name,
|
|
109
|
-
description: block.description,
|
|
110
|
-
files: mergedFiles.length > 0 ? mergedFiles : undefined,
|
|
111
|
-
dependencies: Object.keys(mergedDeps).length > 0 ? mergedDeps : undefined,
|
|
112
|
-
devDependencies: Object.keys(mergedDevDeps).length > 0 ? mergedDevDeps : undefined
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
return Result.ok(block);
|
|
116
|
-
}
|
|
117
|
-
function writeFile(filePath, content, executable) {
|
|
118
|
-
const dir = dirname(filePath);
|
|
119
|
-
if (!existsSync(dir)) {
|
|
120
|
-
mkdirSync(dir, { recursive: true });
|
|
121
|
-
}
|
|
122
|
-
writeFileSync(filePath, content, "utf-8");
|
|
123
|
-
if (executable) {
|
|
124
|
-
chmodSync(filePath, 493);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
function updatePackageJson(cwd, dependencies, devDependencies, dryRun) {
|
|
128
|
-
const packageJsonPath = join(cwd, "package.json");
|
|
129
|
-
if (!existsSync(packageJsonPath)) {
|
|
130
|
-
return { dependencies, devDependencies };
|
|
131
|
-
}
|
|
132
|
-
const content = readFileSync(packageJsonPath, "utf-8");
|
|
133
|
-
const pkg = JSON.parse(content);
|
|
134
|
-
const existingDeps = pkg["dependencies"] ?? {};
|
|
135
|
-
const existingDevDeps = pkg["devDependencies"] ?? {};
|
|
136
|
-
const addedDeps = {};
|
|
137
|
-
const addedDevDeps = {};
|
|
138
|
-
for (const [name, version] of Object.entries(dependencies)) {
|
|
139
|
-
if (!existingDeps[name]) {
|
|
140
|
-
existingDeps[name] = version;
|
|
141
|
-
addedDeps[name] = version;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
for (const [name, version] of Object.entries(devDependencies)) {
|
|
145
|
-
if (!(existingDevDeps[name] || existingDeps[name])) {
|
|
146
|
-
existingDevDeps[name] = version;
|
|
147
|
-
addedDevDeps[name] = version;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
if (!dryRun && (Object.keys(addedDeps).length > 0 || Object.keys(addedDevDeps).length > 0)) {
|
|
151
|
-
if (Object.keys(existingDeps).length > 0) {
|
|
152
|
-
pkg["dependencies"] = existingDeps;
|
|
153
|
-
}
|
|
154
|
-
if (Object.keys(existingDevDeps).length > 0) {
|
|
155
|
-
pkg["devDependencies"] = existingDevDeps;
|
|
156
|
-
}
|
|
157
|
-
writeFileSync(packageJsonPath, `${JSON.stringify(pkg, null, 2)}
|
|
158
|
-
`);
|
|
159
|
-
}
|
|
160
|
-
return { dependencies: addedDeps, devDependencies: addedDevDeps };
|
|
161
|
-
}
|
|
162
|
-
async function runAdd(input) {
|
|
163
|
-
const { block: blockName, force, dryRun, cwd = process.cwd() } = input;
|
|
164
|
-
const resolvedCwd = resolve(cwd);
|
|
165
|
-
const registryResult = loadRegistry();
|
|
166
|
-
if (registryResult.isErr()) {
|
|
167
|
-
return registryResult;
|
|
168
|
-
}
|
|
169
|
-
const { registry, toolingVersion } = registryResult.value;
|
|
170
|
-
const blockResult = resolveBlock(registry, blockName);
|
|
171
|
-
if (blockResult.isErr()) {
|
|
172
|
-
return blockResult;
|
|
173
|
-
}
|
|
174
|
-
const block = blockResult.value;
|
|
175
|
-
const created = [];
|
|
176
|
-
const skipped = [];
|
|
177
|
-
const overwritten = [];
|
|
178
|
-
if (block.files) {
|
|
179
|
-
for (const file of block.files) {
|
|
180
|
-
const targetPath = join(resolvedCwd, file.path);
|
|
181
|
-
const fileExists = existsSync(targetPath);
|
|
182
|
-
if (fileExists && !force) {
|
|
183
|
-
skipped.push(file.path);
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
if (!dryRun) {
|
|
187
|
-
writeFile(targetPath, file.content, file.executable ?? false);
|
|
188
|
-
}
|
|
189
|
-
if (fileExists) {
|
|
190
|
-
overwritten.push(file.path);
|
|
191
|
-
} else {
|
|
192
|
-
created.push(file.path);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
const { dependencies, devDependencies } = updatePackageJson(resolvedCwd, block.dependencies ?? {}, block.devDependencies ?? {}, dryRun);
|
|
197
|
-
if (!dryRun) {
|
|
198
|
-
const stampResult = await stampBlock(resolvedCwd, blockName, toolingVersion);
|
|
199
|
-
if (stampResult.isErr()) {
|
|
200
|
-
process.stderr.write(`Warning: failed to stamp manifest: ${stampResult.error.message}
|
|
201
|
-
`);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
return Result.ok({
|
|
205
|
-
created,
|
|
206
|
-
skipped,
|
|
207
|
-
overwritten,
|
|
208
|
-
dependencies,
|
|
209
|
-
devDependencies
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
async function printAddResults(result, dryRun, options) {
|
|
213
|
-
const structuredMode = resolveStructuredOutputMode(options?.mode);
|
|
214
|
-
if (structuredMode) {
|
|
215
|
-
await output({
|
|
216
|
-
dryRun,
|
|
217
|
-
created: result.created,
|
|
218
|
-
overwritten: result.overwritten,
|
|
219
|
-
skipped: result.skipped,
|
|
220
|
-
dependencies: result.dependencies,
|
|
221
|
-
devDependencies: result.devDependencies
|
|
222
|
-
}, { mode: structuredMode });
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
const lines = [];
|
|
226
|
-
const prefix = dryRun ? "[dry-run] Would " : "";
|
|
227
|
-
if (result.created.length > 0) {
|
|
228
|
-
lines.push(`${prefix}create ${result.created.length} file(s):`);
|
|
229
|
-
for (const file of result.created) {
|
|
230
|
-
lines.push(` \u2713 ${file}`);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
if (result.overwritten.length > 0) {
|
|
234
|
-
lines.push(`${prefix}overwrite ${result.overwritten.length} file(s):`);
|
|
235
|
-
for (const file of result.overwritten) {
|
|
236
|
-
lines.push(` \u2713 ${file}`);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
if (result.skipped.length > 0) {
|
|
240
|
-
lines.push(`Skipped ${result.skipped.length} existing file(s):`);
|
|
241
|
-
for (const file of result.skipped) {
|
|
242
|
-
lines.push(` - ${file} (use --force to overwrite)`);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
const depCount = Object.keys(result.dependencies).length + Object.keys(result.devDependencies).length;
|
|
246
|
-
if (depCount > 0) {
|
|
247
|
-
lines.push("", `${prefix}add ${depCount} package(s) to package.json:`);
|
|
248
|
-
for (const [name, version] of Object.entries(result.dependencies)) {
|
|
249
|
-
lines.push(` + ${name}@${version}`);
|
|
250
|
-
}
|
|
251
|
-
for (const [name, version] of Object.entries(result.devDependencies)) {
|
|
252
|
-
lines.push(` + ${name}@${version} (dev)`);
|
|
253
|
-
}
|
|
254
|
-
if (!dryRun) {
|
|
255
|
-
lines.push("", "Run `bun install` to install new dependencies.");
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
await output(lines, { mode: "human" });
|
|
259
|
-
}
|
|
260
|
-
function listBlocks() {
|
|
261
|
-
const registryResult = loadRegistry();
|
|
262
|
-
if (registryResult.isErr()) {
|
|
263
|
-
return registryResult;
|
|
264
|
-
}
|
|
265
|
-
const blocks = Object.keys(registryResult.value.registry.blocks);
|
|
266
|
-
return Result.ok(blocks);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
export { AddError, runAdd, printAddResults, listBlocks };
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { ScaffoldError } from "./outfitter-qfh36ddg";
|
|
2
|
-
import { Result } from "@outfitter/contracts";
|
|
3
|
-
declare function buildWorkspaceRootPackageJson(workspaceName: string): string;
|
|
4
|
-
declare function scaffoldWorkspaceRoot(rootDir: string, workspaceName: string, force: boolean): Result<void, ScaffoldError>;
|
|
5
|
-
declare function detectWorkspaceRoot(cwd: string): Result<string | null, ScaffoldError>;
|
|
6
|
-
export { buildWorkspaceRootPackageJson, scaffoldWorkspaceRoot, detectWorkspaceRoot };
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
// apps/outfitter/src/output-mode.ts
|
|
3
|
-
function resolveOutputModeFromContext(flags) {
|
|
4
|
-
if (flags["json"])
|
|
5
|
-
return "json";
|
|
6
|
-
if (flags["jsonl"])
|
|
7
|
-
return "jsonl";
|
|
8
|
-
if (process.env["OUTFITTER_JSONL"] === "1")
|
|
9
|
-
return "jsonl";
|
|
10
|
-
if (process.env["OUTFITTER_JSON"] === "1")
|
|
11
|
-
return "json";
|
|
12
|
-
return "human";
|
|
13
|
-
}
|
|
14
|
-
function resolveStructuredOutputMode(mode) {
|
|
15
|
-
if (mode !== undefined) {
|
|
16
|
-
if (mode === "json" || mode === "jsonl") {
|
|
17
|
-
return mode;
|
|
18
|
-
}
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
if (process.env["OUTFITTER_JSONL"] === "1") {
|
|
22
|
-
return "jsonl";
|
|
23
|
-
}
|
|
24
|
-
if (process.env["OUTFITTER_JSON"] === "1") {
|
|
25
|
-
return "json";
|
|
26
|
-
}
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export { resolveOutputModeFromContext, resolveStructuredOutputMode };
|