Skip to content

Commit ee1fa6f

Browse files
committed
Added relationship type
1 parent 44c0589 commit ee1fa6f

File tree

5 files changed

+197
-93
lines changed

5 files changed

+197
-93
lines changed

src/packages/dumbo/src/core/schema/components/relationships/relationshipTypes.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,35 @@ export type AllColumnReferences<DB> =
4747
}[keyof Schemas]
4848
: never;
4949

50+
export type RelationshipType =
51+
| 'one-to-one'
52+
| 'one-to-many'
53+
| 'many-to-one'
54+
| 'many-to-many';
55+
5056
export type RelationshipDefinition<Columns = string, References = string> = {
5157
readonly columns: readonly Columns[];
5258
readonly references: readonly References[];
59+
readonly type: RelationshipType;
5360
};
5461

62+
export type TableRelationships<Columns extends string = string> = Record<
63+
string,
64+
RelationshipDefinition<Columns, string>
65+
>;
66+
5567
export const relationship = <
5668
const Columns extends readonly string[],
5769
const References extends readonly string[],
5870
>(
5971
columns: Columns,
6072
references: References,
73+
type: RelationshipType,
6174
) => {
6275
return {
6376
columns,
6477
references,
78+
type,
6579
} as const;
6680
};
6781
// eslint-disable-next-line @typescript-eslint/no-explicit-any

src/packages/dumbo/src/core/schema/components/relationships/relationshipValidation.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,14 @@ export type ValidateSingleRelationship<
111111
? ValidationResult<false, E>
112112
: ValidationResult<true>;
113113

114-
export type ValidateRelationshipArray<
115-
FKs extends readonly AnyRelationshipDefinition[],
114+
export type ValidateRelationship<
115+
FKs extends Record<string, AnyRelationshipDefinition>,
116116
TableColumns extends string,
117117
ValidReferences extends string,
118-
> = FKs extends readonly []
118+
> = keyof FKs extends never
119119
? ValidationResult<true>
120120
: ValidateSingleRelationship<
121-
FKs[number],
121+
FKs[keyof FKs],
122122
TableColumns,
123123
ValidReferences
124124
> extends {
@@ -133,7 +133,7 @@ export type ValidateTableRelationships<
133133
ValidReferences extends string,
134134
> =
135135
Table extends TableSchemaComponent<infer _Columns, infer FKs>
136-
? ValidateRelationshipArray<
136+
? ValidateRelationship<
137137
FKs,
138138
TableColumnNames<Table> & string,
139139
ValidReferences

src/packages/dumbo/src/core/schema/components/relationships/relationshipValidation.type.spec.ts

Lines changed: 117 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ type _Test9 = Expect<
140140
const _validFK: RelationshipDefinition = {
141141
columns: ['user_id'],
142142
references: ['public.users.id'],
143+
type: 'one-to-one',
143144
};
144145

145146
type _ColumnsType = typeof _validFK.columns;
@@ -148,6 +149,7 @@ type _Test10 = Expect<Equal<_ColumnsType, readonly string[]>>;
148149
const _compositeFK: RelationshipDefinition = {
149150
columns: ['user_id', 'tenant_id'],
150151
references: ['public.users.id', 'public.users.tenant_id'],
152+
type: 'one-to-one',
151153
};
152154

153155
type _CompositeColumnsType = typeof _compositeFK.columns;
@@ -312,28 +314,30 @@ type _Test24A = Expect<
312314
>
313315
>;
314316

315-
import type { ValidateRelationshipArray } from './relationshipValidation';
317+
import type { ValidateRelationship } from './relationshipValidation';
316318

317-
type _FKArray_Mixed = readonly [
318-
{
319+
type _FKRecord_Mixed = {
320+
user_fk: {
319321
columns: ['user_id'];
320322
references: ['public.users.id'];
321-
},
322-
{
323+
type: 'one-to-many';
324+
};
325+
invalid_fk: {
323326
columns: ['invalid_col'];
324327
references: ['public.users.email'];
325-
},
326-
];
328+
type: 'one-to-many';
329+
};
330+
};
327331

328-
type _Result_FKArray_Mixed = ValidateRelationshipArray<
329-
_FKArray_Mixed,
332+
type _Result_FKRecord_Mixed = ValidateRelationship<
333+
_FKRecord_Mixed,
330334
'id' | 'user_id',
331335
'public.users.id' | 'public.users.email'
332336
>;
333337

334338
type _Test25A = Expect<
335339
Equal<
336-
_Result_FKArray_Mixed,
340+
_Result_FKRecord_Mixed,
337341
{
338342
valid: false;
339343
error:
@@ -342,31 +346,39 @@ type _Test25A = Expect<
342346
}
343347
>
344348
>;
345-
type _Test35 = Expect<IsError<_Result_FKArray_Mixed>>;
349+
type _Test35 = Expect<IsError<_Result_FKRecord_Mixed>>;
346350

347-
type _FKArray_AllValid = readonly [
348-
{
351+
type _FKRecord_AllValid = {
352+
user_fk: {
349353
columns: ['user_id'];
350354
references: ['public.users.id'];
351-
},
352-
{
355+
type: 'one-to-many';
356+
};
357+
email_fk: {
353358
columns: ['email'];
354359
references: ['public.users.email'];
355-
},
356-
];
360+
type: 'one-to-many';
361+
};
362+
};
357363

358-
type _Result_FKArray_AllValid = ValidateRelationshipArray<
359-
_FKArray_AllValid,
364+
type _Result_FKRecord_AllValid = ValidateRelationship<
365+
_FKRecord_AllValid,
360366
'id' | 'user_id' | 'email',
361367
'public.users.id' | 'public.users.email'
362368
>;
363-
type _ValidateRelationshipArrayResult_InvalidFK = ValidateRelationshipArray<
364-
[{ columns: ['invalid']; references: ['public.users.id'] }],
369+
type _ValidateRelationshipRecordResult_InvalidFK = ValidateRelationship<
370+
{
371+
invalid_fk: {
372+
columns: ['invalid'];
373+
references: ['public.users.id'];
374+
type: 'one-to-many';
375+
};
376+
},
365377
'id' | 'user_id',
366378
'public.users.id' | 'public.users.email'
367379
>;
368-
type _TestValidateRelationshipArrayResult_InvalidFK = Expect<
369-
IsError<_ValidateRelationshipArrayResult_InvalidFK>
380+
type _TestValidateRelationshipRecordResult_InvalidFK = Expect<
381+
IsError<_ValidateRelationshipRecordResult_InvalidFK>
370382
>;
371383

372384
import type { ValidateTableRelationships } from './relationshipValidation';
@@ -387,7 +399,13 @@ type _Table_SingleFK = TableSchemaComponent<
387399
id: AnyColumnSchemaComponent;
388400
user_id: AnyColumnSchemaComponent;
389401
},
390-
[{ columns: ['user_id']; references: ['public.users.id'] }]
402+
{
403+
author: {
404+
columns: ['user_id'];
405+
references: ['public.users.id'];
406+
type: 'one-to-many';
407+
};
408+
}
391409
>;
392410

393411
type _Result_SingleFK = ValidateTableRelationships<
@@ -402,10 +420,18 @@ type _Table_MultipleFK = TableSchemaComponent<
402420
user_id: AnyColumnSchemaComponent;
403421
author_id: AnyColumnSchemaComponent;
404422
},
405-
[
406-
{ columns: ['user_id']; references: ['public.users.id'] },
407-
{ columns: ['author_id']; references: ['public.users.id'] },
408-
]
423+
{
424+
user: {
425+
columns: ['user_id'];
426+
references: ['public.users.id'];
427+
type: 'one-to-many';
428+
};
429+
author: {
430+
columns: ['author_id'];
431+
references: ['public.users.id'];
432+
type: 'one-to-many';
433+
};
434+
}
409435
>;
410436

411437
type _Result_MultipleFK = ValidateTableRelationships<
@@ -419,7 +445,13 @@ type _Table_InvalidFK = TableSchemaComponent<
419445
id: AnyColumnSchemaComponent;
420446
user_id: AnyColumnSchemaComponent;
421447
},
422-
[{ readonly columns: ['id']; references: readonly ['public.users.id'] }]
448+
{
449+
user: {
450+
readonly columns: ['id'];
451+
references: readonly ['public.users.id'];
452+
type: 'one-to-many';
453+
};
454+
}
423455
>;
424456

425457
type _Result_InvalidFK = ValidateTableRelationships<
@@ -440,7 +472,13 @@ type _Schema_MultiTable = DatabaseSchemaSchemaComponent<{
440472
id: AnyColumnSchemaComponent;
441473
user_id: AnyColumnSchemaComponent;
442474
},
443-
[{ columns: ['user_id']; references: ['public.users.id'] }]
475+
{
476+
user: {
477+
columns: ['user_id'];
478+
references: ['public.users.id'];
479+
type: 'one-to-many';
480+
};
481+
}
444482
>;
445483
}>;
446484

@@ -456,7 +494,13 @@ type _Schema_WithError = DatabaseSchemaSchemaComponent<{
456494
id: AnyColumnSchemaComponent;
457495
user_id: AnyColumnSchemaComponent;
458496
},
459-
[{ columns: ['id']; references: ['public.users.id'] }]
497+
{
498+
user: {
499+
columns: ['user_id'];
500+
references: ['public.users.id'];
501+
type: 'one-to-many';
502+
};
503+
}
460504
>;
461505
}>;
462506

@@ -473,7 +517,13 @@ const _dbWithErrorVSInDB = database('test', {
473517
id: column('id', Varchar('max')),
474518
user_id: column('user_id', Varchar('max')),
475519
},
476-
relationships: [{ columns: ['id'], references: ['public.users.id'] }],
520+
relationships: {
521+
invalid: {
522+
columns: ['id'],
523+
references: ['public.users.id'],
524+
type: 'one-to-many',
525+
},
526+
},
477527
}),
478528
}),
479529
});
@@ -495,9 +545,13 @@ const _fullDb = database('test', {
495545
id: column('id', Varchar('max')),
496546
user_id: column('user_id', Varchar('max')),
497547
},
498-
relationships: [
499-
{ columns: ['user_id'], references: ['public.users.id'] },
500-
],
548+
relationships: {
549+
user: {
550+
type: 'many-to-one',
551+
columns: ['user_id'],
552+
references: ['public.users.id'],
553+
},
554+
},
501555
}),
502556
}),
503557
});
@@ -512,9 +566,13 @@ const _dbWithSelfRef = database('test', {
512566
id: column('id', Varchar('max')),
513567
manager_id: column('manager_id', Varchar('max')),
514568
},
515-
relationships: [
516-
{ columns: ['manager_id'], references: ['public.users.id'] },
517-
],
569+
relationships: {
570+
manager: {
571+
columns: ['manager_id'],
572+
references: ['public.users.id'],
573+
type: 'many-to-one',
574+
},
575+
},
518576
}),
519577
}),
520578
});
@@ -529,7 +587,13 @@ const _dbWithError = database('test', {
529587
id: column('id', Varchar('max')),
530588
user_id: column('user_id', Varchar('max')),
531589
},
532-
relationships: [{ columns: ['id'], references: ['public.users.id'] }],
590+
relationships: {
591+
invalid: {
592+
columns: ['id'],
593+
references: ['public.users.id'],
594+
type: 'many-to-one',
595+
},
596+
},
533597
}),
534598
}),
535599
});
@@ -544,7 +608,13 @@ const _dbInvalidColumn = database('test', {
544608
id: column('id', Varchar('max')),
545609
user_id: column('id', Varchar('max')),
546610
},
547-
relationships: [{ columns: ['id'], references: ['public.users.id'] }],
611+
relationships: {
612+
invalid: {
613+
columns: ['id'],
614+
references: ['public.users.id'],
615+
type: 'many-to-one',
616+
},
617+
},
548618
}),
549619
}),
550620
});
@@ -563,9 +633,13 @@ const _dbValid = database('test', {
563633
id: column('id', Varchar('max')),
564634
user_id: column('user_id', Varchar('max')),
565635
},
566-
relationships: [
567-
{ columns: ['user_id'], references: ['public.users.id'] },
568-
],
636+
relationships: {
637+
user: {
638+
columns: ['user_id'],
639+
references: ['public.users.id'],
640+
type: 'many-to-one',
641+
},
642+
},
569643
}),
570644
}),
571645
});

src/packages/dumbo/src/core/schema/components/tableSchemaComponent.ts

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
IndexURNType,
1313
type IndexSchemaComponent,
1414
} from './indexSchemaComponent';
15-
import type { RelationshipDefinition } from './relationships/relationshipTypes';
15+
import type { TableRelationships } from './relationships/relationshipTypes';
1616
import type { TableColumnNames } from './tableTypesInference';
1717

1818
export type TableURNType = 'sc:dumbo:table';
@@ -23,24 +23,11 @@ export const TableURN = ({ name }: { name: string }): TableURN =>
2323
`${TableURNType}:${name}`;
2424

2525
export type TableColumns = Record<string, AnyColumnSchemaComponent>;
26-
export type TableRelationships<
27-
Columns extends string = string,
28-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
29-
FKS extends RelationshipDefinition<Columns, any> = RelationshipDefinition<
30-
Columns,
31-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
32-
any
33-
>,
34-
> =
35-
FKS extends RelationshipDefinition<infer C, infer R>
36-
? readonly RelationshipDefinition<C, R>[]
37-
: never;
3826

3927
export type TableSchemaComponent<
4028
Columns extends TableColumns = TableColumns,
41-
Relationships extends TableRelationships<
42-
keyof Columns & string
43-
> = TableRelationships<keyof Columns & string>,
29+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
30+
Relationships extends TableRelationships<keyof Columns & string> = {},
4431
> = SchemaComponent<
4532
TableURN,
4633
Readonly<{
@@ -61,7 +48,8 @@ export type AnyTableSchemaComponent = TableSchemaComponent<any, any>;
6148

6249
export const tableSchemaComponent = <
6350
Columns extends TableColumns = TableColumns,
64-
const Relationships extends TableRelationships = TableRelationships,
51+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
52+
const Relationships extends TableRelationships<keyof Columns & string> = {},
6553
>({
6654
tableName,
6755
columns,

0 commit comments

Comments
 (0)