-
Notifications
You must be signed in to change notification settings - Fork 180
/
types.ts
71 lines (60 loc) · 1.94 KB
/
types.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import type { FunctionParamType } from '../operations/functions';
import type { Type } from '../operations/generalTypes';
import type { ColumnDefinition, ColumnDefinitions } from '../operations/tables';
const TYPE_ADAPTERS = Object.freeze({
int: 'integer',
string: 'text',
float: 'real',
double: 'double precision',
datetime: 'timestamp',
bool: 'boolean',
});
const DEFAULT_TYPE_SHORTHANDS: Readonly<ColumnDefinitions> = Object.freeze({
id: { type: 'serial', primaryKey: true }, // convenience type for serial primary keys
});
// some convenience adapters -- see above
export function applyTypeAdapters(type: string): string {
return type in TYPE_ADAPTERS
? TYPE_ADAPTERS[type as keyof typeof TYPE_ADAPTERS]
: type;
}
function toType(type: string | Readonly<ColumnDefinition>): ColumnDefinition {
return typeof type === 'string' ? { type } : type;
}
function removeType<TColumnDefinition extends Readonly<ColumnDefinition>>({
// eslint-disable-next-line @typescript-eslint/no-unused-vars
type,
...rest
}: TColumnDefinition): Omit<TColumnDefinition, 'type'> {
return rest;
}
export function applyType(
type: Readonly<Type>,
extendingTypeShorthands: Readonly<ColumnDefinitions> = {}
): ColumnDefinition & FunctionParamType {
const typeShorthands: ColumnDefinitions = {
...DEFAULT_TYPE_SHORTHANDS,
...extendingTypeShorthands,
};
const options = toType(type);
let ext: ColumnDefinition | null = null;
const types: string[] = [options.type];
while (typeShorthands[types[types.length - 1]]) {
ext = {
...toType(typeShorthands[types[types.length - 1]]),
...(ext === null ? {} : removeType(ext)),
};
if (types.includes(ext.type)) {
throw new Error(
`Shorthands contain cyclic dependency: ${types.join(', ')}, ${ext.type}`
);
} else {
types.push(ext.type);
}
}
return {
...ext,
...options,
type: applyTypeAdapters(ext?.type ?? options.type),
};
}