Skip to content

Commit 2eb02c2

Browse files
committed
chore: simplify known import processing
1 parent 045974d commit 2eb02c2

File tree

4 files changed

+194
-122
lines changed

4 files changed

+194
-122
lines changed

packages/openapi-generator/src/codec.ts

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,10 @@ function parseObjectExpression(
122122
if (E.isLeft(initE)) {
123123
return initE;
124124
}
125-
const [newSourceFile, init] = initE.right;
125+
let [newSourceFile, init] = initE.right;
126+
if (init.type === 'TsAsExpression' || init.type === 'TsConstAssertion') {
127+
init = init.expression;
128+
}
126129
if (init.type !== 'ObjectExpression') {
127130
return E.left('Spread element must be object');
128131
}
@@ -209,6 +212,8 @@ export function parsePlainInitializer(
209212
return E.right({ type: 'literal', kind: 'null', value: null });
210213
} else if (init.type === 'Identifier' && init.value === 'undefined') {
211214
return E.right({ type: 'undefined' });
215+
} else if (init.type === 'TsConstAssertion' || init.type === 'TsAsExpression') {
216+
return parsePlainInitializer(project, source, init.expression);
212217
} else if (
213218
init.type === 'Identifier' ||
214219
init.type === 'MemberExpression' ||
@@ -253,23 +258,21 @@ export function parseCodecInitializer(
253258
return E.right(identifier);
254259
}
255260

256-
function deref(source: SourceFile): DerefFn {
257-
return (schema, fn) => {
258-
if (schema.type !== 'ref') {
259-
return fn(deref(source), schema);
260-
} else {
261-
const initE = findSymbolInitializer(project, source, schema.name);
262-
if (E.isLeft(initE)) {
263-
return initE;
264-
}
265-
const [newSourceFile, init] = initE.right;
266-
const newSchemaE = parsePlainInitializer(project, newSourceFile, init);
267-
if (E.isLeft(newSchemaE)) {
268-
return newSchemaE;
269-
}
270-
return fn(deref(newSourceFile), newSchemaE.right);
261+
function deref(schema: Schema): E.Either<string, Schema> {
262+
if (schema.type !== 'ref') {
263+
return E.right(schema);
264+
} else {
265+
const refSource = project.get(schema.location);
266+
if (refSource === undefined) {
267+
return E.left(`Unknown source ${schema.location}`);
271268
}
272-
};
269+
const initE = findSymbolInitializer(project, refSource, schema.name);
270+
if (E.isLeft(initE)) {
271+
return initE;
272+
}
273+
const [newSourceFile, init] = initE.right;
274+
return parsePlainInitializer(project, newSourceFile, init);
275+
}
273276
}
274277
const args = init.arguments.map<E.Either<string, Schema>>(({ expression }) => {
275278
return parsePlainInitializer(project, source, expression);
@@ -278,7 +281,8 @@ export function parseCodecInitializer(
278281
return pipe(
279282
args,
280283
E.sequenceArray,
281-
E.chain((args) => identifier.schema(deref(source), ...args)),
284+
E.chain((args) => pipe(args.map(deref), E.sequenceArray)),
285+
E.chain((args) => identifier.schema(deref, ...args)),
282286
);
283287
} else {
284288
return E.left(`Unimplemented initializer type ${init.type}`);

packages/openapi-generator/src/knownImports.ts

Lines changed: 70 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import * as E from 'fp-ts/Either';
2-
import { pipe } from 'fp-ts/lib/function';
32

43
import type { Schema } from './ir';
54

6-
export type DerefFn = (ref: Schema, fn: KnownCodec) => E.Either<string, Schema>;
5+
export type DerefFn = (ref: Schema) => E.Either<string, Schema>;
76
export type KnownCodec = (
87
deref: DerefFn,
98
...schemas: Schema[]
@@ -32,31 +31,27 @@ export const KNOWN_IMPORTS: KnownImports = {
3231
boolean: () => E.right({ type: 'primitive', value: 'boolean' }),
3332
null: () => E.right({ type: 'primitive', value: 'null' }),
3433
array: (_, innerSchema) => E.right({ type: 'array', items: innerSchema }),
35-
type: (deref, schema) => {
36-
return deref(schema, (_, schema) => {
37-
if (schema.type !== 'object') {
38-
return E.left('typeC parameter must be object');
39-
}
40-
const props = Object.entries(schema.properties).reduce((acc, [key, prop]) => {
41-
return { ...acc, [key]: prop };
42-
}, {});
43-
return E.right({
44-
type: 'object',
45-
properties: props,
46-
required: Object.keys(props),
47-
});
34+
type: (_, schema) => {
35+
if (schema.type !== 'object') {
36+
return E.left('typeC parameter must be object');
37+
}
38+
const props = Object.entries(schema.properties).reduce((acc, [key, prop]) => {
39+
return { ...acc, [key]: prop };
40+
}, {});
41+
return E.right({
42+
type: 'object',
43+
properties: props,
44+
required: Object.keys(props),
4845
});
4946
},
50-
partial: (deref, schema) => {
51-
return deref(schema, (_, schema) => {
52-
if (schema.type !== 'object') {
53-
return E.left('typeC parameter must be object');
54-
}
55-
const props = Object.entries(schema.properties).reduce((acc, [key, prop]) => {
56-
return { ...acc, [key]: prop };
57-
}, {});
58-
return E.right({ type: 'object', properties: props, required: [] });
59-
});
47+
partial: (_, schema) => {
48+
if (schema.type !== 'object') {
49+
return E.left('typeC parameter must be object');
50+
}
51+
const props = Object.entries(schema.properties).reduce((acc, [key, prop]) => {
52+
return { ...acc, [key]: prop };
53+
}, {});
54+
return E.right({ type: 'object', properties: props, required: [] });
6055
},
6156
record: (_, _domain, codomain) => {
6257
if (!codomain) {
@@ -65,46 +60,37 @@ export const KNOWN_IMPORTS: KnownImports = {
6560
return E.right({ type: 'record', codomain });
6661
}
6762
},
68-
union: (deref, schema) => {
69-
return deref(schema, (_, schema) => {
70-
if (schema.type !== 'tuple') {
71-
return E.left('unionC parameter must be array');
72-
}
73-
return E.right({ type: 'union', schemas: schema.schemas });
74-
});
63+
union: (_, schema) => {
64+
if (schema.type !== 'tuple') {
65+
return E.left('unionC parameter must be array');
66+
}
67+
return E.right({ type: 'union', schemas: schema.schemas });
7568
},
76-
intersection: (deref, schema) => {
77-
return deref(schema, (_, schema) => {
78-
if (schema.type !== 'tuple') {
79-
return E.left('unionC parameter must be array');
80-
}
81-
return E.right({ type: 'intersection', schemas: schema.schemas });
82-
});
69+
intersection: (_, schema) => {
70+
if (schema.type !== 'tuple') {
71+
return E.left('unionC parameter must be array');
72+
}
73+
return E.right({ type: 'intersection', schemas: schema.schemas });
8374
},
84-
literal: (deref, arg) => {
85-
return deref(arg, (_, arg) => {
86-
if (arg.type !== 'literal') {
87-
return E.left(`Unimplemented literal type ${arg.type}`);
88-
} else {
89-
return E.right(arg);
90-
}
91-
});
75+
literal: (_, arg) => {
76+
if (arg.type !== 'literal') {
77+
return E.left(`Unimplemented literal type ${arg.type}`);
78+
} else {
79+
return E.right(arg);
80+
}
9281
},
93-
keyof: (deref, arg) => {
94-
return deref(arg, (_, arg) => {
95-
if (arg.type !== 'object') {
96-
return E.left(`Unimplemented keyof type ${arg.type}`);
97-
}
98-
const schemas: E.Either<string, Schema>[] = Object.keys(arg.properties).map(
99-
(prop) => {
100-
return E.right({ type: 'literal', kind: 'string', value: prop });
101-
},
102-
);
103-
return pipe(
104-
schemas,
105-
E.sequenceArray,
106-
E.map((schemas) => ({ type: 'union', schemas: [...schemas] })),
107-
);
82+
keyof: (_, arg) => {
83+
if (arg.type !== 'object') {
84+
return E.left(`Unimplemented keyof type ${arg.type}`);
85+
}
86+
const schemas: Schema[] = Object.keys(arg.properties).map((prop) => ({
87+
type: 'literal',
88+
kind: 'string',
89+
value: prop,
90+
}));
91+
return E.right({
92+
type: 'union',
93+
schemas,
10894
});
10995
},
11096
brand: (_, arg) => E.right(arg),
@@ -120,26 +106,22 @@ export const KNOWN_IMPORTS: KnownImports = {
120106
'@api-ts/io-ts-http': {
121107
optional: (_, innerSchema) =>
122108
E.right({ type: 'union', schemas: [innerSchema, { type: 'undefined' }] }),
123-
optionalized: (deref, props) => {
124-
return deref(props, (_, props) => {
125-
if (props.type !== 'object') {
126-
return E.left('optionalized parameter must be object');
127-
}
128-
const required = Object.keys(props.properties).filter(
129-
(key) => !isOptional(props.properties[key]!),
130-
);
131-
return E.right({ type: 'object', properties: props.properties, required });
132-
});
109+
optionalized: (_, props) => {
110+
if (props.type !== 'object') {
111+
return E.left('optionalized parameter must be object');
112+
}
113+
const required = Object.keys(props.properties).filter(
114+
(key) => !isOptional(props.properties[key]!),
115+
);
116+
return E.right({ type: 'object', properties: props.properties, required });
133117
},
134118
httpRequest: (deref, arg) => {
135119
if (arg.type !== 'object') {
136120
return E.left(`Unimplemented httpRequest type ${arg.type}`);
137121
}
138122
const properties: Record<string, Schema> = {};
139123
for (const [outerKey, outerValue] of Object.entries(arg.properties)) {
140-
const innerPropsE = deref(outerValue, (_, innerProps) => {
141-
return E.right(innerProps);
142-
});
124+
const innerPropsE = deref(outerValue);
143125

144126
if (E.isLeft(innerPropsE)) {
145127
return innerPropsE;
@@ -164,22 +146,20 @@ export const KNOWN_IMPORTS: KnownImports = {
164146
});
165147
},
166148
httpRoute: (deref, schema) => {
167-
return deref(schema, (_, schema) => {
168-
if (schema.type !== 'object') {
169-
return E.left('httpRoute parameter must be object');
149+
if (schema.type !== 'object') {
150+
return E.left('httpRoute parameter must be object');
151+
}
152+
const props = Object.entries(schema.properties).reduce((acc, [key, prop]) => {
153+
const derefedE = deref(prop);
154+
if (E.isLeft(derefedE)) {
155+
return acc;
170156
}
171-
const props = Object.entries(schema.properties).reduce((acc, [key, prop]) => {
172-
const derefedE = deref(prop, (_, derefed) => E.right(derefed));
173-
if (E.isLeft(derefedE)) {
174-
return acc;
175-
}
176-
return { ...acc, [key]: derefedE.right };
177-
}, {});
178-
return E.right({
179-
type: 'object',
180-
properties: props,
181-
required: Object.keys(props),
182-
});
157+
return { ...acc, [key]: derefedE.right };
158+
}, {});
159+
return E.right({
160+
type: 'object',
161+
properties: props,
162+
required: Object.keys(props),
183163
});
184164
},
185165
},

0 commit comments

Comments
 (0)