outfitter 0.3.2 → 0.3.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.
Files changed (256) hide show
  1. package/README.md +33 -5
  2. package/dist/actions/add.d.ts +18 -0
  3. package/dist/actions/add.js +14 -0
  4. package/dist/actions/check-automation.d.ts +20 -0
  5. package/dist/actions/check-automation.js +27 -0
  6. package/dist/actions/check.d.ts +34 -0
  7. package/dist/actions/check.js +19 -0
  8. package/dist/actions/demo.d.ts +12 -0
  9. package/dist/actions/demo.js +11 -0
  10. package/dist/actions/docs-output-mode.d.ts +4 -0
  11. package/dist/actions/docs-output-mode.js +8 -0
  12. package/dist/actions/docs.d.ts +25 -0
  13. package/dist/actions/docs.js +31 -0
  14. package/dist/actions/doctor.d.ts +10 -0
  15. package/dist/actions/doctor.js +15 -0
  16. package/dist/actions/init.d.ts +28 -0
  17. package/dist/actions/init.js +31 -0
  18. package/dist/actions/scaffold.d.ts +19 -0
  19. package/dist/actions/scaffold.js +21 -0
  20. package/dist/actions/shared.d.ts +61 -0
  21. package/dist/actions/shared.js +30 -0
  22. package/dist/actions/upgrade.d.ts +17 -0
  23. package/dist/actions/upgrade.js +21 -0
  24. package/dist/actions.d.ts +2 -0
  25. package/dist/actions.js +66 -0
  26. package/dist/cli.js +66 -4
  27. package/dist/commands/add.d.ts +54 -0
  28. package/dist/commands/add.js +16 -0
  29. package/dist/commands/check-action-ceremony.d.ts +55 -0
  30. package/dist/commands/check-action-ceremony.js +15 -0
  31. package/dist/commands/check-docs-sentinel.d.ts +27 -0
  32. package/dist/commands/check-docs-sentinel.js +18 -0
  33. package/dist/commands/check-orchestrator.d.ts +2 -0
  34. package/dist/commands/check-orchestrator.js +17 -0
  35. package/dist/commands/check-preset-versions.d.ts +20 -0
  36. package/dist/commands/check-preset-versions.js +15 -0
  37. package/dist/commands/check-publish-guardrails.d.ts +38 -0
  38. package/dist/commands/check-publish-guardrails.js +19 -0
  39. package/dist/commands/check-surface-map-format.d.ts +29 -0
  40. package/dist/commands/check-surface-map-format.js +19 -0
  41. package/dist/commands/check-surface-map.d.ts +20 -0
  42. package/dist/commands/check-surface-map.js +15 -0
  43. package/dist/commands/check-tsdoc.d.ts +3 -0
  44. package/dist/commands/check-tsdoc.js +9 -0
  45. package/dist/commands/check.d.ts +93 -0
  46. package/dist/commands/check.js +14 -0
  47. package/dist/commands/demo.d.ts +21 -0
  48. package/dist/commands/demo.js +8 -0
  49. package/dist/commands/docs-api.d.ts +4 -0
  50. package/dist/commands/docs-api.js +13 -0
  51. package/dist/commands/docs-export.d.ts +4 -0
  52. package/dist/commands/docs-export.js +12 -0
  53. package/dist/commands/docs-list.d.ts +3 -0
  54. package/dist/commands/docs-list.js +13 -0
  55. package/dist/commands/docs-module-loader.d.ts +2 -0
  56. package/dist/commands/docs-module-loader.js +8 -0
  57. package/dist/commands/docs-search.d.ts +3 -0
  58. package/dist/commands/docs-search.js +13 -0
  59. package/dist/commands/docs-show.d.ts +3 -0
  60. package/dist/commands/docs-show.js +13 -0
  61. package/dist/commands/docs-types.d.ts +21 -0
  62. package/dist/commands/docs-types.js +1 -0
  63. package/dist/commands/doctor.d.ts +2 -0
  64. package/dist/commands/doctor.js +17 -0
  65. package/dist/commands/init-execution.d.ts +8 -0
  66. package/dist/commands/init-execution.js +11 -0
  67. package/dist/commands/init-option-resolution.d.ts +5 -0
  68. package/dist/commands/init-option-resolution.js +14 -0
  69. package/dist/commands/init-output.d.ts +9 -0
  70. package/dist/commands/init-output.js +11 -0
  71. package/dist/commands/init.d.ts +9 -0
  72. package/dist/commands/init.js +24 -0
  73. package/dist/commands/jq-utils.d.ts +17 -0
  74. package/dist/commands/jq-utils.js +8 -0
  75. package/dist/commands/repo.d.ts +3 -0
  76. package/dist/commands/repo.js +13 -0
  77. package/dist/commands/scaffold-output.d.ts +4 -0
  78. package/dist/commands/scaffold-output.js +11 -0
  79. package/dist/commands/scaffold-planning.d.ts +65 -0
  80. package/dist/commands/scaffold-planning.js +20 -0
  81. package/dist/commands/scaffold.d.ts +4 -0
  82. package/dist/commands/scaffold.js +26 -0
  83. package/dist/commands/shared-deps.d.ts +22 -0
  84. package/dist/commands/shared-deps.js +11 -0
  85. package/dist/commands/upgrade-apply.d.ts +14 -0
  86. package/dist/commands/upgrade-apply.js +8 -0
  87. package/dist/commands/upgrade-codemods.d.ts +47 -0
  88. package/dist/commands/upgrade-codemods.js +14 -0
  89. package/dist/commands/upgrade-latest-version.d.ts +8 -0
  90. package/dist/commands/upgrade-latest-version.js +8 -0
  91. package/dist/commands/upgrade-migration-docs.d.ts +3 -0
  92. package/dist/commands/upgrade-migration-docs.js +15 -0
  93. package/dist/commands/upgrade-migration-frontmatter.d.ts +2 -0
  94. package/dist/commands/upgrade-migration-frontmatter.js +10 -0
  95. package/dist/commands/upgrade-migration-guides.d.ts +5 -0
  96. package/dist/commands/upgrade-migration-guides.js +10 -0
  97. package/dist/commands/upgrade-output.d.ts +5 -0
  98. package/dist/commands/upgrade-output.js +11 -0
  99. package/dist/commands/upgrade-planner.d.ts +58 -0
  100. package/dist/commands/upgrade-planner.js +8 -0
  101. package/dist/commands/upgrade-report.d.ts +5 -0
  102. package/dist/commands/upgrade-report.js +8 -0
  103. package/dist/commands/upgrade-workspace.d.ts +2 -0
  104. package/dist/commands/upgrade-workspace.js +16 -0
  105. package/dist/commands/upgrade.d.ts +5 -0
  106. package/dist/commands/upgrade.js +37 -0
  107. package/dist/create/index.d.ts +5 -0
  108. package/dist/create/index.js +2 -0
  109. package/dist/create/planner.d.ts +3 -0
  110. package/dist/create/planner.js +85 -0
  111. package/dist/create/presets.d.ts +3 -0
  112. package/dist/create/presets.js +12 -0
  113. package/dist/create/types.d.ts +2 -0
  114. package/dist/create/types.js +1 -0
  115. package/dist/engine/blocks.d.ts +3 -0
  116. package/dist/engine/blocks.js +12 -0
  117. package/dist/engine/collector.d.ts +2 -0
  118. package/dist/engine/collector.js +8 -0
  119. package/dist/engine/config.d.ts +3 -0
  120. package/dist/engine/config.js +15 -0
  121. package/dist/engine/dependency-versions.d.ts +17 -0
  122. package/dist/engine/dependency-versions.js +12 -0
  123. package/dist/engine/executor.d.ts +3 -0
  124. package/dist/engine/executor.js +156 -0
  125. package/dist/engine/index.d.ts +10 -0
  126. package/dist/engine/index.js +54 -0
  127. package/dist/engine/names.d.ts +2 -0
  128. package/dist/engine/names.js +24 -0
  129. package/dist/engine/post-scaffold.d.ts +3 -0
  130. package/dist/engine/post-scaffold.js +8 -0
  131. package/dist/engine/preset.d.ts +3 -0
  132. package/dist/engine/preset.js +17 -0
  133. package/dist/engine/render-plan.d.ts +7 -0
  134. package/dist/engine/render-plan.js +9 -0
  135. package/dist/engine/template.d.ts +4 -0
  136. package/dist/engine/template.js +34 -0
  137. package/dist/engine/types.d.ts +2 -0
  138. package/dist/engine/types.js +8 -0
  139. package/dist/engine/workspace.d.ts +3 -0
  140. package/dist/engine/workspace.js +20 -0
  141. package/dist/index.d.ts +17 -397
  142. package/dist/index.js +7 -165
  143. package/dist/manifest.d.ts +71 -0
  144. package/dist/manifest.js +16 -0
  145. package/dist/output-mode.d.ts +2 -0
  146. package/dist/output-mode.js +10 -0
  147. package/dist/shared/outfitter-109s75x0.d.ts +76 -0
  148. package/dist/shared/outfitter-1fy7byz5.js +170 -0
  149. package/dist/shared/outfitter-1h7k8xxt.js +29 -0
  150. package/dist/shared/outfitter-1tfa9hke.d.ts +55 -0
  151. package/dist/shared/outfitter-2nx0k4b3.d.ts +4 -0
  152. package/dist/shared/outfitter-2ysjerp6.d.ts +44 -0
  153. package/dist/shared/outfitter-2z61gp5w.js +29 -0
  154. package/dist/shared/outfitter-34vg353f.d.ts +82 -0
  155. package/dist/shared/outfitter-3dq4r10s.d.ts +24 -0
  156. package/dist/shared/outfitter-3rcrvva8.js +103 -0
  157. package/dist/shared/outfitter-3tx3adgj.js +278 -0
  158. package/dist/shared/outfitter-4q1zfmvc.js +154 -0
  159. package/dist/shared/outfitter-4s9meh3j.js +221 -0
  160. package/dist/shared/outfitter-507ra35w.js +285 -0
  161. package/dist/shared/outfitter-56jq0rh2.d.ts +42 -0
  162. package/dist/shared/outfitter-58rn1sj1.d.ts +30 -0
  163. package/dist/shared/outfitter-5d9wbzhh.d.ts +19 -0
  164. package/dist/shared/outfitter-5j7zee11.d.ts +180 -0
  165. package/dist/shared/outfitter-5r6q2749.d.ts +18 -0
  166. package/dist/shared/outfitter-5vx1bp7h.js +41 -0
  167. package/dist/shared/outfitter-6ddf91vh.js +190 -0
  168. package/dist/shared/outfitter-6mpkh3zn.js +432 -0
  169. package/dist/shared/outfitter-6rtcemk7.d.ts +18 -0
  170. package/dist/shared/outfitter-6t7xeyg1.js +159 -0
  171. package/dist/shared/outfitter-738z4c37.js +262 -0
  172. package/dist/shared/outfitter-76k25svs.js +322 -0
  173. package/dist/shared/outfitter-7n7vsz95.js +101 -0
  174. package/dist/shared/outfitter-7q9fnbwa.js +60 -0
  175. package/dist/shared/outfitter-7r12fj7f.js +30 -0
  176. package/dist/shared/outfitter-84chvazx.js +480 -0
  177. package/dist/shared/outfitter-8ggmja91.js +301 -0
  178. package/dist/shared/outfitter-8kmak0wc.d.ts +4 -0
  179. package/dist/shared/outfitter-8y2dfx6n.js +11 -0
  180. package/dist/shared/outfitter-940h0x7b.js +71 -0
  181. package/dist/shared/outfitter-954y4mzx.d.ts +5 -0
  182. package/dist/shared/outfitter-a79xrm12.d.ts +17 -0
  183. package/dist/shared/outfitter-b9cpnr7e.js +110 -0
  184. package/dist/shared/outfitter-bpr28y54.js +70 -0
  185. package/dist/shared/outfitter-c7sbs7es.js +92 -0
  186. package/dist/shared/outfitter-cyhzstz0.js +93 -0
  187. package/dist/shared/outfitter-cyvr4r8d.d.ts +67 -0
  188. package/dist/shared/outfitter-d0kqashd.d.ts +98 -0
  189. package/dist/shared/outfitter-dx4hn4ta.js +325 -0
  190. package/dist/shared/outfitter-e84cr97g.js +232 -0
  191. package/dist/shared/outfitter-ec83h4v2.js +17 -0
  192. package/dist/shared/outfitter-eepj7rf7.js +4 -0
  193. package/dist/shared/outfitter-ekb6t1zz.js +35 -0
  194. package/dist/shared/outfitter-ex8gn945.js +51 -0
  195. package/dist/shared/outfitter-f3a70135.js +75 -0
  196. package/dist/shared/outfitter-fbvfd5zq.d.ts +13 -0
  197. package/dist/shared/outfitter-fj2v5ffz.js +165 -0
  198. package/dist/shared/outfitter-fx1m251y.js +122 -0
  199. package/dist/shared/outfitter-fxry5n58.js +254 -0
  200. package/dist/shared/outfitter-g3hvjshg.js +1 -0
  201. package/dist/shared/outfitter-gdc7b7de.d.ts +5 -0
  202. package/dist/shared/outfitter-gyayfx5r.js +156 -0
  203. package/dist/shared/outfitter-h0wmtxw8.d.ts +23 -0
  204. package/dist/shared/outfitter-hcexcvxe.d.ts +25 -0
  205. package/dist/shared/outfitter-hf5bj2gq.js +117 -0
  206. package/dist/shared/outfitter-hsp8vy5m.d.ts +146 -0
  207. package/dist/shared/outfitter-htx4asgr.d.ts +52 -0
  208. package/dist/shared/outfitter-jkct38dh.js +53 -0
  209. package/dist/shared/outfitter-jwxggvz4.js +42 -0
  210. package/dist/shared/outfitter-k6zyvg2n.js +306 -0
  211. package/dist/shared/outfitter-ksyvwmb5.js +191 -0
  212. package/dist/shared/outfitter-m3ehh37q.d.ts +22 -0
  213. package/dist/shared/outfitter-mstr60zz.js +215 -0
  214. package/dist/shared/outfitter-n0ed012k.js +101 -0
  215. package/dist/shared/outfitter-n13pqaft.js +19 -0
  216. package/dist/shared/outfitter-nxvjxrmw.d.ts +48 -0
  217. package/dist/shared/outfitter-p2wn07b7.js +160 -0
  218. package/dist/shared/outfitter-px5sv5gn.js +321 -0
  219. package/dist/shared/outfitter-q1g58t85.js +8 -0
  220. package/dist/shared/outfitter-qsd5638j.js +378 -0
  221. package/dist/shared/outfitter-qsrx7m4w.js +72 -0
  222. package/dist/shared/outfitter-r2awqszh.d.ts +52 -0
  223. package/dist/shared/outfitter-rdpw2sbp.d.ts +77 -0
  224. package/dist/shared/outfitter-rp89dafm.js +109 -0
  225. package/dist/shared/outfitter-s1c0whzj.js +121 -0
  226. package/dist/shared/outfitter-ssrtakh3.js +342 -0
  227. package/dist/shared/outfitter-ssynegbs.js +167 -0
  228. package/dist/shared/outfitter-svts4wk2.js +36 -0
  229. package/dist/shared/outfitter-tavatb5p.js +166 -0
  230. package/dist/shared/outfitter-tqznjgbm.js +44 -0
  231. package/dist/shared/outfitter-ttjr95y9.js +98 -0
  232. package/dist/shared/outfitter-wcrp7d7m.d.ts +5 -0
  233. package/dist/shared/outfitter-wkt0a0ra.js +67 -0
  234. package/dist/shared/outfitter-wrcqq29p.js +132 -0
  235. package/dist/shared/outfitter-wyg1tpp5.d.ts +43 -0
  236. package/dist/shared/outfitter-x0vpb7tj.js +126 -0
  237. package/dist/shared/outfitter-x39awx8g.js +146 -0
  238. package/dist/shared/outfitter-x4cc5xsq.js +168 -0
  239. package/dist/shared/outfitter-x8w5sjnd.d.ts +39 -0
  240. package/dist/shared/outfitter-xr6g13nz.d.ts +50 -0
  241. package/dist/shared/outfitter-xs94pkfe.js +106 -0
  242. package/dist/shared/outfitter-y37yfehn.d.ts +37 -0
  243. package/dist/shared/outfitter-y6ee0k45.d.ts +18 -0
  244. package/dist/shared/outfitter-ydw7x6bh.js +61 -0
  245. package/dist/shared/outfitter-yhb23pjc.js +89 -0
  246. package/dist/shared/outfitter-ypcvwg1s.js +91 -0
  247. package/dist/shared/outfitter-znbqe5zy.d.ts +45 -0
  248. package/dist/shared/outfitter-zng6w0t9.d.ts +4 -0
  249. package/dist/targets/index.d.ts +4 -0
  250. package/dist/targets/index.js +28 -0
  251. package/dist/targets/registry.d.ts +3 -0
  252. package/dist/targets/registry.js +221 -0
  253. package/dist/targets/types.d.ts +2 -0
  254. package/dist/targets/types.js +1 -0
  255. package/package.json +194 -35
  256. package/dist/shared/chunk-3pwh8ys4.js +0 -6461
@@ -0,0 +1,221 @@
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 };
@@ -0,0 +1,285 @@
1
+ // @bun
2
+ import {
3
+ applyJq
4
+ } from "./outfitter-5vx1bp7h.js";
5
+
6
+ // apps/outfitter/src/commands/check-tsdoc.ts
7
+ import { existsSync, readFileSync } from "fs";
8
+ import { createRequire } from "module";
9
+ import { dirname, join, relative } from "path";
10
+ import { pathToFileURL } from "url";
11
+ import { Result, ValidationError } from "@outfitter/contracts";
12
+ var require2 = createRequire(import.meta.url);
13
+ var DEFAULT_TSDOC_DISCOVERY_PATTERNS = [
14
+ "packages/*/src/index.ts",
15
+ "apps/*/src/index.ts",
16
+ "src/index.ts"
17
+ ];
18
+ function calculateCoverage(declarations) {
19
+ const total = declarations.length;
20
+ if (total === 0) {
21
+ return {
22
+ documented: 0,
23
+ partial: 0,
24
+ undocumented: 0,
25
+ total: 0,
26
+ percentage: 100
27
+ };
28
+ }
29
+ const documented = declarations.filter((d) => d.level === "documented").length;
30
+ const partial = declarations.filter((d) => d.level === "partial").length;
31
+ const undocumented = declarations.filter((d) => d.level === "undocumented").length;
32
+ const score = documented + partial * 0.5;
33
+ const percentage = Math.round(score / total * 100);
34
+ return { documented, partial, undocumented, total, percentage };
35
+ }
36
+ function asRecord(value) {
37
+ return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
38
+ }
39
+ function readJsonFile(filePath) {
40
+ try {
41
+ return JSON.parse(readFileSync(filePath, "utf-8"));
42
+ } catch {
43
+ return;
44
+ }
45
+ }
46
+ function readEntrypointsFromTsdocObject(value) {
47
+ const tsdoc = asRecord(value);
48
+ const entrypoints = tsdoc?.["entrypoints"];
49
+ if (!Array.isArray(entrypoints)) {
50
+ return;
51
+ }
52
+ const normalized = entrypoints.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
53
+ return normalized.length > 0 ? normalized : undefined;
54
+ }
55
+ function resolveConfiguredEntrypoints(cwd) {
56
+ const configPath = join(cwd, ".outfitter", "config.json");
57
+ if (existsSync(configPath)) {
58
+ const parsed = readJsonFile(configPath);
59
+ if (parsed) {
60
+ const fromRoot = readEntrypointsFromTsdocObject(parsed["tsdoc"]);
61
+ if (fromRoot) {
62
+ return {
63
+ entrypoints: fromRoot,
64
+ source: ".outfitter/config.json#tsdoc.entrypoints"
65
+ };
66
+ }
67
+ const fromOutfitter = readEntrypointsFromTsdocObject(asRecord(parsed["outfitter"])?.["tsdoc"]);
68
+ if (fromOutfitter) {
69
+ return {
70
+ entrypoints: fromOutfitter,
71
+ source: ".outfitter/config.json#outfitter.tsdoc.entrypoints"
72
+ };
73
+ }
74
+ }
75
+ }
76
+ const packageJsonPath = join(cwd, "package.json");
77
+ if (!existsSync(packageJsonPath)) {
78
+ return null;
79
+ }
80
+ const parsedPackageJson = readJsonFile(packageJsonPath);
81
+ const fromPackageJson = readEntrypointsFromTsdocObject(asRecord(parsedPackageJson?.["outfitter"])?.["tsdoc"]);
82
+ if (!fromPackageJson) {
83
+ return null;
84
+ }
85
+ return {
86
+ entrypoints: fromPackageJson,
87
+ source: "package.json#outfitter.tsdoc.entrypoints"
88
+ };
89
+ }
90
+ function derivePackagePathFromEntrypoint(match) {
91
+ const normalized = match.replaceAll("\\", "/");
92
+ if (normalized === "src/index.ts") {
93
+ return ".";
94
+ }
95
+ if (normalized.endsWith("/src/index.ts")) {
96
+ return normalized.slice(0, -"/src/index.ts".length);
97
+ }
98
+ const srcSegment = normalized.lastIndexOf("/src/");
99
+ if (srcSegment >= 0) {
100
+ return srcSegment === 0 ? "." : normalized.slice(0, srcSegment);
101
+ }
102
+ const separator = normalized.lastIndexOf("/");
103
+ return separator > 0 ? normalized.slice(0, separator) : ".";
104
+ }
105
+ function discoverPathsFromEntrypoints(cwd, entrypoints) {
106
+ const paths = new Set;
107
+ for (const pattern of entrypoints) {
108
+ const glob = new Bun.Glob(pattern);
109
+ for (const match of glob.scanSync({ cwd, dot: false })) {
110
+ paths.add(derivePackagePathFromEntrypoint(match));
111
+ }
112
+ }
113
+ return [...paths].toSorted();
114
+ }
115
+ function formatDiscoveryMessage(entrypoints, source) {
116
+ const patterns = entrypoints.join(", ");
117
+ return source ? `${patterns} (from ${source})` : patterns;
118
+ }
119
+ function recalculateCounts(pkg, declarations) {
120
+ const coverage = calculateCoverage(declarations);
121
+ return {
122
+ ...pkg,
123
+ declarations,
124
+ ...coverage
125
+ };
126
+ }
127
+ function filterResult(result, options) {
128
+ let packages = [...result.packages];
129
+ if (options.packageNames.length > 0) {
130
+ const names = new Set(options.packageNames);
131
+ packages = packages.filter((pkg) => names.has(pkg.name));
132
+ }
133
+ if (options.level) {
134
+ packages = packages.map((pkg) => {
135
+ const declarations = pkg.declarations.filter((d) => d.level === options.level);
136
+ return recalculateCounts(pkg, declarations);
137
+ });
138
+ }
139
+ const summary = calculateCoverage(packages.flatMap((pkg) => pkg.declarations));
140
+ const ok = options.strict ? summary.percentage >= options.minCoverage : true;
141
+ return {
142
+ ok,
143
+ packages,
144
+ summary
145
+ };
146
+ }
147
+ function summarizeResult(result) {
148
+ return {
149
+ ok: result.ok,
150
+ packages: result.packages.map((pkg) => ({
151
+ ...pkg,
152
+ declarations: []
153
+ })),
154
+ summary: result.summary
155
+ };
156
+ }
157
+ function emitJsonlLines(result, summary) {
158
+ const lines = [];
159
+ lines.push({ type: "meta", version: "1.0.0", ok: result.ok });
160
+ lines.push({ type: "summary", ...result.summary });
161
+ const sortedPackages = [...result.packages].toSorted((a, b) => a.name.localeCompare(b.name));
162
+ for (const pkg of sortedPackages) {
163
+ lines.push({
164
+ type: "package",
165
+ name: pkg.name,
166
+ percentage: pkg.percentage,
167
+ documented: pkg.documented,
168
+ partial: pkg.partial,
169
+ undocumented: pkg.undocumented,
170
+ total: pkg.total
171
+ });
172
+ }
173
+ if (!summary) {
174
+ for (const pkg of sortedPackages) {
175
+ for (const decl of pkg.declarations) {
176
+ lines.push({
177
+ type: "declaration",
178
+ package: pkg.name,
179
+ name: decl.name,
180
+ kind: decl.kind,
181
+ level: decl.level,
182
+ file: relative(pkg.path, decl.file),
183
+ line: decl.line
184
+ });
185
+ }
186
+ }
187
+ }
188
+ return lines;
189
+ }
190
+ function normalizeJsonlRecord(text) {
191
+ try {
192
+ return JSON.stringify(JSON.parse(text));
193
+ } catch {
194
+ return JSON.stringify(text);
195
+ }
196
+ }
197
+ var toolingCheckTsdocModule;
198
+ function resolveToolingEntrypoint() {
199
+ const packageJsonPath = require2.resolve("@outfitter/tooling/package.json");
200
+ const packageRoot = dirname(packageJsonPath);
201
+ const srcEntrypoint = join(packageRoot, "src", "index.ts");
202
+ if (existsSync(srcEntrypoint)) {
203
+ return srcEntrypoint;
204
+ }
205
+ const distEntrypoint = join(packageRoot, "dist", "index.js");
206
+ if (existsSync(distEntrypoint)) {
207
+ return distEntrypoint;
208
+ }
209
+ throw new Error("Unable to resolve @outfitter/tooling entrypoint (expected src/index.ts or dist/index.js).");
210
+ }
211
+ function loadToolingCheckTsdocModule() {
212
+ if (!toolingCheckTsdocModule) {
213
+ toolingCheckTsdocModule = import(pathToFileURL(resolveToolingEntrypoint()).href);
214
+ }
215
+ return toolingCheckTsdocModule;
216
+ }
217
+ async function runCheckTsdoc(input) {
218
+ try {
219
+ const tooling = await loadToolingCheckTsdocModule();
220
+ const configuredEntrypoints = resolveConfiguredEntrypoints(input.cwd);
221
+ const configuredPaths = configuredEntrypoints ? discoverPathsFromEntrypoints(input.cwd, configuredEntrypoints.entrypoints) : [];
222
+ if (configuredEntrypoints && configuredPaths.length === 0) {
223
+ return Result.err(ValidationError.fromMessage(`No packages found. Searched ${formatDiscoveryMessage(configuredEntrypoints.entrypoints, configuredEntrypoints.source)}.`, { cwd: input.cwd }));
224
+ }
225
+ const rawResult = tooling.analyzeCheckTsdoc({
226
+ strict: input.strict,
227
+ minCoverage: input.minCoverage,
228
+ cwd: input.cwd,
229
+ ...configuredEntrypoints ? { paths: configuredPaths } : {}
230
+ });
231
+ if (!rawResult) {
232
+ const discoveryPatterns = configuredEntrypoints ? configuredEntrypoints.entrypoints : DEFAULT_TSDOC_DISCOVERY_PATTERNS;
233
+ const discoverySource = configuredEntrypoints?.source;
234
+ return Result.err(ValidationError.fromMessage(`No packages found. Searched ${formatDiscoveryMessage(discoveryPatterns, discoverySource)}. Use --package <path> to specify explicitly.`, { cwd: input.cwd }));
235
+ }
236
+ const hasFilters = input.level !== undefined || input.packages.length > 0;
237
+ const filteredResult = hasFilters ? filterResult(rawResult, {
238
+ level: input.level,
239
+ packageNames: input.packages,
240
+ strict: input.strict,
241
+ minCoverage: input.minCoverage
242
+ }) : rawResult;
243
+ const outputData = input.summary ? summarizeResult(filteredResult) : filteredResult;
244
+ if (input.emitOutput !== false) {
245
+ if (input.outputMode === "jsonl") {
246
+ const lines = emitJsonlLines(filteredResult, input.summary);
247
+ if (input.jq) {
248
+ for (const line of lines) {
249
+ const filtered = await applyJq(line, input.jq, { compact: true });
250
+ for (const rawLine of filtered.split(/\r?\n/)) {
251
+ const trimmed = rawLine.trim();
252
+ if (!trimmed) {
253
+ continue;
254
+ }
255
+ process.stdout.write(`${normalizeJsonlRecord(trimmed)}
256
+ `);
257
+ }
258
+ }
259
+ } else {
260
+ for (const line of lines) {
261
+ process.stdout.write(`${JSON.stringify(line)}
262
+ `);
263
+ }
264
+ }
265
+ } else if (input.jq) {
266
+ const filtered = await applyJq(outputData, input.jq);
267
+ process.stdout.write(filtered);
268
+ } else if (input.outputMode === "json") {
269
+ process.stdout.write(`${JSON.stringify(outputData, null, 2)}
270
+ `);
271
+ } else {
272
+ tooling.printCheckTsdocHuman(outputData, {
273
+ strict: input.strict,
274
+ minCoverage: input.minCoverage
275
+ });
276
+ }
277
+ }
278
+ return Result.ok(outputData);
279
+ } catch (error) {
280
+ const message = error instanceof Error ? error.message : "Failed to run check-tsdoc";
281
+ return Result.err(new Error(message));
282
+ }
283
+ }
284
+
285
+ export { runCheckTsdoc };
@@ -0,0 +1,42 @@
1
+ import { MigrationFrontmatter } from "./outfitter-y37yfehn.js";
2
+ /** A migration doc with parsed frontmatter and body content. */
3
+ interface MigrationDocWithMetadata {
4
+ readonly body: string;
5
+ readonly frontmatter: MigrationFrontmatter;
6
+ readonly version: string;
7
+ }
8
+ /**
9
+ * Find migration docs directory, checking known locations.
10
+ *
11
+ * Searches:
12
+ * 1. Relative to the target cwd
13
+ * 2. Walking up parent directories from cwd (monorepo root detection)
14
+ * 3. Relative to the outfitter binary itself (development mode)
15
+ */
16
+ declare function findMigrationDocsDir(cwd: string, binaryDir?: string): string | null;
17
+ /**
18
+ * Read all migration docs for a package between two versions.
19
+ *
20
+ * Scans the migrations directory for docs matching the package name,
21
+ * filters to versions greater than `fromVersion` and at most `toVersion`,
22
+ * and returns their contents sorted by version ascending.
23
+ */
24
+ declare function readMigrationDocs(migrationsDir: string, shortName: string, fromVersion: string, toVersion: string): string[];
25
+ /**
26
+ * Read the `breaking` flag for an exact migration doc version, if present.
27
+ *
28
+ * Returns:
29
+ * - `true` or `false` when the frontmatter contains `breaking: ...`
30
+ * - `undefined` when the doc is missing, unreadable, or has no valid flag
31
+ */
32
+ declare function readMigrationBreakingFlag(migrationsDir: string, shortName: string, version: string): boolean | undefined;
33
+ /**
34
+ * Read all migration docs for a package between two versions,
35
+ * returning parsed frontmatter alongside the body content.
36
+ *
37
+ * Like `readMigrationDocs` but returns structured metadata instead of
38
+ * plain strings. Used by the codemod infrastructure to discover
39
+ * machine-actionable changes.
40
+ */
41
+ declare function readMigrationDocsWithMetadata(migrationsDir: string, shortName: string, fromVersion: string, toVersion: string): MigrationDocWithMetadata[];
42
+ export { MigrationDocWithMetadata, findMigrationDocsDir, readMigrationDocs, readMigrationBreakingFlag, readMigrationDocsWithMetadata };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Unique identifier for a scaffold target.
3
+ */
4
+ type TargetId = "minimal" | "cli" | "mcp" | "daemon" | "library" | "full-stack" | "api" | "worker" | "web";
5
+ /**
6
+ * Whether the target produces a runnable application or a library package.
7
+ */
8
+ type TargetCategory = "runnable" | "library";
9
+ /**
10
+ * Whether the target has a working template or is a planned placeholder.
11
+ */
12
+ type TargetStatus = "ready" | "stub";
13
+ /**
14
+ * Whether a target can be used with init, scaffold, or both.
15
+ */
16
+ type TargetScope = "init-only" | "scaffold-only" | "both";
17
+ /**
18
+ * Complete definition for a scaffold target.
19
+ */
20
+ interface TargetDefinition {
21
+ readonly category: TargetCategory;
22
+ readonly defaultBlocks: readonly string[];
23
+ readonly description: string;
24
+ readonly id: TargetId;
25
+ readonly placement: "apps" | "packages";
26
+ readonly presetDir: string;
27
+ readonly scope: TargetScope;
28
+ readonly status: TargetStatus;
29
+ }
30
+ export { TargetId, TargetCategory, TargetStatus, TargetScope, TargetDefinition };
@@ -0,0 +1,19 @@
1
+ import { TargetId } from "./outfitter-58rn1sj1.js";
2
+ import { Result } from "@outfitter/contracts";
3
+ /** Subset of target IDs that are valid presets for `outfitter init`. */
4
+ type InitPresetId = Extract<TargetId, "minimal" | "cli" | "mcp" | "daemon" | "library" | "full-stack">;
5
+ /**
6
+ * Parses a comma-separated `--with` flag value into an array of block names.
7
+ * @returns The parsed block names, or `undefined` if the flag is empty/absent.
8
+ */
9
+ declare function parseBlocks(withFlag: string | undefined): readonly string[] | undefined;
10
+ /** Returns `true` if the preset produces a project with a binary entry point. */
11
+ declare function isBinaryPreset(preset: InitPresetId): boolean;
12
+ /** Type guard that narrows a string to {@link InitPresetId}. */
13
+ declare function isValidInitPreset(value: string): value is InitPresetId;
14
+ /**
15
+ * Validates and resolves a `--preset` flag value against the available preset list.
16
+ * @returns The validated preset ID, `undefined` if no flag was provided, or an error for unknown presets.
17
+ */
18
+ declare function resolvePresetFromFlags(presetFromFlag: string | undefined, availablePresetIds: readonly string[]): Result<InitPresetId | undefined, string>;
19
+ export { InitPresetId, parseBlocks, isBinaryPreset, isValidInitPreset, resolvePresetFromFlags };