Skip to content

Commit

Permalink
Merge pull request #53 from open-formulieren/feature/4542-support-ema…
Browse files Browse the repository at this point in the history
…il-verification

Add type definition to support e-mail verification
  • Loading branch information
sergei-maertens authored Aug 20, 2024
2 parents 58230c0 + 58edc62 commit da09769
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 60 deletions.
18 changes: 14 additions & 4 deletions src/formio/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,15 @@ export interface PrefillConfig {

/**
* @group Open Forms schema extensions
*
* The `Extra` type variable allows specifying additional, component-specific,
* extensions namespaced under the `openForms` key.
*/
export interface OFExtensions<TK extends string = string> {
export interface OFExtensions<TK extends string = string, Extra = {}> {
isSensitiveData?: boolean;
openForms?: {
translations: ComponentTranslations<TK>;
};
} & Extra;
registration?: {
attribute: string;
};
Expand Down Expand Up @@ -173,12 +176,19 @@ export type MultipleCapable<S> = S extends {defaultValue?: infer DV}

/**
* @group Schema primitives
*
* The `ExtraExtensions` type variable allows specifying additional, component-specific,
* extensions namespaced under the `openForms` key.
*/
export type InputComponentSchema<
T = unknown,
VN extends CuratedValidatorNames = CuratedValidatorNames,
TK extends string = string
> = StrictComponentSchema<T | T[]> & DisplayConfig & OFExtensions<TK> & HasValidation<VN>;
TK extends string = string,
ExtraExtensions = {}
> = StrictComponentSchema<T | T[]> &
DisplayConfig &
OFExtensions<TK, ExtraExtensions> &
HasValidation<VN>;

/**
* @group Schema primitives
Expand Down
21 changes: 11 additions & 10 deletions src/formio/components/addressNL.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {HasValidation, InputComponentSchema} from '..';
import {ComponentTranslations} from '../i18n';

type Validator = 'required';
type TranslatableKeys = 'label' | 'description' | 'tooltip';
Expand All @@ -19,22 +18,24 @@ export interface AddressComponents {
city?: HasValidation<'pattern', false>;
}

export type AddressNLInputSchema = InputComponentSchema<AddressData, Validator, TranslatableKeys>;
export interface AddressNLExtensions {
components?: AddressComponents;
}

export type AddressNLInputSchema = InputComponentSchema<
AddressData,
Validator,
TranslatableKeys,
AddressNLExtensions
>;

/**
* @group Form.io components
* @category Concrete types
*/
export interface AddressNLComponentSchema
extends Omit<
AddressNLInputSchema,
'hideLabel' | 'placeholder' | 'disabled' | 'validateOn' | 'openForms'
> {
extends Omit<AddressNLInputSchema, 'hideLabel' | 'placeholder' | 'disabled' | 'validateOn'> {
type: 'addressNL';
deriveAddress: boolean;
layout: 'singleColumn' | 'doubleColumn';
openForms?: {
components?: AddressComponents;
translations?: ComponentTranslations<TranslatableKeys>;
};
}
21 changes: 12 additions & 9 deletions src/formio/components/date.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {InputComponentSchema, MultipleCapable, PrefillConfig} from '..';
import {OFExtensions} from '../base';
import {
FutureDateConstraint as BaseFutureDateConstraint,
PastDateConstraint as BasePastDateConstraint,
Expand All @@ -11,8 +10,6 @@ import {
type Validator = 'required' | 'minDate' | 'maxDate';
type TranslatableKeys = 'label' | 'description' | 'tooltip';

export type DateInputSchema = InputComponentSchema<string, Validator, TranslatableKeys>;

export interface IncludeToday {
includeToday: boolean | null;
}
Expand All @@ -21,18 +18,24 @@ type FutureOrPastDateConstraint = BaseFutureDateConstraint | BasePastDateConstra
type FutureDateConstraint = BaseFutureDateConstraint & IncludeToday;
type PastDateConstraint = BasePastDateConstraint & IncludeToday;

export interface DateExtensions {
minDate?: Exclude<DateConstraintConfiguration, FutureOrPastDateConstraint> | FutureDateConstraint;
maxDate?: Exclude<DateConstraintConfiguration, FutureOrPastDateConstraint> | PastDateConstraint;
}

export type DateInputSchema = InputComponentSchema<
string,
Validator,
TranslatableKeys,
DateExtensions
>;

/**
* @group Form.io components
* @category Base types
*/
export interface BaseDateComponentSchema extends Omit<DateInputSchema, 'hideLabel'>, PrefillConfig {
type: 'date';
openForms?: OFExtensions<TranslatableKeys>['openForms'] & {
minDate?:
| Exclude<DateConstraintConfiguration, FutureOrPastDateConstraint>
| FutureDateConstraint;
maxDate?: Exclude<DateConstraintConfiguration, FutureOrPastDateConstraint> | PastDateConstraint;
};
datePicker?: DatePickerConfig;
customOptions?: PickerCustomOptions;
}
Expand Down
17 changes: 11 additions & 6 deletions src/formio/components/datetime.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {InputComponentSchema, MultipleCapable, PrefillConfig} from '..';
import {OFExtensions} from '../base';
import {
DateConstraintConfiguration,
DatePickerConfig,
Expand All @@ -11,7 +10,17 @@ import {
type Validator = 'required' | 'minDate' | 'maxDate';
type TranslatableKeys = 'label' | 'description' | 'tooltip';

export type DateTimeInputSchema = InputComponentSchema<string, Validator, TranslatableKeys>;
export interface DateTimeExtensions {
minDate?: Exclude<DateConstraintConfiguration, PastDateConstraint>;
maxDate?: Exclude<DateConstraintConfiguration, FutureDateConstraint>;
}

export type DateTimeInputSchema = InputComponentSchema<
string,
Validator,
TranslatableKeys,
DateTimeExtensions
>;

/**
* @group Form.io components
Expand All @@ -21,10 +30,6 @@ export interface BaseDateTimeComponentSchema
extends Omit<DateTimeInputSchema, 'hideLabel'>,
PrefillConfig {
type: 'datetime';
openForms?: OFExtensions<TranslatableKeys>['openForms'] & {
minDate?: Exclude<DateConstraintConfiguration, PastDateConstraint>;
maxDate?: Exclude<DateConstraintConfiguration, FutureDateConstraint>;
};
datePicker?: DatePickerConfig;
customOptions?: PickerCustomOptions;
}
Expand Down
11 changes: 10 additions & 1 deletion src/formio/components/email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@ import {InputComponentSchema, MultipleCapable} from '..';
type Validator = 'required';
type TranslatableKeys = 'label' | 'description' | 'tooltip';

export type EmailInputSchema = InputComponentSchema<string, Validator, TranslatableKeys>;
export interface EmailExtensions {
requireVerification?: boolean;
}

export type EmailInputSchema = InputComponentSchema<
string,
Validator,
TranslatableKeys,
EmailExtensions
>;

/**
* @group Form.io components
Expand Down
23 changes: 14 additions & 9 deletions src/formio/components/radio.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import {InputComponentSchema} from '..';
import {OFExtensions} from '../base';
import {ManualValues, Option, VariableValues} from '../common';
import {Require} from '../util';

type Validator = 'required';
type TranslatableKeys = 'label' | 'description' | 'tooltip';

export type RadioInputSchema = InputComponentSchema<string | null, Validator, TranslatableKeys>;
export type RadioInputSchema<Extensions> = InputComponentSchema<
string | null,
Validator,
TranslatableKeys,
Extensions
>;

/**
* @group Form.io components
Expand All @@ -20,23 +25,23 @@ interface BaseRadioSchema {
* @group Form.io components
* @category Base types
*/
type RadioManualValuesSchema = Omit<RadioInputSchema, 'hideLabel' | 'disabled'> &
type RadioManualValuesSchema = Omit<RadioInputSchema<ManualValues>, 'hideLabel' | 'disabled'> &
BaseRadioSchema & {
openForms: OFExtensions<TranslatableKeys>['openForms'] & ManualValues;
values: Option[];
};

/**
* @group Form.io components
* @category Base types
*/
type RadioVariableValuesSchema = Omit<RadioInputSchema, 'hideLabel' | 'disabled'> &
BaseRadioSchema & {
openForms: OFExtensions<TranslatableKeys>['openForms'] & VariableValues;
};
type RadioVariableValuesSchema = Omit<RadioInputSchema<VariableValues>, 'hideLabel' | 'disabled'> &
BaseRadioSchema;

/**
* @group Form.io components
* @category Concrete types
*/
export type RadioComponentSchema = RadioManualValuesSchema | RadioVariableValuesSchema;
export type RadioComponentSchema = Require<
RadioManualValuesSchema | RadioVariableValuesSchema,
'openForms'
>;
21 changes: 12 additions & 9 deletions src/formio/components/select.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import {InputComponentSchema} from '..';
import {MultipleCapable, OFExtensions} from '../base';
import {MultipleCapable} from '../base';
import {ManualValues, Option, VariableValues} from '../common';
import {Require} from '../util';

type Validator = 'required';
type TranslatableKeys = 'label' | 'description' | 'tooltip';

export type SelectInputSchema = InputComponentSchema<string, Validator, TranslatableKeys>;
export type SelectInputSchema<Extensions> = InputComponentSchema<
string,
Validator,
TranslatableKeys,
Extensions
>;

export type SelectUnsupported = 'hideLabel' | 'disabled' | 'placeholder';

Expand All @@ -26,9 +32,8 @@ interface BaseSelectSchema {
* @group Form.io components
* @category Base types
*/
type SelectManualValuesSchema = Omit<SelectInputSchema, SelectUnsupported> &
type SelectManualValuesSchema = Omit<SelectInputSchema<ManualValues>, SelectUnsupported> &
BaseSelectSchema & {
openForms: OFExtensions<TranslatableKeys>['openForms'] & ManualValues;
data: {
values: Option[];
};
Expand All @@ -38,15 +43,13 @@ type SelectManualValuesSchema = Omit<SelectInputSchema, SelectUnsupported> &
* @group Form.io components
* @category Base types
*/
type SelectVariableValuesSchema = Omit<SelectInputSchema, SelectUnsupported> &
BaseSelectSchema & {
openForms: OFExtensions<TranslatableKeys>['openForms'] & VariableValues;
};
type SelectVariableValuesSchema = Omit<SelectInputSchema<VariableValues>, SelectUnsupported> &
BaseSelectSchema;

/**
* @group Form.io components
* @category Concrete types
*/
export type SelectComponentSchema = MultipleCapable<
SelectManualValuesSchema | SelectVariableValuesSchema
Require<SelectManualValuesSchema | SelectVariableValuesSchema, 'openForms'>
>;
29 changes: 17 additions & 12 deletions src/formio/components/selectboxes.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import {InputComponentSchema} from '..';
import {OFExtensions} from '../base';
import {ManualValues, Option, VariableValues} from '../common';
import {Require} from '../util';

type Validator = 'required' | 'minSelectedCount' | 'maxSelectedCount';
type TranslatableKeys = 'label' | 'description' | 'tooltip';

export type SelectboxesInputSchema = InputComponentSchema<
export type SelectboxesInputSchema<Extensions> = InputComponentSchema<
Record<string, boolean>,
Validator,
TranslatableKeys
TranslatableKeys,
Extensions
>;

/**
Expand All @@ -24,25 +25,29 @@ interface BaseSelectboxesSchema {
* @group Form.io components
* @category Base types
*/
type SelectboxesManualValuesSchema = Omit<SelectboxesInputSchema, 'hideLabel' | 'disabled'> &
type SelectboxesManualValuesSchema = Omit<
SelectboxesInputSchema<ManualValues>,
'hideLabel' | 'disabled'
> &
BaseSelectboxesSchema & {
openForms: OFExtensions<TranslatableKeys>['openForms'] & ManualValues;
values: Option[];
};

/**
* @group Form.io components
* @category Base types
*/
type SelectboxesVariableValuesSchema = Omit<SelectboxesInputSchema, 'hideLabel' | 'disabled'> &
BaseSelectboxesSchema & {
openForms: OFExtensions<TranslatableKeys>['openForms'] & VariableValues;
};
type SelectboxesVariableValuesSchema = Omit<
SelectboxesInputSchema<VariableValues>,
'hideLabel' | 'disabled'
> &
BaseSelectboxesSchema;

/**
* @group Form.io components
* @category Concrete types
*/
export type SelectboxesComponentSchema =
| SelectboxesManualValuesSchema
| SelectboxesVariableValuesSchema;
export type SelectboxesComponentSchema = Require<
SelectboxesManualValuesSchema | SelectboxesVariableValuesSchema,
'openForms'
>;
8 changes: 8 additions & 0 deletions src/formio/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Given a type `T` with optional key(s) `K`, make the key(s) `K` required.
*
* The ternary is to force distribution over unions in `T`.
*/
export type Require<T, K extends keyof T> = T extends any
? Omit<T, K> & Required<Pick<T, K>>
: never;
1 change: 1 addition & 0 deletions test-d/formio/components/email.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ expectAssignable<EmailComponentSchema>({
translations: {
nl: {label: 'foo'},
},
requireVerification: true,
},
// fixed but not editable
validateOn: 'blur',
Expand Down

0 comments on commit da09769

Please sign in to comment.