@salsita-ai/sdk 0.50.0-develop.2f8d91de91 → 0.50.0-develop.30ea3b5e1a
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.
- package/dist/application-spec/generate-application/code/project-scaffolding.js +2 -2
- package/dist/application-spec/generate-application/code/standalone-app-files.d.ts +2 -2
- package/dist/application-spec/generate-application/code/standalone-app-files.js +1 -1
- package/dist/application-spec/generate-application/code/templates/index.d.ts +0 -1
- package/dist/application-spec/generate-application/code/templates/index.js +1 -1
- package/dist/application-spec/generate-application/code/templates/package-json.js +1 -1
- package/dist/application-spec/generate-application/code/templates/skills/sdk-content.d.ts +1 -1
- package/dist/application-spec/generate-application/code/templates/skills/sdk-content.js +1 -1
- package/dist/application-spec/generate-application/code/templates/webhook-index.d.ts +6 -1
- package/dist/application-spec/generate-application/code/templates/webhook-index.js +10 -1
- package/dist/application-spec/generate-application/index.d.ts +2 -0
- package/dist/application-spec/generate-application/index.js +1 -1
- package/dist/application-spec/generate-application/runtime/admin-runtime/admin-runtime.d.ts +6 -2
- package/dist/application-spec/generate-application/runtime/admin-runtime/admin-runtime.js +1 -1
- package/dist/application-spec/generate-application/runtime/application-runtime.d.ts +8 -1
- package/dist/application-spec/generate-application/runtime/application-runtime.js +1 -1
- package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-runtime.d.ts +5 -1
- package/dist/application-spec/generate-application/runtime/configurator-runtime/configurator-runtime.js +1 -1
- package/dist/application-spec/generate-application/runtime/factory-data/factory-data-runtime.d.ts +43 -0
- package/dist/application-spec/generate-application/runtime/factory-data/factory-data-runtime.js +1 -0
- package/dist/application-spec/generate-application/runtime/factory-data/index.d.ts +3 -0
- package/dist/application-spec/generate-application/runtime/factory-data/index.js +1 -0
- package/dist/application-spec/generate-application/runtime/factory-data/recipe-defaults.d.ts +13 -0
- package/dist/application-spec/generate-application/runtime/factory-data/recipe-defaults.js +1 -0
- package/dist/application-spec/generate-application/runtime/factory-data/static-violations.d.ts +16 -0
- package/dist/application-spec/generate-application/runtime/factory-data/static-violations.js +1 -0
- package/dist/application-spec/generate-application/runtime/migrations/index.d.ts +1 -0
- package/dist/application-spec/generate-application/runtime/migrations/index.js +1 -0
- package/dist/application-spec/generate-application/runtime/migrations/migration-runtime.d.ts +53 -0
- package/dist/application-spec/generate-application/runtime/migrations/migration-runtime.js +1 -0
- package/dist/application-spec/parse-application-files/categorize/categorize-files.d.ts +6 -0
- package/dist/application-spec/parse-application-files/categorize/categorize-files.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.d.ts +29 -0
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/assistant-system.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.d.ts +7 -1
- package/dist/configurator/application-runtime/extensions/systems/assistant-system/graphql-tools.js +1 -1
- package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.d.ts +6 -0
- package/dist/configurator/application-runtime/extensions/systems/graphql-system/graphql-system.js +1 -1
- package/dist/configurator/common/configurator-interface.d.ts +10 -1
- package/dist/configurator/common/configurator-interface.js +1 -1
- package/dist/configurator/common/index.d.ts +1 -0
- package/dist/configurator/common/index.js +1 -1
- package/dist/configurator/common/use-finalize-action.d.ts +5 -1
- package/dist/configurator/common/use-finalize-action.js +1 -1
- package/dist/configurator/common/use-reset-camera.d.ts +6 -0
- package/dist/configurator/common/use-reset-camera.js +1 -0
- package/dist/configurator/ui/assistant/AssistantChips.d.ts +8 -2
- package/dist/configurator/ui/assistant/AssistantChips.js +1 -1
- package/dist/configurator/ui/assistant/AssistantThread.js +1 -1
- package/dist/docs/index.json +1 -1
- package/dist/docs/layouts/custom-layout.mdx +886 -161
- package/dist/docs/phoenix/configurator-interface.mdx +18 -10
- package/dist/docs/phoenix/layout-slots.mdx +4 -2
- package/dist/docs/phoenix/phoenix-cli.mdx +20 -6
- package/dist/docs/phoenix/project-structure.mdx +8 -3
- package/dist/docs/phoenix/sdk-builder-workflow.mdx +1 -1
- package/dist/docs/phoenix/webhooks.mdx +17 -0
- package/dist/domain/domain-context/index.d.ts +1 -1
- package/dist/domain/domain-context/undo-system.d.ts +28 -1
- package/dist/domain/domain-context/undo-system.js +1 -1
- package/dist/i18n/locales/cs/messages.js +1 -1
- package/dist/i18n/locales/da/messages.js +1 -1
- package/dist/i18n/locales/de/messages.js +1 -1
- package/dist/i18n/locales/de-AT/messages.js +1 -1
- package/dist/i18n/locales/en/messages.js +1 -1
- package/dist/i18n/locales/en-AU/messages.js +1 -1
- package/dist/i18n/locales/en-GB/messages.js +1 -1
- package/dist/i18n/locales/es/messages.js +1 -1
- package/dist/i18n/locales/fr/messages.js +1 -1
- package/dist/i18n/locales/hu/messages.js +1 -1
- package/dist/i18n/locales/it/messages.js +1 -1
- package/dist/i18n/locales/nl/messages.js +1 -1
- package/dist/i18n/locales/pl/messages.js +1 -1
- package/dist/i18n/locales/pt/messages.js +1 -1
- package/dist/i18n/locales/ro/messages.js +1 -1
- package/dist/i18n/locales/sk/messages.js +1 -1
- package/dist/i18n/locales/tr/messages.js +1 -1
- package/dist/phoenix/application-spec/application-spec-builder.js +1 -1
- package/dist/phoenix/commands/check.js +1 -1
- package/dist/phoenix/commands/dev.js +5 -5
- package/dist/phoenix/commands/fix.js +1 -1
- package/dist/phoenix/services/application-spec-project-watcher.d.ts +2 -0
- package/dist/phoenix/services/application-spec-project-watcher.js +3 -3
- package/dist/phoenix/services/swc.js +1 -1
- package/dist/react-sdk/domain-context/index.d.ts +1 -1
- package/dist/react-sdk/domain-context/index.js +1 -1
- package/dist/react-sdk/domain-context/system-hooks/navigation-hooks.d.ts +5 -0
- package/dist/react-sdk/domain-context/system-hooks/navigation-hooks.js +1 -1
- package/dist/ui-sdk/theme/types.d.ts +1 -1
- package/package.json +33 -29
- package/dist/application-spec/generate-application/code/templates/webhook-implementation.d.ts +0 -1
- package/dist/application-spec/generate-application/code/templates/webhook-implementation.js +0 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{GeneratedApplicationFile as e}from"../../core/index.js";import{followsCanaryBuilds as t,generateApplicationSpecEslintConfig as n,generateApplicationSpecFavicon as r,generateApplicationSpecGitignore as o,generateApplicationSpecNvmrc as i,generateApplicationSpecPackageJson as a,generateApplicationSpecPrettierConfig as c,generateApplicationSpecRobotsTxt as s,generateApplicationSpecTsconfig as l,
|
|
1
|
+
import{GeneratedApplicationFile as e}from"../../core/index.js";import{followsCanaryBuilds as t,generateApplicationSpecEslintConfig as n,generateApplicationSpecFavicon as r,generateApplicationSpecGitignore as o,generateApplicationSpecNvmrc as i,generateApplicationSpecPackageJson as a,generateApplicationSpecPrettierConfig as c,generateApplicationSpecRobotsTxt as s,generateApplicationSpecTsconfig as l,generateLinguiRcFile as p,generatePhoenixCliSkill as f,generatePhoenixCreateConfiguratorSkill as m,generatePhoenixCreateConfiguratorSkillReferences as d,generatePhoenixFeedbackSkill as g,generatePhoenixReviewSkill as u,generatePhoenixSkill as x,generatePhoenixVariantsSkill as h,stripSdkMarkerContent as j}from"./templates/index.js";export const agentSkillRoots=[".claude/skills",".agents/skills"];let v=[{path:"CLAUDE.md",generatedPrefix:""},{path:".cursor/rules/phoenix.mdc",generatedPrefix:`---
|
|
2
2
|
description: Phoenix SDK project rules
|
|
3
3
|
globs:
|
|
4
4
|
alwaysApply: true
|
|
5
5
|
---
|
|
6
|
-
`}],
|
|
6
|
+
`}],k=[".claude/commands/review.md",".cursor/commands/review.md"],b=(e,t)=>e.projectFiles.find(e=>e.file.name===t)?.file.content;export const generateProjectScaffolding=F=>{let P,{applicationSpec:w,categorizedFiles:C,sdkVersion:L,projectInGitRepository:S=!0,cliUseWorkspace:$,name:y,description:M}=F,A=b(C,"package.json"),D=b(C,".gitignore"),K=void 0!==$?$:w.appMetadata.workspace,R=(t=>{let n=[],r=[...k];for(let{path:o,generatedPrefix:i}of v){let a=b(t,o);if(void 0===a)continue;let c=j(a,i);void 0===c?r.push(o):c!==a&&n.push(e(o,c,{format:!1}))}return{strippedFiles:n,removedFiles:r}})(C);return{generatedProjectFiles:[e("package.json",a({sdkVersion:L,useWorkspace:K,useClerk:w.appMetadata.useClerk??!1,name:y,description:M,existingContent:A})),e(".nvmrc",i(),{format:!1}),e(".linguirc",p(w.configurator.ui.availableLocales),{format:!1}),e("tsconfig.json",l()),e("eslint.config.js",n()),...S?[e(".gitignore",o(D))]:[],...(P=[{name:"phoenix",content:x({checkLatestCanary:t({useWorkspace:K,sdkVersion:L})}),references:[]},{name:"phoenix-cli",content:f(),references:[]},{name:"phoenix-create-configurator",content:m(),references:d()},{name:"phoenix-feedback",content:g(),references:[]},{name:"phoenix-review",content:u(),references:[]},{name:"phoenix-variants",content:h(),references:[]}],agentSkillRoots.flatMap(t=>P.flatMap(n=>[e(`${t}/${n.name}/SKILL.md`,n.content),...n.references.map(r=>e(`${t}/${n.name}/${r.path}`,r.content))]))),...R.strippedFiles],initialProjectFiles:[e("public/favicon.ico",r(),{binary:!0}),e("public/robots.txt",s(),{format:!1})],prettierFiles:[e("prettier.config.js",c())],removedProjectFiles:R.removedFiles}};
|
|
@@ -18,8 +18,8 @@ import type { ApplicationSpec, CategorizedFiles, RawMockTemplates } from '../../
|
|
|
18
18
|
* The project and environment slugs address the deployed environment the embedding bootstraps talk
|
|
19
19
|
* to, and `enableEditor` together with `inlineTemplates` and the raw mock templates decide whether
|
|
20
20
|
* and how the optional editor entry point is emitted. The categorized files are needed only to find
|
|
21
|
-
* the authored handlers that are implicitly registered or explicitly pinned into the webhook,
|
|
22
|
-
* to bind the runtime.
|
|
21
|
+
* the authored handlers that are implicitly registered or explicitly pinned into the webhook, and
|
|
22
|
+
* to read whether the project has its own webhook entry, not to bind the runtime.
|
|
23
23
|
*/
|
|
24
24
|
export interface GenerateStandaloneAppFilesOptions {
|
|
25
25
|
readonly applicationSpec: ApplicationSpec;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{GeneratedApplicationFile as e}from"../../core/index.js";import{generateApplicationSpecAdminConfig as t,generateApplicationSpecAdminFile as a,generateApplicationSpecConfiguratorFile as o,generateApplicationSpecEditorFile as n,generateApplicationSpecEmbeddedAdmin as
|
|
1
|
+
import{GeneratedApplicationFile as e}from"../../core/index.js";import{generateApplicationSpecAdminConfig as t,generateApplicationSpecAdminFile as a,generateApplicationSpecConfiguratorFile as o,generateApplicationSpecEditorFile as n,generateApplicationSpecEmbeddedAdmin as s,generateApplicationSpecEmbeddedConfigurator as d,generateApplicationSpecFrontendConfig as p,generateApplicationSpecHtmlAdminIndex as i,generateApplicationSpecHtmlIndex as r,generateApplicationSpecWebhookBuilders as m,generateApplicationSpecWebhookIndex as b,generateApplicationSpecWebhooksConfig as l}from"./templates/index.js";import{getWebhookHandlerFileNames as f}from"./webhook-safe-files.js";export const generateStandaloneAppFiles=g=>{let{applicationSpec:h,categorizedFiles:c,projectSlug:w,environmentSlug:k,enableEditor:x,inlineTemplates:M,rawMockTemplates:T}=g,u=T.templates,j=f(c.handlers);return[e("index.html",r(h.appMetadata.webComponentTag,x,h.appMetadata.pageTitle)),e("configurator.ts",o(h.appMetadata.webComponentTag)),e("admin.html",i(h.appMetadata.pageTitle)),e("admin.ts",a()),e("admin-config.ts",t()),e("frontend.config.ts",p(h)),e("webhooks.config.ts",l(h)),e("webhook.ts",b({hasWebhookEntry:c.hasWebhookEntry})),e("webhook-builders.ts",m(h,j)),e("embedded-admin.ts",s(w,k)),e("embedded-configurator.ts",d(w,k)),...x?[e("editor.tsx",n(h.appMetadata.webComponentTag,M,u,k))]:[]]};
|
|
@@ -50,6 +50,5 @@ export { generateApplicationSpecRobotsTxt } from './robots-txt.js';
|
|
|
50
50
|
export { generateApplicationSpecStoryDevDeclaration, generateApplicationSpecStoryPhxModule, generateApplicationSpecStoryRawProjectFiles, generateApplicationSpecStoryWrapper, } from './story/index.js';
|
|
51
51
|
export { generateApplicationSpecTsconfig } from './tsconfig.js';
|
|
52
52
|
export { generateApplicationSpecWebhookBuilders } from './webhook-builders.js';
|
|
53
|
-
export { generateApplicationSpecWebhookImplementation } from './webhook-implementation.js';
|
|
54
53
|
export { generateApplicationSpecWebhookIndex } from './webhook-index.js';
|
|
55
54
|
export { generateApplicationSpecWebhooksConfig } from './webhooks-config.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{stripSdkMarkerContent}from"./common/strip-sdk-marker-content.js";export{generateApplicationSpecAdminConfig}from"./admin-config.js";export{generateApplicationSpecAdminCode}from"./admin-domain-code.js";export{generateApplicationSpecAdminFrontendCode}from"./admin-frontend-code.js";export{generateAdminGlobalBindingBlock,generateApplicationSpecAdminGlobals}from"./admin-globals.js";export{generateApplicationSpecTypesModule}from"./application-types.js";export{generateApplicationSpecAdminFile}from"./admin.js";export{generateApplicationSpecConfiguratorConfig}from"./configurator-config.js";export{generateApplicationSpecConfiguratorCode}from"./configurator-domain-code.js";export{generateApplicationSpecConfiguratorFrontendCode}from"./configurator-frontend-code.js";export{generateApplicationSpecConfiguratorGlobals,generateConfiguratorGlobalBindingBlock}from"./configurator-globals.js";export{generateApplicationSpecConfiguratorFile}from"./configurator.js";export{generateApplicationSpecDomainSpecFile}from"./domain-spec.js";export{generateImportedStateConstants,generatePhxExportsBlock,generatePhxGlobalsBlock,generateStateConstants}from"./domain-spec/index.js";export{generateApplicationSpecDomainFile}from"./domain.js";export{generateApplicationSpecEditorFile}from"./editor.js";export{generateApplicationSpecEmbeddedAdmin}from"./embedded-admin.js";export{generateApplicationSpecEmbeddedConfigurator}from"./embedded-configurator.js";export{generateApplicationSpecEslintConfig}from"./eslint-config.js";export{generateApplicationSpecFavicon}from"./favicon.js";export{generateApplicationSpecFrontendConfig}from"./frontend-config.js";export{generateApplicationSpecGitignore}from"./gitignore.js";export{generateApplicationSpecGlobals}from"./globals.js";export{generateApplicationSpecHtmlAdminIndex}from"./html-admin-index.js";export{generateApplicationSpecHtmlIndex}from"./html-index.js";export{generateLinguiRcFile}from"./lingui-rc.js";export{generateApplicationSpecNvmrc}from"./nvmrc.js";export{generateApplicationSpecPackageJson}from"./package-json.js";export{generatePhoenixCliSkill}from"./skills/phoenix-cli-skill.js";export{generatePhoenixCreateConfiguratorSkill,generatePhoenixCreateConfiguratorSkillReferences}from"./skills/phoenix-create-configurator-skill.js";export{generatePhoenixFeedbackSkill}from"./skills/phoenix-feedback-skill.js";export{generatePhoenixReviewSkill}from"./skills/phoenix-review-skill.js";export{followsCanaryBuilds,generatePhoenixSkill}from"./skills/phoenix-skill.js";export{generatePhoenixVariantsSkill}from"./skills/phoenix-variants-skill.js";export{generateApplicationSpecPrettierConfig}from"./prettier-config.js";export{generateApplicationSpecRobotsTxt}from"./robots-txt.js";export{generateApplicationSpecStoryDevDeclaration,generateApplicationSpecStoryPhxModule,generateApplicationSpecStoryRawProjectFiles,generateApplicationSpecStoryWrapper}from"./story/index.js";export{generateApplicationSpecTsconfig}from"./tsconfig.js";export{generateApplicationSpecWebhookBuilders}from"./webhook-builders.js";export{
|
|
1
|
+
export{stripSdkMarkerContent}from"./common/strip-sdk-marker-content.js";export{generateApplicationSpecAdminConfig}from"./admin-config.js";export{generateApplicationSpecAdminCode}from"./admin-domain-code.js";export{generateApplicationSpecAdminFrontendCode}from"./admin-frontend-code.js";export{generateAdminGlobalBindingBlock,generateApplicationSpecAdminGlobals}from"./admin-globals.js";export{generateApplicationSpecTypesModule}from"./application-types.js";export{generateApplicationSpecAdminFile}from"./admin.js";export{generateApplicationSpecConfiguratorConfig}from"./configurator-config.js";export{generateApplicationSpecConfiguratorCode}from"./configurator-domain-code.js";export{generateApplicationSpecConfiguratorFrontendCode}from"./configurator-frontend-code.js";export{generateApplicationSpecConfiguratorGlobals,generateConfiguratorGlobalBindingBlock}from"./configurator-globals.js";export{generateApplicationSpecConfiguratorFile}from"./configurator.js";export{generateApplicationSpecDomainSpecFile}from"./domain-spec.js";export{generateImportedStateConstants,generatePhxExportsBlock,generatePhxGlobalsBlock,generateStateConstants}from"./domain-spec/index.js";export{generateApplicationSpecDomainFile}from"./domain.js";export{generateApplicationSpecEditorFile}from"./editor.js";export{generateApplicationSpecEmbeddedAdmin}from"./embedded-admin.js";export{generateApplicationSpecEmbeddedConfigurator}from"./embedded-configurator.js";export{generateApplicationSpecEslintConfig}from"./eslint-config.js";export{generateApplicationSpecFavicon}from"./favicon.js";export{generateApplicationSpecFrontendConfig}from"./frontend-config.js";export{generateApplicationSpecGitignore}from"./gitignore.js";export{generateApplicationSpecGlobals}from"./globals.js";export{generateApplicationSpecHtmlAdminIndex}from"./html-admin-index.js";export{generateApplicationSpecHtmlIndex}from"./html-index.js";export{generateLinguiRcFile}from"./lingui-rc.js";export{generateApplicationSpecNvmrc}from"./nvmrc.js";export{generateApplicationSpecPackageJson}from"./package-json.js";export{generatePhoenixCliSkill}from"./skills/phoenix-cli-skill.js";export{generatePhoenixCreateConfiguratorSkill,generatePhoenixCreateConfiguratorSkillReferences}from"./skills/phoenix-create-configurator-skill.js";export{generatePhoenixFeedbackSkill}from"./skills/phoenix-feedback-skill.js";export{generatePhoenixReviewSkill}from"./skills/phoenix-review-skill.js";export{followsCanaryBuilds,generatePhoenixSkill}from"./skills/phoenix-skill.js";export{generatePhoenixVariantsSkill}from"./skills/phoenix-variants-skill.js";export{generateApplicationSpecPrettierConfig}from"./prettier-config.js";export{generateApplicationSpecRobotsTxt}from"./robots-txt.js";export{generateApplicationSpecStoryDevDeclaration,generateApplicationSpecStoryPhxModule,generateApplicationSpecStoryRawProjectFiles,generateApplicationSpecStoryWrapper}from"./story/index.js";export{generateApplicationSpecTsconfig}from"./tsconfig.js";export{generateApplicationSpecWebhookBuilders}from"./webhook-builders.js";export{generateApplicationSpecWebhookIndex}from"./webhook-index.js";export{generateApplicationSpecWebhooksConfig}from"./webhooks-config.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
let e=["@salsita-ai/platform-project-sdk","@salsita-ai/platform-common","@salsita-ai/platform-contracts","@salsita-ai/common","@salsita-ai/contracts"],t={private:!0,type:"module",packageManager:"pnpm@11.1.3",engines:{node:"24.14.1",pnpm:"11.1.3"}},r={"babel-plugin-macros":"3.1.0",vite:"6.4.3","@vitejs/plugin-react":"5.2.0","@swc/cli":"0.8.1","@swc/core":"1.15.40",typescript:"npm:@typescript/typescript6@6.0.2","@lingui/cli":"5.9.5","@types/lodash-es":"4.17.12","@lingui/macro":"5.9.5","@lingui/swc-plugin":"5.11.0","@types/node":"24.12.2","@types/react":"18.3.8","@types/react-dom":"18.3.0","@types/three":"0.160.0","@typescript/native":"npm:typescript@7.0.2",envalid:"8.1.1",eslint:"9.39.4",prettier:"3.8.3",vitest:"4.1.11"},i=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),
|
|
1
|
+
let e=["@salsita-ai/platform-project-sdk","@salsita-ai/platform-common","@salsita-ai/platform-contracts","@salsita-ai/common","@salsita-ai/contracts"],t={private:!0,type:"module",packageManager:"pnpm@11.1.3",engines:{node:"24.14.1",pnpm:"11.1.3"}},r={"babel-plugin-macros":"3.1.0",vite:"6.4.3","@vitejs/plugin-react":"5.2.0","@swc/cli":"0.8.1","@swc/core":"1.15.40",typescript:"npm:@typescript/typescript6@6.0.2","@lingui/cli":"5.9.5","@types/lodash-es":"4.17.12","@lingui/macro":"5.9.5","@lingui/swc-plugin":"5.11.0","@types/node":"24.12.2","@types/react":"18.3.8","@types/react-dom":"18.3.0","@types/three":"0.160.0","@typescript/native":"npm:typescript@7.0.2",envalid:"8.1.1",eslint:"9.39.4",prettier:"3.8.3",vitest:"4.1.11"},i=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),s=e=>{if(!i(e))return;let t=[];for(let[r,i]of Object.entries(e)){if("string"!=typeof i)return;t.push([r,i])}return Object.fromEntries(t)},a=e=>e.replace(/^[\^~]/,""),n=(t,r)=>{let i={};for(let[e,r]of Object.entries(t))i[e]=a(r);if(r)for(let[e,t]of Object.entries(r))e in i||(i[e]=a(t));return Object.fromEntries(Object.entries(i).filter(([t])=>!e.includes(t)).sort(([e],[t])=>e>t?1:e<t?-1:0))};export const generateApplicationSpecPackageJson=e=>{let{sdkVersion:a,useWorkspace:c,useClerk:o=!1,name:p,description:l,existingContent:m}=e,u=(e=>{if(!e)return{};try{let t=JSON.parse(e);if(i(t))return t}catch{}return{}})(m),f=n({...o?{"@clerk/clerk-react":"5.61.8"}:{},"camera-controls":"2.4.2","lodash-es":"4.18.1",react:"18.3.1","react-dom":"18.3.1","@emotion/react":"11.11.3","@emotion/styled":"11.11.0","@mui/material":"5.15.5","@mui/system":"5.16.7","@lingui/core":"5.9.5","@lingui/react":"5.9.5",three:"0.160.1","@react-three/fiber":"8.15.16","@react-three/drei":"9.97.6","@react-three/postprocessing":"2.16.3",postprocessing:"6.36.3",motion:"12.34.0","@tanstack/react-query":"5.100.14",rxjs:"7.8.2",uuid:"14.0.0","ts-pattern":"5.9.0","@salsita-ai/sdk":c?"workspace:^":a,zod:"3.25.76"},s(u.dependencies)),d=n(r,s(u.devDependencies)),y=u.name,g=p?p.toLowerCase().replace(/[^a-z0-9-]/g,"-"):"string"==typeof y?y:"project-name",j={...u,name:g,...t,dependencies:f,devDependencies:d};return void 0!==l&&(j.description=l),JSON.stringify(j,null,2)+"\n"};
|
|
@@ -34,7 +34,7 @@ export declare const sdkGuidanceSections: {
|
|
|
34
34
|
- Finalize over the spec's \`finalizeAction\` components, each naming a handler registered with \`phx.frontend.createPhoenixHandler\`: run each with \`phx.frontend.useFinalizeAction(handler)\` in a component of its own wrapped in \`PhoenixHandlerBoundary\` (from \`@salsita-ai/sdk/react\`), or mount \`FinalizeActions\` (from \`@salsita-ai/sdk/configurator\`) for the built-in buttons. \`finalizePage\` and \`finalizeButton\` are legacy
|
|
35
35
|
- Read mode and fullscreen are the layout's job, no hook enforces them: hide what a viewer must not change while \`phx.frontend.useAccessService().accessInfo.viewMode\` is \`true\`, and remove panels while \`phx.frontend.useIsFullscreenActive()\` is set; \`phx.frontend.useSetFullscreen()\` returns its setter
|
|
36
36
|
- \`src/handlers/\` — Event & lifecycle handlers
|
|
37
|
-
- \`src/webhooks/\` — Server-side webhook handlers (\`phx.webhooks.*Builder\`)
|
|
37
|
+
- \`src/webhooks/\` — Server-side webhook handlers (\`phx.webhooks.*Builder\`); the webhook is the default export of \`src/webhooks/index.ts\`, which you create when the project needs its own handlers — without it the build uses a built-in inert webhook that answers only anonymous auth, so create the file before setting \`useAuthHook\` or \`useClerk\`
|
|
38
38
|
- \`src/migrations/\` — Schema version migrations (v*.ts)
|
|
39
39
|
- \`src/locales/\` — Locale catalogs (authored .po sources; compiled .ts, do not edit)
|
|
40
40
|
- \`src/admin/\` — Admin interface (mirrors main src/ structure)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const sdkGuidanceSections={buildCommands:"## Build Commands\n- `pnpm phoenix build` — Full production build\n- `pnpm phoenix dev` — Development mode with hot reload\n- `pnpm phoenix sync` — Sync generated files without full build",devLogs:"## Dev Logs\n- `pnpm phoenix dev` writes all logs to `.phoenix/phoenix-dev.log`\n- Contains: spec parse errors, build errors, browser runtime errors, file watcher events\n- After making changes, always check the log for errors: `tail -50 .phoenix/phoenix-dev.log` or `grep ERROR .phoenix/phoenix-dev.log`\n- Rotated automatically at 10MB (`.log.1`, `.log.2` are older rotations)",projectStructure:"## Project Structure\n- `spec/` — Domain YAML specs (entities, relations, expressions, invariants, components, application config)\n- `src/expressions/` — Computed/derived entity properties (`phx.domain.implementCustomExpressions()`)\n- `src/actions/` — Domain operations declared under `actions:` in the spec (`phx.domain.implementActions()`), run by controls and exposed to the assistant\n- `src/invariants/` — Business rule constraints (`phx.domain.implementCustomInvariants()`)\n- `src/transformers/` — Automatic state fixers (`phx.frontend.transformerBuilder`)\n- `src/components/` — ECS system components (`phx.domain.attachComponent.withEntity()`)\n- `src/elements/` — Page-level React components (`phx.frontend.createCustomPhoenixLayoutElement()`)\n - `ConfiguratorLayout`: a layout element with this name replaces everything the built-in layout renders for a loaded configuration, in owner and read mode, finalization included. Prefer arranging the spec's layout components; write one for shell-level changes, such as moving the sidebar or adding an area the built-in layout has no place for\n - Mount `LayoutSlots.SharedCanvas` (from `@salsita-ai/sdk/configurator`) in a positioned root covering the page, or the app loader stays on screen; put the UI above it, positioned and after it in the markup. Call `useSceneSafeArea()` (same import) and put `containerRef` on the element covering the whole canvas and `safeAreaRef` on the region the UI leaves free, with `pointerEvents: 'none'`, so the camera frames the scene there\n - Sidebar moved, contents as the spec configures them: mount `LayoutSlots.DesktopSidebar` in a positioned container that sets its size, with `side=\"start\"` on the left; `docs/layouts/sidebar/in-a-custom-layout.mdx` is the whole layout\n - Your own UI: \"Hooks for a Project Layout\" in `docs/phoenix/configurator-interface.mdx` lists the hooks with what each returns (`pnpm phoenix docs -r docs/phoenix/configurator-interface.mdx`), `docs/phoenix/layout-slots.mdx` the built-in pieces you can still mount, and `docs/layouts/custom-layout.mdx` is a worked example\n - Messages: mount `LayoutSlots.Services` for the built-in snackbars, or show violations, side-effect hints and errors yourself with `phx.frontend.useConfiguratorMessages(onMessage)`, not both. Either way mount a snackbar root (`LayoutSlots.DesktopSnackbarsRoot` or `LayoutSlots.MobileSnackbarsRoot`): save and built-in action errors are always snackbars\n - Finalize over the spec's `finalizeAction` components, each naming a handler registered with `phx.frontend.createPhoenixHandler`: run each with `phx.frontend.useFinalizeAction(handler)` in a component of its own wrapped in `PhoenixHandlerBoundary` (from `@salsita-ai/sdk/react`), or mount `FinalizeActions` (from `@salsita-ai/sdk/configurator`) for the built-in buttons. `finalizePage` and `finalizeButton` are legacy\n - Read mode and fullscreen are the layout's job, no hook enforces them: hide what a viewer must not change while `phx.frontend.useAccessService().accessInfo.viewMode` is `true`, and remove panels while `phx.frontend.useIsFullscreenActive()` is set; `phx.frontend.useSetFullscreen()` returns its setter\n- `src/handlers/` — Event & lifecycle handlers\n- `src/webhooks/` — Server-side webhook handlers (`phx.webhooks.*Builder`)
|
|
1
|
+
export const sdkGuidanceSections={buildCommands:"## Build Commands\n- `pnpm phoenix build` — Full production build\n- `pnpm phoenix dev` — Development mode with hot reload\n- `pnpm phoenix sync` — Sync generated files without full build",devLogs:"## Dev Logs\n- `pnpm phoenix dev` writes all logs to `.phoenix/phoenix-dev.log`\n- Contains: spec parse errors, build errors, browser runtime errors, file watcher events\n- After making changes, always check the log for errors: `tail -50 .phoenix/phoenix-dev.log` or `grep ERROR .phoenix/phoenix-dev.log`\n- Rotated automatically at 10MB (`.log.1`, `.log.2` are older rotations)",projectStructure:"## Project Structure\n- `spec/` — Domain YAML specs (entities, relations, expressions, invariants, components, application config)\n- `src/expressions/` — Computed/derived entity properties (`phx.domain.implementCustomExpressions()`)\n- `src/actions/` — Domain operations declared under `actions:` in the spec (`phx.domain.implementActions()`), run by controls and exposed to the assistant\n- `src/invariants/` — Business rule constraints (`phx.domain.implementCustomInvariants()`)\n- `src/transformers/` — Automatic state fixers (`phx.frontend.transformerBuilder`)\n- `src/components/` — ECS system components (`phx.domain.attachComponent.withEntity()`)\n- `src/elements/` — Page-level React components (`phx.frontend.createCustomPhoenixLayoutElement()`)\n - `ConfiguratorLayout`: a layout element with this name replaces everything the built-in layout renders for a loaded configuration, in owner and read mode, finalization included. Prefer arranging the spec's layout components; write one for shell-level changes, such as moving the sidebar or adding an area the built-in layout has no place for\n - Mount `LayoutSlots.SharedCanvas` (from `@salsita-ai/sdk/configurator`) in a positioned root covering the page, or the app loader stays on screen; put the UI above it, positioned and after it in the markup. Call `useSceneSafeArea()` (same import) and put `containerRef` on the element covering the whole canvas and `safeAreaRef` on the region the UI leaves free, with `pointerEvents: 'none'`, so the camera frames the scene there\n - Sidebar moved, contents as the spec configures them: mount `LayoutSlots.DesktopSidebar` in a positioned container that sets its size, with `side=\"start\"` on the left; `docs/layouts/sidebar/in-a-custom-layout.mdx` is the whole layout\n - Your own UI: \"Hooks for a Project Layout\" in `docs/phoenix/configurator-interface.mdx` lists the hooks with what each returns (`pnpm phoenix docs -r docs/phoenix/configurator-interface.mdx`), `docs/phoenix/layout-slots.mdx` the built-in pieces you can still mount, and `docs/layouts/custom-layout.mdx` is a worked example\n - Messages: mount `LayoutSlots.Services` for the built-in snackbars, or show violations, side-effect hints and errors yourself with `phx.frontend.useConfiguratorMessages(onMessage)`, not both. Either way mount a snackbar root (`LayoutSlots.DesktopSnackbarsRoot` or `LayoutSlots.MobileSnackbarsRoot`): save and built-in action errors are always snackbars\n - Finalize over the spec's `finalizeAction` components, each naming a handler registered with `phx.frontend.createPhoenixHandler`: run each with `phx.frontend.useFinalizeAction(handler)` in a component of its own wrapped in `PhoenixHandlerBoundary` (from `@salsita-ai/sdk/react`), or mount `FinalizeActions` (from `@salsita-ai/sdk/configurator`) for the built-in buttons. `finalizePage` and `finalizeButton` are legacy\n - Read mode and fullscreen are the layout's job, no hook enforces them: hide what a viewer must not change while `phx.frontend.useAccessService().accessInfo.viewMode` is `true`, and remove panels while `phx.frontend.useIsFullscreenActive()` is set; `phx.frontend.useSetFullscreen()` returns its setter\n- `src/handlers/` — Event & lifecycle handlers\n- `src/webhooks/` — Server-side webhook handlers (`phx.webhooks.*Builder`); the webhook is the default export of `src/webhooks/index.ts`, which you create when the project needs its own handlers — without it the build uses a built-in inert webhook that answers only anonymous auth, so create the file before setting `useAuthHook` or `useClerk`\n- `src/migrations/` — Schema version migrations (v*.ts)\n- `src/locales/` — Locale catalogs (authored .po sources; compiled .ts, do not edit)\n- `src/admin/` — Admin interface (mirrors main src/ structure)\n- `src/_shared/` — Shared utilities (NOT auto-imported, requires explicit imports)\n- `.phoenix/` — Auto-generated files (DO NOT EDIT, except the option files in `.phoenix/variants/`)\n- `public/` — Static assets (3D models, textures, images, HDRI maps, fonts)\n- `assets/` — Uploadable resources (PDF templates, email assets)",architecturePrinciples:"## Architecture Principles\n- YAML-first: 99% of configuration in spec/*.yaml, custom code is last resort\n- ECS pattern: entities (domain objects) + components (behavior/UI) + systems (SDK runtime)\n- Reactive state: immutable domain state flows through RxJS pipelines\n- Data binding: `$read` (read-only), `$write` (write-only), `$bind` (bidirectional) connect components to domain\n- memoEval: all component implementations must use memoEval for stable object references",keyPatterns:"## Key Patterns\n- Expressions = computed properties on entities (prefix: `$`), implemented per-entity in src/expressions/\n- Actions = named domain operations (`actions:` in YAML with `params` and `result` schemas), implemented in src/actions/, prepared through `actionSystem.prepareAction()` and exposed as assistant mutations through `assistant.actions`\n- Invariants = validation rules returning violations, static or dynamic\n- Transformers = auto-fixers maintaining consistency after state changes\n- Components defined in YAML with `$read`/`$bind` bindings, or custom in src/components/ using attachComponent builder\n- Webhooks = server-side finalization tasks (PDF, email, CSV, image rendering)\n- Filters = contextual component activation via navigationStates, viewStates, modes, selectedEntityIds",fileConventions:`## File Conventions
|
|
2
2
|
- Components: PascalCase (.tsx)
|
|
3
3
|
- Utilities: kebab-case (.ts)
|
|
4
4
|
- Expressions: entity-name.ts
|
|
@@ -1 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
/** Where the generated webhook entry takes its handler from. */
|
|
2
|
+
export interface WebhookIndexOptions {
|
|
3
|
+
/** Whether the project has `src/webhooks/index.ts`; without it the entry holds the built-in webhook. */
|
|
4
|
+
readonly hasWebhookEntry: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare const generateApplicationSpecWebhookIndex: ({ hasWebhookEntry }: WebhookIndexOptions) => string;
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import{autoHeader as e}from"../common/file-headers.js";export const generateApplicationSpecWebhookIndex=()
|
|
1
|
+
import{autoHeader as e}from"../common/file-headers.js";export const generateApplicationSpecWebhookIndex=({hasWebhookEntry:o})=>o?`${e("webhook.ts","Webhook entry point — imports builders (sets globalThis.phx.webhooks) then re-exports user handler.")}
|
|
2
2
|
export * as builders from './webhook-builders.js'
|
|
3
3
|
|
|
4
4
|
import implementation from '../src/webhooks/index.js'
|
|
5
5
|
|
|
6
6
|
export const handler = implementation
|
|
7
|
+
`:`${e("webhook.ts","Webhook entry point — imports builders (sets globalThis.phx.webhooks) then exports the built-in handler, because the project has no src/webhooks/index.ts.")}
|
|
8
|
+
export * as builders from './webhook-builders.js'
|
|
9
|
+
|
|
10
|
+
// A webhook needs at least one handler; anonymous auth stays inert until spec/application.yaml sets useAuthHook
|
|
11
|
+
const authHandler = phx.webhooks.authHandlerBuilder
|
|
12
|
+
.withAnonymousHandler(async () => ({ success: true, data: {}, role: 'anonymous' }))
|
|
13
|
+
.build()
|
|
14
|
+
|
|
15
|
+
export const handler = phx.webhooks.webhookBuilder.withAuthHook(authHandler).build()
|
|
7
16
|
`;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export * from './runtime/sections/index.js';
|
|
2
2
|
export * from './runtime/application-runtime.js';
|
|
3
|
+
export * from './runtime/factory-data/index.js';
|
|
4
|
+
export * from './runtime/migrations/index.js';
|
|
3
5
|
export { isConfiguratorModelSchemaCompatible } from './runtime/configurator-runtime/configurator-model-runtime.js';
|
|
4
6
|
export * from './code/index.js';
|
|
5
7
|
export { generateRuntimeInstance } from './runtime/generate-runtime-instance.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export*from"./runtime/sections/index.js";export*from"./runtime/application-runtime.js";export{isConfiguratorModelSchemaCompatible}from"./runtime/configurator-runtime/configurator-model-runtime.js";export*from"./code/index.js";export{generateRuntimeInstance}from"./runtime/generate-runtime-instance.js";
|
|
1
|
+
export*from"./runtime/sections/index.js";export*from"./runtime/application-runtime.js";export*from"./runtime/factory-data/index.js";export*from"./runtime/migrations/index.js";export{isConfiguratorModelSchemaCompatible}from"./runtime/configurator-runtime/configurator-model-runtime.js";export*from"./code/index.js";export{generateRuntimeInstance}from"./runtime/generate-runtime-instance.js";
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Branded } from '@salsita-ai/common/utils';
|
|
2
2
|
import type { RuntimeReferenceStore } from '../../../caching/index.js';
|
|
3
3
|
import type { ApplicationSpec } from '../../../parse-application-files/index.js';
|
|
4
|
+
import { FactoryDataRuntime } from '../factory-data/index.js';
|
|
5
|
+
import { type MigrationModules, MigrationRuntime } from '../migrations/index.js';
|
|
4
6
|
import { ComponentOptics } from '../sections/component-optic.js';
|
|
5
|
-
import { type ExpressionImplementations, ExpressionRuntime, type MissingExpression } from '../sections/expression-runtime.js';
|
|
7
|
+
import { type ExpressionImplementations, ExpressionRuntime, type InvariantImplementations, type MissingExpression } from '../sections/expression-runtime.js';
|
|
6
8
|
import { PresetRuntime } from '../sections/preset-runtime.js';
|
|
7
9
|
import { AdminModelRuntime } from './admin-model-runtime.js';
|
|
8
10
|
import { AdminStatesRuntime } from './states-runtime.js';
|
|
@@ -12,6 +14,8 @@ export type AdminRuntime = Branded<'AdminRuntime', {
|
|
|
12
14
|
readonly expressionRuntime: ExpressionRuntime;
|
|
13
15
|
readonly presetRuntime: PresetRuntime;
|
|
14
16
|
readonly statesRuntime: AdminStatesRuntime;
|
|
17
|
+
readonly migrationRuntime: MigrationRuntime;
|
|
18
|
+
readonly factoryDataRuntime: FactoryDataRuntime;
|
|
15
19
|
}>;
|
|
16
20
|
export type AdminRuntimeResult = {
|
|
17
21
|
readonly ok: true;
|
|
@@ -20,4 +24,4 @@ export type AdminRuntimeResult = {
|
|
|
20
24
|
readonly ok: false;
|
|
21
25
|
readonly missingExpressions: readonly MissingExpression[];
|
|
22
26
|
};
|
|
23
|
-
export declare const AdminRuntime: (spec: ApplicationSpec, referenceStore: RuntimeReferenceStore, implementations
|
|
27
|
+
export declare const AdminRuntime: (spec: ApplicationSpec, referenceStore: RuntimeReferenceStore, implementations: ExpressionImplementations, invariantImplementations: InvariantImplementations, migrationModules: MigrationModules) => AdminRuntimeResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Branded as e}from"@salsita-ai/common/utils";import{Preset as t,PresetCategory as i,commonAdminCustomExpressions as
|
|
1
|
+
import{Branded as e}from"@salsita-ai/common/utils";import{Preset as t,PresetCategory as i,commonAdminCustomExpressions as n,commonAdminViolationExpressions as r}from"#package/domain";import{FactoryDataRuntime as s}from"../factory-data/index.js";import{MigrationRuntime as o}from"../migrations/index.js";import{ComponentOptics as m}from"../sections/component-optic.js";import{ExpressionRuntime as a}from"../sections/expression-runtime.js";import{PresetRuntime as p}from"../sections/preset-runtime.js";import{AdminModelRuntime as f}from"./admin-model-runtime.js";import{AdminStatesRuntime as u}from"./states-runtime.js";let c={Preset:[{evaluate:(e,i,n)=>{let s=n.domain.get$Entity(e,i);return t.assert(s),r.Preset.nameNotEmpty(s)}}]},l={PresetCategory:{$isDraft:{origin:{name:"$isDraft",typeOrAlias:"PresetCategory"},evaluate:(e,t,r)=>{let s=r.domain.get$Entity(e,t);return i.assert(s),n.PresetCategory.$isDraft(s)},meta:{}}}},d=new WeakMap;export const AdminRuntime=(t,i,n,r,g)=>{let R={...l};for(let[e,t]of Object.entries(n))R[e]={...R[e],...t};let y=f(t.admin,t.configurator.dataSchemas,i),j=a(t.admin,i,R,"adminExpressionRuntime",((e,t)=>{if(0===Object.keys(e).length)return c;let i=d.get(t)??new WeakMap;d.set(t,i);let n=i.get(e);if(n)return n;let r={};for(let i of[c,e])for(let[e,n]of Object.entries(i))for(let i of t[e]??[e])r[i]=[...r[i]??[],...n];return i.set(e,r),r})(r,y.aliases));return j.ok?{ok:!0,runtime:e({modelRuntime:y,componentOptics:m(i,{components:t.admin.components,referenceScope:"adminRuntime/componentOptics",modelRuntime:y}),expressionRuntime:j.runtime,presetRuntime:p(i,{referenceScope:"adminRuntime/presetRuntime",presets:t.admin.presets.presets}),statesRuntime:u(t,i),migrationRuntime:o(i,{referenceScope:"adminRuntime/migrationRuntime",resolvedVersions:t.admin.resolvedVersions,latestEntities:y.entities,migrationModules:g}),factoryDataRuntime:s(i,{referenceScope:"adminRuntime/factoryDataRuntime",invariants:t.admin.invariants,defaults:t.admin.defaults,aliases:y.aliases,entities:y.entities})})}:{ok:!1,missingExpressions:j.missing}};
|
|
@@ -4,6 +4,7 @@ import type { RuntimeReferenceStore } from '../../caching/index.js';
|
|
|
4
4
|
import type { ApplicationSpec } from '../../parse-application-files/index.js';
|
|
5
5
|
import { AdminRuntime } from './admin-runtime/admin-runtime.js';
|
|
6
6
|
import { ConfiguratorRuntime } from './configurator-runtime/configurator-runtime.js';
|
|
7
|
+
import type { MigrationModules } from './migrations/index.js';
|
|
7
8
|
import { DataRuntime } from './sections/data-runtime.js';
|
|
8
9
|
import type { ExpressionImplementations, InvariantImplementations, MissingExpression } from './sections/expression-runtime.js';
|
|
9
10
|
/**
|
|
@@ -28,6 +29,12 @@ export type ApplicationRuntimeResult = {
|
|
|
28
29
|
* section-level changes across rebuilds.
|
|
29
30
|
* Each field on the result carries its own `changed` flag.
|
|
30
31
|
*
|
|
32
|
+
* `adminInvariantImplementations` are the project's admin invariants (`src/admin/invariants/`); the
|
|
33
|
+
* admin domain checks them after the invariants every admin domain has. `migrationModules` are the
|
|
34
|
+
* project's migration modules of both domains (`src/migrations/`, `src/admin/migrations/`), keyed by
|
|
35
|
+
* project path; a migration they do not provide is listed in `missingMigrations` of the domain's
|
|
36
|
+
* `migrationRuntime`.
|
|
37
|
+
*
|
|
31
38
|
* Returns an error result when declared expressions are missing implementations.
|
|
32
39
|
*/
|
|
33
|
-
export declare const ApplicationRuntime: (spec: ApplicationSpec, referenceStore: RuntimeReferenceStore, implementations: ExpressionImplementations, importedTransformers: readonly ImportedTransformer[], invariantImplementations?: InvariantImplementations, adminImplementations?: ExpressionImplementations) => ApplicationRuntimeResult;
|
|
40
|
+
export declare const ApplicationRuntime: (spec: ApplicationSpec, referenceStore: RuntimeReferenceStore, implementations: ExpressionImplementations, importedTransformers: readonly ImportedTransformer[], invariantImplementations?: InvariantImplementations, adminImplementations?: ExpressionImplementations, adminInvariantImplementations?: InvariantImplementations, migrationModules?: MigrationModules) => ApplicationRuntimeResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Branded as i}from"@salsita-ai/common/utils";import{AdminRuntime as r}from"./admin-runtime/admin-runtime.js";import{ConfiguratorRuntime as n}from"./configurator-runtime/configurator-runtime.js";import{DataRuntime as o}from"./sections/data-runtime.js";export const ApplicationRuntime=(s,t,m,e,u,a)=>{let
|
|
1
|
+
import{Branded as i}from"@salsita-ai/common/utils";import{AdminRuntime as r}from"./admin-runtime/admin-runtime.js";import{ConfiguratorRuntime as n}from"./configurator-runtime/configurator-runtime.js";import{DataRuntime as o}from"./sections/data-runtime.js";export const ApplicationRuntime=(s,t,m,e,u,a={},p={},f={})=>{let c=n(s,t,m,e,u,f);if(!c.ok)return{ok:!1,missingExpressions:c.missingExpressions};let g=r(s,t,a,p,f);return g.ok?{ok:!0,runtime:i({configurator:c.runtime,admin:g.runtime,data:o(s,t)})}:{ok:!1,missingExpressions:g.missingExpressions}};
|
|
@@ -2,6 +2,8 @@ import { Branded } from '@salsita-ai/common/utils';
|
|
|
2
2
|
import type { ImportedTransformer } from '#package/domain';
|
|
3
3
|
import type { RuntimeReferenceStore } from '../../../caching/index.js';
|
|
4
4
|
import type { ApplicationSpec } from '../../../parse-application-files/index.js';
|
|
5
|
+
import { FactoryDataRuntime } from '../factory-data/index.js';
|
|
6
|
+
import { type MigrationModules, MigrationRuntime } from '../migrations/index.js';
|
|
5
7
|
import { ActionsRuntime } from '../sections/actions-runtime.js';
|
|
6
8
|
import { AssistantRuntime } from '../sections/assistant-runtime.js';
|
|
7
9
|
import { ComponentOptics } from '../sections/component-optic.js';
|
|
@@ -21,6 +23,8 @@ export type ConfiguratorRuntime = Branded<'ConfiguratorRuntime', {
|
|
|
21
23
|
readonly transformersRuntime: TransformersRuntime;
|
|
22
24
|
readonly assistantRuntime: AssistantRuntime;
|
|
23
25
|
readonly actionsRuntime: ActionsRuntime;
|
|
26
|
+
readonly migrationRuntime: MigrationRuntime;
|
|
27
|
+
readonly factoryDataRuntime: FactoryDataRuntime;
|
|
24
28
|
}>;
|
|
25
29
|
export type ConfiguratorRuntimeResult = {
|
|
26
30
|
readonly ok: true;
|
|
@@ -29,4 +33,4 @@ export type ConfiguratorRuntimeResult = {
|
|
|
29
33
|
readonly ok: false;
|
|
30
34
|
readonly missingExpressions: readonly MissingExpression[];
|
|
31
35
|
};
|
|
32
|
-
export declare const ConfiguratorRuntime: (spec: ApplicationSpec, referenceStore: RuntimeReferenceStore, implementations: ExpressionImplementations, importedTransformers: readonly ImportedTransformer[], invariantImplementations
|
|
36
|
+
export declare const ConfiguratorRuntime: (spec: ApplicationSpec, referenceStore: RuntimeReferenceStore, implementations: ExpressionImplementations, importedTransformers: readonly ImportedTransformer[], invariantImplementations: InvariantImplementations | undefined, migrationModules: MigrationModules) => ConfiguratorRuntimeResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Branded as t}from"@salsita-ai/common/utils";import{ActionsRuntime as o}from"../sections/actions-runtime.js";import{AssistantRuntime as
|
|
1
|
+
import{Branded as t}from"@salsita-ai/common/utils";import{FactoryDataRuntime as e}from"../factory-data/index.js";import{MigrationRuntime as i}from"../migrations/index.js";import{ActionsRuntime as o}from"../sections/actions-runtime.js";import{AssistantRuntime as r}from"../sections/assistant-runtime.js";import{ComponentOptics as n}from"../sections/component-optic.js";import{ExpressionRuntime as s}from"../sections/expression-runtime.js";import{PresetRuntime as m}from"../sections/preset-runtime.js";import{ThemeRuntime as a}from"../sections/theme-runtime.js";import{TransformersRuntime as u}from"../sections/transformers-runtime.js";import{ConfiguratorModelRuntime as c}from"./configurator-model-runtime.js";import{ConfiguratorStatesRuntime as f}from"./states-runtime.js";export const ConfiguratorRuntime=(p,g,R,j,l,d)=>{let x=c(p.configurator,g),v=s(p.configurator,g,R,"configuratorExpressionRuntime",l);return v.ok?{ok:!0,runtime:t({modelRuntime:x,componentOptics:n(g,{components:p.configurator.components,referenceScope:"configuratorRuntime/componentOptics",modelRuntime:x}),presetRuntime:m(g,{referenceScope:"configuratorRuntime/presetRuntime",presets:p.configurator.presets.presets}),statesRuntime:f(p,g),expressionRuntime:v.runtime,themeRuntime:a(p,g),transformersRuntime:u(p,g,j),assistantRuntime:r(p,g),actionsRuntime:o(p.configurator.actions,g),migrationRuntime:i(g,{referenceScope:"configuratorRuntime/migrationRuntime",resolvedVersions:p.configurator.resolvedVersions,latestEntities:x.entities,migrationModules:d}),factoryDataRuntime:e(g,{referenceScope:"configuratorRuntime/factoryDataRuntime",invariants:p.configurator.invariants,defaults:p.configurator.defaults,aliases:x.aliases,entities:x.entities})})}:{ok:!1,missingExpressions:v.missing}};
|
package/dist/application-spec/generate-application/runtime/factory-data/factory-data-runtime.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Branded } from '@salsita-ai/common/utils';
|
|
2
|
+
import type { AnyEntityReflections, DomainEntity, DomainEntityReflection } from '#package/domain';
|
|
3
|
+
import type { RuntimeReferenceStore } from '../../../caching/index.js';
|
|
4
|
+
import type { Defaults, Invariants } from '../../../parse-application-files/index.js';
|
|
5
|
+
import { type RecipeDefaults } from './recipe-defaults.js';
|
|
6
|
+
import { type StaticViolations } from './static-violations.js';
|
|
7
|
+
interface FactoryDataRuntimeFields {
|
|
8
|
+
/**
|
|
9
|
+
* The member types of each alias: what `phx.domain.attachComponent` expands an alias with, and
|
|
10
|
+
* what `phx.domain.createRecipe` expands alias defaults with.
|
|
11
|
+
*/
|
|
12
|
+
readonly aliases: Readonly<Record<string, readonly string[]>>;
|
|
13
|
+
/** The entity reflections `phx.domain.createRecipe` validates the defaults with. */
|
|
14
|
+
readonly entityReflections: ReadonlyArray<DomainEntityReflection<DomainEntity<string>>>;
|
|
15
|
+
/** The violations `phx.domain.implementCustomInvariants` reports for a static invariant that fails. */
|
|
16
|
+
readonly staticViolations: StaticViolations;
|
|
17
|
+
/** The defaults `phx.domain.createRecipe` puts into a new recipe. */
|
|
18
|
+
readonly defaults: RecipeDefaults;
|
|
19
|
+
readonly changed: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The data the `phx.domain` factories of one domain carry, built from the parsed spec: the static
|
|
23
|
+
* violations of `implementCustomInvariants`, the aliases of `attachComponent`, and the aliases,
|
|
24
|
+
* entity reflections and defaults of `createRecipe`. Generated `domain-spec.ts` passes the same
|
|
25
|
+
* values to those factories as literals; with this section the factories can be built from the
|
|
26
|
+
* spec instead. The configurator and the admin domain each have one.
|
|
27
|
+
*/
|
|
28
|
+
export type FactoryDataRuntime = Branded<'FactoryDataRuntime', FactoryDataRuntimeFields>;
|
|
29
|
+
interface FactoryDataRuntimeInput {
|
|
30
|
+
readonly invariants: Invariants;
|
|
31
|
+
readonly defaults: Defaults;
|
|
32
|
+
readonly aliases: Readonly<Record<string, readonly string[]>>;
|
|
33
|
+
readonly entities: AnyEntityReflections;
|
|
34
|
+
}
|
|
35
|
+
interface FactoryDataRuntimeProps extends FactoryDataRuntimeInput {
|
|
36
|
+
readonly referenceScope: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Builds the factory data of one domain. The result keeps its reference while the invariants and
|
|
40
|
+
* defaults are equal and the model runtime's aliases and entity reflections are the same objects.
|
|
41
|
+
*/
|
|
42
|
+
export declare const FactoryDataRuntime: (referenceStore: RuntimeReferenceStore, props: FactoryDataRuntimeProps) => FactoryDataRuntime;
|
|
43
|
+
export {};
|
package/dist/application-spec/generate-application/runtime/factory-data/factory-data-runtime.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import e from"lodash-es/isEqual.js";import{Branded as t}from"@salsita-ai/common/utils";import{createRecipeDefaults as i}from"./recipe-defaults.js";import{createStaticViolations as s}from"./static-violations.js";let a=e=>({aliases:e.aliases,entityReflections:Object.values(e.entities),staticViolations:s(e.invariants),defaults:i(e.defaults)});export const FactoryDataRuntime=(i,s)=>{let n=i.createBuilder(s.referenceScope,{build:a,getKey:()=>"singleton",compare:(t,i)=>t.aliases===i.aliases&&t.entities===i.entities&&e(t.invariants.entries,i.invariants.entries)&&e(t.defaults.entries,i.defaults.entries)}).build({invariants:s.invariants,defaults:s.defaults,aliases:s.aliases,entities:s.entities});return t({...n.output,changed:n.changed})};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{FactoryDataRuntime}from"./factory-data-runtime.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Defaults } from '../../../parse-application-files/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* The default property values of each entity type, keyed by entity type: what
|
|
4
|
+
* `phx.domain.createRecipe` puts into a new recipe before the caller's overrides. Alias entries are
|
|
5
|
+
* already expanded to their member types by the parser.
|
|
6
|
+
*/
|
|
7
|
+
export type RecipeDefaults = Readonly<Record<string, Readonly<Record<string, unknown>>>>;
|
|
8
|
+
/**
|
|
9
|
+
* The runtime counterpart of the `defaults` literal the generated `domain-spec.ts` passes to
|
|
10
|
+
* `createRecipeFactory`: the parsed per-entity defaults with every `$msg` lowered to the descriptor
|
|
11
|
+
* the `msg` macro produces.
|
|
12
|
+
*/
|
|
13
|
+
export declare const createRecipeDefaults: (defaults: Defaults) => RecipeDefaults;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createMessageDescriptor as e,isEvalMarker as t,isMsgMarker as r}from"../../../core/index.js";let s=(a,i)=>{if(null===a||"object"!=typeof a)return a;if(r(a))return e(a);if(t(a))throw Error(`The default at ${i} is an $eval expression. Defaults are static values; the parser rejects $eval in them, so the spec given to the runtime was not produced by it. Parse the spec again and pass the result.`);return Array.isArray(a)?a.map((e,t)=>s(e,`${i}[${t}]`)):Object.fromEntries(Object.entries(a).map(([e,t])=>[e,s(t,`${i}.${e}`)]))};export const createRecipeDefaults=e=>Object.fromEntries(Object.entries(e.entries).map(([e,t])=>[e,Object.fromEntries(Object.entries(t).map(([t,r])=>[t,s(r,`${e}.${t}`)]))]));
|
package/dist/application-spec/generate-application/runtime/factory-data/static-violations.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Violation } from '#package/domain';
|
|
2
|
+
import type { Invariants } from '../../../parse-application-files/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* The violation each static invariant of a domain reports when its implementation returns `false`,
|
|
5
|
+
* by entity type or alias and by invariant name. `phx.domain.implementCustomInvariants` closes over
|
|
6
|
+
* it: a project implements a static invariant as a boolean and the factory turns `false` into this
|
|
7
|
+
* violation.
|
|
8
|
+
*/
|
|
9
|
+
export type StaticViolations = Readonly<Record<string, Readonly<Record<string, Violation<string>>>>>;
|
|
10
|
+
/**
|
|
11
|
+
* The runtime counterpart of the `staticViolations` literal the generated `domain-spec.ts` passes
|
|
12
|
+
* to `createCustomInvariantFactory`: one entry per static invariant, keyed as the spec declares it,
|
|
13
|
+
* with a `$msg` message lowered to the descriptor the `msg` macro produces. Types and aliases
|
|
14
|
+
* without a static invariant have no entry.
|
|
15
|
+
*/
|
|
16
|
+
export declare const createStaticViolations: (invariants: Invariants) => StaticViolations;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createMessageDescriptor as t}from"../../../core/index.js";export const createStaticViolations=e=>{let i={};for(let[o,r]of Object.entries(e.entries))for(let e of Object.values(r)){if("static"!==e.kind)continue;let r={type:String(e.violationType),severity:e.severity,message:"string"==typeof e.message?e.message:t(e.message),...void 0===e.controlViolationPriority?{}:{controlViolationPriority:e.controlViolationPriority}};i[o]={...i[o],[String(e.name)]:r}}return i};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MigrationRuntime, type MigrationModules } from './migration-runtime.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{MigrationRuntime}from"./migration-runtime.js";
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Branded } from '@salsita-ai/common/utils';
|
|
2
|
+
import { type AnyEntityReflections, type DomainEntity, type MigrateFunction, type Migration } from '#package/domain';
|
|
3
|
+
import type { RuntimeReferenceStore } from '../../../caching/index.js';
|
|
4
|
+
import type { ResolvedVersions } from '../../../parse-application-files/index.js';
|
|
5
|
+
type AnyEntity = DomainEntity<string>;
|
|
6
|
+
type AnyMigration = Migration<AnyEntity, AnyEntity>;
|
|
7
|
+
/**
|
|
8
|
+
* The project's migration modules, keyed by the project path the parser records for each model
|
|
9
|
+
* version (`src/migrations/v2.ts`, `src/admin/migrations/v2.ts`), each holding the module's exports.
|
|
10
|
+
* The module of version `N` exports the migration to that version as `migrateToV<N>`, the name the
|
|
11
|
+
* generated `domain.ts` imports.
|
|
12
|
+
*/
|
|
13
|
+
export type MigrationModules = Readonly<Record<string, Readonly<Record<string, unknown>>>>;
|
|
14
|
+
interface MigrationRuntimeFields {
|
|
15
|
+
/** The entity reflections of each model version, keyed by version; the latest is the domain's own. */
|
|
16
|
+
readonly modelVersions: Readonly<Record<number, AnyEntityReflections>>;
|
|
17
|
+
/** The migration to each version, keyed by the version it yields. */
|
|
18
|
+
readonly migrations: Readonly<Record<number, AnyMigration>>;
|
|
19
|
+
readonly migrate: MigrateFunction<AnyEntity>;
|
|
20
|
+
/**
|
|
21
|
+
* The migrations the spec declares but the migration modules do not provide, as
|
|
22
|
+
* `<migration file>#migrateToV<N>`. A state that needs one fails to load with a
|
|
23
|
+
* `StateMigrationError` naming the missing step.
|
|
24
|
+
*/
|
|
25
|
+
readonly missingMigrations: readonly string[];
|
|
26
|
+
readonly changed: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* How a domain migrates a stored state of any of its model versions to the latest one: the entity
|
|
30
|
+
* reflections of every version, the project's migration to each version above the first, and the
|
|
31
|
+
* migrate function built from both, which `DomainBuilder.withMigrate` takes.
|
|
32
|
+
*
|
|
33
|
+
* The configurator and the admin domain each have one. The admin domain's factory first applies the
|
|
34
|
+
* SDK's own migration of the common admin entities (`migrateCommonAdminDomain`) and then this one.
|
|
35
|
+
*/
|
|
36
|
+
export type MigrationRuntime = Branded<'MigrationRuntime', MigrationRuntimeFields>;
|
|
37
|
+
interface MigrationRuntimeInput {
|
|
38
|
+
readonly resolvedVersions: ResolvedVersions;
|
|
39
|
+
readonly latestEntities: AnyEntityReflections;
|
|
40
|
+
readonly migrationModules: MigrationModules;
|
|
41
|
+
}
|
|
42
|
+
interface MigrationRuntimeProps extends MigrationRuntimeInput {
|
|
43
|
+
readonly referenceScope: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Builds a domain's migrations from its resolved model versions and the project's migration
|
|
47
|
+
* modules: the runtime counterpart of the `modelVersions` literal of the generated `domain-spec.ts`
|
|
48
|
+
* and the `createMigrateFunction(...)` call of the generated `domain.ts`. The latest version uses the
|
|
49
|
+
* domain's own entity reflections, as generated code does. The result keeps its reference while
|
|
50
|
+
* the versions, the latest reflections and the migration modules stay the same.
|
|
51
|
+
*/
|
|
52
|
+
export declare const MigrationRuntime: (referenceStore: RuntimeReferenceStore, props: MigrationRuntimeProps) => MigrationRuntime;
|
|
53
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import e from"lodash-es/isEqual.js";import{Branded as i}from"@salsita-ai/common/utils";import{DomainEntityReflection as t,createMigrateFunction as s}from"#package/domain";let o=e=>"function"==typeof e,r=e=>`migrateToV${e}`,n=e=>{let{resolvedVersions:i,latestEntities:n,migrationModules:a}=e,l={},m={},d=[];for(let e of i.versionedModels){if(e.isLatest)l[e.version]=n;else{let i={};for(let s of e.modelVersion.entitySchemas)i[String(s.entityType)]=new t(String(s.entityType),[s.shapeSchema]);l[e.version]=i}if(void 0===e.migrationFile)continue;let i=r(e.version),s=a[e.migrationFile]?.[i];o(s)?m[e.version]=s:d.push(`${e.migrationFile}#${i}`)}return{modelVersions:l,migrations:m,migrate:s(l,i.latestVersion,m),missingMigrations:d}},a=e=>e.versionedModels.map(e=>({version:e.version,isLatest:e.isLatest,migrationFile:e.migrationFile,schemas:e.isLatest?[]:e.modelVersion.entitySchemas.map(e=>e.shapeSchema)})),l=(i,t)=>i.latestEntities===t.latestEntities&&i.resolvedVersions.latestVersion===t.resolvedVersions.latestVersion&&e(a(i.resolvedVersions),a(t.resolvedVersions))&&i.resolvedVersions.versionedModels.every(e=>void 0===e.migrationFile||i.migrationModules[e.migrationFile]===t.migrationModules[e.migrationFile]);export const MigrationRuntime=(e,t)=>{let s=e.createBuilder(t.referenceScope,{build:n,getKey:()=>"singleton",compare:l}).build({resolvedVersions:t.resolvedVersions,latestEntities:t.latestEntities,migrationModules:t.migrationModules});return i({...s.output,changed:s.changed})};
|
|
@@ -58,6 +58,12 @@ export type CategorizedFiles = Branded<'CategorizedFiles', {
|
|
|
58
58
|
readonly adminElementsChanged: boolean;
|
|
59
59
|
readonly webhooks: readonly CategorizedFile[];
|
|
60
60
|
readonly webhooksChanged: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Whether the project has its webhook entry, `src/webhooks/index.ts`, whose default export is the
|
|
63
|
+
* project's webhook. Generation reads it to decide the generated webhook entry: without it the
|
|
64
|
+
* entry holds the built-in inert webhook.
|
|
65
|
+
*/
|
|
66
|
+
readonly hasWebhookEntry: boolean;
|
|
61
67
|
readonly locales: readonly CategorizedFile[];
|
|
62
68
|
readonly localesChanged: boolean;
|
|
63
69
|
readonly mockTemplates: readonly CategorizedFile[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"lodash-es/isEqual.js";import{Branded as n}from"@salsita-ai/common/utils";import{computeFileDepHashes as s}from"../../caching/index.js";import{DiagnosticCode as o,diagnosticMessages as a}from"../../errors/index.js";import{findWebhookHandlerRegistration as i}from"./module-analysis.js";import{findWebhookSafetyViolation as t}from"./webhook-safety.js";export const buildProjectFileIndex=e=>new Map([...e.spec,...e.expressions,...e.actions,...e.handlers,...e.elements,...e.transformers,...e.components,...e.invariants,...e.migrations,...e.adminMigrations,...e.adminExpressions,...e.adminInvariants,...e.adminComponents,...e.adminElements,...e.webhooks,...e.locales,...e.mockTemplates,...e.projectFiles,...e.customCode].map(e=>[e.file.name,e]));let r=e=>/\/_[^/]+\//.test(e),m=[{path:"spec/",key:"spec"},{path:"src/admin/expressions/",key:"adminExpressions"},{path:"src/admin/invariants/",key:"adminInvariants"},{path:"src/admin/components/",key:"adminComponents"},{path:"src/admin/elements/",key:"adminElements"},{path:"src/admin/migrations/",key:"adminMigrations"},{path:"src/expressions/",key:"expressions"},{path:"src/actions/",key:"actions"},{path:"src/handlers/",key:"handlers"},{path:"src/elements/",key:"elements"},{path:"src/transformers/",key:"transformers"},{path:"src/components/",key:"components"},{path:"src/invariants/",key:"invariants"},{path:"src/migrations/",key:"migrations"},{path:"src/webhooks/",key:"webhooks"},{path:"src/locales/",key:"locales"},{path:"mocks/",key:"mockTemplates"}],l=new Set(["package.json",".gitignore","CLAUDE.md",".cursor/rules/phoenix.mdc"]),d=new Set(["migrations","adminMigrations"]),c=m.filter(({path:e,key:n})=>e.startsWith("src/")&&d.has(n)),p=(e,n)=>{let s=e.slice(n.length).split("/");return!(s.length<=1)&&s.slice(0,-1).some(e=>!e.startsWith("_"))},h=/\.(ts|tsx|js|jsx)$/,f=(e,n)=>{if("components"===e||"adminComponents"===e)return n.hasUseWebhookDirective?{membership:"pinned",logSuffix:"webhook ('use webhook' directive)"}:{membership:"frontend",logSuffix:"frontend only (no 'use webhook' directive)"};if("handlers"===e){let e=i(n);return void 0!==e?{membership:"named-handler",logSuffix:`webhook (the ${e} registration)`}:n.hasUseWebhookDirective?{membership:"pinned",logSuffix:"webhook ('use webhook' directive)"}:{membership:"frontend",logSuffix:"frontend only (not a named handler or pin)"}}};export const CategorizedFiles=(i,d,g,u)=>{let k={spec:[],expressions:[],actions:[],handlers:[],elements:[],transformers:[],components:[],invariants:[],migrations:[],adminMigrations:[],adminExpressions:[],adminInvariants:[],adminComponents:[],adminElements:[],webhooks:[],locales:[],mockTemplates:[],projectFiles:[],customCode:[]},b=[];for(let e of i.files){if("text"!==e.kind)continue;if(r(e.name)){k.customCode.push({file:e,category:"customCode"});continue}if(l.has(e.name)){k.projectFiles.push({file:e,category:"projectFiles"});continue}let n=!1;for(let{path:s,key:o}of m)if(e.name.startsWith(s)){k[o].push({file:e,category:o}),n=!0;break}n||b.push(e.name)}for(let e of b)e.startsWith("src/")&&g.error(o.UNKNOWN_SRC_PATH,a.UNKNOWN_SRC_PATH(e));for(let{path:e,key:n}of c)for(let s of k[n])p(s.file.name,e)&&g.error(o.INVALID_SUBDIRECTORY,a.INVALID_SUBDIRECTORY(s.file.name,e));
|
|
1
|
+
import e from"lodash-es/isEqual.js";import{Branded as n}from"@salsita-ai/common/utils";import{computeFileDepHashes as s}from"../../caching/index.js";import{DiagnosticCode as o,diagnosticMessages as a}from"../../errors/index.js";import{findWebhookHandlerRegistration as i}from"./module-analysis.js";import{findWebhookSafetyViolation as t}from"./webhook-safety.js";export const buildProjectFileIndex=e=>new Map([...e.spec,...e.expressions,...e.actions,...e.handlers,...e.elements,...e.transformers,...e.components,...e.invariants,...e.migrations,...e.adminMigrations,...e.adminExpressions,...e.adminInvariants,...e.adminComponents,...e.adminElements,...e.webhooks,...e.locales,...e.mockTemplates,...e.projectFiles,...e.customCode].map(e=>[e.file.name,e]));let r=e=>/\/_[^/]+\//.test(e),m=[{path:"spec/",key:"spec"},{path:"src/admin/expressions/",key:"adminExpressions"},{path:"src/admin/invariants/",key:"adminInvariants"},{path:"src/admin/components/",key:"adminComponents"},{path:"src/admin/elements/",key:"adminElements"},{path:"src/admin/migrations/",key:"adminMigrations"},{path:"src/expressions/",key:"expressions"},{path:"src/actions/",key:"actions"},{path:"src/handlers/",key:"handlers"},{path:"src/elements/",key:"elements"},{path:"src/transformers/",key:"transformers"},{path:"src/components/",key:"components"},{path:"src/invariants/",key:"invariants"},{path:"src/migrations/",key:"migrations"},{path:"src/webhooks/",key:"webhooks"},{path:"src/locales/",key:"locales"},{path:"mocks/",key:"mockTemplates"}],l=new Set(["package.json",".gitignore","CLAUDE.md",".cursor/rules/phoenix.mdc"]),d=new Set(["migrations","adminMigrations"]),c=m.filter(({path:e,key:n})=>e.startsWith("src/")&&d.has(n)),p=(e,n)=>{let s=e.slice(n.length).split("/");return!(s.length<=1)&&s.slice(0,-1).some(e=>!e.startsWith("_"))},h=/\.(ts|tsx|js|jsx)$/,f=(e,n)=>{if("components"===e||"adminComponents"===e)return n.hasUseWebhookDirective?{membership:"pinned",logSuffix:"webhook ('use webhook' directive)"}:{membership:"frontend",logSuffix:"frontend only (no 'use webhook' directive)"};if("handlers"===e){let e=i(n);return void 0!==e?{membership:"named-handler",logSuffix:`webhook (the ${e} registration)`}:n.hasUseWebhookDirective?{membership:"pinned",logSuffix:"webhook ('use webhook' directive)"}:{membership:"frontend",logSuffix:"frontend only (not a named handler or pin)"}}};export const CategorizedFiles=(i,d,g,u)=>{let k={spec:[],expressions:[],actions:[],handlers:[],elements:[],transformers:[],components:[],invariants:[],migrations:[],adminMigrations:[],adminExpressions:[],adminInvariants:[],adminComponents:[],adminElements:[],webhooks:[],locales:[],mockTemplates:[],projectFiles:[],customCode:[]},b=[];for(let e of i.files){if("text"!==e.kind)continue;if(r(e.name)){k.customCode.push({file:e,category:"customCode"});continue}if(l.has(e.name)){k.projectFiles.push({file:e,category:"projectFiles"});continue}let n=!1;for(let{path:s,key:o}of m)if(e.name.startsWith(s)){k[o].push({file:e,category:o}),n=!0;break}n||b.push(e.name)}for(let e of b)e.startsWith("src/")&&g.error(o.UNKNOWN_SRC_PATH,a.UNKNOWN_SRC_PATH(e));for(let{path:e,key:n}of c)for(let s of k[n])p(s.file.name,e)&&g.error(o.INVALID_SUBDIRECTORY,a.INVALID_SUBDIRECTORY(s.file.name,e));let C=k.webhooks.some(e=>"src/webhooks/index.ts"===e.file.name);if(k.webhooks.length>0&&!C&&g.error(o.MISSING_WEBHOOK_INDEX,a.MISSING_WEBHOOK_INDEX()),g.hasErrors)return;let v=[];for(let e of Object.values(k))for(let n of e)v.push(n.file.name);let x=s(i,v),{analyzer:y,logger:E}=u,I=d.createBuilder("categorizedFiles/moduleAnalysis",{build:e=>{try{return{analysis:y(e.name,e.content)}}catch(e){return{error:e instanceof Error?e.message:String(e)}}},getKey:e=>e.name,compare:(e,n)=>e.content===n.content}),w=new Set,S=e=>{if(!h.test(e.name))return;w.add(e.name);let n=I.build({name:e.name,content:e.content}).output;return void 0!==n.error?void g.error(o.MODULE_ANALYSIS_FAILED,a[o.MODULE_ANALYSIS_FAILED](e.name,n.error)):n.analysis},j={},_={};for(let[e,s]of Object.entries(k)){let o=d.createBuilder(`categorizedFiles/${e}`,{build:e=>e,getKey:e=>e.name,compare:(e,n)=>e.depHash===n.depHash}),a=new Set;j[e]=s.map(e=>{let s=x[e.file.name]??{deps:[],hash:""},{changed:i}=o.build({name:e.file.name,depHash:s.hash});a.add(e.file.name);let t=S(e.file),r=void 0===t?void 0:f(e.category,t);return void 0!==r&&E.debug(`Webhook membership: ${e.file.name} -> ${r.logSuffix}`),n({file:e.file,category:e.category,deps:s.deps,depHash:s.hash,changed:i,analysis:t,webhookMembership:r?.membership})}),_[e]=o.cleanup(a)}I.cleanup(w);let F=(e,n)=>n.some(e=>e.changed)||!0===_[e],M=d.createBuilder("categorizedFiles/envs",{build:e=>e.envs,getKey:()=>"singleton",compare:(n,s)=>e(n.envs,s.envs)}).build({envs:i.envs}),O=n({spec:j.spec,specChanged:F("spec",j.spec),expressions:j.expressions,expressionsChanged:F("expressions",j.expressions),actions:j.actions,actionsChanged:F("actions",j.actions),handlers:j.handlers,handlersChanged:F("handlers",j.handlers),elements:j.elements,elementsChanged:F("elements",j.elements),transformers:j.transformers,transformersChanged:F("transformers",j.transformers),components:j.components,componentsChanged:F("components",j.components),invariants:j.invariants,invariantsChanged:F("invariants",j.invariants),migrations:j.migrations,migrationsChanged:F("migrations",j.migrations),adminMigrations:j.adminMigrations,adminMigrationsChanged:F("adminMigrations",j.adminMigrations),adminExpressions:j.adminExpressions,adminExpressionsChanged:F("adminExpressions",j.adminExpressions),adminInvariants:j.adminInvariants,adminInvariantsChanged:F("adminInvariants",j.adminInvariants),adminComponents:j.adminComponents,adminComponentsChanged:F("adminComponents",j.adminComponents),adminElements:j.adminElements,adminElementsChanged:F("adminElements",j.adminElements),webhooks:j.webhooks,webhooksChanged:F("webhooks",j.webhooks),hasWebhookEntry:C,locales:j.locales,localesChanged:F("locales",j.locales),mockTemplates:j.mockTemplates,mockTemplatesChanged:F("mockTemplates",j.mockTemplates),projectFiles:j.projectFiles,projectFilesChanged:F("projectFiles",j.projectFiles),customCode:j.customCode,customCodeChanged:F("customCode",j.customCode),envs:M.output,envsChanged:M.changed}),N=buildProjectFileIndex(O);for(let e of N.values()){if("pinned"!==e.webhookMembership&&"named-handler"!==e.webhookMembership)continue;let n=t(e,N);void 0!==n&&g.error(o.WEBHOOK_UNSAFE_IMPORT,a[o.WEBHOOK_UNSAFE_IMPORT](n.fileName,n.inclusionReason,n.importer,n.specifier))}return O};
|
|
@@ -127,11 +127,25 @@ export declare class AssistantSystem implements InitializableSystem {
|
|
|
127
127
|
private readonly _recorder;
|
|
128
128
|
/** The recorder's subscription to the committed emissions of the store; made by the first `initialize()`. */
|
|
129
129
|
private _recording;
|
|
130
|
+
/**
|
|
131
|
+
* The tool call of every `apply` by the state it committed or held, for as long as the state
|
|
132
|
+
* lives: an undone state that the undo history dropped is forgotten with it.
|
|
133
|
+
*
|
|
134
|
+
* Accepted: a commit the project's `registerIsUndoable` keeps out of the history never becomes a
|
|
135
|
+
* step, so the row of its `apply` never offers Undo.
|
|
136
|
+
*/
|
|
137
|
+
private readonly _applyToolCallIds;
|
|
138
|
+
private readonly _undoTipToolCallId;
|
|
130
139
|
constructor(_context: AssistantSystemContext);
|
|
131
140
|
/** The conversation. It never completes, and holds the empty chat whenever no chat is active. */
|
|
132
141
|
readonly chat$: ObservableWithLastValue<AssistantChatSnapshot>;
|
|
133
142
|
/** The state of the built-in panel. It never completes. */
|
|
134
143
|
readonly panel$: ObservableWithLastValue<AssistantPanelSnapshot>;
|
|
144
|
+
/**
|
|
145
|
+
* The `apply` tool call whose committed state is the step of the undo history the configuration is
|
|
146
|
+
* at; nothing when that step is not a change of the assistant. It never completes.
|
|
147
|
+
*/
|
|
148
|
+
readonly undoTipToolCallId$: ObservableWithLastValue<string | undefined>;
|
|
135
149
|
/**
|
|
136
150
|
* A new configuration load: the chat of the previous one is deactivated and both observables go
|
|
137
151
|
* back to their empty values. An activation that is still held outlives it and gets the chat of
|
|
@@ -227,6 +241,15 @@ export declare class AssistantSystem implements InitializableSystem {
|
|
|
227
241
|
* server is therefore gone from the thread and has to be written again.
|
|
228
242
|
*/
|
|
229
243
|
reloadThread: () => void;
|
|
244
|
+
/**
|
|
245
|
+
* Undoes the changes of the given `apply` tool calls, one undo step at a time, while the step the
|
|
246
|
+
* configuration is at is one of them. A change the user made in between stops it, so it is never
|
|
247
|
+
* taken back; the non-undoable commits made on top of an undone change go with it, as with the
|
|
248
|
+
* toolbar's undo.
|
|
249
|
+
*
|
|
250
|
+
* Accepted: like the toolbar's undo, it does not check the session mode; only `apply` requires `owner`.
|
|
251
|
+
*/
|
|
252
|
+
undoToolCalls: (toolCallIds: ReadonlySet<string>) => void;
|
|
230
253
|
setOpen: (open: boolean) => void;
|
|
231
254
|
setInputFocused: (isInputFocused: boolean) => void;
|
|
232
255
|
/**
|
|
@@ -237,6 +260,12 @@ export declare class AssistantSystem implements InitializableSystem {
|
|
|
237
260
|
private _findRefusedMessageIndex;
|
|
238
261
|
private _sendOn;
|
|
239
262
|
private _resume;
|
|
263
|
+
/**
|
|
264
|
+
* The `apply` call whose committed state is the step the configuration is at. Nothing at the bottom
|
|
265
|
+
* of the history, where nothing can be undone: that step was not made by a change it could take back.
|
|
266
|
+
*/
|
|
267
|
+
private _findTipToolCallId;
|
|
268
|
+
private _refreshUndoTip;
|
|
240
269
|
private _committedState;
|
|
241
270
|
private _patchPanel;
|
|
242
271
|
/**
|