@typetron/framework 0.5.3 → 0.5.5

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 (195) hide show
  1. package/.eslintrc-old.js +208 -0
  2. package/Cache/Cache.ts +13 -0
  3. package/Cache/Stores/DatabaseStore.ts +120 -0
  4. package/Cache/Stores/FileStore.ts +69 -0
  5. package/Cache/Stores/MemoryStore.ts +71 -0
  6. package/Cache/index.ts +5 -0
  7. package/Cache/types.ts +4 -0
  8. package/Container/ClassResolver.ts +106 -0
  9. package/Container/Container.ts +144 -0
  10. package/Container/Contracts.ts +3 -0
  11. package/Container/Decorators.ts +20 -0
  12. package/Container/Metadata.ts +16 -0
  13. package/Container/Resolver.ts +27 -0
  14. package/Container/index.ts +5 -0
  15. package/Database/Clauses/Where.ts +0 -0
  16. package/Database/Connection.ts +52 -0
  17. package/Database/Decorators.ts +142 -0
  18. package/Database/Drivers/DatabaseDriver.ts +37 -0
  19. package/Database/Drivers/MySQL/Alter/index.ts +55 -0
  20. package/Database/Drivers/MySQL/ColumnDefinition.ts +16 -0
  21. package/Database/Drivers/MySQL/Create.ts +47 -0
  22. package/Database/Drivers/MySQL/MysqlDriver.ts +123 -0
  23. package/Database/Drivers/MySQL/Schema.ts +82 -0
  24. package/Database/Drivers/MySQL/index.ts +13 -0
  25. package/Database/Drivers/SQL/Schema.ts +73 -0
  26. package/Database/Drivers/SQL/Statements/Alter.ts +22 -0
  27. package/Database/Drivers/SQL/Statements/BaseStatement.ts +55 -0
  28. package/Database/Drivers/SQL/Statements/Delete.ts +20 -0
  29. package/Database/Drivers/SQL/Statements/Insert.ts +24 -0
  30. package/Database/Drivers/SQL/Statements/Select.ts +55 -0
  31. package/Database/Drivers/SQL/Statements/Update.ts +33 -0
  32. package/Database/Drivers/SQL/index.ts +8 -0
  33. package/Database/Drivers/SQLite/Create.ts +45 -0
  34. package/Database/Drivers/SQLite/Schema.ts +54 -0
  35. package/Database/Drivers/SQLite/SqliteDriver.ts +144 -0
  36. package/Database/Drivers/SQLite/index.ts +15 -0
  37. package/Database/Drivers/SchemaContract.ts +11 -0
  38. package/Database/Drivers/Statement.ts +16 -0
  39. package/Database/Drivers/index.ts +4 -0
  40. package/Database/Entity.ts +377 -0
  41. package/Database/EntityNotFoundError.ts +5 -0
  42. package/Database/EntityProxyHandler.ts +43 -0
  43. package/Database/EntityQuery.ts +197 -0
  44. package/Database/Expression.ts +3 -0
  45. package/Database/Fields.ts +816 -0
  46. package/Database/Helpers.ts +12 -0
  47. package/Database/List.ts +71 -0
  48. package/Database/Migrations/Migration.ts +10 -0
  49. package/Database/Migrations/MigrationHistory.ts +20 -0
  50. package/Database/Migrations/Migrator.ts +122 -0
  51. package/Database/Migrations/index.ts +3 -0
  52. package/Database/ORM/BaseRelationship.ts +10 -0
  53. package/Database/Query.ts +374 -0
  54. package/Database/Seeders/Seeder.ts +3 -0
  55. package/Database/Seeders/SeederManager.ts +27 -0
  56. package/Database/Seeders/index.ts +2 -0
  57. package/Database/StringExpression.ts +9 -0
  58. package/Database/Types.ts +165 -0
  59. package/Database/index.ts +23 -0
  60. package/Encryption/index.ts +51 -0
  61. package/Forms/Decorators.ts +29 -0
  62. package/Forms/Form.ts +70 -0
  63. package/Forms/FormFields.ts +36 -0
  64. package/Forms/index.ts +3 -0
  65. package/Framework/App.ts +10 -0
  66. package/Framework/Application.ts +118 -0
  67. package/Framework/Auth/Auth.ts +122 -0
  68. package/Framework/Auth/Authenticatable.ts +9 -0
  69. package/Framework/Auth/User.ts +27 -0
  70. package/Framework/Auth/index.ts +29 -0
  71. package/Framework/Config/AppConfig.ts +25 -0
  72. package/Framework/Config/AuthConfig.ts +9 -0
  73. package/Framework/Config/BaseConfig.ts +9 -0
  74. package/Framework/Config/CacheConfig.ts +38 -0
  75. package/Framework/Config/DatabaseConfig.ts +21 -0
  76. package/Framework/Config/MailConfig.ts +30 -0
  77. package/Framework/Config/index.ts +6 -0
  78. package/Framework/Middleware/AuthMiddleware.ts +31 -0
  79. package/Framework/Middleware/CorsMiddleware.ts +32 -0
  80. package/Framework/Middleware/StaticAssetsMiddleware.ts +76 -0
  81. package/Framework/Middleware/index.ts +2 -0
  82. package/Framework/Provider.ts +9 -0
  83. package/Framework/Providers/CacheProvider.ts +28 -0
  84. package/Framework/Providers/DatabaseProvider.ts +36 -0
  85. package/Framework/Providers/MailProvider.ts +31 -0
  86. package/Framework/Providers/WebsocketsProvider.ts +120 -0
  87. package/Framework/Resolvers/AuthResolver.ts +23 -0
  88. package/Framework/Resolvers/EntityResolver.ts +41 -0
  89. package/Framework/Resolvers/FormResolver.ts +37 -0
  90. package/Framework/RootDir.ts +1 -0
  91. package/Framework/index.ts +8 -0
  92. package/Frontend/Angular/index.ts +24 -0
  93. package/Frontend/Websockets/index.ts +86 -0
  94. package/Mail/MailAddress.ts +4 -0
  95. package/Mail/MailTransport.ts +6 -0
  96. package/Mail/Mailable.ts +16 -0
  97. package/Mail/Mailer.ts +27 -0
  98. package/Mail/PendingMail.ts +68 -0
  99. package/Mail/SentMessage.ts +20 -0
  100. package/Mail/Transports/MemoryTransport.ts +13 -0
  101. package/Mail/Transports/SendGridTransport.ts +95 -0
  102. package/Mail/index.ts +3 -0
  103. package/Models/Model.ts +41 -0
  104. package/Models/index.ts +54 -0
  105. package/Router/BaseController.ts +7 -0
  106. package/Router/Decorators.ts +224 -0
  107. package/Router/Guard.ts +10 -0
  108. package/Router/Http/Contracts.ts +4 -0
  109. package/Router/Http/ErrorHandler.ts +45 -0
  110. package/Router/Http/ErrorHandlerInterface.ts +6 -0
  111. package/Router/Http/Errors/HttpError.ts +15 -0
  112. package/Router/Http/Handler.ts +183 -0
  113. package/Router/Http/HttpRoute.ts +110 -0
  114. package/Router/Http/Middleware.ts +7 -0
  115. package/Router/Http/Request.ts +225 -0
  116. package/Router/Http/Response.ts +35 -0
  117. package/Router/Http/index.ts +85 -0
  118. package/Router/Metadata.ts +34 -0
  119. package/Router/Middleware.ts +16 -0
  120. package/Router/Request.ts +65 -0
  121. package/Router/Route.ts +16 -0
  122. package/Router/RouteNotFoundError.ts +5 -0
  123. package/Router/Router.ts +35 -0
  124. package/Router/Servers/index.ts +6 -0
  125. package/Router/Servers/node.ts +49 -0
  126. package/Router/Servers/uNetworking.ts +151 -0
  127. package/Router/Websockets/Handler.ts +82 -0
  128. package/Router/Websockets/Middleware.ts +7 -0
  129. package/Router/Websockets/Request.ts +3 -0
  130. package/Router/Websockets/WebsocketRoute.ts +61 -0
  131. package/Router/Websockets/index.ts +57 -0
  132. package/Router/Websockets/types.ts +23 -0
  133. package/Router/index.ts +6 -0
  134. package/Storage/File.ts +30 -0
  135. package/Storage/Image.ts +19 -0
  136. package/Storage/InvalidImage.ts +3 -0
  137. package/Storage/Storage.ts +98 -0
  138. package/Storage/index.ts +4 -0
  139. package/Storage/utils.ts +18 -0
  140. package/Support/Array.ts +184 -0
  141. package/Support/Math.ts +12 -0
  142. package/Support/Metadata.ts +31 -0
  143. package/Support/String.ts +38 -0
  144. package/Support/index.ts +19 -0
  145. package/Support/utils.ts +7 -0
  146. package/Testing/TestCase.ts +193 -0
  147. package/Validation/Rule.ts +9 -0
  148. package/Validation/RuleInterface.ts +10 -0
  149. package/Validation/Rules/Email.ts +20 -0
  150. package/Validation/Rules/FileExtension.ts +21 -0
  151. package/Validation/Rules/MaxLength.ts +17 -0
  152. package/Validation/Rules/MinLength.ts +18 -0
  153. package/Validation/Rules/Optional.ts +18 -0
  154. package/Validation/Rules/Required.ts +29 -0
  155. package/Validation/Validator.ts +7 -0
  156. package/Validation/index.ts +12 -0
  157. package/benchmark-index.js +20 -0
  158. package/benchmark.ts +47 -0
  159. package/package.json +7 -3
  160. package/tests/Cache/DatabaseStoreTest.ts +110 -0
  161. package/tests/Cache/FileStoreTest.ts +93 -0
  162. package/tests/Cache/MemoryStoreTest.ts +92 -0
  163. package/tests/Container/ContainerTest.ts +336 -0
  164. package/tests/Database/Drivers/MySQL/AlterTest.ts +100 -0
  165. package/tests/Database/Drivers/MySQL/CreateTest.ts +39 -0
  166. package/tests/Database/Drivers/MysqlDriverTest.ts +140 -0
  167. package/tests/Database/Drivers/SqliteDriverTest.ts +126 -0
  168. package/tests/Database/Entities/Article.ts +21 -0
  169. package/tests/Database/Entities/Profile.ts +21 -0
  170. package/tests/Database/Entities/Role.ts +15 -0
  171. package/tests/Database/Entities/User.ts +35 -0
  172. package/tests/Database/EntityRelationshipsTest.ts +475 -0
  173. package/tests/Database/EntityTest.ts +202 -0
  174. package/tests/Database/Migrations/RunnerTest.ts +96 -0
  175. package/tests/Database/Migrations/migrations/1.createUserTable.ts +12 -0
  176. package/tests/Database/Migrations/migrations/2.createArticlesTable.ts +12 -0
  177. package/tests/Database/QueryTest.ts +573 -0
  178. package/tests/Database/SchemaTest.ts +32 -0
  179. package/tests/Database/Seeders/RunnerTest.ts +30 -0
  180. package/tests/Database/Seeders/seeders/RandomSeeder.ts +10 -0
  181. package/tests/Database/utils.ts +16 -0
  182. package/tests/Forms/FormsTest.ts +59 -0
  183. package/tests/Framework/Middleware/StaticAssetsMiddlewareTest.ts +129 -0
  184. package/tests/Framework/Resolvers/EntityResolverTest.ts +48 -0
  185. package/tests/Framework/Router/RouterTest.ts +33 -0
  186. package/tests/Mail/MailerTest.ts +76 -0
  187. package/tests/Model/ModelTest.ts +183 -0
  188. package/tests/Router/HttpHandlerTest.ts +72 -0
  189. package/tests/Router/RequestTest.ts +77 -0
  190. package/tests/Router/WebSocketsHandlerTest.ts +51 -0
  191. package/tests/Storage/StorageTest.ts +97 -0
  192. package/tests/Support/ArrayTest.ts +167 -0
  193. package/tests/Support/StringTest.ts +18 -0
  194. package/tests/Validation/RulesTest.ts +54 -0
  195. package/types.d.ts +8 -0
@@ -0,0 +1,12 @@
1
+ export function wrap(strings: string | string[]) {
2
+ if (typeof strings === 'string') {
3
+ strings = [strings]
4
+ }
5
+ return strings.map(column => {
6
+ // // Only add backticks for columns that contain characters outside the following set
7
+ // if (/^[0-9,a-z,A-Z$_]+$/.test(column)) {
8
+ // return column
9
+ // }
10
+ return '`' + column + '`'
11
+ }).join(', ')
12
+ }
@@ -0,0 +1,71 @@
1
+ import { Entity } from './Entity'
2
+ import { EntityKeys } from './index'
3
+ import { EntityQuery } from './EntityQuery'
4
+ import { BooleanOperator, Operator, WhereValue } from './Types'
5
+ import { BelongsToManyField, HasManyField } from './Fields'
6
+ import { BaseRelationship as Relationship } from './ORM/BaseRelationship'
7
+
8
+ export abstract class List<E extends Entity, P extends Entity = Entity> extends Relationship<E, P> implements Iterable<E>, ArrayLike<E> {
9
+
10
+ items: E[] = []
11
+
12
+ declare public relationship: HasManyField<P, E> | BelongsToManyField<P, E>
13
+
14
+ protected constructor(
15
+ relationship: HasManyField<P, E> | BelongsToManyField<P, E>,
16
+ parent: P
17
+ ) {
18
+ super(relationship, parent)
19
+ return new Proxy(this, new ListProxyHandler())
20
+ }
21
+
22
+ get length() {
23
+ return this.items.length
24
+ }
25
+
26
+ [Symbol.iterator]() {
27
+ return this.items[Symbol.iterator]()
28
+ }
29
+
30
+ readonly [n: number]: E;
31
+
32
+ async load() {
33
+ await this.parent.load(this.relationship.property)
34
+ return this
35
+ }
36
+
37
+ async get() {
38
+ await this.load()
39
+ return this.items
40
+ }
41
+
42
+ newQuery(): EntityQuery<E> {
43
+ return this.relationship.getQuery(this.parent)
44
+ }
45
+
46
+ where<K extends EntityKeys<E>>(
47
+ column: EntityKeys<E>,
48
+ operator: Operator | WhereValue | E[K],
49
+ value?: WhereValue | E[K],
50
+ boolean?: BooleanOperator
51
+ ): EntityQuery<E> {
52
+ return this.relationship.getQuery(this.parent).where(column, operator, value, boolean)
53
+ }
54
+
55
+ findWhere(name: string, value: string): E | undefined {
56
+ return undefined
57
+ }
58
+
59
+ toJSON() {
60
+ return this.items
61
+ }
62
+ }
63
+
64
+ export class ListProxyHandler<E extends Entity, P extends Entity> {
65
+ get(target: List<E, P>, property: string | symbol) {
66
+ if (Number.isInteger(Number(property.toString()))) {
67
+ return target.items[property as unknown as number]
68
+ }
69
+ return target[property as keyof List<E, P>]
70
+ }
71
+ }
@@ -0,0 +1,10 @@
1
+ import { Connection } from '../Connection'
2
+
3
+ export abstract class Migration {
4
+
5
+ constructor(protected connection: Connection) {}
6
+
7
+ abstract up(): void | Promise<void>;
8
+
9
+ abstract down(): void | Promise<void>;
10
+ }
@@ -0,0 +1,20 @@
1
+ import { Column, CreatedAt, ID, Options, PrimaryColumn } from '../Decorators'
2
+ import { Entity } from '../Entity'
3
+
4
+ @Options({
5
+ table: 'migration_history'
6
+ })
7
+ export class MigrationHistory extends Entity {
8
+
9
+ @PrimaryColumn()
10
+ id: ID
11
+
12
+ @Column()
13
+ name: string
14
+
15
+ @Column()
16
+ batch: number
17
+
18
+ @CreatedAt()
19
+ createdAt: Date
20
+ }
@@ -0,0 +1,122 @@
1
+ import { MigrationHistory } from './MigrationHistory'
2
+ import { Migration } from './Migration'
3
+ import * as path from 'path'
4
+ import { File, Storage } from '@Typetron/Storage'
5
+ import { Connection } from '..'
6
+ import { Constructor } from '@Typetron/Support'
7
+
8
+ interface MigrateOptions {
9
+ fresh?: boolean;
10
+ }
11
+
12
+ export class Migrator {
13
+
14
+ constructor(
15
+ public storage: Storage,
16
+ public connection: Connection,
17
+ public directory: string
18
+ ) {}
19
+
20
+ async files(): Promise<File[]> {
21
+ return this.storage.files(this.directory, true).where('extension', 'ts')
22
+ }
23
+
24
+ public async migrate(options?: MigrateOptions): Promise<boolean> {
25
+ await this.createMigrationTable()
26
+
27
+ if (options?.fresh) {
28
+ await this.clearTable()
29
+ }
30
+
31
+ const files = await this.files()
32
+ const migrates = await MigrationHistory.whereIn('name', files.pluck('name')).get()
33
+ const filesToMigrate = files.filter(file => !migrates.findWhere('name', file.name))
34
+
35
+ if (!filesToMigrate.length) {
36
+ console.log('Nothing to migrate')
37
+ return true
38
+ }
39
+
40
+ const lastBatch = await this.getLastBatchId()
41
+ for await(const file of filesToMigrate) {
42
+ const migration = this.getMigration(file.path)
43
+ const migrationName = migration.constructor.name
44
+
45
+ console.log(`Migrating '${migrationName}'`)
46
+ try {
47
+ await migration.up()
48
+ await MigrationHistory.create({
49
+ name: file,
50
+ batch: lastBatch + 1,
51
+ createdAt: new Date()
52
+ })
53
+ console.log(`Migrated '${migrationName}'`)
54
+ } catch (error) {
55
+ console.error(`Failed to run the migration from '${migrationName}'`, (error as Error).message)
56
+ return false
57
+ }
58
+ }
59
+ return true
60
+ }
61
+
62
+ public async rollback(steps = 0) {
63
+ await this.createMigrationTable()
64
+
65
+ const lastMigration = await MigrationHistory.newQuery().orderBy('batch', 'DESC').first()
66
+ if (!lastMigration) {
67
+ throw new Error('Can not find any migration to rollback.')
68
+ }
69
+ const migrations = await MigrationHistory
70
+ .where('batch', '>=', Math.max(0, lastMigration.batch - steps))
71
+ .orderBy('batch', 'DESC')
72
+ .get()
73
+
74
+ for (const migrationEntity of migrations) {
75
+ const migration = this.getMigration(path.join(this.directory, migrationEntity.name))
76
+ const migrationName = migration.constructor.name
77
+
78
+ console.log(`Rolling back the '${migrationName}' migration.`)
79
+ try {
80
+ await migration.down()
81
+ console.log(`Reverted '${migrationName}' migration.`)
82
+ await migrationEntity.delete()
83
+ } catch (error) {
84
+ console.error(`Failed to run the migration '${migrationName}'`, error)
85
+ return false
86
+ }
87
+ }
88
+
89
+ return true
90
+ }
91
+
92
+ protected async getLastBatchId(): Promise<number> {
93
+ const lastMigration = await MigrationHistory.orderBy('batch', 'DESC').first()
94
+ return lastMigration?.batch ?? 0
95
+ }
96
+
97
+ public async reset() {
98
+ await this.createMigrationTable()
99
+
100
+ const lastMigration = await MigrationHistory.newQuery().orderBy('batch', 'DESC').first()
101
+
102
+ if (!lastMigration) {
103
+ return true
104
+ }
105
+
106
+ return this.rollback(lastMigration?.batch)
107
+ }
108
+
109
+ private getMigration(migrationFilePath: string): Migration {
110
+ const migrationModule: Record<string, Constructor<Migration>> = require(migrationFilePath)
111
+ const MigrationClass = Object.values(migrationModule)[0]
112
+ return new MigrationClass(this.connection)
113
+ }
114
+
115
+ protected async createMigrationTable(): Promise<void> {
116
+ await this.connection.driver.schema.synchronize([MigrationHistory].pluck('metadata'))
117
+ }
118
+
119
+ protected async clearTable(): Promise<unknown> {
120
+ return MigrationHistory.truncate()
121
+ }
122
+ }
@@ -0,0 +1,3 @@
1
+ export * from './Migrator'
2
+ export * from './Migration'
3
+ export * from './MigrationHistory'
@@ -0,0 +1,10 @@
1
+ import { Entity } from '../Entity'
2
+ import { InverseRelationship, RelationshipField } from '../Fields'
3
+
4
+ export abstract class BaseRelationship<E extends Entity, P extends Entity = Entity> {
5
+ constructor(
6
+ public relationship: RelationshipField<P, E> | InverseRelationship<P, E>,
7
+ public parent: P
8
+ ) {
9
+ }
10
+ }
@@ -0,0 +1,374 @@
1
+ import {
2
+ BooleanOperator,
3
+ Components,
4
+ Direction,
5
+ JoinType,
6
+ Operator,
7
+ SqlValue,
8
+ SqlValueMap,
9
+ Where,
10
+ WhereBetween,
11
+ WhereFunction,
12
+ WhereIn,
13
+ WhereLike,
14
+ WhereNull,
15
+ WhereSubSelect,
16
+ WhereValue
17
+ } from './Types'
18
+ import { Connection } from './Connection'
19
+ import { StringExpression } from './StringExpression'
20
+ import { Statement } from './Drivers/Statement'
21
+ import { Constructor } from '@Typetron/Support'
22
+ import { Expression } from './Expression'
23
+
24
+ export class Query<T = {}> extends Expression {
25
+ static connection: Connection
26
+
27
+ private statementType: Constructor<Statement> = Query.connection.driver.statements.select
28
+
29
+ private useDistinct = false
30
+
31
+ private components: Components = {
32
+ table: '',
33
+ distinct: false,
34
+ columns: [],
35
+ joins: [],
36
+ wheres: [],
37
+ groups: [],
38
+ orders: [],
39
+ having: [],
40
+ }
41
+
42
+ get statement(): Statement {
43
+ return new this.statementType(this.components)
44
+ }
45
+
46
+ static table<T = object>(table: string): Query<T> {
47
+ return (new this() as Query<T>).table(table)
48
+ }
49
+
50
+ static from<T = {}>(table: string) {
51
+ return Query.table<T>(table)
52
+ }
53
+
54
+ static truncate(table: string) {
55
+ return Query.connection.truncate(table)
56
+ }
57
+
58
+ truncate() {
59
+ return Query.truncate(this.components.table)
60
+ }
61
+
62
+ getBindings() {
63
+ const statement = this.statement
64
+ statement.toSQL()
65
+ return statement.bindings
66
+ }
67
+
68
+ toSQL() {
69
+ return this.statement.toSQL().replace(/\s{2,}/g, ' ').trim()
70
+ }
71
+
72
+ async get<K extends keyof T>(...columns: (K | string | StringExpression)[]): Promise<T[]> {
73
+ return Query.connection.get(this.select(...(columns.length ? columns : this.components.columns)))
74
+ }
75
+
76
+ async run<K extends keyof T>(): Promise<void> {
77
+ await Query.connection.run(this as Query<{}>)
78
+ }
79
+
80
+ table(table: string) {
81
+ this.components.table = table
82
+
83
+ return this
84
+ }
85
+
86
+ from(table: string) {
87
+ return this.table(table)
88
+ }
89
+
90
+ async first<K extends keyof T>(...columns: (K | string | StringExpression)[]): Promise<T | undefined> {
91
+ return Query.connection.first(this.select(...(columns.length ? columns : this.components.columns)))
92
+ }
93
+
94
+ select<K extends keyof T>(...columns: (K | string | StringExpression)[]) {
95
+ this.statementType = Query.connection.driver.statements.select
96
+ this.components.columns = columns as string[]
97
+
98
+ return this
99
+ }
100
+
101
+ where<K extends keyof T>(
102
+ column: K | string,
103
+ operator: Operator | Query | WhereValue | WhereFunction | T[K],
104
+ value?: Query | WhereValue | WhereFunction | T[K],
105
+ boolean: BooleanOperator = 'AND'
106
+ ): this {
107
+ // if (column instanceof Function) {
108
+ // const query = new WhereNested();
109
+ // this.components.wheres = query;
110
+ // column(query);
111
+ // return this;
112
+ // }
113
+ if (value === undefined) {
114
+ value = operator
115
+ operator = '=' as Operator
116
+ }
117
+
118
+ if (value instanceof Query) {
119
+ this.components.wheres.push(new WhereSubSelect(column as string, operator as Operator, value, boolean))
120
+ return this
121
+ }
122
+
123
+ if (typeof value === 'function') {
124
+ const query = new Query()
125
+ // @ts-ignore
126
+ value(query)
127
+ this.components.wheres.push(new WhereSubSelect(column as string, operator as Operator, query, boolean))
128
+ return this
129
+ }
130
+
131
+ // this.bindings.push(value);
132
+ // const where = new Where();
133
+ // where.boolean = this.components.wheres.length ? boolean : 'WHERE';
134
+ // this.components.wheres.push({
135
+ // column, operator, value, boolean
136
+ // });
137
+
138
+ if (typeof value === 'object') {
139
+ return this
140
+ }
141
+
142
+ this.components.wheres.push(new Where(column as string, operator as Operator, value as WhereValue, boolean))
143
+
144
+ return this
145
+ }
146
+
147
+ orWhere<K extends keyof T>(column: K | string, operator: Operator | WhereValue | T[K], value?: WhereValue | T[K]): this {
148
+ return this.where(column, operator, value, 'OR')
149
+ }
150
+
151
+ andWhere<K extends keyof T>(column: K | string, operator: Operator | WhereValue | T[K], value?: WhereValue | T[K]): this {
152
+ return this.where(column, operator, value)
153
+ }
154
+
155
+ whereIn<K extends keyof T>(
156
+ column: K | string,
157
+ values: Query | WhereFunction | WhereValue[] | T[K][],
158
+ boolean: BooleanOperator = 'AND',
159
+ not = false
160
+ ): this {
161
+ if (values instanceof Query) {
162
+ this.components.wheres.push(new WhereSubSelect(column as string, not ? 'NOT IN' : 'IN', values, boolean))
163
+ return this
164
+ }
165
+ if (typeof values === 'function') {
166
+ const query = new Query()
167
+ values(query)
168
+ this.components.wheres.push(new WhereSubSelect(column as string, not ? 'NOT IN' : 'IN', query, boolean))
169
+ return this
170
+ }
171
+ this.components.wheres.push(new WhereIn(column as string, values as WhereValue[], boolean, not))
172
+
173
+ return this
174
+ }
175
+
176
+ andWhereIn<K extends keyof T>(column: K | string, values: SqlValue[]): this {
177
+ return this.whereIn(column, values)
178
+ }
179
+
180
+ andWhereNotIn<K extends keyof T>(column: K | string, values: SqlValue[]): this {
181
+ return this.whereIn(column, values, 'AND', true)
182
+ }
183
+
184
+ whereLike<K extends keyof T>(column: K | string, value: SqlValue, boolean: BooleanOperator = 'AND', not = false): this {
185
+ this.components.wheres.push(new WhereLike(column as string, value, boolean, not))
186
+
187
+ return this
188
+ }
189
+
190
+ whereNotIn<K extends keyof T>(
191
+ column: K | string,
192
+ values: Query | WhereFunction | WhereValue[] | T[K][],
193
+ boolean: BooleanOperator = 'AND'
194
+ ): this {
195
+ return this.whereIn(column, values, boolean, true)
196
+ }
197
+
198
+ orWhereIn<K extends keyof T>(column: K | string, values: SqlValue[]): this {
199
+ return this.whereIn(column, values, 'OR')
200
+ }
201
+
202
+ orWhereNotIn<K extends keyof T>(column: K | string, values: SqlValue[]): this {
203
+ return this.whereIn(column, values, 'OR', true)
204
+ }
205
+
206
+ orWhereLike<K extends keyof T>(column: K | string, value: SqlValue, not = false): this {
207
+ return this.whereLike(column, value, 'OR', not)
208
+ }
209
+
210
+ orWhereNotLike<K extends keyof T>(column: K | string, value: SqlValue): this {
211
+ return this.whereLike(column, value, 'OR', true)
212
+ }
213
+
214
+ whereBetween<K extends keyof T>(column: K | string, values: [SqlValue, SqlValue], boolean: BooleanOperator = 'AND', not = false): this {
215
+ this.components.wheres.push(new WhereBetween(column as string, values, boolean, not))
216
+
217
+ return this
218
+ }
219
+
220
+ whereNotBetween<K extends keyof T>(column: K | string, values: [SqlValue, SqlValue], boolean: BooleanOperator = 'AND'): this {
221
+ return this.whereBetween(column, values, boolean, true)
222
+ }
223
+
224
+ orWhereBetween<K extends keyof T>(column: K | string, values: [SqlValue, SqlValue]): this {
225
+ return this.whereBetween(column, values, 'OR')
226
+ }
227
+
228
+ orWhereNotBetween<K extends keyof T>(column: K | string, values: [SqlValue, SqlValue]): this {
229
+ return this.whereBetween(column, values, 'OR', true)
230
+ }
231
+
232
+ whereNull<K extends keyof T>(column: K | string, boolean: BooleanOperator = 'AND', not = false): this {
233
+ this.components.wheres.push(new WhereNull(column as string, boolean, not))
234
+
235
+ return this
236
+ }
237
+
238
+ andWhereNull<K extends keyof T>(column: K | string): this {
239
+ return this.whereNull(column)
240
+ }
241
+
242
+ whereNotNull<K extends keyof T>(column: K | string, boolean: BooleanOperator = 'AND'): this {
243
+ return this.whereNull(column, boolean, true)
244
+ }
245
+
246
+ andWhereNotNull<K extends keyof T>(column: K | string, boolean: BooleanOperator = 'AND'): this {
247
+ return this.whereNotNull(column, boolean)
248
+ }
249
+
250
+ orWhereNull<K extends keyof T>(column: K | string): this {
251
+ return this.whereNull(column, 'OR')
252
+ }
253
+
254
+ orWhereNotNull<K extends keyof T>(column: K | string): this {
255
+ return this.whereNull(column, 'OR', true)
256
+ }
257
+
258
+ distinct(value = true) {
259
+ this.components.distinct = value
260
+
261
+ return this
262
+ }
263
+
264
+ join(table: string, first: string, operator: Operator, second: string, type: keyof typeof JoinType = JoinType.INNER) {
265
+ this.components.joins.push({type, table, first, operator, second})
266
+
267
+ return this
268
+ }
269
+
270
+ innerJoin(table: string, first: string, operator: Operator, second: string) {
271
+ return this.join(table, first, operator, second, JoinType.INNER)
272
+ }
273
+
274
+ leftJoin(table: string, first: string, operator: Operator, second: string) {
275
+ return this.join(table, first, operator, second, JoinType.LEFT)
276
+ }
277
+
278
+ rightJoin(table: string, first: string, operator: Operator, second: string) {
279
+ return this.join(table, first, operator, second, JoinType.RIGHT)
280
+ }
281
+
282
+ orderBy<K extends keyof T>(column: K | [string | K, Direction][], direction: Direction = 'DESC') {
283
+ if (typeof column === 'string') {
284
+ column = [[column, direction]]
285
+ }
286
+ this.components.orders = column as [string, Direction][]
287
+
288
+ return this
289
+ }
290
+
291
+ groupBy<K extends keyof T>(...columns: (K | string) []) {
292
+ this.components.groups = columns as string[]
293
+
294
+ return this
295
+ }
296
+
297
+ addSelect<K extends keyof T>(...columns: (K | string | StringExpression)[]) {
298
+ this.components.columns = this.components.columns.concat(columns as string[])
299
+
300
+ return this
301
+ }
302
+
303
+ async count<K extends keyof T>(...columns: (K | string | StringExpression)[]): Promise<number> {
304
+ this.components.aggregate = {
305
+ function: 'COUNT',
306
+ columns: columns as string[],
307
+ }
308
+ const value = await Query.connection.first(this as unknown as Query<{aggregate: number}>)
309
+ return value?.aggregate || 0
310
+ }
311
+
312
+ selectCount<K extends keyof T>(...columns: (K | string | StringExpression)[]): this {
313
+ this.components.aggregate = {
314
+ function: 'COUNT',
315
+ columns: columns as string[],
316
+ }
317
+ return this
318
+ }
319
+
320
+ async max<K extends keyof T>(column: (K | string | StringExpression), ...columns: (K | string | StringExpression)[]): Promise<T[]> {
321
+ this.components.aggregate = {
322
+ function: 'MAX',
323
+ columns: [column].concat(columns) as string[],
324
+ }
325
+ return Query.connection.get(this)
326
+ }
327
+
328
+ async insert(data: SqlValueMap | SqlValueMap[]) {
329
+ this.statementType = Query.connection.driver.statements.insert
330
+
331
+ if (!Array.isArray(data)) {
332
+ data = [data]
333
+ }
334
+
335
+ this.components.insert = data
336
+
337
+ await this.run()
338
+ }
339
+
340
+ async insertOne(data: SqlValueMap): Promise<number> {
341
+ this.statementType = Query.connection.driver.statements.insert
342
+
343
+ this.components.insert = [data]
344
+
345
+ return await Query.connection.insertOne(this as Query<{}>)
346
+ }
347
+
348
+ async delete() {
349
+ this.statementType = Query.connection.driver.statements.delete
350
+
351
+ await this.run()
352
+ }
353
+
354
+ async update(name: string | keyof T | Record<keyof T, SqlValue> | SqlValueMap, value?: SqlValue) {
355
+ this.statementType = Query.connection.driver.statements.update
356
+
357
+ let data: SqlValueMap
358
+ if (typeof name === 'string') {
359
+ data = {[name]: value}
360
+ } else {
361
+ data = name as SqlValueMap
362
+ }
363
+
364
+ this.components.update = data
365
+
366
+ await this.run()
367
+ }
368
+
369
+ limit<K extends keyof T>(from: number, count?: number) {
370
+ this.components.limit = {from, count}
371
+
372
+ return this
373
+ }
374
+ }
@@ -0,0 +1,3 @@
1
+ export abstract class Seeder {
2
+ public abstract run():void
3
+ }
@@ -0,0 +1,27 @@
1
+ import { Storage } from "@Typetron/Storage"
2
+ import { Constructor } from "@Typetron/Support"
3
+ import { Seeder } from "./Seeder"
4
+
5
+ export class SeederManager {
6
+ constructor(
7
+ public storage: Storage,
8
+ public directory: string
9
+ ) {}
10
+
11
+ async seed() {
12
+ const files = await this.storage
13
+ .files(this.directory, true)
14
+ .where("extension", "ts")
15
+ .whenEmpty(() => console.log('Nothing to seed!'))
16
+
17
+ files.forEachAsync(async file => {
18
+ await this.getSeed(file.path).run()
19
+ })
20
+ }
21
+
22
+ private getSeed(path: string): Seeder {
23
+ const module: Record<string, Constructor<Seeder>> = require(path)
24
+ const Class = Object.values(module)[0]
25
+ return new Class()
26
+ }
27
+ }
@@ -0,0 +1,2 @@
1
+ export * from './Seeder'
2
+ export * from './SeederManager'
@@ -0,0 +1,9 @@
1
+ import { Expression } from '@Typetron/Database/Expression'
2
+
3
+ export class StringExpression extends Expression {
4
+ constructor(public value: string) {super()}
5
+
6
+ toSQL() {
7
+ return this.value
8
+ }
9
+ }