@sealcode/sealgen 0.18.10 → 0.19.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +20 -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 +5 -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/register-external.d.ts +2 -2
- package/@types/templates/form.d.ts +1 -3
- package/@types/templates/jdd-component.d.ts +1 -1
- package/@types/templates/page.d.ts +1 -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 +1 -68
- package/@types/templates/templates.d.ts +1 -21
- 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/eslint.config.mjs +56 -0
- package/lib/add-crud.js +77 -89
- package/lib/add-jdd-component.js +3 -3
- package/lib/add-list-route.test.js +1 -1
- package/lib/add-route.js +2 -9
- package/lib/build.js +6 -4
- package/lib/builders/backend-ts-builder.js +0 -1
- package/lib/builders/colors-builder.js +11 -8
- package/lib/builders/fonts-builder.js +0 -1
- package/lib/builders/frontend-ts-builder.js +0 -1
- package/lib/cli.js +4 -7
- package/lib/components/tabs.js +36 -36
- package/lib/controllers/table-add-button.stimulus.js +35 -0
- package/lib/esbuild-plugins/rewrite-asset-imports.js +7 -10
- package/lib/forms/controls/array.js +25 -22
- 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 +7 -1
- package/lib/forms/controls/checkboxed-list-input.test.js +6 -6
- package/lib/forms/controls/controls.js +2 -2
- package/lib/forms/controls/derived-frame.js +8 -4
- package/lib/forms/controls/derived.js +1 -1
- package/lib/forms/controls/dropdown.js +5 -3
- 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/form-control.js +1 -1
- 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} +8 -23
- 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/single-reference.test.js +1 -1
- package/lib/forms/controls/table.js +62 -25
- package/lib/forms/controls/textarea.js +5 -3
- 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 +8 -8
- package/lib/forms/fields/fields.js +23 -8
- package/lib/forms/fields/file.js +33 -9
- package/lib/forms/fields/file.test.js +5 -17
- 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 +61 -2
- package/lib/forms/fields/single-reference.js +44 -0
- package/lib/forms/fields/structured-array.js +61 -12
- package/lib/forms/fields/table.js +29 -2
- package/lib/forms/fields/text.js +17 -0
- package/lib/forms/fields/url.js +17 -0
- package/lib/forms/form.js +30 -14
- package/lib/forms/form.test.js +5 -7
- package/lib/forms/multiform.js +10 -9
- package/lib/forms/multiform.test.js +5 -5
- package/lib/generate-collections.js +2 -3
- package/lib/generate-components.js +2 -3
- package/lib/generate-routes.js +3 -5
- package/lib/generate-routes.test.js +7 -16
- package/lib/generate-stimulus.js +4 -4
- package/lib/get-fonts.js +29 -27
- package/lib/index.js +1 -0
- package/lib/make-env.js +1 -1
- package/lib/make-hidden-inputs.js +4 -4
- package/lib/mount.js +11 -1
- package/lib/notifier.js +3 -4
- package/lib/page/list.js +20 -15
- package/lib/page/mountable-with-fields.js +14 -6
- package/lib/page/mountable-with-fields.test.js +1 -1
- package/lib/page/mountable.js +0 -1
- package/lib/page/page.js +0 -1
- package/lib/register-external.js +4 -4
- package/lib/templates/form.js +9 -10
- package/lib/templates/jdd-component.js +1 -1
- package/lib/templates/jdd-editor.js +1 -1
- package/lib/templates/multiform.js +4 -4
- package/lib/templates/page.js +1 -3
- package/lib/templates/shared/collection-create-form.js +31 -44
- package/lib/templates/shared/collection-edit-form.js +43 -81
- package/lib/templates/shared/collection-list.js +13 -21
- package/lib/templates/shared/shared-crud-form-fields.js +28 -98
- package/lib/test_utils/exec_async.js +3 -3
- package/lib/test_utils/test-on-real-app.js +12 -14
- 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/lib/utils/write-file.js +1 -1
- package/package.json +11 -9
- package/src/add-collection.ts +1 -3
- package/src/add-crud.ts +84 -100
- package/src/add-jdd-component.ts +4 -5
- package/src/add-list-route.test.ts +1 -1
- package/src/add-route.ts +3 -13
- package/src/build.ts +6 -4
- package/src/builders/backend-ts-builder.ts +0 -1
- package/src/builders/builder.ts +4 -1
- package/src/builders/colors-builder.ts +11 -9
- package/src/builders/css-builder.ts +4 -1
- package/src/builders/fonts-builder.ts +0 -1
- package/src/builders/frontend-ts-builder.ts +0 -1
- package/src/cli.ts +5 -7
- package/src/components/tabs.ts +38 -37
- package/src/components/toggle-modal.ts +1 -1
- package/src/controllers/table-add-button.stimulus.ts +35 -0
- package/src/esbuild-plugins/rewrite-asset-imports.ts +7 -10
- package/src/forms/controls/array.ts +35 -36
- package/src/forms/controls/autocomplete.ts +2 -2
- package/src/forms/controls/big-radio-group.ts +4 -4
- package/src/forms/controls/checkbox-group.ts +10 -10
- package/src/forms/controls/checkboxed-list-input.test.ts +6 -6
- package/src/forms/controls/checkboxed-list-input.ts +16 -8
- package/src/forms/controls/controls.ts +2 -2
- package/src/forms/controls/derived-frame.ts +16 -11
- package/src/forms/controls/derived.ts +7 -6
- package/src/forms/controls/dropdown.ts +13 -13
- package/src/forms/controls/editable-collection-subset.ts +4 -3
- package/src/forms/controls/field-group.ts +1 -1
- package/src/forms/controls/file.test.ts +4 -2
- package/src/forms/controls/file.ts +30 -7
- package/src/forms/controls/form-control.ts +8 -3
- package/src/forms/controls/hidden-input.ts +5 -1
- package/src/forms/controls/html.ts +1 -0
- package/src/forms/controls/{photo.test.ts → image.test.ts} +7 -24
- package/src/forms/controls/{photo.ts → image.ts} +4 -6
- package/src/forms/controls/multiple-files.ts +23 -8
- package/src/forms/controls/{multiple-photos.ts → multiple-images.ts} +2 -2
- package/src/forms/controls/number.ts +1 -1
- package/src/forms/controls/simple-input.ts +21 -33
- package/src/forms/controls/single-reference.test.ts +1 -1
- package/src/forms/controls/single-reference.ts +11 -3
- package/src/forms/controls/table.ts +87 -33
- package/src/forms/controls/textarea.ts +7 -5
- package/src/forms/controls/tickable.ts +13 -7
- package/src/forms/fields/boolean.ts +27 -2
- package/src/forms/fields/checkboxed-list.ts +11 -2
- package/src/forms/fields/collection-field.ts +21 -3
- 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 +130 -0
- package/src/forms/fields/deep-reverse-single-reference-table.ts +213 -0
- package/src/forms/fields/email.ts +10 -1
- package/src/forms/fields/enum-multiple-sealious.ts +48 -0
- package/src/forms/fields/existing-sealious-value.ts +1 -1
- package/src/forms/fields/field.test.ts +8 -8
- package/src/forms/fields/field.ts +98 -11
- package/src/forms/fields/fields.ts +23 -8
- package/src/forms/fields/file.test.ts +5 -17
- package/src/forms/fields/file.ts +44 -16
- package/src/forms/fields/float.ts +9 -0
- package/src/forms/fields/get-field-for-sealious.ts +337 -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 +10 -3
- package/src/forms/fields/password.ts +13 -0
- package/src/forms/fields/pick-from-list-sealious.ts +22 -0
- package/src/forms/fields/pick-from-list.ts +8 -4
- package/src/forms/fields/proxy-field.ts +7 -1
- package/src/forms/fields/regexp.ts +27 -1
- package/src/forms/fields/simple-form-field.ts +103 -7
- package/src/forms/fields/single-reference.ts +62 -0
- package/src/forms/fields/structured-array.ts +111 -18
- package/src/forms/fields/table.ts +39 -16
- package/src/forms/fields/text.ts +18 -0
- package/src/forms/fields/url.ts +20 -0
- package/src/forms/form-types.ts +5 -4
- package/src/forms/form.test.ts +5 -7
- package/src/forms/form.ts +42 -23
- package/src/forms/forms.css +0 -85
- package/src/forms/multiform.test.ts +9 -9
- package/src/forms/multiform.ts +12 -10
- package/src/generate-collections.ts +2 -3
- package/src/generate-components.ts +2 -3
- package/src/generate-routes.test.ts +7 -16
- package/src/generate-routes.ts +6 -10
- package/src/generate-stimulus.ts +4 -5
- package/src/get-fonts.ts +32 -30
- package/src/index.ts +2 -1
- package/src/make-env.ts +1 -1
- package/src/make-hidden-inputs.ts +8 -7
- package/src/mount.ts +16 -7
- package/src/notifier.ts +4 -7
- package/src/page/default-list-filters.ts +1 -0
- package/src/page/list.ts +33 -28
- package/src/page/mountable-with-fields.test.ts +1 -1
- package/src/page/mountable-with-fields.ts +21 -12
- package/src/page/mountable.ts +0 -1
- package/src/page/page.ts +2 -3
- package/src/page/props-parser.ts +1 -1
- package/src/page/sealious-list.ts +1 -1
- package/src/page/stateful-page.ts +6 -10
- package/src/register-external.ts +5 -5
- package/src/templates/form.ts +9 -11
- package/src/templates/jdd-component.ts +1 -1
- package/src/templates/jdd-editor.ts +2 -4
- package/src/templates/list.ts +0 -1
- package/src/templates/multiform.ts +4 -4
- package/src/templates/page.ts +1 -6
- package/src/templates/shared/collection-create-form.ts +34 -71
- package/src/templates/shared/collection-edit-form.ts +46 -108
- package/src/templates/shared/collection-list.ts +13 -21
- package/src/templates/shared/item-delete.ts +0 -1
- package/src/templates/shared/shared-crud-form-fields.ts +38 -177
- package/src/templates/templates.ts +5 -1
- package/src/test_utils/exec_async.ts +3 -4
- package/src/test_utils/test-on-real-app.ts +13 -14
- package/src/utils/browser-creator.js +0 -1
- package/src/utils/exec.ts +0 -1
- package/src/utils/extract-fields-from-collection.ts +76 -25
- package/src/utils/input-wrapper.ts +1 -1
- package/src/utils/make-slug.ts +1 -1
- package/src/utils/wrap-attributes.ts +17 -0
- package/src/utils/write-file.ts +1 -1
- package/.eslintrc.cjs +0 -39
- 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
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { TextBasedSimpleField } from "./simple-form-field.js";
|
|
2
|
+
|
|
3
|
+
export class Password<
|
|
4
|
+
Required extends boolean,
|
|
5
|
+
> extends TextBasedSimpleField<Required> {
|
|
6
|
+
constructor(required: Required) {
|
|
7
|
+
super(required, "password");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async sealiousValueToForm(): Promise<undefined> {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FieldTypes as SealiousFieldTypes } from "sealious";
|
|
2
|
+
import { PickFromListField } from "./pick-from-list.js";
|
|
3
|
+
import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
|
|
4
|
+
|
|
5
|
+
export class PickFromListSealious<
|
|
6
|
+
Required extends boolean,
|
|
7
|
+
> extends PickFromListField<Required> {
|
|
8
|
+
constructor(public sealious_field: SealiousFieldTypes.Enum<string>) {
|
|
9
|
+
super(sealious_field.required as Required, async (ctx) =>
|
|
10
|
+
sealious_field
|
|
11
|
+
.getAllowedValues(ctx.$app)
|
|
12
|
+
.map((value) => ({ value, label: value }))
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
generateFieldDeclaration(
|
|
17
|
+
field_info: ExtractedFieldInfo,
|
|
18
|
+
vars: { form_field_types: string; sealious_field: string }
|
|
19
|
+
): string {
|
|
20
|
+
return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { is, predicates } from "@sealcode/ts-predicates";
|
|
2
2
|
import { Context } from "koa";
|
|
3
|
-
import
|
|
3
|
+
import { Dropdown, DropdownOption } from "../controls/dropdown.js";
|
|
4
4
|
import { FormFieldValidationResponse } from "./field.js";
|
|
5
|
-
import {
|
|
5
|
+
import { TextBasedSimpleField } from "./simple-form-field.js";
|
|
6
6
|
|
|
7
7
|
export class PickFromListField<
|
|
8
|
-
Required extends boolean
|
|
9
|
-
> extends
|
|
8
|
+
Required extends boolean,
|
|
9
|
+
> extends TextBasedSimpleField<Required, Dropdown> {
|
|
10
10
|
constructor(
|
|
11
11
|
public required: Required,
|
|
12
12
|
public generateOptions: (ctx: Context) => Promise<DropdownOption[]>,
|
|
@@ -49,4 +49,8 @@ export class PickFromListField<
|
|
|
49
49
|
public getEmptyValue(): string {
|
|
50
50
|
return "";
|
|
51
51
|
}
|
|
52
|
+
|
|
53
|
+
getControl(): Dropdown {
|
|
54
|
+
return new Dropdown(this);
|
|
55
|
+
}
|
|
52
56
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { FormControl } from "../controls/form-control.js";
|
|
1
2
|
import { FormField } from "./field.js";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
|
+
export class ProxyFormField<T> extends FormField<boolean, T, any> {
|
|
4
6
|
constructor(
|
|
5
7
|
required: boolean,
|
|
6
8
|
public name: string,
|
|
@@ -21,4 +23,8 @@ export class ProxyFormField<T> extends FormField<boolean, T> {
|
|
|
21
23
|
parsed_value: this.parsed_value,
|
|
22
24
|
};
|
|
23
25
|
}
|
|
26
|
+
|
|
27
|
+
getControl(): FormControl {
|
|
28
|
+
throw new Error("This field does not have a default control assigned");
|
|
29
|
+
}
|
|
24
30
|
}
|
|
@@ -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
|
}
|
|
@@ -1,30 +1,126 @@
|
|
|
1
|
+
/* eslint @typescript-eslint/no-unused-vars: off */
|
|
1
2
|
import { FormDataValue } from "../form-types.js";
|
|
2
3
|
import { Context } from "koa";
|
|
3
4
|
import { predicates } from "@sealcode/ts-predicates";
|
|
4
5
|
import { FieldParseResult, FormField } from "./field.js";
|
|
6
|
+
import { SimpleInput } from "../controls/simple-input.js";
|
|
7
|
+
import { FormControl } from "../controls/controls.js";
|
|
8
|
+
import { CollectionItem } from "sealious";
|
|
9
|
+
import { FormControlContext } from "../controls/form-control.js";
|
|
5
10
|
|
|
6
|
-
export class SimpleFormField<
|
|
7
|
-
Required,
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
export abstract class SimpleFormField<
|
|
12
|
+
Required extends boolean,
|
|
13
|
+
DefaultControl extends FormControl = SimpleInput,
|
|
14
|
+
Parsed = string,
|
|
15
|
+
> extends FormField<Required, Parsed, DefaultControl> {
|
|
16
|
+
predicate = predicates.string;
|
|
17
|
+
|
|
18
|
+
constructor(
|
|
19
|
+
required: Required,
|
|
20
|
+
public type: string = "text"
|
|
21
|
+
) {
|
|
22
|
+
super(required);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async sealiousValueToForm(
|
|
26
|
+
_ctx: Context,
|
|
27
|
+
value: unknown
|
|
28
|
+
): Promise<FormDataValue> {
|
|
29
|
+
if (value === null) {
|
|
30
|
+
return "";
|
|
31
|
+
}
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
33
|
+
return String(value) as FormDataValue;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export class TextBasedSimpleField<
|
|
38
|
+
Required extends boolean,
|
|
39
|
+
DefaultControl extends FormControl = SimpleInput,
|
|
40
|
+
> extends SimpleFormField<Required, DefaultControl, string | null> {
|
|
10
41
|
async parse(
|
|
11
42
|
_: Context,
|
|
12
43
|
raw_value: FormDataValue
|
|
13
44
|
): Promise<FieldParseResult<string>> {
|
|
14
45
|
return {
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
15
47
|
parsed_value: (raw_value || "").toString(),
|
|
16
48
|
parsable: true,
|
|
17
49
|
error: null,
|
|
18
50
|
};
|
|
19
51
|
}
|
|
20
52
|
|
|
21
|
-
|
|
53
|
+
async getSealiousCreateValue(
|
|
54
|
+
fctx: FormControlContext
|
|
55
|
+
): Promise<string | null> {
|
|
56
|
+
const { parsed } = await this.getParsedValue(
|
|
57
|
+
fctx.ctx,
|
|
58
|
+
fctx.data.raw_values
|
|
59
|
+
);
|
|
60
|
+
return parsed || "";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async postSealiousCreate(
|
|
64
|
+
ctx: Context,
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
66
|
+
created_item: CollectionItem<any>
|
|
67
|
+
): Promise<void> {}
|
|
68
|
+
|
|
69
|
+
async postSealiousEdit(
|
|
70
|
+
ctx: Context,
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
72
|
+
edited_item: CollectionItem<any>
|
|
73
|
+
): Promise<void> {}
|
|
74
|
+
|
|
75
|
+
getControl(): DefaultControl {
|
|
76
|
+
return new SimpleInput(this, {
|
|
77
|
+
label: this.name,
|
|
78
|
+
type: this.type,
|
|
79
|
+
}) as unknown as DefaultControl;
|
|
80
|
+
}
|
|
22
81
|
|
|
23
82
|
public getEmptyValue(): string {
|
|
24
83
|
return "";
|
|
25
84
|
}
|
|
85
|
+
}
|
|
26
86
|
|
|
27
|
-
|
|
28
|
-
|
|
87
|
+
export class NumberBasedSimpleField<
|
|
88
|
+
Required extends boolean,
|
|
89
|
+
DefaultControl extends FormControl = SimpleInput,
|
|
90
|
+
> extends SimpleFormField<Required, DefaultControl, number> {
|
|
91
|
+
async parse(
|
|
92
|
+
_: Context,
|
|
93
|
+
raw_value: FormDataValue
|
|
94
|
+
): Promise<FieldParseResult<number>> {
|
|
95
|
+
return {
|
|
96
|
+
parsed_value: parseFloat(raw_value as string) || 0,
|
|
97
|
+
parsable: true,
|
|
98
|
+
error: null,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async getSealiousCreateValue(
|
|
103
|
+
fctx: FormControlContext
|
|
104
|
+
): Promise<number | undefined> {
|
|
105
|
+
const { parsed } = await this.getParsedValue(
|
|
106
|
+
fctx.ctx,
|
|
107
|
+
fctx.data.raw_values
|
|
108
|
+
);
|
|
109
|
+
return parsed || 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async postSealiousCreate(): Promise<void> {}
|
|
113
|
+
|
|
114
|
+
async postSealiousEdit(): Promise<void> {}
|
|
115
|
+
|
|
116
|
+
getControl(): DefaultControl {
|
|
117
|
+
return new SimpleInput(this, {
|
|
118
|
+
label: this.name,
|
|
119
|
+
type: this.type,
|
|
120
|
+
}) as unknown as DefaultControl;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public getEmptyValue(): number {
|
|
124
|
+
return 0;
|
|
29
125
|
}
|
|
30
126
|
}
|
|
@@ -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,120 @@
|
|
|
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
|
+
return new TableControl<{
|
|
54
|
+
[name in keyof SealiousFields]: SealiousToFormField<
|
|
55
|
+
SealiousFields[name]
|
|
56
|
+
>;
|
|
57
|
+
}>(this as any, {
|
|
58
|
+
label: this.name,
|
|
59
|
+
subfield_controls: Object.fromEntries(
|
|
60
|
+
Object.entries(this.columns).map(([column_name, subfield]) => [
|
|
61
|
+
column_name as keyof SealiousFields,
|
|
62
|
+
subfield.getControl(),
|
|
63
|
+
])
|
|
64
|
+
) as unknown as Record<keyof SealiousFields, FormControl>,
|
|
65
|
+
allow_adding: true,
|
|
66
|
+
make_new_row: () => ({}) as any,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
generateFieldDeclaration(
|
|
71
|
+
_field_info: ExtractedFieldInfo,
|
|
72
|
+
vars: { form_field_types: string; sealious_field: string }
|
|
73
|
+
): string {
|
|
74
|
+
return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async getSealiousCreateValue(
|
|
78
|
+
fctx: FormControlContext
|
|
79
|
+
): Promise<
|
|
80
|
+
SealiousFieldTypes.ArrayStorageInput<FieldsetInput<SealiousFields>>
|
|
81
|
+
> {
|
|
82
|
+
const { parsed } = await this.getParsedValue(
|
|
83
|
+
fctx.ctx,
|
|
84
|
+
fctx.data.raw_values
|
|
85
|
+
);
|
|
86
|
+
return (
|
|
87
|
+
(parsed as SealiousFieldTypes.ArrayStorageInput<
|
|
88
|
+
FieldsetInput<SealiousFields>
|
|
89
|
+
>) || this.getEmptyValue()
|
|
90
|
+
);
|
|
22
91
|
}
|
|
23
92
|
|
|
24
|
-
|
|
25
|
-
|
|
93
|
+
async sealiousValueToForm(
|
|
94
|
+
ctx: Context,
|
|
95
|
+
sealiousValue: Record<string, FormDataValue | null>[] | null
|
|
96
|
+
): Promise<FormDataValue> {
|
|
97
|
+
return Promise.all(
|
|
98
|
+
(sealiousValue || []).map(async (element) =>
|
|
99
|
+
Object.fromEntries(
|
|
100
|
+
await Promise.all(
|
|
101
|
+
Object.entries(element).map(async ([key, value]) => {
|
|
102
|
+
const form_subfield = this.columns[key];
|
|
103
|
+
if (!form_subfield) {
|
|
104
|
+
return [key, ""];
|
|
105
|
+
}
|
|
106
|
+
return [
|
|
107
|
+
key,
|
|
108
|
+
await form_subfield.sealiousValueToForm(
|
|
109
|
+
ctx,
|
|
110
|
+
value,
|
|
111
|
+
{} as any
|
|
112
|
+
),
|
|
113
|
+
];
|
|
114
|
+
})
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
);
|
|
26
119
|
}
|
|
27
120
|
}
|
|
@@ -2,21 +2,18 @@ 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
|
-
Field extends FormField<
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
|
-
true,
|
|
10
|
-
infer T
|
|
11
|
-
>
|
|
12
|
+
Field extends FormField<true, infer T>
|
|
12
13
|
? NonNullable<T>
|
|
13
|
-
: Field extends FormField<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
infer T
|
|
17
|
-
>
|
|
18
|
-
? T
|
|
19
|
-
: never;
|
|
14
|
+
: Field extends FormField<true, infer T>
|
|
15
|
+
? T
|
|
16
|
+
: never;
|
|
20
17
|
|
|
21
18
|
export type TableFieldParsed<F extends Record<string, FormField>> = {
|
|
22
19
|
[field_name in keyof F]: ExtractFormFieldParsed<F[field_name]>;
|
|
@@ -34,6 +31,16 @@ export class Table<F extends Record<string, FormField>> extends FormField<
|
|
|
34
31
|
return [];
|
|
35
32
|
}
|
|
36
33
|
|
|
34
|
+
setName(name: string) {
|
|
35
|
+
super.setName(name);
|
|
36
|
+
for (const [column_name, field] of Object.entries(this.columns)) {
|
|
37
|
+
field.setName(
|
|
38
|
+
`${this.name}[${TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER}][${column_name}]`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
return this;
|
|
42
|
+
}
|
|
43
|
+
|
|
37
44
|
async parse(
|
|
38
45
|
ctx: Context,
|
|
39
46
|
raw_value: FormDataValue
|
|
@@ -51,10 +58,10 @@ export class Table<F extends Record<string, FormField>> extends FormField<
|
|
|
51
58
|
const row_data = raw_value[row_number];
|
|
52
59
|
const parsed_row: Record<string, unknown> = {};
|
|
53
60
|
if (!is(row_data, predicates.object)) {
|
|
54
|
-
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
55
62
|
throw new Error(`Expected object, got ${String(row_data)}`);
|
|
56
63
|
}
|
|
57
|
-
for (const key
|
|
64
|
+
for (const key of Object.keys(row_data)) {
|
|
58
65
|
const field = this.columns[key];
|
|
59
66
|
if (field == undefined) {
|
|
60
67
|
return {
|
|
@@ -80,13 +87,29 @@ export class Table<F extends Record<string, FormField>> extends FormField<
|
|
|
80
87
|
parsed_value: null,
|
|
81
88
|
};
|
|
82
89
|
}
|
|
83
|
-
// eslint-disable-next-line @typescript-eslint/
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
91
|
parsed_row[key] = parse_result.parsed_value as any;
|
|
85
92
|
}
|
|
86
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
87
93
|
result.push(parsed_row as { [field_name in keyof F]: unknown });
|
|
88
94
|
}
|
|
89
95
|
const ret = { parsed_value: result, parsable: true, error: null };
|
|
90
96
|
return ret as FieldParseResult<TableFieldParsed<F>>;
|
|
91
97
|
}
|
|
98
|
+
|
|
99
|
+
getControl(): TableControl<F> {
|
|
100
|
+
return new TableControl<F>(this, {
|
|
101
|
+
label: this.name,
|
|
102
|
+
subfield_controls: Object.fromEntries(
|
|
103
|
+
Object.entries(this.columns).map(([column_name, field]) => [
|
|
104
|
+
column_name as keyof F,
|
|
105
|
+
field.getControl(),
|
|
106
|
+
])
|
|
107
|
+
) as Record<keyof F, FormControl>,
|
|
108
|
+
allow_adding: true,
|
|
109
|
+
make_new_row: async () =>
|
|
110
|
+
Object.fromEntries(
|
|
111
|
+
Object.keys(this.columns).map((key) => [key, ""])
|
|
112
|
+
) as Record<keyof F, string>,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
92
115
|
}
|
|
@@ -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
|
|
@@ -13,12 +14,11 @@ export type FormDataValue =
|
|
|
13
14
|
| FormDataPrimitive
|
|
14
15
|
| Record<string, FormDataPrimitive>;
|
|
15
16
|
|
|
16
|
-
export type FieldValueType<F extends FormField> =
|
|
17
|
-
? R
|
|
18
|
-
: never;
|
|
17
|
+
export type FieldValueType<F extends FormField> =
|
|
18
|
+
F extends FormField<infer R> ? R : never;
|
|
19
19
|
|
|
20
20
|
export type FormFieldsToValues<
|
|
21
|
-
F extends Record<string, FormField<boolean, keyof F
|
|
21
|
+
F extends Record<string, FormField<boolean, keyof F>>,
|
|
22
22
|
> = {
|
|
23
23
|
[Property in keyof F]: FieldValueType<F[Property]>;
|
|
24
24
|
};
|
|
@@ -28,6 +28,7 @@ export type FormMessage = { type: "info" | "success" | "error"; text: string };
|
|
|
28
28
|
export type FormData<Fieldnames extends string = string> = {
|
|
29
29
|
raw_values: Record<Fieldnames, FormDataValue>;
|
|
30
30
|
messages: FormMessage[];
|
|
31
|
+
field_messages: FieldMessages<Fieldnames>;
|
|
31
32
|
};
|
|
32
33
|
|
|
33
34
|
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> {
|
|
@@ -36,7 +36,7 @@ export function form_factory(canAccessFun?: Mountable["canAccess"]): Form<typeof
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
const port = await getPort();
|
|
39
|
-
console.
|
|
39
|
+
console.info("Using port " + port + " for form.test.ts");
|
|
40
40
|
|
|
41
41
|
describe("form test", () => {
|
|
42
42
|
let page: Page;
|
|
@@ -91,7 +91,6 @@ describe("form test", () => {
|
|
|
91
91
|
},
|
|
92
92
|
}
|
|
93
93
|
);
|
|
94
|
-
console.log(res_axios.data);
|
|
95
94
|
if (!res_axios.data.includes("Some fields are invalid")) {
|
|
96
95
|
throw new Error("when sending a empty request with axios, the error didnt appear");
|
|
97
96
|
}
|
|
@@ -139,7 +138,6 @@ describe("form test", () => {
|
|
|
139
138
|
async (
|
|
140
139
|
ctx: Koa.Context
|
|
141
140
|
): Promise<{ canAccess: boolean; message: string }> => {
|
|
142
|
-
console.log("CAN ACCESS? FALSE");
|
|
143
141
|
return { canAccess: false, message: "" };
|
|
144
142
|
}
|
|
145
143
|
),
|
|
@@ -349,7 +347,7 @@ describe("form test", () => {
|
|
|
349
347
|
await page.getByPlaceholder("text").click();
|
|
350
348
|
await page.getByPlaceholder("text").fill("yes@an.email");
|
|
351
349
|
await page.getByRole("button", { name: "Submit" }).click();
|
|
352
|
-
assertThrowsAsync(async () => {
|
|
350
|
+
await assertThrowsAsync(async () => {
|
|
353
351
|
return page
|
|
354
352
|
.getByText("Please enter a proper email address")
|
|
355
353
|
.click({ timeout: 500 });
|
|
@@ -370,7 +368,7 @@ describe("form test", () => {
|
|
|
370
368
|
const router = new Router();
|
|
371
369
|
|
|
372
370
|
const fields = {
|
|
373
|
-
title: new
|
|
371
|
+
title: new TextBasedSimpleField(true),
|
|
374
372
|
};
|
|
375
373
|
|
|
376
374
|
mount(
|