@ostack.tech/ui-kform-scaffolder 0.3.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -139,78 +139,55 @@ function scaffoldIssueMessagesConstant(schematic, data) {
139
139
  export const ${constantCase(schematic.name)}_ISSUE_MESSAGES: Record<string, IssueMessagesByCode> = {};
140
140
  `);
141
141
  }
142
- function scaffoldFormPages(schematic, data) {
142
+ function scaffoldPageComponents(schematic, data) {
143
143
  const layout = reactAppLayout(schematic, {
144
144
  kmpModuleName: `${kebabCase(schematic.name)}-shared`,
145
145
  ...data
146
146
  });
147
147
  for (const annex of layout) {
148
148
  for (const formPage of annex.formPages) {
149
- scaffoldFormPage(formPage.schematic, formPage.data);
149
+ scaffoldPageComponent(formPage.schematic, formPage.data);
150
150
  if (formPage.data.currentPath !== "/") {
151
151
  scaffoldIssueMessages(formPage.schematic, formPage.data);
152
152
  }
153
153
  }
154
154
  }
155
155
  }
156
- function scaffoldFormPage(schematic, data) {
156
+ function scaffoldPageComponent(schematic, data) {
157
157
  const fileName = joinPaths(data.currentDir, `${schematic.name}.tsx`);
158
158
  let file = data.files.get(fileName);
159
159
  if (!file) {
160
160
  data.files.set(fileName, file = tsFile());
161
161
  }
162
- scaffoldFormPageComponent(schematic, {
162
+ scaffoldPageComponentDeclarations(schematic, {
163
163
  kmpModuleName: `${kebabCase(data.rootSchematic.name)}-shared`,
164
164
  ...data,
165
165
  currentFile: file
166
166
  });
167
167
  }
168
- function scaffoldFormPageComponent(schematic, data) {
169
- data.currentFile.imports.push(
170
- { moduleName: "@ostack.tech/ui-kform", name: "FormPage" },
171
- { moduleName: "@ostack.tech/ui", name: "Grid" }
172
- );
173
- if (data.currentPath !== "/") {
174
- data.currentFile.imports.push({
175
- moduleName: `./${schematic.name}IssueMessages.tsx`,
176
- name: `${constantCase(schematic.name)}_ISSUE_MESSAGES`
177
- });
178
- }
179
- let pathString;
180
- let preamble;
181
- const splitPath = data.currentPath.split("/");
182
- if (splitPath.some((fragment) => fragment === "*")) {
183
- data.currentFile.imports.push({
184
- moduleName: "react-router",
185
- name: "useParams"
186
- });
187
- pathString = `{\`${splitPath.map((f) => f === "*" ? "${id}" : f).join("/")}\`}`;
188
- preamble = "\n const { id } = useParams();\n";
189
- } else {
190
- pathString = `"${data.currentPath}"`;
191
- preamble = "";
192
- }
193
- const pageComponent = code`
194
- export function ${schematic.name}() {${preamble}
168
+ function scaffoldPageComponentDeclarations(schematic, data) {
169
+ data.currentFile.imports.push({
170
+ moduleName: "@ostack.tech/ui",
171
+ name: "Grid"
172
+ });
173
+ data.currentFile.declarations.push(code`
174
+ export function ${schematic.name}() {
195
175
  return (
196
- <FormPage${data.currentPath === "/" ? "" : ` path=${pathString} issueMessages={${constantCase(schematic.name)}_ISSUE_MESSAGES}`}>
197
- <Grid container>
198
- ${schematic.children.map(
176
+ <Grid container>
177
+ ${schematic.children.map(
199
178
  (child) => code`
200
- <Grid xs={12}>
201
- ${scaffoldField(child, {
179
+ <Grid xs={12}>
180
+ ${scaffoldField(child, {
202
181
  ...data,
203
182
  currentPath: child.childName
204
183
  })}
205
- </Grid>
206
- `
184
+ </Grid>
185
+ `
207
186
  ).join("\n\n")}
208
- </Grid>
209
- </FormPage>
187
+ </Grid>
210
188
  );
211
189
  }
212
- `;
213
- data.currentFile.declarations.push(pageComponent);
190
+ `);
214
191
  }
215
192
  function scaffoldField(schematic, data) {
216
193
  const schematicKind = data.schematicKinds.get(
@@ -753,6 +730,7 @@ function layoutAnnex(schematic, data) {
753
730
  }
754
731
  return { schematic, data, formPages };
755
732
  }
733
+ const DEFAULT_ACTIVE_PATH_SEARCH_PARAM = "activePath";
756
734
  function scaffoldAppComponent(schematic, data) {
757
735
  const fileName = joinPaths(data.currentDir, `${schematic.name}App.tsx`);
758
736
  let file = data.files.get(fileName);
@@ -768,10 +746,18 @@ function scaffoldAppComponent(schematic, data) {
768
746
  }
769
747
  function scaffoldAppComponentFile(schematic, data) {
770
748
  const localeVar = (data.defaultLocale ?? DEFAULT_LOCALE).replaceAll("-", "");
749
+ const activePathSearchParam = data.activePathSearchParam ?? DEFAULT_ACTIVE_PATH_SEARCH_PARAM;
771
750
  data.currentFile.imports.push(
772
751
  { moduleName: "@ostack.tech/kform", name: "ktMapToObject" },
752
+ { moduleName: "@ostack.tech/ui", name: "useSearchParam" },
773
753
  { moduleName: "@ostack.tech/ui-kform", name: "FormApp" },
774
754
  { moduleName: "@ostack.tech/ui-kform", name: localeVar },
755
+ { moduleName: "@ostack.tech/ui-kform", name: "TopBar" },
756
+ { moduleName: "@ostack.tech/ui-kform", name: "TopBarActions" },
757
+ { moduleName: "@ostack.tech/ui-kform", name: "Annexes" },
758
+ { moduleName: "@ostack.tech/ui-kform", name: "Annex" },
759
+ { moduleName: "@ostack.tech/ui-kform", name: "FormPages" },
760
+ { moduleName: "@ostack.tech/ui-kform", name: "IssuesPanel" },
775
761
  { moduleName: "react", name: "useMemo" },
776
762
  { moduleName: data.kmpModuleName, name: schematic.name },
777
763
  { moduleName: data.kmpModuleName, name: `${schematic.name}FormMode` },
@@ -784,11 +770,27 @@ function scaffoldAppComponentFile(schematic, data) {
784
770
  {
785
771
  moduleName: `./${schematic.name}IssueMessages.tsx`,
786
772
  name: `${constantCase(schematic.name)}_ISSUE_MESSAGES`
787
- }
773
+ },
774
+ { moduleName: "./actions/Load.tsx", name: "Load" },
775
+ { moduleName: "./actions/Save.tsx", name: "Save" },
776
+ { moduleName: "./actions/Validate.tsx", name: "Validate" },
777
+ { moduleName: "./actions/Submit.tsx", name: "Submit" }
788
778
  );
779
+ const layout = reactAppLayout(schematic, data);
780
+ let annexesManager = "";
781
+ if (layout.length > 1) {
782
+ data.currentFile.imports.push({
783
+ moduleName: "@ostack.tech/ui-kform",
784
+ name: "AnnexesManager"
785
+ });
786
+ annexesManager = `
787
+ <AnnexesManager />
788
+ `;
789
+ }
789
790
  data.currentFile.declarations.push(code`
790
791
  export function ${schematic.name}App() {
791
792
  const { externalContexts } = use${schematic.name}Context();
793
+ const [activePath, setActivePath] = useSearchParam("${activePathSearchParam}");
792
794
 
793
795
  return (
794
796
  <FormApp
@@ -807,79 +809,13 @@ function scaffoldAppComponentFile(schematic, data) {
807
809
  ? "manual"
808
810
  : "auto"
809
811
  }
812
+ activePath={activePath}
813
+ onActivePathChange={setActivePath}
810
814
  issueMessages={${constantCase(schematic.name)}_ISSUE_MESSAGES}
811
815
  defaultLocale={${localeVar}}
812
816
  reportError={reportError}
813
817
  >
814
- <${schematic.name}Layout />
815
- </FormApp>
816
- );
817
- }
818
- `);
819
- const layout = reactAppLayout(schematic, data);
820
- data.currentFile.imports.push(
821
- { moduleName: "react-router", name: "useNavigate" },
822
- { moduleName: "react-router", name: "useLocation" },
823
- { moduleName: "react-router", name: "Outlet" },
824
- { moduleName: "@ostack.tech/ui-kform", name: "Annexes" },
825
- { moduleName: "@ostack.tech/ui-kform", name: "Annex" },
826
- {
827
- moduleName: "@ostack.tech/ui-kform",
828
- name: "AnnexObject",
829
- isType: true
830
- },
831
- { moduleName: "@ostack.tech/ui-kform", name: "TopBar" },
832
- { moduleName: "@ostack.tech/ui-kform", name: "TopBarActions" },
833
- { moduleName: "./actions/Load.tsx", name: "Load" },
834
- { moduleName: "./actions/Save.tsx", name: "Save" },
835
- { moduleName: "./actions/Validate.tsx", name: "Validate" },
836
- { moduleName: "./actions/Submit.tsx", name: "Submit" },
837
- { moduleName: "@ostack.tech/ui-kform", name: "FormPages" },
838
- {
839
- moduleName: "@ostack.tech/ui-kform",
840
- name: "FormPageObject",
841
- isType: true
842
- },
843
- { moduleName: "@ostack.tech/ui-kform", name: "IssuesPanel" }
844
- );
845
- let annexesManager = "";
846
- if (layout.length > 1) {
847
- data.currentFile.imports.push({
848
- moduleName: "@ostack.tech/ui-kform",
849
- name: "AnnexesManager"
850
- });
851
- annexesManager = `
852
- <AnnexesManager />
853
- `;
854
- }
855
- let formPagesNavigation = "";
856
- if (layout.some((annex) => annex.formPages.length > 1)) {
857
- data.currentFile.imports.push({
858
- moduleName: "@ostack.tech/ui-kform",
859
- name: "FormPagesNavigation"
860
- });
861
- if (layout.every((annex) => annex.formPages.length > 1)) {
862
- formPagesNavigation = `
863
- <FormPagesNavigation />
864
- `;
865
- } else {
866
- formPagesNavigation = `
867
- {pages.length > 1 && <FormPagesNavigation />}
868
- `;
869
- }
870
- }
871
- data.currentFile.declarations.push(code`
872
- function ${schematic.name}Layout() {
873
- const navigate = useNavigate();
874
- const { pathname } = useLocation();
875
-
876
- const annexes: AnnexObject[] = useMemo(() => ${scaffoldAnnexesArray(layout)}, []);
877
-
878
- const pagesByAnnex: Record<string, FormPageObject[]> = useMemo(() => (${scaffoldFormPagesByAnnexObject(layout)}), []);
879
-
880
- return (
881
- <>
882
- <Annexes annexes={annexes} activeAnnex={pathname}>
818
+ <Annexes>
883
819
  <TopBar>${annexesManager}
884
820
  <TopBarActions>
885
821
  <Load />
@@ -889,64 +825,70 @@ function scaffoldAppComponentFile(schematic, data) {
889
825
  </TopBarActions>
890
826
  </TopBar>
891
827
 
892
- {Object.entries(pagesByAnnex).map(([annexPath, pages]) => (
893
- <Annex path={annexPath} key={annexPath}>
894
- <FormPages
895
- pages={pages}
896
- activePage={pathname}
897
- onActivePageChange={(activePage) => {
898
- const newPathname = activePage?.toString() ?? "/";
899
- if (pathname !== newPathname) {
900
- void navigate(newPathname, {
901
- replace: newPathname.startsWith(
902
- pathname.endsWith("/") ? pathname : \`\${pathname}/\`,
903
- )
904
- });
905
- }
906
- }}
907
- >${formPagesNavigation}
908
- <Outlet />
909
- </FormPages>
910
- </Annex>
911
- ))}
828
+ ${scaffoldAnnexes(layout, data)}
912
829
  </Annexes>
913
830
 
914
831
  <IssuesPanel />
915
- </>
832
+ </FormApp>
916
833
  );
917
834
  }
918
835
  `);
919
836
  }
920
- function scaffoldAnnexesArray(layout) {
837
+ function scaffoldAnnexes(layout, data) {
838
+ return layout.map((annex) => scaffoldAnnex(annex, data)).join("\n\n");
839
+ }
840
+ function scaffoldAnnex(annex, data) {
841
+ let formPagesNavigation = "";
842
+ if (annex.formPages.length > 1) {
843
+ data.currentFile.imports.push({
844
+ moduleName: "@ostack.tech/ui-kform",
845
+ name: "FormPagesNavigation"
846
+ });
847
+ formPagesNavigation = `
848
+ <FormPagesNavigation />
849
+ `;
850
+ }
921
851
  return code`
922
- [
923
- ${layout.map(
924
- (annex) => `{ path: "${annex.data.currentPath}", title: "${sentenceCase(
925
- annex.schematic.name
926
- )}"${annex.formPages.length === 1 && annex.data.currentPath === annex.formPages[0].data.currentPath ? ", documentTitle: null" : ""} }`
927
- ).join(",\n")}
928
- ]
852
+ <Annex path="${annex.data.currentPath}" title="${sentenceCase(annex.schematic.name)}"${annex.formPages.length === 1 && annex.schematic === annex.formPages[0].schematic ? " documentTitle={null}" : ""}>
853
+ <FormPages>${formPagesNavigation}
854
+ ${annex.formPages.map((formPage) => scaffoldFormPage(annex, formPage, data))}
855
+ </FormPages>
856
+ </Annex>
929
857
  `;
930
858
  }
931
- function scaffoldFormPagesByAnnexObject(layout) {
932
- return code`
933
- {
934
- ${layout.map(
935
- (annex) => `"${annex.data.currentPath}": ` + code`
936
- [
937
- ${annex.formPages.map(
938
- (formPage) => annex.schematic === formPage.schematic ? `{ title: "${sentenceCase(
939
- formPage.schematic.name
940
- )}", code: "${formPage.schematic.name?.[0].toUpperCase()}"${formPage.data.currentPath === "/" ? ", documentTitle: null" : ""} }` : `{ path: "${formPage.data.currentPath.slice(
941
- annex.data.currentPath.length + (annex.data.currentPath.endsWith("/") ? 0 : 1)
942
- )}", title: "${sentenceCase(
859
+ function scaffoldFormPage(annex, formPage, data) {
860
+ data.currentFile.imports.push({
861
+ moduleName: `./${joinPaths(
862
+ formPage.data.currentDir.slice(
863
+ data.currentDir.length + (data.currentDir.endsWith("/") ? 0 : 1)
864
+ ),
865
+ formPage.schematic.name
866
+ )}.tsx`,
867
+ name: formPage.schematic.name
868
+ });
869
+ let issueMessagesProp = "";
870
+ if (formPage.data.currentPath !== "/") {
871
+ data.currentFile.imports.push({
872
+ moduleName: `./${joinPaths(
873
+ formPage.data.currentDir.slice(
874
+ data.currentDir.length + (data.currentDir.endsWith("/") ? 0 : 1)
875
+ ),
943
876
  formPage.schematic.name
944
- )}", code: "${formPage.schematic.name?.[0].toUpperCase()}" }`
945
- ).join(",\n")}
946
- ]
947
- `
948
- ).join(",\n")}
949
- }
877
+ )}IssueMessages.tsx`,
878
+ name: `${constantCase(formPage.schematic.name)}_ISSUE_MESSAGES`
879
+ });
880
+ issueMessagesProp = ` issueMessages={${constantCase(formPage.schematic.name)}_ISSUE_MESSAGES}`;
881
+ }
882
+ const pathProp = annex.schematic === formPage.schematic ? "" : ` path="${formPage.data.currentPath.slice(
883
+ annex.data.currentPath.length + (annex.data.currentPath.endsWith("/") ? 0 : 1)
884
+ )}"`;
885
+ const documentTitleProp = formPage.data.currentPath === "/" ? " documentTitle={null}" : "";
886
+ return code`
887
+ <FormPage${pathProp} title="${sentenceCase(
888
+ formPage.schematic.name
889
+ )}" code="${formPage.schematic.name?.[0].toUpperCase()}"${documentTitleProp}${issueMessagesProp}>
890
+ <${formPage.schematic.name} />
891
+ </FormPage>
950
892
  `;
951
893
  }
952
894
  const contextTsEjs = 'import { createContext, useContext } from "react";\nimport { <%= formClass %>ExternalContexts } from "<%= kmpModuleName %>";\n\nexport interface <%= formClass %>ContextValue {\n externalContexts: <%= formClass %>ExternalContexts;\n}\n\nexport const <%= formClass %>Context = createContext<<%= formClass %>ContextValue>(null as never);\n\nexport function use<%= formClass %>Context(): <%= formClass %>ContextValue {\n return useContext(<%= formClass %>Context);\n}\n';
@@ -977,11 +919,13 @@ function scaffoldExternalContexts(schematic, data) {
977
919
  }
978
920
  const buildGradleKts = "allprojects {\n repositories { mavenCentral() }\n}\n";
979
921
  const gradlePropertiesEjs = "group=<%= gradlePropertiesGroup %>\nversion=0.0.1\n\norg.gradle.caching=true\norg.gradle.configuration-cache=true\n";
980
- const libsVersionsTomlEjs = '[versions]\n# Plugins\nkotlin = "2.2.20"\nnodeGradle = "7.1.0"\n# Libraries\nkotlinxCoroutines = "1.10.2"\nkform = "<%= kFormVersion %>"\n<%_ if (usesKotlinxDatetime) { -%>\nkotlinxDatetime = "0.7.1"\n<%_ } -%>\n<%_ if (serializationFormat === "json") { -%>\nkotlinxSerialization = "1.9.0"\n<%_ } -%>\n<%_ if (usesKtMath) { -%>\nktMath = "0.10.2"\n<%_ } -%>\nslf4j = "2.0.17"\n<%_ if (serializationFormat === "xml") { -%>\nxmlutil = "0.91.1"\n<%_ } -%>\n# Runtimes\njvmToolchain = "17"\nnodejs = "22.20.0"\n\n[libraries]\nkform = { module = "tech.ostack:kform", version.ref = "kform" }\nkform-jsBindings = { module = "tech.ostack:kform-js-bindings", version.ref = "kform" }\nkotlinxCoroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" }\n<%_ if (usesKotlinxDatetime) { -%>\nkotlinxDatetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetime" }\n<%_ } -%>\n<%_ if (serializationFormat === "json") { -%>\nkotlinxSerialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerialization" }\n<%_ } -%>\n<%_ if (usesKtMath) { -%>\nktMath = { module = "io.github.gciatto:kt-math", version.ref = "ktMath" }\n<%_ } -%>\nslf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" }\n<%_ if (serializationFormat === "xml") { -%>\nxmlutil-serialization = { module = "io.github.pdvrieze.xmlutil:serialization", version.ref = "xmlutil" }\n<%_ } -%>\n\n[plugins]\nkotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }\nkotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }\nnodeGradle = { id = "com.github.node-gradle.node", version.ref = "nodeGradle" }\n';
922
+ const libsVersionsTomlEjs = '[versions]\n# Plugins\nkotlin = "2.2.21"\nnodeGradle = "7.1.0"\n# Libraries\nkotlinxCoroutines = "1.10.2"\nkform = "<%= kFormVersion %>"\n<%_ if (includeKotlinxDatetime) { -%>\nkotlinxDatetime = "0.7.1"\n<%_ } -%>\n<%_ if (serializationFormat === "json") { -%>\nkotlinxSerialization = "1.9.0"\n<%_ } -%>\n<%_ if (includeKtMath) { -%>\nktMath = "0.10.2"\n<%_ } -%>\nslf4j = "2.0.17"\n<%_ if (serializationFormat === "xml") { -%>\nxmlutil = "0.91.1"\n<%_ } -%>\n# Runtimes\njvmToolchain = "<%= jvmToolchainVersion %>"\nnodejs = "<%= nodejsVersion %>"\n\n[libraries]\nkform = { module = "tech.ostack:kform", version.ref = "kform" }\nkform-jsBindings = { module = "tech.ostack:kform-js-bindings", version.ref = "kform" }\nkotlinxCoroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" }\n<%_ if (includeKotlinxDatetime) { -%>\nkotlinxDatetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetime" }\n<%_ } -%>\n<%_ if (serializationFormat === "json") { -%>\nkotlinxSerialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerialization" }\n<%_ } -%>\n<%_ if (includeKtMath) { -%>\nktMath = { module = "io.github.gciatto:kt-math", version.ref = "ktMath" }\n<%_ } -%>\nslf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" }\n<%_ if (serializationFormat === "xml") { -%>\nxmlutil-serialization = { module = "io.github.pdvrieze.xmlutil:serialization", version.ref = "xmlutil" }\n<%_ } -%>\n\n[plugins]\nkotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }\nkotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }\nnodeGradle = { id = "com.github.node-gradle.node", version.ref = "nodeGradle" }\n';
981
923
  const reactAppBuildGradleKtsEjs = 'import com.github.gradle.node.npm.task.NpmTask\n\nplugins {\n alias(libs.plugins.nodeGradle)\n base\n}\n\nval isCI = System.getenv("CI") !in arrayOf(null, "0", "false")\nnode {\n download = true\n version = libs.versions.nodejs.get()\n npmInstallCommand = if (isCI) "ci" else "install"\n}\n\nval sharedPackage = project(":shared").file("build/<%= formId %>-shared-$version.tgz")\n\nval npmInstallShared by tasks.registering(NpmTask::class) {\n group = "build"\n dependsOn(":shared:packJsPackage")\n npmCommand = listOf("install", "<%= formId %>-shared@file:$sharedPackage")\n\n inputs.file(sharedPackage)\n outputs.dir("node_modules/<%= formId %>-shared")\n}\n\ntasks.npmInstall {\n dependsOn(npmInstallShared)\n}\n\nval npmRunDev by tasks.registering(NpmTask::class) {\n group = "development"\n dependsOn(tasks.npmInstall)\n npmCommand = listOf("run", "dev")\n}\n\nprivate fun NpmTask.npmRunBuild(buildReason: String) {\n group = "build"\n dependsOn(tasks.npmInstall)\n npmCommand = listOf("run", "build")\n environment = mapOf("VITE_BUILD_REASON" to buildReason)\n\n inputs.dir("src")\n inputs.file(sharedPackage)\n inputs.file("index.html")\n inputs.file("package.json")\n inputs.file("tsconfig.json")\n inputs.file("tsconfig.app.json")\n inputs.file("tsconfig.node.json")\n inputs.file("vite.config.ts")\n outputs.dir("build/dist")\n}\n\nval npmRunBuild by tasks.registering(NpmTask::class) {\n npmRunBuild("production")\n}\n\nval npmRunBuildPreview by tasks.registering(NpmTask::class) {\n npmRunBuild("preview")\n}\n\nval npmRunPreview by tasks.registering(NpmTask::class) {\n group = "development"\n dependsOn(npmRunBuildPreview)\n npmCommand = listOf("run", "preview")\n}\n\nval npmRunLint by tasks.registering(NpmTask::class) {\n group = "verification"\n dependsOn(tasks.npmInstall)\n npmCommand = listOf("run", "lint")\n\n inputs.dir("src")\n inputs.file("eslint.config.js")\n inputs.file("package.json")\n inputs.file("tsconfig.json")\n inputs.file("tsconfig.app.json")\n inputs.file("tsconfig.node.json")\n outputs.upToDateWhen { true }\n}\n\ntasks.assemble {\n dependsOn(npmRunBuild)\n}\n';
982
924
  const settingsGradleKtsEjs = 'plugins {\n id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"\n}\n\nrootProject.name = "<%= formId %>"\n\ninclude("shared", "react-app")\n';
983
- const sharedBuildGradleKtsEjs = 'import com.github.gradle.node.npm.task.NpmTask\n\nplugins {\n alias(libs.plugins.kotlin.multiplatform)\n alias(libs.plugins.kotlin.serialization)\n alias(libs.plugins.nodeGradle)\n}\n\nkotlin {\n jvmToolchain(libs.versions.jvmToolchain.get().toInt())\n jvm {\n testRuns["test"].executionTask.configure { useJUnitPlatform() }\n }\n js {\n compilerOptions {\n target = "es2015"\n freeCompilerArgs.add("-Xes-long-as-bigint")\n freeCompilerArgs.add("-Xwarning-level=NON_EXPORTABLE_TYPE:disabled")\n }\n binaries.library()\n browser { testTask { useMocha() } }\n generateTypeScriptDefinitions()\n }\n\n sourceSets {\n all {\n // Opt in to the experimental `JsExport` annotation\n languageSettings.optIn("kotlin.js.ExperimentalJsExport")\n }\n\n commonMain.dependencies {\n api(libs.kform)\n <%_ if (usesKotlinxDatetime) { -%>\n api(libs.kotlinxDatetime)\n <%_ } -%>\n <%_ if (serializationFormat === "json") { -%>\n api(libs.kotlinxSerialization.json)\n <%_ } -%>\n <%_ if (usesKtMath) { -%>\n api(libs.ktMath)\n <%_ } -%>\n <%_ if (serializationFormat === "xml") { -%>\n api(libs.xmlutil.serialization)\n <%_ } -%>\n }\n commonTest.dependencies {\n implementation(kotlin("test"))\n implementation(libs.kotlinxCoroutines.test)\n }\n jvmTest.dependencies {\n implementation(libs.slf4j.simple)\n }\n jsMain.dependencies {\n implementation(libs.kform.jsBindings)\n <%_ if (usesKotlinxDatetime) { -%>\n implementation(npm("@js-joda/timezone", "2.3.0"))\n <%_ } -%>\n }\n }\n}\n\nval isCI = System.getenv("CI") !in arrayOf(null, "0", "false")\nnode {\n download = true\n version = libs.versions.nodejs.get()\n npmInstallCommand = if (isCI) "ci" else "install"\n}\n\n// Packs the result of the JS compilation, for consumption by the React app\nval packJsPackage by tasks.registering(NpmTask::class) {\n group = "build"\n dependsOn("jsBrowserProductionLibraryDistribution")\n\n val libraryDir = "build/dist/js/productionLibrary"\n npmCommand = listOf("pack", libraryDir, "--pack-destination", "build")\n\n inputs.dir(libraryDir)\n outputs.file("build/<%= formId %>-shared-${version}.tgz")\n}\n';
925
+ const sharedBuildGradleKtsEjs = 'import com.github.gradle.node.npm.task.NpmTask\n\nplugins {\n alias(libs.plugins.kotlin.multiplatform)\n alias(libs.plugins.kotlin.serialization)\n alias(libs.plugins.nodeGradle)\n}\n\nkotlin {\n jvmToolchain(libs.versions.jvmToolchain.get().toInt())\n jvm {\n testRuns["test"].executionTask.configure { useJUnitPlatform() }\n }\n js {\n compilerOptions {\n target = "es2015"\n freeCompilerArgs.add("-Xes-long-as-bigint")\n freeCompilerArgs.add("-Xwarning-level=NON_EXPORTABLE_TYPE:disabled")\n }\n binaries.library()\n browser { testTask { useMocha() } }\n generateTypeScriptDefinitions()\n }\n\n sourceSets {\n all {\n // Opt in to the experimental `JsExport` annotation\n languageSettings.optIn("kotlin.js.ExperimentalJsExport")\n }\n\n commonMain.dependencies {\n api(libs.kform)\n <%_ if (includeKotlinxDatetime) { -%>\n api(libs.kotlinxDatetime)\n <%_ } -%>\n <%_ if (serializationFormat === "json") { -%>\n api(libs.kotlinxSerialization.json)\n <%_ } -%>\n <%_ if (includeKtMath) { -%>\n api(libs.ktMath)\n <%_ } -%>\n <%_ if (serializationFormat === "xml") { -%>\n api(libs.xmlutil.serialization)\n <%_ } -%>\n }\n commonTest.dependencies {\n implementation(kotlin("test"))\n implementation(libs.kotlinxCoroutines.test)\n }\n jvmTest.dependencies {\n implementation(libs.slf4j.simple)\n }\n jsMain.dependencies {\n implementation(libs.kform.jsBindings)\n <%_ if (includeKotlinxDatetime) { -%>\n implementation(npm("@js-joda/timezone", "2.3.0"))\n <%_ } -%>\n }\n }\n}\n\nnode {\n download = true\n version = libs.versions.nodejs.get()\n}\n\n// Packs the result of the JS compilation, for consumption by the React app\nval packJsPackage by tasks.registering(NpmTask::class) {\n group = "build"\n dependsOn("jsBrowserProductionLibraryDistribution")\n\n val libraryDir = "build/dist/js/productionLibrary"\n npmCommand = listOf("pack", libraryDir, "--pack-destination", "build")\n\n inputs.dir(libraryDir)\n outputs.file("build/<%= formId %>-shared-${version}.tgz")\n}\n';
984
926
  const jsJodaTimeZoneKtEjs = 'package <%= filePackage %>\n\n// See: https://github.com/Kotlin/kotlinx-datetime?tab=readme-ov-file#note-about-time-zones-in-js\n@JsModule("@js-joda/timezone")\n@JsNonModule\nexternal object JsJodaTimeZoneModule\n\n@JsExport\nval jsJodaTz = JsJodaTimeZoneModule\n';
927
+ const DEFAULT_JVM_TOOLCHAIN_VERSION = "17";
928
+ const DEFAULT_NODEJS_VERSION = "22.20.0";
985
929
  function scaffoldGradleProject(schematic, data) {
986
930
  const ejsData = {
987
931
  gradlePropertiesGroup: data.gradlePropertiesGroup ?? data.currentPackage,
@@ -990,8 +934,10 @@ function scaffoldGradleProject(schematic, data) {
990
934
  formTitle: capitalCase(schematic.name),
991
935
  kFormVersion: "0.31.5",
992
936
  serializationFormat: data.serializationFormat ?? "json",
993
- usesKotlinxDatetime: usesKotlinxDatetime(schematic, data),
994
- usesKtMath: usesKtMath(schematic)
937
+ includeKotlinxDatetime: data.includeKotlinxDatetime ?? usesKotlinxDatetime(schematic, data),
938
+ includeKtMath: data.includeKtMath ?? usesKtMath(schematic),
939
+ jvmToolchainVersion: data.jvmToolchainVersion ?? DEFAULT_JVM_TOOLCHAIN_VERSION,
940
+ nodejsVersion: data.nodejsVersion ?? DEFAULT_NODEJS_VERSION
995
941
  };
996
942
  addEjsTemplateFile(data, "gradle.properties", gradlePropertiesEjs, ejsData);
997
943
  addEjsTemplateFile(
@@ -1013,7 +959,7 @@ function scaffoldGradleProject(schematic, data) {
1013
959
  sharedBuildGradleKtsEjs,
1014
960
  ejsData
1015
961
  );
1016
- if (ejsData.usesKotlinxDatetime) {
962
+ if (ejsData.includeKotlinxDatetime) {
1017
963
  addEjsTemplateFile(
1018
964
  data,
1019
965
  "shared/src/jsMain/kotlin/JsJodaTimeZone.kt",
@@ -1402,24 +1348,17 @@ function scaffoldMain(schematic, data) {
1402
1348
  if (!file) {
1403
1349
  data.files.set(fileName, file = tsFile());
1404
1350
  }
1405
- scaffoldMainFile(schematic, {
1351
+ scaffoldMainDeclarations(schematic, {
1406
1352
  kmpModuleName: `${kebabCase(schematic.name)}-shared`,
1407
1353
  ...data,
1408
1354
  currentFile: file
1409
1355
  });
1410
1356
  }
1411
- function scaffoldMainFile(schematic, data) {
1357
+ function scaffoldMainDeclarations(schematic, data) {
1412
1358
  data.currentFile.imports.push(
1413
1359
  { moduleName: "./index.scss" },
1414
- { moduleName: "react-router-dom", name: "createHashRouter" }
1415
- );
1416
- data.currentFile.declarations.push(
1417
- `const router = createHashRouter([${scaffoldRouteObject(schematic, data)}]);`
1418
- );
1419
- data.currentFile.imports.push(
1420
- { moduleName: "react-dom/client", name: "createRoot" },
1421
1360
  { moduleName: "react", name: "StrictMode" },
1422
- { moduleName: "react-router-dom", name: "RouterProvider" },
1361
+ { moduleName: "react-dom/client", name: "createRoot" },
1423
1362
  {
1424
1363
  moduleName: data.kmpModuleName,
1425
1364
  name: `decode${schematic.name}ExternalContextsFromString`
@@ -1427,6 +1366,10 @@ function scaffoldMainFile(schematic, data) {
1427
1366
  {
1428
1367
  moduleName: `./${schematic.name}Context.ts`,
1429
1368
  name: `${schematic.name}Context`
1369
+ },
1370
+ {
1371
+ moduleName: `./${schematic.name}App.tsx`,
1372
+ name: `${schematic.name}App`
1430
1373
  }
1431
1374
  );
1432
1375
  data.currentFile.declarations.push(code`
@@ -1442,51 +1385,13 @@ function scaffoldMainFile(schematic, data) {
1442
1385
  createRoot(root).render(
1443
1386
  <StrictMode>
1444
1387
  <${schematic.name}Context.Provider value={{ externalContexts }}>
1445
- <RouterProvider router={router} />
1388
+ <${schematic.name}App />
1446
1389
  </${schematic.name}Context.Provider>
1447
1390
  </StrictMode>,
1448
1391
  );
1449
1392
  };
1450
1393
  `);
1451
1394
  }
1452
- function scaffoldRouteObject(schematic, data) {
1453
- const layout = reactAppLayout(schematic, data);
1454
- const formPages = layout.flatMap((annex) => annex.formPages);
1455
- data.currentFile.imports.push({
1456
- moduleName: `./${schematic.name}App.tsx`,
1457
- name: `${schematic.name}App`
1458
- });
1459
- for (const formPage of formPages) {
1460
- data.currentFile.imports.push({
1461
- moduleName: `./${joinPaths(
1462
- formPage.data.currentDir.slice(
1463
- data.currentDir.length + (data.currentDir.endsWith("/") ? 0 : 1)
1464
- ),
1465
- pascalCase(formPage.schematic.name)
1466
- )}.tsx`,
1467
- name: pascalCase(formPage.schematic.name)
1468
- });
1469
- }
1470
- const firstFormPage = formPages.find(
1471
- (formPage) => !formPage.schematic.nullable && !formPage.data.currentPath.split("/").includes("*")
1472
- );
1473
- const routes = [
1474
- firstFormPage && `{ path: "*", element: <${pascalCase(firstFormPage.schematic.name)} /> }`,
1475
- ...formPages.filter((formPage) => formPage !== firstFormPage).map(
1476
- (formPage) => `{ path: "${formPage.data.currentPath.split("/").map((f) => f === "*" ? ":id" : f).join(
1477
- "/"
1478
- )}", element: <${pascalCase(formPage.schematic.name)} /> }`
1479
- )
1480
- ];
1481
- return code`
1482
- {
1483
- element: <${schematic.name}App />,
1484
- children: [
1485
- ${routes.filter((r) => r).join(",\n")}
1486
- ]
1487
- }
1488
- `;
1489
- }
1490
1395
  const editorconfig = "# http://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_style = space\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[{*.kt,*.kts,*.md}]\nindent_size = 4\nmax_line_length = 100\n\n[{*.js,*.jsx,*.ts,*.tsx,*.json,*.html,*.css,*.scss,*.toml}]\nindent_size = 2\nmax_line_length = 80";
1491
1396
  const gitignore = "# Gradle\n.gradle/\nbuild/\n!**/src/**/build/\n\n# Kotlin\n.kotlin/\n\n# Node.js\nnode_modules/\n.npmrc\n\n# Typescript\n*.tsbuildinfo\n\n# Local env files\n.env*.local\n\n# Logs\nlogs\n*.log\n\n# IDEs and editors\n.vscode/\n.idea/\n.project\n.classpath\n.c9/\n*.launch\n.settings/\n*.sublime-workspace\nout/\n!**/src/**/out/\n\n# Misc\n.DS_Store\n*.pem\n";
1492
1397
  function scaffoldProjectMisc(_schematic, data) {
@@ -1528,7 +1433,7 @@ function scaffoldStyles(_schematic, data) {
1528
1433
  }
1529
1434
  const eslintConfigJs = 'import js from "@eslint/js";\nimport { defineConfig, globalIgnores } from "eslint/config";\nimport reactHooks from "eslint-plugin-react-hooks";\nimport reactRefresh from "eslint-plugin-react-refresh";\nimport globals from "globals";\nimport tseslint from "typescript-eslint";\n\nexport default defineConfig([\n globalIgnores([".gradle", "build"]),\n {\n files: ["**/*.{ts,tsx}"],\n extends: [\n js.configs.recommended,\n tseslint.configs.recommended,\n reactHooks.configs.flat.recommended,\n reactRefresh.configs.vite,\n ],\n languageOptions: {\n ecmaVersion: 2020,\n globals: globals.browser,\n },\n },\n]);\n';
1530
1435
  const indexHtmlEjs = '<!doctype html>\n<html lang="en">\n <head>\n <meta charset="UTF-8" />\n <link rel="icon" type="image/svg+xml" href="/vite.svg" />\n <meta name="viewport" content="width=device-width, initial-scale=1.0" />\n <title><%= formTitle %></title>\n </head>\n <body>\n <div\n id="<%= formId %>-app-root"\n data-external-contexts="<%= externalContextsData %>"\n ></div>\n <script type="module" src="/src/main.tsx"><\/script>\n <script type="module">\n render<%= formClass %>App();\n <\/script>\n </body>\n</html>\n';
1531
- const packageJsonEjs = '{\n "name": "<%= formId %>-react-app",\n "private": true,\n "version": "0.0.0",\n "type": "module",\n "scripts": {\n "dev": "vite",\n "build": "tsc -b && vite build",\n "lint": "eslint .",\n "preview": "vite preview"\n },\n "dependencies": {\n "@fortawesome/fontawesome-svg-core": "<%= dependencyVersions["@fortawesome/fontawesome-svg-core"] %>",\n "@fortawesome/free-regular-svg-icons": "<%= dependencyVersions["@fortawesome/free-regular-svg-icons"] %>",\n "@fortawesome/free-solid-svg-icons": "<%= dependencyVersions["@fortawesome/free-solid-svg-icons"] %>",\n "@ostack.tech/kform-react": "~<%= kFormVersion %>",\n "@ostack.tech/ui": "~<%= ostackUiVersion %>",\n "@ostack.tech/ui-kform": "~<%= ostackUiVersion %>",\n "date-fns": "<%= dependencyVersions["date-fns"] %>",\n "<%= formId %>-shared": "file:../shared/build/<%= formId %>-shared-0.0.1.tgz",\n "react": "<%= dependencyVersions.react %>",\n "react-dom": "<%= dependencyVersions["react-dom"] %>",\n "react-router": "<%= dependencyVersions["react-router"] %>",\n "react-router-dom": "<%= dependencyVersions["react-router-dom"] %>"\n },\n "devDependencies": {\n "@eslint/js": "<%= dependencyVersions["@eslint/js"] %>",\n "@types/node": "<%= dependencyVersions["@types/node"] %>",\n "@types/ostack.tech__kform": "npm:@ostack.tech/kform@~<%= kFormVersion %>",\n "@types/react": "<%= dependencyVersions["@types/react"] %>",\n "@types/react-dom": "<%= dependencyVersions["@types/react-dom"] %>",\n "@vitejs/plugin-react-swc": "<%= dependencyVersions["@vitejs/plugin-react-swc"] %>",\n "eslint": "<%= dependencyVersions.eslint %>",\n "eslint-plugin-react-hooks": "<%= dependencyVersions["eslint-plugin-react-hooks"] %>",\n "eslint-plugin-react-refresh": "<%= dependencyVersions["eslint-plugin-react-refresh"] %>",\n "globals": "<%= dependencyVersions.globals %>",\n "sass-embedded": "<%= dependencyVersions["sass-embedded"] %>",\n "typescript": "<%= dependencyVersions.typescript %>",\n "typescript-eslint": "<%= dependencyVersions["typescript-eslint"] %>",\n "vite": "<%= dependencyVersions.vite %>"\n }\n}\n';
1436
+ const packageJsonEjs = '{\n "name": "<%= formId %>-react-app",\n "private": true,\n "version": "0.0.0",\n "type": "module",\n "scripts": {\n "dev": "vite",\n "build": "tsc -b && vite build",\n "lint": "eslint .",\n "preview": "vite preview"\n },\n "dependencies": {\n "@fortawesome/fontawesome-svg-core": "<%= dependencyVersions["@fortawesome/fontawesome-svg-core"] %>",\n "@fortawesome/free-regular-svg-icons": "<%= dependencyVersions["@fortawesome/free-regular-svg-icons"] %>",\n "@fortawesome/free-solid-svg-icons": "<%= dependencyVersions["@fortawesome/free-solid-svg-icons"] %>",\n "@ostack.tech/kform-react": "~<%= kFormVersion %>",\n "@ostack.tech/ui": "~<%= ostackUiVersion %>",\n "@ostack.tech/ui-kform": "~<%= ostackUiVersion %>",\n "date-fns": "<%= dependencyVersions["date-fns"] %>",\n "<%= formId %>-shared": "file:../shared/build/<%= formId %>-shared-0.0.1.tgz",\n "react": "<%= dependencyVersions.react %>",\n "react-dom": "<%= dependencyVersions["react-dom"] %>"\n },\n "devDependencies": {\n "@eslint/js": "<%= dependencyVersions["@eslint/js"] %>",\n "@types/node": "<%= dependencyVersions["@types/node"] %>",\n "@types/ostack.tech__kform": "npm:@ostack.tech/kform@~<%= kFormVersion %>",\n "@types/react": "<%= dependencyVersions["@types/react"] %>",\n "@types/react-dom": "<%= dependencyVersions["@types/react-dom"] %>",\n "@vitejs/plugin-react-swc": "<%= dependencyVersions["@vitejs/plugin-react-swc"] %>",\n "eslint": "<%= dependencyVersions.eslint %>",\n "eslint-plugin-react-hooks": "<%= dependencyVersions["eslint-plugin-react-hooks"] %>",\n "eslint-plugin-react-refresh": "<%= dependencyVersions["eslint-plugin-react-refresh"] %>",\n "globals": "<%= dependencyVersions.globals %>",\n "sass-embedded": "<%= dependencyVersions["sass-embedded"] %>",\n "typescript": "<%= dependencyVersions.typescript %>",\n "typescript-eslint": "<%= dependencyVersions["typescript-eslint"] %>",\n "vite": "<%= dependencyVersions.vite %>"\n }\n}\n';
1532
1437
  const viteSvg = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>\n';
1533
1438
  const tsConfigAppJson = '{\n "compilerOptions": {\n "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",\n "target": "ES2022",\n "useDefineForClassFields": true,\n "lib": ["ES2022", "DOM", "DOM.Iterable"],\n "module": "ESNext",\n "types": ["vite/client"],\n "skipLibCheck": true,\n\n /* Bundler mode */\n "moduleResolution": "bundler",\n "allowImportingTsExtensions": true,\n "verbatimModuleSyntax": true,\n "moduleDetection": "force",\n "noEmit": true,\n "jsx": "react-jsx",\n\n /* Linting */\n "strict": true,\n "noUnusedLocals": true,\n "noUnusedParameters": true,\n "erasableSyntaxOnly": true,\n "noFallthroughCasesInSwitch": true,\n "noUncheckedSideEffectImports": true\n },\n "include": ["src"]\n}\n';
1534
1439
  const tsConfigJson = '{\n "files": [],\n "references": [\n { "path": "./tsconfig.app.json" },\n { "path": "./tsconfig.node.json" }\n ]\n}\n';
@@ -1541,9 +1446,9 @@ function scaffoldViteProject(schematic, data) {
1541
1446
  formId: kebabCase(schematic.name),
1542
1447
  formClass: schematic.name,
1543
1448
  formTitle: capitalCase(schematic.name),
1544
- ostackUiVersion: "0.3.3",
1449
+ ostackUiVersion: "0.4.0",
1545
1450
  kFormVersion: "0.31.5",
1546
- dependencyVersions: JSON.parse('{"@eslint/js":"^9.38.0","@fortawesome/fontawesome-svg-core":"^7.1.0","@fortawesome/free-brands-svg-icons":"^7.1.0","@fortawesome/free-regular-svg-icons":"^7.1.0","@fortawesome/free-solid-svg-icons":"^7.1.0","@ostack.tech/kform":"~0.31.5","@ostack.tech/kform-react":"~0.31.5","@ostack.tech/kform-scaffolder":"~0.31.5","@storybook/addon-docs":"^9.1.16","@storybook/addon-links":"^9.1.16","@storybook/react-vite":"^9.1.16","@types/node":"^22.18.13","@types/react":"^19.2.2","@types/react-dom":"^19.2.2","@vitejs/plugin-react-swc":"^4.2.0","change-case":"^5.4.4","cpy-cli":"^6.0.0","date-fns":"^4.1.0","eslint":"^9.38.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.4","eslint-plugin-react-hooks":"^7.0.1","eslint-plugin-react-refresh":"^0.4.24","eslint-plugin-simple-import-sort":"^12.1.1","eslint-plugin-storybook":"^9.1.16","globals":"^16.4.0","happy-dom":"^20.0.10","lint-staged":"^16.2.6","prettier":"^3.6.2","prettier-plugin-jsdoc":"^1.5.0","react":"^19.2.0","react-dom":"^19.2.0","react-router":"^7.9.5","react-router-dom":"^7.9.5","rimraf":"^6.0.1","sass-embedded":"^1.93.2","simple-git-hooks":"^2.13.1","storybook":"^9.1.16","terser":"^5.44.0","tslib":"^2.8.1","typescript":"~5.9.3","typescript-eslint":"^8.46.2","vite":"^7.1.12","vite-plugin-dts":"^4.5.4","vitest":"^4.0.5","zustand":"^5.0.8"}'),
1451
+ dependencyVersions: JSON.parse('{"@eslint/js":"^9.39.1","@fortawesome/fontawesome-svg-core":"^7.1.0","@fortawesome/free-brands-svg-icons":"^7.1.0","@fortawesome/free-regular-svg-icons":"^7.1.0","@fortawesome/free-solid-svg-icons":"^7.1.0","@ostack.tech/kform":"~0.31.5","@ostack.tech/kform-react":"~0.31.5","@ostack.tech/kform-scaffolder":"~0.31.5","@storybook/addon-docs":"^10.0.5","@storybook/addon-links":"^10.0.5","@storybook/react-vite":"^10.0.5","@types/node":"^24.10.0","@types/react":"^19.2.2","@types/react-dom":"^19.2.2","@vitejs/plugin-react-swc":"^4.2.1","change-case":"^5.4.4","cpy-cli":"^6.0.0","date-fns":"^4.1.0","eslint":"^9.39.1","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.4","eslint-plugin-react-hooks":"^7.0.1","eslint-plugin-react-refresh":"^0.4.24","eslint-plugin-simple-import-sort":"^12.1.1","eslint-plugin-storybook":"^10.0.5","globals":"^16.5.0","happy-dom":"^20.0.10","lint-staged":"^16.2.6","prettier":"^3.6.2","prettier-plugin-jsdoc":"^1.5.0","react":"^19.2.0","react-dom":"^19.2.0","rimraf":"^6.1.0","sass-embedded":"^1.93.2","simple-git-hooks":"^2.13.1","storybook":"^10.0.5","terser":"^5.44.1","tslib":"^2.8.1","typescript":"~5.9.3","typescript-eslint":"^8.46.3","vite":"^7.2.1","vite-plugin-dts":"^4.5.4","vitest":"^4.0.7","zustand":"^5.0.8"}'),
1547
1452
  externalContextsData: data.serializationFormat === "json" ? "{}" : `<${schematic.name}ExternalContexts />`,
1548
1453
  apiBasePath: data.apiBasePath ?? DEFAULT_API_BASE_PATH,
1549
1454
  viteConfigOutDir: data.viteConfigOutDir ?? DEFAULT_VITE_CONFIG_OUT_DIR,
@@ -1592,7 +1497,7 @@ function SchematicBuilder({
1592
1497
  configScaffolder(scaffoldAppContext, reactAppData),
1593
1498
  configScaffolder(scaffoldActions, reactAppData),
1594
1499
  configScaffolder(scaffoldApi, reactAppData),
1595
- configScaffolder(scaffoldFormPages, reactAppData)
1500
+ configScaffolder(scaffoldPageComponents, reactAppData)
1596
1501
  ],
1597
1502
  scaffoldingData = (schematic) => ({
1598
1503
  useFileBase64Serializer: true,
@@ -1618,8 +1523,11 @@ function SchematicBuilder({
1618
1523
  );
1619
1524
  }
1620
1525
  export {
1526
+ DEFAULT_ACTIVE_PATH_SEARCH_PARAM,
1621
1527
  DEFAULT_API_BASE_PATH,
1528
+ DEFAULT_JVM_TOOLCHAIN_VERSION,
1622
1529
  DEFAULT_LOCALE,
1530
+ DEFAULT_NODEJS_VERSION,
1623
1531
  DEFAULT_REPORT_ERROR_API_ENDPOINT,
1624
1532
  DEFAULT_SERIALIZATION_FORMAT,
1625
1533
  DEFAULT_SUBMIT_API_ENDPOINT,
@@ -1652,21 +1560,21 @@ export {
1652
1560
  longSchematicKind,
1653
1561
  reactAppLayout,
1654
1562
  scaffoldActions,
1655
- scaffoldAnnexesArray,
1563
+ scaffoldAnnex,
1564
+ scaffoldAnnexes,
1656
1565
  scaffoldApi,
1657
1566
  scaffoldAppComponent,
1658
1567
  scaffoldAppContext,
1659
1568
  scaffoldExternalContexts,
1660
1569
  scaffoldField,
1661
- scaffoldFormPages,
1662
- scaffoldFormPagesByAnnexObject,
1570
+ scaffoldFormPage,
1663
1571
  scaffoldGradleProject,
1664
1572
  scaffoldGradleWrapper,
1665
1573
  scaffoldIssueMessages,
1666
1574
  scaffoldMain,
1575
+ scaffoldPageComponents,
1667
1576
  scaffoldProjectMisc,
1668
1577
  scaffoldResponses,
1669
- scaffoldRouteObject,
1670
1578
  scaffoldSerializer,
1671
1579
  scaffoldStyles,
1672
1580
  scaffoldViteProject,