@sealcode/sealgen 0.18.10 → 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 +74 -69
- 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 -3
- 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 -2
- 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 -4
- 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 -1
- 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 -3
- 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 -8
- 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 -2
- 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/mount.d.ts +0 -1
- 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/mountable.d.ts +0 -1
- package/@types/page/page.d.sync-conflict-20250918-184320-TFDLWFG.ts +18 -0
- package/@types/page/page.d.ts +0 -1
- 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/page/stateful-page.d.ts +0 -1
- 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 +4 -3
- 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,5 +1,9 @@
|
|
|
1
1
|
import { is, predicates } from "@sealcode/ts-predicates";
|
|
2
2
|
import { FormField } from "./field.js";
|
|
3
|
+
import {
|
|
4
|
+
Table as TableControl,
|
|
5
|
+
TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER
|
|
6
|
+
} from "../controls/table.js";
|
|
3
7
|
class Table extends FormField {
|
|
4
8
|
constructor(columns) {
|
|
5
9
|
super(false);
|
|
@@ -8,6 +12,15 @@ class Table extends FormField {
|
|
|
8
12
|
getEmptyValue() {
|
|
9
13
|
return [];
|
|
10
14
|
}
|
|
15
|
+
setName(name) {
|
|
16
|
+
super.setName(name);
|
|
17
|
+
for (const [column_name, field] of Object.entries(this.columns)) {
|
|
18
|
+
field.setName(
|
|
19
|
+
`${this.name}[${TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER}][${column_name}]`
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
11
24
|
async parse(ctx, raw_value) {
|
|
12
25
|
if (!is(raw_value, predicates.object)) {
|
|
13
26
|
return {
|
|
@@ -21,7 +34,6 @@ class Table extends FormField {
|
|
|
21
34
|
const row_data = raw_value[row_number];
|
|
22
35
|
const parsed_row = {};
|
|
23
36
|
if (!is(row_data, predicates.object)) {
|
|
24
|
-
console.log("table.ts<fields>:55", this.name);
|
|
25
37
|
throw new Error(`Expected object, got ${String(row_data)}`);
|
|
26
38
|
}
|
|
27
39
|
for (const key in row_data) {
|
|
@@ -56,6 +68,21 @@ class Table extends FormField {
|
|
|
56
68
|
const ret = { parsed_value: result, parsable: true, error: null };
|
|
57
69
|
return ret;
|
|
58
70
|
}
|
|
71
|
+
getControl() {
|
|
72
|
+
return new TableControl(this, {
|
|
73
|
+
label: this.name,
|
|
74
|
+
subfield_controls: Object.fromEntries(
|
|
75
|
+
Object.entries(this.columns).map(([column_name, field]) => [
|
|
76
|
+
column_name,
|
|
77
|
+
field.getControl()
|
|
78
|
+
])
|
|
79
|
+
),
|
|
80
|
+
allow_adding: true,
|
|
81
|
+
make_new_row: async () => Object.fromEntries(
|
|
82
|
+
Object.keys(this.columns).map((key) => [key, ""])
|
|
83
|
+
)
|
|
84
|
+
});
|
|
85
|
+
}
|
|
59
86
|
}
|
|
60
87
|
export {
|
|
61
88
|
Table
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { TextBasedSimpleField } from "./simple-form-field.js";
|
|
2
|
+
class Text extends TextBasedSimpleField {
|
|
3
|
+
constructor(required) {
|
|
4
|
+
super(required, "text");
|
|
5
|
+
}
|
|
6
|
+
async getSealiousCreateValue(fctx) {
|
|
7
|
+
const { parsed } = await this.getParsedValue(
|
|
8
|
+
fctx.ctx,
|
|
9
|
+
fctx.data.raw_values
|
|
10
|
+
);
|
|
11
|
+
return parsed || this.getEmptyValue();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
Text
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { TextBasedSimpleField } from "./simple-form-field.js";
|
|
2
|
+
class URLField extends TextBasedSimpleField {
|
|
3
|
+
constructor(required) {
|
|
4
|
+
super(required, "text");
|
|
5
|
+
}
|
|
6
|
+
async getSealiousCreateValue(fctx) {
|
|
7
|
+
const { parsed } = await this.getParsedValue(
|
|
8
|
+
fctx.ctx,
|
|
9
|
+
fctx.data.raw_values
|
|
10
|
+
);
|
|
11
|
+
return parsed || null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
URLField
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=url.js.map
|
package/lib/forms/form.js
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
MountableWithFields
|
|
12
12
|
} from "../page/mountable-with-fields.js";
|
|
13
|
+
import { Errors as SealiousErrors } from "sealious";
|
|
13
14
|
class Form extends MountableWithFields {
|
|
14
15
|
constructor() {
|
|
15
16
|
super(...arguments);
|
|
@@ -59,7 +60,7 @@ class Form extends MountableWithFields {
|
|
|
59
60
|
makeCloseFormTag() {
|
|
60
61
|
return `</div>`;
|
|
61
62
|
}
|
|
62
|
-
async onValuesInvalid(ctx, form_messages,
|
|
63
|
+
async onValuesInvalid(ctx, form_messages, field_errors) {
|
|
63
64
|
const messages = form_messages.length ? form_messages : [{ type: "error", text: "Some fields are invalid" }];
|
|
64
65
|
return {
|
|
65
66
|
action: "stay",
|
|
@@ -67,7 +68,8 @@ class Form extends MountableWithFields {
|
|
|
67
68
|
ctx,
|
|
68
69
|
{
|
|
69
70
|
raw_values: await this.extractRawValues(ctx),
|
|
70
|
-
messages
|
|
71
|
+
messages,
|
|
72
|
+
field_messages: field_errors
|
|
71
73
|
},
|
|
72
74
|
true
|
|
73
75
|
),
|
|
@@ -76,9 +78,18 @@ class Form extends MountableWithFields {
|
|
|
76
78
|
}
|
|
77
79
|
async onError(ctx, data, error) {
|
|
78
80
|
let error_message = "Unknown error has occured";
|
|
81
|
+
let field_messages = {};
|
|
79
82
|
if (is(error, predicates.object) && hasShape({ message: predicates.string }, error)) {
|
|
80
83
|
error_message = error.message;
|
|
81
84
|
}
|
|
85
|
+
if (error instanceof SealiousErrors.FieldsError) {
|
|
86
|
+
field_messages = Object.fromEntries(
|
|
87
|
+
Object.entries(error.field_messages).map(([key, value]) => {
|
|
88
|
+
const message = value?.message || "";
|
|
89
|
+
return [key, { type: "error", message }];
|
|
90
|
+
})
|
|
91
|
+
);
|
|
92
|
+
}
|
|
82
93
|
const messages = [{ type: "error", text: error_message }];
|
|
83
94
|
return {
|
|
84
95
|
action: "stay",
|
|
@@ -86,7 +97,8 @@ class Form extends MountableWithFields {
|
|
|
86
97
|
ctx,
|
|
87
98
|
{
|
|
88
99
|
raw_values: data.raw_values,
|
|
89
|
-
messages
|
|
100
|
+
messages,
|
|
101
|
+
field_messages
|
|
90
102
|
},
|
|
91
103
|
true
|
|
92
104
|
)
|
|
@@ -102,7 +114,8 @@ class Form extends MountableWithFields {
|
|
|
102
114
|
ctx,
|
|
103
115
|
{
|
|
104
116
|
raw_values: await this.getInitialValues(ctx),
|
|
105
|
-
messages
|
|
117
|
+
messages,
|
|
118
|
+
field_messages: {}
|
|
106
119
|
},
|
|
107
120
|
false
|
|
108
121
|
),
|
|
@@ -119,23 +132,21 @@ class Form extends MountableWithFields {
|
|
|
119
132
|
raw_values
|
|
120
133
|
);
|
|
121
134
|
if (!valid) {
|
|
122
|
-
console.debug("Form values invalid: ", {
|
|
123
|
-
form_messages,
|
|
124
|
-
field_errors
|
|
125
|
-
});
|
|
126
135
|
return this.onValuesInvalid(ctx, form_messages, field_errors);
|
|
127
136
|
}
|
|
128
137
|
try {
|
|
129
138
|
ctx.status = 303;
|
|
130
139
|
const result = await this.onSubmit(ctx, {
|
|
131
140
|
raw_values,
|
|
132
|
-
messages: []
|
|
141
|
+
messages: [],
|
|
142
|
+
field_messages: {}
|
|
133
143
|
});
|
|
134
144
|
return this.onSuccess(
|
|
135
145
|
ctx,
|
|
136
146
|
{
|
|
137
147
|
raw_values: await this.getRawValuesOnSuccess(ctx),
|
|
138
|
-
messages: []
|
|
148
|
+
messages: [],
|
|
149
|
+
field_messages: {}
|
|
139
150
|
},
|
|
140
151
|
result
|
|
141
152
|
);
|
|
@@ -151,7 +162,8 @@ class Form extends MountableWithFields {
|
|
|
151
162
|
type: "error",
|
|
152
163
|
text: message
|
|
153
164
|
}
|
|
154
|
-
]
|
|
165
|
+
],
|
|
166
|
+
field_messages: {}
|
|
155
167
|
},
|
|
156
168
|
e
|
|
157
169
|
);
|
|
@@ -181,13 +193,13 @@ class Form extends MountableWithFields {
|
|
|
181
193
|
ctx,
|
|
182
194
|
{
|
|
183
195
|
raw_values: await this.extractRawValues(ctx),
|
|
184
|
-
messages: []
|
|
196
|
+
messages: [],
|
|
197
|
+
field_messages: {}
|
|
185
198
|
},
|
|
186
199
|
false
|
|
187
200
|
);
|
|
188
201
|
});
|
|
189
202
|
router.post(path, async (ctx) => {
|
|
190
|
-
console.log("REGULAR FORM HANDLE");
|
|
191
203
|
const reaction = ctx.override_reaction || await this.handlePost(ctx);
|
|
192
204
|
if (reaction.action == "stay") {
|
|
193
205
|
ctx.status = 422;
|
|
@@ -201,6 +213,11 @@ class Form extends MountableWithFields {
|
|
|
201
213
|
async extractRawValues(ctx) {
|
|
202
214
|
return Object.keys(ctx.$body).length ? ctx.$body : this.getInitialValues(ctx);
|
|
203
215
|
}
|
|
216
|
+
static initFieldNames(fields) {
|
|
217
|
+
for (const [field_name, field] of Object.entries(fields)) {
|
|
218
|
+
field.setName(field_name);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
204
221
|
}
|
|
205
222
|
export {
|
|
206
223
|
Form
|
package/lib/forms/form.test.js
CHANGED
|
@@ -7,10 +7,10 @@ import { locator_is_visible } from "../test_utils/locator_is_visible.js";
|
|
|
7
7
|
import { getBrowser } from "../utils/browser-creator.js";
|
|
8
8
|
import { assertThrowsAsync } from "../utils/utils.js";
|
|
9
9
|
import getPort from "get-port";
|
|
10
|
-
import {
|
|
10
|
+
import { TextBasedSimpleField } from "./fields/simple-form-field.js";
|
|
11
11
|
import { expect as PlaywritghtExpect } from "@playwright/test";
|
|
12
12
|
const fields = {
|
|
13
|
-
text: new Fields.
|
|
13
|
+
text: new Fields.TextBasedSimpleField(true)
|
|
14
14
|
};
|
|
15
15
|
function form_factory(canAccessFun) {
|
|
16
16
|
const result = new class extends Form {
|
|
@@ -121,7 +121,6 @@ describe("form test", () => {
|
|
|
121
121
|
"/",
|
|
122
122
|
form_factory(
|
|
123
123
|
async (ctx) => {
|
|
124
|
-
console.log("CAN ACCESS? FALSE");
|
|
125
124
|
return { canAccess: false, message: "" };
|
|
126
125
|
}
|
|
127
126
|
),
|
|
@@ -322,7 +321,7 @@ describe("form test", () => {
|
|
|
322
321
|
const app = new Koa();
|
|
323
322
|
const router = new Router();
|
|
324
323
|
const fields2 = {
|
|
325
|
-
title: new
|
|
324
|
+
title: new TextBasedSimpleField(true)
|
|
326
325
|
};
|
|
327
326
|
mount(
|
|
328
327
|
router,
|
package/lib/forms/multiform.js
CHANGED
|
@@ -78,7 +78,8 @@ class Multiform extends MountableWithFields {
|
|
|
78
78
|
ctx,
|
|
79
79
|
{
|
|
80
80
|
raw_values: await this.getSubformRawValues(ctx, sub_form_name),
|
|
81
|
-
messages: []
|
|
81
|
+
messages: [],
|
|
82
|
+
field_messages: {}
|
|
82
83
|
},
|
|
83
84
|
show_field_errors
|
|
84
85
|
);
|
|
@@ -97,7 +98,8 @@ class Multiform extends MountableWithFields {
|
|
|
97
98
|
async render(ctx, messages, prerenderedForms = {}, show_field_errors) {
|
|
98
99
|
return tempstream`${this.renderMessages(ctx, {
|
|
99
100
|
raw_values: {},
|
|
100
|
-
messages
|
|
101
|
+
messages,
|
|
102
|
+
field_messages: {}
|
|
101
103
|
})}
|
|
102
104
|
<div class="forms">
|
|
103
105
|
<form
|
|
@@ -8,7 +8,7 @@ import { Multiform } from "./multiform.js";
|
|
|
8
8
|
import { assertThrowsAsync } from "../utils/utils.js";
|
|
9
9
|
import { form_factory } from "./form.test.js";
|
|
10
10
|
import { getBrowser } from "../utils/browser-creator.js";
|
|
11
|
-
import {
|
|
11
|
+
import { TextBasedSimpleField } from "./fields/simple-form-field.js";
|
|
12
12
|
import { Form } from "./form.js";
|
|
13
13
|
import { FormHeader } from "./controls/form-header.js";
|
|
14
14
|
import { SimpleInput } from "./controls/simple-input.js";
|
|
@@ -17,7 +17,7 @@ import getPort from "get-port";
|
|
|
17
17
|
const port = await getPort();
|
|
18
18
|
console.log(`Using port ${port} form multiform.test.ts`);
|
|
19
19
|
const fields1 = {
|
|
20
|
-
email: new
|
|
20
|
+
email: new TextBasedSimpleField(true)
|
|
21
21
|
};
|
|
22
22
|
const form1 = new class extends Form {
|
|
23
23
|
constructor() {
|
|
@@ -31,7 +31,7 @@ const form1 = new class extends Form {
|
|
|
31
31
|
}
|
|
32
32
|
}();
|
|
33
33
|
const fields2 = {
|
|
34
|
-
name: new
|
|
34
|
+
name: new TextBasedSimpleField(true)
|
|
35
35
|
};
|
|
36
36
|
const form2 = new class extends Form {
|
|
37
37
|
constructor() {
|
package/lib/generate-stimulus.js
CHANGED
|
@@ -12,6 +12,7 @@ async function generateStimulusControllers(controller_dirs) {
|
|
|
12
12
|
target_locreq.resolve("src/"),
|
|
13
13
|
...controller_dirs
|
|
14
14
|
];
|
|
15
|
+
console.log("Looking for controllers in ", stimulus_search_dirs);
|
|
15
16
|
const controller_names = (await Promise.all(stimulus_search_dirs.map((dir) => recursive(dir)))).flat().filter((c) => c.endsWith(".stimulus.ts")).sort();
|
|
16
17
|
const controller_data = controller_names.map(
|
|
17
18
|
(p) => "./" + path.relative(target_locreq.resolve(dirname(output_file)), p).replace(/\.[tj]sx?$/, ".js")
|
package/lib/index.js
CHANGED
|
@@ -16,6 +16,7 @@ export * from "./forms/multiform.js";
|
|
|
16
16
|
import * as Components from "./components/components.js";
|
|
17
17
|
export * from "./mount.js";
|
|
18
18
|
export * from "./page/default-list-filters.js";
|
|
19
|
+
export * from "./forms/fields/get-field-for-sealious.js";
|
|
19
20
|
export {
|
|
20
21
|
Components,
|
|
21
22
|
Controls,
|
|
@@ -5,7 +5,7 @@ function makeHiddenInputs(ctx, fields, values, fields_to_skip) {
|
|
|
5
5
|
([key, field]) => tempstream`<input
|
|
6
6
|
type="hidden"
|
|
7
7
|
name="${key}"
|
|
8
|
-
value="${field.
|
|
8
|
+
value="${field.getParsedValue(ctx, values).then((r) => attribute(JSON.stringify(r.raw) || ""))}"
|
|
9
9
|
/>`
|
|
10
10
|
)}`;
|
|
11
11
|
}
|
package/lib/mount.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FileManager } from "@sealcode/file-manager";
|
|
2
2
|
import { Middlewares as SealiousMiddlewares } from "sealious";
|
|
3
|
+
import { KoaResponsiveImageRouter } from "koa-responsive-image-router";
|
|
3
4
|
async function handleHtmlPromise(ctx, next) {
|
|
4
5
|
await next();
|
|
5
6
|
if (ctx.body instanceof Promise) {
|
|
@@ -9,9 +10,19 @@ async function handleHtmlPromise(ctx, next) {
|
|
|
9
10
|
}
|
|
10
11
|
function mount(router, url, mountable, use_dummy_app = false, file_manager = use_dummy_app ? new FileManager("/tmp", "/uploaded_files") : void 0) {
|
|
11
12
|
const raw_url = typeof url === "string" ? url : url.rawURL;
|
|
13
|
+
const imageRouter = new KoaResponsiveImageRouter({
|
|
14
|
+
staticPath: "/tmp",
|
|
15
|
+
thumbnailSize: 10,
|
|
16
|
+
cacheManagerResolutionThreshold: 10,
|
|
17
|
+
imageStoragePath: "/tmp",
|
|
18
|
+
smartCropStoragePath: "/tmp"
|
|
19
|
+
});
|
|
20
|
+
const fileManager = new FileManager("/tmp", "/uploaded_files");
|
|
12
21
|
const args = use_dummy_app ? [
|
|
13
22
|
async (ctx, next) => {
|
|
14
23
|
ctx.$app = {
|
|
24
|
+
fileManager,
|
|
25
|
+
imageRouter,
|
|
15
26
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
16
27
|
Logger: new Proxy(
|
|
17
28
|
{},
|
package/lib/notifier.js
CHANGED
|
@@ -34,7 +34,6 @@ async function wait_for_app_to_be_stable(app_port, n = 3) {
|
|
|
34
34
|
console.log("Waiting for app to be stable....");
|
|
35
35
|
let counter = 0;
|
|
36
36
|
while (true) {
|
|
37
|
-
console.debug("notifier.ts:53");
|
|
38
37
|
const { status } = await get_status(app_port).catch(() => ({
|
|
39
38
|
status: "down"
|
|
40
39
|
}));
|
package/lib/page/list.js
CHANGED
|
@@ -4,13 +4,13 @@ import { naturalNumbers, UrlWithNewParams } from "../utils/utils.js";
|
|
|
4
4
|
import { makeHiddenInputs } from "../make-hidden-inputs.js";
|
|
5
5
|
import qs from "qs";
|
|
6
6
|
import { NumberField } from "../forms/fields/number.js";
|
|
7
|
-
import {
|
|
7
|
+
import { TextBasedSimpleField } from "../forms/fields/simple-form-field.js";
|
|
8
8
|
const BasePagePropsShape = {};
|
|
9
9
|
const DEFAULT_ITEMS_PER_PAGE = 12;
|
|
10
10
|
const BaseListPageFields = {
|
|
11
11
|
page: new NumberField(false, 1),
|
|
12
12
|
itemsPerPage: new NumberField(false, DEFAULT_ITEMS_PER_PAGE),
|
|
13
|
-
sort: new
|
|
13
|
+
sort: new TextBasedSimpleField(false)
|
|
14
14
|
};
|
|
15
15
|
const SORT_SEPARATOR = ":";
|
|
16
16
|
function decodeSort(s) {
|
|
@@ -40,8 +40,8 @@ class ListPage extends Page {
|
|
|
40
40
|
}
|
|
41
41
|
init() {
|
|
42
42
|
super.init();
|
|
43
|
-
for (const [
|
|
44
|
-
void field.init(
|
|
43
|
+
for (const [, field] of Object.entries(this.filterFields)) {
|
|
44
|
+
void field.init();
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
renderListContainer(_, content) {
|
|
@@ -49,11 +49,14 @@ class ListPage extends Page {
|
|
|
49
49
|
}
|
|
50
50
|
async getPaginationConfig(ctx) {
|
|
51
51
|
const values = await this.extractRawValues(ctx);
|
|
52
|
-
let { parsed: page } = await this.fields.page.
|
|
52
|
+
let { parsed: page } = await this.fields.page.getParsedValue(
|
|
53
|
+
ctx,
|
|
54
|
+
values
|
|
55
|
+
);
|
|
53
56
|
if (!page) {
|
|
54
57
|
page = 1;
|
|
55
58
|
}
|
|
56
|
-
const { parsed: itemsPerPage } = await this.fields.itemsPerPage.
|
|
59
|
+
const { parsed: itemsPerPage } = await this.fields.itemsPerPage.getParsedValue(ctx, values);
|
|
57
60
|
return { page, itemsPerPage };
|
|
58
61
|
}
|
|
59
62
|
async renderItems(ctx, values, items) {
|
|
@@ -127,7 +130,7 @@ class ListPage extends Page {
|
|
|
127
130
|
const filter = {};
|
|
128
131
|
const raw_values = await this.extractRawValues(ctx);
|
|
129
132
|
for (const [fieldname, field] of Object.entries(this.filterFields)) {
|
|
130
|
-
const { parsed } = await field.
|
|
133
|
+
const { parsed } = await field.getParsedValue(ctx, raw_values);
|
|
131
134
|
filter[fieldname] = field.mapToFilter(parsed);
|
|
132
135
|
}
|
|
133
136
|
return filter;
|
|
@@ -163,7 +166,11 @@ class ListPage extends Page {
|
|
|
163
166
|
return control.render(
|
|
164
167
|
this.makeFormControlContext(
|
|
165
168
|
ctx,
|
|
166
|
-
{
|
|
169
|
+
{
|
|
170
|
+
raw_values: values,
|
|
171
|
+
messages: [],
|
|
172
|
+
field_messages: {}
|
|
173
|
+
},
|
|
167
174
|
false
|
|
168
175
|
)
|
|
169
176
|
);
|
|
@@ -13,14 +13,15 @@ class MountableWithFields extends Mountable {
|
|
|
13
13
|
this.fields = {};
|
|
14
14
|
}
|
|
15
15
|
init() {
|
|
16
|
-
for (const [
|
|
17
|
-
void field.init(
|
|
16
|
+
for (const [field_name, field] of Object.entries(this.fields)) {
|
|
17
|
+
void field.init();
|
|
18
|
+
field.setName(field_name);
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
21
|
makeFormControlContext(ctx, data, validate, field_name_prefix = this.field_names_prefix, form_id = this.form_id) {
|
|
21
22
|
return new FormControlContext(
|
|
22
23
|
ctx,
|
|
23
|
-
data
|
|
24
|
+
data,
|
|
24
25
|
data.messages,
|
|
25
26
|
field_name_prefix,
|
|
26
27
|
form_id,
|
|
@@ -44,10 +45,13 @@ class MountableWithFields extends Mountable {
|
|
|
44
45
|
await Promise.all(
|
|
45
46
|
Object.keys(this.fields).map(async (key) => {
|
|
46
47
|
const field = this.fields[key];
|
|
47
|
-
const { valid: fieldvalid, message: fieldmessage } = await field.
|
|
48
|
+
const { valid: fieldvalid, message: fieldmessage } = await field.getParsedValue(ctx, values, true);
|
|
48
49
|
if (!fieldvalid) {
|
|
49
50
|
valid = false;
|
|
50
|
-
field_errors[field.name] =
|
|
51
|
+
field_errors[field.name] = {
|
|
52
|
+
type: "error",
|
|
53
|
+
message: fieldmessage
|
|
54
|
+
};
|
|
51
55
|
}
|
|
52
56
|
})
|
|
53
57
|
);
|
|
@@ -81,7 +85,11 @@ class MountableWithFields extends Mountable {
|
|
|
81
85
|
const result = {};
|
|
82
86
|
const promises = Object.entries(this.fields).map(
|
|
83
87
|
async ([key, field]) => {
|
|
84
|
-
const { parsed } = await field.
|
|
88
|
+
const { parsed } = await field.getParsedValue(
|
|
89
|
+
ctx,
|
|
90
|
+
raw_values,
|
|
91
|
+
false
|
|
92
|
+
);
|
|
85
93
|
result[key] = parsed;
|
|
86
94
|
}
|
|
87
95
|
);
|
|
@@ -17,7 +17,7 @@ describe("mountable-with-fields", () => {
|
|
|
17
17
|
const data = await this.getParsedValues(ctx);
|
|
18
18
|
data.not_required?.trim();
|
|
19
19
|
data.required.trim();
|
|
20
|
-
const { parsed: data2 } = await this.fields.not_required.
|
|
20
|
+
const { parsed: data2 } = await this.fields.not_required.getParsedValue(
|
|
21
21
|
ctx,
|
|
22
22
|
form_values.raw_values
|
|
23
23
|
);
|
package/lib/templates/form.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { curryImportPath } from "../utils/import-path.js";
|
|
3
|
-
import { getPrettierConfig } from "../utils/prettier.js";
|
|
1
|
+
import { formatWithPrettier } from "../utils/prettier.js";
|
|
4
2
|
const defaults = {
|
|
5
3
|
postimport: `
|
|
6
4
|
import { Fields } from "@sealcode/sealgen";
|
|
7
5
|
import type {FormDataValue} from "@sealcode/sealgen";`,
|
|
8
6
|
fields: `
|
|
9
|
-
password: new Fields.
|
|
7
|
+
password: new Fields.Password(true),`,
|
|
10
8
|
controls: `
|
|
11
9
|
new Controls.SimpleInput(fields.password, {
|
|
12
10
|
label: "Password:",
|
|
@@ -17,8 +15,8 @@ const defaults = {
|
|
|
17
15
|
data: Record<string, FormDataValue>
|
|
18
16
|
): Promise<{ valid: boolean; error: string }> {
|
|
19
17
|
// just a silly example, please remove this with better logic
|
|
20
|
-
const { parsed: email } = await this.fields.email.
|
|
21
|
-
const { parsed: password } = await this.fields.password.
|
|
18
|
+
const { parsed: email } = await this.fields.email.getParsedValue(ctx, data);
|
|
19
|
+
const { parsed: password } = await this.fields.password.getParsedValue(ctx, data);
|
|
22
20
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
23
21
|
if ((password || "").length > ((email as string) || "").length) {
|
|
24
22
|
return { valid: false, error: "Password cannot be longer than email" };
|
|
@@ -43,11 +41,10 @@ const defaults = {
|
|
|
43
41
|
};
|
|
44
42
|
async function formTemplate(action_name, newfilefullpath, _params = defaults) {
|
|
45
43
|
const params = { ...defaults, ..._params };
|
|
46
|
-
const rel = curryImportPath(newfilefullpath);
|
|
47
44
|
const content = `import type { Context } from "koa";
|
|
48
45
|
import type { FormData } from "@sealcode/sealgen";
|
|
49
46
|
import { Form, Controls, fieldsToShape } from "@sealcode/sealgen";
|
|
50
|
-
import html from "
|
|
47
|
+
import html from "src/back/html.js";
|
|
51
48
|
|
|
52
49
|
${params.postimport}
|
|
53
50
|
|
|
@@ -57,6 +54,8 @@ const fields = {
|
|
|
57
54
|
${params.fields}
|
|
58
55
|
};
|
|
59
56
|
|
|
57
|
+
Form.initFieldNames(fields);
|
|
58
|
+
|
|
60
59
|
export const ${action_name}Shape = fieldsToShape(fields);
|
|
61
60
|
|
|
62
61
|
export default new (class ${action_name}Form extends Form<typeof fields, void> {
|
|
@@ -78,7 +77,7 @@ export default new (class ${action_name}Form extends Form<typeof fields, void> {
|
|
|
78
77
|
${params.render}
|
|
79
78
|
})();
|
|
80
79
|
`;
|
|
81
|
-
return
|
|
80
|
+
return formatWithPrettier(content);
|
|
82
81
|
}
|
|
83
82
|
export {
|
|
84
83
|
formTemplate
|
|
@@ -9,8 +9,8 @@ import { FlatTemplatable } from "tempstream";
|
|
|
9
9
|
export const actionName = "${action_name}";
|
|
10
10
|
|
|
11
11
|
const fields1 = {
|
|
12
|
-
email: new Fields.
|
|
13
|
-
password: new Fields.
|
|
12
|
+
email: new Fields.TextBasedSimpleField(true),
|
|
13
|
+
password: new Fields.TextBasedSimpleField(true),
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
const form1 = new (class extends Form<typeof fields1, unknown> {
|
|
@@ -26,8 +26,8 @@ const form1 = new (class extends Form<typeof fields1, unknown> {
|
|
|
26
26
|
})();
|
|
27
27
|
|
|
28
28
|
const fields2 = {
|
|
29
|
-
name: new Fields.
|
|
30
|
-
surname: new Fields.
|
|
29
|
+
name: new Fields.TextBasedSimpleField(true),
|
|
30
|
+
surname: new Fields.TextBasedSimpleField(true),
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
const form2 = new (class extends Form<typeof fields2, unknown> {
|
package/lib/templates/page.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { curryImportPath } from "../utils/import-path.js";
|
|
2
1
|
async function pageTemplate(action_name, newfilefullpath) {
|
|
3
|
-
const rel = curryImportPath(newfilefullpath);
|
|
4
2
|
return `import type { Context } from "koa";
|
|
5
3
|
import { TempstreamJSX } from "tempstream";
|
|
6
4
|
import { Page } from "@sealcode/sealgen";
|
|
@@ -1,70 +1,58 @@
|
|
|
1
1
|
import { toKebabCase, toPascalCase } from "js-convert-case";
|
|
2
2
|
import { formTemplate } from "../form.js";
|
|
3
|
-
import { curryImportPath } from "../../utils/import-path.js";
|
|
4
3
|
import extract_fields_from_collection from "../../utils/extract-fields-from-collection.js";
|
|
5
|
-
import {
|
|
4
|
+
import { wrapAttribute } from "../../utils/wrap-attributes.js";
|
|
6
5
|
async function createItemFormTemplate(create_action_name, newfilefullpath, collection_name, list_action) {
|
|
7
6
|
const collection_fields = await extract_fields_from_collection(
|
|
8
7
|
collection_name
|
|
9
8
|
);
|
|
10
|
-
const
|
|
11
|
-
const field_handler_results = await Promise.all(
|
|
12
|
-
collection_fields.map(
|
|
13
|
-
(field) => getFieldHandler(collection_name, field, importPath)
|
|
14
|
-
)
|
|
15
|
-
);
|
|
16
|
-
const post_create_actions = field_handler_results.map(({ post_create }) => post_create).filter((e) => e != "");
|
|
9
|
+
const formFieldsVar = `${toPascalCase(collection_name)}FormFields`;
|
|
17
10
|
return formTemplate(create_action_name, newfilefullpath, {
|
|
18
11
|
success_message: "Created!",
|
|
19
|
-
postimport: `import {${toPascalCase(
|
|
20
|
-
collection_name
|
|
21
|
-
)}FormFields, ${toPascalCase(
|
|
12
|
+
postimport: `import {${formFieldsVar}, get${toPascalCase(
|
|
22
13
|
collection_name
|
|
23
14
|
)}FormControls }from "./shared.js";
|
|
24
15
|
|
|
25
|
-
import { ${toPascalCase(
|
|
26
|
-
|
|
27
|
-
)}";
|
|
28
|
-
|
|
29
|
-
import { ${list_action}URL } from "${importPath("src/back/routes/urls.js")}";
|
|
16
|
+
import { ${toPascalCase(
|
|
17
|
+
collection_name
|
|
18
|
+
)} } from "src/back/collections/collections.js";
|
|
30
19
|
|
|
31
|
-
|
|
20
|
+
import { ${list_action}URL } from "src/back/routes/urls.js";
|
|
21
|
+
import {tempstream} from "tempstream";
|
|
32
22
|
`,
|
|
33
23
|
fields: `...${toPascalCase(collection_name)}FormFields`,
|
|
34
24
|
controls: `
|
|
35
25
|
new Controls.FormHeader("Create ${toPascalCase(
|
|
36
26
|
collection_name
|
|
37
27
|
)}"),
|
|
38
|
-
|
|
28
|
+
...get${toPascalCase(collection_name)}FormControls()`,
|
|
39
29
|
can_access: `canAccess = async (ctx: Context) => {
|
|
40
30
|
const policy = ${toPascalCase(collection_name)}.getPolicy("create");
|
|
41
31
|
const response = await policy.check(ctx.$context);
|
|
42
32
|
return { canAccess: response?.allowed || false, message: response?.reason || "" };
|
|
43
33
|
};`,
|
|
44
|
-
get_initial_values:
|
|
45
|
-
return {
|
|
46
|
-
${field_handler_results.filter((r) => !r.hide_initial_value_create).map(
|
|
47
|
-
({ initial_value_create }) => initial_value_create
|
|
48
|
-
).join(",\n")}
|
|
49
|
-
}
|
|
50
|
-
}` : ``,
|
|
34
|
+
get_initial_values: "",
|
|
51
35
|
onsubmit: `
|
|
52
|
-
async onSubmit(ctx: Context) {
|
|
53
|
-
const
|
|
54
|
-
if (!data) {
|
|
55
|
-
throw new Error("Error when parsing the form values");
|
|
56
|
-
}
|
|
36
|
+
async onSubmit(ctx: Context, formData: FormData) {
|
|
37
|
+
const fctx = this.makeFormControlContext(ctx, formData, true);
|
|
57
38
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
39
|
+
const created = await ctx.$app.collections["${toKebabCase(
|
|
40
|
+
collection_name
|
|
41
|
+
)}"].createExtraSafe(
|
|
61
42
|
ctx.$context,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
${
|
|
67
|
-
|
|
43
|
+
{
|
|
44
|
+
${collection_fields.map(
|
|
45
|
+
(field_info) => field_info.form_field.generateCreateValueGetter(field_info, {
|
|
46
|
+
form_field_types: formFieldsVar,
|
|
47
|
+
sealious_field: `fields${wrapAttribute(field_info.name)}`,
|
|
48
|
+
form_fields: "fields"
|
|
49
|
+
})
|
|
50
|
+
).join(",\n")}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
for(const field of Object.values(${formFieldsVar})){
|
|
54
|
+
await field.postSealiousCreate(ctx, created, formData)
|
|
55
|
+
}
|
|
68
56
|
}
|
|
69
57
|
`,
|
|
70
58
|
render: ` async render(ctx: Context, data: FormData, show_field_errors: boolean) {
|