@salsita-ai/sdk 0.50.0-develop.b5468d6828 → 0.50.0-develop.bb1eefaada

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 (411) hide show
  1. package/README.md +8 -4
  2. package/dist/admin/default-admin-elements.d.ts +9 -0
  3. package/dist/admin/default-admin-elements.js +1 -0
  4. package/dist/admin/default-elements/built-in-entity-element.d.ts +10 -0
  5. package/dist/admin/default-elements/built-in-entity-element.js +1 -0
  6. package/dist/admin/default-elements/built-in-layout-element.d.ts +10 -0
  7. package/dist/admin/default-elements/built-in-layout-element.js +1 -0
  8. package/dist/admin/default-elements/index.d.ts +2 -0
  9. package/dist/admin/default-elements/index.js +1 -0
  10. package/dist/admin/index.d.ts +1 -0
  11. package/dist/admin/index.js +1 -1
  12. package/dist/application-spec/caching/content-diff.js +1 -1
  13. package/dist/application-spec/core/application-file.d.ts +0 -2
  14. package/dist/application-spec/core/application-file.js +1 -1
  15. package/dist/application-spec/errors/diagnostic-codes.d.ts +5 -0
  16. package/dist/application-spec/errors/diagnostic-codes.js +1 -1
  17. package/dist/application-spec/errors/diagnostic-messages.d.ts +5 -0
  18. package/dist/application-spec/errors/diagnostic-messages.js +1 -1
  19. package/dist/application-spec/generate-application/code/common/code-imports.js +1 -1
  20. package/dist/application-spec/generate-application/code/common/env-reader.js +2 -2
  21. package/dist/application-spec/generate-application/code/common/index.d.ts +1 -0
  22. package/dist/application-spec/generate-application/code/common/index.js +1 -1
  23. package/dist/application-spec/generate-application/code/common/single-quoted-string.d.ts +6 -0
  24. package/dist/application-spec/generate-application/code/common/single-quoted-string.js +1 -0
  25. package/dist/application-spec/generate-application/code/domain-runtime-files.js +1 -1
  26. package/dist/application-spec/generate-application/code/project-scaffolding.d.ts +10 -14
  27. package/dist/application-spec/generate-application/code/project-scaffolding.js +2 -2
  28. package/dist/application-spec/generate-application/code/templates/admin-config.js +3 -0
  29. package/dist/application-spec/generate-application/code/templates/common/format-property-key.d.ts +7 -0
  30. package/dist/application-spec/generate-application/code/templates/common/format-property-key.js +1 -0
  31. package/dist/application-spec/generate-application/code/templates/common/schema-to-type-string.js +3 -3
  32. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-component-optics.d.ts +1 -1
  33. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-component-optics.js +6 -6
  34. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-presets.js +1 -1
  35. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-resources.js +13 -13
  36. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-states.d.ts +1 -1
  37. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-states.js +2 -2
  38. package/dist/application-spec/generate-application/code/templates/eslint-config.d.ts +5 -0
  39. package/dist/application-spec/generate-application/code/templates/eslint-config.js +4 -5
  40. package/dist/application-spec/generate-application/code/templates/gitignore.js +1 -3
  41. package/dist/application-spec/generate-application/code/templates/globals.js +7 -4
  42. package/dist/application-spec/generate-application/code/templates/index.d.ts +2 -2
  43. package/dist/application-spec/generate-application/code/templates/index.js +1 -1
  44. package/dist/application-spec/generate-application/code/templates/lingui-rc.d.ts +5 -0
  45. package/dist/application-spec/generate-application/code/templates/lingui-rc.js +4 -4
  46. package/dist/application-spec/generate-application/code/templates/prettier-config.d.ts +5 -0
  47. package/dist/application-spec/generate-application/code/templates/prettier-config.js +4 -5
  48. package/dist/application-spec/generate-application/code/templates/skills/phoenix-cli-skill.js +1 -1
  49. package/dist/application-spec/generate-application/code/templates/skills/phoenix-create-configurator-skill.js +1 -1
  50. package/dist/application-spec/generate-application/code/templates/skills/phoenix-feedback-skill.js +5 -5
  51. package/dist/application-spec/generate-application/code/templates/skills/phoenix-review-skill.js +3 -3
  52. package/dist/application-spec/generate-application/code/templates/skills/phoenix-skill.js +1 -1
  53. package/dist/application-spec/generate-application/code/templates/skills/phoenix-variants-skill.js +2 -2
  54. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.d.ts +13 -2
  55. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.js +2 -2
  56. package/dist/application-spec/generate-application/code/templates/spec-code/collect-spec-code.d.ts +58 -0
  57. package/dist/application-spec/generate-application/code/templates/spec-code/collect-spec-code.js +1 -0
  58. package/dist/application-spec/generate-application/code/templates/spec-code/index.d.ts +2 -0
  59. package/dist/application-spec/generate-application/code/templates/spec-code/index.js +1 -0
  60. package/dist/application-spec/generate-application/code/templates/spec-code/spec-code.d.ts +18 -0
  61. package/dist/application-spec/generate-application/code/templates/spec-code/spec-code.js +41 -0
  62. package/dist/application-spec/generate-application/code/templates/spec-messages/index.d.ts +1 -0
  63. package/dist/application-spec/generate-application/code/templates/spec-messages/index.js +1 -0
  64. package/dist/application-spec/generate-application/code/templates/spec-messages/spec-messages.d.ts +20 -0
  65. package/dist/application-spec/generate-application/code/templates/spec-messages/spec-messages.js +6 -0
  66. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-model-runtime.d.ts +6 -4
  67. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-model-runtime.js +1 -1
  68. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-runtime.d.ts +3 -2
  69. package/dist/application-spec/generate-application/runtime/admin-runtime/admin-runtime.js +1 -1
  70. package/dist/application-spec/generate-application/runtime/admin-runtime/states-runtime.d.ts +2 -2
  71. package/dist/application-spec/generate-application/runtime/application-runtime.d.ts +13 -6
  72. package/dist/application-spec/generate-application/runtime/application-runtime.js +1 -1
  73. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-model-runtime.d.ts +6 -4
  74. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-model-runtime.js +1 -1
  75. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-runtime.d.ts +3 -2
  76. package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-runtime.js +1 -1
  77. package/dist/application-spec/generate-application/runtime/configurator-runtime/states-runtime.d.ts +2 -2
  78. package/dist/application-spec/generate-application/runtime/migrations/migration-runtime.d.ts +2 -2
  79. package/dist/application-spec/generate-application/runtime/sections/assistant-runtime.d.ts +2 -2
  80. package/dist/application-spec/generate-application/runtime/sections/build-sdk-optic.d.ts +2 -1
  81. package/dist/application-spec/generate-application/runtime/sections/build-sdk-optic.js +1 -1
  82. package/dist/application-spec/generate-application/runtime/sections/build-user-bound-optic.d.ts +2 -1
  83. package/dist/application-spec/generate-application/runtime/sections/build-user-bound-optic.js +1 -1
  84. package/dist/application-spec/generate-application/runtime/sections/component-optic.d.ts +3 -0
  85. package/dist/application-spec/generate-application/runtime/sections/component-optic.js +1 -1
  86. package/dist/application-spec/generate-application/runtime/sections/data-runtime.d.ts +4 -4
  87. package/dist/application-spec/generate-application/runtime/sections/expression-runtime.d.ts +7 -4
  88. package/dist/application-spec/generate-application/runtime/sections/expression-runtime.js +1 -1
  89. package/dist/application-spec/generate-application/runtime/sections/generate-memo-eval-plan-runtime.d.ts +9 -5
  90. package/dist/application-spec/generate-application/runtime/sections/generate-memo-eval-plan-runtime.js +1 -1
  91. package/dist/application-spec/generate-application/runtime/sections/reflection-constants-runtime.d.ts +3 -1
  92. package/dist/application-spec/generate-application/runtime/sections/reflection-constants-runtime.js +1 -1
  93. package/dist/application-spec/generate-application/runtime/sections/theme-runtime.d.ts +2 -2
  94. package/dist/application-spec/generate-application/runtime/sections/transformers-runtime.d.ts +3 -3
  95. package/dist/application-spec/generate-application/runtime/spec-code/index.d.ts +2 -0
  96. package/dist/application-spec/generate-application/runtime/spec-code/index.js +1 -0
  97. package/dist/application-spec/generate-application/runtime/spec-code/resolve-spec-code.d.ts +18 -0
  98. package/dist/application-spec/generate-application/runtime/spec-code/resolve-spec-code.js +1 -0
  99. package/dist/application-spec/generate-application/runtime/spec-code/spec-code-module.d.ts +17 -0
  100. package/dist/application-spec/generate-application/runtime/spec-code/spec-code-module.js +1 -0
  101. package/dist/application-spec/generate-application/runtime-spec/decode-runtime-spec.d.ts +9 -0
  102. package/dist/application-spec/generate-application/runtime-spec/decode-runtime-spec.js +1 -0
  103. package/dist/application-spec/generate-application/runtime-spec/encode-runtime-spec.d.ts +8 -0
  104. package/dist/application-spec/generate-application/runtime-spec/encode-runtime-spec.js +1 -0
  105. package/dist/application-spec/generate-application/runtime-spec/encoded-runtime-spec.d.ts +27 -0
  106. package/dist/application-spec/generate-application/runtime-spec/encoded-runtime-spec.js +1 -0
  107. package/dist/application-spec/generate-application/runtime-spec/index.d.ts +5 -0
  108. package/dist/application-spec/generate-application/runtime-spec/index.js +1 -0
  109. package/dist/application-spec/generate-application/runtime-spec/runtime-spec.d.ts +68 -0
  110. package/dist/application-spec/generate-application/runtime-spec/runtime-spec.js +1 -0
  111. package/dist/application-spec/generate-application/runtime-spec/spec-code-id.d.ts +40 -0
  112. package/dist/application-spec/generate-application/runtime-spec/spec-code-id.js +1 -0
  113. package/dist/application-spec/parse-application-files/categorize/categorize-files.d.ts +18 -0
  114. package/dist/application-spec/parse-application-files/categorize/categorize-files.js +1 -1
  115. package/dist/application-spec/parse-application-files/categorize/earlier-generated-editor-configs.d.ts +16 -0
  116. package/dist/application-spec/parse-application-files/categorize/earlier-generated-editor-configs.js +9 -0
  117. package/dist/application-spec/parse-application-files/raw-spec/parse-yaml-spec-file.js +1 -1
  118. package/dist/application-spec/parse-application-files/spec/application/admin-spec/admin-spec.js +1 -1
  119. package/dist/application-spec/parse-application-files/spec/application/configurator-spec/configurator-spec.js +1 -1
  120. package/dist/application-spec/parse-application-files/spec/common/index.d.ts +1 -0
  121. package/dist/application-spec/parse-application-files/spec/common/index.js +1 -1
  122. package/dist/application-spec/parse-application-files/spec/common/value-type/format-value-type.d.ts +3 -0
  123. package/dist/application-spec/parse-application-files/spec/common/value-type/format-value-type.js +1 -0
  124. package/dist/application-spec/parse-application-files/spec/common/value-type/index.d.ts +5 -0
  125. package/dist/application-spec/parse-application-files/spec/common/value-type/index.js +1 -0
  126. package/dist/application-spec/parse-application-files/spec/common/value-type/intersect-value-types.d.ts +6 -0
  127. package/dist/application-spec/parse-application-files/spec/common/value-type/intersect-value-types.js +1 -0
  128. package/dist/application-spec/parse-application-files/spec/common/value-type/is-assignable-value-type.d.ts +8 -0
  129. package/dist/application-spec/parse-application-files/spec/common/value-type/is-assignable-value-type.js +1 -0
  130. package/dist/application-spec/parse-application-files/spec/common/value-type/value-type-at.d.ts +10 -0
  131. package/dist/application-spec/parse-application-files/spec/common/value-type/value-type-at.js +1 -0
  132. package/dist/application-spec/parse-application-files/spec/common/value-type/value-type.d.ts +98 -0
  133. package/dist/application-spec/parse-application-files/spec/common/value-type/value-type.js +1 -0
  134. package/dist/application-spec/parse-application-files/spec/components/bindings/component-path.d.ts +13 -0
  135. package/dist/application-spec/parse-application-files/spec/components/bindings/component-path.js +1 -0
  136. package/dist/application-spec/parse-application-files/spec/components/bindings/index.d.ts +2 -0
  137. package/dist/application-spec/parse-application-files/spec/components/bindings/index.js +1 -1
  138. package/dist/application-spec/parse-application-files/spec/components/bindings/read-binding-type.d.ts +24 -0
  139. package/dist/application-spec/parse-application-files/spec/components/bindings/read-binding-type.js +1 -0
  140. package/dist/application-spec/parse-application-files/spec/components/component-state-type.d.ts +8 -0
  141. package/dist/application-spec/parse-application-files/spec/components/component-state-type.js +1 -0
  142. package/dist/application-spec/parse-application-files/spec/components/filter-criterion-types.d.ts +13 -0
  143. package/dist/application-spec/parse-application-files/spec/components/filter-criterion-types.js +1 -0
  144. package/dist/application-spec/parse-application-files/spec/components/static-entity-id.d.ts +14 -0
  145. package/dist/application-spec/parse-application-files/spec/components/static-entity-id.js +1 -0
  146. package/dist/application-spec/parse-application-files/spec/components/user-component-entry.d.ts +6 -0
  147. package/dist/application-spec/parse-application-files/spec/components/user-component-entry.js +1 -1
  148. package/dist/application-spec/parse-application-files/spec/components/user-components.d.ts +7 -4
  149. package/dist/application-spec/parse-application-files/spec/components/user-components.js +1 -1
  150. package/dist/application-spec/parse-application-files/spec/expressions/expression-read-types.d.ts +24 -0
  151. package/dist/application-spec/parse-application-files/spec/expressions/expression-read-types.js +1 -0
  152. package/dist/application-spec/parse-application-files/spec/expressions/expression-read.d.ts +13 -0
  153. package/dist/application-spec/parse-application-files/spec/expressions/expression-read.js +1 -0
  154. package/dist/application-spec/parse-application-files/spec/expressions/expression-value-type.d.ts +9 -0
  155. package/dist/application-spec/parse-application-files/spec/expressions/expression-value-type.js +1 -0
  156. package/dist/application-spec/parse-application-files/spec/expressions/expressions.d.ts +6 -2
  157. package/dist/application-spec/parse-application-files/spec/expressions/expressions.js +1 -1
  158. package/dist/application-spec/parse-application-files/spec/expressions/user-expressions.d.ts +3 -1
  159. package/dist/application-spec/parse-application-files/spec/expressions/user-expressions.js +1 -1
  160. package/dist/application-spec/parse-application-files/spec/invariants/invariants.d.ts +2 -2
  161. package/dist/application-spec/parse-application-files/spec/invariants/invariants.js +1 -1
  162. package/dist/application-spec/parse-application-files/spec/model/index.d.ts +1 -0
  163. package/dist/application-spec/parse-application-files/spec/model/index.js +1 -1
  164. package/dist/application-spec/parse-application-files/spec/model/model-type-resolution.d.ts +10 -0
  165. package/dist/application-spec/parse-application-files/spec/model/model-type-resolution.js +1 -0
  166. package/dist/client/phoenix-api.d.ts +367 -0
  167. package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.d.ts +7 -1
  168. package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.js +1 -1
  169. package/dist/configurator/application-runtime/extensions/systems/graphql-system/close-unclosed-braces.d.ts +12 -0
  170. package/dist/configurator/application-runtime/extensions/systems/graphql-system/close-unclosed-braces.js +1 -0
  171. package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.d.ts +1 -1
  172. package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.js +1 -1
  173. package/dist/configurator/configuration-not-found-page/ConfigurationNotFoundPageElement.d.ts +12 -0
  174. package/dist/configurator/configuration-not-found-page/ConfigurationNotFoundPageElement.js +1 -0
  175. package/dist/configurator/configuration-not-found-page/index.d.ts +1 -0
  176. package/dist/configurator/configuration-not-found-page/index.js +1 -0
  177. package/dist/configurator/pages/ConfiguratorNotFoundPage.js +1 -1
  178. package/dist/configurator/pages/DefaultConfiguratorLayout.d.ts +3 -2
  179. package/dist/configurator/pages/LoadedConfiguratorDetailPage.js +1 -1
  180. package/dist/configurator/pages/RootPage.js +1 -1
  181. package/dist/configurator/pages/default-configurator-elements.d.ts +3 -1
  182. package/dist/configurator/pages/default-configurator-elements.js +1 -1
  183. package/dist/configurator/pages/default-elements/built-in-entity-element.d.ts +10 -0
  184. package/dist/configurator/pages/default-elements/built-in-entity-element.js +1 -0
  185. package/dist/configurator/pages/default-elements/built-in-layout-element.d.ts +10 -0
  186. package/dist/configurator/pages/default-elements/built-in-layout-element.js +1 -0
  187. package/dist/configurator/pages/default-elements/domain-control-elements.d.ts +6 -0
  188. package/dist/configurator/pages/default-elements/domain-control-elements.js +1 -0
  189. package/dist/configurator/pages/default-elements/index.d.ts +4 -0
  190. package/dist/configurator/pages/default-elements/index.js +1 -0
  191. package/dist/configurator/pages/default-elements/recipe-panel-elements.d.ts +3 -0
  192. package/dist/configurator/pages/default-elements/recipe-panel-elements.js +1 -0
  193. package/dist/configurator/pages/default-elements/sidebar-footer-elements.d.ts +7 -0
  194. package/dist/configurator/pages/default-elements/sidebar-footer-elements.js +1 -0
  195. package/dist/configurator/pages/default-elements/toolbar-elements.d.ts +7 -0
  196. package/dist/configurator/pages/default-elements/toolbar-elements.js +1 -0
  197. package/dist/configurator/ui/assistant/AssistantMarkdown.d.ts +7 -2
  198. package/dist/configurator/ui/assistant/AssistantMarkdown.js +1 -1
  199. package/dist/configurator/ui/assistant/AssistantPanel.js +1 -1
  200. package/dist/configurator/ui/assistant/AssistantThread.js +1 -1
  201. package/dist/configurator/ui/assistant/entity-link/AssistantEntityLink.d.ts +1 -1
  202. package/dist/configurator/ui/assistant/entity-link/AssistantEntityLink.js +1 -1
  203. package/dist/configurator/ui/assistant/entity-link/entity-link-state.d.ts +1 -1
  204. package/dist/configurator/ui/assistant/entity-link/index.d.ts +0 -1
  205. package/dist/configurator/ui/assistant/entity-link/index.js +1 -1
  206. package/dist/configurator/ui/assistant/form/AssistantForm.d.ts +19 -0
  207. package/dist/configurator/ui/assistant/form/AssistantForm.js +1 -0
  208. package/dist/configurator/ui/assistant/form/built-in-form-registry.d.ts +10 -0
  209. package/dist/configurator/ui/assistant/form/built-in-form-registry.js +1 -0
  210. package/dist/configurator/ui/assistant/form/compose-answer.d.ts +11 -0
  211. package/dist/configurator/ui/assistant/form/compose-answer.js +1 -0
  212. package/dist/configurator/ui/assistant/form/describe-build-errors.d.ts +6 -0
  213. package/dist/configurator/ui/assistant/form/describe-build-errors.js +1 -0
  214. package/dist/configurator/ui/assistant/form/form-element-definition.d.ts +14 -0
  215. package/dist/configurator/ui/assistant/form/form-element-definition.js +1 -0
  216. package/dist/configurator/ui/assistant/form/form-model.d.ts +38 -0
  217. package/dist/configurator/ui/assistant/form/form-model.js +1 -0
  218. package/dist/configurator/ui/assistant/form/form-registry.d.ts +31 -0
  219. package/dist/configurator/ui/assistant/form/form-registry.js +8 -0
  220. package/dist/configurator/ui/assistant/form/form-state.d.ts +4 -0
  221. package/dist/configurator/ui/assistant/form/form-state.js +1 -0
  222. package/dist/configurator/ui/assistant/form/index.d.ts +2 -0
  223. package/dist/configurator/ui/assistant/form/index.js +1 -0
  224. package/dist/configurator/ui/assistant/form/parse-form-block.d.ts +9 -0
  225. package/dist/configurator/ui/assistant/form/parse-form-block.js +1 -0
  226. package/dist/configurator/ui/assistant/form/read-form-attributes.d.ts +13 -0
  227. package/dist/configurator/ui/assistant/form/read-form-attributes.js +1 -0
  228. package/dist/configurator/ui/assistant/form-elements/FormGroup.d.ts +3 -0
  229. package/dist/configurator/ui/assistant/form-elements/FormGroup.js +1 -0
  230. package/dist/configurator/ui/assistant/form-elements/FormOptions.d.ts +3 -0
  231. package/dist/configurator/ui/assistant/form-elements/FormOptions.js +1 -0
  232. package/dist/configurator/ui/assistant/form-elements/FormReply.d.ts +3 -0
  233. package/dist/configurator/ui/assistant/form-elements/FormReply.js +1 -0
  234. package/dist/configurator/ui/assistant/form-elements/FormText.d.ts +3 -0
  235. package/dist/configurator/ui/assistant/form-elements/FormText.js +1 -0
  236. package/dist/configurator/ui/assistant/form-elements/form-element-props.d.ts +34 -0
  237. package/dist/configurator/ui/assistant/form-elements/form-element-props.js +1 -0
  238. package/dist/configurator/ui/assistant/form-elements/index.d.ts +5 -0
  239. package/dist/configurator/ui/assistant/form-elements/index.js +1 -0
  240. package/dist/configurator/ui/assistant/reference-link/AssistantReferenceLink.d.ts +16 -0
  241. package/dist/configurator/ui/assistant/reference-link/AssistantReferenceLink.js +1 -0
  242. package/dist/configurator/ui/assistant/reference-link/assistant-link-target.d.ts +34 -0
  243. package/dist/configurator/ui/assistant/reference-link/assistant-link-target.js +1 -0
  244. package/dist/configurator/ui/assistant/reference-link/assistant-reference-details.d.ts +25 -0
  245. package/dist/configurator/ui/assistant/reference-link/assistant-reference-details.js +1 -0
  246. package/dist/configurator/ui/assistant/reference-link/index.d.ts +3 -0
  247. package/dist/configurator/ui/assistant/reference-link/index.js +1 -0
  248. package/dist/configurator/ui/assistant/reference-link/reference-styles.d.ts +12 -0
  249. package/dist/configurator/ui/assistant/reference-link/reference-styles.js +1 -0
  250. package/dist/configurator/ui/assistant/reference-link/use-assistant-reference-details.d.ts +8 -0
  251. package/dist/configurator/ui/assistant/reference-link/use-assistant-reference-details.js +1 -0
  252. package/dist/configurator/ui/assistant/resource-image/AssistantImage.d.ts +9 -0
  253. package/dist/configurator/ui/assistant/resource-image/AssistantImage.js +1 -0
  254. package/dist/configurator/ui/assistant/resource-image/index.d.ts +3 -0
  255. package/dist/configurator/ui/assistant/resource-image/index.js +1 -0
  256. package/dist/configurator/ui/assistant/resource-image/resource-path.d.ts +11 -0
  257. package/dist/configurator/ui/assistant/resource-image/resource-path.js +1 -0
  258. package/dist/configurator/ui/assistant/resource-image/use-resource-image-url.d.ts +5 -0
  259. package/dist/configurator/ui/assistant/resource-image/use-resource-image-url.js +1 -0
  260. package/dist/configurator/ui/assistant/streamed-markdown.d.ts +2 -0
  261. package/dist/configurator/ui/assistant/streamed-markdown.js +2 -2
  262. package/dist/configurator/ui/assistant/thread-items.d.ts +8 -1
  263. package/dist/configurator/ui/assistant/thread-items.js +1 -1
  264. package/dist/configurator/ui/assistant/use-follow-stream.js +1 -1
  265. package/dist/configurator/ui/configurator-layout/slots/services/InvariantViolations.js +1 -1
  266. package/dist/configurator/ui/configurator-layout/slots/services/Services.js +1 -1
  267. package/dist/configurator/ui/legacy/layout/common/SummaryReadLayout.js +1 -1
  268. package/dist/configurator/ui/legacy/layout/simple/SimpleOwnerLayout.js +1 -1
  269. package/dist/configurator/ui/legacy/layout/steps/StepsOwnerLayout.js +1 -1
  270. package/dist/configurator/ui/legacy/layout/tabs/TabsOwnerLayout.js +1 -1
  271. package/dist/configurator/ui/phoenix-layout-elements/LayoutCustomOwnerUi.d.ts +1 -0
  272. package/dist/configurator/ui/phoenix-layout-elements/LayoutCustomOwnerUi.js +1 -1
  273. package/dist/configurator/ui/phoenix-layout-elements/LayoutCustomReadUi.d.ts +1 -0
  274. package/dist/configurator/ui/phoenix-layout-elements/LayoutCustomReadUi.js +1 -1
  275. package/dist/configurator/ui/preset-layout/CategoryPresetUi.js +1 -1
  276. package/dist/configurator/ui/save-message-snackbars/SaveMessageSnackbars.d.ts +10 -0
  277. package/dist/configurator/ui/save-message-snackbars/SaveMessageSnackbars.js +1 -0
  278. package/dist/configurator/ui/save-message-snackbars/index.d.ts +1 -0
  279. package/dist/configurator/ui/save-message-snackbars/index.js +1 -0
  280. package/dist/docs/controls/select-child-entity/cardselect.mdx +1 -0
  281. package/dist/docs/fabs/basic.mdx +2 -2
  282. package/dist/docs/index.json +1 -1
  283. package/dist/docs/layouts/custom-layout.mdx +324 -15
  284. package/dist/docs/other-features/not-found-404.mdx +1 -1
  285. package/dist/docs/phoenix/clerk-sign-in.mdx +1 -1
  286. package/dist/docs/phoenix/components.mdx +6 -0
  287. package/dist/docs/phoenix/configurator-interface.mdx +35 -11
  288. package/dist/docs/phoenix/domain-model.mdx +2 -0
  289. package/dist/docs/phoenix/getting-started.mdx +5 -3
  290. package/dist/docs/phoenix/layout-slots.mdx +9 -9
  291. package/dist/docs/phoenix/localization.mdx +6 -2
  292. package/dist/docs/phoenix/migration-guide.mdx +12 -10
  293. package/dist/docs/phoenix/phoenix-cli.mdx +31 -16
  294. package/dist/docs/phoenix/project-structure.mdx +52 -30
  295. package/dist/docs/phoenix/quickstart.mdx +7 -7
  296. package/dist/docs/phoenix/sdk-builder-workflow.mdx +6 -6
  297. package/dist/docs/phoenix/testing.mdx +8 -0
  298. package/dist/domain/application/assistant/assistant-form-elements.d.ts +28 -0
  299. package/dist/domain/application/assistant/assistant-form-elements.js +1 -0
  300. package/dist/domain/application/assistant/generate-assistant-prompt.js +1 -1
  301. package/dist/domain/application/assistant/index.d.ts +2 -0
  302. package/dist/domain/application/assistant/index.js +1 -1
  303. package/dist/domain/application/assistant-recipe-groups.d.ts +3 -1
  304. package/dist/domain/core/schema/extended-schema-validator.js +1 -1
  305. package/dist/domain/domain-runtime/spec/module-checks/element-registration.d.ts +12 -11
  306. package/dist/domain/domain-runtime/spec/module-checks/element-registration.js +1 -1
  307. package/dist/domain/domain-runtime/spec/module-checks/index.d.ts +1 -1
  308. package/dist/domain/domain-runtime/spec/module-checks/index.js +1 -1
  309. package/dist/domain/domain-runtime/spec/selectors.js +1 -1
  310. package/dist/domain/system-components/child-entity-selection.js +1 -1
  311. package/dist/domain/system-components/common/scene-entity-control-schema.d.ts +3 -0
  312. package/dist/domain/system-components/common/scene-entity-control-schema.js +1 -1
  313. package/dist/editor/mocks/CreateMockYaml.js +2 -2
  314. package/dist/i18n/locales/cs/messages.js +1 -1
  315. package/dist/i18n/locales/da/messages.js +1 -1
  316. package/dist/i18n/locales/de/messages.js +1 -1
  317. package/dist/i18n/locales/de-AT/messages.js +1 -1
  318. package/dist/i18n/locales/en/messages.js +1 -1
  319. package/dist/i18n/locales/en-AU/messages.js +1 -1
  320. package/dist/i18n/locales/en-GB/messages.js +1 -1
  321. package/dist/i18n/locales/es/messages.js +1 -1
  322. package/dist/i18n/locales/fr/messages.js +1 -1
  323. package/dist/i18n/locales/hu/messages.js +1 -1
  324. package/dist/i18n/locales/it/messages.js +1 -1
  325. package/dist/i18n/locales/nl/messages.js +1 -1
  326. package/dist/i18n/locales/pl/messages.js +1 -1
  327. package/dist/i18n/locales/pt/messages.js +1 -1
  328. package/dist/i18n/locales/ro/messages.js +1 -1
  329. package/dist/i18n/locales/sk/messages.js +1 -1
  330. package/dist/i18n/locales/tr/messages.js +1 -1
  331. package/dist/legacy/domain-cli/utils/cache.d.ts +1 -1
  332. package/dist/legacy/domain-cli/utils/cache.js +1 -1
  333. package/dist/legacy/domain-spec/__generated/domain-schema.d.ts +79 -80
  334. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-admin.js +10 -11
  335. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/frontend-embedded-admin.js +9 -10
  336. package/dist/phoenix/application-spec/application-spec-builder.d.ts +0 -2
  337. package/dist/phoenix/application-spec/application-spec-builder.js +1 -1
  338. package/dist/phoenix/application-spec/generate-application-spec-project.d.ts +0 -2
  339. package/dist/phoenix/application-spec/generate-application-spec-project.js +2 -2
  340. package/dist/phoenix/application-spec/generate-application-spec-story.js +2 -2
  341. package/dist/phoenix/application-spec/generate-project-files.d.ts +0 -2
  342. package/dist/phoenix/application-spec/project-files.js +1 -1
  343. package/dist/phoenix/bin.d.ts +2 -0
  344. package/dist/phoenix/bin.js +2 -0
  345. package/dist/phoenix/check-configs/built-in-eslint-config.d.ts +9 -0
  346. package/dist/phoenix/check-configs/built-in-eslint-config.js +1 -0
  347. package/dist/phoenix/check-configs/eslint-config.d.ts +10 -0
  348. package/dist/phoenix/check-configs/eslint-config.js +1 -0
  349. package/dist/phoenix/check-configs/index.d.ts +8 -0
  350. package/dist/phoenix/check-configs/index.js +1 -0
  351. package/dist/phoenix/check-configs/typescript-project.d.ts +5 -0
  352. package/dist/phoenix/check-configs/typescript-project.js +1 -0
  353. package/dist/phoenix/cli.d.ts +0 -1
  354. package/dist/phoenix/cli.js +1 -2
  355. package/dist/phoenix/commands/build.js +1 -1
  356. package/dist/phoenix/commands/check.js +1 -1
  357. package/dist/phoenix/commands/clean.js +1 -1
  358. package/dist/phoenix/commands/deploy.js +2 -2
  359. package/dist/phoenix/commands/deps/deps.d.ts +22 -1
  360. package/dist/phoenix/commands/deps/deps.js +2 -2
  361. package/dist/phoenix/commands/deps/index.d.ts +1 -1
  362. package/dist/phoenix/commands/deps/index.js +1 -1
  363. package/dist/phoenix/commands/deps/sdk-manifest.js +1 -1
  364. package/dist/phoenix/commands/dev.js +4 -4
  365. package/dist/phoenix/commands/fix.js +1 -1
  366. package/dist/phoenix/commands/init.d.ts +17 -5
  367. package/dist/phoenix/commands/init.js +1 -1
  368. package/dist/phoenix/commands/link.js +1 -1
  369. package/dist/phoenix/commands/prettier.js +1 -1
  370. package/dist/phoenix/commands/sync.js +1 -1
  371. package/dist/phoenix/commands/unlink.js +1 -1
  372. package/dist/phoenix/services/application-spec-project-watcher.d.ts +0 -2
  373. package/dist/phoenix/services/application-spec-project-watcher.js +2 -2
  374. package/dist/phoenix/services/lingui.d.ts +8 -0
  375. package/dist/phoenix/services/lingui.js +1 -1
  376. package/dist/phoenix/services/swc.js +1 -1
  377. package/dist/phoenix/services/vite-config.js +1 -1
  378. package/dist/phoenix/utils/index.d.ts +3 -2
  379. package/dist/phoenix/utils/index.js +1 -1
  380. package/dist/phoenix/utils/node-version/index.d.ts +1 -0
  381. package/dist/phoenix/utils/node-version/index.js +1 -0
  382. package/dist/phoenix/utils/node-version/supported-node-version.d.ts +12 -0
  383. package/dist/phoenix/utils/node-version/supported-node-version.js +4 -0
  384. package/dist/phoenix/utils/package-info.d.ts +0 -9
  385. package/dist/phoenix/utils/package-info.js +1 -1
  386. package/dist/phoenix/utils/package-manager/index.d.ts +2 -0
  387. package/dist/phoenix/utils/package-manager/index.js +1 -0
  388. package/dist/phoenix/utils/package-manager/package-manager-commands.d.ts +19 -0
  389. package/dist/phoenix/utils/package-manager/package-manager-commands.js +1 -0
  390. package/dist/phoenix/utils/package-manager/pnpm-project.d.ts +9 -0
  391. package/dist/phoenix/utils/package-manager/pnpm-project.js +1 -0
  392. package/dist/phoenix/utils/run-command.d.ts +11 -0
  393. package/dist/phoenix/utils/run-command.js +1 -1
  394. package/dist/phoenix/utils/sdk-tool/index.d.ts +1 -0
  395. package/dist/phoenix/utils/sdk-tool/index.js +1 -0
  396. package/dist/phoenix/utils/sdk-tool/resolve-sdk-tool-bin.d.ts +15 -0
  397. package/dist/phoenix/utils/sdk-tool/resolve-sdk-tool-bin.js +1 -0
  398. package/dist/react-sdk/domain-application-context/DomainLifecycleBoundary.js +1 -1
  399. package/dist/react-sdk/domain-context/common-hooks/use-configurator-messages.d.ts +15 -4
  400. package/dist/react-sdk/domain-context/common-hooks/use-configurator-messages.js +1 -1
  401. package/dist/ui-sdk/theme/types.d.ts +1 -1
  402. package/package.json +16 -9
  403. package/schema/domain-spec.json +86 -8
  404. package/dist/application-spec/generate-application/code/templates/nvmrc.d.ts +0 -1
  405. package/dist/application-spec/generate-application/code/templates/nvmrc.js +0 -2
  406. package/dist/application-spec/generate-application/code/templates/package-json.d.ts +0 -10
  407. package/dist/application-spec/generate-application/code/templates/package-json.js +0 -1
  408. package/dist/configurator/ui/assistant/entity-link/entity-link-target.d.ts +0 -5
  409. package/dist/configurator/ui/assistant/entity-link/entity-link-target.js +0 -1
  410. package/dist/phoenix/commands/generate-project-files.d.ts +0 -6
  411. package/dist/phoenix/commands/generate-project-files.js +0 -1
@@ -1,4 +1,4 @@
1
- import{openAsBlob as e}from"node:fs";import{createApiBaseClient as t}from"#package/client";import{resolveApplicationSpecDeploymentData as i}from"../application-spec/index.js";import{createSourceArchive as o,getServerCredentials as r}from"../services/index.js";import{ensureWorkspaceInstallSettings as a}from"../utils/index.js";let s={queued:"Waiting for a build runner",preparing:"Preparing the deployment",building:"Building the project",deploying:"Deploying the frontend, webhooks and assets",live:"Live",failed:"Failed",cancelled:"Cancelled"},n=e=>new Promise(t=>setTimeout(t,e)),l=async(t,i)=>{let o=new FormData;for(let[e,i]of Object.entries(t.fields))o.append(e,i);o.append("file",await e(i,{type:"application/gzip"}),"sources.tgz");let r=await fetch(t.url,{method:"POST",body:o});if(!r.ok)throw Error(`Uploading the sources failed with HTTP ${r.status}: ${await r.text()}`)};export const runDeployCommand=async(e,{logger:d})=>{let u=await r(e.serverUrl),{pollIntervalMs:c}=e;if(!u)throw Error(`You are not signed in to ${e.serverUrl}. Run \`phoenix login <workspace>\` first.`);let p=t(e.serverUrl),h={authorization:`Bearer ${u.token}`};d.step("Validating the application spec");let m=await i({skipUpload:!0,logger:d});d.success(`The spec is valid (application version ${m.applicationVersion})`),d.step(`Packing the project for ${u.customerName}`),a(e.projectDir);let f=await o(e.projectDir);try{let t;f.hasConversationLog?d.info("Including conversation.log in the private sources archive. It is not published with the application."):d.warn("No conversation.log found in the project root. Deploying without a conversation transcript."),d.info(` ${f.fileCount} files, ${(t=f.size)<1048576?`${(t/1024).toFixed(1)} KB`:`${(t/1024/1024).toFixed(1)} MB`}`);let i=await p.POST("/deployments/builds",{body:{sdkVersion:e.sdkVersion,sizeBytes:f.size,configurationSchema:{version:m.schemaVersion,schema:m.schema},adminConfigurationSchema:m.adminSchema?{version:m.adminSchemaVersion,schema:m.adminSchema}:void 0},headers:h});if(i.error||!i.data)throw Error(`The server did not create a build: ${i.error?.message??"no response"}`);let{buildId:o,upload:r}=i.data;d.step("Uploading the sources"),await l(r,f.path);let a=await p.POST("/deployments/builds/{buildId}/start",{params:{path:{buildId:o}},headers:{...h,"content-type":null}});if(a.error)throw Error(`The server did not start the build: ${a.error.message}`);if(a.data?.status==="failed")throw Error(`Build ${o} could not be started: ${a.data.error??"the server gave no reason"}`);if(d.success(`Build ${o} started`),u.studioUrl){let e=new URL(`/builder/deployments/${o}`,u.studioUrl);e.searchParams.set("customer",u.customerSlug),d.info(`Follow the build in Studio: ${e.toString()}`)}if(!e.wait)return;let g=null,w=0;for(;;){let{data:e,error:t}=await p.GET("/deployments/builds/{buildId}",{params:{path:{buildId:o}},headers:h}).catch(e=>({data:void 0,error:{message:String(e)}}));if(t||!e){if((w+=1)>=5)throw Error(`Following build ${o} failed: ${t?.message??"no response"}. The build may still finish; check Deployments in Studio.`);await n(c);continue}if(w=0,e.status!==g&&(g=e.status,d.step(s[e.status])),"live"===e.status){d.success(`Your configurator is live at ${e.configuratorUrl}`),d.info("Coding agents: when the user has nothing more to build, offer the run evaluation from the phoenix-feedback skill, once per conversation.");return}if("failed"===e.status||"cancelled"===e.status||e.timedOut){let t=await p.GET("/deployments/builds/{buildId}/log",{params:{path:{buildId:o}},headers:h}).catch(()=>({data:void 0})),i=(t.data?.log??"").trim().split("\n").slice(-40).join("\n");i&&d.info(`
1
+ import{openAsBlob as e}from"node:fs";import{createApiBaseClient as t}from"#package/client";import{resolveApplicationSpecDeploymentData as i}from"../application-spec/index.js";import{createSourceArchive as o,getServerCredentials as a}from"../services/index.js";let r={queued:"Waiting for a build runner",preparing:"Preparing the deployment",building:"Building the project",deploying:"Deploying the frontend, webhooks and assets",live:"Live",failed:"Failed",cancelled:"Cancelled"},s=e=>new Promise(t=>setTimeout(t,e)),n=async(t,i)=>{let o=new FormData;for(let[e,i]of Object.entries(t.fields))o.append(e,i);o.append("file",await e(i,{type:"application/gzip"}),"sources.tgz");let a=await fetch(t.url,{method:"POST",body:o});if(!a.ok)throw Error(`Uploading the sources failed with HTTP ${a.status}: ${await a.text()}`)};export const runDeployCommand=async(e,{logger:l})=>{let d=await a(e.serverUrl),{pollIntervalMs:u}=e;if(!d)throw Error(`You are not signed in to ${e.serverUrl}. Run \`phoenix login <workspace>\` first.`);let c=t(e.serverUrl),p={authorization:`Bearer ${d.token}`};l.step("Validating the application spec");let h=await i({skipUpload:!0,logger:l});l.success(`The spec is valid (application version ${h.applicationVersion})`),l.step(`Packing the project for ${d.customerName}`);let m=await o(e.projectDir);try{let t;m.hasConversationLog?l.info("Including conversation.log in the private sources archive. It is not published with the application."):l.warn("No conversation.log found in the project root. Deploying without a conversation transcript."),l.info(` ${m.fileCount} files, ${(t=m.size)<1048576?`${(t/1024).toFixed(1)} KB`:`${(t/1024/1024).toFixed(1)} MB`}`);let i=await c.POST("/deployments/builds",{body:{sdkVersion:e.sdkVersion,sizeBytes:m.size,configurationSchema:{version:h.schemaVersion,schema:h.schema},adminConfigurationSchema:h.adminSchema?{version:h.adminSchemaVersion,schema:h.adminSchema}:void 0},headers:p});if(i.error||!i.data)throw Error(`The server did not create a build: ${i.error?.message??"no response"}`);let{buildId:o,upload:a}=i.data;l.step("Uploading the sources"),await n(a,m.path);let f=await c.POST("/deployments/builds/{buildId}/start",{params:{path:{buildId:o}},headers:{...p,"content-type":null}});if(f.error)throw Error(`The server did not start the build: ${f.error.message}`);if(f.data?.status==="failed")throw Error(`Build ${o} could not be started: ${f.data.error??"the server gave no reason"}`);if(l.success(`Build ${o} started`),d.studioUrl){let e=new URL(`/builder/deployments/${o}`,d.studioUrl);e.searchParams.set("customer",d.customerSlug),l.info(`Follow the build in Studio: ${e.toString()}`)}if(!e.wait)return;let g=null,w=0;for(;;){let{data:e,error:t}=await c.GET("/deployments/builds/{buildId}",{params:{path:{buildId:o}},headers:p}).catch(e=>({data:void 0,error:{message:String(e)}}));if(t||!e){if((w+=1)>=5)throw Error(`Following build ${o} failed: ${t?.message??"no response"}. The build may still finish; check Deployments in Studio.`);await s(u);continue}if(w=0,e.status!==g&&(g=e.status,l.step(r[e.status])),"live"===e.status){l.success(`Your configurator is live at ${e.configuratorUrl}`),l.info("Coding agents: when the user has nothing more to build, offer the run evaluation from the phoenix-feedback skill, once per conversation.");return}if("failed"===e.status||"cancelled"===e.status||e.timedOut){let t=await c.GET("/deployments/builds/{buildId}/log",{params:{path:{buildId:o}},headers:p}).catch(()=>({data:void 0})),i=(t.data?.log??"").trim().split("\n").slice(-40).join("\n");i&&l.info(`
2
2
  Last lines of the build log:
3
3
  ${i}
4
- `);let r=e.timedOut?"it took too long":e.error??"see the build log";throw Error(`Build ${o} did not go live: ${r}`)}await n(c)}}finally{await f.cleanup()}};
4
+ `);let a=e.timedOut?"it took too long":e.error??"see the build log";throw Error(`Build ${o} did not go live: ${a}`)}await s(u)}}finally{await m.cleanup()}};
@@ -31,6 +31,12 @@ interface PeerMismatch {
31
31
  readonly specifier: string;
32
32
  } | undefined;
33
33
  }
34
+ /** A package to add to the project's `package.json` when no dependency field declares it yet. */
35
+ export interface MissingDependency {
36
+ readonly name: string;
37
+ readonly version: string;
38
+ readonly field: 'dependencies' | 'devDependencies';
39
+ }
34
40
  type JsonObject = Readonly<Record<string, unknown>>;
35
41
  /**
36
42
  * Lists every peer of the SDK the project's `package.json` does not satisfy, in the order of the SDK's
@@ -42,11 +48,26 @@ export declare const findSdkPeerMismatches: ({ packageJson, useClerk, }: {
42
48
  readonly packageJson: JsonObject;
43
49
  readonly useClerk: boolean;
44
50
  }) => readonly PeerMismatch[];
51
+ /**
52
+ * Returns the `package.json` with each given package added that no dependency field declares yet, at the given
53
+ * version in the given field, in alphabetical order among the entries already there. A field is created only when it
54
+ * gains an entry, and a package the project declares stays as it is, whatever its version.
55
+ */
56
+ export declare const addMissingDependencies: (packageJson: JsonObject, dependencies: readonly MissingDependency[]) => JsonObject;
57
+ /**
58
+ * Returns the `package.json` with every required peer of the SDK added that no dependency field declares yet, at the
59
+ * version `phoenix deps` writes. A peer the project declares stays as it is, even outside the SDK's range: moving it
60
+ * into the range is the job of `phoenix deps`.
61
+ */
62
+ export declare const addMissingSdkPeers: (packageJson: JsonObject, { useClerk }: {
63
+ readonly useClerk: boolean;
64
+ }) => JsonObject;
45
65
  /**
46
66
  * Brings the project's `package.json` in line with the SDK: adds every required peer it does not declare and moves
47
67
  * every declared peer whose version falls outside the SDK's range to the lowest version of that range, in the field
48
68
  * that declares it. Specifiers that are not semver ranges stay as they are. The only entries it removes are the
49
- * packages `@salsita-ai/sdk` replaces. It installs nothing; the next step is `pnpm install`.
69
+ * packages `@salsita-ai/sdk` replaces. It installs nothing; the next step it prints is the install of the package manager
70
+ * that ran it.
50
71
  */
51
72
  export declare const runDepsCommand: (props: DepsCommandProps, { logger }: CommandContext) => Promise<void>;
52
73
  export {};
@@ -1,3 +1,3 @@
1
- import{existsSync as e}from"fs";import{readFile as r,writeFile as t}from"fs/promises";import{join as a}from"path";import{lt as n,minVersion as i,satisfies as o,validRange as s}from"semver";import{RuntimeReferenceStore as p,buildPhoenixDefinitions as l,parseApplicationFiles as d}from"#package/application-spec";import{getAllPhxDefinitions as c}from"#package/domain";import{readApplicationFiles as m}from"../../application-spec/application-spec-file-reader.js";import{swcEvalExpressionParser as f,swcModuleAnalyzer as u}from"../../application-spec/swc-module-analyzer.js";import{naturalCompare as h}from"../../utils/index.js";import{readSdkManifest as g}from"./sdk-manifest.js";let j=["@salsita-ai/platform-project-sdk","@salsita-ai/platform-common","@salsita-ai/platform-contracts","@salsita-ai/common","@salsita-ai/contracts"],k=["dependencies","devDependencies","optionalDependencies"],v=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),$=async t=>{let a;if(!e(t))throw Error(`phoenix deps found no package.json at ${t}. It brings the dependencies of an existing project in line with the SDK, so run it in the project folder.`);let n=await r(t,"utf-8");try{a=JSON.parse(n)}catch(e){throw Error(`phoenix deps could not read package.json because it is not valid JSON: ${e instanceof Error?e.message:String(e)} Fix the file and run phoenix deps again.`)}if(!v(a))throw Error("phoenix deps could not read package.json because it is not a JSON object. Fix the file and run phoenix deps again.");return{content:n,packageJson:a}},w=async(e,r)=>{let t=d({rawProjectFiles:await m({projectRoot:e,envs:{}}),phxDefinitions:l(c())},{analyzer:u,evalExpressionParser:f,referenceStore:new p,logger:r});if(!t.ok)throw Error(`phoenix deps could not parse the application spec, which says through useClerk whether the project needs @clerk/clerk-react:
1
+ import{existsSync as e}from"fs";import{readFile as r,writeFile as t}from"fs/promises";import{join as a}from"path";import{lt as n,minVersion as i,satisfies as o,validRange as s}from"semver";import{RuntimeReferenceStore as d,buildPhoenixDefinitions as p,parseApplicationFiles as l}from"#package/application-spec";import{getAllPhxDefinitions as c}from"#package/domain";import{readApplicationFiles as f}from"../../application-spec/application-spec-file-reader.js";import{swcEvalExpressionParser as m,swcModuleAnalyzer as u}from"../../application-spec/swc-module-analyzer.js";import{findPackageManagerCommands as h,naturalCompare as g}from"../../utils/index.js";import{readSdkManifest as v}from"./sdk-manifest.js";let k=["@salsita-ai/platform-project-sdk","@salsita-ai/platform-common","@salsita-ai/platform-contracts","@salsita-ai/common","@salsita-ai/contracts"],j=["dependencies","devDependencies","optionalDependencies"],$=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),w=async t=>{let a;if(!e(t))throw Error(`phoenix deps found no package.json at ${t}. It brings the dependencies of an existing project in line with the SDK, so run it in the project folder.`);let n=await r(t,"utf-8");try{a=JSON.parse(n)}catch(e){throw Error(`phoenix deps could not read package.json because it is not valid JSON: ${e instanceof Error?e.message:String(e)} Fix the file and run phoenix deps again.`)}if(!$(a))throw Error("phoenix deps could not read package.json because it is not a JSON object. Fix the file and run phoenix deps again.");return{content:n,packageJson:a}},x=async(e,r)=>{let t=l({rawProjectFiles:await f({projectRoot:e,envs:{}}),phxDefinitions:p(c())},{analyzer:u,evalExpressionParser:m,referenceStore:new d,logger:r});if(!t.ok)throw Error(`phoenix deps could not parse the application spec, which says through useClerk whether the project needs @clerk/clerk-react:
2
2
  ${t.errors.map(e=>` [${e.code}] ${e.message}`).join("\n")}
3
- Fix these errors and run phoenix deps again.`);return t.value.applicationSpec.appMetadata.useClerk},x=e=>Object.fromEntries(k.map(r=>{let t=e[r];return[r,v(t)?Object.fromEntries(Object.entries(t).filter(e=>"string"==typeof e[1])):{}]})),b=({peer:e,found:r})=>void 0===r?{kind:"add",field:e.field,name:e.name,to:e.version}:{kind:"update",field:r.field,name:e.name,from:r.specifier,to:e.version,range:e.range},y=(e,r)=>{let t=new Set(r.flatMap(e=>"remove"===e.kind?[e.name]:[])),a=new Map(r.flatMap(e=>"update"===e.kind?[[e.name,e.to]]:[])),n=r.flatMap(e=>"add"===e.kind?[e]:[]),i=Object.entries(v(e)?e:{}).filter(([e])=>!t.has(e)).map(([e,r])=>[e,a.get(e)??r]);return Object.fromEntries([...n].sort((e,r)=>h(e.name,r.name)).reduce((e,r)=>{var t,a;let n;return t=r.name,a=r.to,-1===(n=e.findIndex(([e])=>h(e,t)>0))?[...e,[t,a]]:[...e.slice(0,n),[t,a],...e.slice(n)]},i))},S=e=>{switch(e.kind){case"add":return` ${e.field}: added ${e.name} ${e.to}`;case"update":var r,t;let a;return(r=e.from,t=e.to,null!==(a=i(r))&&n(t,a))?` ${e.field}: downgraded ${e.name} ${e.from} → ${e.to}, because the SDK supports ${e.range}`:` ${e.field}: updated ${e.name} ${e.from} → ${e.to}`;case"remove":return` ${e.field}: removed ${e.name}, which @salsita-ai/sdk replaces`}};export const findSdkPeerMismatches=({packageJson:e,useClerk:r})=>{let t=x(e);return(e=>{let{peerDependencies:r,optionalPeers:t}=g();return Object.entries(r).filter(([r])=>"@clerk/clerk-react"===r&&e||!t.includes(r)).map(([e,r])=>((e,r)=>{let t=i(r);if(null===t)throw Error(`The SDK's peer range "${r}" for ${e} matches no version, so no version of it can be required. The SDK installation is damaged; reinstall @salsita-ai/sdk.`);return{name:e,range:r,version:t.version,field:e.startsWith("@types/")?"devDependencies":"dependencies"}})(e,r))})(r).flatMap(e=>{let r=k.flatMap(r=>{let a=t[r]?.[e.name];return void 0===a?[]:[{field:r,specifier:a}]});return 0===r.length?[{peer:e,found:void 0}]:r.filter(r=>!((e,r)=>{if(null===s(e))return!0;let t=i(e);return null!==t&&o(t,r,{includePrerelease:!0})})(r.specifier,e.range)).map(r=>({peer:e,found:r}))})};export const runDepsCommand=async(e,{logger:r})=>{var n,i;let o,s,p,l,d,c,m,f=a(e.projectRoot,"package.json"),{content:u,packageJson:h}=await $(f),g=await w(e.projectRoot,r),v=(n=findSdkPeerMismatches({packageJson:h,useClerk:g}),o=x(h),s=k.flatMap(e=>j.filter(r=>o[e]?.[r]!==void 0).map(r=>({kind:"remove",field:e,name:r}))),[...n.map(b),...s]);0===v.length?r.success("package.json already declares every package the SDK needs. Nothing to change."):(await t(f,(p=e=>v.filter(r=>r.field===e),l=k.filter(e=>p(e).length>0),i=Object.fromEntries([...Object.entries(h).map(([e,r])=>{let t=l.find(r=>r===e);return void 0===t?[e,r]:[e,y(r,p(t))]}),...l.filter(e=>!(e in h)).map(e=>[e,y(void 0,p(e))])]),d=/^[ \t]+(?=")/m.exec(u)?.[0]??" ",c=u.includes("\r\n")?"\r\n":"\n",m=/\r?\n$/.test(u)?c:"",JSON.stringify(i,null,d).replace(/\n/g,c)+m)),r.success("Updated package.json:"),r.info(["",...v.map(S),"","Next step: pnpm install"].join("\n")))};
3
+ Fix these errors and run phoenix deps again.`);return t.value.applicationSpec.appMetadata.useClerk},y=e=>Object.fromEntries(j.map(r=>{let t=e[r];return[r,$(t)?Object.fromEntries(Object.entries(t).filter(e=>"string"==typeof e[1])):{}]})),S=({peer:e,found:r})=>void 0===r?{kind:"add",field:e.field,name:e.name,to:e.version}:{kind:"update",field:r.field,name:e.name,from:r.specifier,to:e.version,range:e.range},b=(e,r)=>{let t=new Set(r.flatMap(e=>"remove"===e.kind?[e.name]:[])),a=new Map(r.flatMap(e=>"update"===e.kind?[[e.name,e.to]]:[])),n=r.flatMap(e=>"add"===e.kind?[e]:[]),i=Object.entries($(e)?e:{}).filter(([e])=>!t.has(e)).map(([e,r])=>[e,a.get(e)??r]);return Object.fromEntries([...n].sort((e,r)=>g(e.name,r.name)).reduce((e,r)=>{var t,a;let n;return t=r.name,a=r.to,-1===(n=e.findIndex(([e])=>g(e,t)>0))?[...e,[t,a]]:[...e.slice(0,n),[t,a],...e.slice(n)]},i))},M=(e,r)=>{let t=e=>r.filter(r=>r.field===e),a=j.filter(e=>t(e).length>0);return Object.fromEntries([...Object.entries(e).map(([e,r])=>{let n=a.find(r=>r===e);return void 0===n?[e,r]:[e,b(r,t(n))]}),...a.filter(r=>!(r in e)).map(e=>[e,b(void 0,t(e))])])},D=e=>{switch(e.kind){case"add":return` ${e.field}: added ${e.name} ${e.to}`;case"update":var r,t;let a;return(r=e.from,t=e.to,null!==(a=i(r))&&n(t,a))?` ${e.field}: downgraded ${e.name} ${e.from} → ${e.to}, because the SDK supports ${e.range}`:` ${e.field}: updated ${e.name} ${e.from} → ${e.to}`;case"remove":return` ${e.field}: removed ${e.name}, which @salsita-ai/sdk replaces`}};export const findSdkPeerMismatches=({packageJson:e,useClerk:r})=>{let t=y(e);return(e=>{let{peerDependencies:r,optionalPeers:t}=v();return Object.entries(r).filter(([r])=>"@clerk/clerk-react"===r&&e||!t.includes(r)).map(([e,r])=>((e,r)=>{let t=i(r);if(null===t)throw Error(`The SDK's peer range "${r}" for ${e} matches no version, so no version of it can be required. The SDK installation is damaged; reinstall @salsita-ai/sdk.`);return{name:e,range:r,version:t.version,field:e.startsWith("@types/")?"devDependencies":"dependencies"}})(e,r))})(r).flatMap(e=>{let r=j.flatMap(r=>{let a=t[r]?.[e.name];return void 0===a?[]:[{field:r,specifier:a}]});return 0===r.length?[{peer:e,found:void 0}]:r.filter(r=>!((e,r)=>{if(null===s(e))return!0;let t=i(e);return null!==t&&o(t,r,{includePrerelease:!0})})(r.specifier,e.range)).map(r=>({peer:e,found:r}))})};export const addMissingDependencies=(e,r)=>{let t=y(e);return M(e,r.filter(({name:e})=>j.every(r=>t[r]?.[e]===void 0)).map(({name:e,version:r,field:t})=>({kind:"add",field:t,name:e,to:r})))};export const addMissingSdkPeers=(e,{useClerk:r})=>{let t=findSdkPeerMismatches({packageJson:e,useClerk:r}).flatMap(({peer:e,found:r})=>void 0===r?[{name:e.name,version:e.version,field:e.field}]:[]);return addMissingDependencies(e,t)};export const runDepsCommand=async(e,{logger:r})=>{var n,i;let o,s,d,p,l,c=a(e.projectRoot,"package.json"),{content:f,packageJson:m}=await w(c),u=await x(e.projectRoot,r),g=(n=findSdkPeerMismatches({packageJson:m,useClerk:u}),o=y(m),s=j.flatMap(e=>k.filter(r=>o[e]?.[r]!==void 0).map(r=>({kind:"remove",field:e,name:r}))),[...n.map(S),...s]);if(0===g.length)return void r.success("package.json already declares every package the SDK needs. Nothing to change.");await t(c,(i=M(m,g),d=/^[ \t]+(?=")/m.exec(f)?.[0]??" ",p=f.includes("\r\n")?"\r\n":"\n",l=/\r?\n$/.test(f)?p:"",JSON.stringify(i,null,d).replace(/\n/g,p)+l));let v=h(process.env.npm_config_user_agent),$=void 0===v?"install the dependencies with your package manager":v.install;r.success("Updated package.json:"),r.info(["",...g.map(D),"",`Next step: ${$}`].join("\n"))};
@@ -1 +1 @@
1
- export { findSdkPeerMismatches, runDepsCommand } from './deps.js';
1
+ export { type MissingDependency, addMissingDependencies, addMissingSdkPeers, findSdkPeerMismatches, runDepsCommand, } from './deps.js';
@@ -1 +1 @@
1
- export{findSdkPeerMismatches,runDepsCommand}from"./deps.js";
1
+ export{addMissingDependencies,addMissingSdkPeers,findSdkPeerMismatches,runDepsCommand}from"./deps.js";
@@ -1 +1 @@
1
- import{readFileSync as e}from"fs";import{fileURLToPath as r}from"url";import{z as t}from"zod";let a=t.object({peerDependencies:t.record(t.string(),t.string()).default({}),peerDependenciesMeta:t.record(t.string(),t.object({optional:t.boolean().optional()})).default({})}),o=r(new URL("../../../../package.json",import.meta.url));export const readSdkManifest=()=>{let r=a.safeParse(JSON.parse(e(o,"utf-8")));if(!r.success)throw Error(`The SDK's package.json at ${o} has no readable peerDependencies: ${r.error.message}. The SDK installation is damaged; reinstall @salsita-ai/sdk.`);let{peerDependencies:t,peerDependenciesMeta:s}=r.data;return{peerDependencies:t,optionalPeers:Object.entries(s).filter(([,e])=>!0===e.optional).map(([e])=>e)}};
1
+ import{readFileSync as e}from"fs";import{dirname as r,join as t}from"path";import{fileURLToPath as a}from"url";import{z as o}from"zod";let s=o.object({peerDependencies:o.record(o.string(),o.string()).default({}),peerDependenciesMeta:o.record(o.string(),o.object({optional:o.boolean().optional()})).default({})}),i=t(r(a(import.meta.url)),"../../../../package.json");export const readSdkManifest=()=>{let r=s.safeParse(JSON.parse(e(i,"utf-8")));if(!r.success)throw Error(`The SDK's package.json at ${i} has no readable peerDependencies: ${r.error.message}. The SDK installation is damaged; reinstall @salsita-ai/sdk.`);let{peerDependencies:t,peerDependenciesMeta:a}=r.data;return{peerDependencies:t,optionalPeers:Object.entries(a).filter(([,e])=>!0===e.optional).map(([e])=>e)}};
@@ -1,5 +1,5 @@
1
- import{mkdir as e}from"node:fs/promises";import{dirname as r}from"node:path";import{format as t}from"node:util";import{createServer as o}from"vite";import{resolveGeneratedEnvFile as s}from"@salsita-ai/common/env";import{startEditorServer as n}from"../editor-server/index.js";import{getDevelopmentCredentialHint as i}from"../services/development-credential.js";import{ApplicationSpecProjectWatcher as a,LinguiWatcher as l,LogBus as c,MockTemplateWatcher as p,PhoenixApplication as d,PhoenixPubSub as u,PhoenixStore as m,VariantPreviewService as w,WebhookTunnelMonitor as v,createBusLogger as g,getViteDevConfig as h,patchConsole as f,setViteLogSink as E}from"../services/index.js";import{prepareDevelopmentEnvironment as b}from"../services/prepare-development-environment.js";import{createWebhookTunnelTransport as S,readOrCreateTunnelSessionId as k,startWebhookService as I}from"../services/webhook-service/index.js";import{startTui as $}from"../tui/index.js";import{FileLogger as x,createLogger as j,exists as P}from"../utils/index.js";import{buildWebhooks as R,setLogger as T,webhookLogContext as N}from"../webhooks/index.js";import{generateProjectFilesAndInstallDependencies as y}from"./generate-project-files.js";import{readGeneratedEnvMarkers as D}from"./generated-env-markers.js";export const runDevCommand=async(_,U)=>{let{logger:O}=U,{sdkVersion:L,projectSlug:M,environmentSlug:V,cliUseWorkspace:W,enableEditor:G,editorWsPort:Y,debug:C=!1,withLingui:H=!1,persistenceMode:B,force:X=!1,tui:q=!1,serverUrl:J,credential:Q,skipUpload:z}=_,A=null,F=null,K=null,Z=null,ee=null,er=null,et=null,eo=new x,es=new u,en=new c,ei=q&&!!process.stdout.isTTY&&!!process.stdin.isTTY,ea=!ei,el=null;q&&!ei&&O.warn("TUI requested but stdin/stdout is not an interactive terminal — falling back to plain log output. Run phoenix dev --tui directly in a terminal to use the TUI.");let ec=null,ep=O,ed=null,eu=async(t,o)=>{let n=s(".");await e(r(n),{recursive:!0}),await b({serverUrl:t.serverUrl,projectSlug:M,environmentSlug:V,credential:t.credential,outFile:n,skipUpload:o.skipUpload,overrideSchema:!0,debug:o.debug,projectVersion:L},{logger:ep})},em=()=>{el&&(el(),el=null),ec&&(ec.unmount(),ec=null,ep=j({debug:C,fileLogger:eo}))},ew=(e=0)=>ed||(ed=(async()=>{process.off("SIGINT",ev),process.off("SIGTERM",ev),process.off("uncaughtException",eg),em(),ep.debug("Shutting down...");let r=[];for(let e of[{name:"lingui watcher",close:()=>Z?.close()},{name:"project watcher",close:()=>er?.close()},{name:"mock template watcher",close:()=>ee?.close()},{name:"editor server",close:()=>K?.close()},{name:"variant previews",close:()=>et?.close()},{name:"vite server",close:()=>A?.close()},{name:"webhook tunnel",close:()=>F?.stop()}])try{ep.debug(`Shutting down ${e.name}`),await e.close()}catch(t){r.push(`${e.name}: ${t instanceof Error?t.message:String(t)}`)}r.length>0&&ep.warn(`Cleanup warnings:
2
- ${r.join("\n ")}`),ep.debug("Shutdown complete"),await eo.close(),process.exit(e)})()),ev=()=>{ew(0)},eg=e=>{em(),ep.error(`Uncaught exception: ${e.message}`),ew(1)};process.once("SIGINT",ev),process.once("SIGTERM",ev),process.once("uncaughtException",eg);try{await eo.init(".phoenix"),ep=g({bus:en,stream:"spec",debug:C,fileLogger:eo,echo:!0}),E((e,r)=>en.push("vite",e,r),{echo:ea}),T({transports:[],log:(e,...r)=>{en.push("webhook","warn"===e||"error"===e?e:"info",t(...r)),ea&&process.stdout.write(`${t(e,...r)}
1
+ import{mkdir as e}from"node:fs/promises";import{dirname as r}from"node:path";import{format as t}from"node:util";import{createServer as o}from"vite";import{resolveGeneratedEnvFile as s}from"@salsita-ai/common/env";import{generateProjectFiles as n}from"../application-spec/index.js";import{startEditorServer as i}from"../editor-server/index.js";import{getDevelopmentCredentialHint as a}from"../services/development-credential.js";import{ApplicationSpecProjectWatcher as l,LinguiWatcher as c,LogBus as p,MockTemplateWatcher as d,PhoenixApplication as u,PhoenixPubSub as m,PhoenixStore as w,VariantPreviewService as v,WebhookTunnelMonitor as g,createBusLogger as h,getViteDevConfig as f,patchConsole as E,setViteLogSink as b}from"../services/index.js";import{prepareDevelopmentEnvironment as S}from"../services/prepare-development-environment.js";import{createWebhookTunnelTransport as k,readOrCreateTunnelSessionId as I,startWebhookService as $}from"../services/webhook-service/index.js";import{startTui as x}from"../tui/index.js";import{FileLogger as j,createLogger as P,exists as R}from"../utils/index.js";import{buildWebhooks as T,setLogger as N,webhookLogContext as y}from"../webhooks/index.js";import{readGeneratedEnvMarkers as D}from"./generated-env-markers.js";export const runDevCommand=async(_,U)=>{let{logger:O}=U,{sdkVersion:L,projectSlug:M,environmentSlug:V,cliUseWorkspace:W,enableEditor:G,editorWsPort:Y,debug:C=!1,withLingui:H=!1,persistenceMode:B,force:X=!1,tui:q=!1,serverUrl:J,credential:Q,skipUpload:z}=_,A=null,F=null,K=null,Z=null,ee=null,er=null,et=null,eo=new j,es=new m,en=new p,ei=q&&!!process.stdout.isTTY&&!!process.stdin.isTTY,ea=!ei,el=null;q&&!ei&&O.warn("TUI requested but stdin/stdout is not an interactive terminal — falling back to plain log output. Run phoenix dev --tui directly in a terminal to use the TUI.");let ec=null,ep=O,ed=null,eu=async(t,o)=>{let n=s(".");await e(r(n),{recursive:!0}),await S({serverUrl:t.serverUrl,projectSlug:M,environmentSlug:V,credential:t.credential,outFile:n,skipUpload:o.skipUpload,overrideSchema:!0,debug:o.debug,projectVersion:L},{logger:ep})},em=()=>{el&&(el(),el=null),ec&&(ec.unmount(),ec=null,ep=P({debug:C,fileLogger:eo}))},ew=(e=0)=>ed||(ed=(async()=>{process.off("SIGINT",ev),process.off("SIGTERM",ev),process.off("uncaughtException",eg),em(),ep.debug("Shutting down...");let r=[];for(let e of[{name:"lingui watcher",close:()=>Z?.close()},{name:"project watcher",close:()=>er?.close()},{name:"mock template watcher",close:()=>ee?.close()},{name:"editor server",close:()=>K?.close()},{name:"variant previews",close:()=>et?.close()},{name:"vite server",close:()=>A?.close()},{name:"webhook tunnel",close:()=>F?.stop()}])try{ep.debug(`Shutting down ${e.name}`),await e.close()}catch(t){r.push(`${e.name}: ${t instanceof Error?t.message:String(t)}`)}r.length>0&&ep.warn(`Cleanup warnings:
2
+ ${r.join("\n ")}`),ep.debug("Shutdown complete"),await eo.close(),process.exit(e)})()),ev=()=>{ew(0)},eg=e=>{em(),ep.error(`Uncaught exception: ${e.message}`),ew(1)};process.once("SIGINT",ev),process.once("SIGTERM",ev),process.once("uncaughtException",eg);try{await eo.init(".phoenix"),ep=h({bus:en,stream:"spec",debug:C,fileLogger:eo,echo:!0}),b((e,r)=>en.push("vite",e,r),{echo:ea}),N({transports:[],log:(e,...r)=>{en.push("webhook","warn"===e||"error"===e?e:"info",t(...r)),ea&&process.stdout.write(`${t(e,...r)}
3
3
  `)}}),es.browserConsole$.subscribe(e=>{en.push("browser",e.level,e.source?`[${e.source}] ${e.message}`:e.message);let r=`[${e.source?`browser:${e.source}`:"browser"}] ${e.message}`;eo.write("warn",r),ea&&process.stderr.write(`⚠️ ${r}
4
- `)}),ea&&(el=f(en,{echo:!0})),process.env.NODE_ENV="development",B&&(process.env.PERSISTENCE_MODE=B);let e=!B||"server"===B;e&&J&&(process.env.SERVER_URL=J);let r=e&&J?new v(J):void 0;if(ep.step("Starting development mode"),!await P("spec")){ep.error('Spec folder not found. Run "phoenix init" first.'),await ew(1);return}if(e){if(!J||!Q)throw Error("Server persistence needs a server and a credential. Run `phoenix login <workspace>`, or create a development environment in Studio and paste its .env block into .env.");let e=s("."),r=await D(e);r?.PHOENIX_PROJECT_SLUG!==M||r.PHOENIX_ENVIRONMENT_SLUG!==V||r.PHOENIX_SERVER_URL!==J?(ep.step("Preparing development deployment"),await eu({serverUrl:J,credential:Q},{skipUpload:z,debug:C})):ep.debug(`${e} matches the current development environment, skipping prepare`)}ep.step("Building project files");let{templateFiles:c}=await y({sdkVersion:L,projectSlug:M,environmentSlug:V,cliUseWorkspace:W,enableEditor:G,withLingui:H,force:X},{logger:ep});if(ep.success("Project files built successfully"),ei&&(ep=g({bus:en,stream:"spec",debug:C,fileLogger:eo}),el=f(en),ec=$(en,{onQuit:()=>void ew(0)})),H?(Z=new l({logger:ep})).start():ep.warn("Lingui is disabled: i18n messages are not extracted or compiled during dev. Pass --withLingui or set WITH_LINGUI=true to enable."),e&&(ep.step("Building webhooks"),await N.run("webhook",async()=>{await R({experimental:!0,skipNodeEnvOverride:!0,webhookEntryPoint:"./.phoenix/.swc/.phoenix/webhook.js"})})),e&&J&&Q){let e=s("."),t=await D(e);if(!t?.DEPLOYMENT_ID)throw Error(`Webhook tunnel cannot start because ${e} has no DEPLOYMENT_ID. Rerun phoenix dev to prepare the development deployment.`);let o=await k();F=await I({experimental:!0,transport:S({serverUrl:J,credential:Q,projectSlug:M,environmentSlug:V}),rejectionHint:i(Q,M),environmentSlug:V,deploymentId:t.DEPLOYMENT_ID,sessionId:o,onStatus:(e,s)=>{r?.setStatus(e,{deploymentId:t.DEPLOYMENT_ID,sessionId:o,message:s??null})},onRequest:e=>r?.record(e)}),r?.setStatus("waiting",{deploymentId:t.DEPLOYMENT_ID,sessionId:o}),F.stopped.catch(e=>{em(),ep.error(`Webhook tunnel failed: ${e instanceof Error?e.message:String(e)}`),ew(1)}),ep.success("Webhook tunnel started")}er=new a({pubsub:es,logger:ep,onRebuilt:()=>Z?.trigger(),onViteServerChange:e=>{A=e},sdkVersion:L,projectSlug:M,environmentSlug:V,cliUseWorkspace:W,enableEditor:G??!0,inlineTemplates:!1,useServer:e});let u=new m;if(et=new d({store:u,pubsub:es,variantPreviews:new w({projectRoot:process.cwd()},{store:u,logger:ep,projectWatcher:er})}),G&&Y){ep.step("Starting editor WebSocket server");let t=parseInt(Y,10);K=n({port:t,projectRoot:process.cwd(),application:et,logger:ep,logBus:en,tunnelMonitor:r,debug:C,prepareDeployment:e&&J&&Q?()=>eu({serverUrl:J,credential:Q},{skipUpload:!0,debug:!1}):void 0}),await K.ready,ep.debug(`Editor WebSocket server started on port ${t}`),(ee=new p({projectRoot:process.cwd(),pubsub:es,logger:ep})).start()}let b=await h({templateFiles:c});A=await o(b),await A.listen(),ep.step("Starting Vite dev server"),er.start(A);let x=A.resolvedUrls?.local[0];if(ei)ep.success("Vite dev server started — watching for changes"),x&&ep.info(`Preview: ${x}`),G&&Y&&ep.info(`Editor WebSocket: ws://localhost:${Y}`);else if(C)ep.success("Vite dev server started"),x&&ep.info(`Preview: ${x}`);else{let e=e=>{en.push("spec","info",e),process.stdout.write(`${e}
5
- `)};e("\n\uD83D\uDE80 Phoenix Dev Server\n"),x&&(e(`Preview: ${x}`),eo.write("info",`Preview: ${x}`)),G&&Y&&e(`Editor WebSocket: ws://localhost:${Y}`),e("\n\uD83D\uDC40 Watching for changes...\n")}}catch(e){em(),ep.error(`Dev mode failed: ${e instanceof Error?e.message:String(e)}`,e),await ew(1)}};
4
+ `)}),ea&&(el=E(en,{echo:!0})),process.env.NODE_ENV="development",B&&(process.env.PERSISTENCE_MODE=B);let e=!B||"server"===B;e&&J&&(process.env.SERVER_URL=J);let r=e&&J?new g(J):void 0;if(ep.step("Starting development mode"),!await R("spec")){ep.error('Spec folder not found. Run "phoenix init" first.'),await ew(1);return}if(e){if(!J||!Q)throw Error("Server persistence needs a server and a credential. Run `phoenix login <workspace>`, or create a development environment in Studio and paste its .env block into .env.");let e=s("."),r=await D(e);r?.PHOENIX_PROJECT_SLUG!==M||r.PHOENIX_ENVIRONMENT_SLUG!==V||r.PHOENIX_SERVER_URL!==J?(ep.step("Preparing development deployment"),await eu({serverUrl:J,credential:Q},{skipUpload:z,debug:C})):ep.debug(`${e} matches the current development environment, skipping prepare`)}ep.step("Building project files");let{templateFiles:p}=await n({sdkVersion:L,projectSlug:M,environmentSlug:V,cliUseWorkspace:W,enableEditor:G,withLingui:H,force:X},{logger:ep});if(ep.success("Project files built successfully"),ei&&(ep=h({bus:en,stream:"spec",debug:C,fileLogger:eo}),el=E(en),ec=x(en,{onQuit:()=>void ew(0)})),H?(Z=new c({logger:ep})).start():ep.warn("Lingui is disabled: i18n messages are not extracted or compiled during dev. Pass --withLingui or set WITH_LINGUI=true to enable."),e&&(ep.step("Building webhooks"),await y.run("webhook",async()=>{await T({experimental:!0,skipNodeEnvOverride:!0,webhookEntryPoint:"./.phoenix/.swc/.phoenix/webhook.js"})})),e&&J&&Q){let e=s("."),t=await D(e);if(!t?.DEPLOYMENT_ID)throw Error(`Webhook tunnel cannot start because ${e} has no DEPLOYMENT_ID. Rerun phoenix dev to prepare the development deployment.`);let o=await I();F=await $({experimental:!0,transport:k({serverUrl:J,credential:Q,projectSlug:M,environmentSlug:V}),rejectionHint:a(Q,M),environmentSlug:V,deploymentId:t.DEPLOYMENT_ID,sessionId:o,onStatus:(e,s)=>{r?.setStatus(e,{deploymentId:t.DEPLOYMENT_ID,sessionId:o,message:s??null})},onRequest:e=>r?.record(e)}),r?.setStatus("waiting",{deploymentId:t.DEPLOYMENT_ID,sessionId:o}),F.stopped.catch(e=>{em(),ep.error(`Webhook tunnel failed: ${e instanceof Error?e.message:String(e)}`),ew(1)}),ep.success("Webhook tunnel started")}er=new l({pubsub:es,logger:ep,onRebuilt:()=>Z?.trigger(),onViteServerChange:e=>{A=e},sdkVersion:L,projectSlug:M,environmentSlug:V,cliUseWorkspace:W,enableEditor:G??!0,inlineTemplates:!1,useServer:e});let m=new w;if(et=new u({store:m,pubsub:es,variantPreviews:new v({projectRoot:process.cwd()},{store:m,logger:ep,projectWatcher:er})}),G&&Y){ep.step("Starting editor WebSocket server");let t=parseInt(Y,10);K=i({port:t,projectRoot:process.cwd(),application:et,logger:ep,logBus:en,tunnelMonitor:r,debug:C,prepareDeployment:e&&J&&Q?()=>eu({serverUrl:J,credential:Q},{skipUpload:!0,debug:!1}):void 0}),await K.ready,ep.debug(`Editor WebSocket server started on port ${t}`),(ee=new d({projectRoot:process.cwd(),pubsub:es,logger:ep})).start()}let S=await f({templateFiles:p});A=await o(S),await A.listen(),ep.step("Starting Vite dev server"),er.start(A);let j=A.resolvedUrls?.local[0];if(ei)ep.success("Vite dev server started — watching for changes"),j&&ep.info(`Preview: ${j}`),G&&Y&&ep.info(`Editor WebSocket: ws://localhost:${Y}`);else if(C)ep.success("Vite dev server started"),j&&ep.info(`Preview: ${j}`);else{let e=e=>{en.push("spec","info",e),process.stdout.write(`${e}
5
+ `)};e("\n\uD83D\uDE80 Phoenix Dev Server\n"),j&&(e(`Preview: ${j}`),eo.write("info",`Preview: ${j}`)),G&&Y&&e(`Editor WebSocket: ws://localhost:${Y}`),e("\n\uD83D\uDC40 Watching for changes...\n")}}catch(e){em(),ep.error(`Dev mode failed: ${e instanceof Error?e.message:String(e)}`,e),await ew(1)}};
@@ -1 +1 @@
1
- import{runCommand as t}from"../utils/index.js";import{formatFiles as e}from"./prettier.js";export const runFixCommand=async(r,i)=>{let{logger:s}=i,n=!0===r.lint||!0===r.format,o=!n||!0===r.lint,a=!n||!0===r.format;try{s.step("Running fixes"),o&&await t({command:"eslint",args:["src","--fix","--no-error-on-unmatched-pattern"],description:"ESLint fix",quiet:!0},{logger:s}),a&&(s.step("Prettier fix"),await e(".",{logger:s}),s.success("Prettier fix completed")),s.success("Fixes completed!")}catch(t){s.error(`Fix failed: ${t instanceof Error?t.message:String(t)}`,t),process.exit(1)}};
1
+ import{eslintConfigArgs as e}from"../check-configs/index.js";import{runSdkTool as t}from"../utils/index.js";import{formatFiles as r}from"./prettier.js";export const runFixCommand=async(i,s)=>{let{logger:o}=s,n=!0===i.lint||!0===i.format,a=!n||!0===i.lint,c=!n||!0===i.format;try{o.step("Running fixes"),a&&await t({tool:{packageName:"eslint",binName:"eslint"},args:["src","--fix","--no-error-on-unmatched-pattern",...e()],description:"ESLint fix",quiet:!0},{logger:o}),c&&(o.step("Prettier fix"),await r(".",{logger:o}),o.success("Prettier fix completed")),o.success("Fixes completed!")}catch(e){o.error(`Fix failed: ${e instanceof Error?e.message:String(e)}`,e),process.exit(1)}};
@@ -1,15 +1,27 @@
1
1
  import type { CommandContext } from './types.js';
2
+ /**
3
+ * The versions of the tools the SDK runs itself and editors load from the project, taken from the SDK's own
4
+ * `dependencies`, so the editor and `phoenix check` use the same release.
5
+ */
6
+ export interface EditorToolVersions {
7
+ readonly eslint: string;
8
+ readonly prettier: string;
9
+ }
2
10
  export interface InitCommandProps {
3
11
  readonly sdkVersion: string;
12
+ readonly editorToolVersions: EditorToolVersions;
4
13
  /** Directory to initialize; defaults to the working directory. */
5
14
  readonly projectRoot?: string;
6
15
  }
7
16
  /**
8
- * Starts a Phoenix project: writes a `package.json` that depends on this CLI's SDK version when the folder has none,
9
- * the starter spec and the pnpm settings the first install needs, adds the `dev`, `build`, `deploy`, `check` and `fix`
10
- * scripts the project does not have yet, and switches the project to the application-spec pipeline. It touches no
11
- * server and asks nothing: the starter spec names the default project of whichever workspace the developer signs in
12
- * to, and everything else is generated by sync or the build.
17
+ * Starts a Phoenix project: writes a `package.json` that depends on this CLI's SDK version when the folder has none
18
+ * and the starter spec, and switches the project to the application-spec pipeline. The project's `package.json` gains
19
+ * what it does not have yet: the SDK's required peers, ESLint and Prettier, and the `dev`, `build`, `deploy`, `check`
20
+ * and `fix` scripts. An entry the project already has stays as it is. It writes no package-manager settings or
21
+ * `packageManager` field: the project installs with any package manager, and its maintainer owns those settings.
22
+ * The next steps it prints name the package manager that ran it. It touches no server and asks nothing: the starter
23
+ * spec names the default project of whichever workspace the developer signs in to, and everything else is generated
24
+ * by sync or the build.
13
25
  *
14
26
  * Refuses when a `spec/` folder exists, and when an existing `package.json` does not depend on the SDK.
15
27
  */
@@ -1 +1 @@
1
- import{existsSync as e}from"fs";import{mkdir as n,readFile as t,writeFile as i}from"fs/promises";import{basename as o,dirname as r,join as p}from"path";import{ensureWorkspaceInstallSettings as s}from"../utils/index.js";import{starterSpecFiles as a}from"./init-starter-spec.js";let c="@salsita-ai/sdk",l={dev:"phoenix dev",build:"phoenix build",deploy:"phoenix deploy",check:"phoenix check",fix:"phoenix fix"},d=async e=>{let n=`Install the SDK first (\`pnpm add ${c}\`), then rerun \`pnpm phoenix init\`.`,i=JSON.parse(await t(e,"utf-8"));if("object"!=typeof i||null===i||Array.isArray(i))throw Error(`phoenix init could not read package.json because it is not a JSON object. ${n}`);if(!["dependencies","devDependencies"].some(e=>{let n=Reflect.get(i,e);return"object"==typeof n&&null!==n&&c in n}))throw Error(`phoenix init found no ${c} dependency in package.json. ${n}`);return{...i}},h=async e=>{for(let t of a){let o=p(e,t.path);await n(r(o),{recursive:!0}),await i(o,t.content)}},f=async(e,n)=>{let t=n.phoenix,o=n.scripts,r="object"==typeof o&&null!==o?o:{},p=Object.fromEntries(Object.entries(l).filter(([e])=>!(e in r)));await i(e,JSON.stringify({...n,scripts:{...r,...p},phoenix:{..."object"==typeof t&&null!==t?t:{},applicationFlow:!0}},null,2)+"\n")};export const runInitCommand=async(t,{logger:i})=>{var r,a;let u,m=t.projectRoot??process.cwd(),x=p(m,"package.json");if(e(p(m,"spec")))throw Error("phoenix init found an existing spec/ folder. init only starts new projects, and writing a starter spec would overwrite or mix with the existing one. To update an existing project, run `pnpm phoenix sync`; to start over, run init in an empty project folder.");let w=e(x)?await d(x):(r=m,a=t.sdkVersion,{name:(u=o(r).toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^[._-]+|[-]+$/g,"")).length>0?u:"phoenix-configurator",private:!0,type:"module",scripts:l,dependencies:{[c]:a},devDependencies:{"@lingui/cli":"5.9.5","@lingui/swc-plugin":"5.11.0"}});i.step(`Writing the starter project to ${m}`),await n(m,{recursive:!0}),await h(m),await f(x,w),s(m),i.success(`Phoenix project created in ${m}.`),i.info("\nNext steps, in the project folder:\n pnpm install\n pnpm phoenix sync\n pnpm phoenix login <workspace>\n pnpm phoenix dev\n pnpm phoenix deploy\n\nDeveloping against a Studio development environment instead? Paste its .env block into .env before phoenix dev.")};
1
+ import{existsSync as e}from"fs";import{mkdir as t,readFile as i,writeFile as n}from"fs/promises";import{basename as o,dirname as r,join as a}from"path";import{findPackageManagerCommands as s}from"../utils/index.js";import{addMissingDependencies as p,addMissingSdkPeers as c}from"./deps/index.js";import{starterSpecFiles as d}from"./init-starter-spec.js";let l="@salsita-ai/sdk",h={dev:"phoenix dev",build:"phoenix build",deploy:"phoenix deploy",check:"phoenix check",fix:"phoenix fix"},f=(e,t)=>void 0===e?`\`phoenix ${t}\` through your package manager`:`\`${e.phoenix(t)}\``,u=async(e,t)=>{let n=void 0===t?`add ${l} with your package manager`:`\`${t.add(l)}\``,o=`Install the SDK first (${n}), then rerun ${f(t,"init")}.`,r=JSON.parse(await i(e,"utf-8"));if("object"!=typeof r||null===r||Array.isArray(r))throw Error(`phoenix init could not read package.json because it is not a JSON object. ${o}`);if(!["dependencies","devDependencies"].some(e=>{let t=Reflect.get(r,e);return"object"==typeof t&&null!==t&&l in t}))throw Error(`phoenix init found no ${l} dependency in package.json. ${o}`);return{...r}},m=async e=>{for(let i of d){let o=a(e,i.path);await t(r(o),{recursive:!0}),await n(o,i.content)}},x=async(e,t,i)=>{let o=t.phoenix,r=t.scripts,a="object"==typeof r&&null!==r?r:{},s=Object.fromEntries(Object.entries(h).filter(([e])=>!(e in a))),d=p(c({...t,scripts:{...a,...s}},{useClerk:!1}),Object.entries(i).map(([e,t])=>({name:e,version:t,field:"devDependencies"})));await n(e,JSON.stringify({...d,phoenix:{..."object"==typeof o&&null!==o?o:{},applicationFlow:!0}},null,2)+"\n")};export const runInitCommand=async(i,{logger:n})=>{var r,p;let c,d,h=i.projectRoot??process.cwd(),g=a(h,"package.json"),j=s(process.env.npm_config_user_agent);if(e(a(h,"spec")))throw Error(`phoenix init found an existing spec/ folder. init only starts new projects, and writing a starter spec would overwrite or mix with the existing one. To update an existing project, run ${f(j,"sync")}; to start over, run init in an empty project folder.`);let y=e(g)?await u(g,j):(r=h,p=i.sdkVersion,{name:(c=o(r).toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^[._-]+|[-]+$/g,"")).length>0?c:"phoenix-configurator",private:!0,type:"module",scripts:{},dependencies:{[l]:p}});n.step(`Writing the starter project to ${h}`),await t(h,{recursive:!0}),await m(h),await x(g,y,i.editorToolVersions),n.success(`Phoenix project created in ${h}.`),n.info(["",...(d=["sync","login <workspace>","dev","deploy"],void 0===j?["Next steps, in the project folder, through your package manager:"," install the dependencies",...d.map(e=>` phoenix ${e}`)]:["Next steps, in the project folder:",` ${j.install}`,...d.map(e=>` ${j.phoenix(e)}`)]),"","Developing against a Studio development environment instead? Paste its .env block into .env before phoenix dev."].join("\n"))};
@@ -1 +1 @@
1
- import{relative as e,resolve as t}from"path";import{addWorkspaceOverrides as a,getSdkPackages as i,getWorkspaceDir as n,runCommand as o}from"../utils/index.js";export const runLinkCommand=async(s,r)=>{let{logger:c}=r,l=s.sdkPath??"../configurator-phoenix";try{c.step("Linking local SDK packages");let s=t(l);c.debug(`SDK path: ${s}`);let r=i(s);c.debug(`Found ${r.length} packages to link`);let p=n(),g={};r.forEach(({name:t,path:a})=>{let i=e(p,a);g[t]=`file:${i}`,c.debug(` ${t} -> ${i}`)}),a(g),c.success(`Linked ${r.length} SDK packages`),await o({command:"pnpm",args:["install","--config.optimistic-repeat-install=false"],description:"Installing packages",quiet:!0},{logger:c}),c.info("\nNext step:"),c.info(" Run: phoenix dev")}catch(e){throw c.error(`Failed to link SDK packages: ${e instanceof Error?e.message:String(e)}. The SDK path must contain a packages/libs directory. Use --sdk-path flag to specify correct SDK location.`,e),e}};
1
+ import{relative as e,resolve as t}from"path";import{addWorkspaceOverrides as o,assertPnpmProject as r,getSdkPackages as a,getWorkspaceDir as n}from"../utils/index.js";export const runLinkCommand=async(s,i)=>{let{logger:c}=i,l=s.sdkPath??"../configurator-phoenix";try{r({projectRoot:process.cwd(),command:"link"})}catch(e){throw c.error(e instanceof Error?e.message:String(e)),e}try{c.step("Linking local SDK packages");let r=t(l);c.debug(`SDK path: ${r}`);let s=a(r);c.debug(`Found ${s.length} packages to link`);let i=n(),p={};s.forEach(({name:t,path:o})=>{let r=e(i,o);p[t]=`file:${r}`,c.debug(` ${t} -> ${r}`)}),o(p),c.success(`Linked ${s.length} SDK packages`),c.info("\nNext steps:\n pnpm install --config.optimistic-repeat-install=false\n phoenix dev")}catch(e){throw c.error(`Failed to link SDK packages: ${e instanceof Error?e.message:String(e)}. The SDK path must contain a packages/libs directory. Use --sdk-path flag to specify correct SDK location.`,e),e}};
@@ -1 +1 @@
1
- import{readFile as t,writeFile as e}from"fs/promises";import{globby as o}from"globby";import{resolve as i}from"path";import*as r from"prettier";let a=["**/node_modules/**","**/dist/**","**/.git/**","**/.phoenix/**","**/locales/*/*.ts","pnpm-lock.yaml",".linguirc"];export const formatFiles=async(n,l)=>{let{logger:f}=l,s=await o("."===n?"**/*":n,{gitignore:!0,ignore:a}),c=0;for(let o of s)try{let a=i(o),n=await t(a,"utf-8"),l=await r.resolveConfig(a);if((await r.getFileInfo(a)).ignored)continue;let f=await r.format(n,{...l,filepath:a});f!==n&&(await e(a,f,"utf-8"),c++)}catch(t){}c>0&&f.info(`Formatted ${c} file${1!==c?"s":""}`)};export const checkFiles=async(e,n)=>{let{logger:l}=n,f=await o("."===e?"**/*":e,{gitignore:!0,ignore:a}),s=[];for(let e of f)try{let o=i(e),a=await t(o,"utf-8"),n=await r.resolveConfig(o);if((await r.getFileInfo(o)).ignored)continue;await r.check(a,{...n,filepath:o})||s.push(e)}catch(t){}return!(s.length>0)||(l.error(`Found ${s.length} unformatted file${1!==s.length?"s":""}:`),s.forEach(t=>{console.error(` - ${t}`)}),!1)};
1
+ import{readFile as t,writeFile as o}from"fs/promises";import{globby as e}from"globby";import{resolve as r}from"path";import*as i from"prettier";import{prettierrc as a}from"@salsita-ai/common/prettier";let n=["**/node_modules/**","**/dist/**","**/.git/**","**/.phoenix/**","**/locales/*/*.ts","pnpm-lock.yaml","pnpm-workspace.yaml","package-lock.json","npm-shrinkwrap.json","yarn.lock",".yarnrc.yml","bun.lock","bun.lockb",".linguirc"];export const formatFiles=async(l,f)=>{let{logger:c}=f,s=await e("."===l?"**/*":l,{gitignore:!0,ignore:n}),m=0;for(let e of s)try{let n=r(e),l=await t(n,"utf-8"),f=await i.resolveConfig(n)??a;if((await i.getFileInfo(n)).ignored)continue;let c=await i.format(l,{...f,filepath:n});c!==l&&(await o(n,c,"utf-8"),m++)}catch(t){}m>0&&c.info(`Formatted ${m} file${1!==m?"s":""}`)};export const checkFiles=async(o,l)=>{let{logger:f}=l,c=await e("."===o?"**/*":o,{gitignore:!0,ignore:n}),s=[];for(let o of c)try{let e=r(o),n=await t(e,"utf-8"),l=await i.resolveConfig(e)??a;if((await i.getFileInfo(e)).ignored)continue;await i.check(n,{...l,filepath:e})||s.push(o)}catch(t){}return!(s.length>0)||(f.error(`Found ${s.length} unformatted file${1!==s.length?"s":""}:`),s.forEach(t=>{console.error(` - ${t}`)}),!1)};
@@ -1 +1 @@
1
- import{ensureWorkspaceInstallSettings as e,runCommand as s}from"../utils/index.js";import{generateProjectFilesAndInstallDependencies as c}from"./generate-project-files.js";export const runSyncCommand=async(t,i)=>{let{logger:r}=i,{sdkVersion:n,projectSlug:o,environmentSlug:l,cliUseWorkspace:a,enableEditor:p,force:m=!1,analyze:u=!1}=t;try{r.step("Syncing Phoenix project files"),e(process.cwd()),await s({command:"pnpm",args:["install"],description:"Installing packages",quiet:!0},{logger:r}),r.step("Building project files"),await c({sdkVersion:n,projectSlug:o,environmentSlug:l,cliUseWorkspace:a,enableEditor:p,inlineTemplates:!0,force:m,analyze:u},i),r.success("Project files built successfully"),r.success("Sync completed successfully!")}catch(e){r.error(`Sync failed: ${e instanceof Error?e.message:String(e)}`,e),process.exit(1)}};
1
+ import{generateProjectFiles as e}from"../application-spec/index.js";export const runSyncCommand=async(s,c)=>{let{logger:i}=c,{sdkVersion:r,projectSlug:t,environmentSlug:n,cliUseWorkspace:o,enableEditor:l,force:p=!1,analyze:a=!1}=s;try{i.step("Syncing Phoenix project files"),i.step("Building project files"),await e({sdkVersion:r,projectSlug:t,environmentSlug:n,cliUseWorkspace:o,enableEditor:l,inlineTemplates:!0,force:p,analyze:a},c),i.success("Project files built successfully"),i.success("Sync completed successfully!")}catch(e){i.error(`Sync failed: ${e instanceof Error?e.message:String(e)}`,e),process.exit(1)}};
@@ -1 +1 @@
1
- import{getLocalOverrides as n,removeWorkspaceOverrides as e,runCommand as i}from"../utils/index.js";export const runUnlinkCommand=async a=>{let{logger:s}=a;try{s.step("Unlinking local SDK packages");let a=n();if(0===a.length)return void s.info("No linked SDK packages found");s.debug(`Found ${a.length} linked packages`),a.forEach(n=>{s.debug(` Unlinked ${n}`)}),e(a),s.success(`Unlinked ${a.length} SDK packages`),await i({command:"pnpm",args:["install","--config.optimistic-repeat-install=false"],description:"Installing packages",quiet:!0},{logger:s}),s.info("\nNext step:"),s.info(" Run: phoenix dev")}catch(n){throw s.error(`Failed to unlink SDK packages: ${n instanceof Error?n.message:String(n)}. pnpm-workspace.yaml may be missing or invalid. Check that an overrides section exists in pnpm-workspace.yaml.`),n}};
1
+ import{assertPnpmProject as n,getLocalOverrides as e,removeWorkspaceOverrides as r}from"../utils/index.js";export const runUnlinkCommand=async o=>{let{logger:i}=o;try{n({projectRoot:process.cwd(),command:"unlink"})}catch(n){throw i.error(n instanceof Error?n.message:String(n)),n}try{i.step("Unlinking local SDK packages");let n=e();if(0===n.length)return void i.info("No linked SDK packages found");i.debug(`Found ${n.length} linked packages`),n.forEach(n=>{i.debug(` Unlinked ${n}`)}),r(n),i.success(`Unlinked ${n.length} SDK packages`),i.info("\nNext steps:\n pnpm install --config.optimistic-repeat-install=false\n phoenix dev")}catch(n){throw i.error(`Failed to unlink SDK packages: ${n instanceof Error?n.message:String(n)}. pnpm-workspace.yaml may be missing or invalid. Check that an overrides section exists in pnpm-workspace.yaml.`),n}};
@@ -14,8 +14,6 @@ export interface ApplicationSpecProjectWatcherConfig {
14
14
  readonly projectSlug: string;
15
15
  readonly environmentSlug: string;
16
16
  readonly cliUseWorkspace?: boolean;
17
- readonly name?: string;
18
- readonly description?: string;
19
17
  readonly enableEditor: boolean;
20
18
  readonly inlineTemplates: boolean;
21
19
  readonly useServer: boolean;
@@ -1,4 +1,4 @@
1
- import{mkdirSync as e}from"fs";import{resolve as t}from"path";import i from"promise-queue";import{Subject as s,buffer as r,debounceTime as o}from"rxjs";import{createServer as n,normalizePath as l}from"vite";import{watch as a}from"#package/watch";import{ApplicationSpecBuilder as h}from"../application-spec/application-spec-builder.js";import{logDiagnostics as c}from"../application-spec/metrics/index.js";import{syncTemplateFiles as u}from"../application-spec/template-files.js";import{buildWebhooks as p}from"../webhooks/index.js";import{getViteDevConfig as g}from"./vite-config.js";export const WATCH_PATTERNS=["spec/**/*.{yaml,yml}","src/**/*.{ts,tsx,yaml,yml,json,html,css}","templates/*.html",".env",".env.generated",".phoenix/.env.generated"];export const IGNORED_PATTERNS=["src/locales/**/*.{ts,tsx}",".phoenix/!(.env.generated)/**"];export class ApplicationSpecProjectWatcher{watcher=null;subscription=null;rebuildQueue=new i(1,1/0);changeSubject$=new s;viteServer=null;pubsub;logger;onRebuilt;onViteServerChange;builder;useServer;isShuttingDown=!1;suspended=!1;heldChanges=new Set;constructor(e){this.pubsub=e.pubsub,this.logger=e.logger,this.onRebuilt=e.onRebuilt,this.onViteServerChange=e.onViteServerChange,this.builder=new h({logger:e.logger,sdkVersion:e.sdkVersion,projectSlug:e.projectSlug,environmentSlug:e.environmentSlug,cliUseWorkspace:e.cliUseWorkspace,name:e.name,description:e.description,enableEditor:e.enableEditor,inlineTemplates:e.inlineTemplates}),this.useServer=e.useServer}start(e){this.viteServer=e,this.setupFileWatcher(),this.setupRebuildSubscription()}applyVariantFiles(e){this.rebuildQueue.add(async()=>{this.isShuttingDown||await this.rebuild(new Set(e.map(e=>e.fileName)),!1,!0)})}suspend(){this.suspended=!0}resume(){for(let e of(this.suspended=!1,this.heldChanges))this.changeSubject$.next(e);this.heldChanges.clear()}async close(){this.isShuttingDown=!0,this.watcher&&(await this.watcher.close(),this.watcher=null),this.subscription?.unsubscribe(),this.changeSubject$.complete()}setupFileWatcher(){e(t(process.cwd(),"src"),{recursive:!0}),this.watcher=a(WATCH_PATTERNS,{ignored:IGNORED_PATTERNS,cwd:process.cwd(),persistent:!0,ignoreInitial:!1}),this.watcher.on("all",(e,t)=>{if("change"===e||"add"===e||"unlink"===e){if(this.suspended)return void this.heldChanges.add(t);this.logger.info(`
1
+ import{mkdirSync as e}from"fs";import{resolve as t}from"path";import i from"promise-queue";import{Subject as s,buffer as r,debounceTime as o}from"rxjs";import{createServer as n,normalizePath as l}from"vite";import{watch as h}from"#package/watch";import{ApplicationSpecBuilder as a}from"../application-spec/application-spec-builder.js";import{logDiagnostics as c}from"../application-spec/metrics/index.js";import{syncTemplateFiles as u}from"../application-spec/template-files.js";import{buildWebhooks as p}from"../webhooks/index.js";import{getViteDevConfig as g}from"./vite-config.js";export const WATCH_PATTERNS=["spec/**/*.{yaml,yml}","src/**/*.{ts,tsx,yaml,yml,json,html,css}","templates/*.html",".env",".env.generated",".phoenix/.env.generated"];export const IGNORED_PATTERNS=["src/locales/**/*.{ts,tsx}",".phoenix/!(.env.generated)/**"];export class ApplicationSpecProjectWatcher{watcher=null;subscription=null;rebuildQueue=new i(1,1/0);changeSubject$=new s;viteServer=null;pubsub;logger;onRebuilt;onViteServerChange;builder;useServer;isShuttingDown=!1;suspended=!1;heldChanges=new Set;constructor(e){this.pubsub=e.pubsub,this.logger=e.logger,this.onRebuilt=e.onRebuilt,this.onViteServerChange=e.onViteServerChange,this.builder=new a({logger:e.logger,sdkVersion:e.sdkVersion,projectSlug:e.projectSlug,environmentSlug:e.environmentSlug,cliUseWorkspace:e.cliUseWorkspace,enableEditor:e.enableEditor,inlineTemplates:e.inlineTemplates}),this.useServer=e.useServer}start(e){this.viteServer=e,this.setupFileWatcher(),this.setupRebuildSubscription()}applyVariantFiles(e){this.rebuildQueue.add(async()=>{this.isShuttingDown||await this.rebuild(new Set(e.map(e=>e.fileName)),!1,!0)})}suspend(){this.suspended=!0}resume(){for(let e of(this.suspended=!1,this.heldChanges))this.changeSubject$.next(e);this.heldChanges.clear()}async close(){this.isShuttingDown=!0,this.watcher&&(await this.watcher.close(),this.watcher=null),this.subscription?.unsubscribe(),this.changeSubject$.complete()}setupFileWatcher(){e(t(process.cwd(),"src"),{recursive:!0}),this.watcher=h(WATCH_PATTERNS,{ignored:IGNORED_PATTERNS,cwd:process.cwd(),persistent:!0,ignoreInitial:!1}),this.watcher.on("all",(e,t)=>{if("change"===e||"add"===e||"unlink"===e){if(this.suspended)return void this.heldChanges.add(t);this.logger.info(`
2
2
  📝 Detected ${e}: ${t}`),this.changeSubject$.next(t)}})}setupRebuildSubscription(){let e=this.changeSubject$.pipe(o(10));this.subscription=this.changeSubject$.pipe(r(e)).subscribe(e=>{let t=new Set(e),i=t.has(".env");this.rebuildQueue.add(async()=>{this.isShuttingDown||(this.logger.info(`
3
3
  🔨 Rebuilding spec files...
4
- `),await this.rebuild(t,i,!1))})})}async rebuild(e,i,s){try{let r=this.viteServer;if(!r)throw Error("Cannot rebuild the project: the watcher has no Vite server yet, because it was not started. Start the watcher before applying files");let o=await u();if(this.isShuttingDown)return;let a=await this.builder.build({compile:!s});if(this.isShuttingDown)return;if(c(a.diagnostics,this.logger),!a.ok){for(let e of a.errors)this.logger.error(`[${e.code}] ${e.message}${e.file?` (${e.file})`:""}`);this.pubsub.specFile$.next({rawProjectFiles:a.rawProjectFiles,projectRoot:process.cwd()});return}this.onRebuilt?.();let{application:h,changedFiles:d}=a,w=r.moduleGraph,b=Date.now(),f=new Set,S=process.cwd(),m=e=>{let t=w.getModulesByFile(l(e));if(t)for(let e of t)w.invalidateModule(e,f,b,!0)};for(let i of e)m(t(S,i));for(let e of d)m(t(S,`.phoenix/${e.path}`));if(this.pubsub.specFile$.next({rawProjectFiles:h.rawProjectFiles,projectRoot:process.cwd(),configurationSchemaHash:h.applicationSpec.configurator.configurationSchema.hash}),this.isShuttingDown)return;if(i){if(await r.close(),this.isShuttingDown)return;let e=await g({templateFiles:o});if(this.isShuttingDown)return;let t=await n(e);if(this.isShuttingDown||(await t.listen(),this.isShuttingDown))return void await t.close();this.viteServer=t,this.onViteServerChange?.(t),this.logger.success("Vite server restarted (env changed)")}if(this.useServer&&!s){if(this.logger.step("Building webhooks"),await p({experimental:!0,skipNodeEnvOverride:!0,webhookEntryPoint:"./.phoenix/.swc/.phoenix/webhook.js",preserveExistingOutput:!0}),this.isShuttingDown)return;this.logger.success("Webhooks rebuilt successfully")}this.logger.success("Project files rebuilt successfully")}catch(e){this.logger.error(`Build failed: ${e instanceof Error?e.message:String(e)}`,e)}}}
4
+ `),await this.rebuild(t,i,!1))})})}async rebuild(e,i,s){try{let r=this.viteServer;if(!r)throw Error("Cannot rebuild the project: the watcher has no Vite server yet, because it was not started. Start the watcher before applying files");let o=await u();if(this.isShuttingDown)return;let h=await this.builder.build({compile:!s});if(this.isShuttingDown)return;if(c(h.diagnostics,this.logger),!h.ok){for(let e of h.errors)this.logger.error(`[${e.code}] ${e.message}${e.file?` (${e.file})`:""}`);this.pubsub.specFile$.next({rawProjectFiles:h.rawProjectFiles,projectRoot:process.cwd()});return}this.onRebuilt?.();let{application:a,changedFiles:d}=h,w=r.moduleGraph,b=Date.now(),f=new Set,S=process.cwd(),m=e=>{let t=w.getModulesByFile(l(e));if(t)for(let e of t)w.invalidateModule(e,f,b,!0)};for(let i of e)m(t(S,i));for(let e of d)m(t(S,`.phoenix/${e.path}`));if(this.pubsub.specFile$.next({rawProjectFiles:a.rawProjectFiles,projectRoot:process.cwd(),configurationSchemaHash:a.applicationSpec.configurator.configurationSchema.hash}),this.isShuttingDown)return;if(i){if(await r.close(),this.isShuttingDown)return;let e=await g({templateFiles:o});if(this.isShuttingDown)return;let t=await n(e);if(this.isShuttingDown||(await t.listen(),this.isShuttingDown))return void await t.close();this.viteServer=t,this.onViteServerChange?.(t),this.logger.success("Vite server restarted (env changed)")}if(this.useServer&&!s){if(this.logger.step("Building webhooks"),await p({experimental:!0,skipNodeEnvOverride:!0,webhookEntryPoint:"./.phoenix/.swc/.phoenix/webhook.js",preserveExistingOutput:!0}),this.isShuttingDown)return;this.logger.success("Webhooks rebuilt successfully")}this.logger.success("Project files rebuilt successfully")}catch(e){this.logger.error(`Build failed: ${e instanceof Error?e.message:String(e)}`,e)}}}
@@ -1,4 +1,12 @@
1
1
  import { type Logger } from '../utils/index.js';
2
+ /**
3
+ * The project's Lingui configuration, which sync generates, relative to the project root. The Lingui
4
+ * CLI, the Lingui Vite plugin and the Lingui macros in the Vite builds are always given this path, so a
5
+ * `.linguirc` that earlier SDK versions left in the project root is not read. Lingui searches the
6
+ * working directory instead only when the named file is missing; generation writes it with the rest of
7
+ * `.phoenix/` before Phoenix runs Lingui or Vite.
8
+ */
9
+ export declare const LINGUI_CONFIG_PATH = ".phoenix/.linguirc";
2
10
  interface LinguiCommandContext {
3
11
  readonly logger: Logger;
4
12
  }
@@ -1 +1 @@
1
- import{runCommand as i}from"../utils/index.js";let n=async n=>{await i({command:"lingui",args:["extract"],description:"Extracting i18n messages",quiet:!0,extraEnv:{LC_ALL:"en_US.UTF-8"}},n)};export const compileLingui=async n=>{await i({command:"lingui",args:["compile"],description:"Compiling i18n messages",quiet:!0},n)};export const extractAndCompileLingui=async i=>{await n(i),await compileLingui(i)};
1
+ import{runSdkTool as i}from"../utils/index.js";export const LINGUI_CONFIG_PATH=".phoenix/.linguirc";let n=async n=>{await i({tool:{packageName:"@lingui/cli",binName:"lingui"},args:["extract","--config",LINGUI_CONFIG_PATH],description:"Extracting i18n messages",quiet:!0,extraEnv:{LC_ALL:"en_US.UTF-8"}},n)};export const compileLingui=async n=>{await i({tool:{packageName:"@lingui/cli",binName:"lingui"},args:["compile","--config",LINGUI_CONFIG_PATH],description:"Compiling i18n messages",quiet:!0},n)};export const extractAndCompileLingui=async i=>{await n(i),await compileLingui(i)};
@@ -1,3 +1,3 @@
1
- import{transform as e}from"@swc/core";import{remove as t}from"fs-extra";import{copyFile as s,mkdir as o,readFile as a,writeFile as i}from"fs/promises";import{globby as r}from"globby";import{dirname as c,relative as l,resolve as n}from"path";import{Subject as p}from"rxjs";import{watch as m}from"#package/watch";import{createLogger as w}from"../utils/index.js";let d=()=>({sourceMaps:!0,module:{type:"es6"},jsc:{target:"es2022",parser:{syntax:"typescript",tsx:!0},transform:{react:{runtime:"automatic"}},keepClassNames:!0,experimental:{plugins:[["@lingui/swc-plugin",{}]]}}}),u=async(e,t,a)=>{let i=process.cwd(),p=n(i,e),m=n(i,t),w=await r(["**/*.{html,css,json,txt,md}","**/.env*"],{cwd:p,ignore:["**/*.{spec,test}.{html,css,json,txt,md}","**/__tests__/**","**/__mocks__/**","**/tsconfig.json",".env.generated"],absolute:!1}),d=0,u=0;for(let e of w)try{let t=n(p,e),a=n(m,e);await o(c(a),{recursive:!0}),await s(t,a),d++}catch(t){u++,console.error(`Failed to copy ${l(i,n(p,e))}:`,t)}if(u>0)throw Error(`Failed to copy ${u} file(s)`);d>0&&a.debug(`Copied ${d} non-compilable file(s)`)};export const compileWithSwc=async(s,p)=>{let{sourceDir:m="src",outDir:f="./node_modules/.phoenix"}=s??{},g=p?.logger??w(),h=process.cwd(),x=n(h,m),_=n(h,f);await t(_);let y=await r(["**/*.{ts,tsx}"],{cwd:x,ignore:["**/*.{spec,test}.{ts,tsx}","**/__tests__/**","**/__mocks__/**"],absolute:!1}),b=d(),$=0,j=0;for(let t of y)try{let s=n(x,t),r=n(_,t.replace(/\.tsx?$/,".js")),l=await a(s,"utf-8"),p=await e(l,{...b,filename:s,sourceMaps:!0,outputPath:r});await o(c(r),{recursive:!0}),await i(r,p.code,"utf-8"),p.map&&await i(`${r}.map`,p.map,"utf-8"),$++}catch(e){j++,console.error(`Failed to compile ${l(h,n(x,t))}:`,e)}if(j>0)throw Error(`Failed to compile ${j} file(s)`);g.isDebug&&g.debug(`Compiled ${$} file(s) with swc`),await u(m,f,g)};let f=async(t,s,r)=>{let l=process.cwd(),p=n(l,s),m=n(l,r),w=d(),u=n(p,t),f=n(m,t.replace(/\.tsx?$/,".js")),g=await a(u,"utf-8"),h=await e(g,{...w,filename:u,sourceMaps:!0,outputPath:f});await o(c(f),{recursive:!0}),await i(f,h.code,"utf-8"),h.map&&await i(`${f}.map`,h.map,"utf-8")},g=async(e,t,a)=>{let i=process.cwd(),r=n(i,t),l=n(i,a),p=n(r,e),m=n(l,e);await o(c(m),{recursive:!0}),await s(p,m)};export const watchWithSwc=async(e,t)=>{let{sourceDir:s="src",outDir:o="./node_modules/.phoenix"}=e??{},a=t?.logger??w(),i=n(process.cwd(),s);a.isDebug&&a.step("Running initial SWC compilation"),await compileWithSwc({sourceDir:s,outDir:o},t),a.isDebug&&a.success("Initial compilation complete");let r=new p,c=m(["**/*.{ts,tsx,html,css,json,txt,md}","../.env*"],{cwd:i,ignored:["**/*.{spec,test}.{ts,tsx}","**/__tests__/**","**/cache.json"],persistent:!0,ignoreInitial:!0});return c.on("all",(e,t)=>{("change"===e||"add"===e)&&r.next({file:t,type:e})}),r.subscribe(async({file:e})=>{let t=l(i,n(i,e));try{e.match(/\.tsx?$/)?(await f(t,s,o),a.fileChanged(t)):(e.match(/\.(html|css|json|txt|md)$/)||e.match(/\.env/))&&(await g(t,s,o),a.fileChanged(t))}catch(e){a.error(`Failed to process ${t}`),a.isDebug&&console.error(e)}}),a.isDebug&&console.log(`
1
+ import{transform as e}from"@swc/core";import{remove as t}from"fs-extra";import{copyFile as s,mkdir as o,readFile as a,writeFile as r}from"fs/promises";import{globby as i}from"globby";import{createRequire as c}from"node:module";import{dirname as l,relative as n,resolve as p}from"path";import{Subject as m}from"rxjs";import{watch as w}from"#package/watch";import{createLogger as d}from"../utils/index.js";let u=()=>({sourceMaps:!0,module:{type:"es6"},jsc:{target:"es2022",parser:{syntax:"typescript",tsx:!0},transform:{react:{runtime:"automatic"}},keepClassNames:!0,experimental:{plugins:[[c(import.meta.url).resolve("@lingui/swc-plugin"),{}]]}}}),f=async(e,t,a)=>{let r=process.cwd(),c=p(r,e),m=p(r,t),w=await i(["**/*.{html,css,json,txt,md}","**/.env*"],{cwd:c,ignore:["**/*.{spec,test}.{html,css,json,txt,md}","**/__tests__/**","**/__mocks__/**","**/tsconfig.json",".env.generated"],absolute:!1}),d=0,u=0;for(let e of w)try{let t=p(c,e),a=p(m,e);await o(l(a),{recursive:!0}),await s(t,a),d++}catch(t){u++,console.error(`Failed to copy ${n(r,p(c,e))}:`,t)}if(u>0)throw Error(`Failed to copy ${u} file(s)`);d>0&&a.debug(`Copied ${d} non-compilable file(s)`)};export const compileWithSwc=async(s,c)=>{let{sourceDir:m="src",outDir:w="./node_modules/.phoenix"}=s??{},g=c?.logger??d(),h=process.cwd(),x=p(h,m),_=p(h,w);await t(_);let y=await i(["**/*.{ts,tsx}"],{cwd:x,ignore:["**/*.{spec,test}.{ts,tsx}","**/__tests__/**","**/__mocks__/**"],absolute:!1}),b=u(),$=0,j=0;for(let t of y)try{let s=p(x,t),i=p(_,t.replace(/\.tsx?$/,".js")),c=await a(s,"utf-8"),n=await e(c,{...b,filename:s,sourceMaps:!0,outputPath:i});await o(l(i),{recursive:!0}),await r(i,n.code,"utf-8"),n.map&&await r(`${i}.map`,n.map,"utf-8"),$++}catch(e){j++,console.error(`Failed to compile ${n(h,p(x,t))}:`,e)}if(j>0)throw Error(`Failed to compile ${j} file(s)`);g.isDebug&&g.debug(`Compiled ${$} file(s) with swc`),await f(m,w,g)};let g=async(t,s,i)=>{let c=process.cwd(),n=p(c,s),m=p(c,i),w=u(),d=p(n,t),f=p(m,t.replace(/\.tsx?$/,".js")),g=await a(d,"utf-8"),h=await e(g,{...w,filename:d,sourceMaps:!0,outputPath:f});await o(l(f),{recursive:!0}),await r(f,h.code,"utf-8"),h.map&&await r(`${f}.map`,h.map,"utf-8")},h=async(e,t,a)=>{let r=process.cwd(),i=p(r,t),c=p(r,a),n=p(i,e),m=p(c,e);await o(l(m),{recursive:!0}),await s(n,m)};export const watchWithSwc=async(e,t)=>{let{sourceDir:s="src",outDir:o="./node_modules/.phoenix"}=e??{},a=t?.logger??d(),r=p(process.cwd(),s);a.isDebug&&a.step("Running initial SWC compilation"),await compileWithSwc({sourceDir:s,outDir:o},t),a.isDebug&&a.success("Initial compilation complete");let i=new m,c=w(["**/*.{ts,tsx,html,css,json,txt,md}","../.env*"],{cwd:r,ignored:["**/*.{spec,test}.{ts,tsx}","**/__tests__/**","**/cache.json"],persistent:!0,ignoreInitial:!0});return c.on("all",(e,t)=>{("change"===e||"add"===e)&&i.next({file:t,type:e})}),i.subscribe(async({file:e})=>{let t=n(r,p(r,e));try{e.match(/\.tsx?$/)?(await g(t,s,o),a.fileChanged(t)):(e.match(/\.(html|css|json|txt|md)$/)||e.match(/\.env/))&&(await h(t,s,o),a.fileChanged(t))}catch(e){a.error(`Failed to process ${t}`),a.isDebug&&console.error(e)}}),a.isDebug&&console.log(`
2
2
  👀 Watching ${s} for changes...
3
3
  `),{stop:async()=>{await c.close(),a.isDebug&&a.info("SWC watcher stopped")}}};
@@ -1 +1 @@
1
- import{lingui as e}from"@lingui/vite-plugin";import i from"@vitejs/plugin-react";import{mkdir as t,readFile as n,writeFile as r}from"fs/promises";import o from"lodash-es/camelCase.js";import{createRequire as a}from"node:module";import{dirname as s,resolve as m}from"path";import{createLogger as l}from"vite";import p from"vite-plugin-css-injected-by-js";import{isUsingLocalSdk as d}from"../utils/package-info.js";import{loadFrontendConfigModule as f}from"./frontend-config.js";import{phxBannerPlugin as c}from"./phx-banner-plugin.js";import{phxCspNoncePlugin as g}from"./phx-csp-nonce-plugin.js";import{phxGlobalIsolationPlugin as u}from"./phx-global-isolation-plugin.js";import{phxLicensesPlugin as h}from"./phx-licenses-plugin.js";import{phxVariantPreviewsPlugin as S}from"./phx-variant-previews-plugin.js";let b=null;export const setViteLogSink=(e,i={})=>{b={sink:e,echo:i.echo??!1}};let y=["react","react-dom","three","@react-three/fiber","@react-three/drei","@react-three/postprocessing","its-fine","@emotion/react","@emotion/styled","@mui/material","@mui/system","@tanstack/react-query","rxjs"],O=e=>{let i=e.DEPLOYMENT_ID;if("string"!=typeof i)throw Error("DEPLOYMENT_ID is required in runtime config");return i};export const getViteDevConfig=async t=>{var n,r;let o,p,c=d(),g=f(),h=g.readRuntimeConfig(),x=g.frontendBuildConfig,D=Object.fromEntries((t?.templateFiles??[]).map(e=>[e,`.phoenix/${e}`]));return{...b&&{customLogger:(n=b.sink,r=b.echo,o=l(),{get hasWarned(){return o.hasWarned},info:(e,i)=>{n("info",e),r&&o.info(e,i)},warn:(e,i)=>{n("warn",e),r&&o.warn(e,i)},warnOnce:(e,i)=>{n("warn",e),r&&o.warnOnce(e,i)},error:(e,i)=>{n("error",e),r&&o.error(e,i)},clearScreen:e=>{r&&o.clearScreen(e)},hasErrorLogged:e=>o.hasErrorLogged(e)}),...b.echo?{}:{clearScreen:!1}},mode:"development",optimizeDeps:{exclude:["@swc/wasm-web"],...c&&{entries:["index.html","admin.html",...t?.templateFiles??[]],force:!0}},...c&&{resolve:{alias:(p=a(m(process.cwd(),"package.json")),y.flatMap(e=>{try{let i=s(p.resolve(`${e}/package.json`));return[{find:RegExp(`^${e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}(/|$)`),replacement:`${i}$1`}]}catch{return[]}}))}},plugins:[i({babel:{plugins:["macros"]}}),e(),{name:"vite:runtime-config",apply:(e,i)=>"build"===i.command||"development"===i.mode,config:e=>{let i=g.readRuntimeConfig(),t=g.frontendBuildConfig;return{...e,define:{...e.define,"phx.frontendEnv":JSON.stringify(i),"globalThis.PHX_SCHEMA_VALIDATOR":JSON.stringify(t.jsonSchemaValidator),"globalThis.PHX_GLTF_DECODER":JSON.stringify(t.gltfDecoder)}}}},u({getDeploymentId:()=>O(g.readRuntimeConfig())}),S()],define:{"process.env":{},"import.meta.env.DEV":!0,"import.meta.env.PROD":!1,"phx.frontendEnv":JSON.stringify(h),"globalThis.PHX_SCHEMA_VALIDATOR":JSON.stringify(x.jsonSchemaValidator),"globalThis.PHX_GLTF_DECODER":JSON.stringify(x.gltfDecoder)},build:{rollupOptions:{input:{index:".phoenix/index.html",admin:".phoenix/admin.html",...D}}},root:m(process.cwd(),"./.phoenix"),server:{watch:{ignored:["./**/*.{ts,tsx}","./.swc/**","../spec/**","../src/**"]}}}};export const getViteBuildConfigs=async a=>{let l=f(),d=l.readRuntimeConfig(),S=l.frontendBuildConfig,b=h(),y=c({sdkVersion:a.sdkVersion,banner:a.banner}),x=[{name:"salsita-configurator",entryFile:"./configurator.ts",mainScriptPath:"./configurator.ts",htmlFiles:["./index.html",...{templateFiles:a.templateFiles}.templateFiles],main:!0,format:"iife"},{name:"salsita-admin",entryFile:"./admin.ts",mainScriptPath:"./admin.ts",htmlFiles:["./admin.html"],main:!1,format:"iife"},{name:"salsita-embedded-admin",entryFile:"./embedded-admin.ts",mainScriptPath:"./embedded-admin.ts",htmlFiles:[],main:!1,format:"es"},{name:"salsita-embedded-configurator",entryFile:"./embedded-configurator.ts",mainScriptPath:"./embedded-configurator.ts",htmlFiles:[],main:!1,format:"es"}].map(f=>({plugins:[i({babel:{plugins:["macros"]}}),e(),p({useStrictCSP:!0}),g(),u({getDeploymentId:()=>O(l.readRuntimeConfig())}),{name:"vite:lib-index",writeBundle:async()=>{if(!f.htmlFiles.length)return;let e="iife"===f.format?`${f.name}.iife.js`:`${f.name}.js`;for(let i of f.htmlFiles){if(f.main&&a.enableEditor&&"./index.html"===i)continue;let o=m("./.phoenix",i),l=m("./.phoenix/dist/frontend",i);await t(s(l),{recursive:!0});let p=(await n(o,"utf-8")).replace(f.mainScriptPath,e);await r(l,p,"utf-8")}}},b,y],build:{outDir:"./dist/frontend",chunkSizeWarningLimit:4e3,lib:{entry:f.entryFile,name:o(f.name),formats:[f.format],fileName:()=>"iife"===f.format?`${f.name}.iife.js`:`${f.name}.js`},rollupOptions:{external:[],output:{assetFileNames:`${f.name}.[ext]`}},minify:!0,emptyOutDir:!1},root:m(process.cwd(),"./.phoenix"),define:{"process.env":{},"process.env.NODE_ENV":JSON.stringify("production"),"phx.frontendEnv":JSON.stringify(d),"globalThis.PHX_SCHEMA_VALIDATOR":JSON.stringify(S.jsonSchemaValidator),"globalThis.PHX_GLTF_DECODER":JSON.stringify(S.gltfDecoder)}}));return a.enableEditor?[...x,{plugins:[i({babel:{plugins:["macros"]}}),e(),p({useStrictCSP:!0}),g(),b,y],build:{outDir:"./dist/frontend",chunkSizeWarningLimit:4e3,rollupOptions:{external:[]},minify:!0,emptyOutDir:!1},root:m(process.cwd(),"./.phoenix"),define:{"process.env":{},"process.env.NODE_ENV":JSON.stringify("production"),"phx.frontendEnv":JSON.stringify(d),"globalThis.PHX_SCHEMA_VALIDATOR":JSON.stringify(S.jsonSchemaValidator),"globalThis.PHX_GLTF_DECODER":JSON.stringify(S.gltfDecoder)}}]:x};
1
+ import{getConfig as e}from"@lingui/conf";import{lingui as i}from"@lingui/vite-plugin";import t from"@vitejs/plugin-react";import{mkdir as n,readFile as r,writeFile as o}from"fs/promises";import a from"lodash-es/camelCase.js";import{createRequire as s}from"node:module";import{dirname as l,resolve as m}from"path";import{createLogger as f}from"vite";import p from"vite-plugin-css-injected-by-js";import{isUsingLocalSdk as d}from"../utils/package-info.js";import{loadFrontendConfigModule as c}from"./frontend-config.js";import{LINGUI_CONFIG_PATH as g}from"./lingui.js";import{phxBannerPlugin as u}from"./phx-banner-plugin.js";import{phxCspNoncePlugin as h}from"./phx-csp-nonce-plugin.js";import{phxGlobalIsolationPlugin as b}from"./phx-global-isolation-plugin.js";import{phxLicensesPlugin as S}from"./phx-licenses-plugin.js";import{phxVariantPreviewsPlugin as y}from"./phx-variant-previews-plugin.js";let O=null;export const setViteLogSink=(e,i={})=>{O={sink:e,echo:i.echo??!1}};let x=["react","react-dom","three","@react-three/fiber","@react-three/drei","@react-three/postprocessing","its-fine","@emotion/react","@emotion/styled","@mui/material","@mui/system","@tanstack/react-query","rxjs"],D=()=>[s(import.meta.url).resolve("@lingui/babel-plugin-lingui-macro"),{linguiConfig:e({configPath:g})}],E=e=>{let i=e.DEPLOYMENT_ID;if("string"!=typeof i)throw Error("DEPLOYMENT_ID is required in runtime config");return i};export const getViteDevConfig=async e=>{var n,r;let o,a,p=d(),u=c(),h=u.readRuntimeConfig(),S=u.frontendBuildConfig,v=D(),j=Object.fromEntries((e?.templateFiles??[]).map(e=>[e,`.phoenix/${e}`]));return{...O&&{customLogger:(n=O.sink,r=O.echo,o=f(),{get hasWarned(){return o.hasWarned},info:(e,i)=>{n("info",e),r&&o.info(e,i)},warn:(e,i)=>{n("warn",e),r&&o.warn(e,i)},warnOnce:(e,i)=>{n("warn",e),r&&o.warnOnce(e,i)},error:(e,i)=>{n("error",e),r&&o.error(e,i)},clearScreen:e=>{r&&o.clearScreen(e)},hasErrorLogged:e=>o.hasErrorLogged(e)}),...O.echo?{}:{clearScreen:!1}},mode:"development",optimizeDeps:{exclude:["@swc/wasm-web"],...p&&{entries:["index.html","admin.html",...e?.templateFiles??[]],force:!0}},...p&&{resolve:{alias:(a=s(m(process.cwd(),"package.json")),x.flatMap(e=>{try{let i=l(a.resolve(`${e}/package.json`));return[{find:RegExp(`^${e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}(/|$)`),replacement:`${i}$1`}]}catch{return[]}}))}},plugins:[t({babel:{plugins:[v]}}),i({configPath:g}),{name:"vite:runtime-config",apply:(e,i)=>"build"===i.command||"development"===i.mode,config:e=>{let i=u.readRuntimeConfig(),t=u.frontendBuildConfig;return{...e,define:{...e.define,"phx.frontendEnv":JSON.stringify(i),"globalThis.PHX_SCHEMA_VALIDATOR":JSON.stringify(t.jsonSchemaValidator),"globalThis.PHX_GLTF_DECODER":JSON.stringify(t.gltfDecoder)}}}},b({getDeploymentId:()=>E(u.readRuntimeConfig())}),y()],define:{"process.env":{},"import.meta.env.DEV":!0,"import.meta.env.PROD":!1,"phx.frontendEnv":JSON.stringify(h),"globalThis.PHX_SCHEMA_VALIDATOR":JSON.stringify(S.jsonSchemaValidator),"globalThis.PHX_GLTF_DECODER":JSON.stringify(S.gltfDecoder)},build:{rollupOptions:{input:{index:".phoenix/index.html",admin:".phoenix/admin.html",...j}}},root:m(process.cwd(),"./.phoenix"),server:{watch:{ignored:["./**/*.{ts,tsx}","./.swc/**","../spec/**","../src/**"]}}}};export const getViteBuildConfigs=async e=>{let s=c(),f=s.readRuntimeConfig(),d=s.frontendBuildConfig,y=D(),O=S(),x=u({sdkVersion:e.sdkVersion,banner:e.banner}),v=[{name:"salsita-configurator",entryFile:"./configurator.ts",mainScriptPath:"./configurator.ts",htmlFiles:["./index.html",...{templateFiles:e.templateFiles}.templateFiles],main:!0,format:"iife"},{name:"salsita-admin",entryFile:"./admin.ts",mainScriptPath:"./admin.ts",htmlFiles:["./admin.html"],main:!1,format:"iife"},{name:"salsita-embedded-admin",entryFile:"./embedded-admin.ts",mainScriptPath:"./embedded-admin.ts",htmlFiles:[],main:!1,format:"es"},{name:"salsita-embedded-configurator",entryFile:"./embedded-configurator.ts",mainScriptPath:"./embedded-configurator.ts",htmlFiles:[],main:!1,format:"es"}].map(c=>({plugins:[t({babel:{plugins:[y]}}),i({configPath:g}),p({useStrictCSP:!0}),h(),b({getDeploymentId:()=>E(s.readRuntimeConfig())}),{name:"vite:lib-index",writeBundle:async()=>{if(!c.htmlFiles.length)return;let i="iife"===c.format?`${c.name}.iife.js`:`${c.name}.js`;for(let t of c.htmlFiles){if(c.main&&e.enableEditor&&"./index.html"===t)continue;let a=m("./.phoenix",t),s=m("./.phoenix/dist/frontend",t);await n(l(s),{recursive:!0});let f=(await r(a,"utf-8")).replace(c.mainScriptPath,i);await o(s,f,"utf-8")}}},O,x],build:{outDir:"./dist/frontend",chunkSizeWarningLimit:4e3,lib:{entry:c.entryFile,name:a(c.name),formats:[c.format],fileName:()=>"iife"===c.format?`${c.name}.iife.js`:`${c.name}.js`},rollupOptions:{external:[],output:{assetFileNames:`${c.name}.[ext]`}},minify:!0,emptyOutDir:!1},root:m(process.cwd(),"./.phoenix"),define:{"process.env":{},"process.env.NODE_ENV":JSON.stringify("production"),"phx.frontendEnv":JSON.stringify(f),"globalThis.PHX_SCHEMA_VALIDATOR":JSON.stringify(d.jsonSchemaValidator),"globalThis.PHX_GLTF_DECODER":JSON.stringify(d.gltfDecoder)}}));return e.enableEditor?[...v,{plugins:[t({babel:{plugins:[y]}}),i({configPath:g}),p({useStrictCSP:!0}),h(),O,x],build:{outDir:"./dist/frontend",chunkSizeWarningLimit:4e3,rollupOptions:{external:[]},minify:!0,emptyOutDir:!1},root:m(process.cwd(),"./.phoenix"),define:{"process.env":{},"process.env.NODE_ENV":JSON.stringify("production"),"phx.frontendEnv":JSON.stringify(f),"globalThis.PHX_SCHEMA_VALIDATOR":JSON.stringify(d.jsonSchemaValidator),"globalThis.PHX_GLTF_DECODER":JSON.stringify(d.gltfDecoder)}}]:v};
@@ -6,9 +6,10 @@ export { createDirectoryFromYaml, exists, scanFolderForFiles, syncChangedFiles,
6
6
  export { FileLogger } from './file-logger.js';
7
7
  export { isInsideGitRepository } from './git/index.js';
8
8
  export { type Logger, type CreateLoggerOptions, createLogger } from './logger.js';
9
- export { addWorkspaceOverrides, ensureWorkspaceInstallSettings, getLocalOverrides, getSdkPackages, getWorkspaceDir, hasLocalOverrides, readPackageJson, removeWorkspaceOverrides, } from './package-info.js';
9
+ export { addWorkspaceOverrides, getLocalOverrides, getSdkPackages, getWorkspaceDir, hasLocalOverrides, readPackageJson, removeWorkspaceOverrides, } from './package-info.js';
10
10
  export { naturalCompare } from './natural-compare.js';
11
+ export { type PackageManagerCommands, assertPnpmProject, findPackageManagerCommands } from './package-manager/index.js';
11
12
  export { toPascalCase } from './pascal-case.js';
12
13
  export { readGitCommit } from './read-git-commit.js';
13
- export { type RunCommandProps, runCommand } from './run-command.js';
14
+ export { type RunCommandProps, type RunSdkToolProps, runCommand, runSdkTool } from './run-command.js';
14
15
  export { type FileUploadInfo, type UploadLinksData, uploadFilesWithPresignedUrls, readUploadLinks, } from './upload-utils.js';
@@ -1 +1 @@
1
- export{askQuestion}from"./ask-question.js";export{checkBundleSizeBudgets}from"./check-bundle-size-budgets.js";export{formatEnvContent,formatEnvLine}from"./env-file.js";export{parseChangelog,getLatestVersion,getVersion,paginateVersions,getVersionNumbers}from"./changelog-parser.js";export{createDirectoryFromYaml,exists,scanFolderForFiles,syncChangedFiles,syncExistingFolders,validateFolders,writeFileIfNotExists,writeFilesIfNotExists,writeRawFiles}from"./file-system.js";export{FileLogger}from"./file-logger.js";export{isInsideGitRepository}from"./git/index.js";export{createLogger}from"./logger.js";export{addWorkspaceOverrides,ensureWorkspaceInstallSettings,getLocalOverrides,getSdkPackages,getWorkspaceDir,hasLocalOverrides,readPackageJson,removeWorkspaceOverrides}from"./package-info.js";export{naturalCompare}from"./natural-compare.js";export{toPascalCase}from"./pascal-case.js";export{readGitCommit}from"./read-git-commit.js";export{runCommand}from"./run-command.js";export{uploadFilesWithPresignedUrls,readUploadLinks}from"./upload-utils.js";
1
+ export{askQuestion}from"./ask-question.js";export{checkBundleSizeBudgets}from"./check-bundle-size-budgets.js";export{formatEnvContent,formatEnvLine}from"./env-file.js";export{parseChangelog,getLatestVersion,getVersion,paginateVersions,getVersionNumbers}from"./changelog-parser.js";export{createDirectoryFromYaml,exists,scanFolderForFiles,syncChangedFiles,syncExistingFolders,validateFolders,writeFileIfNotExists,writeFilesIfNotExists,writeRawFiles}from"./file-system.js";export{FileLogger}from"./file-logger.js";export{isInsideGitRepository}from"./git/index.js";export{createLogger}from"./logger.js";export{addWorkspaceOverrides,getLocalOverrides,getSdkPackages,getWorkspaceDir,hasLocalOverrides,readPackageJson,removeWorkspaceOverrides}from"./package-info.js";export{naturalCompare}from"./natural-compare.js";export{assertPnpmProject,findPackageManagerCommands}from"./package-manager/index.js";export{toPascalCase}from"./pascal-case.js";export{readGitCommit}from"./read-git-commit.js";export{runCommand,runSdkTool}from"./run-command.js";export{uploadFilesWithPresignedUrls,readUploadLinks}from"./upload-utils.js";
@@ -0,0 +1 @@
1
+ export { assertSupportedNodeVersion, findUnsupportedNodeVersionMessage } from './supported-node-version.js';
@@ -0,0 +1 @@
1
+ export{assertSupportedNodeVersion,findUnsupportedNodeVersionMessage}from"./supported-node-version.js";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Explains why the SDK cannot run on the given Node.js version, or returns `undefined` when the version satisfies the
3
+ * SDK's `engines.node` range.
4
+ */
5
+ export declare const findUnsupportedNodeVersionMessage: (version: string) => string | undefined;
6
+ /**
7
+ * Stops the process with a non-zero exit code when the running Node.js does not satisfy the SDK's `engines.node`
8
+ * range. The `phoenix` binary's entry module (`bin.ts`) calls it and only then loads `cli.ts` with a dynamic import:
9
+ * static imports are evaluated before the importing module's body, so on an older Node.js the CLI's own imports could
10
+ * fail with an unrelated error before a check in its body ran.
11
+ */
12
+ export declare const assertSupportedNodeVersion: () => void;
@@ -0,0 +1,4 @@
1
+ import{readFileSync as e}from"node:fs";import{satisfies as o}from"semver";import{z as s}from"zod";let r=s.object({name:s.string(),engines:s.object({node:s.string()})});export const findUnsupportedNodeVersionMessage=s=>{let{name:t,engines:n}=r.parse(JSON.parse(e(new URL("../../../../package.json",import.meta.url),"utf-8")));if(!o(s,n.node,{includePrerelease:!0}))return`${t} requires Node.js ${n.node}, but this is Node.js ${s}.
2
+ The SDK and the tools it runs use Node.js features that older versions do not have, so a command would fail part way through.
3
+ Switch to a Node.js version that satisfies ${n.node} and run the command again.`};export const assertSupportedNodeVersion=()=>{let e=findUnsupportedNodeVersionMessage(process.version);void 0!==e&&(process.stderr.write(`${e}
4
+ `),process.exit(1))};
@@ -10,15 +10,6 @@ export declare const readPackageJson: (path?: string) => PackageJson;
10
10
  export declare const getWorkspaceDir: () => string;
11
11
  export declare const addWorkspaceOverrides: (entries: Record<string, string>) => void;
12
12
  export declare const removeWorkspaceOverrides: (names: readonly string[]) => void;
13
- /**
14
- * Makes a standalone project installable with pnpm 11: its `pnpm-workspace.yaml` decides the build scripts of the
15
- * SDK's dependencies and exempts the SDK's own packages from the minimum release age. Only missing answers are
16
- * added, so a value the project set stays, and the file travels with a deploy so the server-side install follows it.
17
- *
18
- * A project inside a monorepo is left alone: the workspace root owns these settings, and a file in the project
19
- * folder would turn it into a workspace root of its own.
20
- */
21
- export declare const ensureWorkspaceInstallSettings: (projectRoot: string) => void;
22
13
  export declare const hasLocalOverrides: () => boolean;
23
14
  export declare const getLocalOverrides: () => string[];
24
15
  export declare const hasLocalSymlinks: () => boolean;
@@ -1 +1 @@
1
- import{existsSync as e,lstatSync as t,readFileSync as r,readdirSync as s,writeFileSync as o}from"fs";import{dirname as a,join as i,resolve as l}from"path";import{isMap as n,isScalar as c,isSeq as d,parse as p,parseDocument as m}from"yaml";let u="pnpm-workspace.yaml",f="@salsita-ai/";export const readPackageJson=(t=".")=>{let s=l(t,"package.json");if(!e(s))throw Error(`package.json not found at ${s}`);return JSON.parse(r(s,"utf8"))};let g=(t=process.cwd())=>{let r=l(t);for(;;){let t=i(r,u);if(e(t))return t;let s=a(r);if(s===r)return;r=s}},k=()=>g()??i(process.cwd(),u),h=()=>{try{let e=g();if(!e)return{};let t=p(r(e,"utf8"));return t?.overrides??{}}catch{return{}}};export const getWorkspaceDir=()=>a(k());export const addWorkspaceOverrides=t=>{let s=k(),a=m(e(s)?r(s,"utf8"):"");Object.entries(t).forEach(([e,t])=>{a.setIn(["overrides",e],t)}),a.setIn(["optimisticRepeatInstall"],!1),o(s,a.toString())};export const removeWorkspaceOverrides=e=>{let t=g();if(!t)return;let s=m(r(t,"utf8"));e.forEach(e=>{s.deleteIn(["overrides",e])});let a=s.getIn(["overrides"]);n(a)&&0===a.items.length&&s.delete("overrides"),s.delete("optimisticRepeatInstall"),o(t,s.toString())};let x={"@swc/core":!0,esbuild:!0,"es5-ext":!1},y=`${f}*`;export const ensureWorkspaceInstallSettings=t=>{let s=i(t,u);if(!e(s)&&g(t))return;let a=e(s)?r(s,"utf8"):"",l=m(a);n(l.get("allowBuilds"))||l.set("allowBuilds",l.createNode({})),Object.entries(x).forEach(([e,t])=>{"boolean"!=typeof l.getIn(["allowBuilds",e])&&l.setIn(["allowBuilds",e],t)});let p=l.getIn(["minimumReleaseAgeExclude"]);d(p)?p.items.some(e=>c(e)&&e.value===y)||p.add(y):l.setIn(["minimumReleaseAgeExclude"],l.createNode([y]));let f=l.toString();f!==a&&o(s,f)};export const hasLocalOverrides=()=>Object.keys(h()).some(e=>e.startsWith(f));export const getLocalOverrides=()=>Object.keys(h()).filter(e=>e.startsWith(f));let v=["@salsita-ai/common","@salsita-ai/contracts","@salsita-ai/sdk"];export const hasLocalSymlinks=()=>v.some(e=>{let r=l("node_modules",e);try{return t(r).isSymbolicLink()}catch{return!1}});export const isUsingLocalSdk=()=>hasLocalOverrides()||hasLocalSymlinks();export const getSdkPackages=t=>{let r=l(t,"packages/libs");if(!e(r))throw Error(`SDK libs directory not found at ${r}`);return s(r,{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name).map(e=>{let t=i(r,e),s=readPackageJson(t);if(!s.name)throw Error(`Package at ${t} has no name in package.json`);return{name:s.name,path:t}})};
1
+ import{existsSync as e,lstatSync as t,readFileSync as r,readdirSync as s,writeFileSync as o}from"fs";import{dirname as a,join as i,resolve as n}from"path";import{isMap as c,parse as l,parseDocument as p}from"yaml";let m="pnpm-workspace.yaml",d="@salsita-ai/";export const readPackageJson=(t=".")=>{let s=n(t,"package.json");if(!e(s))throw Error(`package.json not found at ${s}`);return JSON.parse(r(s,"utf8"))};let f=(t=process.cwd())=>{let r=n(t);for(;;){let t=i(r,m);if(e(t))return t;let s=a(r);if(s===r)return;r=s}},k=()=>f()??i(process.cwd(),m),h=()=>{try{let e=f();if(!e)return{};let t=l(r(e,"utf8"));return t?.overrides??{}}catch{return{}}};export const getWorkspaceDir=()=>a(k());export const addWorkspaceOverrides=t=>{let s=k(),a=p(e(s)?r(s,"utf8"):"");Object.entries(t).forEach(([e,t])=>{a.setIn(["overrides",e],t)}),a.setIn(["optimisticRepeatInstall"],!1),o(s,a.toString())};export const removeWorkspaceOverrides=e=>{let t=f();if(!t)return;let s=p(r(t,"utf8"));e.forEach(e=>{s.deleteIn(["overrides",e])});let a=s.getIn(["overrides"]);c(a)&&0===a.items.length&&s.delete("overrides"),s.delete("optimisticRepeatInstall"),o(t,s.toString())};export const hasLocalOverrides=()=>Object.keys(h()).some(e=>e.startsWith(d));export const getLocalOverrides=()=>Object.keys(h()).filter(e=>e.startsWith(d));let u=["@salsita-ai/common","@salsita-ai/contracts","@salsita-ai/sdk"];export const hasLocalSymlinks=()=>u.some(e=>{let r=n("node_modules",e);try{return t(r).isSymbolicLink()}catch{return!1}});export const isUsingLocalSdk=()=>hasLocalOverrides()||hasLocalSymlinks();export const getSdkPackages=t=>{let r=n(t,"packages/libs");if(!e(r))throw Error(`SDK libs directory not found at ${r}`);return s(r,{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name).map(e=>{let t=i(r,e),s=readPackageJson(t);if(!s.name)throw Error(`Package at ${t} has no name in package.json`);return{name:s.name,path:t}})};
@@ -0,0 +1,2 @@
1
+ export { type PackageManagerCommands, findPackageManagerCommands } from './package-manager-commands.js';
2
+ export { assertPnpmProject } from './pnpm-project.js';
@@ -0,0 +1 @@
1
+ export{findPackageManagerCommands}from"./package-manager-commands.js";export{assertPnpmProject}from"./pnpm-project.js";
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The commands of a package manager the CLI names in the next steps it prints, so a developer can copy the one for
3
+ * the package manager they use. Phoenix works with any package manager; these only phrase the hints.
4
+ */
5
+ export interface PackageManagerCommands {
6
+ /** Installs the project's dependencies, such as `npm install`. */
7
+ readonly install: string;
8
+ /** Adds a package to the project's dependencies, such as `npm install @salsita-ai/sdk`. */
9
+ readonly add: (packageName: string) => string;
10
+ /** Runs a `phoenix` command from the project's install, such as `npx phoenix sync`. */
11
+ readonly phoenix: (args: string) => string;
12
+ }
13
+ /**
14
+ * The commands of the package manager that started the CLI, read from the `npm_config_user_agent` value npm, pnpm,
15
+ * Yarn and Bun set for the binaries they run (`pnpm/11.1.3 npm/? node/v22.13.0 linux x64`). `undefined` when the CLI
16
+ * was started some other way, such as straight from `node_modules/.bin`, or by a package manager it does not know;
17
+ * the hint then names no package manager.
18
+ */
19
+ export declare const findPackageManagerCommands: (userAgent: string | undefined) => PackageManagerCommands | undefined;
@@ -0,0 +1 @@
1
+ let n=new Map([["pnpm",{install:"pnpm install",add:n=>`pnpm add ${n}`,phoenix:n=>`pnpm phoenix ${n}`}],["npm",{install:"npm install",add:n=>`npm install ${n}`,phoenix:n=>`npx phoenix ${n}`}],["yarn",{install:"yarn install",add:n=>`yarn add ${n}`,phoenix:n=>`yarn phoenix ${n}`}],["bun",{install:"bun install",add:n=>`bun add ${n}`,phoenix:n=>`bunx phoenix ${n}`}]]);export const findPackageManagerCommands=a=>{let p=a?.split("/")[0]?.trim();return void 0===p?void 0:n.get(p)};
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Stops a pnpm-only command in a project that clearly installs with another package manager: one with another
3
+ * package manager's lockfile and no `pnpm-lock.yaml`. A project without any lockfile is let through, as it has not
4
+ * installed yet. Only the project folder is looked at.
5
+ */
6
+ export declare const assertPnpmProject: (props: {
7
+ readonly projectRoot: string;
8
+ readonly command: string;
9
+ }) => void;
@@ -0,0 +1 @@
1
+ import{existsSync as o}from"fs";import{join as t}from"path";let n=["package-lock.json","npm-shrinkwrap.json","yarn.lock","bun.lock","bun.lockb"];export const assertPnpmProject=r=>{if(o(t(r.projectRoot,"pnpm-lock.yaml")))return;let a=n.find(n=>o(t(r.projectRoot,n)));if(void 0!==a)throw Error(`phoenix ${r.command} works with pnpm only, and this project installs with another package manager: it has ${a} and no pnpm-lock.yaml. It is an internal tool for linking a local SDK checkout through the overrides in pnpm-workspace.yaml. Use it in a project that installs with pnpm.`)};
@@ -1,4 +1,5 @@
1
1
  import type { Logger } from './logger.js';
2
+ import { type SdkTool } from './sdk-tool/index.js';
2
3
  export interface RunCommandProps {
3
4
  readonly command: string;
4
5
  readonly args: readonly string[];
@@ -7,6 +8,16 @@ export interface RunCommandProps {
7
8
  readonly cwd?: string;
8
9
  readonly extraEnv?: Record<string, string>;
9
10
  }
11
+ export interface RunSdkToolProps extends Omit<RunCommandProps, 'command'> {
12
+ readonly tool: SdkTool;
13
+ }
10
14
  export declare const runCommand: (props: RunCommandProps, context?: {
11
15
  readonly logger: Logger;
12
16
  }) => Promise<void>;
17
+ /**
18
+ * Runs a tool from the SDK's own installation with the Node.js that runs the CLI. It starts no shell, so paths
19
+ * with spaces reach the tool unchanged.
20
+ */
21
+ export declare const runSdkTool: (props: RunSdkToolProps, context?: {
22
+ readonly logger: Logger;
23
+ }) => Promise<void>;
@@ -1 +1 @@
1
- import{spawn as e}from"node:child_process";import{createLogger as r}from"./logger.js";export const runCommand=async(o,t)=>{let n=t?.logger??r(),{command:s,args:i,description:a,quiet:l=!1,cwd:c,extraEnv:d}=o;l?n.isDebug&&n.debug(`Running: ${s} ${i.join(" ")}`):n.step(a);let u=n.isDebug?"inherit":l?"pipe":"inherit";await new Promise((r,o)=>{let t=e(s,i,{stdio:u,shell:!0,cwd:c,env:d?{...process.env,...d}:void 0}),l=[],f=[],m=!1;t.stdout?.on("data",e=>l.push(Buffer.from(e))),t.stderr?.on("data",e=>f.push(Buffer.from(e))),t.once("error",e=>{m=!0,n.error(`${a} failed to execute`),n.error(`Error: ${e.message}`),o(Error(`Failed to execute command '${s}': ${e.message}. Ensure the command is installed and available in PATH.`))}),t.once("close",(e,t)=>{if(!m){if(0!==e){let r=null!==e?`exit code ${e}`:"unknown error (process was terminated or failed to start)";n.error(`${a} failed with ${r}`),t&&n.error(`Process was killed with signal: ${t}`),l.length>0&&console.error(Buffer.concat(l).toString()),f.length>0&&console.error(Buffer.concat(f).toString()),o(Error(`${a} failed with ${r}`));return}r()}})}),(!l||n.isDebug)&&n.success(`${a} completed`)};
1
+ import{spawn as e}from"node:child_process";import{createLogger as r}from"./logger.js";import{resolveSdkToolBin as o}from"./sdk-tool/index.js";let t=async(o,t)=>{let s=t?.logger??r(),{command:n,file:i,shell:a,startFailureHint:l,args:c,description:d,quiet:m=!1,cwd:u,extraEnv:f}=o;m?s.isDebug&&s.debug(`Running: ${n} ${c.join(" ")}`):s.step(d);let g=s.isDebug?"inherit":m?"pipe":"inherit";await new Promise((r,o)=>{let t=e(i,c,{stdio:g,shell:a,cwd:u,env:f?{...process.env,...f}:void 0}),m=[],p=[],h=!1;t.stdout?.on("data",e=>m.push(Buffer.from(e))),t.stderr?.on("data",e=>p.push(Buffer.from(e))),t.once("error",e=>{h=!0,s.error(`${d} failed to execute`),s.error(`Error: ${e.message}`),o(Error(`Failed to execute command '${n}': ${e.message}. ${l}`))}),t.once("close",(e,t)=>{if(!h){if(0!==e){let r=null!==e?`exit code ${e}`:"unknown error (process was terminated or failed to start)";s.error(`${d} failed with ${r}`),t&&s.error(`Process was killed with signal: ${t}`),m.length>0&&console.error(Buffer.concat(m).toString()),p.length>0&&console.error(Buffer.concat(p).toString()),o(Error(`${d} failed with ${r}`));return}r()}})}),(!m||s.isDebug)&&s.success(`${d} completed`)};export const runCommand=async(e,r)=>{await t({...e,file:e.command,shell:!0,startFailureHint:"Ensure the command is installed and available in PATH."},r)};export const runSdkTool=async(e,r)=>{let{tool:s,args:n,...i}=e;await t({...i,command:s.binName,file:process.execPath,args:[o(s),...n],shell:!1,startFailureHint:"Ensure Node.js can start this process."},r)};
@@ -0,0 +1 @@
1
+ export { type SdkTool, resolveSdkToolBin } from './resolve-sdk-tool-bin.js';