@sealcode/sealgen 0.15.33 → 0.15.35

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 (33) hide show
  1. package/@types/src/forms/controls/controls.d.ts +1 -0
  2. package/@types/src/forms/controls/table.d.ts +15 -0
  3. package/@types/src/forms/fields/fields.d.ts +1 -0
  4. package/@types/src/forms/fields/table.d.ts +12 -0
  5. package/@types/src/templates/shared/collection-create-form.d.ts +2 -0
  6. package/@types/src/templates/shared/collection-edit-form.d.ts +1 -0
  7. package/@types/src/templates/shared/collection-list.d.ts +1 -0
  8. package/@types/src/templates/shared/confirm-item-delete.d.ts +1 -0
  9. package/@types/src/templates/shared/item-delete.d.ts +1 -0
  10. package/@types/src/templates/shared/shared-crud-form-fields.d.ts +44 -0
  11. package/@types/src/utils/utils.d.ts +1 -0
  12. package/@types/src/utils/with-fallback.d.ts +2 -0
  13. package/lib/add-crud.js +131 -0
  14. package/lib/forms/controls/controls.js +1 -0
  15. package/lib/forms/controls/table.js +62 -0
  16. package/lib/forms/fields/fields.js +1 -0
  17. package/lib/forms/fields/table.js +58 -0
  18. package/lib/templates/shared/collection-create-form.js +146 -0
  19. package/lib/templates/shared/collection-edit-form.js +200 -0
  20. package/lib/templates/shared/collection-list.js +211 -0
  21. package/lib/templates/shared/confirm-item-delete.js +72 -0
  22. package/lib/templates/shared/item-delete.js +41 -0
  23. package/lib/templates/shared/shared-crud-form-fields.js +118 -0
  24. package/lib/utils/utils.js +1 -0
  25. package/lib/utils/with-fallback.js +21 -0
  26. package/lib/utils/write-file.js +11 -0
  27. package/package.json +1 -1
  28. package/src/forms/controls/controls.ts +1 -0
  29. package/src/forms/controls/table.ts +78 -0
  30. package/src/forms/fields/fields.ts +1 -0
  31. package/src/forms/fields/table.ts +72 -0
  32. package/src/utils/utils.ts +1 -0
  33. package/src/utils/with-fallback.ts +47 -0
@@ -29,3 +29,4 @@ export * from "./number.js";
29
29
  export * from "./multiple-photos.js";
30
30
  // export * from "./reverse-single-reference";
31
31
  export * from "./array.js";
32
+ export * from "./table.js";
@@ -0,0 +1,78 @@
1
+ import { FlatTemplatable } from "tempstream";
2
+ import { FormField } from "../fields/field.js";
3
+ import { Table as TableField } from "../fields/table.js";
4
+ import { FormControl, FormControlContext } from "./form-control.js";
5
+
6
+ export class Table<F extends Record<string, FormField>> extends FormControl {
7
+ role = <const>"input";
8
+ constructor(
9
+ public table_field: TableField<F>,
10
+ public render_fields: {
11
+ [field_name in keyof F]: (
12
+ fctx: FormControlContext,
13
+ name: string,
14
+ value: string
15
+ ) => string;
16
+ }
17
+ ) {
18
+ super();
19
+ }
20
+
21
+ async render(fctx: FormControlContext): Promise<FlatTemplatable> {
22
+ const { parsed: rows } = await this.table_field.getValue(
23
+ fctx.ctx,
24
+ fctx.data
25
+ );
26
+ if (!rows) {
27
+ return "";
28
+ }
29
+ return /* HTML */ `<div
30
+ class="${[
31
+ "form-input__wrapper",
32
+ "form-input__wrapper--type--table",
33
+ "form-input__wrapper--options-count--" + rows.length.toString(),
34
+ ...(rows.length >= 5
35
+ ? ["form-input__wrapper--options-count--5-or-more"]
36
+ : []),
37
+ ...(rows.length >= 10
38
+ ? ["form-input__wrapper--options-count--10-or-more"]
39
+ : []),
40
+ ...(rows.length >= 15
41
+ ? ["form-input__wrapper--options-count--15-or-more"]
42
+ : []),
43
+ ...(rows.length >= 20
44
+ ? ["form-input__wrapper--options-count--20-or-more"]
45
+ : []),
46
+ ].join(" ")}"
47
+ >
48
+ <div class="table__wrapper">
49
+ <table>
50
+ <tbody>
51
+ <tr>
52
+ ${rows
53
+ ?.map((row, row_index) => {
54
+ return /* HTML */ `<tr>
55
+ ${Object.entries(
56
+ this.table_field.columns
57
+ )
58
+ .map(([key]) => {
59
+ return `<td>${this.render_fields[
60
+ key
61
+ ](
62
+ fctx,
63
+ `${this.table_field.name}[${row_index}][${key}]`,
64
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
65
+ row[key] as string
66
+ )}</td>`;
67
+ })
68
+ .join("")}
69
+ </tr>`;
70
+ })
71
+ .join("")}
72
+ </tr>
73
+ </tbody>
74
+ </table>
75
+ </div>
76
+ </div>`;
77
+ }
78
+ }
@@ -13,3 +13,4 @@ export * from "./file.js";
13
13
  export * from "./multiple-files.js";
14
14
  export * from "./reverse-single-reference.js";
15
15
  export * from "./structured-array.js";
16
+ export * from "./table.js";
@@ -0,0 +1,72 @@
1
+ import { is, predicates } from "@sealcode/ts-predicates";
2
+ import { Context } from "koa";
3
+ import { FormDataValue } from "../form-types.js";
4
+ import { FieldParseResult, FormField } from "./field.js";
5
+
6
+ export type TableFieldParsed<F extends Record<string, FormField>> = {
7
+ [field_name in keyof F]: unknown;
8
+ }[];
9
+
10
+ export class Table<F extends Record<string, FormField>> extends FormField<
11
+ true,
12
+ TableFieldParsed<F>
13
+ > {
14
+ constructor(public columns: F) {
15
+ super(true);
16
+ }
17
+
18
+ getEmptyValue() {
19
+ return [];
20
+ }
21
+
22
+ async parse(
23
+ ctx: Context,
24
+ raw_value: FormDataValue
25
+ ): Promise<FieldParseResult<TableFieldParsed<F>>> {
26
+ // we expect an array-like object: {"0": {...}, ...etc}
27
+ if (!is(raw_value, predicates.object)) {
28
+ return {
29
+ parsable: false,
30
+ error: "Expected an object",
31
+ parsed_value: null,
32
+ };
33
+ }
34
+ const result: { [field_name in keyof F]: unknown }[] = [];
35
+ for (const row_number in raw_value) {
36
+ const row_data = raw_value[row_number];
37
+ const parsed_row: Record<string, unknown> = {};
38
+ if (!is(row_data, predicates.object)) {
39
+ throw new Error(`Expected object, got ${String(row_data)}`);
40
+ }
41
+ for (const key in row_data) {
42
+ const field = this.columns[key];
43
+ if (field == undefined) {
44
+ return {
45
+ parsable: false,
46
+ error: `Unknown column: ${key}`,
47
+ parsed_value: null,
48
+ };
49
+ }
50
+ // eslint-disable-next-line no-await-in-loop, @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
51
+ const parse_result = await field.parse(
52
+ ctx,
53
+ (row_data as any)[key]
54
+ );
55
+ if (!parse_result.parsable) {
56
+ console.debug("table.ts:51");
57
+ return {
58
+ parsable: false,
59
+ error: `Invalid value for row ${row_number}.${key}: ${parse_result.error}`,
60
+ parsed_value: null,
61
+ };
62
+ }
63
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
64
+ parsed_row[key] = parse_result.parsed_value as any;
65
+ }
66
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
67
+ result.push(parsed_row as { [field_name in keyof F]: unknown });
68
+ }
69
+ const ret = { parsed_value: result, parsable: true, error: null };
70
+ return ret as FieldParseResult<TableFieldParsed<F>>;
71
+ }
72
+ }
@@ -23,3 +23,4 @@ export * from "./make-slug.js";
23
23
  export * from "./render-attributes.js";
24
24
  export * from "./format-external-url.js";
25
25
  export * from "./base64.js";
26
+ export * from "./with-fallback.js";
@@ -0,0 +1,47 @@
1
+ // use this to more concisely define values with one or more fallbacks to use when they are null.
2
+
3
+ // If called with two args, the second one has to be non-null
4
+ // if called with three args, the third one has to be non-null
5
+ //
6
+ // in two-arg mode, if the first argument is not null, then it's returned and fallback is not used.
7
+ // if the first argument is null, then the second arg is returned
8
+ //
9
+ // in three-arg mode, the first value is never returned. If the first arg is not-null, then the second arg is returned (if it's not null). Otherwise the third arg is returned
10
+
11
+ export function withFallback<T1, T2 extends NonNullable<unknown>>(
12
+ value1: T1,
13
+ value2: T2
14
+ ): NonNullable<T1> | T2;
15
+ export function withFallback<T1, T2, T3 extends NonNullable<unknown>>(
16
+ value1: T1,
17
+ value2: T2,
18
+ value3?: T3
19
+ ): NonNullable<T1> | NonNullable<T2> | T3;
20
+ export function withFallback<T1, T2, T3 extends NonNullable<unknown>>(
21
+ value1: T1,
22
+ value2: T2,
23
+ value3?: T3
24
+ ): NonNullable<T1> | NonNullable<T2> | T3 {
25
+ if (value3 !== undefined) {
26
+ // three arg mode
27
+ if (
28
+ value1 !== null &&
29
+ value1 !== undefined &&
30
+ value2 !== null &&
31
+ value2 !== undefined
32
+ ) {
33
+ return value2;
34
+ } else {
35
+ return value3;
36
+ }
37
+ } else {
38
+ // two arg mode
39
+ if (value1 !== null && value1 !== undefined) {
40
+ return value1;
41
+ } else if (value2 !== undefined && value2 !== null) {
42
+ return value2;
43
+ } else {
44
+ throw new Error("No suitable fallback: ${arguments}");
45
+ }
46
+ }
47
+ }