Skip to content

Commit 7739952

Browse files
committed
feat: add branded numeric types and codecs
1 parent 0288b0a commit 7739952

File tree

4 files changed

+54
-6
lines changed

4 files changed

+54
-6
lines changed

src/language/typescript/2.0/serializers/swagger-object.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { clientFile } from '../../common/bundled/client';
1212
import { serializeParametersDefinitionsObject } from './parameters-definitions-object';
1313
import { combineReader } from '@devexperts/utils/dist/adt/reader.utils';
1414
import { serializeResponsesDefinitionsObject } from './responses-definitions-object';
15+
import { utilsFile } from '../../common/bundled/utils';
1516

1617
const definitionsRef = fromString('#/definitions');
1718
const parametersRef = fromString('#/parameters');
@@ -56,8 +57,8 @@ export const serializeSwaggerObject = combineReader(
5657
pathsRef,
5758
either.chain(from => serializePaths(from, swaggerObject.paths)),
5859
);
59-
return combineEither(additional, paths, clientFile, (additional, paths, clientFile) =>
60-
directory(name, [clientFile, ...additional, paths]),
60+
return combineEither(additional, paths, clientFile, utilsFile, (additional, paths, clientFile, utilsFile) =>
61+
directory(name, [clientFile, utilsFile, ...additional, paths]),
6162
);
6263
},
6364
);

src/language/typescript/3.0/serializers/document.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { applyTo } from '../../../../utils/function';
1111
import { OpenapiObject } from '../../../../schema/3.0/openapi-object';
1212
import { pathsRef } from '../../common/utils';
1313
import { clientFile } from '../../common/bundled/client';
14+
import { utilsFile } from '../../common/bundled/utils';
1415

1516
export const serializeDocument = combineReader(
1617
serializeComponentsObject,
@@ -42,8 +43,8 @@ export const serializeDocument = combineReader(
4243
array.compact([components]),
4344
sequenceEither,
4445
);
45-
return combineEither(paths, additional, clientFile, (paths, additional, clientFile) =>
46-
directory(name, [paths, ...additional, clientFile]),
46+
return combineEither(paths, additional, clientFile, utilsFile, (paths, additional, clientFile, utilsFile) =>
47+
directory(name, [paths, ...additional, clientFile, utilsFile]),
4748
);
4849
},
4950
);

src/language/typescript/asyncapi-2.0.0/serializers/asyncapi-object.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { array, either, option } from 'fp-ts';
99
import { combineEither, sequenceEither } from '@devexperts/utils/dist/adt/either.utils';
1010
import { serializeChannelsObject } from './channels-object';
1111
import { clientFile } from '../../common/bundled/client';
12+
import { utilsFile } from '../../common/bundled/utils';
1213

1314
export const serializeAsyncAPIObject = combineReader(
1415
serializeComponentsObject,
@@ -32,8 +33,13 @@ export const serializeAsyncAPIObject = combineReader(
3233
either.chain(from => serializeChannelsObject(from, asyncAPIObject.channels)),
3334
either.map(content => directory('channels', [content])),
3435
);
35-
return combineEither(channels, additional, clientFile, (channels, additional, clientFile) =>
36-
directory(name, [channels, clientFile, ...additional]),
36+
return combineEither(
37+
channels,
38+
additional,
39+
clientFile,
40+
utilsFile,
41+
(channels, additional, clientFile, utilsFile) =>
42+
directory(name, [channels, clientFile, utilsFile, ...additional]),
3743
);
3844
},
3945
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { fromString } from '../../../../utils/ref';
2+
import { pipe } from 'fp-ts/lib/pipeable';
3+
import { either } from 'fp-ts';
4+
import { fromRef } from '../../../../utils/fs';
5+
6+
export const utilsRef = fromString('#/utils/utils');
7+
8+
const utils = `
9+
import { brand, Branded, intersection, number, Type } from 'io-ts';
10+
11+
export interface IntegerBrand {
12+
readonly Integer: unique symbol;
13+
}
14+
export type Integer = Branded<number, IntegerBrand>;
15+
export const integer: Type<Integer, number> = brand(
16+
number,
17+
(n): n is Integer => n !== -Infinity && n !== Infinity && Math.floor(n) === n,
18+
'Integer',
19+
);
20+
21+
export interface NonNegativeBrand {
22+
readonly NonNegative: unique symbol;
23+
}
24+
export type NonNegative = Branded<number, NonNegativeBrand>;
25+
export const nonNegative: Type<NonNegative, number> = brand(number, (n): n is NonNegative => n >= 0.0, 'NonNegative');
26+
27+
export interface PositiveBrand {
28+
readonly Positive: unique symbol;
29+
}
30+
export type Positive = Branded<number, PositiveBrand>;
31+
export const positive: Type<Positive, number> = brand(number, (n): n is Positive => n > 0.0, 'Positive');
32+
33+
export type Natural = NonNegative & Integer;
34+
export const natural: Type<Natural, number> = intersection([nonNegative, integer], 'Natural');
35+
`;
36+
37+
export const utilsFile = pipe(
38+
utilsRef,
39+
either.map(ref => fromRef(ref, '.ts', utils)),
40+
);

0 commit comments

Comments
 (0)