Skip to content

Commit cc89631

Browse files
committed
Use dataSource instead of ormconfig
1 parent 51b03f5 commit cc89631

File tree

8 files changed

+137
-157
lines changed

8 files changed

+137
-157
lines changed

sample/test/datasource.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { join } from 'path'
2+
import { DataSource } from 'typeorm'
3+
4+
const ds = new DataSource({
5+
name: 'file',
6+
type: 'sqlite',
7+
database: ':memory:',
8+
entities: ['sample/entities/**/*{.ts,.js}'],
9+
})
10+
11+
export default ds

sample/test/sample.integration.test.ts

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,53 @@ import {
44
tearDownDatabase,
55
factory,
66
setConnectionOptions,
7+
ConnectionOptions,
8+
configureConnection,
79
} from '../../src/typeorm-seeding'
810
import { User } from '../entities/User.entity'
9-
import { Connection } from 'typeorm'
11+
import { DataSource } from 'typeorm'
12+
import { join } from 'path'
13+
14+
const inMemoryDb: ConnectionOptions = {
15+
name: 'memory',
16+
type: 'sqlite',
17+
database: ':memory:',
18+
entities: ['sample/entities/**/*{.ts,.js}'],
19+
factories: ['sample/factories/**/*{.ts,.js}'],
20+
seeds: ['sample/seeds/**/*{.ts,.js}'],
21+
}
1022

1123
describe('Sample Integration Test', () => {
12-
let connection: Connection
13-
beforeAll(async () => {
14-
setConnectionOptions({
15-
type: 'sqlite',
16-
database: ':memory:',
17-
entities: ['sample/entities/**/*{.ts,.js}'],
18-
})
19-
connection = await useRefreshDatabase()
20-
await useSeeding()
21-
})
24+
let dataSource: DataSource
2225

23-
afterAll(async () => {
26+
afterEach(async () => {
2427
await tearDownDatabase()
2528
})
2629

2730
test('Should create a user with the entity factory', async () => {
31+
setConnectionOptions(inMemoryDb)
32+
dataSource = await useRefreshDatabase()
33+
await useSeeding()
34+
2835
const createdUser = await factory(User)().create()
29-
const user = await connection.getRepository(User).findOne({ where: { id: createdUser.id } })
36+
const user = await dataSource.getRepository(User).findOne({ where: { id: createdUser.id } })
3037
expect(createdUser.firstName).toBe(user.firstName)
3138
})
39+
40+
test('Should be able to load a datasource.ts file', async () => {
41+
setConnectionOptions({})
42+
configureConnection({
43+
dataSourcePath: join(__dirname, 'datasource.ts'),
44+
})
45+
46+
dataSource = await useRefreshDatabase()
47+
expect(dataSource.options).toEqual(
48+
expect.objectContaining({
49+
database: ':memory:',
50+
entities: ['sample/entities/**/*{.ts,.js}'],
51+
name: 'file',
52+
type: 'sqlite',
53+
}),
54+
)
55+
})
3256
})

src/commands/config.command.ts

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,18 @@
11
import * as yargs from 'yargs'
22
import * as chalk from 'chalk'
33
import { printError } from '../utils/log.util'
4-
import { configureConnection, getConnectionOptions } from '../connection'
4+
import { configureConnection, loadDataSource } from '../connection'
55

66
export class ConfigCommand implements yargs.CommandModule {
77
command = 'config'
88
describe = 'Show the TypeORM config'
99

1010
builder(args: yargs.Argv) {
11-
return args
12-
.option('n', {
13-
alias: 'configName',
14-
default: '',
15-
describe: 'Name of the typeorm config file (json or js).',
16-
})
17-
.option('c', {
18-
alias: 'connection',
19-
default: '',
20-
describe: 'Name of the typeorm connection',
21-
})
22-
.option('r', {
23-
alias: 'root',
24-
default: process.cwd(),
25-
describe: 'Path to your typeorm config file',
26-
})
11+
return args.option('d', {
12+
alias: 'dataSource',
13+
demandOption: true,
14+
describe: 'Path to the file where your DataSource instance is defined.',
15+
})
2716
}
2817

2918
async handler(args: yargs.Arguments) {
@@ -32,12 +21,10 @@ export class ConfigCommand implements yargs.CommandModule {
3221
log('🌱 ' + chalk.bold(`TypeORM Seeding v${(pkg as any).version}`))
3322
try {
3423
configureConnection({
35-
root: args.root as string,
36-
configName: args.configName as string,
37-
connection: args.connection as string,
24+
dataSourcePath: args.dataSource as string,
3825
})
39-
const option = await getConnectionOptions()
40-
log(option)
26+
const ds = await loadDataSource()
27+
log(ds.options)
4128
} catch (error) {
4229
printError('Could not find the orm config file', error)
4330
process.exit(1)

src/commands/seed.command.ts

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,19 @@ import * as chalk from 'chalk'
44
import { importSeed } from '../importer'
55
import { loadFiles, importFiles } from '../utils/file.util'
66
import { runSeeder } from '../typeorm-seeding'
7-
import { configureConnection, getConnectionOptions, ConnectionOptions, createConnection } from '../connection'
7+
import { DataSource } from 'typeorm'
8+
import { configureConnection, getConnectionOptions, ConnectionOptions, loadDataSource } from '../connection'
89

910
export class SeedCommand implements yargs.CommandModule {
1011
command = 'seed'
1112
describe = 'Runs the seeds'
1213

1314
builder(args: yargs.Argv) {
1415
return args
15-
.option('n', {
16-
alias: 'configName',
17-
default: '',
18-
describe: 'Name of the typeorm config file (json or js).',
19-
})
20-
.option('c', {
21-
alias: 'connection',
22-
default: '',
23-
describe: 'Name of the typeorm connection',
24-
})
25-
.option('r', {
26-
alias: 'root',
27-
default: process.cwd(),
28-
describe: 'Path to your typeorm config file',
16+
.option('d', {
17+
alias: 'dataSource',
18+
demandOption: true,
19+
describe: 'Path to the file where your DataSource instance is defined.',
2920
})
3021
.option('seed', {
3122
alias: 's',
@@ -39,16 +30,16 @@ export class SeedCommand implements yargs.CommandModule {
3930
log('🌱 ' + chalk.bold(`TypeORM Seeding v${(pkg as any).version}`))
4031
const spinner = ora('Loading ormconfig').start()
4132
const configureOption = {
42-
root: args.root as string,
43-
configName: args.configName as string,
44-
connection: args.connection as string,
33+
dataSourcePath: args.dataSource as string,
4534
}
4635

36+
let dataSource: DataSource | null = null
4737
// Get TypeORM config file
4838
let option: ConnectionOptions
4939
try {
5040
configureConnection(configureOption)
5141
option = await getConnectionOptions()
42+
dataSource = await loadDataSource()
5243
spinner.succeed('ORM Config loaded')
5344
} catch (error) {
5445
panic(spinner, error, 'Could not load the config file!')
@@ -81,7 +72,7 @@ export class SeedCommand implements yargs.CommandModule {
8172
// Get database connection and pass it to the seeder
8273
spinner.start('Connecting to the database')
8374
try {
84-
await createConnection()
75+
await loadDataSource()
8576
spinner.succeed('Database connected')
8677
} catch (error) {
8778
panic(spinner, error, 'Database connection failed! Check your typeORM config file.')

src/connection.ts

Lines changed: 39 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,73 @@
1-
import {
2-
ConnectionOptionsReader,
3-
Connection as TypeORMConnection,
4-
ConnectionOptions as TypeORMConnectionOptions,
5-
createConnection as TypeORMCreateConnection,
6-
getConnection as TypeORMGetConnection,
7-
} from 'typeorm'
8-
import { printError } from './utils/log.util'
1+
import { resolve } from 'path'
2+
import { DataSource, DataSourceOptions } from 'typeorm'
93

104
interface SeedingOptions {
115
factories: string[]
126
seeds: string[]
137
}
148

15-
export declare type ConnectionOptions = TypeORMConnectionOptions & SeedingOptions
9+
export declare type ConnectionOptions = DataSourceOptions & SeedingOptions
1610

1711
export interface ConfigureOption {
18-
root?: string
19-
configName?: string
20-
connection?: string
12+
dataSourcePath?: string
2113
}
2214

2315
const KEY = 'TypeORM_Seeding_Connection'
2416

25-
const defaultConfigureOption: ConfigureOption = {
26-
root: process.cwd(),
27-
configName: '',
28-
connection: '',
29-
}
30-
3117
if ((global as any)[KEY] === undefined) {
3218
;(global as any)[KEY] = {
33-
configureOption: defaultConfigureOption,
19+
dataSource: undefined as DataSource | undefined,
20+
dataSourcePath: undefined as string | undefined,
3421
ormConfig: undefined,
3522
connection: undefined,
36-
overrideConnectionOptions: {},
23+
overrideConnectionOptions: {
24+
factories: [process.env.TYPEORM_SEEDING_FACTORIES || 'src/database/factories/**/*{.ts,.js}'],
25+
seeds: [process.env.TYPEORM_SEEDING_SEEDS || 'src/database/seeds/**/*{.ts,.js}'],
26+
} as ConnectionOptions,
3727
}
3828
}
3929

4030
export const configureConnection = (option: ConfigureOption = {}) => {
41-
;(global as any)[KEY].configureOption = {
42-
...defaultConfigureOption,
31+
;(global as any)[KEY] = {
32+
...(global as any)[KEY],
4333
...option,
4434
}
4535
}
4636

47-
export const setConnectionOptions = (options: Partial<TypeORMConnectionOptions>): void => {
48-
;(global as any)[KEY].overrideConnectionOptions = options
37+
export const setConnectionOptions = (options: Partial<ConnectionOptions>): void => {
38+
;(global as any)[KEY].overrideConnectionOptions = {
39+
...(global as any)[KEY].overrideConnectionOptions,
40+
...options,
41+
}
4942
}
5043

5144
export const getConnectionOptions = async (): Promise<ConnectionOptions> => {
52-
const ormConfig = (global as any)[KEY].ormConfig
53-
const overrideConnectionOptions = (global as any)[KEY].overrideConnectionOptions
54-
if (ormConfig === undefined) {
55-
const configureOption = (global as any)[KEY].configureOption
56-
const connection = configureOption.connection
57-
const reader = new ConnectionOptionsReader({
58-
root: configureOption.root,
59-
configName: configureOption.configName,
60-
})
61-
let options = (await reader.all()) as any[]
62-
if (connection !== undefined && connection !== '') {
63-
const filteredOptions = options.filter((o) => o.name === connection)
64-
if (filteredOptions.length === 1) {
65-
options = filteredOptions
66-
}
67-
}
68-
if (options.length > 1) {
69-
const filteredOptions = options.filter((o) => o.name === 'default')
70-
if (filteredOptions.length === 1) {
71-
options = filteredOptions
72-
}
73-
}
74-
if (options.length === 1) {
75-
const option = options[0]
76-
if (!option.factories) {
77-
option.factories = [process.env.TYPEORM_SEEDING_FACTORIES || 'src/database/factories/**/*{.ts,.js}']
78-
}
79-
if (!option.seeds) {
80-
option.seeds = [process.env.TYPEORM_SEEDING_SEEDS || 'src/database/seeds/**/*{.ts,.js}']
81-
}
82-
;(global as any)[KEY].ormConfig = {
83-
...option,
84-
...overrideConnectionOptions,
85-
}
86-
return (global as any)[KEY].ormConfig
87-
}
88-
printError('There are multiple connections please provide a connection name')
89-
}
90-
return ormConfig
45+
return (global as any)[KEY].overrideConnectionOptions
9146
}
9247

93-
export const createConnection = async (option?: TypeORMConnectionOptions): Promise<TypeORMConnection> => {
94-
const configureOption = (global as any)[KEY].configureOption
95-
let connection = (global as any)[KEY].connection
96-
let ormConfig = (global as any)[KEY].ormConfig
97-
98-
if (option !== undefined) {
99-
ormConfig = option
48+
export const resetDataSource = async () => {
49+
;(global as any)[KEY].overrideConnectionOptions = {}
50+
const ds = (global as any)[KEY].dataSource as DataSource
51+
if (ds) {
52+
;(global as any)[KEY].dataSource = undefined
53+
return ds && ds.isInitialized ? ds.destroy() : undefined
10054
}
55+
}
56+
57+
export const loadDataSource = async (options?: DataSourceOptions): Promise<DataSource> => {
58+
const { dataSourcePath, dataSource, overrideConnectionOptions } = (global as any)[KEY]
10159

102-
if (connection === undefined) {
103-
try {
104-
connection = await TypeORMGetConnection(configureOption.name)
105-
} catch (_) {}
106-
if (connection === undefined) {
107-
connection = await TypeORMCreateConnection(ormConfig)
60+
let ds: DataSource | undefined
61+
if (!dataSource) {
62+
if (dataSourcePath) {
63+
ds = (await require(resolve(process.cwd(), dataSourcePath))).default as DataSource
64+
ds.setOptions({ ...overrideConnectionOptions, ...options })
65+
} else {
66+
ds = new DataSource({ ...overrideConnectionOptions, ...options })
10867
}
109-
;(global as any)[KEY].connection = connection
68+
await ds.initialize()
69+
;(global as any)[KEY].dataSource = ds
11070
}
111-
return connection
71+
72+
return (global as any)[KEY].dataSource
11273
}

src/entity-factory.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ObjectLiteral, ObjectType, SaveOptions } from 'typeorm'
33
import { FactoryFunction, EntityProperty } from './types'
44
import { isPromiseLike } from './utils/factory.util'
55
import { printError, printWarning } from './utils/log.util'
6-
import { getConnectionOptions, createConnection } from './connection'
6+
import { getConnectionOptions, loadDataSource } from './connection'
77

88
export class EntityFactory<Entity extends ObjectLiteral, Context> {
99
private mapFunction: (entity: Entity) => Promise<Entity>
@@ -39,10 +39,9 @@ export class EntityFactory<Entity extends ObjectLiteral, Context> {
3939
* Create makes a new entity and does persist it
4040
*/
4141
public async create(overrideParams: EntityProperty<Entity> = {}, saveOptions?: SaveOptions): Promise<Entity> {
42-
const option = await getConnectionOptions()
43-
const connection = await createConnection(option)
44-
if (connection && connection.isConnected) {
45-
const em = connection.createEntityManager()
42+
const dataSource = await loadDataSource()
43+
if (dataSource && dataSource.isInitialized) {
44+
const em = dataSource.createEntityManager()
4645
try {
4746
const entity = await this.makeEnity(overrideParams, true)
4847
return await em.save<Entity>(entity, saveOptions)
@@ -52,6 +51,7 @@ export class EntityFactory<Entity extends ObjectLiteral, Context> {
5251
throw new Error(message)
5352
}
5453
} else {
54+
console.warn('No db connection is given: ', dataSource.isInitialized, dataSource)
5555
const message = 'No db connection is given'
5656
printError(message)
5757
throw new Error(message)

0 commit comments

Comments
 (0)