@elytracms/studio 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 (558) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/convex/assets.ts +107 -0
  4. package/convex/auth.config.ts +15 -0
  5. package/convex/auth.ts +50 -0
  6. package/convex/cliTokens.ts +63 -0
  7. package/convex/cms.ts +174 -0
  8. package/convex/content.ts +316 -0
  9. package/convex/delivery.ts +266 -0
  10. package/convex/functions.ts +35 -0
  11. package/convex/graphs.ts +51 -0
  12. package/convex/guard.ts +67 -0
  13. package/convex/http.ts +30 -0
  14. package/convex/members.ts +83 -0
  15. package/convex/publishing.ts +102 -0
  16. package/convex/references.ts +168 -0
  17. package/convex/schema.ts +173 -0
  18. package/convex/sync.ts +322 -0
  19. package/convex/tsconfig.json +12 -0
  20. package/convex/users.ts +23 -0
  21. package/convex/webhooks.ts +85 -0
  22. package/dist/components/assets/asset-library.d.ts +14 -0
  23. package/dist/components/assets/asset-library.js +191 -0
  24. package/dist/components/assets/asset-library.js.map +1 -0
  25. package/dist/components/assets/asset-metadata.d.ts +34 -0
  26. package/dist/components/assets/asset-metadata.js +40 -0
  27. package/dist/components/assets/asset-metadata.js.map +1 -0
  28. package/dist/components/assets/asset-search.d.ts +7 -0
  29. package/dist/components/assets/asset-search.js +12 -0
  30. package/dist/components/assets/asset-search.js.map +1 -0
  31. package/dist/components/assets/asset-selection.d.ts +17 -0
  32. package/dist/components/assets/asset-selection.js +33 -0
  33. package/dist/components/assets/asset-selection.js.map +1 -0
  34. package/dist/components/assets/assets-store.d.ts +51 -0
  35. package/dist/components/assets/assets-store.js +153 -0
  36. package/dist/components/assets/assets-store.js.map +1 -0
  37. package/dist/components/auth-context.d.ts +38 -0
  38. package/dist/components/auth-context.js +88 -0
  39. package/dist/components/auth-context.js.map +1 -0
  40. package/dist/components/backend-gate.d.ts +19 -0
  41. package/dist/components/backend-gate.js +63 -0
  42. package/dist/components/backend-gate.js.map +1 -0
  43. package/dist/components/breadcrumb-context.d.ts +39 -0
  44. package/dist/components/breadcrumb-context.js +38 -0
  45. package/dist/components/breadcrumb-context.js.map +1 -0
  46. package/dist/components/builder/blocks-model.d.ts +80 -0
  47. package/dist/components/builder/blocks-model.js +181 -0
  48. package/dist/components/builder/blocks-model.js.map +1 -0
  49. package/dist/components/builder/blocks-panel.d.ts +44 -0
  50. package/dist/components/builder/blocks-panel.js +147 -0
  51. package/dist/components/builder/blocks-panel.js.map +1 -0
  52. package/dist/components/builder/builder-store.d.ts +69 -0
  53. package/dist/components/builder/builder-store.js +294 -0
  54. package/dist/components/builder/builder-store.js.map +1 -0
  55. package/dist/components/builder/canvas-stylesheet.d.ts +4 -0
  56. package/dist/components/builder/canvas-stylesheet.js +24 -0
  57. package/dist/components/builder/canvas-stylesheet.js.map +1 -0
  58. package/dist/components/builder/canvas.d.ts +8 -0
  59. package/dist/components/builder/canvas.js +723 -0
  60. package/dist/components/builder/canvas.js.map +1 -0
  61. package/dist/components/builder/clipboard-actions.d.ts +93 -0
  62. package/dist/components/builder/clipboard-actions.js +246 -0
  63. package/dist/components/builder/clipboard-actions.js.map +1 -0
  64. package/dist/components/builder/composition-field-editor.d.ts +11 -0
  65. package/dist/components/builder/composition-field-editor.js +150 -0
  66. package/dist/components/builder/composition-field-editor.js.map +1 -0
  67. package/dist/components/builder/composition-scope.d.ts +16 -0
  68. package/dist/components/builder/composition-scope.js +7 -0
  69. package/dist/components/builder/composition-scope.js.map +1 -0
  70. package/dist/components/builder/drag-session.d.ts +41 -0
  71. package/dist/components/builder/drag-session.js +51 -0
  72. package/dist/components/builder/drag-session.js.map +1 -0
  73. package/dist/components/builder/fixture-thumbnail.d.ts +18 -0
  74. package/dist/components/builder/fixture-thumbnail.js +97 -0
  75. package/dist/components/builder/fixture-thumbnail.js.map +1 -0
  76. package/dist/components/builder/inline-edit.d.ts +142 -0
  77. package/dist/components/builder/inline-edit.js +136 -0
  78. package/dist/components/builder/inline-edit.js.map +1 -0
  79. package/dist/components/builder/insert-context.d.ts +14 -0
  80. package/dist/components/builder/insert-context.js +65 -0
  81. package/dist/components/builder/insert-context.js.map +1 -0
  82. package/dist/components/builder/insert-menu.d.ts +9 -0
  83. package/dist/components/builder/insert-menu.js +9 -0
  84. package/dist/components/builder/insert-menu.js.map +1 -0
  85. package/dist/components/builder/layout-inspector.d.ts +14 -0
  86. package/dist/components/builder/layout-inspector.js +84 -0
  87. package/dist/components/builder/layout-inspector.js.map +1 -0
  88. package/dist/components/builder/node-factory.d.ts +17 -0
  89. package/dist/components/builder/node-factory.js +90 -0
  90. package/dist/components/builder/node-factory.js.map +1 -0
  91. package/dist/components/builder/page-tree.d.ts +3 -0
  92. package/dist/components/builder/page-tree.js +207 -0
  93. package/dist/components/builder/page-tree.js.map +1 -0
  94. package/dist/components/builder/property-inspector.d.ts +1 -0
  95. package/dist/components/builder/property-inspector.js +233 -0
  96. package/dist/components/builder/property-inspector.js.map +1 -0
  97. package/dist/components/builder/rich-text-toolbar.d.ts +4 -0
  98. package/dist/components/builder/rich-text-toolbar.js +104 -0
  99. package/dist/components/builder/rich-text-toolbar.js.map +1 -0
  100. package/dist/components/builder/spacing-handles.d.ts +22 -0
  101. package/dist/components/builder/spacing-handles.js +213 -0
  102. package/dist/components/builder/spacing-handles.js.map +1 -0
  103. package/dist/components/cms/asset-picker.d.ts +12 -0
  104. package/dist/components/cms/asset-picker.js +60 -0
  105. package/dist/components/cms/asset-picker.js.map +1 -0
  106. package/dist/components/cms/bulk-actions.d.ts +60 -0
  107. package/dist/components/cms/bulk-actions.js +95 -0
  108. package/dist/components/cms/bulk-actions.js.map +1 -0
  109. package/dist/components/cms/bulk-bar.d.ts +23 -0
  110. package/dist/components/cms/bulk-bar.js +26 -0
  111. package/dist/components/cms/bulk-bar.js.map +1 -0
  112. package/dist/components/cms/cell-edit.d.ts +91 -0
  113. package/dist/components/cms/cell-edit.js +144 -0
  114. package/dist/components/cms/cell-edit.js.map +1 -0
  115. package/dist/components/cms/cell.d.ts +29 -0
  116. package/dist/components/cms/cell.js +127 -0
  117. package/dist/components/cms/cell.js.map +1 -0
  118. package/dist/components/cms/cms-index.d.ts +8 -0
  119. package/dist/components/cms/cms-index.js +23 -0
  120. package/dist/components/cms/cms-index.js.map +1 -0
  121. package/dist/components/cms/cms-store.d.ts +188 -0
  122. package/dist/components/cms/cms-store.js +702 -0
  123. package/dist/components/cms/cms-store.js.map +1 -0
  124. package/dist/components/cms/collection-table.d.ts +6 -0
  125. package/dist/components/cms/collection-table.js +250 -0
  126. package/dist/components/cms/collection-table.js.map +1 -0
  127. package/dist/components/cms/collections-sidebar.d.ts +9 -0
  128. package/dist/components/cms/collections-sidebar.js +25 -0
  129. package/dist/components/cms/collections-sidebar.js.map +1 -0
  130. package/dist/components/cms/detail-editor.d.ts +7 -0
  131. package/dist/components/cms/detail-editor.js +386 -0
  132. package/dist/components/cms/detail-editor.js.map +1 -0
  133. package/dist/components/cms/doc-state.d.ts +13 -0
  134. package/dist/components/cms/doc-state.js +18 -0
  135. package/dist/components/cms/doc-state.js.map +1 -0
  136. package/dist/components/cms/document-editor-context.d.ts +48 -0
  137. package/dist/components/cms/document-editor-context.js +23 -0
  138. package/dist/components/cms/document-editor-context.js.map +1 -0
  139. package/dist/components/cms/editable-cell.d.ts +22 -0
  140. package/dist/components/cms/editable-cell.js +176 -0
  141. package/dist/components/cms/editable-cell.js.map +1 -0
  142. package/dist/components/cms/field-control.d.ts +8 -0
  143. package/dist/components/cms/field-control.js +149 -0
  144. package/dist/components/cms/field-control.js.map +1 -0
  145. package/dist/components/cms/filter-builder.d.ts +12 -0
  146. package/dist/components/cms/filter-builder.js +84 -0
  147. package/dist/components/cms/filter-builder.js.map +1 -0
  148. package/dist/components/cms/import-export.d.ts +6 -0
  149. package/dist/components/cms/import-export.js +33 -0
  150. package/dist/components/cms/import-export.js.map +1 -0
  151. package/dist/components/cms/new-page-dialog.d.ts +22 -0
  152. package/dist/components/cms/new-page-dialog.js +42 -0
  153. package/dist/components/cms/new-page-dialog.js.map +1 -0
  154. package/dist/components/cms/reference-confirm.d.ts +25 -0
  155. package/dist/components/cms/reference-confirm.js +124 -0
  156. package/dist/components/cms/reference-confirm.js.map +1 -0
  157. package/dist/components/cms/relation-picker.d.ts +16 -0
  158. package/dist/components/cms/relation-picker.js +47 -0
  159. package/dist/components/cms/relation-picker.js.map +1 -0
  160. package/dist/components/cms/use-cell-edit.d.ts +33 -0
  161. package/dist/components/cms/use-cell-edit.js +125 -0
  162. package/dist/components/cms/use-cell-edit.js.map +1 -0
  163. package/dist/components/cms/versions-model.d.ts +15 -0
  164. package/dist/components/cms/versions-model.js +23 -0
  165. package/dist/components/cms/versions-model.js.map +1 -0
  166. package/dist/components/cms/versions-pane.d.ts +14 -0
  167. package/dist/components/cms/versions-pane.js +86 -0
  168. package/dist/components/cms/versions-pane.js.map +1 -0
  169. package/dist/components/cms/view-bar.d.ts +11 -0
  170. package/dist/components/cms/view-bar.js +80 -0
  171. package/dist/components/cms/view-bar.js.map +1 -0
  172. package/dist/components/collab/collab-context.d.ts +34 -0
  173. package/dist/components/collab/collab-context.js +52 -0
  174. package/dist/components/collab/collab-context.js.map +1 -0
  175. package/dist/components/collab/collab-seed.d.ts +27 -0
  176. package/dist/components/collab/collab-seed.js +42 -0
  177. package/dist/components/collab/collab-seed.js.map +1 -0
  178. package/dist/components/components/component-detail.d.ts +9 -0
  179. package/dist/components/components/component-detail.js +30 -0
  180. package/dist/components/components/component-detail.js.map +1 -0
  181. package/dist/components/components/component-status.d.ts +10 -0
  182. package/dist/components/components/component-status.js +30 -0
  183. package/dist/components/components/component-status.js.map +1 -0
  184. package/dist/components/components/components-index.d.ts +8 -0
  185. package/dist/components/components/components-index.js +42 -0
  186. package/dist/components/components/components-index.js.map +1 -0
  187. package/dist/components/components/field-inspector.d.ts +9 -0
  188. package/dist/components/components/field-inspector.js +38 -0
  189. package/dist/components/components/field-inspector.js.map +1 -0
  190. package/dist/components/components/fixture-runner.d.ts +10 -0
  191. package/dist/components/components/fixture-runner.js +24 -0
  192. package/dist/components/components/fixture-runner.js.map +1 -0
  193. package/dist/components/components/registry-browser.d.ts +4 -0
  194. package/dist/components/components/registry-browser.js +64 -0
  195. package/dist/components/components/registry-browser.js.map +1 -0
  196. package/dist/components/current-user-menu.d.ts +13 -0
  197. package/dist/components/current-user-menu.js +31 -0
  198. package/dist/components/current-user-menu.js.map +1 -0
  199. package/dist/components/dev-login-badge.d.ts +9 -0
  200. package/dist/components/dev-login-badge.js +18 -0
  201. package/dist/components/dev-login-badge.js.map +1 -0
  202. package/dist/components/extensions/extensions-view.d.ts +7 -0
  203. package/dist/components/extensions/extensions-view.js +126 -0
  204. package/dist/components/extensions/extensions-view.js.map +1 -0
  205. package/dist/components/guards.d.ts +27 -0
  206. package/dist/components/guards.js +46 -0
  207. package/dist/components/guards.js.map +1 -0
  208. package/dist/components/inspector/inspector-sidebar.d.ts +26 -0
  209. package/dist/components/inspector/inspector-sidebar.js +17 -0
  210. package/dist/components/inspector/inspector-sidebar.js.map +1 -0
  211. package/dist/components/operation-error.d.ts +17 -0
  212. package/dist/components/operation-error.js +54 -0
  213. package/dist/components/operation-error.js.map +1 -0
  214. package/dist/components/playground-badge.d.ts +10 -0
  215. package/dist/components/playground-badge.js +19 -0
  216. package/dist/components/playground-badge.js.map +1 -0
  217. package/dist/components/project-list.d.ts +15 -0
  218. package/dist/components/project-list.js +52 -0
  219. package/dist/components/project-list.js.map +1 -0
  220. package/dist/components/project-session.d.ts +46 -0
  221. package/dist/components/project-session.js +107 -0
  222. package/dist/components/project-session.js.map +1 -0
  223. package/dist/components/project-switcher.d.ts +11 -0
  224. package/dist/components/project-switcher.js +44 -0
  225. package/dist/components/project-switcher.js.map +1 -0
  226. package/dist/components/references/builder-deep-link.d.ts +12 -0
  227. package/dist/components/references/builder-deep-link.js +53 -0
  228. package/dist/components/references/builder-deep-link.js.map +1 -0
  229. package/dist/components/references/references-panel.d.ts +17 -0
  230. package/dist/components/references/references-panel.js +66 -0
  231. package/dist/components/references/references-panel.js.map +1 -0
  232. package/dist/components/routes/redirect-chain.d.ts +9 -0
  233. package/dist/components/routes/redirect-chain.js +16 -0
  234. package/dist/components/routes/redirect-chain.js.map +1 -0
  235. package/dist/components/routes/redirect-manager.d.ts +13 -0
  236. package/dist/components/routes/redirect-manager.js +24 -0
  237. package/dist/components/routes/redirect-manager.js.map +1 -0
  238. package/dist/components/routes/route-list.d.ts +35 -0
  239. package/dist/components/routes/route-list.js +69 -0
  240. package/dist/components/routes/route-list.js.map +1 -0
  241. package/dist/components/routes/routes-shell.d.ts +14 -0
  242. package/dist/components/routes/routes-shell.js +68 -0
  243. package/dist/components/routes/routes-shell.js.map +1 -0
  244. package/dist/components/section-nav.d.ts +17 -0
  245. package/dist/components/section-nav.js +33 -0
  246. package/dist/components/section-nav.js.map +1 -0
  247. package/dist/components/section-state.d.ts +24 -0
  248. package/dist/components/section-state.js +78 -0
  249. package/dist/components/section-state.js.map +1 -0
  250. package/dist/components/section-surface.d.ts +31 -0
  251. package/dist/components/section-surface.js +46 -0
  252. package/dist/components/section-surface.js.map +1 -0
  253. package/dist/components/sections.d.ts +38 -0
  254. package/dist/components/sections.js +72 -0
  255. package/dist/components/sections.js.map +1 -0
  256. package/dist/components/settings-form.d.ts +10 -0
  257. package/dist/components/settings-form.js +17 -0
  258. package/dist/components/settings-form.js.map +1 -0
  259. package/dist/components/studio-context.d.ts +22 -0
  260. package/dist/components/studio-context.js +48 -0
  261. package/dist/components/studio-context.js.map +1 -0
  262. package/dist/components/studio-project-screen.d.ts +19 -0
  263. package/dist/components/studio-project-screen.js +195 -0
  264. package/dist/components/studio-project-screen.js.map +1 -0
  265. package/dist/components/studio-shell.d.ts +18 -0
  266. package/dist/components/studio-shell.js +64 -0
  267. package/dist/components/studio-shell.js.map +1 -0
  268. package/dist/components/theme-context.d.ts +17 -0
  269. package/dist/components/theme-context.js +26 -0
  270. package/dist/components/theme-context.js.map +1 -0
  271. package/dist/components/workspace-gate.d.ts +12 -0
  272. package/dist/components/workspace-gate.js +27 -0
  273. package/dist/components/workspace-gate.js.map +1 -0
  274. package/dist/components/workspace-projects.d.ts +13 -0
  275. package/dist/components/workspace-projects.js +18 -0
  276. package/dist/components/workspace-projects.js.map +1 -0
  277. package/dist/lib/assets/delete-asset.d.ts +34 -0
  278. package/dist/lib/assets/delete-asset.js +34 -0
  279. package/dist/lib/assets/delete-asset.js.map +1 -0
  280. package/dist/lib/assets/image-dimensions.d.ts +18 -0
  281. package/dist/lib/assets/image-dimensions.js +26 -0
  282. package/dist/lib/assets/image-dimensions.js.map +1 -0
  283. package/dist/lib/assets/index.d.ts +9 -0
  284. package/dist/lib/assets/index.js +10 -0
  285. package/dist/lib/assets/index.js.map +1 -0
  286. package/dist/lib/assets/upload-state.d.ts +53 -0
  287. package/dist/lib/assets/upload-state.js +59 -0
  288. package/dist/lib/assets/upload-state.js.map +1 -0
  289. package/dist/lib/assets/upload.d.ts +56 -0
  290. package/dist/lib/assets/upload.js +125 -0
  291. package/dist/lib/assets/upload.js.map +1 -0
  292. package/dist/lib/auth/auth-adapter.d.ts +57 -0
  293. package/dist/lib/auth/auth-adapter.js +13 -0
  294. package/dist/lib/auth/auth-adapter.js.map +1 -0
  295. package/dist/lib/auth/convex-auth-adapter.d.ts +39 -0
  296. package/dist/lib/auth/convex-auth-adapter.js +171 -0
  297. package/dist/lib/auth/convex-auth-adapter.js.map +1 -0
  298. package/dist/lib/auth/dev-auto-login-adapter.d.ts +25 -0
  299. package/dist/lib/auth/dev-auto-login-adapter.js +40 -0
  300. package/dist/lib/auth/dev-auto-login-adapter.js.map +1 -0
  301. package/dist/lib/auth/index.d.ts +28 -0
  302. package/dist/lib/auth/index.js +61 -0
  303. package/dist/lib/auth/index.js.map +1 -0
  304. package/dist/lib/auth/local-auth-adapter.d.ts +57 -0
  305. package/dist/lib/auth/local-auth-adapter.js +78 -0
  306. package/dist/lib/auth/local-auth-adapter.js.map +1 -0
  307. package/dist/lib/auth/route-guard.d.ts +33 -0
  308. package/dist/lib/auth/route-guard.js +51 -0
  309. package/dist/lib/auth/route-guard.js.map +1 -0
  310. package/dist/lib/auth-errors.d.ts +42 -0
  311. package/dist/lib/auth-errors.js +74 -0
  312. package/dist/lib/auth-errors.js.map +1 -0
  313. package/dist/lib/bindings/section-bindings.d.ts +24 -0
  314. package/dist/lib/bindings/section-bindings.js +9 -0
  315. package/dist/lib/bindings/section-bindings.js.map +1 -0
  316. package/dist/lib/clipboard/index.d.ts +7 -0
  317. package/dist/lib/clipboard/index.js +8 -0
  318. package/dist/lib/clipboard/index.js.map +1 -0
  319. package/dist/lib/clipboard/os-clipboard.d.ts +46 -0
  320. package/dist/lib/clipboard/os-clipboard.js +105 -0
  321. package/dist/lib/clipboard/os-clipboard.js.map +1 -0
  322. package/dist/lib/clipboard/paste-issues.d.ts +34 -0
  323. package/dist/lib/clipboard/paste-issues.js +67 -0
  324. package/dist/lib/clipboard/paste-issues.js.map +1 -0
  325. package/dist/lib/clipboard/paste-target.d.ts +20 -0
  326. package/dist/lib/clipboard/paste-target.js +28 -0
  327. package/dist/lib/clipboard/paste-target.js.map +1 -0
  328. package/dist/lib/cms/published-documents.d.ts +30 -0
  329. package/dist/lib/cms/published-documents.js +75 -0
  330. package/dist/lib/cms/published-documents.js.map +1 -0
  331. package/dist/lib/cms-views/index.d.ts +9 -0
  332. package/dist/lib/cms-views/index.js +10 -0
  333. package/dist/lib/cms-views/index.js.map +1 -0
  334. package/dist/lib/cms-views/selection.d.ts +29 -0
  335. package/dist/lib/cms-views/selection.js +46 -0
  336. package/dist/lib/cms-views/selection.js.map +1 -0
  337. package/dist/lib/cms-views/view-model.d.ts +192 -0
  338. package/dist/lib/cms-views/view-model.js +353 -0
  339. package/dist/lib/cms-views/view-model.js.map +1 -0
  340. package/dist/lib/cms-views/views-store.d.ts +70 -0
  341. package/dist/lib/cms-views/views-store.js +129 -0
  342. package/dist/lib/cms-views/views-store.js.map +1 -0
  343. package/dist/lib/data/collection-content.d.ts +105 -0
  344. package/dist/lib/data/collection-content.js +196 -0
  345. package/dist/lib/data/collection-content.js.map +1 -0
  346. package/dist/lib/data/data-store.d.ts +97 -0
  347. package/dist/lib/data/data-store.js +205 -0
  348. package/dist/lib/data/data-store.js.map +1 -0
  349. package/dist/lib/data/index.d.ts +4 -0
  350. package/dist/lib/data/index.js +8 -0
  351. package/dist/lib/data/index.js.map +1 -0
  352. package/dist/lib/data/providers.d.ts +143 -0
  353. package/dist/lib/data/providers.js +255 -0
  354. package/dist/lib/data/providers.js.map +1 -0
  355. package/dist/lib/data/sample-capture.d.ts +30 -0
  356. package/dist/lib/data/sample-capture.js +70 -0
  357. package/dist/lib/data/sample-capture.js.map +1 -0
  358. package/dist/lib/data/sources-store.d.ts +42 -0
  359. package/dist/lib/data/sources-store.js +120 -0
  360. package/dist/lib/data/sources-store.js.map +1 -0
  361. package/dist/lib/dnd/drop-rules.d.ts +219 -0
  362. package/dist/lib/dnd/drop-rules.js +257 -0
  363. package/dist/lib/dnd/drop-rules.js.map +1 -0
  364. package/dist/lib/dnd/gap-drag.d.ts +66 -0
  365. package/dist/lib/dnd/gap-drag.js +95 -0
  366. package/dist/lib/dnd/gap-drag.js.map +1 -0
  367. package/dist/lib/locale/binding-fallback.d.ts +28 -0
  368. package/dist/lib/locale/binding-fallback.js +66 -0
  369. package/dist/lib/locale/binding-fallback.js.map +1 -0
  370. package/dist/lib/locale/fallback.d.ts +43 -0
  371. package/dist/lib/locale/fallback.js +52 -0
  372. package/dist/lib/locale/fallback.js.map +1 -0
  373. package/dist/lib/locale/index.d.ts +6 -0
  374. package/dist/lib/locale/index.js +7 -0
  375. package/dist/lib/locale/index.js.map +1 -0
  376. package/dist/lib/locale/locale-store.d.ts +40 -0
  377. package/dist/lib/locale/locale-store.js +61 -0
  378. package/dist/lib/locale/locale-store.js.map +1 -0
  379. package/dist/lib/locale/locale-switcher.d.ts +10 -0
  380. package/dist/lib/locale/locale-switcher.js +24 -0
  381. package/dist/lib/locale/locale-switcher.js.map +1 -0
  382. package/dist/lib/locale/route-variant.d.ts +14 -0
  383. package/dist/lib/locale/route-variant.js +11 -0
  384. package/dist/lib/locale/route-variant.js.map +1 -0
  385. package/dist/lib/locale/use-studio-locale.d.ts +10 -0
  386. package/dist/lib/locale/use-studio-locale.js +8 -0
  387. package/dist/lib/locale/use-studio-locale.js.map +1 -0
  388. package/dist/lib/operations/asset-repository.d.ts +15 -0
  389. package/dist/lib/operations/asset-repository.js +56 -0
  390. package/dist/lib/operations/asset-repository.js.map +1 -0
  391. package/dist/lib/operations/cms-persistence.d.ts +35 -0
  392. package/dist/lib/operations/cms-persistence.js +75 -0
  393. package/dist/lib/operations/cms-persistence.js.map +1 -0
  394. package/dist/lib/operations/graph-commands.d.ts +140 -0
  395. package/dist/lib/operations/graph-commands.js +86 -0
  396. package/dist/lib/operations/graph-commands.js.map +1 -0
  397. package/dist/lib/operations/graph-persistence.d.ts +27 -0
  398. package/dist/lib/operations/graph-persistence.js +35 -0
  399. package/dist/lib/operations/graph-persistence.js.map +1 -0
  400. package/dist/lib/operations/index.d.ts +13 -0
  401. package/dist/lib/operations/index.js +14 -0
  402. package/dist/lib/operations/index.js.map +1 -0
  403. package/dist/lib/operations/operations-package.d.ts +6 -0
  404. package/dist/lib/operations/operations-package.js +7 -0
  405. package/dist/lib/operations/operations-package.js.map +1 -0
  406. package/dist/lib/operations/persist-queue.d.ts +16 -0
  407. package/dist/lib/operations/persist-queue.js +18 -0
  408. package/dist/lib/operations/persist-queue.js.map +1 -0
  409. package/dist/lib/operations/session-hydration.d.ts +84 -0
  410. package/dist/lib/operations/session-hydration.js +112 -0
  411. package/dist/lib/operations/session-hydration.js.map +1 -0
  412. package/dist/lib/operations/studio-operations.d.ts +59 -0
  413. package/dist/lib/operations/studio-operations.js +92 -0
  414. package/dist/lib/operations/studio-operations.js.map +1 -0
  415. package/dist/lib/persistence/backend-mode.d.ts +69 -0
  416. package/dist/lib/persistence/backend-mode.js +120 -0
  417. package/dist/lib/persistence/backend-mode.js.map +1 -0
  418. package/dist/lib/persistence/convex-adapter.d.ts +34 -0
  419. package/dist/lib/persistence/convex-adapter.js +681 -0
  420. package/dist/lib/persistence/convex-adapter.js.map +1 -0
  421. package/dist/lib/persistence/convex-blob-storage.d.ts +57 -0
  422. package/dist/lib/persistence/convex-blob-storage.js +97 -0
  423. package/dist/lib/persistence/convex-blob-storage.js.map +1 -0
  424. package/dist/lib/persistence/convex-client.d.ts +19 -0
  425. package/dist/lib/persistence/convex-client.js +40 -0
  426. package/dist/lib/persistence/convex-client.js.map +1 -0
  427. package/dist/lib/persistence/index.d.ts +30 -0
  428. package/dist/lib/persistence/index.js +60 -0
  429. package/dist/lib/persistence/index.js.map +1 -0
  430. package/dist/lib/persona/labels.d.ts +23 -0
  431. package/dist/lib/persona/labels.js +122 -0
  432. package/dist/lib/persona/labels.js.map +1 -0
  433. package/dist/lib/rail.d.ts +11 -0
  434. package/dist/lib/rail.js +26 -0
  435. package/dist/lib/rail.js.map +1 -0
  436. package/dist/lib/references/impact.d.ts +64 -0
  437. package/dist/lib/references/impact.js +62 -0
  438. package/dist/lib/references/impact.js.map +1 -0
  439. package/dist/lib/references/index.d.ts +7 -0
  440. package/dist/lib/references/index.js +8 -0
  441. package/dist/lib/references/index.js.map +1 -0
  442. package/dist/lib/references/reference-model.d.ts +125 -0
  443. package/dist/lib/references/reference-model.js +242 -0
  444. package/dist/lib/references/reference-model.js.map +1 -0
  445. package/dist/lib/references/references-store.d.ts +65 -0
  446. package/dist/lib/references/references-store.js +221 -0
  447. package/dist/lib/references/references-store.js.map +1 -0
  448. package/dist/lib/registry/index.d.ts +65 -0
  449. package/dist/lib/registry/index.js +114 -0
  450. package/dist/lib/registry/index.js.map +1 -0
  451. package/dist/lib/registry/preview.d.ts +15 -0
  452. package/dist/lib/registry/preview.js +110 -0
  453. package/dist/lib/registry/preview.js.map +1 -0
  454. package/dist/lib/registry/project-components.d.ts +16 -0
  455. package/dist/lib/registry/project-components.js +152 -0
  456. package/dist/lib/registry/project-components.js.map +1 -0
  457. package/dist/lib/routing/index.d.ts +10 -0
  458. package/dist/lib/routing/index.js +11 -0
  459. package/dist/lib/routing/index.js.map +1 -0
  460. package/dist/lib/routing/routing-analysis.d.ts +26 -0
  461. package/dist/lib/routing/routing-analysis.js +37 -0
  462. package/dist/lib/routing/routing-analysis.js.map +1 -0
  463. package/dist/lib/routing/routing-store.d.ts +50 -0
  464. package/dist/lib/routing/routing-store.js +72 -0
  465. package/dist/lib/routing/routing-store.js.map +1 -0
  466. package/dist/lib/starters/kit-session.d.ts +5 -0
  467. package/dist/lib/starters/kit-session.js +17 -0
  468. package/dist/lib/starters/kit-session.js.map +1 -0
  469. package/dist/lib/theme.d.ts +21 -0
  470. package/dist/lib/theme.js +32 -0
  471. package/dist/lib/theme.js.map +1 -0
  472. package/dist/lib/utils.d.ts +11 -0
  473. package/dist/lib/utils.js +28 -0
  474. package/dist/lib/utils.js.map +1 -0
  475. package/dist/lib/webhooks/config.d.ts +15 -0
  476. package/dist/lib/webhooks/config.js +64 -0
  477. package/dist/lib/webhooks/config.js.map +1 -0
  478. package/dist/lib/webhooks/dispatcher.d.ts +67 -0
  479. package/dist/lib/webhooks/dispatcher.js +61 -0
  480. package/dist/lib/webhooks/dispatcher.js.map +1 -0
  481. package/dist/lib/webhooks/index.d.ts +11 -0
  482. package/dist/lib/webhooks/index.js +10 -0
  483. package/dist/lib/webhooks/index.js.map +1 -0
  484. package/dist/lib/webhooks/signing.d.ts +15 -0
  485. package/dist/lib/webhooks/signing.js +24 -0
  486. package/dist/lib/webhooks/signing.js.map +1 -0
  487. package/dist/lib/webhooks/tags.d.ts +25 -0
  488. package/dist/lib/webhooks/tags.js +173 -0
  489. package/dist/lib/webhooks/tags.js.map +1 -0
  490. package/dist/lib/working-graph.d.ts +82 -0
  491. package/dist/lib/working-graph.js +113 -0
  492. package/dist/lib/working-graph.js.map +1 -0
  493. package/dist/lib/workspace/index.d.ts +109 -0
  494. package/dist/lib/workspace/index.js +206 -0
  495. package/dist/lib/workspace/index.js.map +1 -0
  496. package/dist/lib/workspace/switcher-source.d.ts +39 -0
  497. package/dist/lib/workspace/switcher-source.js +23 -0
  498. package/dist/lib/workspace/switcher-source.js.map +1 -0
  499. package/dist/lib/workspace/workspace-source.d.ts +47 -0
  500. package/dist/lib/workspace/workspace-source.js +67 -0
  501. package/dist/lib/workspace/workspace-source.js.map +1 -0
  502. package/dist/router/index.d.ts +32 -0
  503. package/dist/router/index.js +32 -0
  504. package/dist/router/index.js.map +1 -0
  505. package/dist/router/match.d.ts +75 -0
  506. package/dist/router/match.js +87 -0
  507. package/dist/router/match.js.map +1 -0
  508. package/dist/router/search.d.ts +22 -0
  509. package/dist/router/search.js +16 -0
  510. package/dist/router/search.js.map +1 -0
  511. package/dist/ui/avatar.d.ts +17 -0
  512. package/dist/ui/avatar.js +38 -0
  513. package/dist/ui/avatar.js.map +1 -0
  514. package/dist/ui/badge.d.ts +9 -0
  515. package/dist/ui/badge.js +23 -0
  516. package/dist/ui/badge.js.map +1 -0
  517. package/dist/ui/button.d.ts +11 -0
  518. package/dist/ui/button.js +30 -0
  519. package/dist/ui/button.js.map +1 -0
  520. package/dist/ui/card.d.ts +11 -0
  521. package/dist/ui/card.js +23 -0
  522. package/dist/ui/card.js.map +1 -0
  523. package/dist/ui/dialog.d.ts +12 -0
  524. package/dist/ui/dialog.js +27 -0
  525. package/dist/ui/dialog.js.map +1 -0
  526. package/dist/ui/dropdown-menu.d.ts +15 -0
  527. package/dist/ui/dropdown-menu.js +24 -0
  528. package/dist/ui/dropdown-menu.js.map +1 -0
  529. package/dist/ui/field.d.ts +15 -0
  530. package/dist/ui/field.js +14 -0
  531. package/dist/ui/field.js.map +1 -0
  532. package/dist/ui/index.d.ts +14 -0
  533. package/dist/ui/index.js +15 -0
  534. package/dist/ui/index.js.map +1 -0
  535. package/dist/ui/input.d.ts +3 -0
  536. package/dist/ui/input.js +7 -0
  537. package/dist/ui/input.js.map +1 -0
  538. package/dist/ui/inspector.d.ts +18 -0
  539. package/dist/ui/inspector.js +14 -0
  540. package/dist/ui/inspector.js.map +1 -0
  541. package/dist/ui/layout.d.ts +45 -0
  542. package/dist/ui/layout.js +48 -0
  543. package/dist/ui/layout.js.map +1 -0
  544. package/dist/ui/panel.d.ts +12 -0
  545. package/dist/ui/panel.js +20 -0
  546. package/dist/ui/panel.js.map +1 -0
  547. package/dist/ui/separator.d.ts +6 -0
  548. package/dist/ui/separator.js +7 -0
  549. package/dist/ui/separator.js.map +1 -0
  550. package/dist/ui/toolbar.d.ts +9 -0
  551. package/dist/ui/toolbar.js +16 -0
  552. package/dist/ui/toolbar.js.map +1 -0
  553. package/dist/ui/typography.d.ts +50 -0
  554. package/dist/ui/typography.js +43 -0
  555. package/dist/ui/typography.js.map +1 -0
  556. package/package.json +149 -0
  557. package/src/styles/studio.css +101 -0
  558. package/src/styles/tokens.css +63 -0
@@ -0,0 +1,67 @@
1
+ import type { OperationEvent, OperationEventBus } from '@elytracms/operations';
2
+ /**
3
+ * Revalidation webhook dispatcher (EC-146): subscribes to the EC-139
4
+ * operations event bus and POSTs a signed `{projectId, event, tags,
5
+ * timestamp}` payload to every configured host revalidate endpoint whenever a
6
+ * publish-shaped command succeeds (document upsert/delete/setState, graph
7
+ * publish/unpublish). The host's `createRevalidateRoute` (`@elytracms/next`)
8
+ * verifies the HMAC and maps the tags onto `revalidateTag`.
9
+ *
10
+ * This runs **wherever the operations client runs** — in the v1 studio that
11
+ * is the browser, so deliveries are cross-origin `fetch` calls. CORS
12
+ * implications (documented honestly):
13
+ *
14
+ * - the custom signature header always triggers a preflight, so the host
15
+ * endpoint must answer `OPTIONS` and allow the studio origin —
16
+ * `createRevalidateRoute({ allowOrigin })` does both;
17
+ * - the shared secret necessarily ships in the studio bundle in this mode.
18
+ * Acceptable for v1 (the secret only gates cache invalidation, never
19
+ * content access); the server-side Convex action variant
20
+ * (`apps/builder/convex/webhooks.ts`) keeps the secret out of the browser
21
+ * for Convex-backed deployments.
22
+ *
23
+ * Deliveries are fire-and-forget on a serial queue (same pattern as the
24
+ * EC-155 reference index): a slow or unreachable host never blocks the
25
+ * command pipeline, failures surface through `onError` only, and tests await
26
+ * `flush()` for determinism.
27
+ */
28
+ export interface WebhookEndpoint {
29
+ /** Absolute URL of the host's revalidate route, e.g. `https://site/api/revalidate`. */
30
+ url: string;
31
+ /** Shared HMAC secret for this endpoint. */
32
+ secret: string;
33
+ }
34
+ export interface WebhookDispatcherOptions {
35
+ endpoints: readonly WebhookEndpoint[];
36
+ /**
37
+ * All locales the project serves. Document events sweep the collection
38
+ * membership tag once per locale (`collection:<name>:<locale>`).
39
+ */
40
+ locales: readonly string[];
41
+ /** Injectable transport (tests); defaults to global `fetch`. */
42
+ fetchFn?: typeof fetch;
43
+ /** Injectable clock (tests); payload `timestamp` is `now().toISOString()`. */
44
+ now?: () => Date;
45
+ /** Delivery failures land here (never thrown into the command pipeline). */
46
+ onError?: (error: unknown, context: {
47
+ url: string;
48
+ event: OperationEvent;
49
+ }) => void;
50
+ }
51
+ export interface WebhookDispatcherAttachment {
52
+ detach(): void;
53
+ /** Await all queued deliveries (tests / shutdown). */
54
+ flush(): Promise<void>;
55
+ }
56
+ /** The signed payload shape (mirror of `revalidatePayloadSchema` in @elytracms/next). */
57
+ export interface RevalidateWebhookPayload {
58
+ projectId: string;
59
+ event: string;
60
+ tags: string[];
61
+ timestamp: string;
62
+ }
63
+ /**
64
+ * Attach the dispatcher to an event bus; returns a detach/flush handle.
65
+ * With no endpoints configured this still subscribes but never queues work.
66
+ */
67
+ export declare function attachRevalidationWebhooks(events: OperationEventBus, options: WebhookDispatcherOptions): WebhookDispatcherAttachment;
@@ -0,0 +1,61 @@
1
+ import { WEBHOOK_SIGNATURE_HEADER, signWebhookBody } from './signing';
2
+ import { webhookTagsForEvent } from './tags';
3
+ async function deliver(endpoint, tagSet, timestamp, fetchFn) {
4
+ const payload = {
5
+ projectId: tagSet.projectId,
6
+ event: tagSet.event,
7
+ tags: tagSet.tags,
8
+ timestamp,
9
+ };
10
+ // Sign the exact string that goes on the wire.
11
+ const rawBody = JSON.stringify(payload);
12
+ const signature = await signWebhookBody(rawBody, endpoint.secret);
13
+ const response = await fetchFn(endpoint.url, {
14
+ method: 'POST',
15
+ headers: {
16
+ 'content-type': 'application/json',
17
+ [WEBHOOK_SIGNATURE_HEADER]: signature,
18
+ },
19
+ body: rawBody,
20
+ });
21
+ if (!response.ok) {
22
+ throw new Error(`Revalidation webhook to ${endpoint.url} answered ${response.status}.`);
23
+ }
24
+ }
25
+ /**
26
+ * Attach the dispatcher to an event bus; returns a detach/flush handle.
27
+ * With no endpoints configured this still subscribes but never queues work.
28
+ */
29
+ export function attachRevalidationWebhooks(events, options) {
30
+ const fetchFn = options.fetchFn ?? fetch;
31
+ const now = options.now ?? (() => new Date());
32
+ let pending = Promise.resolve();
33
+ const listener = (event) => {
34
+ if (options.endpoints.length === 0)
35
+ return;
36
+ const tagSet = webhookTagsForEvent(event, { locales: options.locales });
37
+ if (!tagSet)
38
+ return;
39
+ const timestamp = now().toISOString();
40
+ for (const endpoint of options.endpoints) {
41
+ pending = pending
42
+ .then(() => deliver(endpoint, tagSet, timestamp, fetchFn))
43
+ .catch((error) => {
44
+ options.onError?.(error, { url: endpoint.url, event });
45
+ });
46
+ }
47
+ };
48
+ const unsubscribe = events.subscribe(listener);
49
+ return {
50
+ detach: unsubscribe,
51
+ flush: async () => {
52
+ // Drain until no new deliveries were queued while awaiting.
53
+ let current;
54
+ do {
55
+ current = pending;
56
+ await current;
57
+ } while (current !== pending);
58
+ },
59
+ };
60
+ }
61
+ //# sourceMappingURL=dispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../../src/lib/webhooks/dispatcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAA;AAkE5C,KAAK,UAAU,OAAO,CACpB,QAAyB,EACzB,MAAqB,EACrB,SAAiB,EACjB,OAAqB;IAErB,MAAM,OAAO,GAA6B;QACxC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,SAAS;KACV,CAAA;IACD,+CAA+C;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IACvC,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IACjE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE;QAC3C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,CAAC,wBAAwB,CAAC,EAAE,SAAS;SACtC;QACD,IAAI,EAAE,OAAO;KACd,CAAC,CAAA;IACF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,CAAC,GAAG,aAAa,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAA;IACzF,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAAyB,EACzB,OAAiC;IAEjC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAA;IACxC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;IAE7C,IAAI,OAAO,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAA;IAE9C,MAAM,QAAQ,GAAG,CAAC,KAAqB,EAAQ,EAAE;QAC/C,IAAI,OAAO,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,OAAM;QAC1C,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;QACvE,IAAI,CAAC,MAAM;YAAE,OAAM;QACnB,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,WAAW,EAAE,CAAA;QACrC,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACzC,OAAO,GAAG,OAAO;iBACd,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;iBACzD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBACxB,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAA;YACxD,CAAC,CAAC,CAAA;QACN,CAAC;IACH,CAAC,CAAA;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;IAC9C,OAAO;QACL,MAAM,EAAE,WAAW;QACnB,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,4DAA4D;YAC5D,IAAI,OAAsB,CAAA;YAC1B,GAAG,CAAC;gBACF,OAAO,GAAG,OAAO,CAAA;gBACjB,MAAM,OAAO,CAAA;YACf,CAAC,QAAQ,OAAO,KAAK,OAAO,EAAC;QAC/B,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * EC-146 instant publish, emitter side: operations-event-driven webhook
3
+ * dispatch to host revalidate endpoints. See `dispatcher.ts` for the
4
+ * delivery/CORS model and `tags.ts` for the tag computation.
5
+ */
6
+ export { attachRevalidationWebhooks } from './dispatcher';
7
+ export type { RevalidateWebhookPayload, WebhookDispatcherAttachment, WebhookDispatcherOptions, WebhookEndpoint, } from './dispatcher';
8
+ export { attachConfiguredRevalidationWebhooks } from './config';
9
+ export { WEBHOOK_SIGNATURE_HEADER, signWebhookBody } from './signing';
10
+ export { collectionWebhookTag, docWebhookTag, projectSweepWebhookTag, webhookTagsForEvent, } from './tags';
11
+ export type { WebhookTagSet } from './tags';
@@ -0,0 +1,10 @@
1
+ /**
2
+ * EC-146 instant publish, emitter side: operations-event-driven webhook
3
+ * dispatch to host revalidate endpoints. See `dispatcher.ts` for the
4
+ * delivery/CORS model and `tags.ts` for the tag computation.
5
+ */
6
+ export { attachRevalidationWebhooks } from './dispatcher';
7
+ export { attachConfiguredRevalidationWebhooks } from './config';
8
+ export { WEBHOOK_SIGNATURE_HEADER, signWebhookBody } from './signing';
9
+ export { collectionWebhookTag, docWebhookTag, projectSweepWebhookTag, webhookTagsForEvent, } from './tags';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/webhooks/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AAOzD,OAAO,EAAE,oCAAoC,EAAE,MAAM,UAAU,CAAA;AAC/D,OAAO,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AACrE,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,QAAQ,CAAA"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * HMAC-SHA256 webhook signing (EC-146), emitter side.
3
+ *
4
+ * Uses the Web Crypto API (`crypto.subtle`) so the same code runs in the
5
+ * browser (the v1 studio dispatcher), in Node tests, and in Convex actions.
6
+ * The receiving end (`@elytracms/next` `evaluateRevalidateRequest`) verifies
7
+ * the same scheme with `node:crypto` and a timing-safe compare.
8
+ *
9
+ * The signature is computed over the **exact raw body string** that is sent
10
+ * — never re-serialize between signing and sending.
11
+ */
12
+ /** Header carrying the signature (mirror of `REVALIDATE_SIGNATURE_HEADER`). */
13
+ export declare const WEBHOOK_SIGNATURE_HEADER = "x-elytra-signature";
14
+ /** Sign a raw webhook body: `sha256=<hex hmac>`. */
15
+ export declare function signWebhookBody(rawBody: string, secret: string): Promise<string>;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * HMAC-SHA256 webhook signing (EC-146), emitter side.
3
+ *
4
+ * Uses the Web Crypto API (`crypto.subtle`) so the same code runs in the
5
+ * browser (the v1 studio dispatcher), in Node tests, and in Convex actions.
6
+ * The receiving end (`@elytracms/next` `evaluateRevalidateRequest`) verifies
7
+ * the same scheme with `node:crypto` and a timing-safe compare.
8
+ *
9
+ * The signature is computed over the **exact raw body string** that is sent
10
+ * — never re-serialize between signing and sending.
11
+ */
12
+ /** Header carrying the signature (mirror of `REVALIDATE_SIGNATURE_HEADER`). */
13
+ export const WEBHOOK_SIGNATURE_HEADER = 'x-elytra-signature';
14
+ function toHex(buffer) {
15
+ return [...new Uint8Array(buffer)].map((byte) => byte.toString(16).padStart(2, '0')).join('');
16
+ }
17
+ /** Sign a raw webhook body: `sha256=<hex hmac>`. */
18
+ export async function signWebhookBody(rawBody, secret) {
19
+ const encoder = new TextEncoder();
20
+ const key = await crypto.subtle.importKey('raw', encoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
21
+ const signature = await crypto.subtle.sign('HMAC', key, encoder.encode(rawBody));
22
+ return `sha256=${toHex(signature)}`;
23
+ }
24
+ //# sourceMappingURL=signing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.js","sourceRoot":"","sources":["../../../src/lib/webhooks/signing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,wBAAwB,GAAG,oBAAoB,CAAA;AAE5D,SAAS,KAAK,CAAC,MAAmB;IAChC,OAAO,CAAC,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AAC/F,CAAC;AAED,oDAAoD;AACpD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAe,EAAE,MAAc;IACnE,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;IACjC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CACvC,KAAK,EACL,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EACtB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EACjC,KAAK,EACL,CAAC,MAAM,CAAC,CACT,CAAA;IACD,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;IAChF,OAAO,UAAU,KAAK,CAAC,SAAS,CAAC,EAAE,CAAA;AACrC,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { OperationEvent } from '@elytracms/operations';
2
+ /** `p:<projectId>:doc:<collection>:<id>` — mirror of `docCacheTag`. */
3
+ export declare function docWebhookTag(projectId: string, collection: string, id: string): string;
4
+ /** `p:<projectId>:collection:<name>:<locale>` — mirror of `collectionCacheTag`. */
5
+ export declare function collectionWebhookTag(projectId: string, collection: string, locale: string): string;
6
+ /** `p:<projectId>:asset:<id>` — mirror of `assetCacheTag` (EC-227). */
7
+ export declare function assetWebhookTag(projectId: string, assetId: string): string;
8
+ /** `p:<projectId>:project` — mirror of `projectSweepTag`. */
9
+ export declare function projectSweepWebhookTag(projectId: string): string;
10
+ /** One computed webhook emission: which project, why, and which tags. */
11
+ export interface WebhookTagSet {
12
+ projectId: string;
13
+ /** The operation name, carried verbatim as the webhook `event`. */
14
+ event: string;
15
+ /** Sorted, deduplicated, fully scoped Next tag strings. */
16
+ tags: string[];
17
+ }
18
+ /**
19
+ * Compute the webhook tag set for one lifecycle event, or `null` when the
20
+ * event is not a successful publish-shaped command (queries, failures, and
21
+ * unrelated domains never fire webhooks).
22
+ */
23
+ export declare function webhookTagsForEvent(event: Pick<OperationEvent, 'operation' | 'kind' | 'status' | 'inputSummary'>, options: {
24
+ locales: readonly string[];
25
+ }): WebhookTagSet | null;
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Pure tag computation for the EC-146 revalidation webhooks: map a succeeded
3
+ * publish-shaped operation event onto the Next cache tags it invalidates.
4
+ *
5
+ * ## Tag format (mirror of `packages/next/src/cache.ts`)
6
+ *
7
+ * The canonical tag format lives in `@elytracms/next` (`src/cache.ts`). The
8
+ * builder cannot depend on that package — it would drag the `next` peer
9
+ * dependency into the studio bundle — so the three formatters are mirrored
10
+ * here. Both sides pin the exact literal strings in their tests
11
+ * (`tags.test.ts` here, `cache.test.ts` there) to keep them in lock-step.
12
+ *
13
+ * Every emitted tag is scoped `p:<projectId>:…` — the dispatcher always knows
14
+ * the project id, and the scope keeps multi-project hosts from
15
+ * cross-invalidating. Hosts must configure the same id as `cache.scope`.
16
+ *
17
+ * ## Which events produce which tags
18
+ *
19
+ * - **Document publish/unpublish/delete/save** (`documents.publish`,
20
+ * `documents.unpublish`, `documents.pinVersion`, `documents.upsert`,
21
+ * `documents.delete`): the document's own
22
+ * `doc:<collection>:<id>` tag — dropping its detail page *and every cached
23
+ * list that actually contained it* (fetch-time tagging) — plus the coarse
24
+ * `collection:<name>:<locale>` membership tag for **all** configured
25
+ * locales, sweeping cached lists whose membership may have changed
26
+ * (new/removed/newly-matching documents).
27
+ * - **Graph publish/unpublish** (`publishing.*`): the whole-project sweep tag
28
+ * `project` — a layout, route, or binding change can affect any page, so
29
+ * the honest v1 fallback (a superset of the per-route + per-collection
30
+ * sweep) is to drop every cached entry of the project. Unrelated projects
31
+ * stay cached.
32
+ * - **Asset edit** (`assets.upsert` of an existing asset, `assets.remove`,
33
+ * EC-227): the `asset:<id>` tag, dropping exactly the pages that *baked* that
34
+ * asset's delivery shape (alt/dimensions/url). An `assets.upsert` CREATE (no
35
+ * id in the summary — minted server-side) fires nothing: a brand-new asset is
36
+ * in no cached page yet.
37
+ * - **Fallback**: when a `documents` (or `assets.remove`) event's input summary
38
+ * was truncated past the identity (EC-139 caps summaries at 160 chars; only
39
+ * very large upserts hit this), the project sweep tag is emitted — coarse,
40
+ * always correct, mirroring the EC-155 reference-index fallback.
41
+ */
42
+ function scoped(projectId, tag) {
43
+ return `p:${projectId}:${tag}`;
44
+ }
45
+ /** `p:<projectId>:doc:<collection>:<id>` — mirror of `docCacheTag`. */
46
+ export function docWebhookTag(projectId, collection, id) {
47
+ return scoped(projectId, `doc:${collection}:${id}`);
48
+ }
49
+ /** `p:<projectId>:collection:<name>:<locale>` — mirror of `collectionCacheTag`. */
50
+ export function collectionWebhookTag(projectId, collection, locale) {
51
+ return scoped(projectId, `collection:${collection}:${locale}`);
52
+ }
53
+ /** `p:<projectId>:asset:<id>` — mirror of `assetCacheTag` (EC-227). */
54
+ export function assetWebhookTag(projectId, assetId) {
55
+ return scoped(projectId, `asset:${assetId}`);
56
+ }
57
+ /** `p:<projectId>:project` — mirror of `projectSweepTag`. */
58
+ export function projectSweepWebhookTag(projectId) {
59
+ return scoped(projectId, 'project');
60
+ }
61
+ /** The operations whose success must reach the host's revalidate endpoint. */
62
+ const DOCUMENT_OPERATIONS = new Set([
63
+ 'documents.upsert',
64
+ 'documents.delete',
65
+ // EC-224: publish/unpublish/pinVersion move the version pointer; their
66
+ // `{ projectId, ref }` input drives the same doc + per-locale collection tag
67
+ // set (the flat `documents.setState` op is gone).
68
+ 'documents.publish',
69
+ 'documents.unpublish',
70
+ 'documents.pinVersion',
71
+ ]);
72
+ const PUBLISHING_OPERATIONS = new Set(['publishing.publish', 'publishing.unpublish']);
73
+ /**
74
+ * Asset-record mutations (EC-227): editing an asset (alt/dimensions/re-upload)
75
+ * must drop the published pages that *baked* its delivery shape, which carry the
76
+ * `asset:<id>` tag. `assets.remove` always carries `assetId`; `assets.upsert`
77
+ * carries `asset.id` only on an EDIT (a CREATE mints the id server-side).
78
+ */
79
+ const ASSET_OPERATIONS = new Set(['assets.upsert', 'assets.remove']);
80
+ /** Tolerant parse of an EC-139 input summary (may be truncated past 160 chars). */
81
+ function parseSummary(summary) {
82
+ try {
83
+ const parsed = JSON.parse(summary);
84
+ return typeof parsed === 'object' && parsed !== null
85
+ ? parsed
86
+ : undefined;
87
+ }
88
+ catch {
89
+ return undefined;
90
+ }
91
+ }
92
+ /** Extract the projectId even from a truncated summary (it serializes first). */
93
+ function projectIdOfSummary(summary) {
94
+ const match = /"projectId":"([^"]+)"/.exec(summary);
95
+ return match?.[1];
96
+ }
97
+ function documentRefOf(value) {
98
+ if (typeof value !== 'object' || value === null)
99
+ return undefined;
100
+ const candidate = value;
101
+ return typeof candidate.collection === 'string' &&
102
+ candidate.collection.length > 0 &&
103
+ typeof candidate.id === 'string' &&
104
+ candidate.id.length > 0
105
+ ? { collection: candidate.collection, id: candidate.id }
106
+ : undefined;
107
+ }
108
+ /**
109
+ * Compute the webhook tag set for one lifecycle event, or `null` when the
110
+ * event is not a successful publish-shaped command (queries, failures, and
111
+ * unrelated domains never fire webhooks).
112
+ */
113
+ export function webhookTagsForEvent(event, options) {
114
+ if (event.status !== 'succeeded' || event.kind !== 'command')
115
+ return null;
116
+ const isDocument = DOCUMENT_OPERATIONS.has(event.operation);
117
+ const isPublishing = PUBLISHING_OPERATIONS.has(event.operation);
118
+ const isAsset = ASSET_OPERATIONS.has(event.operation);
119
+ if (!isDocument && !isPublishing && !isAsset)
120
+ return null;
121
+ const projectId = projectIdOfSummary(event.inputSummary);
122
+ if (projectId === undefined)
123
+ return null;
124
+ if (isPublishing) {
125
+ return {
126
+ projectId,
127
+ event: event.operation,
128
+ tags: [projectSweepWebhookTag(projectId)],
129
+ };
130
+ }
131
+ if (isAsset)
132
+ return assetTagsForEvent(projectId, event);
133
+ const parsed = parseSummary(event.inputSummary);
134
+ const ref = documentRefOf(parsed?.['ref']) ?? documentRefOf(parsed?.['document']);
135
+ if (!ref) {
136
+ // Truncated summary (large upsert payload): honest coarse fallback.
137
+ return { projectId, event: event.operation, tags: [projectSweepWebhookTag(projectId)] };
138
+ }
139
+ const tags = new Set([docWebhookTag(projectId, ref.collection, ref.id)]);
140
+ for (const locale of options.locales) {
141
+ tags.add(collectionWebhookTag(projectId, ref.collection, locale));
142
+ }
143
+ // EC-207: routes/redirects are config-owned (a code deploy, which rebuilds the
144
+ // host) — they are no longer DB documents, so there is no route-document event
145
+ // to sweep the project for. Graph publishes still emit the project sweep above.
146
+ return { projectId, event: event.operation, tags: [...tags].sort() };
147
+ }
148
+ /** A non-empty string, else `undefined` (the asset id out of a summary). */
149
+ function stringOf(value) {
150
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
151
+ }
152
+ /**
153
+ * Tags for an asset mutation (EC-227). The edit cases — `assets.remove` (carries
154
+ * `assetId`) and `assets.upsert` of an existing asset (carries `asset.id`) —
155
+ * emit exactly `asset:<id>`, dropping the pages that baked that asset. An
156
+ * `assets.upsert` with **no** id is a CREATE: the id is minted server-side and a
157
+ * brand-new asset cannot be baked into any existing page, so it invalidates
158
+ * nothing (`null`, no webhook). A `remove` missing its id means a truncated
159
+ * summary — sweep the project (coarse, always correct — the document fallback).
160
+ */
161
+ function assetTagsForEvent(projectId, event) {
162
+ const parsed = parseSummary(event.inputSummary);
163
+ const assetId = event.operation === 'assets.remove'
164
+ ? stringOf(parsed?.['assetId'])
165
+ : stringOf(parsed?.['asset']?.id);
166
+ if (assetId) {
167
+ return { projectId, event: event.operation, tags: [assetWebhookTag(projectId, assetId)] };
168
+ }
169
+ return event.operation === 'assets.remove'
170
+ ? { projectId, event: event.operation, tags: [projectSweepWebhookTag(projectId)] }
171
+ : null;
172
+ }
173
+ //# sourceMappingURL=tags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tags.js","sourceRoot":"","sources":["../../../src/lib/webhooks/tags.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ import type { ComponentNode, Layout, ProjectGraph } from '@elytracms/project-graph';
2
+ /**
3
+ * Builder-local WORKING GRAPH (EC-187).
4
+ *
5
+ * The canonical {@link ProjectGraph} is now LAYOUTS-ONLY — a page is a document
6
+ * in the `page` collection (its `body` is a composition field value). But the
7
+ * legacy `/builder` editor and the composition-field editor are *node-tree*
8
+ * editors: they edit a single root-bearing surface with undo/redo, selection,
9
+ * and the same structural edit ops. So the builder store keeps its own
10
+ * root-bearing working type, decoupled from the page-less canonical schema.
11
+ *
12
+ * A `WorkingGraph` is a `ProjectGraph` (layouts + metadata) PLUS a `pages`
13
+ * array of {@link WorkingPage} — exactly the shape the reducer/history/edit ops
14
+ * have always operated on. It NEVER persists in this shape: page-body edits lift
15
+ * into a CMS document (the composition-field editor), and layout edits persist
16
+ * through the canonical layouts-only `graph.save`. {@link toProjectGraph} drops
17
+ * the pages to produce the canonical graph when one is needed.
18
+ */
19
+ /**
20
+ * Per-page SEO block (EC-171, legacy `/builder` chrome). The canonical
21
+ * `PageSeo` shape lived in `@elytracms/project-graph` and was deleted with the
22
+ * page node (EC-187); page SEO now lives on the `page` collection document's
23
+ * flat `seo*` fields. The legacy page-SEO panel keeps editing this local block
24
+ * so it stays compiling/tested until `/builder` is retired.
25
+ */
26
+ export interface WorkingPageSeo {
27
+ title?: string;
28
+ description?: string;
29
+ ogTitle?: string;
30
+ ogImage?: string;
31
+ noindex?: boolean;
32
+ }
33
+ /** A page in the builder's working state — a root-bearing editable surface. */
34
+ export interface WorkingPage {
35
+ id: string;
36
+ name: string;
37
+ /** Optional shared layout wrapper id (canvas preview only). */
38
+ layoutId?: string;
39
+ /** Root node of the page's component tree (the edited surface). */
40
+ root: ComponentNode;
41
+ /** Legacy per-page SEO block (EC-171). */
42
+ seo?: WorkingPageSeo;
43
+ }
44
+ /** The builder's internal working graph: the canonical layouts-only graph + editable pages. */
45
+ export interface WorkingGraph {
46
+ id: string;
47
+ schemaVersion: number;
48
+ metadata?: {
49
+ name?: string;
50
+ };
51
+ settingsRef?: string;
52
+ layouts: Layout[];
53
+ pages: WorkingPage[];
54
+ }
55
+ /**
56
+ * Lift a (layouts-only) canonical {@link ProjectGraph} into a {@link WorkingGraph}
57
+ * with a single editable page, so the legacy builder canvas has a root to edit.
58
+ * The page root is an empty Stack the editor fills; the page selects the first
59
+ * layout for canvas preview (if any).
60
+ */
61
+ export declare function toWorkingGraph(graph: ProjectGraph): WorkingGraph;
62
+ /** Drop the editable pages to produce the canonical (layouts-only) {@link ProjectGraph}. */
63
+ export declare function toProjectGraph(graph: WorkingGraph): ProjectGraph;
64
+ /** Build a working graph that wraps one composition value in a single editable page. */
65
+ export declare function workingGraphFromPage(page: WorkingPage, layouts?: Layout[]): WorkingGraph;
66
+ /**
67
+ * Normalize every editable surface of a working graph — each page root AND
68
+ * each layout root — via `normalizeContainers`. Mirrors the OLD
69
+ * `normalizeProjectGraph` (which normalized pages too, before EC-187 made the
70
+ * canonical graph layouts-only). Identity-preserving: returns the same graph
71
+ * reference when nothing changed so undo histories can detect no-ops by
72
+ * reference.
73
+ */
74
+ export declare function normalizeWorkingGraph(graph: WorkingGraph): WorkingGraph;
75
+ /** Strip empty fields; an all-empty block becomes `undefined` (clear the block). */
76
+ export declare function cleanWorkingPageSeo(seo: WorkingPageSeo): WorkingPageSeo | undefined;
77
+ /**
78
+ * Apply a (cleaned) SEO block to a page in the working graph. Identity on
79
+ * no-ops — callers dispatch only when this returns a new graph. An `undefined`
80
+ * block removes `seo` from the page entity entirely.
81
+ */
82
+ export declare function setWorkingPageSeo(graph: WorkingGraph, pageId: string, seo: WorkingPageSeo | undefined): WorkingGraph;
@@ -0,0 +1,113 @@
1
+ import { normalizeContainers, PROJECT_GRAPH_SCHEMA_VERSION } from '@elytracms/project-graph';
2
+ const SYNTH_PAGE_ID = 'page.working';
3
+ /**
4
+ * Lift a (layouts-only) canonical {@link ProjectGraph} into a {@link WorkingGraph}
5
+ * with a single editable page, so the legacy builder canvas has a root to edit.
6
+ * The page root is an empty Stack the editor fills; the page selects the first
7
+ * layout for canvas preview (if any).
8
+ */
9
+ export function toWorkingGraph(graph) {
10
+ return {
11
+ ...graph,
12
+ pages: [
13
+ {
14
+ id: SYNTH_PAGE_ID,
15
+ name: graph.metadata?.name ?? 'Page',
16
+ ...(graph.layouts[0] ? { layoutId: graph.layouts[0].id } : {}),
17
+ root: { id: 'working.root', componentId: 'base.primitives.Stack', slots: { children: [] } },
18
+ },
19
+ ],
20
+ };
21
+ }
22
+ /** Drop the editable pages to produce the canonical (layouts-only) {@link ProjectGraph}. */
23
+ export function toProjectGraph(graph) {
24
+ const { pages: _pages, ...canonical } = graph;
25
+ return canonical;
26
+ }
27
+ /** Build a working graph that wraps one composition value in a single editable page. */
28
+ export function workingGraphFromPage(page, layouts = []) {
29
+ return {
30
+ id: 'working',
31
+ schemaVersion: PROJECT_GRAPH_SCHEMA_VERSION,
32
+ layouts,
33
+ pages: [page],
34
+ };
35
+ }
36
+ /**
37
+ * Normalize every editable surface of a working graph — each page root AND
38
+ * each layout root — via `normalizeContainers`. Mirrors the OLD
39
+ * `normalizeProjectGraph` (which normalized pages too, before EC-187 made the
40
+ * canonical graph layouts-only). Identity-preserving: returns the same graph
41
+ * reference when nothing changed so undo histories can detect no-ops by
42
+ * reference.
43
+ */
44
+ export function normalizeWorkingGraph(graph) {
45
+ let changed = false;
46
+ const pages = graph.pages.map((page) => {
47
+ const root = normalizeContainers(page.root);
48
+ if (root !== page.root)
49
+ changed = true;
50
+ return root === page.root ? page : { ...page, root };
51
+ });
52
+ const layouts = graph.layouts.map((layout) => {
53
+ const root = normalizeContainers(layout.root);
54
+ if (root !== layout.root)
55
+ changed = true;
56
+ return root === layout.root ? layout : { ...layout, root };
57
+ });
58
+ return changed ? { ...graph, pages, layouts } : graph;
59
+ }
60
+ // ---- Legacy page SEO (EC-171) ----------------------------------------------
61
+ //
62
+ // The canonical `setPageSeo`/`cleanPageSeo`/`PageSeo` were deleted with the
63
+ // page node (EC-187). These local helpers mirror the old behavior over the
64
+ // working graph's per-page `seo` block so the legacy SEO panel keeps working.
65
+ /** Strip empty fields; an all-empty block becomes `undefined` (clear the block). */
66
+ export function cleanWorkingPageSeo(seo) {
67
+ const trimmed = (value) => {
68
+ const next = value?.trim();
69
+ return next ? next : undefined;
70
+ };
71
+ const next = {};
72
+ const title = trimmed(seo.title);
73
+ const description = trimmed(seo.description);
74
+ const ogTitle = trimmed(seo.ogTitle);
75
+ const ogImage = trimmed(seo.ogImage);
76
+ if (title !== undefined)
77
+ next.title = title;
78
+ if (description !== undefined)
79
+ next.description = description;
80
+ if (ogTitle !== undefined)
81
+ next.ogTitle = ogTitle;
82
+ if (ogImage !== undefined)
83
+ next.ogImage = ogImage;
84
+ if (seo.noindex)
85
+ next.noindex = true;
86
+ return Object.keys(next).length > 0 ? next : undefined;
87
+ }
88
+ /**
89
+ * Apply a (cleaned) SEO block to a page in the working graph. Identity on
90
+ * no-ops — callers dispatch only when this returns a new graph. An `undefined`
91
+ * block removes `seo` from the page entity entirely.
92
+ */
93
+ export function setWorkingPageSeo(graph, pageId, seo) {
94
+ const page = graph.pages.find((p) => p.id === pageId);
95
+ if (!page)
96
+ return graph;
97
+ const sameBlock = JSON.stringify(page.seo ?? null) === JSON.stringify(seo ?? null);
98
+ if (sameBlock)
99
+ return graph;
100
+ return {
101
+ ...graph,
102
+ pages: graph.pages.map((p) => {
103
+ if (p.id !== pageId)
104
+ return p;
105
+ if (seo === undefined) {
106
+ const { seo: _drop, ...rest } = p;
107
+ return rest;
108
+ }
109
+ return { ...p, seo };
110
+ }),
111
+ };
112
+ }
113
+ //# sourceMappingURL=working-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"working-graph.js","sourceRoot":"","sources":["../../src/lib/working-graph.ts"],"names":[],"mappings":"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"}