@sealcode/sealgen 0.15.2 → 0.15.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/.eslintrc.cjs +38 -0
  2. package/.xunit +53 -0
  3. package/@types/src/page/stateful-page.d.ts +4 -2
  4. package/build.js +1 -1
  5. package/{dist → lib}/add-route.test.js +2 -2
  6. package/{dist → lib}/build.js +3 -3
  7. package/{dist → lib}/builder.js +3 -0
  8. package/lib/cli.js +39 -0
  9. package/{dist → lib}/esbuild-plugins/load-assets.js +2 -2
  10. package/{dist → lib}/forms/controls/array.js +1 -2
  11. package/{dist → lib}/forms/controls/autocomplete.js +8 -10
  12. package/{dist → lib}/forms/controls/checkboxed-list-input.test.js +3 -2
  13. package/{dist → lib}/forms/controls/collapsible-field-group.js +2 -1
  14. package/{dist → lib}/forms/controls/editable-collection-subset.js +6 -4
  15. package/{dist → lib}/forms/controls/field-group.js +1 -1
  16. package/{dist → lib}/forms/controls/file.js +2 -5
  17. package/{dist → lib}/forms/controls/form-control.js +2 -1
  18. package/{dist → lib}/forms/controls/photo.js +1 -1
  19. package/{dist → lib}/forms/controls/photo.test.js +5 -7
  20. package/{dist → lib}/forms/controls/textarea.js +1 -1
  21. package/{dist → lib}/forms/fields/boolean.test.js +0 -1
  22. package/{dist → lib}/forms/fields/field.js +2 -5
  23. package/{dist → lib}/forms/fields/file.js +8 -2
  24. package/{dist → lib}/forms/fields/structured-array.js +1 -1
  25. package/{dist → lib}/forms/form.test.js +8 -9
  26. package/{dist → lib}/forms/multiform.test.js +14 -14
  27. package/{dist → lib}/generate-components.js +1 -1
  28. package/{dist → lib}/generate-routes.test.js +1 -0
  29. package/{dist → lib}/generate-stimulus.js +1 -1
  30. package/lib/index.js +25 -0
  31. package/{dist → lib}/mount.js +4 -3
  32. package/{dist → lib}/notifier.js +3 -1
  33. package/{dist → lib}/page/list.js +1 -1
  34. package/{dist → lib}/page/mountable-with-fields.js +1 -1
  35. package/{dist → lib}/page/sealious-list.js +2 -2
  36. package/{dist → lib}/page/stateful-page.js +34 -17
  37. package/{dist → lib}/templates/jdd-component.js +2 -2
  38. package/{dist → lib}/utils/extract-fields-from-collection.js +16 -1
  39. package/package.json +19 -14
  40. package/src/add-route.test.ts +2 -2
  41. package/src/add-route.ts +2 -2
  42. package/src/build.ts +3 -3
  43. package/src/builder.ts +3 -2
  44. package/src/esbuild-plugins/load-assets.ts +5 -4
  45. package/src/esbuild-plugins/rewrite-asset-imports.ts +4 -3
  46. package/src/forms/controls/array.ts +5 -3
  47. package/src/forms/controls/autocomplete.ts +2 -2
  48. package/src/forms/controls/checkbox-group.ts +1 -5
  49. package/src/forms/controls/checkboxed-list-input.test.ts +3 -2
  50. package/src/forms/controls/checkboxed-list-input.ts +0 -1
  51. package/src/forms/controls/collapsible-field-group.ts +4 -2
  52. package/src/forms/controls/derived.ts +1 -1
  53. package/src/forms/controls/dropdown.ts +3 -3
  54. package/src/forms/controls/editable-collection-subset.ts +10 -4
  55. package/src/forms/controls/field-group.ts +1 -1
  56. package/src/forms/controls/file.ts +1 -1
  57. package/src/forms/controls/form-control.ts +2 -1
  58. package/src/forms/controls/hidden-input.ts +0 -2
  59. package/src/forms/controls/multiple-files.ts +8 -5
  60. package/src/forms/controls/number.ts +1 -1
  61. package/src/forms/controls/photo.test.ts +6 -7
  62. package/src/forms/controls/photo.ts +3 -6
  63. package/src/forms/controls/simple-input.ts +3 -5
  64. package/src/forms/controls/textarea.ts +3 -8
  65. package/src/forms/controls/tickable.ts +2 -4
  66. package/src/forms/fields/boolean.test.ts +0 -1
  67. package/src/forms/fields/existing-sealious-value.ts +1 -0
  68. package/src/forms/fields/field.ts +5 -8
  69. package/src/forms/fields/file.ts +13 -6
  70. package/src/forms/fields/structured-array.ts +2 -2
  71. package/src/forms/form.test.ts +9 -10
  72. package/src/forms/form.ts +1 -1
  73. package/src/forms/multiform.test.ts +14 -14
  74. package/src/forms/multiform.ts +2 -1
  75. package/src/generate-components.ts +1 -2
  76. package/src/generate-routes.test.ts +1 -0
  77. package/src/generate-stimulus.ts +1 -1
  78. package/src/get-fonts.ts +2 -0
  79. package/src/mount.ts +8 -3
  80. package/src/notifier.ts +3 -1
  81. package/src/page/list.ts +1 -1
  82. package/src/page/mountable-with-fields.ts +3 -1
  83. package/src/page/sealious-list.ts +3 -2
  84. package/src/page/stateful-page.ts +50 -22
  85. package/src/templates/jdd-component.ts +2 -2
  86. package/src/utils/extract-fields-from-collection.ts +19 -1
  87. package/src/utils/translate.ts +1 -1
  88. package/src/utils/utils.ts +2 -0
  89. package/test.cjs +54 -0
  90. package/tsconfig.json +3 -4
  91. package/dist/back/routes/sample.page.js +0 -17
  92. package/dist/back/routes/sample.test.js +0 -39
  93. package/dist/hehe.test.js +0 -7
  94. package/dist/sample-index.js +0 -3
  95. package/dist/sample-lib.js +0 -9
  96. package/dist/vitest.config.js +0 -23
  97. package/src/vitest.config.ts +0 -21
  98. /package/{dist → lib}/add-collection.js +0 -0
  99. /package/{dist → lib}/add-jdd-component.js +0 -0
  100. /package/{dist → lib}/add-route.js +0 -0
  101. /package/{dist → lib}/components/components.js +0 -0
  102. /package/{dist → lib}/components/tabs.js +0 -0
  103. /package/{dist → lib}/components/toggle-modal.js +0 -0
  104. /package/{dist → lib}/embeddable-file-extensions.js +0 -0
  105. /package/{dist → lib}/esbuild-plugins/rewrite-asset-imports.js +0 -0
  106. /package/{dist → lib}/example.test.js +0 -0
  107. /package/{dist → lib}/find-css-includes.js +0 -0
  108. /package/{dist → lib}/forms/controls/big-radio-group.js +0 -0
  109. /package/{dist → lib}/forms/controls/checkbox-group.js +0 -0
  110. /package/{dist → lib}/forms/controls/checkbox.js +0 -0
  111. /package/{dist → lib}/forms/controls/checkboxed-list-input.js +0 -0
  112. /package/{dist → lib}/forms/controls/collapsible-checkbox-group.js +0 -0
  113. /package/{dist → lib}/forms/controls/controls.js +0 -0
  114. /package/{dist → lib}/forms/controls/derived-frame.js +0 -0
  115. /package/{dist → lib}/forms/controls/derived.js +0 -0
  116. /package/{dist → lib}/forms/controls/dropdown.js +0 -0
  117. /package/{dist → lib}/forms/controls/form-field-control.js +0 -0
  118. /package/{dist → lib}/forms/controls/form-header.js +0 -0
  119. /package/{dist → lib}/forms/controls/form-paragraph.js +0 -0
  120. /package/{dist → lib}/forms/controls/frame.js +0 -0
  121. /package/{dist → lib}/forms/controls/hidden-input.js +0 -0
  122. /package/{dist → lib}/forms/controls/html.js +0 -0
  123. /package/{dist → lib}/forms/controls/multiple-files.js +0 -0
  124. /package/{dist → lib}/forms/controls/multiple-photos.js +0 -0
  125. /package/{dist → lib}/forms/controls/number.js +0 -0
  126. /package/{dist → lib}/forms/controls/radio.js +0 -0
  127. /package/{dist → lib}/forms/controls/reverse-single-reference.js +0 -0
  128. /package/{dist → lib}/forms/controls/simple-input.js +0 -0
  129. /package/{dist → lib}/forms/controls/tickable.js +0 -0
  130. /package/{dist → lib}/forms/fields/boolean.js +0 -0
  131. /package/{dist → lib}/forms/fields/checkboxed-list.js +0 -0
  132. /package/{dist → lib}/forms/fields/collection-field.js +0 -0
  133. /package/{dist → lib}/forms/fields/email.js +0 -0
  134. /package/{dist → lib}/forms/fields/email.test.js +0 -0
  135. /package/{dist → lib}/forms/fields/enum-multiple.js +0 -0
  136. /package/{dist → lib}/forms/fields/enum-multiple.test.js +0 -0
  137. /package/{dist → lib}/forms/fields/enum.js +0 -0
  138. /package/{dist → lib}/forms/fields/enum.test.js +0 -0
  139. /package/{dist → lib}/forms/fields/existing-sealious-value.js +0 -0
  140. /package/{dist → lib}/forms/fields/fields.js +0 -0
  141. /package/{dist → lib}/forms/fields/multiple-files.js +0 -0
  142. /package/{dist → lib}/forms/fields/number.js +0 -0
  143. /package/{dist → lib}/forms/fields/number.test.js +0 -0
  144. /package/{dist → lib}/forms/fields/pick-from-list.js +0 -0
  145. /package/{dist → lib}/forms/fields/pick-from-list.test.js +0 -0
  146. /package/{dist → lib}/forms/fields/proxy-field.js +0 -0
  147. /package/{dist → lib}/forms/fields/regexp.js +0 -0
  148. /package/{dist → lib}/forms/fields/regexp.test.js +0 -0
  149. /package/{dist → lib}/forms/fields/reverse-single-reference.js +0 -0
  150. /package/{dist → lib}/forms/fields/simple-form-field.js +0 -0
  151. /package/{dist → lib}/forms/form-types.js +0 -0
  152. /package/{dist → lib}/forms/form.js +0 -0
  153. /package/{dist → lib}/forms/multiform.js +0 -0
  154. /package/{dist → lib}/generate-collections.js +0 -0
  155. /package/{dist → lib}/generate-routes.js +0 -0
  156. /package/{dist → lib}/get-fonts.js +0 -0
  157. /package/{dist → lib}/koa.d.js +0 -0
  158. /package/{dist → lib}/make-env.js +0 -0
  159. /package/{dist → lib}/make-hidden-inputs.js +0 -0
  160. /package/{dist → lib}/page/access-control.js +0 -0
  161. /package/{dist → lib}/page/default-list-filters.js +0 -0
  162. /package/{dist → lib}/page/mountable.js +0 -0
  163. /package/{dist → lib}/page/page.js +0 -0
  164. /package/{dist → lib}/page/props-parser.js +0 -0
  165. /package/{dist → lib}/run.js +0 -0
  166. /package/{dist → lib}/sanitize.js +0 -0
  167. /package/{dist → lib}/target-locreq.js +0 -0
  168. /package/{dist → lib}/templates/collection.js +0 -0
  169. /package/{dist → lib}/templates/form.js +0 -0
  170. /package/{dist → lib}/templates/list.js +0 -0
  171. /package/{dist → lib}/templates/long-running-process.js +0 -0
  172. /package/{dist → lib}/templates/multiform.js +0 -0
  173. /package/{dist → lib}/templates/page.js +0 -0
  174. /package/{dist → lib}/templates/post.js +0 -0
  175. /package/{dist → lib}/templates/redirect.js +0 -0
  176. /package/{dist → lib}/templates/route-test.js +0 -0
  177. /package/{dist → lib}/templates/stateful-page.js +0 -0
  178. /package/{dist → lib}/templates/stimulus-controller.js +0 -0
  179. /package/{dist → lib}/templates/templates.js +0 -0
  180. /package/{dist → lib}/test_utils/locator_is_visible.js +0 -0
  181. /package/{dist → lib}/utils/assert-throws.js +0 -0
  182. /package/{dist → lib}/utils/base64.js +0 -0
  183. /package/{dist → lib}/utils/browser-creator.js +0 -0
  184. /package/{dist → lib}/utils/escape-url-params.js +0 -0
  185. /package/{dist → lib}/utils/exec.js +0 -0
  186. /package/{dist → lib}/utils/format-external-url.js +0 -0
  187. /package/{dist → lib}/utils/import-path.js +0 -0
  188. /package/{dist → lib}/utils/input-wrapper.js +0 -0
  189. /package/{dist → lib}/utils/list-collections.js +0 -0
  190. /package/{dist → lib}/utils/make-slug.js +0 -0
  191. /package/{dist → lib}/utils/module-dirname.js +0 -0
  192. /package/{dist → lib}/utils/natural-numbers.js +0 -0
  193. /package/{dist → lib}/utils/prettier.js +0 -0
  194. /package/{dist → lib}/utils/question.js +0 -0
  195. /package/{dist → lib}/utils/render-attributes.js +0 -0
  196. /package/{dist → lib}/utils/sleep.js +0 -0
  197. /package/{dist → lib}/utils/translate.js +0 -0
  198. /package/{dist → lib}/utils/url-with-new-params.js +0 -0
  199. /package/{dist → lib}/utils/utils.js +0 -0
  200. /package/{dist → lib}/utils/walk.js +0 -0
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import Router from "@koa/router";
2
3
  import { hasShape, predicates } from "@sealcode/ts-predicates";
3
4
  import { Context } from "koa";
@@ -57,7 +58,6 @@ export class StructuredArray<
57
58
  }
58
59
 
59
60
  makeSubfield(_field_name: string): FormField {
60
- const fields = this;
61
61
  return new SimpleFormField(false);
62
62
  }
63
63
 
@@ -77,6 +77,7 @@ export class StructuredArray<
77
77
  validate: false,
78
78
  };
79
79
  if (Array.isArray(control)) {
80
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
80
81
  const [constructor, field_name, params] = control;
81
82
  const field = this.makeSubfield(field_name);
82
83
  if (!field) {
@@ -173,13 +174,14 @@ export class StructuredArray<
173
174
  }
174
175
 
175
176
  async getTargetItemID(ctx: Context): Promise<string> {
176
- return ctx.params.id;
177
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
178
+ return ctx.params.id as string;
177
179
  }
178
180
 
179
181
  mount(router: Router) {
180
182
  console.log("mounting!", this.getActionURL());
181
183
  router.post(this.getActionURL(), async (ctx) => {
182
- let form_id = ctx.query.form_id;
184
+ const form_id = ctx.query.form_id;
183
185
  if (typeof form_id != "string") {
184
186
  throw new Error("Missing form_id query param");
185
187
  }
@@ -1,6 +1,6 @@
1
1
  import { Context } from "koa";
2
+ import { tempstream } from "tempstream";
2
3
  import { PickFromListField } from "../fields/pick-from-list.js";
3
- import { FormDataValue } from "../form-types.js";
4
4
  import { FormControlContext } from "./form-control.js";
5
5
  import { SimpleInput } from "./simple-input.js";
6
6
 
@@ -24,7 +24,7 @@ export class Autocomplete extends SimpleInput<string | null> {
24
24
  }
25
25
 
26
26
  async postInput(ctx: Context) {
27
- return /* HTML */ `<datalist id="${this.getListID()}">
27
+ return tempstream/* HTML */ `<datalist id="${this.getListID()}">
28
28
  ${(await this.field.generateOptions(ctx)).map(
29
29
  ({ value }) => /* HTML */ `<option>${value}</option>`
30
30
  )}
@@ -1,7 +1,5 @@
1
- import { Context } from "koa";
2
1
  import { FlatTemplatable } from "tempstream";
3
2
  import { EnumMultipleField } from "../fields/enum-multiple.js";
4
- import { FormField } from "../fields/field.js";
5
3
  import { ProxyFormField } from "../fields/proxy-field.js";
6
4
  import { CheckboxWithValue } from "./checkbox.js";
7
5
  import { FieldGroup } from "./field-group.js";
@@ -41,9 +39,7 @@ export class CheckboxGroup<
41
39
  }).render(fctx);
42
40
  }
43
41
 
44
- async render<Fields extends Record<string, FormField>>(
45
- fctx: FormControlContext
46
- ): Promise<FlatTemplatable> {
42
+ async render(fctx: FormControlContext): Promise<FlatTemplatable> {
47
43
  const { parsed: values } = await this.field.getValue(
48
44
  fctx.ctx,
49
45
  fctx.data
@@ -8,14 +8,15 @@ import { CheckboxedListField } from "../fields/checkboxed-list.js";
8
8
  import { Form } from "../form.js";
9
9
  import { CheckboxedListInput } from "./checkboxed-list-input.js";
10
10
  import { getBrowser } from "../../utils/browser-creator.js";
11
+ import assert from "assert";
11
12
 
12
- describe.only("checkboxed-list", () => {
13
+ describe("checkboxed-list", () => {
13
14
  describe("basic tests", async () => {
14
15
  let server: ReturnType<Koa["listen"]>;
15
16
  let browser: Browser;
16
17
  let page: Page;
17
18
 
18
- afterAll(() => {
19
+ afterEach(() => {
19
20
  server.close();
20
21
  });
21
22
 
@@ -1,4 +1,3 @@
1
- import { is, predicates } from "@sealcode/ts-predicates";
2
1
  import { tempstream } from "tempstream";
3
2
  import { getRequiredClass, inputWrapper } from "../../utils/input-wrapper.js";
4
3
  import { CheckboxedListField } from "../fields/checkboxed-list.js";
@@ -1,4 +1,4 @@
1
- import { FlatTemplatable } from "tempstream";
1
+ import { FlatTemplatable, tempstream } from "tempstream";
2
2
  import { FieldGroup } from "./field-group.js";
3
3
  import { randomUUID } from "crypto";
4
4
  import { FormControl } from "./form-control.js";
@@ -26,7 +26,9 @@ export class CollapsibleFieldGroup extends FieldGroup {
26
26
  }
27
27
 
28
28
  getGroupLabelProps() {
29
- return super.getGroupLabelProps() + ` for="${this.collapseID}"`;
29
+ return tempstream`${super.getGroupLabelProps()} for="${
30
+ this.collapseID
31
+ }"`;
30
32
  }
31
33
 
32
34
  preLabelContainer(): FlatTemplatable {
@@ -54,7 +54,7 @@ export class Derived<
54
54
  typeof value === "object"
55
55
  ? JSON.stringify(value)
56
56
  : typeof value == "string"
57
- ? '"' + (value as string).toString() + '"'
57
+ ? '"' + value.toString() + '"'
58
58
  : (value as string).toString()
59
59
  }`;
60
60
  })
@@ -43,13 +43,13 @@ export class FreeformDropdown extends SimpleInput<string | null> {
43
43
  ? [
44
44
  [
45
45
  "onchange",
46
- (original.onchange || "") +
47
- ";this.form.submit();",
46
+ ((original.onchange as string | undefined) ||
47
+ "") + ";this.form.submit();",
48
48
  ],
49
49
  ]
50
50
  : []),
51
51
  ]),
52
- };
52
+ } as Record<string, string>;
53
53
  }
54
54
 
55
55
  async renderInput(
@@ -42,7 +42,12 @@ export class EditableCollectionSubset extends FormFieldControl {
42
42
  method="POST"
43
43
  action="${fctx.ctx.path}"
44
44
  >
45
- <span>${text}</span>
45
+ <span
46
+ >${
47
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
48
+ text
49
+ }</span
50
+ >
46
51
  <input
47
52
  type="hidden"
48
53
  name="${this.field.name}"
@@ -79,9 +84,10 @@ export class EditableCollectionSubset extends FormFieldControl {
79
84
  )
80
85
  .map(
81
86
  ([value, text]) =>
82
- `<option value="${attribute(
83
- value
84
- )}">${text}</option>`
87
+ `<option value="${attribute(value)}">${
88
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
89
+ text
90
+ }</option>`
85
91
  )
86
92
  )}
87
93
  </select>
@@ -52,7 +52,7 @@ export class FieldGroup extends FormFieldControl {
52
52
  <div class="field-group__label-container">
53
53
  ${this.preLabel()}
54
54
  ${label
55
- ? `<label ${this.getGroupLabelProps()}>${label}</label>`
55
+ ? tempstream`<label ${this.getGroupLabelProps()}>${label}</label>`
56
56
  : ""}
57
57
  ${this.postLabel()}
58
58
  </div>
@@ -21,7 +21,7 @@ export class File extends SimpleInput<FileContainer> {
21
21
  if (!file) {
22
22
  return empty_container;
23
23
  }
24
- return /* HTML */ `<div class="${class_name}">
24
+ return tempstream/* HTML */ `<div class="${class_name}">
25
25
  ${file.getOriginalFilename()}
26
26
  </div>`;
27
27
  }
@@ -20,5 +20,6 @@ export abstract class FormControl {
20
20
  ): FlatTemplatable | Promise<FlatTemplatable>;
21
21
  abstract role: "input" | "decoration" | "messages" | "submit";
22
22
 
23
- mount(router: Router) {}
23
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
24
+ mount(_router: Router) {}
24
25
  }
@@ -1,8 +1,6 @@
1
- import { Context } from "koa";
2
1
  import { FlatTemplatable, tempstream } from "tempstream";
3
2
  import { attribute } from "../../sanitize.js";
4
3
  import { FormField } from "../fields/field.js";
5
- import { FormDataValue } from "../form-types.js";
6
4
  import { FormControlContext } from "./form-control.js";
7
5
  import { FormFieldControl } from "./form-field-control.js";
8
6
 
@@ -1,5 +1,5 @@
1
1
  import Router from "@koa/router";
2
- import { CollectionItem, Field as SealiousField } from "sealious";
2
+ import { Collection, CollectionItem, Field as SealiousField } from "sealious";
3
3
  import { Context } from "koa";
4
4
  import { inputWrapper } from "../../utils/input-wrapper.js";
5
5
  import { FlatTemplatable, tempstream } from "tempstream";
@@ -140,14 +140,14 @@ export class MultipleFiles extends FormFieldControl {
140
140
  }
141
141
 
142
142
  async extractFileFromItem(
143
- item: CollectionItem
143
+ item: CollectionItem<Collection>
144
144
  ): Promise<FilePointer | null> {
145
145
  const sealious_field = this.getFileField();
146
146
  if (!sealious_field) {
147
147
  return null;
148
148
  }
149
149
  return await item.collection.app.FileManager.fromToken(
150
- item.get(sealious_field.name).token
150
+ (item.get(sealious_field.name) as FilePointer).token
151
151
  );
152
152
  }
153
153
 
@@ -216,12 +216,15 @@ export class MultipleFiles extends FormFieldControl {
216
216
  await this.getFileItems(ctx)
217
217
  )
218
218
  .filter((item) => item) // filter out undefineds
219
- .map(async (item) => [
219
+ .map(async (item: CollectionItem<Collection>) => [
220
220
  item,
221
221
  await this.extractFileFromItem(item),
222
222
  ])
223
223
  )
224
- ).filter(([_, f]) => f !== null) as [CollectionItem, FilePointer][];
224
+ ).filter(([_, f]) => f !== null) as [
225
+ CollectionItem<Collection>,
226
+ FilePointer
227
+ ][];
225
228
 
226
229
  return inputWrapper(
227
230
  ["multiple-files", this.field.name, ...this.getClassModifiers()],
@@ -30,6 +30,6 @@ export class Number extends SimpleInput<number | null> {
30
30
  : []),
31
31
  ...(this.options.step ? [["step", this.options.step]] : []),
32
32
  ]),
33
- };
33
+ } as Record<string, string>;
34
34
  }
35
35
  }
@@ -13,15 +13,16 @@ import { KoaResponsiveImageRouter } from "koa-responsive-image-router";
13
13
  import _locreq from "locreq";
14
14
  import { module_dirname } from "../../utils/module-dirname.js";
15
15
  import { FileManager, PathFilePointer } from "@sealcode/file-manager";
16
+ import assert from "node:assert";
16
17
  const locreq = _locreq(module_dirname(import.meta.url));
17
18
 
18
- describe("photo-controll", () => {
19
+ describe("photo-control", () => {
19
20
  describe("basic tests", async () => {
20
21
  let server: ReturnType<Koa["listen"]>;
21
22
  let browser: Browser;
22
23
  let page: Page;
23
24
 
24
- afterAll(() => {
25
+ after(() => {
25
26
  server.close();
26
27
  });
27
28
 
@@ -53,13 +54,11 @@ describe("photo-controll", () => {
53
54
  controls = [new Photo(fields.photo, imageRouter)];
54
55
 
55
56
  async onSubmit(ctx: Context) {
56
- console.log("OnSubmit!");
57
57
  const data = await this.getParsedValues(ctx);
58
- console.log({ data });
59
58
  received_photo = data.photo;
60
59
  }
61
60
 
62
- async getInitialValues(ctx: Context) {
61
+ async getInitialValues(_ctx: Context) {
63
62
  const file = new PathFilePointer(
64
63
  new FileManager("/tmp", "/uploaded_files"),
65
64
  locreq.resolve("assets/important.png")
@@ -77,14 +76,14 @@ describe("photo-controll", () => {
77
76
  );
78
77
  app.use(router.routes()).use(router.allowedMethods());
79
78
  server = app.listen(port);
79
+ // await sleep(99999999);
80
80
 
81
81
  browser = await getBrowser();
82
82
  const context = await browser.newContext();
83
83
  page = await context.newPage();
84
84
  await page.goto(`http://localhost:${port}`);
85
85
  await page.getByRole("button", { name: "Wyślij" }).click();
86
- console.log({ received_photo });
87
86
  assert(received_photo !== undefined && (received_photo as any).old !== null);
88
87
  });
89
- });
88
+ }).timeout(99999999999);
90
89
  });
@@ -22,7 +22,7 @@ export class Photo extends File {
22
22
  }
23
23
 
24
24
  async renderFilePreview(
25
- ctx: Context,
25
+ _ctx: Context,
26
26
  file: FilePointer | null
27
27
  ): Promise<FlatTemplatable> {
28
28
  const class_name = "file_preview";
@@ -48,15 +48,12 @@ export class Photo extends File {
48
48
  }
49
49
 
50
50
  async getInputAttributes(fctx: FormControlContext) {
51
- const original = (await super.getInputAttributes(fctx)) as Record<
52
- string,
53
- string | boolean
54
- >;
51
+ const original = await super.getInputAttributes(fctx);
55
52
  return {
56
53
  ...original,
57
54
  accept: "image/*",
58
55
  onchange:
59
- (original.onchange || "") +
56
+ ((original.onchange as string) || "") +
60
57
  ";" +
61
58
  `
62
59
  const file = this.files[0];
@@ -91,7 +91,7 @@ export class SimpleInput<
91
91
  !valid && raw
92
92
  ? raw.toString()
93
93
  : parsed !== undefined && parsed !== null
94
- ? ((parsed as any)?.toString() as string) || ""
94
+ ? (parsed as string)?.toString() || ""
95
95
  : "",
96
96
  ],
97
97
  ...(fctx.form_id ? [["form", fctx.form_id]] : []),
@@ -100,7 +100,7 @@ export class SimpleInput<
100
100
  ...(required ? [["required", true]] : []),
101
101
  ...(!this.options.autocomplete ? [["autocomplete", "off"]] : []),
102
102
  ...(this.options.step ? [["step", this.options.step]] : []),
103
- ]);
103
+ ]) as Record<string, string>;
104
104
  }
105
105
 
106
106
  async postInput(_: Context): Promise<FlatTemplatable> {
@@ -126,9 +126,7 @@ export class SimpleInput<
126
126
  ];
127
127
  }
128
128
 
129
- async render<Fields extends Record<string, FormField>>(
130
- fctx: FormControlContext
131
- ): Promise<FlatTemplatable> {
129
+ async render(fctx: FormControlContext): Promise<FlatTemplatable> {
132
130
  const id = this.getID();
133
131
  const label = this.getLabel();
134
132
 
@@ -4,9 +4,7 @@ import { FormDataValue } from "../form-types.js";
4
4
  import { FormControlContext } from "./form-control.js";
5
5
  import { SimpleInput, SimpleInputOptions } from "./simple-input.js";
6
6
 
7
- export class Textarea<Required extends boolean> extends SimpleInput<
8
- string | null
9
- > {
7
+ export class Textarea extends SimpleInput<string | null> {
10
8
  constructor(
11
9
  public field: FormField<boolean, string | null>,
12
10
  public options: SimpleInputOptions & {
@@ -31,10 +29,7 @@ export class Textarea<Required extends boolean> extends SimpleInput<
31
29
  async getInputAttributes(
32
30
  fctx: FormControlContext
33
31
  ): Promise<Record<string, string | boolean>> {
34
- const original = (await super.getInputAttributes(fctx)) as Record<
35
- string,
36
- string | boolean
37
- >;
32
+ const original = await super.getInputAttributes(fctx);
38
33
  let onkeydown = original.onkeydown || "";
39
34
  if (this.options.autogrow) {
40
35
  onkeydown += `;this.style.height = '5px';this.style.height = Math.max((this.scrollHeight)+32, ${
@@ -55,6 +50,6 @@ export class Textarea<Required extends boolean> extends SimpleInput<
55
50
  data: Record<string, FormDataValue>
56
51
  ) {
57
52
  const { parsed: value } = await this.field.getValue(ctx, data);
58
- return /* HTML */ `<textarea ${attributes}>${value}</textarea>`;
53
+ return /* HTML */ `<textarea ${attributes}>${value || ""}</textarea>`;
59
54
  }
60
55
  }
@@ -15,7 +15,7 @@ export type TickableOptions = {
15
15
  readonly?: boolean;
16
16
  };
17
17
 
18
- export abstract class Tickable<T extends unknown> extends FormFieldControl {
18
+ export abstract class Tickable<T> extends FormFieldControl {
19
19
  constructor(
20
20
  public field: FormField<boolean, T>,
21
21
  public options: TickableOptions = {}
@@ -63,9 +63,7 @@ export abstract class Tickable<T extends unknown> extends FormFieldControl {
63
63
  ];
64
64
  }
65
65
 
66
- async render<Fields extends Record<string, FormField>>(
67
- fctx: FormControlContext
68
- ): Promise<FlatTemplatable> {
66
+ async render(fctx: FormControlContext): Promise<FlatTemplatable> {
69
67
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
70
68
  const { parsed, valid, message } = await this.field.getValue(
71
69
  fctx.ctx,
@@ -1,4 +1,3 @@
1
- import { describe, it, beforeAll, afterAll, afterEach, beforeEach } from "vitest";
2
1
  import assert from "assert";
3
2
  import { Fields } from "../../index.js";
4
3
 
@@ -7,6 +7,7 @@ export class ExistingSealiousValue<
7
7
  constructor(required: Required, field: Field) {
8
8
  super(required, async (ctx) => {
9
9
  const { items } = await field.collection.list(ctx.$context).fetch();
10
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
10
11
  return Object.fromEntries(
11
12
  items.map((item) => {
12
13
  const value = item.get(field.name);
@@ -49,7 +49,7 @@ export type FieldParseResult<T> =
49
49
 
50
50
  export abstract class FormField<
51
51
  Required extends boolean = boolean,
52
- ParsedValue extends unknown = unknown
52
+ ParsedValue = unknown
53
53
  > {
54
54
  name: string;
55
55
  constructor(public readonly required: Required) {}
@@ -85,8 +85,8 @@ export abstract class FormField<
85
85
  public abstract getEmptyValue(): ParsedValue;
86
86
 
87
87
  public async isValueValid(
88
- ctx: Context,
89
- value: ParsedValue
88
+ _ctx: Context,
89
+ _value: ParsedValue
90
90
  ): Promise<FormFieldValidationResponse> {
91
91
  return { valid: true, message: "" };
92
92
  }
@@ -128,12 +128,9 @@ export abstract class FormField<
128
128
  message: parse_error || "Error",
129
129
  };
130
130
  }
131
- const { valid, message } = await this._validate(
132
- ctx,
133
- parsed_value as ParsedValue
134
- );
131
+ const { valid, message } = await this._validate(ctx, parsed_value);
135
132
  return {
136
- parsed: parsed_value as ParsedValue,
133
+ parsed: parsed_value,
137
134
  valid,
138
135
  message,
139
136
  raw: all_form_values[this.name],
@@ -21,7 +21,7 @@ export class File<Required extends boolean> extends FormField<
21
21
  }
22
22
 
23
23
  async parse(
24
- ctx: Context,
24
+ _ctx: Context,
25
25
  raw_value: FormDataValue
26
26
  ): Promise<FieldParseResult<FileContainer>> {
27
27
  let result;
@@ -30,17 +30,23 @@ export class File<Required extends boolean> extends FormField<
30
30
  result = {
31
31
  parsed_value: { old: file, new: null },
32
32
  error: null,
33
- parsable: true as true,
33
+ parsable: true as const,
34
34
  };
35
35
  } else if (!is(raw_value, predicates.object)) {
36
36
  result = {
37
37
  parsed_value: null,
38
38
  error: "Expected a field with old.id:string, old.filename:string and new?:File",
39
- parsable: false as false,
39
+ parsable: false as const,
40
40
  };
41
41
  } else {
42
- const old_file = hasFieldOfType(raw_value, "old", predicates.string)
43
- ? await this.file_manager.fromToken(raw_value.old)
42
+ const old_file = hasFieldOfType(
43
+ raw_value,
44
+ "old",
45
+ predicates.or(predicates.string, predicates.object)
46
+ )
47
+ ? await this.file_manager.toPointer(
48
+ raw_value.old as string | FilePointer
49
+ )
44
50
  : null;
45
51
  const new_file =
46
52
  hasFieldOfType(
@@ -51,11 +57,12 @@ export class File<Required extends boolean> extends FormField<
51
57
  ? raw_value.new[0]
52
58
  : null;
53
59
  result = {
54
- parsable: true as true,
60
+ parsable: true as const,
55
61
  error: null,
56
62
  parsed_value: { old: old_file, new: new_file },
57
63
  };
58
64
  }
65
+
59
66
  return result;
60
67
  }
61
68
 
@@ -1,5 +1,5 @@
1
1
  import { Context } from "koa";
2
- import { Field, FieldsetInput, FieldsetOutput, FieldTypes } from "sealious";
2
+ import { Field, FieldsetOutput, FieldTypes } from "sealious";
3
3
  import { FormDataValue } from "../form-types.js";
4
4
  import { FormField } from "./field.js";
5
5
 
@@ -13,7 +13,7 @@ export class StructuredArrayField<
13
13
  super(true);
14
14
  }
15
15
 
16
- async parse(context: Context, value: FormDataValue) {
16
+ async parse(_context: Context, value: FormDataValue) {
17
17
  return {
18
18
  parsable: <const>true,
19
19
  error: null,
@@ -1,5 +1,4 @@
1
1
  import Router from "@koa/router";
2
- import { describe, it, beforeAll, afterAll, afterEach, beforeEach } from "vitest";
3
2
  import axios from "axios";
4
3
  import Koa, { BaseContext } from "koa";
5
4
  import { Page } from "playwright";
@@ -7,7 +6,7 @@ import { Controls, Fields, Form, Mountable } from "../index.js";
7
6
  import { mount } from "../mount.js";
8
7
  import { locator_is_visible } from "../test_utils/locator_is_visible.js";
9
8
  import { getBrowser } from "../utils/browser-creator.js";
10
- import { assertThrowsAsync, sleep } from "../utils/utils.js";
9
+ import { assertThrowsAsync } from "../utils/utils.js";
11
10
  import { FormDataValue } from "./form-types.js";
12
11
  import getPort from "get-port";
13
12
  import { SimpleFormField } from "./fields/simple-form-field.js";
@@ -42,7 +41,7 @@ console.log("Using port " + port + " for form.test.ts");
42
41
  describe("form test", () => {
43
42
  let page: Page;
44
43
 
45
- beforeAll(async () => {
44
+ before(async () => {
46
45
  const browser = await getBrowser();
47
46
  const context = await browser.newContext();
48
47
  page = await context.newPage();
@@ -51,7 +50,7 @@ describe("form test", () => {
51
50
  describe("basic tests", async () => {
52
51
  let server: ReturnType<Koa["listen"]>;
53
52
 
54
- beforeAll(async () => {
53
+ before(async () => {
55
54
  const app = new Koa();
56
55
  const router = new Router();
57
56
 
@@ -61,7 +60,7 @@ describe("form test", () => {
61
60
  await page.goto(`http://localhost:${port}`);
62
61
  });
63
62
 
64
- afterAll(async () => {
63
+ after(async () => {
65
64
  server.close();
66
65
  });
67
66
 
@@ -131,7 +130,7 @@ describe("form test", () => {
131
130
  const app = new Koa();
132
131
  const router = new Router();
133
132
 
134
- beforeAll(async () => {
133
+ before(async () => {
135
134
  mount(
136
135
  router,
137
136
  "/",
@@ -236,7 +235,7 @@ describe("form test", () => {
236
235
  describe("validation message", async () => {
237
236
  let server: ReturnType<Koa["listen"]>;
238
237
 
239
- beforeAll(async () => {
238
+ before(async () => {
240
239
  const app = new Koa();
241
240
  const router = new Router();
242
241
 
@@ -277,7 +276,7 @@ describe("form test", () => {
277
276
  await page.goto(`http://localhost:${port}`);
278
277
  });
279
278
 
280
- afterAll(async () => {
279
+ after(async () => {
281
280
  server.close();
282
281
  });
283
282
 
@@ -302,7 +301,7 @@ describe("form test", () => {
302
301
  describe("field specific validation message", async () => {
303
302
  let server: ReturnType<Koa["listen"]>;
304
303
 
305
- beforeAll(async () => {
304
+ before(async () => {
306
305
  const app = new Koa();
307
306
  const router = new Router();
308
307
  const fields = {
@@ -334,7 +333,7 @@ describe("form test", () => {
334
333
  await page.goto(`http://localhost:${port}`);
335
334
  });
336
335
 
337
- afterAll(async () => {
336
+ after(async () => {
338
337
  server.close();
339
338
  });
340
339
 
package/src/forms/form.ts CHANGED
@@ -25,7 +25,7 @@ import {
25
25
 
26
26
  export abstract class Form<
27
27
  F extends Fields,
28
- SubmitResult extends any
28
+ SubmitResult
29
29
  > extends MountableWithFields<F> {
30
30
  defaultSuccessMessage = "Done";
31
31
  submitButtonText = "Wyślij";