@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
package/src/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ export * from "./forms/multiform.js";
|
|
|
16
16
|
export * 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
|
|
|
20
21
|
import { Context } from "koa";
|
|
21
22
|
import { Readable } from "node:stream";
|
|
@@ -37,7 +38,7 @@ export interface HTMLHeadOptions {
|
|
|
37
38
|
export interface HTMLArgs {
|
|
38
39
|
ctx: Context;
|
|
39
40
|
title: string | Promise<string>;
|
|
40
|
-
body: string | Promise<string
|
|
41
|
+
body: string | Promise<string> | Readable;
|
|
41
42
|
htmlOptions?: Partial<HTMLOptions>;
|
|
42
43
|
makeHead?: (
|
|
43
44
|
args: HTMLHeadOptions
|
package/src/make-env.ts
CHANGED
|
@@ -13,12 +13,13 @@ export function makeHiddenInputs(
|
|
|
13
13
|
return tempstream`${Object.entries(fields)
|
|
14
14
|
.filter(([key]) => !fields_to_skip.includes(key))
|
|
15
15
|
.map(
|
|
16
|
-
([key, field]) =>
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
([key, field]) =>
|
|
17
|
+
tempstream /* HTML */ `<input
|
|
18
|
+
type="hidden"
|
|
19
|
+
name="${key}"
|
|
20
|
+
value="${field
|
|
21
|
+
.getParsedValue(ctx, values)
|
|
22
|
+
.then((r) => attribute(JSON.stringify(r.raw) || ""))}"
|
|
23
|
+
/>`
|
|
23
24
|
)}`;
|
|
24
25
|
}
|
package/src/mount.ts
CHANGED
|
@@ -4,11 +4,11 @@ import { FileManager } from "@sealcode/file-manager";
|
|
|
4
4
|
import Koa, { Context } from "koa";
|
|
5
5
|
import { Middlewares as SealiousMiddlewares } from "sealious";
|
|
6
6
|
import { Mountable } from "./page/mountable.js";
|
|
7
|
+
import { KoaResponsiveImageRouter } from "koa-responsive-image-router";
|
|
7
8
|
|
|
8
9
|
async function handleHtmlPromise(ctx: Context, next: Koa.Next) {
|
|
9
10
|
await next();
|
|
10
11
|
if (ctx.body instanceof Promise) {
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
12
12
|
ctx.body = await ctx.body;
|
|
13
13
|
}
|
|
14
14
|
ctx.set("content-type", "text/html;charset=utf-8");
|
|
@@ -24,6 +24,17 @@ export function mount(
|
|
|
24
24
|
: undefined
|
|
25
25
|
): void {
|
|
26
26
|
const raw_url = typeof url === "string" ? url : url.rawURL;
|
|
27
|
+
|
|
28
|
+
const imageRouter = new KoaResponsiveImageRouter({
|
|
29
|
+
staticPath: "/tmp",
|
|
30
|
+
thumbnailSize: 10,
|
|
31
|
+
cacheManagerResolutionThreshold: 10,
|
|
32
|
+
imageStoragePath: "/tmp",
|
|
33
|
+
smartCropStoragePath: "/tmp",
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const fileManager = new FileManager("/tmp", "/uploaded_files");
|
|
37
|
+
|
|
27
38
|
const args = use_dummy_app
|
|
28
39
|
? [
|
|
29
40
|
async (ctx: Context, next: any) => {
|
|
@@ -32,37 +43,35 @@ export function mount(
|
|
|
32
43
|
// regard
|
|
33
44
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
34
45
|
ctx.$app = {
|
|
46
|
+
fileManager,
|
|
47
|
+
imageRouter,
|
|
35
48
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
36
49
|
Logger: new Proxy(
|
|
37
50
|
{},
|
|
38
51
|
{
|
|
39
52
|
get: (_target: any, prop: any) => {
|
|
40
53
|
if (prop === "info") {
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
42
54
|
return () => {};
|
|
43
55
|
} else {
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
45
56
|
return () => {};
|
|
46
57
|
}
|
|
47
58
|
},
|
|
48
59
|
}
|
|
49
60
|
),
|
|
50
61
|
getString: (x: string) => x,
|
|
51
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
52
62
|
} as any;
|
|
53
63
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
54
64
|
await next();
|
|
55
65
|
},
|
|
56
66
|
SealiousMiddlewares.parseBody(file_manager),
|
|
57
67
|
handleHtmlPromise,
|
|
58
|
-
|
|
68
|
+
]
|
|
59
69
|
: [
|
|
60
70
|
SealiousMiddlewares.extractContext(),
|
|
61
71
|
SealiousMiddlewares.parseBody(file_manager),
|
|
62
72
|
handleHtmlPromise,
|
|
63
|
-
|
|
73
|
+
];
|
|
64
74
|
|
|
65
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
66
75
|
router.use(raw_url, ...args);
|
|
67
76
|
mountable.init();
|
|
68
77
|
|
package/src/notifier.ts
CHANGED
|
@@ -12,7 +12,6 @@ async function get_status(
|
|
|
12
12
|
app_port: number
|
|
13
13
|
): Promise<{ started_at: number; status: string }> {
|
|
14
14
|
const r = await fetch(`http://127.0.0.1:${app_port}/status.json`);
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
16
15
|
return (await r.json()) as { started_at: number; status: string };
|
|
17
16
|
}
|
|
18
17
|
|
|
@@ -21,7 +20,7 @@ async function wait_for_run_id_to_change(app_port: number) {
|
|
|
21
20
|
try {
|
|
22
21
|
const { started_at } = await get_status(app_port);
|
|
23
22
|
first_timestamp = started_at;
|
|
24
|
-
} catch (
|
|
23
|
+
} catch (_e) {
|
|
25
24
|
await wait_for_app_to_be_stable(app_port);
|
|
26
25
|
return;
|
|
27
26
|
}
|
|
@@ -30,7 +29,6 @@ async function wait_for_run_id_to_change(app_port: number) {
|
|
|
30
29
|
throw new Error(APP_DOWN_ERROR_MESSAGE);
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
// eslint-disable-next-line no-constant-condition
|
|
34
32
|
while (true) {
|
|
35
33
|
// eslint-disable-next-line no-await-in-loop
|
|
36
34
|
const { started_at } = await get_status(app_port).catch(() => ({
|
|
@@ -48,9 +46,8 @@ async function wait_for_app_to_be_stable(app_port: number, n = 3) {
|
|
|
48
46
|
// eslint-disable-next-line no-console
|
|
49
47
|
console.log("Waiting for app to be stable....");
|
|
50
48
|
let counter = 0;
|
|
51
|
-
|
|
49
|
+
|
|
52
50
|
while (true) {
|
|
53
|
-
console.debug("notifier.ts:53");
|
|
54
51
|
// eslint-disable-next-line no-await-in-loop
|
|
55
52
|
const { status } = await get_status(app_port).catch(() => ({
|
|
56
53
|
status: "down",
|
|
@@ -104,8 +101,8 @@ export function make_notifier(port: number, app_port: number) {
|
|
|
104
101
|
});
|
|
105
102
|
});
|
|
106
103
|
|
|
107
|
-
console.
|
|
108
|
-
"
|
|
104
|
+
console.info(
|
|
105
|
+
"🔔 Build notifier listening on websocket at port " + port.toString()
|
|
109
106
|
);
|
|
110
107
|
return function notify(message: string) {
|
|
111
108
|
sockets.forEach((s) => s.send(message));
|
package/src/page/list.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { naturalNumbers, UrlWithNewParams } from "../utils/utils.js";
|
|
|
8
8
|
import { makeHiddenInputs } from "../make-hidden-inputs.js";
|
|
9
9
|
import qs from "qs";
|
|
10
10
|
import { NumberField } from "../forms/fields/number.js";
|
|
11
|
-
import {
|
|
11
|
+
import { TextBasedSimpleField } from "../forms/fields/simple-form-field.js";
|
|
12
12
|
import { FormDataValue } from "../forms/form-types.js";
|
|
13
13
|
|
|
14
14
|
export const BasePagePropsShape = <const>{};
|
|
@@ -19,7 +19,7 @@ export const DEFAULT_ITEMS_PER_PAGE = 12;
|
|
|
19
19
|
export const BaseListPageFields = <const>{
|
|
20
20
|
page: new NumberField(false, 1),
|
|
21
21
|
itemsPerPage: new NumberField(false, DEFAULT_ITEMS_PER_PAGE),
|
|
22
|
-
sort: new
|
|
22
|
+
sort: new TextBasedSimpleField(false),
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
export type ListSort = { field: string; order: "asc" | "desc" };
|
|
@@ -48,7 +48,7 @@ function encodeSort(field: string, order: "asc" | "desc"): string {
|
|
|
48
48
|
|
|
49
49
|
export abstract class ListPage<
|
|
50
50
|
ItemType,
|
|
51
|
-
F extends typeof BaseListPageFields
|
|
51
|
+
F extends typeof BaseListPageFields,
|
|
52
52
|
> extends Page<F> {
|
|
53
53
|
abstract getItems(
|
|
54
54
|
ctx: Context,
|
|
@@ -74,8 +74,8 @@ export abstract class ListPage<
|
|
|
74
74
|
|
|
75
75
|
init(): void {
|
|
76
76
|
super.init();
|
|
77
|
-
for (const [
|
|
78
|
-
void field.init(
|
|
77
|
+
for (const [, field] of Object.entries(this.filterFields)) {
|
|
78
|
+
void field.init();
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
@@ -85,12 +85,15 @@ export abstract class ListPage<
|
|
|
85
85
|
|
|
86
86
|
async getPaginationConfig(ctx: Context) {
|
|
87
87
|
const values = await this.extractRawValues(ctx);
|
|
88
|
-
let { parsed: page } = await this.fields.page.
|
|
88
|
+
let { parsed: page } = await this.fields.page.getParsedValue(
|
|
89
|
+
ctx,
|
|
90
|
+
values
|
|
91
|
+
);
|
|
89
92
|
if (!page) {
|
|
90
93
|
page = 1;
|
|
91
94
|
}
|
|
92
95
|
const { parsed: itemsPerPage } =
|
|
93
|
-
await this.fields.itemsPerPage.
|
|
96
|
+
await this.fields.itemsPerPage.getParsedValue(ctx, values);
|
|
94
97
|
return { page, itemsPerPage };
|
|
95
98
|
}
|
|
96
99
|
|
|
@@ -123,7 +126,7 @@ export abstract class ListPage<
|
|
|
123
126
|
values
|
|
124
127
|
);
|
|
125
128
|
|
|
126
|
-
return tempstream/* HTML */ `<div class="list-pagination">
|
|
129
|
+
return tempstream /* HTML */ `<div class="list-pagination">
|
|
127
130
|
<div class="list-pagination__left">
|
|
128
131
|
${page > 1
|
|
129
132
|
? this.renderPageButton(ctx, 1, "Pierwsza strona")
|
|
@@ -138,18 +141,18 @@ export abstract class ListPage<
|
|
|
138
141
|
onchange="if (this.value) Turbo.visit(this.value)"
|
|
139
142
|
>
|
|
140
143
|
${Array.from(naturalNumbers(1, totalIems)).map(
|
|
141
|
-
(n) =>
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
144
|
+
(n) =>
|
|
145
|
+
/* HTML */ `<option
|
|
146
|
+
value="${UrlWithNewParams(
|
|
147
|
+
ctx,
|
|
148
|
+
this.propsParser.overwriteProp(ctx, {
|
|
149
|
+
page: n,
|
|
150
|
+
} as Partial<Record<string, unknown>>)
|
|
151
|
+
)}"
|
|
152
|
+
${page === n ? "selected" : ""}
|
|
153
|
+
>
|
|
154
|
+
${n}
|
|
155
|
+
</option>`
|
|
153
156
|
)}
|
|
154
157
|
</select>
|
|
155
158
|
</div>
|
|
@@ -168,7 +171,6 @@ export abstract class ListPage<
|
|
|
168
171
|
return /* HTML */ `<a
|
|
169
172
|
href="${UrlWithNewParams(
|
|
170
173
|
ctx,
|
|
171
|
-
//eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
172
174
|
this.propsParser.overwriteProp(ctx, {
|
|
173
175
|
page,
|
|
174
176
|
} as Partial<Record<string, unknown>>)
|
|
@@ -182,7 +184,7 @@ export abstract class ListPage<
|
|
|
182
184
|
const raw_values = await this.extractRawValues(ctx);
|
|
183
185
|
for (const [fieldname, field] of Object.entries(this.filterFields)) {
|
|
184
186
|
// eslint-disable-next-line no-await-in-loop
|
|
185
|
-
const { parsed } = await field.
|
|
187
|
+
const { parsed } = await field.getParsedValue(ctx, raw_values);
|
|
186
188
|
filter[fieldname] = field.mapToFilter(parsed);
|
|
187
189
|
}
|
|
188
190
|
return filter;
|
|
@@ -216,17 +218,20 @@ export abstract class ListPage<
|
|
|
216
218
|
|
|
217
219
|
async renderFilters(ctx: Context): Promise<FlatTemplatable> {
|
|
218
220
|
const values = await this.extractRawValues(ctx);
|
|
219
|
-
return tempstream/* HTML */ `<form method="GET">
|
|
221
|
+
return tempstream /* HTML */ `<form method="GET">
|
|
220
222
|
${makeHiddenInputs(ctx, this.fields, values, [
|
|
221
223
|
"page",
|
|
222
224
|
...Object.values(this.filterFields).map((f) => f.name),
|
|
223
225
|
])}
|
|
224
226
|
${this.filterControls.map((control) => {
|
|
225
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
226
227
|
return control.render(
|
|
227
228
|
this.makeFormControlContext(
|
|
228
229
|
ctx,
|
|
229
|
-
{
|
|
230
|
+
{
|
|
231
|
+
raw_values: values,
|
|
232
|
+
messages: [],
|
|
233
|
+
field_messages: {},
|
|
234
|
+
},
|
|
230
235
|
false
|
|
231
236
|
)
|
|
232
237
|
);
|
|
@@ -246,8 +251,8 @@ export abstract class ListPage<
|
|
|
246
251
|
current_order === "asc" // cycles the sort order: null → "asc" → "desc" → null → ...
|
|
247
252
|
? "desc"
|
|
248
253
|
: current_order === null
|
|
249
|
-
|
|
250
|
-
|
|
254
|
+
? "asc"
|
|
255
|
+
: null;
|
|
251
256
|
return /* HTML */ `<th data-field="${field}">
|
|
252
257
|
<a href="${this.makeSortLink(ctx, field, order)}"
|
|
253
258
|
>${label}
|
|
@@ -265,7 +270,7 @@ export abstract class ListPage<
|
|
|
265
270
|
ctx: Context,
|
|
266
271
|
fields: { field: string; label?: string }[]
|
|
267
272
|
): FlatTemplatable {
|
|
268
|
-
return tempstream/* HTML */ `<thead>
|
|
273
|
+
return tempstream /* HTML */ `<thead>
|
|
269
274
|
<tr>
|
|
270
275
|
${fields.map(({ label, field }) =>
|
|
271
276
|
this.renderHeading(ctx, field, label)
|
|
@@ -19,7 +19,7 @@ describe("mountable-with-fields", () => {
|
|
|
19
19
|
data.not_required?.trim();
|
|
20
20
|
// this should work without the optional chaining:
|
|
21
21
|
data.required.trim();
|
|
22
|
-
const { parsed: data2 } = await this.fields.not_required.
|
|
22
|
+
const { parsed: data2 } = await this.fields.not_required.getParsedValue(
|
|
23
23
|
ctx,
|
|
24
24
|
form_values.raw_values
|
|
25
25
|
);
|
|
@@ -2,6 +2,7 @@ import { ShapeToType } from "@sealcode/ts-predicates";
|
|
|
2
2
|
import { Context } from "koa";
|
|
3
3
|
import { FlatTemplatable, tempstream } from "tempstream";
|
|
4
4
|
import {
|
|
5
|
+
FieldMessages,
|
|
5
6
|
FormControl,
|
|
6
7
|
FormControlContext,
|
|
7
8
|
} from "../forms/controls/form-control.js";
|
|
@@ -20,11 +21,11 @@ export type Fields = Record<string, FormField<boolean, any>>;
|
|
|
20
21
|
|
|
21
22
|
type Resolved<T> = T extends Promise<infer X> ? X : never;
|
|
22
23
|
type ParsedValue<T extends FormField> = Resolved<
|
|
23
|
-
ReturnType<T["
|
|
24
|
+
ReturnType<T["getParsedValue"]>
|
|
24
25
|
>["parsed"];
|
|
25
26
|
|
|
26
27
|
export abstract class MountableWithFields<
|
|
27
|
-
F extends Fields = Fields
|
|
28
|
+
F extends Fields = Fields,
|
|
28
29
|
> extends Mountable {
|
|
29
30
|
fields: F;
|
|
30
31
|
field_names_prefix = ""; // useful for multiform, where many forms are merged into one and field assignment is made using the prefix
|
|
@@ -37,8 +38,9 @@ export abstract class MountableWithFields<
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
init(): void {
|
|
40
|
-
for (const [
|
|
41
|
-
void field.init(
|
|
41
|
+
for (const [field_name, field] of Object.entries(this.fields)) {
|
|
42
|
+
void field.init();
|
|
43
|
+
field.setName(field_name);
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
|
|
@@ -51,7 +53,7 @@ export abstract class MountableWithFields<
|
|
|
51
53
|
) {
|
|
52
54
|
return new FormControlContext(
|
|
53
55
|
ctx,
|
|
54
|
-
data
|
|
56
|
+
data,
|
|
55
57
|
data.messages,
|
|
56
58
|
field_name_prefix,
|
|
57
59
|
form_id,
|
|
@@ -81,10 +83,10 @@ export abstract class MountableWithFields<
|
|
|
81
83
|
values: Record<string, FormDataValue>
|
|
82
84
|
): Promise<{
|
|
83
85
|
valid: boolean;
|
|
84
|
-
field_errors:
|
|
86
|
+
field_errors: FieldMessages;
|
|
85
87
|
form_messages: FormMessage[];
|
|
86
88
|
}> {
|
|
87
|
-
const field_errors = {} as
|
|
89
|
+
const field_errors = {} as FieldMessages;
|
|
88
90
|
let valid = true;
|
|
89
91
|
const form_messages = [] as FormMessage[];
|
|
90
92
|
|
|
@@ -92,10 +94,13 @@ export abstract class MountableWithFields<
|
|
|
92
94
|
Object.keys(this.fields).map(async (key: keyof F) => {
|
|
93
95
|
const field = this.fields[key];
|
|
94
96
|
const { valid: fieldvalid, message: fieldmessage } =
|
|
95
|
-
await field.
|
|
97
|
+
await field.getParsedValue(ctx, values, true);
|
|
96
98
|
if (!fieldvalid) {
|
|
97
99
|
valid = false;
|
|
98
|
-
field_errors[field.name] =
|
|
100
|
+
field_errors[field.name] = {
|
|
101
|
+
type: "error",
|
|
102
|
+
message: fieldmessage,
|
|
103
|
+
};
|
|
99
104
|
}
|
|
100
105
|
})
|
|
101
106
|
);
|
|
@@ -111,7 +116,7 @@ export abstract class MountableWithFields<
|
|
|
111
116
|
}
|
|
112
117
|
|
|
113
118
|
public renderControls(fctx: FormControlContext): FlatTemplatable {
|
|
114
|
-
return tempstream/* HTML */ `${this.controls.map((control) =>
|
|
119
|
+
return tempstream /* HTML */ `${this.controls.map((control) =>
|
|
115
120
|
control.render(fctx)
|
|
116
121
|
)}`;
|
|
117
122
|
}
|
|
@@ -127,7 +132,7 @@ export abstract class MountableWithFields<
|
|
|
127
132
|
_: Context,
|
|
128
133
|
data: FormData<keyof Fields>
|
|
129
134
|
): FlatTemplatable {
|
|
130
|
-
return tempstream/* HTML */ `<div class="form-messages">
|
|
135
|
+
return tempstream /* HTML */ `<div class="form-messages">
|
|
131
136
|
${data.messages.map(
|
|
132
137
|
(message) =>
|
|
133
138
|
`<div class="form-message form-message--${message.type}">${message.text}</div>`
|
|
@@ -149,7 +154,11 @@ export abstract class MountableWithFields<
|
|
|
149
154
|
const promises = Object.entries(this.fields).map(
|
|
150
155
|
async ([key, field]) => {
|
|
151
156
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
152
|
-
const { parsed } = await field.
|
|
157
|
+
const { parsed } = await field.getParsedValue(
|
|
158
|
+
ctx,
|
|
159
|
+
raw_values,
|
|
160
|
+
false
|
|
161
|
+
);
|
|
153
162
|
result[key] = parsed;
|
|
154
163
|
}
|
|
155
164
|
);
|
package/src/page/mountable.ts
CHANGED
package/src/page/page.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import { AllQueryParams, PagePropsParser } from "./props-parser.js";
|
|
12
12
|
|
|
13
13
|
export abstract class Page<
|
|
14
|
-
F extends Fields = Record<string, never
|
|
14
|
+
F extends Fields = Record<string, never>,
|
|
15
15
|
> extends MountableWithFields<F> {
|
|
16
16
|
propsParser: PagePropsParser<Record<keyof Fields, unknown>> =
|
|
17
17
|
new AllQueryParams();
|
|
@@ -23,7 +23,6 @@ export abstract class Page<
|
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
27
26
|
async canAccess(_: Context) {
|
|
28
27
|
return { canAccess: true, message: "" };
|
|
29
28
|
}
|
|
@@ -32,7 +31,7 @@ export abstract class Page<
|
|
|
32
31
|
_: Context,
|
|
33
32
|
error: PageErrorMessage
|
|
34
33
|
): Promise<FlatTemplatable> {
|
|
35
|
-
return tempstream/* HTML */ `<div>${error.message}</div>`;
|
|
34
|
+
return tempstream /* HTML */ `<div>${error.message}</div>`;
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
public abstract render(ctx: Context): Promise<FlatTemplatable>;
|
package/src/page/props-parser.ts
CHANGED
|
@@ -22,7 +22,7 @@ export abstract class PagePropsParser<PropsType> {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export class AllQueryParams<
|
|
25
|
-
PropsType extends BasePageProps
|
|
25
|
+
PropsType extends BasePageProps,
|
|
26
26
|
> extends PagePropsParser<PropsType> {
|
|
27
27
|
decode(ctx: Context): Record<string, FormDataValue> {
|
|
28
28
|
return ctx.query;
|
|
@@ -18,7 +18,7 @@ import { is, predicates } from "@sealcode/ts-predicates";
|
|
|
18
18
|
|
|
19
19
|
export abstract class SealiousItemListPage<
|
|
20
20
|
C extends Collection,
|
|
21
|
-
F extends typeof BaseListPageFields
|
|
21
|
+
F extends typeof BaseListPageFields,
|
|
22
22
|
> extends ListPage<CollectionItem<C>, F> {
|
|
23
23
|
constructor(public collection: C) {
|
|
24
24
|
super();
|
|
@@ -34,7 +34,7 @@ export type StateAndMetadata<State, Actions> =
|
|
|
34
34
|
|
|
35
35
|
export type StatefulPageActionArgument<
|
|
36
36
|
State extends Record<string, unknown>,
|
|
37
|
-
Args extends unknown[] = unknown[]
|
|
37
|
+
Args extends unknown[] = unknown[],
|
|
38
38
|
> = {
|
|
39
39
|
ctx: Context;
|
|
40
40
|
state: State;
|
|
@@ -45,19 +45,15 @@ export type StatefulPageActionArgument<
|
|
|
45
45
|
|
|
46
46
|
export type StatefulPageAction<
|
|
47
47
|
State extends Record<string, unknown>,
|
|
48
|
-
Args extends unknown[] = unknown[]
|
|
48
|
+
Args extends unknown[] = unknown[],
|
|
49
49
|
> = (obj: StatefulPageActionArgument<State, Args>) => State | Promise<State>;
|
|
50
50
|
|
|
51
|
-
export type ExtractStatefulPageActionArgs<X> =
|
|
52
|
-
any,
|
|
53
|
-
infer Args
|
|
54
|
-
>
|
|
55
|
-
? Args
|
|
56
|
-
: never;
|
|
51
|
+
export type ExtractStatefulPageActionArgs<X> =
|
|
52
|
+
X extends StatefulPageAction<any, infer Args> ? Args : never;
|
|
57
53
|
|
|
58
54
|
export abstract class StatefulPage<
|
|
59
55
|
State extends Record<string, unknown>,
|
|
60
|
-
Actions extends Record<string, StatefulPageAction<State
|
|
56
|
+
Actions extends Record<string, StatefulPageAction<State>>,
|
|
61
57
|
> extends Mountable {
|
|
62
58
|
abstract actions: Actions;
|
|
63
59
|
abstract getInitialState(ctx: Context): State | Promise<State>;
|
|
@@ -104,7 +100,7 @@ export abstract class StatefulPage<
|
|
|
104
100
|
state: State,
|
|
105
101
|
content: Templatable
|
|
106
102
|
): Promise<Templatable> {
|
|
107
|
-
return tempstream/* HTML */ `<form
|
|
103
|
+
return tempstream /* HTML */ `<form
|
|
108
104
|
action="./"
|
|
109
105
|
method="POST"
|
|
110
106
|
enctype="multipart/form-data"
|
package/src/register-external.ts
CHANGED
|
@@ -70,11 +70,11 @@ async function updatePackageJson(
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
const pathToAdd = `node_modules/${moduleName}/${subdirectory}`;
|
|
73
|
-
const existingPaths = packageJson.sealgen[type]
|
|
73
|
+
const existingPaths = packageJson.sealgen[type];
|
|
74
74
|
|
|
75
75
|
// Check if the path is already present
|
|
76
76
|
if (existingPaths.includes(pathToAdd)) {
|
|
77
|
-
console.
|
|
77
|
+
console.warn(`${type} already contains: ${pathToAdd}`);
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -88,11 +88,11 @@ async function updatePackageJson(
|
|
|
88
88
|
);
|
|
89
89
|
|
|
90
90
|
await fs.writeFile(packageJsonPath, updatedContent);
|
|
91
|
-
console.
|
|
91
|
+
console.info(`Added ${pathToAdd} to ${type} in ${packageJsonPath}`);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
export async function registerExternalControllers(
|
|
95
|
-
|
|
95
|
+
_args: Record<string, string | boolean>
|
|
96
96
|
): Promise<void> {
|
|
97
97
|
// Extract positional arguments from process.argv since yargs doesn't handle them for these commands
|
|
98
98
|
const moduleName = process.argv.at(3);
|
|
@@ -120,7 +120,7 @@ export async function registerExternalControllers(
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
export async function registerExternalStyles(
|
|
123
|
-
|
|
123
|
+
_args: Record<string, string | boolean>
|
|
124
124
|
): Promise<void> {
|
|
125
125
|
// Extract positional arguments from process.argv since yargs doesn't handle them for these commands
|
|
126
126
|
const moduleName = process.argv.at(3);
|
package/src/templates/form.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
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
|
|
|
5
3
|
const defaults = {
|
|
6
4
|
postimport: `
|
|
7
5
|
import { Fields } from "@sealcode/sealgen";
|
|
8
6
|
import type {FormDataValue} from "@sealcode/sealgen";`,
|
|
9
7
|
fields: `
|
|
10
|
-
password: new Fields.
|
|
8
|
+
password: new Fields.Password(true),`,
|
|
11
9
|
controls: `
|
|
12
10
|
new Controls.SimpleInput(fields.password, {
|
|
13
11
|
label: "Password:",
|
|
@@ -18,8 +16,8 @@ const defaults = {
|
|
|
18
16
|
data: Record<string, FormDataValue>
|
|
19
17
|
): Promise<{ valid: boolean; error: string }> {
|
|
20
18
|
// just a silly example, please remove this with better logic
|
|
21
|
-
const { parsed: email } = await this.fields.email.
|
|
22
|
-
const { parsed: password } = await this.fields.password.
|
|
19
|
+
const { parsed: email } = await this.fields.email.getParsedValue(ctx, data);
|
|
20
|
+
const { parsed: password } = await this.fields.password.getParsedValue(ctx, data);
|
|
23
21
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
24
22
|
if ((password || "").length > ((email as string) || "").length) {
|
|
25
23
|
return { valid: false, error: "Password cannot be longer than email" };
|
|
@@ -45,15 +43,13 @@ const defaults = {
|
|
|
45
43
|
|
|
46
44
|
export async function formTemplate(
|
|
47
45
|
action_name: string,
|
|
48
|
-
|
|
49
|
-
_params: Partial<typeof defaults> & { success_message: string } = defaults
|
|
46
|
+
_params: Partial<typeof defaults> = defaults
|
|
50
47
|
): Promise<string> {
|
|
51
48
|
const params = { ...defaults, ..._params };
|
|
52
|
-
const rel = curryImportPath(newfilefullpath);
|
|
53
49
|
const content = `import type { Context } from "koa";
|
|
54
50
|
import type { FormData } from "@sealcode/sealgen";
|
|
55
51
|
import { Form, Controls, fieldsToShape } from "@sealcode/sealgen";
|
|
56
|
-
import html from "
|
|
52
|
+
import html from "src/back/html.js";
|
|
57
53
|
|
|
58
54
|
${params.postimport}
|
|
59
55
|
|
|
@@ -63,6 +59,8 @@ const fields = {
|
|
|
63
59
|
${params.fields}
|
|
64
60
|
};
|
|
65
61
|
|
|
62
|
+
Form.initFieldNames(fields);
|
|
63
|
+
|
|
66
64
|
export const ${action_name}Shape = fieldsToShape(fields);
|
|
67
65
|
|
|
68
66
|
export default new (class ${action_name}Form extends Form<typeof fields, void> {
|
|
@@ -84,5 +82,5 @@ export default new (class ${action_name}Form extends Form<typeof fields, void> {
|
|
|
84
82
|
${params.render}
|
|
85
83
|
})();
|
|
86
84
|
`;
|
|
87
|
-
return
|
|
85
|
+
return formatWithPrettier(content);
|
|
88
86
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { toKebabCase, toPascalCase } from "js-convert-case";
|
|
2
2
|
|
|
3
|
-
export function jddComponentTemplate(component_name: string) {
|
|
3
|
+
export async function jddComponentTemplate(component_name: string) {
|
|
4
4
|
return `import { TempstreamJSX } from "tempstream";
|
|
5
5
|
import type { ComponentToHTMLArgs } from "@sealcode/jdd";
|
|
6
6
|
import { Component, ComponentArguments } from "@sealcode/jdd";
|
|
@@ -12,9 +12,7 @@ export async function jddEditorTemplate(actionName: string) {
|
|
|
12
12
|
name: "collection",
|
|
13
13
|
message:
|
|
14
14
|
"Which sealious collection do you like to add CRUD forms for?",
|
|
15
|
-
choices: (
|
|
16
|
-
await listCollections()
|
|
17
|
-
).map((collection) => ({
|
|
15
|
+
choices: (await listCollections()).map((collection) => ({
|
|
18
16
|
title: collection,
|
|
19
17
|
value: collection,
|
|
20
18
|
})),
|
|
@@ -30,7 +28,7 @@ export async function jddEditorTemplate(actionName: string) {
|
|
|
30
28
|
let field_name = "";
|
|
31
29
|
if (jdd_fields.length == 1) {
|
|
32
30
|
field_name = jdd_fields[0].name;
|
|
33
|
-
console.
|
|
31
|
+
console.info(
|
|
34
32
|
`Only one field of type JDD found: ${field_name}, so skipping the question...`
|
|
35
33
|
);
|
|
36
34
|
} else if (jdd_fields.length > 1) {
|
package/src/templates/list.ts
CHANGED