@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.
- package/.eslintrc.cjs +7 -2
- package/.xunit +75 -0
- package/@types/add-crud.d.sync-conflict-20250918-184311-TFDLWFG.ts +1 -0
- package/@types/builders/colors-builder.d.sync-conflict-20250918-184323-TFDLWFG.ts +10 -0
- package/@types/builders/colors-builder.d.ts +1 -1
- package/@types/builders/fonts-builder.d.sync-conflict-20250918-184322-TFDLWFG.ts +7 -0
- package/@types/builders/fonts-builder.d.ts +1 -1
- package/@types/controllers/table-add-button.d.ts +6 -0
- package/@types/controllers/table-add-button.stimulus.d.ts +6 -0
- package/@types/crud-field-snippets.d.sync-conflict-20250918-184323-TFDLWFG.ts +1 -0
- package/@types/crud-field-snippets.d.ts +1 -3
- package/@types/forms/controls/array.d.sync-conflict-20250918-184306-TFDLWFG.ts +33 -0
- package/@types/forms/controls/array.d.ts +1 -2
- package/@types/forms/controls/array.sync-conflict-20250918-222045-TFDLWFG.d.ts +33 -0
- package/@types/forms/controls/autocomplete.d.sync-conflict-20250918-222042-TFDLWFG.ts +22 -0
- package/@types/forms/controls/autocomplete.d.ts +1 -1
- package/@types/forms/controls/checkbox-group.d.sync-conflict-20250918-184319-TFDLWFG.ts +21 -0
- package/@types/forms/controls/checkbox-group.d.ts +3 -3
- package/@types/forms/controls/checkboxed-list-input.d.sync-conflict-20250918-184323-TFDLWFG.ts +21 -0
- package/@types/forms/controls/checkboxed-list-input.d.ts +3 -3
- package/@types/forms/controls/controls.d.ts +2 -2
- package/@types/forms/controls/derived-frame.d.sync-conflict-20250918-184314-TFDLWFG.ts +19 -0
- package/@types/forms/controls/derived-frame.d.ts +0 -1
- package/@types/forms/controls/dropdown.d.sync-conflict-20250918-222044-TFDLWFG.ts +30 -0
- package/@types/forms/controls/dropdown.d.ts +1 -1
- package/@types/forms/controls/file.d.sync-conflict-20250918-222045-TFDLWFG.ts +13 -0
- package/@types/forms/controls/file.d.ts +1 -2
- package/@types/forms/controls/form-control.d.sync-conflict-20250918-184322-TFDLWFG.ts +19 -0
- package/@types/forms/controls/form-control.d.sync-conflict-20250918-222046-TFDLWFG.ts +19 -0
- package/@types/forms/controls/form-control.d.ts +7 -3
- package/@types/forms/controls/image.d.ts +19 -0
- package/@types/forms/controls/image.test.d.ts +1 -0
- package/@types/forms/controls/multiple-files.d.sync-conflict-20250918-184318-TFDLWFG.ts +42 -0
- package/@types/forms/controls/multiple-files.d.ts +3 -0
- package/@types/forms/controls/multiple-images.d.ts +19 -0
- package/@types/forms/controls/number.d.sync-conflict-20250918-222046-TFDLWFG.ts +13 -0
- package/@types/forms/controls/number.d.ts +1 -1
- package/@types/forms/controls/photo.d.sync-conflict-20250918-184321-TFDLWFG.ts +19 -0
- package/@types/forms/controls/photo.d.ts +3 -5
- package/@types/forms/controls/simple-input.d.sync-conflict-20250918-184310-TFDLWFG.ts +33 -0
- package/@types/forms/controls/simple-input.d.sync-conflict-20250918-222042-TFDLWFG.ts +33 -0
- package/@types/forms/controls/simple-input.d.ts +5 -4
- package/@types/forms/controls/simple-input.sync-conflict-20250918-222045-TFDLWFG.d.ts +33 -0
- package/@types/forms/controls/single-reference.d.ts +3 -2
- package/@types/forms/controls/table.d.sync-conflict-20250918-184302-TFDLWFG.ts +39 -0
- package/@types/forms/controls/table.d.ts +8 -2
- package/@types/forms/controls/table.sync-conflict-20250918-222042-TFDLWFG.d.ts +39 -0
- package/@types/forms/controls/textarea.d.sync-conflict-20250918-222045-TFDLWFG.ts +25 -0
- package/@types/forms/controls/textarea.d.ts +3 -3
- package/@types/forms/fields/boolean.d.sync-conflict-20250918-184325-TFDLWFG.ts +22 -0
- package/@types/forms/fields/boolean.d.ts +6 -1
- package/@types/forms/fields/boolean.sync-conflict-20250918-222042-TFDLWFG.d.ts +22 -0
- package/@types/forms/fields/checkboxed-list.d.sync-conflict-20250918-184325-TFDLWFG.ts +23 -0
- package/@types/forms/fields/checkboxed-list.d.ts +3 -1
- package/@types/forms/fields/collection-field.d.sync-conflict-20250918-184319-TFDLWFG.ts +22 -0
- package/@types/forms/fields/collection-field.d.sync-conflict-20250918-222047-TFDLWFG.ts +22 -0
- package/@types/forms/fields/collection-field.d.ts +8 -1
- package/@types/forms/fields/color.d.ts +4 -0
- package/@types/forms/fields/coordinates.d.sync-conflict-20250918-222044-TFDLWFG.ts +14 -0
- package/@types/forms/fields/coordinates.d.ts +14 -0
- package/@types/forms/fields/date.d.ts +13 -0
- package/@types/forms/fields/datetime.d.sync-conflict-20250918-222050-TFDLWFG.ts +4 -0
- package/@types/forms/fields/datetime.d.ts +14 -0
- package/@types/forms/fields/deep-reverse-single-reference-list.d.ts +24 -0
- package/@types/forms/fields/deep-reverse-single-reference-table.d.ts +16 -0
- package/@types/forms/fields/email.d.sync-conflict-20250918-184303-TFDLWFG.ts +8 -0
- package/@types/forms/fields/email.d.ts +3 -0
- package/@types/forms/fields/enum-multiple-sealious.d.ts +16 -0
- package/@types/forms/fields/enum-multiple-sealious.sync-conflict-20250918-222047-TFDLWFG.d.ts +16 -0
- package/@types/forms/fields/field.d.sync-conflict-20250918-184306-TFDLWFG.ts +70 -0
- package/@types/forms/fields/field.d.ts +37 -5
- package/@types/forms/fields/fields.d.sync-conflict-20250918-184314-TFDLWFG.ts +29 -0
- package/@types/forms/fields/fields.d.ts +23 -8
- package/@types/forms/fields/file.d.sync-conflict-20250918-184310-TFDLWFG.ts +23 -0
- package/@types/forms/fields/file.d.sync-conflict-20250918-222046-TFDLWFG.ts +23 -0
- package/@types/forms/fields/file.d.ts +11 -5
- package/@types/forms/fields/file.sync-conflict-20250918-222049-TFDLWFG.d.ts +23 -0
- package/@types/forms/fields/float.d.ts +4 -0
- package/@types/forms/fields/get-field-for-sealious.d.sync-conflict-20250918-222046-TFDLWFG.ts +29 -0
- package/@types/forms/fields/get-field-for-sealious.d.ts +31 -0
- package/@types/forms/fields/get-field-for-sealious.sync-conflict-20250918-222042-TFDLWFG.d.ts +29 -0
- package/@types/forms/fields/html.d.ts +6 -0
- package/@types/forms/fields/image.d.sync-conflict-20250918-222042-TFDLWFG.ts +5 -0
- package/@types/forms/fields/image.d.ts +5 -0
- package/@types/forms/fields/int.d.ts +6 -0
- package/@types/forms/fields/json.d.ts +13 -0
- package/@types/forms/fields/markdown.d.ts +6 -0
- package/@types/forms/fields/multiple-files.d.sync-conflict-20250918-184304-TFDLWFG.ts +16 -0
- package/@types/forms/fields/multiple-files.d.ts +3 -1
- package/@types/forms/fields/number.d.sync-conflict-20250918-184317-TFDLWFG.ts +25 -0
- package/@types/forms/fields/number.d.sync-conflict-20250918-222047-TFDLWFG.ts +25 -0
- package/@types/forms/fields/number.d.ts +3 -1
- package/@types/forms/fields/password.d.ts +6 -0
- package/@types/forms/fields/pick-from-list-sealious.d.ts +11 -0
- package/@types/forms/fields/pick-from-list.d.sync-conflict-20250918-184322-TFDLWFG.ts +15 -0
- package/@types/forms/fields/pick-from-list.d.ts +4 -3
- package/@types/forms/fields/proxy-field.d.sync-conflict-20250918-184307-TFDLWFG.ts +15 -0
- package/@types/forms/fields/proxy-field.d.ts +3 -1
- package/@types/forms/fields/regexp.d.sync-conflict-20250918-184305-TFDLWFG.ts +21 -0
- package/@types/forms/fields/regexp.d.sync-conflict-20250918-222045-TFDLWFG.ts +21 -0
- package/@types/forms/fields/regexp.d.ts +6 -1
- package/@types/forms/fields/regexp.sync-conflict-20250918-222047-TFDLWFG.d.ts +21 -0
- package/@types/forms/fields/simple-form-field.d.sync-conflict-20250918-184309-TFDLWFG.ts +29 -0
- package/@types/forms/fields/simple-form-field.d.sync-conflict-20250918-222044-TFDLWFG.ts +29 -0
- package/@types/forms/fields/simple-form-field.d.ts +23 -3
- package/@types/forms/fields/simple-form-field.sync-conflict-20250918-222049-TFDLWFG.d.ts +29 -0
- package/@types/forms/fields/single-reference.d.ts +19 -0
- package/@types/forms/fields/single-reference.sync-conflict-20250918-222043-TFDLWFG.d.ts +10 -0
- package/@types/forms/fields/structured-array.d.sync-conflict-20250918-184302-TFDLWFG.ts +27 -0
- package/@types/forms/fields/structured-array.d.sync-conflict-20250918-222049-TFDLWFG.ts +27 -0
- package/@types/forms/fields/structured-array.d.ts +19 -10
- package/@types/forms/fields/structured-array.sync-conflict-20250918-222047-TFDLWFG.d.ts +27 -0
- package/@types/forms/fields/table.d.sync-conflict-20250918-184303-TFDLWFG.ts +16 -0
- package/@types/forms/fields/table.d.ts +3 -0
- package/@types/forms/fields/text.d.ts +6 -0
- package/@types/forms/fields/url.d.ts +6 -0
- package/@types/forms/form-types.d.sync-conflict-20250918-222045-TFDLWFG.ts +26 -0
- package/@types/forms/form-types.d.ts +2 -0
- package/@types/forms/form.d.sync-conflict-20250918-184315-TFDLWFG.ts +32 -0
- package/@types/forms/form.d.sync-conflict-20250918-222049-TFDLWFG.ts +32 -0
- package/@types/forms/form.d.ts +10 -7
- package/@types/forms/form.sync-conflict-20250918-222049-TFDLWFG.d.ts +33 -0
- package/@types/forms/form.test.d.sync-conflict-20250918-184318-TFDLWFG.ts +6 -0
- package/@types/forms/form.test.d.sync-conflict-20250918-222047-TFDLWFG.ts +6 -0
- package/@types/forms/form.test.d.ts +2 -2
- package/@types/forms/multiform.d.sync-conflict-20250918-184308-TFDLWFG.ts +23 -0
- package/@types/forms/multiform.d.ts +1 -1
- package/@types/forms/multiform.sync-conflict-20250918-222044-TFDLWFG.d.ts +23 -0
- package/@types/index.d.sync-conflict-20250918-184316-TFDLWFG.ts +46 -0
- package/@types/index.d.ts +2 -2
- package/@types/mount.d.sync-conflict-20250918-184320-TFDLWFG.ts +6 -0
- package/@types/page/list.d.sync-conflict-20250918-184318-TFDLWFG.ts +48 -0
- package/@types/page/list.d.sync-conflict-20250918-222046-TFDLWFG.ts +48 -0
- package/@types/page/list.d.ts +2 -2
- package/@types/page/list.sync-conflict-20250918-222048-TFDLWFG.d.ts +48 -0
- package/@types/page/mountable-with-fields.d.sync-conflict-20250918-184321-TFDLWFG.ts +42 -0
- package/@types/page/mountable-with-fields.d.sync-conflict-20250918-222046-TFDLWFG.ts +42 -0
- package/@types/page/mountable-with-fields.d.ts +3 -3
- package/@types/page/mountable-with-fields.sync-conflict-20250918-222044-TFDLWFG.d.ts +42 -0
- package/@types/page/mountable.d.sync-conflict-20250918-184306-TFDLWFG.ts +10 -0
- package/@types/page/page.d.sync-conflict-20250918-184320-TFDLWFG.ts +18 -0
- package/@types/page/props-parser.d.sync-conflict-20250918-184305-TFDLWFG.ts +15 -0
- package/@types/page/props-parser.d.ts +0 -1
- package/@types/page/stateful-page.d.sync-conflict-20250918-184326-TFDLWFG.ts +62 -0
- package/@types/templates/shared/shared-crud-form-fields.d.sync-conflict-20250918-184306-TFDLWFG.ts +1 -0
- package/@types/templates/shared/shared-crud-form-fields.d.ts +0 -67
- package/@types/test_utils/test-on-real-app.d.sync-conflict-20250918-184320-TFDLWFG.ts +26 -0
- package/@types/test_utils/test-on-real-app.d.ts +0 -1
- package/@types/utils/extract-fields-from-collection.d.sync-conflict-20250918-184312-TFDLWFG.ts +18 -0
- package/@types/utils/extract-fields-from-collection.d.ts +5 -1
- package/@types/utils/extract-fields-from-collection.sync-conflict-20250918-222045-TFDLWFG.d.ts +18 -0
- package/@types/utils/wrap-attributes.d.ts +3 -0
- package/README.md +5 -0
- package/assets/file-icon.svg +5 -0
- package/lib/add-crud.js +80 -89
- package/lib/add-list-route.test.js +1 -1
- package/lib/add-route.js +0 -7
- package/lib/build.js +3 -1
- package/lib/cli.js +2 -5
- package/lib/controllers/table-add-button.stimulus.js +35 -0
- package/lib/forms/controls/array.js +20 -16
- package/lib/forms/controls/big-radio-group.js +2 -2
- package/lib/forms/controls/checkbox-group.js +7 -7
- package/lib/forms/controls/checkboxed-list-input.js +9 -2
- package/lib/forms/controls/controls.js +2 -2
- package/lib/forms/controls/derived-frame.js +5 -1
- package/lib/forms/controls/derived.js +1 -1
- package/lib/forms/controls/dropdown.js +4 -1
- package/lib/forms/controls/editable-collection-subset.js +2 -2
- package/lib/forms/controls/file.js +26 -2
- package/lib/forms/controls/file.test.js +2 -2
- package/lib/forms/controls/hidden-input.js +4 -1
- package/lib/forms/controls/{photo.js → image.js} +6 -7
- package/lib/forms/controls/{photo.test.js → image.test.js} +6 -21
- package/lib/forms/controls/multiple-files.js +10 -1
- package/lib/forms/controls/{multiple-photos.js → multiple-images.js} +3 -3
- package/lib/forms/controls/simple-input.js +13 -12
- package/lib/forms/controls/single-reference.js +4 -0
- package/lib/forms/controls/table.js +66 -24
- package/lib/forms/controls/textarea.js +4 -2
- package/lib/forms/controls/tickable.js +13 -5
- package/lib/forms/fields/boolean.js +14 -0
- package/lib/forms/fields/checkboxed-list.js +4 -0
- package/lib/forms/fields/collection-field.js +9 -0
- package/lib/forms/fields/color.js +10 -0
- package/lib/forms/fields/coordinates.js +49 -0
- package/lib/forms/fields/date.js +34 -0
- package/lib/forms/fields/datetime.js +46 -0
- package/lib/forms/fields/deep-reverse-single-reference-list.js +81 -0
- package/lib/forms/fields/deep-reverse-single-reference-table.js +122 -0
- package/lib/forms/fields/email.js +7 -0
- package/lib/forms/fields/enum-multiple-sealious.js +32 -0
- package/lib/forms/fields/field.js +32 -4
- package/lib/forms/fields/field.test.js +5 -5
- package/lib/forms/fields/fields.js +23 -8
- package/lib/forms/fields/file.js +33 -9
- package/lib/forms/fields/file.test.js +4 -16
- package/lib/forms/fields/float.js +10 -0
- package/lib/forms/fields/get-field-for-sealious.js +213 -0
- package/lib/forms/fields/html.js +14 -0
- package/lib/forms/fields/image.js +13 -0
- package/lib/forms/fields/int.js +23 -0
- package/lib/forms/fields/json.js +31 -0
- package/lib/forms/fields/markdown.js +14 -0
- package/lib/forms/fields/multiple-files.js +4 -0
- package/lib/forms/fields/number.js +6 -0
- package/lib/forms/fields/password.js +13 -0
- package/lib/forms/fields/pick-from-list-sealious.js +17 -0
- package/lib/forms/fields/pick-from-list.js +6 -2
- package/lib/forms/fields/proxy-field.js +3 -0
- package/lib/forms/fields/regexp.js +14 -0
- package/lib/forms/fields/simple-form-field.js +60 -2
- package/lib/forms/fields/single-reference.js +44 -0
- package/lib/forms/fields/structured-array.js +63 -12
- package/lib/forms/fields/table.js +28 -1
- package/lib/forms/fields/text.js +17 -0
- package/lib/forms/fields/url.js +17 -0
- package/lib/forms/form.js +30 -13
- package/lib/forms/form.test.js +3 -4
- package/lib/forms/multiform.js +4 -2
- package/lib/forms/multiform.test.js +3 -3
- package/lib/generate-stimulus.js +1 -0
- package/lib/index.js +1 -0
- package/lib/make-hidden-inputs.js +1 -1
- package/lib/mount.js +11 -0
- package/lib/notifier.js +0 -1
- package/lib/page/list.js +15 -8
- package/lib/page/mountable-with-fields.js +14 -6
- package/lib/page/mountable-with-fields.test.js +1 -1
- package/lib/templates/form.js +8 -9
- package/lib/templates/multiform.js +4 -4
- package/lib/templates/page.js +0 -2
- package/lib/templates/shared/collection-create-form.js +28 -40
- package/lib/templates/shared/collection-edit-form.js +40 -77
- package/lib/templates/shared/collection-list.js +12 -20
- package/lib/templates/shared/shared-crud-form-fields.js +27 -95
- package/lib/test_utils/test-on-real-app.js +3 -3
- package/lib/utils/extract-fields-from-collection.js +60 -20
- package/lib/utils/make-slug.js +1 -1
- package/lib/utils/wrap-attributes.js +20 -0
- package/package.json +5 -4
- package/src/add-crud.ts +86 -97
- package/src/add-list-route.test.ts +1 -1
- package/src/add-route.ts +0 -7
- package/src/build.ts +3 -1
- package/src/cli.ts +3 -5
- package/src/controllers/table-add-button.stimulus.ts +35 -0
- package/src/forms/controls/array.ts +23 -20
- package/src/forms/controls/autocomplete.ts +1 -1
- package/src/forms/controls/big-radio-group.ts +2 -2
- package/src/forms/controls/checkbox-group.ts +9 -9
- package/src/forms/controls/checkboxed-list-input.ts +27 -15
- package/src/forms/controls/controls.ts +2 -2
- package/src/forms/controls/derived-frame.ts +5 -1
- package/src/forms/controls/derived.ts +1 -1
- package/src/forms/controls/dropdown.ts +5 -2
- package/src/forms/controls/editable-collection-subset.ts +2 -2
- package/src/forms/controls/file.test.ts +4 -2
- package/src/forms/controls/file.ts +31 -5
- package/src/forms/controls/form-control.ts +7 -2
- package/src/forms/controls/hidden-input.ts +4 -1
- package/src/forms/controls/{photo.test.ts → image.test.ts} +5 -22
- package/src/forms/controls/{photo.ts → image.ts} +3 -5
- package/src/forms/controls/multiple-files.ts +18 -1
- package/src/forms/controls/{multiple-photos.ts → multiple-images.ts} +1 -1
- package/src/forms/controls/number.ts +1 -1
- package/src/forms/controls/simple-input.ts +18 -34
- package/src/forms/controls/single-reference.ts +10 -2
- package/src/forms/controls/table.ts +90 -31
- package/src/forms/controls/textarea.ts +6 -4
- package/src/forms/controls/tickable.ts +13 -5
- package/src/forms/fields/boolean.ts +23 -1
- package/src/forms/fields/checkboxed-list.ts +11 -2
- package/src/forms/fields/collection-field.ts +16 -1
- package/src/forms/fields/color.ts +9 -0
- package/src/forms/fields/coordinates.ts +66 -0
- package/src/forms/fields/date.ts +50 -0
- package/src/forms/fields/datetime.ts +66 -0
- package/src/forms/fields/deep-reverse-single-reference-list.ts +136 -0
- package/src/forms/fields/deep-reverse-single-reference-table.ts +213 -0
- package/src/forms/fields/email.ts +9 -0
- package/src/forms/fields/enum-multiple-sealious.ts +48 -0
- package/src/forms/fields/field.test.ts +5 -5
- package/src/forms/fields/field.ts +94 -8
- package/src/forms/fields/fields.ts +23 -8
- package/src/forms/fields/file.test.ts +4 -16
- package/src/forms/fields/file.ts +43 -15
- package/src/forms/fields/float.ts +9 -0
- package/src/forms/fields/get-field-for-sealious.ts +304 -0
- package/src/forms/fields/html.ts +15 -0
- package/src/forms/fields/image.ts +12 -0
- package/src/forms/fields/int.ts +25 -0
- package/src/forms/fields/json.ts +48 -0
- package/src/forms/fields/markdown.ts +15 -0
- package/src/forms/fields/multiple-files.ts +10 -1
- package/src/forms/fields/number.ts +8 -1
- package/src/forms/fields/password.ts +17 -0
- package/src/forms/fields/pick-from-list-sealious.ts +22 -0
- package/src/forms/fields/pick-from-list.ts +7 -3
- package/src/forms/fields/proxy-field.ts +6 -1
- package/src/forms/fields/regexp.ts +27 -1
- package/src/forms/fields/simple-form-field.ts +95 -7
- package/src/forms/fields/single-reference.ts +62 -0
- package/src/forms/fields/structured-array.ts +115 -18
- package/src/forms/fields/table.ts +32 -1
- package/src/forms/fields/text.ts +18 -0
- package/src/forms/fields/url.ts +20 -0
- package/src/forms/form-types.ts +2 -0
- package/src/forms/form.test.ts +3 -4
- package/src/forms/form.ts +37 -16
- package/src/forms/forms.css +0 -85
- package/src/forms/multiform.test.ts +3 -3
- package/src/forms/multiform.ts +2 -0
- package/src/generate-stimulus.ts +1 -0
- package/src/index.ts +2 -1
- package/src/make-hidden-inputs.ts +1 -1
- package/src/mount.ts +14 -0
- package/src/notifier.ts +0 -1
- package/src/page/list.ts +15 -8
- package/src/page/mountable-with-fields.test.ts +1 -1
- package/src/page/mountable-with-fields.ts +18 -9
- package/src/register-external.ts +1 -1
- package/src/templates/form.ts +8 -9
- package/src/templates/multiform.ts +4 -4
- package/src/templates/page.ts +0 -2
- package/src/templates/shared/collection-create-form.ts +30 -66
- package/src/templates/shared/collection-edit-form.ts +41 -102
- package/src/templates/shared/collection-list.ts +12 -20
- package/src/templates/shared/item-delete.ts +0 -1
- package/src/templates/shared/shared-crud-form-fields.ts +37 -171
- package/src/test_utils/test-on-real-app.ts +4 -3
- package/src/utils/extract-fields-from-collection.ts +76 -25
- package/src/utils/make-slug.ts +1 -1
- package/src/utils/wrap-attributes.ts +17 -0
- package/lib/add-verbose-crud.js +0 -119
- package/lib/crud-field-snippets.js +0 -52
- package/lib/find-css-includes.js +0 -3
- package/lib/forms/controls/reverse-single-reference.js +0 -1
- package/lib/forms/fields/enum-multiple.js +0 -47
- package/lib/forms/fields/enum-multiple.test.js +0 -27
- package/lib/forms/fields/enum.js +0 -41
- package/lib/forms/fields/enum.test.js +0 -21
- package/lib/forms/fields/reverse-single-reference.js +0 -17
- package/lib/templates/shared/handlers/boolean.js +0 -14
- package/lib/templates/shared/handlers/date.js +0 -8
- package/lib/templates/shared/handlers/deep-reverse-single-reference.js +0 -209
- package/lib/templates/shared/handlers/default.js +0 -49
- package/lib/templates/shared/handlers/enum.js +0 -19
- package/lib/templates/shared/handlers/file.js +0 -23
- package/lib/templates/shared/handlers/image.js +0 -32
- package/lib/templates/shared/handlers/int.js +0 -11
- package/lib/templates/shared/handlers/jdd.js +0 -10
- package/lib/templates/shared/handlers/single-reference.js +0 -12
- package/lib/templates/shared/handlers/structured-array.js +0 -33
- package/src/add-verbose-crud.ts +0 -138
- package/src/crud-field-snippets.ts +0 -57
- package/src/find-css-includes.ts +0 -3
- package/src/forms/controls/reverse-single-reference.ts +0 -50
- package/src/forms/fields/enum-multiple.test.ts +0 -31
- package/src/forms/fields/enum-multiple.ts +0 -62
- package/src/forms/fields/enum.test.ts +0 -25
- package/src/forms/fields/enum.ts +0 -56
- package/src/forms/fields/reverse-single-reference.ts +0 -20
- package/src/templates/shared/handlers/boolean.ts +0 -18
- package/src/templates/shared/handlers/date.ts +0 -12
- package/src/templates/shared/handlers/deep-reverse-single-reference.ts +0 -244
- package/src/templates/shared/handlers/default.ts +0 -64
- package/src/templates/shared/handlers/enum.ts +0 -23
- package/src/templates/shared/handlers/file.ts +0 -27
- package/src/templates/shared/handlers/image.ts +0 -45
- package/src/templates/shared/handlers/int.ts +0 -15
- package/src/templates/shared/handlers/jdd.ts +0 -14
- package/src/templates/shared/handlers/single-reference.ts +0 -16
- package/src/templates/shared/handlers/structured-array.ts +0 -42
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { is, predicates } from "@sealcode/ts-predicates";
|
|
2
2
|
import { Context } from "koa";
|
|
3
|
+
import { SimpleInput } from "../controls/simple-input.js";
|
|
3
4
|
import { FormDataValue } from "../form-types.js";
|
|
4
5
|
import { FieldParseResult, FormField } from "./field.js";
|
|
6
|
+
import { FormControlContext } from "../controls/form-control.js";
|
|
5
7
|
|
|
6
|
-
export class RegExpField<Required extends boolean> extends FormField<
|
|
8
|
+
export class RegExpField<Required extends boolean> extends FormField<
|
|
9
|
+
Required,
|
|
10
|
+
string,
|
|
11
|
+
SimpleInput,
|
|
12
|
+
string
|
|
13
|
+
> {
|
|
7
14
|
constructor(
|
|
8
15
|
required: Required,
|
|
9
16
|
public regexp: RegExp,
|
|
@@ -50,4 +57,23 @@ export class RegExpField<Required extends boolean> extends FormField<Required> {
|
|
|
50
57
|
public getEmptyValue(): string {
|
|
51
58
|
return this.default_value || "";
|
|
52
59
|
}
|
|
60
|
+
|
|
61
|
+
public getControl(): SimpleInput {
|
|
62
|
+
return new SimpleInput(this, { label: this.name });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async getSealiousCreateValue(fctx: FormControlContext): Promise<string> {
|
|
66
|
+
const { parsed } = await this.getParsedValue(
|
|
67
|
+
fctx.ctx,
|
|
68
|
+
fctx.data.raw_values
|
|
69
|
+
);
|
|
70
|
+
return parsed || "";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async sealiousValueToForm(
|
|
74
|
+
ctx: Context,
|
|
75
|
+
sealious_value: string | null
|
|
76
|
+
): Promise<FormDataValue> {
|
|
77
|
+
return sealious_value || "";
|
|
78
|
+
}
|
|
53
79
|
}
|
|
@@ -2,11 +2,37 @@ import { FormDataValue } from "../form-types.js";
|
|
|
2
2
|
import { Context } from "koa";
|
|
3
3
|
import { predicates } from "@sealcode/ts-predicates";
|
|
4
4
|
import { FieldParseResult, FormField } from "./field.js";
|
|
5
|
+
import { SimpleInput } from "../controls/simple-input.js";
|
|
6
|
+
import { FormControl } from "../controls/controls.js";
|
|
7
|
+
import { CollectionItem } from "sealious";
|
|
8
|
+
import { FormControlContext } from "../controls/form-control.js";
|
|
5
9
|
|
|
6
|
-
export class SimpleFormField<
|
|
7
|
-
Required,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
export abstract class SimpleFormField<
|
|
11
|
+
Required extends boolean,
|
|
12
|
+
DefaultControl extends FormControl = SimpleInput,
|
|
13
|
+
Parsed = string
|
|
14
|
+
> extends FormField<Required, Parsed, DefaultControl> {
|
|
15
|
+
predicate = predicates.string;
|
|
16
|
+
|
|
17
|
+
constructor(required: Required, public type: string = "text") {
|
|
18
|
+
super(required);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async sealiousValueToForm(
|
|
22
|
+
ctx: Context,
|
|
23
|
+
value: unknown
|
|
24
|
+
): Promise<FormDataValue> {
|
|
25
|
+
if (value === null) {
|
|
26
|
+
return "";
|
|
27
|
+
}
|
|
28
|
+
return String(value) as FormDataValue;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class TextBasedSimpleField<
|
|
33
|
+
Required extends boolean,
|
|
34
|
+
DefaultControl extends FormControl = SimpleInput
|
|
35
|
+
> extends SimpleFormField<Required, DefaultControl, string | null> {
|
|
10
36
|
async parse(
|
|
11
37
|
_: Context,
|
|
12
38
|
raw_value: FormDataValue
|
|
@@ -18,13 +44,75 @@ export class SimpleFormField<Required extends boolean> extends FormField<
|
|
|
18
44
|
};
|
|
19
45
|
}
|
|
20
46
|
|
|
21
|
-
|
|
47
|
+
async getSealiousCreateValue(
|
|
48
|
+
fctx: FormControlContext
|
|
49
|
+
): Promise<string | null> {
|
|
50
|
+
const { parsed } = await this.getParsedValue(
|
|
51
|
+
fctx.ctx,
|
|
52
|
+
fctx.data.raw_values
|
|
53
|
+
);
|
|
54
|
+
return parsed || "";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async postSealiousCreate(
|
|
58
|
+
ctx: Context,
|
|
59
|
+
created_item: CollectionItem<any>
|
|
60
|
+
): Promise<void> {}
|
|
61
|
+
|
|
62
|
+
async postSealiousEdit(
|
|
63
|
+
ctx: Context,
|
|
64
|
+
edited_item: CollectionItem<any>
|
|
65
|
+
): Promise<void> {}
|
|
66
|
+
|
|
67
|
+
getControl(): DefaultControl {
|
|
68
|
+
return new SimpleInput(this, {
|
|
69
|
+
label: this.name,
|
|
70
|
+
type: this.type,
|
|
71
|
+
}) as unknown as DefaultControl;
|
|
72
|
+
}
|
|
22
73
|
|
|
23
74
|
public getEmptyValue(): string {
|
|
24
75
|
return "";
|
|
25
76
|
}
|
|
77
|
+
}
|
|
26
78
|
|
|
27
|
-
|
|
28
|
-
|
|
79
|
+
export class NumberBasedSimpleField<
|
|
80
|
+
Required extends boolean,
|
|
81
|
+
DefaultControl extends FormControl = SimpleInput
|
|
82
|
+
> extends SimpleFormField<Required, DefaultControl, number> {
|
|
83
|
+
async parse(
|
|
84
|
+
_: Context,
|
|
85
|
+
raw_value: FormDataValue
|
|
86
|
+
): Promise<FieldParseResult<number>> {
|
|
87
|
+
return {
|
|
88
|
+
parsed_value: parseFloat(raw_value as string) || 0,
|
|
89
|
+
parsable: true,
|
|
90
|
+
error: null,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async getSealiousCreateValue(
|
|
95
|
+
fctx: FormControlContext
|
|
96
|
+
): Promise<number | undefined> {
|
|
97
|
+
const { parsed } = await this.getParsedValue(
|
|
98
|
+
fctx.ctx,
|
|
99
|
+
fctx.data.raw_values
|
|
100
|
+
);
|
|
101
|
+
return parsed || 0;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async postSealiousCreate(): Promise<void> {}
|
|
105
|
+
|
|
106
|
+
async postSealiousEdit(): Promise<void> {}
|
|
107
|
+
|
|
108
|
+
getControl(): DefaultControl {
|
|
109
|
+
return new SimpleInput(this, {
|
|
110
|
+
label: this.name,
|
|
111
|
+
type: this.type,
|
|
112
|
+
}) as unknown as DefaultControl;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public getEmptyValue(): number {
|
|
116
|
+
return 0;
|
|
29
117
|
}
|
|
30
118
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Collection, FieldTypes as SealiousFieldTypes } from "sealious";
|
|
2
|
+
import { CollectionField } from "./collection-field.js";
|
|
3
|
+
import { SingleReferenceDropdown } from "../controls/single-reference.js";
|
|
4
|
+
import { FormControlContext } from "../controls/form-control.js";
|
|
5
|
+
import { Context } from "koa";
|
|
6
|
+
import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
|
|
7
|
+
import { toPascalCase } from "js-convert-case";
|
|
8
|
+
|
|
9
|
+
export class SingleReference<
|
|
10
|
+
TargetCollection extends Collection,
|
|
11
|
+
Required extends boolean,
|
|
12
|
+
F extends SealiousFieldTypes.SingleReference
|
|
13
|
+
> extends CollectionField<F, Required> {
|
|
14
|
+
getControl(): SingleReferenceDropdown<TargetCollection, F, Required> {
|
|
15
|
+
return new SingleReferenceDropdown(this, {
|
|
16
|
+
label: this.name,
|
|
17
|
+
getLabel: (item) => item.id,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async getSealiousCreateValue(
|
|
22
|
+
fctx: FormControlContext
|
|
23
|
+
): Promise<string | undefined> {
|
|
24
|
+
const { parsed } = await this.getParsedValue(
|
|
25
|
+
fctx.ctx,
|
|
26
|
+
fctx.data.raw_values
|
|
27
|
+
);
|
|
28
|
+
return parsed || undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async sealiousValueToForm(ctx: Context, value: string | null) {
|
|
32
|
+
return value || undefined;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
generateImportsForFieldList(field_info: ExtractedFieldInfo) {
|
|
36
|
+
if (!field_info.target) {
|
|
37
|
+
throw new Error("Expected 'target' attribute in field info");
|
|
38
|
+
}
|
|
39
|
+
return [
|
|
40
|
+
{
|
|
41
|
+
what: toPascalCase(field_info.target),
|
|
42
|
+
from: "src/back/collections/collections.js",
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
generateFieldDeclaration(
|
|
48
|
+
field_info: ExtractedFieldInfo,
|
|
49
|
+
vars: { form_field_types: string; sealious_field: string }
|
|
50
|
+
): string {
|
|
51
|
+
if (!field_info.target) {
|
|
52
|
+
throw new Error("Expected 'target' attribute in field info");
|
|
53
|
+
}
|
|
54
|
+
return `new ${vars.form_field_types}.${
|
|
55
|
+
this.constructor.name
|
|
56
|
+
}<typeof ${toPascalCase(field_info.target)}, ${String(
|
|
57
|
+
field_info.is_required
|
|
58
|
+
)}, typeof ${vars.sealious_field}>(${String(field_info.is_required)}, ${
|
|
59
|
+
vars.sealious_field
|
|
60
|
+
})`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -1,27 +1,124 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
1
6
|
import { Context } from "koa";
|
|
2
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
Field as SealiousField,
|
|
9
|
+
FieldTypes as SealiousFieldTypes,
|
|
10
|
+
FieldsetInput,
|
|
11
|
+
} from "sealious";
|
|
3
12
|
import { FormDataValue } from "../form-types.js";
|
|
4
|
-
import {
|
|
13
|
+
import { Table as TableControl } from "../controls/table.js";
|
|
14
|
+
import {
|
|
15
|
+
sealiousToFormField,
|
|
16
|
+
SealiousToFormField,
|
|
17
|
+
} from "./get-field-for-sealious.js";
|
|
18
|
+
import { FormControl, FormControlContext } from "../controls/form-control.js";
|
|
19
|
+
import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
|
|
20
|
+
import { Table } from "./table.js";
|
|
5
21
|
|
|
6
|
-
export class
|
|
7
|
-
|
|
8
|
-
> extends
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
constructor(public sealious_field: FieldTypes.StructuredArray<Fields>) {
|
|
13
|
-
super(true);
|
|
14
|
-
}
|
|
22
|
+
export class StructuredArray<
|
|
23
|
+
SealiousFields extends Record<string, SealiousField<unknown>>
|
|
24
|
+
> extends Table<{
|
|
25
|
+
[name in keyof SealiousFields]: SealiousToFormField<SealiousFields[name]>;
|
|
26
|
+
}> {
|
|
27
|
+
public sealious_field: SealiousFieldTypes.StructuredArray<SealiousFields>;
|
|
15
28
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
29
|
+
constructor(
|
|
30
|
+
sealious_field: SealiousFieldTypes.StructuredArray<SealiousFields>
|
|
31
|
+
) {
|
|
32
|
+
const columns = Object.fromEntries(
|
|
33
|
+
Object.entries(sealious_field.subfields).map(
|
|
34
|
+
([key, sealious_field]) => [
|
|
35
|
+
key,
|
|
36
|
+
sealiousToFormField(sealious_field),
|
|
37
|
+
]
|
|
38
|
+
)
|
|
39
|
+
) as {
|
|
40
|
+
[name in keyof SealiousFields]: SealiousToFormField<
|
|
41
|
+
SealiousFields[name]
|
|
42
|
+
>;
|
|
21
43
|
};
|
|
44
|
+
super(columns);
|
|
45
|
+
this.sealious_field = sealious_field;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
getControl(): TableControl<{
|
|
49
|
+
[name in keyof SealiousFields]: SealiousToFormField<
|
|
50
|
+
SealiousFields[name]
|
|
51
|
+
>;
|
|
52
|
+
}> {
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
55
|
+
return new TableControl<{
|
|
56
|
+
[name in keyof SealiousFields]: SealiousToFormField<
|
|
57
|
+
SealiousFields[name]
|
|
58
|
+
>;
|
|
59
|
+
}>(this as any, {
|
|
60
|
+
label: this.name,
|
|
61
|
+
subfield_controls: Object.fromEntries(
|
|
62
|
+
Object.entries(this.columns).map(([column_name, subfield]) => [
|
|
63
|
+
column_name as keyof SealiousFields,
|
|
64
|
+
subfield.getControl(),
|
|
65
|
+
])
|
|
66
|
+
) as unknown as Record<keyof SealiousFields, FormControl>,
|
|
67
|
+
allow_adding: true,
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
70
|
+
make_new_row: () => ({} as any),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
generateFieldDeclaration(
|
|
75
|
+
_field_info: ExtractedFieldInfo,
|
|
76
|
+
vars: { form_field_types: string; sealious_field: string }
|
|
77
|
+
): string {
|
|
78
|
+
return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async getSealiousCreateValue(
|
|
82
|
+
fctx: FormControlContext
|
|
83
|
+
): Promise<
|
|
84
|
+
SealiousFieldTypes.ArrayStorageInput<FieldsetInput<SealiousFields>>
|
|
85
|
+
> {
|
|
86
|
+
const { parsed } = await this.getParsedValue(
|
|
87
|
+
fctx.ctx,
|
|
88
|
+
fctx.data.raw_values
|
|
89
|
+
);
|
|
90
|
+
return (
|
|
91
|
+
(parsed as SealiousFieldTypes.ArrayStorageInput<
|
|
92
|
+
FieldsetInput<SealiousFields>
|
|
93
|
+
>) || this.getEmptyValue()
|
|
94
|
+
);
|
|
22
95
|
}
|
|
23
96
|
|
|
24
|
-
|
|
25
|
-
|
|
97
|
+
async sealiousValueToForm(
|
|
98
|
+
ctx: Context,
|
|
99
|
+
sealiousValue: Record<string, FormDataValue | null>[] | null
|
|
100
|
+
): Promise<FormDataValue> {
|
|
101
|
+
return Promise.all(
|
|
102
|
+
(sealiousValue || []).map(async (element) =>
|
|
103
|
+
Object.fromEntries(
|
|
104
|
+
await Promise.all(
|
|
105
|
+
Object.entries(element).map(async ([key, value]) => {
|
|
106
|
+
const form_subfield = this.columns[key];
|
|
107
|
+
if (!form_subfield) {
|
|
108
|
+
return [key, ""];
|
|
109
|
+
}
|
|
110
|
+
return [
|
|
111
|
+
key,
|
|
112
|
+
await form_subfield.sealiousValueToForm(
|
|
113
|
+
ctx,
|
|
114
|
+
value,
|
|
115
|
+
{} as any
|
|
116
|
+
),
|
|
117
|
+
];
|
|
118
|
+
})
|
|
119
|
+
)
|
|
120
|
+
)
|
|
121
|
+
)
|
|
122
|
+
);
|
|
26
123
|
}
|
|
27
124
|
}
|
|
@@ -2,6 +2,11 @@ import { is, predicates } from "@sealcode/ts-predicates";
|
|
|
2
2
|
import { Context } from "koa";
|
|
3
3
|
import { FormDataValue } from "../form-types.js";
|
|
4
4
|
import { FieldParseResult, FormField } from "./field.js";
|
|
5
|
+
import {
|
|
6
|
+
Table as TableControl,
|
|
7
|
+
TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER,
|
|
8
|
+
} from "../controls/table.js";
|
|
9
|
+
import { FormControl } from "../controls/form-control.js";
|
|
5
10
|
|
|
6
11
|
export type ExtractFormFieldParsed<Field extends FormField> =
|
|
7
12
|
Field extends FormField<
|
|
@@ -34,6 +39,16 @@ export class Table<F extends Record<string, FormField>> extends FormField<
|
|
|
34
39
|
return [];
|
|
35
40
|
}
|
|
36
41
|
|
|
42
|
+
setName(name: string) {
|
|
43
|
+
super.setName(name);
|
|
44
|
+
for (const [column_name, field] of Object.entries(this.columns)) {
|
|
45
|
+
field.setName(
|
|
46
|
+
`${this.name}[${TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER}][${column_name}]`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
|
|
37
52
|
async parse(
|
|
38
53
|
ctx: Context,
|
|
39
54
|
raw_value: FormDataValue
|
|
@@ -51,7 +66,6 @@ export class Table<F extends Record<string, FormField>> extends FormField<
|
|
|
51
66
|
const row_data = raw_value[row_number];
|
|
52
67
|
const parsed_row: Record<string, unknown> = {};
|
|
53
68
|
if (!is(row_data, predicates.object)) {
|
|
54
|
-
console.log("table.ts<fields>:55", this.name);
|
|
55
69
|
throw new Error(`Expected object, got ${String(row_data)}`);
|
|
56
70
|
}
|
|
57
71
|
for (const key in row_data) {
|
|
@@ -89,4 +103,21 @@ export class Table<F extends Record<string, FormField>> extends FormField<
|
|
|
89
103
|
const ret = { parsed_value: result, parsable: true, error: null };
|
|
90
104
|
return ret as FieldParseResult<TableFieldParsed<F>>;
|
|
91
105
|
}
|
|
106
|
+
|
|
107
|
+
getControl(): TableControl<F> {
|
|
108
|
+
return new TableControl<F>(this, {
|
|
109
|
+
label: this.name,
|
|
110
|
+
subfield_controls: Object.fromEntries(
|
|
111
|
+
Object.entries(this.columns).map(([column_name, field]) => [
|
|
112
|
+
column_name as keyof F,
|
|
113
|
+
field.getControl(),
|
|
114
|
+
])
|
|
115
|
+
) as Record<keyof F, FormControl>,
|
|
116
|
+
allow_adding: true,
|
|
117
|
+
make_new_row: async () =>
|
|
118
|
+
Object.fromEntries(
|
|
119
|
+
Object.keys(this.columns).map((key) => [key, ""])
|
|
120
|
+
) as Record<keyof F, string>,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
92
123
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FormControlContext } from "../controls/form-control.js";
|
|
2
|
+
import { TextBasedSimpleField } from "./simple-form-field.js";
|
|
3
|
+
|
|
4
|
+
export class Text<
|
|
5
|
+
Required extends boolean
|
|
6
|
+
> extends TextBasedSimpleField<Required> {
|
|
7
|
+
constructor(required: Required) {
|
|
8
|
+
super(required, "text");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async getSealiousCreateValue(fctx: FormControlContext): Promise<string> {
|
|
12
|
+
const { parsed } = await this.getParsedValue(
|
|
13
|
+
fctx.ctx,
|
|
14
|
+
fctx.data.raw_values
|
|
15
|
+
);
|
|
16
|
+
return parsed || this.getEmptyValue();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { FormControlContext } from "../controls/form-control.js";
|
|
2
|
+
import { TextBasedSimpleField } from "./simple-form-field.js";
|
|
3
|
+
|
|
4
|
+
export class URLField<
|
|
5
|
+
Required extends boolean
|
|
6
|
+
> extends TextBasedSimpleField<Required> {
|
|
7
|
+
constructor(required: Required) {
|
|
8
|
+
super(required, "text");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async getSealiousCreateValue(
|
|
12
|
+
fctx: FormControlContext
|
|
13
|
+
): Promise<string | null> {
|
|
14
|
+
const { parsed } = await this.getParsedValue(
|
|
15
|
+
fctx.ctx,
|
|
16
|
+
fctx.data.raw_values
|
|
17
|
+
);
|
|
18
|
+
return parsed || null;
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/forms/form-types.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FilePointer } from "@sealcode/file-manager";
|
|
2
2
|
import type { FlatTemplatable } from "tempstream";
|
|
3
3
|
import type { FormField } from "./fields/field.js";
|
|
4
|
+
import { FieldMessages } from "./controls/form-control.js";
|
|
4
5
|
|
|
5
6
|
export type FormDataPrimitive =
|
|
6
7
|
| string
|
|
@@ -28,6 +29,7 @@ export type FormMessage = { type: "info" | "success" | "error"; text: string };
|
|
|
28
29
|
export type FormData<Fieldnames extends string = string> = {
|
|
29
30
|
raw_values: Record<Fieldnames, FormDataValue>;
|
|
30
31
|
messages: FormMessage[];
|
|
32
|
+
field_messages: FieldMessages<Fieldnames>;
|
|
31
33
|
};
|
|
32
34
|
|
|
33
35
|
export type FormReaction =
|
package/src/forms/form.test.ts
CHANGED
|
@@ -9,11 +9,11 @@ import { getBrowser } from "../utils/browser-creator.js";
|
|
|
9
9
|
import { assertThrowsAsync } from "../utils/utils.js";
|
|
10
10
|
import { FormDataValue } from "./form-types.js";
|
|
11
11
|
import getPort from "get-port";
|
|
12
|
-
import {
|
|
12
|
+
import { TextBasedSimpleField } from "./fields/simple-form-field.js";
|
|
13
13
|
import { expect as PlaywritghtExpect } from "@playwright/test";
|
|
14
14
|
|
|
15
15
|
const fields = {
|
|
16
|
-
text: new Fields.
|
|
16
|
+
text: new Fields.TextBasedSimpleField(true),
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
export function form_factory(canAccessFun?: Mountable["canAccess"]): Form<typeof fields, void> {
|
|
@@ -139,7 +139,6 @@ describe("form test", () => {
|
|
|
139
139
|
async (
|
|
140
140
|
ctx: Koa.Context
|
|
141
141
|
): Promise<{ canAccess: boolean; message: string }> => {
|
|
142
|
-
console.log("CAN ACCESS? FALSE");
|
|
143
142
|
return { canAccess: false, message: "" };
|
|
144
143
|
}
|
|
145
144
|
),
|
|
@@ -370,7 +369,7 @@ describe("form test", () => {
|
|
|
370
369
|
const router = new Router();
|
|
371
370
|
|
|
372
371
|
const fields = {
|
|
373
|
-
title: new
|
|
372
|
+
title: new TextBasedSimpleField(true),
|
|
374
373
|
};
|
|
375
374
|
|
|
376
375
|
mount(
|
package/src/forms/form.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Context } from "koa";
|
|
|
2
2
|
import { randomUUID } from "crypto";
|
|
3
3
|
|
|
4
4
|
import Router from "@koa/router";
|
|
5
|
-
import {
|
|
5
|
+
import { tempstream } from "tempstream";
|
|
6
6
|
import {
|
|
7
7
|
hasFieldOfType,
|
|
8
8
|
hasShape,
|
|
@@ -22,6 +22,10 @@ import {
|
|
|
22
22
|
MountableWithFields,
|
|
23
23
|
PageErrorMessage,
|
|
24
24
|
} from "../page/mountable-with-fields.js";
|
|
25
|
+
import { Readable } from "stream";
|
|
26
|
+
import { FormField } from "../index.js";
|
|
27
|
+
import { FieldMessages } from "./controls/form-control.js";
|
|
28
|
+
import { Errors as SealiousErrors } from "sealious";
|
|
25
29
|
|
|
26
30
|
export abstract class Form<
|
|
27
31
|
F extends Fields,
|
|
@@ -43,11 +47,11 @@ export abstract class Form<
|
|
|
43
47
|
async renderError(
|
|
44
48
|
_: Context,
|
|
45
49
|
error: PageErrorMessage
|
|
46
|
-
): Promise<
|
|
50
|
+
): Promise<JSX.Element | Readable> {
|
|
47
51
|
return tempstream/* HTML */ `<div>${error.message}</div>`;
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
makeSubmitButton():
|
|
54
|
+
makeSubmitButton(): JSX.Element {
|
|
51
55
|
return /* HTML */ `<input
|
|
52
56
|
type="submit"
|
|
53
57
|
value="${this.submitButtonText}"
|
|
@@ -60,7 +64,7 @@ export abstract class Form<
|
|
|
60
64
|
ctx: Context,
|
|
61
65
|
data: FormData,
|
|
62
66
|
show_field_errors: boolean
|
|
63
|
-
): Promise<
|
|
67
|
+
): Promise<JSX.Element | Readable> {
|
|
64
68
|
return tempstream/* HTML */ `<div class="form-container">
|
|
65
69
|
${this.makeOpenFormTag(ctx)}
|
|
66
70
|
${!this.controls.some((control) => control.role == "messages")
|
|
@@ -81,7 +85,7 @@ export abstract class Form<
|
|
|
81
85
|
return [];
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
public makeOpenFormTag(ctx: Context):
|
|
88
|
+
public makeOpenFormTag(ctx: Context): JSX.Element {
|
|
85
89
|
return tempstream`<form enctype="multipart/form-data" method="POST" id="${
|
|
86
90
|
this.form_id
|
|
87
91
|
}" action="${this.action}" class="${this.makeFormClasses(ctx).then(
|
|
@@ -91,14 +95,14 @@ export abstract class Form<
|
|
|
91
95
|
}></form><div class="form">`;
|
|
92
96
|
}
|
|
93
97
|
|
|
94
|
-
public makeCloseFormTag():
|
|
98
|
+
public makeCloseFormTag(): JSX.Element {
|
|
95
99
|
return `</div>`;
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
public async onValuesInvalid(
|
|
99
103
|
ctx: Context,
|
|
100
104
|
form_messages: FormMessage[],
|
|
101
|
-
|
|
105
|
+
field_errors: FieldMessages<keyof Fields>
|
|
102
106
|
): Promise<FormReaction> {
|
|
103
107
|
const messages = form_messages.length
|
|
104
108
|
? form_messages
|
|
@@ -110,8 +114,9 @@ export abstract class Form<
|
|
|
110
114
|
{
|
|
111
115
|
raw_values: await this.extractRawValues(ctx),
|
|
112
116
|
messages,
|
|
117
|
+
field_messages: field_errors,
|
|
113
118
|
},
|
|
114
|
-
|
|
119
|
+
true
|
|
115
120
|
),
|
|
116
121
|
messages,
|
|
117
122
|
};
|
|
@@ -123,12 +128,21 @@ export abstract class Form<
|
|
|
123
128
|
error: unknown
|
|
124
129
|
): Promise<FormReaction> {
|
|
125
130
|
let error_message = "Unknown error has occured";
|
|
131
|
+
let field_messages: FieldMessages = {};
|
|
126
132
|
if (
|
|
127
133
|
is(error, predicates.object) &&
|
|
128
134
|
hasShape({ message: predicates.string }, error)
|
|
129
135
|
) {
|
|
130
136
|
error_message = error.message;
|
|
131
137
|
}
|
|
138
|
+
if (error instanceof SealiousErrors.FieldsError) {
|
|
139
|
+
field_messages = Object.fromEntries(
|
|
140
|
+
Object.entries(error.field_messages).map(([key, value]) => {
|
|
141
|
+
const message = value?.message || "";
|
|
142
|
+
return [key, { type: "error", message }];
|
|
143
|
+
})
|
|
144
|
+
);
|
|
145
|
+
}
|
|
132
146
|
const messages = [<const>{ type: "error", text: error_message }];
|
|
133
147
|
return {
|
|
134
148
|
action: "stay",
|
|
@@ -137,8 +151,9 @@ export abstract class Form<
|
|
|
137
151
|
{
|
|
138
152
|
raw_values: data.raw_values,
|
|
139
153
|
messages,
|
|
154
|
+
field_messages,
|
|
140
155
|
},
|
|
141
|
-
|
|
156
|
+
true
|
|
142
157
|
),
|
|
143
158
|
};
|
|
144
159
|
}
|
|
@@ -163,8 +178,9 @@ export abstract class Form<
|
|
|
163
178
|
{
|
|
164
179
|
raw_values: await this.getInitialValues(ctx),
|
|
165
180
|
messages,
|
|
181
|
+
field_messages: {},
|
|
166
182
|
},
|
|
167
|
-
|
|
183
|
+
false
|
|
168
184
|
),
|
|
169
185
|
messages,
|
|
170
186
|
};
|
|
@@ -181,10 +197,6 @@ export abstract class Form<
|
|
|
181
197
|
raw_values
|
|
182
198
|
);
|
|
183
199
|
if (!valid) {
|
|
184
|
-
console.debug("Form values invalid: ", {
|
|
185
|
-
form_messages,
|
|
186
|
-
field_errors,
|
|
187
|
-
});
|
|
188
200
|
return this.onValuesInvalid(ctx, form_messages, field_errors);
|
|
189
201
|
}
|
|
190
202
|
try {
|
|
@@ -192,12 +204,14 @@ export abstract class Form<
|
|
|
192
204
|
const result = await this.onSubmit(ctx, {
|
|
193
205
|
raw_values,
|
|
194
206
|
messages: [],
|
|
207
|
+
field_messages: {},
|
|
195
208
|
});
|
|
196
209
|
return this.onSuccess(
|
|
197
210
|
ctx,
|
|
198
211
|
{
|
|
199
212
|
raw_values: await this.getRawValuesOnSuccess(ctx),
|
|
200
213
|
messages: [],
|
|
214
|
+
field_messages: {},
|
|
201
215
|
},
|
|
202
216
|
result
|
|
203
217
|
);
|
|
@@ -222,6 +236,7 @@ export abstract class Form<
|
|
|
222
236
|
text: message,
|
|
223
237
|
},
|
|
224
238
|
],
|
|
239
|
+
field_messages: {},
|
|
225
240
|
},
|
|
226
241
|
e
|
|
227
242
|
);
|
|
@@ -257,12 +272,12 @@ export abstract class Form<
|
|
|
257
272
|
{
|
|
258
273
|
raw_values: await this.extractRawValues(ctx),
|
|
259
274
|
messages: [],
|
|
275
|
+
field_messages: {},
|
|
260
276
|
},
|
|
261
|
-
|
|
277
|
+
false
|
|
262
278
|
);
|
|
263
279
|
});
|
|
264
280
|
router.post(path, async (ctx) => {
|
|
265
|
-
console.log("REGULAR FORM HANDLE");
|
|
266
281
|
const reaction =
|
|
267
282
|
(ctx.override_reaction as FormReaction | undefined) ||
|
|
268
283
|
(await this.handlePost(ctx));
|
|
@@ -283,4 +298,10 @@ export abstract class Form<
|
|
|
283
298
|
? ctx.$body
|
|
284
299
|
: this.getInitialValues(ctx);
|
|
285
300
|
}
|
|
301
|
+
|
|
302
|
+
static initFieldNames(fields: Record<string, FormField>): void {
|
|
303
|
+
for (const [field_name, field] of Object.entries(fields)) {
|
|
304
|
+
field.setName(field_name);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
286
307
|
}
|