Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validator fix #2220

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
85 changes: 39 additions & 46 deletions drizzle-typebox/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,6 @@ type MaybeOptional<
type GetTypeboxType<TColumn extends Column> = TColumn['_']['dataType'] extends infer TDataType
? TDataType extends 'custom' ? TAny
: TDataType extends 'json' ? Json
: TColumn extends { enumValues: [string, ...string[]] }
? Equal<TColumn['enumValues'], [string, ...string[]]> extends true ? TString
: TUnion<TUnionLiterals<TColumn['enumValues']>>
: TDataType extends 'array' ? TArray<
GetTypeboxType<
Assume<
Expand All @@ -93,6 +90,9 @@ type GetTypeboxType<TColumn extends Column> = TColumn['_']['dataType'] extends i
>['baseColumn']
>
>
: TColumn extends { enumValues: [string, ...string[]] }
? Equal<TColumn['enumValues'], [string, ...string[]]> extends true ? TString
: TUnion<TUnionLiterals<TColumn['enumValues']>>
: TDataType extends 'bigint' ? TBigInt
: TDataType extends 'number' ? TNumber
: TDataType extends 'string' ? TString
Expand Down Expand Up @@ -166,7 +166,7 @@ export function createInsertSchema<
& string}' does not exist in table '${TTable['_']['name']}'`
>;
},
//
// @ts-ignore - following error does not break types during usage in any way
): TObject<
BuildInsertSchema<
TTable,
Expand Down Expand Up @@ -281,8 +281,7 @@ function isWithEnum(
column: AnyColumn,
): column is typeof column & { enumValues: [string, ...string[]] } {
return (
'enumValues' in column
&& Array.isArray(column.enumValues)
Array.isArray(column.enumValues)
&& column.enumValues.length > 0
);
}
Expand All @@ -293,47 +292,41 @@ function mapColumnToSchema(column: Column): TSchema {
let type: TSchema | undefined;

if (isWithEnum(column)) {
type = column.enumValues?.length
? Type.Union(column.enumValues.map((value) => Type.Literal(value)))
: Type.String();
}

if (!type) {
if (column.dataType === 'custom') {
type = Type.Any();
} else if (column.dataType === 'json') {
type = jsonSchema;
} else if (column.dataType === 'array') {
type = Type.Array(
mapColumnToSchema((column as PgArray<any, any>).baseColumn),
);
} else if (column.dataType === 'number') {
type = Type.Number();
} else if (column.dataType === 'bigint') {
type = Type.BigInt();
} else if (column.dataType === 'boolean') {
type = Type.Boolean();
} else if (column.dataType === 'date') {
type = Type.Date();
} else if (column.dataType === 'string') {
const sType = Type.String();

if (
(is(column, PgChar)
|| is(column, PgVarchar)
|| is(column, MySqlVarChar)
|| is(column, MySqlVarBinary)
|| is(column, MySqlChar)
|| is(column, SQLiteText))
&& typeof column.length === 'number'
) {
sType.maxLength = column.length;
}

type = sType;
} else if (is(column, PgUUID)) {
type = Type.RegEx(uuidPattern);
type = Type.Union(column.enumValues.map((value) => Type.Literal(value)));
} else if (column.dataType === 'custom') {
type = Type.Any();
} else if (column.dataType === 'json') {
type = jsonSchema;
} else if (column.dataType === 'array') {
type = Type.Array(
mapColumnToSchema((column as PgArray<any, any>).baseColumn),
);
} else if (column.dataType === 'number') {
type = Type.Number();
} else if (column.dataType === 'bigint') {
type = Type.BigInt();
} else if (column.dataType === 'boolean') {
type = Type.Boolean();
} else if (column.dataType === 'date') {
type = Type.Date();
} else if (column.dataType === 'string') {
const sType = Type.String();

if (
(is(column, PgChar)
|| is(column, PgVarchar)
|| is(column, MySqlVarChar)
|| is(column, MySqlVarBinary)
|| is(column, MySqlChar)
|| is(column, SQLiteText))
&& typeof column.length === 'number'
) {
sType.maxLength = column.length;
}

type = sType;
} else if (is(column, PgUUID)) {
type = Type.RegEx(uuidPattern);
}

if (!type) {
Expand Down
6 changes: 6 additions & 0 deletions drizzle-typebox/tests/pg.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const roleEnum = pgEnum('role', ['admin', 'user']);

const users = pgTable('users', {
a: integer('a').array(),
strArr: text('str_arr').array(),
id: serial('id').primaryKey(),
name: text('name'),
email: text('email').notNull(),
Expand All @@ -26,6 +27,7 @@ const users = pgTable('users', {

const testUser = {
a: [1, 2, 3],
strArr: ['one', 'two', 'three'],
id: 1,
name: 'John Doe',
email: 'john.doe@example.com',
Expand Down Expand Up @@ -92,6 +94,7 @@ test('users insert schema', (t) => {

const expected = Type.Object({
a: Type.Optional(Nullable(Type.Array(Type.Number()))),
strArr: Type.Optional(Nullable(Type.Array(Type.String()))),
id: Type.Optional(Type.Number({ minimum: 0 })),
name: Type.Optional(Nullable(Type.String())),
email: Type.String(),
Expand Down Expand Up @@ -119,6 +122,7 @@ test('users insert schema w/ defaults', (t) => {

const expected = Type.Object({
a: Type.Optional(Nullable(Type.Array(Type.Number()))),
strArr: Type.Optional(Nullable(Type.Array(Type.String()))),
id: Type.Optional(Type.Number()),
name: Type.Optional(Nullable(Type.String())),
email: Type.String(),
Expand Down Expand Up @@ -150,6 +154,7 @@ test('users select schema', (t) => {

const expected = Type.Object({
a: Nullable(Type.Array(Type.Number())),
strArr: Nullable(Type.Array(Type.String())),
id: Type.Number({ minimum: 0 }),
name: Nullable(Type.String()),
email: Type.String(),
Expand All @@ -175,6 +180,7 @@ test('users select schema w/ defaults', (t) => {

const expected = Type.Object({
a: Nullable(Type.Array(Type.Number())),
strArr: Nullable(Type.Array(Type.String())),
id: Type.Number(),
name: Nullable(Type.String()),
email: Type.String(),
Expand Down
86 changes: 40 additions & 46 deletions drizzle-valibot/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,12 @@ type MaybeOptional<
type GetValibotType<TColumn extends Column> = TColumn['_']['dataType'] extends infer TDataType
? TDataType extends 'custom' ? AnySchema
: TDataType extends 'json' ? Json
: TDataType extends 'array'
? TColumn['_']['baseColumn'] extends Column ? ArraySchema<GetValibotType<TColumn['_']['baseColumn']>>
: never
: TColumn extends { enumValues: [string, ...string[]] }
? Equal<TColumn['enumValues'], [string, ...string[]]> extends true ? StringSchema
: PicklistSchema<TColumn['enumValues']>
: TDataType extends 'array'
? TColumn['_']['baseColumn'] extends Column ? ArraySchema<GetValibotType<TColumn['_']['baseColumn']>> : never
: TDataType extends 'bigint' ? BigintSchema
: TDataType extends 'number' ? NumberSchema
: TDataType extends 'string' ? StringSchema
Expand Down Expand Up @@ -156,8 +157,8 @@ export function createInsertSchema<
& string}' does not exist in table '${TTable['_']['name']}'`
>;
},
//
): ObjectSchema<
): // @ts-ignore - following error does not break types during usage in any way
ObjectSchema<
BuildInsertSchema<
TTable,
Equal<TRefine, Refine<TTable, 'insert'>> extends true ? {} : TRefine
Expand Down Expand Up @@ -271,8 +272,7 @@ function isWithEnum(
column: AnyColumn,
): column is typeof column & { enumValues: [string, ...string[]] } {
return (
'enumValues' in column
&& Array.isArray(column.enumValues)
Array.isArray(column.enumValues)
&& column.enumValues.length > 0
);
}
Expand All @@ -281,47 +281,41 @@ function mapColumnToSchema(column: Column): BaseSchema<any, any> {
let type: BaseSchema<any, any> | undefined;

if (isWithEnum(column)) {
type = column.enumValues?.length
? picklist(column.enumValues)
: string();
}

if (!type) {
if (column.dataType === 'custom') {
type = any();
} else if (column.dataType === 'json') {
type = jsonSchema;
} else if (column.dataType === 'array') {
type = array(
mapColumnToSchema((column as PgArray<any, any>).baseColumn),
);
} else if (column.dataType === 'number') {
type = number();
} else if (column.dataType === 'bigint') {
type = bigint();
} else if (column.dataType === 'boolean') {
type = boolean();
} else if (column.dataType === 'date') {
type = date();
} else if (column.dataType === 'string') {
let sType = string();

if (
(is(column, PgChar)
|| is(column, PgVarchar)
|| is(column, MySqlVarChar)
|| is(column, MySqlVarBinary)
|| is(column, MySqlChar)
|| is(column, SQLiteText))
&& typeof column.length === 'number'
) {
sType = string([maxLength(column.length)]);
}

type = sType;
} else if (is(column, PgUUID)) {
type = string([uuid()]);
type = picklist(column.enumValues);
} else if (column.dataType === 'custom') {
type = any();
} else if (column.dataType === 'json') {
type = jsonSchema;
} else if (column.dataType === 'array') {
type = array(
mapColumnToSchema((column as PgArray<any, any>).baseColumn),
);
} else if (column.dataType === 'number') {
type = number();
} else if (column.dataType === 'bigint') {
type = bigint();
} else if (column.dataType === 'boolean') {
type = boolean();
} else if (column.dataType === 'date') {
type = date();
} else if (column.dataType === 'string') {
let sType = string();

if (
(is(column, PgChar)
|| is(column, PgVarchar)
|| is(column, MySqlVarChar)
|| is(column, MySqlVarBinary)
|| is(column, MySqlChar)
|| is(column, SQLiteText))
&& typeof column.length === 'number'
) {
sType = string([maxLength(column.length)]);
}

type = sType;
} else if (is(column, PgUUID)) {
type = string([uuid()]);
}

if (!type) {
Expand Down
6 changes: 6 additions & 0 deletions drizzle-valibot/tests/pg.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const roleEnum = pgEnum('role', ['admin', 'user']);

const users = pgTable('users', {
a: integer('a').array(),
strArr: text('str_arr').array(),
id: serial('id').primaryKey(),
name: text('name'),
email: text('email').notNull(),
Expand All @@ -39,6 +40,7 @@ const users = pgTable('users', {

const testUser = {
a: [1, 2, 3],
strArr: ['one', 'two', 'three'],
id: 1,
name: 'John Doe',
email: 'john.doe@example.com',
Expand Down Expand Up @@ -102,6 +104,7 @@ test('users insert schema', (t) => {

const expected = object({
a: optional(nullable(array(number()))),
strArr: optional(nullable(array(string()))),
id: optional(number([minValue(0)])),
name: optional(nullable(string())),
email: string(),
Expand All @@ -123,6 +126,7 @@ test('users insert schema w/ defaults', (t) => {

const expected = object({
a: optional(nullable(array(number()))),
strArr: optional(nullable(array(string()))),
id: optional(number()),
name: optional(nullable(string())),
email: string(),
Expand All @@ -148,6 +152,7 @@ test('users select schema', (t) => {

const expected = object({
a: nullable(array(number())),
strArr: nullable(array(string())),
id: number([minValue(0)]),
name: nullable(string()),
email: string(),
Expand All @@ -169,6 +174,7 @@ test('users select schema w/ defaults', (t) => {

const expected = object({
a: nullable(array(number())),
strArr: nullable(array(string())),
id: number(),
name: nullable(string()),
email: string(),
Expand Down