Last active
July 22, 2021 13:14
-
-
Save tux86/4cc1066647054cc7958bfd81f3337758 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*** | |
* typeorm-cli very fast fixtures loading (based on transactions) | |
* | |
* Usage example : | |
* ts-node typeorm-fixtures-cli.ts --fixturesPath ./fixtures --transactionBatchSize 250 --delete | |
*/ | |
import * as path from 'path' | |
import * as fs from 'fs' | |
import { program } from 'commander' | |
import { Builder, fixturesIterator, IEntity, Loader, Parser, Resolver } from 'typeorm-fixtures-cli' | |
import { getConnection } from '@/clients/typeOrm' | |
import { getRepository } from 'typeorm' | |
interface Options { | |
fixturesPath: string, | |
transactionBatchSize: number | |
deleteEnabled: boolean | |
} | |
program.version('0.0.1') | |
.requiredOption('-p, --fixturesPath <path>', 'fixtures directory path', './fixtures') | |
.requiredOption('-s, --transactionBatchSize <size>', 'transaction batch size', '250') | |
.option('-d, --delete', 'enable data deleting before loading fixtures') | |
program.parse(process.argv) | |
const opts = program.opts() | |
const options = { | |
fixturesPath: opts.fixturesPath, | |
transactionBatchSize: parseInt(opts.transactionBatchSize), | |
deleteEnabled: opts.delete || false | |
} | |
const loadFixtures = async (options: Options) => { | |
const { fixturesPath, transactionBatchSize, deleteEnabled } = options | |
const connection = await getConnection() | |
await connection.synchronize(false) | |
const queryRunner = connection.createQueryRunner() | |
try { | |
const loader = new Loader() | |
// load fixtures files | |
fs.readdirSync(fixturesPath).forEach(file => { | |
const fullPath = path.resolve(fixturesPath, file) | |
if (fs.lstatSync(fullPath).isDirectory()) { | |
loader.load(fullPath) | |
} | |
}) | |
const resolver = new Resolver() | |
const fixtures = resolver.resolve(loader.fixtureConfigs) | |
const builder = new Builder(connection, new Parser()) | |
let total = 0 | |
const entitiesMap = new Map<string, IEntity[]>() | |
const entityTableMapping = new Map<string, string>() | |
for (const fixture of fixturesIterator(fixtures)) { | |
total++ | |
const entity = await builder.build(fixture) | |
const { name } = entity.constructor | |
if (!entityTableMapping.has(name)) { | |
entityTableMapping.set(name, getRepository(name).metadata.tableName) | |
} | |
if (!entitiesMap.has(name)) { | |
entitiesMap.set(name, []) | |
} | |
entitiesMap.get(name).push(entity) | |
} | |
console.log('total fixtures:', total) | |
// =================== WRITE TRANSACTION ======================== | |
await queryRunner.startTransaction() | |
const truncatePromises = [] | |
if (deleteEnabled) { | |
for (const [k, v] of entityTableMapping) { | |
// console.log('truncate ', v) | |
truncatePromises.push(queryRunner.query(`TRUNCATE TABLE ${v} CASCADE`)) | |
} | |
} | |
process.stdout.write('deleting ... ') | |
await Promise.all(truncatePromises) | |
process.stdout.write('ok\n') | |
for (const [entityName, entities] of entitiesMap) { | |
const total = entities.length | |
const savePromises = [] | |
while (entities.length > 0) { | |
const entitiesBatch = entities.splice(0, transactionBatchSize) | |
savePromises.push(queryRunner.manager.save(entityName, entitiesBatch)) | |
} | |
process.stdout.write(`persisting "${entityName}" ${total} fixture(s) ... `) | |
await Promise.all(savePromises) | |
process.stdout.write('ok\n') | |
} | |
await queryRunner.commitTransaction() | |
} catch (err) { | |
console.error(err) | |
if (queryRunner.isTransactionActive) { | |
await queryRunner.rollbackTransaction() | |
} | |
throw err | |
} finally { | |
await queryRunner.release() | |
if (connection) { | |
await connection.close() | |
} | |
} | |
} | |
loadFixtures(options) | |
.then(() => { | |
console.log('Fixtures are successfully loaded.') | |
}) | |
.catch(err => console.log(err)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment