@sealcode/sealgen 0.14.10 → 0.14.12

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.
@@ -1,13 +1,13 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
- import { ChekboxedListField } from "../fields/checkboxed-list.js";
2
+ import { CheckboxedListField } from "../fields/checkboxed-list.js";
3
3
  import { FormControlContext } from "./form-control.js";
4
4
  import { FormFieldControl } from "./form-field-control.js";
5
5
  export declare class CheckboxedListInput extends FormFieldControl {
6
- field: ChekboxedListField<boolean>;
6
+ field: CheckboxedListField<boolean>;
7
7
  options: {
8
8
  label: string;
9
9
  };
10
- constructor(field: ChekboxedListField<boolean>, options?: {
10
+ constructor(field: CheckboxedListField<boolean>, options?: {
11
11
  label: string;
12
12
  });
13
13
  render(fctx: FormControlContext): Promise<import("stream").Readable>;
@@ -1,15 +1,17 @@
1
1
  import { Context } from "koa";
2
2
  import { FormDataValue } from "../form-types.js";
3
3
  import { FieldParseResult, FormField, FormFieldValidationResponse } from "./field.js";
4
- export declare class ChekboxedListField<Required extends boolean> extends FormField<Required, Record<string, "on">> {
4
+ export declare class CheckboxedListField<Required extends boolean> extends FormField<Required, Record<string, "on">> {
5
5
  required: Required;
6
- generateOptions: (ctx: Context) => Promise<Record<string, string> | {
7
- [i: string]: string;
8
- }>;
6
+ generateOptions: (ctx: Context) => Promise<{
7
+ value: string;
8
+ label?: string;
9
+ }[]>;
9
10
  isVisible: (ctx: Context) => Promise<boolean>;
10
- constructor(required: Required, generateOptions: (ctx: Context) => Promise<Record<string, string> | {
11
- [i: string]: string;
12
- }>, isVisible?: (ctx: Context) => Promise<boolean>);
11
+ constructor(required: Required, generateOptions: (ctx: Context) => Promise<{
12
+ value: string;
13
+ label?: string;
14
+ }[]>, isVisible?: (ctx: Context) => Promise<boolean>);
13
15
  predicate: (v: unknown, w: unknown) => {
14
16
  readonly match: boolean;
15
17
  readonly wildcard: string[];
@@ -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 { FormFieldControl } from "./form-field-control.js";
@@ -9,20 +8,18 @@ class CheckboxedListInput extends FormFieldControl {
9
8
  this.options = options;
10
9
  }
11
10
  async render(fctx) {
12
- const { parsed: pickedValues } = await this.field.getValue(
11
+ const { parsed: currentValue } = await this.field.getValue(
13
12
  fctx.ctx,
14
13
  fctx.data
15
14
  );
16
- if (!is(pickedValues, predicates.array(predicates.string))) {
17
- throw new Error("picked values is not an array of strings");
18
- }
15
+ const pickedValues = Object.entries(currentValue).filter(([, is_on]) => is_on).map(([key]) => key);
19
16
  const [options, isVisible] = await Promise.all([
20
17
  this.field.generateOptions(fctx.ctx),
21
18
  this.field.isVisible(fctx.ctx)
22
19
  ]);
23
20
  const { name, required } = this.field;
24
- return tempstream`${isVisible ? Object.entries(options).map(
25
- ([value, text]) => inputWrapper(
21
+ return tempstream`${isVisible ? options.map(
22
+ ({ value, label }) => inputWrapper(
26
23
  [name, getRequiredClass(required)],
27
24
  /* HTML */
28
25
  `
@@ -31,8 +28,11 @@ class CheckboxedListInput extends FormFieldControl {
31
28
  id="${name}.${value}"
32
29
  name="${name}.${value}"
33
30
  ${pickedValues.includes(value) ? "checked" : ""}
31
+ form=${fctx.form_id}
34
32
  />
35
- <label for="${name}.${value}">${text}</label>
33
+ <label for="${name}.${value}"
34
+ >${label || value}</label
35
+ >
36
36
  `
37
37
  )
38
38
  ) : ""}`;
@@ -0,0 +1,62 @@
1
+ import Router from "@koa/router";
2
+ import getPort from "get-port";
3
+ import Koa from "koa";
4
+ import { mount } from "../../mount.js";
5
+ import { CheckboxedListField } from "../fields/checkboxed-list.js";
6
+ import { Form } from "../form.js";
7
+ import { CheckboxedListInput } from "./checkboxed-list-input.js";
8
+ import { getBrowser } from "../../utils/browser-creator.js";
9
+ describe.only("checkboxed-list", () => {
10
+ describe("basic tests", async () => {
11
+ let server;
12
+ let browser;
13
+ let page;
14
+ afterAll(() => {
15
+ server.close();
16
+ });
17
+ it("sends the values", async () => {
18
+ const port = await getPort();
19
+ console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
20
+ const app = new Koa();
21
+ const router = new Router();
22
+ const fields = {
23
+ syllables: new CheckboxedListField(true, async () => {
24
+ return ["sa", "mple", "co", "de"].map((s) => ({
25
+ value: s,
26
+ label: s.toLocaleUpperCase()
27
+ }));
28
+ })
29
+ };
30
+ let received_values;
31
+ mount(
32
+ router,
33
+ "/",
34
+ new class extends Form {
35
+ constructor() {
36
+ super(...arguments);
37
+ this.fields = fields;
38
+ this.controls = [new CheckboxedListInput(fields.syllables)];
39
+ }
40
+ async onSubmit(ctx) {
41
+ received_values = await this.getParsedValues(ctx);
42
+ }
43
+ async canAccess(_) {
44
+ return { canAccess: true, message: "" };
45
+ }
46
+ }(),
47
+ true
48
+ );
49
+ app.use(router.routes()).use(router.allowedMethods());
50
+ server = app.listen(port);
51
+ browser = await getBrowser();
52
+ const context = await browser.newContext();
53
+ page = await context.newPage();
54
+ await page.goto(`http://localhost:${port}`);
55
+ await page.getByLabel("CO").check();
56
+ await page.getByLabel("DE").check();
57
+ await page.getByRole("button", { name: "Wy\u015Blij" }).click();
58
+ assert.deepStrictEqual(received_values, { syllables: { co: "on", de: "on" } });
59
+ });
60
+ });
61
+ });
62
+ //# sourceMappingURL=checkboxed-list-input.test.js.map
@@ -2,7 +2,7 @@ import { is, predicates } from "@sealcode/ts-predicates";
2
2
  import {
3
3
  FormField
4
4
  } from "./field.js";
5
- class ChekboxedListField extends FormField {
5
+ class CheckboxedListField extends FormField {
6
6
  constructor(required, generateOptions, isVisible = () => Promise.resolve(true)) {
7
7
  super(required);
8
8
  this.required = required;
@@ -44,6 +44,6 @@ class ChekboxedListField extends FormField {
44
44
  }
45
45
  }
46
46
  export {
47
- ChekboxedListField
47
+ CheckboxedListField
48
48
  };
49
49
  //# sourceMappingURL=checkboxed-list.js.map
@@ -25,10 +25,10 @@ function generateURL(actionName, url) {
25
25
  const parts = url.split("/");
26
26
  const params = parts.filter((part) => part.startsWith(":")).map((part) => part.slice(1));
27
27
  if (params.length === 0) {
28
- return `export const ${actionName}URL = "${url}";`;
28
+ return `export const ${actionName}URL = "${encodeURI(url)}";`;
29
29
  }
30
30
  return `export const ${actionName}URL = (${params.map((s) => s + ": string").join(", ")})=>\`${parts.map(
31
- (part) => part.startsWith(":") ? "${" + part.slice(1) + "}" : part
31
+ (part) => part.startsWith(":") ? "${" + part.slice(1) + "}" : encodeURIComponent(part)
32
32
  ).join("/")}\`;
33
33
  ${actionName}URL.params = [${params.map((param) => `"${param}"`).join(",")}];
34
34
  ${actionName}URL.rawURL = "${url}";`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sealcode/sealgen",
3
- "version": "0.14.10",
3
+ "version": "0.14.12",
4
4
  "description": "Module to automate adding routes and collections to a sealious application",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -0,0 +1,70 @@
1
+ import Router from "@koa/router";
2
+ import getPort from "get-port";
3
+ import { Browser, Page } from "playwright";
4
+ import type { Context } from "koa";
5
+ import Koa from "koa";
6
+ import { mount } from "../../mount.js";
7
+ import { CheckboxedListField } from "../fields/checkboxed-list.js";
8
+ import { Form } from "../form.js";
9
+ import { CheckboxedListInput } from "./checkboxed-list-input.js";
10
+ import { getBrowser } from "../../utils/browser-creator.js";
11
+ import { sleep } from "../../utils/sleep.js";
12
+
13
+ describe.only("checkboxed-list", () => {
14
+ describe("basic tests", async () => {
15
+ let server: ReturnType<Koa["listen"]>;
16
+ let browser: Browser;
17
+ let page: Page;
18
+
19
+ afterAll(() => {
20
+ server.close();
21
+ });
22
+
23
+ it("sends the values", async () => {
24
+ const port = await getPort();
25
+ console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
26
+ const app = new Koa();
27
+ const router = new Router();
28
+
29
+ const fields = {
30
+ syllables: new CheckboxedListField(true, async () => {
31
+ return ["sa", "mple", "co", "de"].map((s) => ({
32
+ value: s,
33
+ label: s.toLocaleUpperCase(),
34
+ }));
35
+ }),
36
+ };
37
+
38
+ let received_values: unknown;
39
+
40
+ mount(
41
+ router,
42
+ "/",
43
+ new (class extends Form<typeof fields, unknown> {
44
+ fields = fields;
45
+ controls = [new CheckboxedListInput(fields.syllables)];
46
+
47
+ async onSubmit(ctx: Context) {
48
+ received_values = await this.getParsedValues(ctx);
49
+ }
50
+
51
+ async canAccess(_: Context) {
52
+ return { canAccess: true, message: "" };
53
+ }
54
+ })(),
55
+ true
56
+ );
57
+ app.use(router.routes()).use(router.allowedMethods());
58
+ server = app.listen(port);
59
+
60
+ browser = await getBrowser();
61
+ const context = await browser.newContext();
62
+ page = await context.newPage();
63
+ await page.goto(`http://localhost:${port}`);
64
+ await page.getByLabel("CO").check();
65
+ await page.getByLabel("DE").check();
66
+ await page.getByRole("button", { name: "Wyślij" }).click();
67
+ assert.deepStrictEqual(received_values, { syllables: { co: "on", de: "on" } });
68
+ });
69
+ });
70
+ });
@@ -1,35 +1,34 @@
1
1
  import { is, predicates } from "@sealcode/ts-predicates";
2
2
  import { tempstream } from "tempstream";
3
3
  import { getRequiredClass, inputWrapper } from "../../utils/input-wrapper.js";
4
- import { ChekboxedListField } from "../fields/checkboxed-list.js";
4
+ import { CheckboxedListField } from "../fields/checkboxed-list.js";
5
5
  import { FormControlContext } from "./form-control.js";
6
6
  import { FormFieldControl } from "./form-field-control.js";
7
7
 
8
8
  export class CheckboxedListInput extends FormFieldControl {
9
9
  constructor(
10
- public field: ChekboxedListField<boolean>,
10
+ public field: CheckboxedListField<boolean>,
11
11
  public options: { label: string } = { label: field.name }
12
12
  ) {
13
13
  super([field]);
14
14
  }
15
15
 
16
16
  async render(fctx: FormControlContext) {
17
- const { parsed: pickedValues } = await this.field.getValue(
17
+ const { parsed: currentValue } = await this.field.getValue(
18
18
  fctx.ctx,
19
19
  fctx.data
20
20
  );
21
- if (!is(pickedValues, predicates.array(predicates.string))) {
22
- throw new Error("picked values is not an array of strings");
23
- }
21
+ const pickedValues = Object.entries(currentValue)
22
+ .filter(([, is_on]) => is_on)
23
+ .map(([key]) => key);
24
24
  const [options, isVisible] = await Promise.all([
25
25
  this.field.generateOptions(fctx.ctx),
26
26
  this.field.isVisible(fctx.ctx),
27
27
  ]);
28
28
 
29
29
  const { name, required } = this.field;
30
-
31
30
  return tempstream/* HTML */ `${isVisible
32
- ? Object.entries(options).map(([value, text]) =>
31
+ ? options.map(({ value, label }) =>
33
32
  inputWrapper(
34
33
  [name, getRequiredClass(required)],
35
34
  /* HTML */ `
@@ -38,8 +37,11 @@ export class CheckboxedListInput extends FormFieldControl {
38
37
  id="${name}.${value}"
39
38
  name="${name}.${value}"
40
39
  ${pickedValues.includes(value) ? "checked" : ""}
40
+ form=${fctx.form_id}
41
41
  />
42
- <label for="${name}.${value}">${text}</label>
42
+ <label for="${name}.${value}"
43
+ >${label || value}</label
44
+ >
43
45
  `
44
46
  )
45
47
  )
@@ -7,7 +7,7 @@ import {
7
7
  FormFieldValidationResponse,
8
8
  } from "./field.js";
9
9
 
10
- export class ChekboxedListField<Required extends boolean> extends FormField<
10
+ export class CheckboxedListField<Required extends boolean> extends FormField<
11
11
  Required,
12
12
  Record<string, "on">
13
13
  > {
@@ -15,7 +15,7 @@ export class ChekboxedListField<Required extends boolean> extends FormField<
15
15
  public required: Required,
16
16
  public generateOptions: (
17
17
  ctx: Context
18
- ) => Promise<Record<string, string> | { [i: string]: string }>,
18
+ ) => Promise<{ value: string; label?: string }[]>,
19
19
  public isVisible: (ctx: Context) => Promise<boolean> = () =>
20
20
  Promise.resolve(true)
21
21
  ) {
@@ -30,13 +30,15 @@ function generateURL(actionName: string, url: string) {
30
30
  .filter((part) => part.startsWith(":"))
31
31
  .map((part) => part.slice(1));
32
32
  if (params.length === 0) {
33
- return `export const ${actionName}URL = "${url}";`;
33
+ return `export const ${actionName}URL = "${encodeURI(url)}";`;
34
34
  }
35
35
  return `export const ${actionName}URL = (${params
36
36
  .map((s) => s + ": string")
37
37
  .join(", ")})=>\`${parts
38
38
  .map((part) =>
39
- part.startsWith(":") ? "${" + part.slice(1) + "}" : part
39
+ part.startsWith(":")
40
+ ? "${" + part.slice(1) + "}"
41
+ : encodeURIComponent(part)
40
42
  )
41
43
  .join("/")}\`;
42
44
  ${actionName}URL.params = [${params