astro-tractstack 2.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (427) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +56 -0
  3. package/astro.d.ts +64 -0
  4. package/bin/create-tractstack.js +483 -0
  5. package/dist/config.js +80 -0
  6. package/dist/index.js +2129 -0
  7. package/package.json +89 -0
  8. package/templates/artpacks/kCz/captainBreakfast_1080px.webp +0 -0
  9. package/templates/artpacks/kCz/captainBreakfast_1920px.webp +0 -0
  10. package/templates/artpacks/kCz/captainBreakfast_600px.webp +0 -0
  11. package/templates/artpacks/kCz/cleanDrips_1080px.webp +0 -0
  12. package/templates/artpacks/kCz/cleanDrips_1920px.webp +0 -0
  13. package/templates/artpacks/kCz/cleanDrips_600px.webp +0 -0
  14. package/templates/artpacks/kCz/crispwaves_1080px.webp +0 -0
  15. package/templates/artpacks/kCz/crispwaves_1920px.webp +0 -0
  16. package/templates/artpacks/kCz/crispwaves_600px.webp +0 -0
  17. package/templates/artpacks/kCz/dragonSkin_1080px.webp +0 -0
  18. package/templates/artpacks/kCz/dragonSkin_1920px.webp +0 -0
  19. package/templates/artpacks/kCz/dragonSkin_600px.webp +0 -0
  20. package/templates/artpacks/kCz/dragon_1080px.webp +0 -0
  21. package/templates/artpacks/kCz/dragon_1920px.webp +0 -0
  22. package/templates/artpacks/kCz/dragon_600px.webp +0 -0
  23. package/templates/artpacks/kCz/nightcity_1080px.webp +0 -0
  24. package/templates/artpacks/kCz/nightcity_1920px.webp +0 -0
  25. package/templates/artpacks/kCz/nightcity_600px.webp +0 -0
  26. package/templates/artpacks/kCz/pattern1_1080px.webp +0 -0
  27. package/templates/artpacks/kCz/pattern1_1920px.webp +0 -0
  28. package/templates/artpacks/kCz/pattern1_600px.webp +0 -0
  29. package/templates/artpacks/kCz/pattern2_1080px.webp +0 -0
  30. package/templates/artpacks/kCz/pattern2_1920px.webp +0 -0
  31. package/templates/artpacks/kCz/pattern2_600px.webp +0 -0
  32. package/templates/artpacks/kCz/skindrips_1080px.webp +0 -0
  33. package/templates/artpacks/kCz/skindrips_1920px.webp +0 -0
  34. package/templates/artpacks/kCz/skindrips_600px.webp +0 -0
  35. package/templates/artpacks/kCz/slimetime_1080px.webp +0 -0
  36. package/templates/artpacks/kCz/slimetime_1920px.webp +0 -0
  37. package/templates/artpacks/kCz/slimetime_600px.webp +0 -0
  38. package/templates/artpacks/kCz/snake_1080px.webp +0 -0
  39. package/templates/artpacks/kCz/snake_1920px.webp +0 -0
  40. package/templates/artpacks/kCz/snake_600px.webp +0 -0
  41. package/templates/artpacks/kCz/toxicshock_1080px.webp +0 -0
  42. package/templates/artpacks/kCz/toxicshock_1920px.webp +0 -0
  43. package/templates/artpacks/kCz/toxicshock_600px.webp +0 -0
  44. package/templates/artpacks/kCz/tractstack_1080px.webp +0 -0
  45. package/templates/artpacks/kCz/tractstack_1920px.webp +0 -0
  46. package/templates/artpacks/kCz/tractstack_600px.webp +0 -0
  47. package/templates/artpacks/kCz/tripdrips_1080px.webp +0 -0
  48. package/templates/artpacks/kCz/tripdrips_1920px.webp +0 -0
  49. package/templates/artpacks/kCz/tripdrips_600px.webp +0 -0
  50. package/templates/artpacks/kCz/wavedrips_1080px.webp +0 -0
  51. package/templates/artpacks/kCz/wavedrips_1920px.webp +0 -0
  52. package/templates/artpacks/kCz/wavedrips_600px.webp +0 -0
  53. package/templates/artpacks/t8k/beach_1080px.webp +0 -0
  54. package/templates/artpacks/t8k/beach_1920px.webp +0 -0
  55. package/templates/artpacks/t8k/beach_600px.webp +0 -0
  56. package/templates/artpacks/t8k/blast_1080px.webp +0 -0
  57. package/templates/artpacks/t8k/blast_1920px.webp +0 -0
  58. package/templates/artpacks/t8k/blast_600px.webp +0 -0
  59. package/templates/artpacks/t8k/bokeh_1080px.webp +0 -0
  60. package/templates/artpacks/t8k/bokeh_1920px.webp +0 -0
  61. package/templates/artpacks/t8k/bokeh_600px.webp +0 -0
  62. package/templates/artpacks/t8k/cartoon_1080px.webp +0 -0
  63. package/templates/artpacks/t8k/cartoon_1920px.webp +0 -0
  64. package/templates/artpacks/t8k/cartoon_600px.webp +0 -0
  65. package/templates/artpacks/t8k/darkeggshell_1080px.webp +0 -0
  66. package/templates/artpacks/t8k/darkeggshell_1920px.webp +0 -0
  67. package/templates/artpacks/t8k/darkeggshell_600px.webp +0 -0
  68. package/templates/artpacks/t8k/explosion_1080px.webp +0 -0
  69. package/templates/artpacks/t8k/explosion_1920px.webp +0 -0
  70. package/templates/artpacks/t8k/explosion_600px.webp +0 -0
  71. package/templates/artpacks/t8k/floral_1080px.webp +0 -0
  72. package/templates/artpacks/t8k/floral_1920px.webp +0 -0
  73. package/templates/artpacks/t8k/floral_600px.webp +0 -0
  74. package/templates/artpacks/t8k/flower_1080px.webp +0 -0
  75. package/templates/artpacks/t8k/flower_1920px.webp +0 -0
  76. package/templates/artpacks/t8k/flower_600px.webp +0 -0
  77. package/templates/artpacks/t8k/foliage_1080px.webp +0 -0
  78. package/templates/artpacks/t8k/foliage_1920px.webp +0 -0
  79. package/templates/artpacks/t8k/foliage_600px.webp +0 -0
  80. package/templates/artpacks/t8k/mist_1080px.webp +0 -0
  81. package/templates/artpacks/t8k/mist_1920px.webp +0 -0
  82. package/templates/artpacks/t8k/mist_600px.webp +0 -0
  83. package/templates/artpacks/t8k/portal_1080px.webp +0 -0
  84. package/templates/artpacks/t8k/portal_1920px.webp +0 -0
  85. package/templates/artpacks/t8k/portal_600px.webp +0 -0
  86. package/templates/artpacks/t8k/storytime_1080px.webp +0 -0
  87. package/templates/artpacks/t8k/storytime_1920px.webp +0 -0
  88. package/templates/artpacks/t8k/storytime_600px.webp +0 -0
  89. package/templates/artpacks/t8k/tacky_1080px.webp +0 -0
  90. package/templates/artpacks/t8k/tacky_1920px.webp +0 -0
  91. package/templates/artpacks/t8k/tacky_600px.webp +0 -0
  92. package/templates/artpacks/t8k/wallpaper_1080px.webp +0 -0
  93. package/templates/artpacks/t8k/wallpaper_1920px.webp +0 -0
  94. package/templates/artpacks/t8k/wallpaper_600px.webp +0 -0
  95. package/templates/brand/favicon.ico +0 -0
  96. package/templates/brand/logo.svg +19 -0
  97. package/templates/brand/static.jpg +0 -0
  98. package/templates/brand/wordmark.svg +4 -0
  99. package/templates/css/custom.css +51 -0
  100. package/templates/css/frontend.css +3519 -0
  101. package/templates/css/storykeep.css +92872 -0
  102. package/templates/custom/minimal/CodeHook.astro +53 -0
  103. package/templates/custom/minimal/CustomRoutes.astro +46 -0
  104. package/templates/custom/with-examples/CodeHook.astro +49 -0
  105. package/templates/custom/with-examples/CustomHero.astro +13 -0
  106. package/templates/custom/with-examples/CustomRoutes.astro +39 -0
  107. package/templates/custom/with-examples/pages/Collections.astro +110 -0
  108. package/templates/env.example +8 -0
  109. package/templates/fonts/Inter-Black.woff2 +0 -0
  110. package/templates/fonts/Inter-Bold.woff2 +0 -0
  111. package/templates/fonts/Inter-Regular.woff2 +0 -0
  112. package/templates/icons/h2.svg +1 -0
  113. package/templates/icons/h3.svg +1 -0
  114. package/templates/icons/h4.svg +1 -0
  115. package/templates/icons/h5.svg +1 -0
  116. package/templates/icons/image.svg +7 -0
  117. package/templates/icons/text.svg +6 -0
  118. package/templates/socials/codepen.svg +1 -0
  119. package/templates/socials/discord.svg +1 -0
  120. package/templates/socials/facebook.svg +1 -0
  121. package/templates/socials/github.svg +1 -0
  122. package/templates/socials/instagram.svg +1 -0
  123. package/templates/socials/linkedin.svg +1 -0
  124. package/templates/socials/mail.svg +1 -0
  125. package/templates/socials/rumble.svg +1 -0
  126. package/templates/socials/tiktok.svg +1 -0
  127. package/templates/socials/twitch.svg +1 -0
  128. package/templates/socials/twitter.svg +1 -0
  129. package/templates/socials/x.svg +1 -0
  130. package/templates/socials/youtube.svg +1 -0
  131. package/templates/src/client/analytics-events.ts +213 -0
  132. package/templates/src/client/belief-events.ts +205 -0
  133. package/templates/src/client/sse.ts +667 -0
  134. package/templates/src/components/Footer.astro +246 -0
  135. package/templates/src/components/Fragment.astro +70 -0
  136. package/templates/src/components/Header.astro +458 -0
  137. package/templates/src/components/Menu.tsx +196 -0
  138. package/templates/src/components/codehooks/BunnyVideoSetup.tsx +692 -0
  139. package/templates/src/components/codehooks/BunnyVideoWrapper.astro +78 -0
  140. package/templates/src/components/codehooks/EpinetDurationSelector.tsx +1020 -0
  141. package/templates/src/components/codehooks/EpinetTableView.tsx +594 -0
  142. package/templates/src/components/codehooks/EpinetWrapper.tsx +424 -0
  143. package/templates/src/components/codehooks/FeaturedContent.astro +273 -0
  144. package/templates/src/components/codehooks/FeaturedContentSetup.tsx +738 -0
  145. package/templates/src/components/codehooks/ListContent.astro +460 -0
  146. package/templates/src/components/codehooks/ListContentSetup.tsx +649 -0
  147. package/templates/src/components/codehooks/SankeyDiagram.tsx +359 -0
  148. package/templates/src/components/compositor/Compositor.tsx +144 -0
  149. package/templates/src/components/compositor/Node.tsx +415 -0
  150. package/templates/src/components/compositor/NodeWithGuid.tsx +25 -0
  151. package/templates/src/components/compositor/PanelVisibilityWrapper.tsx +87 -0
  152. package/templates/src/components/compositor/elements/Belief.tsx +148 -0
  153. package/templates/src/components/compositor/elements/BgImage.tsx +118 -0
  154. package/templates/src/components/compositor/elements/BgVisualBreak.tsx +102 -0
  155. package/templates/src/components/compositor/elements/BunnyVideo.tsx +63 -0
  156. package/templates/src/components/compositor/elements/IdentifyAs.tsx +66 -0
  157. package/templates/src/components/compositor/elements/PlayButton.tsx +19 -0
  158. package/templates/src/components/compositor/elements/SignUp.tsx +179 -0
  159. package/templates/src/components/compositor/elements/Svg.tsx +33 -0
  160. package/templates/src/components/compositor/elements/ToggleBelief.tsx +36 -0
  161. package/templates/src/components/compositor/elements/YouTubeWrapper.tsx +33 -0
  162. package/templates/src/components/compositor/nodes/BgPaneWrapper.tsx +35 -0
  163. package/templates/src/components/compositor/nodes/GhostInsertBlock.tsx +189 -0
  164. package/templates/src/components/compositor/nodes/Markdown.tsx +179 -0
  165. package/templates/src/components/compositor/nodes/Pane.tsx +277 -0
  166. package/templates/src/components/compositor/nodes/Pane_eraser.tsx +69 -0
  167. package/templates/src/components/compositor/nodes/Pane_layout.tsx +77 -0
  168. package/templates/src/components/compositor/nodes/RenderChildren.tsx +19 -0
  169. package/templates/src/components/compositor/nodes/StoryFragment.tsx +35 -0
  170. package/templates/src/components/compositor/nodes/TagElement.tsx +14 -0
  171. package/templates/src/components/compositor/nodes/Widget.tsx +115 -0
  172. package/templates/src/components/compositor/nodes/tagElements/NodeA.tsx +4 -0
  173. package/templates/src/components/compositor/nodes/tagElements/NodeA_eraser.tsx +26 -0
  174. package/templates/src/components/compositor/nodes/tagElements/NodeAnchorComponent.tsx +248 -0
  175. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag.tsx +684 -0
  176. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag_eraser.tsx +62 -0
  177. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag_insert.tsx +120 -0
  178. package/templates/src/components/compositor/nodes/tagElements/NodeBasicTag_settings.tsx +62 -0
  179. package/templates/src/components/compositor/nodes/tagElements/NodeButton.tsx +5 -0
  180. package/templates/src/components/compositor/nodes/tagElements/NodeButton_eraser.tsx +26 -0
  181. package/templates/src/components/compositor/nodes/tagElements/NodeImg.tsx +28 -0
  182. package/templates/src/components/compositor/nodes/tagElements/NodeText.tsx +18 -0
  183. package/templates/src/components/compositor/nodes/tagElements/TabIndicator.tsx +51 -0
  184. package/templates/src/components/compositor/preview/FeaturedContentPreview.tsx +128 -0
  185. package/templates/src/components/compositor/preview/ListContentPreview.tsx +213 -0
  186. package/templates/src/components/compositor/preview/OgImagePreview.tsx +223 -0
  187. package/templates/src/components/compositor/preview/PaneSnapshotGenerator.tsx +199 -0
  188. package/templates/src/components/compositor/preview/PanesPreviewGenerator.tsx +123 -0
  189. package/templates/src/components/compositor/preview/VisualBreakPreview.tsx +154 -0
  190. package/templates/src/components/edit/Header.tsx +181 -0
  191. package/templates/src/components/edit/PanelSwitch.tsx +446 -0
  192. package/templates/src/components/edit/SettingsPanel.tsx +70 -0
  193. package/templates/src/components/edit/ToolBar.tsx +101 -0
  194. package/templates/src/components/edit/ToolMode.tsx +121 -0
  195. package/templates/src/components/edit/context/ContextPaneConfig.tsx +91 -0
  196. package/templates/src/components/edit/context/ContextPaneConfig_slug.tsx +174 -0
  197. package/templates/src/components/edit/context/ContextPaneConfig_title.tsx +186 -0
  198. package/templates/src/components/edit/pane/AddPanePanel.tsx +136 -0
  199. package/templates/src/components/edit/pane/AddPanePanel_break.tsx +470 -0
  200. package/templates/src/components/edit/pane/AddPanePanel_codehook.tsx +264 -0
  201. package/templates/src/components/edit/pane/AddPanePanel_new.tsx +623 -0
  202. package/templates/src/components/edit/pane/AddPanePanel_newAICopy.tsx +107 -0
  203. package/templates/src/components/edit/pane/AddPanePanel_newAICopy_modal.tsx +217 -0
  204. package/templates/src/components/edit/pane/AddPanePanel_newCopyMode.tsx +109 -0
  205. package/templates/src/components/edit/pane/AddPanePanel_newCustomCopy.tsx +39 -0
  206. package/templates/src/components/edit/pane/AddPanePanel_reuse.tsx +445 -0
  207. package/templates/src/components/edit/pane/ConfigPanePanel.tsx +245 -0
  208. package/templates/src/components/edit/pane/PageGen.tsx +485 -0
  209. package/templates/src/components/edit/pane/PageGenSelector.tsx +238 -0
  210. package/templates/src/components/edit/pane/PageGenSpecial.tsx +362 -0
  211. package/templates/src/components/edit/pane/PageGen_preview.tsx +495 -0
  212. package/templates/src/components/edit/pane/PanePanel_impression.tsx +258 -0
  213. package/templates/src/components/edit/pane/PanePanel_path.tsx +268 -0
  214. package/templates/src/components/edit/pane/PanePanel_slug.tsx +219 -0
  215. package/templates/src/components/edit/pane/PanePanel_title.tsx +142 -0
  216. package/templates/src/components/edit/panels/StyleBreakPanel.tsx +182 -0
  217. package/templates/src/components/edit/panels/StyleCodeHookPanel.tsx +439 -0
  218. package/templates/src/components/edit/panels/StyleElementPanel.tsx +177 -0
  219. package/templates/src/components/edit/panels/StyleElementPanel_add.tsx +349 -0
  220. package/templates/src/components/edit/panels/StyleElementPanel_remove.tsx +159 -0
  221. package/templates/src/components/edit/panels/StyleElementPanel_update.tsx +320 -0
  222. package/templates/src/components/edit/panels/StyleImagePanel.tsx +460 -0
  223. package/templates/src/components/edit/panels/StyleImagePanel_add.tsx +296 -0
  224. package/templates/src/components/edit/panels/StyleImagePanel_remove.tsx +153 -0
  225. package/templates/src/components/edit/panels/StyleImagePanel_update.tsx +312 -0
  226. package/templates/src/components/edit/panels/StyleLiElementPanel.tsx +273 -0
  227. package/templates/src/components/edit/panels/StyleLiElementPanel_add.tsx +301 -0
  228. package/templates/src/components/edit/panels/StyleLiElementPanel_remove.tsx +132 -0
  229. package/templates/src/components/edit/panels/StyleLiElementPanel_update.tsx +313 -0
  230. package/templates/src/components/edit/panels/StyleLinkPanel.tsx +346 -0
  231. package/templates/src/components/edit/panels/StyleLinkPanel_add.tsx +265 -0
  232. package/templates/src/components/edit/panels/StyleLinkPanel_config.tsx +240 -0
  233. package/templates/src/components/edit/panels/StyleLinkPanel_remove.tsx +94 -0
  234. package/templates/src/components/edit/panels/StyleLinkPanel_update.tsx +110 -0
  235. package/templates/src/components/edit/panels/StyleParentPanel.tsx +263 -0
  236. package/templates/src/components/edit/panels/StyleParentPanel_add.tsx +275 -0
  237. package/templates/src/components/edit/panels/StyleParentPanel_deleteLayer.tsx +112 -0
  238. package/templates/src/components/edit/panels/StyleParentPanel_remove.tsx +87 -0
  239. package/templates/src/components/edit/panels/StyleParentPanel_update.tsx +141 -0
  240. package/templates/src/components/edit/panels/StyleWidgetPanel.tsx +428 -0
  241. package/templates/src/components/edit/panels/StyleWidgetPanel_add.tsx +292 -0
  242. package/templates/src/components/edit/panels/StyleWidgetPanel_config.tsx +190 -0
  243. package/templates/src/components/edit/panels/StyleWidgetPanel_remove.tsx +152 -0
  244. package/templates/src/components/edit/panels/StyleWidgetPanel_update.tsx +308 -0
  245. package/templates/src/components/edit/state/SaveModal.tsx +811 -0
  246. package/templates/src/components/edit/state/StylesMemory.tsx +310 -0
  247. package/templates/src/components/edit/storyfragment/StoryFragmentConfigPanel.tsx +289 -0
  248. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_menu.tsx +320 -0
  249. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_og.tsx +888 -0
  250. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_slug.tsx +269 -0
  251. package/templates/src/components/edit/storyfragment/StoryFragmentPanel_title.tsx +190 -0
  252. package/templates/src/components/edit/widgets/BeliefWidget.tsx +183 -0
  253. package/templates/src/components/edit/widgets/BunnyWidget.tsx +134 -0
  254. package/templates/src/components/edit/widgets/IdentifyAsWidget.tsx +193 -0
  255. package/templates/src/components/edit/widgets/SignupWidget.tsx +177 -0
  256. package/templates/src/components/edit/widgets/ToggleWidget.tsx +152 -0
  257. package/templates/src/components/edit/widgets/YouTubeWidget.tsx +65 -0
  258. package/templates/src/components/fields/ActionBuilderTimeSelector.tsx +353 -0
  259. package/templates/src/components/fields/ArtpackImage.tsx +480 -0
  260. package/templates/src/components/fields/BackgroundImage.tsx +530 -0
  261. package/templates/src/components/fields/BackgroundImageWrapper.tsx +192 -0
  262. package/templates/src/components/fields/BooleanParam.tsx +67 -0
  263. package/templates/src/components/fields/BunnyMomentSelector.tsx +56 -0
  264. package/templates/src/components/fields/ColorPickerCombo.tsx +284 -0
  265. package/templates/src/components/fields/ImageUpload.tsx +405 -0
  266. package/templates/src/components/fields/MultiParam.tsx +75 -0
  267. package/templates/src/components/fields/PaneBreakCollectionSelector.tsx +97 -0
  268. package/templates/src/components/fields/PaneBreakShapeSelector.tsx +134 -0
  269. package/templates/src/components/fields/SelectedTailwindClass.tsx +44 -0
  270. package/templates/src/components/fields/SingleParam.tsx +73 -0
  271. package/templates/src/components/fields/ViewportComboBox.tsx +252 -0
  272. package/templates/src/components/form/ActionBuilderField.tsx +282 -0
  273. package/templates/src/components/form/ActionBuilderSlugSelector.tsx +182 -0
  274. package/templates/src/components/form/BooleanToggle.tsx +94 -0
  275. package/templates/src/components/form/ColorPicker.tsx +153 -0
  276. package/templates/src/components/form/DateTimeInput.tsx +638 -0
  277. package/templates/src/components/form/EnumSelect.tsx +88 -0
  278. package/templates/src/components/form/FileUpload.tsx +465 -0
  279. package/templates/src/components/form/MagicPathBuilder.tsx +546 -0
  280. package/templates/src/components/form/NumberInput.tsx +101 -0
  281. package/templates/src/components/form/ParagraphArrayInput.tsx +207 -0
  282. package/templates/src/components/form/StringArrayInput.tsx +163 -0
  283. package/templates/src/components/form/StringInput.tsx +88 -0
  284. package/templates/src/components/form/UnsavedChangesBar.tsx +295 -0
  285. package/templates/src/components/form/advanced/APIConfigSection.tsx +69 -0
  286. package/templates/src/components/form/advanced/AuthConfigSection.tsx +97 -0
  287. package/templates/src/components/form/brand/BrandAssetsSection.tsx +93 -0
  288. package/templates/src/components/form/brand/BrandColorsSection.tsx +201 -0
  289. package/templates/src/components/form/brand/SEOSection.tsx +101 -0
  290. package/templates/src/components/form/brand/SiteConfigSection.tsx +61 -0
  291. package/templates/src/components/form/brand/SocialLinksSection.tsx +393 -0
  292. package/templates/src/components/profile/ProfileConsent.tsx +65 -0
  293. package/templates/src/components/profile/ProfileCreate.tsx +462 -0
  294. package/templates/src/components/profile/ProfileEdit.tsx +409 -0
  295. package/templates/src/components/profile/ProfileSwitch.tsx +255 -0
  296. package/templates/src/components/profile/ProfileUnlock.tsx +221 -0
  297. package/templates/src/components/storykeep/Dashboard.tsx +160 -0
  298. package/templates/src/components/storykeep/Dashboard_Activity.tsx +56 -0
  299. package/templates/src/components/storykeep/Dashboard_Advanced.tsx +165 -0
  300. package/templates/src/components/storykeep/Dashboard_Analytics.tsx +451 -0
  301. package/templates/src/components/storykeep/Dashboard_Branding.tsx +95 -0
  302. package/templates/src/components/storykeep/Dashboard_Content.tsx +191 -0
  303. package/templates/src/components/storykeep/controls/UsageCell.tsx +71 -0
  304. package/templates/src/components/storykeep/controls/content/BeliefForm.tsx +378 -0
  305. package/templates/src/components/storykeep/controls/content/BeliefTable.tsx +329 -0
  306. package/templates/src/components/storykeep/controls/content/ContentBrowser.tsx +385 -0
  307. package/templates/src/components/storykeep/controls/content/ContentSummary.tsx +149 -0
  308. package/templates/src/components/storykeep/controls/content/KnownResourceForm.tsx +397 -0
  309. package/templates/src/components/storykeep/controls/content/KnownResourceTable.tsx +260 -0
  310. package/templates/src/components/storykeep/controls/content/ManageContent.tsx +439 -0
  311. package/templates/src/components/storykeep/controls/content/MenuForm.tsx +239 -0
  312. package/templates/src/components/storykeep/controls/content/MenuTable.tsx +332 -0
  313. package/templates/src/components/storykeep/controls/content/ResourceBulkIngest.tsx +724 -0
  314. package/templates/src/components/storykeep/controls/content/ResourceForm.tsx +355 -0
  315. package/templates/src/components/storykeep/controls/content/ResourceTable.tsx +222 -0
  316. package/templates/src/components/storykeep/controls/content/StoryFragmentTable.tsx +482 -0
  317. package/templates/src/components/storykeep/state/BrandingWrapper.tsx +42 -0
  318. package/templates/src/components/storykeep/state/FetchAnalytics.tsx +350 -0
  319. package/templates/src/components/storykeep/widgets/ResponsiveLine.tsx +319 -0
  320. package/templates/src/components/storykeep/widgets/Wizard.tsx +278 -0
  321. package/templates/src/components/tenant/RegistrationForm.tsx +447 -0
  322. package/templates/src/components/widgets/BunnyVideoHero.astro +775 -0
  323. package/templates/src/components/widgets/Impression.tsx +102 -0
  324. package/templates/src/components/widgets/ImpressionWrapper.tsx +214 -0
  325. package/templates/src/constants/beliefs.ts +61 -0
  326. package/templates/src/constants/brandThemes.ts +133 -0
  327. package/templates/src/constants/prompts.json +55 -0
  328. package/templates/src/constants/shapes.ts +556 -0
  329. package/templates/src/constants/stopWords.ts +116 -0
  330. package/templates/src/constants/tailwindColors.json +344 -0
  331. package/templates/src/constants.ts +274 -0
  332. package/templates/src/hooks/useFormState.ts +203 -0
  333. package/templates/src/layouts/Layout.astro +290 -0
  334. package/templates/src/lib/session.ts +126 -0
  335. package/templates/src/lib/storyData.ts +56 -0
  336. package/templates/src/middleware.ts +52 -0
  337. package/templates/src/pages/404.astro +54 -0
  338. package/templates/src/pages/[...slug]/edit.astro +216 -0
  339. package/templates/src/pages/[...slug].astro +148 -0
  340. package/templates/src/pages/api/auth/decode.ts +101 -0
  341. package/templates/src/pages/api/auth/login.ts +122 -0
  342. package/templates/src/pages/api/auth/logout.ts +37 -0
  343. package/templates/src/pages/api/auth/profile.ts +76 -0
  344. package/templates/src/pages/api/orphan-analysis.ts +106 -0
  345. package/templates/src/pages/api/tailwind.ts +116 -0
  346. package/templates/src/pages/collections/[param1].astro +65 -0
  347. package/templates/src/pages/context/[...contextSlug]/edit.astro +207 -0
  348. package/templates/src/pages/context/[...contextSlug].astro +161 -0
  349. package/templates/src/pages/llms.txt.ts +122 -0
  350. package/templates/src/pages/maint.astro +183 -0
  351. package/templates/src/pages/media/[...slug].astro +67 -0
  352. package/templates/src/pages/robots.txt.ts +36 -0
  353. package/templates/src/pages/sandbox/activate.astro +258 -0
  354. package/templates/src/pages/sandbox/register.astro +44 -0
  355. package/templates/src/pages/sandbox/success.astro +179 -0
  356. package/templates/src/pages/sitemap.xml.ts +119 -0
  357. package/templates/src/pages/storykeep/advanced.astro +69 -0
  358. package/templates/src/pages/storykeep/branding.astro +57 -0
  359. package/templates/src/pages/storykeep/content.astro +71 -0
  360. package/templates/src/pages/storykeep/init.astro +36 -0
  361. package/templates/src/pages/storykeep/login.astro +266 -0
  362. package/templates/src/pages/storykeep/logout.astro +84 -0
  363. package/templates/src/pages/storykeep/profile.astro +98 -0
  364. package/templates/src/pages/storykeep.astro +81 -0
  365. package/templates/src/stores/analytics.ts +171 -0
  366. package/templates/src/stores/backend.ts +16 -0
  367. package/templates/src/stores/navigation.ts +149 -0
  368. package/templates/src/stores/nodes.ts +2390 -0
  369. package/templates/src/stores/nodesHistory.ts +85 -0
  370. package/templates/src/stores/notificationSystem.ts +41 -0
  371. package/templates/src/stores/orphanAnalysis.ts +409 -0
  372. package/templates/src/stores/storykeep.ts +247 -0
  373. package/templates/src/types/astro.ts +86 -0
  374. package/templates/src/types/compositorTypes.ts +456 -0
  375. package/templates/src/types/formTypes.ts +281 -0
  376. package/templates/src/types/multiTenant.ts +77 -0
  377. package/templates/src/types/nodeProps.ts +66 -0
  378. package/templates/src/types/tractstack.ts +445 -0
  379. package/templates/src/utils/aai/getTitleSlug.ts +72 -0
  380. package/templates/src/utils/actions/actionButton.ts +101 -0
  381. package/templates/src/utils/actions/lispLexer.ts +57 -0
  382. package/templates/src/utils/actions/preParse_Action.ts +85 -0
  383. package/templates/src/utils/actions/preParse_Bunny.ts +50 -0
  384. package/templates/src/utils/actions/preParse_Clicked.ts +87 -0
  385. package/templates/src/utils/actions/preParse_Impression.ts +71 -0
  386. package/templates/src/utils/api/advancedConfig.ts +66 -0
  387. package/templates/src/utils/api/advancedHelpers.ts +134 -0
  388. package/templates/src/utils/api/beliefConfig.ts +87 -0
  389. package/templates/src/utils/api/beliefHelpers.ts +196 -0
  390. package/templates/src/utils/api/brandConfig.ts +126 -0
  391. package/templates/src/utils/api/brandHelpers.ts +155 -0
  392. package/templates/src/utils/api/fileHelpers.ts +306 -0
  393. package/templates/src/utils/api/menuConfig.ts +57 -0
  394. package/templates/src/utils/api/menuHelpers.ts +156 -0
  395. package/templates/src/utils/api/resourceConfig.ts +158 -0
  396. package/templates/src/utils/api/resourceHelpers.ts +72 -0
  397. package/templates/src/utils/api/tenantConfig.ts +97 -0
  398. package/templates/src/utils/api/tenantHelpers.ts +172 -0
  399. package/templates/src/utils/api.ts +183 -0
  400. package/templates/src/utils/auth.ts +150 -0
  401. package/templates/src/utils/backend.ts +243 -0
  402. package/templates/src/utils/compositor/TemplateMarkdowns.ts +118 -0
  403. package/templates/src/utils/compositor/TemplateNodes.ts +138 -0
  404. package/templates/src/utils/compositor/TemplatePanes.ts +100 -0
  405. package/templates/src/utils/compositor/allowInsert.ts +100 -0
  406. package/templates/src/utils/compositor/domHelpers.ts +37 -0
  407. package/templates/src/utils/compositor/handleClickEvent.ts +131 -0
  408. package/templates/src/utils/compositor/nodesHelper.ts +491 -0
  409. package/templates/src/utils/compositor/nodesMarkdownGenerator.ts +292 -0
  410. package/templates/src/utils/compositor/processMarkdown.ts +431 -0
  411. package/templates/src/utils/compositor/reduceNodesClassNames.ts +192 -0
  412. package/templates/src/utils/compositor/tailwindClasses.ts +1795 -0
  413. package/templates/src/utils/compositor/tailwindColors.ts +227 -0
  414. package/templates/src/utils/compositor/templateMarkdownStyles.ts +1265 -0
  415. package/templates/src/utils/compositor/typeGuards.ts +193 -0
  416. package/templates/src/utils/etl/extractor.ts +119 -0
  417. package/templates/src/utils/etl/index.ts +88 -0
  418. package/templates/src/utils/etl/loader.ts +36 -0
  419. package/templates/src/utils/etl/transformer.ts +286 -0
  420. package/templates/src/utils/helpers.ts +435 -0
  421. package/templates/src/utils/layout.ts +209 -0
  422. package/templates/src/utils/profileStorage.ts +306 -0
  423. package/templates/src/utils/useInterval.ts +27 -0
  424. package/templates/tailwind.config.cjs +169 -0
  425. package/utils/create-resolver.ts +10 -0
  426. package/utils/inject-files.ts +2140 -0
  427. package/utils/validate-config.ts +43 -0
@@ -0,0 +1,101 @@
1
+ import { preParseClicked } from './preParse_Clicked';
2
+ import type { BrandConfig } from '@/types/tractstack';
3
+
4
+ interface ActionButtonParams {
5
+ callbackPayload: any;
6
+ targetUrl: string;
7
+ paneId: string;
8
+ config: BrandConfig;
9
+ }
10
+
11
+ // Import the sendAnalyticsEvent function to send events to backend
12
+ async function sendAnalyticsEvent(event: {
13
+ contentId: string;
14
+ contentType: 'Pane' | 'StoryFragment';
15
+ eventVerb: string;
16
+ duration?: number;
17
+ }): Promise<void> {
18
+ try {
19
+ const config = window.TRACTSTACK_CONFIG;
20
+ if (!config || !config.sessionId) return;
21
+
22
+ const sessionId = config.sessionId;
23
+ const formData: { [key: string]: string } = {
24
+ beliefId: event.contentId,
25
+ beliefType: event.contentType,
26
+ beliefValue: event.eventVerb,
27
+ paneId: '',
28
+ };
29
+
30
+ if (event.duration !== undefined) {
31
+ formData.duration = event.duration.toString();
32
+ }
33
+
34
+ await fetch(`${config.backendUrl}/api/v1/state`, {
35
+ method: 'POST',
36
+ headers: {
37
+ 'Content-Type': 'application/x-www-form-urlencoded',
38
+ 'X-Tenant-ID': config.tenantId,
39
+ 'X-TractStack-Session-ID': sessionId,
40
+ 'X-StoryFragment-ID': config.storyfragmentId,
41
+ },
42
+ body: new URLSearchParams(formData),
43
+ });
44
+ } catch (error) {
45
+ console.error('⛔ API ERROR: Analytics event failed', error, event);
46
+ }
47
+ }
48
+
49
+ export function handleActionButtonClick({
50
+ callbackPayload,
51
+ targetUrl,
52
+ paneId,
53
+ config,
54
+ }: ActionButtonParams): void {
55
+ const event = preParseClicked(paneId, callbackPayload, config);
56
+
57
+ if (event) {
58
+ console.log(event);
59
+ sendAnalyticsEvent({
60
+ contentId: event.targetId || event.targetSlug || event.id,
61
+ contentType: 'Pane',
62
+ eventVerb: event.verb,
63
+ });
64
+ }
65
+
66
+ // Handle URL navigation and scroll
67
+ if (targetUrl.startsWith('#') || targetUrl.includes('#')) {
68
+ const id = targetUrl.split('#')[1];
69
+ const element = document.getElementById(id);
70
+
71
+ if (element) {
72
+ // Calculate the target position
73
+ const elementRect = element.getBoundingClientRect();
74
+ const targetPosition = elementRect.top + window.scrollY;
75
+
76
+ // Perform smooth scroll
77
+ window.scrollTo({
78
+ top: targetPosition,
79
+ behavior: 'smooth',
80
+ });
81
+
82
+ // After scrolling, ensure the page layout is preserved
83
+ const checkScrollEnd = setInterval(() => {
84
+ if (
85
+ window.scrollY === targetPosition ||
86
+ Math.abs(window.scrollY - targetPosition) < 2
87
+ ) {
88
+ clearInterval(checkScrollEnd);
89
+ document.body.style.minHeight = `${Math.max(
90
+ document.body.scrollHeight,
91
+ document.documentElement.scrollHeight
92
+ )}px`;
93
+ }
94
+ }, 100);
95
+ } else {
96
+ window.location.href = targetUrl;
97
+ }
98
+ } else {
99
+ window.location.href = targetUrl;
100
+ }
101
+ }
@@ -0,0 +1,57 @@
1
+ const DOUBLEQUOTE = [`"`];
2
+ const BRACKETLEFT = `(`;
3
+ const BRACKETRIGHT = `)`;
4
+ const SEMICOLON = `;`;
5
+ const NEWLINE = `\n`;
6
+ const WHITESPACE = [` `, `\n`, `\t`];
7
+
8
+ type LispToken = string | number | LispToken[];
9
+
10
+ export function lispLexer(
11
+ payload: string = ``,
12
+ inString: boolean = false
13
+ /* eslint-disable @typescript-eslint/no-explicit-any */
14
+ ): [LispToken[], string] {
15
+ const tokens: LispToken[] = [];
16
+ let curToken = ``;
17
+
18
+ for (let i = 0; i < payload.length; i++) {
19
+ const char = payload.charAt(i);
20
+ if (DOUBLEQUOTE.includes(char) && inString === false) {
21
+ const [tokenized, remaining] = lispLexer(payload.substring(i + 1), true);
22
+ tokens.push(tokenized);
23
+ payload = remaining;
24
+ i = -1;
25
+ } else if (DOUBLEQUOTE.includes(char)) {
26
+ if (curToken.length) {
27
+ tokens.push(+curToken || curToken);
28
+ }
29
+ return [tokens, payload.substring(i + 1)];
30
+ } else if (char === BRACKETLEFT) {
31
+ // if (inString && payload?.charAt(i - 1) === ESCAPED) throw "PARSING ERROR"
32
+ const [tokenized, remaining] = lispLexer(payload.substring(i + 1));
33
+ tokens.push(tokenized);
34
+ payload = remaining;
35
+ i = -1;
36
+ } else if (char === BRACKETRIGHT) {
37
+ // if (inString && payload?.charAt(i - 1) === ESCAPED) throw "PARSING ERROR"
38
+ if (curToken.length) {
39
+ tokens.push(+curToken || curToken);
40
+ }
41
+ return [tokens, payload.substring(i + 1)];
42
+ } else if (char === SEMICOLON) {
43
+ // skip comments
44
+ while (payload.charAt(i) !== NEWLINE) {
45
+ i++;
46
+ }
47
+ } else if (WHITESPACE.includes(char) && inString !== true) {
48
+ if (curToken.length) {
49
+ tokens.push(+curToken || curToken);
50
+ }
51
+ curToken = ``;
52
+ } else {
53
+ curToken += char;
54
+ }
55
+ }
56
+ return [tokens, ``];
57
+ }
@@ -0,0 +1,85 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import type { BrandConfig } from '@/types/tractstack';
3
+
4
+ export const preParseAction = (
5
+ payload: any,
6
+ slug: string,
7
+ isContext: boolean,
8
+ config: BrandConfig
9
+ ) => {
10
+ const thisPayload = (payload && payload[0]) || false;
11
+ const command = (thisPayload && thisPayload[0] && thisPayload[0][0]) || null;
12
+ const parameters =
13
+ (thisPayload && thisPayload[0] && thisPayload[0][1]) || null;
14
+ const parameterOne = (parameters && parameters[0]) || null;
15
+ const parameterTwo = (parameters && parameters[1]) || null;
16
+ const parameterThree = (parameters && parameters[2]) || null;
17
+ //const parameterFour = (parameters && parameters[3]) || null;
18
+
19
+ switch (command) {
20
+ case `goto`:
21
+ switch (parameterOne) {
22
+ case `storykeep`:
23
+ if (parameterTwo) {
24
+ switch (parameterTwo) {
25
+ case `dashboard`:
26
+ return `/storykeep`;
27
+ case `settings`:
28
+ return `/storykeep/settings`;
29
+ case `login`:
30
+ return `/storykeep/login?force=true`;
31
+ case `logout`:
32
+ return `/storykeep/logout`;
33
+ default:
34
+ console.log(`LispActionPayload preParse misfire`, payload);
35
+ }
36
+ }
37
+ if (!isContext) return `/${slug}/edit`;
38
+ return `/context/${slug}/edit`;
39
+ case `home`:
40
+ return `/`;
41
+ case `concierge`:
42
+ return `/concierge/${parameterTwo}`;
43
+ case `context`:
44
+ return `/context/${parameterTwo}`;
45
+ //case `product`:
46
+ // return `/products/${parameterTwo}`;
47
+ case `storyFragment`:
48
+ if (parameterTwo !== config.HOME_SLUG) return `/${parameterTwo}`;
49
+ return `/`;
50
+ case `storyFragmentPane`:
51
+ if (parameterTwo && parameterThree) {
52
+ if (parameterTwo !== config.HOME_SLUG)
53
+ return `/${parameterTwo}#${parameterThree}`;
54
+ return `/#${parameterThree}`;
55
+ }
56
+ console.log(
57
+ `LispActionPayload preParse misfire on goto storyFragmentPane`,
58
+ parameterTwo,
59
+ parameterThree
60
+ );
61
+ break;
62
+ case `bunny`:
63
+ if (parameterTwo && parameterThree)
64
+ return `/${parameterTwo}?t=${parameterThree}s`;
65
+ return null;
66
+ case `url`:
67
+ return parameterTwo;
68
+ case `sandbox`:
69
+ if (parameterTwo) {
70
+ switch (parameterTwo) {
71
+ case `claim`:
72
+ return `/sandbox/claim`;
73
+ }
74
+ }
75
+ return ``;
76
+ default:
77
+ console.log(`LispActionPayload preParse misfire on goto`, payload);
78
+ }
79
+ break;
80
+ default:
81
+ console.log(`LispActionPayload preParse misfire`, payload);
82
+ break;
83
+ }
84
+ return ``;
85
+ };
@@ -0,0 +1,50 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ export const preParseBunny = (
3
+ payload: any
4
+ ): {
5
+ t: string;
6
+ videoId: string | null;
7
+ slug?: string;
8
+ isContext?: boolean;
9
+ } | null => {
10
+ const thisPayload = (payload && payload[0]) || false;
11
+
12
+ // Early exit if no valid payload
13
+ if (!thisPayload) return null;
14
+
15
+ const command = (thisPayload && thisPayload[0] && thisPayload[0][0]) || null;
16
+ const parameters =
17
+ (thisPayload && thisPayload[0] && thisPayload[0][1]) || null;
18
+
19
+ // Handle legacy format: (goto (bunny crusade-2024-june-24 1623 252933/65c99d97-8aec-4084-b47a-3dc4c5dd3e09))
20
+ if (command === `goto` && parameters) {
21
+ const parameterOne = parameters[0] || null;
22
+ const parameterTwo = parameters[1] || null;
23
+ const parameterThree = parameters[2] || null;
24
+ const parameterFour = parameters[3] || null; // video ID parameter
25
+
26
+ if ([`bunny`, `bunnyContext`].includes(parameterOne)) {
27
+ return {
28
+ slug: parameterTwo as string,
29
+ t: parameterThree as string,
30
+ videoId: parameterFour as string | null,
31
+ isContext: parameterOne === `bunnyContext`,
32
+ };
33
+ }
34
+ }
35
+
36
+ // Handle new format: (bunnyMoment (252933/65c99d97-8aec-4084-b47a-3dc4c5dd3e09 1623))
37
+ if (command === 'bunnyMoment' && parameters) {
38
+ if (Array.isArray(parameters)) {
39
+ const videoId = parameters[0];
40
+ const timestamp = parameters[1];
41
+
42
+ return {
43
+ videoId: videoId || null,
44
+ t: timestamp ? timestamp.toString() : '0',
45
+ };
46
+ }
47
+ }
48
+
49
+ return null;
50
+ };
@@ -0,0 +1,87 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import type { BrandConfig } from '@/types/tractstack';
3
+
4
+ export const preParseClicked = (
5
+ id: string,
6
+ payload: any,
7
+ config: BrandConfig
8
+ ) => {
9
+ const thisPayload = (payload && payload[0]) || false;
10
+
11
+ if (!thisPayload || !config?.HOME_SLUG) {
12
+ return null;
13
+ }
14
+
15
+ const command = (thisPayload && thisPayload[0] && thisPayload[0][0]) || null;
16
+ const parameters =
17
+ (thisPayload && thisPayload[0] && thisPayload[0][1]) || null;
18
+
19
+ if (command === 'bunnyMoment' && parameters) {
20
+ const videoId = parameters[0];
21
+ return {
22
+ id: id,
23
+ type: `StartVideoMoment`,
24
+ verb: `WATCHED`,
25
+ targetId: videoId || null,
26
+ };
27
+ }
28
+
29
+ if (command === `goto` && parameters) {
30
+ const parameterOne = parameters[0] || null;
31
+ const parameterTwo = parameters[1] || null;
32
+ //const parameterThree = parameters[2] || null;
33
+
34
+ switch (parameterOne) {
35
+ case `home`:
36
+ return {
37
+ id: id,
38
+ type: `PaneClicked`,
39
+ verb: `CLICKED`,
40
+ targetSlug: config?.HOME_SLUG,
41
+ };
42
+
43
+ case `storyFragment`:
44
+ case `storyFragmentPane`:
45
+ return {
46
+ id: id,
47
+ type: `PaneClicked`,
48
+ verb: `CLICKED`,
49
+ targetSlug: parameterTwo,
50
+ };
51
+
52
+ case `bunny`:
53
+ return {
54
+ id: id,
55
+ type: `StartVideo`,
56
+ verb: `WATCHED`,
57
+ targetSlug: parameterTwo,
58
+ };
59
+
60
+ case `sandbox`:
61
+ return {
62
+ id: id,
63
+ type: `SandboxAction`,
64
+ verb: `CLICKED`,
65
+ targetSlug: parameterTwo || 'main',
66
+ };
67
+
68
+ case `storykeep`:
69
+ case `context`:
70
+ case `concierge`:
71
+ case `product`:
72
+ case `url`:
73
+ // ignore these
74
+ break;
75
+
76
+ default:
77
+ console.log(
78
+ `LispActionPayload preParseEvent misfire`,
79
+ command,
80
+ parameters
81
+ );
82
+ break;
83
+ }
84
+ }
85
+
86
+ return null;
87
+ };
@@ -0,0 +1,71 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import type { BrandConfig } from '@/types/tractstack';
3
+
4
+ export const preParseImpression = (
5
+ id: string,
6
+ title: string,
7
+ parentId: string,
8
+ payload: any,
9
+ config: BrandConfig
10
+ ) => {
11
+ const thisPayload = (payload && payload[0]) || false;
12
+ const command = (thisPayload && thisPayload[0] && thisPayload[0][0]) || null;
13
+ const parameters =
14
+ (thisPayload && thisPayload[0] && thisPayload[0][1]) || null;
15
+ const parameterOne = (parameters && parameters[0]) || null;
16
+ const parameterTwo = (parameters && parameters[1]) || null;
17
+ //const parameterThree = (parameters && parameters[2]) || null;
18
+
19
+ if (!config.SITE_INIT) {
20
+ console.log(`Site misconfiguration: SITE_INIT not found`);
21
+ return null;
22
+ }
23
+
24
+ if (!config.HOME_SLUG) {
25
+ console.log(`Site misconfiguration: HOME_SLUG not found`);
26
+ return null;
27
+ }
28
+
29
+ switch (command) {
30
+ case `goto`: {
31
+ switch (parameterOne) {
32
+ case `home`:
33
+ return {
34
+ id: id,
35
+ parentId: parentId,
36
+ title,
37
+ type: `Impression`,
38
+ verb: `CLICKED`,
39
+ targetSlug: config.HOME_SLUG,
40
+ };
41
+
42
+ case `storyFragment`:
43
+ case `storyFragmentPane`:
44
+ return {
45
+ id: id,
46
+ parentId: parentId,
47
+ title,
48
+ type: `Impression`,
49
+ verb: `CLICKED`,
50
+ targetSlug: parameterTwo,
51
+ };
52
+
53
+ case `context`:
54
+ case `concierge`:
55
+ case `product`:
56
+ case `url`:
57
+ // ignore these
58
+ break;
59
+
60
+ default:
61
+ console.log(
62
+ `LispActionPayload preParseImpression misfire`,
63
+ command,
64
+ parameters
65
+ );
66
+ break;
67
+ }
68
+ }
69
+ }
70
+ return null;
71
+ };
@@ -0,0 +1,66 @@
1
+ import { TractStackAPI } from '../api';
2
+ import type {
3
+ AdvancedConfigStatus,
4
+ AdvancedConfigUpdateRequest,
5
+ } from '@/types/tractstack';
6
+
7
+ /**
8
+ * Get advanced configuration status (boolean flags only)
9
+ */
10
+ export async function getAdvancedConfigStatus(
11
+ tenantId: string
12
+ ): Promise<AdvancedConfigStatus> {
13
+ const api = new TractStackAPI(tenantId);
14
+ try {
15
+ const response = await api.get<AdvancedConfigStatus>(
16
+ '/api/v1/config/advanced'
17
+ );
18
+
19
+ if (!response.success || !response.data) {
20
+ throw new Error(response.error || 'No data received from server');
21
+ }
22
+
23
+ const data = response.data;
24
+
25
+ // Validate response structure
26
+ if (
27
+ typeof data.tursoConfigured !== 'boolean' ||
28
+ typeof data.tursoTokenSet !== 'boolean' ||
29
+ typeof data.adminPasswordSet !== 'boolean' ||
30
+ typeof data.editorPasswordSet !== 'boolean' ||
31
+ typeof data.aaiAPIKeySet !== 'boolean'
32
+ ) {
33
+ throw new Error('Invalid response format from server');
34
+ }
35
+
36
+ return data;
37
+ } catch (error) {
38
+ console.error('Failed to fetch advanced config status:', error);
39
+ throw new Error('Failed to load advanced configuration status');
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Save advanced configuration
45
+ */
46
+ export async function saveAdvancedConfig(
47
+ tenantId: string,
48
+ config: AdvancedConfigUpdateRequest
49
+ ): Promise<void> {
50
+ const api = new TractStackAPI(tenantId);
51
+ try {
52
+ const response = await api.put('/api/v1/config/advanced', config);
53
+
54
+ if (!response.success) {
55
+ throw new Error(response.error || 'Failed to save configuration');
56
+ }
57
+ } catch (error) {
58
+ console.error('Failed to save advanced config:', error);
59
+
60
+ if (error instanceof Error) {
61
+ throw error;
62
+ }
63
+
64
+ throw new Error('Failed to save advanced configuration');
65
+ }
66
+ }
@@ -0,0 +1,134 @@
1
+ import type {
2
+ AdvancedConfigStatus,
3
+ AdvancedConfigState,
4
+ AdvancedConfigUpdateRequest,
5
+ FieldErrors,
6
+ } from '@/types/tractstack';
7
+
8
+ /**
9
+ * Convert backend status response to local form state
10
+ * Since backend only returns boolean flags, we use empty strings for form values
11
+ */
12
+ export function convertToLocalState(
13
+ status: AdvancedConfigStatus | null
14
+ ): AdvancedConfigState {
15
+ if (!status) {
16
+ return {
17
+ tursoUrl: '',
18
+ tursoToken: '',
19
+ adminPassword: '',
20
+ editorPassword: '',
21
+ aaiApiKey: '',
22
+ };
23
+ }
24
+
25
+ // Convert boolean status to empty string form state
26
+ // The form will show as "configured" or "not configured" based on boolean flags
27
+ // but never expose actual values
28
+ return {
29
+ tursoUrl: '',
30
+ tursoToken: '',
31
+ adminPassword: '',
32
+ editorPassword: '',
33
+ aaiApiKey: '',
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Convert local form state to backend update request format
39
+ * Only include fields that have values (user has entered something)
40
+ */
41
+ export function convertToBackendFormat(
42
+ state: AdvancedConfigState
43
+ ): AdvancedConfigUpdateRequest {
44
+ const request: AdvancedConfigUpdateRequest = {};
45
+
46
+ // Only include fields that have been filled in
47
+ if (state.tursoUrl?.trim()) {
48
+ request.TURSO_DATABASE_URL = state.tursoUrl.trim();
49
+ }
50
+
51
+ if (state.tursoToken?.trim()) {
52
+ request.TURSO_AUTH_TOKEN = state.tursoToken.trim();
53
+ }
54
+
55
+ if (state.adminPassword?.trim()) {
56
+ request.ADMIN_PASSWORD = state.adminPassword.trim();
57
+ }
58
+
59
+ if (state.editorPassword?.trim()) {
60
+ request.EDITOR_PASSWORD = state.editorPassword.trim();
61
+ }
62
+
63
+ if (state.aaiApiKey?.trim()) {
64
+ request.AAI_API_KEY = state.aaiApiKey.trim();
65
+ }
66
+
67
+ return request;
68
+ }
69
+
70
+ /**
71
+ * Validate advanced configuration state
72
+ */
73
+ export function validateAdvancedConfig(
74
+ state: AdvancedConfigState
75
+ ): FieldErrors {
76
+ const errors: FieldErrors = {};
77
+
78
+ // Turso validation: both URL and token must be provided together
79
+ const hasTursoUrl = Boolean(state.tursoUrl?.trim());
80
+ const hasTursoToken = Boolean(state.tursoToken?.trim());
81
+
82
+ if (hasTursoUrl && !hasTursoToken) {
83
+ errors.tursoToken =
84
+ 'Turso Auth Token is required when Turso URL is provided';
85
+ }
86
+
87
+ if (hasTursoToken && !hasTursoUrl) {
88
+ errors.tursoUrl =
89
+ 'Turso Database URL is required when Turso Token is provided';
90
+ }
91
+
92
+ // Basic URL validation for Turso
93
+ if (hasTursoUrl && state.tursoUrl) {
94
+ const urlPattern = /^libsql:\/\/.+/;
95
+ if (!urlPattern.test(state.tursoUrl.trim())) {
96
+ errors.tursoUrl = 'Turso Database URL must start with "libsql://"';
97
+ }
98
+ }
99
+
100
+ // Password strength validation (optional but recommended)
101
+ if (state.adminPassword && state.adminPassword.length < 8) {
102
+ errors.adminPassword =
103
+ 'Admin password should be at least 8 characters long';
104
+ }
105
+
106
+ if (state.editorPassword && state.editorPassword.length < 8) {
107
+ errors.editorPassword =
108
+ 'Editor password should be at least 8 characters long';
109
+ }
110
+
111
+ return errors;
112
+ }
113
+
114
+ /**
115
+ * State interceptor for advanced config form
116
+ * This allows for custom logic when state changes
117
+ */
118
+ export function advancedStateIntercept(
119
+ newState: AdvancedConfigState,
120
+ field: keyof AdvancedConfigState,
121
+ value: any
122
+ ): AdvancedConfigState {
123
+ // Clear related field when one half of Turso config is cleared
124
+ if (field === 'tursoUrl' && !value.trim()) {
125
+ return { ...newState, tursoUrl: value, tursoToken: '' };
126
+ }
127
+
128
+ if (field === 'tursoToken' && !value.trim()) {
129
+ return { ...newState, tursoToken: value, tursoUrl: '' };
130
+ }
131
+
132
+ // Default behavior - just update the field
133
+ return newState;
134
+ }