outfitter 0.2.1 → 0.2.3
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 +215 -116
- package/dist/actions.d.ts +2 -0
- package/dist/actions.js +34 -0
- package/dist/cli.js +29 -5
- package/dist/commands/add.d.ts +54 -0
- package/dist/commands/add.js +16 -0
- package/dist/commands/check.d.ts +91 -0
- package/dist/commands/check.js +14 -0
- package/dist/commands/demo.d.ts +21 -0
- package/dist/commands/demo.js +8 -0
- package/dist/commands/docs-module-loader.d.ts +2 -0
- package/dist/commands/docs-module-loader.js +8 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +13 -0
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.js +31 -0
- package/dist/commands/migrate-kit.d.ts +2 -0
- package/dist/commands/migrate-kit.js +15 -0
- package/dist/commands/repo.d.ts +3 -0
- package/dist/commands/repo.js +9 -0
- package/dist/commands/scaffold.d.ts +4 -0
- package/dist/commands/scaffold.js +31 -0
- package/dist/commands/shared-deps.d.ts +36 -0
- package/dist/commands/shared-deps.js +10 -0
- package/dist/commands/update-planner.d.ts +58 -0
- package/dist/commands/update-planner.js +8 -0
- package/dist/commands/update-workspace.d.ts +76 -0
- package/dist/commands/update-workspace.js +16 -0
- package/dist/commands/update.d.ts +113 -0
- package/dist/commands/update.js +21 -0
- package/dist/create/index.d.ts +5 -0
- package/dist/create/index.js +29 -0
- package/dist/create/planner.d.ts +3 -0
- package/dist/create/planner.js +21 -0
- package/dist/create/presets.d.ts +3 -0
- package/dist/create/presets.js +12 -0
- package/dist/create/types.d.ts +2 -0
- package/dist/create/types.js +1 -0
- package/dist/engine/blocks.d.ts +3 -0
- package/dist/engine/blocks.js +12 -0
- package/dist/engine/collector.d.ts +2 -0
- package/dist/engine/collector.js +8 -0
- package/dist/engine/config.d.ts +3 -0
- package/dist/engine/config.js +12 -0
- package/dist/engine/executor.d.ts +3 -0
- package/dist/engine/executor.js +16 -0
- package/dist/engine/index.d.ts +8 -0
- package/dist/engine/index.js +59 -0
- package/dist/engine/names.d.ts +2 -0
- package/dist/engine/names.js +16 -0
- package/dist/engine/post-scaffold.d.ts +3 -0
- package/dist/engine/post-scaffold.js +8 -0
- package/dist/engine/render-plan.d.ts +7 -0
- package/dist/engine/render-plan.js +9 -0
- package/dist/engine/template.d.ts +3 -0
- package/dist/engine/template.js +17 -0
- package/dist/engine/types.d.ts +2 -0
- package/dist/engine/types.js +8 -0
- package/dist/engine/workspace.d.ts +3 -0
- package/dist/engine/workspace.js +13 -0
- package/dist/index.d.ts +265 -50
- package/dist/index.js +157 -3
- package/dist/manifest.d.ts +71 -0
- package/dist/manifest.js +16 -0
- package/dist/output-mode.d.ts +2 -0
- package/dist/output-mode.js +10 -0
- package/dist/shared/chunk-b0y0cwkr.js +5533 -0
- package/dist/shared/outfitter-193jvzg4.d.ts +5 -0
- package/dist/shared/outfitter-1dd0k853.js +194 -0
- package/dist/shared/outfitter-1h7k8xxt.js +29 -0
- package/dist/shared/outfitter-1qwpjt6w.js +125 -0
- package/dist/shared/outfitter-2ngep1h2.d.ts +5 -0
- package/dist/shared/outfitter-2np85etz.js +95 -0
- package/dist/shared/outfitter-33w361tc.d.ts +18 -0
- package/dist/shared/outfitter-344t1r38.js +1 -0
- package/dist/shared/outfitter-3weh61w7.d.ts +25 -0
- package/dist/shared/outfitter-4s9meh3j.js +221 -0
- package/dist/shared/outfitter-6a4bq054.js +322 -0
- package/dist/shared/outfitter-6bkqjk86.d.ts +3 -0
- package/dist/shared/outfitter-6gc3g5wk.js +98 -0
- package/dist/shared/outfitter-7cv5fg1m.js +61 -0
- package/dist/shared/outfitter-7ha7p61k.d.ts +6 -0
- package/dist/shared/outfitter-7r12fj7f.js +30 -0
- package/dist/shared/outfitter-8y2dfx6n.js +11 -0
- package/dist/shared/outfitter-9c8edfsn.js +715 -0
- package/dist/shared/outfitter-9x1brcmq.js +184 -0
- package/dist/shared/outfitter-a79xrm12.d.ts +17 -0
- package/dist/shared/outfitter-amc4jbs1.d.ts +50 -0
- package/dist/shared/outfitter-ara3djt0.js +73 -0
- package/dist/shared/outfitter-avhm5z6w.js +82 -0
- package/dist/shared/outfitter-b5nd42y4.d.ts +45 -0
- package/dist/shared/outfitter-dd0btgec.d.ts +40 -0
- package/dist/shared/outfitter-e2zz5wv7.d.ts +51 -0
- package/dist/shared/outfitter-ehp18x1n.js +1 -0
- package/dist/shared/outfitter-fnsmx3xg.js +750 -0
- package/dist/shared/outfitter-gdvm5c0b.d.ts +4 -0
- package/dist/shared/outfitter-gp4v5gkf.js +322 -0
- package/dist/shared/outfitter-h1mnzzd1.d.ts +14 -0
- package/dist/shared/outfitter-hpymx4m9.js +184 -0
- package/dist/shared/outfitter-hvsaxgcp.js +1 -0
- package/dist/shared/outfitter-j8yc7294.d.ts +22 -0
- package/dist/shared/outfitter-jyxwznk1.js +404 -0
- package/dist/shared/outfitter-k112c427.js +21 -0
- package/dist/shared/outfitter-k56rmt24.d.ts +30 -0
- package/dist/shared/outfitter-ksa1pp4t.d.ts +4 -0
- package/dist/shared/outfitter-mdt37hqm.js +4 -0
- package/dist/shared/outfitter-mtbpabf3.js +91 -0
- package/dist/shared/outfitter-nm4m0v6x.d.ts +131 -0
- package/dist/shared/outfitter-nmeecf1b.js +531 -0
- package/dist/shared/outfitter-npyfbdmc.d.ts +6 -0
- package/dist/shared/outfitter-pxt58tsq.js +582 -0
- package/dist/shared/outfitter-q9agarmb.js +42 -0
- package/dist/shared/outfitter-qfgj5xpq.js +70 -0
- package/dist/shared/outfitter-qfh36ddg.d.ts +66 -0
- package/dist/shared/outfitter-s6k8y2p4.js +269 -0
- package/dist/shared/outfitter-sftf1s26.js +199 -0
- package/dist/shared/outfitter-sg7ncy4a.d.ts +51 -0
- package/dist/shared/outfitter-sgtq57qr.d.ts +5 -0
- package/dist/shared/outfitter-txre6cdn.d.ts +60 -0
- package/dist/shared/outfitter-vh4xgb93.js +35 -0
- package/dist/shared/outfitter-ya44h1km.js +191 -0
- package/dist/shared/outfitter-zwyvewr1.js +36 -0
- package/dist/targets/index.d.ts +4 -0
- package/dist/targets/index.js +29 -0
- package/dist/targets/registry.d.ts +3 -0
- package/dist/targets/registry.js +28 -0
- package/dist/targets/types.d.ts +2 -0
- package/dist/targets/types.js +1 -0
- package/package.json +182 -29
- package/templates/basic/.lefthook.yml.template +4 -5
- package/templates/basic/package.json.template +10 -5
- package/templates/cli/.lefthook.yml.template +4 -5
- package/templates/cli/biome.json.template +2 -15
- package/templates/cli/package.json.template +11 -7
- package/templates/daemon/.lefthook.yml.template +4 -5
- package/templates/daemon/biome.json.template +2 -15
- package/templates/daemon/package.json.template +11 -7
- package/templates/mcp/.lefthook.yml.template +4 -5
- package/templates/mcp/biome.json.template +2 -15
- package/templates/mcp/package.json.template +11 -7
- package/templates/minimal/.gitignore.template +30 -0
- package/templates/minimal/.lefthook.yml.template +26 -0
- package/templates/minimal/package.json.template +46 -0
- package/templates/minimal/src/index.ts.template +26 -0
- package/templates/minimal/tsconfig.json.template +34 -0
- package/dist/shared/chunk-f3sch043.js +0 -1858
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { EngineOptions, ScaffoldError } from "./outfitter-qfh36ddg";
|
|
2
|
+
import { Result } from "@outfitter/contracts";
|
|
3
|
+
import { AddBlockResult } from "@outfitter/tooling";
|
|
4
|
+
declare function addBlocks(targetDir: string, blocks: readonly string[], options: EngineOptions): Promise<Result<AddBlockResult, ScaffoldError>>;
|
|
5
|
+
export { addBlocks };
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// apps/outfitter/src/targets/registry.ts
|
|
3
|
+
import { NotFoundError, Result, ValidationError } from "@outfitter/contracts";
|
|
4
|
+
var TARGET_ALIASES = new Map([
|
|
5
|
+
["basic", "minimal"]
|
|
6
|
+
]);
|
|
7
|
+
var TARGET_REGISTRY = new Map([
|
|
8
|
+
[
|
|
9
|
+
"minimal",
|
|
10
|
+
{
|
|
11
|
+
id: "minimal",
|
|
12
|
+
description: "Minimal Bun + TypeScript project",
|
|
13
|
+
category: "library",
|
|
14
|
+
placement: "packages",
|
|
15
|
+
templateDir: "minimal",
|
|
16
|
+
defaultBlocks: ["scaffolding"],
|
|
17
|
+
status: "ready",
|
|
18
|
+
scope: "init-only"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
[
|
|
22
|
+
"cli",
|
|
23
|
+
{
|
|
24
|
+
id: "cli",
|
|
25
|
+
description: "CLI application with Outfitter command ergonomics",
|
|
26
|
+
category: "runnable",
|
|
27
|
+
placement: "apps",
|
|
28
|
+
templateDir: "cli",
|
|
29
|
+
defaultBlocks: ["scaffolding"],
|
|
30
|
+
status: "ready",
|
|
31
|
+
scope: "both"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
"mcp",
|
|
36
|
+
{
|
|
37
|
+
id: "mcp",
|
|
38
|
+
description: "MCP server with typed tools and action registry",
|
|
39
|
+
category: "runnable",
|
|
40
|
+
placement: "apps",
|
|
41
|
+
templateDir: "mcp",
|
|
42
|
+
defaultBlocks: ["scaffolding"],
|
|
43
|
+
status: "ready",
|
|
44
|
+
scope: "both"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
[
|
|
48
|
+
"daemon",
|
|
49
|
+
{
|
|
50
|
+
id: "daemon",
|
|
51
|
+
description: "Background daemon with control CLI",
|
|
52
|
+
category: "runnable",
|
|
53
|
+
placement: "apps",
|
|
54
|
+
templateDir: "daemon",
|
|
55
|
+
defaultBlocks: ["scaffolding"],
|
|
56
|
+
status: "ready",
|
|
57
|
+
scope: "both"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
[
|
|
61
|
+
"api",
|
|
62
|
+
{
|
|
63
|
+
id: "api",
|
|
64
|
+
description: "HTTP API server (Hono)",
|
|
65
|
+
category: "runnable",
|
|
66
|
+
placement: "apps",
|
|
67
|
+
templateDir: "api",
|
|
68
|
+
defaultBlocks: ["scaffolding"],
|
|
69
|
+
status: "stub",
|
|
70
|
+
scope: "both"
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
[
|
|
74
|
+
"worker",
|
|
75
|
+
{
|
|
76
|
+
id: "worker",
|
|
77
|
+
description: "Background job worker",
|
|
78
|
+
category: "runnable",
|
|
79
|
+
placement: "apps",
|
|
80
|
+
templateDir: "worker",
|
|
81
|
+
defaultBlocks: ["scaffolding"],
|
|
82
|
+
status: "stub",
|
|
83
|
+
scope: "both"
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
[
|
|
87
|
+
"web",
|
|
88
|
+
{
|
|
89
|
+
id: "web",
|
|
90
|
+
description: "Web application (TanStack Start)",
|
|
91
|
+
category: "runnable",
|
|
92
|
+
placement: "apps",
|
|
93
|
+
templateDir: "web",
|
|
94
|
+
defaultBlocks: ["scaffolding"],
|
|
95
|
+
status: "stub",
|
|
96
|
+
scope: "both"
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
[
|
|
100
|
+
"lib",
|
|
101
|
+
{
|
|
102
|
+
id: "lib",
|
|
103
|
+
description: "Shared library package",
|
|
104
|
+
category: "library",
|
|
105
|
+
placement: "packages",
|
|
106
|
+
templateDir: "lib",
|
|
107
|
+
defaultBlocks: ["scaffolding"],
|
|
108
|
+
status: "stub",
|
|
109
|
+
scope: "both"
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
]);
|
|
113
|
+
var TARGET_IDS = [...TARGET_REGISTRY.keys()];
|
|
114
|
+
var READY_TARGET_IDS = TARGET_IDS.filter((id) => TARGET_REGISTRY.get(id)?.status === "ready");
|
|
115
|
+
var INIT_TARGET_IDS = TARGET_IDS.filter((id) => {
|
|
116
|
+
const target = TARGET_REGISTRY.get(id);
|
|
117
|
+
return target?.status === "ready" && target.scope !== "scaffold-only";
|
|
118
|
+
});
|
|
119
|
+
var SCAFFOLD_TARGET_IDS = TARGET_IDS.filter((id) => {
|
|
120
|
+
const target = TARGET_REGISTRY.get(id);
|
|
121
|
+
return target?.status === "ready" && target.scope !== "init-only";
|
|
122
|
+
});
|
|
123
|
+
function getTarget(id) {
|
|
124
|
+
const resolvedId = TARGET_ALIASES.get(id) ?? id;
|
|
125
|
+
const target = TARGET_REGISTRY.get(resolvedId);
|
|
126
|
+
if (!target) {
|
|
127
|
+
return Result.err(new NotFoundError({
|
|
128
|
+
message: `Unknown target '${id}'. Available targets: ${TARGET_IDS.join(", ")}`,
|
|
129
|
+
resourceType: "target",
|
|
130
|
+
resourceId: id
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
return Result.ok(target);
|
|
134
|
+
}
|
|
135
|
+
function getReadyTarget(id) {
|
|
136
|
+
const targetResult = getTarget(id);
|
|
137
|
+
if (targetResult.isErr()) {
|
|
138
|
+
return targetResult;
|
|
139
|
+
}
|
|
140
|
+
const target = targetResult.value;
|
|
141
|
+
if (target.status === "stub") {
|
|
142
|
+
return Result.err(new ValidationError({
|
|
143
|
+
message: `Target '${id}' is not yet available. ` + "It is planned but the template has not been implemented. " + `Ready targets: ${READY_TARGET_IDS.join(", ")}`,
|
|
144
|
+
field: "target"
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
return Result.ok(target);
|
|
148
|
+
}
|
|
149
|
+
function getInitTarget(id) {
|
|
150
|
+
const targetResult = getReadyTarget(id);
|
|
151
|
+
if (targetResult.isErr()) {
|
|
152
|
+
return targetResult;
|
|
153
|
+
}
|
|
154
|
+
const target = targetResult.value;
|
|
155
|
+
if (target.scope === "scaffold-only") {
|
|
156
|
+
return Result.err(new ValidationError({
|
|
157
|
+
message: `Target '${id}' cannot be used with init. Use 'outfitter scaffold ${id}' instead.`,
|
|
158
|
+
field: "target"
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
161
|
+
return Result.ok(target);
|
|
162
|
+
}
|
|
163
|
+
function getScaffoldTarget(id) {
|
|
164
|
+
const targetResult = getReadyTarget(id);
|
|
165
|
+
if (targetResult.isErr()) {
|
|
166
|
+
return targetResult;
|
|
167
|
+
}
|
|
168
|
+
const target = targetResult.value;
|
|
169
|
+
if (target.scope === "init-only") {
|
|
170
|
+
return Result.err(new ValidationError({
|
|
171
|
+
message: `Target '${id}' cannot be scaffolded into an existing project. ` + `It is only available for new project creation via 'outfitter init'.`,
|
|
172
|
+
field: "target"
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
return Result.ok(target);
|
|
176
|
+
}
|
|
177
|
+
function resolvePlacement(target) {
|
|
178
|
+
return target.placement;
|
|
179
|
+
}
|
|
180
|
+
function listTargets(filter) {
|
|
181
|
+
let targets = [...TARGET_REGISTRY.values()];
|
|
182
|
+
if (filter?.status) {
|
|
183
|
+
targets = targets.filter((target) => target.status === filter.status);
|
|
184
|
+
}
|
|
185
|
+
if (filter?.scope) {
|
|
186
|
+
targets = targets.filter((target) => target.scope === filter.scope);
|
|
187
|
+
}
|
|
188
|
+
if (filter?.category) {
|
|
189
|
+
targets = targets.filter((target) => target.category === filter.category);
|
|
190
|
+
}
|
|
191
|
+
return targets;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export { TARGET_REGISTRY, TARGET_IDS, READY_TARGET_IDS, INIT_TARGET_IDS, SCAFFOLD_TARGET_IDS, getTarget, getReadyTarget, getInitTarget, getScaffoldTarget, resolvePlacement, listTargets };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// apps/outfitter/src/engine/collector.ts
|
|
3
|
+
class OperationCollector {
|
|
4
|
+
operations = [];
|
|
5
|
+
add(op) {
|
|
6
|
+
this.operations.push(op);
|
|
7
|
+
}
|
|
8
|
+
getOperations() {
|
|
9
|
+
return this.operations;
|
|
10
|
+
}
|
|
11
|
+
countByType() {
|
|
12
|
+
const counts = {};
|
|
13
|
+
for (const op of this.operations) {
|
|
14
|
+
counts[op.type] = (counts[op.type] ?? 0) + 1;
|
|
15
|
+
}
|
|
16
|
+
return counts;
|
|
17
|
+
}
|
|
18
|
+
isEmpty() {
|
|
19
|
+
return this.operations.length === 0;
|
|
20
|
+
}
|
|
21
|
+
toJSON() {
|
|
22
|
+
return {
|
|
23
|
+
operations: this.operations,
|
|
24
|
+
summary: this.countByType()
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { OperationCollector };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
copyTemplateFiles,
|
|
4
|
+
getTemplatesDir
|
|
5
|
+
} from "./outfitter-9x1brcmq.js";
|
|
6
|
+
import {
|
|
7
|
+
addBlocks
|
|
8
|
+
} from "./outfitter-7cv5fg1m.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 };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { CreatePresetDefinition, CreatePresetId } from "./outfitter-e2zz5wv7";
|
|
2
|
+
declare const CREATE_PRESETS: Readonly<Record<CreatePresetId, CreatePresetDefinition>>;
|
|
3
|
+
declare const CREATE_PRESET_IDS: CreatePresetId[];
|
|
4
|
+
declare function getCreatePreset(id: string): CreatePresetDefinition | undefined;
|
|
5
|
+
export { CREATE_PRESETS, CREATE_PRESET_IDS, getCreatePreset };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
ScaffoldError
|
|
4
|
+
} from "./outfitter-8y2dfx6n.js";
|
|
5
|
+
|
|
6
|
+
// apps/outfitter/src/engine/workspace.ts
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
8
|
+
import { dirname, join, resolve } from "path";
|
|
9
|
+
import { Result } from "@outfitter/contracts";
|
|
10
|
+
function buildWorkspaceRootPackageJson(workspaceName) {
|
|
11
|
+
const workspacePackage = {
|
|
12
|
+
name: workspaceName,
|
|
13
|
+
private: true,
|
|
14
|
+
version: "0.1.0",
|
|
15
|
+
workspaces: ["apps/*", "packages/*"],
|
|
16
|
+
scripts: {
|
|
17
|
+
build: "bun run --filter '*' build",
|
|
18
|
+
dev: "bun run --filter '*' dev",
|
|
19
|
+
test: "bun run --filter '*' test",
|
|
20
|
+
typecheck: "bun run --filter '*' typecheck",
|
|
21
|
+
lint: "bun run --filter '*' lint",
|
|
22
|
+
"lint:fix": "bun run --filter '*' lint:fix",
|
|
23
|
+
format: "bun run --filter '*' format"
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
return `${JSON.stringify(workspacePackage, null, 2)}
|
|
27
|
+
`;
|
|
28
|
+
}
|
|
29
|
+
function scaffoldWorkspaceRoot(rootDir, workspaceName, force) {
|
|
30
|
+
const packageJsonPath = join(rootDir, "package.json");
|
|
31
|
+
if (existsSync(packageJsonPath) && !force) {
|
|
32
|
+
return Result.err(new ScaffoldError(`Directory '${rootDir}' already has a package.json. Use --force to overwrite.`));
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
if (!existsSync(rootDir)) {
|
|
36
|
+
mkdirSync(rootDir, { recursive: true });
|
|
37
|
+
}
|
|
38
|
+
mkdirSync(join(rootDir, "apps"), { recursive: true });
|
|
39
|
+
mkdirSync(join(rootDir, "packages"), { recursive: true });
|
|
40
|
+
writeFileSync(packageJsonPath, buildWorkspaceRootPackageJson(workspaceName), "utf-8");
|
|
41
|
+
const gitignorePath = join(rootDir, ".gitignore");
|
|
42
|
+
if (force || !existsSync(gitignorePath)) {
|
|
43
|
+
writeFileSync(gitignorePath, `node_modules
|
|
44
|
+
**/dist
|
|
45
|
+
`, "utf-8");
|
|
46
|
+
}
|
|
47
|
+
return Result.ok(undefined);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
50
|
+
return Result.err(new ScaffoldError(`Failed to scaffold workspace root: ${message}`));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function hasWorkspacesField(pkg) {
|
|
54
|
+
const workspaces = pkg.workspaces;
|
|
55
|
+
if (Array.isArray(workspaces) && workspaces.length > 0) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
if (workspaces && typeof workspaces === "object" && !Array.isArray(workspaces)) {
|
|
59
|
+
const packages = workspaces.packages;
|
|
60
|
+
if (Array.isArray(packages) && packages.length > 0) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
function detectWorkspaceRoot(cwd) {
|
|
67
|
+
let current = resolve(cwd);
|
|
68
|
+
const root = resolve("/");
|
|
69
|
+
while (true) {
|
|
70
|
+
if (existsSync(join(current, "pnpm-workspace.yaml"))) {
|
|
71
|
+
return Result.ok(current);
|
|
72
|
+
}
|
|
73
|
+
const pkgPath = join(current, "package.json");
|
|
74
|
+
if (existsSync(pkgPath)) {
|
|
75
|
+
try {
|
|
76
|
+
const raw = readFileSync(pkgPath, "utf-8");
|
|
77
|
+
const pkg = JSON.parse(raw);
|
|
78
|
+
if (hasWorkspacesField(pkg)) {
|
|
79
|
+
return Result.ok(current);
|
|
80
|
+
}
|
|
81
|
+
} catch {}
|
|
82
|
+
}
|
|
83
|
+
if (current === root) {
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
const parent = dirname(current);
|
|
87
|
+
if (parent === current) {
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
current = parent;
|
|
91
|
+
}
|
|
92
|
+
return Result.ok(null);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { buildWorkspaceRootPackageJson, scaffoldWorkspaceRoot, detectWorkspaceRoot };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { TargetCategory, TargetDefinition, TargetId, TargetScope, TargetStatus } from "./outfitter-k56rmt24";
|
|
2
|
+
import { NotFoundError, Result, ValidationError } from "@outfitter/contracts";
|
|
3
|
+
declare const TARGET_REGISTRY: ReadonlyMap<TargetId, TargetDefinition>;
|
|
4
|
+
declare const TARGET_IDS: readonly TargetId[];
|
|
5
|
+
declare const READY_TARGET_IDS: readonly TargetId[];
|
|
6
|
+
declare const INIT_TARGET_IDS: readonly TargetId[];
|
|
7
|
+
declare const SCAFFOLD_TARGET_IDS: readonly TargetId[];
|
|
8
|
+
declare function getTarget(id: string): Result<TargetDefinition, NotFoundError>;
|
|
9
|
+
declare function getReadyTarget(id: string): Result<TargetDefinition, NotFoundError | ValidationError>;
|
|
10
|
+
declare function getInitTarget(id: string): Result<TargetDefinition, NotFoundError | ValidationError>;
|
|
11
|
+
declare function getScaffoldTarget(id: string): Result<TargetDefinition, NotFoundError | ValidationError>;
|
|
12
|
+
declare function resolvePlacement(target: TargetDefinition): "apps" | "packages";
|
|
13
|
+
declare function listTargets(filter?: {
|
|
14
|
+
readonly status?: TargetStatus;
|
|
15
|
+
readonly scope?: TargetScope;
|
|
16
|
+
readonly category?: TargetCategory;
|
|
17
|
+
}): readonly TargetDefinition[];
|
|
18
|
+
export { TARGET_REGISTRY, TARGET_IDS, READY_TARGET_IDS, INIT_TARGET_IDS, SCAFFOLD_TARGET_IDS, getTarget, getReadyTarget, getInitTarget, getScaffoldTarget, resolvePlacement, listTargets };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// @bun
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { OperationCollector } from "./outfitter-amc4jbs1";
|
|
2
|
+
import { Result } from "@outfitter/contracts";
|
|
3
|
+
type ScaffoldOrigin = "init" | "scaffold";
|
|
4
|
+
interface PostScaffoldOptions {
|
|
5
|
+
readonly rootDir: string;
|
|
6
|
+
readonly projectDir: string;
|
|
7
|
+
readonly origin: ScaffoldOrigin;
|
|
8
|
+
readonly target: string;
|
|
9
|
+
readonly structure: "single" | "workspace";
|
|
10
|
+
readonly skipInstall: boolean;
|
|
11
|
+
readonly skipGit: boolean;
|
|
12
|
+
readonly skipCommit: boolean;
|
|
13
|
+
readonly dryRun: boolean;
|
|
14
|
+
readonly installTimeoutMs: number;
|
|
15
|
+
}
|
|
16
|
+
interface PostScaffoldResult {
|
|
17
|
+
readonly installResult: "success" | "failed" | "skipped";
|
|
18
|
+
readonly installError?: string | undefined;
|
|
19
|
+
readonly gitInitResult: "success" | "failed" | "skipped" | "already-repo";
|
|
20
|
+
readonly gitCommitResult: "success" | "failed" | "skipped";
|
|
21
|
+
readonly gitError?: string | undefined;
|
|
22
|
+
readonly nextSteps: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
declare function runPostScaffold(options: PostScaffoldOptions, collector?: OperationCollector): Promise<Result<PostScaffoldResult, never>>;
|
|
25
|
+
export { PostScaffoldOptions, PostScaffoldResult, runPostScaffold };
|