Skip to content

Commit

Permalink
feat: add 'shouldValidate' option
Browse files Browse the repository at this point in the history
  • Loading branch information
KDxCBdP7 committed May 8, 2022
1 parent 7597f6e commit 3806ece
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 15 deletions.
38 changes: 33 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,25 @@ const parsedParameters = parameters.parse({
//=> { TOKEN: 'xxxx', FIREBASE_CONFIG: { apiKey: 'xxxx' } }
```

### API
## API

see `test/index.spec.ts`.

```ts
import { createTypedParameters } from 'construct-typed-parameters';
### createTypedParameters

// type ParameterValidate<T> = (value: T) => string | string[] | null;
```ts
import {
createTypedParameters,
TypedParametersConstruct,
} from 'construct-typed-parameters';

const parameters = createTypedParameters(pt => ({
const parameters: TypedParametersConstruct<T> = createTypedParameters(pt => ({
stringValue: pt.String({
// required: boolean
required: true,
// defaultValue?: T1
defaultValue: 'xxxx',
// validate?: (value: T1) => string | string[] | null;
validate: v => (v.includes('x') ? null : 'the value must contain x'),
}),
unionStringValue: pt.UnionString<'v1' | 'v2'>({
Expand Down Expand Up @@ -99,6 +105,28 @@ const parameters = createTypedParameters(pt => ({
}));
```

### TypedParametersConstruct#parse

```ts
const parameters: TypedParametersConstruct<T> = createTypedParameters(pt => ({ ... }));

parameters.parse(
stringifiedParameters: Partial<StringifiedParameters<T>>,
shouldValidate = true
) : ParsedParameters<T>
```

### TypedParametersConstruct#stringify

```ts
const parameters: TypedParametersConstruct<T> = createTypedParameters(pt => ({ ... }));

parameters.stringify(
parsedParameters: Partial<ParsedParameters<T>>,
shouldValidate = true
) : StringifiedParameters<T>
```

[build-img]: https://github.com/masahirompp/construct-typed-parameters/actions/workflows/release.yml/badge.svg
[build-url]: https://github.com/masahirompp/construct-typed-parameters/actions/workflows/release.yml
[downloads-img]: https://img.shields.io/npm/dt/construct-typed-parameters
Expand Down
34 changes: 24 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,17 @@ const ParameterType = {
class TypedParameters<T extends Record<string, ParameterConstruct<any>>> {
constructor(private parametersConstruct: T) {}

parse(serializedParameters: Partial<StringifiedParameters<T>>) {
parse(
stringifiedParameters: Partial<StringifiedParameters<T>>,
shouldValidate = true
) {
const requiredErrorParameters: string[] = [];
const validationErrorParameterMap: Record<string, string[]> = {};
const result = Object.entries(this.parametersConstruct).reduce<
ParsedParameters<T>
>((payload, [parameterName, construct]) => {
const value = (() => {
const serialized = serializedParameters[parameterName];
const serialized = stringifiedParameters[parameterName];
const parsedValue =
typeof serialized === 'string'
? construct.parse(serialized)
Expand All @@ -156,13 +159,17 @@ class TypedParameters<T extends Record<string, ParameterConstruct<any>>> {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return construct.defaultValue;
}
if (construct.required) {
if (shouldValidate && construct.required) {
requiredErrorParameters.push(parameterName);
}
return undefined;
})();

if (value != null && typeof construct.validate === 'function') {
if (
shouldValidate &&
value != null &&
typeof construct.validate === 'function'
) {
const validationError = construct.validate(value);
if (validationError) {
if (Array.isArray(validationError)) {
Expand All @@ -188,23 +195,30 @@ class TypedParameters<T extends Record<string, ParameterConstruct<any>>> {
throw new ParameterError(
requiredErrorParameters,
validationErrorParameterMap,
serializedParameters,
stringifiedParameters,
result
);
}
return result;
}

stringify(parameters: Partial<ParsedParameters<T>>) {
stringify(
parsedParameters: Partial<ParsedParameters<T>>,
shouldValidate = true
) {
const requiredErrorParameters: string[] = [];
const validationErrorParameterMap: Record<string, string[]> = {};
const result = Object.entries(this.parametersConstruct).reduce<
StringifiedParameters<T>
>((payload, [parameterName, construct]) => {
const serialized = (() => {
const value = parameters[parameterName];
const value = parsedParameters[parameterName];

if (value != null && typeof construct.validate === 'function') {
if (
shouldValidate &&
value != null &&
typeof construct.validate === 'function'
) {
const validationError = construct.validate(value);
if (validationError) {
if (Array.isArray(validationError)) {
Expand All @@ -230,7 +244,7 @@ class TypedParameters<T extends Record<string, ParameterConstruct<any>>> {
return serializedDefaultValue;
}
}
if (construct.required) {
if (shouldValidate && construct.required) {
requiredErrorParameters.push(parameterName);
}
return undefined;
Expand All @@ -250,7 +264,7 @@ class TypedParameters<T extends Record<string, ParameterConstruct<any>>> {
requiredErrorParameters,
validationErrorParameterMap,
result,
parameters
parsedParameters
);
}
return result;
Expand Down
96 changes: 96 additions & 0 deletions test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ describe('index', () => {
);
});

it('parse required error but should not validate', () => {
expect(parameters.parse({}, false)).toEqual({});
});

it('stringify', () => {
expect(
parameters.stringify({
Expand Down Expand Up @@ -69,6 +73,10 @@ describe('index', () => {
'stringValue is required, unionStringValue is required, numberValue is required, unionNumberValue is required, booleanValue is required, jsonValue is required, arrayValue is required.'
);
});

it('stringify required error but should not validate', () => {
expect(parameters.stringify({}, false)).toEqual({});
});
});

describe('all required with defaultValue.', () => {
Expand Down Expand Up @@ -401,6 +409,33 @@ describe('index', () => {
);
});

it('parse validation error but should not validate', () => {
expect(
parameters.parse(
{
stringValue: 'yyyy',
unionStringValue: 'v3',
numberValue: '0',
unionNumberValue: '-1',
booleanValue: 'false',
jsonValue: '{"apiKey":""}',
arrayValue: '[]',
},
false
)
).toEqual({
arrayValue: [],
booleanValue: false,
jsonValue: {
apiKey: '',
},
numberValue: 0,
stringValue: 'yyyy',
unionNumberValue: -1,
unionStringValue: 'v3',
});
});

it('parse required error and validation error', () => {
expect(() =>
parameters.parse({
Expand All @@ -414,6 +449,25 @@ describe('index', () => {
);
});

it('parse required error and validation error, but should not validaet', () => {
expect(
parameters.parse(
{
stringValue: 'yyyy',
numberValue: '0',
booleanValue: 'false',
arrayValue: '[]',
},
false
)
).toEqual({
stringValue: 'yyyy',
numberValue: 0,
booleanValue: false,
arrayValue: [],
});
});

it('stringify', () => {
expect(
parameters.stringify({
Expand Down Expand Up @@ -463,6 +517,31 @@ describe('index', () => {
);
});

it('stringify validation error but should not validate', () => {
expect(
parameters.stringify(
{
stringValue: 'yyyy',
unionStringValue: 'v3' as never,
numberValue: 0,
unionNumberValue: -1 as never,
booleanValue: false,
jsonValue: { apiKey: '' },
arrayValue: [],
},
false
)
).toEqual({
stringValue: 'yyyy',
unionStringValue: 'v3',
numberValue: '0',
unionNumberValue: '-1',
booleanValue: 'false',
jsonValue: '{"apiKey":""}',
arrayValue: '[]',
});
});

it('stringify required error and validation error', () => {
expect(() =>
parameters.stringify({
Expand All @@ -474,5 +553,22 @@ describe('index', () => {
'stringValue is required, numberValue is required, booleanValue is required, arrayValue is required. unionStringValue: the value must be v1 or v2, unionNumberValue: the value must be 0 or 1, jsonValue: apiKey must be specified.'
);
});

it('stringify required error and validation error, but should not validate', () => {
expect(
parameters.stringify(
{
unionStringValue: 'v3' as never,
unionNumberValue: -1 as never,
jsonValue: { apiKey: '' },
},
false
)
).toEqual({
unionStringValue: 'v3',
unionNumberValue: '-1',
jsonValue: '{"apiKey":""}',
});
});
});
});

0 comments on commit 3806ece

Please sign in to comment.