youiyoux 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/README.md +10 -0
  2. package/dist/chunks/{chunk-S7UV34H5.js → chunk-42YJX3W5.js} +1 -3
  3. package/dist/chunks/{chunk-FUB7B3VK.js → chunk-4BBYLTZX.js} +10 -10
  4. package/dist/chunks/chunk-52KOKYY6.js +8710 -0
  5. package/dist/chunks/chunk-FJZFCAL5.js +129 -0
  6. package/dist/chunks/chunk-FVVL5JCY.js +24 -0
  7. package/dist/chunks/{chunk-UHPK62Q5.js → chunk-M5XZWCPS.js} +240 -60
  8. package/dist/chunks/{chunk-ZLRFD5JI.js → chunk-NYDJYMID.js} +263 -16
  9. package/dist/chunks/{src-7ENJHYG4.js → chunk-RDTHHRZN.js} +319 -165
  10. package/dist/chunks/{chunk-E4HNK7VF.js → chunk-WNTS7ZO4.js} +1 -1
  11. package/dist/chunks/chunk-XAEMVEYX.js +188 -0
  12. package/dist/chunks/{chunk-CLNMVQZJ.js → chunk-YFCMTTXS.js} +708 -494
  13. package/dist/chunks/chunk-YJ7WMBTT.js +13761 -0
  14. package/dist/chunks/src-5IP4NGKT.js +115 -0
  15. package/dist/chunks/src-6CJR547Y.js +124 -0
  16. package/dist/chunks/{src-WQWYJ6IQ.js → src-BPETAFLW.js} +175 -76
  17. package/dist/chunks/{src-B742AYFC.js → src-LLV7IY6W.js} +55 -16
  18. package/dist/chunks/src-RHNZELGE.js +306 -0
  19. package/dist/chunks/{src-4KFNL3MY.js → src-SFKFERZ2.js} +18 -8
  20. package/dist/chunks/{src-VEHGMKYV.js → src-VL2ZYO6X.js} +4 -4
  21. package/dist/hub/assets/Badge-CUJUit4d.js +1 -0
  22. package/dist/hub/assets/CandidatePanel-CnbK4S0j.js +1 -0
  23. package/dist/hub/assets/CatalogScreen-B5OVL-AR.js +1 -0
  24. package/dist/hub/assets/ChangesScreen-GwGqJwxN.js +1 -0
  25. package/dist/hub/assets/CheatSheet-BLSOq-xa.js +1 -0
  26. package/dist/hub/assets/CodeBlock-CsiGFgvI.js +1 -0
  27. package/dist/hub/assets/CommandPalette-CAWQfdXJ.js +1 -0
  28. package/dist/hub/assets/CopyButton-DE8drl4P.js +1 -0
  29. package/dist/hub/assets/Disclosure-B1kTgPgk.js +1 -0
  30. package/dist/hub/assets/DiscoverScreen-Tl_Z6mgY.js +2 -0
  31. package/dist/hub/assets/DraftEditor-yIDapXTs.js +5 -0
  32. package/dist/hub/assets/Field-LwrJXoOs.js +1 -0
  33. package/dist/hub/assets/GapsScreen-DXZAlm6v.js +1 -0
  34. package/dist/hub/assets/HomeScreen-CEpiVhOa.js +1 -0
  35. package/dist/hub/assets/InventoryScreen-CEG3Pmw_.js +1 -0
  36. package/dist/hub/assets/KindIcon-BJ6bz-ny.js +1 -0
  37. package/dist/hub/assets/LibraryScreen-IaVnxrX9.js +1 -0
  38. package/dist/hub/assets/LicenceBadge-CLCUMMHE.js +1 -0
  39. package/dist/hub/assets/Opened-DJyf4Hnj.js +1 -0
  40. package/dist/hub/assets/Preview-C069zVMP.js +1 -0
  41. package/dist/hub/assets/RuleDetail-B4g2-TRe.js +3 -0
  42. package/dist/hub/assets/RulesScreen-CAaXIWjO.js +3 -0
  43. package/dist/hub/assets/ScreenImage-DcI7_G3O.js +1 -0
  44. package/dist/hub/assets/ScreensScreen-DwczCjZD.js +1 -0
  45. package/dist/hub/assets/SearchField-DaCpNAj6.js +1 -0
  46. package/dist/hub/assets/Section-BTnvUq_W.js +1 -0
  47. package/dist/hub/assets/Segmented-Dzi1x49S.js +1 -0
  48. package/dist/hub/assets/ServiceDown-Bv-BPXro.js +1 -0
  49. package/dist/hub/assets/SpecimenCapture-DlsjshVE.js +1 -0
  50. package/dist/hub/assets/Specimens-C-lHp7sr.js +2 -0
  51. package/dist/hub/assets/StackScreen-DkmELsqR.js +1 -0
  52. package/dist/hub/assets/StubScreens-Bt7lWLVK.js +1 -0
  53. package/dist/hub/assets/StyleScreen-tq1tbRBo.js +1 -0
  54. package/dist/hub/assets/Swatch-KDz4qxdM.js +1 -0
  55. package/dist/hub/assets/Tabs-1QQDS0I6.js +1 -0
  56. package/dist/hub/assets/TokenDetail-DvCw6GqC.js +1 -0
  57. package/dist/hub/assets/TokenValue-CsPRc2ai.js +1 -0
  58. package/dist/hub/assets/TokensScreen-DoENV8Xy.js +1 -0
  59. package/dist/hub/assets/arrow-right-DcbNDzqs.js +1 -0
  60. package/dist/hub/assets/bot-B3gC9oUR.js +1 -0
  61. package/dist/hub/assets/button-6mvMVtpb.js +1 -0
  62. package/dist/hub/assets/button.demo-DuU0DQbv.js +1 -0
  63. package/dist/hub/assets/card.demo-CufAxMAA.js +1 -0
  64. package/dist/hub/assets/chevron-down-CzN07vMi.js +1 -0
  65. package/dist/hub/assets/circle-alert-DT2LC4yf.js +1 -0
  66. package/dist/hub/assets/circle-check-DkwBMT62.js +1 -0
  67. package/dist/hub/assets/client-D7whEyep.js +1 -0
  68. package/dist/hub/assets/clsx-DB0hHKMi.js +1 -0
  69. package/dist/hub/assets/compass-BkKOZPYe.js +1 -0
  70. package/dist/hub/assets/contrast-BkNHUAPa.js +1 -0
  71. package/dist/hub/assets/createLucideIcon-CGDJWtKO.js +1 -0
  72. package/dist/hub/assets/discover-XjJEViwk.js +1 -0
  73. package/dist/hub/assets/dist-BYQYaPBV.js +1 -0
  74. package/dist/hub/assets/dist-Bk4srtDn.js +41 -0
  75. package/dist/hub/assets/dist-BogNzeK9.js +1 -0
  76. package/dist/hub/assets/dist-D0z7Bvsy.js +1 -0
  77. package/dist/hub/assets/download-BQI-Si9R.js +1 -0
  78. package/dist/hub/assets/engine-CMmt9yEz.js +1 -0
  79. package/dist/hub/assets/esm-NPpg23M8.js +1 -0
  80. package/dist/hub/assets/family-tiles-CyTdy_cP.js +1 -0
  81. package/dist/hub/assets/format-DxAYNTN_.js +1 -0
  82. package/dist/hub/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  83. package/dist/hub/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  84. package/dist/hub/assets/geist-latin-core-vkBVTr4s.woff2 +0 -0
  85. package/dist/hub/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  86. package/dist/hub/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  87. package/dist/hub/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
  88. package/dist/hub/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
  89. package/dist/hub/assets/geist-mono-latin-core-DccGGzmg.woff2 +0 -0
  90. package/dist/hub/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
  91. package/dist/hub/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
  92. package/dist/hub/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
  93. package/dist/hub/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
  94. package/dist/hub/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  95. package/dist/hub/assets/git-pull-request-arrow-RqUUIRCU.js +1 -0
  96. package/dist/hub/assets/input.demo-238gqWpz.js +1 -0
  97. package/dist/hub/assets/inventory-BI8QBdar.js +1 -0
  98. package/dist/hub/assets/inventory-source-lZYzcA8O.js +1 -0
  99. package/dist/hub/assets/jsx-runtime-D6zNwnaE.js +9 -0
  100. package/dist/hub/assets/layers-DfzdK_wG.js +1 -0
  101. package/dist/hub/assets/layout-grid-xFY9L9Oc.js +1 -0
  102. package/dist/hub/assets/library-W5R8GwvG.js +1 -0
  103. package/dist/hub/assets/main-7snyIdoi.css +2 -0
  104. package/dist/hub/assets/main-B9CIkk5m.js +2 -0
  105. package/dist/hub/assets/minus-BDifFhOo.js +1 -0
  106. package/dist/hub/assets/monitor-X_lELkcU.js +1 -0
  107. package/dist/hub/assets/mouse-pointer-click-CVJ6hWg8.js +1 -0
  108. package/dist/hub/assets/paintbrush-DOkEgSTO.js +1 -0
  109. package/dist/hub/assets/plural-BbGQPQKA.js +1 -0
  110. package/dist/hub/assets/preview-BA8CPsKb.css +2 -0
  111. package/dist/hub/assets/preview-DUm13vr1.js +3 -0
  112. package/dist/hub/assets/protocol-caP6umNL.js +1 -0
  113. package/dist/hub/assets/react-DB-4Zxce.js +1 -0
  114. package/dist/hub/assets/shield-check-0ka0kQct.js +1 -0
  115. package/dist/hub/assets/trash-B7aEfJps.js +1 -0
  116. package/dist/hub/assets/triangle-alert-Dkdi9eDR.js +1 -0
  117. package/dist/hub/assets/try-live-zX3CSd3P.js +1 -0
  118. package/dist/hub/assets/utils-BoaXfs8y.js +1 -0
  119. package/dist/hub/assets/values-DzxR_TlI.js +1 -0
  120. package/dist/hub/assets/worker-Bh-wSp42.js +1 -0
  121. package/dist/hub/assets/workflow-jpV8wh-U.js +1 -0
  122. package/dist/hub/assets/x-MLbFVa4v.js +1 -0
  123. package/dist/hub/favicon.svg +1 -0
  124. package/dist/hub/index.html +35 -0
  125. package/dist/hub/kit/candidates.json +1 -0
  126. package/dist/hub/kit/chunks/chunk-2NYFUOIV.js +14 -0
  127. package/dist/hub/kit/chunks/chunk-DCANE7XH.js +1 -0
  128. package/dist/hub/kit/chunks/chunk-FTGHCY4I.js +14 -0
  129. package/dist/hub/kit/chunks/chunk-IBF3UTJF.js +33 -0
  130. package/dist/hub/kit/chunks/chunk-LLXY4VSH.js +1 -0
  131. package/dist/hub/kit/chunks/chunk-PUPZMW4P.js +14 -0
  132. package/dist/hub/kit/chunks/chunk-PWLNZQET.js +1 -0
  133. package/dist/hub/kit/chunks/chunk-ULXWVOKJ.js +1 -0
  134. package/dist/hub/kit/chunks/chunk-WM4BGGMK.js +1 -0
  135. package/dist/hub/kit/chunks/chunk-ZQUNRK72.js +1 -0
  136. package/dist/hub/kit/class-variance-authority.js +1 -0
  137. package/dist/hub/kit/clsx.js +1 -0
  138. package/dist/hub/kit/fonts/geist-cyrillic-ext-wght-normal.woff2 +0 -0
  139. package/dist/hub/kit/fonts/geist-cyrillic-wght-normal.woff2 +0 -0
  140. package/dist/hub/kit/fonts/geist-latin-ext-wght-normal.woff2 +0 -0
  141. package/dist/hub/kit/fonts/geist-latin-wght-normal.woff2 +0 -0
  142. package/dist/hub/kit/fonts/geist-vietnamese-wght-normal.woff2 +0 -0
  143. package/dist/hub/kit/frame.css.src +73 -0
  144. package/dist/hub/kit/frame.js +2 -0
  145. package/dist/hub/kit/lucide-react.js +1878 -0
  146. package/dist/hub/kit/preview.html +13 -0
  147. package/dist/hub/kit/radix-ui-react-dialog.js +41 -0
  148. package/dist/hub/kit/radix-ui-react-label.js +1 -0
  149. package/dist/hub/kit/radix-ui-react-separator.js +1 -0
  150. package/dist/hub/kit/radix-ui-react-slot.js +1 -0
  151. package/dist/hub/kit/radix-ui-react-switch.js +1 -0
  152. package/dist/hub/kit/radix-ui-react-tabs.js +1 -0
  153. package/dist/hub/kit/react-dom-client.js +1 -0
  154. package/dist/hub/kit/react-dom.js +1 -0
  155. package/dist/hub/kit/react-jsx-runtime.js +1 -0
  156. package/dist/hub/kit/react.js +1 -0
  157. package/dist/hub/kit/tailwind-merge.js +1 -0
  158. package/dist/hub/kit/tailwindcss/index.css +950 -0
  159. package/dist/hub/kit/tailwindcss/preflight.css +398 -0
  160. package/dist/hub/kit/tailwindcss/theme.css +510 -0
  161. package/dist/hub/kit/tailwindcss/utilities.css +1 -0
  162. package/dist/hub-demo/frame/button.demo.js +1 -0
  163. package/dist/hub-demo/frame/card.demo.js +1 -0
  164. package/dist/hub-demo/frame/demos.js +6 -0
  165. package/dist/hub-demo/frame/frame.css +770 -0
  166. package/dist/hub-demo/frame/input.demo.js +1 -0
  167. package/dist/hub-demo/preview/components/button.demo.tsx +47 -0
  168. package/dist/hub-demo/preview/components/button.tsx +31 -0
  169. package/dist/hub-demo/preview/components/card.demo.tsx +26 -0
  170. package/dist/hub-demo/preview/components/card.tsx +20 -0
  171. package/dist/hub-demo/preview/components/input.demo.tsx +39 -0
  172. package/dist/hub-demo/preview/components/input.tsx +19 -0
  173. package/dist/hub-demo/preview/components/utils.ts +5 -0
  174. package/dist/hub-demo/preview/system.css +161 -0
  175. package/dist/hub-demo/public/data/demo-app.usage.bedd9c82fe.json +1 -0
  176. package/dist/hub-demo/public/data/demo.catalog.a605de2281.json +1 -0
  177. package/dist/hub-demo/public/data/gaps.129a93538d.json +1 -0
  178. package/dist/hub-demo/public/data/inventory.165a4f6408.json +1 -0
  179. package/dist/hub-demo/public/data/inventory.console.badge.ad0238784e.json +1 -0
  180. package/dist/hub-demo/public/data/inventory.console.button.3249daff35.json +1 -0
  181. package/dist/hub-demo/public/data/inventory.console.card.9ea88708ac.json +1 -0
  182. package/dist/hub-demo/public/data/inventory.console.dialog.8b6574d93a.json +1 -0
  183. package/dist/hub-demo/public/data/inventory.console.input.bdffb756a7.json +1 -0
  184. package/dist/hub-demo/public/data/inventory.console.link-as-button.1ce7faa1f3.json +1 -0
  185. package/dist/hub-demo/public/data/inventory.console.tabs.813e694c44.json +1 -0
  186. package/dist/hub-demo/public/data/inventory.extras.e5d06c6ff4.json +1 -0
  187. package/dist/hub-demo/public/data/inventory.site.badge.047a68f644.json +1 -0
  188. package/dist/hub-demo/public/data/inventory.site.button.720938384e.json +1 -0
  189. package/dist/hub-demo/public/data/inventory.site.card.d8df5f6873.json +1 -0
  190. package/dist/hub-demo/public/data/inventory.site.link-as-button.9c1f8a55bf.json +1 -0
  191. package/dist/hub-demo/public/data/inventory.site.tabs.59bd0200b9.json +1 -0
  192. package/dist/hub-demo/public/data/manifest.json +39 -0
  193. package/dist/hub-demo/public/data/specimens.console.dark.046471907d.css +786 -0
  194. package/dist/hub-demo/public/data/specimens.console.light.aaffa2d213.css +786 -0
  195. package/dist/hub-demo/public/data/specimens.site.dark.94a6706908.css +92 -0
  196. package/dist/hub-demo/public/data/specimens.site.light.3ddbc8d28d.css +92 -0
  197. package/dist/hub-demo/public/previews/button.dark.webp +0 -0
  198. package/dist/hub-demo/public/previews/button.light.webp +0 -0
  199. package/dist/hub-demo/public/previews/card.dark.webp +0 -0
  200. package/dist/hub-demo/public/previews/card.light.webp +0 -0
  201. package/dist/hub-demo/public/previews/input.dark.webp +0 -0
  202. package/dist/hub-demo/public/previews/input.light.webp +0 -0
  203. package/dist/hub-previews.js +173 -0
  204. package/dist/hub-server.js +6329 -0
  205. package/dist/hub-snapshot.js +573 -0
  206. package/dist/schema/youi.gaps.schema.json +235 -0
  207. package/dist/schema/youi.request.schema.json +229 -0
  208. package/dist/tailwind-worker.js +3 -3
  209. package/dist/youi.js +10 -8
  210. package/dist/youiyoux.js +10 -8
  211. package/package.json +4 -4
  212. package/dist/chunks/chunk-3ZHGONNA.js +0 -21797
@@ -0,0 +1,573 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __youiRequire } from "node:module"; import { dirname as __youiDir } from "node:path"; import { fileURLToPath as __youiPath } from "node:url"; const require = __youiRequire(import.meta.url); const __youiDirname = __youiDir(__youiPath(import.meta.url));
3
+ import {
4
+ loadPackage,
5
+ tryProject
6
+ } from "./chunks/chunk-XAEMVEYX.js";
7
+ import "./chunks/chunk-FVVL5JCY.js";
8
+ import "./chunks/chunk-WNTS7ZO4.js";
9
+
10
+ // ../../apps/web/scripts/snapshot.ts
11
+ import { execFileSync } from "node:child_process";
12
+ import { createHash } from "node:crypto";
13
+ import { existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
14
+ import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
15
+ import { parseArgs } from "node:util";
16
+
17
+ // ../../apps/web/src/data/inventory.ts
18
+ var ROLES = ["button", "link-as-button", "input", "card", "badge", "dialog", "tabs"];
19
+
20
+ // ../../apps/web/src/data/inventory-split.ts
21
+ var json = (value) => `${JSON.stringify(value)}
22
+ `;
23
+ var stemOf = (id) => id.toLowerCase().replace(/[^a-z0-9-]+/g, "-");
24
+ function splitInventory(report, specimens, name) {
25
+ const files = [];
26
+ const add = (stem, ext, text) => {
27
+ const file = name(stem, ext, text);
28
+ files.push({ name: file, text });
29
+ return file;
30
+ };
31
+ const projects = report.projects.map((p) => {
32
+ const built = specimens[p.id];
33
+ const specimenCss = built?.css ? { light: add(`specimens.${stemOf(p.id)}.light`, "css", built.css.light), dark: add(`specimens.${stemOf(p.id)}.dark`, "css", built.css.dark) } : null;
34
+ return { id: p.id, root: p.root, commit: p.commit, status: p.status, files: p.files, routes: p.routes, failed: p.failed.length, warnings: p.warnings, specimenCss, specimenNotes: built?.notes ?? ["no specimens were built: looks show their shape"] };
35
+ });
36
+ const roles = ROLES.flatMap((role) => {
37
+ const all = report.looks.filter((l) => l.role === role);
38
+ if (all.length === 0) return [];
39
+ const looks = all.filter((l) => !l.story);
40
+ const families = report.families.filter((f) => f.role === role);
41
+ const cells = {};
42
+ const chunks = {};
43
+ for (const project of report.projects) {
44
+ const mine = all.filter((l) => l.project === project.id);
45
+ const used = mine.filter((l) => !l.story);
46
+ cells[project.id] = { families: new Set(mine.flatMap((l) => l.family ? [l.family] : [])).size, looks: used.length };
47
+ if (mine.length === 0) continue;
48
+ const built = specimens[project.id];
49
+ const drawn = {};
50
+ const chunkLooks = mine.map((l) => {
51
+ const id = built?.looks[l.id];
52
+ const specimen = id ? built.specimens[id] : void 0;
53
+ if (id && specimen) drawn[id] = specimen;
54
+ return { id: l.id, file: l.file, line: l.line, column: l.column, tag: l.tag, kit: l.kit, family: l.family, shape: l.shape, specimen: id && specimen ? id : null, ...l.story ? { story: l.story } : {} };
55
+ });
56
+ const chunk = { schema: "youiyoux.inventory-chunk/v1", project: project.id, role, families: families.filter((f) => f.projects.includes(project.id)), looks: chunkLooks, specimens: drawn };
57
+ chunks[project.id] = add(`inventory.${stemOf(project.id)}.${role}`, "json", json(chunk));
58
+ }
59
+ return [{ role, looks: looks.length, unshaped: looks.filter((l) => l.family === null).length, families: families.length, shared: families.filter((f) => f.nearDuplicate && f.projects.length > 1).length, cells, chunks }];
60
+ });
61
+ const extras = { schema: "youiyoux.inventory-extras/v1", kits: report.kits, primitives: report.primitives, flags: report.flags };
62
+ const index = {
63
+ schema: "youiyoux.inventory-index/v1",
64
+ scanner: report.scanner,
65
+ generatedAt: report.generatedAt,
66
+ tolerance: report.tolerance,
67
+ projects,
68
+ // Families only stories have are drawn, but not counted among the families built.
69
+ summary: { ...report.summary, families: report.families.filter((f) => !f.authored).length, nearDuplicates: report.families.filter((f) => f.nearDuplicate).length, flags: report.flags.length },
70
+ roles,
71
+ extras: add("inventory.extras", "json", json(extras))
72
+ };
73
+ return { index, files };
74
+ }
75
+
76
+ // ../../apps/web/src/data/usage.ts
77
+ var EVERY_SCREEN = "*";
78
+ var UNROUTED = "(no screen)";
79
+
80
+ // ../../apps/web/src/data/screens.ts
81
+ function screenSlug(route) {
82
+ if (route === EVERY_SCREEN) return "app-shell";
83
+ if (route === UNROUTED) return "unrouted";
84
+ const slug = route.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
85
+ return slug || "root";
86
+ }
87
+
88
+ // ../../apps/web/scripts/snapshot.ts
89
+ var APP = resolve(__youiDirname, "..");
90
+ var TOOL = resolve(APP, "../..");
91
+ var DEFAULT_OUT = join(APP, "snapshot");
92
+ var DEMO_PROJECT = join(TOOL, "examples/demo-app");
93
+ var DEMO_INVENTORY = ["console", "site"].map((name) => join(TOOL, "packages/scanner/test/fixtures/inventory", name));
94
+ var STYLES_DIR = join(APP, "src/styles/generated");
95
+ var HASH_LENGTH = 10;
96
+ var HUB_PREFIX = "yx";
97
+ var SCOPE = ".system-scope";
98
+ var STAGE = ["color.paper", "color.surface", "color.background"];
99
+ var INK = ["color.ink", "color.foreground", "color.text"];
100
+ var HUB_TAILWIND_MAP = {
101
+ ...Object.fromEntries(["xs", "sm", "md", "lg", "xl", "full"].map((size) => [`radius-${size}`, `radius.${size}`])),
102
+ "font-sans": "font.sans",
103
+ "font-mono": "font.mono",
104
+ "ease-out": "easing.out"
105
+ };
106
+ var loadOptions = (values) => ({ ...values.config ? { configPath: resolve(values.config) } : {}, ...values.design ? { designRoot: resolve(values.design) } : {}, ...values.root !== void 0 ? { productRoot: resolve(values.root) } : {} });
107
+ var hash = (content) => createHash("sha256").update(content).digest("hex").slice(0, HASH_LENGTH);
108
+ var json2 = (value) => `${JSON.stringify(value)}
109
+ `;
110
+ var generated = (what) => `/* @generated by apps/web/scripts/snapshot.ts from ${what}. Do not edit: run \`pnpm data\`. */
111
+ `;
112
+ function write(path, content) {
113
+ mkdirSync(dirname(path), { recursive: true });
114
+ writeFileSync(path, content);
115
+ }
116
+ function definitionsCommit(root, paths) {
117
+ try {
118
+ const sha = execFileSync("git", ["-C", root, "log", "-1", "--format=%H", "--", ...paths], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
119
+ return sha || null;
120
+ } catch {
121
+ return null;
122
+ }
123
+ }
124
+ function aliasChain(token, byId) {
125
+ const chain = [token.id];
126
+ let next = token.aliasOf;
127
+ while (next && !chain.includes(next)) {
128
+ chain.push(next);
129
+ next = byId.get(next)?.aliasOf;
130
+ }
131
+ return chain;
132
+ }
133
+ function catalogTokens(system, prefix, tokens, darkOwn, lib) {
134
+ const byId = new Map(tokens.map((t) => [t.id, t]));
135
+ const elementId = (path) => `youi:${system}/token/${path}`;
136
+ return tokens.map((token) => ({
137
+ id: elementId(token.id),
138
+ path: token.id,
139
+ group: token.id.split(".")[0],
140
+ type: token.type,
141
+ cssVar: `--${prefix}-${token.cssName}`,
142
+ light: lib.cssValue(token.type, token.light),
143
+ dark: lib.cssValue(token.type, token.dark),
144
+ ...token.type === "typography" ? { lightValue: token.light } : {},
145
+ aliasChain: aliasChain(token, byId).map(elementId),
146
+ ...token.description ? { description: token.description } : {},
147
+ // What the style editor starts from: the values as written (aliases kept) and whether dark has its own.
148
+ ...token.source ? { source: token.source } : {},
149
+ darkOwn: darkOwn.has(token.id)
150
+ }));
151
+ }
152
+ function darkOverrides(repoRoot, config, core, lib) {
153
+ if (!config.themeModifier) return /* @__PURE__ */ new Set();
154
+ const resolverFile = join(repoRoot, config.tokens);
155
+ const layout = lib.resolverLayout(JSON.parse(readFileSync(resolverFile, "utf8")), config.themeModifier);
156
+ const files = layout.contexts[config.themeModifier.dark] ?? [];
157
+ return new Set(files.flatMap((ref) => core.flattenTokens({ file: ref, document: JSON.parse(readFileSync(join(dirname(resolverFile), ref), "utf8")) }).map((t) => t.path)));
158
+ }
159
+ function componentFiles(componentsRoot, sourceFile, support) {
160
+ return [sourceFile, ...support].map((file) => ({ path: basename(file), code: readFileSync(join(componentsRoot, file), "utf8") }));
161
+ }
162
+ function systemCss(name, tokens, contracts, output, lib) {
163
+ const prefix = output.cssVarPrefix;
164
+ const byId = new Map(tokens.map((t) => [t.id, t]));
165
+ const variable = (paths) => {
166
+ const token = paths.map((p) => byId.get(p)).find(Boolean);
167
+ return token ? `var(--${prefix}-${token.cssName})` : null;
168
+ };
169
+ const ref = (path, suffix = "") => `var(--${prefix}-${byId.get(path)?.cssName ?? path.replace(/\./g, "-")}${suffix})`;
170
+ const decl = (scheme) => tokens.flatMap((t) => lib.tokenVariables(t.type, t.source?.[scheme] ?? t[scheme], ref).map(([suffix, css]) => ` --${prefix}-${t.cssName}${suffix}: ${css};`)).join("\n");
171
+ const states = lib.stateVariables(contracts, tokens, prefix).map(([property, css]) => ` ${property}: ${css};`).join("\n");
172
+ const stage = [variable(STAGE) && ` background: ${variable(STAGE)};`, variable(INK) && ` color: ${variable(INK)};`].filter(Boolean).join("\n");
173
+ const theme = lib.renderTailwind(tokens, output, "").trim();
174
+ return `${generated(`the ${name} tokens`)}@source "./components";
175
+
176
+ ${SCOPE} {
177
+ color-scheme: light;
178
+ ${decl("light")}
179
+ ${states ? `${states}
180
+ ` : ""}${stage}
181
+ }
182
+
183
+ ${SCOPE}[data-scheme="dark"] {
184
+ color-scheme: dark;
185
+ ${decl("dark")}
186
+ }
187
+
188
+ ${theme}
189
+ `;
190
+ }
191
+ async function buildHubTokens(core, lib) {
192
+ const system = core.SystemConfig.parse({
193
+ id: "youiyoux",
194
+ name: "YouIyouX",
195
+ version: "0.1.0",
196
+ description: "The hub's own design language.",
197
+ tokens: "design/youiyoux.resolver.json",
198
+ themeModifier: { name: "theme", light: "light", dark: "dark" }
199
+ });
200
+ const output = core.OutputConfig.parse({ cssVarPrefix: HUB_PREFIX, targets: ["css-vars", "tailwind-v4"], tailwind: { includeAll: true, map: HUB_TAILWIND_MAP } });
201
+ const built = await lib.buildTokens(APP, system, output);
202
+ rmSync(STYLES_DIR, { recursive: true, force: true });
203
+ for (const file of built.files) write(join(STYLES_DIR, file.path), file.content);
204
+ }
205
+ function projectArg(values) {
206
+ if (values.project) return values.project;
207
+ if (values.config) return values.root !== void 0 ? dirname(resolve(values.config)) : void 0;
208
+ return values.design ? void 0 : DEMO_PROJECT;
209
+ }
210
+ async function readSource(values, core, scanner) {
211
+ const projectDir = projectArg(values);
212
+ if (projectDir) {
213
+ const project = await scanner.loadProject(projectDir, loadOptions(values));
214
+ const { report } = await scanner.scanProject(project);
215
+ return { designRoot: project.repo.root, projectDir: project.root, systemId: project.config.system, output: project.config.outputs, usage: core.ScanReport.parse(report) };
216
+ }
217
+ if (values.config) {
218
+ const configFile = resolve(values.config);
219
+ const config = core.ProjectConfig.parse(JSON.parse(readFileSync(configFile, "utf8")));
220
+ const designRoot = values.design ? resolve(values.design) : isAbsolute(config.source.path) ? config.source.path : resolve(dirname(configFile), config.source.path);
221
+ return { designRoot, systemId: config.system, output: config.outputs, usage: null };
222
+ }
223
+ return { designRoot: resolve(values.design), output: core.OutputConfig.parse({}), usage: null };
224
+ }
225
+ function writePreview(out, system, componentsRoot) {
226
+ const header = (from) => `// @generated from ${from} by apps/web/scripts/snapshot.ts. Do not edit.
227
+ `;
228
+ const files = /* @__PURE__ */ new Set([...system.components.map((c) => c.contract.source.file), ...system.config.support]);
229
+ for (const file of files) write(join(out, "components", basename(file)), `${header(`components/${file}`)}${readFileSync(join(componentsRoot, file), "utf8")}`);
230
+ let demos = 0;
231
+ for (const { dir } of system.components) {
232
+ for (const name of readdirSync(dir).filter((f) => f.endsWith(".demo.tsx"))) {
233
+ write(join(out, "components", name), `${header(relative(componentsRoot, join(dir, name)))}${readFileSync(join(dir, name), "utf8")}`);
234
+ demos++;
235
+ }
236
+ }
237
+ return demos;
238
+ }
239
+ function readScreensFile(dir, project) {
240
+ const path = join(dir, "screens.json");
241
+ const value = JSON.parse(readFileSync(path, "utf8"));
242
+ const valid = value.schema === "youiyoux.screens/v1" && value.project === project && typeof value.source === "string" && typeof value.capturedAt === "string" && typeof value.viewport?.width === "number" && typeof value.viewport.height === "number" && Array.isArray(value.screens) && value.screens.every((s) => typeof s.route === "string" && typeof s.path === "string");
243
+ if (!valid) throw new Error(`${path} is not a youiyoux.screens/v1 document for ${project}`);
244
+ return value;
245
+ }
246
+ function copyShot(dir, dataDir, project, slug, variant) {
247
+ const source = join(dir, `${slug}.${variant}.webp`);
248
+ if (!existsSync(source)) return null;
249
+ const bytes = readFileSync(source);
250
+ const file = `${project}.screen.${hash(bytes)}.webp`;
251
+ write(join(dataDir, file), bytes);
252
+ return file;
253
+ }
254
+ function copyPlaces(dir, dataDir, project, slug) {
255
+ const source = join(dir, `${slug}.places.json`);
256
+ if (!existsSync(source)) return null;
257
+ const bytes = readFileSync(source);
258
+ try {
259
+ if (JSON.parse(bytes.toString("utf8")).schema !== "youiyoux.places/v1") return null;
260
+ } catch {
261
+ return null;
262
+ }
263
+ const file = `${project}.places.${hash(bytes)}.json`;
264
+ write(join(dataDir, file), bytes);
265
+ return file;
266
+ }
267
+ function writeScreens(dir, dataDir, project) {
268
+ const file = readScreensFile(dir, project);
269
+ const screens = file.screens.map((screen) => {
270
+ const slug = screenSlug(screen.route);
271
+ const schemes = Object.fromEntries(
272
+ ["light", "dark"].flatMap((scheme) => {
273
+ const full = copyShot(dir, dataDir, project, slug, scheme);
274
+ const thumb = copyShot(dir, dataDir, project, slug, `${scheme}.thumb`);
275
+ return full && thumb ? [[scheme, { full, thumb }]] : [];
276
+ })
277
+ );
278
+ const places = copyPlaces(dir, dataDir, project, slug);
279
+ return { route: screen.route, path: screen.path, ...screen.note ? { note: screen.note } : {}, ...schemes, ...places ? { places } : {} };
280
+ });
281
+ return { source: file.source, capturedAt: file.capturedAt, viewport: file.viewport, screens };
282
+ }
283
+ function screensDir(explicit, projectDir) {
284
+ if (explicit) return resolve(explicit);
285
+ const conventional = projectDir ? join(projectDir, ".youi/screens") : null;
286
+ return conventional && existsSync(join(conventional, "screens.json")) ? conventional : null;
287
+ }
288
+ function previousSystemId(dataDir) {
289
+ try {
290
+ const manifest = JSON.parse(readFileSync(join(dataDir, "manifest.json"), "utf8"));
291
+ return manifest.systems?.[0]?.id;
292
+ } catch {
293
+ return void 0;
294
+ }
295
+ }
296
+ function dropPreviewsOfOtherSystem(out, previousId, systemId) {
297
+ if (previousId !== systemId) rmSync(join(out, "public/previews"), { recursive: true, force: true });
298
+ }
299
+ async function writeSystem(out, designRoot, systemId, output, commitOverride, { core, lib, scanner }) {
300
+ const repo = await core.loadDesignRepo(designRoot);
301
+ const system = core.getSystem(repo, systemId);
302
+ const { config } = system;
303
+ const built = await lib.buildTokens(repo.root, config, output);
304
+ const componentsRoot = join(repo.root, config.components);
305
+ const catalog = {
306
+ schema: "youiyoux.catalog/v1",
307
+ system: {
308
+ id: config.id,
309
+ name: config.name,
310
+ version: config.version,
311
+ description: config.description,
312
+ cssPrefix: output.cssVarPrefix,
313
+ design: config.design ? readFileSync(join(repo.root, config.design), "utf8") : ""
314
+ },
315
+ tokens: catalogTokens(config.id, output.cssVarPrefix, built.tokens, darkOverrides(repo.root, config, core, lib), lib),
316
+ components: system.components.map(({ contract }) => ({ contract, files: componentFiles(componentsRoot, contract.source.file, config.support) })),
317
+ // Each rule with how youiyoux check executes it, so the hub never shows an uncompilable rule as enforced.
318
+ rules: system.rules.map((rule) => ({ ...rule, execution: scanner.ruleCapability(rule) }))
319
+ };
320
+ const catalogText = json2(catalog);
321
+ const catalogFile = `${config.id}.catalog.${hash(catalogText)}.json`;
322
+ write(join(out, "public/data", catalogFile), catalogText);
323
+ const previewDir = join(out, "preview");
324
+ rmSync(previewDir, { recursive: true, force: true });
325
+ write(join(previewDir, "system.css"), systemCss(config.name, built.tokens, system.components.map((c) => c.contract), output, lib));
326
+ const demos = writePreview(previewDir, system, componentsRoot);
327
+ const commit = commitOverride ?? definitionsCommit(repo.root, ["youi.config.json", dirname(config.tokens), config.components, config.rules, ...config.design ? [config.design] : []]);
328
+ const summary = `${config.name} from ${repo.root} @ ${commit ?? "unknown"}: ${catalog.tokens.length} tokens, ${catalog.components.length} components (${demos} demos), ${catalog.rules.length} rules`;
329
+ return { id: config.id, name: config.name, components: system.components.map((c) => c.contract.name), catalogFile, commit, summary };
330
+ }
331
+ function writeUsage(dataDir, report, screens) {
332
+ const text = json2(report);
333
+ const file = `${report.project}.usage.${hash(text)}.json`;
334
+ write(join(dataDir, file), text);
335
+ return { project: report.project, file, ...screens ? { screens } : {} };
336
+ }
337
+ function writeInventory(dataDir, inventory, specimens = {}) {
338
+ const { index, files } = splitInventory(inventory, specimens, (stem, ext, text2) => `${stem}.${hash(text2)}.${ext}`);
339
+ for (const f of files) write(join(dataDir, f.name), f.text);
340
+ const text = json2(index);
341
+ const file = `inventory.${hash(text)}.json`;
342
+ write(join(dataDir, file), text);
343
+ return { file, files: files.map((f) => f.name) };
344
+ }
345
+ function inventoryRoots(inventory, path) {
346
+ const bases = path ? [process.cwd(), dirname(resolve(path))] : [TOOL];
347
+ const roots = /* @__PURE__ */ new Map();
348
+ for (const project of inventory.projects) {
349
+ const root = bases.map((base) => resolve(base, project.root)).find((dir) => existsSync(join(dir, "package.json")));
350
+ if (root) roots.set(project.id, root);
351
+ }
352
+ return roots;
353
+ }
354
+ function configuredSpecimenCss(values, core) {
355
+ if (!values.config) return null;
356
+ const configFile = resolve(values.config);
357
+ const config = core.ProjectConfig.parse(JSON.parse(readFileSync(configFile, "utf8")));
358
+ const sheets = config.specimens?.css;
359
+ if (!sheets?.length) return null;
360
+ const root = values.root !== void 0 ? resolve(values.root || ".") : config.root ? resolve(dirname(configFile), config.root) : dirname(configFile);
361
+ return { root, sheets, from: configFile };
362
+ }
363
+ var realOr = (path) => {
364
+ try {
365
+ return realpathSync(path);
366
+ } catch {
367
+ return resolve(path);
368
+ }
369
+ };
370
+ function sheetReport(id, used, skipped = []) {
371
+ const left = skipped.map((line) => ` ${line}`);
372
+ if (used.length === 0) return [`specimens ${id}: no stylesheet`, ...left];
373
+ return [`specimens ${id}: ${used.length} stylesheet${used.length === 1 ? "" : "s"}, in page order`, ...used.map((line, i) => ` ${i + 1}. ${line}`), ...left];
374
+ }
375
+ async function buildSpecimens(inventory, roots, scanner, configured = null, log = (line) => process.stdout.write(`${line}
376
+ `)) {
377
+ const out = {};
378
+ let matched = false;
379
+ for (const project of inventory.projects) {
380
+ const root = roots.get(project.id);
381
+ if (!root) {
382
+ out[project.id] = { css: null, specimens: {}, looks: {}, notes: [`${project.root} is not on this machine: looks show their shape`] };
383
+ continue;
384
+ }
385
+ const css = configured && realOr(configured.root) === realOr(root) ? { sheets: configured.sheets, from: configured.from } : null;
386
+ matched ||= css !== null;
387
+ try {
388
+ const built = await scanner.projectSpecimens({ id: project.id, root, commit: project.commit, looks: inventory.looks.filter((l) => l.project === project.id) }, css ? { css } : {});
389
+ out[project.id] = { css: built.css, specimens: built.specimens, looks: built.looks, notes: [`CSS: ${built.tailwind}`, ...built.used, ...built.skipped, ...built.warnings], try: { root, tsconfig: built.tsconfig } };
390
+ for (const line of sheetReport(project.id, built.used, built.skipped)) log(line);
391
+ } catch (error) {
392
+ out[project.id] = { css: null, specimens: {}, looks: {}, notes: [`specimens failed: ${error instanceof Error ? error.message : String(error)}`] };
393
+ }
394
+ }
395
+ if (configured && !matched) log(`specimens.css in ${configured.from}: its product ${configured.root} is not an inventoried project on this machine; not used`);
396
+ return out;
397
+ }
398
+ function tryIndex(out, inventory, specimens, scanner) {
399
+ const projects = {};
400
+ for (const project of inventory.projects) {
401
+ const built = specimens[project.id];
402
+ if (!built?.try) continue;
403
+ const looks = inventory.looks.filter((l) => l.project === project.id);
404
+ projects[project.id] = tryProject(relative(out, built.try.root) || ".", built.try.tsconfig, looks, built.looks, built.specimens, (recipe, role) => scanner.browserLookOf(recipe, role));
405
+ }
406
+ return { schema: "youiyoux.try/v1", projects };
407
+ }
408
+ async function writeInventoryWithSpecimens(out, inventory, path, libs, values) {
409
+ const specimens = await buildSpecimens(inventory, inventoryRoots(inventory, path), libs.scanner, configuredSpecimenCss(values, libs.core));
410
+ write(join(out, "try.json"), `${JSON.stringify(tryIndex(out, inventory, specimens, libs.scanner), null, 2)}
411
+ `);
412
+ return writeInventory(join(out, "public/data"), inventory, specimens);
413
+ }
414
+ async function readInventory(path, isDefault, { core, scanner }) {
415
+ if (path) return core.parseDefinition(resolve(path), readFileSync(resolve(path), "utf8"), core.InventoryReport);
416
+ return isDefault ? core.InventoryReport.parse(await scanner.buildInventory(DEMO_INVENTORY, { cwd: TOOL })) : null;
417
+ }
418
+ function writeDetect(file, dataDir, core) {
419
+ const report = core.DetectReport.parse(JSON.parse(readFileSync(file, "utf8")));
420
+ const base = dirname(resolve(file));
421
+ const shots = [];
422
+ const elements = report.elements.map(({ screenshot, ...element }) => {
423
+ const source = screenshot ? join(base, screenshot) : null;
424
+ if (!source || !existsSync(source)) return element;
425
+ const bytes = readFileSync(source);
426
+ const name2 = `detect.shot.${hash(bytes)}.png`;
427
+ write(join(dataDir, name2), bytes);
428
+ shots.push(name2);
429
+ return { ...element, screenshot: name2 };
430
+ });
431
+ const text = json2({ ...report, elements });
432
+ const name = `detect.${hash(text)}.json`;
433
+ write(join(dataDir, name), text);
434
+ return { file: name, name: report.target.name, kind: report.target.kind, shots };
435
+ }
436
+ var DISCOVER_LISTINGS_MAX = 2e3;
437
+ async function writeDiscover(dataDir, cacheDir, discover) {
438
+ const index = await discover.readIndex(cacheDir);
439
+ if (!index) return null;
440
+ const ordered = [...index.entries].sort((a, b) => Number(discover.sourceClassOf(b) === "official") - Number(discover.sourceClassOf(a) === "official") || (b.signals?.weeklyDownloads ?? b.signals?.via?.weeklyDownloads ?? -1) - (a.signals?.weeklyDownloads ?? a.signals?.via?.weeklyDownloads ?? -1) || a.id.localeCompare(b.id));
441
+ const card = (entry) => {
442
+ const { score: _score, why: _why, ...hit } = discover.hitOf(entry, 0, []);
443
+ return hit;
444
+ };
445
+ const entries = ordered.slice(0, DISCOVER_LISTINGS_MAX).map((entry) => ({ ...card(entry), registry: discover.registryName(entry), roles: discover.rolesOf(entry), style: discover.styleOf(entry), text: discover.searchTextOf(entry) }));
446
+ const text = json2({ schema: "youiyoux.discover-listings/v1", builtAt: index.builtAt, total: index.entries.length, capped: index.entries.length > entries.length, note: discover.DISCOVER_RULE, entries });
447
+ const file = `discover.${hash(text)}.json`;
448
+ write(join(dataDir, file), text);
449
+ return file;
450
+ }
451
+ function discoverCache(values, out, discover) {
452
+ if (values.discover) return resolve(values.discover);
453
+ if (out === DEFAULT_OUT) return null;
454
+ const dir = discover.discoverCacheDir();
455
+ return existsSync(join(dir, discover.INDEX_FILE)) ? dir : null;
456
+ }
457
+ async function writeGaps(dataDir, inventory, path, system, discoverDir, discoverArg, discover) {
458
+ const store = discoverDir ? await discover.readCatalog(discoverDir, discover.discoverIndexPath(discoverArg ? discoverDir : void 0)).catch(() => null) : null;
459
+ const report = await discover.buildGaps({ inventory, system: { name: system.name, components: system.components }, dependencies: discover.declaredPackages(inventoryRoots(inventory, path)), now: new Date(inventory.generatedAt) }, store);
460
+ const text = json2(report);
461
+ const file = `gaps.${hash(text)}.json`;
462
+ write(join(dataDir, file), text);
463
+ return file;
464
+ }
465
+ function usageFiles(usage) {
466
+ return usage.flatMap((u) => [u.file, ...(u.screens?.screens ?? []).flatMap((shot) => [...[shot.light, shot.dark].flatMap((f) => f ? [f.full, f.thumb] : []), ...shot.places ? [shot.places] : []])]);
467
+ }
468
+ function writeManifest(dataDir, system, usage, live, inventory, detect, discover, gaps) {
469
+ const manifest = { schema: "youiyoux.manifest/v1", source: { commit: system.commit }, systems: [{ id: system.id, catalog: system.catalogFile, usage }], ...inventory ? { inventory: inventory.file, inventoryFiles: inventory.files } : {}, ...detect ? { detect: { file: detect.file, name: detect.name, kind: detect.kind } } : {}, ...discover ? { discover } : {}, ...gaps ? { gaps } : {}, ...live ? { live } : {} };
470
+ const file = join(dataDir, "manifest.json");
471
+ write(`${file}.tmp`, `${JSON.stringify(manifest, null, 2)}
472
+ `);
473
+ renameSync(`${file}.tmp`, file);
474
+ }
475
+ function pruneData(dataDir, keep) {
476
+ for (const name of readdirSync(dataDir)) if (name !== "manifest.json" && !keep.has(name)) rmSync(join(dataDir, name), { force: true });
477
+ }
478
+ async function watchSnapshot(values, out, libs) {
479
+ const dataDir = join(out, "public/data");
480
+ mkdirSync(dataDir, { recursive: true });
481
+ const read = await readInventory(values.inventory, false, libs);
482
+ const inventory = read ? await writeInventoryWithSpecimens(out, read, values.inventory, libs, values) : null;
483
+ const detect = values.detect ? writeDetect(values.detect, dataDir, libs.core) : null;
484
+ const discoverDir = discoverCache(values, out, libs.discover);
485
+ const discover = discoverDir ? await writeDiscover(dataDir, discoverDir, libs.discover) : null;
486
+ const root = projectArg(values) ?? (values.config ? dirname(resolve(values.config)) : DEMO_PROJECT);
487
+ let previousId = previousSystemId(dataDir);
488
+ let system = null;
489
+ let systemOf = null;
490
+ let usage = [];
491
+ let shots;
492
+ let previous = /* @__PURE__ */ new Set();
493
+ let gaps = null;
494
+ const stamp = () => (/* @__PURE__ */ new Date()).toISOString();
495
+ const watcher = await libs.scanner.ProjectWatcher.start({
496
+ root,
497
+ load: loadOptions(values),
498
+ job: async (project, cache) => {
499
+ if (project !== systemOf) {
500
+ system = await writeSystem(out, project.repo.root, project.config.system, project.config.outputs, values.commit, libs);
501
+ dropPreviewsOfOtherSystem(out, previousId, system.id);
502
+ previousId = system.id;
503
+ systemOf = project;
504
+ if (read) gaps = await writeGaps(dataDir, read, values.inventory, system, discoverDir, values.discover, libs.discover);
505
+ }
506
+ const scan = await libs.scanner.scanProject(project, { cache });
507
+ const report = libs.core.ScanReport.parse(scan.report);
508
+ return { report, rules: libs.scanner.describeIdentity(scan.identity) };
509
+ },
510
+ onUpdate: (update) => {
511
+ if (!system) return void process.stderr.write(`youiyoux ui: ${update.status === "failed" ? update.error : "no system"}
512
+ `);
513
+ if (update.status === "ok") {
514
+ const { report } = update.result;
515
+ if (shots === void 0) {
516
+ const dir = screensDir(values.screens, systemOf?.root ?? resolve(root));
517
+ shots = dir ? writeScreens(dir, dataDir, report.project) : null;
518
+ }
519
+ usage = [writeUsage(dataDir, report, shots)];
520
+ }
521
+ const live = update.status === "ok" ? { generation: update.generation, status: update.result.report.status, updatedAt: stamp(), rules: update.result.rules } : { generation: update.generation, status: "failed", updatedAt: stamp(), message: update.error };
522
+ writeManifest(dataDir, system, usage, live, inventory, detect, discover, gaps);
523
+ const current = /* @__PURE__ */ new Set([system.catalogFile, ...usageFiles(usage), ...inventory ? [inventory.file, ...inventory.files] : [], ...detect ? [detect.file, ...detect.shots] : [], ...discover ? [discover] : [], ...gaps ? [gaps] : []]);
524
+ pruneData(dataDir, /* @__PURE__ */ new Set([...current, ...previous]));
525
+ previous = current;
526
+ process.stdout.write(`youiyoux ui: generation ${update.generation} ${live.status}${live.message ? `: ${live.message}` : ""}
527
+ `);
528
+ }
529
+ });
530
+ const stop = () => {
531
+ watcher.close();
532
+ process.exit(0);
533
+ };
534
+ process.once("SIGINT", stop);
535
+ process.once("SIGTERM", stop);
536
+ }
537
+ async function libraries() {
538
+ return { core: await loadPackage("core"), lib: await loadPackage("tokens"), scanner: await loadPackage("scanner"), discover: await loadPackage("discover") };
539
+ }
540
+ async function main() {
541
+ const { values } = parseArgs({ options: { design: { type: "string" }, project: { type: "string" }, config: { type: "string" }, root: { type: "string" }, out: { type: "string" }, commit: { type: "string" }, screens: { type: "string" }, inventory: { type: "string" }, detect: { type: "string" }, discover: { type: "string" }, watch: { type: "boolean", default: false } } });
542
+ const libs = await libraries();
543
+ const out = resolve(values.out ?? DEFAULT_OUT);
544
+ if (values.watch) {
545
+ if (out === DEFAULT_OUT) throw new Error("--watch writes a live snapshot; pass --out (the committed default snapshot is never watched)");
546
+ return watchSnapshot(values, out, libs);
547
+ }
548
+ if (values.detect && out === DEFAULT_OUT) throw new Error("--detect adds a report you ran; pass --out (the committed demo snapshot never holds one)");
549
+ const dataDir = join(out, "public/data");
550
+ const source = await readSource(values, libs.core, libs.scanner);
551
+ const previousId = previousSystemId(dataDir);
552
+ rmSync(dataDir, { recursive: true, force: true });
553
+ const system = await writeSystem(out, source.designRoot, source.systemId, source.output, values.commit, libs);
554
+ dropPreviewsOfOtherSystem(out, previousId, system.id);
555
+ const shotsDir = source.usage ? screensDir(values.screens, source.projectDir) : null;
556
+ const shots = source.usage && shotsDir ? writeScreens(shotsDir, dataDir, source.usage.project) : null;
557
+ const usage = source.usage ? [writeUsage(dataDir, source.usage, shots)] : [];
558
+ const read = await readInventory(values.inventory, out === DEFAULT_OUT, libs);
559
+ const inventory = read ? await writeInventoryWithSpecimens(out, read, values.inventory, libs, values) : null;
560
+ if (!read) rmSync(join(out, "try.json"), { force: true });
561
+ const detect = values.detect ? writeDetect(values.detect, dataDir, libs.core) : null;
562
+ const discoverDir = discoverCache(values, out, libs.discover);
563
+ const discover = discoverDir ? await writeDiscover(dataDir, discoverDir, libs.discover) : null;
564
+ const gaps = read ? await writeGaps(dataDir, read, values.inventory, system, discoverDir, values.discover, libs.discover) : null;
565
+ writeManifest(dataDir, system, usage, void 0, inventory, detect, discover, gaps);
566
+ if (out === DEFAULT_OUT) await buildHubTokens(libs.core, libs.lib);
567
+ process.stdout.write(`snapshot of ${system.summary}; ${usage.length ? `usage map of ${usage[0].project}${shots ? ` with ${shots.screens.length} screens` : ""}` : "no usage map"}${inventory ? `; ${inventory.file} (+${inventory.files.length} chunks and stylesheets)` : ""}${gaps ? `; ${gaps}` : ""}${detect ? `; detect report of ${detect.name} (${detect.shots.length} screenshots)` : ""}${discover ? `; Discover listings ${discover}` : ""} \u2192 ${relative(process.cwd(), out) || "."}
568
+ `);
569
+ }
570
+ if (false) await main();
571
+
572
+ // src/hub-snapshot.js
573
+ await main();