@stacksjs/database 0.58.48 → 0.58.49
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.
- package/package.json +3 -2
- package/src/index.ts +63 -0
- package/src/kysely-bun-worker/driver.ts +144 -0
- package/src/kysely-bun-worker/index.ts +46 -0
- package/src/kysely-bun-worker/mitt.ts +24 -0
- package/src/kysely-bun-worker/type.ts +40 -0
- package/src/kysely-bun-worker/worker.ts +53 -0
- package/src/migrations/index.ts +73 -0
- package/src/seeder/index.ts +79 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/database",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.58.
|
|
4
|
+
"version": "0.58.49",
|
|
5
5
|
"description": "The Stacks database integration.",
|
|
6
6
|
"author": "Chris Breuer",
|
|
7
7
|
"license": "MIT",
|
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
],
|
|
43
43
|
"files": [
|
|
44
44
|
"README.md",
|
|
45
|
-
"dist"
|
|
45
|
+
"dist",
|
|
46
|
+
"src"
|
|
46
47
|
],
|
|
47
48
|
"scripts": {
|
|
48
49
|
"build": "bun --bun build.ts",
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// export * from './migrations'
|
|
2
|
+
// export * from './seeder''
|
|
3
|
+
import { Kysely, MysqlDialect } from 'kysely'
|
|
4
|
+
import { createPool } from 'mysql2'
|
|
5
|
+
import type { ColumnType, Generated } from 'kysely'
|
|
6
|
+
import { BunWorkerDialect } from './kysely-bun-worker'
|
|
7
|
+
|
|
8
|
+
// const driver = config.database.default
|
|
9
|
+
const driver = 'mysql'
|
|
10
|
+
|
|
11
|
+
// const dbName = config.database.name
|
|
12
|
+
|
|
13
|
+
export interface UsersTable {
|
|
14
|
+
// Columns that are generated by the database should be marked
|
|
15
|
+
// using the `Generated` type. This way they are automatically
|
|
16
|
+
// made optional in inserts and updates.
|
|
17
|
+
id: Generated<number>
|
|
18
|
+
|
|
19
|
+
name: string
|
|
20
|
+
email: string
|
|
21
|
+
|
|
22
|
+
// If the column is nullable in the database, make its type nullable.
|
|
23
|
+
// Don't use optional properties. Optionality is always determined
|
|
24
|
+
// automatically by Kysely.
|
|
25
|
+
password: string
|
|
26
|
+
|
|
27
|
+
// You can specify a different type for each operation (select, insert and
|
|
28
|
+
// update) using the `ColumnType<SelectType, InsertType, UpdateType>`
|
|
29
|
+
// wrapper. Here we define a column `created_at` that is selected as
|
|
30
|
+
// a `Date`, can optionally be provided as a `string` in inserts and
|
|
31
|
+
// can never be updated:
|
|
32
|
+
created_at: ColumnType<Date, string | undefined, never>
|
|
33
|
+
deleted_at: ColumnType<Date, string | undefined, never>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface Database {
|
|
37
|
+
users: UsersTable
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let dialect
|
|
41
|
+
|
|
42
|
+
if (driver === 'sqlite') {
|
|
43
|
+
dialect = new BunWorkerDialect({
|
|
44
|
+
url: 'stacks.sqlite',
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
dialect = new MysqlDialect({
|
|
49
|
+
pool: createPool({
|
|
50
|
+
database: 'stacks',
|
|
51
|
+
host: '127.0.0.1',
|
|
52
|
+
user: 'root',
|
|
53
|
+
password: '',
|
|
54
|
+
port: 3306,
|
|
55
|
+
}),
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const db = new Kysely<Database>({
|
|
60
|
+
dialect,
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
export const dbDialect = dialect
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/* eslint-disable eslint-comments/no-unlimited-disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
import type { DatabaseConnection, Driver, QueryResult } from 'kysely'
|
|
4
|
+
import { CompiledQuery } from 'kysely'
|
|
5
|
+
import type { EmitterOnce } from './mitt'
|
|
6
|
+
import MittOnce from './mitt'
|
|
7
|
+
import type { EventWithError, MainMsg, WorkerMsg } from './type'
|
|
8
|
+
import type { BunWorkerDialectConfig } from '.'
|
|
9
|
+
|
|
10
|
+
export class BunWorkerDriver implements Driver {
|
|
11
|
+
private config?: BunWorkerDialectConfig
|
|
12
|
+
private worker?: Worker
|
|
13
|
+
private connection?: DatabaseConnection
|
|
14
|
+
private connectionMutex = new ConnectionMutex()
|
|
15
|
+
private mitt?: EmitterOnce<EventWithError>
|
|
16
|
+
constructor(config?: BunWorkerDialectConfig) {
|
|
17
|
+
this.config = config
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async init(): Promise<void> {
|
|
21
|
+
this.worker = this.config?.worker ?? new Worker(
|
|
22
|
+
new URL('../src/kysely-bun-worker/worker', import.meta.url),
|
|
23
|
+
{ type: 'module' },
|
|
24
|
+
)
|
|
25
|
+
this.mitt = MittOnce<EventWithError>()
|
|
26
|
+
this.worker.onmessage = ({ data: { data, err, type } }: MessageEvent<WorkerMsg>) => {
|
|
27
|
+
this.mitt?.emit(type, { data, err })
|
|
28
|
+
}
|
|
29
|
+
const msg: MainMsg = {
|
|
30
|
+
type: 'init',
|
|
31
|
+
url: this.config?.url ?? ':memory:',
|
|
32
|
+
cache: this.config?.cacheStatment ?? false,
|
|
33
|
+
}
|
|
34
|
+
this.worker.postMessage(msg)
|
|
35
|
+
await new Promise<void>((resolve, reject) => {
|
|
36
|
+
this.mitt?.once('init', ({ err }) => {
|
|
37
|
+
err ? reject(err) : resolve()
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
this.connection = new BunWorkerConnection(this.worker, this.mitt)
|
|
41
|
+
|
|
42
|
+
await this.config?.onCreateConnection?.(this.connection)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async acquireConnection(): Promise<DatabaseConnection> {
|
|
46
|
+
// SQLite only has one single connection. We use a mutex here to wait
|
|
47
|
+
// until the single connection has been released.
|
|
48
|
+
await this.connectionMutex.lock()
|
|
49
|
+
return this.connection!
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async beginTransaction(connection: DatabaseConnection): Promise<void> {
|
|
53
|
+
await connection.executeQuery(CompiledQuery.raw('begin'))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async commitTransaction(connection: DatabaseConnection): Promise<void> {
|
|
57
|
+
await connection.executeQuery(CompiledQuery.raw('commit'))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async rollbackTransaction(connection: DatabaseConnection): Promise<void> {
|
|
61
|
+
await connection.executeQuery(CompiledQuery.raw('rollback'))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async releaseConnection(): Promise<void> {
|
|
65
|
+
this.connectionMutex.unlock()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async destroy(): Promise<void> {
|
|
69
|
+
if (!this.worker)
|
|
70
|
+
return
|
|
71
|
+
|
|
72
|
+
this.worker.postMessage({
|
|
73
|
+
type: 'close',
|
|
74
|
+
})
|
|
75
|
+
return new Promise<void>((resolve, reject) => {
|
|
76
|
+
this.mitt?.once('close', ({ err }) => {
|
|
77
|
+
if (err) {
|
|
78
|
+
reject(err)
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
this.worker?.terminate()
|
|
82
|
+
this.mitt?.all.clear()
|
|
83
|
+
this.mitt = undefined
|
|
84
|
+
resolve()
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
class ConnectionMutex {
|
|
92
|
+
private promise?: Promise<void>
|
|
93
|
+
private resolve?: () => void
|
|
94
|
+
|
|
95
|
+
async lock(): Promise<void> {
|
|
96
|
+
while (this.promise)
|
|
97
|
+
await this.promise
|
|
98
|
+
|
|
99
|
+
this.promise = new Promise((resolve) => {
|
|
100
|
+
this.resolve = resolve
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
unlock(): void {
|
|
105
|
+
const resolve = this.resolve
|
|
106
|
+
|
|
107
|
+
this.promise = undefined
|
|
108
|
+
this.resolve = undefined
|
|
109
|
+
|
|
110
|
+
resolve?.()
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
class BunWorkerConnection implements DatabaseConnection {
|
|
115
|
+
readonly worker: Worker
|
|
116
|
+
readonly mitt?: EmitterOnce<EventWithError>
|
|
117
|
+
constructor(worker: Worker, mitt?: EmitterOnce<EventWithError>) {
|
|
118
|
+
this.worker = worker
|
|
119
|
+
this.mitt = mitt
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
streamQuery<R>(): AsyncIterableIterator<QueryResult<R>> {
|
|
123
|
+
throw new Error('Sqlite driver doesn\'t support streaming')
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async executeQuery<R>(compiledQuery: CompiledQuery<unknown>): Promise<QueryResult<R>> {
|
|
127
|
+
const { parameters, sql, query } = compiledQuery
|
|
128
|
+
const mode = query.kind === 'SelectQueryNode'
|
|
129
|
+
? 'query'
|
|
130
|
+
: query.kind === 'RawNode'
|
|
131
|
+
? 'raw'
|
|
132
|
+
: 'exec'
|
|
133
|
+
const msg: MainMsg = { type: 'run', mode, sql, parameters }
|
|
134
|
+
this.worker.postMessage(msg)
|
|
135
|
+
return new Promise((resolve, reject) => {
|
|
136
|
+
if (!this.mitt)
|
|
137
|
+
reject('kysely instance has been destroyed')
|
|
138
|
+
|
|
139
|
+
this.mitt.once('run', ({ data, err }) => {
|
|
140
|
+
(!err && data) ? resolve(data) : reject(err)
|
|
141
|
+
})
|
|
142
|
+
})
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { DatabaseConnection, DatabaseIntrospector, Dialect, DialectAdapter, Driver, Kysely, QueryCompiler } from 'kysely'
|
|
2
|
+
import { SqliteAdapter, SqliteIntrospector, SqliteQueryCompiler } from 'kysely'
|
|
3
|
+
import { BunWorkerDriver } from './driver'
|
|
4
|
+
import type { Promisable } from './type'
|
|
5
|
+
|
|
6
|
+
export interface BunWorkerDialectConfig {
|
|
7
|
+
/**
|
|
8
|
+
* db file path
|
|
9
|
+
*
|
|
10
|
+
* @default ':memory:'
|
|
11
|
+
*/
|
|
12
|
+
url?: string
|
|
13
|
+
onCreateConnection?: (connection: DatabaseConnection) => Promisable<void>
|
|
14
|
+
/**
|
|
15
|
+
* use bun:sqlite's built-in statment cache
|
|
16
|
+
* @see https://bun.sh/docs/api/sqlite#query
|
|
17
|
+
*/
|
|
18
|
+
cacheStatment?: boolean
|
|
19
|
+
/**
|
|
20
|
+
* custom worker, default is a worker that use bun:sqlite
|
|
21
|
+
*/
|
|
22
|
+
worker?: Worker
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class BunWorkerDialect implements Dialect {
|
|
26
|
+
#config?: BunWorkerDialectConfig
|
|
27
|
+
constructor(config?: BunWorkerDialectConfig) {
|
|
28
|
+
this.#config = config
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
createDriver(): Driver {
|
|
32
|
+
return new BunWorkerDriver(this.#config)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
createQueryCompiler(): QueryCompiler {
|
|
36
|
+
return new SqliteQueryCompiler()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
createAdapter(): DialectAdapter {
|
|
40
|
+
return new SqliteAdapter()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
createIntrospector(db: Kysely<any>): DatabaseIntrospector {
|
|
44
|
+
return new SqliteIntrospector(db)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Emitter, EventHandlerMap, EventType, Handler } from 'mitt'
|
|
2
|
+
import mitt from 'mitt'
|
|
3
|
+
|
|
4
|
+
export interface EmitterOnce<Events extends Record<EventType, unknown>> extends Emitter<Events> {
|
|
5
|
+
once<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function mittOnce<Events extends Record<EventType, unknown>>(
|
|
9
|
+
all?: EventHandlerMap<Events>,
|
|
10
|
+
): EmitterOnce<Events> {
|
|
11
|
+
const emitter = mitt<Events>(all)
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
...emitter,
|
|
15
|
+
|
|
16
|
+
once<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>) {
|
|
17
|
+
const fn = (arg: Events[Key]) => {
|
|
18
|
+
emitter.off(type, fn)
|
|
19
|
+
handler(arg)
|
|
20
|
+
}
|
|
21
|
+
emitter.on(type, fn)
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { QueryResult } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export type Promisable<T> = T | Promise<T>
|
|
4
|
+
|
|
5
|
+
export type RunMode = 'exec' | 'query' | 'raw'
|
|
6
|
+
|
|
7
|
+
export type MainMsg =
|
|
8
|
+
| {
|
|
9
|
+
type: 'run'
|
|
10
|
+
mode: RunMode
|
|
11
|
+
sql: string
|
|
12
|
+
parameters?: readonly unknown[]
|
|
13
|
+
}
|
|
14
|
+
| {
|
|
15
|
+
type: 'close'
|
|
16
|
+
}
|
|
17
|
+
| {
|
|
18
|
+
type: 'init'
|
|
19
|
+
url: string
|
|
20
|
+
cache: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type WorkerMsg = {
|
|
24
|
+
[K in keyof Events]: {
|
|
25
|
+
type: K
|
|
26
|
+
data: Events[K]
|
|
27
|
+
err: unknown
|
|
28
|
+
}
|
|
29
|
+
}[keyof Events]
|
|
30
|
+
interface Events {
|
|
31
|
+
run: QueryResult<any> | null
|
|
32
|
+
init: null
|
|
33
|
+
close: null
|
|
34
|
+
}
|
|
35
|
+
export type EventWithError = {
|
|
36
|
+
[K in keyof Events]: {
|
|
37
|
+
data: Events[K]
|
|
38
|
+
err: unknown
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import Database from 'bun:sqlite'
|
|
2
|
+
import type { QueryResult } from 'kysely'
|
|
3
|
+
import type { MainMsg, RunMode, WorkerMsg } from './type'
|
|
4
|
+
|
|
5
|
+
let db: Database
|
|
6
|
+
let cache: boolean
|
|
7
|
+
function run(mode: RunMode, sql: string, parameters?: readonly unknown[]): QueryResult<any> {
|
|
8
|
+
const stmt = db[cache ? 'query' : 'prepare'](sql)
|
|
9
|
+
|
|
10
|
+
let rows: unknown[] = []
|
|
11
|
+
if (mode !== 'exec')
|
|
12
|
+
|
|
13
|
+
rows = stmt.all(parameters as any)
|
|
14
|
+
|
|
15
|
+
if (mode === 'query')
|
|
16
|
+
return { rows }
|
|
17
|
+
|
|
18
|
+
stmt.run(parameters as any)
|
|
19
|
+
return {
|
|
20
|
+
rows,
|
|
21
|
+
// @ts-expect-error get insert id
|
|
22
|
+
insertId: db.query('SELECT last_insert_rowid() as i').get().i,
|
|
23
|
+
// @ts-expect-error get changes
|
|
24
|
+
numAffectedRows: db.query('SELECT changes() as c').get().c,
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// @ts-expect-error bun worker
|
|
29
|
+
onmessage = ({ data }: MessageEvent<MainMsg>) => {
|
|
30
|
+
const ret: WorkerMsg = {
|
|
31
|
+
type: data.type,
|
|
32
|
+
data: null,
|
|
33
|
+
err: null,
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
switch (data.type) {
|
|
37
|
+
case 'run':
|
|
38
|
+
ret.data = run(data.mode, data.sql, data.parameters)
|
|
39
|
+
break
|
|
40
|
+
case 'close':
|
|
41
|
+
db.close()
|
|
42
|
+
break
|
|
43
|
+
case 'init':
|
|
44
|
+
db = new Database(data.url, { create: true })
|
|
45
|
+
cache = data.cache
|
|
46
|
+
break
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
ret.err = error
|
|
51
|
+
}
|
|
52
|
+
postMessage(ret)
|
|
53
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// import { storage } from '@stacksjs/storage'
|
|
2
|
+
import { path as p } from '@stacksjs/path'
|
|
3
|
+
import { log } from '@stacksjs/cli'
|
|
4
|
+
|
|
5
|
+
// import type { Model, SchemaOptions } from '@stacksjs/types'
|
|
6
|
+
// import { titleCase } from '@stacksjs/strings'
|
|
7
|
+
|
|
8
|
+
// const { fs } = storage
|
|
9
|
+
|
|
10
|
+
// function readModelsFromFolder(folderPath: string): Promise<Model[]> {
|
|
11
|
+
// return new Promise((resolve, reject) => {
|
|
12
|
+
// const models: Model[] = []
|
|
13
|
+
|
|
14
|
+
// fs.readdir(folderPath, (err, files) => {
|
|
15
|
+
// if (err)
|
|
16
|
+
// reject(err)
|
|
17
|
+
|
|
18
|
+
// const promises = files
|
|
19
|
+
// .filter(file => file.endsWith('.ts'))
|
|
20
|
+
// .map((file) => {
|
|
21
|
+
// const filePath = `${folderPath}/${file}`
|
|
22
|
+
|
|
23
|
+
// return import(filePath).then((data) => {
|
|
24
|
+
// models.push({
|
|
25
|
+
// name: data.default.name,
|
|
26
|
+
// fields: data.default.fields,
|
|
27
|
+
// })
|
|
28
|
+
// })
|
|
29
|
+
// })
|
|
30
|
+
|
|
31
|
+
// Promise.all(promises)
|
|
32
|
+
// .then(() => resolve(models))
|
|
33
|
+
// .catch(err => reject(err))
|
|
34
|
+
// })
|
|
35
|
+
// })
|
|
36
|
+
// }
|
|
37
|
+
|
|
38
|
+
// async function migrate(path: string, options: SchemaOptions): Promise<void> {
|
|
39
|
+
// const models = await readModelsFromFolder(projectPath('app/Models'))
|
|
40
|
+
|
|
41
|
+
// generatePrismaSchema(models, path, options)
|
|
42
|
+
// }
|
|
43
|
+
|
|
44
|
+
export interface MigrationOptions {
|
|
45
|
+
name: string
|
|
46
|
+
up: string
|
|
47
|
+
down: string
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function generateMigrationFile(options: MigrationOptions) {
|
|
51
|
+
const { name, up, down } = options
|
|
52
|
+
|
|
53
|
+
const timestamp = new Date().getTime().toString()
|
|
54
|
+
const fileName = `${timestamp}-${name}.ts`
|
|
55
|
+
const filePath = p.frameworkPath(`database/migrations/${fileName}`)
|
|
56
|
+
const fileContent = `
|
|
57
|
+
import { Migration } from '@stacksjs/database'
|
|
58
|
+
|
|
59
|
+
export default new Migration({
|
|
60
|
+
name: '${name}',
|
|
61
|
+
up: \`
|
|
62
|
+
${up}
|
|
63
|
+
\`,
|
|
64
|
+
down: \`
|
|
65
|
+
${down}
|
|
66
|
+
\`,
|
|
67
|
+
})
|
|
68
|
+
`
|
|
69
|
+
// TODO: use Bun.write
|
|
70
|
+
fs.writeFileSync(filePath, fileContent)
|
|
71
|
+
|
|
72
|
+
log.info(`Created migration file: ${fileName}`)
|
|
73
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// import { MysqlDialect, QueryBuilder, createPool } from '@stacksjs/query-builder'
|
|
2
|
+
// import { filesystem } from '@stacksjs/storage'
|
|
3
|
+
// import type { Model } from '@stacksjs/types'
|
|
4
|
+
// import { projectPath } from '@stacksjs/path'
|
|
5
|
+
// import { database as config } from '@stacksjs/config'
|
|
6
|
+
|
|
7
|
+
// const { fs } = filesystem
|
|
8
|
+
|
|
9
|
+
// function readModels(folderPath: string): Promise<Model[]> {
|
|
10
|
+
// return new Promise((resolve, reject) => {
|
|
11
|
+
// const models: Model[] = []
|
|
12
|
+
|
|
13
|
+
// fs.readdir(folderPath, (err, files) => {
|
|
14
|
+
// if (err)
|
|
15
|
+
// reject(err)
|
|
16
|
+
|
|
17
|
+
// const promises = files
|
|
18
|
+
// .filter(file => file.endsWith('.ts'))
|
|
19
|
+
// .map((file) => {
|
|
20
|
+
// const filePath = `${folderPath}/${file}`
|
|
21
|
+
|
|
22
|
+
// return import(filePath).then((data) => {
|
|
23
|
+
// models.push({
|
|
24
|
+
// name: data.default.name,
|
|
25
|
+
// fields: data.default.fields,
|
|
26
|
+
// useSeed: data.default.useSeed,
|
|
27
|
+
// })
|
|
28
|
+
// })
|
|
29
|
+
// })
|
|
30
|
+
|
|
31
|
+
// Promise.all(promises)
|
|
32
|
+
// .then(() => resolve(models))
|
|
33
|
+
// .catch(err => reject(err))
|
|
34
|
+
// })
|
|
35
|
+
// })
|
|
36
|
+
// }
|
|
37
|
+
|
|
38
|
+
async function seed() {
|
|
39
|
+
// const db = new QueryBuilder({
|
|
40
|
+
// dialect: new MysqlDialect({
|
|
41
|
+
// pool: createPool({
|
|
42
|
+
// database: config.database,
|
|
43
|
+
// host: config.host,
|
|
44
|
+
// password: config.password,
|
|
45
|
+
// user: config.username,
|
|
46
|
+
// }),
|
|
47
|
+
// }),
|
|
48
|
+
// })
|
|
49
|
+
|
|
50
|
+
// const models = await readModels(projectPath('app/Models'))
|
|
51
|
+
|
|
52
|
+
// const queries = models.flatMap((model) => {
|
|
53
|
+
// const { seedable, fields } = model
|
|
54
|
+
|
|
55
|
+
// if (!seedable)
|
|
56
|
+
// return []
|
|
57
|
+
|
|
58
|
+
// const count = typeof seedable === 'boolean' ? 10 : seedable.count
|
|
59
|
+
|
|
60
|
+
// const records: Record<string, any>[] = []
|
|
61
|
+
// for (let i = 0; i < count; i++) {
|
|
62
|
+
// const record: Record<string, any> = {}
|
|
63
|
+
// Object.entries(fields).forEach(([name, field]) => {
|
|
64
|
+
// if (field.factory)
|
|
65
|
+
// record[name] = field.factory()
|
|
66
|
+
// })
|
|
67
|
+
// records.push(record)
|
|
68
|
+
// }
|
|
69
|
+
|
|
70
|
+
// return model
|
|
71
|
+
// // return db.insertInto('users').values(records).build(sql`RETURNING *`)
|
|
72
|
+
// })
|
|
73
|
+
|
|
74
|
+
// const { rows } = await db.transaction().execute()
|
|
75
|
+
|
|
76
|
+
// return rows
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { seed }
|