@cimplify/cli 0.2.8 → 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-7PTWJV4F.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-H2HJQGFY.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-UPEHLREA.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-44MLIFI2.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-6KEG7EWK.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,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { REGISTRY_INDEX, REGISTRY } from './chunk-H2HJQGFY.mjs';
3
- import { promptYesNo } from './chunk-L6474RPL.mjs';
4
- import { parseArgs, flagString, flagBool } from './chunk-4SBJVRGM.mjs';
5
- import { CliError, CLI_ERROR_CODE, info, bold, dim, success, result, yellow } from './chunk-NZ4RG62Z.mjs';
2
+ import { REGISTRY_INDEX, REGISTRY } from './chunk-MHK4WVNF.mjs';
3
+ import { promptYesNo } from './chunk-RZQTHTXX.mjs';
4
+ import { parseArgs, flagString, flagBool } from './chunk-C4M3DXKC.mjs';
5
+ import { CliError, CLI_ERROR_CODE, info, bold, dim, success, result, yellow } from './chunk-I3XQSSOT.mjs';
6
6
  import { mkdirSync, existsSync, writeFileSync } from 'fs';
7
7
  import { resolve, join, dirname } from 'path';
8
8
 
@@ -54,21 +54,21 @@ async function writeComponent(component, options) {
54
54
  }
55
55
  return outcome;
56
56
  }
57
- function resolveDependencyOrder(roots) {
57
+ function resolveOrder(roots, getDeps) {
58
58
  const visited = /* @__PURE__ */ new Set();
59
59
  const order = [];
60
60
  function visit(name) {
61
61
  if (visited.has(name)) return;
62
62
  visited.add(name);
63
- const component = loadComponent(name);
64
- for (const dep of component.registryDependencies) {
65
- visit(dep);
66
- }
63
+ for (const dep of getDeps(name)) visit(dep);
67
64
  order.push(name);
68
65
  }
69
66
  for (const root of roots) visit(root);
70
67
  return order;
71
68
  }
69
+ function resolveDependencyOrder(roots) {
70
+ return resolveOrder(roots, (name) => loadComponent(name).registryDependencies);
71
+ }
72
72
  async function run(argv) {
73
73
  const args = parseArgs(argv);
74
74
  const dirFlag = flagString(args, "dir");
@@ -122,4 +122,4 @@ async function run(argv) {
122
122
  });
123
123
  }
124
124
 
125
- export { run as default };
125
+ export { run as default, resolveOrder };
@@ -0,0 +1,208 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs, flagString, flagBool } from './chunk-C4M3DXKC.mjs';
3
+ import { ApiClient } from './chunk-D7WMSGKK.mjs';
4
+ import { readAuth } from './chunk-LS2VTSMQ.mjs';
5
+ import { CliError, CLI_ERROR_CODE, step, yellow, dim, success, info, result, bold, green } from './chunk-I3XQSSOT.mjs';
6
+ import { createHash } from 'crypto';
7
+ import { promises } from 'fs';
8
+ import path from 'path';
9
+
10
+ var MANIFEST_FILE = "cimplify-assets.json";
11
+ var DEFAULT_FOLDER = "assets";
12
+ var MAX_FILE_SIZE_BYTES = 50 * 1024 * 1024;
13
+ var CONTENT_TYPE_FALLBACK = "application/octet-stream";
14
+ var MIME_BY_EXT = {
15
+ ".jpg": "image/jpeg",
16
+ ".jpeg": "image/jpeg",
17
+ ".png": "image/png",
18
+ ".gif": "image/gif",
19
+ ".webp": "image/webp",
20
+ ".avif": "image/avif",
21
+ ".svg": "image/svg+xml",
22
+ ".pdf": "application/pdf",
23
+ ".mp4": "video/mp4",
24
+ ".webm": "video/webm",
25
+ ".woff2": "font/woff2",
26
+ ".woff": "font/woff",
27
+ ".ttf": "font/ttf"
28
+ };
29
+ function endpointInit(businessId) {
30
+ return `/v1/businesses/${encodeURIComponent(businessId)}/assets/init`;
31
+ }
32
+ function endpointConfirm(businessId) {
33
+ return `/v1/businesses/${encodeURIComponent(businessId)}/assets/confirm`;
34
+ }
35
+ function manifestPath(cwd = process.cwd()) {
36
+ return path.join(cwd, MANIFEST_FILE);
37
+ }
38
+ async function readManifest(cwd = process.cwd()) {
39
+ try {
40
+ const raw = await promises.readFile(manifestPath(cwd), "utf8");
41
+ return JSON.parse(raw);
42
+ } catch (err) {
43
+ if (err.code === "ENOENT") return {};
44
+ throw err;
45
+ }
46
+ }
47
+ async function writeManifest(manifest, cwd = process.cwd()) {
48
+ const payload = `${JSON.stringify(manifest, null, 2)}
49
+ `;
50
+ await promises.writeFile(manifestPath(cwd), payload, "utf8");
51
+ }
52
+ function mimeOf(filename) {
53
+ const ext = path.extname(filename).toLowerCase();
54
+ return MIME_BY_EXT[ext] ?? CONTENT_TYPE_FALLBACK;
55
+ }
56
+ function sha256Hex(buf) {
57
+ return createHash("sha256").update(buf).digest("hex");
58
+ }
59
+ async function walkFiles(root) {
60
+ const out = [];
61
+ async function visit(dir) {
62
+ const entries = await promises.readdir(dir, { withFileTypes: true });
63
+ for (const e of entries) {
64
+ const abs = path.join(dir, e.name);
65
+ if (e.isDirectory()) await visit(abs);
66
+ else if (e.isFile()) out.push(abs);
67
+ }
68
+ }
69
+ await visit(root);
70
+ return out;
71
+ }
72
+ async function run(argv) {
73
+ const args = parseArgs(argv);
74
+ const sub = args.positional[0];
75
+ if (!sub) {
76
+ throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, "Usage: cimplify assets <upload|ls|rm>");
77
+ }
78
+ switch (sub) {
79
+ case "upload":
80
+ return runUpload(args);
81
+ case "ls":
82
+ return runLs(args);
83
+ case "rm":
84
+ return runRm(args);
85
+ default:
86
+ throw new CliError(
87
+ CLI_ERROR_CODE.INVALID_INPUT,
88
+ `Unknown subcommand "${sub}". Use upload, ls, or rm.`
89
+ );
90
+ }
91
+ }
92
+ async function runUpload(args) {
93
+ const dir = args.positional[1];
94
+ if (!dir) {
95
+ throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, "Usage: cimplify assets upload <dir> [--folder <path>]");
96
+ }
97
+ const folder = flagString(args, "folder") ?? DEFAULT_FOLDER;
98
+ const force = flagBool(args, "force");
99
+ const root = path.resolve(process.cwd(), dir);
100
+ const stat = await promises.stat(root).catch(() => null);
101
+ if (!stat?.isDirectory()) {
102
+ throw new CliError(CLI_ERROR_CODE.NOT_FOUND, `Directory not found: ${root}`);
103
+ }
104
+ const auth = await readAuth();
105
+ const client = ApiClient.fromAuth(auth);
106
+ const manifest = await readManifest();
107
+ const files = await walkFiles(root);
108
+ const uploaded = [];
109
+ const skipped = [];
110
+ for (const abs of files) {
111
+ const rel = path.relative(root, abs).replaceAll(path.sep, "/");
112
+ const filename = path.basename(rel);
113
+ const keyForManifest = `${folder}/${rel}`;
114
+ const contentType = mimeOf(filename);
115
+ const buf = await promises.readFile(abs);
116
+ if (buf.byteLength > MAX_FILE_SIZE_BYTES) {
117
+ throw new CliError(
118
+ CLI_ERROR_CODE.INVALID_INPUT,
119
+ `${rel}: ${buf.byteLength} bytes exceeds 50 MB limit`
120
+ );
121
+ }
122
+ const hash = sha256Hex(buf);
123
+ const existing = manifest[keyForManifest];
124
+ if (existing && existing.sha256 === hash && !force) {
125
+ step(`${yellow("skip")} ${keyForManifest} ${dim("(unchanged)")}`);
126
+ skipped.push(keyForManifest);
127
+ continue;
128
+ }
129
+ const subfolder = path.posix.join(folder, path.posix.dirname(rel));
130
+ const init = await client.post(endpointInit(auth.businessId), {
131
+ folder: subfolder,
132
+ filename,
133
+ content_type: contentType,
134
+ size_bytes: buf.byteLength
135
+ });
136
+ step(`${dim("\u2192")} ${keyForManifest} ${dim(`(${buf.byteLength} bytes)`)}`);
137
+ const putRes = await fetch(init.upload_url, {
138
+ method: "PUT",
139
+ headers: { "content-type": contentType },
140
+ body: buf
141
+ });
142
+ if (!putRes.ok) {
143
+ throw new CliError(
144
+ CLI_ERROR_CODE.NETWORK_ERROR,
145
+ `PUT to R2 failed for ${keyForManifest}: ${putRes.status} ${putRes.statusText}`
146
+ );
147
+ }
148
+ const confirmed = await client.post(endpointConfirm(auth.businessId), {
149
+ upload_id: init.upload_id
150
+ });
151
+ manifest[keyForManifest] = {
152
+ url: confirmed.url,
153
+ upload_id: init.upload_id,
154
+ folder: subfolder,
155
+ filename,
156
+ content_type: contentType,
157
+ size_bytes: buf.byteLength,
158
+ sha256: hash,
159
+ uploaded_at: (/* @__PURE__ */ new Date()).toISOString()
160
+ };
161
+ uploaded.push(keyForManifest);
162
+ }
163
+ await writeManifest(manifest);
164
+ success(`Uploaded ${uploaded.length} file${uploaded.length === 1 ? "" : "s"} (${skipped.length} skipped)`);
165
+ info(dim(`Manifest: ${manifestPath()}`));
166
+ result({
167
+ uploaded_count: uploaded.length,
168
+ skipped_count: skipped.length,
169
+ manifest_path: manifestPath(),
170
+ uploaded,
171
+ skipped
172
+ });
173
+ }
174
+ async function runLs(args) {
175
+ const prefix = flagString(args, "prefix");
176
+ const manifest = await readManifest();
177
+ const entries = Object.entries(manifest).filter(([k]) => prefix ? k.startsWith(prefix) : true).sort(([a], [b]) => a.localeCompare(b));
178
+ if (entries.length === 0) {
179
+ info(dim("No assets uploaded yet."));
180
+ } else {
181
+ info(bold(`Assets in ${MANIFEST_FILE}:`));
182
+ for (const [key, entry] of entries) {
183
+ info(` ${green("\u25CF")} ${key} ${dim(`\u2192 ${entry.url}`)}`);
184
+ }
185
+ }
186
+ result({
187
+ count: entries.length,
188
+ assets: entries.map(([key, entry]) => ({ key, ...entry }))
189
+ });
190
+ }
191
+ async function runRm(args) {
192
+ const key = args.positional[1];
193
+ if (!key) {
194
+ throw new CliError(CLI_ERROR_CODE.INVALID_INPUT, "Usage: cimplify assets rm <key>");
195
+ }
196
+ const manifest = await readManifest();
197
+ if (!(key in manifest)) {
198
+ throw new CliError(CLI_ERROR_CODE.NOT_FOUND, `Key not found in manifest: ${key}`);
199
+ }
200
+ const removed = manifest[key];
201
+ delete manifest[key];
202
+ await writeManifest(manifest);
203
+ success(`Removed ${key} from manifest`);
204
+ info(dim("Note: remote blob is not deleted in v1 \u2014 only the manifest entry."));
205
+ result({ removed_key: key, removed_url: removed.url });
206
+ }
207
+
208
+ export { run as default, endpointConfirm, endpointInit, mimeOf, readManifest, sha256Hex, walkFiles, writeManifest };
@@ -0,0 +1,259 @@
1
+ #!/usr/bin/env node
2
+ import { gitDetectRoot, gitCurrentBranch, gitCurrentSha, gitStatusPorcelain } from './chunk-RRY3NEZZ.mjs';
3
+ import { parseEnvFile } from './chunk-YI7UMMM7.mjs';
4
+ import { package_default } from './chunk-YQVMG62Z.mjs';
5
+ import { parseArgs } from './chunk-C4M3DXKC.mjs';
6
+ import { readAuthOrNull, readProjectLinkOrNull, readProjectState } from './chunk-LS2VTSMQ.mjs';
7
+ import { bold, dim, yellow, green, info, result, red } from './chunk-I3XQSSOT.mjs';
8
+ import { promises } from 'fs';
9
+ import path from 'path';
10
+
11
+ var CLI_VERSION = package_default.version ?? "unknown";
12
+ var SHA_DISPLAY_LEN = 7;
13
+ var BRAND_FILE_CANDIDATES = ["lib/brand.ts", "src/lib/brand.ts"];
14
+ var GLOBALS_CSS_CANDIDATES = ["app/globals.css", "src/app/globals.css"];
15
+ var NEXT_CONFIG_CANDIDATES = ["next.config.ts", "next.config.mjs", "next.config.js"];
16
+ var ENV_FILE_CANDIDATES = [".env.local", ".env.example", ".env.production"];
17
+ async function readTextOrNull(filePath) {
18
+ try {
19
+ return await promises.readFile(filePath, "utf8");
20
+ } catch (err) {
21
+ if (err.code === "ENOENT") return null;
22
+ throw err;
23
+ }
24
+ }
25
+ async function findFirstExisting(cwd, candidates) {
26
+ for (const rel of candidates) {
27
+ const abs = path.join(cwd, rel);
28
+ const content = await readTextOrNull(abs);
29
+ if (content !== null) return { rel, abs, content };
30
+ }
31
+ return null;
32
+ }
33
+ async function gatherAuth() {
34
+ const auth = await readAuthOrNull();
35
+ if (!auth) {
36
+ return { logged_in: false, account_id: null, business_id: null, email: null, api_base_url: null };
37
+ }
38
+ return {
39
+ logged_in: true,
40
+ account_id: auth.accountId,
41
+ business_id: auth.businessId,
42
+ email: auth.email ?? null,
43
+ api_base_url: auth.apiBaseUrl
44
+ };
45
+ }
46
+ async function gatherProject(cwd) {
47
+ const link = await readProjectLinkOrNull(cwd);
48
+ if (!link) {
49
+ return {
50
+ linked: false,
51
+ id: null,
52
+ remote_url: null,
53
+ default_branch: null,
54
+ framework: null,
55
+ last_deployment: null
56
+ };
57
+ }
58
+ const state = await readProjectState(cwd);
59
+ return {
60
+ linked: true,
61
+ id: link.projectId,
62
+ remote_url: link.remoteUrl ?? null,
63
+ default_branch: link.defaultBranch ?? null,
64
+ framework: link.framework ?? null,
65
+ last_deployment: state?.lastDeploymentId ? {
66
+ id: state.lastDeploymentId,
67
+ sha: state.lastDeploymentSha ?? null,
68
+ environment: state.lastDeploymentEnv ?? null,
69
+ at: state.lastDeploymentAt ?? null
70
+ } : null
71
+ };
72
+ }
73
+ async function gatherPackage(cwd) {
74
+ const raw = await readTextOrNull(path.join(cwd, "package.json"));
75
+ if (!raw) return { found: false, name: null, sdk_pin: null, scripts: [] };
76
+ try {
77
+ const json = JSON.parse(raw);
78
+ const sdkPin = json.dependencies?.["@cimplify/sdk"] ?? json.devDependencies?.["@cimplify/sdk"] ?? null;
79
+ return {
80
+ found: true,
81
+ name: json.name ?? null,
82
+ sdk_pin: sdkPin,
83
+ scripts: json.scripts ? Object.keys(json.scripts) : []
84
+ };
85
+ } catch {
86
+ return { found: true, name: null, sdk_pin: null, scripts: [] };
87
+ }
88
+ }
89
+ var BRAND_NAME_RE = /\bname:\s*"([^"]+)"/;
90
+ var BRAND_SCHEMA_TYPE_RE = /\bschemaType:\s*"([^"]+)"/;
91
+ async function gatherBrand(cwd) {
92
+ const hit = await findFirstExisting(cwd, BRAND_FILE_CANDIDATES);
93
+ if (!hit) return { found: false, path: null, name: null, schema_type: null };
94
+ return {
95
+ found: true,
96
+ path: hit.rel,
97
+ name: BRAND_NAME_RE.exec(hit.content)?.[1] ?? null,
98
+ schema_type: BRAND_SCHEMA_TYPE_RE.exec(hit.content)?.[1] ?? null
99
+ };
100
+ }
101
+ async function gatherTheme(cwd) {
102
+ const hit = await findFirstExisting(cwd, GLOBALS_CSS_CANDIDATES);
103
+ if (!hit) return { globals_css_path: null, has_theme_block: false };
104
+ return {
105
+ globals_css_path: hit.rel,
106
+ has_theme_block: /@theme\b/.test(hit.content)
107
+ };
108
+ }
109
+ var NEXT_CACHE_COMPONENTS_RE = /\bcacheComponents:\s*(true|false)\b/;
110
+ async function gatherNextConfig(cwd) {
111
+ const hit = await findFirstExisting(cwd, NEXT_CONFIG_CANDIDATES);
112
+ if (!hit) return { path: null, cache_components: null };
113
+ const match = NEXT_CACHE_COMPONENTS_RE.exec(hit.content);
114
+ return {
115
+ path: hit.rel,
116
+ cache_components: match ? match[1] === "true" : null
117
+ };
118
+ }
119
+ var MOCK_SEED_RE = /cimplify-mock[^"]*?--seed\s+([a-z0-9-]+)/;
120
+ function extractMockSeed(pkgJsonText) {
121
+ return MOCK_SEED_RE.exec(pkgJsonText)?.[1] ?? null;
122
+ }
123
+ async function gatherMock(cwd) {
124
+ const raw = await readTextOrNull(path.join(cwd, "package.json"));
125
+ if (!raw) return { seed: null };
126
+ return { seed: extractMockSeed(raw) };
127
+ }
128
+ async function gatherEnvFiles(cwd) {
129
+ const out = [];
130
+ for (const file of ENV_FILE_CANDIDATES) {
131
+ const text = await readTextOrNull(path.join(cwd, file));
132
+ if (text === null) continue;
133
+ out.push({ file, keys: parseEnvFile(text).map((e) => e.key) });
134
+ }
135
+ return out;
136
+ }
137
+ async function gatherGit(cwd) {
138
+ const root = await gitDetectRoot(cwd);
139
+ if (!root) return null;
140
+ const [branch, sha, porcelain] = await Promise.all([
141
+ gitCurrentBranch(root).catch(() => ""),
142
+ gitCurrentSha(root).catch(() => ""),
143
+ gitStatusPorcelain(root).catch(() => "")
144
+ ]);
145
+ return {
146
+ branch: branch || null,
147
+ sha: sha || null,
148
+ dirty: porcelain.trim().length > 0
149
+ };
150
+ }
151
+ async function gatherIntrospection(cwd = process.cwd()) {
152
+ const [auth, project, pkg, brand, theme, nextConfig, mock, envFiles, git] = await Promise.all([
153
+ gatherAuth(),
154
+ gatherProject(cwd),
155
+ gatherPackage(cwd),
156
+ gatherBrand(cwd),
157
+ gatherTheme(cwd),
158
+ gatherNextConfig(cwd),
159
+ gatherMock(cwd),
160
+ gatherEnvFiles(cwd),
161
+ gatherGit(cwd)
162
+ ]);
163
+ return {
164
+ cwd,
165
+ cli: { version: CLI_VERSION },
166
+ auth,
167
+ project,
168
+ package: pkg,
169
+ brand,
170
+ theme,
171
+ next_config: nextConfig,
172
+ mock,
173
+ env_files: envFiles,
174
+ git
175
+ };
176
+ }
177
+ var LABEL_WIDTH = 12;
178
+ function label(name) {
179
+ return bold(name.padEnd(LABEL_WIDTH));
180
+ }
181
+ function check(ok) {
182
+ return ok ? green("\u2713") : red("\u2717");
183
+ }
184
+ function renderIntrospection(snapshot) {
185
+ const out = [];
186
+ out.push(bold("Cimplify"));
187
+ out.push("");
188
+ out.push(` ${label("CLI")}${snapshot.cli.version}`);
189
+ const a = snapshot.auth;
190
+ if (a.logged_in) {
191
+ const who = a.email ?? a.account_id ?? "unknown";
192
+ out.push(` ${label("Auth")}${check(true)} ${who} ${dim(`(${a.business_id ?? "?"})`)}`);
193
+ } else {
194
+ out.push(` ${label("Auth")}${check(false)} not logged in ${dim("(cimplify login)")}`);
195
+ }
196
+ const p = snapshot.project;
197
+ if (p.linked) {
198
+ out.push(` ${label("Project")}${check(true)} ${p.id}`);
199
+ if (p.last_deployment) {
200
+ const d = p.last_deployment;
201
+ const shortSha = d.sha ? d.sha.slice(0, SHA_DISPLAY_LEN) : "?";
202
+ out.push(` ${" ".repeat(LABEL_WIDTH)}last deploy: ${d.environment ?? "?"} \xB7 ${shortSha} \xB7 ${d.id}`);
203
+ }
204
+ } else {
205
+ out.push(` ${label("Project")}${check(false)} not linked ${dim("(cimplify link <id>)")}`);
206
+ }
207
+ const pkg = snapshot.package;
208
+ if (pkg.found) {
209
+ const bits = [pkg.name ?? "?", `@cimplify/sdk ${pkg.sdk_pin ?? "(missing)"}`];
210
+ out.push(` ${label("Package")}${bits.join(" \xB7 ")}`);
211
+ if (pkg.scripts.length > 0) {
212
+ out.push(` ${" ".repeat(LABEL_WIDTH)}${dim(`scripts: ${pkg.scripts.join(", ")}`)}`);
213
+ }
214
+ } else {
215
+ out.push(` ${label("Package")}${dim("no package.json in this directory")}`);
216
+ }
217
+ const b = snapshot.brand;
218
+ if (b.found) {
219
+ const name = b.name ?? "(no name found)";
220
+ const tag = b.schema_type ? ` ${dim(`(${b.schema_type})`)}` : "";
221
+ out.push(` ${label("Brand")}${check(true)} ${name}${tag} ${dim(b.path ?? "")}`);
222
+ } else {
223
+ out.push(` ${label("Brand")}${dim("no lib/brand.ts")}`);
224
+ }
225
+ const t = snapshot.theme;
226
+ if (t.globals_css_path) {
227
+ out.push(
228
+ ` ${label("Theme")}${check(t.has_theme_block)} ${t.globals_css_path}${t.has_theme_block ? "" : dim(" (no @theme block)")}`
229
+ );
230
+ }
231
+ const nc = snapshot.next_config;
232
+ if (nc.path) {
233
+ const flag = nc.cache_components;
234
+ const sigil = flag === true ? check(true) : flag === false ? yellow("!") : dim("?");
235
+ const note = flag === true ? "cacheComponents: true" : flag === false ? "cacheComponents: false" : "cacheComponents not set";
236
+ out.push(` ${label("Next")}${sigil} ${note} ${dim(nc.path)}`);
237
+ }
238
+ if (snapshot.mock.seed) {
239
+ out.push(` ${label("Mock")}seed: ${snapshot.mock.seed}`);
240
+ }
241
+ if (snapshot.env_files.length > 0) {
242
+ const summary = snapshot.env_files.map((e) => `${e.file}: ${e.keys.length} key${e.keys.length === 1 ? "" : "s"}`).join(" \xB7 ");
243
+ out.push(` ${label("Env")}${summary}`);
244
+ }
245
+ if (snapshot.git) {
246
+ const g = snapshot.git;
247
+ const dirty = g.dirty ? yellow("dirty") : green("clean");
248
+ out.push(` ${label("Git")}${g.branch ?? "(no branch)"} \xB7 ${dirty}`);
249
+ }
250
+ return out;
251
+ }
252
+ async function run(argv) {
253
+ parseArgs(argv);
254
+ const snapshot = await gatherIntrospection();
255
+ for (const line of renderIntrospection(snapshot)) info(line);
256
+ result(snapshot);
257
+ }
258
+
259
+ export { extractMockSeed, gatherIntrospection, renderIntrospection, run };
@@ -32,7 +32,9 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
32
32
  // Dev / login / logs
33
33
  "remote",
34
34
  "no-browser",
35
- "follow"
35
+ "follow",
36
+ // Doctor
37
+ "offline"
36
38
  ]);
37
39
  function parseArgs(argv) {
38
40
  const positional = [];
@@ -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/api-client.ts
5
5
  var DEFAULT_API_BASE_URL = "https://api.cimplify.io";
@@ -65,6 +65,9 @@ var CliError = class extends Error {
65
65
  this.remediation = options.remediation;
66
66
  }
67
67
  };
68
+ function isCliError(err) {
69
+ return err instanceof CliError || typeof err === "object" && err !== null && err.name === "CliError" && typeof err.code === "string" && typeof err.exitCode === "number";
70
+ }
68
71
 
69
72
  // src/output.ts
70
73
  var RESET = "\x1B[0m";
@@ -138,4 +141,4 @@ function result(data) {
138
141
  `);
139
142
  }
140
143
 
141
- export { CLI_ERROR_CODE, CliError, EXIT_CODE, bold, dim, failure, green, info, isAutoYes, isInteractive, isJsonMode, red, result, step, success, yellow };
144
+ export { CLI_ERROR_CODE, CliError, EXIT_CODE, bold, dim, failure, green, info, isAutoYes, isCliError, isInteractive, isJsonMode, red, result, step, success, yellow };
@@ -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
  import { promises } from 'fs';
4
4
  import os from 'os';
5
5
  import path from 'path';
@@ -61,6 +61,9 @@ async function readAuth() {
61
61
  }
62
62
  return data;
63
63
  }
64
+ async function readAuthOrNull() {
65
+ return readJsonFile(authConfigPath());
66
+ }
64
67
  async function writeAuth(creds) {
65
68
  await writeJsonFile(authConfigPath(), creds, FILE_MODE_PRIVATE);
66
69
  }
@@ -83,6 +86,9 @@ async function readProjectLink(cwd = process.cwd()) {
83
86
  }
84
87
  return data;
85
88
  }
89
+ async function readProjectLinkOrNull(cwd = process.cwd()) {
90
+ return readJsonFile(projectConfigPath(cwd));
91
+ }
86
92
  async function writeProjectLink(link, cwd = process.cwd()) {
87
93
  await writeJsonFile(projectConfigPath(cwd), link);
88
94
  await ensureStateGitignored(cwd);
@@ -124,4 +130,4 @@ ${STATE_GITIGNORE_LINE}
124
130
  await promises.writeFile(gitignore, next, ENCODING_UTF8);
125
131
  }
126
132
 
127
- export { clearAuth, clearProjectLink, readAuth, readProjectLink, readProjectState, writeAuth, writeProjectLink, writeProjectState };
133
+ export { clearAuth, clearProjectLink, readAuth, readAuthOrNull, readProjectLink, readProjectLinkOrNull, readProjectState, writeAuth, writeProjectLink, writeProjectState };