@sealcode/sealgen 0.18.10 → 0.19.2

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 (444) hide show
  1. package/.xunit +74 -69
  2. package/@types/add-crud.d.sync-conflict-20250918-184311-TFDLWFG.ts +1 -0
  3. package/@types/builders/colors-builder.d.sync-conflict-20250918-184323-TFDLWFG.ts +10 -0
  4. package/@types/builders/colors-builder.d.ts +1 -1
  5. package/@types/builders/fonts-builder.d.sync-conflict-20250918-184322-TFDLWFG.ts +7 -0
  6. package/@types/builders/fonts-builder.d.ts +1 -1
  7. package/@types/controllers/table-add-button.d.ts +6 -0
  8. package/@types/controllers/table-add-button.stimulus.d.ts +6 -0
  9. package/@types/crud-field-snippets.d.sync-conflict-20250918-184323-TFDLWFG.ts +1 -0
  10. package/@types/crud-field-snippets.d.ts +1 -3
  11. package/@types/forms/controls/array.d.sync-conflict-20250918-184306-TFDLWFG.ts +33 -0
  12. package/@types/forms/controls/array.d.ts +1 -3
  13. package/@types/forms/controls/array.sync-conflict-20250918-222045-TFDLWFG.d.ts +33 -0
  14. package/@types/forms/controls/autocomplete.d.sync-conflict-20250918-222042-TFDLWFG.ts +22 -0
  15. package/@types/forms/controls/autocomplete.d.ts +1 -1
  16. package/@types/forms/controls/checkbox-group.d.sync-conflict-20250918-184319-TFDLWFG.ts +21 -0
  17. package/@types/forms/controls/checkbox-group.d.ts +3 -3
  18. package/@types/forms/controls/checkboxed-list-input.d.sync-conflict-20250918-184323-TFDLWFG.ts +21 -0
  19. package/@types/forms/controls/checkboxed-list-input.d.ts +3 -3
  20. package/@types/forms/controls/controls.d.ts +2 -2
  21. package/@types/forms/controls/derived-frame.d.sync-conflict-20250918-184314-TFDLWFG.ts +19 -0
  22. package/@types/forms/controls/derived-frame.d.ts +0 -2
  23. package/@types/forms/controls/dropdown.d.sync-conflict-20250918-222044-TFDLWFG.ts +30 -0
  24. package/@types/forms/controls/dropdown.d.ts +1 -1
  25. package/@types/forms/controls/file.d.sync-conflict-20250918-222045-TFDLWFG.ts +13 -0
  26. package/@types/forms/controls/file.d.ts +1 -2
  27. package/@types/forms/controls/form-control.d.sync-conflict-20250918-184322-TFDLWFG.ts +19 -0
  28. package/@types/forms/controls/form-control.d.sync-conflict-20250918-222046-TFDLWFG.ts +19 -0
  29. package/@types/forms/controls/form-control.d.ts +7 -4
  30. package/@types/forms/controls/image.d.ts +19 -0
  31. package/@types/forms/controls/image.test.d.ts +1 -0
  32. package/@types/forms/controls/multiple-files.d.sync-conflict-20250918-184318-TFDLWFG.ts +42 -0
  33. package/@types/forms/controls/multiple-files.d.ts +3 -1
  34. package/@types/forms/controls/multiple-images.d.ts +19 -0
  35. package/@types/forms/controls/number.d.sync-conflict-20250918-222046-TFDLWFG.ts +13 -0
  36. package/@types/forms/controls/number.d.ts +1 -1
  37. package/@types/forms/controls/photo.d.sync-conflict-20250918-184321-TFDLWFG.ts +19 -0
  38. package/@types/forms/controls/photo.d.ts +3 -5
  39. package/@types/forms/controls/simple-input.d.sync-conflict-20250918-184310-TFDLWFG.ts +33 -0
  40. package/@types/forms/controls/simple-input.d.sync-conflict-20250918-222042-TFDLWFG.ts +33 -0
  41. package/@types/forms/controls/simple-input.d.ts +5 -4
  42. package/@types/forms/controls/simple-input.sync-conflict-20250918-222045-TFDLWFG.d.ts +33 -0
  43. package/@types/forms/controls/single-reference.d.ts +3 -2
  44. package/@types/forms/controls/table.d.sync-conflict-20250918-184302-TFDLWFG.ts +39 -0
  45. package/@types/forms/controls/table.d.ts +8 -3
  46. package/@types/forms/controls/table.sync-conflict-20250918-222042-TFDLWFG.d.ts +39 -0
  47. package/@types/forms/controls/textarea.d.sync-conflict-20250918-222045-TFDLWFG.ts +25 -0
  48. package/@types/forms/controls/textarea.d.ts +3 -3
  49. package/@types/forms/fields/boolean.d.sync-conflict-20250918-184325-TFDLWFG.ts +22 -0
  50. package/@types/forms/fields/boolean.d.ts +6 -1
  51. package/@types/forms/fields/boolean.sync-conflict-20250918-222042-TFDLWFG.d.ts +22 -0
  52. package/@types/forms/fields/checkboxed-list.d.sync-conflict-20250918-184325-TFDLWFG.ts +23 -0
  53. package/@types/forms/fields/checkboxed-list.d.ts +3 -1
  54. package/@types/forms/fields/collection-field.d.sync-conflict-20250918-184319-TFDLWFG.ts +22 -0
  55. package/@types/forms/fields/collection-field.d.sync-conflict-20250918-222047-TFDLWFG.ts +22 -0
  56. package/@types/forms/fields/collection-field.d.ts +8 -1
  57. package/@types/forms/fields/color.d.ts +4 -0
  58. package/@types/forms/fields/coordinates.d.sync-conflict-20250918-222044-TFDLWFG.ts +14 -0
  59. package/@types/forms/fields/coordinates.d.ts +14 -0
  60. package/@types/forms/fields/date.d.ts +13 -0
  61. package/@types/forms/fields/datetime.d.sync-conflict-20250918-222050-TFDLWFG.ts +4 -0
  62. package/@types/forms/fields/datetime.d.ts +14 -0
  63. package/@types/forms/fields/deep-reverse-single-reference-list.d.ts +20 -0
  64. package/@types/forms/fields/deep-reverse-single-reference-table.d.ts +16 -0
  65. package/@types/forms/fields/email.d.sync-conflict-20250918-184303-TFDLWFG.ts +8 -0
  66. package/@types/forms/fields/email.d.ts +3 -0
  67. package/@types/forms/fields/enum-multiple-sealious.d.ts +16 -0
  68. package/@types/forms/fields/enum-multiple-sealious.sync-conflict-20250918-222047-TFDLWFG.d.ts +16 -0
  69. package/@types/forms/fields/field.d.sync-conflict-20250918-184306-TFDLWFG.ts +70 -0
  70. package/@types/forms/fields/field.d.ts +37 -5
  71. package/@types/forms/fields/fields.d.sync-conflict-20250918-184314-TFDLWFG.ts +29 -0
  72. package/@types/forms/fields/fields.d.ts +23 -8
  73. package/@types/forms/fields/file.d.sync-conflict-20250918-184310-TFDLWFG.ts +23 -0
  74. package/@types/forms/fields/file.d.sync-conflict-20250918-222046-TFDLWFG.ts +23 -0
  75. package/@types/forms/fields/file.d.ts +11 -5
  76. package/@types/forms/fields/file.sync-conflict-20250918-222049-TFDLWFG.d.ts +23 -0
  77. package/@types/forms/fields/float.d.ts +4 -0
  78. package/@types/forms/fields/get-field-for-sealious.d.sync-conflict-20250918-222046-TFDLWFG.ts +29 -0
  79. package/@types/forms/fields/get-field-for-sealious.d.ts +31 -0
  80. package/@types/forms/fields/get-field-for-sealious.sync-conflict-20250918-222042-TFDLWFG.d.ts +29 -0
  81. package/@types/forms/fields/html.d.ts +6 -0
  82. package/@types/forms/fields/image.d.sync-conflict-20250918-222042-TFDLWFG.ts +5 -0
  83. package/@types/forms/fields/image.d.ts +5 -0
  84. package/@types/forms/fields/int.d.ts +6 -0
  85. package/@types/forms/fields/json.d.ts +13 -0
  86. package/@types/forms/fields/markdown.d.ts +6 -0
  87. package/@types/forms/fields/multiple-files.d.sync-conflict-20250918-184304-TFDLWFG.ts +16 -0
  88. package/@types/forms/fields/multiple-files.d.ts +3 -1
  89. package/@types/forms/fields/number.d.sync-conflict-20250918-184317-TFDLWFG.ts +25 -0
  90. package/@types/forms/fields/number.d.sync-conflict-20250918-222047-TFDLWFG.ts +25 -0
  91. package/@types/forms/fields/number.d.ts +3 -1
  92. package/@types/forms/fields/password.d.ts +5 -0
  93. package/@types/forms/fields/pick-from-list-sealious.d.ts +11 -0
  94. package/@types/forms/fields/pick-from-list.d.sync-conflict-20250918-184322-TFDLWFG.ts +15 -0
  95. package/@types/forms/fields/pick-from-list.d.ts +4 -3
  96. package/@types/forms/fields/proxy-field.d.sync-conflict-20250918-184307-TFDLWFG.ts +15 -0
  97. package/@types/forms/fields/proxy-field.d.ts +3 -1
  98. package/@types/forms/fields/regexp.d.sync-conflict-20250918-184305-TFDLWFG.ts +21 -0
  99. package/@types/forms/fields/regexp.d.sync-conflict-20250918-222045-TFDLWFG.ts +21 -0
  100. package/@types/forms/fields/regexp.d.ts +6 -1
  101. package/@types/forms/fields/regexp.sync-conflict-20250918-222047-TFDLWFG.d.ts +21 -0
  102. package/@types/forms/fields/simple-form-field.d.sync-conflict-20250918-184309-TFDLWFG.ts +29 -0
  103. package/@types/forms/fields/simple-form-field.d.sync-conflict-20250918-222044-TFDLWFG.ts +29 -0
  104. package/@types/forms/fields/simple-form-field.d.ts +23 -3
  105. package/@types/forms/fields/simple-form-field.sync-conflict-20250918-222049-TFDLWFG.d.ts +29 -0
  106. package/@types/forms/fields/single-reference.d.ts +19 -0
  107. package/@types/forms/fields/single-reference.sync-conflict-20250918-222043-TFDLWFG.d.ts +10 -0
  108. package/@types/forms/fields/structured-array.d.sync-conflict-20250918-184302-TFDLWFG.ts +27 -0
  109. package/@types/forms/fields/structured-array.d.sync-conflict-20250918-222049-TFDLWFG.ts +27 -0
  110. package/@types/forms/fields/structured-array.d.ts +19 -10
  111. package/@types/forms/fields/structured-array.sync-conflict-20250918-222047-TFDLWFG.d.ts +27 -0
  112. package/@types/forms/fields/table.d.sync-conflict-20250918-184303-TFDLWFG.ts +16 -0
  113. package/@types/forms/fields/table.d.ts +3 -0
  114. package/@types/forms/fields/text.d.ts +6 -0
  115. package/@types/forms/fields/url.d.ts +6 -0
  116. package/@types/forms/form-types.d.sync-conflict-20250918-222045-TFDLWFG.ts +26 -0
  117. package/@types/forms/form-types.d.ts +2 -0
  118. package/@types/forms/form.d.sync-conflict-20250918-184315-TFDLWFG.ts +32 -0
  119. package/@types/forms/form.d.sync-conflict-20250918-222049-TFDLWFG.ts +32 -0
  120. package/@types/forms/form.d.ts +10 -8
  121. package/@types/forms/form.sync-conflict-20250918-222049-TFDLWFG.d.ts +33 -0
  122. package/@types/forms/form.test.d.sync-conflict-20250918-184318-TFDLWFG.ts +6 -0
  123. package/@types/forms/form.test.d.sync-conflict-20250918-222047-TFDLWFG.ts +6 -0
  124. package/@types/forms/form.test.d.ts +2 -2
  125. package/@types/forms/multiform.d.sync-conflict-20250918-184308-TFDLWFG.ts +23 -0
  126. package/@types/forms/multiform.d.ts +1 -2
  127. package/@types/forms/multiform.sync-conflict-20250918-222044-TFDLWFG.d.ts +23 -0
  128. package/@types/index.d.sync-conflict-20250918-184316-TFDLWFG.ts +46 -0
  129. package/@types/index.d.ts +2 -2
  130. package/@types/mount.d.sync-conflict-20250918-184320-TFDLWFG.ts +6 -0
  131. package/@types/mount.d.ts +0 -1
  132. package/@types/page/list.d.sync-conflict-20250918-184318-TFDLWFG.ts +48 -0
  133. package/@types/page/list.d.sync-conflict-20250918-222046-TFDLWFG.ts +48 -0
  134. package/@types/page/list.d.ts +2 -2
  135. package/@types/page/list.sync-conflict-20250918-222048-TFDLWFG.d.ts +48 -0
  136. package/@types/page/mountable-with-fields.d.sync-conflict-20250918-184321-TFDLWFG.ts +42 -0
  137. package/@types/page/mountable-with-fields.d.sync-conflict-20250918-222046-TFDLWFG.ts +42 -0
  138. package/@types/page/mountable-with-fields.d.ts +3 -3
  139. package/@types/page/mountable-with-fields.sync-conflict-20250918-222044-TFDLWFG.d.ts +42 -0
  140. package/@types/page/mountable.d.sync-conflict-20250918-184306-TFDLWFG.ts +10 -0
  141. package/@types/page/mountable.d.ts +0 -1
  142. package/@types/page/page.d.sync-conflict-20250918-184320-TFDLWFG.ts +18 -0
  143. package/@types/page/page.d.ts +0 -1
  144. package/@types/page/props-parser.d.sync-conflict-20250918-184305-TFDLWFG.ts +15 -0
  145. package/@types/page/props-parser.d.ts +0 -1
  146. package/@types/page/stateful-page.d.sync-conflict-20250918-184326-TFDLWFG.ts +62 -0
  147. package/@types/page/stateful-page.d.ts +0 -1
  148. package/@types/register-external.d.ts +2 -2
  149. package/@types/templates/form.d.ts +1 -3
  150. package/@types/templates/jdd-component.d.ts +1 -1
  151. package/@types/templates/page.d.ts +1 -1
  152. package/@types/templates/shared/shared-crud-form-fields.d.sync-conflict-20250918-184306-TFDLWFG.ts +1 -0
  153. package/@types/templates/shared/shared-crud-form-fields.d.ts +1 -68
  154. package/@types/templates/templates.d.ts +1 -21
  155. package/@types/test_utils/test-on-real-app.d.sync-conflict-20250918-184320-TFDLWFG.ts +26 -0
  156. package/@types/test_utils/test-on-real-app.d.ts +0 -1
  157. package/@types/utils/extract-fields-from-collection.d.sync-conflict-20250918-184312-TFDLWFG.ts +18 -0
  158. package/@types/utils/extract-fields-from-collection.d.ts +5 -1
  159. package/@types/utils/extract-fields-from-collection.sync-conflict-20250918-222045-TFDLWFG.d.ts +18 -0
  160. package/@types/utils/wrap-attributes.d.ts +3 -0
  161. package/README.md +5 -0
  162. package/assets/file-icon.svg +5 -0
  163. package/eslint.config.mjs +56 -0
  164. package/lib/add-crud.js +77 -89
  165. package/lib/add-jdd-component.js +3 -3
  166. package/lib/add-list-route.test.js +1 -1
  167. package/lib/add-route.js +2 -9
  168. package/lib/build.js +6 -4
  169. package/lib/builders/backend-ts-builder.js +0 -1
  170. package/lib/builders/colors-builder.js +11 -8
  171. package/lib/builders/fonts-builder.js +0 -1
  172. package/lib/builders/frontend-ts-builder.js +0 -1
  173. package/lib/cli.js +4 -7
  174. package/lib/components/tabs.js +36 -36
  175. package/lib/controllers/table-add-button.stimulus.js +35 -0
  176. package/lib/esbuild-plugins/rewrite-asset-imports.js +7 -10
  177. package/lib/forms/controls/array.js +25 -22
  178. package/lib/forms/controls/big-radio-group.js +2 -2
  179. package/lib/forms/controls/checkbox-group.js +7 -7
  180. package/lib/forms/controls/checkboxed-list-input.js +7 -1
  181. package/lib/forms/controls/checkboxed-list-input.test.js +6 -6
  182. package/lib/forms/controls/controls.js +2 -2
  183. package/lib/forms/controls/derived-frame.js +8 -4
  184. package/lib/forms/controls/derived.js +1 -1
  185. package/lib/forms/controls/dropdown.js +5 -3
  186. package/lib/forms/controls/editable-collection-subset.js +2 -2
  187. package/lib/forms/controls/file.js +26 -2
  188. package/lib/forms/controls/file.test.js +2 -2
  189. package/lib/forms/controls/form-control.js +1 -1
  190. package/lib/forms/controls/hidden-input.js +4 -1
  191. package/lib/forms/controls/{photo.js → image.js} +6 -7
  192. package/lib/forms/controls/{photo.test.js → image.test.js} +8 -23
  193. package/lib/forms/controls/multiple-files.js +10 -1
  194. package/lib/forms/controls/{multiple-photos.js → multiple-images.js} +3 -3
  195. package/lib/forms/controls/simple-input.js +13 -12
  196. package/lib/forms/controls/single-reference.js +4 -0
  197. package/lib/forms/controls/single-reference.test.js +1 -1
  198. package/lib/forms/controls/table.js +62 -25
  199. package/lib/forms/controls/textarea.js +5 -3
  200. package/lib/forms/controls/tickable.js +13 -5
  201. package/lib/forms/fields/boolean.js +14 -0
  202. package/lib/forms/fields/checkboxed-list.js +4 -0
  203. package/lib/forms/fields/collection-field.js +9 -0
  204. package/lib/forms/fields/color.js +10 -0
  205. package/lib/forms/fields/coordinates.js +49 -0
  206. package/lib/forms/fields/date.js +34 -0
  207. package/lib/forms/fields/datetime.js +46 -0
  208. package/lib/forms/fields/deep-reverse-single-reference-list.js +81 -0
  209. package/lib/forms/fields/deep-reverse-single-reference-table.js +122 -0
  210. package/lib/forms/fields/email.js +7 -0
  211. package/lib/forms/fields/enum-multiple-sealious.js +32 -0
  212. package/lib/forms/fields/field.js +32 -4
  213. package/lib/forms/fields/field.test.js +8 -8
  214. package/lib/forms/fields/fields.js +23 -8
  215. package/lib/forms/fields/file.js +33 -9
  216. package/lib/forms/fields/file.test.js +5 -17
  217. package/lib/forms/fields/float.js +10 -0
  218. package/lib/forms/fields/get-field-for-sealious.js +213 -0
  219. package/lib/forms/fields/html.js +14 -0
  220. package/lib/forms/fields/image.js +13 -0
  221. package/lib/forms/fields/int.js +23 -0
  222. package/lib/forms/fields/json.js +31 -0
  223. package/lib/forms/fields/markdown.js +14 -0
  224. package/lib/forms/fields/multiple-files.js +4 -0
  225. package/lib/forms/fields/number.js +6 -0
  226. package/lib/forms/fields/password.js +13 -0
  227. package/lib/forms/fields/pick-from-list-sealious.js +17 -0
  228. package/lib/forms/fields/pick-from-list.js +6 -2
  229. package/lib/forms/fields/proxy-field.js +3 -0
  230. package/lib/forms/fields/regexp.js +14 -0
  231. package/lib/forms/fields/simple-form-field.js +61 -2
  232. package/lib/forms/fields/single-reference.js +44 -0
  233. package/lib/forms/fields/structured-array.js +61 -12
  234. package/lib/forms/fields/table.js +29 -2
  235. package/lib/forms/fields/text.js +17 -0
  236. package/lib/forms/fields/url.js +17 -0
  237. package/lib/forms/form.js +30 -14
  238. package/lib/forms/form.test.js +5 -7
  239. package/lib/forms/multiform.js +10 -9
  240. package/lib/forms/multiform.test.js +5 -5
  241. package/lib/generate-collections.js +2 -3
  242. package/lib/generate-components.js +2 -3
  243. package/lib/generate-routes.js +3 -5
  244. package/lib/generate-routes.test.js +7 -16
  245. package/lib/generate-stimulus.js +4 -4
  246. package/lib/get-fonts.js +29 -27
  247. package/lib/index.js +1 -0
  248. package/lib/make-env.js +1 -1
  249. package/lib/make-hidden-inputs.js +4 -4
  250. package/lib/mount.js +11 -1
  251. package/lib/notifier.js +3 -4
  252. package/lib/page/list.js +20 -15
  253. package/lib/page/mountable-with-fields.js +14 -6
  254. package/lib/page/mountable-with-fields.test.js +1 -1
  255. package/lib/page/mountable.js +0 -1
  256. package/lib/page/page.js +0 -1
  257. package/lib/register-external.js +4 -4
  258. package/lib/templates/form.js +9 -10
  259. package/lib/templates/jdd-component.js +1 -1
  260. package/lib/templates/jdd-editor.js +1 -1
  261. package/lib/templates/multiform.js +4 -4
  262. package/lib/templates/page.js +1 -3
  263. package/lib/templates/shared/collection-create-form.js +31 -44
  264. package/lib/templates/shared/collection-edit-form.js +43 -81
  265. package/lib/templates/shared/collection-list.js +13 -21
  266. package/lib/templates/shared/shared-crud-form-fields.js +28 -98
  267. package/lib/test_utils/exec_async.js +3 -3
  268. package/lib/test_utils/test-on-real-app.js +12 -14
  269. package/lib/utils/extract-fields-from-collection.js +60 -20
  270. package/lib/utils/make-slug.js +1 -1
  271. package/lib/utils/wrap-attributes.js +20 -0
  272. package/lib/utils/write-file.js +1 -1
  273. package/package.json +11 -9
  274. package/src/add-collection.ts +1 -3
  275. package/src/add-crud.ts +84 -100
  276. package/src/add-jdd-component.ts +4 -5
  277. package/src/add-list-route.test.ts +1 -1
  278. package/src/add-route.ts +3 -13
  279. package/src/build.ts +6 -4
  280. package/src/builders/backend-ts-builder.ts +0 -1
  281. package/src/builders/builder.ts +4 -1
  282. package/src/builders/colors-builder.ts +11 -9
  283. package/src/builders/css-builder.ts +4 -1
  284. package/src/builders/fonts-builder.ts +0 -1
  285. package/src/builders/frontend-ts-builder.ts +0 -1
  286. package/src/cli.ts +5 -7
  287. package/src/components/tabs.ts +38 -37
  288. package/src/components/toggle-modal.ts +1 -1
  289. package/src/controllers/table-add-button.stimulus.ts +35 -0
  290. package/src/esbuild-plugins/rewrite-asset-imports.ts +7 -10
  291. package/src/forms/controls/array.ts +35 -36
  292. package/src/forms/controls/autocomplete.ts +2 -2
  293. package/src/forms/controls/big-radio-group.ts +4 -4
  294. package/src/forms/controls/checkbox-group.ts +10 -10
  295. package/src/forms/controls/checkboxed-list-input.test.ts +6 -6
  296. package/src/forms/controls/checkboxed-list-input.ts +16 -8
  297. package/src/forms/controls/controls.ts +2 -2
  298. package/src/forms/controls/derived-frame.ts +16 -11
  299. package/src/forms/controls/derived.ts +7 -6
  300. package/src/forms/controls/dropdown.ts +13 -13
  301. package/src/forms/controls/editable-collection-subset.ts +4 -3
  302. package/src/forms/controls/field-group.ts +1 -1
  303. package/src/forms/controls/file.test.ts +4 -2
  304. package/src/forms/controls/file.ts +30 -7
  305. package/src/forms/controls/form-control.ts +8 -3
  306. package/src/forms/controls/hidden-input.ts +5 -1
  307. package/src/forms/controls/html.ts +1 -0
  308. package/src/forms/controls/{photo.test.ts → image.test.ts} +7 -24
  309. package/src/forms/controls/{photo.ts → image.ts} +4 -6
  310. package/src/forms/controls/multiple-files.ts +23 -8
  311. package/src/forms/controls/{multiple-photos.ts → multiple-images.ts} +2 -2
  312. package/src/forms/controls/number.ts +1 -1
  313. package/src/forms/controls/simple-input.ts +21 -33
  314. package/src/forms/controls/single-reference.test.ts +1 -1
  315. package/src/forms/controls/single-reference.ts +11 -3
  316. package/src/forms/controls/table.ts +87 -33
  317. package/src/forms/controls/textarea.ts +7 -5
  318. package/src/forms/controls/tickable.ts +13 -7
  319. package/src/forms/fields/boolean.ts +27 -2
  320. package/src/forms/fields/checkboxed-list.ts +11 -2
  321. package/src/forms/fields/collection-field.ts +21 -3
  322. package/src/forms/fields/color.ts +9 -0
  323. package/src/forms/fields/coordinates.ts +66 -0
  324. package/src/forms/fields/date.ts +50 -0
  325. package/src/forms/fields/datetime.ts +66 -0
  326. package/src/forms/fields/deep-reverse-single-reference-list.ts +130 -0
  327. package/src/forms/fields/deep-reverse-single-reference-table.ts +213 -0
  328. package/src/forms/fields/email.ts +10 -1
  329. package/src/forms/fields/enum-multiple-sealious.ts +48 -0
  330. package/src/forms/fields/existing-sealious-value.ts +1 -1
  331. package/src/forms/fields/field.test.ts +8 -8
  332. package/src/forms/fields/field.ts +98 -11
  333. package/src/forms/fields/fields.ts +23 -8
  334. package/src/forms/fields/file.test.ts +5 -17
  335. package/src/forms/fields/file.ts +44 -16
  336. package/src/forms/fields/float.ts +9 -0
  337. package/src/forms/fields/get-field-for-sealious.ts +337 -0
  338. package/src/forms/fields/html.ts +15 -0
  339. package/src/forms/fields/image.ts +12 -0
  340. package/src/forms/fields/int.ts +25 -0
  341. package/src/forms/fields/json.ts +48 -0
  342. package/src/forms/fields/markdown.ts +15 -0
  343. package/src/forms/fields/multiple-files.ts +10 -1
  344. package/src/forms/fields/number.ts +10 -3
  345. package/src/forms/fields/password.ts +13 -0
  346. package/src/forms/fields/pick-from-list-sealious.ts +22 -0
  347. package/src/forms/fields/pick-from-list.ts +8 -4
  348. package/src/forms/fields/proxy-field.ts +7 -1
  349. package/src/forms/fields/regexp.ts +27 -1
  350. package/src/forms/fields/simple-form-field.ts +103 -7
  351. package/src/forms/fields/single-reference.ts +62 -0
  352. package/src/forms/fields/structured-array.ts +111 -18
  353. package/src/forms/fields/table.ts +39 -16
  354. package/src/forms/fields/text.ts +18 -0
  355. package/src/forms/fields/url.ts +20 -0
  356. package/src/forms/form-types.ts +5 -4
  357. package/src/forms/form.test.ts +5 -7
  358. package/src/forms/form.ts +42 -23
  359. package/src/forms/forms.css +0 -85
  360. package/src/forms/multiform.test.ts +9 -9
  361. package/src/forms/multiform.ts +12 -10
  362. package/src/generate-collections.ts +2 -3
  363. package/src/generate-components.ts +2 -3
  364. package/src/generate-routes.test.ts +7 -16
  365. package/src/generate-routes.ts +6 -10
  366. package/src/generate-stimulus.ts +4 -5
  367. package/src/get-fonts.ts +32 -30
  368. package/src/index.ts +2 -1
  369. package/src/make-env.ts +1 -1
  370. package/src/make-hidden-inputs.ts +8 -7
  371. package/src/mount.ts +16 -7
  372. package/src/notifier.ts +4 -7
  373. package/src/page/default-list-filters.ts +1 -0
  374. package/src/page/list.ts +33 -28
  375. package/src/page/mountable-with-fields.test.ts +1 -1
  376. package/src/page/mountable-with-fields.ts +21 -12
  377. package/src/page/mountable.ts +0 -1
  378. package/src/page/page.ts +2 -3
  379. package/src/page/props-parser.ts +1 -1
  380. package/src/page/sealious-list.ts +1 -1
  381. package/src/page/stateful-page.ts +6 -10
  382. package/src/register-external.ts +5 -5
  383. package/src/templates/form.ts +9 -11
  384. package/src/templates/jdd-component.ts +1 -1
  385. package/src/templates/jdd-editor.ts +2 -4
  386. package/src/templates/list.ts +0 -1
  387. package/src/templates/multiform.ts +4 -4
  388. package/src/templates/page.ts +1 -6
  389. package/src/templates/shared/collection-create-form.ts +34 -71
  390. package/src/templates/shared/collection-edit-form.ts +46 -108
  391. package/src/templates/shared/collection-list.ts +13 -21
  392. package/src/templates/shared/item-delete.ts +0 -1
  393. package/src/templates/shared/shared-crud-form-fields.ts +38 -177
  394. package/src/templates/templates.ts +5 -1
  395. package/src/test_utils/exec_async.ts +3 -4
  396. package/src/test_utils/test-on-real-app.ts +13 -14
  397. package/src/utils/browser-creator.js +0 -1
  398. package/src/utils/exec.ts +0 -1
  399. package/src/utils/extract-fields-from-collection.ts +76 -25
  400. package/src/utils/input-wrapper.ts +1 -1
  401. package/src/utils/make-slug.ts +1 -1
  402. package/src/utils/wrap-attributes.ts +17 -0
  403. package/src/utils/write-file.ts +1 -1
  404. package/.eslintrc.cjs +0 -39
  405. package/lib/add-verbose-crud.js +0 -119
  406. package/lib/crud-field-snippets.js +0 -52
  407. package/lib/find-css-includes.js +0 -3
  408. package/lib/forms/controls/reverse-single-reference.js +0 -1
  409. package/lib/forms/fields/enum-multiple.js +0 -47
  410. package/lib/forms/fields/enum-multiple.test.js +0 -27
  411. package/lib/forms/fields/enum.js +0 -41
  412. package/lib/forms/fields/enum.test.js +0 -21
  413. package/lib/forms/fields/reverse-single-reference.js +0 -17
  414. package/lib/templates/shared/handlers/boolean.js +0 -14
  415. package/lib/templates/shared/handlers/date.js +0 -8
  416. package/lib/templates/shared/handlers/deep-reverse-single-reference.js +0 -209
  417. package/lib/templates/shared/handlers/default.js +0 -49
  418. package/lib/templates/shared/handlers/enum.js +0 -19
  419. package/lib/templates/shared/handlers/file.js +0 -23
  420. package/lib/templates/shared/handlers/image.js +0 -32
  421. package/lib/templates/shared/handlers/int.js +0 -11
  422. package/lib/templates/shared/handlers/jdd.js +0 -10
  423. package/lib/templates/shared/handlers/single-reference.js +0 -12
  424. package/lib/templates/shared/handlers/structured-array.js +0 -33
  425. package/src/add-verbose-crud.ts +0 -138
  426. package/src/crud-field-snippets.ts +0 -57
  427. package/src/find-css-includes.ts +0 -3
  428. package/src/forms/controls/reverse-single-reference.ts +0 -50
  429. package/src/forms/fields/enum-multiple.test.ts +0 -31
  430. package/src/forms/fields/enum-multiple.ts +0 -62
  431. package/src/forms/fields/enum.test.ts +0 -25
  432. package/src/forms/fields/enum.ts +0 -56
  433. package/src/forms/fields/reverse-single-reference.ts +0 -20
  434. package/src/templates/shared/handlers/boolean.ts +0 -18
  435. package/src/templates/shared/handlers/date.ts +0 -12
  436. package/src/templates/shared/handlers/deep-reverse-single-reference.ts +0 -244
  437. package/src/templates/shared/handlers/default.ts +0 -64
  438. package/src/templates/shared/handlers/enum.ts +0 -23
  439. package/src/templates/shared/handlers/file.ts +0 -27
  440. package/src/templates/shared/handlers/image.ts +0 -45
  441. package/src/templates/shared/handlers/int.ts +0 -15
  442. package/src/templates/shared/handlers/jdd.ts +0 -14
  443. package/src/templates/shared/handlers/single-reference.ts +0 -16
  444. package/src/templates/shared/handlers/structured-array.ts +0 -42
@@ -0,0 +1,130 @@
1
+ /* eslint @typescript-eslint/no-explicit-any: off */
2
+ import { Context } from "koa";
3
+ import { CollectionItem, FieldTypes as SealiousFieldTypes } from "sealious";
4
+ import { FormDataValue, FormData } from "../form-types.js";
5
+ import { CheckboxedListField } from "./checkboxed-list.js";
6
+ import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
7
+ import { wrapKeyName } from "../../utils/wrap-attributes.js";
8
+
9
+ export class DeepReverseSingleReferenceList extends CheckboxedListField<
10
+ false,
11
+ string
12
+ > {
13
+ public item_label_getter: (item: CollectionItem<any>) => string = (item) =>
14
+ item.get("name") as string;
15
+
16
+ constructor(
17
+ public sealious_field: SealiousFieldTypes.DeepReverseSingleReference
18
+ ) {
19
+ super(false, async (ctx: Context) => {
20
+ const { items } = await ctx.$app.collections[
21
+ sealious_field.target_collection
22
+ ]
23
+ .list(ctx.$context)
24
+ .fetch();
25
+
26
+ return items.map((s) => ({
27
+ label: this.item_label_getter(s),
28
+ value: s.id,
29
+ }));
30
+ });
31
+ }
32
+
33
+ setItemLabelGetter(getter: (item: CollectionItem<any>) => string) {
34
+ this.item_label_getter = getter;
35
+ }
36
+
37
+ getSealiousCreateValue(): never {
38
+ throw new Error(
39
+ "This field is not set directly through field value, but instead relies on postSealiousCreate and postSealiousEdit"
40
+ );
41
+ }
42
+
43
+ async postSealiousCreate(
44
+ ctx: Context,
45
+ created_item: CollectionItem<any>,
46
+ form_data: FormData
47
+ ) {
48
+ // First, we remove links refering to current item
49
+ const { items: existing_links } = await ctx.$app.collections[
50
+ this.sealious_field.intermediary_collection
51
+ ]
52
+ .list(ctx.$context)
53
+ .filter({
54
+ [this.sealious_field.referencing_field]: created_item.id,
55
+ })
56
+ .fetch();
57
+ const { parsed: value } = await this.getParsedValue(
58
+ ctx,
59
+ form_data.raw_values,
60
+ false
61
+ );
62
+ const should_exist_ids = Object.entries(value || {})
63
+ .filter(([, value]) => value === "on")
64
+ .map(([key]) => key);
65
+ const to_delete = existing_links.filter(
66
+ (link) =>
67
+ !should_exist_ids.includes(
68
+ link.get(
69
+ this.sealious_field.intermediary_field_that_points_there
70
+ ) as string
71
+ )
72
+ );
73
+ const to_create_ids = should_exist_ids.filter(
74
+ (id) =>
75
+ !existing_links
76
+ .map((link) =>
77
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
78
+ link.get(
79
+ this.sealious_field
80
+ .intermediary_field_that_points_there
81
+ )
82
+ )
83
+ .includes(id)
84
+ );
85
+ await Promise.all(
86
+ to_delete.map((item) => {
87
+ return item.remove(ctx.$context);
88
+ })
89
+ );
90
+ // Then, we iterate over all selected values and insert appropriate missing links
91
+ const promises = to_create_ids.map(async (id) => {
92
+ await this.sealious_field
93
+ .getReferencingCollection()
94
+ .create(ctx.$context, {
95
+ [this.sealious_field.referencing_field]: created_item.id,
96
+ [this.sealious_field.intermediary_field_that_points_there]:
97
+ id,
98
+ });
99
+ });
100
+ await Promise.all(promises);
101
+ }
102
+
103
+ async postSealiousEdit(
104
+ ctx: Context,
105
+ edited_item: CollectionItem<any>,
106
+ value: FormData
107
+ ) {
108
+ return this.postSealiousCreate(ctx, edited_item, value);
109
+ }
110
+
111
+ async sealiousValueToForm(
112
+ _ctx: Context,
113
+ value: string[] | null
114
+ ): Promise<FormDataValue> {
115
+ return Object.fromEntries((value || []).map((id) => [id, "on"]));
116
+ }
117
+
118
+ generateFieldDeclaration(
119
+ _field_info: ExtractedFieldInfo,
120
+ vars: { form_field_types: string; sealious_field: string }
121
+ ): string {
122
+ return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
123
+ }
124
+
125
+ generateCreateValueGetter(field_info: ExtractedFieldInfo): string {
126
+ return `${wrapKeyName(
127
+ field_info.name
128
+ )}: undefined /* handled below in postSealiousCreate */`;
129
+ }
130
+ }
@@ -0,0 +1,213 @@
1
+ /* eslint @typescript-eslint/no-explicit-any: off */
2
+ import {
3
+ FieldTypes as SealiousFieldTypes,
4
+ Field as SealiousField,
5
+ CollectionItem,
6
+ } from "sealious";
7
+ import { Boolean, TextBasedSimpleField } from "./fields.js";
8
+ import { sealiousToFormField } from "./get-field-for-sealious.js";
9
+ import { Table } from "./table.js";
10
+ import { Table as TableControl } from "../controls/table.js";
11
+ import { Context } from "koa";
12
+ import { FormDataValue, FormData } from "../form-types.js";
13
+ import { FormControlContext } from "../controls/form-control.js";
14
+ import { HiddenInput } from "../controls/hidden-input.js";
15
+ import { FormField } from "./field.js";
16
+
17
+ function getReferencingFields(
18
+ sealious_field: SealiousFieldTypes.DeepReverseSingleReference
19
+ ): Record<string, SealiousField<unknown>> {
20
+ const referencing_collection =
21
+ sealious_field.collection.app.collections[
22
+ sealious_field.referencing_collection
23
+ ];
24
+ if (!referencing_collection) {
25
+ throw new Error(
26
+ "Unknown collection: " + sealious_field.referencing_collection
27
+ );
28
+ }
29
+ return referencing_collection.fields;
30
+ }
31
+
32
+ export class DeepReverseSingleReferenceTable extends Table<
33
+ Record<string, FormField>
34
+ > {
35
+ constructor(
36
+ public sealious_field: SealiousFieldTypes.DeepReverseSingleReference
37
+ ) {
38
+ super({
39
+ selected: new Boolean(false),
40
+ [sealious_field.referencing_field]: new TextBasedSimpleField(true),
41
+ [sealious_field.intermediary_field_that_points_there]:
42
+ new TextBasedSimpleField(true),
43
+ ...Object.fromEntries(
44
+ Object.values(getReferencingFields(sealious_field))
45
+ .filter(
46
+ (field) =>
47
+ !(
48
+ field instanceof
49
+ SealiousFieldTypes.SingleReference
50
+ )
51
+ )
52
+ .map((field) => [field.name, sealiousToFormField(field)])
53
+ ),
54
+ });
55
+ }
56
+
57
+ getControl(): TableControl<any> {
58
+ return new TableControl(this, {
59
+ label: this.name,
60
+ allow_adding: false,
61
+ subfield_controls: {
62
+ selected: this.columns.selected.getControl(),
63
+ [this.sealious_field.referencing_field]: new HiddenInput(
64
+ this.columns[this.sealious_field.referencing_field]
65
+ ),
66
+ [this.sealious_field.intermediary_field_that_points_there]:
67
+ new HiddenInput(
68
+ this.columns[
69
+ this.sealious_field.intermediary_field_that_points_there
70
+ ]
71
+ ),
72
+ ...Object.fromEntries(
73
+ Object.values(getReferencingFields(this.sealious_field))
74
+ .filter(
75
+ (field) =>
76
+ !(
77
+ field instanceof
78
+ SealiousFieldTypes.SingleReference
79
+ )
80
+ )
81
+ .map((field) => [
82
+ field.name,
83
+ this.columns[field.name].getControl(),
84
+ ])
85
+ ),
86
+ },
87
+ });
88
+ }
89
+
90
+ getSealiousCreateValue(_fctx: FormControlContext): Promise<unknown> {
91
+ throw new Error("Method not implemented.");
92
+ }
93
+
94
+ async postSealiousCreate(
95
+ ctx: Context,
96
+ created_item: CollectionItem<any>,
97
+ form_data: FormData
98
+ ): Promise<void> {
99
+ // First, we remove links refering to current item
100
+ const { items: to_delete } = await ctx.$app.collections[
101
+ "${toKebabCase(referencing_collection)}"
102
+ ]
103
+ .list(ctx.$context)
104
+ .filter({ "${referencing_field}": created_item.id })
105
+ .fetch();
106
+ await Promise.all(to_delete.map((item) => item.remove(ctx.$context)));
107
+
108
+ // Then, we iterate over all selected values and insert appropriate entries for the subcategories relation
109
+
110
+ const referencing_fields = getReferencingFields(this.sealious_field);
111
+
112
+ const { parsed: value } = await this.getParsedValue(
113
+ ctx,
114
+ form_data.raw_values,
115
+ false
116
+ );
117
+ const promises = (value || [])
118
+ .filter((s) => s.selected == true)
119
+ .map(async (link_info) => {
120
+ await ctx.$app.collections[
121
+ "${toKebabCase(referencing_collection)}"
122
+ ].create(ctx.$context, {
123
+ "${referencing_field}": created_item.id,
124
+ "${intermediary_field_that_points_there}": String(
125
+ link_info["${intermediary_field_that_points_there}"]
126
+ ),
127
+ ...Object.fromEntries(
128
+ Object.values(referencing_fields)
129
+ .filter(
130
+ (field) =>
131
+ !(
132
+ field instanceof
133
+ SealiousFieldTypes.SingleReference
134
+ )
135
+ )
136
+ .map((field) => [field.name, link_info[field.name]])
137
+ ),
138
+ });
139
+ });
140
+
141
+ await Promise.all(promises);
142
+ }
143
+
144
+ postSealiousEdit(
145
+ ctx: Context,
146
+ edited_item: CollectionItem<any>,
147
+ form_data: FormData
148
+ ): Promise<void> {
149
+ return this.postSealiousCreate(ctx, edited_item, form_data);
150
+ }
151
+
152
+ async sealiousValueToForm(
153
+ ctx: Context,
154
+ _value: string[],
155
+ item: CollectionItem<any>
156
+ ): Promise<FormDataValue> {
157
+ // convert from an array to array-like object
158
+ const referencing_fields = getReferencingFields(this.sealious_field);
159
+ return Object.fromEntries(
160
+ await Promise.all([
161
+ this.sealious_field.collection.list(ctx.$context).fetch(),
162
+ this.sealious_field
163
+ .getReferencingCollection()
164
+ .list(ctx.$context)
165
+ .fetch(),
166
+ ]).then(([{ items: targets }, { items: links }]) =>
167
+ targets
168
+ .map((target) => {
169
+ return {
170
+ selected: (
171
+ (item.get(
172
+ this.sealious_field.name
173
+ ) as string[]) || []
174
+ ).includes(target.id)
175
+ ? "on"
176
+ : "off",
177
+ [this.sealious_field.referencing_field]: item.id,
178
+ [this.sealious_field
179
+ .intermediary_field_that_points_there]:
180
+ target.id,
181
+ ...Object.fromEntries(
182
+ Object.values(referencing_fields)
183
+ .filter(
184
+ (field) =>
185
+ !(
186
+ field instanceof
187
+ SealiousFieldTypes.SingleReference
188
+ )
189
+ )
190
+ .map((field) => [
191
+ field.name,
192
+ links
193
+ .find(
194
+ (e) =>
195
+ e.get(
196
+ this.sealious_field
197
+ .intermediary_field_that_points_there
198
+ ) == target.id &&
199
+ e.get(
200
+ this.sealious_field
201
+ .referencing_field
202
+ ) == item.id
203
+ )
204
+ ?.get("rank") || 0,
205
+ ])
206
+ ),
207
+ };
208
+ })
209
+ .entries()
210
+ )
211
+ ) as FormDataValue;
212
+ }
213
+ }
@@ -1,8 +1,9 @@
1
1
  import { predicates } from "@sealcode/ts-predicates";
2
2
  import { RegExpField } from "./regexp.js";
3
+ import { SimpleInput } from "../controls/controls.js";
3
4
 
4
5
  export class EmailField<
5
- Required extends boolean
6
+ Required extends boolean,
6
7
  > extends RegExpField<Required> {
7
8
  predicate = predicates.string;
8
9
  constructor(
@@ -17,4 +18,12 @@ export class EmailField<
17
18
  default_value
18
19
  );
19
20
  }
21
+
22
+ setErrorMessage(message: string) {
23
+ this.error_message = message;
24
+ }
25
+
26
+ public getControl(): SimpleInput {
27
+ return new SimpleInput(this, { label: this.name, type: "email" });
28
+ }
20
29
  }
@@ -0,0 +1,48 @@
1
+ import { FieldTypes as SealiousFieldTypes } from "sealious";
2
+ import { Context } from "koa";
3
+ import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
4
+ import { CheckboxedListField } from "./checkboxed-list.js";
5
+ import { FormControlContext } from "../controls/form-control.js";
6
+ import { FormDataValue } from "../form-types.js";
7
+
8
+ export class EnumMultipleSealious<
9
+ Values extends string,
10
+ > extends CheckboxedListField<boolean, Values> {
11
+ public sealious_field: SealiousFieldTypes.EnumMultiple<Values>;
12
+
13
+ constructor(sealious_field: SealiousFieldTypes.EnumMultiple<Values>) {
14
+ super(sealious_field.required, async (ctx: Context) =>
15
+ (await sealious_field.getAllowedValues(ctx.$context)).map(
16
+ (value: Values) => ({ value, label: value })
17
+ )
18
+ );
19
+ this.sealious_field = sealious_field;
20
+ }
21
+
22
+ generateFieldDeclaration(
23
+ field_info: ExtractedFieldInfo,
24
+ vars: { form_field_types: string; sealious_field: string }
25
+ ): string {
26
+ return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
27
+ }
28
+
29
+ async getSealiousCreateValue(fctx: FormControlContext): Promise<Values[]> {
30
+ const { parsed } = await this.getParsedValue(
31
+ fctx.ctx,
32
+ fctx.data.raw_values
33
+ );
34
+ const result = Object.entries(parsed || {})
35
+ .filter(([, value]) => value == "on")
36
+ .map(([key]) => key as Values);
37
+ return result;
38
+ }
39
+
40
+ async sealiousValueToForm(
41
+ ctx: Context,
42
+ sealious_value: Values[] | null
43
+ ): Promise<FormDataValue> {
44
+ return Object.fromEntries(
45
+ (sealious_value || []).map((key) => [key, "on"])
46
+ );
47
+ }
48
+ }
@@ -2,7 +2,7 @@ import { Field } from "sealious";
2
2
  import { PickFromListField } from "./pick-from-list.js";
3
3
 
4
4
  export class ExistingSealiousValue<
5
- Required extends boolean
5
+ Required extends boolean,
6
6
  > extends PickFromListField<Required> {
7
7
  constructor(required: Required, field: Field<unknown>) {
8
8
  super(required, async (ctx) => {
@@ -7,7 +7,7 @@ import { mount } from "../../mount.js";
7
7
  import { Form } from "../form.js";
8
8
  import { getBrowser } from "../../utils/browser-creator.js";
9
9
  import assert from "assert";
10
- import { SimpleFormField } from "./simple-form-field.js";
10
+ import { TextBasedSimpleField } from "./simple-form-field.js";
11
11
  import { SimpleInput } from "../controls/simple-input.js";
12
12
  import { FormData } from "../form-types.js";
13
13
  import { Boolean } from "./boolean.js";
@@ -25,12 +25,12 @@ describe("basic field", () => {
25
25
 
26
26
  it("sends the values", async () => {
27
27
  const port = await getPort();
28
- console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
28
+ console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
29
29
  const app = new Koa();
30
30
  const router = new Router();
31
31
 
32
32
  const fields = {
33
- text: new SimpleFormField(true),
33
+ text: new TextBasedSimpleField(true),
34
34
  };
35
35
 
36
36
  let received_values: unknown;
@@ -44,7 +44,7 @@ describe("basic field", () => {
44
44
 
45
45
  async onSubmit(ctx: Context, data: FormData) {
46
46
  received_values = await this.getParsedValues(ctx);
47
- const { parsed: email } = await this.fields.text.getValue(
47
+ const { parsed: email } = await this.fields.text.getParsedValue(
48
48
  ctx,
49
49
  data.raw_values
50
50
  );
@@ -68,7 +68,7 @@ describe("basic field", () => {
68
68
 
69
69
  it("Doesn't call `isValueValid` and `parse` if the value is empty", async () => {
70
70
  const port = await getPort();
71
- console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
71
+ console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
72
72
  const app = new Koa();
73
73
  const router = new Router();
74
74
 
@@ -76,7 +76,7 @@ describe("basic field", () => {
76
76
  let parse_called = false;
77
77
 
78
78
  const fields = {
79
- text: new (class MockField extends SimpleFormField<false> {
79
+ text: new (class MockField extends TextBasedSimpleField<false> {
80
80
  public async isValueValid() {
81
81
  is_value_valid_called = true;
82
82
  return true as any;
@@ -120,14 +120,14 @@ describe("basic field", () => {
120
120
 
121
121
  it("Accepts a form where non-required values are empty", async () => {
122
122
  const port = await getPort();
123
- console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
123
+ console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
124
124
  const app = new Koa();
125
125
  const router = new Router();
126
126
 
127
127
  let submit_called = false;
128
128
 
129
129
  const fields = {
130
- text: new SimpleFormField(false),
130
+ text: new TextBasedSimpleField(false),
131
131
  checkbox: new Boolean(false),
132
132
  };
133
133
 
@@ -1,10 +1,21 @@
1
+ /* eslint @typescript-eslint/no-unused-vars: off, @typescript-eslint/no-explicit-any: off */
1
2
  import { Predicate, predicates } from "@sealcode/ts-predicates";
2
3
  import { Context } from "koa";
4
+ import { Collection, CollectionItem } from "sealious";
3
5
  import { t } from "../../utils/translate.js";
4
- import { FormDataValue } from "../form-types.js";
6
+ import { FormControl, FormControlContext } from "../controls/form-control.js";
7
+ import { FormDataValue, FormData } from "../form-types.js";
8
+ import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
9
+ import { wrapAttribute, wrapKeyName } from "../../utils/wrap-attributes.js";
5
10
 
6
11
  export type FormFieldValidationResponse = { valid: boolean; message: string };
7
12
 
13
+ export type FormDisplayInfo<C extends Collection> = {
14
+ field: keyof C["fields"];
15
+ label: string;
16
+ format?: (value: unknown, item: CollectionItem<C>) => JSX.Element;
17
+ };
18
+
8
19
  export type FormFieldValidationFn<ValueType> = (
9
20
  ctx: Context,
10
21
  value: ValueType,
@@ -13,9 +24,10 @@ export type FormFieldValidationFn<ValueType> = (
13
24
 
14
25
  export type FieldParsedValue<T> = T extends FormField<infer R> ? R : never;
15
26
 
16
- export type GetPredicate<F extends FormField> = F extends FormField<true>
17
- ? F["predicate"]
18
- : F["predicate"] | typeof predicates.undefined;
27
+ export type GetPredicate<F extends FormField> =
28
+ F extends FormField<true>
29
+ ? F["predicate"]
30
+ : F["predicate"] | typeof predicates.undefined;
19
31
 
20
32
  // for quickly testing GetPredicate conditonally applying the undefined predicate:
21
33
  // const f = new SimpleFormField(true);
@@ -49,15 +61,20 @@ export type FieldParseResult<T> =
49
61
 
50
62
  export abstract class FormField<
51
63
  Required extends boolean = boolean,
52
- ParsedValue = unknown
64
+ ParsedValue = unknown,
65
+ DefaultFormControl extends FormControl = FormControl,
66
+ SealiousValue = any,
53
67
  > {
54
68
  name: string;
55
69
  constructor(public readonly required: Required) {}
56
70
  predicate: Predicate = predicates.unknown;
57
71
  mapToFilter: (parsed: ParsedValue) => unknown = (value) => value;
58
72
 
59
- async init(fieldname: string): Promise<void> {
60
- this.name = fieldname;
73
+ async init(): Promise<void> {}
74
+
75
+ setName(name: string): this {
76
+ this.name = name;
77
+ return this;
61
78
  }
62
79
 
63
80
  public async _validate(
@@ -100,7 +117,7 @@ export abstract class FormField<
100
117
  raw_value: FormDataValue
101
118
  ): Promise<FieldParseResult<ParsedValue>>;
102
119
 
103
- async getValue(
120
+ async getParsedValue(
104
121
  ctx: Context,
105
122
  all_form_values: Record<string, FormDataValue>,
106
123
  validate: true
@@ -110,7 +127,7 @@ export abstract class FormField<
110
127
  parsed: ParsedValue | null;
111
128
  raw: FormDataValue;
112
129
  }>;
113
- async getValue(
130
+ async getParsedValue(
114
131
  ctx: Context,
115
132
  all_form_values: Record<string, FormDataValue>,
116
133
  validate?: false
@@ -119,7 +136,7 @@ export abstract class FormField<
119
136
  parsed: ParsedValue | null;
120
137
  raw: FormDataValue;
121
138
  }>;
122
- async getValue(
139
+ async getParsedValue(
123
140
  ctx: Context,
124
141
  all_form_values: Record<string, FormDataValue>,
125
142
  validate = false
@@ -176,7 +193,77 @@ export abstract class FormField<
176
193
  ctx: Context,
177
194
  data: Record<string, FormDataValue>
178
195
  ): Promise<unknown> {
179
- const { parsed } = await this.getValue(ctx, data);
196
+ const { parsed } = await this.getParsedValue(ctx, data);
180
197
  return parsed;
181
198
  }
199
+
200
+ abstract getControl(): DefaultFormControl;
201
+
202
+ getSealiousCreateValue(fctx: FormControlContext): Promise<SealiousValue> {
203
+ throw new Error("This field does not have a default sealious mapping");
204
+ }
205
+
206
+ sealiousValueToForm(
207
+ ctx: Context,
208
+ sealiousValue: SealiousValue | null,
209
+ item: CollectionItem<any>
210
+ ): Promise<FormDataValue> {
211
+ throw new Error("This field does not have a default sealious mapping");
212
+ }
213
+
214
+ async postSealiousCreate(
215
+ ctx: Context,
216
+ created_item: CollectionItem<any>,
217
+ form_data: FormData
218
+ ): Promise<void> {}
219
+
220
+ async postSealiousEdit(
221
+ ctx: Context,
222
+ edited_item: CollectionItem<any>,
223
+ form_data: FormData
224
+ ): Promise<void> {}
225
+
226
+ generateFieldDeclaration(
227
+ field_info: ExtractedFieldInfo,
228
+ vars: { form_field_types: string; sealious_field: string }
229
+ ): string {
230
+ return `new ${vars.form_field_types}.${this.constructor.name}(${String(
231
+ field_info.is_required
232
+ )})`;
233
+ }
234
+
235
+ generateCreateValueGetter(
236
+ field_info: ExtractedFieldInfo,
237
+ vars: {
238
+ form_field_types: string;
239
+ sealious_field: string;
240
+ form_fields: string;
241
+ }
242
+ ): string {
243
+ return `${wrapKeyName(field_info.name)}: await ${
244
+ vars.form_fields
245
+ }${wrapAttribute(field_info.name)}.getSealiousCreateValue(fctx)`;
246
+ }
247
+
248
+ generateInitialValue(
249
+ field_info: ExtractedFieldInfo,
250
+ vars: {
251
+ form_field_types: string;
252
+ form_fields: string;
253
+ }
254
+ ): string {
255
+ return `${wrapKeyName(field_info.name)}: await ${
256
+ vars.form_fields
257
+ }${wrapAttribute(field_info.name)}.sealiousValueToForm(ctx, item.get("${
258
+ field_info.name
259
+ }"))`;
260
+ }
261
+
262
+ generateImportsForFieldList(field_info: ExtractedFieldInfo): {
263
+ what: string;
264
+ from: string;
265
+ as?: string;
266
+ }[] {
267
+ return [];
268
+ }
182
269
  }
@@ -1,16 +1,31 @@
1
- export * from "./simple-form-field.js";
1
+ export * from "./boolean.js";
2
2
  export * from "./checkboxed-list.js";
3
3
  export * from "./collection-field.js";
4
- export * from "./number.js";
5
- export * from "./pick-from-list.js";
6
- export * from "./regexp.js";
4
+ export * from "./color.js";
5
+ export * from "./coordinates.js";
6
+ export * from "./date.js";
7
+ export * from "./datetime.js";
8
+ export * from "./deep-reverse-single-reference-list.js";
9
+ export * from "./deep-reverse-single-reference-table.js";
7
10
  export * from "./email.js";
8
- export * from "./enum.js";
9
- export * from "./boolean.js";
10
- export * from "./enum-multiple.js";
11
+ export * from "./enum-multiple-sealious.js";
11
12
  export * from "./existing-sealious-value.js";
12
13
  export * from "./file.js";
14
+ export * from "./float.js";
15
+ export * from "./html.js";
16
+ export * from "./image.js";
17
+ export * from "./int.js";
18
+ export * from "./json.js";
19
+ export * from "./markdown.js";
13
20
  export * from "./multiple-files.js";
14
- export * from "./reverse-single-reference.js";
21
+ export * from "./number.js";
22
+ export * from "./password.js";
23
+ export * from "./pick-from-list-sealious.js";
24
+ export * from "./pick-from-list.js";
25
+ export * from "./regexp.js";
26
+ export * from "./simple-form-field.js";
27
+ export * from "./single-reference.js";
15
28
  export * from "./structured-array.js";
16
29
  export * from "./table.js";
30
+ export * from "./text.js";
31
+ export * from "./url.js";