@salsita-ai/sdk 0.50.0-develop.abef6d86a1 → 0.50.0-develop.ae52227c7e

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 (74) hide show
  1. package/README.md +2 -2
  2. package/dist/application-spec/errors/diagnostic-codes.d.ts +1 -0
  3. package/dist/application-spec/errors/diagnostic-codes.js +1 -1
  4. package/dist/application-spec/errors/diagnostic-messages.d.ts +1 -0
  5. package/dist/application-spec/errors/diagnostic-messages.js +1 -1
  6. package/dist/application-spec/generate-application/code/project-scaffolding.d.ts +7 -0
  7. package/dist/application-spec/generate-application/code/project-scaffolding.js +1 -1
  8. package/dist/application-spec/generate-application/code/templates/domain-spec/generate-domain-block.js +25 -23
  9. package/dist/application-spec/generate-application/code/templates/domain.js +3 -3
  10. package/dist/application-spec/generate-application/code/templates/package-json.js +1 -1
  11. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.d.ts +1 -0
  12. package/dist/application-spec/generate-application/code/templates/skills/sdk-content.js +1 -1
  13. package/dist/application-spec/parse-application-files/spec/model/defaults.d.ts +5 -0
  14. package/dist/application-spec/parse-application-files/spec/model/defaults.js +1 -1
  15. package/dist/configurator/pages/DefaultConfiguratorLayout.d.ts +6 -0
  16. package/dist/configurator/pages/DefaultConfiguratorLayout.js +1 -0
  17. package/dist/configurator/pages/LoadedConfiguratorDetailPage.js +1 -1
  18. package/dist/configurator/ui/configurator-layout/universal/DesktopLayout.js +4 -4
  19. package/dist/configurator/ui/configurator-layout/universal/DesktopPreview.js +1 -1
  20. package/dist/configurator/ui/configurator-layout/universal/MobileLayout.js +4 -4
  21. package/dist/configurator/ui/configurator-layout/universal/MobilePreview.js +1 -1
  22. package/dist/configurator/ui/configurator-layout/universal/use-layout-scene-safe-area.d.ts +47 -0
  23. package/dist/configurator/ui/configurator-layout/universal/use-layout-scene-safe-area.js +1 -0
  24. package/dist/configurator/ui/configurator-layout/universal/use-scene-safe-area.d.ts +11 -26
  25. package/dist/configurator/ui/configurator-layout/universal/use-scene-safe-area.js +1 -1
  26. package/dist/docs/complex-use-cases/filtered-controls-with-fix-dialog.mdx +16 -19
  27. package/dist/docs/complex-use-cases/sketching.mdx +0 -38
  28. package/dist/docs/controls/select-attribute/cardselect.mdx +9 -13
  29. package/dist/docs/index.json +1 -1
  30. package/dist/docs/integrations/woocommerce/local-development.mdx +1 -1
  31. package/dist/docs/other-features/side-effects.mdx +8 -11
  32. package/dist/docs/other-features/violation-messages.mdx +52 -56
  33. package/dist/docs/phoenix/configurator-interface.mdx +100 -65
  34. package/dist/docs/phoenix/phoenix-cli.mdx +19 -26
  35. package/dist/docs/phoenix/project-structure.mdx +8 -6
  36. package/dist/docs/phoenix/quickstart.mdx +2 -2
  37. package/dist/docs/phoenix/sdk-builder-workflow.mdx +2 -2
  38. package/dist/docs/phoenix/webhooks.mdx +1 -1
  39. package/dist/domain/core/component/domain-component-optic.d.ts +10 -17
  40. package/dist/domain/core/component/domain-component-optic.js +2 -2
  41. package/dist/domain/core/component/legacy-filter.d.ts +2 -17
  42. package/dist/domain/core/component/system-component-filter.d.ts +21 -16
  43. package/dist/domain/core/invariant/custom-invariants.d.ts +6 -14
  44. package/dist/domain/core/invariant/invariants.d.ts +1 -4
  45. package/dist/domain/core/state/migrations.d.ts +14 -45
  46. package/dist/domain/core/state/migrations.js +1 -1
  47. package/dist/domain/domain-builder.js +1 -1
  48. package/dist/domain/domain-runtime/spec/create-violation-expressions.d.ts +24 -0
  49. package/dist/domain/domain-runtime/spec/create-violation-expressions.js +1 -0
  50. package/dist/domain/domain-runtime/spec/index.d.ts +1 -1
  51. package/dist/domain/domain-runtime/spec/index.js +1 -1
  52. package/dist/domain/domain-runtime/spec/module-checks/index.d.ts +1 -1
  53. package/dist/domain/domain-runtime/spec/module-checks/resolve-invariant-modules.d.ts +2 -2
  54. package/dist/legacy/domain-cli/gen/invariants.js +3 -4
  55. package/dist/legacy/domain-cli/utils/cache.d.ts +1 -1
  56. package/dist/legacy/domain-cli/utils/cache.js +1 -1
  57. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/claude-md.d.ts +1 -1
  58. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/cursor-rules.d.ts +1 -1
  59. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/shared-sdk-content.d.ts +1 -1
  60. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/agents/shared-sdk-content.js +1 -0
  61. package/dist/legacy/phoenix-cli/project-gen/generators/file-templates/domain-index.js +17 -15
  62. package/dist/phoenix/application-spec/application-spec-builder.js +1 -1
  63. package/dist/phoenix/commands/init.d.ts +4 -4
  64. package/dist/phoenix/commands/init.js +1 -1
  65. package/dist/phoenix/commands/prettier.js +1 -1
  66. package/dist/phoenix/utils/git/index.d.ts +1 -0
  67. package/dist/phoenix/utils/git/index.js +1 -0
  68. package/dist/phoenix/utils/git/is-inside-git-repository.d.ts +6 -0
  69. package/dist/phoenix/utils/git/is-inside-git-repository.js +1 -0
  70. package/dist/phoenix/utils/index.d.ts +1 -0
  71. package/dist/phoenix/utils/index.js +1 -1
  72. package/package.json +3 -3
  73. package/dist/domain/domain-runtime/spec/invariant-builder.d.ts +0 -26
  74. package/dist/domain/domain-runtime/spec/invariant-builder.js +0 -1
@@ -2,39 +2,39 @@ import{fileHeader as n}from"./file-header.js";import{generateImports as i,getImp
2
2
  ${n.join(",\n ")}
3
3
  )`,a=(n,i)=>{if(0===n.length)return"{}";let o=n.map((n,o)=>{let t=e(n);return null===t?null:` ${t}: ${i[o]}`}).filter(n=>null!==n);return 0===o.length?"{}":`{
4
4
  ${o.join(",\n")}
5
- }`};export const generateIndexDomainFile=(s={})=>{let{includeMigrations:r=!0,includeI18n:m=!0,expressionsFiles:d=[],invariantsFiles:l=[],adminExpressionsFiles:p=[],adminInvariantsFiles:c=[],migrationsFiles:u=[],adminMigrationsFiles:g=[]}=s,x=(n,i)=>`${i?"adminMigrateToV":"migrateToV"}${e(n)}`,$=u.map(n=>{let i=e(n),o=n.replace(/\.ts$/,""),t=`../src/${o}.js`;return`import { migrateToV${i} } from '${t}'`}).join("\n"),f=g.map(n=>{let i=e(n),o=n.replace(/\.ts$/,""),t=`../src/${o}.js`;return`import { migrateToV${i} as adminMigrateToV${i} } from '${t}'`}).join("\n"),h=u.map(n=>x(n,!1)),A=g.map(n=>x(n,!0)),E=u.length>0,j=g.length>0,y=i(d,"expressions"),D=i(l,"invariants"),V=i(p,"adminExpressions"),v=i(c,"adminInvariants"),M=o(d,"expressions"),B=o(l,"invariants"),I=o(p,"adminExpressions"),F=o(c,"adminInvariants"),w=t(B),b=t(M),R=t(F),T=t(I),C=[y,D,V,v].filter(Boolean).join("\n"),P=[$,f].filter(Boolean).join("\n"),S=d.length>1||l.length>1||p.length>1||c.length>1,k=a(u,h),q=a(g,A),z=E?`
5
+ }`};export const generateIndexDomainFile=(s={})=>{let{includeMigrations:r=!0,includeI18n:m=!0,expressionsFiles:d=[],invariantsFiles:l=[],adminExpressionsFiles:p=[],adminInvariantsFiles:c=[],migrationsFiles:x=[],adminMigrationsFiles:g=[]}=s,u=(n,i)=>`${i?"adminMigrateToV":"migrateToV"}${e(n)}`,$=x.map(n=>{let i=e(n),o=n.replace(/\.ts$/,""),t=`../src/${o}.js`;return`import { migrateToV${i} } from '${t}'`}).join("\n"),A=g.map(n=>{let i=e(n),o=n.replace(/\.ts$/,""),t=`../src/${o}.js`;return`import { migrateToV${i} as adminMigrateToV${i} } from '${t}'`}).join("\n"),h=x.map(n=>u(n,!1)),f=g.map(n=>u(n,!0)),E=x.length>0,j=g.length>0,y=i(d,"expressions"),D=i(l,"invariants"),V=i(p,"adminExpressions"),M=i(c,"adminInvariants"),F=o(d,"expressions"),I=o(l,"invariants"),v=o(p,"adminExpressions"),w=o(c,"adminInvariants"),B=t(I),R=t(F),b=t(w),T=t(v),C=[y,D,V,M].filter(Boolean).join("\n"),P=[$,A].filter(Boolean).join("\n"),S=d.length>1||l.length>1||p.length>1||c.length>1,k=a(x,h),q=a(g,f),z=E?`
6
6
  const migrations = ${k}
7
7
 
8
- const migrate = MigrateFunctionBuilder.fromVersions(modelVersions).to(modelVersion).using(migrations).build()`:"",G=j?`
8
+ const migrate = createMigrateFunction(modelVersions, modelVersion, migrations)`:"",G=j?`
9
9
  const adminMigrations = ${q}
10
10
 
11
- const migrateAdmin = MigrateFunctionBuilder.fromVersions(adminModelVersions).to(adminModelVersion).using(adminMigrations).build()`:"";return`${n}
11
+ const migrateAdmin = createMigrateFunction(adminModelVersions, adminModelVersion, adminMigrations)`:"";return`${n}
12
12
  ${S?"import merge from 'lodash-es/merge.js'\n":""}
13
- import { type AliasedExpressions${r&&(E||j)?", MigrateFunctionBuilder":""} } from '@salsita-ai/sdk/domain'
13
+ import { type AliasedExpressions${r&&(E||j)?", createMigrateFunction":""}, createViolationExpressions } from '@salsita-ai/sdk/domain'
14
14
 
15
15
  ${m?"import { createI18n } from './i18n.js'":""}
16
- import { adminDomainBuilder, adminInvariantBuilder } from './domain/admin-implementation.js'
16
+ import { adminDomainBuilder, commonAdminInvariants } from './domain/admin-implementation.js'
17
17
  import type {
18
18
  Aliases as AdminAliases,
19
19
  AnyDomainEntity as AdminAnyDomainEntity,
20
20
  RootEntity as AdminRootEntity,
21
21
  } from './domain/admin-model/index.js'
22
- ${j?"import { modelVersion as adminModelVersion, modelVersions as adminModelVersions } from './domain/admin-model/index.js'\n":""}
22
+ import { aliases as adminAliases${j?", modelVersion as adminModelVersion, modelVersions as adminModelVersions":""} } from './domain/admin-model/index.js'
23
23
  import type { FrontendData, PublishedData, SessionData } from './domain/application-types.js'
24
24
  import {
25
25
  generatedConfiguratorBuilder,
26
26
  } from './domain/configurator-builder.js'
27
- import { domainBuilder, invariantBuilder } from './domain/implementation.js'
27
+ import { domainBuilder } from './domain/implementation.js'
28
28
  import type { Aliases, AnyDomainEntity, RootEntity } from './domain/model/index.js'
29
- ${E?"import { modelVersion, modelVersions } from './domain/model/index.js'\n":""}
29
+ import { aliases${E?", modelVersion, modelVersions":""} } from './domain/model/index.js'
30
30
  ${C?`
31
31
  ${C}`:""}
32
32
  ${P?`
33
33
  ${P}`:""}${z}${G}
34
34
 
35
- const customInvariants = ${w}
35
+ const customInvariants = ${B}
36
36
 
37
- const violationExpressions = invariantBuilder.withInvariants(customInvariants).buildViolationExpressions()
37
+ const violationExpressions = createViolationExpressions(aliases, [{ origin: '.phoenix/domain.ts', exports: customInvariants }])
38
38
 
39
39
  const customExpressions: AliasedExpressions<
40
40
  AnyDomainEntity,
@@ -43,18 +43,20 @@ const customExpressions: AliasedExpressions<
43
43
  SessionData,
44
44
  FrontendData,
45
45
  Aliases
46
- > = ${b}
46
+ > = ${R}
47
47
 
48
48
  const domainFactory = domainBuilder
49
49
  .withExpressions(violationExpressions)
50
50
  .withExpressions(customExpressions)${r&&E?"\n .withMigrate(migrate)":""}
51
51
  .build()
52
52
 
53
- const customAdminInvariants = ${R}
53
+ const customAdminInvariants = ${b}
54
54
 
55
- const adminViolationExpressions = adminInvariantBuilder
56
- .withInvariants(customAdminInvariants)
57
- .buildViolationExpressions()
55
+ const adminViolationExpressions = createViolationExpressions(
56
+ adminAliases,
57
+ [{ origin: '.phoenix/domain.ts', exports: customAdminInvariants }],
58
+ commonAdminInvariants
59
+ )
58
60
 
59
61
  const customAdminExpressions: AliasedExpressions<
60
62
  AdminAnyDomainEntity,
@@ -1 +1 @@
1
- import{existsSync as e,lstatSync as i,readFileSync as t,readdirSync as r,rmSync as o,unlinkSync as s}from"fs";import{join as n}from"path";import{format as a}from"prettier";import{prettierrc as l}from"@salsita-ai/common/prettier";import{GeneratedApplication as c,GeneratedApplicationFile as p,RuntimeReferenceStore as g,buildPhoenixDefinitions as f,createContentDiffTracker as h,generateApplicationCode as m,parseApplicationFiles as d}from"#package/application-spec";import{getAllPhxDefinitions as u}from"#package/domain";import{compileWithSwc as S}from"../services/swc.js";import{syncChangedFiles as b}from"../utils/index.js";import{readApplicationFiles as w}from"./application-spec-file-reader.js";import{cleanStaleAgentSkills as j,removeProjectFiles as v}from"./clean-project-files.js";import{swcEvalExpressionParser as D,swcModuleAnalyzer as F}from"./swc-module-analyzer.js";let x=".phoenix",y=`${x}/`,P=async e=>{if(e.binary||!1===e.format)return e;try{let i=await a(e.content,{...l,filepath:e.path});return p(e.path,i,{binary:e.binary,format:e.format})}catch{return e}},k=async e=>{let[i,t,r]=await Promise.all([Promise.all(e.generatedProjectFiles.map(P)),Promise.all(e.initialProjectFiles.map(P)),Promise.all(e.prettierFiles.map(P))]);return c({files:e.files,generatedProjectFiles:i,initialProjectFiles:t,prettierFiles:r,removedProjectFiles:e.removedProjectFiles})};export class ApplicationSpecBuilder{contentDiff;referenceStore;config;logger;phxDefinitions;constructor(e){this.config=e,this.logger=e.logger,this.referenceStore=new g,this.contentDiff=h({readDiskContent:this.readDiskContent}),this.phxDefinitions=f(u())}async build(e){let i=e?.parsingContext,t=e?.compile??!0;e?.force&&this.referenceStore.clear();let r=i?.startSpan("readFiles","build","application-spec-builder.ts"),o=e?.rawProjectFiles??await w({envs:{}});r?.();let s=d({rawProjectFiles:o,phxDefinitions:this.phxDefinitions},{analyzer:F,evalExpressionParser:D,referenceStore:this.referenceStore,logger:this.logger,parsingContext:i});if(!s.ok)return{ok:!1,rawProjectFiles:o,errors:s.errors,diagnostics:s.diagnostics,metrics:s.metrics,counts:s.counts};let{applicationSpec:n,categorizedFiles:a,rawMockTemplates:l}=s.value,c=i?.startSpan("generateCode","build","application-spec-builder.ts"),p=m({applicationSpec:n,categorizedFiles:a,phxDefinitions:this.phxDefinitions,sdkVersion:this.config.sdkVersion,cliUseWorkspace:this.config.cliUseWorkspace,name:this.config.name,description:this.config.description,projectSlug:this.config.projectSlug,environmentSlug:this.config.environmentSlug,enableEditor:this.config.enableEditor,inlineTemplates:this.config.inlineTemplates,rawMockTemplates:l});c?.();let g=i?.startSpan("cleanStaleFiles","build","application-spec-builder.ts"),f=new Set(p.files.map(e=>e.path));this.cleanStaleGeneratedFiles(f),v(p.removedProjectFiles,{logger:this.logger}),j(new Set(p.generatedProjectFiles.map(e=>e.path)),{logger:this.logger}),g?.();let h=i?.startSpan("contentDiff","build","application-spec-builder.ts"),u=await k(p),S=this.contentDiff.getChangedApplicationFiles(u,{generatedFilesPathPrefix:y,force:e?.force}),x=S.changedGeneratedFiles;h?.(),x.length>0?this.logger.info(` ${x.length}/${p.files.length} generated files changed`):this.logger.info(" No generated files changed");let P=S.filesToWrite.length-x.length;P>0&&this.logger.info(` ${P} project files changed`);let C=i?.startSpan("writeFiles","build","application-spec-builder.ts");return await b(S.filesToWrite,{logger:this.logger,skipChecksum:!0}),C?.(),t&&await this.compile(i),{ok:!0,application:s.value,changedFiles:x,diagnostics:s.diagnostics,metrics:s.metrics,counts:s.counts}}async compile(e){let i=e?.startSpan("swcCompile(src)","build","application-spec-builder.ts");await S({sourceDir:"src",outDir:`./${x}/.swc/src`},{logger:this.logger}),i?.();let t=e?.startSpan("swcCompile(.phoenix)","build","application-spec-builder.ts");await S({sourceDir:x,outDir:`./${x}/.swc/${x}`},{logger:this.logger}),t?.()}readDiskContent=i=>{try{if(e(i))return t(i,"utf-8")}catch{}};cleanStaleGeneratedFiles(t){let a=new Set(["public",".swc","dist","phoenix-dev.log","phoenix-dev.log.1","phoenix-dev.log.2","variants","variant-recovery.json"]);try{if(!e(x))return;for(let e of r(x)){if(a.has(e)||t.has(e))continue;let r=n(x,e);try{let e=i(r);if(e.isSymbolicLink())continue;e.isDirectory()?o(r,{recursive:!0}):s(r),this.logger.debug(` Removed stale: ${r}`)}catch{}}}catch{}}}
1
+ import{existsSync as e,lstatSync as i,readFileSync as t,readdirSync as r,rmSync as o,unlinkSync as s}from"fs";import{join as n}from"path";import{format as a}from"prettier";import{prettierrc as l}from"@salsita-ai/common/prettier";import{GeneratedApplication as c,GeneratedApplicationFile as p,RuntimeReferenceStore as g,buildPhoenixDefinitions as f,createContentDiffTracker as h,generateApplicationCode as d,parseApplicationFiles as m}from"#package/application-spec";import{getAllPhxDefinitions as u}from"#package/domain";import{compileWithSwc as w}from"../services/swc.js";import{isInsideGitRepository as b,syncChangedFiles as S}from"../utils/index.js";import{readApplicationFiles as j}from"./application-spec-file-reader.js";import{cleanStaleAgentSkills as v,removeProjectFiles as D}from"./clean-project-files.js";import{swcEvalExpressionParser as F,swcModuleAnalyzer as x}from"./swc-module-analyzer.js";let y=".phoenix",P=`${y}/`,k=async e=>{if(e.binary||!1===e.format)return e;try{let i=await a(e.content,{...l,filepath:e.path});return p(e.path,i,{binary:e.binary,format:e.format})}catch{return e}},C=async e=>{let[i,t,r]=await Promise.all([Promise.all(e.generatedProjectFiles.map(k)),Promise.all(e.initialProjectFiles.map(k)),Promise.all(e.prettierFiles.map(k))]);return c({files:e.files,generatedProjectFiles:i,initialProjectFiles:t,prettierFiles:r,removedProjectFiles:e.removedProjectFiles})};export class ApplicationSpecBuilder{contentDiff;referenceStore;config;logger;phxDefinitions;constructor(e){this.config=e,this.logger=e.logger,this.referenceStore=new g,this.contentDiff=h({readDiskContent:this.readDiskContent}),this.phxDefinitions=f(u())}async build(e){let i=e?.parsingContext,t=e?.compile??!0;e?.force&&this.referenceStore.clear();let r=i?.startSpan("readFiles","build","application-spec-builder.ts"),o=e?.rawProjectFiles??await j({envs:{}});r?.();let s=m({rawProjectFiles:o,phxDefinitions:this.phxDefinitions},{analyzer:x,evalExpressionParser:F,referenceStore:this.referenceStore,logger:this.logger,parsingContext:i});if(!s.ok)return{ok:!1,rawProjectFiles:o,errors:s.errors,diagnostics:s.diagnostics,metrics:s.metrics,counts:s.counts};let{applicationSpec:n,categorizedFiles:a,rawMockTemplates:l}=s.value,c=i?.startSpan("generateCode","build","application-spec-builder.ts"),p=b(process.cwd());p||this.logger.debug(" Not inside a git repository, .gitignore is not written");let g=d({applicationSpec:n,categorizedFiles:a,phxDefinitions:this.phxDefinitions,sdkVersion:this.config.sdkVersion,projectInGitRepository:p,cliUseWorkspace:this.config.cliUseWorkspace,name:this.config.name,description:this.config.description,projectSlug:this.config.projectSlug,environmentSlug:this.config.environmentSlug,enableEditor:this.config.enableEditor,inlineTemplates:this.config.inlineTemplates,rawMockTemplates:l});c?.();let f=i?.startSpan("cleanStaleFiles","build","application-spec-builder.ts"),h=new Set(g.files.map(e=>e.path));this.cleanStaleGeneratedFiles(h),D(g.removedProjectFiles,{logger:this.logger}),v(new Set(g.generatedProjectFiles.map(e=>e.path)),{logger:this.logger}),f?.();let u=i?.startSpan("contentDiff","build","application-spec-builder.ts"),w=await C(g),y=this.contentDiff.getChangedApplicationFiles(w,{generatedFilesPathPrefix:P,force:e?.force}),k=y.changedGeneratedFiles;u?.(),k.length>0?this.logger.info(` ${k.length}/${g.files.length} generated files changed`):this.logger.info(" No generated files changed");let $=y.filesToWrite.length-k.length;$>0&&this.logger.info(` ${$} project files changed`);let T=i?.startSpan("writeFiles","build","application-spec-builder.ts");return await S(y.filesToWrite,{logger:this.logger,skipChecksum:!0}),T?.(),t&&await this.compile(i),{ok:!0,application:s.value,changedFiles:k,diagnostics:s.diagnostics,metrics:s.metrics,counts:s.counts}}async compile(e){let i=e?.startSpan("swcCompile(src)","build","application-spec-builder.ts");await w({sourceDir:"src",outDir:`./${y}/.swc/src`},{logger:this.logger}),i?.();let t=e?.startSpan("swcCompile(.phoenix)","build","application-spec-builder.ts");await w({sourceDir:y,outDir:`./${y}/.swc/${y}`},{logger:this.logger}),t?.()}readDiskContent=i=>{try{if(e(i))return t(i,"utf-8")}catch{}};cleanStaleGeneratedFiles(t){let a=new Set(["public",".swc","dist","phoenix-dev.log","phoenix-dev.log.1","phoenix-dev.log.2","variants","variant-recovery.json"]);try{if(!e(y))return;for(let e of r(y)){if(a.has(e)||t.has(e))continue;let r=n(y,e);try{let e=i(r);if(e.isSymbolicLink())continue;e.isDirectory()?o(r,{recursive:!0}):s(r),this.logger.debug(` Removed stale: ${r}`)}catch{}}}catch{}}}
@@ -6,10 +6,10 @@ export interface InitCommandProps {
6
6
  }
7
7
  /**
8
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, and switches the project to the application-spec
10
- * pipeline. It touches no server and asks
11
- * nothing: the starter spec names the default project of whichever workspace the developer signs in to, and
12
- * everything else is generated by sync or the build.
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.
13
13
  *
14
14
  * Refuses when a `spec/` folder exists, and when an existing `package.json` does not depend on the SDK.
15
15
  */
@@ -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 a}from"../utils/index.js";import{starterSpecFiles as s}from"./init-starter-spec.js";let c="@salsita-ai/sdk",l=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}},d=async e=>{for(let t of s){let o=p(e,t.path);await n(r(o),{recursive:!0}),await i(o,t.content)}},m=async(e,n)=>{let t=n.phoenix;await i(e,JSON.stringify({...n,phoenix:{..."object"==typeof t&&null!==t?t:{},applicationFlow:!0}},null,2)+"\n")};export const runInitCommand=async(t,{logger:i})=>{var r,s;let f,u=t.projectRoot??process.cwd(),h=p(u,"package.json");if(e(p(u,"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(h)?await l(h):(r=u,s=t.sdkVersion,{name:(f=o(r).toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^[._-]+|[-]+$/g,"")).length>0?f:"phoenix-configurator",private:!0,type:"module",dependencies:{[c]:s},devDependencies:{"@lingui/cli":"5.9.5","@lingui/swc-plugin":"5.11.0"}});i.step(`Writing the starter project to ${u}`),await n(u,{recursive:!0}),await d(u),await m(h,w),a(u),i.success(`Phoenix project created in ${u}.`),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 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 +1 @@
1
- import{readFile as t,writeFile as e}from"fs/promises";import{globby as o}from"globby";import{resolve as r}from"path";import*as i from"prettier";let a=["**/node_modules/**","**/dist/**","**/.git/**","**/webhooks/index.ts`","**/frontend-configurator.ts`","**/frontend-admin.ts`","**/frontend-embedded-admin.ts`","pnpm-lock.yaml",".linguirc"];export const formatFiles=async(n,f)=>{let{logger:l}=f,s=await o("."===n?"**/*":n,{gitignore:!0,ignore:a}),c=0;for(let o of s)try{let a=r(o),n=await t(a,"utf-8"),f=await i.resolveConfig(a);if((await i.getFileInfo(a)).ignored)continue;let l=await i.format(n,{...f,filepath:a});l!==n&&(await e(a,l,"utf-8"),c++)}catch(t){}c>0&&l.info(`Formatted ${c} file${1!==c?"s":""}`)};export const checkFiles=async(e,n)=>{let{logger:f}=n,l=await o("."===e?"**/*":e,{gitignore:!0,ignore:a}),s=[];for(let e of l)try{let o=r(e),a=await t(o,"utf-8"),n=await i.resolveConfig(o);if((await i.getFileInfo(o)).ignored)continue;await i.check(a,{...n,filepath:o})||s.push(e)}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
+ 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)};
@@ -0,0 +1 @@
1
+ export { isInsideGitRepository } from './is-inside-git-repository.js';
@@ -0,0 +1 @@
1
+ export{isInsideGitRepository}from"./is-inside-git-repository.js";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Whether a folder is inside a git work tree: the folder or one of its parents, up to the file-system root, holds a
3
+ * `.git` entry. The entry is a directory in a plain checkout and a file in a linked worktree or a submodule; both
4
+ * count. Only the file system is read, so the answer does not depend on git being installed.
5
+ */
6
+ export declare const isInsideGitRepository: (folder: string) => boolean;
@@ -0,0 +1 @@
1
+ import{existsSync as t,realpathSync as r}from"fs";import{dirname as e,join as i,resolve as o}from"path";export const isInsideGitRepository=f=>{let n=(t=>{let e=o(t);try{return r(e)}catch{return e}})(f);for(;;){if(t(i(n,".git")))return!0;let r=e(n);if(r===n)return!1;n=r}};
@@ -4,6 +4,7 @@ export { formatEnvContent, formatEnvLine } from './env-file.js';
4
4
  export { parseChangelog, getLatestVersion, getVersion, paginateVersions, getVersionNumbers, type ChangelogVersion, type PaginatedVersions, } from './changelog-parser.js';
5
5
  export { createDirectoryFromYaml, exists, scanFolderForFiles, syncChangedFiles, syncExistingFolders, validateFolders, writeFileIfNotExists, writeFilesIfNotExists, writeRawFiles, } from './file-system.js';
6
6
  export { FileLogger } from './file-logger.js';
7
+ export { isInsideGitRepository } from './git/index.js';
7
8
  export { type Logger, type CreateLoggerOptions, createLogger } from './logger.js';
8
9
  export { addWorkspaceOverrides, ensureWorkspaceInstallSettings, getLocalOverrides, getSdkPackages, getWorkspaceDir, hasLocalOverrides, readPackageJson, removeWorkspaceOverrides, } from './package-info.js';
9
10
  export { toPascalCase } from './pascal-case.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{createLogger}from"./logger.js";export{addWorkspaceOverrides,ensureWorkspaceInstallSettings,getLocalOverrides,getSdkPackages,getWorkspaceDir,hasLocalOverrides,readPackageJson,removeWorkspaceOverrides}from"./package-info.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,ensureWorkspaceInstallSettings,getLocalOverrides,getSdkPackages,getWorkspaceDir,hasLocalOverrides,readPackageJson,removeWorkspaceOverrides}from"./package-info.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";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salsita-ai/sdk",
3
- "version": "0.50.0-develop.abef6d86a1",
3
+ "version": "0.50.0-develop.ae52227c7e",
4
4
  "description": "TypeScript SDK and CLI for building, running, and deploying Phoenix configurator applications.",
5
5
  "keywords": [
6
6
  "salsita",
@@ -292,8 +292,8 @@
292
292
  "yaml": "2.9.0",
293
293
  "yargs": "17.7.2",
294
294
  "zod": "3.25.76",
295
- "@salsita-ai/common": "0.50.0-develop.abef6d86a1",
296
- "@salsita-ai/contracts": "0.50.0-develop.abef6d86a1"
295
+ "@salsita-ai/common": "0.50.0-develop.ae52227c7e",
296
+ "@salsita-ai/contracts": "0.50.0-develop.ae52227c7e"
297
297
  },
298
298
  "devDependencies": {
299
299
  "@clerk/clerk-react": "5.61.8",
@@ -1,26 +0,0 @@
1
- import { type $DomainEntity, type AliasMap, type AliasedInvariants, type AnonymousExpression, type DomainEntity, type EntityByType, type EventualAlias, type ExpandAlias, type ExtractFromAliasedRecord, type Invariant, type TypeOrAlias, type Violation } from '../../core/index.js';
2
- import { type ProjectModule } from './module-checks/index.js';
3
- type ViolationOfInvariants<INVARIANTS> = INVARIANTS extends ReadonlyArray<infer INVARIANT> ? INVARIANT : never;
4
- type ExpandAndMergeInvariants<ENTITIES extends DomainEntity<string>, ALLOWED_ROOT_ENTITIES extends ENTITIES, PUBLISHED_DATA extends Record<string, unknown>, SESSION_DATA extends Record<string, unknown>, FRONTEND_DATA extends Record<string, unknown>, ALIASES extends Readonly<Record<string, ENTITIES>>, EXPANDED extends Partial<Record<ENTITIES['type'], ReadonlyArray<Invariant<ENTITIES, ALLOWED_ROOT_ENTITIES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ENTITIES, string>>>>, ALIASED extends Partial<Record<TypeOrAlias<ENTITIES, ALIASES>, ReadonlyArray<Invariant<ENTITIES, ALLOWED_ROOT_ENTITIES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ENTITIES, string>>>>> = {
5
- [K in keyof EXPANDED | ExpandAlias<ENTITIES, ALIASES, keyof ALIASED & string>['type']]: K extends ENTITIES['type'] ? ExtractFromAliasedRecord<ENTITIES, ALIASES, ALIASED, EventualAlias<ENTITIES, ALIASES, K> | K> extends infer INVARIANTS_FROM_ALIAS ? [
6
- INVARIANTS_FROM_ALIAS
7
- ] extends [never] ? K extends keyof EXPANDED ? EXPANDED[K] : never : K extends keyof EXPANDED ? ReadonlyArray<ViolationOfInvariants<EXPANDED[K]> | ViolationOfInvariants<INVARIANTS_FROM_ALIAS>> : ReadonlyArray<ViolationOfInvariants<INVARIANTS_FROM_ALIAS>> : never : never;
8
- };
9
- type ExpressionsFromInvariants<ENTITIES extends DomainEntity<string>, ALLOWED_ROOT_ENTITIES extends ENTITIES, PUBLISHED_DATA extends Record<string, unknown>, SESSION_DATA extends Record<string, unknown>, FRONTEND_DATA extends Record<string, unknown>, INVARIANTS extends Partial<Record<ENTITIES['type'], ReadonlyArray<Invariant<ENTITIES, ALLOWED_ROOT_ENTITIES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ENTITIES, string>>>>> = {
10
- [K in keyof INVARIANTS & ENTITIES['type']]: {
11
- $violations: AnonymousExpression<ENTITIES, ALLOWED_ROOT_ENTITIES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, EntityByType<ENTITIES, K>, ReadonlyArray<Violation<INVARIANTS[K] extends ReadonlyArray<infer ELEMENT> ? ELEMENT extends Invariant<any, any, any, any, any, any, infer VIOLATION_TYPE> ? VIOLATION_TYPE : never : never>>>;
12
- };
13
- };
14
- export declare class InvariantBuilder<ENTITIES extends DomainEntity<string>, ALLOWED_ROOT_ENTITIES extends ENTITIES, $MAP extends Record<ENTITIES['type'], $DomainEntity<ENTITIES>>, PUBLISHED_DATA extends Record<string, unknown>, SESSION_DATA extends Record<string, unknown>, FRONTEND_DATA extends Record<string, unknown>, ALIASES extends Record<string, ENTITIES>, INVARIANTS extends Partial<Record<ENTITIES['type'], ReadonlyArray<Invariant<ENTITIES, ALLOWED_ROOT_ENTITIES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ENTITIES, string>>>> = Record<never, never>> {
15
- private readonly aliasMap;
16
- private readonly invariants;
17
- constructor(aliasMap: AliasMap<ALIASES>, invariants?: INVARIANTS);
18
- /**
19
- * Adds the invariants of the `src/invariants/` files, as the generated barrel lists them, after
20
- * checking each file against the folder's contract.
21
- */
22
- withInvariantModules(modules: readonly ProjectModule[]): InvariantBuilder<ENTITIES, ALLOWED_ROOT_ENTITIES, $MAP, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ALIASES, ExpandAndMergeInvariants<ENTITIES, ALLOWED_ROOT_ENTITIES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ALIASES, INVARIANTS, AliasedInvariants<ENTITIES, ALLOWED_ROOT_ENTITIES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ALIASES, string>>>;
23
- withInvariants<ALIASED_INVARIANTS extends AliasedInvariants<ENTITIES, ALLOWED_ROOT_ENTITIES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ALIASES, string>>(aliasedInvariants: ALIASED_INVARIANTS): InvariantBuilder<ENTITIES, ALLOWED_ROOT_ENTITIES, $MAP, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ALIASES, ExpandAndMergeInvariants<ENTITIES, ALLOWED_ROOT_ENTITIES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, ALIASES, INVARIANTS, ALIASED_INVARIANTS>>;
24
- buildViolationExpressions: () => ExpressionsFromInvariants<ENTITIES, ALLOWED_ROOT_ENTITIES, PUBLISHED_DATA, SESSION_DATA, FRONTEND_DATA, INVARIANTS>;
25
- }
26
- export {};
@@ -1 +0,0 @@
1
- import{expandAlias as a}from"../../core/index.js";import{resolveInvariantModules as i}from"./module-checks/index.js";export class InvariantBuilder{aliasMap;invariants;constructor(a,i={}){this.aliasMap=a,this.invariants=i}withInvariantModules(a){return this.withInvariants(i(a))}withInvariants(i){let t={...this.invariants};return Object.entries(i).forEach(([i,r])=>{a(this.aliasMap,i).forEach(a=>{t[a]=[...t[a]??[],...r]})}),new InvariantBuilder(this.aliasMap,t)}buildViolationExpressions=()=>{let a={};return Object.entries(this.invariants).forEach(([i,t])=>{a[i]={$violations:{evaluate:(a,i,r)=>t.flatMap(t=>t.evaluate(a,i,r)),meta:{}}}}),a}}