@salsita-ai/sdk 0.50.0-develop.8c8c362f86 → 0.50.0-develop.8e3768cb11

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 (293) hide show
  1. package/dist/application-spec/core/components/component-filter.d.ts +53 -0
  2. package/dist/application-spec/core/components/component-filter.js +1 -0
  3. package/dist/application-spec/core/components/index.d.ts +2 -0
  4. package/dist/application-spec/core/components/index.js +1 -0
  5. package/dist/application-spec/core/components/sdk-code-ref.d.ts +9 -0
  6. package/dist/application-spec/core/components/sdk-code-ref.js +1 -0
  7. package/dist/application-spec/core/enhanced-json-value.d.ts +0 -68
  8. package/dist/application-spec/core/enhanced-json-value.js +1 -1
  9. package/dist/application-spec/core/expressions/index.d.ts +2 -0
  10. package/dist/application-spec/core/expressions/index.js +1 -0
  11. package/dist/application-spec/core/expressions/relation-expression-params.d.ts +11 -0
  12. package/dist/application-spec/core/expressions/relation-expression-params.js +1 -0
  13. package/dist/application-spec/core/expressions/sdk-expression-implementation.d.ts +24 -0
  14. package/dist/application-spec/core/expressions/sdk-expression-implementation.js +1 -0
  15. package/dist/application-spec/core/index.d.ts +2 -0
  16. package/dist/application-spec/core/index.js +1 -1
  17. package/dist/application-spec/core/json-value.d.ts +1 -1
  18. package/dist/application-spec/{core → enhanced-json}/eval-to-constant.d.ts +1 -1
  19. package/dist/application-spec/enhanced-json/index.d.ts +4 -0
  20. package/dist/application-spec/enhanced-json/index.js +1 -0
  21. package/dist/application-spec/enhanced-json/is-enhanced-json-array.d.ts +2 -0
  22. package/dist/application-spec/enhanced-json/is-enhanced-json-array.js +1 -0
  23. package/dist/application-spec/enhanced-json/resolve-enhanced-json-value.d.ts +18 -0
  24. package/dist/application-spec/enhanced-json/resolve-enhanced-json-value.js +1 -0
  25. package/dist/application-spec/enhanced-json/schema-from-value.d.ts +24 -0
  26. package/dist/application-spec/enhanced-json/schema-from-value.js +1 -0
  27. package/dist/application-spec/enhanced-json/stringify-enhanced-json-value.d.ts +14 -0
  28. package/dist/application-spec/enhanced-json/stringify-enhanced-json-value.js +1 -0
  29. package/dist/application-spec/enhanced-json/validate-enhanced-json-value-caps.d.ts +12 -0
  30. package/dist/application-spec/enhanced-json/validate-enhanced-json-value-caps.js +1 -0
  31. package/dist/application-spec/enhanced-json/validate-no-legacy-code-ref.d.ts +13 -0
  32. package/dist/application-spec/enhanced-json/validate-no-legacy-code-ref.js +1 -0
  33. package/dist/application-spec/generate-application/code/generate-application-code.d.ts +3 -2
  34. package/dist/application-spec/generate-application/code/generate-application-code.js +1 -1
  35. package/dist/application-spec/generate-application/code/project-scaffolding.d.ts +9 -4
  36. package/dist/application-spec/generate-application/code/project-scaffolding.js +2 -2
  37. package/dist/application-spec/generate-application/code/standalone-app-files.d.ts +2 -2
  38. package/dist/application-spec/generate-application/code/standalone-app-files.js +1 -1
  39. package/dist/application-spec/generate-application/code/templates/configurator-config.js +6 -4
  40. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-component-optics.js +4 -4
  41. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-defaults.js +1 -1
  42. package/dist/application-spec/generate-application/code/templates/gitignore.js +1 -2
  43. package/dist/application-spec/generate-application/code/templates/index.d.ts +1 -1
  44. package/dist/application-spec/generate-application/code/templates/index.js +1 -1
  45. package/dist/application-spec/generate-application/code/templates/package-json.js +1 -1
  46. package/dist/application-spec/generate-application/code/templates/root-tsconfig.d.ts +6 -0
  47. package/dist/application-spec/generate-application/code/templates/root-tsconfig.js +2 -0
  48. package/dist/application-spec/generate-application/code/templates/skills/phoenix-review-skill.js +1 -1
  49. package/dist/application-spec/generate-application/code/templates/skills/phoenix-skill.js +1 -1
  50. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.d.ts +10 -4
  51. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.js +2 -2
  52. package/dist/application-spec/generate-application/code/templates/tsconfig.d.ts +5 -0
  53. package/dist/application-spec/generate-application/code/templates/tsconfig.js +1 -1
  54. package/dist/application-spec/generate-application/code/templates/webhook-index.d.ts +6 -1
  55. package/dist/application-spec/generate-application/code/templates/webhook-index.js +10 -1
  56. package/dist/application-spec/generate-application/index.d.ts +2 -0
  57. package/dist/application-spec/generate-application/index.js +1 -1
  58. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-runtime.d.ts +6 -2
  59. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-runtime.js +1 -1
  60. package/dist/application-spec/generate-application/runtime/application-runtime.d.ts +8 -1
  61. package/dist/application-spec/generate-application/runtime/application-runtime.js +1 -1
  62. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-runtime.d.ts +5 -1
  63. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-runtime.js +1 -1
  64. package/dist/application-spec/generate-application/runtime/factory-data/factory-data-runtime.d.ts +43 -0
  65. package/dist/application-spec/generate-application/runtime/factory-data/factory-data-runtime.js +1 -0
  66. package/dist/application-spec/generate-application/runtime/factory-data/index.d.ts +3 -0
  67. package/dist/application-spec/generate-application/runtime/factory-data/index.js +1 -0
  68. package/dist/application-spec/generate-application/runtime/factory-data/recipe-defaults.d.ts +13 -0
  69. package/dist/application-spec/generate-application/runtime/factory-data/recipe-defaults.js +1 -0
  70. package/dist/application-spec/generate-application/runtime/factory-data/static-violations.d.ts +16 -0
  71. package/dist/application-spec/generate-application/runtime/factory-data/static-violations.js +1 -0
  72. package/dist/application-spec/generate-application/runtime/migrations/index.d.ts +1 -0
  73. package/dist/application-spec/generate-application/runtime/migrations/index.js +1 -0
  74. package/dist/application-spec/generate-application/runtime/migrations/migration-runtime.d.ts +53 -0
  75. package/dist/application-spec/generate-application/runtime/migrations/migration-runtime.js +1 -0
  76. package/dist/application-spec/generate-application/runtime/sections/build-sdk-optic.d.ts +1 -1
  77. package/dist/application-spec/generate-application/runtime/sections/build-sdk-optic.js +1 -1
  78. package/dist/application-spec/generate-application/runtime/sections/expression-runtime.js +1 -1
  79. package/dist/application-spec/index.d.ts +1 -0
  80. package/dist/application-spec/index.js +1 -1
  81. package/dist/application-spec/parse-application-files/categorize/categorize-files.d.ts +16 -0
  82. package/dist/application-spec/parse-application-files/categorize/categorize-files.js +1 -1
  83. package/dist/application-spec/parse-application-files/categorize/earlier-generated-tsconfig.d.ts +9 -0
  84. package/dist/application-spec/parse-application-files/categorize/earlier-generated-tsconfig.js +1 -0
  85. package/dist/application-spec/parse-application-files/raw-spec/raw-spec-file.js +1 -1
  86. package/dist/application-spec/parse-application-files/spec/components/component-entry.d.ts +1 -9
  87. package/dist/application-spec/parse-application-files/spec/components/component-entry.js +1 -1
  88. package/dist/application-spec/parse-application-files/spec/components/component-filter.d.ts +1 -54
  89. package/dist/application-spec/parse-application-files/spec/components/component-filter.js +1 -1
  90. package/dist/application-spec/parse-application-files/spec/components/index.d.ts +1 -1
  91. package/dist/application-spec/parse-application-files/spec/components/index.js +1 -1
  92. package/dist/application-spec/parse-application-files/spec/expressions/expression.d.ts +1 -28
  93. package/dist/application-spec/parse-application-files/spec/expressions/expression.js +1 -1
  94. package/dist/application-spec/parse-application-files/spec/expressions/expressions.d.ts +1 -1
  95. package/dist/application-spec/parse-application-files/spec/expressions/expressions.js +1 -1
  96. package/dist/application-spec/parse-application-files/spec/expressions/index.d.ts +0 -1
  97. package/dist/application-spec/parse-application-files/spec/expressions/index.js +1 -1
  98. package/dist/application-spec/parse-application-files/spec/expressions/memo-eval-plan.js +1 -1
  99. package/dist/application-spec/parse-application-files/spec/expressions/user-expressions.js +1 -1
  100. package/dist/application-spec/parse-application-files/spec/model/defaults.js +1 -1
  101. package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.d.ts +29 -0
  102. package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.js +1 -1
  103. package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.d.ts +7 -1
  104. package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.js +1 -1
  105. package/dist/configurator/application-runtime/extensions/systems/drag-and-drop-system/drag-and-drop-system.d.ts +3 -3
  106. package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.d.ts +6 -0
  107. package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.js +1 -1
  108. package/dist/configurator/application-runtime/extensions/systems/layout-system/layout-system.d.ts +2 -2
  109. package/dist/configurator/common/configurator-interface.d.ts +22 -1
  110. package/dist/configurator/common/configurator-interface.js +1 -1
  111. package/dist/configurator/common/frontend-analytics.d.ts +2 -0
  112. package/dist/configurator/common/frontend-analytics.js +1 -1
  113. package/dist/configurator/common/index.d.ts +2 -0
  114. package/dist/configurator/common/index.js +1 -1
  115. package/dist/configurator/common/use-finalize-action.d.ts +31 -0
  116. package/dist/configurator/common/use-finalize-action.js +1 -0
  117. package/dist/configurator/common/use-reset-camera.d.ts +6 -0
  118. package/dist/configurator/common/use-reset-camera.js +1 -0
  119. package/dist/configurator/configurator-context/configurator-hooks/layout-hooks.d.ts +1 -1
  120. package/dist/configurator/pages/DefaultConfiguratorLayout.d.ts +2 -2
  121. package/dist/configurator/pages/LoadedConfiguratorDetailPage.js +1 -1
  122. package/dist/configurator/pages/configurator-layout-name.d.ts +2 -0
  123. package/dist/configurator/pages/configurator-layout-name.js +1 -0
  124. package/dist/configurator/pages/default-configurator-elements.d.ts +7 -0
  125. package/dist/configurator/pages/default-configurator-elements.js +1 -0
  126. package/dist/configurator/pages/index.d.ts +1 -0
  127. package/dist/configurator/pages/index.js +1 -1
  128. package/dist/configurator/scene/scene-controls/hotspot-drag-handle/HotspotDragHandle.d.ts +1 -1
  129. package/dist/configurator/scene/scene-controls/hotspot-drag-handle/HotspotDragSceneHandle.d.ts +1 -1
  130. package/dist/configurator/scene/scene-entity/dimension-indicators/DimensionIndicator.d.ts +1 -1
  131. package/dist/configurator/scene/scene-entity/dimension-indicators/DimensionIndicatorInternal.d.ts +1 -1
  132. package/dist/configurator/scene/scene-entity/drag-and-drop/shared.d.ts +2 -2
  133. package/dist/configurator/scene/scene-entity/drag-and-drop/use-drag-object.d.ts +1 -1
  134. package/dist/configurator/scene/scene-entity/materials/RemoteReplacedMaterial.js +1 -1
  135. package/dist/configurator/scene/scene-entity/objects/SceneEntityObjectTextDecal.d.ts +1 -1
  136. package/dist/configurator/ui/assistant/AssistantChips.d.ts +8 -2
  137. package/dist/configurator/ui/assistant/AssistantChips.js +1 -1
  138. package/dist/configurator/ui/assistant/AssistantMarkdown.d.ts +1 -1
  139. package/dist/configurator/ui/assistant/AssistantMarkdown.js +1 -1
  140. package/dist/configurator/ui/assistant/AssistantThread.js +1 -1
  141. package/dist/configurator/ui/assistant/entity-link/AssistantEntityLink.d.ts +13 -0
  142. package/dist/configurator/ui/assistant/entity-link/AssistantEntityLink.js +1 -0
  143. package/dist/configurator/ui/assistant/entity-link/entity-link-selection.d.ts +22 -0
  144. package/dist/configurator/ui/assistant/entity-link/entity-link-selection.js +1 -0
  145. package/dist/configurator/ui/assistant/entity-link/entity-link-state.d.ts +27 -0
  146. package/dist/configurator/ui/assistant/entity-link/entity-link-state.js +1 -0
  147. package/dist/configurator/ui/assistant/entity-link/entity-link-target.d.ts +5 -0
  148. package/dist/configurator/ui/assistant/entity-link/entity-link-target.js +1 -0
  149. package/dist/configurator/ui/assistant/entity-link/index.d.ts +3 -0
  150. package/dist/configurator/ui/assistant/entity-link/index.js +1 -0
  151. package/dist/configurator/ui/configurator-layout/slots/services/InvariantViolations.d.ts +4 -4
  152. package/dist/configurator/ui/configurator-layout/slots/services/InvariantViolations.js +1 -1
  153. package/dist/configurator/ui/configurator-layout/slots/services/SideEffects.d.ts +3 -6
  154. package/dist/configurator/ui/configurator-layout/slots/services/SideEffects.js +1 -1
  155. package/dist/configurator/ui/legacy/layout/steps/StepsNavigation.d.ts +2 -2
  156. package/dist/configurator/ui/phoenix-layout-elements/header/common/step-navigation/StepsNavigation.d.ts +2 -2
  157. package/dist/docs/dimensions/3d-scene-integration/dimension-indicators.mdx +2 -2
  158. package/dist/docs/dimensions/3d-scene-integration/editable-angle-indicator.mdx +1 -1
  159. package/dist/docs/dimensions/3d-scene-integration/editable-distance-dimension-indicator.mdx +1 -1
  160. package/dist/docs/dimensions/3d-scene-integration/list-selector-dimension-indicator.mdx +1 -1
  161. package/dist/docs/drag-and-drop/drag-handle.mdx +1 -1
  162. package/dist/docs/drag-and-drop/hotspot-handle.mdx +1 -1
  163. package/dist/docs/drag-and-drop/planes.mdx +1 -1
  164. package/dist/docs/drag-and-drop/rotatable.mdx +2 -2
  165. package/dist/docs/index.json +11 -1
  166. package/dist/docs/layouts/custom-layout.mdx +1323 -179
  167. package/dist/docs/layouts/header/fixed.mdx +2 -2
  168. package/dist/docs/layouts/header/floating.mdx +2 -2
  169. package/dist/docs/layouts/sidebar/in-a-custom-layout.mdx +2 -2
  170. package/dist/docs/layouts/sidebar-footer/basic.mdx +32 -77
  171. package/dist/docs/other-features/client-side-rendering/declarative.mdx +1 -1
  172. package/dist/docs/phoenix/application-states.mdx +9 -7
  173. package/dist/docs/phoenix/configurator-interface.mdx +134 -18
  174. package/dist/docs/phoenix/finalization.mdx +1 -1
  175. package/dist/docs/phoenix/layout-slots.mdx +116 -0
  176. package/dist/docs/phoenix/migration-guide.mdx +19 -8
  177. package/dist/docs/phoenix/phoenix-cli.mdx +26 -8
  178. package/dist/docs/phoenix/project-structure.mdx +20 -5
  179. package/dist/docs/phoenix/sdk-builder-workflow.mdx +2 -2
  180. package/dist/docs/phoenix/webhooks.mdx +17 -0
  181. package/dist/domain/application/application-config.d.ts +3 -1
  182. package/dist/domain/application/assistant/generate-assistant-prompt.js +1 -1
  183. package/dist/domain/application/configurator-builder.d.ts +4 -1
  184. package/dist/domain/application/configurator-builder.js +1 -1
  185. package/dist/domain/core/invariant/violation.d.ts +50 -2
  186. package/dist/domain/core/invariant/violation.js +1 -1
  187. package/dist/domain/core/model/model.d.ts +1 -1
  188. package/dist/domain/domain-context/index.d.ts +1 -1
  189. package/dist/domain/domain-context/undo-system.d.ts +28 -1
  190. package/dist/domain/domain-context/undo-system.js +1 -1
  191. package/dist/domain/domain-runtime/spec/initialize.js +1 -1
  192. package/dist/domain/domain-runtime/spec/selectors.js +1 -1
  193. package/dist/domain/domain-runtime/spec/types.d.ts +2 -0
  194. package/dist/domain/extensions/attribute-switch.d.ts +1 -1
  195. package/dist/domain/extensions/attribute-switch.js +1 -1
  196. package/dist/domain/extensions/canvas-config.d.ts +1 -1
  197. package/dist/domain/extensions/client-side-image.d.ts +2 -2
  198. package/dist/domain/extensions/client-side-image.js +1 -1
  199. package/dist/domain/extensions/common/angle-indicator-schema.d.ts +2 -2
  200. package/dist/domain/extensions/common/dimension-indicator-schema.d.ts +2 -2
  201. package/dist/domain/extensions/editable-angle-indicator.d.ts +1 -1
  202. package/dist/domain/extensions/editable-distance-dimension-indicator.d.ts +1 -1
  203. package/dist/domain/extensions/editable-offset-indicator.d.ts +1 -1
  204. package/dist/domain/extensions/editable-offset-indicator.js +1 -1
  205. package/dist/domain/extensions/fit-selection-orthographic-camera-component.js +1 -1
  206. package/dist/domain/extensions/fit-selection-perspective-camera-component.js +1 -1
  207. package/dist/domain/extensions/horizontal-tabs.d.ts +2 -2
  208. package/dist/domain/extensions/list-selector-dimension-indicator.d.ts +1 -1
  209. package/dist/domain/extensions/navigation-steps.d.ts +2 -2
  210. package/dist/domain/extensions/offset-indicator.js +1 -1
  211. package/dist/domain/extensions/rotation-handle.d.ts +2 -2
  212. package/dist/domain/extensions/save-template-thumbnail.d.ts +2 -2
  213. package/dist/domain/extensions/save-template-thumbnail.js +1 -1
  214. package/dist/domain/extensions/scene-entity-animation.js +1 -1
  215. package/dist/domain/system-components/application-config.d.ts +2 -2
  216. package/dist/domain/system-components/child-entity-selection.js +1 -1
  217. package/dist/domain/system-components/collision-box-geometry.d.ts +4 -2
  218. package/dist/domain/system-components/collision-geometry.d.ts +4 -2
  219. package/dist/domain/system-components/collision-point-geometry.d.ts +4 -2
  220. package/dist/domain/system-components/common/material-override-schema.d.ts +2 -2
  221. package/dist/domain/system-components/common/recipes.d.ts +21 -3
  222. package/dist/domain/system-components/common/recipes.js +1 -1
  223. package/dist/domain/system-components/constraint.d.ts +10 -23
  224. package/dist/domain/system-components/drag-handle.d.ts +1 -1
  225. package/dist/domain/system-components/drag-handle.js +1 -1
  226. package/dist/domain/system-components/fit-entity-orthographic-camera-component.js +1 -1
  227. package/dist/domain/system-components/fit-entity-perspective-camera-component.js +1 -1
  228. package/dist/domain/system-components/fit-root-orthographic-camera-component.js +1 -1
  229. package/dist/domain/system-components/fit-root-perspective-camera-component.js +1 -1
  230. package/dist/domain/system-components/hotspot-drag-handle.d.ts +1 -1
  231. package/dist/domain/system-components/hotspot-drag-handle.js +1 -1
  232. package/dist/domain/system-components/material-swatch.js +1 -1
  233. package/dist/domain/system-components/scene-entity-material-override.d.ts +1 -1
  234. package/dist/domain/system-components/scene-entity-object-material-override.d.ts +1 -1
  235. package/dist/domain/system-components/scene-entity-object-text-decal.d.ts +1 -1
  236. package/dist/domain/system-components/scene-entity-object-transimissive-material-override.d.ts +1 -1
  237. package/dist/domain/system-components/scene-entity-transimissive-material-override.d.ts +1 -1
  238. package/dist/domain/system-components/static-orthographic-camera-component.js +1 -1
  239. package/dist/domain/system-components/static-perspective-camera-component.js +1 -1
  240. package/dist/i18n/locales/cs/messages.js +1 -1
  241. package/dist/i18n/locales/da/messages.js +1 -1
  242. package/dist/i18n/locales/de/messages.js +1 -1
  243. package/dist/i18n/locales/de-AT/messages.js +1 -1
  244. package/dist/i18n/locales/en/messages.js +1 -1
  245. package/dist/i18n/locales/en-AU/messages.js +1 -1
  246. package/dist/i18n/locales/en-GB/messages.js +1 -1
  247. package/dist/i18n/locales/es/messages.js +1 -1
  248. package/dist/i18n/locales/fr/messages.js +1 -1
  249. package/dist/i18n/locales/hu/messages.js +1 -1
  250. package/dist/i18n/locales/it/messages.js +1 -1
  251. package/dist/i18n/locales/nl/messages.js +1 -1
  252. package/dist/i18n/locales/pl/messages.js +1 -1
  253. package/dist/i18n/locales/pt/messages.js +1 -1
  254. package/dist/i18n/locales/ro/messages.js +1 -1
  255. package/dist/i18n/locales/sk/messages.js +1 -1
  256. package/dist/i18n/locales/tr/messages.js +1 -1
  257. package/dist/legacy/domain-cli/utils/cache.d.ts +1 -1
  258. package/dist/legacy/domain-cli/utils/cache.js +1 -1
  259. package/dist/legacy/domain-spec/__generated/domain-schema.d.ts +81 -68
  260. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/claude-md.d.ts +1 -1
  261. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/cursor-rules.d.ts +1 -1
  262. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/shared-sdk-content.d.ts +1 -1
  263. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/shared-sdk-content.js +7 -1
  264. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-admin.js +18 -16
  265. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-configurator.js +14 -12
  266. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-embedded-admin.js +13 -11
  267. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-embedded-configurator.js +13 -11
  268. package/dist/phoenix/application-spec/application-spec-builder.js +1 -1
  269. package/dist/phoenix/application-spec/project-files.js +1 -1
  270. package/dist/phoenix/commands/check.js +1 -1
  271. package/dist/phoenix/commands/deploy.js +1 -1
  272. package/dist/phoenix/commands/dev.js +5 -5
  273. package/dist/phoenix/commands/fix.js +1 -1
  274. package/dist/phoenix/services/application-spec-project-watcher.d.ts +2 -0
  275. package/dist/phoenix/services/application-spec-project-watcher.js +3 -3
  276. package/dist/phoenix/services/source-archive.d.ts +1 -0
  277. package/dist/phoenix/services/source-archive.js +1 -1
  278. package/dist/phoenix/services/swc.js +1 -1
  279. package/dist/react-sdk/domain-context/common-hooks/use-configurator-messages.d.ts +30 -0
  280. package/dist/react-sdk/domain-context/common-hooks/use-configurator-messages.js +1 -0
  281. package/dist/react-sdk/domain-context/index.d.ts +2 -1
  282. package/dist/react-sdk/domain-context/index.js +1 -1
  283. package/dist/react-sdk/domain-context/system-hooks/navigation-hooks.d.ts +5 -0
  284. package/dist/react-sdk/domain-context/system-hooks/navigation-hooks.js +1 -1
  285. package/dist/react-sdk/domain-controls/hooks/use-angle-dimension.d.ts +1 -1
  286. package/dist/ui-sdk/theme/types.d.ts +1 -1
  287. package/package.json +33 -29
  288. package/schema/domain-spec.json +1115 -209
  289. package/dist/application-spec/generate-application/code/templates/webhook-implementation.d.ts +0 -1
  290. package/dist/application-spec/generate-application/code/templates/webhook-implementation.js +0 -7
  291. /package/dist/application-spec/{core → enhanced-json}/eval-code-uses-self.d.ts +0 -0
  292. /package/dist/application-spec/{core → enhanced-json}/eval-code-uses-self.js +0 -0
  293. /package/dist/application-spec/{core → enhanced-json}/eval-to-constant.js +0 -0
@@ -0,0 +1,116 @@
1
+ # Layout Slots
2
+
3
+ A project layout registered as `ConfiguratorLayout` builds its UI from its own components and from the pieces of the built-in layout it wants to keep. Those pieces are the members of `LayoutSlots`, from `@salsita-ai/sdk/configurator`. This page lists every member: what it shows, what in the spec or the configurator's state feeds it, what it renders when the spec configures nothing for it, and what it does in read mode. [Configurator Interface → Loaded Configuration UI](?path=/docs/phoenix-configurator-interface--docs#loaded-configuration-ui) says what a project layout has to mount, and its [Hooks for a Project Layout](?path=/docs/phoenix-configurator-interface--docs#hooks-for-a-project-layout) list the hooks for a layout that draws its own UI.
4
+
5
+ - [How the slots behave](#how-the-slots-behave)
6
+ - [Canvas and services](#canvas-and-services)
7
+ - [Desktop sidebar](#desktop-sidebar)
8
+ - [Header, toolbar and controls](#header-toolbar-and-controls)
9
+ - [Banners and branding](#banners-and-branding)
10
+ - [Page footer](#page-footer)
11
+ - [Phone layout](#phone-layout)
12
+ - [Others](#others)
13
+
14
+ ## How the slots behave
15
+
16
+ ```tsx
17
+ import { LayoutSlots } from '@salsita-ai/sdk/configurator'
18
+
19
+ // Part of a ConfiguratorLayout: the built-in toolbar, placed by the layout in the bottom right corner
20
+ export const Toolbar = () => (
21
+ <div style={{ position: 'absolute', insetBlockEnd: 24, insetInlineEnd: 24 }}>
22
+ <LayoutSlots.DesktopToolbar />
23
+ </div>
24
+ )
25
+ ```
26
+
27
+ - A slot takes no props unless its row names them, and reads what it shows from the spec and the configurator's state. It renders inside the configurator only, under a `ConfiguratorLayout`.
28
+ - A slot brings its own look but not its place: it adds no padding or scrolling around itself, so the layout puts it in a container. Two members differ: `SharedCanvas` fills its nearest positioned ancestor, and `DesktopSidebar` brings the sidebar's spacing and scrolling with it.
29
+ - Read mode means `useAccessService().accessInfo.viewMode` is `true`: a configuration shared for viewing is open, or the host sets the `readonly` property. "No change" in the read-mode column means the slot renders the same for a viewer, so the layout decides whether a viewer sees it.
30
+ - `Desktop*` and `Mobile*` members are twins that differ in size and arrangement; [Phone layout](#phone-layout) lists the phone ones. The container's width, not the window's, decides which one fits: `useActiveViewports()` from `@salsita-ai/sdk/react` returns the breakpoints the container satisfies. The built-in layout uses the `Desktop*` members while `desktop` is active, for a container wider than 768 pixels, and the `Mobile*` members otherwise, while `mobile` is active; `phone` means narrower than 480 pixels and `tablet` between 480 and 1024.
31
+
32
+ ## Canvas and services
33
+
34
+ | Member | Shows | Fed by | With nothing configured | Read mode |
35
+ | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ----------------------- | --------- |
36
+ | `SharedCanvas` | The 3D scene, in a container that is `position: absolute; inset: 0` with the scene's background colour. The scene is hidden for a moment while the preview expands or collapses. | The scene of the spec, through `Canvas` | Always renders | No change |
37
+ | `Canvas` | The WebGL canvas alone, or `GPUIssuePage` when the browser has no WebGL or no GPU acceleration. It reports the scene-assets loading phase the app loader waits for. | The scene, the canvas settings and the `CanvasLoader` element | Always renders | No change |
38
+ | `Services` | Nothing visible: it mounts `InvariantViolations` and `SideEffects`, which show the messages of `useConfiguratorMessages()` as snackbars | The configurator's state | Always mounted | No change |
39
+ | `InvariantViolations` | When a change is rejected, a snackbar for each violation of the rejected state, including notices and warnings already present, as `<entity id>: <message>` (a `notice` as info, a `warning` as warning, `fixable` and `fatal` as error), and "Oops, something went wrong" for an error thrown while the state was validated | The spec's invariants | Nothing | No change |
40
+ | `SideEffects` | An info snackbar for each committed update that carries a hint | The hints of committed updates | Nothing | No change |
41
+ | `DesktopSnackbarsRoot` | The element the snackbars are rendered into: a stack anchored to its bottom edge, at most 320 pixels wide | Every snackbar the configurator raises | An empty element | No change |
42
+
43
+ - Mount `SharedCanvas`, not `Canvas`: `Canvas` suspends while it probes the GPU on its first mount, and `SharedCanvas` holds the boundary that catches it. Without either, the app loader stays on screen unless the project sets `appLoader: legacy`.
44
+ - `SharedCanvas` fills its nearest positioned ancestor and paints an opaque background, so the layout positions its own UI after it in the markup.
45
+ - Snackbars are raised by `Services`, and also by the built-in finalize and footer actions when their handler fails and when saving the configuration fails. A layout that shows violations, side-effect hints and validation errors its own way calls `phx.frontend.useConfiguratorMessages(onMessage)` instead of mounting `Services`, see [Configurator Interface → Hooks for a Project Layout](?path=/docs/phoenix-configurator-interface--docs#hooks-for-a-project-layout); the other snackbars still need a root. They render into the snackbar root the layout mounts; with no root mounted they render into the page's `document.body`, outside the configurator. The desktop root is a zero-height element the snackbars stack upwards from, so the layout places it where their bottom edge belongs. The phone root leaves them fixed to the viewport, see `MobileSnackbarsRoot`. A finalize action the layout runs with `phx.frontend.useFinalizeAction` raises no snackbar; its error is the hook's `error`.
46
+
47
+ ## Desktop sidebar
48
+
49
+ | Member | Shows | Fed by | With nothing configured | Read mode |
50
+ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
51
+ | `DesktopSidebar` | The whole built-in desktop sidebar: tabs, back button, property pages and sidebar footer with their spacing, scrolling and empty states, and the assistant panel. Props: `width`, and `side` (`'start'` or `'end'`, typed `DesktopSidebarSide`; `DesktopSidebarProps` types both) | The members below | As its parts | As its parts. In fullscreen it stays in place, transparent and inert |
52
+ | `DesktopSidebarTabs` | Tabs that switch the navigation state | The `sidebarTabs` components of the selected entity; the `horizontalTabs` component is not shown here | Nothing; also nothing while the summary is shown | No change |
53
+ | `useSidebarTabs()` | A hook, `{ tabs, activeTab, onChange }`: each tab is `{ label, icon, value, isActive }`, `activeTab` is the active tab's value or `'none'`, and `onChange(value)` switches to that tab's first navigation state | As `DesktopSidebarTabs` | `tabs` is empty | No change |
54
+ | `DesktopSidebarBackButton` | A "Back" button. Props: the MUI `Button` props and `icon`, also settable in the theme as `PhxDesktopSidebarBackButton`; the application config's `sidebarBackIcon` takes precedence over both | The sidebar's way back: a navigation state to pop, a stacked property page, or a selected entity other than the root, unless the application config sets `showSelectionBackButton` to `false` or sets `ignoreSelectionInSidebar` | Nothing while there is no way back | No change |
55
+ | `DesktopSidebarContent` | The property pages of the selected entity with its entity header, a stacked page opened from them, or the summary page while the summary is shown. With the application config's `ignoreSelectionInSidebar` set, every `propertyPage` of every entity shows under the root, whatever is selected | `propertyPage`, `entityHeader`, `simpleSummary` and `customSummaryPage` components, and `ignoreSelectionInSidebar` | Nothing | **No change: the controls stay editable.** Limit them with `$filter.modes`, or render something else in read mode |
56
+ | `useSidebarContent(options?)` | A hook, `{ content, goBack, hasMiniSidebar, hasSplitSidebar }`: `content` is what `DesktopSidebarContent` shows, `goBack` is the back action or `null`. `options` sets the `HeaderContainer` and `BodyContainer` components the content is wrapped in | As `DesktopSidebarContent` | `content` is empty | No change |
57
+ | `EntityHeader` | An entity's title, subtitle, description and thumbnail, with its primary and secondary buttons, such as delete or replace. Props, typed `EntityHeaderProps`: `entityId` and `headerComponent` | The texts and thumbnail from the entity's `detail` component (the title falls back to the entity type); the buttons from the `entityHeader` component passed in | — | No change |
58
+ | `DesktopSidebarFooter` | The price and the actions | `basicSidebarFooter`, `universalSidebarFooter`, `readSidebarFooter`, `hiddenSidebarFooter` or `customSidebarFooter`. The basic footer offers a `finalizeButton`, else a button for a `finalizePage`, else a disabled button; the universal footer offers the `finalizeAction` and `otherAction` components | The basic footer: the price and a finalize button. With a `navigationSteps` component of two or more steps, previous and next step buttons and the finalize button only on the last step; with a summary and no steps, a **Summary** button until the summary is shown; in a preset embed, **Save Template** instead of finalize | With nothing configured, the read footer: price only. The basic footer hides its buttons. **The universal footer still shows its finalize and other actions to a viewer**; limit them with `$filter.modes` |
59
+
60
+ A sidebar footer with `universalSidebarFooter` does not check read mode, although the component's own description says its buttons are hidden then. A viewer of a shared configuration sees its actions. The `custom` footer renders its children unchanged as well.
61
+
62
+ ## Header, toolbar and controls
63
+
64
+ | Member | Shows | Fed by | With nothing configured | Read mode |
65
+ | --------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
66
+ | `DesktopHeader` | The floating, fixed or custom header | The first `floatingHeader`, `fixedHeader`, `hiddenHeader` or `customHeader` component | The floating header. Nothing with `hiddenHeader` or in fullscreen | The floating header shows the back button instead of the step navigation; the fixed header hides its horizontal tabs |
67
+ | `DesktopToolbar` | The toolbar's button groups | The `toolbar` component's `desktop` list, or else a default set | Default buttons: fullscreen and camera reset; language with more than one locale; share unless sharing is disabled; measurements with more than one dimension or with `indicatorSwitch` on (the default), and help in that group when the project registers a `ToolbarHelp` element; undo and redo; the assistant when the spec has an `assistant` section. In fullscreen, only the exit button | The default set drops share and undo/redo; a configured `toolbar` is shown unchanged |
68
+ | `DesktopViewControls` | A toggle between view states | The root entity's `viewControls` component and the active view state | Nothing without the component or without an active view state | No change |
69
+ | `DesktopToolControls` | A vertical group of tool buttons that switch the tool state | The root entity's `toolControls` component | Nothing without the component | No change |
70
+ | `ToolControls` | The same component as `DesktopToolControls` and `MobileToolControls` | As `DesktopToolControls` | Nothing without the component | No change |
71
+ | `DesktopCallToAction` | **The button that leaves a tool mode, not the finalize button.** Clicking it switches to the component's `exitTo` tool state | An `exitToolModeFab` component, usually filtered to the tool states it belongs to | Nothing. It throws when more than one is active | Nothing |
72
+
73
+ Instead of `DesktopViewControls` or `MobileViewControls`, a layout can build its own view buttons with `phx.frontend.useActiveViewState()` and `phx.frontend.useSetViewState()`, which need no `viewControls` component, see [Hooks for a Project Layout](?path=/docs/phoenix-configurator-interface--docs#hooks-for-a-project-layout).
74
+
75
+ ## Banners and branding
76
+
77
+ | Member | Shows | Fed by | With nothing configured | Read mode |
78
+ | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
79
+ | `DesktopReadonlyBanner` | "You're viewing a read-only configuration" with an **Edit configuration** button that opens `CloneToEditDialog`. Props: the MUI `Alert` props and `icon`, also settable in the theme as `PhxDesktopReadonlyBanner` | `useIsCloningAllowed()`; its icon from the application config's `readonlyBannerIcon` | Nothing unless cloning is allowed | **It does not check read mode.** The layout renders it only in read mode, as the built-in layout does while not in fullscreen |
80
+ | `MobileReadonlyBanner` | An **Edit** button that opens `CloneToEditDialog`. Props: the MUI `Button` props and `icon`, also settable in the theme as `PhxMobileReadonlyBanner` | As `DesktopReadonlyBanner` | Nothing unless cloning is allowed | As `DesktopReadonlyBanner` |
81
+ | `CloneToEditDialog` | The "Edit configuration" dialog that creates an editable copy of the configuration and opens it. Props, typed `CloneToEditDialogProps`: `open` and `onClose` | The open configuration | — | — |
82
+ | `useIsCloningAllowed()` | A hook, `boolean`: `true` when the application config sets `shareCloneToEdit` and the session's role may create configurations | The application config and the session | `false` | Does not check read mode |
83
+ | `DesktopPoweredBy` / `MobilePoweredBy` | The "Powered by Salsita" mark, a link | Its props `visible`, `variant` (`'black'` or `'white'`), `href`, `title`, `slots` and `slotProps`. All but `href` and `title` are also settable in the theme as `PhxDesktopBrandingPoweredBy` / `PhxMobileBrandingPoweredBy` | The mark | No change |
84
+
85
+ ## Page footer
86
+
87
+ | Member | Shows | Fed by | With nothing configured | Read mode |
88
+ | -------------------------------- | ------------------------------------------------------- | --------------------------------------------------------------------------------------- | ----------------------- | --------- |
89
+ | `DesktopFooter` / `MobileFooter` | A footer below the whole layout, not the sidebar footer | The project's `LayoutFooter` element, registered with `phx.frontend.createLayoutFooter` | Nothing | No change |
90
+
91
+ ## Phone layout
92
+
93
+ The phone twins read the same spec as their desktop members.
94
+
95
+ | Member | Shows | Differences from the desktop member |
96
+ | ------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
97
+ | `MobileHeader` | The header | The floating and fixed headers show a back button and the branding; the back button is hidden with steps and in read mode |
98
+ | `MobileToolbar` | The toolbar | Reads the `toolbar` component's `mobile` list, rendered in reverse order. The default set has undo and redo, camera reset, fullscreen and the assistant, and drops undo and redo in read mode |
99
+ | `MobileHamburgerMenu` | A menu button that opens the remaining actions in a dialog | Reads the `toolbar` component's `mobileMenu` list, or else share, measurements, language and help under the same conditions as the desktop toolbar; share is dropped in read mode. Nothing when the list is empty. Props: `icon` and `closeIcon`, also settable in the theme as `PhxMobileHamburgerMenu`; the application config's `hamburgerIcon` and `toolbarCloseIcon` take precedence |
100
+ | `MobileTabs` | Scrollable tabs that switch the navigation state | Reads the selected entity's `sidebarTabs` or the `horizontalTabs` component, and throws when both are active or when more than one of either is active. Nothing without tabs or while the summary is shown. Unlike the desktop fixed header, it keeps horizontal tabs in read mode |
101
+ | `MobileViewControls` | A toolbar button with the active view's icon that opens the list of views | Nothing without the component, an active view state or that view's icon |
102
+ | `MobileToolControls` | The tool buttons | Same component as `DesktopToolControls` |
103
+ | `MobileCallToAction` | The button that leaves a tool mode | Same as `DesktopCallToAction` |
104
+ | `MobileSidebarBackButton` | A "Back" button | Same as `DesktopSidebarBackButton`, smaller, with `sidebarBackIcon` taking precedence the same way; its theme name is `PhxMobileSidebarBackButton` |
105
+ | `MobileSidebarContent` | The property pages | Same content as `DesktopSidebarContent` |
106
+ | `MobileSidebarFooter` | The price and the actions | Same as `DesktopSidebarFooter`; the universal footer adds the step label and progress |
107
+ | `MobileSnackbarsRoot` | The element the snackbars are rendered into | It does not position the snackbars: they keep notistack's `position: fixed` and sit at the viewport's edge wherever the root is. The built-in phone layout positions them with its own styles; a project layout styles `notistackSnackbarClasses.container` from `@salsita-ai/sdk/ui` |
108
+
109
+ ## Others
110
+
111
+ | Member | Shows |
112
+ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
113
+ | `GPUIssuePage` | `WebGLNotSupported` or `GPUAccelerationDisabled`, chosen by its `issue` prop. `Canvas` renders it; a layout does not need it |
114
+ | `GPUIssue` | The two values of that prop, `'no-gpu'` and `'no-acceleration'`, as a constant and a type |
115
+ | `WebGLNotSupported` | A full-page message that WebGL is not supported, with a **Go To Homepage** button that returns to the configurator's start page |
116
+ | `GPUAccelerationDisabled` | A full-page message that GPU acceleration is disabled, with the same button |
@@ -251,8 +251,19 @@ rm src/frontend/frontend.tsx
251
251
  # Remove empty domain/frontend folders after moving all files
252
252
  rmdir src/domain/implementation src/domain/data src/domain
253
253
  rmdir src/frontend/systems/transformers src/frontend/systems src/frontend/ui src/frontend/admin-pages src/frontend
254
+
255
+ # Remove the root TypeScript settings (sync writes the file again)
256
+ rm tsconfig.json
254
257
  ```
255
258
 
259
+ With the application-spec pipeline (`phoenix.applicationFlow` in `package.json`; see [Current and legacy project tooling](?path=/docs/phoenix-phoenix-cli--docs#current-and-legacy-project-tooling)), the project's TypeScript settings are generated into `.phoenix/tsconfig.json`. Sync writes the root `tsconfig.json` only into a project that has none, as a single line that extends them:
260
+
261
+ ```json
262
+ { "extends": "./.phoenix/tsconfig.json" }
263
+ ```
264
+
265
+ A root `tsconfig.json` from the old multi-folder template, or one written by hand, stays as it is and does not pick up the generated settings or the global `phx` types in `.phoenix/globals.d.ts`, so `pnpm ts:check` fails. Delete it, or replace its content with the line above, before the first sync.
266
+
256
267
  ### 10. Create Mocks (Optional)
257
268
 
258
269
  If you have mock files, move them to `mocks/`:
@@ -390,7 +401,7 @@ pnpm install
390
401
 
391
402
  1. Run type check: `pnpm ts:check`
392
403
  2. Update any broken type imports
393
- 3. Ensure `tsconfig.json` paths are correct (auto-generated by Phoenix)
404
+ 3. With the application-spec pipeline (`phoenix.applicationFlow`; see [Current and legacy project tooling](?path=/docs/phoenix-phoenix-cli--docs#current-and-legacy-project-tooling)), check that the root `tsconfig.json` is the one-line file that extends `.phoenix/tsconfig.json` (see [step 9](#9-remove-auto-generated-files))
394
405
 
395
406
  ## Checklist
396
407
 
@@ -433,13 +444,13 @@ Use this checklist to verify migration completeness:
433
444
 
434
445
  The following files are no longer needed - they are auto-generated by the CLI:
435
446
 
436
- | File | Replacement |
437
- | --------------------------- | -------------------------------------------- |
438
- | `src/domain/domain.ts` | Auto-generated in `.phoenix/domain.ts` |
439
- | `src/frontend/frontend.tsx` | Auto-generated in `.phoenix/configurator.ts` |
440
- | `tsconfig.json` | Auto-generated by CLI |
441
- | `eslint.config.js` | Auto-generated by CLI |
442
- | `prettier.config.js` | Auto-generated by CLI |
447
+ | File | Replacement |
448
+ | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
449
+ | `src/domain/domain.ts` | Auto-generated in `.phoenix/domain.ts` |
450
+ | `src/frontend/frontend.tsx` | Auto-generated in `.phoenix/configurator.ts` |
451
+ | `tsconfig.json` | Delete before the first sync; with the application-spec pipeline, sync writes a one-line file that extends `.phoenix/tsconfig.json` |
452
+ | `eslint.config.js` | Auto-generated by CLI |
453
+ | `prettier.config.js` | Auto-generated by CLI |
443
454
 
444
455
  ## Builder Options Moved to YAML
445
456
 
@@ -137,8 +137,8 @@ The same streams are available in the editor's **Logs** sidebar panel with per-s
137
137
 
138
138
  Runs all code quality checks in sequence:
139
139
 
140
- 1. **TypeScript** — Type checking with `tsc`
141
- 2. **ESLint** — Linting rules
140
+ 1. **TypeScript** — Type checking with `tsc`, with the project's root `tsconfig.json`, or with `.phoenix/tsconfig.json` when the project has none (see [Project Structure](?path=/docs/phoenix-project-structure--docs#root-level-files))
141
+ 2. **ESLint** — Linting rules, over `src/`; a project with no files there passes
142
142
  3. **Prettier** — Code formatting
143
143
 
144
144
  ### `phoenix fix`
@@ -147,12 +147,23 @@ Auto-fixes ESLint and Prettier issues. Equivalent to running `eslint --fix` and
147
147
 
148
148
  ## Environment Variables
149
149
 
150
- When you run `deployment:prepare-local` or `deployment:prepare`, the CLI communicates with the Phoenix server, which generates environment variables and writes them to `.env.generated`.
150
+ When you run `deployment:prepare-local` or `deployment:prepare`, the CLI communicates with the Phoenix server, which generates environment variables and writes them to `.env.generated`. `phoenix dev` does the same for its development deployment when it starts.
151
+
152
+ ### The generated env file
153
+
154
+ A project has one generated env file. Phoenix keeps it in `.phoenix/`, as `.phoenix/.env.generated`, unless the project has a `.env.generated` in its root, which then is the one that counts.
155
+
156
+ - `phoenix dev` reads and writes `.phoenix/.env.generated` in a project without a root `.env.generated`, and creates no file in the project root. In a project that has a root `.env.generated`, it reads and writes that file and `.phoenix/.env.generated` is not used.
157
+ - The deployment and environment commands (`deployment:prepare`, `deployment:prepare-dev`, `deployment:prepare-local`, `deployment:build-envs` and the others with an `--outFile` option) write `.env.generated` in the project root unless `--outFile` or `OUT_FILE` names another file. Deploy pipelines read it there. Once one of them has written it, `phoenix dev` and `phoenix build` use it.
158
+ - Everything that reads environment variables follows the same rule: the root `.env.generated` when it exists, otherwise `.phoenix/.env.generated`. The two files are never merged.
159
+ - `phoenix clean` removes `.phoenix/` and with it `.phoenix/.env.generated`; the next `phoenix dev` prepares the development deployment again. A root `.env.generated` stays.
160
+
161
+ This holds for a project on the application-spec pipeline. In a project on the legacy pipeline (see [Current and legacy project tooling](#current-and-legacy-project-tooling)), `phoenix dev` always reads and writes `.env.generated` in the project root.
151
162
 
152
163
  ### Data Flow
153
164
 
154
165
  ```
155
- spec/application.yaml → Server prepares environment → CLI writes .env.generated → Frontend/Webhooks read it
166
+ spec/application.yaml → Server prepares environment → CLI writes the generated env file → Frontend/Webhooks read it
156
167
  ```
157
168
 
158
169
  ### Project Scripts
@@ -173,7 +184,7 @@ A project may have other scripts than these five, such as `sync`, `test` or `ver
173
184
 
174
185
  ### Server-Generated Variables
175
186
 
176
- These are automatically computed by the server and written to `.env.generated`:
187
+ These are automatically computed by the server and written to the generated env file:
177
188
 
178
189
  | Variable | Purpose |
179
190
  | -------------------------------- | ------------------------------------------------------- |
@@ -222,7 +233,7 @@ A build pipeline that receives the source archive of a [`phoenix deploy`](#phoen
222
233
  - it refuses an archive over 200 MB, one that extracts to more than 1 GB, or one with more than 100,000 files;
223
234
  - it refuses links, special files, absolute paths, paths that leave the folder, names with control characters, and entries that repeat or collide with an earlier one;
224
235
  - it refuses an archive it cannot read to the end, such as a truncated upload;
225
- - it extracts only project files, the same set `phoenix deploy` packs, and reports the entries it left out.
236
+ - it extracts only project files and reports the entries it left out, including the optional `conversation.log` that deploy keeps in the private archive for review.
226
237
 
227
238
  `<folder>` must be new or empty. When the command refuses an archive, it removes the folder, so a partly extracted project is never built.
228
239
 
@@ -261,7 +272,7 @@ A development environment keeps the AI assistant's conversation when the assista
261
272
  Environment variables are resolved in this order (highest to lowest priority):
262
273
 
263
274
  1. Process environment variables (shell)
264
- 2. `.env.generated` (created by deployment commands)
275
+ 2. [The generated env file](#the-generated-env-file): `.env.generated` in the project root when the project has one, otherwise `.phoenix/.env.generated`
265
276
  3. `.env` (manual overrides)
266
277
 
267
278
  ### Generated Config Files
@@ -292,13 +303,16 @@ Starts the full development environment: Vite dev server, development webhook tu
292
303
  | `--region` | `PHOENIX_REGION` | `eu` | Region of the signed-in workspace, used when no server URL is set |
293
304
  | `--skipUpload` / `--su` | `SKIP_UPLOAD` | `false` | Skip the S3 asset upload when the development deployment is prepared at startup |
294
305
 
306
+ With the application-spec pipeline, `phoenix dev` creates an empty `src/` folder when the project has none, so that it rebuilds when the first source file, such as `src/webhooks/index.ts`, is added.
307
+
295
308
  In `server` persistence mode the project comes from `--projectSlug`, `PROJECT_SLUG` or `project` in the spec, and the credential from `DEVELOPMENT_KEY` or the `phoenix login` sign-in; see [Starting a New Project](#starting-a-new-project). When signed in, the environment is always your own development environment and `--environmentSlug` is ignored.
296
309
 
297
310
  The dev server watches for changes in:
298
311
 
299
312
  - `spec/**/*.yaml` — Domain specification files
300
313
  - `src/**/*.{ts,tsx,yaml,yml,json,html,css}` — Source files
301
- - `.env`, `.env.generated` — Environment files (triggers full Vite restart)
314
+ - `.env` — Environment file; a change restarts the Vite dev server
315
+ - `.env.generated`, `.phoenix/.env.generated` — Generated env files; a change rebuilds the project files. Only a file that exists when `phoenix dev` starts is watched: a root `.env.generated` that a deployment command creates while dev runs is not watched; restart `phoenix dev` to use it.
302
316
 
303
317
  When linked SDK packages are detected (`phoenix link`), changes to SDK dist files are also watched.
304
318
 
@@ -705,6 +719,10 @@ Revokes the token on the server and removes it from the credentials file. `--reg
705
719
 
706
720
  Validates the spec, adds the pnpm settings `phoenix init` writes to `pnpm-workspace.yaml` when they are missing, packs and uploads the project, starts its build on the server and follows it until the configurator is live. Before the upload the server compares the domain model with the deployed one: a model that changed under an already deployed model version is refused with the reason, and needs a new model version and a [migration](?path=/docs/phoenix-migrations--docs). Once the build starts it prints `Follow the build in Studio: <url>`, the build's page in the Studio you signed in through; a sign-in stored by an older CLI has no Studio URL, so sign in again to get the link. After `Your configurator is live at <url>` it prints one line for coding agents, which tells them to offer the run evaluation of the `phoenix-feedback` skill once you have nothing more to build; you can ignore it when you run the command yourself. `--region` or `--serverUrl` selects the server, as for `login`; `--no-wait` returns as soon as the build starts.
707
721
 
722
+ To keep the conversation that led to a build, place a reviewed UTF-8 transcript in `conversation.log` at the project root before deploying. Deploy automatically includes it in the private source archive. Download the build's sources from Studio to read it; access is the same as for the rest of that build's sources. The build extractor skips the log, so it is not an application build input or a public asset. Missing logs produce a warning and deployment continues. Directories, links and special files at that path are rejected.
723
+
724
+ The Phoenix agent skill explains how to prepare the transcript: prefer a native session export; otherwise mark a reconstruction as incomplete. Preserve available user/assistant messages and tool calls, cap individual tool results at 16 KiB with explicit truncation markers, and reference images rather than embedding them. Include the agent, export time, source and known omissions. Review and redact credentials or unrelated sensitive content before approving upload. The CLI uploads the file as supplied; it does not collect agent history, redact content, check freshness or verify completeness. Remove the file from the project root to deploy without it. The log counts toward the source archive's existing size limits; there is no separate conversation upload or viewer.
725
+
708
726
  ### `phoenix feedback [message]`
709
727
 
710
728
  Sends feedback about the SDK, the CLI, the documentation or Studio to the Phoenix team. It needs `phoenix login`: the server records the workspace, user and API token of the sign-in, so the message itself needs no introduction.
@@ -44,7 +44,7 @@ project-root/
44
44
  | `invariants/` | Domain constraints |
45
45
  | `transformers/` | Data transformation logic |
46
46
  | `handlers/` | Event & lifecycle handlers |
47
- | `webhooks/` | Webhook implementations |
47
+ | `webhooks/` | Webhook implementations, entered through `index.ts` |
48
48
  | `migrations/` | Data schema migrations (v\*.ts) - auto-created based on model versions |
49
49
  | `locales/` | Locale catalogs (`.po` sources; compiled `.ts`, do not edit) |
50
50
  | `_*` | Shared code folders at any depth (not auto-imported) |
@@ -56,6 +56,9 @@ factory returns, or an array of those. A file that exports anything else, such a
56
56
  shape. When several files in `handlers/`, `elements/`, `transformers/`, `components/`, `admin/elements/` and
57
57
  `admin/components/` are wrong, the error lists all of them, one numbered line per file. Keep plain components and helpers in a `_*` folder.
58
58
 
59
+ With the application-spec pipeline, sync does not write `src/webhooks/index.ts`, and a project without it gets a
60
+ built-in webhook; see [Webhook Entry Point](?path=/docs/phoenix-webhooks--docs#webhook-entry-point).
61
+
59
62
  ### Admin Folders (src/admin/)
60
63
 
61
64
  The `admin/` folder supports these admin-specific categories:
@@ -180,7 +183,7 @@ type CustomMaterial = Phx['AdminModel']['CustomMaterial']
180
183
  | File | Auto-Generated? | Notes |
181
184
  | ------------------------------------------------------ | --------------- | -------------------------------------- |
182
185
  | `package.json` | Partially | Dependencies merged, scripts untouched |
183
- | `tsconfig.json` | Yes | Managed by Phoenix |
186
+ | `tsconfig.json` | Once | Yours; see below |
184
187
  | `eslint.config.js` | Yes | Managed by Phoenix |
185
188
  | `prettier.config.js` | Yes | Managed by Phoenix |
186
189
  | `.prettierignore` | No | Optional and your own; see below |
@@ -189,19 +192,29 @@ type CustomMaterial = Phx['AdminModel']['CustomMaterial']
189
192
  | `.gitignore` | Partially | Only in a git repository; see Markers |
190
193
  | `.env` | No | Git-ignored, local config |
191
194
  | `.env.example` | No | Template for env vars |
192
- | `.env.generated` | Yes | Auto-generated IDs, git-ignored |
195
+ | `.env.generated` | Yes | Optional, git-ignored; see below |
193
196
  | `README.md` | No | Project documentation |
194
197
  | `AGENTS.md` | No | Your own coding-agent instructions |
195
198
  | `.claude/skills/phoenix*/`, `.agents/skills/phoenix*/` | Yes | Phoenix agent skills |
196
199
 
197
200
  Sync does not write `README.md`, `AGENTS.md`, `.env.example`, `.env.ci` or the `README.md` files in `assets/public/` and `assets/private/`. Earlier SDK versions wrote them once; a project that has them keeps them, and they are yours to edit.
198
201
 
202
+ Phoenix keeps the generated env file, with the IDs and values of the prepared deployment, in `.phoenix/` unless the project has a `.env.generated` in its root, which then is the one that counts. `phoenix dev` creates no `.env.generated` in the project root; the deployment and environment commands write it there. See [The generated env file](?path=/docs/phoenix-phoenix-cli--docs#the-generated-env-file).
203
+
199
204
  With the application-spec pipeline (see [Current and legacy project tooling](?path=/docs/phoenix-phoenix-cli--docs#current-and-legacy-project-tooling)), Phoenix does not write a `.prettierignore`, and a fresh clone or CI checkout of a project has none. `phoenix check` and `phoenix fix` do not read one: they skip `.phoenix/`, `dist/`, the compiled catalogs in `src/locales/`, `pnpm-lock.yaml` and `.linguirc` on their own. A project that runs Prettier directly, as `prettier --check .` or from an editor, can add its own `.prettierignore`. To commit it, add a `!.prettierignore` line after the Phoenix block of `.gitignore`, because that block lists the file. The legacy pipeline writes `.prettierignore` on every sync.
200
205
 
206
+ With the application-spec pipeline, the project's TypeScript settings are in `.phoenix/tsconfig.json`, which sync rewrites with the rest of `.phoenix/`. The root `tsconfig.json` is the one editors and tools find: sync writes it only when the project has none, as a single line that extends the generated settings, and it is yours to commit and to add to:
207
+
208
+ ```json
209
+ { "extends": "./.phoenix/tsconfig.json" }
210
+ ```
211
+
212
+ The only root `tsconfig.json` sync replaces is the full file earlier SDK versions generated there, recognised by its settings; any other stays as it is. `phoenix dev`, `phoenix build` and the webhook bundle do not resolve `paths` aliases, so an alias added to the root file passes `phoenix check` and fails the build. `phoenix check` type-checks with the root `tsconfig.json`, or with `.phoenix/tsconfig.json` when the project has none. The legacy pipeline writes the full `tsconfig.json` on every sync.
213
+
201
214
  ### DO NOT EDIT (Fully Auto-Generated)
202
215
 
203
- - **Everything in `.phoenix/`** - Completely regenerated on each build. The one exception is `.phoenix/variants/`, where a coding agent writes the option files for `phoenix variants`; a rebuild keeps it
204
- - `tsconfig.json`, `eslint.config.js`, `prettier.config.js`
216
+ - **Everything in `.phoenix/`** - Completely regenerated on each build. The exceptions are `.phoenix/variants/`, where a coding agent writes the option files for `phoenix variants`, and `.phoenix/.env.generated`, the generated env file of `phoenix dev`; a rebuild keeps both
217
+ - `eslint.config.js`, `prettier.config.js`
205
218
  - `.linguirc`, `.nvmrc`
206
219
  - `src/locales/**/*.ts` - Compiled from `.po` catalogs
207
220
  - `.env.generated`
@@ -239,6 +252,7 @@ With the application-spec pipeline (see [Current and legacy project tooling](?pa
239
252
  - `templates/`
240
253
  - `package.json` (scripts section, custom dependencies)
241
254
  - `.env`, `.env.example`, `.env.ci`
255
+ - `tsconfig.json` (application-spec pipeline; keep it extending `.phoenix/tsconfig.json`)
242
256
  - `README.md`, `AGENTS.md`
243
257
 
244
258
  ## File Naming Conventions
@@ -346,6 +360,7 @@ project-root/
346
360
  │ ├── admin-interface.ts # Admin interface types
347
361
  │ ├── i18n.ts # i18n initialization
348
362
  │ ├── globals.d.ts # Global type definitions
363
+ │ ├── tsconfig.json # TypeScript settings, extended by the root tsconfig.json
349
364
  │ ├── index.html # Configurator HTML entry
350
365
  │ └── admin.html # Admin HTML entry
351
366
  │
@@ -22,7 +22,7 @@ pnpm install
22
22
  pnpm phoenix sync
23
23
  ```
24
24
 
25
- `phoenix init [folder]` writes the starter project: `package.json`, `pnpm-workspace.yaml` and the starter spec, `spec/application.yaml` and `spec/configurator.yaml`, which describe one box you can resize and recolour. The starter depends on the same SDK version as the CLI that created it, and its `package.json` has the `dev`, `build`, `deploy`, `check` and `fix` scripts, which are yours to change. `phoenix sync` then adds the rest of the project: webhooks and lint config. It writes a `.gitignore` only when the folder is inside a git repository; run `git init` before the first sync, or sync again after it, to get the file.
25
+ `phoenix init [folder]` writes the starter project: `package.json`, `pnpm-workspace.yaml` and the starter spec, `spec/application.yaml` and `spec/configurator.yaml`, which describe one box you can resize and recolour. The starter depends on the same SDK version as the CLI that created it, and its `package.json` has the `dev`, `build`, `deploy`, `check` and `fix` scripts, which are yours to change. `phoenix sync` then adds the rest of the project: the TypeScript, lint and formatting config and the agent skills. It writes no webhook code: a project without `src/webhooks/index.ts` gets a built-in webhook (see [Webhook Entry Point](?path=/docs/phoenix-webhooks--docs#webhook-entry-point)). It writes a `.gitignore` only when the folder is inside a git repository; run `git init` before the first sync, or sync again after it, to get the file.
26
26
 
27
27
  `init` only writes these files: it asks nothing and contacts no server. It refuses a folder that already has a `spec/` folder. A `package.json` already in the folder is kept, as long as it depends on the SDK.
28
28
 
@@ -76,7 +76,7 @@ pnpm phoenix deploy
76
76
  `phoenix deploy` goes through these steps:
77
77
 
78
78
  1. It validates the application spec.
79
- 2. It packs the project files: the `.yaml` files in `spec`, everything in `src`, `mocks`, `assets`, `public` and `templates`, and `package.json`, `pnpm-lock.yaml`, `pnpm-workspace.yaml`, `.gitignore`, `CLAUDE.md` and `.cursor/rules/phoenix.mdc`. Every `node_modules`, `.phoenix` and `__generated` folder, every `.DS_Store` and `._*` file and every `.env` and `.env.*` file are left out, at any depth.
79
+ 2. It packs the project files: the `.yaml` files in `spec`, everything in `src`, `mocks`, `assets`, `public` and `templates`, and `package.json`, `tsconfig.json`, `pnpm-lock.yaml`, `pnpm-workspace.yaml`, `.gitignore`, `CLAUDE.md` and `.cursor/rules/phoenix.mdc`. Every `node_modules`, `.phoenix` and `__generated` folder, every `.DS_Store` and `._*` file and every `.env` and `.env.*` file are left out, at any depth.
80
80
  3. It asks the server for a build. The server compares your domain model with the deployed one and refuses, before anything is uploaded, a model that changed under an already deployed model version; see [Migrations](?path=/docs/phoenix-migrations--docs).
81
81
  4. It uploads the archive, which may be up to 200 MB.
82
82
  5. It starts the build, prints a link to the build's page in Studio and follows the build until your configurator is live, then prints its URL.
@@ -34,6 +34,23 @@ Phoenix provides domain-aware builders through the global `phx.webhooks` namespa
34
34
 
35
35
  ### Webhook Entry Point
36
36
 
37
+ Your webhook is the default export of `src/webhooks/index.ts`. With the application-spec pipeline (see [Current and legacy project tooling](?path=/docs/phoenix-phoenix-cli--docs#current-and-legacy-project-tooling)), the file is yours to create; sync does not write it. A project without it gets a built-in webhook, so it builds and deploys with no webhook code. The built-in webhook has one handler, an anonymous auth handler, which the platform calls only when `spec/application.yaml` sets `useAuthHook`. The legacy pipeline writes the file with that webhook on the first sync.
38
+
39
+ Create `src/webhooks/index.ts` when the project needs its own handlers: finalization, backend data, or an auth handler that does more than start an anonymous session. A project that sets `useAuthHook` or `useClerk` needs its own auth handler, because the built-in one answers only anonymous requests. The smallest file is the built-in webhook itself:
40
+
41
+ ```ts
42
+ // src/webhooks/index.ts
43
+ const authHandler = phx.webhooks.authHandlerBuilder
44
+ .withAnonymousHandler(async () => ({ success: true, data: {}, role: 'anonymous' }))
45
+ .build()
46
+
47
+ export default phx.webhooks.webhookBuilder.withAuthHook(authHandler).build()
48
+ ```
49
+
50
+ The next `phoenix sync` or `phoenix build`, or the rebuild of a running `phoenix dev`, uses the file; deleting it brings the built-in webhook back. A webhook needs at least one handler, and a project with any other file in `src/webhooks/` must have `index.ts`.
51
+
52
+ A webhook with more handlers:
53
+
37
54
  ```ts
38
55
  // src/webhooks/index.ts
39
56
  import { authHandler } from './handlers/auth-handler.js'
@@ -8,7 +8,7 @@ import type { CellValue } from '@salsita-ai/contracts/webhook';
8
8
  import type { AdminIntegrationService } from '#package/react-sdk';
9
9
  import type { $DomainEntity, DataCellValue, DataSchema, DomainEntity, DomainFactory, ProductPreset } from '../core/index.js';
10
10
  import type { AnalyticsSystem, RegistrableTransformer, TransformerFactory } from '../domain-context/index.js';
11
- import type { ProjectModule } from '../domain-runtime/index.js';
11
+ import type { ElementRegistration, ProjectModule } from '../domain-runtime/index.js';
12
12
  import type { AssistantResolvedManifest } from './assistant/index.js';
13
13
  import type { WebComponentEventDescriptor } from './web-component-event.js';
14
14
  import type { WebComponentPropertyDescriptor } from './web-component-property.js';
@@ -292,6 +292,8 @@ export interface ApplicationConfig<ENTITIES extends DomainEntity<string>, ALLOWE
292
292
  /** The `src/handlers/` and `src/elements/` files as project modules; the runtime spec validates and flattens both. */
293
293
  readonly handlers: readonly ProjectModule[];
294
294
  readonly elements: readonly ProjectModule[];
295
+ /** The SDK's default element registrations; a project element with the same name replaces one. */
296
+ readonly defaultElements?: readonly ElementRegistration[];
295
297
  readonly mount: MountConfig<ENTITIES, ALLOWED_ROOT_ENTITIES, $MAP, NAVIGATION_STATES, VIEW_STATES, TOOL_STATES, EXPORT_STATES, CHAT_CONTEXT, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ADMIN_ENTITIES, ADMIN_ALLOWED_ROOT_ENTITIES, ADMIN_$MAP, ADMIN_NAVIGATION_STATES, ADMIN_VIEW_STATES>;
296
298
  }
297
299
  export {};
@@ -1 +1 @@
1
- export const generateAssistantPrompt=e=>{let t=Object.values(e.childRecipes??{}).some(e=>e.length>0),a=Object.values(e.replaceRecipes??{}).some(e=>e.length>0),n=Object.values(e.fieldOptions??{}).some(e=>e.length>0),s=Object.keys(e.actions??{}).length>0,i=(e.deletableTypes?.length??0)>0||Object.values(e.writableFields??{}).some(e=>Object.keys(e).length>0)||t||a||s,o=t||a||n,h=[...t?["`childRecipes` is what can be added to it"]:[],...a?["`replaceRecipes` what it can be replaced with"]:[],...n?["`<field>Options` the values a field accepts"]:[]],r=["`selected`",...(e.navigationFields??[]).map(e=>`\`${e}\``)].join(", ");return[["Tools","- Put related operations in one call and select only the fields you need.",...i?[`- Use a mutation inside \`query\` to answer a what-if about a change ${o?"the lists under `meta` do not show":"before making it"}.`,"- Use `apply` only for what the user asked for."]:["- Nothing in this configurator can be changed through you. Say so when the user asks for a change."],"- When an operation fails, its `errors` say why and what to send instead."],...i?[["After a change","- A change is made only when the `apply` result has `committed: true`. Otherwise `errors` or `message` says what happened; without either, nothing changed. Never say a change was made when it was not.","- `sideEffects` names the major or unexpected things the configurator changed along with your change. Tell the user about them when committed; otherwise they describe what would happen. Smaller adjustments are not listed.","- A mutation returns the state after the change: use the ids and values it returned, not the ones you sent.",...s?["- When one mutation does the whole of what the user asked, use it instead of building the same change from several others."]:[]]]:[],...o?[["What can be done to an entity",`- \`meta\` lists what is possible right now: ${h.join(", ")}. Read the list before such a change and before telling the user what is available.`,`- You can select \`dryRun\` on ${[...t||a?["recipes"]:[],...n?["options"]:[]].join(" or ")} to look ahead and pick one that meets what the user asked for. It is optional before a change.`,"- Read the lists again after a change, unless their descriptions say they stay the same."]]:[],["The `[changes]` block","- Every user message starts with it: a glimpse of what the user did in the configurator since your last turn.",`- \`[changes: none]\`, or only ${r} lines: what you know still holds. Do not query it again.`,"- Other lines are a hint at what to read again: `A` added, `D` deleted, `M` modified with the fields. Text after `#` says what caused the line; `reset: undo/redo` says the user undid or redid changes.","- Read computed fields again when a listed change may affect them.","- `[changes: unavailable]` and `[changes: too many (n)]`: read again before relying on anything you read earlier.",...i?["- Your applied changes are not listed, except those waiting for user approval: they appear once approved."]:[]],["Reading the schema","- Take ids from results.",...(e.deletableTypes?.length??0)>0||a?["- The id of a deleted or replaced entity is gone and may later be given to another entity."]:[],`- A field whose name starts with \`_\` is computed: read it${i?", never write it":""}.`,"- Numbers are in the unit the field description names. Convert when the user uses another unit."],...e.lenses?.declarations?[["Built-in fragments","- These fragments are already defined for every operation. Spread one by name on a field of its type, as in `field { ...FragmentName }`, instead of listing its fields.","- A fragment is a starting selection: add the other fields you need next to the spread, by name from the schema.","- Never define a fragment with one of these names.","",e.lenses.declarations]]:[]].map(e=>e.join("\n")).join("\n\n")};
1
+ export const generateAssistantPrompt=e=>{let t=Object.values(e.childRecipes??{}).some(e=>e.length>0),a=Object.values(e.replaceRecipes??{}).some(e=>e.length>0),n=Object.values(e.fieldOptions??{}).some(e=>e.length>0),s=Object.keys(e.actions??{}).length>0,i=(e.deletableTypes?.length??0)>0||Object.values(e.writableFields??{}).some(e=>Object.keys(e).length>0)||t||a||s,o=t||a||n,r=[...t?["`childRecipes` is what can be added to it"]:[],...a?["`replaceRecipes` what it can be replaced with"]:[],...n?["`<field>Options` the values a field accepts"]:[]],h=["`selected`",...(e.navigationFields??[]).map(e=>`\`${e}\``)].join(", ");return[["Tools","- Put related operations in one call and select only the fields you need.",...i?[`- Use a mutation inside \`query\` to answer a what-if about a change ${o?"the lists under `meta` do not show":"before making it"}.`,"- Use `apply` only for what the user asked for."]:["- Nothing in this configurator can be changed through you. Say so when the user asks for a change."],"- When an operation fails, its `errors` say why and what to send instead."],...i?[["After a change","- A change is made only when the `apply` result has `committed: true`. Otherwise `errors` or `message` says what happened; without either, nothing changed. Never say a change was made when it was not.","- `sideEffects` names the major or unexpected things the configurator changed along with your change. Tell the user about them when committed; otherwise they describe what would happen. Smaller adjustments are not listed.","- A mutation returns the state after the change: use the ids and values it returned, not the ones you sent.",...s?["- When one mutation does the whole of what the user asked, use it instead of building the same change from several others."]:[]]]:[],...o?[["What can be done to an entity",`- \`meta\` lists what is possible right now: ${r.join(", ")}. Read the list before such a change and before telling the user what is available.`,`- You can select \`dryRun\` on ${[...t||a?["recipes"]:[],...n?["options"]:[]].join(" or ")} to look ahead and pick one that meets what the user asked for. It is optional before a change.`,"- Read the lists again after a change, unless their descriptions say they stay the same."]]:[],["The `[changes]` block","- Every user message starts with it: a glimpse of what the user did in the configurator since your last turn.",`- \`[changes: none]\`, or only ${h} lines: what you know still holds. Do not query it again.`,"- Other lines are a hint at what to read again: `A` added, `D` deleted, `M` modified with the fields. Text after `#` says what caused the line; `reset: undo/redo` says the user undid or redid changes.","- Read computed fields again when a listed change may affect them.","- `[changes: unavailable]` and `[changes: too many (n)]`: read again before relying on anything you read earlier.",...i?["- Your applied changes are not listed, except those waiting for user approval: they appear once approved."]:[]],["Reading the schema","- Take ids from results.",...(e.deletableTypes?.length??0)>0||a?["- The id of a deleted or replaced entity is gone and may later be given to another entity."]:[],`- A field whose name starts with \`_\` is computed: read it${i?", never write it":""}.`,"- Numbers are in the unit the field description names. Convert when the user uses another unit."],["Entity links","- When you name an entity the user may want to find, write it as a Markdown link whose target is `entity:` and its id: `[the corner cabinet](entity:<id>)`. The user sees only the text; the id is never shown.","- Link only entities that exist in the configuration now, never one created only inside `query`."],...e.lenses?.declarations?[["Built-in fragments","- These fragments are already defined for every operation. Spread one by name on a field of its type, as in `field { ...FragmentName }`, instead of listing its fields.","- A fragment is a starting selection: add the other fields you need next to the spread, by name from the schema.","- Never define a fragment with one of these names.","",e.lenses.declarations]]:[]].map(e=>e.join("\n")).join("\n\n")};
@@ -3,7 +3,7 @@ import type { ThemeOptions } from '@mui/material';
3
3
  import type { z } from 'zod';
4
4
  import type { FinalizeTaskResource } from '@salsita-ai/contracts/webhook';
5
5
  import { type $DomainEntity, type DomainEntity, type DomainFactory, type EnumLike, type ProductPreset, type SchemaOfObject } from '../core/index.js';
6
- import { type ProjectModule } from '../domain-runtime/index.js';
6
+ import { type ElementRegistration, type ProjectModule } from '../domain-runtime/index.js';
7
7
  import type { AclConfig, ApplicationConfig, DataSpec, DefaultEnvs, ResourcesConfig, SpecTransformer, TransformersConfig, UserInterfaceConfig } from './application-config.js';
8
8
  import { type AssistantResolvedManifest } from './assistant/index.js';
9
9
  interface ConfiguratorBuilderContext<ENTITIES extends DomainEntity<string> = never, ALLOWED_ROOT_ENTITIES extends ENTITIES = never, $MAP extends Record<ENTITIES['type'], $DomainEntity<ENTITIES>> = never, NAVIGATION_STATES extends string = never, VIEW_STATES extends string = never, TOOL_STATES extends string = never, EXPORT_STATES extends string = never, PUBLISHED_DATA extends Record<string, unknown> = never, SESSION_DATA extends Record<string, unknown> = never, FRONTEND_DATA extends Record<string, unknown> = never, ADMIN_ENTITIES extends DomainEntity<string> = never, ADMIN_ALLOWED_ROOT_ENTITIES extends ADMIN_ENTITIES = never, ADMIN_$MAP extends Record<ADMIN_ENTITIES['type'], $DomainEntity<ADMIN_ENTITIES>> = never, ADMIN_NAVIGATION_STATES extends string = never, ADMIN_VIEW_STATES extends string = never, FINALIZE_DATA extends Record<string, unknown> = never, PREFETCHED_FINALIZE_DATA extends Record<string, unknown> = never, FINALIZE_RESULT extends Record<string, unknown> = never, CALLBACK_DATA extends Record<string, unknown> = never, RESOURCE extends string = never> {
@@ -44,6 +44,7 @@ interface ConfiguratorBuilderContext<ENTITIES extends DomainEntity<string> = nev
44
44
  tagName?: string;
45
45
  handlers?: readonly ProjectModule[];
46
46
  elements?: readonly ProjectModule[];
47
+ defaultElements?: readonly ElementRegistration[];
47
48
  }
48
49
  export declare class ConfiguratorBuilder<ENTITIES extends DomainEntity<string> = never, ALLOWED_ROOT_ENTITIES extends ENTITIES = never, $MAP extends Record<ENTITIES['type'], $DomainEntity<ENTITIES>> = never, NAVIGATION_STATES extends string = never, VIEW_STATES extends string = never, TOOL_STATES extends string = never, EXPORT_STATES extends string = never, PUBLISHED_DATA extends Record<string, unknown> = never, SESSION_DATA extends Record<string, unknown> = never, FRONTEND_DATA extends Record<string, unknown> = never, ADMIN_ENTITIES extends DomainEntity<string> = never, ADMIN_ALLOWED_ROOT_ENTITIES extends ADMIN_ENTITIES = never, ADMIN_$MAP extends Record<ADMIN_ENTITIES['type'], $DomainEntity<ADMIN_ENTITIES>> = never, ADMIN_NAVIGATION_STATES extends string = never, ADMIN_VIEW_STATES extends string = never, FINALIZE_DATA extends Record<string, unknown> = never, PREFETCHED_FINALIZE_DATA extends Record<string, unknown> = never, FINALIZE_RESULT extends Record<string, unknown> = never, CALLBACK_DATA extends Record<string, unknown> = never, RESOURCE extends string = never> {
49
50
  private readonly _context;
@@ -87,6 +88,8 @@ export declare class ConfiguratorBuilder<ENTITIES extends DomainEntity<string> =
87
88
  withHandlers(handlers: readonly ProjectModule[]): ConfiguratorBuilder<ENTITIES, ALLOWED_ROOT_ENTITIES, $MAP, NAVIGATION_STATES, VIEW_STATES, TOOL_STATES, EXPORT_STATES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ADMIN_ENTITIES, ADMIN_ALLOWED_ROOT_ENTITIES, ADMIN_$MAP, ADMIN_NAVIGATION_STATES, ADMIN_VIEW_STATES, FINALIZE_DATA, PREFETCHED_FINALIZE_DATA, FINALIZE_RESULT, CALLBACK_DATA, RESOURCE>;
88
89
  /** Sets the elements as project modules, one per `src/elements/` file, for the runtime spec to validate. */
89
90
  withElements(elements: readonly ProjectModule[]): ConfiguratorBuilder<ENTITIES, ALLOWED_ROOT_ENTITIES, $MAP, NAVIGATION_STATES, VIEW_STATES, TOOL_STATES, EXPORT_STATES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ADMIN_ENTITIES, ADMIN_ALLOWED_ROOT_ENTITIES, ADMIN_$MAP, ADMIN_NAVIGATION_STATES, ADMIN_VIEW_STATES, FINALIZE_DATA, PREFETCHED_FINALIZE_DATA, FINALIZE_RESULT, CALLBACK_DATA, RESOURCE>;
91
+ /** Sets the SDK's default element registrations; a project element with the same name replaces one. */
92
+ withDefaultElements(defaultElements: readonly ElementRegistration[]): ConfiguratorBuilder<ENTITIES, ALLOWED_ROOT_ENTITIES, $MAP, NAVIGATION_STATES, VIEW_STATES, TOOL_STATES, EXPORT_STATES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ADMIN_ENTITIES, ADMIN_ALLOWED_ROOT_ENTITIES, ADMIN_$MAP, ADMIN_NAVIGATION_STATES, ADMIN_VIEW_STATES, FINALIZE_DATA, PREFETCHED_FINALIZE_DATA, FINALIZE_RESULT, CALLBACK_DATA, RESOURCE>;
90
93
  withResources<NEW_RESOURCE extends string>(resources: ReadonlyArray<FinalizeTaskResource<NEW_RESOURCE>>): ConfiguratorBuilder<ENTITIES, ALLOWED_ROOT_ENTITIES, $MAP, NAVIGATION_STATES, VIEW_STATES, TOOL_STATES, EXPORT_STATES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ADMIN_ENTITIES, ADMIN_ALLOWED_ROOT_ENTITIES, ADMIN_$MAP, ADMIN_NAVIGATION_STATES, ADMIN_VIEW_STATES, FINALIZE_DATA, PREFETCHED_FINALIZE_DATA, FINALIZE_RESULT, CALLBACK_DATA, NEW_RESOURCE>;
91
94
  withWebComponentTag(tagName: string): ConfiguratorBuilder<ENTITIES, ALLOWED_ROOT_ENTITIES, $MAP, NAVIGATION_STATES, VIEW_STATES, TOOL_STATES, EXPORT_STATES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ADMIN_ENTITIES, ADMIN_ALLOWED_ROOT_ENTITIES, ADMIN_$MAP, ADMIN_NAVIGATION_STATES, ADMIN_VIEW_STATES, FINALIZE_DATA, PREFETCHED_FINALIZE_DATA, FINALIZE_RESULT, CALLBACK_DATA, RESOURCE>;
92
95
  /**
@@ -1 +1 @@
1
- import{initConsoleLogger as t}from"@salsita-ai/common/utils";import{defaultI18n as e}from"#package/i18n";import{extendedSchemaValidator as i}from"../core/index.js";import{NoopAnalyticsSystem as r}from"../domain-context/index.js";import{createDomainRuntime as n}from"../domain-runtime/index.js";import{isGetApplicationWrapperHandler as o}from"./GetApplicationWrapperHandler.js";import{isGetWebComponentOptionsHandler as a}from"./GetWebComponentOptions.js";import{isAssistantSetupHandler as s}from"./assistant/index.js";import{createInitialPublishedData as l}from"./create-initial-published-data.js";import{isDataRowValidatorHandler as h}from"./published-data/DataRowValidatorHandler.js";import{isFilterPublishedChunksHandler as u}from"./published-data/FilterPublishedChunksHandler.js";import{isMapPublishedChunkedDataHandler as d}from"./published-data/MapPublishedChunkedDataHandler.js";import{isMapPublishedRevisionDataHandler as c}from"./published-data/MapPublishedRevisionDataHandler.js";import{isSheetValidatorHandler as f}from"./published-data/SheetValidatorHandler.js";export class ConfiguratorBuilder{_context;constructor(t){this._context=t}withDefaultEnvs(t){return new ConfiguratorBuilder({...this._context,defaultEnvs:t})}withVersion(t){return new ConfiguratorBuilder({...this._context,version:t})}withTextLanguages(t){return new ConfiguratorBuilder({...this._context,textLanguages:t})}withAcl(t){return new ConfiguratorBuilder({...this._context,acl:t})}withAdminRelease(t){return new ConfiguratorBuilder({...this._context,enableAdminRelease:t})}withUi(t){return new ConfiguratorBuilder({...this._context,ui:t})}withResourcesConfig(t){return new ConfiguratorBuilder({...this._context,resourcesConfig:t})}withChunks(t){return new ConfiguratorBuilder({...this._context,chunks:t})}withPublishedDataHash(t){return new ConfiguratorBuilder({...this._context,publishedDataHash:t})}withAssistant(t){return new ConfiguratorBuilder({...this._context,assistant:t})}withTheme(t){return new ConfiguratorBuilder({...this._context,theme:t})}withDomainFactory(t){return new ConfiguratorBuilder({...this._context,domainFactory:t})}withAdminDomainFactory(t){return new ConfiguratorBuilder({...this._context,adminDomainFactory:t})}withI18n=t=>new ConfiguratorBuilder({...this._context,i18n:t});withPrefetchedFinalizeData(t){return new ConfiguratorBuilder({...this._context,prefetchedFinalizeData:t})}withFinalizeData(t){return new ConfiguratorBuilder({...this._context,finalizeData:t})}withFinalizeResult(t){return new ConfiguratorBuilder({...this._context,finalizeResult:t})}withCallbackData(t){return new ConfiguratorBuilder({...this._context,callbackData:t})}withNavigationState(t){return new ConfiguratorBuilder({...this._context,navigationState:t})}withViewState(t){return new ConfiguratorBuilder({...this._context,viewState:t})}withToolState(t){return new ConfiguratorBuilder({...this._context,toolState:t})}withExportState(t){return new ConfiguratorBuilder({...this._context,exportState:t})}withAdminNavigationState(t){return new ConfiguratorBuilder({...this._context,adminNavigationState:t})}withAdminViewState(t){return new ConfiguratorBuilder({...this._context,adminViewState:t})}withPresets(t){return new ConfiguratorBuilder({...this._context,presets:t})}withAdminPresets(t){return new ConfiguratorBuilder({...this._context,adminPresets:t})}withComponentOptics(t){return new ConfiguratorBuilder({...this._context,componentOptics:[...this._context.componentOptics,...t]})}withAdminComponentOptics(t){return new ConfiguratorBuilder({...this._context,adminComponentOptics:[...this._context.adminComponentOptics??[],...t]})}withHandlers(t){return new ConfiguratorBuilder({...this._context,handlers:t})}withElements(t){return new ConfiguratorBuilder({...this._context,elements:t})}withResources(t){return new ConfiguratorBuilder({...this._context,resources:t})}withWebComponentTag(t){return new ConfiguratorBuilder({...this._context,tagName:t})}withTransformers(t,e){return new ConfiguratorBuilder({...this._context,transformers:{importedTransformers:t,specTransformers:e}})}withInterface(t){return this}withDataSpec=t=>new ConfiguratorBuilder({...this._context,dataSpec:t});_computeInitialPublishedData(t,e,i){if(!this._context.adminDomainFactory)throw Error("adminDomainFactory is required!");return l({adminDomainFactory:this._context.adminDomainFactory,domainRuntime:e,adminPresets:this._context.adminPresets??[],handlers:i,dataSpec:this._context.dataSpec,chunks:this._context.chunks,logger:t})}buildConfig(){return this._buildConfigWithHandlers().config}_buildConfigWithHandlers(){if(!this._context.domainFactory)throw Error("Can not create application config, domainFactory is required! Is it registered with the ConfiguratorBuilder?");if(!this._context.presets)throw Error("Can not create application config, presets are required! Is it registered with the ConfiguratorBuilder?");if(!this._context.adminDomainFactory)throw Error("Can not create application config, adminDomainFactory is required! Is it registered with the ConfiguratorBuilder?");if(!this._context.adminPresets)throw Error("Can not create application config, adminPresets are required! Is it registered with the ConfiguratorBuilder?");if(!this._context.version)throw Error("Can not create application config, version is required!");let i=this._context.tagName??"salsita-configurator",l={defaultEnvs:this._context.defaultEnvs,services:{i18n:this._context.i18n},version:this._context.version,initialPublishedData:{},domain:{textLanguages:this._context.textLanguages,componentOptics:this._context.componentOptics,presets:this._context.presets,domainFactory:this._context.domainFactory},navigation:{navigationStates:this._context.navigationState?.values(),viewStates:this._context.viewState?.values(),toolStates:this._context.toolState?.values(),exportStates:this._context.exportState?.values()},adminNavigation:{navigationStates:this._context.adminNavigationState?.values(),viewStates:this._context.adminViewState?.values()},adminDomain:{textLanguages:this._context.textLanguages,componentOptics:this._context.adminComponentOptics??[],presets:this._context.adminPresets,domainFactory:this._context.adminDomainFactory},mount:{tag:i,options:{}},handlers:this._context.handlers??[],elements:this._context.elements??[],transformers:this._context.transformers,features:{acl:this._context.acl,enableAdminRelease:this._context.enableAdminRelease},ui:{preview:this._context.ui?.preview,alwaysExpand:this._context.ui?.alwaysExpand,theme:this._context.theme},resources:this._context.resourcesConfig,chunks:this._context.chunks,publishedDataHash:this._context.publishedDataHash,assistant:this._context.assistant,dataSpec:this._context.dataSpec},d=t(),c=n({config:l,services:{analyticsService:new r,i18n:e,logger:d}}),m=c.getState().spec.configurator.handlers;if(m.filter(s).length>1)throw Error("Multiple createAssistantSetupHandler handlers found. Only one handler is allowed.");if(m.filter(t=>u(t)).length>1)throw Error("Multiple createFilterPublishedChunksHandler handlers found. Only one handler is allowed.");if(m.filter(t=>h(t)).length>1)throw Error("Multiple createDataRowValidatorHandler handlers found. Only one handler is allowed.");if(m.filter(t=>f(t)).length>1)throw Error("Multiple createSheetValidatorHandler handlers found. Only one handler is allowed.");let w=m.find(o)?.handler().handler,x=m.find(a)?.handler().handler(void 0),p=this._computeInitialPublishedData(d,c,m);return{config:{...l,mount:{tag:i,options:x??{},Application:w},initialPublishedData:p},handlers:m}}buildWebhookContext(){if(!this._context.domainFactory)throw Error("domainFactory is required!");if(!this._context.adminDomainFactory)throw Error("adminDomainFactory is required!");if(!this._context.adminPresets)throw Error("adminPresets are required!");let{config:t,handlers:e}=this._buildConfigWithHandlers(),r=t=>{if(null==this._context.finalizeData)return{};let e=i.compile(this._context.finalizeData);if(!e(t))throw console.error("Finalize data validation errors:",e.errors),Error("Invalid finalize data!");return t},n=t=>{if(null==this._context.finalizeResult)return{};let e=i.compile(this._context.finalizeResult);if(!e(t))throw console.error("Finalize result validation errors:",e.errors),Error("Invalid finalize result!");return t},o=t=>{if(null==this._context.callbackData)return{};let e=i.compile(this._context.callbackData);if(!e(t))throw console.error("Callback data validation errors:",e.errors),Error("Invalid callback data!");return t},a=e.find(c)?.handler().handler,s=e.find(d)?.handler().handler,l=e.find(h)?.handler().handler,u=e.find(f)?.handler().handler;return{config:t,parseFinalizeData:r,parseFinalizeResult:n,resources:this._context.resources??[],parseCallbackData:o,mapPublishedRevisionData:a,mapPublishedChunkedData:s,dataRowValidator:l,sheetValidator:u}}}
1
+ import{initConsoleLogger as t}from"@salsita-ai/common/utils";import{defaultI18n as e}from"#package/i18n";import{extendedSchemaValidator as i}from"../core/index.js";import{NoopAnalyticsSystem as r}from"../domain-context/index.js";import{createDomainRuntime as n}from"../domain-runtime/index.js";import{isGetApplicationWrapperHandler as o}from"./GetApplicationWrapperHandler.js";import{isGetWebComponentOptionsHandler as a}from"./GetWebComponentOptions.js";import{isAssistantSetupHandler as s}from"./assistant/index.js";import{createInitialPublishedData as l}from"./create-initial-published-data.js";import{isDataRowValidatorHandler as h}from"./published-data/DataRowValidatorHandler.js";import{isFilterPublishedChunksHandler as u}from"./published-data/FilterPublishedChunksHandler.js";import{isMapPublishedChunkedDataHandler as d}from"./published-data/MapPublishedChunkedDataHandler.js";import{isMapPublishedRevisionDataHandler as c}from"./published-data/MapPublishedRevisionDataHandler.js";import{isSheetValidatorHandler as f}from"./published-data/SheetValidatorHandler.js";export class ConfiguratorBuilder{_context;constructor(t){this._context=t}withDefaultEnvs(t){return new ConfiguratorBuilder({...this._context,defaultEnvs:t})}withVersion(t){return new ConfiguratorBuilder({...this._context,version:t})}withTextLanguages(t){return new ConfiguratorBuilder({...this._context,textLanguages:t})}withAcl(t){return new ConfiguratorBuilder({...this._context,acl:t})}withAdminRelease(t){return new ConfiguratorBuilder({...this._context,enableAdminRelease:t})}withUi(t){return new ConfiguratorBuilder({...this._context,ui:t})}withResourcesConfig(t){return new ConfiguratorBuilder({...this._context,resourcesConfig:t})}withChunks(t){return new ConfiguratorBuilder({...this._context,chunks:t})}withPublishedDataHash(t){return new ConfiguratorBuilder({...this._context,publishedDataHash:t})}withAssistant(t){return new ConfiguratorBuilder({...this._context,assistant:t})}withTheme(t){return new ConfiguratorBuilder({...this._context,theme:t})}withDomainFactory(t){return new ConfiguratorBuilder({...this._context,domainFactory:t})}withAdminDomainFactory(t){return new ConfiguratorBuilder({...this._context,adminDomainFactory:t})}withI18n=t=>new ConfiguratorBuilder({...this._context,i18n:t});withPrefetchedFinalizeData(t){return new ConfiguratorBuilder({...this._context,prefetchedFinalizeData:t})}withFinalizeData(t){return new ConfiguratorBuilder({...this._context,finalizeData:t})}withFinalizeResult(t){return new ConfiguratorBuilder({...this._context,finalizeResult:t})}withCallbackData(t){return new ConfiguratorBuilder({...this._context,callbackData:t})}withNavigationState(t){return new ConfiguratorBuilder({...this._context,navigationState:t})}withViewState(t){return new ConfiguratorBuilder({...this._context,viewState:t})}withToolState(t){return new ConfiguratorBuilder({...this._context,toolState:t})}withExportState(t){return new ConfiguratorBuilder({...this._context,exportState:t})}withAdminNavigationState(t){return new ConfiguratorBuilder({...this._context,adminNavigationState:t})}withAdminViewState(t){return new ConfiguratorBuilder({...this._context,adminViewState:t})}withPresets(t){return new ConfiguratorBuilder({...this._context,presets:t})}withAdminPresets(t){return new ConfiguratorBuilder({...this._context,adminPresets:t})}withComponentOptics(t){return new ConfiguratorBuilder({...this._context,componentOptics:[...this._context.componentOptics,...t]})}withAdminComponentOptics(t){return new ConfiguratorBuilder({...this._context,adminComponentOptics:[...this._context.adminComponentOptics??[],...t]})}withHandlers(t){return new ConfiguratorBuilder({...this._context,handlers:t})}withElements(t){return new ConfiguratorBuilder({...this._context,elements:t})}withDefaultElements(t){return new ConfiguratorBuilder({...this._context,defaultElements:t})}withResources(t){return new ConfiguratorBuilder({...this._context,resources:t})}withWebComponentTag(t){return new ConfiguratorBuilder({...this._context,tagName:t})}withTransformers(t,e){return new ConfiguratorBuilder({...this._context,transformers:{importedTransformers:t,specTransformers:e}})}withInterface(t){return this}withDataSpec=t=>new ConfiguratorBuilder({...this._context,dataSpec:t});_computeInitialPublishedData(t,e,i){if(!this._context.adminDomainFactory)throw Error("adminDomainFactory is required!");return l({adminDomainFactory:this._context.adminDomainFactory,domainRuntime:e,adminPresets:this._context.adminPresets??[],handlers:i,dataSpec:this._context.dataSpec,chunks:this._context.chunks,logger:t})}buildConfig(){return this._buildConfigWithHandlers().config}_buildConfigWithHandlers(){if(!this._context.domainFactory)throw Error("Can not create application config, domainFactory is required! Is it registered with the ConfiguratorBuilder?");if(!this._context.presets)throw Error("Can not create application config, presets are required! Is it registered with the ConfiguratorBuilder?");if(!this._context.adminDomainFactory)throw Error("Can not create application config, adminDomainFactory is required! Is it registered with the ConfiguratorBuilder?");if(!this._context.adminPresets)throw Error("Can not create application config, adminPresets are required! Is it registered with the ConfiguratorBuilder?");if(!this._context.version)throw Error("Can not create application config, version is required!");let i=this._context.tagName??"salsita-configurator",l={defaultEnvs:this._context.defaultEnvs,services:{i18n:this._context.i18n},version:this._context.version,initialPublishedData:{},domain:{textLanguages:this._context.textLanguages,componentOptics:this._context.componentOptics,presets:this._context.presets,domainFactory:this._context.domainFactory},navigation:{navigationStates:this._context.navigationState?.values(),viewStates:this._context.viewState?.values(),toolStates:this._context.toolState?.values(),exportStates:this._context.exportState?.values()},adminNavigation:{navigationStates:this._context.adminNavigationState?.values(),viewStates:this._context.adminViewState?.values()},adminDomain:{textLanguages:this._context.textLanguages,componentOptics:this._context.adminComponentOptics??[],presets:this._context.adminPresets,domainFactory:this._context.adminDomainFactory},mount:{tag:i,options:{}},handlers:this._context.handlers??[],elements:this._context.elements??[],defaultElements:this._context.defaultElements??[],transformers:this._context.transformers,features:{acl:this._context.acl,enableAdminRelease:this._context.enableAdminRelease},ui:{preview:this._context.ui?.preview,alwaysExpand:this._context.ui?.alwaysExpand,theme:this._context.theme},resources:this._context.resourcesConfig,chunks:this._context.chunks,publishedDataHash:this._context.publishedDataHash,assistant:this._context.assistant,dataSpec:this._context.dataSpec},d=t(),c=n({config:l,services:{analyticsService:new r,i18n:e,logger:d}}),m=c.getState().spec.configurator.handlers;if(m.filter(s).length>1)throw Error("Multiple createAssistantSetupHandler handlers found. Only one handler is allowed.");if(m.filter(t=>u(t)).length>1)throw Error("Multiple createFilterPublishedChunksHandler handlers found. Only one handler is allowed.");if(m.filter(t=>h(t)).length>1)throw Error("Multiple createDataRowValidatorHandler handlers found. Only one handler is allowed.");if(m.filter(t=>f(t)).length>1)throw Error("Multiple createSheetValidatorHandler handlers found. Only one handler is allowed.");let w=m.find(o)?.handler().handler,x=m.find(a)?.handler().handler(void 0),_=this._computeInitialPublishedData(d,c,m);return{config:{...l,mount:{tag:i,options:x??{},Application:w},initialPublishedData:_},handlers:m}}buildWebhookContext(){if(!this._context.domainFactory)throw Error("domainFactory is required!");if(!this._context.adminDomainFactory)throw Error("adminDomainFactory is required!");if(!this._context.adminPresets)throw Error("adminPresets are required!");let{config:t,handlers:e}=this._buildConfigWithHandlers(),r=t=>{if(null==this._context.finalizeData)return{};let e=i.compile(this._context.finalizeData);if(!e(t))throw console.error("Finalize data validation errors:",e.errors),Error("Invalid finalize data!");return t},n=t=>{if(null==this._context.finalizeResult)return{};let e=i.compile(this._context.finalizeResult);if(!e(t))throw console.error("Finalize result validation errors:",e.errors),Error("Invalid finalize result!");return t},o=t=>{if(null==this._context.callbackData)return{};let e=i.compile(this._context.callbackData);if(!e(t))throw console.error("Callback data validation errors:",e.errors),Error("Invalid callback data!");return t},a=e.find(c)?.handler().handler,s=e.find(d)?.handler().handler,l=e.find(h)?.handler().handler,u=e.find(f)?.handler().handler;return{config:t,parseFinalizeData:r,parseFinalizeResult:n,resources:this._context.resources??[],parseCallbackData:o,mapPublishedRevisionData:a,mapPublishedChunkedData:s,dataRowValidator:l,sheetValidator:u}}}