outfitter 0.2.2 → 0.2.4

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/index.d.ts CHANGED
@@ -1,96 +1,7 @@
1
1
  import { ActionRegistry } from "@outfitter/contracts";
2
2
  declare const outfitterActions: ActionRegistry;
3
3
  import { OutputMode } from "@outfitter/cli/types";
4
- import { Result as Result2 } from "@outfitter/contracts";
5
- import { AddBlockResult } from "@outfitter/tooling";
6
4
  import { Command } from "commander";
7
- import { Result, ValidationError } from "@outfitter/contracts";
8
- /**
9
- * Create planner types for kit-first project scaffolding.
10
- *
11
- * These types model preset intent separately from execution so future flows can
12
- * consume a deterministic plan before mutating the filesystem.
13
- */
14
- type CreatePresetId = "basic" | "cli" | "daemon" | "mcp";
15
- interface CreatePresetDefinition {
16
- readonly id: CreatePresetId;
17
- readonly template: CreatePresetId;
18
- readonly summary: string;
19
- readonly defaultBlocks: readonly string[];
20
- }
21
- interface CreateProjectInput {
22
- readonly name: string;
23
- readonly targetDir: string;
24
- readonly preset: CreatePresetId;
25
- readonly packageName?: string;
26
- readonly description?: string;
27
- readonly version?: string;
28
- readonly includeTooling?: boolean;
29
- readonly local?: boolean;
30
- readonly year?: string;
31
- }
32
- type CreatePlanChange = {
33
- readonly type: "copy-template";
34
- readonly template: string;
35
- readonly targetDir: string;
36
- readonly overlayBaseTemplate: boolean;
37
- } | {
38
- readonly type: "inject-shared-config";
39
- } | {
40
- readonly type: "rewrite-local-dependencies";
41
- readonly mode: "workspace";
42
- } | {
43
- readonly type: "add-blocks";
44
- readonly blocks: readonly string[];
45
- };
46
- interface CreateProjectPlan {
47
- readonly preset: CreatePresetDefinition;
48
- readonly values: {
49
- readonly packageName: string;
50
- readonly projectName: string;
51
- readonly version: string;
52
- readonly description: string;
53
- readonly binName: string;
54
- readonly year: string;
55
- };
56
- readonly changes: readonly CreatePlanChange[];
57
- }
58
- declare function planCreateProject(input: CreateProjectInput): Result<CreateProjectPlan, ValidationError>;
59
- declare const CREATE_PRESETS: Readonly<Record<CreatePresetId, CreatePresetDefinition>>;
60
- declare const CREATE_PRESET_IDS: CreatePresetId[];
61
- declare function getCreatePreset(id: string): CreatePresetDefinition | undefined;
62
- type CreateStructure = "single" | "workspace";
63
- interface CreateOptions {
64
- readonly targetDir: string;
65
- readonly name?: string | undefined;
66
- readonly preset?: CreatePresetId | undefined;
67
- readonly structure?: CreateStructure | undefined;
68
- readonly workspaceName?: string | undefined;
69
- readonly local?: boolean | undefined;
70
- readonly force: boolean;
71
- readonly with?: string | undefined;
72
- readonly noTooling?: boolean | undefined;
73
- readonly yes?: boolean | undefined;
74
- }
75
- interface CreateResult {
76
- readonly structure: CreateStructure;
77
- readonly rootDir: string;
78
- readonly projectDir: string;
79
- readonly preset: CreatePresetId;
80
- readonly packageName: string;
81
- readonly blocksAdded?: AddBlockResult | undefined;
82
- }
83
- declare class CreateError extends Error {
84
- readonly _tag: "CreateError";
85
- constructor(message: string);
86
- }
87
- declare function runCreate(options: CreateOptions): Promise<Result2<CreateResult, CreateError>>;
88
- declare function printCreateResults(result: CreateResult, options?: {
89
- mode?: OutputMode;
90
- }): Promise<void>;
91
- declare function createCommand(program: Command): void;
92
- import { OutputMode as OutputMode2 } from "@outfitter/cli/types";
93
- import { Command as Command2 } from "commander";
94
5
  /**
95
6
  * Options for the doctor command.
96
7
  */
@@ -202,7 +113,7 @@ declare function runDoctor(options: DoctorOptions): DoctorResult;
202
113
  * Formats and outputs doctor results.
203
114
  */
204
115
  declare function printDoctorResults(result: DoctorResult, options?: {
205
- mode?: OutputMode2;
116
+ mode?: OutputMode;
206
117
  }): Promise<void>;
207
118
  /**
208
119
  * Registers the doctor command with the CLI program.
@@ -218,37 +129,104 @@ declare function printDoctorResults(result: DoctorResult, options?: {
218
129
  * doctorCommand(program);
219
130
  * ```
220
131
  */
221
- declare function doctorCommand(program: Command2): void;
132
+ declare function doctorCommand(program: Command): void;
133
+ import { OutputMode as OutputMode2 } from "@outfitter/cli/types";
222
134
  import { Result as Result3 } from "@outfitter/contracts";
223
- import { AddBlockResult as AddBlockResult2 } from "@outfitter/tooling";
224
- import { Command as Command3 } from "commander";
135
+ import { AddBlockResult } from "@outfitter/tooling";
136
+ import { Command as Command2 } from "commander";
137
+ interface PostScaffoldResult {
138
+ readonly installResult: "success" | "failed" | "skipped";
139
+ readonly installError?: string | undefined;
140
+ readonly gitInitResult: "success" | "failed" | "skipped" | "already-repo";
141
+ readonly gitCommitResult: "success" | "failed" | "skipped";
142
+ readonly gitError?: string | undefined;
143
+ readonly nextSteps: readonly string[];
144
+ }
145
+ import { NotFoundError, Result as Result2, ValidationError } from "@outfitter/contracts";
146
+ /**
147
+ * Unique identifier for a scaffold target.
148
+ */
149
+ type TargetId = "minimal" | "cli" | "mcp" | "daemon" | "api" | "worker" | "web" | "lib";
150
+ /**
151
+ * Whether the target produces a runnable application or a library package.
152
+ */
153
+ type TargetCategory = "runnable" | "library";
154
+ /**
155
+ * Whether the target has a working template or is a planned placeholder.
156
+ */
157
+ type TargetStatus = "ready" | "stub";
158
+ /**
159
+ * Whether a target can be used with init, scaffold, or both.
160
+ */
161
+ type TargetScope = "init-only" | "scaffold-only" | "both";
162
+ /**
163
+ * Complete definition for a scaffold target.
164
+ */
165
+ interface TargetDefinition {
166
+ readonly id: TargetId;
167
+ readonly description: string;
168
+ readonly category: TargetCategory;
169
+ readonly placement: "apps" | "packages";
170
+ readonly templateDir: string;
171
+ readonly defaultBlocks: readonly string[];
172
+ readonly status: TargetStatus;
173
+ readonly scope: TargetScope;
174
+ }
175
+ declare const TARGET_REGISTRY: ReadonlyMap<TargetId, TargetDefinition>;
176
+ declare const TARGET_IDS: readonly TargetId[];
177
+ declare const READY_TARGET_IDS: readonly TargetId[];
178
+ declare const INIT_TARGET_IDS: readonly TargetId[];
179
+ declare const SCAFFOLD_TARGET_IDS: readonly TargetId[];
180
+ declare function getTarget(id: string): Result2<TargetDefinition, NotFoundError>;
181
+ declare function getReadyTarget(id: string): Result2<TargetDefinition, NotFoundError | ValidationError>;
182
+ declare function getInitTarget(id: string): Result2<TargetDefinition, NotFoundError | ValidationError>;
183
+ declare function getScaffoldTarget(id: string): Result2<TargetDefinition, NotFoundError | ValidationError>;
184
+ declare function resolvePlacement(target: TargetDefinition): "apps" | "packages";
185
+ declare function listTargets(filter?: {
186
+ readonly status?: TargetStatus;
187
+ readonly scope?: TargetScope;
188
+ readonly category?: TargetCategory;
189
+ }): readonly TargetDefinition[];
190
+ type InitStructure = "single" | "workspace";
191
+ type InitPresetId = Extract<TargetId, "minimal" | "cli" | "mcp" | "daemon">;
225
192
  /**
226
193
  * Options for the init command.
227
194
  */
228
195
  interface InitOptions {
229
- /** Target directory to initialize the project in */
230
196
  readonly targetDir: string;
231
- /** Package name (defaults to directory name if not provided) */
232
197
  readonly name: string | undefined;
233
- /** Binary name (defaults to project name if not provided) */
234
198
  readonly bin?: string | undefined;
235
- /** Template to use (defaults to 'basic') */
236
- readonly template: string | undefined;
237
- /** Whether to use local/workspace dependencies */
199
+ readonly preset?: InitPresetId | undefined;
200
+ /** @deprecated Use `preset` instead. */
201
+ readonly template?: string | undefined;
202
+ readonly structure?: InitStructure | undefined;
203
+ readonly workspaceName?: string | undefined;
238
204
  readonly local?: boolean | undefined;
239
- /** Whether to overwrite existing files */
240
205
  readonly force: boolean;
241
- /** Tooling blocks to add (e.g., "scaffolding" or "claude,biome,lefthook") */
242
206
  readonly with?: string | undefined;
243
- /** Skip tooling prompt in interactive mode */
244
207
  readonly noTooling?: boolean | undefined;
208
+ readonly yes?: boolean | undefined;
209
+ readonly dryRun?: boolean | undefined;
210
+ readonly skipInstall?: boolean | undefined;
211
+ readonly skipGit?: boolean | undefined;
212
+ readonly skipCommit?: boolean | undefined;
213
+ readonly installTimeout?: number | undefined;
245
214
  }
246
215
  /**
247
- * Result of running init, including any blocks added.
216
+ * Result of running init.
248
217
  */
249
218
  interface InitResult {
250
- /** The blocks that were added, if any */
251
- readonly blocksAdded?: AddBlockResult2 | undefined;
219
+ readonly structure: InitStructure;
220
+ readonly rootDir: string;
221
+ readonly projectDir: string;
222
+ readonly preset: InitPresetId;
223
+ readonly packageName: string;
224
+ readonly blocksAdded?: AddBlockResult | undefined;
225
+ readonly postScaffold: PostScaffoldResult;
226
+ readonly dryRunPlan?: {
227
+ readonly operations: readonly unknown[];
228
+ readonly summary: Record<string, number>;
229
+ } | undefined;
252
230
  }
253
231
  /**
254
232
  * Error returned when initialization fails.
@@ -257,51 +235,14 @@ declare class InitError extends Error {
257
235
  readonly _tag: "InitError";
258
236
  constructor(message: string);
259
237
  }
260
- /**
261
- * Runs the init command programmatically.
262
- *
263
- * @param options - Init options
264
- * @returns Result indicating success or failure
265
- *
266
- * @example
267
- * ```typescript
268
- * const result = await runInit({
269
- * targetDir: "./my-project",
270
- * name: "my-project",
271
- * template: "basic",
272
- * force: false,
273
- * blocks: "scaffolding", // Optional: add tooling blocks
274
- * });
275
- *
276
- * if (result.isOk()) {
277
- * console.log("Project initialized successfully!");
278
- * if (result.value.blocksAdded) {
279
- * console.log(`Added ${result.value.blocksAdded.created.length} tooling files`);
280
- * }
281
- * } else {
282
- * console.error("Failed:", result.error.message);
283
- * }
284
- * ```
285
- */
286
- declare function runInit(options: InitOptions): Promise<Result3<InitResult, InitError>>;
287
- /**
288
- * Registers the init command with the CLI program.
289
- *
290
- * @param program - Commander program instance
291
- *
292
- * @example
293
- * ```typescript
294
- * import { Command } from "commander";
295
- * import { initCommand } from "./commands/init.js";
296
- *
297
- * const program = new Command();
298
- * initCommand(program);
299
- * ```
300
- */
301
- declare function initCommand(program: Command3): void;
302
- import { OutputMode as OutputMode4 } from "@outfitter/cli/types";
238
+ declare function runInit(options: InitOptions, presetOverride?: InitPresetId): Promise<Result3<InitResult, InitError>>;
239
+ declare function printInitResults(result: InitResult, options?: {
240
+ mode?: OutputMode2;
241
+ }): Promise<void>;
242
+ declare function initCommand(program: Command2): void;
243
+ import { OutputMode as OutputMode3 } from "@outfitter/cli/types";
303
244
  import { Result as Result4 } from "@outfitter/contracts";
304
- import { Command as Command4 } from "commander";
245
+ import { Command as Command3 } from "commander";
305
246
  interface DiffPreview {
306
247
  readonly path: string;
307
248
  readonly preview: string;
@@ -343,10 +284,145 @@ declare function runMigrateKit(options: MigrateKitOptions): Promise<Result4<Migr
343
284
  * Print migrate-kit results.
344
285
  */
345
286
  declare function printMigrateKitResults(result: MigrateKitResult, options?: {
346
- mode?: OutputMode4;
287
+ mode?: OutputMode3;
347
288
  }): Promise<void>;
348
289
  /**
349
290
  * Register `migrate kit` command directly on Commander.
350
291
  */
351
- declare function migrateKitCommand(program: Command4): void;
352
- export { runMigrateKit, runInit, runDoctor, runCreate, printMigrateKitResults, printDoctorResults, printCreateResults, planCreateProject, outfitterActions, migrateKitCommand, initCommand, getCreatePreset, doctorCommand, createCommand, PackageJsonCheck, MigrateKitResult, MigrateKitOptions, MigrateKitError, InitOptions, InitError, DoctorSummary, DoctorResult, DoctorOptions, DirectoriesCheck, DependenciesCheck, CreateStructure, CreateResult, CreateProjectPlan, CreateProjectInput, CreatePresetId, CreatePresetDefinition, CreatePlanChange, CreateOptions, CreateError, ConfigFilesCheck, CheckResult, CREATE_PRESET_IDS, CREATE_PRESETS, BunVersionCheck };
292
+ declare function migrateKitCommand(program: Command3): void;
293
+ import { Command as Command5 } from "commander";
294
+ type DocsMdxMode = "strict" | "lossy";
295
+ interface DocsBaseOptions {
296
+ readonly cwd?: string;
297
+ readonly workspaceRoot?: string;
298
+ readonly packagesDir?: string;
299
+ readonly outputDir?: string;
300
+ readonly excludedFilenames?: readonly string[];
301
+ readonly mdxMode?: DocsMdxMode;
302
+ }
303
+ interface ExecuteCheckCommandOptions extends DocsBaseOptions {}
304
+ interface ExecuteSyncCommandOptions extends DocsBaseOptions {}
305
+ type DocsExportTarget = "packages" | "llms" | "llms-full" | "all";
306
+ interface ExecuteExportCommandOptions extends DocsBaseOptions {
307
+ readonly llmsFile?: string;
308
+ readonly llmsFullFile?: string;
309
+ readonly target?: DocsExportTarget | string;
310
+ }
311
+ type RepoCheckSubject = "docs" | "exports" | "readme" | "registry" | "changeset" | "tree" | "boundary-invocations";
312
+ interface RepoCommandIo {
313
+ readonly out?: (line: string) => void;
314
+ readonly err?: (line: string) => void;
315
+ }
316
+ interface RepoToolingInvocation {
317
+ readonly command: "check-exports" | "check-readme-imports" | "check-bunup-registry" | "check-changeset" | "check-clean-tree" | "check-boundary-invocations";
318
+ readonly args: readonly string[];
319
+ readonly cwd: string;
320
+ }
321
+ interface CreateRepoCommandOptions {
322
+ readonly commandName?: string;
323
+ readonly io?: RepoCommandIo;
324
+ readonly runDocsCheck?: (options: ExecuteCheckCommandOptions, io: Required<RepoCommandIo>) => Promise<number>;
325
+ readonly runDocsSync?: (options: ExecuteSyncCommandOptions, io: Required<RepoCommandIo>) => Promise<number>;
326
+ readonly runDocsExport?: (options: ExecuteExportCommandOptions, io: Required<RepoCommandIo>) => Promise<number>;
327
+ readonly runToolingCommand?: (input: RepoToolingInvocation) => Promise<number>;
328
+ }
329
+ declare function createRepoCommand(options?: CreateRepoCommandOptions): Command5;
330
+ import { OutputMode as OutputMode4 } from "@outfitter/cli/types";
331
+ import { Result as Result5 } from "@outfitter/contracts";
332
+ import { AddBlockResult as AddBlockResult2 } from "@outfitter/tooling";
333
+ import { Command as Command6 } from "commander";
334
+ interface ScaffoldOptions {
335
+ readonly target: string;
336
+ readonly name?: string | undefined;
337
+ readonly force: boolean;
338
+ readonly skipInstall: boolean;
339
+ readonly dryRun: boolean;
340
+ readonly with?: string | undefined;
341
+ readonly noTooling?: boolean | undefined;
342
+ readonly local?: boolean | undefined;
343
+ readonly cwd: string;
344
+ readonly installTimeout?: number | undefined;
345
+ }
346
+ interface ScaffoldCommandResult {
347
+ readonly target: string;
348
+ readonly rootDir: string;
349
+ readonly targetDir: string;
350
+ readonly converted: boolean;
351
+ readonly movedExisting?: {
352
+ readonly from: string;
353
+ readonly to: string;
354
+ readonly name: string;
355
+ } | undefined;
356
+ readonly workspacePatternsUpdated: boolean;
357
+ readonly blocksAdded?: AddBlockResult2 | undefined;
358
+ readonly postScaffold: PostScaffoldResult;
359
+ readonly dryRunPlan?: {
360
+ readonly operations: readonly unknown[];
361
+ readonly summary: Record<string, number>;
362
+ } | undefined;
363
+ }
364
+ declare class ScaffoldCommandError extends Error {
365
+ readonly _tag: "ScaffoldCommandError";
366
+ constructor(message: string);
367
+ }
368
+ declare function runScaffold(options: ScaffoldOptions): Promise<Result5<ScaffoldCommandResult, ScaffoldCommandError>>;
369
+ declare function printScaffoldResults(result: ScaffoldCommandResult, options?: {
370
+ readonly mode?: OutputMode4;
371
+ }): Promise<void>;
372
+ declare function scaffoldCommand(program: Command6): void;
373
+ import { Result as Result6, ValidationError as ValidationError2 } from "@outfitter/contracts";
374
+ /**
375
+ * Create planner types for kit-first project scaffolding.
376
+ *
377
+ * These types model preset intent separately from execution so future flows can
378
+ * consume a deterministic plan before mutating the filesystem.
379
+ */
380
+ type CreatePresetId = "basic" | "cli" | "daemon" | "mcp";
381
+ interface CreatePresetDefinition {
382
+ readonly id: CreatePresetId;
383
+ readonly template: CreatePresetId;
384
+ readonly summary: string;
385
+ readonly defaultBlocks: readonly string[];
386
+ }
387
+ interface CreateProjectInput {
388
+ readonly name: string;
389
+ readonly targetDir: string;
390
+ readonly preset: CreatePresetId;
391
+ readonly packageName?: string;
392
+ readonly description?: string;
393
+ readonly version?: string;
394
+ readonly includeTooling?: boolean;
395
+ readonly local?: boolean;
396
+ readonly year?: string;
397
+ }
398
+ type CreatePlanChange = {
399
+ readonly type: "copy-template";
400
+ readonly template: string;
401
+ readonly targetDir: string;
402
+ readonly overlayBaseTemplate: boolean;
403
+ } | {
404
+ readonly type: "inject-shared-config";
405
+ } | {
406
+ readonly type: "rewrite-local-dependencies";
407
+ readonly mode: "workspace";
408
+ } | {
409
+ readonly type: "add-blocks";
410
+ readonly blocks: readonly string[];
411
+ };
412
+ interface CreateProjectPlan {
413
+ readonly preset: CreatePresetDefinition;
414
+ readonly values: {
415
+ readonly packageName: string;
416
+ readonly projectName: string;
417
+ readonly version: string;
418
+ readonly description: string;
419
+ readonly binName: string;
420
+ readonly year: string;
421
+ };
422
+ readonly changes: readonly CreatePlanChange[];
423
+ }
424
+ declare function planCreateProject(input: CreateProjectInput): Result6<CreateProjectPlan, ValidationError2>;
425
+ declare const CREATE_PRESETS: Readonly<Record<CreatePresetId, CreatePresetDefinition>>;
426
+ declare const CREATE_PRESET_IDS: CreatePresetId[];
427
+ declare function getCreatePreset(id: string): CreatePresetDefinition | undefined;
428
+ export { scaffoldCommand, runScaffold, runMigrateKit, runInit, runDoctor, resolvePlacement, printScaffoldResults, printMigrateKitResults, printInitResults, printDoctorResults, planCreateProject, outfitterActions, migrateKitCommand, listTargets, initCommand, getTarget, getScaffoldTarget, getReadyTarget, getInitTarget, getCreatePreset, doctorCommand, createRepoCommand, TargetStatus, TargetScope, TargetId, TargetDefinition, TargetCategory, TARGET_REGISTRY, TARGET_IDS, ScaffoldOptions, ScaffoldCommandResult, ScaffoldCommandError, SCAFFOLD_TARGET_IDS, RepoToolingInvocation, RepoCommandIo, RepoCheckSubject, READY_TARGET_IDS, PackageJsonCheck, MigrateKitResult, MigrateKitOptions, MigrateKitError, InitStructure, InitResult, InitPresetId, InitOptions, InitError, INIT_TARGET_IDS, DoctorSummary, DoctorResult, DoctorOptions, DirectoriesCheck, DependenciesCheck, CreateRepoCommandOptions, CreateProjectPlan, CreateProjectInput, CreatePresetId, CreatePresetDefinition, CreatePlanChange, ConfigFilesCheck, CheckResult, CREATE_PRESET_IDS, CREATE_PRESETS, BunVersionCheck };
package/dist/index.js CHANGED
@@ -1,42 +1,172 @@
1
1
  import {
2
- CREATE_PRESETS,
3
- CREATE_PRESET_IDS,
4
- CreateError,
2
+ INIT_TARGET_IDS,
5
3
  InitError,
6
4
  MigrateKitError,
7
- createCommand,
5
+ READY_TARGET_IDS,
6
+ SCAFFOLD_TARGET_IDS,
7
+ ScaffoldCommandError,
8
+ TARGET_IDS,
9
+ TARGET_REGISTRY,
10
+ createRepoCommand,
11
+ deriveBinName,
12
+ deriveProjectName,
8
13
  doctorCommand,
9
- getCreatePreset,
14
+ getInitTarget,
15
+ getReadyTarget,
16
+ getScaffoldTarget,
17
+ getTarget,
10
18
  initCommand,
19
+ listTargets,
11
20
  migrateKitCommand,
12
21
  outfitterActions,
13
- planCreateProject,
14
- printCreateResults,
15
22
  printDoctorResults,
23
+ printInitResults,
16
24
  printMigrateKitResults,
17
- runCreate,
25
+ printScaffoldResults,
26
+ resolvePlacement,
18
27
  runDoctor,
19
28
  runInit,
20
- runMigrateKit
21
- } from "./shared/chunk-sak1tt33.js";
29
+ runMigrateKit,
30
+ runScaffold,
31
+ scaffoldCommand
32
+ } from "./shared/chunk-tpwtpa74.js";
33
+ // src/create/planner.ts
34
+ import { Result, ValidationError } from "@outfitter/contracts";
35
+
36
+ // src/create/presets.ts
37
+ var CREATE_PRESETS = {
38
+ basic: {
39
+ id: "basic",
40
+ template: "basic",
41
+ summary: "Minimal Bun + TypeScript project.",
42
+ defaultBlocks: ["scaffolding"]
43
+ },
44
+ cli: {
45
+ id: "cli",
46
+ template: "cli",
47
+ summary: "CLI starter with Outfitter command ergonomics.",
48
+ defaultBlocks: ["scaffolding"]
49
+ },
50
+ daemon: {
51
+ id: "daemon",
52
+ template: "daemon",
53
+ summary: "Daemon + control CLI starter.",
54
+ defaultBlocks: ["scaffolding"]
55
+ },
56
+ mcp: {
57
+ id: "mcp",
58
+ template: "mcp",
59
+ summary: "MCP server starter.",
60
+ defaultBlocks: ["scaffolding"]
61
+ }
62
+ };
63
+ var CREATE_PRESET_IDS = Object.keys(CREATE_PRESETS);
64
+ function getCreatePreset(id) {
65
+ const presets = CREATE_PRESETS;
66
+ return presets[id];
67
+ }
68
+
69
+ // src/create/planner.ts
70
+ function derivePackageName(input) {
71
+ return (input.packageName ?? input.name).trim();
72
+ }
73
+ function planCreateProject(input) {
74
+ const packageName = derivePackageName(input);
75
+ if (packageName.length === 0) {
76
+ return Result.err(new ValidationError({
77
+ message: "Project name must not be empty",
78
+ field: "name"
79
+ }));
80
+ }
81
+ const targetDir = input.targetDir.trim();
82
+ if (targetDir.length === 0) {
83
+ return Result.err(new ValidationError({
84
+ message: "Target directory must not be empty",
85
+ field: "targetDir"
86
+ }));
87
+ }
88
+ if (packageName.startsWith("@") && !packageName.includes("/")) {
89
+ return Result.err(new ValidationError({
90
+ message: "Could not derive a project name from package name",
91
+ field: "packageName"
92
+ }));
93
+ }
94
+ const projectName = deriveProjectName(packageName);
95
+ if (projectName.length === 0) {
96
+ return Result.err(new ValidationError({
97
+ message: "Could not derive a project name from package name",
98
+ field: "packageName"
99
+ }));
100
+ }
101
+ const preset = getCreatePreset(input.preset);
102
+ if (!preset) {
103
+ return Result.err(new ValidationError({
104
+ message: `Unknown create preset '${input.preset}'`,
105
+ field: "preset"
106
+ }));
107
+ }
108
+ const includeTooling = input.includeTooling ?? true;
109
+ const defaultBlocks = includeTooling ? [...preset.defaultBlocks] : [];
110
+ const changes = [
111
+ {
112
+ type: "copy-template",
113
+ template: preset.template,
114
+ targetDir,
115
+ overlayBaseTemplate: true
116
+ },
117
+ { type: "inject-shared-config" }
118
+ ];
119
+ if (input.local) {
120
+ changes.push({ type: "rewrite-local-dependencies", mode: "workspace" });
121
+ }
122
+ if (defaultBlocks.length > 0) {
123
+ changes.push({ type: "add-blocks", blocks: defaultBlocks });
124
+ }
125
+ const plan = {
126
+ preset,
127
+ values: {
128
+ packageName,
129
+ projectName,
130
+ version: input.version?.trim() || "0.1.0",
131
+ description: input.description?.trim() || "A new project created with Outfitter",
132
+ binName: deriveBinName(projectName),
133
+ year: input.year ?? String(new Date().getFullYear())
134
+ },
135
+ changes
136
+ };
137
+ return Result.ok(plan);
138
+ }
22
139
  export {
140
+ scaffoldCommand,
141
+ runScaffold,
23
142
  runMigrateKit,
24
143
  runInit,
25
144
  runDoctor,
26
- runCreate,
145
+ resolvePlacement,
146
+ printScaffoldResults,
27
147
  printMigrateKitResults,
148
+ printInitResults,
28
149
  printDoctorResults,
29
- printCreateResults,
30
150
  planCreateProject,
31
151
  outfitterActions,
32
152
  migrateKitCommand,
153
+ listTargets,
33
154
  initCommand,
155
+ getTarget,
156
+ getScaffoldTarget,
157
+ getReadyTarget,
158
+ getInitTarget,
34
159
  getCreatePreset,
35
160
  doctorCommand,
36
- createCommand,
161
+ createRepoCommand,
162
+ TARGET_REGISTRY,
163
+ TARGET_IDS,
164
+ ScaffoldCommandError,
165
+ SCAFFOLD_TARGET_IDS,
166
+ READY_TARGET_IDS,
37
167
  MigrateKitError,
38
168
  InitError,
39
- CreateError,
169
+ INIT_TARGET_IDS,
40
170
  CREATE_PRESET_IDS,
41
171
  CREATE_PRESETS
42
172
  };