-
Notifications
You must be signed in to change notification settings - Fork 0
Improve structure and readability, split off from main.ts #6
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
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| // Magic getter constant | ||
| // This is used on custom property getters to mark them as ORM relation getters | ||
| export const ormRelationGetter = Symbol('ormRelationGetter'); | ||
|
|
||
| export function isOrmRelationGetter(object: any, property: string) { | ||
| const getter = Object.getOwnPropertyDescriptor(object, property)?.get; | ||
| if (getter == null) return false; | ||
| return ormRelationGetter in getter && getter[ormRelationGetter] != null && getter[ormRelationGetter] == true; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| import { BaseEntity } from "../entities/BaseEntity.js"; | ||
|
|
||
| export type BaseEntityDefinitions = Record<string, BaseEntity>; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| import { BaseEntityDefinitions } from "./BaseEntityDefinitions.js"; | ||
|
|
||
| // Entity helper types | ||
| export type EntityName<ED extends BaseEntityDefinitions> = keyof ED; | ||
| export type EntityDefinition<ED extends BaseEntityDefinitions> = ED[EntityName<ED>]; | ||
| export type EntityByName<ED extends BaseEntityDefinitions, K extends EntityName<ED>> = ED[K]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| // This type is an identity type: the output is identical to the input, except it forces the TypeScript compiler to evaluate the type | ||
| // Collapsing the type is useful both for performance reasons (it makes TypeScript horribly slow otherwise in some scenarios) | ||
| // and it has the added benefit of making the types much more readable in error messages and IDE inlay hints | ||
| // type EvalGeneric<X> = X extends infer C ? { [K in keyof C]: C[K] } : never; | ||
| export type EvalGeneric<X> = unknown extends X | ||
| ? X | ||
| : (X extends infer C ? { [K in keyof C]: C[K] } : never); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import { BaseEntityDefinitions } from "./BaseEntityDefinitions.js"; | ||
| import { EntityDefinition } from "./EntityTypes.js"; | ||
| import { IsNullable } from "./IsNullable.js"; | ||
|
|
||
| // Helper types to get field properties for a specific entity | ||
| export type Fields<ED extends BaseEntityDefinitions, E extends EntityDefinition<ED>> = E['fields']; | ||
| export type FieldNames<ED extends BaseEntityDefinitions, E extends EntityDefinition<ED>> = keyof Fields<ED, E>; | ||
| export type Field<ED extends BaseEntityDefinitions, E extends EntityDefinition<ED>, N extends FieldNames<ED, E>> = Fields<ED, E>[N]; | ||
| export type FieldType<ED extends BaseEntityDefinitions, E extends EntityDefinition<ED>, N extends FieldNames<ED, E>> = ReturnType<Field<ED, E, N>['toType']>; | ||
| export type FieldNullNever<ED extends BaseEntityDefinitions, E extends EntityDefinition<ED>, N extends FieldNames<ED, E>> = IsNullable<Field<ED, E, N>['nullableOnOutput']>; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| import { BaseEntityDefinitions } from "./BaseEntityDefinitions.js"; | ||
| import { EntityByName, EntityDefinition } from "./EntityTypes.js"; | ||
| import { EvalGeneric } from "./EvalGeneric.js"; | ||
| import { FieldType } from "./FieldTypes.js"; | ||
| import { OutputTypeRef } from "./OutputType.js"; | ||
| import { WithOptionalId } from "./WithOptionalId.js"; | ||
|
|
||
| // Define input type for save functions | ||
| type InputTypeFields<ED extends BaseEntityDefinitions, E extends EntityDefinition<ED>> = | ||
| { -readonly [N in keyof E['fields'] as E['fields'][N]['nullableOnInput'] extends true ? never : N]: FieldType<ED, E, N> } // mandatory properties | ||
| & { -readonly [N in keyof E['fields'] as E['fields'][N]['nullableOnInput'] extends true ? N : never]?: FieldType<ED, E, N> | null | undefined }; // optionals | ||
|
|
||
| type InputTypeOneToOneOwned<ED extends BaseEntityDefinitions, E extends EntityDefinition<ED>> = | ||
| { -readonly [N in keyof E['oneToOneOwned'] as E['oneToOneOwned'][N]['nullable'] extends true ? never : N]: OutputTypeRef<ED, EntityByName<ED, E['oneToOneOwned'][N]['entity']>> } // mandatory properties | ||
| & { -readonly [N in keyof E['oneToOneOwned'] as E['oneToOneOwned'][N]['nullable'] extends true ? N : never]?: OutputTypeRef<ED, EntityByName<ED, E['oneToOneOwned'][N]['entity']>> | null | undefined }; // optionals | ||
|
|
||
| type InputTypeManyToOne<ED extends BaseEntityDefinitions, E extends EntityDefinition<ED>> = | ||
| { -readonly [N in keyof E['manyToOne'] as E['manyToOne'][N]['nullable'] extends true ? never : N]: OutputTypeRef<ED, EntityByName<ED, E['manyToOne'][N]['entity']>> } // mandatory properties | ||
| & { -readonly [N in keyof E['manyToOne'] as E['manyToOne'][N]['nullable'] extends true ? N : never]?: OutputTypeRef<ED, EntityByName<ED, E['manyToOne'][N]['entity']>> | null | undefined }; // optionals | ||
|
|
||
| export type InputTypeWithId<ED extends BaseEntityDefinitions, E extends EntityDefinition<ED>> = | ||
| InputTypeFields<ED, E> & InputTypeOneToOneOwned<ED, E> & InputTypeManyToOne<ED, E> & { | ||
| -readonly [N in keyof E['oneToOneInverse']]?: any /* Allow feeding something, but we don't care what exactly since we won't save it. We could narrow this to identical to OutputType<> */ | ||
| } & { | ||
| -readonly [N in keyof E['oneToMany']]?: any /* Allow feeding something, but we don't care what exactly since we won't save it. We could narrow this to identical to OutputType<> */ | ||
| }; | ||
|
|
||
| export type InputType<ED extends BaseEntityDefinitions, E extends EntityDefinition<ED>> = EvalGeneric<WithOptionalId<InputTypeWithId<ED, E>>>; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export type IsNullable<T extends boolean> = T extends true ? null : never; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import { BaseEntityDefinitions } from "./BaseEntityDefinitions.js"; | ||
| import { EntityByName, EntityDefinition } from "./EntityTypes.js"; | ||
| import { EvalGeneric } from "./EvalGeneric.js"; | ||
| import { FieldNullNever, FieldType } from "./FieldTypes.js"; | ||
| import { IsNullable } from "./IsNullable.js"; | ||
|
|
||
| // Prep the output type for a specific entity | ||
| // Defines a type for every field on a given entity, including correctly nullability setting | ||
| // Defines the types for all relations, which will something like Promise<TargetEntity> or Promise<TargetEntity[]>, depending on the relation type, with correct nullability | ||
| export type OutputType<ED extends BaseEntityDefinitions, E extends EntityDefinition<ED>> = EvalGeneric<{ | ||
| -readonly [N in keyof E['fields']]: FieldType<ED, E, N> | FieldNullNever<ED, E, N> | ||
| } & { | ||
| -readonly [N in keyof E['oneToOneOwned']]: Promise<OutputType<ED, EntityByName<ED, E['oneToOneOwned'][N]['entity']>>> | IsNullable<E['oneToOneOwned'][N]['nullable']> | ||
| } & { | ||
| -readonly [N in keyof E['oneToOneInverse']]: Promise<OutputType<ED, EntityByName<ED, E['oneToOneInverse'][N]['entity']>> | IsNullable<E['oneToOneInverse'][N]['nullable']>> | ||
goldenice marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } & { | ||
| -readonly [N in keyof E['manyToOne']]: Promise<OutputType<ED, EntityByName<ED, E['manyToOne'][N]['entity']>>> | IsNullable<E['manyToOne'][N]['nullable']> | ||
| } & { | ||
| [N in keyof E['oneToMany']]: Promise<OutputType<ED, EntityByName<ED, E['oneToMany'][N]['entity']>>[]> | ||
| }>; | ||
|
|
||
| export type OutputTypeRef<ED extends BaseEntityDefinitions, E extends EntityDefinition<ED>> = Promise<OutputType<ED, E>> | OutputType<ED, E>; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import { CamelToSnakeCase, IdSuffixed } from "../util/strings.js"; | ||
| import { BaseEntityDefinitions } from "./BaseEntityDefinitions.js"; | ||
| import { EntityDefinition } from "./EntityTypes.js"; | ||
| import { IsNullable } from "./IsNullable.js"; | ||
|
|
||
| // Construct the RawSqlType, which is a type definition that encompasses what is returned from a SQL-query | ||
| // Currently any types for OneToMany relations that aren't defined as a ManyToOne on the other side are missing | ||
| // (e.g if B defines a OneToMany to A, then A will not have a field for this relation, even though in reality there will be a b_id column in the table for A) | ||
| // The clunky N extends string stuff is to ensure TypeScript does not get confused. Even though the keys of FieldNames<> and such are always strings, | ||
| // for some reason TS tries to use the default key type (symbol | number | string) instead of the more narrow string we know it to be. | ||
| export type RawSqlType<ED extends BaseEntityDefinitions, E extends EntityDefinition<ED>> = { | ||
| -readonly [N in keyof E['fields'] as CamelToSnakeCase<Extract<N, string>>]: ReturnType<E['fields'][N]['toType']> | IsNullable<E['fields'][N]['nullableOnOutput']> | ||
| } & { | ||
| -readonly [N in keyof E['oneToOneOwned'] as IdSuffixed<CamelToSnakeCase<Extract<N, string>>>]: number | IsNullable<E['oneToOneOwned'][N]['nullable']> | ||
| } & { | ||
| -readonly [N in keyof E['manyToOne'] as IdSuffixed<CamelToSnakeCase<Extract<N, string>>>]: number | IsNullable<E['manyToOne'][N]['nullable']> | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export type WithOptionalId<X extends {}> = Omit<X, 'id'> & { id?: string | null }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| export function strictKeysOfObject<T extends object>(input: T): Array<keyof T> { | ||
| return Object.keys(input) as any; | ||
goldenice marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.