@cimplify/cli 0.2.7 → 0.3.0

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 (229) hide show
  1. package/dist/{add-7N2EZR6W.mjs → add-ZJNXWN2B.mjs} +10 -10
  2. package/dist/assets-DMK2QOPD.mjs +208 -0
  3. package/dist/chunk-5IAYN7AJ.mjs +259 -0
  4. package/dist/{chunk-4SBJVRGM.mjs → chunk-C4M3DXKC.mjs} +3 -1
  5. package/dist/{chunk-NC3GKHDD.mjs → chunk-D7WMSGKK.mjs} +1 -1
  6. package/dist/{chunk-NZ4RG62Z.mjs → chunk-I3XQSSOT.mjs} +4 -1
  7. package/dist/{chunk-JJYWETGA.mjs → chunk-LS2VTSMQ.mjs} +8 -2
  8. package/dist/{chunk-G2P6KHM5.mjs → chunk-MHK4WVNF.mjs} +2392 -596
  9. package/dist/{chunk-JOUXICGV.mjs → chunk-MOZQODQS.mjs} +1 -1
  10. package/dist/{chunk-KPGRCXQY.mjs → chunk-QGBXGDA5.mjs} +5 -5
  11. package/dist/chunk-RRY3NEZZ.mjs +79 -0
  12. package/dist/{chunk-L6474RPL.mjs → chunk-RZQTHTXX.mjs} +1 -1
  13. package/dist/{chunk-4YSOZ6LY.mjs → chunk-YI7UMMM7.mjs} +1 -1
  14. package/dist/{chunk-52GZ5B77.mjs → chunk-YQVMG62Z.mjs} +3 -3
  15. package/dist/{deploy-6KVOROT3.mjs → deploy-UKOOPJAE.mjs} +8 -82
  16. package/dist/{dev-AQP6TMYK.mjs → dev-FD4PM3UD.mjs} +5 -5
  17. package/dist/dispatcher.mjs +34 -22
  18. package/dist/doctor-5LBLYT7M.mjs +314 -0
  19. package/dist/{domains-2ZQ7AG27.mjs → domains-JQMV6GAP.mjs} +5 -5
  20. package/dist/{env-FDBPGU3W.mjs → env-EVMYQUIK.mjs} +6 -6
  21. package/dist/explain-3KBMWL6M.mjs +223 -0
  22. package/dist/introspect-PFBI3JHO.mjs +8 -0
  23. package/dist/{link-P4K2HRXY.mjs → link-X3E4UZBF.mjs} +4 -4
  24. package/dist/{list-FL6JZ6A4.mjs → list-TE54SJIB.mjs} +3 -3
  25. package/dist/{login-RSKGT6GU.mjs → login-WSAW4BEA.mjs} +4 -4
  26. package/dist/{logout-ZFZLSJ32.mjs → logout-DJDINVDF.mjs} +2 -2
  27. package/dist/{logs-E2AGTDCF.mjs → logs-KUKGEXR2.mjs} +4 -4
  28. package/dist/{projects-5CJOZ3MT.mjs → projects-364HGWHO.mjs} +13 -11
  29. package/dist/repo-26N2CHF6.mjs +8 -0
  30. package/dist/{rollback-36O4NOEL.mjs → rollback-5YALPQXL.mjs} +5 -5
  31. package/dist/{status-6AT4HF63.mjs → status-W4HW3CX3.mjs} +4 -4
  32. package/dist/{unlink-5ABCT7B6.mjs → unlink-HIIW57OO.mjs} +2 -2
  33. package/dist/{update-LFTHO6Q5.mjs → update-5MRKRVZC.mjs} +7 -7
  34. package/dist/{whoami-DIJZYZIN.mjs → whoami-LACWBSNL.mjs} +3 -3
  35. package/package.json +3 -3
  36. package/templates/storefront-auto/.claude/skills/cimplify-storefront/SKILL.md +145 -0
  37. package/templates/storefront-auto/.cursor/rules/cimplify-storefront.mdc +25 -0
  38. package/templates/storefront-auto/.env.example +22 -0
  39. package/templates/storefront-auto/AGENTS.md +95 -0
  40. package/templates/storefront-auto/CLAUDE.md +22 -0
  41. package/templates/storefront-auto/README.md +48 -0
  42. package/templates/storefront-auto/__tests__/brand.test.ts +4 -0
  43. package/templates/storefront-auto/__tests__/cart-flow.test.ts +4 -0
  44. package/templates/storefront-auto/__tests__/contract.test.ts +4 -0
  45. package/templates/storefront-auto/app/.well-known/ucp/route.ts +65 -0
  46. package/templates/storefront-auto/app/about/page.tsx +41 -0
  47. package/templates/storefront-auto/app/accessibility/page.tsx +11 -0
  48. package/templates/storefront-auto/app/account/addresses/page.tsx +21 -0
  49. package/templates/storefront-auto/app/account/orders/page.tsx +21 -0
  50. package/templates/storefront-auto/app/account/page.tsx +22 -0
  51. package/templates/storefront-auto/app/account/settings/page.tsx +21 -0
  52. package/templates/storefront-auto/app/cart/page.tsx +9 -0
  53. package/templates/storefront-auto/app/categories/[slug]/listing-client.tsx +19 -0
  54. package/templates/storefront-auto/app/categories/[slug]/page.tsx +130 -0
  55. package/templates/storefront-auto/app/checkout/page.tsx +17 -0
  56. package/templates/storefront-auto/app/collections/[slug]/listing-client.tsx +20 -0
  57. package/templates/storefront-auto/app/collections/[slug]/page.tsx +130 -0
  58. package/templates/storefront-auto/app/contact/contact-form.tsx +109 -0
  59. package/templates/storefront-auto/app/contact/page.tsx +54 -0
  60. package/templates/storefront-auto/app/error.tsx +61 -0
  61. package/templates/storefront-auto/app/faq/page.tsx +46 -0
  62. package/templates/storefront-auto/app/globals.css +47 -0
  63. package/templates/storefront-auto/app/layout.tsx +77 -0
  64. package/templates/storefront-auto/app/llms.txt/route.ts +94 -0
  65. package/templates/storefront-auto/app/login/page.tsx +17 -0
  66. package/templates/storefront-auto/app/not-found.tsx +39 -0
  67. package/templates/storefront-auto/app/opensearch.xml/route.ts +37 -0
  68. package/templates/storefront-auto/app/orders/[id]/page.tsx +24 -0
  69. package/templates/storefront-auto/app/page.tsx +94 -0
  70. package/templates/storefront-auto/app/privacy/page.tsx +44 -0
  71. package/templates/storefront-auto/app/products/[slug]/page.tsx +165 -0
  72. package/templates/storefront-auto/app/products/[slug]/product-detail.tsx +70 -0
  73. package/templates/storefront-auto/app/returns/page.tsx +11 -0
  74. package/templates/storefront-auto/app/robots.ts +18 -0
  75. package/templates/storefront-auto/app/search/page.tsx +38 -0
  76. package/templates/storefront-auto/app/search/search-client.tsx +7 -0
  77. package/templates/storefront-auto/app/shipping/page.tsx +16 -0
  78. package/templates/storefront-auto/app/shop/page.tsx +63 -0
  79. package/templates/storefront-auto/app/shop/shop-client.tsx +32 -0
  80. package/templates/storefront-auto/app/signup/page.tsx +17 -0
  81. package/templates/storefront-auto/app/sitemap-page/page.tsx +167 -0
  82. package/templates/storefront-auto/app/sitemap.ts +59 -0
  83. package/templates/storefront-auto/app/terms/page.tsx +44 -0
  84. package/templates/storefront-auto/app/track-order/page.tsx +24 -0
  85. package/templates/storefront-auto/app/track-order/track-order-form.tsx +69 -0
  86. package/templates/storefront-auto/components/account-iframe.tsx +13 -0
  87. package/templates/storefront-auto/components/auto-hero.tsx +85 -0
  88. package/templates/storefront-auto/components/brand-marquee.tsx +27 -0
  89. package/templates/storefront-auto/components/cart-drawer.tsx +14 -0
  90. package/templates/storefront-auto/components/cart-pill.tsx +36 -0
  91. package/templates/storefront-auto/components/category-grid.tsx +28 -0
  92. package/templates/storefront-auto/components/category-tiles.tsx +104 -0
  93. package/templates/storefront-auto/components/collection-strip.tsx +45 -0
  94. package/templates/storefront-auto/components/feature-hero.tsx +84 -0
  95. package/templates/storefront-auto/components/fitment-finder.tsx +184 -0
  96. package/templates/storefront-auto/components/footer.tsx +153 -0
  97. package/templates/storefront-auto/components/header.tsx +45 -0
  98. package/templates/storefront-auto/components/hero.tsx +28 -0
  99. package/templates/storefront-auto/components/nav-link.tsx +20 -0
  100. package/templates/storefront-auto/components/newsletter.tsx +50 -0
  101. package/templates/storefront-auto/components/policy-page.tsx +49 -0
  102. package/templates/storefront-auto/components/promo-banner.tsx +41 -0
  103. package/templates/storefront-auto/components/providers.tsx +35 -0
  104. package/templates/storefront-auto/components/section-heading.tsx +37 -0
  105. package/templates/storefront-auto/components/service-brief.tsx +65 -0
  106. package/templates/storefront-auto/components/store-product-card.tsx +88 -0
  107. package/templates/storefront-auto/components/trade-in-cta.tsx +54 -0
  108. package/templates/storefront-auto/components/trust-bar.tsx +66 -0
  109. package/templates/storefront-auto/lib/brand.ts +744 -0
  110. package/templates/storefront-auto/lib/cart.ts +12 -0
  111. package/templates/storefront-auto/lib/cimplify-loader.ts +19 -0
  112. package/templates/storefront-auto/next.config.ts +45 -0
  113. package/templates/storefront-auto/package.json +35 -0
  114. package/templates/storefront-auto/postcss.config.mjs +7 -0
  115. package/templates/storefront-auto/tsconfig.json +23 -0
  116. package/templates/storefront-auto/vitest.config.ts +9 -0
  117. package/templates/storefront-bakery/.env.example +2 -2
  118. package/templates/storefront-bakery/README.md +1 -1
  119. package/templates/storefront-bakery/lib/cimplify-loader.ts +19 -0
  120. package/templates/storefront-bakery/next.config.ts +3 -0
  121. package/templates/storefront-bakery/package.json +1 -1
  122. package/templates/storefront-fashion/.env.example +2 -2
  123. package/templates/storefront-fashion/README.md +1 -1
  124. package/templates/storefront-fashion/lib/cimplify-loader.ts +19 -0
  125. package/templates/storefront-fashion/next.config.ts +3 -0
  126. package/templates/storefront-fashion/package.json +1 -1
  127. package/templates/storefront-grocery/.env.example +2 -2
  128. package/templates/storefront-grocery/README.md +1 -1
  129. package/templates/storefront-grocery/lib/cimplify-loader.ts +19 -0
  130. package/templates/storefront-grocery/next.config.ts +3 -0
  131. package/templates/storefront-grocery/package.json +1 -1
  132. package/templates/storefront-pharmacy/.claude/skills/cimplify-storefront/SKILL.md +145 -0
  133. package/templates/storefront-pharmacy/.cursor/rules/cimplify-storefront.mdc +25 -0
  134. package/templates/storefront-pharmacy/.env.example +22 -0
  135. package/templates/storefront-pharmacy/AGENTS.md +118 -0
  136. package/templates/storefront-pharmacy/CLAUDE.md +22 -0
  137. package/templates/storefront-pharmacy/README.md +87 -0
  138. package/templates/storefront-pharmacy/__tests__/brand.test.ts +4 -0
  139. package/templates/storefront-pharmacy/__tests__/cart-flow.test.ts +4 -0
  140. package/templates/storefront-pharmacy/__tests__/contract.test.ts +4 -0
  141. package/templates/storefront-pharmacy/app/.well-known/ucp/route.ts +65 -0
  142. package/templates/storefront-pharmacy/app/about/page.tsx +41 -0
  143. package/templates/storefront-pharmacy/app/accessibility/page.tsx +11 -0
  144. package/templates/storefront-pharmacy/app/account/addresses/page.tsx +21 -0
  145. package/templates/storefront-pharmacy/app/account/orders/page.tsx +21 -0
  146. package/templates/storefront-pharmacy/app/account/page.tsx +22 -0
  147. package/templates/storefront-pharmacy/app/account/settings/page.tsx +21 -0
  148. package/templates/storefront-pharmacy/app/cart/page.tsx +9 -0
  149. package/templates/storefront-pharmacy/app/categories/[slug]/listing-client.tsx +19 -0
  150. package/templates/storefront-pharmacy/app/categories/[slug]/page.tsx +130 -0
  151. package/templates/storefront-pharmacy/app/checkout/page.tsx +17 -0
  152. package/templates/storefront-pharmacy/app/collections/[slug]/listing-client.tsx +20 -0
  153. package/templates/storefront-pharmacy/app/collections/[slug]/page.tsx +130 -0
  154. package/templates/storefront-pharmacy/app/contact/contact-form.tsx +109 -0
  155. package/templates/storefront-pharmacy/app/contact/page.tsx +54 -0
  156. package/templates/storefront-pharmacy/app/error.tsx +61 -0
  157. package/templates/storefront-pharmacy/app/faq/page.tsx +46 -0
  158. package/templates/storefront-pharmacy/app/globals.css +47 -0
  159. package/templates/storefront-pharmacy/app/layout.tsx +77 -0
  160. package/templates/storefront-pharmacy/app/llms.txt/route.ts +94 -0
  161. package/templates/storefront-pharmacy/app/login/page.tsx +17 -0
  162. package/templates/storefront-pharmacy/app/not-found.tsx +39 -0
  163. package/templates/storefront-pharmacy/app/opensearch.xml/route.ts +37 -0
  164. package/templates/storefront-pharmacy/app/orders/[id]/page.tsx +24 -0
  165. package/templates/storefront-pharmacy/app/page.tsx +78 -0
  166. package/templates/storefront-pharmacy/app/privacy/page.tsx +44 -0
  167. package/templates/storefront-pharmacy/app/products/[slug]/page.tsx +165 -0
  168. package/templates/storefront-pharmacy/app/products/[slug]/product-detail.tsx +70 -0
  169. package/templates/storefront-pharmacy/app/returns/page.tsx +11 -0
  170. package/templates/storefront-pharmacy/app/robots.ts +18 -0
  171. package/templates/storefront-pharmacy/app/search/page.tsx +38 -0
  172. package/templates/storefront-pharmacy/app/search/search-client.tsx +7 -0
  173. package/templates/storefront-pharmacy/app/shipping/page.tsx +16 -0
  174. package/templates/storefront-pharmacy/app/shop/page.tsx +63 -0
  175. package/templates/storefront-pharmacy/app/shop/shop-client.tsx +32 -0
  176. package/templates/storefront-pharmacy/app/signup/page.tsx +17 -0
  177. package/templates/storefront-pharmacy/app/sitemap-page/page.tsx +167 -0
  178. package/templates/storefront-pharmacy/app/sitemap.ts +59 -0
  179. package/templates/storefront-pharmacy/app/terms/page.tsx +44 -0
  180. package/templates/storefront-pharmacy/app/track-order/page.tsx +24 -0
  181. package/templates/storefront-pharmacy/app/track-order/track-order-form.tsx +69 -0
  182. package/templates/storefront-pharmacy/components/account-iframe.tsx +13 -0
  183. package/templates/storefront-pharmacy/components/brand-marquee.tsx +27 -0
  184. package/templates/storefront-pharmacy/components/cart-drawer.tsx +14 -0
  185. package/templates/storefront-pharmacy/components/cart-pill.tsx +36 -0
  186. package/templates/storefront-pharmacy/components/category-grid.tsx +28 -0
  187. package/templates/storefront-pharmacy/components/category-tiles.tsx +104 -0
  188. package/templates/storefront-pharmacy/components/collection-strip.tsx +45 -0
  189. package/templates/storefront-pharmacy/components/feature-hero.tsx +84 -0
  190. package/templates/storefront-pharmacy/components/footer.tsx +153 -0
  191. package/templates/storefront-pharmacy/components/header.tsx +45 -0
  192. package/templates/storefront-pharmacy/components/health-brief.tsx +65 -0
  193. package/templates/storefront-pharmacy/components/hero.tsx +28 -0
  194. package/templates/storefront-pharmacy/components/nav-link.tsx +20 -0
  195. package/templates/storefront-pharmacy/components/newsletter.tsx +50 -0
  196. package/templates/storefront-pharmacy/components/pharmacy-hero.tsx +95 -0
  197. package/templates/storefront-pharmacy/components/policy-page.tsx +49 -0
  198. package/templates/storefront-pharmacy/components/promo-banner.tsx +41 -0
  199. package/templates/storefront-pharmacy/components/providers.tsx +35 -0
  200. package/templates/storefront-pharmacy/components/section-heading.tsx +37 -0
  201. package/templates/storefront-pharmacy/components/store-product-card.tsx +88 -0
  202. package/templates/storefront-pharmacy/components/symptom-finder.tsx +108 -0
  203. package/templates/storefront-pharmacy/components/trade-in-cta.tsx +54 -0
  204. package/templates/storefront-pharmacy/components/trust-bar.tsx +66 -0
  205. package/templates/storefront-pharmacy/components/urgent-ctas.tsx +117 -0
  206. package/templates/storefront-pharmacy/lib/brand.ts +790 -0
  207. package/templates/storefront-pharmacy/lib/cart.ts +12 -0
  208. package/templates/storefront-pharmacy/lib/cimplify-loader.ts +19 -0
  209. package/templates/storefront-pharmacy/next.config.ts +45 -0
  210. package/templates/storefront-pharmacy/package.json +35 -0
  211. package/templates/storefront-pharmacy/postcss.config.mjs +7 -0
  212. package/templates/storefront-pharmacy/tsconfig.json +23 -0
  213. package/templates/storefront-pharmacy/vitest.config.ts +9 -0
  214. package/templates/storefront-restaurant/.env.example +2 -2
  215. package/templates/storefront-restaurant/README.md +1 -1
  216. package/templates/storefront-restaurant/lib/cimplify-loader.ts +19 -0
  217. package/templates/storefront-restaurant/next.config.ts +3 -0
  218. package/templates/storefront-restaurant/package.json +1 -1
  219. package/templates/storefront-retail/.env.example +2 -2
  220. package/templates/storefront-retail/README.md +1 -1
  221. package/templates/storefront-retail/lib/cimplify-loader.ts +19 -0
  222. package/templates/storefront-retail/next.config.ts +3 -0
  223. package/templates/storefront-retail/package.json +1 -1
  224. package/templates/storefront-services/.env.example +2 -2
  225. package/templates/storefront-services/README.md +1 -1
  226. package/templates/storefront-services/lib/cimplify-loader.ts +19 -0
  227. package/templates/storefront-services/next.config.ts +3 -0
  228. package/templates/storefront-services/package.json +1 -1
  229. package/dist/repo-E6SBKVDG.mjs +0 -8
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { TERMINAL_DEPLOYMENT_STATUSES, DEPLOYMENT_STATUS } from './chunk-MXYUAJEW.mjs';
3
- import { dim, CliError, CLI_ERROR_CODE, failure, success, isJsonMode } from './chunk-NZ4RG62Z.mjs';
3
+ import { dim, CliError, CLI_ERROR_CODE, failure, success, isJsonMode } from './chunk-I3XQSSOT.mjs';
4
4
 
5
5
  // src/progress.ts
6
6
  var POLL_INTERVAL_MS = 1e3;
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { promptYesNo } from './chunk-L6474RPL.mjs';
2
+ import { promptYesNo } from './chunk-RZQTHTXX.mjs';
3
3
  import { TOKEN_PURPOSE, REPO_PROVIDER, REPO_PROVIDER_VALUES } from './chunk-MXYUAJEW.mjs';
4
- import { parseArgs, flagString, flagBool } from './chunk-4SBJVRGM.mjs';
5
- import { ApiClient } from './chunk-NC3GKHDD.mjs';
6
- import { readAuth, readProjectLink } from './chunk-JJYWETGA.mjs';
7
- import { CliError, CLI_ERROR_CODE, isJsonMode, result, dim, success, info, bold } from './chunk-NZ4RG62Z.mjs';
4
+ import { parseArgs, flagString, flagBool } from './chunk-C4M3DXKC.mjs';
5
+ import { ApiClient } from './chunk-D7WMSGKK.mjs';
6
+ import { readAuth, readProjectLink } from './chunk-LS2VTSMQ.mjs';
7
+ import { CliError, CLI_ERROR_CODE, isJsonMode, result, dim, success, info, bold } from './chunk-I3XQSSOT.mjs';
8
8
 
9
9
  // src/commands/repo.ts
10
10
  var SUB_PROVISION = "provision";
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+ import { CliError, CLI_ERROR_CODE } from './chunk-I3XQSSOT.mjs';
3
+ import { spawn } from 'child_process';
4
+
5
+ var GIT_BINARY = "git";
6
+ var ENCODING_UTF8 = "utf8";
7
+ var REMOTE_DEFAULT = "origin";
8
+ var ARGS_STATUS_PORCELAIN = ["status", "--porcelain=v1"];
9
+ var ARGS_REV_PARSE_HEAD = ["rev-parse", "HEAD"];
10
+ var ARGS_REV_PARSE_ABBREV_REF = ["rev-parse", "--abbrev-ref", "HEAD"];
11
+ var ARGS_REV_PARSE_SHOW_TOPLEVEL = ["rev-parse", "--show-toplevel"];
12
+ var ARGS_REMOTE_GET_URL = ["remote", "get-url"];
13
+ var ARGS_PUSH = ["push"];
14
+ async function runGit(args, cwd) {
15
+ return new Promise((resolve, reject) => {
16
+ const child = spawn(GIT_BINARY, args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
17
+ const stdoutChunks = [];
18
+ const stderrChunks = [];
19
+ child.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
20
+ child.stderr.on("data", (chunk) => stderrChunks.push(chunk));
21
+ child.on("error", (err) => {
22
+ reject(new CliError(CLI_ERROR_CODE.GIT_ERROR, `git not found: ${err.message}`));
23
+ });
24
+ child.on("close", (code) => {
25
+ resolve({
26
+ code: code ?? -1,
27
+ stdout: Buffer.concat(stdoutChunks).toString(ENCODING_UTF8),
28
+ stderr: Buffer.concat(stderrChunks).toString(ENCODING_UTF8)
29
+ });
30
+ });
31
+ });
32
+ }
33
+ async function runGitOk(args, cwd) {
34
+ const { code, stdout, stderr } = await runGit(args, cwd);
35
+ if (code !== 0) {
36
+ throw new CliError(
37
+ CLI_ERROR_CODE.GIT_ERROR,
38
+ `git ${args.join(" ")} failed: ${stderr.trim() || stdout.trim() || `exit ${code}`}`
39
+ );
40
+ }
41
+ return stdout.trimEnd();
42
+ }
43
+ async function gitStatusPorcelain(cwd) {
44
+ return runGitOk(ARGS_STATUS_PORCELAIN, cwd);
45
+ }
46
+ async function gitCurrentSha(cwd) {
47
+ return runGitOk(ARGS_REV_PARSE_HEAD, cwd);
48
+ }
49
+ async function gitCurrentBranch(cwd) {
50
+ return runGitOk(ARGS_REV_PARSE_ABBREV_REF, cwd);
51
+ }
52
+ async function gitDetectRoot(cwd) {
53
+ const { code, stdout } = await runGit(ARGS_REV_PARSE_SHOW_TOPLEVEL, cwd);
54
+ if (code !== 0) return null;
55
+ return stdout.trimEnd() || null;
56
+ }
57
+ async function gitGetRemoteUrl(cwd, name = REMOTE_DEFAULT) {
58
+ const { code, stdout } = await runGit([...ARGS_REMOTE_GET_URL, name], cwd);
59
+ if (code !== 0) return null;
60
+ return stdout.trimEnd() || null;
61
+ }
62
+ async function gitPush(cwd, branch) {
63
+ const args = branch ? [...ARGS_PUSH, REMOTE_DEFAULT, branch] : [...ARGS_PUSH];
64
+ await runGitOk(args, cwd);
65
+ }
66
+ async function gitPushToUrl(cwd, url, branch) {
67
+ await runGitOk([...ARGS_PUSH, url, branch], cwd);
68
+ }
69
+ var FREESTYLE_GIT_HOST = "git.freestyle.sh";
70
+ function isFreestyleRemote(url) {
71
+ if (!url) return false;
72
+ try {
73
+ return new URL(url).hostname === FREESTYLE_GIT_HOST;
74
+ } catch {
75
+ return url.includes(FREESTYLE_GIT_HOST);
76
+ }
77
+ }
78
+
79
+ export { gitCurrentBranch, gitCurrentSha, gitDetectRoot, gitGetRemoteUrl, gitPush, gitPushToUrl, gitStatusPorcelain, isFreestyleRemote };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { isAutoYes, isInteractive, CliError, CLI_ERROR_CODE } from './chunk-NZ4RG62Z.mjs';
2
+ import { isAutoYes, isInteractive, CliError, CLI_ERROR_CODE } from './chunk-I3XQSSOT.mjs';
3
3
  import readline from 'readline';
4
4
 
5
5
  async function promptLine(question) {
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { CliError, CLI_ERROR_CODE } from './chunk-NZ4RG62Z.mjs';
2
+ import { CliError, CLI_ERROR_CODE } from './chunk-I3XQSSOT.mjs';
3
3
 
4
4
  // src/envfile.ts
5
5
  var COMMENT_CHAR = "#";
@@ -2,7 +2,7 @@
2
2
  // package.json
3
3
  var package_default = {
4
4
  name: "@cimplify/cli",
5
- version: "0.2.7",
5
+ version: "0.3.0",
6
6
  description: "Cimplify CLI \u2014 deploy, manage env vars, link projects, and scaffold storefronts",
7
7
  keywords: [
8
8
  "cimplify",
@@ -19,7 +19,7 @@ var package_default = {
19
19
  "templates"
20
20
  ],
21
21
  scripts: {
22
- "bundle-assets": "bun scripts/bundle-assets.ts",
22
+ "bundle-assets": "bun scripts/bundle-assets.ts && bun scripts/bundle-docs.ts",
23
23
  prebuild: "bun run bundle-assets",
24
24
  build: "tsup",
25
25
  "build:binary": "bun run bundle-assets && bun scripts/build-binaries.ts",
@@ -29,7 +29,7 @@ var package_default = {
29
29
  prepublishOnly: "bun scripts/sync-template-pins.ts && bun run build",
30
30
  dev: "bun run bundle-assets && tsup --watch",
31
31
  typecheck: "bun run bundle-assets && tsgo --noEmit -p tsconfig.json",
32
- clean: "rm -rf dist bin src/embedded-assets.ts",
32
+ clean: "rm -rf dist bin src/embedded-assets.ts src/embedded-docs.ts",
33
33
  "lint:ox": "oxlint --fix .",
34
34
  format: "oxfmt . --write",
35
35
  "format:check": "oxfmt . --check",
@@ -1,87 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import { pollDeployment } from './chunk-JOUXICGV.mjs';
3
- import { fetchCloneToken } from './chunk-KPGRCXQY.mjs';
4
- import { promptYesNo } from './chunk-L6474RPL.mjs';
2
+ import { pollDeployment } from './chunk-MOZQODQS.mjs';
3
+ import { gitDetectRoot, gitStatusPorcelain, gitCurrentBranch, gitCurrentSha, gitGetRemoteUrl, isFreestyleRemote, gitPushToUrl, gitPush } from './chunk-RRY3NEZZ.mjs';
4
+ import { fetchCloneToken } from './chunk-QGBXGDA5.mjs';
5
+ import { promptYesNo } from './chunk-RZQTHTXX.mjs';
5
6
  import { TOKEN_PURPOSE, ENV_SCOPE, DEPLOY_TRIGGER, DEPLOYMENT_STATUS } from './chunk-MXYUAJEW.mjs';
6
- import { parseArgs, flagBool, flagString } from './chunk-4SBJVRGM.mjs';
7
- import { ApiClient } from './chunk-NC3GKHDD.mjs';
8
- import { readAuth, readProjectLink, writeProjectState } from './chunk-JJYWETGA.mjs';
9
- import { CliError, CLI_ERROR_CODE, step, info, dim, success, result, EXIT_CODE } from './chunk-NZ4RG62Z.mjs';
10
- import { spawn } from 'child_process';
11
-
12
- var GIT_BINARY = "git";
13
- var ENCODING_UTF8 = "utf8";
14
- var REMOTE_DEFAULT = "origin";
15
- var ARGS_STATUS_PORCELAIN = ["status", "--porcelain=v1"];
16
- var ARGS_REV_PARSE_HEAD = ["rev-parse", "HEAD"];
17
- var ARGS_REV_PARSE_ABBREV_REF = ["rev-parse", "--abbrev-ref", "HEAD"];
18
- var ARGS_REV_PARSE_SHOW_TOPLEVEL = ["rev-parse", "--show-toplevel"];
19
- var ARGS_REMOTE_GET_URL = ["remote", "get-url"];
20
- var ARGS_PUSH = ["push"];
21
- async function runGit(args, cwd) {
22
- return new Promise((resolve, reject) => {
23
- const child = spawn(GIT_BINARY, args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
24
- const stdoutChunks = [];
25
- const stderrChunks = [];
26
- child.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
27
- child.stderr.on("data", (chunk) => stderrChunks.push(chunk));
28
- child.on("error", (err) => {
29
- reject(new CliError(CLI_ERROR_CODE.GIT_ERROR, `git not found: ${err.message}`));
30
- });
31
- child.on("close", (code) => {
32
- resolve({
33
- code: code ?? -1,
34
- stdout: Buffer.concat(stdoutChunks).toString(ENCODING_UTF8),
35
- stderr: Buffer.concat(stderrChunks).toString(ENCODING_UTF8)
36
- });
37
- });
38
- });
39
- }
40
- async function runGitOk(args, cwd) {
41
- const { code, stdout, stderr } = await runGit(args, cwd);
42
- if (code !== 0) {
43
- throw new CliError(
44
- CLI_ERROR_CODE.GIT_ERROR,
45
- `git ${args.join(" ")} failed: ${stderr.trim() || stdout.trim() || `exit ${code}`}`
46
- );
47
- }
48
- return stdout.trimEnd();
49
- }
50
- async function gitStatusPorcelain(cwd) {
51
- return runGitOk(ARGS_STATUS_PORCELAIN, cwd);
52
- }
53
- async function gitCurrentSha(cwd) {
54
- return runGitOk(ARGS_REV_PARSE_HEAD, cwd);
55
- }
56
- async function gitCurrentBranch(cwd) {
57
- return runGitOk(ARGS_REV_PARSE_ABBREV_REF, cwd);
58
- }
59
- async function gitDetectRoot(cwd) {
60
- const { code, stdout } = await runGit(ARGS_REV_PARSE_SHOW_TOPLEVEL, cwd);
61
- if (code !== 0) return null;
62
- return stdout.trimEnd() || null;
63
- }
64
- async function gitGetRemoteUrl(cwd, name = REMOTE_DEFAULT) {
65
- const { code, stdout } = await runGit([...ARGS_REMOTE_GET_URL, name], cwd);
66
- if (code !== 0) return null;
67
- return stdout.trimEnd() || null;
68
- }
69
- async function gitPush(cwd, branch) {
70
- const args = branch ? [...ARGS_PUSH, REMOTE_DEFAULT, branch] : [...ARGS_PUSH];
71
- await runGitOk(args, cwd);
72
- }
73
- async function gitPushToUrl(cwd, url, branch) {
74
- await runGitOk([...ARGS_PUSH, url, branch], cwd);
75
- }
76
- var FREESTYLE_GIT_HOST = "git.freestyle.sh";
77
- function isFreestyleRemote(url) {
78
- if (!url) return false;
79
- try {
80
- return new URL(url).hostname === FREESTYLE_GIT_HOST;
81
- } catch {
82
- return url.includes(FREESTYLE_GIT_HOST);
83
- }
84
- }
7
+ import { parseArgs, flagBool, flagString } from './chunk-C4M3DXKC.mjs';
8
+ import { ApiClient } from './chunk-D7WMSGKK.mjs';
9
+ import { readAuth, readProjectLink, writeProjectState } from './chunk-LS2VTSMQ.mjs';
10
+ import { CliError, CLI_ERROR_CODE, step, info, dim, success, result, EXIT_CODE } from './chunk-I3XQSSOT.mjs';
85
11
 
86
12
  // src/commands/deploy.ts
87
13
  var FLAG_PROD = "prod";
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { parseEnvFile, formatEnvFile } from './chunk-4YSOZ6LY.mjs';
2
+ import { parseEnvFile, formatEnvFile } from './chunk-YI7UMMM7.mjs';
3
3
  import { ENV_SCOPE, PUBLIC_ENV_PREFIX } from './chunk-MXYUAJEW.mjs';
4
- import { parseArgs, flagBool } from './chunk-4SBJVRGM.mjs';
5
- import { ApiClient } from './chunk-NC3GKHDD.mjs';
6
- import { readAuth, readProjectLink } from './chunk-JJYWETGA.mjs';
7
- import { info, CliError, CLI_ERROR_CODE, dim } from './chunk-NZ4RG62Z.mjs';
4
+ import { parseArgs, flagBool } from './chunk-C4M3DXKC.mjs';
5
+ import { ApiClient } from './chunk-D7WMSGKK.mjs';
6
+ import { readAuth, readProjectLink } from './chunk-LS2VTSMQ.mjs';
7
+ import { info, CliError, CLI_ERROR_CODE, dim } from './chunk-I3XQSSOT.mjs';
8
8
  import { spawn } from 'child_process';
9
9
  import { promises } from 'fs';
10
10
  import path from 'path';
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { package_default } from './chunk-52GZ5B77.mjs';
3
- import { TEMPLATES } from './chunk-G2P6KHM5.mjs';
2
+ import { TEMPLATES } from './chunk-MHK4WVNF.mjs';
3
+ import { package_default } from './chunk-YQVMG62Z.mjs';
4
4
 
5
5
  // src/dispatcher.ts
6
6
  var VERSION = package_default.version ?? "unknown";
@@ -18,6 +18,12 @@ Project:
18
18
  cimplify projects create <name> Create a Next.js project
19
19
  cimplify link <project-id> Link CWD to a Cimplify project (writes .cimplify/project.json)
20
20
  cimplify unlink Remove the local project link
21
+ cimplify introspect Snapshot the current storefront: auth, link, brand, mock, env, git
22
+ cimplify doctor [--offline] Run pre-flight checks; verdicts + fix hints (exit 1 on any fail)
23
+ cimplify explain [topic] Print canonical guidance on cart, products, bundles, errors, \u2026
24
+ cimplify assets upload <dir> Upload storefront brand assets to the Cimplify CDN
25
+ cimplify assets ls List uploaded assets from cimplify-assets.json
26
+ cimplify assets rm <key> Remove an asset entry from the manifest (remote blob stays)
21
27
 
22
28
  Deploy:
23
29
  cimplify deploy [flags] Push current SHA + trigger a build
@@ -82,7 +88,7 @@ Misc:
82
88
  cimplify --version, -v Show CLI version
83
89
 
84
90
  Init flags:
85
- --template <name>, -t bakery (default) | restaurant | retail | services | grocery | fashion
91
+ --template <name>, -t bakery (default) | restaurant | retail | services | grocery | fashion | pharmacy | auto
86
92
  Picks the storefront design.
87
93
 
88
94
  Login flags:
@@ -115,24 +121,28 @@ Need the mock storefront server? It ships with @cimplify/sdk:
115
121
  bunx @cimplify/sdk mock [flags] Boot the local Cimplify API mock
116
122
  `;
117
123
  var COMMANDS = {
118
- login: () => import('./login-RSKGT6GU.mjs'),
119
- logout: () => import('./logout-ZFZLSJ32.mjs'),
120
- whoami: () => import('./whoami-DIJZYZIN.mjs'),
121
- projects: () => import('./projects-5CJOZ3MT.mjs'),
122
- link: () => import('./link-P4K2HRXY.mjs'),
123
- unlink: () => import('./unlink-5ABCT7B6.mjs'),
124
- deploy: () => import('./deploy-6KVOROT3.mjs'),
125
- rollback: () => import('./rollback-36O4NOEL.mjs'),
126
- env: () => import('./env-FDBPGU3W.mjs'),
127
- domains: () => import('./domains-2ZQ7AG27.mjs'),
128
- logs: () => import('./logs-E2AGTDCF.mjs'),
129
- status: () => import('./status-6AT4HF63.mjs'),
130
- dev: () => import('./dev-AQP6TMYK.mjs'),
131
- repo: () => import('./repo-E6SBKVDG.mjs'),
132
- list: () => import('./list-FL6JZ6A4.mjs'),
133
- add: () => import('./add-7N2EZR6W.mjs'),
134
- update: () => import('./update-LFTHO6Q5.mjs'),
135
- upgrade: () => import('./update-LFTHO6Q5.mjs')
124
+ login: () => import('./login-WSAW4BEA.mjs'),
125
+ logout: () => import('./logout-DJDINVDF.mjs'),
126
+ whoami: () => import('./whoami-LACWBSNL.mjs'),
127
+ projects: () => import('./projects-364HGWHO.mjs'),
128
+ link: () => import('./link-X3E4UZBF.mjs'),
129
+ unlink: () => import('./unlink-HIIW57OO.mjs'),
130
+ deploy: () => import('./deploy-UKOOPJAE.mjs'),
131
+ rollback: () => import('./rollback-5YALPQXL.mjs'),
132
+ env: () => import('./env-EVMYQUIK.mjs'),
133
+ domains: () => import('./domains-JQMV6GAP.mjs'),
134
+ logs: () => import('./logs-KUKGEXR2.mjs'),
135
+ status: () => import('./status-W4HW3CX3.mjs'),
136
+ dev: () => import('./dev-FD4PM3UD.mjs'),
137
+ introspect: () => import('./introspect-PFBI3JHO.mjs'),
138
+ doctor: () => import('./doctor-5LBLYT7M.mjs'),
139
+ explain: () => import('./explain-3KBMWL6M.mjs'),
140
+ assets: () => import('./assets-DMK2QOPD.mjs'),
141
+ repo: () => import('./repo-26N2CHF6.mjs'),
142
+ list: () => import('./list-TE54SJIB.mjs'),
143
+ add: () => import('./add-ZJNXWN2B.mjs'),
144
+ update: () => import('./update-5MRKRVZC.mjs'),
145
+ upgrade: () => import('./update-5MRKRVZC.mjs')
136
146
  };
137
147
  var GLOBAL_FLAGS = /* @__PURE__ */ new Set(["--json", "--yes", "-y"]);
138
148
  function extractGlobalFlags(argv) {
@@ -201,7 +211,9 @@ async function runInit(args) {
201
211
  "retail",
202
212
  "services",
203
213
  "grocery",
204
- "fashion"
214
+ "fashion",
215
+ "pharmacy",
216
+ "auto"
205
217
  ]);
206
218
  let template = "bakery";
207
219
  for (let i = 0; i < args.length; i++) {
@@ -0,0 +1,314 @@
1
+ #!/usr/bin/env node
2
+ import { gatherIntrospection } from './chunk-5IAYN7AJ.mjs';
3
+ import './chunk-RRY3NEZZ.mjs';
4
+ import './chunk-YI7UMMM7.mjs';
5
+ import './chunk-YQVMG62Z.mjs';
6
+ import { parseArgs, flagBool } from './chunk-C4M3DXKC.mjs';
7
+ import { ApiClient } from './chunk-D7WMSGKK.mjs';
8
+ import { readAuthOrNull } from './chunk-LS2VTSMQ.mjs';
9
+ import { bold, dim, info, result, isCliError, CLI_ERROR_CODE, red, yellow, green } from './chunk-I3XQSSOT.mjs';
10
+ import { promises } from 'fs';
11
+ import path from 'path';
12
+
13
+ var ENDPOINT_AUTH_ME = "/v1/auth/me";
14
+ var NON_BUN_LOCKFILES = ["package-lock.json", "yarn.lock", "pnpm-lock.yaml"];
15
+ var BUN_LOCKFILES = ["bun.lock", "bun.lockb"];
16
+ function ok(name, message) {
17
+ return { name, level: "ok", message };
18
+ }
19
+ function warn(name, message, fix) {
20
+ return { name, level: "warn", message, fix };
21
+ }
22
+ function fail(name, message, fix) {
23
+ return { name, level: "fail", message, fix };
24
+ }
25
+ function skip(name, message) {
26
+ return { name, level: "skip", message };
27
+ }
28
+ async function pathExists(abs) {
29
+ try {
30
+ await promises.stat(abs);
31
+ return true;
32
+ } catch {
33
+ return false;
34
+ }
35
+ }
36
+ async function detectLockfile(cwd) {
37
+ let bun = null;
38
+ for (const name of BUN_LOCKFILES) {
39
+ if (await pathExists(path.join(cwd, name))) {
40
+ bun = name;
41
+ break;
42
+ }
43
+ }
44
+ let other = null;
45
+ for (const name of NON_BUN_LOCKFILES) {
46
+ if (await pathExists(path.join(cwd, name))) {
47
+ other = name;
48
+ break;
49
+ }
50
+ }
51
+ return { bun, other };
52
+ }
53
+ function deriveLocalChecks(snapshot, extras) {
54
+ const checks = [];
55
+ checks.push(ok("cli", snapshot.cli.version));
56
+ if (!snapshot.package.found) {
57
+ checks.push(
58
+ fail("package_json", "no package.json in this directory", "run from a Cimplify project root")
59
+ );
60
+ } else {
61
+ checks.push(ok("package_json", snapshot.package.name ?? "(unnamed)"));
62
+ if (!extras.nodeModules) {
63
+ checks.push(fail("node_modules", "missing \u2014 dependencies not installed", "run `bun install`"));
64
+ } else {
65
+ checks.push(ok("node_modules", "installed"));
66
+ }
67
+ if (extras.lockfile.bun) {
68
+ checks.push(ok("lockfile", extras.lockfile.bun));
69
+ } else if (extras.lockfile.other) {
70
+ checks.push(
71
+ warn(
72
+ "lockfile",
73
+ `${extras.lockfile.other} present \u2014 Cimplify expects bun`,
74
+ `delete ${extras.lockfile.other} and run \`bun install\``
75
+ )
76
+ );
77
+ } else {
78
+ checks.push(fail("lockfile", "no lockfile found", "run `bun install`"));
79
+ }
80
+ const pin = snapshot.package.sdk_pin;
81
+ if (!pin) {
82
+ checks.push(
83
+ fail(
84
+ "sdk_pin",
85
+ "@cimplify/sdk not in dependencies",
86
+ "run `bun add @cimplify/sdk`"
87
+ )
88
+ );
89
+ } else if (pin === "*" || pin === "latest") {
90
+ checks.push(
91
+ warn(
92
+ "sdk_pin",
93
+ `@cimplify/sdk pinned to '${pin}' \u2014 unpredictable`,
94
+ "pin to a specific minor (e.g. ^0.45.0)"
95
+ )
96
+ );
97
+ } else {
98
+ checks.push(ok("sdk_pin", `@cimplify/sdk ${pin}`));
99
+ }
100
+ }
101
+ if (snapshot.brand.found) {
102
+ checks.push(ok("brand_file", `${snapshot.brand.path} \xB7 ${snapshot.brand.name ?? "(no name)"}`));
103
+ } else if (snapshot.package.found) {
104
+ checks.push(
105
+ warn(
106
+ "brand_file",
107
+ "no lib/brand.ts \u2014 content is not centralized",
108
+ "scaffold one via `cimplify init` or copy from a template"
109
+ )
110
+ );
111
+ } else {
112
+ checks.push(skip("brand_file", "no package.json \u2014 not a project root"));
113
+ }
114
+ if (snapshot.next_config.path === null) {
115
+ checks.push(skip("next_config", "no next.config \u2014 non-Next project?"));
116
+ } else if (snapshot.next_config.cache_components === true) {
117
+ checks.push(ok("next_config", "cacheComponents: true"));
118
+ } else if (snapshot.next_config.cache_components === false) {
119
+ checks.push(
120
+ fail(
121
+ "next_config",
122
+ "cacheComponents is explicitly false",
123
+ "set `cacheComponents: true` in next.config.ts \u2014 Cimplify templates rely on Next 16 cache primitives"
124
+ )
125
+ );
126
+ } else {
127
+ checks.push(
128
+ warn(
129
+ "next_config",
130
+ "cacheComponents not set",
131
+ "add `cacheComponents: true` to enable `'use cache'` + `cacheTag`"
132
+ )
133
+ );
134
+ }
135
+ if (snapshot.theme.globals_css_path === null) {
136
+ checks.push(skip("globals_css", "no app/globals.css"));
137
+ } else if (snapshot.theme.has_theme_block) {
138
+ checks.push(ok("globals_css", `${snapshot.theme.globals_css_path} \xB7 @theme block present`));
139
+ } else {
140
+ checks.push(
141
+ warn(
142
+ "globals_css",
143
+ `${snapshot.theme.globals_css_path} has no @theme block`,
144
+ "add an @theme block to customize tokens (Tailwind v4)"
145
+ )
146
+ );
147
+ }
148
+ if (snapshot.mock.seed) {
149
+ checks.push(ok("mock_seed", `seed: ${snapshot.mock.seed}`));
150
+ } else if (snapshot.package.found) {
151
+ checks.push(
152
+ warn(
153
+ "mock_seed",
154
+ "no `cimplify-mock --seed <industry>` in dev script",
155
+ "add `cimplify-mock --seed retail` to `scripts.dev`"
156
+ )
157
+ );
158
+ } else {
159
+ checks.push(skip("mock_seed", "no package.json"));
160
+ }
161
+ if (!snapshot.git) {
162
+ checks.push(skip("git", "not a git repo"));
163
+ } else if (snapshot.git.dirty) {
164
+ checks.push(
165
+ warn(
166
+ "git",
167
+ `working tree dirty on ${snapshot.git.branch ?? "(no branch)"}`,
168
+ "commit before `cimplify deploy` (or pass --allow-dirty)"
169
+ )
170
+ );
171
+ } else {
172
+ checks.push(ok("git", `${snapshot.git.branch ?? "(no branch)"} \xB7 clean`));
173
+ }
174
+ if (snapshot.auth.logged_in) {
175
+ checks.push(ok("auth_present", snapshot.auth.email ?? snapshot.auth.account_id ?? "logged in"));
176
+ } else {
177
+ checks.push(fail("auth_present", "not logged in", "run `cimplify login`"));
178
+ }
179
+ if (snapshot.project.linked) {
180
+ checks.push(ok("project_linked", snapshot.project.id ?? ""));
181
+ } else {
182
+ checks.push(
183
+ fail(
184
+ "project_linked",
185
+ ".cimplify/project.json not present",
186
+ "run `cimplify link <project-id>` (or `cimplify projects create`)"
187
+ )
188
+ );
189
+ }
190
+ return checks;
191
+ }
192
+ async function runRemoteChecks(snapshot, auth) {
193
+ if (!auth) {
194
+ return {
195
+ authValid: skip("auth_valid", "not logged in"),
196
+ projectResolves: skip("project_resolves", "not logged in")
197
+ };
198
+ }
199
+ const client = ApiClient.fromAuth(auth);
200
+ let authValid;
201
+ try {
202
+ const me = await client.get(ENDPOINT_AUTH_ME);
203
+ const env = auth.apiKey.startsWith("dk_test_") || auth.apiKey.startsWith("sk_test_") ? "test" : "live";
204
+ authValid = ok("auth_valid", `${env} token \xB7 business ${me.business_id}`);
205
+ } catch (err) {
206
+ if (isCliError(err) && err.code === CLI_ERROR_CODE.AUTH_FAILED) {
207
+ authValid = fail("auth_valid", "token rejected (401)", "run `cimplify login` again");
208
+ } else if (isCliError(err) && err.code === CLI_ERROR_CODE.NETWORK_ERROR) {
209
+ authValid = fail(
210
+ "auth_valid",
211
+ `cannot reach ${auth.apiBaseUrl}`,
212
+ "check connectivity or set CIMPLIFY_API_URL"
213
+ );
214
+ } else {
215
+ const msg = err instanceof Error ? err.message : String(err);
216
+ authValid = fail("auth_valid", msg);
217
+ }
218
+ }
219
+ let projectResolves;
220
+ if (!snapshot.project.linked) {
221
+ projectResolves = skip("project_resolves", "no linked project");
222
+ } else if (authValid.level !== "ok") {
223
+ projectResolves = skip("project_resolves", "auth failed \u2014 cannot check");
224
+ } else {
225
+ const bid = encodeURIComponent(auth.businessId);
226
+ const pid = encodeURIComponent(snapshot.project.id ?? "");
227
+ try {
228
+ const p = await client.get(`/v1/businesses/${bid}/projects/${pid}`);
229
+ projectResolves = ok("project_resolves", `${p.name ?? p.id}`);
230
+ } catch (err) {
231
+ if (isCliError(err) && err.code === CLI_ERROR_CODE.NOT_FOUND) {
232
+ projectResolves = fail(
233
+ "project_resolves",
234
+ "project not found on server",
235
+ "run `cimplify projects ls` to see available projects, then `cimplify link <id>`"
236
+ );
237
+ } else {
238
+ const msg = err instanceof Error ? err.message : String(err);
239
+ projectResolves = fail("project_resolves", msg);
240
+ }
241
+ }
242
+ }
243
+ return { authValid, projectResolves };
244
+ }
245
+ function summarize(checks) {
246
+ const s = { total: checks.length, ok: 0, warn: 0, fail: 0, skip: 0 };
247
+ for (const c of checks) s[c.level]++;
248
+ return s;
249
+ }
250
+ async function gatherDoctorReport(opts = {}) {
251
+ const cwd = opts.cwd ?? process.cwd();
252
+ const snapshot = await gatherIntrospection(cwd);
253
+ const [nodeModules, lockfile, auth] = await Promise.all([
254
+ pathExists(path.join(cwd, "node_modules")),
255
+ detectLockfile(cwd),
256
+ readAuthOrNull()
257
+ ]);
258
+ const local = deriveLocalChecks(snapshot, { nodeModules, lockfile });
259
+ let checks;
260
+ if (opts.offline) {
261
+ checks = [
262
+ ...local,
263
+ skip("auth_valid", "skipped (--offline)"),
264
+ skip("project_resolves", "skipped (--offline)")
265
+ ];
266
+ } else {
267
+ const remote = await runRemoteChecks(snapshot, auth);
268
+ checks = [...local, remote.authValid, remote.projectResolves];
269
+ }
270
+ return { summary: summarize(checks), checks };
271
+ }
272
+ var LABEL_WIDTH = 18;
273
+ function levelGlyph(level) {
274
+ switch (level) {
275
+ case "ok":
276
+ return green("\u2713");
277
+ case "warn":
278
+ return yellow("!");
279
+ case "fail":
280
+ return red("\u2717");
281
+ case "skip":
282
+ return dim("-");
283
+ }
284
+ }
285
+ function renderDoctor(report) {
286
+ const out = [];
287
+ out.push(bold("Cimplify doctor"));
288
+ out.push("");
289
+ for (const c of report.checks) {
290
+ const name = bold(c.name.padEnd(LABEL_WIDTH));
291
+ out.push(` ${levelGlyph(c.level)} ${name}${c.message}`);
292
+ if (c.fix) {
293
+ out.push(` ${" ".repeat(LABEL_WIDTH + 2)}${dim(`\u2192 ${c.fix}`)}`);
294
+ }
295
+ }
296
+ out.push("");
297
+ const s = report.summary;
298
+ const parts = [`${s.total} checks`, `${s.ok} ok`];
299
+ if (s.warn > 0) parts.push(`${s.warn} warn`);
300
+ if (s.fail > 0) parts.push(`${s.fail} fail`);
301
+ if (s.skip > 0) parts.push(`${s.skip} skip`);
302
+ out.push(dim(parts.join(" \xB7 ")));
303
+ return out;
304
+ }
305
+ async function run(argv) {
306
+ const args = parseArgs(argv);
307
+ const offline = flagBool(args, "offline");
308
+ const report = await gatherDoctorReport({ offline });
309
+ for (const line of renderDoctor(report)) info(line);
310
+ result(report);
311
+ if (report.summary.fail > 0) process.exit(1);
312
+ }
313
+
314
+ export { run as default, deriveLocalChecks, gatherDoctorReport, renderDoctor };