@bagelink/vue 1.14.13 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/dist/components/AddressSearch.vue.d.ts +6 -7
  2. package/dist/components/Alert.vue.d.ts.map +1 -1
  3. package/dist/components/Avatar.vue.d.ts.map +1 -1
  4. package/dist/components/Badge.vue.d.ts.map +1 -1
  5. package/dist/components/Btn.vue.d.ts +1 -1
  6. package/dist/components/Btn.vue.d.ts.map +1 -1
  7. package/dist/components/Card.vue.d.ts.map +1 -1
  8. package/dist/components/Carousel.vue.d.ts +0 -11
  9. package/dist/components/Dropdown.vue.d.ts +0 -2
  10. package/dist/components/Dropdown.vue.d.ts.map +1 -1
  11. package/dist/components/Filter.vue.d.ts +30 -0
  12. package/dist/components/Filter.vue.d.ts.map +1 -0
  13. package/dist/components/FilterQuery.vue.d.ts +8 -3
  14. package/dist/components/Image.vue.d.ts.map +1 -1
  15. package/dist/components/ImportData.vue.d.ts.map +1 -1
  16. package/dist/components/ListItem.vue.d.ts.map +1 -1
  17. package/dist/components/MapEmbed/Index.vue.d.ts.map +1 -1
  18. package/dist/components/Modal.vue.d.ts +0 -1
  19. package/dist/components/Pagination.vue.d.ts.map +1 -1
  20. package/dist/components/Pill.vue.d.ts.map +1 -1
  21. package/dist/components/QueryFilter.vue.d.ts +30 -0
  22. package/dist/components/QueryFilter.vue.d.ts.map +1 -0
  23. package/dist/components/Swiper.vue.d.ts +6 -12
  24. package/dist/components/Swiper.vue.d.ts.map +1 -1
  25. package/dist/components/Toast.vue.d.ts.map +1 -1
  26. package/dist/components/analytics/PieChart.vue.d.ts +2 -2
  27. package/dist/components/calendar/CalendarPopover.vue.d.ts +8 -4
  28. package/dist/components/calendar/CalendarPopover.vue.d.ts.map +1 -1
  29. package/dist/components/calendar/CalendarTypes.d.ts +0 -10
  30. package/dist/components/calendar/Index.vue.d.ts +4 -20
  31. package/dist/components/calendar/views/WeekView.vue.d.ts +1 -9
  32. package/dist/components/dataTable/DataTable.vue.d.ts.map +1 -1
  33. package/dist/components/form/index.d.ts.map +1 -1
  34. package/dist/components/form/inputs/ArrayInput.vue.d.ts +2 -4
  35. package/dist/components/form/inputs/CheckInput.vue.d.ts +1 -2
  36. package/dist/components/form/inputs/Checkbox.vue.d.ts.map +1 -1
  37. package/dist/components/form/inputs/CodeEditor/Index.vue.d.ts +0 -54
  38. package/dist/components/form/inputs/ColorInput.vue.d.ts +1 -3
  39. package/dist/components/form/inputs/DateInput.vue.d.ts +1 -2
  40. package/dist/components/form/inputs/DatePicker.vue.d.ts +0 -1
  41. package/dist/components/form/inputs/EmailInput.vue.d.ts +2 -5
  42. package/dist/components/form/inputs/JSONInput.vue.d.ts +1 -2
  43. package/dist/components/form/inputs/MarkdownEditor.vue.d.ts +2 -7
  44. package/dist/components/form/inputs/NumberInput.vue.d.ts +1 -2
  45. package/dist/components/form/inputs/OTP.vue.d.ts +1 -2
  46. package/dist/components/form/inputs/PasswordInput.vue.d.ts +10 -16
  47. package/dist/components/form/inputs/RadioGroup.vue.d.ts +1 -3
  48. package/dist/components/form/inputs/RangeInput.vue.d.ts +1 -6
  49. package/dist/components/form/inputs/RichText/index.vue.d.ts +1 -2
  50. package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
  51. package/dist/components/form/inputs/RichText/utils/media.d.ts.map +1 -1
  52. package/dist/components/form/inputs/SelectBtn.vue.d.ts +2 -2
  53. package/dist/components/form/inputs/SelectInput.vue.d.ts +13 -20
  54. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  55. package/dist/components/form/inputs/SignaturePad.vue.d.ts +1 -6
  56. package/dist/components/form/inputs/TableField.vue.d.ts +1 -2
  57. package/dist/components/form/inputs/TelInput.vue.d.ts +1 -2
  58. package/dist/components/form/inputs/TextInput.vue.d.ts +2 -3
  59. package/dist/components/form/inputs/ToggleInput.vue.d.ts +1 -2
  60. package/dist/components/form/inputs/Upload/UploadInput.vue.d.ts +6 -27
  61. package/dist/components/form/inputs/Upload/upload.d.ts +1 -1
  62. package/dist/components/form/inputs/index.d.ts +0 -1
  63. package/dist/components/index.d.ts +1 -3
  64. package/dist/components/index.d.ts.map +1 -1
  65. package/dist/components/layout/AppContent.vue.d.ts +1 -1
  66. package/dist/components/layout/AppContent.vue.d.ts.map +1 -1
  67. package/dist/components/layout/AppLayout.vue.d.ts +0 -2
  68. package/dist/components/layout/AppLayout.vue.d.ts.map +1 -1
  69. package/dist/components/layout/AppSidebar.vue.d.ts +1 -5
  70. package/dist/components/layout/AppSidebar.vue.d.ts.map +1 -1
  71. package/dist/components/layout/Panel.vue.d.ts.map +1 -1
  72. package/dist/components/layout/Resizable.vue.d.ts.map +1 -1
  73. package/dist/components/layout/Skeleton.vue.d.ts.map +1 -1
  74. package/dist/components/layout/TabsNav.vue.d.ts +1 -12
  75. package/dist/components/layout/TabsNav.vue.d.ts.map +1 -1
  76. package/dist/components/layout/appLayoutContext.d.ts +24 -0
  77. package/dist/components/layout/appLayoutContext.d.ts.map +1 -0
  78. package/dist/components/layout/index.d.ts.map +1 -1
  79. package/dist/components/lightbox/Lightbox.vue.d.ts.map +1 -1
  80. package/dist/composables/index.d.ts.map +1 -1
  81. package/dist/composables/useDevice.d.ts.map +1 -1
  82. package/dist/composables/useEscapeKey.d.ts +12 -0
  83. package/dist/composables/useEscapeKey.d.ts.map +1 -0
  84. package/dist/composables/useSchemaField.d.ts.map +1 -1
  85. package/dist/composables/useTheme.d.ts.map +1 -1
  86. package/dist/dialog/Dialog.vue.d.ts.map +1 -1
  87. package/dist/dialog/DialogConfirm.vue.d.ts.map +1 -1
  88. package/dist/form-flow/FormFlow.vue.d.ts.map +1 -1
  89. package/dist/form-flow/MultiStepForm.vue.d.ts +1 -6
  90. package/dist/form-flow/form-flow.d.ts +1 -24
  91. package/dist/form-flow/form-flow.d.ts.map +1 -1
  92. package/dist/i18n/index.d.ts +0 -838
  93. package/dist/index.cjs +245 -222
  94. package/dist/index.d.ts +0 -2
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.mjs +42201 -51162
  97. package/dist/plugins/bagel.d.ts.map +1 -1
  98. package/dist/style.css +1 -2
  99. package/dist/types/BagelForm.d.ts +1 -10
  100. package/dist/types/BagelForm.d.ts.map +1 -1
  101. package/dist/types/BtnOptions.d.ts.map +1 -1
  102. package/dist/types/NavLink.d.ts +1 -2
  103. package/dist/types/TableSchema.d.ts.map +1 -1
  104. package/dist/types/index.d.ts +1 -2
  105. package/dist/types/index.d.ts.map +1 -1
  106. package/dist/utils/BagelFormUtils.d.ts +0 -1
  107. package/dist/utils/calendar/dateUtils.d.ts +2 -2
  108. package/dist/utils/calendar/dateUtils.d.ts.map +1 -1
  109. package/dist/utils/constants.d.ts.map +1 -1
  110. package/dist/utils/date.d.ts +116 -0
  111. package/dist/utils/date.d.ts.map +1 -0
  112. package/dist/utils/fetch.d.ts +29 -0
  113. package/dist/utils/fetch.d.ts.map +1 -0
  114. package/dist/utils/index.d.ts +1 -1
  115. package/dist/utils/index.d.ts.map +1 -1
  116. package/dist/utils/string.d.ts +7 -0
  117. package/dist/utils/string.d.ts.map +1 -0
  118. package/dist/utils/useSearch.d.ts +1 -1
  119. package/package.json +3 -10
  120. package/src/components/AccordionItem.vue +5 -5
  121. package/src/components/Alert.vue +37 -16
  122. package/src/components/Avatar.vue +2 -1
  123. package/src/components/Badge.vue +145 -22
  124. package/src/components/BglVideo.vue +4 -4
  125. package/src/components/Btn.vue +81 -69
  126. package/src/components/Card.vue +7 -6
  127. package/src/components/Dropdown.vue +7 -14
  128. package/src/components/FieldSetVue.vue +2 -2
  129. package/src/components/FilterQuery.vue +3 -3
  130. package/src/components/Image.vue +5 -3
  131. package/src/components/JSONSchema.vue +4 -4
  132. package/src/components/JsonBuilder.vue +3 -3
  133. package/src/components/ListItem.vue +2 -4
  134. package/src/components/MapEmbed/Index.vue +18 -17
  135. package/src/components/NavBar.vue +2 -2
  136. package/src/components/Spreadsheet/Index.vue +4 -4
  137. package/src/components/Spreadsheet/SpreadsheetTable.vue +10 -10
  138. package/src/components/Swiper.vue +3 -1
  139. package/src/components/Toast.vue +57 -36
  140. package/src/components/calendar/CalendarPopover.vue +1 -1
  141. package/src/components/calendar/Index.vue +5 -5
  142. package/src/components/calendar/views/AgendaView.vue +2 -2
  143. package/src/components/calendar/views/DayView.vue +1 -1
  144. package/src/components/calendar/views/MonthView.vue +8 -8
  145. package/src/components/dataTable/DataTable.vue +68 -10
  146. package/src/components/form/index.ts +0 -4
  147. package/src/components/form/inputs/ArrayInput.vue +1 -1
  148. package/src/components/form/inputs/CheckInput.vue +6 -6
  149. package/src/components/form/inputs/Checkbox.vue +5 -4
  150. package/src/components/form/inputs/CodeEditor/Index.vue +1 -1
  151. package/src/components/form/inputs/ColorInput.vue +5 -5
  152. package/src/components/form/inputs/DatePicker.vue +3 -3
  153. package/src/components/form/inputs/EmailInput.vue +15 -15
  154. package/src/components/form/inputs/NumberInput.vue +11 -11
  155. package/src/components/form/inputs/OTP.vue +4 -4
  156. package/src/components/form/inputs/PasswordInput.vue +3 -3
  157. package/src/components/form/inputs/RadioGroup.vue +1 -1
  158. package/src/components/form/inputs/RichText/editor.css +4 -4
  159. package/src/components/form/inputs/RichText/index.vue +39 -39
  160. package/src/components/form/inputs/RichText/utils/media.ts +1 -92
  161. package/src/components/form/inputs/RichText/utils/table.ts +4 -4
  162. package/src/components/form/inputs/SelectBtn.vue +1 -1
  163. package/src/components/form/inputs/SelectInput.vue +16 -16
  164. package/src/components/form/inputs/SignaturePad.vue +6 -6
  165. package/src/components/form/inputs/TableField.vue +7 -7
  166. package/src/components/form/inputs/TelInput.vue +12 -12
  167. package/src/components/form/inputs/TextInput.vue +11 -11
  168. package/src/components/form/inputs/ToggleInput.vue +11 -11
  169. package/src/components/form/inputs/Upload/upload.css +16 -16
  170. package/src/components/index.ts +2 -9
  171. package/src/components/layout/AppContent.vue +5 -19
  172. package/src/components/layout/AppLayout.vue +47 -18
  173. package/src/components/layout/AppSidebar.vue +19 -36
  174. package/src/components/layout/BottomMenu.vue +1 -1
  175. package/src/components/layout/Resizable.vue +5 -2
  176. package/src/components/layout/Skeleton.vue +5 -4
  177. package/src/components/layout/TabsNav.vue +23 -23
  178. package/src/components/layout/appLayoutContext.ts +44 -0
  179. package/src/components/layout/index.ts +2 -0
  180. package/src/components/lightbox/Lightbox.vue +3 -9
  181. package/src/composables/index.ts +1 -0
  182. package/src/composables/useDevice.ts +2 -1
  183. package/src/composables/useEscapeKey.ts +56 -0
  184. package/src/composables/useSchemaField.ts +2 -17
  185. package/src/composables/useTheme.ts +23 -19
  186. package/src/form-flow/FormFlow.vue +2 -0
  187. package/src/form-flow/form-flow.ts +7 -0
  188. package/src/index.ts +0 -3
  189. package/src/plugins/bagel.ts +0 -15
  190. package/src/styles/app-layout.css +231 -0
  191. package/src/styles/appearance.css +179 -21
  192. package/src/styles/bagel.css +103 -97
  193. package/src/styles/buttons.css +8 -8
  194. package/src/styles/colors.css +0 -103
  195. package/src/styles/dark.css +25 -26
  196. package/src/styles/input-variants.css +11 -11
  197. package/src/styles/inputs.css +44 -61
  198. package/src/styles/layout.css +445 -1258
  199. package/src/styles/loginCard.css +1 -1
  200. package/src/styles/mobilLayout.css +153 -28
  201. package/src/styles/text.css +500 -1508
  202. package/src/styles/theme.css +199 -435
  203. package/src/styles/transitions.css +4 -4
  204. package/src/types/BagelForm.ts +46 -151
  205. package/src/types/BtnOptions.ts +5 -3
  206. package/src/types/TableSchema.ts +1 -0
  207. package/src/types/index.ts +0 -5
  208. package/src/utils/calendar/dateUtils.ts +2 -3
  209. package/src/utils/constants.ts +7 -0
  210. package/src/utils/date.ts +482 -0
  211. package/src/utils/fetch.ts +128 -0
  212. package/src/utils/index.ts +54 -3
  213. package/src/utils/sizeParsing.ts +5 -5
  214. package/src/utils/string.ts +56 -0
  215. package/vite.config.ts +5 -1
  216. package/bin/generateFormSchema.ts +0 -1035
  217. package/bin/utils.ts +0 -223
  218. package/src/components/Carousel.vue +0 -724
  219. package/src/components/ImportData.vue +0 -1749
  220. package/src/components/Modal.vue +0 -184
  221. package/src/components/ModalConfirm.vue +0 -42
  222. package/src/components/ModalForm.vue +0 -102
  223. package/src/components/Pill.vue +0 -149
  224. package/src/components/Slider.vue +0 -1446
  225. package/src/components/Title.vue +0 -23
  226. package/src/components/ToolBar.vue +0 -9
  227. package/src/components/form/BagelForm.vue +0 -219
  228. package/src/components/form/BglFieldSet.vue +0 -14
  229. package/src/components/form/BglMultiStepForm.vue +0 -469
  230. package/src/components/form/FieldArray.vue +0 -422
  231. package/src/components/form/useBagelFormState.ts +0 -76
  232. package/src/composables/useFormField.ts +0 -38
  233. package/src/dialog/DialogOLD.vue +0 -358
  234. package/src/plugins/modalTypes.ts +0 -61
  235. package/src/plugins/useModal.ts +0 -225
  236. package/src/styles/modal.css +0 -120
  237. package/src/styles/pillColors.css +0 -0
  238. package/src/utils/BagelFormUtils.ts +0 -684
@@ -1,1035 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import type {
4
- OpenAPIObject,
5
- SchemaObject,
6
- ReferenceObject,
7
- } from '@bagelink/sdk'
8
- import type {
9
- ArrayBagelField,
10
- ArrayFieldVal,
11
- BaseBagelField,
12
- BglFormSchemaT,
13
- Path,
14
- TextInputOptions,
15
- } from '@bagelink/vue'
16
- import type { InputTypeHTMLAttribute } from 'vue'
17
- import { existsSync, mkdirSync } from 'node:fs'
18
- import path from 'node:path'
19
- import { argv, cwd, exit } from 'node:process'
20
- import { isSchemaObject, isReferenceObject } from '@bagelink/sdk'
21
- import { formatDate, useForm } from '@bagelink/vue'
22
- import axios from 'axios'
23
- import { toValue } from 'vue'
24
- import {
25
- formatAndWriteCode,
26
- runEsLintOnDir,
27
- parseConfig,
28
- validateConfig,
29
- printHelp,
30
- } from './utils'
31
-
32
- // =============================================================================
33
- // FORM UTILITIES (TOP-LEVEL SCOPE)
34
- // =============================================================================
35
-
36
- const {
37
- txtField,
38
- emailField,
39
- dateField,
40
- selectField,
41
- telField,
42
- numField,
43
- arrField,
44
- checkField,
45
- } = useForm()
46
-
47
- // =============================================================================
48
- // TYPES & INTERFACES
49
- // =============================================================================
50
-
51
- interface FieldOptions {
52
- readonly helptext?: string
53
- readonly required: boolean
54
- }
55
-
56
- interface GeneratorConfig {
57
- readonly genSchemaId: string
58
- readonly output: string
59
- readonly url: string
60
- readonly useUtilityFunctions?: boolean
61
- readonly useTableSchema?: boolean
62
- readonly verbose?: boolean
63
- }
64
-
65
- interface SchemaContext {
66
- readonly openApiSchema: OpenAPIObject
67
- }
68
-
69
- type FormSchema<T> = BglFormSchemaT<T>
70
- let USING_FMT_DATE = false
71
- let USING_VERBOSE_FLAG = false
72
-
73
- function logVerbose(...args: any[]): void {
74
- if (USING_VERBOSE_FLAG) {
75
- console.log('🔍', ...args)
76
- }
77
- }
78
-
79
- // =============================================================================
80
- // CONFIGURATION
81
- // =============================================================================
82
-
83
- function parseConfiguration(): GeneratorConfig {
84
- const config = parseConfig({
85
- schemaId: undefined,
86
- defaultOutputFile: 'src/generated/exampleFormSchema.ts',
87
- allowedFlags: ['utility-functions', 'table-schema', 'help', 'verbose'],
88
- })
89
-
90
- if (argv.includes('--help') || argv.includes('-h')) {
91
- printHelp('generateFormSchema')
92
- exit(0)
93
- }
94
-
95
- try {
96
- validateConfig(config, ['baseUrl', 'schemaId'])
97
- } catch (error: any) {
98
- console.error('❌', error?.message)
99
- exit(1)
100
- }
101
-
102
- USING_VERBOSE_FLAG = config.verbose || false
103
-
104
- return {
105
- genSchemaId: config.schemaId || '',
106
- output: config.outputFile || 'src/generated/exampleFormSchema.ts',
107
- url: `${config.baseUrl}/openapi.json`,
108
- useUtilityFunctions: config.useUtilityFunctions,
109
- useTableSchema: config.useTableSchema,
110
- } as const
111
- }
112
-
113
- // =============================================================================
114
- // SCHEMA UTILITIES
115
- // =============================================================================
116
-
117
- function resolveSchemaReference(
118
- schemaOrRef: SchemaObject | ReferenceObject,
119
- openApiSchema: OpenAPIObject,
120
- visitedRefs = new Set<string>()
121
- ): SchemaObject | undefined {
122
- if (!isReferenceObject(schemaOrRef)) {
123
- return isSchemaObject(schemaOrRef) ? schemaOrRef : undefined
124
- }
125
-
126
- const refPath = schemaOrRef.$ref
127
- if (visitedRefs.has(refPath)) {
128
- logVerbose(`Circular reference detected: ${refPath}`)
129
- return undefined
130
- }
131
-
132
- const refName = refPath.split('/').pop()
133
- if (!refName || !openApiSchema.components?.schemas?.[refName]) {
134
- logVerbose(`Could not resolve reference: ${refPath}`)
135
- return undefined
136
- }
137
-
138
- const resolvedSchema = openApiSchema.components.schemas[refName]
139
- if (isReferenceObject(resolvedSchema)) {
140
- visitedRefs.add(refPath)
141
- return resolveSchemaReference(resolvedSchema, openApiSchema, visitedRefs)
142
- }
143
-
144
- return isSchemaObject(resolvedSchema) ? resolvedSchema : undefined
145
- }
146
-
147
- function getSchemaById(
148
- schemaId: string,
149
- openApiSchema: OpenAPIObject
150
- ): SchemaObject | undefined {
151
- const schemaOrRef = openApiSchema.components?.schemas?.[schemaId]
152
- return schemaOrRef
153
- ? resolveSchemaReference(schemaOrRef, openApiSchema)
154
- : undefined
155
- }
156
-
157
- /**
158
- * Resolves a schema reference and returns the actual schema object
159
- */
160
- function resolveFieldSchema(
161
- fieldSchema: SchemaObject | ReferenceObject,
162
- openApiSchema: OpenAPIObject
163
- ): SchemaObject | undefined {
164
- if (isReferenceObject(fieldSchema)) {
165
- return resolveSchemaReference(fieldSchema, openApiSchema)
166
- }
167
- return isSchemaObject(fieldSchema) ? fieldSchema : undefined
168
- }
169
-
170
- /**
171
- * Gets the property schema for a nested field path
172
- */
173
- function getNestedPropertySchema(
174
- fieldPath: string[],
175
- targetSchema: SchemaObject,
176
- openApiSchema: OpenAPIObject
177
- ): SchemaObject | undefined {
178
- if (fieldPath.length === 0) { return targetSchema }
179
-
180
- const [currentProp, ...remainingPath] = fieldPath
181
- const currentProperty = targetSchema.properties?.[currentProp]
182
-
183
- if (!currentProperty) {
184
- logVerbose(`Property '${currentProp}' not found in schema`)
185
- return undefined
186
- }
187
-
188
- const resolvedProperty = resolveFieldSchema(
189
- currentProperty,
190
- openApiSchema
191
- )
192
- if (!resolvedProperty) {
193
- logVerbose(`Could not resolve property '${currentProp}'`)
194
- return undefined
195
- }
196
-
197
- // If there are more path segments, continue resolving
198
- if (remainingPath.length > 0) {
199
- if (resolvedProperty.type === 'object' && resolvedProperty.properties) {
200
- return getNestedPropertySchema(
201
- remainingPath,
202
- resolvedProperty,
203
- openApiSchema
204
- )
205
- }
206
- logVerbose(
207
- `Cannot resolve nested path beyond '${currentProp}' - not an object type`
208
- )
209
- return undefined
210
- }
211
-
212
- return resolvedProperty
213
- }
214
-
215
- // =============================================================================
216
- // STRING FORMATTING
217
- // =============================================================================
218
-
219
- function formatPropertyName(name: string): string {
220
- return name
221
- .replace(/([A-Z])/g, ' $1')
222
- .replace(/_/g, ' ')
223
- .replace(/^\w/, c => c.toUpperCase())
224
- .trim()
225
- }
226
-
227
- function formatTypeName(name: string): string {
228
- return name
229
- .replace(/_([a-z])/g, (_, letter: string) => letter.toUpperCase())
230
- .replace(/^\w/, c => c.toUpperCase())
231
- .replace(/\s+(\w)/g, (_, letter: string) => letter.toUpperCase())
232
- }
233
-
234
- function getHtmlInputType(format?: string): string | undefined {
235
- const formatMap: Record<string, string> = {
236
- 'date': 'date',
237
- 'date-time': 'datetime-local',
238
- 'email': 'email',
239
- 'phone': 'tel',
240
- 'password': 'password',
241
- 'binary': 'file',
242
- 'uri': 'url',
243
- 'double': 'number',
244
- 'float': 'number',
245
- 'int32': 'number',
246
- 'int64': 'number',
247
- }
248
-
249
- return format ? formatMap[format] : undefined
250
- }
251
-
252
- // =============================================================================
253
- // FIELD CREATION
254
- // =============================================================================
255
-
256
- function createStringField<T>(
257
- propName: Path<T>,
258
- schema: SchemaObject,
259
- options: FieldOptions
260
- ): BaseBagelField<T, Path<T>> {
261
- const label = formatPropertyName(propName as string)
262
-
263
- // Email fields
264
- if (schema.format === 'email') {
265
- return emailField(propName, label, {
266
- required: options.required,
267
- placeholder: options.helptext,
268
- })
269
- }
270
-
271
- // Date fields
272
- if (schema.format === 'date' || schema.format === 'date-time') {
273
- return dateField(propName, label, {
274
- required: options.required,
275
- placeholder: options.helptext,
276
- enableTime: schema.format === 'date-time',
277
- })
278
- }
279
-
280
- // Phone fields
281
- if (schema.format === 'phone') {
282
- return telField(propName, label, {
283
- required: options.required,
284
- placeholder: options.helptext,
285
- })
286
- }
287
-
288
- // Enum fields as select
289
- if (schema.enum?.length) {
290
- const selectOptions = schema.enum.map(value => ({
291
- label: String(value)
292
- .replace(/_/g, ' ')
293
- .replace(/\b\w/g, l => l.toUpperCase()),
294
- value,
295
- }))
296
- return selectField(propName, label, selectOptions, {
297
- required: options.required,
298
- placeholder: options.helptext,
299
- })
300
- }
301
-
302
- // Default text field
303
- const textOptions: TextInputOptions<T, Path<T>> = {
304
- required: options.required,
305
- helptext: options.helptext,
306
- multiline: (schema.maxLength ?? 0) > 255,
307
- pattern: schema.pattern,
308
- type: getHtmlInputType(schema.format) as InputTypeHTMLAttribute,
309
- }
310
-
311
- return txtField(propName, label, textOptions)
312
- }
313
-
314
- function createNumberField<T>(
315
- propName: Path<T>,
316
- schema: SchemaObject,
317
- options: FieldOptions
318
- ): BaseBagelField<T, Path<T>> {
319
- return numField(
320
- propName,
321
- formatPropertyName(propName as string),
322
- {
323
- required: options.required,
324
- placeholder: options.helptext,
325
- min: schema.minimum,
326
- max: schema.maximum,
327
- step: schema.type === 'integer' ? 1 : undefined,
328
- }
329
- )
330
- }
331
-
332
- function createBooleanField<T>(
333
- propName: Path<T>,
334
- options: FieldOptions
335
- ): BaseBagelField<T, Path<T>> {
336
- return checkField(propName, formatPropertyName(propName as string), {
337
- required: options.required,
338
- })
339
- }
340
-
341
- function createArrayField<T>(
342
- propName: Path<T>,
343
- schema: SchemaObject,
344
- options: FieldOptions,
345
- schemaType: string,
346
- context: SchemaContext
347
- ): BaseBagelField<T, Path<T>> {
348
- if (!schema.items) {
349
- logVerbose(`Array field '${propName as string}' has no items schema`)
350
- return createFallbackField(propName, options)
351
- }
352
-
353
- const itemsSchema = resolveSchemaReference(
354
- schema.items,
355
- context.openApiSchema
356
- )
357
- if (!itemsSchema) {
358
- logVerbose(
359
- `Array field '${propName as string}' has unresolvable items schema`
360
- )
361
- return createFallbackField(propName, options)
362
- }
363
-
364
- // Object array
365
- if (itemsSchema.type === 'object' && itemsSchema.properties) {
366
- const nestedSchema = convertSchemaToForm(
367
- itemsSchema,
368
- `${schemaType}Item`,
369
- context
370
- ) as FormSchema<ArrayFieldVal<T, Path<T>>>
371
-
372
- return arrField(
373
- propName,
374
- formatPropertyName(propName as string),
375
- nestedSchema
376
- )
377
- }
378
-
379
- // Primitive array
380
- const arrayType
381
- = itemsSchema.type === 'number' || itemsSchema.type === 'integer'
382
- ? 'number'
383
- : 'text'
384
- return arrField(
385
- propName,
386
- formatPropertyName(propName as string),
387
- arrayType
388
- )
389
- }
390
-
391
- function createFallbackField<T>(
392
- propName: Path<T>,
393
- options: FieldOptions
394
- ): BaseBagelField<T, Path<T>> {
395
- return txtField(
396
- propName,
397
- formatPropertyName(propName as string),
398
- {
399
- required: options.required,
400
- placeholder: options.helptext,
401
- }
402
- )
403
- }
404
-
405
- function createFieldByType<T>(
406
- propName: Path<T>,
407
- schema: SchemaObject,
408
- options: FieldOptions,
409
- schemaType: string,
410
- context: SchemaContext
411
- ): BaseBagelField<T, Path<T>> | null {
412
- // Handle nullable union types
413
- const actualSchema = getNonNullSchema(schema) || schema
414
-
415
- switch (actualSchema.type) {
416
- case 'string':
417
- return createStringField(propName, actualSchema, options)
418
- case 'number':
419
- case 'integer':
420
- return createNumberField(propName, actualSchema, options)
421
- case 'boolean':
422
- return createBooleanField(propName, options)
423
- case 'array':
424
- return createArrayField(
425
- propName,
426
- actualSchema,
427
- options,
428
- schemaType,
429
- context
430
- )
431
- case 'object':
432
- return null // Will be handled separately for flattening
433
- default:
434
- logVerbose(
435
- `Unknown type '${actualSchema.type}' for field '${propName as string}', using fallback`
436
- )
437
- return createFallbackField(propName, options)
438
- }
439
- }
440
-
441
- function getNonNullSchema(schema: SchemaObject): SchemaObject | undefined {
442
- // Handle anyOf union types
443
- if (schema.anyOf && Array.isArray(schema.anyOf)) {
444
- const nonNullSchema = schema.anyOf.find((subSchema) => {
445
- if (isReferenceObject(subSchema)) {
446
- // We'd need to resolve this, but for simplicity, assume it's not null
447
- return true
448
- }
449
- return subSchema.type !== 'null'
450
- })
451
-
452
- return nonNullSchema && !isReferenceObject(nonNullSchema)
453
- ? nonNullSchema
454
- : undefined
455
- }
456
-
457
- // Handle oneOf union types
458
- if (schema.oneOf && Array.isArray(schema.oneOf)) {
459
- const nonNullSchema = schema.oneOf.find((subSchema) => {
460
- if (isReferenceObject(subSchema)) {
461
- return true
462
- }
463
- return subSchema.type !== 'null'
464
- })
465
-
466
- return nonNullSchema && !isReferenceObject(nonNullSchema)
467
- ? nonNullSchema
468
- : undefined
469
- }
470
-
471
- return undefined
472
- }
473
-
474
- function processObjectField<T>(
475
- propName: Path<T>,
476
- schema: SchemaObject,
477
- schemaType: string,
478
- formSchema: FormSchema<T>,
479
- context: SchemaContext
480
- ): void {
481
- if (!schema.properties || Object.keys(schema.properties).length === 0) { return }
482
-
483
- logVerbose(`Creating nested fields for object: ${propName as string}`)
484
- const nestedSchema = convertSchemaToForm(
485
- schema,
486
- `${schemaType}${formatTypeName(propName as string)}`,
487
- context
488
- )
489
-
490
- // Flatten nested fields with proper namespacing
491
- nestedSchema.forEach((subField) => {
492
- if (!subField.id) { return }
493
-
494
- const nestedField = {
495
- ...subField,
496
- id: `${propName as string}.${subField.id}` as Path<T>,
497
- }
498
- formSchema.push(nestedField as FormSchema<T>[number])
499
- logVerbose(`Added nested field: ${propName as string}.${subField.id}`)
500
- })
501
- }
502
-
503
- // =============================================================================
504
- // SCHEMA CONVERSION
505
- // =============================================================================
506
-
507
- function convertSchemaToForm<T = Record<string, unknown>>(
508
- schema: SchemaObject,
509
- schemaType: string,
510
- context: SchemaContext
511
- ): FormSchema<T> {
512
- const propertyKeys = Object.keys(schema.properties ?? {})
513
- logVerbose(`Processing schema for ${schemaType}:`, propertyKeys)
514
-
515
- if (!schema.properties) {
516
- logVerbose('Schema has no properties')
517
- return []
518
- }
519
-
520
- const formSchema: FormSchema<T> = []
521
- const requiredFields = Array.isArray(schema.required) ? schema.required : []
522
-
523
- Object.entries(schema.properties).forEach(([propName, propSchemaOrRef]) => {
524
- const resolvedPropSchema = resolveSchemaReference(
525
- propSchemaOrRef,
526
- context.openApiSchema
527
- )
528
- if (!resolvedPropSchema) {
529
- logVerbose(`Skipping unresolvable property: ${propName}`)
530
- return
531
- }
532
-
533
- const fieldOptions: FieldOptions = {
534
- required: requiredFields.includes(propName),
535
- helptext: resolvedPropSchema.description,
536
- }
537
-
538
- logVerbose(
539
- `Processing field: ${propName}, type: ${resolvedPropSchema.type ?? 'undefined'}, format: ${resolvedPropSchema.format ?? 'undefined'}`
540
- )
541
-
542
- // Handle object fields by flattening
543
- if (resolvedPropSchema.type === 'object') {
544
- processObjectField(
545
- propName as Path<T>,
546
- resolvedPropSchema,
547
- schemaType,
548
- formSchema,
549
- context
550
- )
551
- return
552
- }
553
-
554
- const field = createFieldByType(
555
- propName as Path<T>,
556
- resolvedPropSchema,
557
- fieldOptions,
558
- schemaType,
559
- context
560
- )
561
- if (!field) { return }
562
-
563
- // Apply default value if specified
564
- if (resolvedPropSchema.default !== undefined) {
565
- field.defaultValue = resolvedPropSchema.default
566
- }
567
-
568
- formSchema.push(field as FormSchema<T>[number])
569
- logVerbose(`Added field: ${propName} with $el: ${field.$el}`)
570
- })
571
-
572
- logVerbose(`Generated ${formSchema.length} fields for ${schemaType}`)
573
- return formSchema
574
- }
575
-
576
- async function fetchOpenApiSchema(url: string): Promise<OpenAPIObject> {
577
- try {
578
- const basicAuthHeader = {
579
- Authorization: 'Basic YmFnZWxfdXNlcm5hbWU6Tm90U2VjdXJlQGJhZ2Vs',
580
- }
581
- const { data } = await axios.get<OpenAPIObject>(url, {
582
- headers: basicAuthHeader,
583
- timeout: 10000,
584
- })
585
- return data
586
- } catch (error) {
587
- console.error('🚨 Failed to fetch OpenAPI schema:', error)
588
- const message = error instanceof Error ? error.message : 'Unknown error'
589
- throw new Error(`Failed to fetch OpenAPI schema: ${message}`)
590
- }
591
- }
592
-
593
- // =============================================================================
594
- // TABLE SCHEMA CONVERSION
595
- // =============================================================================
596
-
597
- function addTransformForType(
598
- field: BaseBagelField<any, any>,
599
- schemaType: string,
600
- format?: string
601
- ): void {
602
- switch (schemaType) {
603
- case 'boolean':
604
- field.transform = (value: any) => {
605
- if (value === true) { return 'Yes' }
606
- if (value === false) { return 'No' }
607
- return value
608
- }
609
- field.class = (value: any) => `pill ${value === true ? 'green' : 'light'}`
610
- break
611
-
612
- case 'string':
613
- if (format === 'date' || format === 'date-time') {
614
- USING_FMT_DATE = true
615
- field.transform = (value: any) => formatDate(value, 'YYYY-MM-DD')
616
- } else if (format === 'email') {
617
- field.attrs = { ...field.attrs, dir: 'ltr' }
618
- } else if (format === 'phone') {
619
- field.attrs = { ...field.attrs, dir: 'ltr' }
620
- } else if (format === 'uri' || format === 'url') {
621
- field.attrs = { ...field.attrs, dir: 'ltr' }
622
- }
623
- break
624
-
625
- case 'number':
626
- case 'integer':
627
- field.transform = (value: any) => Number.isNaN(value) ? '' : value?.toLocaleString()
628
- field.attrs = { ...field.attrs, dir: 'ltr' }
629
- break
630
-
631
- case 'array':
632
- field.transform = (value: any) => {
633
- if (!Array.isArray(value) || value.length === 0) { return '' }
634
- if (typeof value[0] === 'object') { return `${value.length} items` }
635
- return value.join(', ')
636
- }
637
- field.attrs = { ...field.attrs, dir: 'ltr' }
638
- break
639
-
640
- case 'object':
641
- field.transform = (value: any) => {
642
- if (!value || typeof value !== 'object') { return '' }
643
- return 'Object'
644
- }
645
- break
646
-
647
- default:
648
- // Default string handling
649
- break
650
- }
651
- }
652
-
653
- /**
654
- * Adds fallback transform based on field element type
655
- */
656
- function addFallbackTransform<T>(
657
- tableField: BaseBagelField<T, Path<T>>,
658
- fieldElementType: string | undefined
659
- ): void {
660
- switch (fieldElementType) {
661
- case 'date':
662
- USING_FMT_DATE = true
663
- tableField.transform = (value: any) => formatDate(value, 'YYYY-MM-DD')
664
- break
665
-
666
- case 'check':
667
- tableField.transform = (value: unknown) => value === true ? 'Yes' : value === false ? 'No' : value
668
- tableField.class = (value: unknown) => `pill ${value === true ? 'green' : 'light'}`
669
- break
670
-
671
- case 'email':
672
- tableField.attrs = { ...tableField.attrs, dir: 'ltr' }
673
- break
674
-
675
- case 'tel':
676
- tableField.attrs = { ...tableField.attrs, dir: 'ltr' }
677
- break
678
-
679
- case 'number':
680
- tableField.transform = (value: any) => {
681
- if (value === null || value === undefined) { return '' }
682
- return Number(value).toLocaleString()
683
- }
684
- tableField.attrs = { ...tableField.attrs, dir: 'ltr' }
685
- }
686
- }
687
-
688
- function processFieldForTable<T>(
689
- field: BaseBagelField<T, Path<T>>,
690
- targetSchema: SchemaObject,
691
- openApiSchema: OpenAPIObject
692
- ): BaseBagelField<T, Path<T>> | undefined {
693
- if (!field.id) { return undefined }
694
-
695
- const fieldPath = field.id.toString().split('.')
696
- const resolvedFieldSchema = getNestedPropertySchema(
697
- fieldPath,
698
- targetSchema,
699
- openApiSchema
700
- )
701
-
702
- if (!resolvedFieldSchema) {
703
- logVerbose(`No schema found for field: ${field.id}`)
704
- return undefined
705
- }
706
-
707
- const tableField: BaseBagelField<T, Path<T>> = {
708
- id: field.id,
709
- label: field.label,
710
- attrs: {},
711
- }
712
-
713
- // Handle union types (anyOf) - extract the non-null type
714
- const actualSchema
715
- = getNonNullSchema(resolvedFieldSchema) || resolvedFieldSchema
716
-
717
- // Safely extract the schema type as a string
718
- const schemaType = getSchemaTypeAsString(actualSchema.type)
719
- addTransformForType(tableField, schemaType, actualSchema.format)
720
-
721
- // Handle fallback based on original field element type
722
- if (!tableField.transform) {
723
- addFallbackTransform(tableField, field.$el)
724
- }
725
-
726
- return tableField
727
- }
728
-
729
- /**
730
- * Safely converts schema type to string, handling arrays and undefined values
731
- */
732
- function getSchemaTypeAsString(type: SchemaObject['type']): string {
733
- if (Array.isArray(type)) {
734
- // For arrays of types, prefer non-null types or return the first one
735
- const nonNullType = type.find(t => t !== 'null' && t !== 'undefined')
736
- return nonNullType || type[0] || 'string'
737
- }
738
- return type || 'string'
739
- }
740
-
741
- function convertToTableSchema<T = Record<string, unknown>>(
742
- formSchema: FormSchema<T>,
743
- targetSchema: SchemaObject,
744
- openApiSchema: OpenAPIObject
745
- ): FormSchema<T> {
746
- const tableSchema: any[] = []
747
-
748
- formSchema.forEach((field) => {
749
- const processedField = processFieldForTable(
750
- field as unknown as BaseBagelField<any, Path<any>>,
751
- targetSchema,
752
- openApiSchema
753
- )
754
- if (processedField) {
755
- (tableSchema as any[]).push(processedField as any)
756
- }
757
- })
758
-
759
- logVerbose(
760
- `Converted ${formSchema.length} form fields to ${tableSchema.length} table fields`
761
- )
762
- return tableSchema as FormSchema<T>
763
- }
764
-
765
- // =============================================================================
766
- // CODE GENERATION
767
- // =============================================================================
768
-
769
- function cleanOptions(options: Record<string, any>): string {
770
- if (!options || typeof options !== 'object') { return '{}' }
771
-
772
- const cleaned: Record<string, any> = {}
773
- const skipDefaults = ['step', 'enableTime', 'multiline', 'required']
774
-
775
- Object.entries(options).forEach(([key, value]) => {
776
- const shouldSkip
777
- = value === undefined
778
- || value === null
779
- || value === false
780
- || value === ''
781
- || value === 0
782
- || (skipDefaults.includes(key) && (value === 1 || value === false))
783
- || (key === 'attrs'
784
- && typeof value === 'object'
785
- && Object.keys(value).length === 0)
786
-
787
- if (!shouldSkip) {
788
- cleaned[key] = value
789
- }
790
- })
791
-
792
- return Object.keys(cleaned).length > 0 ? JSON.stringify(cleaned) : '{}'
793
- }
794
-
795
- function extractFieldOptions<T>(field: BaseBagelField<T, Path<T>>) {
796
- const fieldProps = [
797
- 'required',
798
- 'placeholder',
799
- 'helptext',
800
- 'defaultValue',
801
- 'class',
802
- 'disabled',
803
- 'vIf',
804
- 'transform',
805
- 'onUpdate',
806
- 'validate',
807
- ] as const
808
-
809
- type OptFieldProps = typeof fieldProps[number] | (string & {})
810
- const options: Partial<Record<OptFieldProps, any>> = {}
811
-
812
- fieldProps.forEach((prop) => {
813
- if (field[prop] !== undefined) {
814
- options[prop] = field[prop]
815
- }
816
- })
817
-
818
- if (field.attrs && typeof field.attrs === 'object') {
819
- Object.entries(field.attrs).forEach(([key, value]) => {
820
- if (value !== undefined && value !== null) {
821
- options[key] = value
822
- }
823
- })
824
- }
825
-
826
- return options
827
- }
828
-
829
- function generateFieldCall<T>(field: any, useTableSchema: boolean): string {
830
- const fieldId = field.id as string
831
- const fieldLabel = field.label || formatPropertyName(fieldId)
832
- const fieldOptions = extractFieldOptions(field)
833
- const cleanedOptions = cleanOptions(fieldOptions)
834
-
835
- if (useTableSchema) {
836
- const options: string[] = []
837
- const specialProps = ['transform', 'class', 'attrs'] as const
838
-
839
- specialProps.forEach((prop) => {
840
- if (field[prop]) {
841
- const value = prop === 'attrs'
842
- ? JSON.stringify(field[prop])
843
- : field[prop].toString()
844
- options.push(`${prop}: ${value}`)
845
- }
846
- })
847
-
848
- const optionsStr = options.length > 0 ? `{ ${options.join(', ')} }` : ''
849
- return `getBaseField('${fieldId}', '${fieldLabel}'${optionsStr ? `, ${optionsStr}` : ''})`
850
- }
851
-
852
- const fieldTypeMap: Record<string, string> = {
853
- text: 'txtField',
854
- email: 'emailField',
855
- date: 'dateField',
856
- tel: 'telField',
857
- number: 'numField',
858
- check: 'checkField',
859
- checkbox: 'checkField',
860
- }
861
-
862
- const fieldType = fieldTypeMap[field.$el] || 'txtField'
863
-
864
- if (field.$el === 'select') {
865
- const selectOptions
866
- = field.options || (field.attrs && field.attrs.options) || []
867
- const optionsStr = JSON.stringify(selectOptions)
868
- return `selectField('${fieldId}', '${fieldLabel}', ${optionsStr}, ${cleanedOptions})`
869
- }
870
-
871
- if (field.$el === 'array') {
872
- const arrayField = field as ArrayBagelField<any, any>
873
- if (arrayField.attrs?.schema) {
874
- const nestedCalls = toValue(arrayField.attrs.schema).map(
875
- (nestedField: any) => generateFieldCall(nestedField, useTableSchema)
876
- )
877
- const nestedSchemaStr = `[${nestedCalls.join(',')}]`
878
- return `arrField('${fieldId}', '${fieldLabel}', ${nestedSchemaStr})`
879
- }
880
- const arrayType = arrayField.attrs?.type || 'text'
881
- return `arrField('${fieldId}', '${fieldLabel}', '${arrayType}')`
882
- }
883
-
884
- return `${fieldType}('${fieldId}', '${fieldLabel}', ${cleanedOptions})`
885
- }
886
-
887
- function generateCodeWithUtilities<T>(
888
- schemaId: string,
889
- formSchema: FormSchema<T>,
890
- config: GeneratorConfig
891
- ): string {
892
- const imports = new Set<string>()
893
- const fieldCalls: string[] = []
894
-
895
- formSchema.forEach((field) => {
896
- const call = generateFieldCall(field as any, config.useTableSchema || false)
897
- fieldCalls.push(call)
898
-
899
- // Extract import from function call
900
- const functionName = call.split('(')[0]
901
- imports.add(functionName)
902
- })
903
-
904
- if (config.useTableSchema) {
905
- imports.add('getBaseField')
906
- }
907
-
908
- const importList = Array.from(imports).sort().join(', ')
909
- const importStatement
910
- = imports.size > 0 ? `const { ${importList} } = useForm()` : ''
911
-
912
- return `import type { BglFormSchemaT } from '@bagelink/vue'
913
- import type { ${schemaId} } from '@/client/types'
914
- import { useForm ${USING_FMT_DATE ? ', formatDate' : ''} } from '@bagelink/vue'
915
-
916
- ${importStatement}
917
-
918
- /**
919
- * Generated form schema for ${schemaId}
920
- */
921
- export function generate${schemaId}FormSchema(): BglFormSchemaT<${schemaId}> {
922
- return [${fieldCalls.join(',\n\t\t')}]
923
- }`
924
- .replaceAll(`value === !0`, 'value === true')
925
- .replaceAll(`value === !1`, 'value === false')
926
- .replaceAll(`attrs: {}`, '')
927
- .replaceAll('{}', '')
928
- .replaceAll('{ }', '')
929
- }
930
-
931
- function generateCodeWithJson(
932
- schemaId: string,
933
- formSchema: FormSchema<any>
934
- ): string {
935
- const stringifiedSchema = JSON.stringify(formSchema)
936
- .replaceAll(`"step":1`, '')
937
- .replaceAll(`"enableTime":false`, '')
938
- .replaceAll(`"multiline":false`, '')
939
- .replaceAll(`"required":false`, '')
940
- .replaceAll(`"attrs":{}`, '')
941
- .replaceAll(`,,`, ',')
942
-
943
- return `import type { BglFormSchemaT } from '@bagelink/vue'
944
- import type { ${schemaId} } from '@/client/types'
945
-
946
- /**
947
- * Generated form schema for ${schemaId}
948
- */
949
- export function generate${schemaId}FormSchema(): BglFormSchemaT<${schemaId}> {
950
- return ${stringifiedSchema}
951
- }
952
- `
953
- }
954
-
955
- function generateCode(
956
- schemaId: string,
957
- formSchema: FormSchema<any>,
958
- config: GeneratorConfig
959
- ): string {
960
- return config.useUtilityFunctions
961
- ? generateCodeWithUtilities(schemaId, formSchema, config)
962
- : generateCodeWithJson(schemaId, formSchema)
963
- }
964
-
965
- // =============================================================================
966
- // FILE OPERATIONS
967
- // =============================================================================
968
-
969
- async function writeGeneratedCode(
970
- outputFile: string,
971
- content: string
972
- ): Promise<void> {
973
- const outputDir = path.dirname(outputFile)
974
- if (!existsSync(outputDir)) {
975
- mkdirSync(outputDir, { recursive: true })
976
- }
977
-
978
- const fullOutputPath = path.resolve(cwd(), outputFile)
979
- await formatAndWriteCode(fullOutputPath, content)
980
- await runEsLintOnDir(outputDir)
981
-
982
- console.log(`📁 Output file location: ${fullOutputPath}`)
983
- }
984
-
985
- // =============================================================================
986
- // MAIN EXECUTION
987
- // =============================================================================
988
-
989
- async function main(): Promise<void> {
990
- try {
991
- console.log('⚙️ Parsing configuration...')
992
- const config = parseConfiguration()
993
-
994
- console.log(`🌐 Fetching OpenAPI schema from ${config.url}...`)
995
- const openApiSchema = await fetchOpenApiSchema(config.url)
996
-
997
- if (!openApiSchema.components?.schemas) {
998
- throw new Error('OpenAPI schema has no components.schemas section')
999
- }
1000
-
1001
- console.log(`🔍 Finding schema: ${config.genSchemaId}`)
1002
- const targetSchema = getSchemaById(config.genSchemaId, openApiSchema)
1003
- if (!targetSchema) {
1004
- throw new Error(
1005
- `Schema with ID "${config.genSchemaId}" not found or is not resolvable`
1006
- )
1007
- }
1008
-
1009
- const context: SchemaContext = { openApiSchema }
1010
-
1011
- console.log(`🔄 Converting schema to form fields...`)
1012
- let formSchema = convertSchemaToForm(targetSchema, config.genSchemaId, context)
1013
-
1014
- if (config.useTableSchema) {
1015
- console.log('📊 Converting form schema to table schema...')
1016
- formSchema = convertToTableSchema(formSchema, targetSchema, openApiSchema)
1017
- }
1018
-
1019
- console.log('🧑‍💻 Generating TypeScript code...')
1020
- const codeContent = generateCode(config.genSchemaId, formSchema, config)
1021
-
1022
- logVerbose(`Generated code for schema "${config.genSchemaId}":\n${codeContent}`)
1023
-
1024
- console.log(`💾 Writing output to ${config.output}...`)
1025
- await writeGeneratedCode(config.output, codeContent)
1026
-
1027
- console.log('✅ Form schema generation completed successfully!')
1028
- } catch (error) {
1029
- console.error('❌ Error generating form schema:', error)
1030
- exit(1)
1031
- }
1032
- }
1033
-
1034
- // Execute the main pipeline
1035
- main().catch(console.error)