@sealcode/sealgen 0.8.47 → 0.8.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/@types/index.d.ts +1 -0
- package/@types/page/stateful-page.d.ts +34 -0
- package/@types/templates/stateful-page.d.ts +1 -0
- package/@types/utils/base64.d.ts +2 -0
- package/@types/utils/utils.d.ts +3 -0
- package/lib/add-route.js +3 -0
- package/lib/cli.js +0 -0
- package/lib/generate-routes.js +2 -1
- package/lib/index.js +1 -0
- package/lib/page/stateful-page.js +117 -0
- package/lib/templates/stateful-page.js +66 -0
- package/lib/utils/base64.js +12 -0
- package/lib/utils/utils.js +6 -1
- package/package.json +2 -1
- package/.arcconfig +0 -12
- package/.arclint +0 -18
- package/.eslintrc.js +0 -38
- package/.mocharc.js +0 -10
- package/.nycrc +0 -6
- package/.prettierrc +0 -21
- package/jenkins.sanity.sh +0 -3
- package/lib/add-collection.js.map +0 -1
- package/lib/add-route.js.map +0 -1
- package/lib/add-route.test.js.map +0 -1
- package/lib/build.js.map +0 -1
- package/lib/cli.js.map +0 -1
- package/lib/components/components.js.map +0 -1
- package/lib/components/tabs.js.map +0 -1
- package/lib/components/toggle-modal.js.map +0 -1
- package/lib/example.test.js.map +0 -1
- package/lib/find-scss-includes.js.map +0 -1
- package/lib/forms/controls/array.js.map +0 -1
- package/lib/forms/controls/autocomplete.js.map +0 -1
- package/lib/forms/controls/big-radio-group.js.map +0 -1
- package/lib/forms/controls/checkbox-group.js.map +0 -1
- package/lib/forms/controls/checkbox.js.map +0 -1
- package/lib/forms/controls/checkboxed-list-input.js.map +0 -1
- package/lib/forms/controls/collapsible-checkbox-group.js.map +0 -1
- package/lib/forms/controls/collapsible-field-group.js.map +0 -1
- package/lib/forms/controls/controls.js.map +0 -1
- package/lib/forms/controls/derived-frame.js.map +0 -1
- package/lib/forms/controls/derived.js.map +0 -1
- package/lib/forms/controls/dropdown.js.map +0 -1
- package/lib/forms/controls/editable-collection-subset.js.map +0 -1
- package/lib/forms/controls/field-group.js.map +0 -1
- package/lib/forms/controls/file.js.map +0 -1
- package/lib/forms/controls/form-control.js.map +0 -1
- package/lib/forms/controls/form-field-control.js.map +0 -1
- package/lib/forms/controls/form-header.js.map +0 -1
- package/lib/forms/controls/form-paragraph.js.map +0 -1
- package/lib/forms/controls/frame.js.map +0 -1
- package/lib/forms/controls/hidden-input.js.map +0 -1
- package/lib/forms/controls/html.js.map +0 -1
- package/lib/forms/controls/multiple-files.js.map +0 -1
- package/lib/forms/controls/multiple-photos.js.map +0 -1
- package/lib/forms/controls/number.js.map +0 -1
- package/lib/forms/controls/photo.js.map +0 -1
- package/lib/forms/controls/radio.js.map +0 -1
- package/lib/forms/controls/reverse-single-reference.js.map +0 -1
- package/lib/forms/controls/simple-input.js.map +0 -1
- package/lib/forms/controls/textarea.js.map +0 -1
- package/lib/forms/controls/tickable.js.map +0 -1
- package/lib/forms/fields/boolean.js.map +0 -1
- package/lib/forms/fields/boolean.test.js.map +0 -1
- package/lib/forms/fields/checkboxed-list.js.map +0 -1
- package/lib/forms/fields/collection-field.js.map +0 -1
- package/lib/forms/fields/email.js.map +0 -1
- package/lib/forms/fields/email.test.js.map +0 -1
- package/lib/forms/fields/enum-multiple.js.map +0 -1
- package/lib/forms/fields/enum-multiple.test.js.map +0 -1
- package/lib/forms/fields/enum.js.map +0 -1
- package/lib/forms/fields/enum.test.js.map +0 -1
- package/lib/forms/fields/existing-sealious-value.js.map +0 -1
- package/lib/forms/fields/field.js.map +0 -1
- package/lib/forms/fields/file.js.map +0 -1
- package/lib/forms/fields/multiple-files.js.map +0 -1
- package/lib/forms/fields/number.js.map +0 -1
- package/lib/forms/fields/number.test.js.map +0 -1
- package/lib/forms/fields/pick-from-list.js.map +0 -1
- package/lib/forms/fields/pick-from-list.test.js.map +0 -1
- package/lib/forms/fields/proxy-field.js.map +0 -1
- package/lib/forms/fields/regexp.js.map +0 -1
- package/lib/forms/fields/regexp.test.js.map +0 -1
- package/lib/forms/fields/reverse-single-reference.js.map +0 -1
- package/lib/forms/fields/simple-form-field.js.map +0 -1
- package/lib/forms/fields/structured-array.js.map +0 -1
- package/lib/forms/form.js.map +0 -1
- package/lib/forms/form.test.js.map +0 -1
- package/lib/forms/multiform.js.map +0 -1
- package/lib/forms/multiform.test.js.map +0 -1
- package/lib/generate-collections.js.map +0 -1
- package/lib/generate-routes.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/make-env.js.map +0 -1
- package/lib/make-hidden-inputs.js.map +0 -1
- package/lib/mount.js.map +0 -1
- package/lib/page/access-control.js.map +0 -1
- package/lib/page/list.js.map +0 -1
- package/lib/page/mountable-with-fields.js.map +0 -1
- package/lib/page/mountable.js.map +0 -1
- package/lib/page/page.js.map +0 -1
- package/lib/page/props-parser.js.map +0 -1
- package/lib/run.js.map +0 -1
- package/lib/sanitize.js.map +0 -1
- package/lib/templates/collection.js.map +0 -1
- package/lib/templates/form.js.map +0 -1
- package/lib/templates/list.js.map +0 -1
- package/lib/templates/multiform.js.map +0 -1
- package/lib/templates/page.js.map +0 -1
- package/lib/templates/post.js.map +0 -1
- package/lib/templates/redirect.js.map +0 -1
- package/lib/templates/route-test.js.map +0 -1
- package/lib/test_utils/locator_is_visible.js.map +0 -1
- package/lib/utils/assert-throws.js.map +0 -1
- package/lib/utils/browser-creator.js.map +0 -1
- package/lib/utils/escape-url-params.js.map +0 -1
- package/lib/utils/exec.js.map +0 -1
- package/lib/utils/format-external-url.js.map +0 -1
- package/lib/utils/import-path.js.map +0 -1
- package/lib/utils/input-wrapper.js.map +0 -1
- package/lib/utils/list-collections.js.map +0 -1
- package/lib/utils/make-slug.js.map +0 -1
- package/lib/utils/natural-numbers.js.map +0 -1
- package/lib/utils/prettier.js.map +0 -1
- package/lib/utils/question.js.map +0 -1
- package/lib/utils/render-attributes.js.map +0 -1
- package/lib/utils/sleep.js.map +0 -1
- package/lib/utils/translate.js.map +0 -1
- package/lib/utils/url-with-new-params.js.map +0 -1
- package/lib/utils/utils.js.map +0 -1
- package/lib/utils/walk.js.map +0 -1
- package/mocha_root_hooks.js +0 -6
- package/src/add-collection.ts +0 -31
- package/src/add-route.test.ts +0 -58
- package/src/add-route.ts +0 -86
- package/src/build.ts +0 -94
- package/src/cli.ts +0 -36
- package/src/components/components.ts +0 -2
- package/src/components/tabs.ts +0 -95
- package/src/components/toggle-modal.ts +0 -52
- package/src/example.test.ts +0 -3
- package/src/find-scss-includes.ts +0 -32
- package/src/forms/controls/array.ts +0 -226
- package/src/forms/controls/autocomplete.ts +0 -33
- package/src/forms/controls/big-radio-group.ts +0 -48
- package/src/forms/controls/checkbox-group.ts +0 -71
- package/src/forms/controls/checkbox.ts +0 -34
- package/src/forms/controls/checkboxed-list-input.ts +0 -50
- package/src/forms/controls/collapsible-checkbox-group.ts +0 -28
- package/src/forms/controls/collapsible-field-group.ts +0 -94
- package/src/forms/controls/controls.ts +0 -30
- package/src/forms/controls/derived-frame.ts +0 -91
- package/src/forms/controls/derived.ts +0 -108
- package/src/forms/controls/dropdown.ts +0 -87
- package/src/forms/controls/editable-collection-subset.ts +0 -97
- package/src/forms/controls/field-group.ts +0 -69
- package/src/forms/controls/file.ts +0 -47
- package/src/forms/controls/form-control.ts +0 -24
- package/src/forms/controls/form-field-control.ts +0 -22
- package/src/forms/controls/form-header.ts +0 -19
- package/src/forms/controls/form-paragraph.ts +0 -11
- package/src/forms/controls/frame.ts +0 -26
- package/src/forms/controls/hidden-input.ts +0 -22
- package/src/forms/controls/html.ts +0 -38
- package/src/forms/controls/multiple-files.ts +0 -256
- package/src/forms/controls/multiple-photos.ts +0 -44
- package/src/forms/controls/number.ts +0 -38
- package/src/forms/controls/photo.ts +0 -74
- package/src/forms/controls/radio.ts +0 -43
- package/src/forms/controls/reverse-single-reference.ts +0 -50
- package/src/forms/controls/simple-input.ts +0 -148
- package/src/forms/controls/textarea.ts +0 -60
- package/src/forms/controls/tickable.ts +0 -127
- package/src/forms/fields/boolean.test.ts +0 -36
- package/src/forms/fields/boolean.ts +0 -63
- package/src/forms/fields/checkboxed-list.ts +0 -66
- package/src/forms/fields/collection-field.ts +0 -62
- package/src/forms/fields/email.test.ts +0 -24
- package/src/forms/fields/email.ts +0 -20
- package/src/forms/fields/enum-multiple.test.ts +0 -31
- package/src/forms/fields/enum-multiple.ts +0 -62
- package/src/forms/fields/enum.test.ts +0 -25
- package/src/forms/fields/enum.ts +0 -56
- package/src/forms/fields/existing-sealious-value.ts +0 -22
- package/src/forms/fields/field.ts +0 -172
- package/src/forms/fields/file.ts +0 -89
- package/src/forms/fields/multiple-files.ts +0 -20
- package/src/forms/fields/number.test.ts +0 -34
- package/src/forms/fields/number.ts +0 -70
- package/src/forms/fields/pick-from-list.test.ts +0 -19
- package/src/forms/fields/pick-from-list.ts +0 -52
- package/src/forms/fields/proxy-field.ts +0 -24
- package/src/forms/fields/regexp.test.ts +0 -25
- package/src/forms/fields/regexp.ts +0 -53
- package/src/forms/fields/reverse-single-reference.ts +0 -20
- package/src/forms/fields/simple-form-field.ts +0 -30
- package/src/forms/fields/structured-array.ts +0 -27
- package/src/forms/form.test.ts +0 -351
- package/src/forms/form.ts +0 -294
- package/src/forms/forms.scss +0 -85
- package/src/forms/multiform.test.ts +0 -540
- package/src/forms/multiform.ts +0 -236
- package/src/generate-collections.ts +0 -77
- package/src/generate-routes.ts +0 -120
- package/src/index.ts +0 -24
- package/src/make-env.ts +0 -15
- package/src/make-hidden-inputs.ts +0 -24
- package/src/mount.ts +0 -85
- package/src/page/access-control.ts +0 -18
- package/src/page/list.ts +0 -240
- package/src/page/mountable-with-fields.ts +0 -158
- package/src/page/mountable.ts +0 -13
- package/src/page/page.ts +0 -46
- package/src/page/props-parser.ts +0 -38
- package/src/run.ts +0 -0
- package/src/sanitize.ts +0 -9
- package/src/templates/collection.ts +0 -11
- package/src/templates/form.ts +0 -60
- package/src/templates/list.ts +0 -75
- package/src/templates/multiform.ts +0 -58
- package/src/templates/page.ts +0 -25
- package/src/templates/post.ts +0 -21
- package/src/templates/redirect.ts +0 -22
- package/src/templates/route-test.ts +0 -27
- package/src/test_utils/locator_is_visible.ts +0 -17
- package/src/utils/assert-throws.ts +0 -18
- package/src/utils/browser-creator.js +0 -10
- package/src/utils/escape-url-params.ts +0 -14
- package/src/utils/exec.ts +0 -30
- package/src/utils/format-external-url.ts +0 -13
- package/src/utils/import-path.ts +0 -25
- package/src/utils/input-wrapper.ts +0 -21
- package/src/utils/list-collections.ts +0 -16
- package/src/utils/make-slug.ts +0 -5
- package/src/utils/natural-numbers.ts +0 -5
- package/src/utils/prettier.ts +0 -13
- package/src/utils/question.ts +0 -23
- package/src/utils/render-attributes.ts +0 -17
- package/src/utils/sleep.ts +0 -3
- package/src/utils/translate.ts +0 -13
- package/src/utils/url-with-new-params.ts +0 -9
- package/src/utils/utils.ts +0 -14
- package/src/utils/walk.ts +0 -20
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { Predicate, predicates } from "@sealcode/ts-predicates";
|
|
2
|
-
import { Context } from "koa";
|
|
3
|
-
import { t } from "../../utils/translate";
|
|
4
|
-
import { FormDataValue } from "../form";
|
|
5
|
-
|
|
6
|
-
export type FormFieldValidationResponse = { valid: boolean; message: string };
|
|
7
|
-
|
|
8
|
-
export type FormFieldValidationFn<ValueType> = (
|
|
9
|
-
ctx: Context,
|
|
10
|
-
value: ValueType,
|
|
11
|
-
field: FormField<boolean, ValueType>
|
|
12
|
-
) => Promise<FormFieldValidationResponse>;
|
|
13
|
-
|
|
14
|
-
export type FieldParsedValue<T> = T extends FormField<infer R> ? R : never;
|
|
15
|
-
|
|
16
|
-
export type GetPredicate<F extends FormField> = F extends FormField<true>
|
|
17
|
-
? F["predicate"]
|
|
18
|
-
: F["predicate"] | typeof predicates.undefined;
|
|
19
|
-
|
|
20
|
-
// for quickly testing GetPredicate conditonally applying the undefined predicate:
|
|
21
|
-
// const f = new SimpleFormField(true);
|
|
22
|
-
// type p = GetPredicate<typeof f>;
|
|
23
|
-
// const f2 = new SimpleFormField(false);
|
|
24
|
-
// type p2 = GetPredicate<typeof f2>;
|
|
25
|
-
|
|
26
|
-
export type FieldsToShape<T extends Record<string, FormField>> = {
|
|
27
|
-
[property in keyof T]: GetPredicate<T[property]>;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export function fieldsToShape<Fields extends Record<string, FormField>>(
|
|
31
|
-
obj: Fields
|
|
32
|
-
): FieldsToShape<Fields> {
|
|
33
|
-
return Object.fromEntries(
|
|
34
|
-
Object.entries(obj).map(([key, value]) => [key, value.predicate])
|
|
35
|
-
) as FieldsToShape<Fields>;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export type FieldParseResult<T> =
|
|
39
|
-
| {
|
|
40
|
-
parsable: true;
|
|
41
|
-
error: null;
|
|
42
|
-
parsed_value: T;
|
|
43
|
-
}
|
|
44
|
-
| {
|
|
45
|
-
parsable: false;
|
|
46
|
-
error: string;
|
|
47
|
-
parsed_value: null;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export abstract class FormField<
|
|
51
|
-
Required extends boolean = boolean,
|
|
52
|
-
ParsedValue extends unknown = unknown
|
|
53
|
-
> {
|
|
54
|
-
name: string;
|
|
55
|
-
constructor(public readonly required: Required) {}
|
|
56
|
-
predicate: Predicate = predicates.unknown;
|
|
57
|
-
mapToFilter: (parsed: ParsedValue) => unknown = (value) => value;
|
|
58
|
-
|
|
59
|
-
async init(fieldname: string): Promise<void> {
|
|
60
|
-
this.name = fieldname;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
public async _validate(
|
|
64
|
-
ctx: Context,
|
|
65
|
-
value: ParsedValue
|
|
66
|
-
): Promise<FormFieldValidationResponse> {
|
|
67
|
-
if (
|
|
68
|
-
this.required &&
|
|
69
|
-
(value === "" || value === null || value === undefined)
|
|
70
|
-
) {
|
|
71
|
-
return {
|
|
72
|
-
valid: false,
|
|
73
|
-
|
|
74
|
-
message: t(
|
|
75
|
-
ctx,
|
|
76
|
-
"field_is_required",
|
|
77
|
-
[],
|
|
78
|
-
"This field is required"
|
|
79
|
-
),
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
return this.isValueValid(ctx, value);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
public abstract getEmptyValue(): ParsedValue;
|
|
86
|
-
|
|
87
|
-
public async isValueValid(
|
|
88
|
-
ctx: Context,
|
|
89
|
-
value: ParsedValue
|
|
90
|
-
): Promise<FormFieldValidationResponse> {
|
|
91
|
-
return { valid: true, message: "" };
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
abstract parse(
|
|
95
|
-
ctx: Context,
|
|
96
|
-
raw_value: FormDataValue
|
|
97
|
-
): Promise<FieldParseResult<ParsedValue>>;
|
|
98
|
-
|
|
99
|
-
async getValue(
|
|
100
|
-
ctx: Context,
|
|
101
|
-
all_form_values: Record<string, FormDataValue>
|
|
102
|
-
): Promise<{
|
|
103
|
-
valid: boolean;
|
|
104
|
-
message: string;
|
|
105
|
-
parsed: ParsedValue;
|
|
106
|
-
raw: FormDataValue;
|
|
107
|
-
}> {
|
|
108
|
-
if (Object.keys(all_form_values || {}).length === 0) {
|
|
109
|
-
// don't validate on virgin form
|
|
110
|
-
return {
|
|
111
|
-
parsed: this.getEmptyValue(),
|
|
112
|
-
valid: true,
|
|
113
|
-
message: "",
|
|
114
|
-
raw: "",
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
const raw = all_form_values[this.name];
|
|
118
|
-
const {
|
|
119
|
-
parsable,
|
|
120
|
-
parsed_value,
|
|
121
|
-
error: parse_error,
|
|
122
|
-
} = await this.parse(ctx, raw);
|
|
123
|
-
if (!parsable) {
|
|
124
|
-
return {
|
|
125
|
-
valid: false,
|
|
126
|
-
parsed: this.getEmptyValue(),
|
|
127
|
-
raw,
|
|
128
|
-
message: parse_error || "Error",
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
const { valid, message } = await this._validate(
|
|
132
|
-
ctx,
|
|
133
|
-
parsed_value as ParsedValue
|
|
134
|
-
);
|
|
135
|
-
return {
|
|
136
|
-
parsed: parsed_value as ParsedValue,
|
|
137
|
-
valid,
|
|
138
|
-
message,
|
|
139
|
-
raw: all_form_values[this.name],
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
setMapToFilter(fn: (parsed: ParsedValue) => unknown) {
|
|
144
|
-
this.mapToFilter = fn;
|
|
145
|
-
return this;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
//return undefined here to delete a value
|
|
149
|
-
async getDatabaseValue(
|
|
150
|
-
ctx: Context,
|
|
151
|
-
data: Record<string, FormDataValue>
|
|
152
|
-
): Promise<unknown> {
|
|
153
|
-
const { parsed } = await this.getValue(ctx, data);
|
|
154
|
-
return parsed;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export * from "./simple-form-field";
|
|
159
|
-
export * from "./checkboxed-list";
|
|
160
|
-
export * from "./collection-field";
|
|
161
|
-
export * from "./number";
|
|
162
|
-
export * from "./pick-from-list";
|
|
163
|
-
export * from "./regexp";
|
|
164
|
-
export * from "./email";
|
|
165
|
-
export * from "./enum";
|
|
166
|
-
export * from "./boolean";
|
|
167
|
-
export * from "./enum-multiple";
|
|
168
|
-
export * from "./existing-sealious-value";
|
|
169
|
-
export * from "./file";
|
|
170
|
-
export * from "./multiple-files";
|
|
171
|
-
export * from "./reverse-single-reference";
|
|
172
|
-
export * from "./structured-array";
|
package/src/forms/fields/file.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
hasField,
|
|
3
|
-
hasFieldOfType,
|
|
4
|
-
hasShape,
|
|
5
|
-
is,
|
|
6
|
-
predicates,
|
|
7
|
-
} from "@sealcode/ts-predicates";
|
|
8
|
-
import { Context } from "koa";
|
|
9
|
-
import { File as SealiousFile } from "sealious";
|
|
10
|
-
import { FormDataValue } from "../form";
|
|
11
|
-
import { FieldParseResult, FormField } from "./field";
|
|
12
|
-
|
|
13
|
-
export type FileContainer = {
|
|
14
|
-
old: SealiousFile | null;
|
|
15
|
-
new: SealiousFile | null;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export class File<Required extends boolean> extends FormField<
|
|
19
|
-
Required,
|
|
20
|
-
FileContainer
|
|
21
|
-
> {
|
|
22
|
-
async parse(
|
|
23
|
-
ctx: Context,
|
|
24
|
-
raw_value: FormDataValue
|
|
25
|
-
): Promise<FieldParseResult<FileContainer>> {
|
|
26
|
-
let result;
|
|
27
|
-
if (
|
|
28
|
-
raw_value instanceof SealiousFile ||
|
|
29
|
-
(is(raw_value, predicates.object) &&
|
|
30
|
-
hasShape(
|
|
31
|
-
{
|
|
32
|
-
filename: predicates.string,
|
|
33
|
-
id: predicates.string,
|
|
34
|
-
},
|
|
35
|
-
raw_value
|
|
36
|
-
) &&
|
|
37
|
-
raw_value.id)
|
|
38
|
-
) {
|
|
39
|
-
const file = await SealiousFile.fromID(
|
|
40
|
-
ctx.$app,
|
|
41
|
-
raw_value.id as string
|
|
42
|
-
);
|
|
43
|
-
result = {
|
|
44
|
-
parsed_value: { old: file, new: null },
|
|
45
|
-
error: null,
|
|
46
|
-
parsable: true as true,
|
|
47
|
-
};
|
|
48
|
-
} else if (!is(raw_value, predicates.object)) {
|
|
49
|
-
result = {
|
|
50
|
-
parsed_value: null,
|
|
51
|
-
error: "Expected a field with old.id:string, old.filename:string and new?:File",
|
|
52
|
-
parsable: false as false,
|
|
53
|
-
};
|
|
54
|
-
} else {
|
|
55
|
-
const old_file =
|
|
56
|
-
hasFieldOfType(raw_value, "old", predicates.object) &&
|
|
57
|
-
hasShape(
|
|
58
|
-
{ id: predicates.string, filename: predicates.string },
|
|
59
|
-
raw_value.old
|
|
60
|
-
) &&
|
|
61
|
-
raw_value.old.id
|
|
62
|
-
? await SealiousFile.fromID(ctx.$app, raw_value.old.id)
|
|
63
|
-
: null;
|
|
64
|
-
const new_file =
|
|
65
|
-
hasFieldOfType(
|
|
66
|
-
raw_value,
|
|
67
|
-
"new",
|
|
68
|
-
predicates.array(predicates.object)
|
|
69
|
-
) && raw_value.new[0] instanceof SealiousFile
|
|
70
|
-
? raw_value.new[0]
|
|
71
|
-
: null;
|
|
72
|
-
result = {
|
|
73
|
-
parsable: true as true,
|
|
74
|
-
error: null,
|
|
75
|
-
parsed_value: { old: old_file, new: new_file },
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
return result;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async getDatabaseValue(ctx: Context, data: Record<string, FormDataValue>) {
|
|
82
|
-
const { parsed } = await this.getValue(ctx, data);
|
|
83
|
-
return parsed.new || undefined;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
getEmptyValue() {
|
|
87
|
-
return { old: null, new: null };
|
|
88
|
-
}
|
|
89
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { Context } from "koa";
|
|
2
|
-
import { FieldTypes as SealiousFieldTypes } from "sealious";
|
|
3
|
-
import { FormField } from "./field";
|
|
4
|
-
|
|
5
|
-
export class MultipleFiles extends FormField<false> {
|
|
6
|
-
constructor(
|
|
7
|
-
public collection_field: SealiousFieldTypes.ReverseSingleReference,
|
|
8
|
-
public getItemId: (ctx: Context) => Promise<string> | string
|
|
9
|
-
) {
|
|
10
|
-
super(false);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
getEmptyValue() {
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async parse() {
|
|
18
|
-
return <const>{ parsed_value: undefined, parsable: true, error: null }; // the control is supposed to do the heavy lifting here
|
|
19
|
-
}
|
|
20
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import assert from "assert";
|
|
2
|
-
import { Fields } from "../../index";
|
|
3
|
-
|
|
4
|
-
describe("number field", () => {
|
|
5
|
-
const ctx = {} as any;
|
|
6
|
-
|
|
7
|
-
it("validation logic", async () => {
|
|
8
|
-
const required = new Fields.NumberField(true, 0);
|
|
9
|
-
const not_required = new Fields.NumberField(false, 0);
|
|
10
|
-
|
|
11
|
-
assert.strictEqual((await required.isValueValid(ctx, 42)).valid, true);
|
|
12
|
-
assert.strictEqual((await required.isValueValid(ctx, "42")).valid, true);
|
|
13
|
-
assert.strictEqual((await required.isValueValid(ctx, "notvalid")).valid, false);
|
|
14
|
-
assert.strictEqual((await not_required.isValueValid(ctx, "")).valid, true);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("parse function", async () => {
|
|
18
|
-
const required = new Fields.NumberField(true, 0);
|
|
19
|
-
const decimal_digits = new Fields.NumberField(true, 0, { decimalDigits: 1 });
|
|
20
|
-
const number_as_string_response = await required.parse(ctx, "42");
|
|
21
|
-
const number_response = await required.parse(ctx, 42);
|
|
22
|
-
const not_a_number_response = await required.parse(ctx, "notanumber");
|
|
23
|
-
const decimal_number_response = await decimal_digits.parse(ctx, 42.42);
|
|
24
|
-
|
|
25
|
-
assert.strictEqual(number_as_string_response.parsable, true);
|
|
26
|
-
assert.strictEqual(number_as_string_response.parsed_value, 42);
|
|
27
|
-
assert.strictEqual(number_response.parsable, true);
|
|
28
|
-
assert.strictEqual(number_response.parsed_value, 42);
|
|
29
|
-
assert.strictEqual(not_a_number_response.parsable, false);
|
|
30
|
-
assert.strictEqual(not_a_number_response.error, "Please enter a number");
|
|
31
|
-
assert.strictEqual(decimal_number_response.parsable, true);
|
|
32
|
-
assert.strictEqual(decimal_number_response.parsed_value, 42.4);
|
|
33
|
-
});
|
|
34
|
-
});
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { is, predicates } from "@sealcode/ts-predicates";
|
|
2
|
-
import { Context } from "koa";
|
|
3
|
-
import { FormDataValue } from "../form";
|
|
4
|
-
import { FieldParseResult, FormField } from "./field";
|
|
5
|
-
|
|
6
|
-
export class NumberField<
|
|
7
|
-
DefaultValue extends number | null = number,
|
|
8
|
-
Required extends boolean = boolean
|
|
9
|
-
> extends FormField<Required, number | DefaultValue> {
|
|
10
|
-
constructor(
|
|
11
|
-
required: Required,
|
|
12
|
-
public default_value: DefaultValue,
|
|
13
|
-
public options: Partial<{
|
|
14
|
-
max: number;
|
|
15
|
-
min: number;
|
|
16
|
-
decimalDigits: number;
|
|
17
|
-
}> = {}
|
|
18
|
-
) {
|
|
19
|
-
super(required);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
predicate = predicates.number;
|
|
23
|
-
|
|
24
|
-
public async isValueValid(_: Context, value: unknown) {
|
|
25
|
-
if (
|
|
26
|
-
(is(value, predicates.string) &&
|
|
27
|
-
!isNaN(parseFloat(value)) &&
|
|
28
|
-
parseFloat(value).toString() == value.trim()) ||
|
|
29
|
-
is(value, predicates.number) ||
|
|
30
|
-
((is(value, predicates.undefined) || value == "") && !this.required)
|
|
31
|
-
) {
|
|
32
|
-
return { valid: true, message: "" };
|
|
33
|
-
}
|
|
34
|
-
return { valid: false, message: "Proszę wprowadzić liczbę" };
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async parse(
|
|
38
|
-
_: Context,
|
|
39
|
-
value: FormDataValue
|
|
40
|
-
): Promise<FieldParseResult<number>> {
|
|
41
|
-
if (
|
|
42
|
-
(is(value, predicates.string) &&
|
|
43
|
-
!isNaN(parseFloat(value)) &&
|
|
44
|
-
parseFloat(value).toString() == value.trim()) ||
|
|
45
|
-
is(value, predicates.number)
|
|
46
|
-
) {
|
|
47
|
-
return {
|
|
48
|
-
parsable: true,
|
|
49
|
-
parsed_value: this.options.decimalDigits
|
|
50
|
-
? parseFloat(
|
|
51
|
-
parseFloat(value.toString()).toFixed(
|
|
52
|
-
this.options.decimalDigits
|
|
53
|
-
)
|
|
54
|
-
)
|
|
55
|
-
: parseFloat(value.toString()),
|
|
56
|
-
error: null,
|
|
57
|
-
};
|
|
58
|
-
} else {
|
|
59
|
-
return {
|
|
60
|
-
parsable: false,
|
|
61
|
-
parsed_value: null,
|
|
62
|
-
error: "Please enter a number",
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
public getEmptyValue(): DefaultValue {
|
|
68
|
-
return this.default_value;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import assert from "assert";
|
|
2
|
-
import { Fields } from "../../index";
|
|
3
|
-
|
|
4
|
-
describe("pick-from-list field", () => {
|
|
5
|
-
const ctx = {} as any;
|
|
6
|
-
|
|
7
|
-
it("validation logic", async () => {
|
|
8
|
-
const field = new Fields.PickFromListField(true, async () => {
|
|
9
|
-
return [
|
|
10
|
-
{ value: "samplev", label: "samplel" },
|
|
11
|
-
{ value: "samplevv", label: "samplell" },
|
|
12
|
-
];
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
assert.strictEqual((await field.isValueValid(ctx, 42 as any)).valid, false);
|
|
16
|
-
assert.strictEqual((await field.isValueValid(ctx, "samplevv")).valid, true);
|
|
17
|
-
assert.strictEqual((await field.isValueValid(ctx, "notvalid")).valid, false);
|
|
18
|
-
});
|
|
19
|
-
});
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { is, predicates } from "@sealcode/ts-predicates";
|
|
2
|
-
import { Context } from "koa";
|
|
3
|
-
import { DropdownOption } from "../controls/dropdown";
|
|
4
|
-
import { FormFieldValidationResponse } from "./field";
|
|
5
|
-
import { SimpleFormField } from "./simple-form-field";
|
|
6
|
-
|
|
7
|
-
export class PickFromListField<
|
|
8
|
-
Required extends boolean
|
|
9
|
-
> extends SimpleFormField<Required> {
|
|
10
|
-
constructor(
|
|
11
|
-
public required: Required,
|
|
12
|
-
public generateOptions: (ctx: Context) => Promise<DropdownOption[]>,
|
|
13
|
-
public customValidation: (
|
|
14
|
-
ctx: Context,
|
|
15
|
-
value: unknown,
|
|
16
|
-
instance: PickFromListField<Required>
|
|
17
|
-
) => Promise<FormFieldValidationResponse> = (ctx, value, instance) =>
|
|
18
|
-
instance.valueInList(ctx, value)
|
|
19
|
-
) {
|
|
20
|
-
super(required);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
predicate = predicates.string;
|
|
24
|
-
|
|
25
|
-
public isValueValid(
|
|
26
|
-
ctx: Context,
|
|
27
|
-
value: string
|
|
28
|
-
): Promise<FormFieldValidationResponse> {
|
|
29
|
-
return this.customValidation(ctx, value, this);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async valueInList(
|
|
33
|
-
ctx: Context,
|
|
34
|
-
value: unknown
|
|
35
|
-
): Promise<FormFieldValidationResponse> {
|
|
36
|
-
const options = await this.generateOptions(ctx);
|
|
37
|
-
if (!is(value, predicates.string)) {
|
|
38
|
-
return { valid: false, message: "not a string" };
|
|
39
|
-
}
|
|
40
|
-
if (this.required && !options.map((o) => o.value).includes(value)) {
|
|
41
|
-
return {
|
|
42
|
-
valid: false,
|
|
43
|
-
message: `"${value}" is not one of the options`,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
return { valid: true, message: "" };
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
public getEmptyValue(): string {
|
|
50
|
-
return "";
|
|
51
|
-
}
|
|
52
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { FormField } from "./field";
|
|
2
|
-
|
|
3
|
-
export class ProxyFormField<T> extends FormField<boolean, T> {
|
|
4
|
-
constructor(
|
|
5
|
-
required: boolean,
|
|
6
|
-
public name: string,
|
|
7
|
-
public empty_value: T,
|
|
8
|
-
public parsed_value: T
|
|
9
|
-
) {
|
|
10
|
-
super(required);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
getEmptyValue() {
|
|
14
|
-
return this.empty_value;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async parse() {
|
|
18
|
-
return <const>{
|
|
19
|
-
parsable: true,
|
|
20
|
-
error: null,
|
|
21
|
-
parsed_value: this.parsed_value,
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import assert from "assert";
|
|
2
|
-
import { Fields } from "../../index";
|
|
3
|
-
|
|
4
|
-
describe("regexp field", () => {
|
|
5
|
-
const ctx = {} as any;
|
|
6
|
-
|
|
7
|
-
it("validation logic", async () => {
|
|
8
|
-
const field = new Fields.RegExpField(true, /^4/, "error");
|
|
9
|
-
|
|
10
|
-
assert.strictEqual((await field.isValueValid(ctx, "42")).valid, true);
|
|
11
|
-
assert.strictEqual((await field.isValueValid(ctx, "notvalid")).valid, false);
|
|
12
|
-
assert.strictEqual((await field.isValueValid(ctx, 42)).valid, false);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it("parse function", async () => {
|
|
16
|
-
const field = new Fields.RegExpField(true, /^4/, "error");
|
|
17
|
-
const string_response = await field.parse(ctx, "42");
|
|
18
|
-
const number_response = await field.parse(ctx, 42);
|
|
19
|
-
|
|
20
|
-
assert.strictEqual(string_response.parsable, true);
|
|
21
|
-
assert.strictEqual(string_response.parsed_value, "42");
|
|
22
|
-
assert.strictEqual(number_response.parsable, false);
|
|
23
|
-
assert.strictEqual(number_response.error, "Please enter a string");
|
|
24
|
-
});
|
|
25
|
-
});
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { is, predicates } from "@sealcode/ts-predicates";
|
|
2
|
-
import { Context } from "koa";
|
|
3
|
-
import { FormDataValue } from "../form";
|
|
4
|
-
import { FieldParseResult, FormField } from "./field";
|
|
5
|
-
|
|
6
|
-
export class RegExpField<Required extends boolean> extends FormField<Required> {
|
|
7
|
-
constructor(
|
|
8
|
-
required: Required,
|
|
9
|
-
public regexp: RegExp,
|
|
10
|
-
public error_message: string,
|
|
11
|
-
public default_value: string = ""
|
|
12
|
-
) {
|
|
13
|
-
super(required);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
predicate = predicates.string;
|
|
17
|
-
|
|
18
|
-
public async isValueValid(
|
|
19
|
-
_: Context,
|
|
20
|
-
value: unknown
|
|
21
|
-
): Promise<{ valid: boolean; message: string }> {
|
|
22
|
-
if (!is(value, predicates.string)) {
|
|
23
|
-
return { valid: false, message: "expected a string" };
|
|
24
|
-
}
|
|
25
|
-
if (this.regexp.exec(value)) {
|
|
26
|
-
return { valid: true, message: "" };
|
|
27
|
-
}
|
|
28
|
-
return { valid: false, message: this.error_message };
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async parse(
|
|
32
|
-
_: Context,
|
|
33
|
-
value: FormDataValue
|
|
34
|
-
): Promise<FieldParseResult<string>> {
|
|
35
|
-
if (is(value, predicates.string)) {
|
|
36
|
-
return {
|
|
37
|
-
parsable: true,
|
|
38
|
-
parsed_value: value,
|
|
39
|
-
error: null,
|
|
40
|
-
};
|
|
41
|
-
} else {
|
|
42
|
-
return {
|
|
43
|
-
parsable: false,
|
|
44
|
-
parsed_value: null,
|
|
45
|
-
error: "Please enter a string",
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
public getEmptyValue(): string {
|
|
51
|
-
return this.default_value || "";
|
|
52
|
-
}
|
|
53
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { FormField } from "./field";
|
|
2
|
-
import { FieldTypes as SealiousFields } from "sealious";
|
|
3
|
-
import { Context } from "koa";
|
|
4
|
-
|
|
5
|
-
export class ReverseSingleReference extends FormField {
|
|
6
|
-
constructor(
|
|
7
|
-
required: boolean,
|
|
8
|
-
public sealious_field: SealiousFields.ReverseSingleReference
|
|
9
|
-
) {
|
|
10
|
-
super(required);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async parse(ctx: Context, raw_value: unknown) {
|
|
14
|
-
return { parsable: <const>true, error: null, parsed_value: raw_value };
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
getEmptyValue() {
|
|
18
|
-
return [];
|
|
19
|
-
}
|
|
20
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { FieldParseResult, FormField } from "./field";
|
|
2
|
-
import { FormDataValue } from "../form";
|
|
3
|
-
import { Context } from "koa";
|
|
4
|
-
import { predicates } from "@sealcode/ts-predicates";
|
|
5
|
-
|
|
6
|
-
export class SimpleFormField<Required extends boolean> extends FormField<
|
|
7
|
-
Required,
|
|
8
|
-
string | null
|
|
9
|
-
> {
|
|
10
|
-
async parse(
|
|
11
|
-
_: Context,
|
|
12
|
-
raw_value: FormDataValue
|
|
13
|
-
): Promise<FieldParseResult<string>> {
|
|
14
|
-
return {
|
|
15
|
-
parsed_value: (raw_value || "").toString(),
|
|
16
|
-
parsable: true,
|
|
17
|
-
error: null,
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
predicate = predicates.string;
|
|
22
|
-
|
|
23
|
-
public getEmptyValue(): string {
|
|
24
|
-
return "";
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
constructor(required: Required) {
|
|
28
|
-
super(required);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Context } from "koa";
|
|
2
|
-
import { Field, FieldsetInput, FieldsetOutput, FieldTypes } from "sealious";
|
|
3
|
-
import { FormDataValue } from "../form";
|
|
4
|
-
import { FormField } from "./field";
|
|
5
|
-
|
|
6
|
-
export class StructuredArrayField<
|
|
7
|
-
Fields extends Record<string, Field>
|
|
8
|
-
> extends FormField<
|
|
9
|
-
true,
|
|
10
|
-
FieldTypes.ArrayStorageInput<FieldsetOutput<Fields>>
|
|
11
|
-
> {
|
|
12
|
-
constructor(public sealious_field: FieldTypes.StructuredArray<Fields>) {
|
|
13
|
-
super(true);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async parse(context: Context, value: FormDataValue) {
|
|
17
|
-
return {
|
|
18
|
-
parsable: <const>true,
|
|
19
|
-
error: null,
|
|
20
|
-
parsed_value: (value as FieldsetOutput<Fields>) || [],
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
getEmptyValue() {
|
|
25
|
-
return [] as FieldTypes.ArrayStorageInput<FieldsetOutput<Fields>>;
|
|
26
|
-
}
|
|
27
|
-
}
|