@sealcode/sealgen 0.12.0 → 0.12.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 (268) hide show
  1. package/dist/notifier.js +1 -1
  2. package/package.json +2 -2
  3. package/src/notifier.ts +1 -1
  4. package/.madgerc +0 -7
  5. package/coverage/.tmp/coverage-15.json +0 -1
  6. package/coverage/.tmp/coverage-16.json +0 -1
  7. package/coverage/.tmp/coverage-17.json +0 -1
  8. package/coverage/.tmp/coverage-18.json +0 -1
  9. package/coverage/.tmp/coverage-19.json +0 -1
  10. package/coverage/.tmp/coverage-20.json +0 -1
  11. package/coverage/.tmp/coverage-21.json +0 -1
  12. package/coverage/.tmp/coverage-22.json +0 -1
  13. package/coverage/.tmp/coverage-23.json +0 -1
  14. package/coverage/.tmp/coverage-24.json +0 -1
  15. package/coverage/.tmp/coverage-25.json +0 -1
  16. package/coverage/.tmp/coverage-26.json +0 -1
  17. package/lib/add-collection.js +0 -24
  18. package/lib/add-jdd-component.js +0 -27
  19. package/lib/add-route.js +0 -65
  20. package/lib/add-route.test.js +0 -60
  21. package/lib/build.js +0 -187
  22. package/lib/cli.js +0 -35
  23. package/lib/components/components.js +0 -3
  24. package/lib/components/tabs.js +0 -88
  25. package/lib/components/toggle-modal.js +0 -46
  26. package/lib/example.test.js +0 -5
  27. package/lib/find-css-includes.js +0 -23
  28. package/lib/forms/controls/array.js +0 -140
  29. package/lib/forms/controls/autocomplete.js +0 -23
  30. package/lib/forms/controls/big-radio-group.js +0 -34
  31. package/lib/forms/controls/checkbox-group.js +0 -29
  32. package/lib/forms/controls/checkbox.js +0 -24
  33. package/lib/forms/controls/checkboxed-list-input.js +0 -35
  34. package/lib/forms/controls/collapsible-checkbox-group.js +0 -13
  35. package/lib/forms/controls/collapsible-field-group.js +0 -78
  36. package/lib/forms/controls/controls.js +0 -31
  37. package/lib/forms/controls/derived-frame.js +0 -52
  38. package/lib/forms/controls/derived.js +0 -77
  39. package/lib/forms/controls/dropdown.js +0 -55
  40. package/lib/forms/controls/editable-collection-subset.js +0 -68
  41. package/lib/forms/controls/field-group.js +0 -53
  42. package/lib/forms/controls/file.js +0 -35
  43. package/lib/forms/controls/form-control.js +0 -14
  44. package/lib/forms/controls/form-field-control.js +0 -9
  45. package/lib/forms/controls/form-header.js +0 -14
  46. package/lib/forms/controls/form-paragraph.js +0 -12
  47. package/lib/forms/controls/frame.js +0 -25
  48. package/lib/forms/controls/hidden-input.js +0 -14
  49. package/lib/forms/controls/html.js +0 -23
  50. package/lib/forms/controls/multiple-files.js +0 -160
  51. package/lib/forms/controls/multiple-photos.js +0 -33
  52. package/lib/forms/controls/number.js +0 -25
  53. package/lib/forms/controls/photo.js +0 -57
  54. package/lib/forms/controls/radio.js +0 -25
  55. package/lib/forms/controls/reverse-single-reference.js +0 -47
  56. package/lib/forms/controls/simple-input.js +0 -78
  57. package/lib/forms/controls/textarea.js +0 -33
  58. package/lib/forms/controls/tickable.js +0 -75
  59. package/lib/forms/fields/boolean.js +0 -51
  60. package/lib/forms/fields/boolean.test.js +0 -32
  61. package/lib/forms/fields/checkboxed-list.js +0 -40
  62. package/lib/forms/fields/collection-field.js +0 -29
  63. package/lib/forms/fields/email.js +0 -11
  64. package/lib/forms/fields/email.test.js +0 -20
  65. package/lib/forms/fields/enum-multiple.js +0 -47
  66. package/lib/forms/fields/enum-multiple.test.js +0 -27
  67. package/lib/forms/fields/enum.js +0 -39
  68. package/lib/forms/fields/enum.test.js +0 -21
  69. package/lib/forms/fields/existing-sealious-value.js +0 -16
  70. package/lib/forms/fields/field.js +0 -81
  71. package/lib/forms/fields/file.js +0 -53
  72. package/lib/forms/fields/multiple-files.js +0 -15
  73. package/lib/forms/fields/number.js +0 -45
  74. package/lib/forms/fields/number.test.js +0 -30
  75. package/lib/forms/fields/pick-from-list.js +0 -31
  76. package/lib/forms/fields/pick-from-list.test.js +0 -17
  77. package/lib/forms/fields/proxy-field.js +0 -20
  78. package/lib/forms/fields/regexp.js +0 -40
  79. package/lib/forms/fields/regexp.test.js +0 -21
  80. package/lib/forms/fields/reverse-single-reference.js +0 -14
  81. package/lib/forms/fields/simple-form-field.js +0 -20
  82. package/lib/forms/fields/structured-array.js +0 -18
  83. package/lib/forms/form.js +0 -176
  84. package/lib/forms/form.test.js +0 -1
  85. package/lib/forms/multiform.js +0 -174
  86. package/lib/forms/multiform.test.js +0 -426
  87. package/lib/generate-collections.js +0 -52
  88. package/lib/generate-components.js +0 -33
  89. package/lib/generate-routes.js +0 -75
  90. package/lib/index.js +0 -17
  91. package/lib/make-env.js +0 -14
  92. package/lib/make-hidden-inputs.js +0 -14
  93. package/lib/mount.js +0 -70
  94. package/lib/notifier.js +0 -19
  95. package/lib/page/access-control.js +0 -16
  96. package/lib/page/default-list-filters.js +0 -40
  97. package/lib/page/list.js +0 -183
  98. package/lib/page/mountable-with-fields.js +0 -85
  99. package/lib/page/mountable.js +0 -5
  100. package/lib/page/page.js +0 -26
  101. package/lib/page/props-parser.js +0 -23
  102. package/lib/page/sealious-list.js +0 -59
  103. package/lib/page/stateful-page.js +0 -97
  104. package/lib/remove-named-imports.js +0 -47
  105. package/lib/run.js +0 -2
  106. package/lib/sanitize.js +0 -10
  107. package/lib/src/add-collection.js +0 -24
  108. package/lib/src/add-jdd-component.js +0 -27
  109. package/lib/src/add-route.js +0 -65
  110. package/lib/src/add-route.test.js +0 -72
  111. package/lib/src/build.js +0 -142
  112. package/lib/src/cli.js +0 -37
  113. package/lib/src/components/components.js +0 -3
  114. package/lib/src/components/tabs.js +0 -88
  115. package/lib/src/components/toggle-modal.js +0 -46
  116. package/lib/src/example.test.js +0 -5
  117. package/lib/src/find-css-includes.js +0 -23
  118. package/lib/src/forms/controls/array.js +0 -141
  119. package/lib/src/forms/controls/autocomplete.js +0 -23
  120. package/lib/src/forms/controls/big-radio-group.js +0 -34
  121. package/lib/src/forms/controls/checkbox-group.js +0 -30
  122. package/lib/src/forms/controls/checkbox.js +0 -24
  123. package/lib/src/forms/controls/checkboxed-list-input.js +0 -35
  124. package/lib/src/forms/controls/collapsible-checkbox-group.js +0 -13
  125. package/lib/src/forms/controls/collapsible-field-group.js +0 -78
  126. package/lib/src/forms/controls/controls.js +0 -31
  127. package/lib/src/forms/controls/derived-frame.js +0 -52
  128. package/lib/src/forms/controls/derived.js +0 -77
  129. package/lib/src/forms/controls/dropdown.js +0 -55
  130. package/lib/src/forms/controls/editable-collection-subset.js +0 -68
  131. package/lib/src/forms/controls/field-group.js +0 -53
  132. package/lib/src/forms/controls/file.js +0 -35
  133. package/lib/src/forms/controls/form-control.js +0 -14
  134. package/lib/src/forms/controls/form-field-control.js +0 -9
  135. package/lib/src/forms/controls/form-header.js +0 -14
  136. package/lib/src/forms/controls/form-paragraph.js +0 -12
  137. package/lib/src/forms/controls/frame.js +0 -25
  138. package/lib/src/forms/controls/hidden-input.js +0 -14
  139. package/lib/src/forms/controls/html.js +0 -23
  140. package/lib/src/forms/controls/multiple-files.js +0 -160
  141. package/lib/src/forms/controls/multiple-photos.js +0 -33
  142. package/lib/src/forms/controls/number.js +0 -25
  143. package/lib/src/forms/controls/photo.js +0 -57
  144. package/lib/src/forms/controls/radio.js +0 -25
  145. package/lib/src/forms/controls/reverse-single-reference.js +0 -47
  146. package/lib/src/forms/controls/simple-input.js +0 -78
  147. package/lib/src/forms/controls/textarea.js +0 -33
  148. package/lib/src/forms/controls/tickable.js +0 -75
  149. package/lib/src/forms/fields/boolean.js +0 -51
  150. package/lib/src/forms/fields/boolean.test.js +0 -33
  151. package/lib/src/forms/fields/checkboxed-list.js +0 -40
  152. package/lib/src/forms/fields/collection-field.js +0 -29
  153. package/lib/src/forms/fields/email.js +0 -11
  154. package/lib/src/forms/fields/email.test.js +0 -20
  155. package/lib/src/forms/fields/enum-multiple.js +0 -47
  156. package/lib/src/forms/fields/enum-multiple.test.js +0 -27
  157. package/lib/src/forms/fields/enum.js +0 -39
  158. package/lib/src/forms/fields/enum.test.js +0 -21
  159. package/lib/src/forms/fields/existing-sealious-value.js +0 -16
  160. package/lib/src/forms/fields/field.js +0 -66
  161. package/lib/src/forms/fields/fields.js +0 -16
  162. package/lib/src/forms/fields/file.js +0 -53
  163. package/lib/src/forms/fields/multiple-files.js +0 -15
  164. package/lib/src/forms/fields/number.js +0 -45
  165. package/lib/src/forms/fields/number.test.js +0 -31
  166. package/lib/src/forms/fields/pick-from-list.js +0 -31
  167. package/lib/src/forms/fields/pick-from-list.test.js +0 -17
  168. package/lib/src/forms/fields/proxy-field.js +0 -20
  169. package/lib/src/forms/fields/regexp.js +0 -40
  170. package/lib/src/forms/fields/regexp.test.js +0 -21
  171. package/lib/src/forms/fields/reverse-single-reference.js +0 -14
  172. package/lib/src/forms/fields/simple-form-field.js +0 -19
  173. package/lib/src/forms/fields/structured-array.js +0 -18
  174. package/lib/src/forms/form-types.js +0 -2
  175. package/lib/src/forms/form.js +0 -176
  176. package/lib/src/forms/form.test.js +0 -271
  177. package/lib/src/forms/multiform.js +0 -174
  178. package/lib/src/forms/multiform.test.js +0 -430
  179. package/lib/src/generate-collections.js +0 -52
  180. package/lib/src/generate-components.js +0 -33
  181. package/lib/src/generate-routes.js +0 -75
  182. package/lib/src/hehe.test.js +0 -7
  183. package/lib/src/index.js +0 -19
  184. package/lib/src/make-env.js +0 -14
  185. package/lib/src/make-hidden-inputs.js +0 -14
  186. package/lib/src/mount.js +0 -70
  187. package/lib/src/notifier.js +0 -19
  188. package/lib/src/page/access-control.js +0 -16
  189. package/lib/src/page/default-list-filters.js +0 -40
  190. package/lib/src/page/list.js +0 -184
  191. package/lib/src/page/mountable-with-fields.js +0 -85
  192. package/lib/src/page/mountable.js +0 -5
  193. package/lib/src/page/page.js +0 -26
  194. package/lib/src/page/props-parser.js +0 -23
  195. package/lib/src/page/sealious-list.js +0 -59
  196. package/lib/src/page/stateful-page.js +0 -97
  197. package/lib/src/run.js +0 -2
  198. package/lib/src/sample-index.js +0 -3
  199. package/lib/src/sample-lib.js +0 -6
  200. package/lib/src/sanitize.js +0 -10
  201. package/lib/src/templates/collection.js +0 -12
  202. package/lib/src/templates/form.js +0 -57
  203. package/lib/src/templates/jdd-component.js +0 -39
  204. package/lib/src/templates/list.js +0 -139
  205. package/lib/src/templates/long-running-process.js +0 -60
  206. package/lib/src/templates/multiform.js +0 -55
  207. package/lib/src/templates/page.js +0 -23
  208. package/lib/src/templates/post.js +0 -22
  209. package/lib/src/templates/redirect.js +0 -23
  210. package/lib/src/templates/route-test.js +0 -54
  211. package/lib/src/templates/stateful-page.js +0 -66
  212. package/lib/src/templates/templates.js +0 -21
  213. package/lib/src/test_utils/locator_is_visible.js +0 -11
  214. package/lib/src/utils/assert-throws.js +0 -17
  215. package/lib/src/utils/base64.js +0 -7
  216. package/lib/src/utils/browser-creator.js +0 -10
  217. package/lib/src/utils/escape-url-params.js +0 -14
  218. package/lib/src/utils/exec.js +0 -22
  219. package/lib/src/utils/extract-fields-from-collection.js +0 -26
  220. package/lib/src/utils/format-external-url.js +0 -11
  221. package/lib/src/utils/import-path.js +0 -16
  222. package/lib/src/utils/input-wrapper.js +0 -15
  223. package/lib/src/utils/list-collections.js +0 -13
  224. package/lib/src/utils/make-slug.js +0 -6
  225. package/lib/src/utils/natural-numbers.js +0 -6
  226. package/lib/src/utils/prettier.js +0 -10
  227. package/lib/src/utils/question.js +0 -19
  228. package/lib/src/utils/render-attributes.js +0 -19
  229. package/lib/src/utils/sleep.js +0 -4
  230. package/lib/src/utils/translate.js +0 -6
  231. package/lib/src/utils/url-with-new-params.js +0 -5
  232. package/lib/src/utils/utils.js +0 -16
  233. package/lib/src/utils/walk.js +0 -23
  234. package/lib/src/vitest.config.js +0 -20
  235. package/lib/templates/collection.js +0 -12
  236. package/lib/templates/form.js +0 -57
  237. package/lib/templates/jdd-component.js +0 -39
  238. package/lib/templates/list.js +0 -139
  239. package/lib/templates/long-running-process.js +0 -60
  240. package/lib/templates/multiform.js +0 -55
  241. package/lib/templates/page.js +0 -23
  242. package/lib/templates/post.js +0 -22
  243. package/lib/templates/redirect.js +0 -23
  244. package/lib/templates/route-test.js +0 -54
  245. package/lib/templates/stateful-page.js +0 -66
  246. package/lib/templates/templates.js +0 -21
  247. package/lib/test_utils/locator_is_visible.js +0 -11
  248. package/lib/utils/assert-throws.js +0 -17
  249. package/lib/utils/base64.js +0 -7
  250. package/lib/utils/browser-creator.js +0 -10
  251. package/lib/utils/escape-url-params.js +0 -14
  252. package/lib/utils/exec.js +0 -22
  253. package/lib/utils/extract-fields-from-collection.js +0 -26
  254. package/lib/utils/format-external-url.js +0 -11
  255. package/lib/utils/import-path.js +0 -16
  256. package/lib/utils/input-wrapper.js +0 -15
  257. package/lib/utils/list-collections.js +0 -13
  258. package/lib/utils/make-slug.js +0 -6
  259. package/lib/utils/natural-numbers.js +0 -6
  260. package/lib/utils/prettier.js +0 -10
  261. package/lib/utils/question.js +0 -19
  262. package/lib/utils/render-attributes.js +0 -19
  263. package/lib/utils/sleep.js +0 -4
  264. package/lib/utils/translate.js +0 -6
  265. package/lib/utils/url-with-new-params.js +0 -5
  266. package/lib/utils/utils.js +0 -16
  267. package/lib/utils/walk.js +0 -23
  268. package/lib/vitest.config.js +0 -22
@@ -1,174 +0,0 @@
1
- import { is, predicates } from "@sealcode/ts-predicates";
2
- import { tempstream } from "tempstream";
3
- import { MountableWithFields } from "../page/mountable-with-fields.js";
4
- import { attribute } from "../sanitize.js";
5
- const FIELD_PREFIX_SEPARATOR = "___";
6
- export class Multiform extends MountableWithFields {
7
- constructor() {
8
- super(...arguments);
9
- this.controls = [];
10
- }
11
- init() {
12
- super.init();
13
- for (const [key, form] of Object.entries(this.forms)) {
14
- if (key !== attribute(key)) {
15
- throw new Error(`Form name "${key}" is not url-safe. Try: "${attribute(key)}"`);
16
- }
17
- form.makeOpenFormTag = () => `<div>`;
18
- form.makeCloseFormTag = () => `</div>`;
19
- form.field_names_prefix = key + FIELD_PREFIX_SEPARATOR;
20
- form.form_id = this.name;
21
- form.action = "./" + key;
22
- form.init();
23
- form.extractRawValues = async (context) => this.getSubformRawValues(context, key);
24
- const submit_button_id = this.name + "_" + key + "_submit";
25
- form.makeSubmitButton = () => /* HTML */ `<input
26
- type="submit"
27
- value="${form.submitButtonText}"
28
- formaction="${form.action}"
29
- id="${submit_button_id}"
30
- ${form.form_id ? `form="${form.form_id}"` : ""}
31
- /> `;
32
- }
33
- for (const form of Object.values(this.forms)) {
34
- for (const field of Object.values(form.fields)) {
35
- if (field.name.includes(FIELD_PREFIX_SEPARATOR)) {
36
- throw new Error(`A field name within multiform cannot contain '${FIELD_PREFIX_SEPARATOR}'`);
37
- }
38
- }
39
- }
40
- }
41
- async extractRawValues(ctx) {
42
- return ctx.$body || {};
43
- }
44
- async canAccess() {
45
- return {
46
- canAccess: true,
47
- message: "this view includes multiple forms and each of them have their unique access rules",
48
- };
49
- }
50
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
- getSubformsToRender(ctx) {
52
- const requested_frame = ctx.headers["turbo-frame"];
53
- if (!is(requested_frame, predicates.or(predicates.undefined, predicates.string))) {
54
- throw new Error("Wrong turbo-frame header value type");
55
- }
56
- const forms_to_render = requested_frame && this.forms[requested_frame]
57
- ? [[requested_frame, this.forms[requested_frame]]]
58
- : Object.entries(this.forms);
59
- return forms_to_render;
60
- }
61
- async renderSubform(ctx, sub_form_name, show_field_errors) {
62
- const form = this.forms[sub_form_name];
63
- const result = await form.canAccess(ctx);
64
- if (!result.canAccess) {
65
- return result.message;
66
- }
67
- return form.render(ctx, {
68
- raw_values: await this.getSubformRawValues(ctx, sub_form_name),
69
- messages: [],
70
- }, show_field_errors);
71
- }
72
- async getSubformRawValues(ctx, sub_form_name) {
73
- const result = Object.fromEntries(Object.entries(await this.extractRawValues(ctx))
74
- .filter(([key]) => key.startsWith(sub_form_name + FIELD_PREFIX_SEPARATOR))
75
- .map(([key, value]) => [
76
- key.slice((sub_form_name + FIELD_PREFIX_SEPARATOR).length),
77
- value,
78
- ]));
79
- return result;
80
- }
81
- async render(ctx, messages, prerenderedForms = {}, show_field_errors) {
82
- return tempstream /* HTML */ `${this.renderMessages(ctx, {
83
- raw_values: {},
84
- messages,
85
- })}
86
- <div class="forms">
87
- <form
88
- id="${this.name}"
89
- novalidate
90
- ${
91
- /* novalidate is here because all the subforms are actually one form and errors in one will prevent submitting all of the forms */ ""}
92
- method="POST"
93
- ></form>
94
- ${this.getSubformsToRender(ctx).map(([form_name]) => {
95
- const frame_form_id = this.name + "_" + form_name + "_frame_form";
96
- return tempstream /* HTML */ `<turbo-frame
97
- id="${form_name}"
98
- contains-subform
99
- subform-id="${frame_form_id}"
100
- >
101
- ${prerenderedForms[form_name] ||
102
- this.renderSubform(ctx, form_name, show_field_errors)}
103
- <form id="${frame_form_id}" method="POST"></form>
104
- </turbo-frame>`;
105
- })}
106
- </div>
107
- ${this.makeBottomScript()}`;
108
- }
109
- makeBottomScript() {
110
- // this script assigns each field to its corresponding form, instead of
111
- // the html-only version where all fields are attached to one meta-form
112
- return /* HTML */ ` <script>
113
- (function () {
114
- if (!window.subform_handlers) {
115
- window.subform_handlers = {};
116
- }
117
- if (window.subform_handlers["${this.name}"]) {
118
- return;
119
- }
120
- const handler = () => {
121
- document
122
- .querySelectorAll("turbo-frame[contains-subform]")
123
- .forEach((frame) => {
124
- frame_form_id = frame.getAttribute("subform-id");
125
- frame.querySelectorAll("input").forEach((input) => {
126
- input.setAttribute("form", frame_form_id);
127
- });
128
- });
129
- };
130
- window.subform_handlers["${this.name}"] = handler;
131
- document.documentElement.addEventListener(
132
- "turbo:load",
133
- handler
134
- );
135
- document.documentElement.addEventListener(
136
- "turbo:frame-render",
137
- handler
138
- );
139
- })();
140
- </script>`;
141
- }
142
- mount(router, path) {
143
- router.get(path, async (ctx) => {
144
- ctx.type = "html";
145
- ctx.body = await this.render(ctx, [], {}, false);
146
- });
147
- for (const [key, form] of Object.entries(this.forms)) {
148
- router.post(path + (path.endsWith("/") ? "" : "/") + key, async (ctx) => {
149
- const result = await form.canAccess(ctx);
150
- if (!result.canAccess) {
151
- ctx.body = this.renderError(ctx, {
152
- type: "access",
153
- message: result.message,
154
- });
155
- ctx.status = 403;
156
- return;
157
- }
158
- const reaction = await form.handlePost(ctx);
159
- if (reaction.action == "stay") {
160
- ctx.status = 422;
161
- const form_content = reaction.content;
162
- ctx.body = this.render(ctx, [], {
163
- [key]: form_content,
164
- }, true);
165
- }
166
- else if (reaction.action == "redirect") {
167
- ctx.status = 303;
168
- ctx.redirect(reaction.url);
169
- }
170
- });
171
- }
172
- }
173
- }
174
- //# sourceMappingURL=multiform.js.map
@@ -1,430 +0,0 @@
1
- import Router from "@koa/router";
2
- import Koa from "koa";
3
- import axios from "axios";
4
- import { expect } from "@playwright/test";
5
- import { tempstream } from "tempstream";
6
- import { mount } from "../mount.js";
7
- import { Multiform } from "./multiform.js";
8
- import { assertThrowsAsync } from "../utils/utils.js";
9
- import { form_factory } from "./form.test.js";
10
- import { getBrowser } from "../utils/browser-creator.js";
11
- import { SimpleFormField } from "./fields/simple-form-field.js";
12
- import { Form } from "./form.js";
13
- import { FormHeader } from "./controls/form-header.js";
14
- import { SimpleInput } from "./controls/simple-input.js";
15
- import { EmailField } from "./fields/email.js";
16
- const fields1 = {
17
- email: new SimpleFormField(true),
18
- };
19
- const form1 = new (class extends Form {
20
- constructor() {
21
- super(...arguments);
22
- this.defaultSuccessMessage = "Form1 done!";
23
- this.controls = [new FormHeader("form1"), new SimpleInput(fields1.email)];
24
- this.fields = fields1;
25
- }
26
- onSubmit() {
27
- return;
28
- }
29
- })();
30
- const fields2 = {
31
- name: new SimpleFormField(true),
32
- };
33
- const form2 = new (class extends Form {
34
- constructor() {
35
- super(...arguments);
36
- this.defaultSuccessMessage = "Form2 done!";
37
- this.controls = [new FormHeader("form2"), new SimpleInput(fields2.name)];
38
- this.fields = fields2;
39
- }
40
- onSubmit() {
41
- return;
42
- }
43
- })();
44
- function multiform_factory(canAccessFun1, canAccessFun2) {
45
- return new (class extends Multiform {
46
- constructor() {
47
- super(...arguments);
48
- this.name = "multiform_test";
49
- this.forms = {
50
- form1: form_factory(canAccessFun1),
51
- form2: form_factory(canAccessFun2),
52
- };
53
- }
54
- async render(...args) {
55
- return tempstream /* HTML */ `<!DOCTYPE html>
56
- <html>
57
- <head>
58
- <title>Multiform Test - Sealgen</title>
59
- <script type="module">
60
- import hotwiredTurbo from "https://cdn.skypack.dev/pin/@hotwired/turbo@v7.0.0-9XNv1By6uiqRlBzQLO2d/mode=imports,min/optimized/@hotwired/turbo.js";
61
- </script>
62
- </head>
63
- <body>
64
- ${super.render(...args)}
65
- </body>
66
- </html>`;
67
- }
68
- })();
69
- }
70
- async function tests(js_enabled) {
71
- let page;
72
- beforeAll(async () => {
73
- const browser = await getBrowser();
74
- const context = await browser.newContext({
75
- javaScriptEnabled: js_enabled,
76
- });
77
- page = await context.newPage();
78
- await page.goto("http://localhost:8080");
79
- await page.getByLabel("email").click();
80
- await page.getByLabel("email").fill("sample1");
81
- await page.getByLabel("name").click();
82
- await page.getByLabel("name").fill("sample2");
83
- await page.locator("#multiform_test_form1_submit").click();
84
- });
85
- it("checking whether only one submit handler is run", async () => {
86
- await page.getByText("Form1 done!").click();
87
- await assertThrowsAsync(async () => {
88
- return page.getByText("Form2 done!").click({ timeout: 500 });
89
- });
90
- });
91
- it("checking whether the input in the not submitted form prevails", async () => {
92
- await expect(page.getByLabel("name")).toHaveValue("sample2");
93
- });
94
- }
95
- async function general_form_validation_e2e_tests(js_enabled) {
96
- let browser;
97
- let page;
98
- browser = await getBrowser();
99
- const context = await browser.newContext({
100
- javaScriptEnabled: js_enabled,
101
- });
102
- page = await context.newPage();
103
- await page.goto("http://localhost:8080");
104
- await page.getByPlaceholder("text").click();
105
- await page.getByPlaceholder("text").fill("incorrect");
106
- await page.getByPlaceholder("password").click();
107
- await page.getByPlaceholder("password").fill("test");
108
- await page.locator("#multiform_test_form2_submit").click();
109
- await assertThrowsAsync(async () => {
110
- await page.getByText("Incorrect input").click({ timeout: 500 });
111
- });
112
- }
113
- async function individual_field_validation_e2e_tests(javaScriptEnabled) {
114
- let browser;
115
- let page;
116
- beforeAll(async () => {
117
- browser = await getBrowser();
118
- const context = await browser.newContext({
119
- javaScriptEnabled,
120
- });
121
- page = await context.newPage();
122
- await page.goto("http://localhost:8080");
123
- });
124
- it("validation message shows when incorrect input is given", async () => {
125
- await page.getByPlaceholder("text").click();
126
- await page.getByPlaceholder("text").fill("notanemail");
127
- await page.locator("#multiform_test_form1_submit").click();
128
- await page.getByText("Please enter a proper email address").click();
129
- });
130
- it("validation message doesn't show when correct input is given", async () => {
131
- await page.getByPlaceholder("text").click();
132
- await page.getByPlaceholder("text").fill("yes@an.email");
133
- await page.locator("#multiform_test_form1_submit").click();
134
- assertThrowsAsync(async () => {
135
- return page.getByText("Please enter a proper email address").click({ timeout: 500 });
136
- });
137
- });
138
- }
139
- describe("multiform test", () => {
140
- describe("basic tests", async () => {
141
- let server;
142
- beforeAll(async () => {
143
- const app = new Koa();
144
- const router = new Router();
145
- mount(router, "/", new (class extends Multiform {
146
- constructor() {
147
- super(...arguments);
148
- this.name = "multiform_test";
149
- this.forms = { form1, form2 };
150
- }
151
- async render(ctx, messages, prerenderedForms, show_field_errors = true) {
152
- return tempstream /* HTML */ `<!DOCTYPE html>
153
- <html>
154
- <head>
155
- <title>Multiform Test - Sealgen</title>
156
- <script type="module">
157
- import hotwiredTurbo from "https://cdn.skypack.dev/pin/@hotwired/turbo@v7.0.0-9XNv1By6uiqRlBzQLO2d/mode=imports,min/optimized/@hotwired/turbo.js";
158
- </script>
159
- </head>
160
- <body>
161
- ${super.render(ctx, messages, prerenderedForms, show_field_errors)}
162
- </body>
163
- </html>`;
164
- }
165
- })(), true);
166
- app.use(router.routes()).use(router.allowedMethods());
167
- server = app.listen(8080);
168
- });
169
- afterAll(() => {
170
- server.close();
171
- });
172
- describe("turbolinks + js enabled", async () => tests(true));
173
- describe("turbolinks + js disabled", async () => tests(false));
174
- });
175
- describe("canAccess", async () => {
176
- let page;
177
- let server;
178
- describe("allow access to both forms when both canAccess return true", async () => {
179
- beforeAll(async () => {
180
- const app = new Koa();
181
- const router = new Router();
182
- mount(router, "/", multiform_factory(async (ctx) => {
183
- return { canAccess: true, message: "" };
184
- }, async (ctx) => {
185
- return { canAccess: true, message: "" };
186
- }), true);
187
- app.use(router.routes()).use(router.allowedMethods());
188
- server = app.listen(8080);
189
- const browser = await getBrowser();
190
- const context = await browser.newContext();
191
- page = await context.newPage();
192
- });
193
- afterAll(async () => {
194
- server.close();
195
- });
196
- it("check wether it renders", async () => {
197
- const response = await page.goto("http://localhost:8080");
198
- if (response?.status() != 200) {
199
- throw new Error(`Should return 200 status and it returns ${response?.status()}`);
200
- }
201
- await page.locator("#form1").getByText("This is a test:").click();
202
- await page.locator("#form2").getByText("This is a test:").click();
203
- });
204
- it("check wether you can submit through http (axios)", async () => {
205
- await axios.post("http://localhost:8080/form2", {
206
- form2__text: "pass",
207
- }, {
208
- validateStatus: (status) => {
209
- if (status == 422)
210
- return true;
211
- return false;
212
- },
213
- });
214
- });
215
- });
216
- describe("deny access to both forms", async () => {
217
- beforeAll(async () => {
218
- const app = new Koa();
219
- const router = new Router();
220
- mount(router, "/", multiform_factory(async (ctx) => {
221
- return { canAccess: false, message: "" };
222
- }, async (ctx) => {
223
- return { canAccess: false, message: "" };
224
- }), true);
225
- app.use(router.routes()).use(router.allowedMethods());
226
- server = app.listen(8080);
227
- const browser = await getBrowser();
228
- const context = await browser.newContext();
229
- page = await context.newPage();
230
- });
231
- afterAll(async () => {
232
- server.close();
233
- });
234
- it("check wether forms didnt render", async () => {
235
- await page.goto("http://localhost:8080");
236
- await assertThrowsAsync(async () => {
237
- return page
238
- .locator("#form1")
239
- .getByText("This is a test:")
240
- .click({ timeout: 300 });
241
- });
242
- });
243
- it("check wether it's possible to submit through http", async () => {
244
- await axios.post("http://localhost:8080/form2", {
245
- form2__text: "pass",
246
- }, {
247
- validateStatus: (status) => {
248
- if (status == 403)
249
- return true;
250
- return false;
251
- },
252
- });
253
- });
254
- });
255
- describe("allow access to one form, deny to the other", async () => {
256
- beforeAll(async () => {
257
- const app = new Koa();
258
- const router = new Router();
259
- mount(router, "/", multiform_factory(async (ctx) => {
260
- return { canAccess: true, message: "" };
261
- }, async (ctx) => {
262
- return { canAccess: false, message: "" };
263
- }), true);
264
- app.use(router.routes()).use(router.allowedMethods());
265
- server = app.listen(8080);
266
- const browser = await getBrowser();
267
- const context = await browser.newContext({});
268
- page = await context.newPage();
269
- });
270
- afterAll(async () => {
271
- server.close();
272
- });
273
- it("check wether form1 renders", async () => {
274
- await page.goto("http://localhost:8080");
275
- await page.locator("#form1").getByText("This is a test:").click({ timeout: 300 });
276
- });
277
- it("check wether it's possible to submit to form1 through http", async () => {
278
- await axios.post("http://localhost:8080/form1", {
279
- form1__text: "pass",
280
- }, {
281
- validateStatus: (status) => {
282
- if (status == 422)
283
- return true;
284
- return false;
285
- },
286
- });
287
- });
288
- it("check wether form2 does not render", async () => {
289
- await page.goto("http://localhost:8080");
290
- await assertThrowsAsync(async () => {
291
- return page
292
- .locator("#form2")
293
- .getByText("This is a test:")
294
- .click({ timeout: 300 });
295
- });
296
- });
297
- it("check wether it's possible to submit to form2 through http", async () => {
298
- await axios.post("http://localhost:8080/form2", {
299
- form2__text: "pass",
300
- }, {
301
- validateStatus: (status) => {
302
- if (status == 403)
303
- return true;
304
- return false;
305
- },
306
- });
307
- });
308
- });
309
- });
310
- describe("validation e2e", async () => {
311
- describe("basic tests", async () => {
312
- let server;
313
- beforeAll(async () => {
314
- const app = new Koa();
315
- const router = new Router();
316
- mount(router, "/", new (class extends Multiform {
317
- constructor() {
318
- super(...arguments);
319
- this.name = "multiform_test";
320
- this.forms = {
321
- form1: new (class extends Form {
322
- constructor() {
323
- super(...arguments);
324
- this.fields = fields1;
325
- this.submitButtonText = "Submit";
326
- this.controls = [
327
- new SimpleInput(fields1.email, {
328
- label: "This is a test:",
329
- type: "text",
330
- }),
331
- ];
332
- }
333
- async onSubmit() {
334
- return;
335
- }
336
- async validateValues(ctx, data) {
337
- if (data.email === "incorrect")
338
- return {
339
- valid: false,
340
- error: "Incorrect input",
341
- };
342
- return { valid: true, error: "" };
343
- }
344
- })(),
345
- form2: form_factory(),
346
- };
347
- }
348
- async render(...args) {
349
- return tempstream /* HTML */ `<!DOCTYPE html>
350
- <html>
351
- <head>
352
- <title>Multiform Test - Sealgen</title>
353
- <script type="module">
354
- import hotwiredTurbo from "https://cdn.skypack.dev/pin/@hotwired/turbo@v7.0.0-9XNv1By6uiqRlBzQLO2d/mode=imports,min/optimized/@hotwired/turbo.js";
355
- </script>
356
- </head>
357
- <body>
358
- ${super.render(...args)}
359
- </body>
360
- </html>`;
361
- }
362
- })(), true);
363
- app.use(router.routes()).use(router.allowedMethods());
364
- server = app.listen(8080);
365
- });
366
- afterAll(async () => {
367
- server.close();
368
- });
369
- it("js enabled", async () => general_form_validation_e2e_tests(true));
370
- it("js disabled", async () => general_form_validation_e2e_tests(false));
371
- });
372
- describe("field specific validation", async () => {
373
- let server;
374
- beforeAll(async () => {
375
- const app = new Koa();
376
- const router = new Router();
377
- const fields = {
378
- text: new EmailField(true),
379
- };
380
- mount(router, "/", new (class extends Multiform {
381
- constructor() {
382
- super(...arguments);
383
- this.name = "multiform_test";
384
- this.forms = {
385
- form1: new (class extends Form {
386
- constructor() {
387
- super(...arguments);
388
- this.fields = fields;
389
- this.submitButtonText = "Submit";
390
- this.controls = [
391
- new SimpleInput(fields.text, {
392
- label: "This is a test:",
393
- type: "text",
394
- }),
395
- ];
396
- }
397
- async onSubmit() {
398
- return;
399
- }
400
- })(),
401
- form2: form_factory(),
402
- };
403
- }
404
- async render(...args) {
405
- return tempstream /* HTML */ `<!DOCTYPE html>
406
- <html>
407
- <head>
408
- <title>Multiform Test - Sealgen</title>
409
- <script type="module">
410
- import hotwiredTurbo from "https://cdn.skypack.dev/pin/@hotwired/turbo@v7.0.0-9XNv1By6uiqRlBzQLO2d/mode=imports,min/optimized/@hotwired/turbo.js";
411
- </script>
412
- </head>
413
- <body>
414
- ${super.render(...args)}
415
- </body>
416
- </html>`;
417
- }
418
- })(), true);
419
- app.use(router.routes()).use(router.allowedMethods());
420
- server = app.listen(8080);
421
- });
422
- afterAll(async () => {
423
- server.close();
424
- });
425
- describe("js enabled", async () => individual_field_validation_e2e_tests(true));
426
- describe("js disabled", async () => individual_field_validation_e2e_tests(false));
427
- });
428
- });
429
- });
430
- //# sourceMappingURL=multiform.test.js.map
@@ -1,52 +0,0 @@
1
- import _locreq from "locreq";
2
- import * as prettier from "prettier";
3
- import { promises as fs } from "fs";
4
- import { assertType, predicates } from "@sealcode/ts-predicates";
5
- import { getPrettierConfig } from "./utils/prettier.js";
6
- const target_locreq = _locreq(process.cwd());
7
- export async function extractCollectionClassname(full_file_path) {
8
- const file_content = await fs.readFile(full_file_path, "utf-8");
9
- const result = /export default class (\w+)/.exec(file_content);
10
- if (result === null) {
11
- throw new Error("Missing 'export default class' statement?");
12
- }
13
- return assertType(result[1], predicates.string, `Missing export default class in '${full_file_path}'?`);
14
- }
15
- export async function generateCollections() {
16
- const collections_dir = target_locreq.resolve("src/back/collections");
17
- const files = (await fs.readdir(collections_dir)).filter((f) => !/\.(sub)?test\./.exec(f) &&
18
- f != "collections.ts" &&
19
- !f.includes(".#") &&
20
- f.endsWith(".ts"));
21
- const file_data = await Promise.all(files.map(async (file) => {
22
- const full_path = target_locreq.resolve("src/back/collections/" + file);
23
- const class_name = await extractCollectionClassname(full_path);
24
- return {
25
- class_name,
26
- file,
27
- full_path,
28
- urlname: file.replace(".ts", ""),
29
- };
30
- }));
31
- const content = `// DO NOT EDIT! This file is generated automaticaly with 'npm run generate-collections'
32
- import { App } from "sealious";
33
-
34
- ${file_data
35
- .map(({ class_name, urlname }) => `import _${class_name} from "./${urlname}.js";`)
36
- .join("\n")}
37
-
38
- ${file_data
39
- .map(({ class_name }) => `export const ${class_name} = new _${class_name}();`)
40
- .join("\n")}
41
-
42
- export const collections = {
43
- ...App.BaseCollections,
44
- ${file_data
45
- .map(({ class_name, urlname }) => ` "${urlname}": ${class_name},`)
46
- .join("\n")}
47
- };`;
48
- await fs.writeFile(target_locreq.resolve("src/back/collections/collections.ts"), prettier.format(content, await getPrettierConfig()));
49
- // eslint-disable-next-line no-console
50
- console.log("Successfuly generated new src/back/collections/collections.ts file");
51
- }
52
- //# sourceMappingURL=generate-collections.js.map
@@ -1,33 +0,0 @@
1
- import _locreq from "locreq";
2
- import * as prettier from "prettier";
3
- import { promises as fs } from "fs";
4
- import { getPrettierConfig } from "./utils/prettier.js";
5
- import recursive from "recursive-readdir";
6
- import path from "path";
7
- import { toKebabCase, toPascalCase } from "js-convert-case";
8
- const target_locreq = _locreq(process.cwd());
9
- export async function generateComponents() {
10
- const components_dir = target_locreq.resolve("src/back/jdd-components");
11
- const component_names = (await recursive(components_dir)).filter((c) => c.endsWith(".jdd.tsx"));
12
- const component_data = component_names
13
- .map((p) => "./" +
14
- path.relative(components_dir, p).replace(/\.[tj]sx?$/, ".js"))
15
- .map((relative_path) => {
16
- const name = relative_path.match(/\/([^\/]+).jdd/)?.[1];
17
- return { name, relative_path };
18
- });
19
- const content = `// DO NOT EDIT! This file is generated automaticaly with 'npm run generate-components'
20
- import { Registry } from "@sealcode/jdd";
21
-
22
- export const registry = new Registry();
23
- ${component_data
24
- .map((c) => `
25
- import { ${toPascalCase(c.name)} } from "${c.relative_path}";
26
- registry.add("${toKebabCase(c.name)}", ${toPascalCase(c.name)});`)
27
- .join("\n")}`;
28
- const target = "src/back/jdd-components/components.ts";
29
- await fs.writeFile(target_locreq.resolve(target), prettier.format(content, await getPrettierConfig()));
30
- // eslint-disable-next-line no-console
31
- console.log(`Successfuly generated new ${target} file`);
32
- }
33
- //# sourceMappingURL=generate-components.js.map