@typetron/framework 0.5.0 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/build/Database/EntityProxyHandler.js +2 -2
  2. package/build/Database/EntityProxyHandler.js.map +1 -1
  3. package/package.json +4 -7
  4. package/.eslintrc-old.js +0 -208
  5. package/Cache/Cache.ts +0 -13
  6. package/Cache/Stores/DatabaseStore.ts +0 -120
  7. package/Cache/Stores/FileStore.ts +0 -69
  8. package/Cache/Stores/MemoryStore.ts +0 -71
  9. package/Cache/index.ts +0 -5
  10. package/Cache/types.ts +0 -4
  11. package/Container/ClassResolver.ts +0 -106
  12. package/Container/Container.ts +0 -144
  13. package/Container/Contracts.ts +0 -3
  14. package/Container/Decorators.ts +0 -20
  15. package/Container/Metadata.ts +0 -16
  16. package/Container/Resolver.ts +0 -27
  17. package/Container/index.ts +0 -5
  18. package/Database/Clauses/Where.ts +0 -0
  19. package/Database/Connection.ts +0 -52
  20. package/Database/Decorators.ts +0 -142
  21. package/Database/Drivers/DatabaseDriver.ts +0 -37
  22. package/Database/Drivers/MySQL/Alter/index.ts +0 -55
  23. package/Database/Drivers/MySQL/ColumnDefinition.ts +0 -16
  24. package/Database/Drivers/MySQL/Create.ts +0 -47
  25. package/Database/Drivers/MySQL/MysqlDriver.ts +0 -123
  26. package/Database/Drivers/MySQL/Schema.ts +0 -82
  27. package/Database/Drivers/MySQL/index.ts +0 -13
  28. package/Database/Drivers/SQL/Schema.ts +0 -73
  29. package/Database/Drivers/SQL/Statements/Alter.ts +0 -22
  30. package/Database/Drivers/SQL/Statements/BaseStatement.ts +0 -55
  31. package/Database/Drivers/SQL/Statements/Delete.ts +0 -20
  32. package/Database/Drivers/SQL/Statements/Insert.ts +0 -24
  33. package/Database/Drivers/SQL/Statements/Select.ts +0 -55
  34. package/Database/Drivers/SQL/Statements/Update.ts +0 -33
  35. package/Database/Drivers/SQL/index.ts +0 -8
  36. package/Database/Drivers/SQLite/Create.ts +0 -45
  37. package/Database/Drivers/SQLite/Schema.ts +0 -54
  38. package/Database/Drivers/SQLite/SqliteDriver.ts +0 -144
  39. package/Database/Drivers/SQLite/index.ts +0 -15
  40. package/Database/Drivers/SchemaContract.ts +0 -11
  41. package/Database/Drivers/Statement.ts +0 -16
  42. package/Database/Drivers/index.ts +0 -4
  43. package/Database/Entity.ts +0 -377
  44. package/Database/EntityNotFoundError.ts +0 -5
  45. package/Database/EntityProxyHandler.ts +0 -43
  46. package/Database/EntityQuery.ts +0 -197
  47. package/Database/Expression.ts +0 -3
  48. package/Database/Fields.ts +0 -816
  49. package/Database/Helpers.ts +0 -12
  50. package/Database/List.ts +0 -71
  51. package/Database/Migrations/Migration.ts +0 -10
  52. package/Database/Migrations/MigrationHistory.ts +0 -20
  53. package/Database/Migrations/Migrator.ts +0 -122
  54. package/Database/Migrations/index.ts +0 -3
  55. package/Database/ORM/BaseRelationship.ts +0 -10
  56. package/Database/Query.ts +0 -374
  57. package/Database/Seeders/Seeder.ts +0 -3
  58. package/Database/Seeders/SeederManager.ts +0 -27
  59. package/Database/Seeders/index.ts +0 -2
  60. package/Database/StringExpression.ts +0 -9
  61. package/Database/Types.ts +0 -165
  62. package/Database/index.ts +0 -23
  63. package/Encryption/index.ts +0 -51
  64. package/Forms/Decorators.ts +0 -29
  65. package/Forms/Form.ts +0 -70
  66. package/Forms/FormFields.ts +0 -36
  67. package/Forms/index.ts +0 -3
  68. package/Framework/App.ts +0 -10
  69. package/Framework/Application.ts +0 -118
  70. package/Framework/Auth/Auth.ts +0 -122
  71. package/Framework/Auth/Authenticatable.ts +0 -9
  72. package/Framework/Auth/User.ts +0 -27
  73. package/Framework/Auth/index.ts +0 -29
  74. package/Framework/Config/AppConfig.ts +0 -25
  75. package/Framework/Config/AuthConfig.ts +0 -9
  76. package/Framework/Config/BaseConfig.ts +0 -9
  77. package/Framework/Config/CacheConfig.ts +0 -38
  78. package/Framework/Config/DatabaseConfig.ts +0 -21
  79. package/Framework/Config/MailConfig.ts +0 -30
  80. package/Framework/Config/index.ts +0 -6
  81. package/Framework/Middleware/AuthMiddleware.ts +0 -31
  82. package/Framework/Middleware/CorsMiddleware.ts +0 -32
  83. package/Framework/Middleware/StaticAssetsMiddleware.ts +0 -76
  84. package/Framework/Middleware/index.ts +0 -2
  85. package/Framework/Provider.ts +0 -9
  86. package/Framework/Providers/CacheProvider.ts +0 -28
  87. package/Framework/Providers/DatabaseProvider.ts +0 -36
  88. package/Framework/Providers/MailProvider.ts +0 -31
  89. package/Framework/Providers/WebsocketsProvider.ts +0 -120
  90. package/Framework/Resolvers/AuthResolver.ts +0 -23
  91. package/Framework/Resolvers/EntityResolver.ts +0 -41
  92. package/Framework/Resolvers/FormResolver.ts +0 -37
  93. package/Framework/RootDir.ts +0 -1
  94. package/Framework/index.ts +0 -8
  95. package/Frontend/Angular/index.ts +0 -24
  96. package/Frontend/Websockets/index.ts +0 -86
  97. package/Mail/MailAddress.ts +0 -4
  98. package/Mail/MailTransport.ts +0 -6
  99. package/Mail/Mailable.ts +0 -16
  100. package/Mail/Mailer.ts +0 -27
  101. package/Mail/PendingMail.ts +0 -68
  102. package/Mail/SentMessage.ts +0 -20
  103. package/Mail/Transports/MemoryTransport.ts +0 -13
  104. package/Mail/Transports/SendGridTransport.ts +0 -95
  105. package/Mail/index.ts +0 -3
  106. package/Models/Model.ts +0 -41
  107. package/Models/index.ts +0 -54
  108. package/Router/BaseController.ts +0 -7
  109. package/Router/Decorators.ts +0 -224
  110. package/Router/Guard.ts +0 -10
  111. package/Router/Http/Contracts.ts +0 -4
  112. package/Router/Http/ErrorHandler.ts +0 -45
  113. package/Router/Http/ErrorHandlerInterface.ts +0 -6
  114. package/Router/Http/Errors/HttpError.ts +0 -15
  115. package/Router/Http/Handler.ts +0 -183
  116. package/Router/Http/HttpRoute.ts +0 -110
  117. package/Router/Http/Middleware.ts +0 -7
  118. package/Router/Http/Request.ts +0 -225
  119. package/Router/Http/Response.ts +0 -35
  120. package/Router/Http/index.ts +0 -85
  121. package/Router/Metadata.ts +0 -34
  122. package/Router/Middleware.ts +0 -16
  123. package/Router/Request.ts +0 -65
  124. package/Router/Route.ts +0 -16
  125. package/Router/RouteNotFoundError.ts +0 -5
  126. package/Router/Router.ts +0 -35
  127. package/Router/Servers/index.ts +0 -6
  128. package/Router/Servers/node.ts +0 -49
  129. package/Router/Servers/uNetworking.ts +0 -151
  130. package/Router/Websockets/Handler.ts +0 -82
  131. package/Router/Websockets/Middleware.ts +0 -7
  132. package/Router/Websockets/Request.ts +0 -3
  133. package/Router/Websockets/WebsocketRoute.ts +0 -61
  134. package/Router/Websockets/index.ts +0 -57
  135. package/Router/Websockets/types.ts +0 -23
  136. package/Router/index.ts +0 -6
  137. package/Storage/File.ts +0 -30
  138. package/Storage/Image.ts +0 -19
  139. package/Storage/InvalidImage.ts +0 -3
  140. package/Storage/Storage.ts +0 -98
  141. package/Storage/index.ts +0 -4
  142. package/Storage/utils.ts +0 -18
  143. package/Support/Array.ts +0 -184
  144. package/Support/Math.ts +0 -12
  145. package/Support/Metadata.ts +0 -31
  146. package/Support/String.ts +0 -38
  147. package/Support/index.ts +0 -19
  148. package/Support/utils.ts +0 -7
  149. package/Testing/TestCase.ts +0 -193
  150. package/Validation/Rule.ts +0 -9
  151. package/Validation/RuleInterface.ts +0 -10
  152. package/Validation/Rules/Email.ts +0 -20
  153. package/Validation/Rules/FileExtension.ts +0 -21
  154. package/Validation/Rules/MaxLength.ts +0 -17
  155. package/Validation/Rules/MinLength.ts +0 -18
  156. package/Validation/Rules/Optional.ts +0 -18
  157. package/Validation/Rules/Required.ts +0 -29
  158. package/Validation/Validator.ts +0 -7
  159. package/Validation/index.ts +0 -12
  160. package/benchmark-index.js +0 -20
  161. package/benchmark.ts +0 -47
  162. package/tests/Cache/DatabaseStoreTest.ts +0 -110
  163. package/tests/Cache/FileStoreTest.ts +0 -93
  164. package/tests/Cache/MemoryStoreTest.ts +0 -92
  165. package/tests/Container/ContainerTest.ts +0 -336
  166. package/tests/Database/Drivers/MySQL/AlterTest.ts +0 -100
  167. package/tests/Database/Drivers/MySQL/CreateTest.ts +0 -39
  168. package/tests/Database/Drivers/MysqlDriverTest.ts +0 -140
  169. package/tests/Database/Drivers/SqliteDriverTest.ts +0 -126
  170. package/tests/Database/Entities/Article.ts +0 -21
  171. package/tests/Database/Entities/Profile.ts +0 -21
  172. package/tests/Database/Entities/Role.ts +0 -15
  173. package/tests/Database/Entities/User.ts +0 -35
  174. package/tests/Database/EntityRelationshipsTest.ts +0 -475
  175. package/tests/Database/EntityTest.ts +0 -202
  176. package/tests/Database/Migrations/RunnerTest.ts +0 -96
  177. package/tests/Database/Migrations/migrations/1.createUserTable.ts +0 -12
  178. package/tests/Database/Migrations/migrations/2.createArticlesTable.ts +0 -12
  179. package/tests/Database/QueryTest.ts +0 -573
  180. package/tests/Database/SchemaTest.ts +0 -32
  181. package/tests/Database/Seeders/RunnerTest.ts +0 -30
  182. package/tests/Database/Seeders/seeders/RandomSeeder.ts +0 -10
  183. package/tests/Database/utils.ts +0 -16
  184. package/tests/Forms/FormsTest.ts +0 -59
  185. package/tests/Framework/Middleware/StaticAssetsMiddlewareTest.ts +0 -129
  186. package/tests/Framework/Resolvers/EntityResolverTest.ts +0 -48
  187. package/tests/Framework/Router/RouterTest.ts +0 -33
  188. package/tests/Mail/MailerTest.ts +0 -76
  189. package/tests/Model/ModelTest.ts +0 -183
  190. package/tests/Router/HttpHandlerTest.ts +0 -72
  191. package/tests/Router/RequestTest.ts +0 -77
  192. package/tests/Router/WebSocketsHandlerTest.ts +0 -51
  193. package/tests/Storage/StorageTest.ts +0 -97
  194. package/tests/Support/ArrayTest.ts +0 -167
  195. package/tests/Support/StringTest.ts +0 -18
  196. package/tests/Validation/RulesTest.ts +0 -54
  197. package/types.d.ts +0 -8
@@ -1,144 +0,0 @@
1
- import { Database } from 'sqlite3'
2
- import { SqlValue } from '../../Types'
3
- import { DatabaseDriver } from '../DatabaseDriver'
4
- import { Select } from '../SQL/Statements/Select'
5
- import { Insert } from '../SQL/Statements/Insert'
6
- import { Delete } from '../SQL/Statements/Delete'
7
- import { Update } from '../SQL/Statements/Update'
8
- import { Alter } from '../SQL/Statements/Alter'
9
- import { Schema } from './Schema'
10
- import { SchemaContract } from '../SchemaContract'
11
- import { wrap } from '../../Helpers'
12
- import { Create } from './Create'
13
-
14
- interface ColumnInfo {
15
- name: string
16
- type: string
17
- notnull: string
18
- dflt_value: string
19
- pk: string
20
- }
21
-
22
- export class SqliteDriver implements DatabaseDriver {
23
- database: Database
24
-
25
- schema: SchemaContract = new Schema(this)
26
-
27
- statements = {
28
- create: Create,
29
- select: Select,
30
- insert: Insert,
31
- delete: Delete,
32
- update: Update,
33
- alter: Alter,
34
- }
35
-
36
- constructor(databaseFilePath: string) {
37
- this.database = new Database(databaseFilePath)
38
- }
39
-
40
- async run(query: string, params: SqlValue[] = []): Promise<void> {
41
- return new Promise((resolve, reject) => {
42
- const appError = new Error()
43
- this.database.run(query, params, (error) => {
44
- if (error) {
45
- return reject(this.buildError(appError, error, query))
46
- }
47
-
48
- resolve()
49
- })
50
- })
51
- }
52
-
53
- async insertOne(query: string, params: SqlValue[] = []): Promise<number> {
54
- await this.run(query, params)
55
- return this.lastInsertedId()
56
- }
57
-
58
- async truncate(table: string) {
59
- await this.run(`DELETE
60
- FROM ${table}`)
61
- return this.run(`DELETE
62
- FROM SQLITE_SEQUENCE
63
- WHERE name = '${table}'`)
64
- }
65
-
66
- async lastInsertedId(): Promise<number> {
67
- return new Promise<number>((resolve, reject) => {
68
- const appError = new Error()
69
- const query = 'SELECT last_insert_rowid() as id;'
70
- this.database.get(query, [], (error, lastInsert: any) => {
71
- if (error) {
72
- return reject(this.buildError(appError, error, query))
73
- }
74
- resolve(lastInsert.id)
75
- })
76
- })
77
- }
78
-
79
- async get<T>(query: string, params: SqlValue[] = []): Promise<T[]> {
80
- return new Promise<T[]>((resolve, reject) => {
81
- const appError = new Error()
82
- this.database.all(query, params, (error, rows: any) => {
83
- if (error) {
84
- return reject(this.buildError(appError, error, query))
85
- }
86
- resolve(rows)
87
- })
88
- })
89
- }
90
-
91
- async first<T>(query: string, params: SqlValue[] = []): Promise<T> {
92
- return new Promise<T>((resolve, reject) => {
93
- const appError = new Error()
94
- this.database.get(query, params, (error, row: any) => {
95
- if (error) {
96
- return reject(this.buildError(appError, error, query))
97
- }
98
- resolve(row)
99
- })
100
- })
101
- }
102
-
103
- buildError(appError: Error, databaseError: Error, query?: string) {
104
- appError.message = `${databaseError} in '${query}' `
105
- // appError.stack = appError.stack?.replace('Error:', `${appError.message}`)
106
- return appError
107
- }
108
-
109
- tables() {
110
- return this.get<{name: string}>(
111
- `SELECT name
112
- FROM sqlite_master
113
- WHERE type = 'table'`
114
- )
115
- }
116
-
117
- tableExists(table: string): Promise<boolean> {
118
- return this.first(
119
- `SELECT *
120
- FROM sqlite_master
121
- WHERE name = ?`,
122
- [table]
123
- )
124
- }
125
-
126
- async tableColumns(table: string) {
127
- const columnsInfo = await this.get<ColumnInfo>(
128
- `PRAGMA table_info(${wrap(table)})`
129
- )
130
- const autoIncrements = await this.get<{name: string; seq: number}>(`
131
- SELECT *
132
- FROM sqlite_sequence
133
- `)
134
-
135
- return columnsInfo.map((info) => ({
136
- name: info.name,
137
- type: info.type,
138
- nullable: !info.notnull,
139
- default: info.dflt_value,
140
- autoIncrement: Number(Boolean(autoIncrements.findWhere('name', table))),
141
- primaryKey: Boolean(info.pk),
142
- }))
143
- }
144
- }
@@ -1,15 +0,0 @@
1
- import { Entity } from '../../Entity'
2
- import { JSONField, PrimaryField } from '../../Fields'
3
-
4
- export * from './SqliteDriver'
5
-
6
- // tslint:disable-next-line:no-any
7
- export const typesMatches = new Map<any, string>([
8
- [Entity, 'integer'],
9
- [PrimaryField, `integer`],
10
- [Number, 'integer'],
11
- [String, 'varchar(255)'],
12
- [Date, 'datetime'],
13
- [JSONField, 'text'],
14
- [Boolean, 'integer'],
15
- ])
@@ -1,11 +0,0 @@
1
- import { ColumnField, Entity, EntityMetadata } from '..'
2
- import { DatabaseDriver } from './DatabaseDriver'
3
-
4
- export abstract class SchemaContract {
5
- constructor(public driver: DatabaseDriver) {}
6
-
7
- abstract create(table: string, columns: ColumnField<Entity>[]): Promise<void>
8
-
9
- abstract synchronize(entitiesMetadata: EntityMetadata<Entity, Entity>[]): Promise<void>
10
-
11
- }
@@ -1,16 +0,0 @@
1
- import { Components, SqlValue } from '../Types'
2
- import { StringExpression } from '../StringExpression'
3
-
4
- export abstract class Statement extends StringExpression {
5
- bindings: SqlValue[] = []
6
-
7
- constructor(public components: Components) {
8
- super('')
9
- }
10
-
11
- abstract toSQL(): string;
12
-
13
- toString() {
14
- return this.toSQL()
15
- }
16
- }
@@ -1,4 +0,0 @@
1
- export * from './SQLite/SqliteDriver'
2
- export * from './MySQL/MysqlDriver'
3
- export * from './Statement'
4
- export * from './SchemaContract'
@@ -1,377 +0,0 @@
1
- import { EntityProxyHandler } from './EntityProxyHandler'
2
- import { EntityQuery } from './EntityQuery'
3
- import { ChildObject, KeysOfType } from '../Support'
4
- import { EntityMetadata, EntityMetadataKey, ID } from './Decorators'
5
- import { EntityNotFoundError } from './EntityNotFoundError'
6
- import { BelongsTo, BelongsToMany, ColumnField, HasMany, HasOne, InverseField } from './Fields'
7
- import { BooleanOperator, Direction, Operator, WhereFunction, WhereValue } from './Types'
8
- import { DotNotationProperties, EntityConstructor, EntityKeys, EntityObject } from './index'
9
- import { Query } from './Query'
10
- import { List } from './List'
11
-
12
- export abstract class Entity {
13
-
14
- exists = false
15
- // tslint:disable-next-line:no-any
16
- original: Record<string, any> = {}
17
-
18
- constructor() {
19
- const entityProxyHandler = new EntityProxyHandler<this>()
20
- const proxy = new Proxy(this, entityProxyHandler)
21
-
22
- // Weird JS issues: "filling" an instance with data is not possible since the default values of child entities
23
- // are assigned after the constructor of base class (this constructor exactly) is called.
24
- // Calling "proxy.fill will update the instance but then the default values will overwrite them"
25
- // proxy.fill(this.original = data || {})
26
-
27
- return proxy
28
- }
29
-
30
- static get metadata(): EntityMetadata<Entity, Entity> {
31
- return Reflect.getMetadata(EntityMetadataKey, this.prototype) ?? new EntityMetadata<Entity, Entity>()
32
- }
33
-
34
- get metadata(): EntityMetadata<Entity, Entity> {
35
- return this.static.metadata
36
- }
37
-
38
- get static(): EntityConstructor<this> {
39
- return this.constructor as EntityConstructor<this>
40
- }
41
-
42
- static where<T extends Entity, K extends EntityKeys<T>>(
43
- this: EntityConstructor<T>,
44
- column: EntityKeys<T>,
45
- operator: Operator | Query | WhereValue | T[K],
46
- value?: Query | WhereValue | T[K],
47
- boolean?: BooleanOperator
48
- ): EntityQuery<T> {
49
- const columnMetadata = {
50
- ...this.metadata.columns,
51
- ...this.metadata.relationships
52
- }[column as string]
53
- return this.newQuery().where(columnMetadata.column, operator, value, boolean)
54
- }
55
-
56
- static whereIn<T extends Entity, K extends EntityKeys<T>>(
57
- this: EntityConstructor<T>,
58
- column: EntityKeys<T>,
59
- value: Query | WhereValue[] | T[K][],
60
- boolean?: BooleanOperator
61
- ): EntityQuery<T> {
62
- const columnMetadata = {
63
- ...this.metadata.columns,
64
- ...this.metadata.relationships
65
- }[column as string]
66
- return this.newQuery().whereIn(columnMetadata.column, value, boolean)
67
- }
68
-
69
- static whereNotIn<T extends Entity, K extends EntityKeys<T>>(
70
- this: EntityConstructor<T>,
71
- column: EntityKeys<T>,
72
- value: Query | WhereFunction | WhereValue[] | T[K][]
73
- ): EntityQuery<T> {
74
- const columnMetadata = {
75
- ...this.metadata.columns,
76
- ...this.metadata.relationships
77
- }[column as string]
78
- return this.newQuery().whereNotIn(columnMetadata.column, value)
79
- }
80
-
81
- static whereLike<T extends Entity, K extends EntityKeys<T>>(
82
- this: EntityConstructor<T>,
83
- column: EntityKeys<T>,
84
- value?: WhereValue | T[K],
85
- boolean?: BooleanOperator
86
- ): EntityQuery<T> {
87
- const columnMetadata = {
88
- ...this.metadata.columns,
89
- ...this.metadata.relationships
90
- }[column as string]
91
- return this.newQuery().whereLike(columnMetadata.column, value as WhereValue, boolean)
92
- }
93
-
94
- static async first<T extends Entity, K extends EntityKeys<T>>(
95
- this: EntityConstructor<T>,
96
- ...columns: EntityKeys<T>[]
97
- ): Promise<T | undefined> {
98
- return this.newQuery().first(...columns)
99
- }
100
-
101
- // static first2: <T extends Entity>(this: EntityConstructor<T>, ...params: Parameters<Query<T>['first']>) => Query<T>['first'];
102
-
103
- // tslint:disable-next-line:no-any
104
- static async firstOrNew<T extends Entity, K extends keyof Entity>(
105
- this: EntityConstructor<T>,
106
- properties: Partial<EntityObject<T>>,
107
- values?: Partial<EntityObject<T>>
108
- ): Promise<T> {
109
- return this.newQuery().firstOrNew(properties, values)
110
- }
111
-
112
- // tslint:disable-next-line:no-any
113
- static async firstOrCreate<T extends Entity, K extends keyof Entity>(
114
- this: EntityConstructor<T>,
115
- properties: Partial<EntityObject<T>>,
116
- values?: Partial<EntityObject<T>>
117
- ): Promise<T> {
118
- return (await this.firstOrNew(properties, values)).save()
119
- }
120
-
121
- static orderBy<T extends Entity, K extends EntityKeys<T>>(
122
- this: EntityConstructor<T>,
123
- column: EntityKeys<T>,
124
- direction?: Direction
125
- ): EntityQuery<T> {
126
- return this.newQuery().orderBy(column, direction)
127
- }
128
-
129
- static getTable<T extends Entity>(this: EntityConstructor<T>): string {
130
- return this.metadata.table || this.name.toLowerCase() // TODO make metadata.table un-optional
131
- }
132
-
133
- static new<T extends Entity, K extends keyof T>(
134
- this: EntityConstructor<T>,
135
- data: Partial<ChildObject<T, Entity>> | {},
136
- exists = false
137
- ): T {
138
- const instance = new (this as any)()
139
- instance.fill(instance.original = data)
140
- instance.exists = exists
141
-
142
- return instance
143
- }
144
-
145
- static create<T extends Entity>(this: EntityConstructor<T>, data?: ChildObject<T, Entity> | {}): Promise<T> {
146
- return this.new(data ?? {}).save()
147
- }
148
-
149
- static async insert<T extends Entity>(this: EntityConstructor<T>, data: (ChildObject<T, Entity> | {})[]): Promise<void> {
150
- const dataToSave = data.map(piece => {
151
- const instance = this.new(piece)
152
- return instance.getDataToSave(piece)
153
- })
154
-
155
- const query = this.newQuery()
156
-
157
- await query.insert(dataToSave)
158
- }
159
-
160
- static async get<T extends Entity>(this: EntityConstructor<T>, ...columns: EntityKeys<T> []): Promise<T[]> {
161
- return this.newQuery().get(...columns)
162
- }
163
-
164
- static with<T extends Entity>(
165
- this: EntityConstructor<T>,
166
- ...relations: (
167
- // tslint:disable-next-line:no-any
168
- KeysOfType<T, BelongsTo<any> | HasOne<any> | HasMany<any> | BelongsToMany<any>> | DotNotationProperties<T> |
169
- // tslint:disable-next-line:no-any max-line-length
170
- [KeysOfType<T, BelongsTo<any> | HasOne<any> | HasMany<any> | BelongsToMany<any>> | DotNotationProperties<T>, (Query: EntityQuery<any>) => void]
171
- )[]
172
- ) {
173
- return this.newQuery().with(...relations)
174
- }
175
-
176
- static withCount<T extends Entity, K extends KeysOfType<T, List<Entity>>>(
177
- this: EntityConstructor<T>,
178
- ...relations: (
179
- // tslint:disable-next-line:no-any
180
- KeysOfType<T, BelongsTo<any> | HasOne<any> | HasMany<any> | BelongsToMany<any>> | DotNotationProperties<T> |
181
- // tslint:disable-next-line:no-any max-line-length
182
- [KeysOfType<T, BelongsTo<any> | HasOne<any> | HasMany<any> | BelongsToMany<any>> | DotNotationProperties<T>, (Query: EntityQuery<any>) => void]
183
- )[]
184
- ) {
185
- return this.newQuery().withCount(...relations)
186
- }
187
-
188
- static async find<T extends Entity>(this: EntityConstructor<T>, id: string | number | ID): Promise<T | undefined> {
189
- return this.newQuery().where('id' as keyof T, id as number).first()
190
- }
191
-
192
- static async findOrFail<T extends Entity>(this: EntityConstructor<T>, id: string | number | ID): Promise<T> {
193
- const query = this.newQuery().where('id' as keyof T, id as number)
194
- const instance = await query.first()
195
- if (!instance || !Object.entries(instance).length) {
196
- throw new EntityNotFoundError(this, `No records found for entity '${this.name}' when querying with parameters [${query.getBindings().join(', ')}]`)
197
- }
198
- return instance
199
- }
200
-
201
- static getPrimaryKey<T extends Entity>(): EntityKeys<T> {
202
- return 'id' as EntityKeys<T>
203
- }
204
-
205
- static hydrate<T extends Entity>(modelType: EntityConstructor<T>, models: Partial<ChildObject<T, Entity>>[], exist = false) {
206
- return models.map(data => {
207
- return modelType.new(data, exist)
208
- })
209
- }
210
-
211
- static newQuery<T extends Entity>(this: EntityConstructor<T>): EntityQuery<T> {
212
- return (new EntityQuery(this)).table(this.getTable()) as EntityQuery<T>
213
- }
214
-
215
- getTable(): string {
216
- return this.static.getTable()
217
- }
218
-
219
- async load(
220
- ...relations: (
221
- // tslint:disable-next-line:no-any
222
- KeysOfType<this, BelongsTo<any> | HasOne<any> | HasMany<any> | BelongsToMany<any>> | DotNotationProperties<this> |
223
- // tslint:disable-next-line:no-any max-line-length
224
- [KeysOfType<this, BelongsTo<any> | HasOne<any> | HasMany<any> | BelongsToMany<any>> | DotNotationProperties<this>, (Query: EntityQuery<any>) => void]
225
- )[]
226
- ) {
227
- await this.newQuery().with(...relations).eagerLoadRelationships([this])
228
-
229
- return this
230
- }
231
-
232
- async loadCount<K extends KeysOfType<this, List<Entity>>>(
233
- ...relations: (
234
- // tslint:disable-next-line:no-any
235
- KeysOfType<this, BelongsTo<any> | HasOne<any> | HasMany<any> | BelongsToMany<any>> | DotNotationProperties<this> |
236
- // tslint:disable-next-line:no-any max-line-length
237
- [KeysOfType<this, BelongsTo<any> | HasOne<any> | HasMany<any> | BelongsToMany<any>> | DotNotationProperties<this>, (Query: EntityQuery<any>) => void]
238
- )[]
239
- ) {
240
- await this.newQuery().withCount<K>(...relations).eagerLoadRelationshipsCounts([this])
241
-
242
- return this
243
- }
244
-
245
- newQuery<T extends Entity>(this: T) {
246
- return this.static.newQuery()
247
- }
248
-
249
- static async delete<T extends Entity>(this: EntityConstructor<T>, ...ids: [ID, ...ID[]]) {
250
- await this.newQuery().whereIn(this.getPrimaryKey(), ids).delete()
251
- }
252
-
253
- private getDataToSave(data: ChildObject<this, Entity> | object) {
254
- this.fill(data)
255
-
256
- this.updateTimestamps()
257
-
258
- // tslint:disable-next-line:no-any
259
- const dataToSave: Record<string, any> = {}
260
-
261
- // TODO diff the values so we don't update every value from the entity
262
- Object.values({...this.metadata.columns, ...this.metadata.relationships}).forEach(field => {
263
- dataToSave[field.column] = field.value(this, field.property)
264
- })
265
- return dataToSave
266
- }
267
-
268
-
269
- fill(data: ChildObject<this, Entity> | object) {
270
- // TODO, check if we need to uncomment this
271
- // const relationships = this.metadata.relationships
272
- // Object.keys(relationships).forEach(key => {
273
- // relationships[key].update(this)
274
- // })
275
- const fields = {...this.metadata.columns, ...this.metadata.relationships, ...this.metadata.inverseRelationships}
276
- Object.keys(data).forEach(key => {
277
- const field = fields[key]
278
- if (field) {
279
- const value = data[key as keyof object]
280
- field.set(this, this.convertValueByType(value, field))
281
- }
282
- })
283
-
284
- return this
285
- }
286
-
287
- async delete() {
288
- if (!this.exists) {
289
- return
290
- }
291
-
292
- await this.newQuery().where(this.getPrimaryKey(), this[this.getPrimaryKey()]).delete()
293
- }
294
-
295
- static async truncate<T extends Entity>(this: EntityConstructor<T>) {
296
- await this.newQuery().truncate()
297
- }
298
-
299
- async save(data: ChildObject<this, Entity> | object = {}): Promise<this> {
300
- const dataToSave = this.getDataToSave(data)
301
-
302
- const query = this.newQuery()
303
-
304
- if (this.exists) {
305
- delete dataToSave[this.getPrimaryKey() as string]
306
- await query.where(this.getPrimaryKey(), this[this.getPrimaryKey()]).update(dataToSave)
307
- } else {
308
- const id = await query.insertOne(dataToSave)
309
- this.exists = true
310
- this.fill({id})
311
- }
312
-
313
- return this
314
- }
315
-
316
- getPrimaryKey<T extends Entity>(this: T): EntityKeys<T> {
317
- return this.static.getPrimaryKey()
318
- }
319
-
320
- getPrimaryKeyValue<T extends Entity>(this: T): ID {
321
- return this[this.static.getPrimaryKey()]
322
- }
323
-
324
- toJSON() {
325
- return Object.keys({...this.metadata.columns, ...this.metadata.allRelationships})
326
- .reduce((obj, key) => {
327
- if (Object.prototype.hasOwnProperty.call(this, key)) {
328
- obj[key as keyof this] = this[key as keyof this]
329
- }
330
- return obj
331
- }, {} as { [K in keyof this]: this[K] })
332
- }
333
-
334
- private updateTimestamps() {
335
- const metadata = this.metadata
336
- const columnsToFill: Record<keyof this, unknown> = {} as Record<keyof this, unknown>
337
-
338
- const createdAtValue = metadata.createdAtColumn ? this[metadata.createdAtColumn as keyof this] as unknown as Date : undefined
339
- if (metadata.createdAtColumn && !createdAtValue) {
340
- columnsToFill[metadata.createdAtColumn as keyof this] = new Date()
341
- }
342
-
343
- const updatedAtValue = metadata.updatedAtColumn ? this[metadata.updatedAtColumn as keyof this] as unknown as Date : undefined
344
- if (metadata.updatedAtColumn &&
345
- (!updatedAtValue || updatedAtValue?.getTime() === new Date(this.original[metadata.updatedAtColumn]).getTime())
346
- ) {
347
- columnsToFill[metadata.updatedAtColumn as keyof this] = new Date()
348
- }
349
-
350
- this.fill(columnsToFill)
351
- }
352
-
353
- private convertValueByType(value: unknown, property: ColumnField<Entity> | InverseField<Entity>) {
354
- const converter = types.get(property.type()) || (() => value)
355
- return converter(value)
356
- }
357
- }
358
-
359
- const types: Map<Function, Function> = new Map()
360
- types.set(Date, (value: number | string) => value ? new Date(value) : value)
361
- types.set(String, (value: object) => value ? String(value) : value)
362
- types.set(Boolean, (value: string) => Boolean(value))
363
-
364
- // let handler = {
365
- // set: (target, prop, value) => {
366
- // console.log(target, prop, value);
367
- // target[prop] = value;
368
- // return true;
369
- // },
370
- // get: (target, prop) => {
371
- // if(!(prop in Entity))
372
- // return () => {return new Query};
373
- // return target[prop];
374
- // }
375
- // };
376
-
377
- // Object.setPrototypeOf(Entity, new Proxy({}, new EntityProxyHandler(Entity)));
@@ -1,5 +0,0 @@
1
- import { Entity } from './Entity'
2
-
3
- export class EntityNotFoundError extends Error {
4
- constructor(public entity: typeof Entity, message: string) {super(message)}
5
- }
@@ -1,43 +0,0 @@
1
- import { Entity } from './Entity'
2
- import { EntityQuery } from './EntityQuery'
3
- import { EntityConstructor } from './index'
4
-
5
- export class EntityProxyHandler<T extends Entity> {
6
-
7
- set<K extends keyof T>(target: T, property: string, value: T[K]) {
8
- target[property as keyof T] = value
9
- return true
10
- }
11
-
12
- get(target: T, property: string) {
13
- if (!(property in target)) {
14
- const targetConstructor = target.constructor as EntityConstructor<T>
15
- const query = new EntityQuery(targetConstructor)
16
- const queryProperty = query[property as keyof EntityQuery<T>] as Function
17
- if (typeof queryProperty === 'function') {
18
- // @ts-ignore
19
- query.table(target.constructor.getTable())
20
- return (...args: object[]) => {
21
- return queryProperty.apply(query, args)
22
- }
23
- }
24
- }
25
-
26
- const value = target[property as keyof T]
27
-
28
- if (!value) {
29
- const relationships = target.metadata.allRelationships
30
- if (relationships[property]) {
31
- const relationship = new (relationships[property] as any)
32
- const relationshipClass = relationship.relationClass(relationships[property], target) as unknown as T[keyof T]
33
- return target[property as keyof T] = relationshipClass
34
- }
35
- }
36
-
37
- return value
38
- // if (typeof value === 'function') {
39
- // return value.bind(target);
40
- // }
41
- // return value;
42
- }
43
- }