handoff-app 1.2.2-7 → 2.0.0-1

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 (351) hide show
  1. package/Changelog.md +37 -15
  2. package/README.md +372 -118
  3. package/dist/app-builder/build.d.ts +41 -2
  4. package/dist/app-builder/build.js +455 -18
  5. package/dist/app-builder/client-config.d.ts +15 -2
  6. package/dist/app-builder/client-config.js +43 -4
  7. package/dist/app-builder/config-diff/snapshot.d.ts +1 -6
  8. package/dist/app-builder/config-diff/snapshot.js +2 -9
  9. package/dist/app-builder/index.d.ts +1 -1
  10. package/dist/app-builder/index.js +3 -1
  11. package/dist/app-builder/nav-shell.d.ts +23 -0
  12. package/dist/app-builder/nav-shell.js +80 -0
  13. package/dist/app-builder/paths.js +25 -1
  14. package/dist/app-builder/static-export.d.ts +17 -0
  15. package/dist/app-builder/static-export.js +206 -0
  16. package/dist/app-builder/vercel-output.d.ts +39 -0
  17. package/dist/app-builder/vercel-output.js +259 -0
  18. package/dist/app-builder/watchers/utils.d.ts +2 -0
  19. package/dist/app-builder/watchers.d.ts +14 -4
  20. package/dist/app-builder/watchers.js +123 -28
  21. package/dist/app-builder/websocket.js +1 -1
  22. package/dist/artifacts/index.d.ts +2 -0
  23. package/dist/artifacts/index.js +16 -0
  24. package/dist/artifacts/types.d.ts +136 -0
  25. package/dist/artifacts/types.js +24 -0
  26. package/dist/artifacts/url.d.ts +67 -0
  27. package/dist/artifacts/url.js +116 -0
  28. package/dist/cache/build-cache.js +48 -4
  29. package/dist/cli.js +0 -0
  30. package/dist/commands/build/app.js +1 -2
  31. package/dist/commands/build/index.d.ts +17 -0
  32. package/dist/commands/build/index.js +66 -0
  33. package/dist/commands/checkout/index.d.ts +24 -0
  34. package/dist/commands/checkout/index.js +71 -0
  35. package/dist/commands/db/migrate.d.ts +11 -0
  36. package/dist/commands/db/migrate.js +33 -0
  37. package/dist/commands/index.js +8 -0
  38. package/dist/commands/publish/index.d.ts +21 -0
  39. package/dist/commands/publish/index.js +68 -0
  40. package/dist/config/defaults.js +15 -1
  41. package/dist/config/loader.js +6 -1
  42. package/dist/config/normalizers/declaration.js +4 -1
  43. package/dist/config/normalizers/page.d.ts +18 -0
  44. package/dist/config/normalizers/page.js +34 -0
  45. package/dist/config/normalizers/pattern.js +7 -1
  46. package/dist/config/runtime.d.ts +4 -0
  47. package/dist/config/runtime.js +53 -5
  48. package/dist/index.d.ts +65 -1
  49. package/dist/index.js +123 -3
  50. package/dist/nav/index.d.ts +83 -0
  51. package/dist/nav/index.js +9 -0
  52. package/dist/nav/registry.d.ts +15 -0
  53. package/dist/nav/registry.js +42 -0
  54. package/dist/nav/resolver.d.ts +8 -0
  55. package/dist/nav/resolver.js +192 -0
  56. package/dist/nav/workspace.d.ts +18 -0
  57. package/dist/nav/workspace.js +103 -0
  58. package/dist/pipeline/styles.js +7 -35
  59. package/dist/pipeline/token-transformers.d.ts +45 -0
  60. package/dist/pipeline/token-transformers.js +71 -0
  61. package/dist/registry/asset-storage/adapters/vercel-blob.d.ts +17 -0
  62. package/dist/registry/asset-storage/adapters/vercel-blob.js +87 -0
  63. package/dist/registry/asset-storage/define.d.ts +10 -0
  64. package/dist/registry/asset-storage/define.js +13 -0
  65. package/dist/registry/asset-storage/resolve.d.ts +45 -0
  66. package/dist/registry/asset-storage/resolve.js +36 -0
  67. package/dist/registry/asset-storage/types.d.ts +51 -0
  68. package/dist/registry/asset-storage/types.js +9 -0
  69. package/dist/registry/assets/layout.d.ts +22 -0
  70. package/dist/registry/assets/layout.js +30 -0
  71. package/dist/registry/assets/sets.d.ts +18 -0
  72. package/dist/registry/assets/sets.js +44 -0
  73. package/dist/registry/assets/transfer.d.ts +45 -0
  74. package/dist/registry/assets/transfer.js +11 -0
  75. package/dist/registry/checkout/assets.d.ts +16 -0
  76. package/dist/registry/checkout/assets.js +150 -0
  77. package/dist/registry/checkout/index.d.ts +33 -0
  78. package/dist/registry/checkout/index.js +610 -0
  79. package/dist/registry/checkout/tokens.d.ts +15 -0
  80. package/dist/registry/checkout/tokens.js +171 -0
  81. package/dist/registry/client.d.ts +61 -0
  82. package/dist/registry/client.js +211 -0
  83. package/dist/registry/connection.d.ts +30 -0
  84. package/dist/registry/connection.js +36 -0
  85. package/dist/registry/db/adapter.d.ts +43 -0
  86. package/dist/registry/db/adapter.js +59 -0
  87. package/dist/registry/db/client.d.ts +35 -0
  88. package/dist/registry/db/client.js +94 -0
  89. package/dist/registry/db/index.d.ts +5 -0
  90. package/dist/registry/db/index.js +24 -0
  91. package/dist/registry/db/migrate.d.ts +23 -0
  92. package/dist/registry/db/migrate.js +64 -0
  93. package/dist/registry/db/schema.d.ts +4869 -0
  94. package/dist/registry/db/schema.js +347 -0
  95. package/dist/registry/path.d.ts +4 -0
  96. package/dist/registry/path.js +31 -0
  97. package/dist/registry/publish/artifacts.d.ts +16 -0
  98. package/dist/registry/publish/artifacts.js +132 -0
  99. package/dist/registry/publish/assets.d.ts +16 -0
  100. package/dist/registry/publish/assets.js +129 -0
  101. package/dist/registry/publish/errors.d.ts +5 -0
  102. package/dist/registry/publish/errors.js +26 -0
  103. package/dist/registry/publish/index.d.ts +27 -0
  104. package/dist/registry/publish/index.js +126 -0
  105. package/dist/registry/publish/package.d.ts +27 -0
  106. package/dist/registry/publish/package.js +257 -0
  107. package/dist/registry/publish/publish-build.d.ts +12 -0
  108. package/dist/registry/publish/publish-build.js +43 -0
  109. package/dist/registry/publish/tokens.d.ts +18 -0
  110. package/dist/registry/publish/tokens.js +112 -0
  111. package/dist/registry/tokens/sets.d.ts +59 -0
  112. package/dist/registry/tokens/sets.js +109 -0
  113. package/dist/registry/tokens/transfer.d.ts +48 -0
  114. package/dist/registry/tokens/transfer.js +10 -0
  115. package/dist/registry/transfer.d.ts +75 -0
  116. package/dist/registry/transfer.js +11 -0
  117. package/dist/store/filesystem-assets.d.ts +17 -0
  118. package/dist/store/filesystem-assets.js +147 -0
  119. package/dist/store/filesystem.d.ts +76 -0
  120. package/dist/store/filesystem.js +208 -0
  121. package/dist/store/index.d.ts +20 -0
  122. package/dist/store/index.js +38 -0
  123. package/dist/store/registry.d.ts +77 -0
  124. package/dist/store/registry.js +350 -0
  125. package/dist/store/source-files.d.ts +24 -0
  126. package/dist/store/source-files.js +147 -0
  127. package/dist/store/types.d.ts +185 -0
  128. package/dist/store/types.js +12 -0
  129. package/dist/transformers/plugins/csf-render.js +17 -8
  130. package/dist/transformers/plugins/handlebars-previews.js +10 -3
  131. package/dist/transformers/plugins/ssr-render.js +116 -49
  132. package/dist/transformers/preview/component/api.js +3 -1
  133. package/dist/transformers/preview/component/artifacts.js +8 -1
  134. package/dist/transformers/preview/component/builder.js +13 -5
  135. package/dist/transformers/preview/component/css.js +9 -1
  136. package/dist/transformers/preview/component/javascript.d.ts +9 -3
  137. package/dist/transformers/preview/component/javascript.js +45 -17
  138. package/dist/transformers/preview/component/shared-artifacts.d.ts +83 -0
  139. package/dist/transformers/preview/component/shared-artifacts.js +92 -0
  140. package/dist/transformers/preview/component.js +5 -2
  141. package/dist/transformers/preview/pattern/builder.js +28 -9
  142. package/dist/transformers/preview/pattern/html.d.ts +13 -10
  143. package/dist/transformers/preview/pattern/html.js +62 -27
  144. package/dist/transformers/preview/types.d.ts +38 -0
  145. package/dist/transformers/utils/handlebars.d.ts +3 -0
  146. package/dist/transformers/utils/handlebars.js +19 -5
  147. package/dist/types/config.d.ts +124 -31
  148. package/dist/utils/menu-shell.d.ts +60 -0
  149. package/dist/utils/menu-shell.js +221 -0
  150. package/dist/utils/stable-stringify.d.ts +2 -0
  151. package/dist/utils/stable-stringify.js +8 -0
  152. package/docs/cli.md +4 -2
  153. package/drizzle/0000_init_registry_storage.sql +95 -0
  154. package/drizzle/0001_add_review_metadata.sql +2 -0
  155. package/drizzle/0002_add_pages.sql +28 -0
  156. package/drizzle/0003_add_tokens.sql +29 -0
  157. package/drizzle/0004_add_assets.sql +37 -0
  158. package/drizzle/meta/0000_snapshot.json +642 -0
  159. package/drizzle/meta/0001_snapshot.json +654 -0
  160. package/drizzle/meta/0002_snapshot.json +835 -0
  161. package/drizzle/meta/0003_snapshot.json +1023 -0
  162. package/drizzle/meta/0004_snapshot.json +1252 -0
  163. package/drizzle/meta/_journal.json +41 -0
  164. package/drizzle.config.ts +16 -0
  165. package/package.json +10 -1
  166. package/src/app/components/Component/Preview.tsx +3 -2
  167. package/src/app/components/Component/RegistryActions.tsx +150 -0
  168. package/src/app/components/Foundations/DisplayLogo.tsx +11 -3
  169. package/src/app/components/Layout/Header.tsx +21 -3
  170. package/src/app/components/Layout/Main.tsx +11 -3
  171. package/src/app/components/Navigation/MainNav.tsx +4 -2
  172. package/src/app/components/Navigation/MobileNav.tsx +4 -2
  173. package/src/app/components/Navigation/SideNav.tsx +46 -11
  174. package/src/app/components/NotFound.tsx +24 -0
  175. package/src/app/components/context/NavProvider.tsx +71 -0
  176. package/src/app/components/old/Header.tsx +3 -3
  177. package/src/app/components/util/index.ts +203 -380
  178. package/src/app/components/util/useCollectionAssets.ts +125 -0
  179. package/src/app/components/util/useFoundationTokens.ts +67 -0
  180. package/src/app/generated/default-pages.json +1 -0
  181. package/src/app/generated/nav-shell.json +1 -0
  182. package/src/app/lib/api/query.ts +6 -0
  183. package/src/app/lib/api/redact.ts +46 -0
  184. package/src/app/lib/asset-storage.ts +81 -0
  185. package/src/app/lib/docs-api/artifacts.ts +116 -0
  186. package/src/app/lib/docs-api/backend.ts +151 -0
  187. package/src/app/lib/docs-api/errors.ts +52 -0
  188. package/src/app/lib/docs-api/handler.ts +34 -0
  189. package/src/app/lib/docs-api/index.ts +7 -0
  190. package/src/app/lib/docs-api/records.ts +189 -0
  191. package/src/app/lib/docs-api/registry.ts +130 -0
  192. package/src/app/lib/docs-api/runtime-config.ts +173 -0
  193. package/src/app/lib/docs-api/serve.ts +37 -0
  194. package/src/app/lib/docs-api/token-detail.ts +19 -0
  195. package/src/app/lib/registry-api/allowlist.ts +163 -0
  196. package/src/app/lib/registry-api/asset-transfer.ts +363 -0
  197. package/src/app/lib/registry-api/auth.ts +68 -0
  198. package/src/app/lib/registry-api/entity-routes.ts +197 -0
  199. package/src/app/lib/registry-api/errors.ts +51 -0
  200. package/src/app/lib/registry-api/files.ts +135 -0
  201. package/src/app/lib/registry-api/handler.ts +96 -0
  202. package/src/app/lib/registry-api/index.ts +4 -0
  203. package/src/app/lib/registry-api/meta.ts +87 -0
  204. package/src/app/lib/registry-api/revalidate.ts +36 -0
  205. package/src/app/lib/registry-api/store.ts +348 -0
  206. package/src/app/lib/registry-api/token-transfer.ts +231 -0
  207. package/src/app/lib/registry-api/transfer.ts +513 -0
  208. package/src/app/lib/registry-api/validation.ts +74 -0
  209. package/src/app/lib/registry-connection.ts +58 -0
  210. package/src/app/lib/utils.ts +14 -0
  211. package/src/app/next.config.mjs +72 -13
  212. package/src/app/pages/[...slug]/index.tsx +74 -20
  213. package/src/app/pages/_app.tsx +5 -2
  214. package/src/app/pages/api/docs/artifacts/[...artifactPath].ts +16 -0
  215. package/src/app/pages/api/docs/assets/[collection]/[...path].ts +50 -0
  216. package/src/app/pages/api/docs/assets/[collection]/index.ts +22 -0
  217. package/src/app/pages/api/docs/components/[id]/assets/[asset].ts +33 -0
  218. package/src/app/pages/api/docs/components/[id]/inspect/[previewId].ts +20 -0
  219. package/src/app/pages/api/docs/components/[id]/previews/[previewId].ts +21 -0
  220. package/src/app/pages/api/docs/components/[id].ts +24 -0
  221. package/src/app/pages/api/docs/components.json.ts +12 -0
  222. package/src/app/pages/api/docs/nav.json.ts +48 -0
  223. package/src/app/pages/api/docs/patterns/[id]/preview.ts +19 -0
  224. package/src/app/pages/api/docs/patterns/[id].ts +24 -0
  225. package/src/app/pages/api/docs/patterns.json.ts +12 -0
  226. package/src/app/pages/api/docs/tokens/components/[id].ts +30 -0
  227. package/src/app/pages/api/docs/tokens/foundations/[type].ts +32 -0
  228. package/src/app/pages/api/registry/components/[id]/files/[...filePath].ts +19 -0
  229. package/src/app/pages/api/registry/components/[id]/files/index.ts +19 -0
  230. package/src/app/pages/api/registry/components/[id].ts +20 -0
  231. package/src/app/pages/api/registry/components/index.ts +19 -0
  232. package/src/app/pages/api/registry/health.ts +20 -0
  233. package/src/app/pages/api/registry/patterns/[id]/files/[...filePath].ts +19 -0
  234. package/src/app/pages/api/registry/patterns/[id]/files/index.ts +19 -0
  235. package/src/app/pages/api/registry/patterns/[id].ts +20 -0
  236. package/src/app/pages/api/registry/patterns/index.ts +19 -0
  237. package/src/app/pages/api/registry/transfer/[kind]/[id].ts +39 -0
  238. package/src/app/pages/api/registry/transfer/assets/[collection].ts +24 -0
  239. package/src/app/pages/api/registry/transfer/assets/blobs/[hash].ts +23 -0
  240. package/src/app/pages/api/registry/transfer/assets/blobs/have.ts +11 -0
  241. package/src/app/pages/api/registry/transfer/assets/index.ts +10 -0
  242. package/src/app/pages/api/registry/transfer/tokens/[...setId].ts +26 -0
  243. package/src/app/pages/api/registry/transfer/tokens/index.ts +11 -0
  244. package/src/app/pages/assets/fonts.tsx +41 -17
  245. package/src/app/pages/assets/index.tsx +2 -2
  246. package/src/app/pages/assets/logos.tsx +6 -3
  247. package/src/app/pages/foundations/colors.tsx +18 -8
  248. package/src/app/pages/foundations/effects.tsx +18 -8
  249. package/src/app/pages/foundations/icons/[name]/index.tsx +28 -16
  250. package/src/app/pages/foundations/icons/index.tsx +18 -12
  251. package/src/app/pages/foundations/index.tsx +1 -1
  252. package/src/app/pages/foundations/logo.tsx +12 -8
  253. package/src/app/pages/foundations/typography.tsx +19 -9
  254. package/src/app/pages/index.tsx +1 -1
  255. package/src/app/pages/system/component/[component]/index.tsx +87 -17
  256. package/src/app/pages/system/index.tsx +13 -4
  257. package/src/app/pages/system/pattern/[pattern]/index.tsx +70 -14
  258. package/src/app/pages/system/tokens/components/[component]/index.tsx +42 -14
  259. package/src/app/pages/system/tokens/foundations/colors.tsx +7 -5
  260. package/src/app/pages/system/tokens/foundations/effects.tsx +7 -5
  261. package/src/app/pages/system/tokens/foundations/typography.tsx +8 -4
  262. package/src/app/tsconfig.json +2 -3
  263. package/src/app-builder/build.ts +555 -11
  264. package/src/app-builder/client-config.ts +61 -4
  265. package/src/app-builder/config-diff/snapshot.ts +1 -11
  266. package/src/app-builder/index.ts +1 -1
  267. package/src/app-builder/nav-shell.ts +74 -0
  268. package/src/app-builder/paths.ts +27 -1
  269. package/src/app-builder/static-export.ts +242 -0
  270. package/src/app-builder/vercel-output.ts +297 -0
  271. package/src/app-builder/watchers/utils.ts +2 -0
  272. package/src/app-builder/watchers.ts +149 -25
  273. package/src/app-builder/websocket.ts +2 -2
  274. package/src/artifacts/README.md +14 -0
  275. package/src/artifacts/index.ts +24 -0
  276. package/src/artifacts/types.ts +146 -0
  277. package/src/artifacts/url.ts +122 -0
  278. package/src/cache/build-cache.ts +47 -2
  279. package/src/commands/build/app.ts +1 -2
  280. package/src/commands/build/index.ts +61 -0
  281. package/src/commands/checkout/index.ts +66 -0
  282. package/src/commands/db/migrate.ts +25 -0
  283. package/src/commands/index.ts +8 -0
  284. package/src/commands/publish/index.ts +63 -0
  285. package/src/config/defaults.ts +15 -0
  286. package/src/config/loader.ts +10 -1
  287. package/src/config/normalizers/declaration.ts +3 -0
  288. package/src/config/normalizers/page.ts +45 -0
  289. package/src/config/normalizers/pattern.ts +4 -1
  290. package/src/config/runtime.ts +48 -2
  291. package/src/index.ts +126 -3
  292. package/src/nav/index.ts +94 -0
  293. package/src/nav/registry.ts +54 -0
  294. package/src/nav/resolver.ts +217 -0
  295. package/src/nav/workspace.ts +87 -0
  296. package/src/pipeline/styles.ts +4 -35
  297. package/src/pipeline/token-transformers.ts +97 -0
  298. package/src/registry/asset-storage/adapters/vercel-blob.ts +51 -0
  299. package/src/registry/asset-storage/define.ts +15 -0
  300. package/src/registry/asset-storage/resolve.ts +72 -0
  301. package/src/registry/asset-storage/types.ts +46 -0
  302. package/src/registry/assets/layout.ts +38 -0
  303. package/src/registry/assets/sets.ts +48 -0
  304. package/src/registry/assets/transfer.ts +50 -0
  305. package/src/registry/checkout/assets.ts +126 -0
  306. package/src/registry/checkout/index.ts +596 -0
  307. package/src/registry/checkout/tokens.ts +152 -0
  308. package/src/registry/client.ts +234 -0
  309. package/src/registry/connection.ts +50 -0
  310. package/src/registry/db/adapter.ts +74 -0
  311. package/src/registry/db/client.ts +88 -0
  312. package/src/registry/db/index.ts +35 -0
  313. package/src/registry/db/migrate.ts +56 -0
  314. package/src/registry/db/schema.ts +444 -0
  315. package/src/registry/path.ts +26 -0
  316. package/src/registry/publish/artifacts.ts +147 -0
  317. package/src/registry/publish/assets.ts +129 -0
  318. package/src/registry/publish/errors.ts +34 -0
  319. package/src/registry/publish/index.ts +128 -0
  320. package/src/registry/publish/package.ts +272 -0
  321. package/src/registry/publish/publish-build.ts +51 -0
  322. package/src/registry/publish/tokens.ts +119 -0
  323. package/src/registry/tokens/sets.ts +132 -0
  324. package/src/registry/tokens/transfer.ts +53 -0
  325. package/src/registry/transfer.ts +82 -0
  326. package/src/store/filesystem-assets.ts +152 -0
  327. package/src/store/filesystem.ts +237 -0
  328. package/src/store/index.ts +62 -0
  329. package/src/store/registry.ts +334 -0
  330. package/src/store/source-files.ts +155 -0
  331. package/src/store/types.ts +210 -0
  332. package/src/transformers/plugins/csf-render.ts +31 -7
  333. package/src/transformers/plugins/handlebars-previews.ts +22 -3
  334. package/src/transformers/plugins/ssr-render.ts +145 -57
  335. package/src/transformers/preview/component/api.ts +2 -1
  336. package/src/transformers/preview/component/artifacts.ts +10 -1
  337. package/src/transformers/preview/component/builder.ts +9 -2
  338. package/src/transformers/preview/component/css.ts +10 -1
  339. package/src/transformers/preview/component/javascript.ts +55 -20
  340. package/src/transformers/preview/component/shared-artifacts.ts +146 -0
  341. package/src/transformers/preview/component.ts +5 -2
  342. package/src/transformers/preview/pattern/builder.ts +33 -7
  343. package/src/transformers/preview/pattern/html.ts +71 -27
  344. package/src/transformers/preview/types.ts +42 -0
  345. package/src/transformers/utils/handlebars.ts +31 -5
  346. package/src/types/config.ts +129 -31
  347. package/src/utils/menu-shell.ts +241 -0
  348. package/src/utils/stable-stringify.ts +7 -0
  349. package/templates/default/package.json.tpl +1 -1
  350. package/handoff.config.js +0 -90
  351. package/src/app/components/ComponentSearch.tsx +0 -93
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Connected-workspace token publish orchestration.
3
+ *
4
+ * `publish tokens [setId]` runs a **fresh token build** (`handoff.fetch()` — Figma extract +
5
+ * `buildStyles`) so the local `tokens.json` and generated token outputs are current, discovers the
6
+ * logical sets from that document, then uploads each selected set (its extracted record + generated
7
+ * artifacts) to the connected registry. Each set is one atomic upsert; a set whose deterministic
8
+ * `sourceHash` matches the registry's is skipped. Absent sets are never deleted (explicit deletion is
9
+ * a separate management action).
10
+ */
11
+ import Handoff from '../../index';
12
+ /**
13
+ * Publish all discovered token sets, or a single set when `setId` is given. Runs a fresh token build,
14
+ * skips sets whose content is unchanged on the registry, and reports published/unchanged/failed
15
+ * counts. A per-set upload failure is collected and never leaves a partially written set (each set is
16
+ * committed atomically server-side); the run throws at the end if any set failed.
17
+ */
18
+ export declare const publishTokens: (handoff: Handoff, setId?: string) => Promise<void>;
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ /**
3
+ * Connected-workspace token publish orchestration.
4
+ *
5
+ * `publish tokens [setId]` runs a **fresh token build** (`handoff.fetch()` — Figma extract +
6
+ * `buildStyles`) so the local `tokens.json` and generated token outputs are current, discovers the
7
+ * logical sets from that document, then uploads each selected set (its extracted record + generated
8
+ * artifacts) to the connected registry. Each set is one atomic upsert; a set whose deterministic
9
+ * `sourceHash` matches the registry's is skipped. Absent sets are never deleted (explicit deletion is
10
+ * a separate management action).
11
+ */
12
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
+ return new (P || (P = Promise))(function (resolve, reject) {
15
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
19
+ });
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.publishTokens = void 0;
23
+ const logger_1 = require("../../utils/logger");
24
+ const stable_stringify_1 = require("../../utils/stable-stringify");
25
+ const client_1 = require("../client");
26
+ const errors_1 = require("./errors");
27
+ const index_1 = require("./index");
28
+ const publish_build_1 = require("./publish-build");
29
+ /**
30
+ * Deterministic content hash for a token set: the key-order-independent record serialization plus the
31
+ * path-sorted artifact bytes. Independent of JSON key insertion order, so an unchanged set hashes the
32
+ * same across rebuilds and skip-unchanged works reliably.
33
+ */
34
+ const hashTokenSet = (record, artifacts) => {
35
+ return (0, publish_build_1.hashPathValues)(artifacts.map((artifact) => ({ path: artifact.path, value: artifact.content })), (0, stable_stringify_1.stableStringify)(record));
36
+ };
37
+ /** Assemble one set's publish package from the freshly generated local token output. */
38
+ const buildTokenSetPackage = (handoff, set) => __awaiter(void 0, void 0, void 0, function* () {
39
+ const artifacts = (yield handoff.store.tokens.getArtifacts(set.id)).map((artifact) => ({
40
+ path: artifact.path,
41
+ format: artifact.format,
42
+ content: artifact.content,
43
+ contentType: artifact.contentType,
44
+ hash: (0, publish_build_1.sha256)(artifact.content),
45
+ size: Buffer.byteLength(artifact.content, 'utf8'),
46
+ }));
47
+ return {
48
+ id: set.id,
49
+ kind: set.kind,
50
+ record: set.record,
51
+ artifacts,
52
+ build: (0, publish_build_1.createCurrentBuild)({ sourceHash: hashTokenSet(set.record, artifacts) }),
53
+ };
54
+ });
55
+ /**
56
+ * Publish all discovered token sets, or a single set when `setId` is given. Runs a fresh token build,
57
+ * skips sets whose content is unchanged on the registry, and reports published/unchanged/failed
58
+ * counts. A per-set upload failure is collected and never leaves a partially written set (each set is
59
+ * committed atomically server-side); the run throws at the end if any set failed.
60
+ */
61
+ const publishTokens = (handoff, setId) => __awaiter(void 0, void 0, void 0, function* () {
62
+ const connection = (0, index_1.resolveConnectionOrThrow)(handoff);
63
+ logger_1.Logger.info(setId ? `Building tokens to publish "${setId}"…` : 'Building tokens for publish…');
64
+ yield handoff.fetch();
65
+ const allSets = yield handoff.store.tokens.listSets();
66
+ let targetSets = allSets;
67
+ if (setId) {
68
+ const found = allSets.find((set) => set.id === setId);
69
+ if (!found) {
70
+ throw new index_1.PublishError(`Token set "${setId}" was not found in the generated tokens. Discovered sets: ${allSets.map((set) => set.id).join(', ') || '(none)'}.`);
71
+ }
72
+ targetSets = [found];
73
+ }
74
+ const packages = yield Promise.all(targetSets.map((set) => buildTokenSetPackage(handoff, set)));
75
+ const client = (0, client_1.createRegistryClient)({ baseUrl: connection.url, accessToken: connection.accessToken });
76
+ let remote = [];
77
+ try {
78
+ remote = yield client.listTokenSets();
79
+ }
80
+ catch (error) {
81
+ // If the summary listing fails we simply publish everything (the server still no-ops unchanged sets).
82
+ logger_1.Logger.info('Could not read current registry token sets; publishing all selected sets.');
83
+ }
84
+ const remoteHashById = new Map(remote.map((entry) => [entry.id, entry.sourceHash]));
85
+ let published = 0;
86
+ let unchanged = 0;
87
+ const failed = [];
88
+ for (const pkg of packages) {
89
+ const remoteHash = remoteHashById.get(pkg.id);
90
+ if (remoteHash && remoteHash === pkg.build.sourceHash) {
91
+ unchanged += 1;
92
+ logger_1.Logger.info(`Unchanged: ${pkg.id}`);
93
+ continue;
94
+ }
95
+ try {
96
+ yield client.publishTokens(pkg);
97
+ published += 1;
98
+ logger_1.Logger.info(`Published: ${pkg.id} (${pkg.artifacts.length} artifact(s))`);
99
+ }
100
+ catch (error) {
101
+ failed.push({ id: pkg.id, message: (0, errors_1.describePublishError)(error, connection.url, 'token set') });
102
+ }
103
+ }
104
+ logger_1.Logger.success(`Tokens publish complete — ${published} published, ${unchanged} unchanged${failed.length ? `, ${failed.length} failed` : ''}.`);
105
+ if (failed.length > 0) {
106
+ for (const failure of failed) {
107
+ logger_1.Logger.error(` - ${failure.id}: ${failure.message}`);
108
+ }
109
+ throw new index_1.PublishError(`${failed.length} token set(s) failed to publish.`);
110
+ }
111
+ });
112
+ exports.publishTokens = publishTokens;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Logical token-set derivation — the pure, dependency-light boundary between the generated token
3
+ * document and the registry token entity.
4
+ *
5
+ * A **logical token set** is the registry entity boundary for tokens. Its stable ids are:
6
+ *
7
+ * ```text
8
+ * foundation/colors
9
+ * foundation/typography
10
+ * foundation/effects
11
+ * component/<componentId>
12
+ * ```
13
+ *
14
+ * The set `record` is the exact slice extracted from the generated `tokens.json`
15
+ * ({@link CoreTypes.IDocumentationObject}) — no lossy normalization, so new token properties flow
16
+ * through without a database migration. This module is imported by the store, publish, checkout, and
17
+ * server ingestion, so it stays free of fs/DB/React dependencies.
18
+ */
19
+ import type { Types as CoreTypes } from 'handoff-core';
20
+ /** Kind of a logical token set. */
21
+ export type TokenSetKind = 'foundation' | 'component';
22
+ /** A logical token set: its stable id, kind, and the exact extracted token slice. */
23
+ export interface DerivedTokenSet {
24
+ id: string;
25
+ kind: TokenSetKind;
26
+ /** The exact slice from `tokens.json` — `IColorObject[]`/`ITypographyObject[]`/`IEffectObject[]` for a foundation, `IFileComponentObject` for a component. */
27
+ record: unknown;
28
+ }
29
+ /** The three stable foundation set ids, in deterministic order. */
30
+ export declare const FOUNDATION_SET_IDS: readonly ["foundation/colors", "foundation/typography", "foundation/effects"];
31
+ /** Whether a set id refers to a component token set. */
32
+ export declare const isComponentSet: (id: string) => boolean;
33
+ export declare const isTokenSetId: (id: string) => boolean;
34
+ /** The kind of a set id. */
35
+ export declare const kindForSetId: (id: string) => TokenSetKind;
36
+ /**
37
+ * The generated-file base name for a set: `colors`/`typography`/`effects` for a foundation, the
38
+ * component id for a component set. This is the name the style transformers write files under
39
+ * (`<outDir>/<name>.<format>`).
40
+ */
41
+ export declare const setNameForId: (id: string) => string;
42
+ /** The `foundations/<type>` page type (`colors`/`typography`/`effects`) for a foundation set id, else null. */
43
+ export declare const foundationTypeForId: (id: string) => string | null;
44
+ /**
45
+ * Split the generated token document into logical sets: the three foundation sets (each possibly an
46
+ * empty array) plus one set per component. Foundation sets are always emitted so a set can carry zero
47
+ * tokens and so a token removed from a set is reflected as a shrunk `record` on republish.
48
+ */
49
+ export declare const deriveTokenSets: (doc: CoreTypes.IDocumentationObject | null | undefined) => DerivedTokenSet[];
50
+ /** A minimal default token document, used when no local `tokens.json` exists yet on checkout. */
51
+ export declare const emptyTokenDocument: () => CoreTypes.IDocumentationObject;
52
+ /**
53
+ * Splice a set of logical token sets into a token document, returning the merged document. Untouched
54
+ * sets are preserved (single-set checkout never clobbers other sets); a foundation set replaces its
55
+ * `localStyles` slice, a component set replaces `components[<id>]`.
56
+ */
57
+ export declare const mergeTokenSetsIntoDocument: (existing: CoreTypes.IDocumentationObject | null | undefined, sets: DerivedTokenSet[]) => CoreTypes.IDocumentationObject;
58
+ /** The `localStyles` key backing a `foundations/<type>` page (`colors`→`color`, `effects`→`effect`). */
59
+ export declare const localStylesKeyForFoundationType: (type: string) => keyof CoreTypes.IDocumentationObject["localStyles"] | null;
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ /**
3
+ * Logical token-set derivation — the pure, dependency-light boundary between the generated token
4
+ * document and the registry token entity.
5
+ *
6
+ * A **logical token set** is the registry entity boundary for tokens. Its stable ids are:
7
+ *
8
+ * ```text
9
+ * foundation/colors
10
+ * foundation/typography
11
+ * foundation/effects
12
+ * component/<componentId>
13
+ * ```
14
+ *
15
+ * The set `record` is the exact slice extracted from the generated `tokens.json`
16
+ * ({@link CoreTypes.IDocumentationObject}) — no lossy normalization, so new token properties flow
17
+ * through without a database migration. This module is imported by the store, publish, checkout, and
18
+ * server ingestion, so it stays free of fs/DB/React dependencies.
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.localStylesKeyForFoundationType = exports.mergeTokenSetsIntoDocument = exports.emptyTokenDocument = exports.deriveTokenSets = exports.foundationTypeForId = exports.setNameForId = exports.kindForSetId = exports.isTokenSetId = exports.isComponentSet = exports.FOUNDATION_SET_IDS = void 0;
22
+ const path_1 = require("../path");
23
+ /** The three stable foundation set ids, in deterministic order. */
24
+ exports.FOUNDATION_SET_IDS = ['foundation/colors', 'foundation/typography', 'foundation/effects'];
25
+ /**
26
+ * Map a foundation set name (the segment after `foundation/`, and the generated-file base name) to
27
+ * its `localStyles` key. Note the plural set names (`colors`/`effects`) map to the core's singular
28
+ * `localStyles.color`/`localStyles.effect`.
29
+ */
30
+ const LOCAL_STYLES_KEY_BY_FOUNDATION = {
31
+ colors: 'color',
32
+ typography: 'typography',
33
+ effects: 'effect',
34
+ };
35
+ /** Whether a set id refers to a component token set. */
36
+ const isComponentSet = (id) => id.startsWith('component/');
37
+ exports.isComponentSet = isComponentSet;
38
+ const isTokenSetId = (id) => {
39
+ if (exports.FOUNDATION_SET_IDS.includes(id)) {
40
+ return true;
41
+ }
42
+ return (0, exports.isComponentSet)(id) && (0, path_1.isSafePathSegment)(id.slice('component/'.length));
43
+ };
44
+ exports.isTokenSetId = isTokenSetId;
45
+ /** The kind of a set id. */
46
+ const kindForSetId = (id) => ((0, exports.isComponentSet)(id) ? 'component' : 'foundation');
47
+ exports.kindForSetId = kindForSetId;
48
+ /**
49
+ * The generated-file base name for a set: `colors`/`typography`/`effects` for a foundation, the
50
+ * component id for a component set. This is the name the style transformers write files under
51
+ * (`<outDir>/<name>.<format>`).
52
+ */
53
+ const setNameForId = (id) => { var _a; return ((0, exports.isComponentSet)(id) ? id.slice('component/'.length) : ((_a = id.split('/')[1]) !== null && _a !== void 0 ? _a : id)); };
54
+ exports.setNameForId = setNameForId;
55
+ /** The `foundations/<type>` page type (`colors`/`typography`/`effects`) for a foundation set id, else null. */
56
+ const foundationTypeForId = (id) => { var _a; return ((0, exports.isComponentSet)(id) ? null : ((_a = id.split('/')[1]) !== null && _a !== void 0 ? _a : null)); };
57
+ exports.foundationTypeForId = foundationTypeForId;
58
+ /**
59
+ * Split the generated token document into logical sets: the three foundation sets (each possibly an
60
+ * empty array) plus one set per component. Foundation sets are always emitted so a set can carry zero
61
+ * tokens and so a token removed from a set is reflected as a shrunk `record` on republish.
62
+ */
63
+ const deriveTokenSets = (doc) => {
64
+ var _a, _b, _c, _d, _e;
65
+ const localStyles = (_a = doc === null || doc === void 0 ? void 0 : doc.localStyles) !== null && _a !== void 0 ? _a : {};
66
+ const sets = [
67
+ { id: 'foundation/colors', kind: 'foundation', record: (_b = localStyles.color) !== null && _b !== void 0 ? _b : [] },
68
+ { id: 'foundation/typography', kind: 'foundation', record: (_c = localStyles.typography) !== null && _c !== void 0 ? _c : [] },
69
+ { id: 'foundation/effects', kind: 'foundation', record: (_d = localStyles.effect) !== null && _d !== void 0 ? _d : [] },
70
+ ];
71
+ const components = (_e = doc === null || doc === void 0 ? void 0 : doc.components) !== null && _e !== void 0 ? _e : {};
72
+ for (const componentId of Object.keys(components)) {
73
+ sets.push({ id: `component/${componentId}`, kind: 'component', record: components[componentId] });
74
+ }
75
+ return sets;
76
+ };
77
+ exports.deriveTokenSets = deriveTokenSets;
78
+ /** A minimal default token document, used when no local `tokens.json` exists yet on checkout. */
79
+ const emptyTokenDocument = () => ({
80
+ localStyles: { color: [], typography: [], effect: [] },
81
+ components: {},
82
+ assets: {},
83
+ });
84
+ exports.emptyTokenDocument = emptyTokenDocument;
85
+ /**
86
+ * Splice a set of logical token sets into a token document, returning the merged document. Untouched
87
+ * sets are preserved (single-set checkout never clobbers other sets); a foundation set replaces its
88
+ * `localStyles` slice, a component set replaces `components[<id>]`.
89
+ */
90
+ const mergeTokenSetsIntoDocument = (existing, sets) => {
91
+ var _a, _b;
92
+ const base = existing !== null && existing !== void 0 ? existing : (0, exports.emptyTokenDocument)();
93
+ const doc = Object.assign(Object.assign({}, base), { localStyles: Object.assign({}, ((_a = base.localStyles) !== null && _a !== void 0 ? _a : (0, exports.emptyTokenDocument)().localStyles)), components: Object.assign({}, ((_b = base.components) !== null && _b !== void 0 ? _b : {})) });
94
+ for (const set of sets) {
95
+ if ((0, exports.isComponentSet)(set.id)) {
96
+ doc.components[(0, exports.setNameForId)(set.id)] = set.record;
97
+ continue;
98
+ }
99
+ const localStylesKey = LOCAL_STYLES_KEY_BY_FOUNDATION[(0, exports.setNameForId)(set.id)];
100
+ if (localStylesKey) {
101
+ doc.localStyles[localStylesKey] = set.record;
102
+ }
103
+ }
104
+ return doc;
105
+ };
106
+ exports.mergeTokenSetsIntoDocument = mergeTokenSetsIntoDocument;
107
+ /** The `localStyles` key backing a `foundations/<type>` page (`colors`→`color`, `effects`→`effect`). */
108
+ const localStylesKeyForFoundationType = (type) => { var _a; return (_a = LOCAL_STYLES_KEY_BY_FOUNDATION[type]) !== null && _a !== void 0 ? _a : null; };
109
+ exports.localStylesKeyForFoundationType = localStylesKeyForFoundationType;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Transfer payload contract for token sets, shared by the connected-workspace publish/checkout client
3
+ * and the registry-side token ingestion endpoint.
4
+ *
5
+ * Tokens are their own transfer concern (a `record` slice + byte-for-byte generated artifacts, no
6
+ * source files and no artifact reference graph), so they use this dedicated shape rather than the
7
+ * component/pattern/page {@link import('../transfer').TransferPackage}. Types only — no behavior.
8
+ */
9
+ import type { TransferBuild } from '../transfer';
10
+ import type { ArtifactBuildStatus } from '../../artifacts/types';
11
+ import type { TokenSetKind } from './sets';
12
+ /** A generated token artifact in a transfer package (CSS/SCSS/Style Dictionary/types/custom output). */
13
+ export interface TokenSetTransferArtifact {
14
+ /** Registry-safe relative output path under the tokens dir (e.g. `css/colors.css`). */
15
+ path: string;
16
+ /** Logical format label (`css`|`scss`|`types`|`styleDictionary`|custom outDir). */
17
+ format: string;
18
+ content: string;
19
+ contentType: string;
20
+ hash?: string;
21
+ size?: number;
22
+ }
23
+ /**
24
+ * The full token set publish package uploaded to `PUT /api/registry/transfer/tokens/:setId`: the
25
+ * extracted record slice, the generated artifacts, and build metadata keyed by `sourceHash`.
26
+ */
27
+ export interface TokenSetTransferPackage {
28
+ id: string;
29
+ kind: TokenSetKind;
30
+ /** The exact extracted token slice (`IColorObject[]`/…/`IFileComponentObject`). */
31
+ record: unknown;
32
+ artifacts: TokenSetTransferArtifact[];
33
+ build: TransferBuild;
34
+ }
35
+ /** The checkout payload returned by `GET /api/registry/transfer/tokens/:setId`. */
36
+ export interface TokenSetCheckoutPayload {
37
+ id: string;
38
+ kind: TokenSetKind;
39
+ record: unknown;
40
+ artifacts: TokenSetTransferArtifact[];
41
+ }
42
+ /** A lightweight token-set summary (`GET /api/registry/transfer/tokens`) driving skip-unchanged + bulk checkout. */
43
+ export interface TokenSetSummary {
44
+ id: string;
45
+ kind: TokenSetKind;
46
+ sourceHash: string | null;
47
+ status: ArtifactBuildStatus | null;
48
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ /**
3
+ * Transfer payload contract for token sets, shared by the connected-workspace publish/checkout client
4
+ * and the registry-side token ingestion endpoint.
5
+ *
6
+ * Tokens are their own transfer concern (a `record` slice + byte-for-byte generated artifacts, no
7
+ * source files and no artifact reference graph), so they use this dedicated shape rather than the
8
+ * component/pattern/page {@link import('../transfer').TransferPackage}. Types only — no behavior.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Transfer payload contract shared by the connected-workspace publish client and the registry-side
3
+ * ingestion endpoint.
4
+ *
5
+ * Publish is the only path allowed to set render/build-defining fields, source files, rendered
6
+ * artifacts, and build metadata. This module is the single shared description of that wire shape so
7
+ * the CLI (which builds and uploads the package) and the registry API (which validates and ingests
8
+ * it) never drift. Types only — no runtime behavior.
9
+ */
10
+ import type { ArtifactBuildStatus, ArtifactKind, ArtifactOwnerKind, ArtifactReference } from '../artifacts/types';
11
+ import type { RegistryTextFileKind } from '../store/types';
12
+ /** Entity kinds that can be transferred (published/checked out). */
13
+ export type TransferEntityKind = 'component' | 'pattern' | 'page';
14
+ /**
15
+ * A registry-safe source file in a transfer package. Declarations are workspace-only (synthesized on
16
+ * checkout) and are never present here — `kind` excludes `declaration` by type.
17
+ */
18
+ export interface TransferFile {
19
+ /** Registry-safe relative path within the entity (e.g. `Badge.tsx`). */
20
+ path: string;
21
+ kind: RegistryTextFileKind;
22
+ content: string;
23
+ contentType: string;
24
+ }
25
+ /**
26
+ * A rendered docs read-model artifact in a transfer package. Carries the structured ownership and
27
+ * references the registry stores so it can validate, serve, and dedup the artifact without ever
28
+ * parsing HTML.
29
+ */
30
+ export interface TransferArtifact {
31
+ /** Logical artifact path (e.g. `component/badge-primary.html`, `component/main.css`). */
32
+ path: string;
33
+ artifactKind: ArtifactKind;
34
+ content: string;
35
+ contentType: string;
36
+ /** What the artifact belongs to — shared/global artifacts are `asset` with a `null` owner id. */
37
+ ownerKind: ArtifactOwnerKind;
38
+ ownerId: string | null;
39
+ /** Structured references this artifact depends on (drives required-reference validation). */
40
+ references?: ArtifactReference[];
41
+ formatVersion?: string;
42
+ hash?: string;
43
+ size?: number;
44
+ }
45
+ /** Build metadata for the published entity. */
46
+ export interface TransferBuild {
47
+ status: ArtifactBuildStatus;
48
+ builtAt?: string;
49
+ builderVersion?: string;
50
+ artifactHash?: string;
51
+ sourceHash?: string;
52
+ warnings?: string[];
53
+ error?: string;
54
+ }
55
+ /**
56
+ * The full publish package uploaded to `PUT /api/registry/transfer/{component|pattern|page}/:id`.
57
+ * Rendered artifacts are included when the entity has a render pipeline.
58
+ */
59
+ export interface TransferPackage {
60
+ /** Normalized component, pattern, or page record stored as the served record. */
61
+ item: Record<string, unknown>;
62
+ files: TransferFile[];
63
+ artifacts: TransferArtifact[];
64
+ build: TransferBuild;
65
+ }
66
+ /**
67
+ * The checkout payload returned by `GET /api/registry/transfer/{component|pattern|page}/:id`.
68
+ * Declarations are omitted because the consuming workspace creates them locally.
69
+ */
70
+ export interface CheckoutPayload {
71
+ kind: TransferEntityKind;
72
+ /** Normalized record used to reconstruct the entity. */
73
+ item: Record<string, unknown>;
74
+ files: TransferFile[];
75
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ /**
3
+ * Transfer payload contract shared by the connected-workspace publish client and the registry-side
4
+ * ingestion endpoint.
5
+ *
6
+ * Publish is the only path allowed to set render/build-defining fields, source files, rendered
7
+ * artifacts, and build metadata. This module is the single shared description of that wire shape so
8
+ * the CLI (which builds and uploads the package) and the registry API (which validates and ingests
9
+ * it) never drift. Types only — no runtime behavior.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,17 @@
1
+ import type { FilesystemStoreContext } from './filesystem';
2
+ import type { AssetContentResource, AssetMetadata, AssetStore } from './types';
3
+ /**
4
+ * Filesystem backed asset store. Enumerates each collection from the generated `public/api` tree
5
+ * plus the downloadable ZIP and font archives.
6
+ */
7
+ export declare class FilesystemAssetStore implements AssetStore {
8
+ private readonly context;
9
+ constructor(context: FilesystemStoreContext);
10
+ private roots;
11
+ private enumerate;
12
+ private toMetadata;
13
+ listCollections(): string[];
14
+ listAssets(collection: string): AssetMetadata[];
15
+ getAsset(collection: string, assetPath: string): AssetMetadata | null;
16
+ getAssetContent(collection: string, assetPath: string): AssetContentResource | null;
17
+ }
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FilesystemAssetStore = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const layout_1 = require("../registry/assets/layout");
11
+ const sets_1 = require("../registry/assets/sets");
12
+ const sha256 = (bytes) => crypto_1.default.createHash('sha256').update(bytes).digest('hex');
13
+ const isFile = (absolutePath) => {
14
+ try {
15
+ return fs_extra_1.default.existsSync(absolutePath) && fs_extra_1.default.statSync(absolutePath).isFile();
16
+ }
17
+ catch (_a) {
18
+ return false;
19
+ }
20
+ };
21
+ /**
22
+ * Filesystem backed asset store. Enumerates each collection from the generated `public/api` tree
23
+ * plus the downloadable ZIP and font archives.
24
+ */
25
+ class FilesystemAssetStore {
26
+ constructor(context) {
27
+ this.context = context;
28
+ }
29
+ roots() {
30
+ var _a, _b, _c, _d, _e, _f;
31
+ const apiPath = (_b = (_a = this.context).getAssetsApiPath) === null || _b === void 0 ? void 0 : _b.call(_a);
32
+ const iconsZip = (_d = (_c = this.context).getIconsZipFilePath) === null || _d === void 0 ? void 0 : _d.call(_c);
33
+ const logosZip = (_f = (_e = this.context).getLogosZipFilePath) === null || _f === void 0 ? void 0 : _f.call(_e);
34
+ const workingPath = this.context.workingPath;
35
+ if (!apiPath || !iconsZip || !logosZip || !workingPath) {
36
+ return null;
37
+ }
38
+ return { apiPath, iconsZip, logosZip, workingPath };
39
+ }
40
+ enumerate(collection) {
41
+ var _a;
42
+ const roots = this.roots();
43
+ if (!roots) {
44
+ return [];
45
+ }
46
+ if (collection === 'icons' || collection === 'logos') {
47
+ const entries = [];
48
+ const collectionJson = `assets/${collection}.json`;
49
+ let assetObjects = [];
50
+ try {
51
+ const raw = fs_extra_1.default.readFileSync((0, layout_1.resolveAssetPhysicalPath)(collectionJson, roots), 'utf8');
52
+ const parsed = JSON.parse(raw);
53
+ if (Array.isArray(parsed))
54
+ assetObjects = parsed;
55
+ }
56
+ catch (_b) {
57
+ assetObjects = [];
58
+ }
59
+ for (const asset of assetObjects) {
60
+ const logicalPath = `assets/${collection}/${asset.path}`;
61
+ entries.push({
62
+ logicalPath,
63
+ name: asset.name,
64
+ metadata: { icon: asset.icon, index: asset.index, description: (_a = asset.description) !== null && _a !== void 0 ? _a : null },
65
+ absolutePath: (0, layout_1.resolveAssetPhysicalPath)(logicalPath, roots),
66
+ });
67
+ }
68
+ const extras = collection === 'icons'
69
+ ? [collectionJson, 'icons-sprite.svg', 'icons-sprite-manifest.json', 'icons.zip']
70
+ : [collectionJson, 'logos.zip'];
71
+ for (const logicalPath of extras) {
72
+ entries.push({ logicalPath, name: path_1.default.basename(logicalPath), absolutePath: (0, layout_1.resolveAssetPhysicalPath)(logicalPath, roots) });
73
+ }
74
+ return entries.filter((entry) => isFile(entry.absolutePath));
75
+ }
76
+ if (collection === 'fonts') {
77
+ const fontsDir = path_1.default.resolve(roots.workingPath, 'fonts');
78
+ if (!fs_extra_1.default.existsSync(fontsDir)) {
79
+ return [];
80
+ }
81
+ try {
82
+ return fs_extra_1.default
83
+ .readdirSync(fontsDir)
84
+ .filter((file) => file.toLowerCase().endsWith('.zip'))
85
+ .map((file) => ({ logicalPath: `fonts/${file}`, name: file, absolutePath: path_1.default.join(fontsDir, file) }))
86
+ .filter((entry) => isFile(entry.absolutePath));
87
+ }
88
+ catch (_c) {
89
+ return [];
90
+ }
91
+ }
92
+ return [];
93
+ }
94
+ toMetadata(collection, entry, bytes) {
95
+ var _a;
96
+ return {
97
+ collection,
98
+ path: entry.logicalPath,
99
+ name: entry.name,
100
+ contentType: (0, sets_1.assetContentType)(entry.logicalPath),
101
+ size: bytes.length,
102
+ contentHash: sha256(bytes),
103
+ metadata: (_a = entry.metadata) !== null && _a !== void 0 ? _a : null,
104
+ };
105
+ }
106
+ listCollections() {
107
+ return sets_1.ASSET_COLLECTIONS.filter((collection) => this.enumerate(collection).length > 0);
108
+ }
109
+ listAssets(collection) {
110
+ const out = [];
111
+ for (const entry of this.enumerate(collection)) {
112
+ try {
113
+ out.push(this.toMetadata(collection, entry, fs_extra_1.default.readFileSync(entry.absolutePath)));
114
+ }
115
+ catch (_a) {
116
+ // Skip files that vanished between enumeration and read.
117
+ }
118
+ }
119
+ return out;
120
+ }
121
+ getAsset(collection, assetPath) {
122
+ const entry = this.enumerate(collection).find((candidate) => candidate.logicalPath === assetPath);
123
+ if (!entry) {
124
+ return null;
125
+ }
126
+ try {
127
+ return this.toMetadata(collection, entry, fs_extra_1.default.readFileSync(entry.absolutePath));
128
+ }
129
+ catch (_a) {
130
+ return null;
131
+ }
132
+ }
133
+ getAssetContent(collection, assetPath) {
134
+ const entry = this.enumerate(collection).find((candidate) => candidate.logicalPath === assetPath);
135
+ if (!entry) {
136
+ return null;
137
+ }
138
+ try {
139
+ const bytes = fs_extra_1.default.readFileSync(entry.absolutePath);
140
+ return Object.assign(Object.assign({}, this.toMetadata(collection, entry, bytes)), { body: bytes });
141
+ }
142
+ catch (_a) {
143
+ return null;
144
+ }
145
+ }
146
+ }
147
+ exports.FilesystemAssetStore = FilesystemAssetStore;