@ostack.tech/ui-kform-scaffolder 0.1.2 → 0.2.1

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 (37) hide show
  1. package/bin/at-ui-kform-scaffolder +1 -1
  2. package/dist/ostack-ui-kform-scaffolder.js +39 -8
  3. package/dist/ostack-ui-kform-scaffolder.js.map +1 -1
  4. package/dist/types/ui-kform-scaffolder/src/configs/DefaultLocaleConfig.d.ts +5 -0
  5. package/dist/types/{index.d.ts → ui-kform-scaffolder/src/index.d.ts} +1 -1
  6. package/dist/types/ui-kform-scaffolder/src/main.d.ts +1 -0
  7. package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/ScaffoldingData.d.ts +2 -0
  8. package/dist/webapp/assets/{index-SSul4wNF.js → index-Bmpm0sin.js} +99 -98
  9. package/dist/webapp/index.html +1 -1
  10. package/package.json +4 -4
  11. package/dist/ostack-ui-kform-scaffolder.cjs +0 -1761
  12. package/dist/ostack-ui-kform-scaffolder.cjs.map +0 -1
  13. package/dist/types/main.d.ts +0 -1
  14. /package/dist/types/{SchematicBuilder.d.ts → ui-kform-scaffolder/src/SchematicBuilder.d.ts} +0 -0
  15. /package/dist/types/{SchematicKind.d.ts → ui-kform-scaffolder/src/SchematicKind.d.ts} +0 -0
  16. /package/dist/types/{configs → ui-kform-scaffolder/src/configs}/SerializationFormatConfig.d.ts +0 -0
  17. /package/dist/types/{configs → ui-kform-scaffolder/src/configs}/UseTableValuesSerializerConfig.d.ts +0 -0
  18. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/kotlin/KtData.d.ts +0 -0
  19. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/reactApp/ReactAppData.d.ts +0 -0
  20. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/reactApp/util/reactAppLayout.d.ts +0 -0
  21. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldActions.d.ts +0 -0
  22. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldApi.d.ts +0 -0
  23. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldAppComponent.d.ts +0 -0
  24. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldAppContext.d.ts +0 -0
  25. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldExternalContexts.d.ts +0 -0
  26. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldFormPages.d.ts +0 -0
  27. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldGradleProject.d.ts +0 -0
  28. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldGradleWrapper.d.ts +0 -0
  29. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldIssueMessages.d.ts +0 -0
  30. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldMain.d.ts +0 -0
  31. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldProjectMisc.d.ts +0 -0
  32. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldResponses.d.ts +0 -0
  33. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldSerializer.d.ts +0 -0
  34. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldStyles.d.ts +0 -0
  35. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/scaffolders/scaffoldViteProject.d.ts +0 -0
  36. /package/dist/types/{scaffolding → ui-kform-scaffolder/src/scaffolding}/templates/react-app/src/api/reportError.d.ts +0 -0
  37. /package/dist/types/{util → ui-kform-scaffolder/src/util}/arrayify.d.ts +0 -0
@@ -1,1761 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const jsxRuntime = require("react/jsx-runtime");
4
- const kformScaffolder = require("@ostack.tech/kform-scaffolder");
5
- const React = require("react");
6
- function _interopNamespaceDefault(e) {
7
- const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
8
- if (e) {
9
- for (const k in e) {
10
- if (k !== "default") {
11
- const d = Object.getOwnPropertyDescriptor(e, k);
12
- Object.defineProperty(n, k, d.get ? d : {
13
- enumerable: true,
14
- get: () => e[k]
15
- });
16
- }
17
- }
18
- }
19
- n.default = e;
20
- return Object.freeze(n);
21
- }
22
- const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
23
- function SerializationFormatConfig({
24
- defaultValue = "json",
25
- disabled
26
- }) {
27
- const [useTableValuesSerializerConfig, setUseTableValuesSerializerConfig] = kformScaffolder.useConfig("useTableValuesSerializer", false);
28
- const lastUseTableValuesSerializerConfig = React__namespace.useRef(
29
- useTableValuesSerializerConfig
30
- );
31
- const [config, setConfig] = kformScaffolder.useConfig("serializationFormat", defaultValue);
32
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "builder-config-field", children: [
33
- /* @__PURE__ */ jsxRuntime.jsx("label", { children: "Serialization format" }),
34
- /* @__PURE__ */ jsxRuntime.jsxs(
35
- "select",
36
- {
37
- value: config,
38
- onChange: (evt) => {
39
- setConfig(evt.target.value);
40
- if (evt.target.value === "xml") {
41
- lastUseTableValuesSerializerConfig.current = useTableValuesSerializerConfig;
42
- setUseTableValuesSerializerConfig(true);
43
- } else {
44
- setUseTableValuesSerializerConfig(
45
- lastUseTableValuesSerializerConfig.current
46
- );
47
- }
48
- },
49
- disabled,
50
- children: [
51
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "json", children: "JSON" }),
52
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "xml", children: "XML" })
53
- ]
54
- }
55
- )
56
- ] });
57
- }
58
- function UseTableValuesSerializerConfig({
59
- disabled
60
- }) {
61
- const [serializationFormatConfig] = kformScaffolder.useConfig("serializationFormat", "json");
62
- return /* @__PURE__ */ jsxRuntime.jsx(
63
- kformScaffolder.UseTableValuesSerializerConfig,
64
- {
65
- disabled: disabled || serializationFormatConfig === "xml"
66
- }
67
- );
68
- }
69
- const SPLIT_LOWER_UPPER_RE = new RegExp("([\\p{Ll}\\d])(\\p{Lu})", "gu");
70
- const SPLIT_UPPER_UPPER_RE = new RegExp("(\\p{Lu})([\\p{Lu}][\\p{Ll}])", "gu");
71
- const SPLIT_SEPARATE_NUMBER_RE = new RegExp("(\\d)\\p{Ll}|(\\p{L})\\d", "u");
72
- const DEFAULT_STRIP_REGEXP = /[^\p{L}\d]+/giu;
73
- const SPLIT_REPLACE_VALUE = "$1\0$2";
74
- const DEFAULT_PREFIX_SUFFIX_CHARACTERS = "";
75
- function split(value) {
76
- let result = value.trim();
77
- result = result.replace(SPLIT_LOWER_UPPER_RE, SPLIT_REPLACE_VALUE).replace(SPLIT_UPPER_UPPER_RE, SPLIT_REPLACE_VALUE);
78
- result = result.replace(DEFAULT_STRIP_REGEXP, "\0");
79
- let start = 0;
80
- let end = result.length;
81
- while (result.charAt(start) === "\0")
82
- start++;
83
- if (start === end)
84
- return [];
85
- while (result.charAt(end - 1) === "\0")
86
- end--;
87
- return result.slice(start, end).split(/\0/g);
88
- }
89
- function splitSeparateNumbers(value) {
90
- const words = split(value);
91
- for (let i = 0; i < words.length; i++) {
92
- const word = words[i];
93
- const match = SPLIT_SEPARATE_NUMBER_RE.exec(word);
94
- if (match) {
95
- const offset = match.index + (match[1] ?? match[2]).length;
96
- words.splice(i, 1, word.slice(0, offset), word.slice(offset));
97
- }
98
- }
99
- return words;
100
- }
101
- function noCase(input, options) {
102
- const [prefix, words, suffix] = splitPrefixSuffix(input, options);
103
- return prefix + words.map(lowerFactory(options?.locale)).join(options?.delimiter ?? " ") + suffix;
104
- }
105
- function camelCase(input, options) {
106
- const [prefix, words, suffix] = splitPrefixSuffix(input, options);
107
- const lower = lowerFactory(options?.locale);
108
- const upper = upperFactory(options?.locale);
109
- const transform = pascalCaseTransformFactory(lower, upper);
110
- return prefix + words.map((word, index) => {
111
- if (index === 0)
112
- return lower(word);
113
- return transform(word, index);
114
- }).join("") + suffix;
115
- }
116
- function pascalCase(input, options) {
117
- const [prefix, words, suffix] = splitPrefixSuffix(input, options);
118
- const lower = lowerFactory(options?.locale);
119
- const upper = upperFactory(options?.locale);
120
- const transform = pascalCaseTransformFactory(lower, upper);
121
- return prefix + words.map(transform).join("") + suffix;
122
- }
123
- function capitalCase(input, options) {
124
- const [prefix, words, suffix] = splitPrefixSuffix(input, options);
125
- const lower = lowerFactory(options?.locale);
126
- const upper = upperFactory(options?.locale);
127
- return prefix + words.map(capitalCaseTransformFactory(lower, upper)).join(" ") + suffix;
128
- }
129
- function constantCase(input, options) {
130
- const [prefix, words, suffix] = splitPrefixSuffix(input, options);
131
- return prefix + words.map(upperFactory(options?.locale)).join("_") + suffix;
132
- }
133
- function kebabCase(input, options) {
134
- return noCase(input, { delimiter: "-", ...options });
135
- }
136
- function sentenceCase(input, options) {
137
- const [prefix, words, suffix] = splitPrefixSuffix(input, options);
138
- const lower = lowerFactory(options?.locale);
139
- const upper = upperFactory(options?.locale);
140
- const transform = capitalCaseTransformFactory(lower, upper);
141
- return prefix + words.map((word, index) => {
142
- if (index === 0)
143
- return transform(word);
144
- return lower(word);
145
- }).join(" ") + suffix;
146
- }
147
- function lowerFactory(locale) {
148
- return locale === false ? (input) => input.toLowerCase() : (input) => input.toLocaleLowerCase(locale);
149
- }
150
- function upperFactory(locale) {
151
- return (input) => input.toLocaleUpperCase(locale);
152
- }
153
- function capitalCaseTransformFactory(lower, upper) {
154
- return (word) => `${upper(word[0])}${lower(word.slice(1))}`;
155
- }
156
- function pascalCaseTransformFactory(lower, upper) {
157
- return (word, index) => {
158
- const char0 = word[0];
159
- const initial = index > 0 && char0 >= "0" && char0 <= "9" ? "_" + char0 : upper(char0);
160
- return initial + lower(word.slice(1));
161
- };
162
- }
163
- function splitPrefixSuffix(input, options = {}) {
164
- const splitFn = options.split ?? (options.separateNumbers ? splitSeparateNumbers : split);
165
- const prefixCharacters = options.prefixCharacters ?? DEFAULT_PREFIX_SUFFIX_CHARACTERS;
166
- const suffixCharacters = options.suffixCharacters ?? DEFAULT_PREFIX_SUFFIX_CHARACTERS;
167
- let prefixIndex = 0;
168
- let suffixIndex = input.length;
169
- while (prefixIndex < input.length) {
170
- const char = input.charAt(prefixIndex);
171
- if (!prefixCharacters.includes(char))
172
- break;
173
- prefixIndex++;
174
- }
175
- while (suffixIndex > prefixIndex) {
176
- const index = suffixIndex - 1;
177
- const char = input.charAt(index);
178
- if (!suffixCharacters.includes(char))
179
- break;
180
- suffixIndex = index;
181
- }
182
- return [
183
- input.slice(0, prefixIndex),
184
- splitFn(input.slice(prefixIndex, suffixIndex)),
185
- input.slice(suffixIndex)
186
- ];
187
- }
188
- const loadTsxEjs = 'import { LoadAction } from "@ostack.tech/ui-kform";\nimport { decode<%= formClass %>FromString, <%= formClass %>FormMode } from "<%= kmpModuleName %>";\nimport { use<%= formClass %>Context } from "../<%= formClass %>Context.ts";\n\nexport function Load() {\n const { externalContexts } = use<%= formClass %>Context();\n\n return (\n externalContexts.mode !== <%= formClass %>FormMode.READ && (\n <LoadAction\n decode={async (file) => decode<%= formClass %>FromString(await file.text())}\n mimeTypes={["<%= serializationMimeType %>"]}\n extensions={[".<%= serializationFormat %>"]}\n />\n )\n );\n}\n';
189
- const saveTsxEjs = 'import { SaveAction } from "@ostack.tech/ui-kform";\nimport { format } from "date-fns";\nimport { type <%= formClass %>, encode<%= formClass %>ToString, <%= formClass %>FormMode } from "<%= kmpModuleName %>";\nimport { use<%= formClass %>Context } from "../<%= formClass %>Context.ts";\n\nexport function Save() {\n const { externalContexts } = use<%= formClass %>Context();\n\n return (\n <SaveAction\n encode={(<%= formVar %>: <%= formClass %>) => encode<%= formClass %>ToString(<%= formVar %>, true)}\n disableOverwrite={externalContexts.mode === <%= formClass %>FormMode.READ}\n fileName={() => `<%= formTitle %> ${format(new Date(), "yyyy-MM-dd")}.<%= serializationFormat %>`}\n mimeTypes={["<%= serializationMimeType %>"]}\n extensions={[".<%= serializationFormat %>"]}\n />\n );\n}\n';
190
- const submitTsxEjs = 'import { LocatedValidationWarning } from "@ostack.tech/kform";\nimport { SubmitAction } from "@ostack.tech/ui-kform";\nimport {\n type <%= formClass %>,\n <%= formClass %>FormMode,\n <%= formClass %>SubmitSuccess,\n <%= formClass %>SubmitValidationError,\n <%= formClass %>SubmitError,\n} from "<%= kmpModuleName %>";\nimport { use<%= formClass %>Context } from "../<%= formClass %>Context.ts";\nimport { submit } from "../api/submit.ts";\n\nexport function Submit() {\n const { externalContexts } = use<%= formClass %>Context();\n\n const handleSubmit = async (\n <%= formVar %>: <%= formClass %>,\n acceptedWarnings?: LocatedValidationWarning[],\n ) => {\n const response = await submit(<%= formVar %>, acceptedWarnings);\n if (response instanceof <%= formClass %>SubmitSuccess) {\n return response.redirectTo;\n } else if (response instanceof <%= formClass %>SubmitValidationError) {\n return response.issues;\n } else {\n throw response as <%= formClass %>SubmitError;\n }\n };\n\n const handleSuccessfulSubmit = (redirectTo: string) => {\n window.location.href = redirectTo;\n };\n\n return (\n externalContexts.mode !== <%= formClass %>FormMode.READ && (\n <SubmitAction\n onSubmit={handleSubmit}\n onSuccessfulSubmit={handleSuccessfulSubmit}\n <%_ if (useTableValuesSerializer) { -%>\n convertExternalIssuesTableRowIndicesToIds\n <%_ } -%>\n />\n )\n );\n}\n';
191
- const validateTsxEjs = 'import { ValidateAction } from "@ostack.tech/ui-kform";\nimport { <%= formClass %>FormMode } from "<%= kmpModuleName %>";\nimport { use<%= formClass %>Context } from "../<%= formClass %>Context.ts";\n\nexport function Validate() {\n const { externalContexts } = use<%= formClass %>Context();\n\n return externalContexts.mode !== <%= formClass %>FormMode.READ && <ValidateAction />;\n}\n';
192
- function scaffoldActions(schematic, data) {
193
- const ejsData = {
194
- kmpModuleName: data.kmpModuleName ?? `${kebabCase(schematic.name)}-shared`,
195
- serializationFormat: data.serializationFormat ?? "json",
196
- serializationMimeType: `application/${data.serializationFormat}`,
197
- formVar: camelCase(schematic.name),
198
- formClass: schematic.name,
199
- formTitle: capitalCase(schematic.name),
200
- useTableValuesSerializer: data.useTableValuesSerializer
201
- };
202
- kformScaffolder.addEjsTemplateFile(data, "actions/Load.tsx", loadTsxEjs, ejsData);
203
- kformScaffolder.addEjsTemplateFile(data, "actions/Save.tsx", saveTsxEjs, ejsData);
204
- kformScaffolder.addEjsTemplateFile(data, "actions/Submit.tsx", submitTsxEjs, ejsData);
205
- kformScaffolder.addEjsTemplateFile(data, "actions/Validate.tsx", validateTsxEjs, ejsData);
206
- }
207
- const reportErrorTs = 'export const REPORT_ERROR_ENDPOINT = "/api/report-error";\n';
208
- const submitTsEjs = 'import { LocatedValidationWarning } from "@ostack.tech/kform";\nimport {\n decode<%= formClass %>SubmitResponseFromString,\n encode<%= formClass %>ToString,\n <%= formClass %>,\n} from "<%= kmpModuleName %>";\n\nexport const SUBMIT_ENDPOINT = "/api/submit";\n\nexport async function submit(\n <%= formVar %>: <%= formClass %>,\n acceptedWarnings?: LocatedValidationWarning[],\n) {\n const params = new URLSearchParams();\n if (acceptedWarnings?.length) {\n const acceptedWarningCodes = new Set(acceptedWarnings.map((w) => w.code));\n params.set("acceptedWarnings", Array.from(acceptedWarningCodes).join());\n }\n\n const res = await fetch(`${SUBMIT_ENDPOINT}?${params}`, {\n method: "POST",\n headers: { "Content-Type": "<%= serializationMimeType %>" },\n body: encode<%= formClass %>ToString(<%= formVar %>, import.meta.env.DEV),\n });\n return decode<%= formClass %>SubmitResponseFromString(await res.text());\n}\n';
209
- function scaffoldApi(schematic, data) {
210
- const ejsData = {
211
- kmpModuleName: data.kmpModuleName ?? `${kebabCase(schematic.name)}-shared`,
212
- serializationFormat: data.serializationFormat ?? "json",
213
- serializationMimeType: `application/${data.serializationFormat}`,
214
- formVar: camelCase(schematic.name),
215
- formClass: schematic.name
216
- };
217
- kformScaffolder.addTemplateFile(data, "api/reportError.ts", reportErrorTs);
218
- kformScaffolder.addEjsTemplateFile(data, "api/submit.ts", submitTsEjs, ejsData);
219
- }
220
- function scaffoldIssueMessages(schematic, data) {
221
- const fileName = kformScaffolder.joinPaths(
222
- data.currentDir,
223
- `${schematic.name}IssueMessages.tsx`
224
- );
225
- let file = data.files.get(fileName);
226
- if (!file) {
227
- data.files.set(fileName, file = kformScaffolder.tsFile());
228
- }
229
- scaffoldIssueMessagesConstant(schematic, {
230
- kmpModuleName: `${kebabCase(data.rootSchematic.name)}-shared`,
231
- ...data,
232
- currentFile: file
233
- });
234
- }
235
- function scaffoldIssueMessagesConstant(schematic, data) {
236
- data.currentFile.imports.push({
237
- moduleName: "@ostack.tech/ui-kform",
238
- name: "IssueMessagesByCode",
239
- isType: true
240
- });
241
- data.currentFile.declarations.push(kformScaffolder.code`
242
- export const ${constantCase(schematic.name)}_ISSUE_MESSAGES: Record<string, IssueMessagesByCode> = {};
243
- `);
244
- }
245
- function scaffoldFormPages(schematic, data) {
246
- const layout = reactAppLayout(schematic, {
247
- kmpModuleName: `${kebabCase(schematic.name)}-shared`,
248
- ...data
249
- });
250
- for (const annex of layout) {
251
- for (const formPage of annex.formPages) {
252
- scaffoldFormPage(formPage.schematic, formPage.data);
253
- if (formPage.data.currentPath !== "/") {
254
- scaffoldIssueMessages(formPage.schematic, formPage.data);
255
- }
256
- }
257
- }
258
- }
259
- function scaffoldFormPage(schematic, data) {
260
- const fileName = kformScaffolder.joinPaths(data.currentDir, `${schematic.name}.tsx`);
261
- let file = data.files.get(fileName);
262
- if (!file) {
263
- data.files.set(fileName, file = kformScaffolder.tsFile());
264
- }
265
- scaffoldFormPageComponent(schematic, {
266
- kmpModuleName: `${kebabCase(data.rootSchematic.name)}-shared`,
267
- ...data,
268
- currentFile: file
269
- });
270
- }
271
- function scaffoldFormPageComponent(schematic, data) {
272
- data.currentFile.imports.push(
273
- { moduleName: "@ostack.tech/ui-kform", name: "FormPage" },
274
- { moduleName: "@ostack.tech/ui", name: "Grid" }
275
- );
276
- if (data.currentPath !== "/") {
277
- data.currentFile.imports.push({
278
- moduleName: `./${schematic.name}IssueMessages.tsx`,
279
- name: `${constantCase(schematic.name)}_ISSUE_MESSAGES`
280
- });
281
- }
282
- let pathString;
283
- let preamble;
284
- const splitPath = data.currentPath.split("/");
285
- if (splitPath.some((fragment) => fragment === "*")) {
286
- data.currentFile.imports.push({
287
- moduleName: "react-router",
288
- name: "useParams"
289
- });
290
- pathString = `{\`${splitPath.map((f) => f === "*" ? "${id}" : f).join("/")}\`}`;
291
- preamble = "\n const { id } = useParams();\n";
292
- } else {
293
- pathString = `"${data.currentPath}"`;
294
- preamble = "";
295
- }
296
- const pageComponent = kformScaffolder.code`
297
- export function ${schematic.name}() {${preamble}
298
- return (
299
- <FormPage${data.currentPath === "/" ? "" : ` path=${pathString} issueMessages={${constantCase(schematic.name)}_ISSUE_MESSAGES}`}>
300
- <Grid container>
301
- ${schematic.children.map(
302
- (child) => kformScaffolder.code`
303
- <Grid xs={12}>
304
- ${scaffoldField(child, {
305
- ...data,
306
- currentPath: child.childName
307
- })}
308
- </Grid>
309
- `
310
- ).join("\n\n")}
311
- </Grid>
312
- </FormPage>
313
- );
314
- }
315
- `;
316
- data.currentFile.declarations.push(pageComponent);
317
- }
318
- function scaffoldField(schematic, data) {
319
- const schematicKind = data.schematicKinds.get(
320
- schematic.kind
321
- );
322
- if (!schematicKind) {
323
- throw new Error(`Unknown schematic kind ${schematic.kind}`);
324
- }
325
- if (schematicKind.scaffoldField) {
326
- return schematicKind.scaffoldField?.(schematic, data);
327
- }
328
- data.currentFile.imports.push({
329
- moduleName: "@ostack.tech/ui-kform",
330
- name: "ControlField"
331
- });
332
- let controlModuleName;
333
- let controlName;
334
- if (schematicKind.control) {
335
- const controlSeparator = schematicKind.control.lastIndexOf(".");
336
- controlModuleName = schematicKind.control.slice(0, controlSeparator);
337
- controlName = schematicKind.control.slice(controlSeparator + 1);
338
- data.currentFile.imports.push({
339
- moduleName: controlModuleName,
340
- name: controlName
341
- });
342
- }
343
- let control = schematicKind.scaffoldControl?.(schematic, data);
344
- if (!control) {
345
- if (!data.omitLabel) {
346
- data.currentFile.imports.push({
347
- moduleName: "@ostack.tech/ui",
348
- name: "Label"
349
- });
350
- }
351
- control = [
352
- data.omitLabel ? null : `<Label>${sentenceCase(schematic.childName)}</Label>`,
353
- `<${controlName} />`
354
- ].filter((s) => s).join("\n");
355
- }
356
- return kformScaffolder.code`
357
- <ControlField path="${data.currentPath}">
358
- ${control}
359
- </ControlField>
360
- `;
361
- }
362
- function arrayify(value) {
363
- return value == null ? [] : Array.isArray(value) ? value : [value];
364
- }
365
- const anySchematicKind = {
366
- ...kformScaffolder.anySchematicKind
367
- };
368
- const bigDecimalSchematicKind = {
369
- ...kformScaffolder.bigDecimalSchematicKind,
370
- control: "@ostack.tech/ui-kform.NumericControl"
371
- };
372
- const bigIntegerSchematicKind = {
373
- ...kformScaffolder.bigIntegerSchematicKind,
374
- control: "@ostack.tech/ui-kform.NumericControl"
375
- };
376
- const booleanSchematicKind = {
377
- ...kformScaffolder.booleanSchematicKind,
378
- control: "@ostack.tech/ui-kform.CheckboxControl",
379
- scaffoldControl: (schematic, data) => data.omitLabel ? `<CheckboxControl />` : `<CheckboxControl>${sentenceCase(schematic.childName)}</CheckboxControl>`
380
- };
381
- const byteSchematicKind = {
382
- ...kformScaffolder.byteSchematicKind,
383
- control: "@ostack.tech/ui-kform.NumericControl"
384
- };
385
- const classAnnexSchematicKind = {
386
- ...kformScaffolder.classSchematicKind,
387
- defaultPackageSuffix: (childName) => `annexes.${childName.toLowerCase()}`,
388
- kind: "Class (Annex)"
389
- };
390
- const classFormPageSchematicKind = {
391
- ...kformScaffolder.classSchematicKind,
392
- kind: "Class (FormPage)",
393
- nullable: false
394
- };
395
- const classSchematicKind = {
396
- ...kformScaffolder.classSchematicKind,
397
- nullable: false,
398
- scaffoldModel: (schematic, data) => {
399
- const baseModel = kformScaffolder.classSchematicKind.scaffoldModel(schematic, data);
400
- if (data.currentPath !== "/") {
401
- return baseModel;
402
- }
403
- data.currentFile.imports.add("kotlin.js.ExperimentalJsStatic").add("kotlin.js.JsStatic").add("kotlinx.serialization.EncodeDefault").add("kotlinx.serialization.ExperimentalSerializationApi");
404
- const classAnnotations = [];
405
- const versionAnnotations = [
406
- "@EncodeDefault",
407
- "@OptIn(ExperimentalSerializationApi::class)"
408
- ];
409
- if (data.serializationFormat === "xml") {
410
- data.currentFile.imports.add("nl.adaptivity.xmlutil.serialization.XmlChildrenName").add("nl.adaptivity.xmlutil.serialization.XmlElement").add("nl.adaptivity.xmlutil.serialization.XmlSerialName");
411
- const defaultNamespace = `http://${data.currentPackage.split(".").reverse().join(".")}/schema/${(/* @__PURE__ */ new Date()).getFullYear()}`;
412
- classAnnotations.push(
413
- `@XmlSerialName("${schematic.name}", "${defaultNamespace}")`
414
- );
415
- versionAnnotations.push("@XmlElement(false)");
416
- } else {
417
- data.currentFile.imports.add("kotlinx.serialization.SerialName");
418
- versionAnnotations.push('@SerialName($$"$version")');
419
- }
420
- return kformScaffolder.annotate(
421
- classAnnotations,
422
- `${baseModel} ${kformScaffolder.code`
423
- {
424
- ${kformScaffolder.annotate(versionAnnotations, `internal var version = ${constantCase(schematic.name)}_SERIALIZATION_VERSION`)}
425
-
426
- companion object {
427
- @OptIn(ExperimentalJsStatic::class)
428
- @JsStatic
429
- fun createInitialValue(externalContexts: ${schematic.name}ExternalContexts) =
430
- externalContexts.initialValue ?: ${schematic.name}()
431
- }
432
- }
433
- `}`
434
- );
435
- },
436
- scaffoldField: (schematic, data) => {
437
- data.currentFile.imports.push(
438
- { moduleName: "@ostack.tech/ui", name: "FieldGroup" },
439
- { moduleName: "@ostack.tech/ui", name: "FieldGroupHeader" },
440
- { moduleName: "@ostack.tech/ui", name: "FieldGroupTitle" },
441
- { moduleName: "@ostack.tech/ui", name: "FieldGroupBody" },
442
- { moduleName: "@ostack.tech/ui", name: "Grid" }
443
- );
444
- return kformScaffolder.code`
445
- <FieldGroup>
446
- <FieldGroupHeader>
447
- <FieldGroupTitle>${capitalCase(schematic.name)}</FieldGroupTitle>
448
- </FieldGroupHeader>
449
-
450
- <FieldGroupBody>
451
- <Grid container>
452
- ${schematic.children.map(
453
- (child) => kformScaffolder.code`
454
- <Grid xs={12}>
455
- ${scaffoldField(child, {
456
- ...data,
457
- currentPath: kformScaffolder.joinPaths(
458
- data.currentPath,
459
- child.childName
460
- )
461
- })}
462
- </Grid>
463
- `
464
- ).join("\n\n")}
465
- </Grid>
466
- </FieldGroupBody>
467
- </FieldGroup>
468
- `;
469
- }
470
- };
471
- const doubleSchematicKind = {
472
- ...kformScaffolder.doubleSchematicKind,
473
- control: "@ostack.tech/ui-kform.NumericControl"
474
- };
475
- const enumSchematicKind = {
476
- ...kformScaffolder.enumSchematicKind,
477
- kind: "Enum",
478
- internal: true,
479
- nullable: false
480
- };
481
- const enumSelectSchematicKind = {
482
- ...kformScaffolder.enumSchematicKind,
483
- kind: "Enum (Select)",
484
- control: "@ostack.tech/ui-kform.SelectControl",
485
- scaffoldControl: (schematic, data) => {
486
- if (!data.omitLabel) {
487
- data.currentFile.imports.push({
488
- moduleName: "@ostack.tech/ui",
489
- name: "Label"
490
- });
491
- }
492
- data.currentFile.imports.push({
493
- moduleName: data.kmpModuleName,
494
- name: schematic.name
495
- });
496
- return [
497
- data.omitLabel ? null : `<Label>${sentenceCase(schematic.childName)}</Label>`,
498
- kformScaffolder.code`
499
- <SelectControl
500
- options={[
501
- ${schematic.children.map(
502
- (child) => `{ value: ${schematic.name}.${child.childName}, text: ${JSON.stringify(sentenceCase(child.childName))} }`
503
- ).join(",\n")}
504
- ]}
505
- />
506
- `
507
- ].filter((s) => s).join("\n");
508
- }
509
- };
510
- const enumRadioGroupSchematicKind = {
511
- ...kformScaffolder.enumSchematicKind,
512
- kind: "Enum (RadioGroup)",
513
- control: "@ostack.tech/ui-kform.RadioGroupControl",
514
- scaffoldControl: (schematic, data) => {
515
- if (!data.omitLabel) {
516
- data.currentFile.imports.push({
517
- moduleName: "@ostack.tech/ui",
518
- name: "Label"
519
- });
520
- }
521
- data.currentFile.imports.push({
522
- moduleName: data.kmpModuleName,
523
- name: schematic.name
524
- });
525
- return [
526
- data.omitLabel ? null : `<Label>${sentenceCase(schematic.childName)}</Label>`,
527
- kformScaffolder.code`
528
- <RadioGroupControl
529
- options={[
530
- ${schematic.children.map(
531
- (child) => `{ value: ${schematic.name}.${child.childName}, text: ${JSON.stringify(sentenceCase(child.childName))} }`
532
- ).join(",\n")}
533
- ]}
534
- />
535
- `
536
- ].filter((s) => s).join("\n");
537
- }
538
- };
539
- const fileSchematicKind = {
540
- ...kformScaffolder.fileSchematicKind,
541
- nullable: true,
542
- control: "@ostack.tech/ui-kform.FileControl"
543
- };
544
- const floatSchematicKind = {
545
- ...kformScaffolder.floatSchematicKind,
546
- control: "@ostack.tech/ui-kform.NumericControl"
547
- };
548
- const intSchematicKind = {
549
- ...kformScaffolder.intSchematicKind,
550
- control: "@ostack.tech/ui-kform.NumericControl"
551
- };
552
- const listCheckboxGroupSchematicKind = {
553
- ...kformScaffolder.listSchematicKind,
554
- kind: "List<Enum> (CheckboxGroup)",
555
- nullable: false,
556
- initChildren: (childName) => [
557
- kformScaffolder.createSchematic({
558
- kind: "Enum",
559
- name: pascalCase(childName),
560
- nullable: false,
561
- children: []
562
- })
563
- ],
564
- builder: kformScaffolder.ListableBuilderWithoutKindSelect,
565
- control: "@ostack.tech/ui-kform.CheckboxGroupControl",
566
- scaffoldControl: (schematic, data) => {
567
- const childSchematic = schematic.children[0];
568
- if (childSchematic.kind !== "Enum") {
569
- throw new Error("Invalid child kind.");
570
- }
571
- if (!data.omitLabel) {
572
- data.currentFile.imports.push({
573
- moduleName: "@ostack.tech/ui",
574
- name: "Label"
575
- });
576
- }
577
- data.currentFile.imports.push({
578
- moduleName: data.kmpModuleName,
579
- name: childSchematic.name
580
- });
581
- return [
582
- data.omitLabel ? null : `<Label>${sentenceCase(schematic.childName)}</Label>`,
583
- kformScaffolder.code`
584
- <CheckboxGroupControl
585
- options={[
586
- ${childSchematic.children.map(
587
- (child) => `{ value: ${childSchematic.name}.${child.childName}, text: ${JSON.stringify(sentenceCase(child.childName))} }`
588
- ).join(",\n")}
589
- ]}
590
- />
591
- `
592
- ].filter((s) => s).join("\n");
593
- }
594
- };
595
- const listSelectMultipleSchematicKind = {
596
- ...kformScaffolder.listSchematicKind,
597
- kind: "List<Enum> (SelectMultiple)",
598
- nullable: false,
599
- initChildren: (childName) => [
600
- kformScaffolder.createSchematic({
601
- kind: "Enum",
602
- name: pascalCase(childName),
603
- nullable: false,
604
- children: []
605
- })
606
- ],
607
- builder: kformScaffolder.ListableBuilderWithoutKindSelect,
608
- control: "@ostack.tech/ui-kform.SelectMultipleControl",
609
- scaffoldControl: (schematic, data) => {
610
- const childSchematic = schematic.children[0];
611
- if (childSchematic.kind !== "Enum") {
612
- throw new Error("Invalid child kind.");
613
- }
614
- if (!data.omitLabel) {
615
- data.currentFile.imports.push({
616
- moduleName: "@ostack.tech/ui",
617
- name: "Label"
618
- });
619
- }
620
- data.currentFile.imports.push({
621
- moduleName: data.kmpModuleName,
622
- name: childSchematic.name
623
- });
624
- return [
625
- data.omitLabel ? null : `<Label>${sentenceCase(schematic.childName)}</Label>`,
626
- kformScaffolder.code`
627
- <SelectMultipleControl
628
- options={[
629
- ${childSchematic.children.map(
630
- (child) => `{ value: ${childSchematic.name}.${child.childName}, text: ${JSON.stringify(sentenceCase(child.childName))} }`
631
- ).join(",\n")}
632
- ]}
633
- />
634
- `
635
- ].filter((s) => s).join("\n");
636
- }
637
- };
638
- const localDateSchematicKind = {
639
- ...kformScaffolder.localDateSchematicKind,
640
- nullable: true,
641
- control: "@ostack.tech/ui-kform.DateControl"
642
- };
643
- const longSchematicKind = {
644
- ...kformScaffolder.longSchematicKind,
645
- control: "@ostack.tech/ui-kform.NumericControl"
646
- };
647
- const shortSchematicKind = {
648
- ...kformScaffolder.shortSchematicKind,
649
- control: "@ostack.tech/ui-kform.NumericControl"
650
- };
651
- const stringSchematicKind = {
652
- ...kformScaffolder.stringSchematicKind,
653
- control: "@ostack.tech/ui-kform.TextControl"
654
- };
655
- const tableAnnexesSchematicKind = {
656
- ...kformScaffolder.tableSchematicKind,
657
- kind: "Table (Annexes)",
658
- nullable: false,
659
- builder: kformScaffolder.ListableBuilderWithoutKindSelect,
660
- initChildren: (childName) => [
661
- kformScaffolder.createSchematic({
662
- kind: "Class (Annex)",
663
- packageSuffix: `annexes.${childName.toLowerCase()}`,
664
- name: pascalCase(childName),
665
- nullable: false,
666
- children: []
667
- })
668
- ],
669
- propertyAnnotations: (schematic, data) => {
670
- const annotations = arrayify(
671
- typeof kformScaffolder.tableSchematicKind.propertyAnnotations === "function" ? kformScaffolder.tableSchematicKind.propertyAnnotations?.(schematic, data) : kformScaffolder.tableSchematicKind.propertyAnnotations
672
- );
673
- if (data.serializationFormat === "xml") {
674
- data.currentFile.imports.add(
675
- "nl.adaptivity.xmlutil.serialization.XmlChildrenName"
676
- );
677
- annotations.push(
678
- `@XmlChildrenName("${camelCase(schematic.children[0].name)}")`
679
- );
680
- }
681
- return annotations;
682
- }
683
- };
684
- const tableSchematicKind = {
685
- ...kformScaffolder.tableSchematicKind,
686
- nullable: false,
687
- builder: kformScaffolder.ListableBuilderWithoutKindSelect,
688
- initChildren: (childName) => [
689
- kformScaffolder.createSchematic({
690
- kind: "Class",
691
- name: `${pascalCase(childName)}Row`,
692
- nullable: false,
693
- children: []
694
- })
695
- ],
696
- propertyAnnotations: tableAnnexesSchematicKind.propertyAnnotations,
697
- control: "@ostack.tech/ui-kform.TableControl",
698
- scaffoldControl: (schematic, data) => {
699
- const rowSchematic = schematic.children[0];
700
- if (rowSchematic.kind !== "Class") {
701
- throw new Error("Table child schematic is not of Class kind.");
702
- }
703
- data.currentFile.imports.push(
704
- { moduleName: "@ostack.tech/ui", name: "Label" },
705
- {
706
- moduleName: "@ostack.tech/ui-kform",
707
- name: "tableControlIndexColumn"
708
- },
709
- {
710
- moduleName: "@ostack.tech/ui-kform",
711
- name: "tableControlActionsColumn"
712
- },
713
- {
714
- moduleName: "@ostack.tech/ui-kform",
715
- name: "TableControlAddRowTrigger"
716
- },
717
- { moduleName: "@ostack.tech/ui-kform", name: "TableControlContent" }
718
- );
719
- return kformScaffolder.code`
720
- <TableControl
721
- columns={[
722
- tableControlIndexColumn(),
723
- ${rowSchematic.children.map(
724
- (child) => kformScaffolder.code`
725
- {
726
- label: ${JSON.stringify(sentenceCase(child.childName))},
727
- render: () => (
728
- ${scaffoldField(child, {
729
- ...data,
730
- omitLabel: true,
731
- currentPath: child.childName
732
- })}
733
- )
734
- }
735
- `
736
- ).join(",\n")},
737
- tableControlActionsColumn()
738
- ]}
739
- >
740
- <Label>${sentenceCase(schematic.childName)}</Label>
741
- <TableControlAddRowTrigger />
742
- <TableControlContent />
743
- </TableControl>
744
- `;
745
- }
746
- };
747
- const defaultSchematicKinds = [
748
- anySchematicKind,
749
- bigDecimalSchematicKind,
750
- bigIntegerSchematicKind,
751
- booleanSchematicKind,
752
- byteSchematicKind,
753
- classSchematicKind,
754
- classAnnexSchematicKind,
755
- classFormPageSchematicKind,
756
- doubleSchematicKind,
757
- enumSchematicKind,
758
- enumSelectSchematicKind,
759
- enumRadioGroupSchematicKind,
760
- fileSchematicKind,
761
- floatSchematicKind,
762
- intSchematicKind,
763
- listCheckboxGroupSchematicKind,
764
- listSelectMultipleSchematicKind,
765
- localDateSchematicKind,
766
- longSchematicKind,
767
- shortSchematicKind,
768
- stringSchematicKind,
769
- tableAnnexesSchematicKind,
770
- tableSchematicKind
771
- ];
772
- function reactAppLayout(schematic, data) {
773
- const annexes = [];
774
- if (schematic.children?.every(
775
- (child) => child.kind === classAnnexSchematicKind.kind || child.kind === tableAnnexesSchematicKind.kind
776
- )) {
777
- for (const annex of schematic.children) {
778
- if (annex.kind === classAnnexSchematicKind.kind) {
779
- annexes.push(
780
- layoutAnnex(annex, {
781
- ...data,
782
- currentPath: kformScaffolder.joinPaths(data.currentPath, annex.childName),
783
- currentDir: kformScaffolder.joinPaths(
784
- data.currentDir,
785
- annex.packageSuffix?.replace(".", "/")
786
- )
787
- })
788
- );
789
- } else {
790
- annexes.push(
791
- layoutRepetitiveAnnex(annex, {
792
- ...data,
793
- currentPath: kformScaffolder.joinPaths(data.currentPath, annex.childName)
794
- })
795
- );
796
- }
797
- }
798
- } else if (schematic.children?.every(
799
- (child) => child.kind === classFormPageSchematicKind.kind
800
- )) {
801
- annexes.push(layoutAnnex(schematic, data));
802
- } else if (schematic.children?.some(
803
- (child) => child.kind === classAnnexSchematicKind.kind || child.kind === tableAnnexesSchematicKind.kind || child.kind === classFormPageSchematicKind.kind
804
- )) {
805
- throw new Error(
806
- "Annexes/form pages cannot be mixed with other kinds of fields."
807
- );
808
- } else {
809
- annexes.push(layoutAnnex(schematic, data));
810
- }
811
- return annexes;
812
- }
813
- function layoutRepetitiveAnnex(schematic, data) {
814
- const childSchematic = schematic.children[0];
815
- return layoutAnnex(childSchematic, {
816
- ...data,
817
- currentPath: kformScaffolder.joinPaths(data.currentPath, "*"),
818
- currentDir: kformScaffolder.joinPaths(
819
- data.currentDir,
820
- childSchematic.packageSuffix?.replace(".", "/")
821
- )
822
- });
823
- }
824
- function layoutAnnex(schematic, data) {
825
- if (schematic.children?.some(
826
- (child) => child.kind === classAnnexSchematicKind.kind || child.kind === tableAnnexesSchematicKind.kind
827
- )) {
828
- throw new Error(
829
- "Annexes must only appear at the top level of the schematic."
830
- );
831
- }
832
- let formPages;
833
- if (schematic.children?.every(
834
- (child) => child.kind === classFormPageSchematicKind.kind
835
- )) {
836
- formPages = schematic.children?.map((formPage) => ({
837
- schematic: formPage,
838
- data: {
839
- ...data,
840
- currentPath: kformScaffolder.joinPaths(
841
- data.currentPath,
842
- camelCase(formPage.childName)
843
- ),
844
- currentDir: kformScaffolder.joinPaths(
845
- data.currentDir,
846
- formPage.packageSuffix?.replace(".", "/")
847
- )
848
- }
849
- }));
850
- } else if (schematic.children?.some(
851
- (child) => child.kind === classFormPageSchematicKind.kind
852
- )) {
853
- throw new Error("Form pages cannot be mixed with other kinds of fields.");
854
- } else {
855
- formPages = [{ schematic, data }];
856
- }
857
- return { schematic, data, formPages };
858
- }
859
- function scaffoldAppComponent(schematic, data) {
860
- const fileName = kformScaffolder.joinPaths(data.currentDir, `${schematic.name}App.tsx`);
861
- let file = data.files.get(fileName);
862
- if (!file) {
863
- data.files.set(fileName, file = kformScaffolder.tsFile());
864
- }
865
- scaffoldAppComponentFile(schematic, {
866
- kmpModuleName: `${kebabCase(schematic.name)}-shared`,
867
- ...data,
868
- currentFile: file
869
- });
870
- scaffoldIssueMessages(schematic, data);
871
- }
872
- function scaffoldAppComponentFile(schematic, data) {
873
- data.currentFile.imports.push(
874
- { moduleName: "@ostack.tech/kform", name: "ktMapToObject" },
875
- { moduleName: "@ostack.tech/ui-kform", name: "FormApp" },
876
- { moduleName: "react", name: "useMemo" },
877
- { moduleName: data.kmpModuleName, name: schematic.name },
878
- { moduleName: data.kmpModuleName, name: `${schematic.name}FormMode` },
879
- { moduleName: data.kmpModuleName, name: `${schematic.name}Schema` },
880
- { moduleName: `./api/reportError.ts`, name: "REPORT_ERROR_ENDPOINT" },
881
- {
882
- moduleName: `./${schematic.name}Context.ts`,
883
- name: `use${schematic.name}Context`
884
- },
885
- {
886
- moduleName: `./${schematic.name}IssueMessages.tsx`,
887
- name: `${constantCase(schematic.name)}_ISSUE_MESSAGES`
888
- }
889
- );
890
- data.currentFile.declarations.push(kformScaffolder.code`
891
- export function ${schematic.name}App() {
892
- const { externalContexts } = use${schematic.name}Context();
893
-
894
- return (
895
- <FormApp
896
- schema={${schematic.name}Schema.get()}
897
- initialValue={useMemo(
898
- () => ${schematic.name}.createInitialValue(externalContexts),
899
- [externalContexts],
900
- )}
901
- externalContexts={useMemo(
902
- () => ktMapToObject(externalContexts.toMap()),
903
- [externalContexts],
904
- )}
905
- readOnly={externalContexts.mode === ${schematic.name}FormMode.READ}
906
- validationMode={
907
- externalContexts.mode === ${schematic.name}FormMode.READ
908
- ? "manual"
909
- : "auto"
910
- }
911
- issueMessages={${constantCase(schematic.name)}_ISSUE_MESSAGES}
912
- errorReportingUrl={REPORT_ERROR_ENDPOINT}
913
- >
914
- <${schematic.name}Layout />
915
- </FormApp>
916
- );
917
- }
918
- `);
919
- const layout = reactAppLayout(schematic, data);
920
- data.currentFile.imports.push(
921
- { moduleName: "react-router", name: "useNavigate" },
922
- { moduleName: "react-router", name: "useLocation" },
923
- { moduleName: "react-router", name: "Outlet" },
924
- { moduleName: "@ostack.tech/ui-kform", name: "Annexes" },
925
- { moduleName: "@ostack.tech/ui-kform", name: "Annex" },
926
- {
927
- moduleName: "@ostack.tech/ui-kform",
928
- name: "AnnexObject",
929
- isType: true
930
- },
931
- { moduleName: "@ostack.tech/ui-kform", name: "TopBar" },
932
- { moduleName: "@ostack.tech/ui-kform", name: "TopBarActions" },
933
- { moduleName: "./actions/Load.tsx", name: "Load" },
934
- { moduleName: "./actions/Save.tsx", name: "Save" },
935
- { moduleName: "./actions/Validate.tsx", name: "Validate" },
936
- { moduleName: "./actions/Submit.tsx", name: "Submit" },
937
- { moduleName: "@ostack.tech/ui-kform", name: "FormPages" },
938
- {
939
- moduleName: "@ostack.tech/ui-kform",
940
- name: "FormPageObject",
941
- isType: true
942
- },
943
- { moduleName: "@ostack.tech/ui-kform", name: "IssuesPanel" }
944
- );
945
- let annexesManager = "";
946
- if (layout.length > 1) {
947
- data.currentFile.imports.push({
948
- moduleName: "@ostack.tech/ui-kform",
949
- name: "AnnexesManager"
950
- });
951
- annexesManager = `
952
- <AnnexesManager />
953
- `;
954
- }
955
- let formPagesNavigation = "";
956
- if (layout.some((annex) => annex.formPages.length > 1)) {
957
- data.currentFile.imports.push({
958
- moduleName: "@ostack.tech/ui-kform",
959
- name: "FormPagesNavigation"
960
- });
961
- if (layout.every((annex) => annex.formPages.length > 1)) {
962
- formPagesNavigation = `
963
- <FormPagesNavigation />
964
- `;
965
- } else {
966
- formPagesNavigation = `
967
- {pages.length > 1 && <FormPagesNavigation />}
968
- `;
969
- }
970
- }
971
- data.currentFile.declarations.push(kformScaffolder.code`
972
- function ${schematic.name}Layout() {
973
- const navigate = useNavigate();
974
- const { pathname } = useLocation();
975
-
976
- const annexes: AnnexObject[] = useMemo(() => ${scaffoldAnnexesArray(layout)}, []);
977
-
978
- const pagesByAnnex: Record<string, FormPageObject[]> = useMemo(() => (${scaffoldFormPagesByAnnexObject(layout)}), []);
979
-
980
- return (
981
- <>
982
- <Annexes annexes={annexes} activeAnnex={pathname}>
983
- <TopBar>${annexesManager}
984
- <TopBarActions>
985
- <Load />
986
- <Save />
987
- <Validate />
988
- <Submit />
989
- </TopBarActions>
990
- </TopBar>
991
-
992
- {Object.entries(pagesByAnnex).map(([annexPath, pages]) => (
993
- <Annex path={annexPath} key={annexPath}>
994
- <FormPages
995
- pages={pages}
996
- activePage={pathname}
997
- onActivePageChange={(activePage) => {
998
- const newPathname = activePage?.toString() ?? "/";
999
- if (pathname !== newPathname) {
1000
- void navigate(newPathname, {
1001
- replace: newPathname.startsWith(
1002
- pathname.endsWith("/") ? pathname : \`\${pathname}/\`,
1003
- )
1004
- });
1005
- }
1006
- }}
1007
- >${formPagesNavigation}
1008
- <Outlet />
1009
- </FormPages>
1010
- </Annex>
1011
- ))}
1012
- </Annexes>
1013
-
1014
- <IssuesPanel />
1015
- </>
1016
- );
1017
- }
1018
- `);
1019
- }
1020
- function scaffoldAnnexesArray(layout) {
1021
- return kformScaffolder.code`
1022
- [
1023
- ${layout.map(
1024
- (annex) => `{ path: "${annex.data.currentPath}", title: "${sentenceCase(
1025
- annex.schematic.name
1026
- )}"${annex.formPages.length === 1 && annex.data.currentPath === annex.formPages[0].data.currentPath ? ", documentTitle: null" : ""} }`
1027
- ).join(",\n")}
1028
- ]
1029
- `;
1030
- }
1031
- function scaffoldFormPagesByAnnexObject(layout) {
1032
- return kformScaffolder.code`
1033
- {
1034
- ${layout.map(
1035
- (annex) => `"${annex.data.currentPath}": ` + kformScaffolder.code`
1036
- [
1037
- ${annex.formPages.map(
1038
- (formPage) => annex.schematic === formPage.schematic ? `{ title: "${sentenceCase(
1039
- formPage.schematic.name
1040
- )}", code: "${formPage.schematic.name?.[0].toUpperCase()}"${formPage.data.currentPath === "/" ? ", documentTitle: null" : ""} }` : `{ path: "${formPage.data.currentPath.slice(
1041
- annex.data.currentPath.length + (annex.data.currentPath.endsWith("/") ? 0 : 1)
1042
- )}", title: "${sentenceCase(
1043
- formPage.schematic.name
1044
- )}", code: "${formPage.schematic.name?.[0].toUpperCase()}" }`
1045
- ).join(",\n")}
1046
- ]
1047
- `
1048
- ).join(",\n")}
1049
- }
1050
- `;
1051
- }
1052
- 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';
1053
- function scaffoldAppContext(schematic, data) {
1054
- const ejsData = {
1055
- kmpModuleName: data.kmpModuleName ?? `${kebabCase(schematic.name)}-shared`,
1056
- formClass: schematic.name
1057
- };
1058
- kformScaffolder.addEjsTemplateFile(
1059
- data,
1060
- `${schematic.name}Context.ts`,
1061
- contextTsEjs,
1062
- ejsData
1063
- );
1064
- }
1065
- const externalContextsKt = 'package <%= filePackage %>\n\nimport kotlin.js.JsExport\nimport kotlin.jvm.JvmOverloads\nimport kotlinx.serialization.Serializable\n\n@JsExport\n@Serializable\nenum class <%= formClass %>FormMode {\n /** Submitting a new form. */\n NEW,\n /** Reading a previously submitted form (`initialValue` should be provided as context). */\n READ,\n /** Replacing a previously submitted form (`initialValue` should be provided as context). */\n REPLACE,\n}\n\n@JsExport\n@Serializable\ndata class <%= formClass %>ExternalContexts @JvmOverloads constructor(\n val mode: <%= formClass %>FormMode = <%= formClass %>FormMode.NEW,\n val initialValue: <%= formClass %>? = null,\n) {\n fun toMap(): Map<String, Any?> = mapOf("mode" to mode, "initialValue" to initialValue)\n}\n';
1066
- function scaffoldExternalContexts(schematic, data) {
1067
- const ejsData = {
1068
- filePackage: data.currentPackage,
1069
- formClass: schematic.name
1070
- };
1071
- kformScaffolder.addEjsTemplateFile(
1072
- data,
1073
- `${schematic.name}ExternalContexts.kt`,
1074
- externalContextsKt,
1075
- ejsData
1076
- );
1077
- }
1078
- const buildGradleKts = "allprojects {\n repositories { mavenCentral() }\n}\n";
1079
- const gradlePropertiesEjs = "group=<%= group %>\nversion=0.0.1\n\norg.gradle.caching=true\norg.gradle.configuration-cache=true\n";
1080
- 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';
1081
- 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';
1082
- 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';
1083
- 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';
1084
- 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';
1085
- function scaffoldGradleProject(schematic, data) {
1086
- const ejsData = {
1087
- group: data.currentPackage,
1088
- filePackage: data.currentPackage,
1089
- formId: kebabCase(schematic.name),
1090
- formTitle: capitalCase(schematic.name),
1091
- kFormVersion: "0.31.0",
1092
- serializationFormat: data.serializationFormat ?? "json",
1093
- usesKotlinxDatetime: usesKotlinxDatetime(schematic, data),
1094
- usesKtMath: usesKtMath(schematic)
1095
- };
1096
- kformScaffolder.addEjsTemplateFile(data, "gradle.properties", gradlePropertiesEjs, ejsData);
1097
- kformScaffolder.addEjsTemplateFile(
1098
- data,
1099
- "settings.gradle.kts",
1100
- settingsGradleKtsEjs,
1101
- ejsData
1102
- );
1103
- kformScaffolder.addEjsTemplateFile(
1104
- data,
1105
- "gradle/libs.versions.toml",
1106
- libsVersionsTomlEjs,
1107
- ejsData
1108
- );
1109
- kformScaffolder.addTemplateFile(data, "build.gradle.kts", buildGradleKts);
1110
- kformScaffolder.addEjsTemplateFile(
1111
- data,
1112
- "shared/build.gradle.kts",
1113
- sharedBuildGradleKtsEjs,
1114
- ejsData
1115
- );
1116
- if (ejsData.usesKotlinxDatetime) {
1117
- kformScaffolder.addEjsTemplateFile(
1118
- data,
1119
- "shared/src/jsMain/kotlin/JsJodaTimeZone.kt",
1120
- jsJodaTimeZoneKtEjs,
1121
- ejsData
1122
- );
1123
- }
1124
- kformScaffolder.addEjsTemplateFile(
1125
- data,
1126
- "react-app/build.gradle.kts",
1127
- reactAppBuildGradleKtsEjs,
1128
- ejsData
1129
- );
1130
- }
1131
- function usesKotlinxDatetime(schematic, data) {
1132
- const schematicKind = data.schematicKinds.get(schematic.kind);
1133
- return schematicKind?.package === "kotlinx.datetime" || schematic.children?.some((child) => usesKotlinxDatetime(child, data)) === true;
1134
- }
1135
- function usesKtMath(schematic) {
1136
- return ["BigInteger", "BigDecimal"].includes(schematic.kind) || schematic.children?.some((child) => usesKtMath(child)) === true;
1137
- }
1138
- const gradleWrapperJar = "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AAAAAAAAAAAAAAAwDgAATUVUQS1JTkYvTUFOSUZFU1QuTUZVVAUAAQAAAABQSwECFAAUAAgICAAAACEAAsIE3yIBAABwAQAAMQAJAAAAAAAAAAAAAAD2DgAAb3JnL2dyYWRsZS9jbGkvQ29tbWFuZExpbmVBcmd1bWVudEV4Y2VwdGlvbi5jbGFzc1VUBQABAAAAAFBLAQIUABQACAgIAAAAIQBsZK5NbgIAALMDAAAmAAkAAAAAAAAAAAAAAIAQAABvcmcvZ3JhZGxlL2NsaS9Db21tYW5kTGluZU9wdGlvbi5jbGFzc1VUBQABAAAAAFBLAQIUABQACAgIAAAAIQBrrAeZWwIAALYEAAAzAAkAAAAAAAAAAAAAAEsTAABvcmcvZ3JhZGxlL2NsaS9Db21tYW5kTGluZVBhcnNlciRBZnRlck9wdGlvbnMuY2xhc3NVVAUAAQAAAABQSwECFAAUAAgICAAAACEABUgOxC4DAABdBwAAPAAJAAAAAAAAAAAAAAAQFgAAb3JnL2dyYWRsZS9jbGkvQ29tbWFuZExpbmVQYXJzZXIkQmVmb3JlRmlyc3RTdWJDb21tYW5kLmNsYXNzVVQFAAEAAAAAUEsBAhQAFAAICAgAAAAhAO+A7pzcBgAAYg4AAD0ACQAAAAAAAAAAAAAAsRkAAG9yZy9ncmFkbGUvY2xpL0NvbW1hbmRMaW5lUGFyc2VyJEtub3duT3B0aW9uUGFyc2VyU3RhdGUuY2xhc3NVVAUAAQAAAABQSwECFAAUAAgICAAAACEAxIDBO00CAACXBAAAPAAJAAAAAAAAAAAAAAABIQAAb3JnL2dyYWRsZS9jbGkvQ29tbWFuZExpbmVQYXJzZXIkTWlzc2luZ09wdGlvbkFyZ1N0YXRlLmNsYXNzVVQFAAEAAAAAUEsBAhQAFAAICAgAAAAhAKUEGSPYAgAASgUAAD0ACQAAAAAAAAAAAAAAwSMAAG9yZy9ncmFkbGUvY2xpL0NvbW1hbmRMaW5lUGFyc2VyJE9wdGlvbkF3YXJlUGFyc2VyU3RhdGUuY2xhc3NVVAUAAQAAAABQSwECFAAUAAgICAAAACEAIjgzfKIBAAB9AgAAOAAJAAAAAAAAAAAAAAANJwAAb3JnL2dyYWRsZS9jbGkvQ29tbWFuZExpbmVQYXJzZXIkT3B0aW9uUGFyc2Vy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";
1139
- const gradleWrapperProperties = "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.14.2-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n";
1140
- const gradlewBat = `@rem
1141
- @rem Copyright 2015 the original author or authors.
1142
- @rem
1143
- @rem Licensed under the Apache License, Version 2.0 (the "License");
1144
- @rem you may not use this file except in compliance with the License.
1145
- @rem You may obtain a copy of the License at
1146
- @rem
1147
- @rem https://www.apache.org/licenses/LICENSE-2.0
1148
- @rem
1149
- @rem Unless required by applicable law or agreed to in writing, software
1150
- @rem distributed under the License is distributed on an "AS IS" BASIS,
1151
- @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1152
- @rem See the License for the specific language governing permissions and
1153
- @rem limitations under the License.
1154
- @rem
1155
- @rem SPDX-License-Identifier: Apache-2.0
1156
- @rem
1157
-
1158
- @if "%DEBUG%"=="" @echo off
1159
- @rem ##########################################################################
1160
- @rem
1161
- @rem Gradle startup script for Windows
1162
- @rem
1163
- @rem ##########################################################################
1164
-
1165
- @rem Set local scope for the variables with windows NT shell
1166
- if "%OS%"=="Windows_NT" setlocal
1167
-
1168
- set DIRNAME=%~dp0
1169
- if "%DIRNAME%"=="" set DIRNAME=.
1170
- @rem This is normally unused
1171
- set APP_BASE_NAME=%~n0
1172
- set APP_HOME=%DIRNAME%
1173
-
1174
- @rem Resolve any "." and ".." in APP_HOME to make it shorter.
1175
- for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
1176
-
1177
- @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
1178
- set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
1179
-
1180
- @rem Find java.exe
1181
- if defined JAVA_HOME goto findJavaFromJavaHome
1182
-
1183
- set JAVA_EXE=java.exe
1184
- %JAVA_EXE% -version >NUL 2>&1
1185
- if %ERRORLEVEL% equ 0 goto execute
1186
-
1187
- echo. 1>&2
1188
- echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
1189
- echo. 1>&2
1190
- echo Please set the JAVA_HOME variable in your environment to match the 1>&2
1191
- echo location of your Java installation. 1>&2
1192
-
1193
- goto fail
1194
-
1195
- :findJavaFromJavaHome
1196
- set JAVA_HOME=%JAVA_HOME:"=%
1197
- set JAVA_EXE=%JAVA_HOME%/bin/java.exe
1198
-
1199
- if exist "%JAVA_EXE%" goto execute
1200
-
1201
- echo. 1>&2
1202
- echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
1203
- echo. 1>&2
1204
- echo Please set the JAVA_HOME variable in your environment to match the 1>&2
1205
- echo location of your Java installation. 1>&2
1206
-
1207
- goto fail
1208
-
1209
- :execute
1210
- @rem Setup the command line
1211
-
1212
- set CLASSPATH=
1213
-
1214
-
1215
- @rem Execute Gradle
1216
- "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar" %*
1217
-
1218
- :end
1219
- @rem End local scope for the variables with windows NT shell
1220
- if %ERRORLEVEL% equ 0 goto mainEnd
1221
-
1222
- :fail
1223
- rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
1224
- rem the _cmd.exe /c_ return code!
1225
- set EXIT_CODE=%ERRORLEVEL%
1226
- if %EXIT_CODE% equ 0 set EXIT_CODE=1
1227
- if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
1228
- exit /b %EXIT_CODE%
1229
-
1230
- :mainEnd
1231
- if "%OS%"=="Windows_NT" endlocal
1232
-
1233
- :omega
1234
- `;
1235
- const gradlew = `#!/bin/sh
1236
-
1237
- #
1238
- # Copyright © 2015-2021 the original authors.
1239
- #
1240
- # Licensed under the Apache License, Version 2.0 (the "License");
1241
- # you may not use this file except in compliance with the License.
1242
- # You may obtain a copy of the License at
1243
- #
1244
- # https://www.apache.org/licenses/LICENSE-2.0
1245
- #
1246
- # Unless required by applicable law or agreed to in writing, software
1247
- # distributed under the License is distributed on an "AS IS" BASIS,
1248
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1249
- # See the License for the specific language governing permissions and
1250
- # limitations under the License.
1251
- #
1252
- # SPDX-License-Identifier: Apache-2.0
1253
- #
1254
-
1255
- ##############################################################################
1256
- #
1257
- # Gradle start up script for POSIX generated by Gradle.
1258
- #
1259
- # Important for running:
1260
- #
1261
- # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
1262
- # noncompliant, but you have some other compliant shell such as ksh or
1263
- # bash, then to run this script, type that shell name before the whole
1264
- # command line, like:
1265
- #
1266
- # ksh Gradle
1267
- #
1268
- # Busybox and similar reduced shells will NOT work, because this script
1269
- # requires all of these POSIX shell features:
1270
- # * functions;
1271
- # * expansions «$var», «\${var}», «\${var:-default}», «\${var+SET}»,
1272
- # «\${var#prefix}», «\${var%suffix}», and «$( cmd )»;
1273
- # * compound commands having a testable exit status, especially «case»;
1274
- # * various built-in commands including «command», «set», and «ulimit».
1275
- #
1276
- # Important for patching:
1277
- #
1278
- # (2) This script targets any POSIX shell, so it avoids extensions provided
1279
- # by Bash, Ksh, etc; in particular arrays are avoided.
1280
- #
1281
- # The "traditional" practice of packing multiple parameters into a
1282
- # space-separated string is a well documented source of bugs and security
1283
- # problems, so this is (mostly) avoided, by progressively accumulating
1284
- # options in "$@", and eventually passing that to Java.
1285
- #
1286
- # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
1287
- # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
1288
- # see the in-line comments for details.
1289
- #
1290
- # There are tweaks for specific operating systems such as AIX, CygWin,
1291
- # Darwin, MinGW, and NonStop.
1292
- #
1293
- # (3) This script is generated from the Groovy template
1294
- # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
1295
- # within the Gradle project.
1296
- #
1297
- # You can find Gradle at https://github.com/gradle/gradle/.
1298
- #
1299
- ##############################################################################
1300
-
1301
- # Attempt to set APP_HOME
1302
-
1303
- # Resolve links: $0 may be a link
1304
- app_path=$0
1305
-
1306
- # Need this for daisy-chained symlinks.
1307
- while
1308
- APP_HOME=\${app_path%"\${app_path##*/}"} # leaves a trailing /; empty if no leading path
1309
- [ -h "$app_path" ]
1310
- do
1311
- ls=$( ls -ld "$app_path" )
1312
- link=\${ls#*' -> '}
1313
- case $link in #(
1314
- /*) app_path=$link ;; #(
1315
- *) app_path=$APP_HOME$link ;;
1316
- esac
1317
- done
1318
-
1319
- # This is normally unused
1320
- # shellcheck disable=SC2034
1321
- APP_BASE_NAME=\${0##*/}
1322
- # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
1323
- APP_HOME=$( cd -P "\${APP_HOME:-./}" > /dev/null && printf '%s\\n' "$PWD" ) || exit
1324
-
1325
- # Use the maximum available, or set MAX_FD != -1 to use that value.
1326
- MAX_FD=maximum
1327
-
1328
- warn () {
1329
- echo "$*"
1330
- } >&2
1331
-
1332
- die () {
1333
- echo
1334
- echo "$*"
1335
- echo
1336
- exit 1
1337
- } >&2
1338
-
1339
- # OS specific support (must be 'true' or 'false').
1340
- cygwin=false
1341
- msys=false
1342
- darwin=false
1343
- nonstop=false
1344
- case "$( uname )" in #(
1345
- CYGWIN* ) cygwin=true ;; #(
1346
- Darwin* ) darwin=true ;; #(
1347
- MSYS* | MINGW* ) msys=true ;; #(
1348
- NONSTOP* ) nonstop=true ;;
1349
- esac
1350
-
1351
- CLASSPATH="\\\\\\"\\\\\\""
1352
-
1353
-
1354
- # Determine the Java command to use to start the JVM.
1355
- if [ -n "$JAVA_HOME" ] ; then
1356
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
1357
- # IBM's JDK on AIX uses strange locations for the executables
1358
- JAVACMD=$JAVA_HOME/jre/sh/java
1359
- else
1360
- JAVACMD=$JAVA_HOME/bin/java
1361
- fi
1362
- if [ ! -x "$JAVACMD" ] ; then
1363
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
1364
-
1365
- Please set the JAVA_HOME variable in your environment to match the
1366
- location of your Java installation."
1367
- fi
1368
- else
1369
- JAVACMD=java
1370
- if ! command -v java >/dev/null 2>&1
1371
- then
1372
- die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
1373
-
1374
- Please set the JAVA_HOME variable in your environment to match the
1375
- location of your Java installation."
1376
- fi
1377
- fi
1378
-
1379
- # Increase the maximum file descriptors if we can.
1380
- if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
1381
- case $MAX_FD in #(
1382
- max*)
1383
- # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
1384
- # shellcheck disable=SC2039,SC3045
1385
- MAX_FD=$( ulimit -H -n ) ||
1386
- warn "Could not query maximum file descriptor limit"
1387
- esac
1388
- case $MAX_FD in #(
1389
- '' | soft) :;; #(
1390
- *)
1391
- # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
1392
- # shellcheck disable=SC2039,SC3045
1393
- ulimit -n "$MAX_FD" ||
1394
- warn "Could not set maximum file descriptor limit to $MAX_FD"
1395
- esac
1396
- fi
1397
-
1398
- # Collect all arguments for the java command, stacking in reverse order:
1399
- # * args from the command line
1400
- # * the main class name
1401
- # * -classpath
1402
- # * -D...appname settings
1403
- # * --module-path (only if needed)
1404
- # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
1405
-
1406
- # For Cygwin or MSYS, switch paths to Windows format before running java
1407
- if "$cygwin" || "$msys" ; then
1408
- APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
1409
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
1410
-
1411
- JAVACMD=$( cygpath --unix "$JAVACMD" )
1412
-
1413
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
1414
- for arg do
1415
- if
1416
- case $arg in #(
1417
- -*) false ;; # don't mess with options #(
1418
- /?*) t=\${arg#/} t=/\${t%%/*} # looks like a POSIX filepath
1419
- [ -e "$t" ] ;; #(
1420
- *) false ;;
1421
- esac
1422
- then
1423
- arg=$( cygpath --path --ignore --mixed "$arg" )
1424
- fi
1425
- # Roll the args list around exactly as many times as the number of
1426
- # args, so each arg winds up back in the position where it started, but
1427
- # possibly modified.
1428
- #
1429
- # NB: a \`for\` loop captures its iteration list before it begins, so
1430
- # changing the positional parameters here affects neither the number of
1431
- # iterations, nor the values presented in \`arg\`.
1432
- shift # remove old arg
1433
- set -- "$@" "$arg" # push replacement arg
1434
- done
1435
- fi
1436
-
1437
-
1438
- # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
1439
- DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
1440
-
1441
- # Collect all arguments for the java command:
1442
- # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
1443
- # and any embedded shellness will be escaped.
1444
- # * For example: A user cannot expect \${Hostname} to be expanded, as it is an environment variable and will be
1445
- # treated as '\${Hostname}' itself on the command line.
1446
-
1447
- set -- \\
1448
- "-Dorg.gradle.appname=$APP_BASE_NAME" \\
1449
- -classpath "$CLASSPATH" \\
1450
- -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \\
1451
- "$@"
1452
-
1453
- # Stop when "xargs" is not available.
1454
- if ! command -v xargs >/dev/null 2>&1
1455
- then
1456
- die "xargs is not available"
1457
- fi
1458
-
1459
- # Use "xargs" to parse quoted args.
1460
- #
1461
- # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
1462
- #
1463
- # In Bash we could simply go:
1464
- #
1465
- # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
1466
- # set -- "\${ARGS[@]}" "$@"
1467
- #
1468
- # but POSIX shell has neither arrays nor command substitution, so instead we
1469
- # post-process each arg (as a line of input to sed) to backslash-escape any
1470
- # character that might be a shell metacharacter, then use eval to reverse
1471
- # that process (while maintaining the separation between arguments), and wrap
1472
- # the whole thing up as a single "set" statement.
1473
- #
1474
- # This will of course break if any of these variables contains a newline or
1475
- # an unmatched quote.
1476
- #
1477
-
1478
- eval "set -- $(
1479
- printf '%s\\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
1480
- xargs -n1 |
1481
- sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |
1482
- tr '\\n' ' '
1483
- )" '"$@"'
1484
-
1485
- exec "$JAVACMD" "$@"
1486
- `;
1487
- function scaffoldGradleWrapper(_schematic, data) {
1488
- kformScaffolder.addTemplateFile(data, "gradlew", gradlew, { executable: true });
1489
- kformScaffolder.addTemplateFile(data, "gradlew.bat", gradlewBat);
1490
- kformScaffolder.addTemplateFile(data, "gradle/wrapper/gradle-wrapper.jar", gradleWrapperJar, {
1491
- base64: true
1492
- });
1493
- kformScaffolder.addTemplateFile(
1494
- data,
1495
- "gradle/wrapper/gradle-wrapper.properties",
1496
- gradleWrapperProperties
1497
- );
1498
- }
1499
- function scaffoldMain(schematic, data) {
1500
- const fileName = kformScaffolder.joinPaths(data.currentDir, "main.tsx");
1501
- let file = data.files.get(fileName);
1502
- if (!file) {
1503
- data.files.set(fileName, file = kformScaffolder.tsFile());
1504
- }
1505
- scaffoldMainFile(schematic, {
1506
- kmpModuleName: `${kebabCase(schematic.name)}-shared`,
1507
- ...data,
1508
- currentFile: file
1509
- });
1510
- }
1511
- function scaffoldMainFile(schematic, data) {
1512
- data.currentFile.imports.push(
1513
- { moduleName: "./index.scss" },
1514
- { moduleName: "react-router-dom", name: "createHashRouter" }
1515
- );
1516
- data.currentFile.declarations.push(
1517
- `const router = createHashRouter([${scaffoldRouteObject(schematic, data)}]);`
1518
- );
1519
- data.currentFile.imports.push(
1520
- { moduleName: "react-dom/client", name: "createRoot" },
1521
- { moduleName: "react", name: "StrictMode" },
1522
- { moduleName: "react-router-dom", name: "RouterProvider" },
1523
- {
1524
- moduleName: data.kmpModuleName,
1525
- name: `decode${schematic.name}ExternalContextsFromString`
1526
- },
1527
- {
1528
- moduleName: `./${schematic.name}Context.ts`,
1529
- name: `${schematic.name}Context`
1530
- }
1531
- );
1532
- data.currentFile.declarations.push(kformScaffolder.code`
1533
- declare global {
1534
- function render${schematic.name}App(): void;
1535
- }
1536
- globalThis.render${schematic.name}App = () => {
1537
- const root = document.getElementById("${kebabCase(schematic.name)}-app-root")!;
1538
- const externalContexts = decode${schematic.name}ExternalContextsFromString(
1539
- root.dataset.externalContexts!,
1540
- );
1541
-
1542
- createRoot(root).render(
1543
- <StrictMode>
1544
- <${schematic.name}Context.Provider value={{ externalContexts }}>
1545
- <RouterProvider router={router} />
1546
- </${schematic.name}Context.Provider>
1547
- </StrictMode>,
1548
- );
1549
- };
1550
- `);
1551
- }
1552
- function scaffoldRouteObject(schematic, data) {
1553
- const layout = reactAppLayout(schematic, data);
1554
- const formPages = layout.flatMap((annex) => annex.formPages);
1555
- data.currentFile.imports.push({
1556
- moduleName: `./${schematic.name}App.tsx`,
1557
- name: `${schematic.name}App`
1558
- });
1559
- for (const formPage of formPages) {
1560
- data.currentFile.imports.push({
1561
- moduleName: `./${kformScaffolder.joinPaths(
1562
- formPage.data.currentDir.slice(
1563
- data.currentDir.length + (data.currentDir.endsWith("/") ? 0 : 1)
1564
- ),
1565
- pascalCase(formPage.schematic.name)
1566
- )}.tsx`,
1567
- name: pascalCase(formPage.schematic.name)
1568
- });
1569
- }
1570
- const firstFormPage = formPages.find(
1571
- (formPage) => !formPage.schematic.nullable && !formPage.data.currentPath.split("/").includes("*")
1572
- );
1573
- const routes = [
1574
- firstFormPage && `{ path: "*", element: <${pascalCase(firstFormPage.schematic.name)} /> }`,
1575
- ...formPages.filter((formPage) => formPage !== firstFormPage).map(
1576
- (formPage) => `{ path: "${formPage.data.currentPath.split("/").map((f) => f === "*" ? ":id" : f).join(
1577
- "/"
1578
- )}", element: <${pascalCase(formPage.schematic.name)} /> }`
1579
- )
1580
- ];
1581
- return kformScaffolder.code`
1582
- {
1583
- element: <${schematic.name}App />,
1584
- children: [
1585
- ${routes.filter((r) => r).join(",\n")}
1586
- ]
1587
- }
1588
- `;
1589
- }
1590
- 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";
1591
- 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";
1592
- function scaffoldProjectMisc(_schematic, data) {
1593
- kformScaffolder.addTemplateFile(data, ".gitignore", gitignore);
1594
- kformScaffolder.addTemplateFile(data, ".editorconfig", editorconfig);
1595
- }
1596
- const responsesKt = 'package <%= filePackage %>\n\nimport kotlin.js.JsExport\nimport kotlin.jvm.JvmOverloads\nimport kotlinx.serialization.SerialName\nimport kotlinx.serialization.Serializable\nimport tech.ostack.kform.LocatedValidationIssue\n\n@JsExport\n@Serializable\nsealed interface <%= formClass %>SubmitResponse\n\n@JsExport\n@Serializable\n@SerialName("success")\nclass <%= formClass %>SubmitSuccess(val redirectTo: String) : <%= formClass %>SubmitResponse\n\n@JsExport\n@Serializable\n@SerialName("error")\nclass <%= formClass %>SubmitError @JvmOverloads constructor(override val message: String? = null) :\n Throwable(message), <%= formClass %>SubmitResponse\n\n@JsExport\n@Serializable\n@SerialName("validationError")\nclass <%= formClass %>SubmitValidationError(val issues: List<LocatedValidationIssue>) :\n <%= formClass %>SubmitResponse\n';
1597
- function scaffoldResponses(schematic, data) {
1598
- const ejsData = {
1599
- filePackage: data.currentPackage,
1600
- formClass: schematic.name
1601
- };
1602
- kformScaffolder.addEjsTemplateFile(
1603
- data,
1604
- `${schematic.name}Responses.kt`,
1605
- responsesKt,
1606
- ejsData
1607
- );
1608
- }
1609
- const jsonSerializerKt = "package <%= filePackage %>\n\nimport kotlin.js.JsExport\nimport kotlin.jvm.JvmOverloads\nimport kotlinx.serialization.json.Json\n\n/** Base JSON configuration. */\nprivate val JSON_CONFIG = Json.Default\n/** Pretty JSON configuration. */\nprivate val JSON_CONFIG_PRETTY = Json(JSON_CONFIG) { prettyPrint = true }\n\n/** JSON configuration. */\n@JvmOverloads\nfun jsonConfig(prettyPrint: Boolean = false): Json =\n if (prettyPrint) JSON_CONFIG_PRETTY else JSON_CONFIG\n\n/** Version of the serialization format. */\n@JsExport\nconst val <%= formConstant %>_SERIALIZATION_VERSION = 1\n\n@JsExport\n@JvmOverloads\nfun encode<%= formClass %>ToString(<%= formVar %>: <%= formClass %>, prettyPrint: Boolean = false): String =\n jsonConfig(prettyPrint).encodeToString(<%= formVar %>)\n\n@JsExport\nfun decode<%= formClass %>FromString(json: String): <%= formClass %> =\n jsonConfig().decodeFromString(json)\n\n@JvmOverloads\nfun encode<%= formClass %>ExternalContextsToString(externalContexts: <%= formClass %>ExternalContexts, prettyPrint: Boolean = false): String =\n jsonConfig(prettyPrint).encodeToString(externalContexts)\n\n@JsExport\nfun decode<%= formClass %>ExternalContextsFromString(json: String): <%= formClass %>ExternalContexts =\n jsonConfig().decodeFromString(json)\n\n@JvmOverloads\nfun encode<%= formClass %>SubmitResponseToString(response: <%= formClass %>SubmitResponse, prettyPrint: Boolean = false): String =\n jsonConfig(prettyPrint).encodeToString(response)\n\n@JsExport\nfun decode<%= formClass %>SubmitResponseFromString(json: String): <%= formClass %>SubmitResponse =\n jsonConfig().decodeFromString(json)\n";
1610
- const xmlSerializerKt = "package <%= filePackage %>\n\nimport kotlin.js.JsExport\nimport kotlin.jvm.JvmOverloads\nimport kotlinx.serialization.decodeFromString\nimport kotlinx.serialization.encodeToString\nimport nl.adaptivity.xmlutil.ExperimentalXmlUtilApi\nimport nl.adaptivity.xmlutil.QName\nimport nl.adaptivity.xmlutil.XMLConstants\nimport nl.adaptivity.xmlutil.core.XmlVersion\nimport nl.adaptivity.xmlutil.serialization.DefaultXmlSerializationPolicy\nimport nl.adaptivity.xmlutil.serialization.OutputKind\nimport nl.adaptivity.xmlutil.serialization.XML\nimport nl.adaptivity.xmlutil.serialization.XmlSerializationPolicy\nimport nl.adaptivity.xmlutil.serialization.structure.SafeParentInfo\n\n/** Base XML configuration. */\nprivate val XML_CONFIG = XML {\n recommended_0_91_0 {\n xmlVersion = XmlVersion.XML10\n autoPolymorphic = false\n encodeDefault = XmlSerializationPolicy.XmlEncodeDefault.NEVER\n }\n\n // Set policy on top of the current policy config\n @OptIn(ExperimentalXmlUtilApi::class)\n policy =\n object : DefaultXmlSerializationPolicy(policy) {\n // Serialize properties as elements instead of attributes by default\n override val defaultPrimitiveOutputKind: OutputKind = OutputKind.Element\n\n // Use property names as serial names by default\n override fun effectiveName(\n serializerParent: SafeParentInfo,\n tagParent: SafeParentInfo,\n outputKind: OutputKind,\n useName: XmlSerializationPolicy.DeclaredNameInfo,\n ): QName =\n useName.annotatedName\n ?: serializerParent.elementTypeDescriptor.typeQname\n ?: QName(\n if (outputKind == OutputKind.Element) tagParent.namespace.namespaceURI\n else XMLConstants.NULL_NS_URI,\n useName.serialName,\n )\n }\n}\n/** Pretty XML configuration. */\nprivate val XML_CONFIG_PRETTY = XML_CONFIG.copy { indent = 4 }\n\n/** XML configuration. */\n@JvmOverloads\nfun xmlConfig(prettyPrint: Boolean = false): XML =\n if (prettyPrint) XML_CONFIG_PRETTY else XML_CONFIG\n\n/** Version of the serialization format. */\n@JsExport\nconst val <%= formConstant %>_SERIALIZATION_VERSION = 1\n\n@JsExport\n@JvmOverloads\nfun encode<%= formClass %>ToString(<%= formVar %>: <%= formClass %>, prettyPrint: Boolean = false): String =\n xmlConfig(prettyPrint).encodeToString(<%= formVar %>)\n\n@JsExport\nfun decode<%= formClass %>FromString(xml: String): <%= formClass %> =\n xmlConfig().decodeFromString(xml)\n\n@JvmOverloads\nfun encode<%= formClass %>ExternalContextsToString(externalContexts: <%= formClass %>ExternalContexts, prettyPrint: Boolean = false): String =\n xmlConfig(prettyPrint).encodeToString(externalContexts)\n\n@JsExport\nfun decode<%= formClass %>ExternalContextsFromString(xml: String): <%= formClass %>ExternalContexts =\n xmlConfig().decodeFromString(xml)\n\n@JvmOverloads\nfun encode<%= formClass %>SubmitResponseToString(response: <%= formClass %>SubmitResponse, prettyPrint: Boolean = false): String =\n xmlConfig(prettyPrint).encodeToString(response)\n\n@JsExport\nfun decode<%= formClass %>SubmitResponseFromString(xml: String): <%= formClass %>SubmitResponse =\n xmlConfig().decodeFromString(xml)\n";
1611
- function scaffoldSerializer(schematic, data) {
1612
- const ejsData = {
1613
- filePackage: data.currentPackage,
1614
- formVar: camelCase(schematic.name),
1615
- formClass: schematic.name,
1616
- formConstant: constantCase(schematic.name)
1617
- };
1618
- kformScaffolder.addEjsTemplateFile(
1619
- data,
1620
- `${schematic.name}Serializer.kt`,
1621
- data.serializationFormat === "xml" ? xmlSerializerKt : jsonSerializerKt,
1622
- ejsData
1623
- );
1624
- }
1625
- const indexScss = '@use "@ostack.tech/ui/scss" as ostack-ui;\n@use "@ostack.tech/ui-kform/scss" as ostack-ui-kform;\n';
1626
- function scaffoldStyles(_schematic, data) {
1627
- kformScaffolder.addTemplateFile(data, "index.scss", indexScss);
1628
- }
1629
- 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["recommended-latest"],\n reactRefresh.configs.vite,\n ],\n languageOptions: {\n ecmaVersion: 2020,\n globals: globals.browser,\n },\n },\n]);\n';
1630
- 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';
1631
- 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';
1632
- 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';
1633
- 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';
1634
- const tsConfigJson = '{\n "files": [],\n "references": [\n { "path": "./tsconfig.app.json" },\n { "path": "./tsconfig.node.json" }\n ]\n}\n';
1635
- const tsConfigNodeJson = '{\n "compilerOptions": {\n "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",\n "target": "ES2023",\n "lib": ["ES2023"],\n "module": "ESNext",\n "types": ["node"],\n "skipLibCheck": true,\n\n /* Bundler mode */\n "moduleResolution": "bundler",\n "allowImportingTsExtensions": true,\n "verbatimModuleSyntax": true,\n "moduleDetection": "force",\n "noEmit": true,\n\n /* Linting */\n "strict": true,\n "noUnusedLocals": true,\n "noUnusedParameters": true,\n "erasableSyntaxOnly": true,\n "noFallthroughCasesInSwitch": true,\n "noUncheckedSideEffectImports": true\n },\n "include": ["vite.config.ts"]\n}\n';
1636
- const viteConfigTsEjs = 'import path from "node:path";\n\nimport react from "@vitejs/plugin-react-swc";\nimport { defineConfig } from "vite";\n\n// https://vite.dev/config/\nexport default defineConfig({\n plugins: [react()],\n build: {\n outDir: "build/dist",\n rollupOptions: {\n input: {\n "<%= formId %>-app":\n process.env.VITE_BUILD_REASON === "preview"\n ? "index.html"\n : "src/main.tsx",\n },\n output: {\n // Output files without hashes, making it easier to serve them in the\n // server. However, the server is expected to somehow "version" them for\n // cache busting purposes.\n entryFileNames: "assets/[name].js",\n chunkFileNames: "assets/[name].js",\n assetFileNames: "assets/[name].[ext]",\n },\n },\n },\n resolve: {\n alias: [\n // Due to how Kotlin "bundles" dependencies, we need to use the\n // `@ostack.tech/kform` produced by the shared module.\n {\n find: "@ostack.tech/kform",\n replacement: path.resolve(\n import.meta.dirname,\n "node_modules/<%= formId %>-shared/ostack-kform.mjs",\n ),\n },\n ],\n },\n server: {\n proxy: { "/api": "http://127.0.0.1:8080" },\n },\n});\n';
1637
- function scaffoldViteProject(schematic, data) {
1638
- const ejsData = {
1639
- formId: kebabCase(schematic.name),
1640
- formClass: schematic.name,
1641
- formTitle: capitalCase(schematic.name),
1642
- ostackUiVersion: "0.1.2",
1643
- kFormVersion: "0.31.0",
1644
- dependencyVersions: JSON.parse('{"@eslint/js":"^9.37.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.0","@ostack.tech/kform-react":"~0.31.0","@ostack.tech/kform-scaffolder":"~0.31.0","@storybook/addon-docs":"^9.1.10","@storybook/addon-links":"^9.1.10","@storybook/react-vite":"^9.1.10","@types/node":"^22.18.9","@types/react":"^19.2.2","@types/react-dom":"^19.2.1","@vitejs/plugin-react-swc":"^4.1.0","colorjs.io":"^0.5.2","cpy-cli":"^6.0.0","date-fns":"^4.1.0","eslint":"^9.37.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.4","eslint-plugin-react-hooks":"^6.1.1","eslint-plugin-react-refresh":"^0.4.23","eslint-plugin-simple-import-sort":"^12.1.1","eslint-plugin-storybook":"^9.1.10","globals":"^16.4.0","happy-dom":"^20.0.0","lint-staged":"^16.2.3","prettier":"^3.6.2","prettier-plugin-jsdoc":"^1.3.3","react":"^19.2.0","react-dom":"^19.2.0","react-router":"^7.9.4","react-router-dom":"^7.9.4","rimraf":"^6.0.1","sass-embedded":"^1.93.2","simple-git-hooks":"^2.13.1","storybook":"^9.1.10","tslib":"^2.8.1","typescript":"~5.9.3","typescript-eslint":"^8.46.0","vite":"^7.1.9","vitest":"^3.2.4","zustand":"^5.0.8"}'),
1645
- externalContextsData: data.serializationFormat === "json" ? "{}" : `<${schematic.name}ExternalContexts />`
1646
- };
1647
- kformScaffolder.addEjsTemplateFile(data, "react-app/package.json", packageJsonEjs, ejsData);
1648
- kformScaffolder.addEjsTemplateFile(
1649
- data,
1650
- "react-app/vite.config.ts",
1651
- viteConfigTsEjs,
1652
- ejsData
1653
- );
1654
- kformScaffolder.addTemplateFile(data, "react-app/tsconfig.json", tsConfigJson);
1655
- kformScaffolder.addTemplateFile(data, "react-app/tsconfig.app.json", tsConfigAppJson);
1656
- kformScaffolder.addTemplateFile(data, "react-app/tsconfig.node.json", tsConfigNodeJson);
1657
- kformScaffolder.addTemplateFile(data, "react-app/eslint.config.js", eslintConfigJs);
1658
- kformScaffolder.addEjsTemplateFile(data, "react-app/index.html", indexHtmlEjs, ejsData);
1659
- kformScaffolder.addTemplateFile(data, "react-app/public/vite.svg", viteSvg);
1660
- }
1661
- const kotlinMainData = {
1662
- currentDir: "shared/src/commonMain/kotlin"
1663
- };
1664
- const kotlinTestData = {
1665
- currentDir: "shared/src/commonTest/kotlin"
1666
- };
1667
- const reactAppData = {
1668
- currentDir: "react-app/src"
1669
- };
1670
- function SchematicBuilder({
1671
- name = "ostack-ui-kform",
1672
- schematicKinds = defaultSchematicKinds,
1673
- scaffolders = [
1674
- scaffoldProjectMisc,
1675
- scaffoldGradleWrapper,
1676
- scaffoldGradleProject,
1677
- scaffoldViteProject,
1678
- kformScaffolder.configScaffolder(kformScaffolder.scaffoldSchemas, kotlinMainData),
1679
- kformScaffolder.configScaffolder(kformScaffolder.scaffoldModels, kotlinMainData),
1680
- kformScaffolder.configScaffolder(scaffoldResponses, kotlinMainData),
1681
- kformScaffolder.configScaffolder(scaffoldExternalContexts, kotlinMainData),
1682
- kformScaffolder.configScaffolder(scaffoldSerializer, kotlinMainData),
1683
- kformScaffolder.configScaffolder(kformScaffolder.scaffoldValidator, kotlinTestData),
1684
- kformScaffolder.configScaffolder(scaffoldMain, reactAppData),
1685
- kformScaffolder.configScaffolder(scaffoldStyles, reactAppData),
1686
- kformScaffolder.configScaffolder(scaffoldAppComponent, reactAppData),
1687
- kformScaffolder.configScaffolder(scaffoldAppContext, reactAppData),
1688
- kformScaffolder.configScaffolder(scaffoldActions, reactAppData),
1689
- kformScaffolder.configScaffolder(scaffoldApi, reactAppData),
1690
- kformScaffolder.configScaffolder(scaffoldFormPages, reactAppData)
1691
- ],
1692
- scaffoldingData = (schematic) => ({
1693
- useFileBase64Serializer: true,
1694
- ...schematic.config
1695
- }),
1696
- configs = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1697
- /* @__PURE__ */ jsxRuntime.jsx(SerializationFormatConfig, {}),
1698
- /* @__PURE__ */ jsxRuntime.jsx(UseTableValuesSerializerConfig, {})
1699
- ] }),
1700
- ...otherProps
1701
- }) {
1702
- return /* @__PURE__ */ jsxRuntime.jsx(
1703
- kformScaffolder.SchematicBuilder,
1704
- {
1705
- name,
1706
- schematicKinds,
1707
- scaffolders,
1708
- scaffoldingData,
1709
- configs,
1710
- ...otherProps
1711
- }
1712
- );
1713
- }
1714
- exports.SchematicBuilder = SchematicBuilder;
1715
- exports.SerializationFormatConfig = SerializationFormatConfig;
1716
- exports.UseTableValuesSerializerConfig = UseTableValuesSerializerConfig;
1717
- exports.anySchematicKind = anySchematicKind;
1718
- exports.bigDecimalSchematicKind = bigDecimalSchematicKind;
1719
- exports.bigIntegerSchematicKind = bigIntegerSchematicKind;
1720
- exports.booleanSchematicKind = booleanSchematicKind;
1721
- exports.byteSchematicKind = byteSchematicKind;
1722
- exports.classAnnexSchematicKind = classAnnexSchematicKind;
1723
- exports.classFormPageSchematicKind = classFormPageSchematicKind;
1724
- exports.classSchematicKind = classSchematicKind;
1725
- exports.defaultSchematicKinds = defaultSchematicKinds;
1726
- exports.doubleSchematicKind = doubleSchematicKind;
1727
- exports.enumRadioGroupSchematicKind = enumRadioGroupSchematicKind;
1728
- exports.enumSchematicKind = enumSchematicKind;
1729
- exports.enumSelectSchematicKind = enumSelectSchematicKind;
1730
- exports.fileSchematicKind = fileSchematicKind;
1731
- exports.floatSchematicKind = floatSchematicKind;
1732
- exports.intSchematicKind = intSchematicKind;
1733
- exports.listCheckboxGroupSchematicKind = listCheckboxGroupSchematicKind;
1734
- exports.listSelectMultipleSchematicKind = listSelectMultipleSchematicKind;
1735
- exports.localDateSchematicKind = localDateSchematicKind;
1736
- exports.longSchematicKind = longSchematicKind;
1737
- exports.reactAppLayout = reactAppLayout;
1738
- exports.scaffoldActions = scaffoldActions;
1739
- exports.scaffoldAnnexesArray = scaffoldAnnexesArray;
1740
- exports.scaffoldApi = scaffoldApi;
1741
- exports.scaffoldAppComponent = scaffoldAppComponent;
1742
- exports.scaffoldAppContext = scaffoldAppContext;
1743
- exports.scaffoldExternalContexts = scaffoldExternalContexts;
1744
- exports.scaffoldField = scaffoldField;
1745
- exports.scaffoldFormPages = scaffoldFormPages;
1746
- exports.scaffoldFormPagesByAnnexObject = scaffoldFormPagesByAnnexObject;
1747
- exports.scaffoldGradleProject = scaffoldGradleProject;
1748
- exports.scaffoldGradleWrapper = scaffoldGradleWrapper;
1749
- exports.scaffoldIssueMessages = scaffoldIssueMessages;
1750
- exports.scaffoldMain = scaffoldMain;
1751
- exports.scaffoldProjectMisc = scaffoldProjectMisc;
1752
- exports.scaffoldResponses = scaffoldResponses;
1753
- exports.scaffoldRouteObject = scaffoldRouteObject;
1754
- exports.scaffoldSerializer = scaffoldSerializer;
1755
- exports.scaffoldStyles = scaffoldStyles;
1756
- exports.scaffoldViteProject = scaffoldViteProject;
1757
- exports.shortSchematicKind = shortSchematicKind;
1758
- exports.stringSchematicKind = stringSchematicKind;
1759
- exports.tableAnnexesSchematicKind = tableAnnexesSchematicKind;
1760
- exports.tableSchematicKind = tableSchematicKind;
1761
- //# sourceMappingURL=ostack-ui-kform-scaffolder.cjs.map