@sealcode/sealgen 0.18.8 → 0.19.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 (374) hide show
  1. package/.eslintrc.cjs +7 -2
  2. package/.xunit +75 -0
  3. package/@types/add-crud.d.sync-conflict-20250918-184311-TFDLWFG.ts +1 -0
  4. package/@types/builders/colors-builder.d.sync-conflict-20250918-184323-TFDLWFG.ts +10 -0
  5. package/@types/builders/colors-builder.d.ts +1 -1
  6. package/@types/builders/fonts-builder.d.sync-conflict-20250918-184322-TFDLWFG.ts +7 -0
  7. package/@types/builders/fonts-builder.d.ts +1 -1
  8. package/@types/controllers/table-add-button.d.ts +6 -0
  9. package/@types/controllers/table-add-button.stimulus.d.ts +6 -0
  10. package/@types/crud-field-snippets.d.sync-conflict-20250918-184323-TFDLWFG.ts +1 -0
  11. package/@types/crud-field-snippets.d.ts +1 -3
  12. package/@types/forms/controls/array.d.sync-conflict-20250918-184306-TFDLWFG.ts +33 -0
  13. package/@types/forms/controls/array.d.ts +1 -2
  14. package/@types/forms/controls/array.sync-conflict-20250918-222045-TFDLWFG.d.ts +33 -0
  15. package/@types/forms/controls/autocomplete.d.sync-conflict-20250918-222042-TFDLWFG.ts +22 -0
  16. package/@types/forms/controls/autocomplete.d.ts +1 -1
  17. package/@types/forms/controls/checkbox-group.d.sync-conflict-20250918-184319-TFDLWFG.ts +21 -0
  18. package/@types/forms/controls/checkbox-group.d.ts +3 -3
  19. package/@types/forms/controls/checkboxed-list-input.d.sync-conflict-20250918-184323-TFDLWFG.ts +21 -0
  20. package/@types/forms/controls/checkboxed-list-input.d.ts +3 -3
  21. package/@types/forms/controls/controls.d.ts +2 -2
  22. package/@types/forms/controls/derived-frame.d.sync-conflict-20250918-184314-TFDLWFG.ts +19 -0
  23. package/@types/forms/controls/derived-frame.d.ts +0 -1
  24. package/@types/forms/controls/dropdown.d.sync-conflict-20250918-222044-TFDLWFG.ts +30 -0
  25. package/@types/forms/controls/dropdown.d.ts +1 -1
  26. package/@types/forms/controls/file.d.sync-conflict-20250918-222045-TFDLWFG.ts +13 -0
  27. package/@types/forms/controls/file.d.ts +1 -2
  28. package/@types/forms/controls/form-control.d.sync-conflict-20250918-184322-TFDLWFG.ts +19 -0
  29. package/@types/forms/controls/form-control.d.sync-conflict-20250918-222046-TFDLWFG.ts +19 -0
  30. package/@types/forms/controls/form-control.d.ts +7 -3
  31. package/@types/forms/controls/image.d.ts +19 -0
  32. package/@types/forms/controls/image.test.d.ts +1 -0
  33. package/@types/forms/controls/multiple-files.d.sync-conflict-20250918-184318-TFDLWFG.ts +42 -0
  34. package/@types/forms/controls/multiple-files.d.ts +3 -0
  35. package/@types/forms/controls/multiple-images.d.ts +19 -0
  36. package/@types/forms/controls/number.d.sync-conflict-20250918-222046-TFDLWFG.ts +13 -0
  37. package/@types/forms/controls/number.d.ts +1 -1
  38. package/@types/forms/controls/photo.d.sync-conflict-20250918-184321-TFDLWFG.ts +19 -0
  39. package/@types/forms/controls/photo.d.ts +3 -5
  40. package/@types/forms/controls/simple-input.d.sync-conflict-20250918-184310-TFDLWFG.ts +33 -0
  41. package/@types/forms/controls/simple-input.d.sync-conflict-20250918-222042-TFDLWFG.ts +33 -0
  42. package/@types/forms/controls/simple-input.d.ts +5 -4
  43. package/@types/forms/controls/simple-input.sync-conflict-20250918-222045-TFDLWFG.d.ts +33 -0
  44. package/@types/forms/controls/single-reference.d.ts +3 -2
  45. package/@types/forms/controls/table.d.sync-conflict-20250918-184302-TFDLWFG.ts +39 -0
  46. package/@types/forms/controls/table.d.ts +8 -2
  47. package/@types/forms/controls/table.sync-conflict-20250918-222042-TFDLWFG.d.ts +39 -0
  48. package/@types/forms/controls/textarea.d.sync-conflict-20250918-222045-TFDLWFG.ts +25 -0
  49. package/@types/forms/controls/textarea.d.ts +3 -3
  50. package/@types/forms/fields/boolean.d.sync-conflict-20250918-184325-TFDLWFG.ts +22 -0
  51. package/@types/forms/fields/boolean.d.ts +6 -1
  52. package/@types/forms/fields/boolean.sync-conflict-20250918-222042-TFDLWFG.d.ts +22 -0
  53. package/@types/forms/fields/checkboxed-list.d.sync-conflict-20250918-184325-TFDLWFG.ts +23 -0
  54. package/@types/forms/fields/checkboxed-list.d.ts +3 -1
  55. package/@types/forms/fields/collection-field.d.sync-conflict-20250918-184319-TFDLWFG.ts +22 -0
  56. package/@types/forms/fields/collection-field.d.sync-conflict-20250918-222047-TFDLWFG.ts +22 -0
  57. package/@types/forms/fields/collection-field.d.ts +8 -1
  58. package/@types/forms/fields/color.d.ts +4 -0
  59. package/@types/forms/fields/coordinates.d.sync-conflict-20250918-222044-TFDLWFG.ts +14 -0
  60. package/@types/forms/fields/coordinates.d.ts +14 -0
  61. package/@types/forms/fields/date.d.ts +13 -0
  62. package/@types/forms/fields/datetime.d.sync-conflict-20250918-222050-TFDLWFG.ts +4 -0
  63. package/@types/forms/fields/datetime.d.ts +14 -0
  64. package/@types/forms/fields/deep-reverse-single-reference-list.d.ts +24 -0
  65. package/@types/forms/fields/deep-reverse-single-reference-table.d.ts +16 -0
  66. package/@types/forms/fields/email.d.sync-conflict-20250918-184303-TFDLWFG.ts +8 -0
  67. package/@types/forms/fields/email.d.ts +3 -0
  68. package/@types/forms/fields/enum-multiple-sealious.d.ts +16 -0
  69. package/@types/forms/fields/enum-multiple-sealious.sync-conflict-20250918-222047-TFDLWFG.d.ts +16 -0
  70. package/@types/forms/fields/field.d.sync-conflict-20250918-184306-TFDLWFG.ts +70 -0
  71. package/@types/forms/fields/field.d.ts +37 -5
  72. package/@types/forms/fields/fields.d.sync-conflict-20250918-184314-TFDLWFG.ts +29 -0
  73. package/@types/forms/fields/fields.d.ts +23 -8
  74. package/@types/forms/fields/file.d.sync-conflict-20250918-184310-TFDLWFG.ts +23 -0
  75. package/@types/forms/fields/file.d.sync-conflict-20250918-222046-TFDLWFG.ts +23 -0
  76. package/@types/forms/fields/file.d.ts +11 -5
  77. package/@types/forms/fields/file.sync-conflict-20250918-222049-TFDLWFG.d.ts +23 -0
  78. package/@types/forms/fields/float.d.ts +4 -0
  79. package/@types/forms/fields/get-field-for-sealious.d.sync-conflict-20250918-222046-TFDLWFG.ts +29 -0
  80. package/@types/forms/fields/get-field-for-sealious.d.ts +31 -0
  81. package/@types/forms/fields/get-field-for-sealious.sync-conflict-20250918-222042-TFDLWFG.d.ts +29 -0
  82. package/@types/forms/fields/html.d.ts +6 -0
  83. package/@types/forms/fields/image.d.sync-conflict-20250918-222042-TFDLWFG.ts +5 -0
  84. package/@types/forms/fields/image.d.ts +5 -0
  85. package/@types/forms/fields/int.d.ts +6 -0
  86. package/@types/forms/fields/json.d.ts +13 -0
  87. package/@types/forms/fields/markdown.d.ts +6 -0
  88. package/@types/forms/fields/multiple-files.d.sync-conflict-20250918-184304-TFDLWFG.ts +16 -0
  89. package/@types/forms/fields/multiple-files.d.ts +3 -1
  90. package/@types/forms/fields/number.d.sync-conflict-20250918-184317-TFDLWFG.ts +25 -0
  91. package/@types/forms/fields/number.d.sync-conflict-20250918-222047-TFDLWFG.ts +25 -0
  92. package/@types/forms/fields/number.d.ts +3 -1
  93. package/@types/forms/fields/password.d.ts +6 -0
  94. package/@types/forms/fields/pick-from-list-sealious.d.ts +11 -0
  95. package/@types/forms/fields/pick-from-list.d.sync-conflict-20250918-184322-TFDLWFG.ts +15 -0
  96. package/@types/forms/fields/pick-from-list.d.ts +4 -3
  97. package/@types/forms/fields/proxy-field.d.sync-conflict-20250918-184307-TFDLWFG.ts +15 -0
  98. package/@types/forms/fields/proxy-field.d.ts +3 -1
  99. package/@types/forms/fields/regexp.d.sync-conflict-20250918-184305-TFDLWFG.ts +21 -0
  100. package/@types/forms/fields/regexp.d.sync-conflict-20250918-222045-TFDLWFG.ts +21 -0
  101. package/@types/forms/fields/regexp.d.ts +6 -1
  102. package/@types/forms/fields/regexp.sync-conflict-20250918-222047-TFDLWFG.d.ts +21 -0
  103. package/@types/forms/fields/simple-form-field.d.sync-conflict-20250918-184309-TFDLWFG.ts +29 -0
  104. package/@types/forms/fields/simple-form-field.d.sync-conflict-20250918-222044-TFDLWFG.ts +29 -0
  105. package/@types/forms/fields/simple-form-field.d.ts +23 -3
  106. package/@types/forms/fields/simple-form-field.sync-conflict-20250918-222049-TFDLWFG.d.ts +29 -0
  107. package/@types/forms/fields/single-reference.d.ts +19 -0
  108. package/@types/forms/fields/single-reference.sync-conflict-20250918-222043-TFDLWFG.d.ts +10 -0
  109. package/@types/forms/fields/structured-array.d.sync-conflict-20250918-184302-TFDLWFG.ts +27 -0
  110. package/@types/forms/fields/structured-array.d.sync-conflict-20250918-222049-TFDLWFG.ts +27 -0
  111. package/@types/forms/fields/structured-array.d.ts +19 -10
  112. package/@types/forms/fields/structured-array.sync-conflict-20250918-222047-TFDLWFG.d.ts +27 -0
  113. package/@types/forms/fields/table.d.sync-conflict-20250918-184303-TFDLWFG.ts +16 -0
  114. package/@types/forms/fields/table.d.ts +3 -0
  115. package/@types/forms/fields/text.d.ts +6 -0
  116. package/@types/forms/fields/url.d.ts +6 -0
  117. package/@types/forms/form-types.d.sync-conflict-20250918-222045-TFDLWFG.ts +26 -0
  118. package/@types/forms/form-types.d.ts +2 -0
  119. package/@types/forms/form.d.sync-conflict-20250918-184315-TFDLWFG.ts +32 -0
  120. package/@types/forms/form.d.sync-conflict-20250918-222049-TFDLWFG.ts +32 -0
  121. package/@types/forms/form.d.ts +10 -7
  122. package/@types/forms/form.sync-conflict-20250918-222049-TFDLWFG.d.ts +33 -0
  123. package/@types/forms/form.test.d.sync-conflict-20250918-184318-TFDLWFG.ts +6 -0
  124. package/@types/forms/form.test.d.sync-conflict-20250918-222047-TFDLWFG.ts +6 -0
  125. package/@types/forms/form.test.d.ts +2 -2
  126. package/@types/forms/multiform.d.sync-conflict-20250918-184308-TFDLWFG.ts +23 -0
  127. package/@types/forms/multiform.d.ts +1 -1
  128. package/@types/forms/multiform.sync-conflict-20250918-222044-TFDLWFG.d.ts +23 -0
  129. package/@types/index.d.sync-conflict-20250918-184316-TFDLWFG.ts +46 -0
  130. package/@types/index.d.ts +2 -2
  131. package/@types/mount.d.sync-conflict-20250918-184320-TFDLWFG.ts +6 -0
  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/page.d.sync-conflict-20250918-184320-TFDLWFG.ts +18 -0
  142. package/@types/page/props-parser.d.sync-conflict-20250918-184305-TFDLWFG.ts +15 -0
  143. package/@types/page/props-parser.d.ts +0 -1
  144. package/@types/page/stateful-page.d.sync-conflict-20250918-184326-TFDLWFG.ts +62 -0
  145. package/@types/templates/shared/shared-crud-form-fields.d.sync-conflict-20250918-184306-TFDLWFG.ts +1 -0
  146. package/@types/templates/shared/shared-crud-form-fields.d.ts +0 -67
  147. package/@types/test_utils/test-on-real-app.d.sync-conflict-20250918-184320-TFDLWFG.ts +26 -0
  148. package/@types/test_utils/test-on-real-app.d.ts +0 -1
  149. package/@types/utils/extract-fields-from-collection.d.sync-conflict-20250918-184312-TFDLWFG.ts +18 -0
  150. package/@types/utils/extract-fields-from-collection.d.ts +5 -1
  151. package/@types/utils/extract-fields-from-collection.sync-conflict-20250918-222045-TFDLWFG.d.ts +18 -0
  152. package/@types/utils/wrap-attributes.d.ts +3 -0
  153. package/README.md +5 -0
  154. package/assets/file-icon.svg +5 -0
  155. package/lib/add-crud.js +80 -89
  156. package/lib/add-list-route.test.js +1 -1
  157. package/lib/add-route.js +0 -7
  158. package/lib/build.js +3 -1
  159. package/lib/cli.js +2 -5
  160. package/lib/controllers/table-add-button.stimulus.js +35 -0
  161. package/lib/forms/controls/array.js +20 -16
  162. package/lib/forms/controls/big-radio-group.js +2 -2
  163. package/lib/forms/controls/checkbox-group.js +7 -7
  164. package/lib/forms/controls/checkboxed-list-input.js +9 -2
  165. package/lib/forms/controls/controls.js +2 -2
  166. package/lib/forms/controls/derived-frame.js +5 -1
  167. package/lib/forms/controls/derived.js +1 -1
  168. package/lib/forms/controls/dropdown.js +4 -1
  169. package/lib/forms/controls/editable-collection-subset.js +2 -2
  170. package/lib/forms/controls/file.js +26 -2
  171. package/lib/forms/controls/file.test.js +2 -2
  172. package/lib/forms/controls/hidden-input.js +4 -1
  173. package/lib/forms/controls/{photo.js → image.js} +6 -7
  174. package/lib/forms/controls/{photo.test.js → image.test.js} +6 -21
  175. package/lib/forms/controls/multiple-files.js +10 -1
  176. package/lib/forms/controls/{multiple-photos.js → multiple-images.js} +3 -3
  177. package/lib/forms/controls/simple-input.js +13 -12
  178. package/lib/forms/controls/single-reference.js +4 -0
  179. package/lib/forms/controls/table.js +66 -24
  180. package/lib/forms/controls/textarea.js +4 -2
  181. package/lib/forms/controls/tickable.js +13 -5
  182. package/lib/forms/fields/boolean.js +14 -0
  183. package/lib/forms/fields/checkboxed-list.js +4 -0
  184. package/lib/forms/fields/collection-field.js +9 -0
  185. package/lib/forms/fields/color.js +10 -0
  186. package/lib/forms/fields/coordinates.js +49 -0
  187. package/lib/forms/fields/date.js +34 -0
  188. package/lib/forms/fields/datetime.js +46 -0
  189. package/lib/forms/fields/deep-reverse-single-reference-list.js +81 -0
  190. package/lib/forms/fields/deep-reverse-single-reference-table.js +122 -0
  191. package/lib/forms/fields/email.js +7 -0
  192. package/lib/forms/fields/enum-multiple-sealious.js +32 -0
  193. package/lib/forms/fields/field.js +32 -4
  194. package/lib/forms/fields/field.test.js +5 -5
  195. package/lib/forms/fields/fields.js +23 -8
  196. package/lib/forms/fields/file.js +33 -9
  197. package/lib/forms/fields/file.test.js +4 -16
  198. package/lib/forms/fields/float.js +10 -0
  199. package/lib/forms/fields/get-field-for-sealious.js +213 -0
  200. package/lib/forms/fields/html.js +14 -0
  201. package/lib/forms/fields/image.js +13 -0
  202. package/lib/forms/fields/int.js +23 -0
  203. package/lib/forms/fields/json.js +31 -0
  204. package/lib/forms/fields/markdown.js +14 -0
  205. package/lib/forms/fields/multiple-files.js +4 -0
  206. package/lib/forms/fields/number.js +6 -0
  207. package/lib/forms/fields/password.js +13 -0
  208. package/lib/forms/fields/pick-from-list-sealious.js +17 -0
  209. package/lib/forms/fields/pick-from-list.js +6 -2
  210. package/lib/forms/fields/proxy-field.js +3 -0
  211. package/lib/forms/fields/regexp.js +14 -0
  212. package/lib/forms/fields/simple-form-field.js +60 -2
  213. package/lib/forms/fields/single-reference.js +44 -0
  214. package/lib/forms/fields/structured-array.js +63 -12
  215. package/lib/forms/fields/table.js +28 -1
  216. package/lib/forms/fields/text.js +17 -0
  217. package/lib/forms/fields/url.js +17 -0
  218. package/lib/forms/form.js +30 -13
  219. package/lib/forms/form.test.js +3 -4
  220. package/lib/forms/multiform.js +4 -2
  221. package/lib/forms/multiform.test.js +3 -3
  222. package/lib/generate-stimulus.js +1 -0
  223. package/lib/index.js +1 -0
  224. package/lib/make-hidden-inputs.js +1 -1
  225. package/lib/mount.js +11 -0
  226. package/lib/notifier.js +0 -1
  227. package/lib/page/list.js +15 -8
  228. package/lib/page/mountable-with-fields.js +14 -6
  229. package/lib/page/mountable-with-fields.test.js +1 -1
  230. package/lib/templates/form.js +8 -9
  231. package/lib/templates/multiform.js +4 -4
  232. package/lib/templates/page.js +0 -2
  233. package/lib/templates/shared/collection-create-form.js +28 -40
  234. package/lib/templates/shared/collection-edit-form.js +40 -77
  235. package/lib/templates/shared/collection-list.js +12 -20
  236. package/lib/templates/shared/shared-crud-form-fields.js +27 -95
  237. package/lib/test_utils/test-on-real-app.js +3 -3
  238. package/lib/utils/extract-fields-from-collection.js +60 -20
  239. package/lib/utils/make-slug.js +1 -1
  240. package/lib/utils/wrap-attributes.js +20 -0
  241. package/package.json +5 -4
  242. package/src/add-crud.ts +86 -97
  243. package/src/add-list-route.test.ts +1 -1
  244. package/src/add-route.ts +0 -7
  245. package/src/build.ts +3 -1
  246. package/src/cli.ts +3 -5
  247. package/src/controllers/table-add-button.stimulus.ts +35 -0
  248. package/src/forms/controls/array.ts +23 -20
  249. package/src/forms/controls/autocomplete.ts +1 -1
  250. package/src/forms/controls/big-radio-group.ts +2 -2
  251. package/src/forms/controls/checkbox-group.ts +9 -9
  252. package/src/forms/controls/checkboxed-list-input.ts +27 -15
  253. package/src/forms/controls/controls.ts +2 -2
  254. package/src/forms/controls/derived-frame.ts +5 -1
  255. package/src/forms/controls/derived.ts +1 -1
  256. package/src/forms/controls/dropdown.ts +5 -2
  257. package/src/forms/controls/editable-collection-subset.ts +2 -2
  258. package/src/forms/controls/file.test.ts +4 -2
  259. package/src/forms/controls/file.ts +31 -5
  260. package/src/forms/controls/form-control.ts +7 -2
  261. package/src/forms/controls/hidden-input.ts +4 -1
  262. package/src/forms/controls/{photo.test.ts → image.test.ts} +5 -22
  263. package/src/forms/controls/{photo.ts → image.ts} +3 -5
  264. package/src/forms/controls/multiple-files.ts +18 -1
  265. package/src/forms/controls/{multiple-photos.ts → multiple-images.ts} +1 -1
  266. package/src/forms/controls/number.ts +1 -1
  267. package/src/forms/controls/simple-input.ts +18 -34
  268. package/src/forms/controls/single-reference.ts +10 -2
  269. package/src/forms/controls/table.ts +90 -31
  270. package/src/forms/controls/textarea.ts +6 -4
  271. package/src/forms/controls/tickable.ts +13 -5
  272. package/src/forms/fields/boolean.ts +23 -1
  273. package/src/forms/fields/checkboxed-list.ts +11 -2
  274. package/src/forms/fields/collection-field.ts +16 -1
  275. package/src/forms/fields/color.ts +9 -0
  276. package/src/forms/fields/coordinates.ts +66 -0
  277. package/src/forms/fields/date.ts +50 -0
  278. package/src/forms/fields/datetime.ts +66 -0
  279. package/src/forms/fields/deep-reverse-single-reference-list.ts +136 -0
  280. package/src/forms/fields/deep-reverse-single-reference-table.ts +213 -0
  281. package/src/forms/fields/email.ts +9 -0
  282. package/src/forms/fields/enum-multiple-sealious.ts +48 -0
  283. package/src/forms/fields/field.test.ts +5 -5
  284. package/src/forms/fields/field.ts +94 -8
  285. package/src/forms/fields/fields.ts +23 -8
  286. package/src/forms/fields/file.test.ts +4 -16
  287. package/src/forms/fields/file.ts +43 -15
  288. package/src/forms/fields/float.ts +9 -0
  289. package/src/forms/fields/get-field-for-sealious.ts +304 -0
  290. package/src/forms/fields/html.ts +15 -0
  291. package/src/forms/fields/image.ts +12 -0
  292. package/src/forms/fields/int.ts +25 -0
  293. package/src/forms/fields/json.ts +48 -0
  294. package/src/forms/fields/markdown.ts +15 -0
  295. package/src/forms/fields/multiple-files.ts +10 -1
  296. package/src/forms/fields/number.ts +8 -1
  297. package/src/forms/fields/password.ts +17 -0
  298. package/src/forms/fields/pick-from-list-sealious.ts +22 -0
  299. package/src/forms/fields/pick-from-list.ts +7 -3
  300. package/src/forms/fields/proxy-field.ts +6 -1
  301. package/src/forms/fields/regexp.ts +27 -1
  302. package/src/forms/fields/simple-form-field.ts +95 -7
  303. package/src/forms/fields/single-reference.ts +62 -0
  304. package/src/forms/fields/structured-array.ts +115 -18
  305. package/src/forms/fields/table.ts +32 -1
  306. package/src/forms/fields/text.ts +18 -0
  307. package/src/forms/fields/url.ts +20 -0
  308. package/src/forms/form-types.ts +2 -0
  309. package/src/forms/form.test.ts +3 -4
  310. package/src/forms/form.ts +37 -16
  311. package/src/forms/forms.css +0 -85
  312. package/src/forms/multiform.test.ts +3 -3
  313. package/src/forms/multiform.ts +2 -0
  314. package/src/generate-stimulus.ts +1 -0
  315. package/src/index.ts +2 -1
  316. package/src/make-hidden-inputs.ts +1 -1
  317. package/src/mount.ts +14 -0
  318. package/src/notifier.ts +0 -1
  319. package/src/page/list.ts +15 -8
  320. package/src/page/mountable-with-fields.test.ts +1 -1
  321. package/src/page/mountable-with-fields.ts +18 -9
  322. package/src/register-external.ts +1 -1
  323. package/src/templates/form.ts +8 -9
  324. package/src/templates/multiform.ts +4 -4
  325. package/src/templates/page.ts +0 -2
  326. package/src/templates/shared/collection-create-form.ts +30 -66
  327. package/src/templates/shared/collection-edit-form.ts +41 -102
  328. package/src/templates/shared/collection-list.ts +12 -20
  329. package/src/templates/shared/item-delete.ts +0 -1
  330. package/src/templates/shared/shared-crud-form-fields.ts +37 -171
  331. package/src/test_utils/test-on-real-app.ts +4 -3
  332. package/src/utils/extract-fields-from-collection.ts +76 -25
  333. package/src/utils/make-slug.ts +1 -1
  334. package/src/utils/wrap-attributes.ts +17 -0
  335. package/lib/add-verbose-crud.js +0 -119
  336. package/lib/crud-field-snippets.js +0 -52
  337. package/lib/find-css-includes.js +0 -3
  338. package/lib/forms/controls/reverse-single-reference.js +0 -1
  339. package/lib/forms/fields/enum-multiple.js +0 -47
  340. package/lib/forms/fields/enum-multiple.test.js +0 -27
  341. package/lib/forms/fields/enum.js +0 -41
  342. package/lib/forms/fields/enum.test.js +0 -21
  343. package/lib/forms/fields/reverse-single-reference.js +0 -17
  344. package/lib/templates/shared/handlers/boolean.js +0 -14
  345. package/lib/templates/shared/handlers/date.js +0 -8
  346. package/lib/templates/shared/handlers/deep-reverse-single-reference.js +0 -209
  347. package/lib/templates/shared/handlers/default.js +0 -49
  348. package/lib/templates/shared/handlers/enum.js +0 -19
  349. package/lib/templates/shared/handlers/file.js +0 -23
  350. package/lib/templates/shared/handlers/image.js +0 -32
  351. package/lib/templates/shared/handlers/int.js +0 -11
  352. package/lib/templates/shared/handlers/jdd.js +0 -10
  353. package/lib/templates/shared/handlers/single-reference.js +0 -12
  354. package/lib/templates/shared/handlers/structured-array.js +0 -33
  355. package/src/add-verbose-crud.ts +0 -138
  356. package/src/crud-field-snippets.ts +0 -57
  357. package/src/find-css-includes.ts +0 -3
  358. package/src/forms/controls/reverse-single-reference.ts +0 -50
  359. package/src/forms/fields/enum-multiple.test.ts +0 -31
  360. package/src/forms/fields/enum-multiple.ts +0 -62
  361. package/src/forms/fields/enum.test.ts +0 -25
  362. package/src/forms/fields/enum.ts +0 -56
  363. package/src/forms/fields/reverse-single-reference.ts +0 -20
  364. package/src/templates/shared/handlers/boolean.ts +0 -18
  365. package/src/templates/shared/handlers/date.ts +0 -12
  366. package/src/templates/shared/handlers/deep-reverse-single-reference.ts +0 -244
  367. package/src/templates/shared/handlers/default.ts +0 -64
  368. package/src/templates/shared/handlers/enum.ts +0 -23
  369. package/src/templates/shared/handlers/file.ts +0 -27
  370. package/src/templates/shared/handlers/image.ts +0 -45
  371. package/src/templates/shared/handlers/int.ts +0 -15
  372. package/src/templates/shared/handlers/jdd.ts +0 -14
  373. package/src/templates/shared/handlers/single-reference.ts +0 -16
  374. package/src/templates/shared/handlers/structured-array.ts +0 -42
@@ -0,0 +1,42 @@
1
+ import { ShapeToType } from "@sealcode/ts-predicates";
2
+ import { Context } from "koa";
3
+ import { FlatTemplatable } from "tempstream";
4
+ import { FieldMessages, FormControl, FormControlContext } from "../forms/controls/form-control.js";
5
+ import type { FieldsToShape, FormField } from "../forms/fields/field.js";
6
+ import type { FormDataValue, FormMessage, FormData } from "../forms/form-types.js";
7
+ import { Mountable } from "./mountable.js";
8
+ export type PageErrorMessage = {
9
+ type: "access" | "internal";
10
+ message: string;
11
+ };
12
+ export type Fields = Record<string, FormField<boolean, any>>;
13
+ type Resolved<T> = T extends Promise<infer X> ? X : never;
14
+ type ParsedValue<T extends FormField> = Resolved<ReturnType<T["getParsedValue"]>>["parsed"];
15
+ export declare abstract class MountableWithFields<F extends Fields = Fields> extends Mountable {
16
+ fields: F;
17
+ field_names_prefix: string;
18
+ form_id: string;
19
+ abstract controls: FormControl[];
20
+ constructor();
21
+ init(): void;
22
+ makeFormControlContext(ctx: Context, data: FormData, validate: boolean, field_messages: FieldMessages, field_name_prefix?: string, form_id?: string): FormControlContext;
23
+ validateValues(_ctx: Context, _data: Record<string, FormDataValue>): Promise<{
24
+ valid: boolean;
25
+ error: string;
26
+ }>;
27
+ getInitialValues(_ctx: Context): Promise<Record<string, FormDataValue>>;
28
+ validate(ctx: Context, values: Record<string, FormDataValue>): Promise<{
29
+ valid: boolean;
30
+ field_errors: Partial<Record<keyof Fields, string>>;
31
+ form_messages: FormMessage[];
32
+ }>;
33
+ renderControls(fctx: FormControlContext): FlatTemplatable;
34
+ renderError(_: Context, error: PageErrorMessage): Promise<FlatTemplatable>;
35
+ renderMessages(_: Context, data: FormData<keyof Fields>): FlatTemplatable;
36
+ abstract extractRawValues(ctx: Context): Promise<Record<string, FormDataValue>>;
37
+ getParsedValues(ctx: Context): Promise<{
38
+ [field in keyof F]: F[field] extends FormField<true> ? Exclude<ParsedValue<F[field]>, null> : ParsedValue<F[field]>;
39
+ }>;
40
+ getDatabaseValues(ctx: Context): Promise<ShapeToType<FieldsToShape<F>>>;
41
+ }
42
+ export {};
@@ -0,0 +1,10 @@
1
+ import Router from "@koa/router";
2
+ import { Context } from "koa";
3
+ export declare abstract class Mountable {
4
+ init(): void;
5
+ abstract mount(router: Router, path: string): void;
6
+ abstract canAccess(ctx: Context): Promise<{
7
+ canAccess: boolean;
8
+ message: string;
9
+ }>;
10
+ }
@@ -0,0 +1,18 @@
1
+ import Router from "@koa/router";
2
+ import { Context } from "koa";
3
+ import { FlatTemplatable } from "tempstream";
4
+ import type { FormDataValue } from "../forms/form-types.js";
5
+ import { Fields, MountableWithFields, PageErrorMessage } from "./mountable-with-fields.js";
6
+ import { PagePropsParser } from "./props-parser.js";
7
+ export declare abstract class Page<F extends Fields = Record<string, never>> extends MountableWithFields<F> {
8
+ propsParser: PagePropsParser<Record<keyof Fields, unknown>>;
9
+ controls: never[];
10
+ mount(router: Router, path: string): void;
11
+ canAccess(_: Context): Promise<{
12
+ canAccess: boolean;
13
+ message: string;
14
+ }>;
15
+ renderError(_: Context, error: PageErrorMessage): Promise<FlatTemplatable>;
16
+ abstract render(ctx: Context): Promise<FlatTemplatable>;
17
+ extractRawValues(ctx: Context): Promise<Record<string, FormDataValue>>;
18
+ }
@@ -0,0 +1,15 @@
1
+ import { Context } from "koa";
2
+ import { FormDataValue } from "../forms/form-types.js";
3
+ import type { BasePageProps } from "./list.js";
4
+ export type EncodedProps = Record<string, unknown>;
5
+ export declare abstract class PagePropsParser<PropsType> {
6
+ abstract decode(ctx: Context): Record<string, FormDataValue>;
7
+ abstract encode(props: Record<string, FormData>): EncodedProps;
8
+ abstract getHTMLInputName(prop_name: string): string;
9
+ overwriteProp(ctx: Context, new_props: Partial<PropsType>): EncodedProps;
10
+ }
11
+ export declare class AllQueryParams<PropsType extends BasePageProps> extends PagePropsParser<PropsType> {
12
+ decode(ctx: Context): Record<string, FormDataValue>;
13
+ encode(props: PropsType): Record<string, unknown>;
14
+ getHTMLInputName(prop_name: string): string;
15
+ }
@@ -1,4 +1,3 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  import { Context } from "koa";
3
2
  import { FormDataValue } from "../forms/form-types.js";
4
3
  import type { BasePageProps } from "./list.js";
@@ -0,0 +1,62 @@
1
+ import Router from "@koa/router";
2
+ import { Context } from "koa";
3
+ import { Templatable } from "tempstream";
4
+ import { Mountable } from "./mountable.js";
5
+ export type StatefulPageActionDescription<ActionName> = {
6
+ action: ActionName;
7
+ label?: string;
8
+ content?: string;
9
+ disabled?: boolean;
10
+ } | ActionName;
11
+ export type StateAndMetadata<State, Actions> = {
12
+ state: State;
13
+ inputs: Record<string, string>;
14
+ action: keyof Actions;
15
+ action_args: string;
16
+ } | {
17
+ state: State;
18
+ inputs: Record<string, string>;
19
+ action: null;
20
+ action_args: null;
21
+ $: Record<string, unknown>;
22
+ };
23
+ export type StatefulPageActionArgument<State extends Record<string, unknown>, Args extends unknown[] = unknown[]> = {
24
+ ctx: Context;
25
+ state: State;
26
+ inputs: Record<string, string>;
27
+ args: Args;
28
+ page: StatefulPage<any, any>;
29
+ };
30
+ export type StatefulPageAction<State extends Record<string, unknown>, Args extends unknown[] = unknown[]> = (obj: StatefulPageActionArgument<State, Args>) => State | Promise<State>;
31
+ export type ExtractStatefulPageActionArgs<X> = X extends StatefulPageAction<any, infer Args> ? Args : never;
32
+ export declare abstract class StatefulPage<State extends Record<string, unknown>, Actions extends Record<string, StatefulPageAction<State>>> extends Mountable {
33
+ abstract actions: Actions;
34
+ abstract getInitialState(ctx: Context): State | Promise<State>;
35
+ abstract render(ctx: Context, state: State, inputs: Record<string, string>): Templatable | Promise<Templatable>;
36
+ canAccess(_ctx: Context): Promise<{
37
+ canAccess: boolean;
38
+ message: string;
39
+ }>;
40
+ constructor();
41
+ abstract wrapInLayout(ctx: Context, content: Templatable, state: State): Templatable;
42
+ wrapInForm(context: Context, state: State, content: Templatable): Promise<Templatable>;
43
+ extractActionAndLabel<ActionName extends keyof Actions>(action_description: StatefulPageActionDescription<ActionName>): {
44
+ action: string;
45
+ label: string;
46
+ content: string;
47
+ disabled: boolean;
48
+ };
49
+ makeActionURL<ActionName extends keyof Actions>(action_description: StatefulPageActionDescription<ActionName>, ...args: ExtractStatefulPageActionArgs<Actions[ActionName]>): string;
50
+ makeActionButton<ActionName extends keyof Actions>(_state: State, action_description: StatefulPageActionDescription<ActionName>, ...args: ExtractStatefulPageActionArgs<Actions[ActionName]>): string;
51
+ makeActionCallback<ActionName extends keyof Actions>(action_description: {
52
+ action: ActionName;
53
+ label?: string;
54
+ } | ActionName, ...args: ExtractStatefulPageActionArgs<Actions[ActionName]>): string;
55
+ rerender(): string;
56
+ preprocessState(values: State): Promise<State>;
57
+ preprocessOverrides(_context: Context, _state: State, values: Record<string, unknown>): Promise<Record<string, unknown>>;
58
+ serializeState(_context: Context, state: State): Promise<string>;
59
+ deserializeState(_context: Context, s: string): Promise<State>;
60
+ extractState(ctx: Context): Promise<StateAndMetadata<State, Actions>>;
61
+ mount(router: Router, path: string): void;
62
+ }
@@ -0,0 +1 @@
1
+ export declare function sharedCrudFormFields(collection_name: string, newfilefullpath: string): Promise<string>;
@@ -1,68 +1 @@
1
- import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
2
- export type FieldHandlerResult = {
3
- imports: Partial<{
4
- shared: string;
5
- edit: string;
6
- }>;
7
- hide_field: boolean;
8
- field: string;
9
- hide_control: boolean;
10
- controls: string;
11
- is_required: boolean;
12
- is_required_expr: string;
13
- fields_var: string;
14
- top_level_shared: string;
15
- name: string;
16
- hide_initial_value_edit: boolean;
17
- initial_value_edit: Partial<{
18
- main_value: string;
19
- parsed_value: string;
20
- fallback_value: string;
21
- }> | string;
22
- hide_initial_value_create: boolean;
23
- initial_value_create: string;
24
- pre_edit: string;
25
- post_edit: string;
26
- pre_create: string;
27
- post_create: string;
28
- sealious_value: (result: Exclude<FieldHandlerResult, "sealious_value">) => string;
29
- hide_sealious_value: boolean;
30
- fallback_value_sealious: string;
31
- main_value_sealious: string;
32
- };
33
- export type FieldHandler<Defaults extends Partial<FieldHandlerResult>, Result extends Partial<FieldHandlerResult>> = (collection_name: string, field: ExtractedFieldInfo, importPath: (path: string) => string, defaults: Defaults, all_other_handlers: Record<string, FieldHandler<FieldHandlerResult, Partial<FieldHandlerResult>> | undefined>, fields_var?: string) => Promise<Result>;
34
- export declare const field_handlers: Record<Exclude<string, "default">, FieldHandler<FieldHandlerResult, Partial<FieldHandlerResult>> | undefined> & {
35
- default: FieldHandler<Record<string, never>, FieldHandlerResult>;
36
- };
37
- export declare function getFieldHandler(collection_name: string, field: ExtractedFieldInfo, importPath: (path: string) => string, fields_var?: string): Promise<{
38
- imports: Partial<{
39
- shared: string;
40
- edit: string;
41
- }>;
42
- hide_field: boolean;
43
- field: string;
44
- hide_control: boolean;
45
- controls: string;
46
- is_required: boolean;
47
- is_required_expr: string;
48
- fields_var: string;
49
- top_level_shared: string;
50
- name: string;
51
- hide_initial_value_edit: boolean;
52
- initial_value_edit: string | Partial<{
53
- main_value: string;
54
- parsed_value: string;
55
- fallback_value: string;
56
- }>;
57
- hide_initial_value_create: boolean;
58
- initial_value_create: string;
59
- pre_edit: string;
60
- post_edit: string;
61
- pre_create: string;
62
- post_create: string;
63
- sealious_value: (result: FieldHandlerResult) => string;
64
- hide_sealious_value: boolean;
65
- fallback_value_sealious: string;
66
- main_value_sealious: string;
67
- }>;
68
1
  export declare function sharedCrudFormFields(collection_name: string, newfilefullpath: string): Promise<string>;
@@ -0,0 +1,26 @@
1
+ import EventEmitter from "events";
2
+ export declare const callSealgenBin: () => string;
3
+ export declare class RealAppTest {
4
+ node_pid: number;
5
+ app_port: number;
6
+ mongo_port: number;
7
+ app_path: string;
8
+ container_name: string;
9
+ emitter: EventEmitter<[never]>;
10
+ static init(): Promise<RealAppTest>;
11
+ start(): Promise<void>;
12
+ close(): Promise<void>;
13
+ runSealgenCommand(command: string): Promise<void>;
14
+ build(): Promise<void>;
15
+ throwIfItKillsTheApp<T>(cb: () => Promise<T>): Promise<T>;
16
+ httpGET(path: string): Promise<{
17
+ status: number;
18
+ response: string;
19
+ }>;
20
+ httpPOST(path: string, body: Record<string, unknown>): Promise<{
21
+ status: number;
22
+ response: string;
23
+ }>;
24
+ addFile(target_path: string, content: string): Promise<void>;
25
+ fullURL(path: string): string;
26
+ }
@@ -1,4 +1,3 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  import EventEmitter from "events";
3
2
  export declare const callSealgenBin: () => string;
4
3
  export declare class RealAppTest {
@@ -0,0 +1,18 @@
1
+ import { FormField } from "../forms/fields/field.js";
2
+ export type ExtractedFieldInfo = {
3
+ name: string;
4
+ type: string;
5
+ target: string | null;
6
+ referencing_collection: string | null;
7
+ referencing_field: string | null;
8
+ intermediary_field_that_points_there: string | null;
9
+ is_readonly: boolean;
10
+ is_required: boolean;
11
+ subfields: {
12
+ name: string;
13
+ }[];
14
+ };
15
+ export type ExtractedFieldInfoWithFormField = ExtractedFieldInfo & {
16
+ form_field: FormField;
17
+ };
18
+ export default function extract_fields_from_collection(collection_name: string): Promise<ExtractedFieldInfoWithFormField[]>;
@@ -1,3 +1,4 @@
1
+ import { FormField } from "../forms/fields/field.js";
1
2
  export type ExtractedFieldInfo = {
2
3
  name: string;
3
4
  type: string;
@@ -11,4 +12,7 @@ export type ExtractedFieldInfo = {
11
12
  name: string;
12
13
  }[];
13
14
  };
14
- export default function extract_fields_from_collection(collection_name: string): Promise<ExtractedFieldInfo[]>;
15
+ export type ExtractedFieldInfoWithFormField = ExtractedFieldInfo & {
16
+ form_field: FormField;
17
+ };
18
+ export default function extract_fields_from_collection(collection_name: string): Promise<ExtractedFieldInfoWithFormField[]>;
@@ -0,0 +1,18 @@
1
+ import { FormField } from "../forms/fields/field.js";
2
+ export type ExtractedFieldInfo = {
3
+ name: string;
4
+ type: string;
5
+ target: string | null;
6
+ referencing_collection: string | null;
7
+ referencing_field: string | null;
8
+ intermediary_field_that_points_there: string | null;
9
+ is_readonly: boolean;
10
+ is_required: boolean;
11
+ subfields: {
12
+ name: string;
13
+ }[];
14
+ };
15
+ export type ExtractedFieldInfoWithFormField = ExtractedFieldInfo & {
16
+ form_field: FormField;
17
+ };
18
+ export default function extract_fields_from_collection(collection_name: string): Promise<ExtractedFieldInfoWithFormField[]>;
@@ -0,0 +1,3 @@
1
+ export declare function needsQuotes(str: string): boolean;
2
+ export declare function wrapAttribute(name: string): string;
3
+ export declare function wrapKeyName(name: string): string;
package/README.md CHANGED
@@ -67,3 +67,8 @@ You can add these commands to your module's `package.json` postinstall script to
67
67
  5. If the path is already present, it doesn't add a duplicate
68
68
 
69
69
  This ensures that when your module is installed as a dependency, the parent project will automatically know where to find your controllers and styles.
70
+
71
+
72
+ ### Attributions
73
+
74
+ File icon - Gnome Project
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="m 28 8 h 50 l 30.042969 29.917969 v 74.058593 c 0 4.433594 -3.609375 8.023438 -8.042969 8.023438 h -72 c -4.433594 0 -8 -3.566406 -8 -8 v -96 c 0 -4.433594 3.566406 -8 8 -8 z m 0 0" fill="#f6f5f4"/>
4
+ <path d="m 78 8 v 22 c 0 4.433594 3.609375 7.921875 8.042969 7.921875 l 22 -0.003906 z m 0 0" fill="#deddda"/>
5
+ </svg>
package/lib/add-crud.js CHANGED
@@ -1,18 +1,16 @@
1
1
  import _locreq from "locreq";
2
- import prompts from "prompts";
3
2
  import { escape_url_params } from "./utils/escape-url-params.js";
3
+ import prompts from "prompts";
4
4
  import { toKebabCase, toPascalCase } from "js-convert-case";
5
5
  import { listCollections } from "./utils/list-collections.js";
6
- import {
7
- makeDefaultDisplayFields,
8
- makeDefaultFilterFields
9
- } from "./templates/shared/collection-list.js";
6
+ import { collectionListTemplate } from "./templates/shared/collection-list.js";
10
7
  import { writeFile } from "./utils/write-file.js";
11
- import { extractCollectionClassname } from "./generate-collections.js";
12
- import extract_fields_from_collection from "./utils/extract-fields-from-collection.js";
13
- import { getFieldHandler } from "./templates/shared/shared-crud-form-fields.js";
8
+ import { curryImportPath, importPath } from "./utils/import-path.js";
9
+ import { sharedCrudFormFields } from "./templates/shared/shared-crud-form-fields.js";
14
10
  import { generateRoutes } from "./generate-routes.js";
15
- import { formatWithPrettier } from "./utils/prettier.js";
11
+ import { createItemFormTemplate } from "./templates/shared/collection-create-form.js";
12
+ import { editItemFormTemplate } from "./templates/shared/collection-edit-form.js";
13
+ import { itemDeleteTemplate } from "./templates/shared/item-delete.js";
16
14
  async function addCRUD(params, app_directory = process.cwd()) {
17
15
  const target_locreq = _locreq(app_directory);
18
16
  prompts.override(params);
@@ -29,7 +27,7 @@ async function addCRUD(params, app_directory = process.cwd()) {
29
27
  {
30
28
  type: "text",
31
29
  name: "url",
32
- message: "Enter a full absolute path for the new route (for example: /admin/users/): ",
30
+ message: "Enter a full absolute path for the new route (for example: /admin/users/:id/edit): ",
33
31
  validate: (s) => s.trim()[0] == "/" ? true : "Should start with a '/'",
34
32
  initial: function(_, { collection }) {
35
33
  return "/" + toKebabCase(collection);
@@ -38,88 +36,81 @@ async function addCRUD(params, app_directory = process.cwd()) {
38
36
  ]);
39
37
  const collection_name = response.collection;
40
38
  const url = response.url;
39
+ const list_action_name = toPascalCase(collection_name) + "CRUDList";
40
+ const create_action_name = toPascalCase(collection_name) + "CRUDCreate";
41
+ const edit_action_name = toPascalCase(collection_name) + "CRUDEdit";
42
+ const delete_action_name = toPascalCase(collection_name) + "CRUDDelete";
41
43
  const list_path = target_locreq.resolve(
42
- `src/back/routes/${escape_url_params(url)}/index.page.ts`
44
+ `src/back/routes/${escape_url_params(url)}/index.list.tsx`
43
45
  );
44
- const [uppercase_collection, collection_fields] = await Promise.all([
45
- extractCollectionClassname(
46
- target_locreq.resolve(
47
- "src/back/collections/" + collection_name + ".ts"
48
- )
49
- ),
50
- extract_fields_from_collection(collection_name)
51
- ]);
52
- const field_handler_results = await Promise.all(
53
- collection_fields.map(async (field) => {
54
- return getFieldHandler(
55
- collection_name,
56
- field,
57
- (p) => p,
58
- "edit_fields"
59
- );
60
- })
46
+ const list_content = await collectionListTemplate(
47
+ collection_name,
48
+ list_action_name,
49
+ list_path,
50
+ {
51
+ post_import_js: `import { ${create_action_name}URL, ${edit_action_name}URL, ${delete_action_name}URL } from "${importPath(
52
+ list_path,
53
+ "src/back/routes/urls.ts"
54
+ )}";`,
55
+ post_header_html: `<a href={${create_action_name}URL}> Create </a>`,
56
+ render_item: (collection_name2) => ` async renderItem(ctx: Context, item: CollectionItem<typeof ${toPascalCase(
57
+ collection_name2
58
+ )}>) {
59
+ return <tr>
60
+ {displayFields.map(({ field, format }) => {
61
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
62
+ const value = item.get(field as any);
63
+ return <td>{format ? format(value, item) : value}</td>;
64
+ })}
65
+ <td><div class="sealious-list__actions">
66
+ <a href={${edit_action_name}URL(item.id)}>Edit</a>
67
+ <a data-turbo-method="POST" data-turbo-confirm="Delete item?" href={${delete_action_name}URL(item.id)}>Delete</a>
68
+ </div>
69
+ </td>
70
+ </tr>;
71
+ }`
72
+ }
61
73
  );
62
- const list_content = `import { CRUD } from "@sealcode/crud-ui";
63
- import type { CollectionItem } from "sealious";
64
- import type { ListFilterRender } from "@sealcode/sealgen";
65
- import { Controls, DefaultListFilters, Fields } from "@sealcode/sealgen";
66
- import { ${toPascalCase(
67
- collection_name
68
- )} } from "src/back/collections/collections.js";
69
- import html from "src/back/html.js";
70
-
71
- export const actionName = "${toPascalCase(collection_name)}CRUD";
72
-
73
- const edit_fields = <const>
74
- {
75
- ${field_handler_results.filter(({ hide_field }) => !hide_field).map(({ field }) => field).filter((e) => e != "").join(",\n")}
76
- };
77
-
78
-
79
- const edit_controls = [
80
- ${field_handler_results.filter(({ hide_control }) => !hide_control).map(({ controls }) => controls).filter((e) => e != "").join(",\n")}
81
- ]
82
-
83
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
84
- const fields_for_display = [
85
- ${makeDefaultDisplayFields(collection_fields)}
86
- ] as {
87
- field: keyof (typeof ${toPascalCase(collection_name)})["fields"];
88
- label: string;
89
- format?: (value: unknown, item: CollectionItem<typeof ${toPascalCase(
90
- collection_name
91
- )}>) => string | Promise<string>;
92
- }[];
93
-
94
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
95
- const fields_for_filters = [
96
- ${makeDefaultFilterFields(collection_fields)}
97
- ] as {
98
- field: keyof (typeof ${uppercase_collection})["fields"];
99
- render?: ListFilterRender;
100
- prepareValue?: (filter_value: unknown)=>unknown; // set this function to change what filter value is passed to Sealious
101
- }[];
102
-
103
- export default new CRUD({
104
- collection: ${toPascalCase(collection_name)},
105
- nice_collection_name: "${toPascalCase(collection_name)}",
106
- fields_for_display,
107
- fields_for_filters,
108
- html,
109
- list_title: "${toPascalCase(collection_name)} list",
110
- edit_title: "Edit",
111
- edit_button_text: "Edit",
112
- delete_button_text: "Delete",
113
- back_to_list_button_text: "\u2190 Back to ${toPascalCase(collection_name)} list",
114
- edit_fields,
115
- edit_controls,
116
- form_value_to_sealious_value: {},
117
- sealious_value_to_form_value: {},
118
- post_edit: async () => {},
119
- post_create: async () => {},
120
- });
121
- `;
122
- await writeFile(list_path, await formatWithPrettier(list_content));
74
+ await writeFile(list_path, list_content);
75
+ const fields_path = target_locreq.resolve(
76
+ `src/back/routes/${escape_url_params(url)}/shared.ts`
77
+ );
78
+ const fields_content = await sharedCrudFormFields(
79
+ collection_name,
80
+ fields_path
81
+ );
82
+ await writeFile(fields_path, fields_content);
83
+ const create_path = target_locreq.resolve(
84
+ `src/back/routes/${escape_url_params(url)}/create.form.ts`
85
+ );
86
+ const create_content = await createItemFormTemplate(
87
+ create_action_name,
88
+ create_path,
89
+ collection_name,
90
+ list_action_name
91
+ );
92
+ await writeFile(create_path, create_content);
93
+ const edit_path = target_locreq.resolve(
94
+ `src/back/routes/${escape_url_params(url)}/[id]/edit.form.ts`
95
+ );
96
+ const edit_content = await editItemFormTemplate(
97
+ edit_action_name,
98
+ edit_path,
99
+ collection_name,
100
+ list_action_name
101
+ );
102
+ await writeFile(edit_path, edit_content);
103
+ const delete_path = target_locreq.resolve(
104
+ `src/back/routes/${escape_url_params(url)}/[id]/delete.page.tsx`
105
+ );
106
+ const base_import_path = curryImportPath(delete_path);
107
+ const delete_content = await itemDeleteTemplate(
108
+ delete_action_name,
109
+ collection_name,
110
+ list_action_name,
111
+ base_import_path
112
+ );
113
+ await writeFile(delete_path, delete_content);
123
114
  await generateRoutes();
124
115
  }
125
116
  export {
@@ -2,7 +2,7 @@ import { getBrowser } from "./utils/browser-creator.js";
2
2
  import { RealAppTest } from "./test_utils/test-on-real-app.js";
3
3
  import { collectionTemplate } from "./templates/collection.js";
4
4
  import assert from "node:assert";
5
- describe("single-reference.test", () => {
5
+ describe("single-reference", () => {
6
6
  let page;
7
7
  before(async () => {
8
8
  const browser = await getBrowser();
package/lib/add-route.js CHANGED
@@ -2,7 +2,6 @@ import { existsSync, promises as fs } from "fs";
2
2
  import _locreq from "locreq";
3
3
  import { resolve } from "path";
4
4
  import { generateRoutes } from "./generate-routes.js";
5
- import { testTemplate } from "./templates/route-test.js";
6
5
  import { escape_url_params } from "./utils/escape-url-params.js";
7
6
  import prompts from "prompts";
8
7
  import { Templates } from "./templates/templates.js";
@@ -67,12 +66,6 @@ async function addRoute(params, app_directory = process.cwd()) {
67
66
  }
68
67
  await fs.mkdir(resolve(file_path, "../"), { recursive: true });
69
68
  await fs.writeFile(file_path, await template(action, file_path));
70
- if (mode !== "lpr" && mode !== "jdd-editor") {
71
- await fs.writeFile(
72
- test_file_path,
73
- await testTemplate(action, file_path)
74
- );
75
- }
76
69
  console.log(`${file_path} created`);
77
70
  console.log(`${test_file_path} created`);
78
71
  await generateRoutes();
package/lib/build.js CHANGED
@@ -86,7 +86,9 @@ async function build(watch) {
86
86
  ];
87
87
  await Promise.all(builders.map((b) => b.build()));
88
88
  if (watch) {
89
- const watcher = chokidar.watch("src", { ignoreInitial: true });
89
+ const watcher = chokidar.watch(["src", ...controller_dirs], {
90
+ ignoreInitial: true
91
+ });
90
92
  const port = await get_notifier_port();
91
93
  const notifier = make_notifier(port, 8080);
92
94
  await write_notifier_config(watch, port);
package/lib/cli.js CHANGED
@@ -1,17 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import yargs from "yargs/yargs";
3
3
  import { addCollection } from "./add-collection.js";
4
- import { addCRUD } from "./add-crud.js";
5
4
  import { addJDDComponent } from "./add-jdd-component.js";
6
5
  import { addRoute } from "./add-route.js";
7
- import { addVerboseCRUD } from "./add-verbose-crud.js";
6
+ import { addCRUD } from "./add-crud.js";
8
7
  import { buildProject } from "./build.js";
9
8
  import { generateCollections } from "./generate-collections.js";
10
9
  import { generateComponents } from "./generate-components.js";
11
10
  import { generateRoutes } from "./generate-routes.js";
12
11
  import { getFonts } from "./get-fonts.js";
13
12
  import { makeEnv } from "./make-env.js";
14
- import { crudFieldSnippets } from "./crud-field-snippets.js";
15
13
  import {
16
14
  registerExternalControllers,
17
15
  registerExternalStyles
@@ -19,7 +17,6 @@ import {
19
17
  const actions = {
20
18
  "add-collection": addCollection,
21
19
  "add-route": addRoute,
22
- "add-verbose-crud": addVerboseCRUD,
23
20
  "add-crud": addCRUD,
24
21
  "generate-collections": generateCollections,
25
22
  "generate-components": generateComponents,
@@ -34,7 +31,7 @@ const actions = {
34
31
  "make-env": makeEnv,
35
32
  "add-component": addJDDComponent,
36
33
  "get-fonts": getFonts,
37
- "crud-field-snippets": crudFieldSnippets,
34
+ // "crud-field-snippets": crudFieldSnippets,
38
35
  "register-external-controllers": registerExternalControllers,
39
36
  "register-external-styles": registerExternalStyles
40
37
  };
@@ -0,0 +1,35 @@
1
+ import { Controller } from "stimulus";
2
+ class table_add_button_stimulus_default extends Controller {
3
+ constructor() {
4
+ super(...arguments);
5
+ this.defaultRowsNumber = 20;
6
+ }
7
+ static {
8
+ this.targets = ["textarea"];
9
+ }
10
+ addRow() {
11
+ const template = this.element.closest("turbo-frame")?.querySelector("template");
12
+ if (!template) {
13
+ throw new Error("Couldn't find template");
14
+ }
15
+ const tbody = this.element.closest("turbo-frame")?.querySelector("tbody");
16
+ if (!tbody) {
17
+ throw new Error("tbody not found");
18
+ }
19
+ const orig_template = template.innerHTML;
20
+ const placeholder = this.element.getAttribute("data-table-placeholder");
21
+ if (!placeholder) {
22
+ throw new Error("Could find placeholder attribute");
23
+ }
24
+ template.innerHTML = orig_template.replaceAll(
25
+ placeholder,
26
+ String(tbody.querySelectorAll("tr").length)
27
+ );
28
+ tbody.appendChild(template.cloneNode(true).content);
29
+ template.innerHTML = orig_template;
30
+ }
31
+ }
32
+ export {
33
+ table_add_button_stimulus_default as default
34
+ };
35
+ //# sourceMappingURL=table-add-button.stimulus.js.map