-
-
Notifications
You must be signed in to change notification settings - Fork 834
/
Copy pathenum.ts
105 lines (90 loc) · 3.33 KB
/
enum.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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts';
import type { ColumnBaseConfig } from '~/column.ts';
import { entityKind } from '~/entity.ts';
import type { AnyPgTable } from '~/pg-core/table.ts';
import type { Writable } from '~/utils.ts';
import { PgColumn, PgColumnBuilder } from './common.ts';
export type PgEnumColumnBuilderInitial<TName extends string, TValues extends [string, ...string[]]> =
PgEnumColumnBuilder<{
name: TName;
dataType: 'string';
columnType: 'PgEnumColumn';
data: TValues[number];
enumValues: TValues;
driverParam: string;
}>;
const isPgEnumSym = Symbol.for('drizzle:isPgEnum');
export interface PgEnum<TValues extends [string, ...string[]]> {
(): PgEnumColumnBuilderInitial<'', TValues>;
<TName extends string>(name: TName): PgEnumColumnBuilderInitial<TName, TValues>;
<TName extends string>(name?: TName): PgEnumColumnBuilderInitial<TName, TValues>;
readonly enumName: string;
readonly enumValues: TValues;
readonly schema: string | undefined;
/** @internal */
[isPgEnumSym]: true;
}
export type InferPgEnum<T extends PgEnum<any>> = T['enumValues'][number];
export function isPgEnum(obj: unknown): obj is PgEnum<[string, ...string[]]> {
return !!obj && typeof obj === 'function' && isPgEnumSym in obj && obj[isPgEnumSym] === true;
}
export class PgEnumColumnBuilder<
T extends ColumnBuilderBaseConfig<'string', 'PgEnumColumn'> & { enumValues: [string, ...string[]] },
> extends PgColumnBuilder<T, { enum: PgEnum<T['enumValues']> }> {
static override readonly [entityKind]: string = 'PgEnumColumnBuilder';
constructor(name: T['name'], enumInstance: PgEnum<T['enumValues']>) {
super(name, 'string', 'PgEnumColumn');
this.config.enum = enumInstance;
}
/** @internal */
override build<TTableName extends string>(
table: AnyPgTable<{ name: TTableName }>,
): PgEnumColumn<MakeColumnConfig<T, TTableName>> {
return new PgEnumColumn<MakeColumnConfig<T, TTableName>>(
table,
this.config as ColumnBuilderRuntimeConfig<any, any>,
);
}
}
export class PgEnumColumn<T extends ColumnBaseConfig<'string', 'PgEnumColumn'> & { enumValues: [string, ...string[]] }>
extends PgColumn<T, { enum: PgEnum<T['enumValues']> }>
{
static override readonly [entityKind]: string = 'PgEnumColumn';
readonly enum = this.config.enum;
override readonly enumValues = this.config.enum.enumValues;
constructor(
table: AnyPgTable<{ name: T['tableName'] }>,
config: PgEnumColumnBuilder<T>['config'],
) {
super(table, config);
this.enum = config.enum;
}
getSQLType(): string {
return this.enum.enumName;
}
}
// Gratitude to zod for the enum function types
export function pgEnum<U extends string, T extends Readonly<[U, ...U[]]>>(
enumName: string,
values: T | Writable<T>,
): PgEnum<Writable<T>> {
return pgEnumWithSchema(enumName, values, undefined);
}
/** @internal */
export function pgEnumWithSchema<U extends string, T extends Readonly<[U, ...U[]]>>(
enumName: string,
values: T | Writable<T>,
schema?: string,
): PgEnum<Writable<T>> {
const enumInstance: PgEnum<Writable<T>> = Object.assign(
<TName extends string>(name?: TName): PgEnumColumnBuilderInitial<TName, Writable<T>> =>
new PgEnumColumnBuilder(name ?? '' as TName, enumInstance),
{
enumName,
enumValues: values,
schema,
[isPgEnumSym]: true,
} as const,
);
return enumInstance;
}