Created
July 25, 2019 14:26
-
-
Save dgreene1/0506e91c81e7a5b3465b74ea72db1235 to your computer and use it in GitHub Desktop.
How to check that you generated a schema when a TypeOrm entities change
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
import { execSync } from 'child_process'; | |
import * as fs from 'fs'; | |
// tslint:disable-next-line: no-console | |
console.log('...'); | |
// tslint:disable-next-line: no-console | |
console.log('Starting the process of checking if a migration script exists for the current schema...'); | |
const failureArtifactName = 'FAILURE--THIS_PROVES_A_DEV_FORGOT_TO_GENERATE_AND_APPLY_A_SCHEMA'; | |
const walk = (dir: string) : string[] => { | |
let results: string[] = []; | |
const list = fs.readdirSync(dir); | |
list.forEach(file => { | |
file = dir + '/' + file; | |
const stat = fs.statSync(file); | |
if (stat && stat.isDirectory()) { | |
/* Recursively iterate into a subdirectory */ | |
results = results.concat(walk(file)); | |
} else { | |
/* Is a file */ | |
results.push(file); | |
} | |
}); | |
return results; | |
} | |
const findFileInNestedPath = (startingDir: string, fileNameSection: string): string => { | |
const paths = walk(startingDir); | |
const results = paths.filter(aPath => aPath.includes(fileNameSection)); | |
if(results.length === 0){ | |
throw new Error(`Could not find a file containing ${fileNameSection} within the ${startingDir} directory`); | |
} | |
if(results.length > 1){ | |
throw new Error(`Did not expect to find more than one file. However, we found: ${results.join(' and ')}`); | |
} | |
return results[0]; | |
} | |
const stdout = execSync( | |
`ts-node ./node_modules/typeorm/cli migration:generate --dir ./src/db/migration --name ${failureArtifactName}`, | |
); | |
const outputAStr = stdout.toString(); | |
if (!outputAStr.includes('No changes in database schema were found')) { | |
const generalErrMsg = 'The developer forgot to create a migration script'; | |
const errorMsg = outputAStr.includes('generated successfully') | |
? `${generalErrMsg} and/or there were issues: ${outputAStr}` | |
: generalErrMsg; | |
// Now delete the artifact since you don't want that to hang around | |
try{ | |
const pathOfArtifact = findFileInNestedPath('.', failureArtifactName); | |
fs.unlinkSync(pathOfArtifact); | |
} catch(err){ | |
// tslint:disable-next-line: no-console | |
console.warn('Unable to cleanup the artifact due to this error: ' + err); | |
} | |
throw new Error(errorMsg); | |
} else { | |
// tslint:disable-next-line: no-console | |
console.log('Success: Schemas are up-to-date with the code.'); | |
} |
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
{ | |
"name": "EXAMPLE REPO NAME", | |
"version": "1.3.0", | |
"engines": { | |
"node": "10.15.3" | |
}, | |
"description": "THIS IS AN EXAMPLE. PLEASE DON'T COPY AS IS", | |
"main": "build/index.js", | |
"nodemonConfig": { | |
"ignore": [ | |
"serverless/*", | |
"docs/*", | |
"docker/*", | |
"coverage/*" | |
] | |
}, | |
"nyc": { | |
"extension": [ | |
".ts" | |
], | |
"exclude": [ | |
"**/*.d.ts", | |
"**/*_spec.ts", | |
"build", | |
"scripts", | |
"dev-**", | |
"coverage", | |
"plopfile.js", | |
"test/mocks", | |
"test/fixtures", | |
"test/util", | |
"src/api/consumer", | |
"src/db/entities", | |
"src/db/migrations", | |
"src/db/*.ts" | |
], | |
"reporter": [ | |
"html", | |
"lcov", | |
"text" | |
], | |
"all": true | |
}, | |
"husky": { | |
"hooks": { | |
"pre-commit": "lint-staged && yarn pre-commit" | |
} | |
}, | |
"lint-staged": { | |
"*.{js,ts}": [ | |
"prettier --print-width 120 --use-tabs true --single-quote true --trailing-comma all --write", | |
"git add" | |
] | |
}, | |
"scripts": { | |
"build": "yarn tsoa:gen && tsc && mkdirp .tmp && yarn cp:swagger && yarn cp:configs && yarn cp:testfiles", | |
"cp:swagger": "cpx \"./src/swagger.yml\" \"./build\"", | |
"cp:configs": "cpx \"./src/config/*.json\" \"./build/config\"", | |
"cp:testfiles": "cpx src/test/fixtures/json/ ./build/test/fixtures/json", | |
"db:init": "docker-compose up -d && echo 'Next you need to navigate to http://localhost:8000 then enter the email and password defined in docker-compose.yml's pgadmin.environment variables then create a server using the settings defined in docker-compose.yml's db.environment. Note: the ip address on windows will not be localhost, it will be whatever the result is of docker inspect postgres --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ' ", | |
"db:migrate:generate": "echo 'If successful, ignore this message. If it failed, then you forgot to pass a name for this specific migration. Might I recommend the ticket number and branch name?' && ts-node ./node_modules/typeorm/cli migration:generate --dir ./src/db/migration --name", | |
"db:migrate:run": "ts-node ./node_modules/typeorm/cli migration:run", | |
"db:migrate:revert": "ts-node ./node_modules/typeorm/cli migration:revert", | |
"db:migrate:diff": "ts-node ./src/failIfMigrationIsNeeded.ts", | |
"db:start": "docker-compose start", | |
"db:stop": "docker-compose stop", | |
"db:destroy": "docker-compose down --volumes", | |
"dev-server": "mkdirp .tmp && cross-env NODE_ENV=development TZ=UTC nodemon --inspect --nolazy -r ts-node/register -- src/index.ts", | |
"dev-server:debug": "cross-env DEBUG=di-* yarn dev-server", | |
"docker:build": "docker build -t msvc-voice-settings .", | |
"docker:run": "docker run -p 3000:5555 msvc-voice-settings", | |
"lint": "tslint \"{serverless,src}/**/*.ts\"", | |
"start": "cross-env PORT=3000 TZ=UTC node build/index.js", | |
"start:stage": "cross-env NODE_ENV=stage TZ=UTC node build/index.js", | |
"tsoa:gen": "yarn tsoa swagger -c ./tsoa.json && yarn tsoa routes -c ./tsoa.json", | |
"available-routes": "ts-node src/util/available-routes.ts", | |
"pretest": "yarn run build", | |
"test": "cross-env NODE_ENV=test PORT=5554 TZ=UTC mocha --exit --require ts-node/register -t 10000 \"./src/**/*_spec.ts\"", | |
"test:watch": "cross-env NODE_ENV=test PORT=5554 TZ=UTC mocha --watch --watch-extensions ts --exit --require ts-node/register -t 10000 \"./src/**/*_spec.ts\"", | |
"test:cov": "nyc yarn run test", | |
"pre-commit": "tsc && yarn db:migrate:diff && yarn lint && yarn run test:no-watch", | |
"tsnode": "node -r ts-node/register" | |
}, | |
"repository": "THIS IS AN EXAMPLE. PLEASE DON'T COPY THIS AS IS", | |
"license": "UNLICENSED", | |
"private": true, | |
"contributors": [ | |
], | |
"dependencies": { | |
"@types/pino": "^5.8.8", | |
"@types/uuid": "^3.4.5", | |
"axios": "^0.18.0", | |
"boom": "^7.2.0", | |
"cross-env": "^5.2.0", | |
"js-joda": "^1.9.3", | |
"js-joda-timezone": "^2.0.2", | |
"kcors": "^2.2.1", | |
"koa": "^2.5.1", | |
"koa-bodyparser": "^4.2.1", | |
"koa-busboy": "^1.1.1", | |
"koa-compose": "^4.1.0", | |
"koa-compress": "^3.0.0", | |
"koa-router": "^7.4.0", | |
"lodash": "^4.17.11", | |
"nconf": "^0.10.0", | |
"pg": "^7.4.3", | |
"pino": "^5.13.0", | |
"pino-pretty": "^3.2.0", | |
"prom-client": "^11.0.0", | |
"query-string": "^6.1.0", | |
"shortid": "^2.2.8", | |
"swagger2-koa": "^1.0.3", | |
"tsoa": "^2.3.81", | |
"typeorm": "^0.2.13", | |
"uuid": "^3.3.2" | |
}, | |
"devDependencies": { | |
"@types/boom": "^7.2.0", | |
"@types/debug": "^0.0.30", | |
"@types/http-proxy": "^1.16.1", | |
"@types/kcors": "^2.2.3", | |
"@types/koa": "^2.0.45", | |
"@types/koa-bodyparser": "^4.2.0", | |
"@types/koa-compress": "^2.0.8", | |
"@types/koa-router": "^7.0.28", | |
"@types/lodash": "^4.14.109", | |
"@types/nconf": "^0.0.37", | |
"@types/node": "^10.3.3", | |
"@types/query-string": "^5.1.0", | |
"@types/shortid": "^0.0.29", | |
"axios-mock-adapter": "^1.15.0", | |
"cpx": "^1.5.0", | |
"factory.ts": "^0.2.2", | |
"husky": "^1.0.1", | |
"koa-sslify": "^2.1.2", | |
"lint-staged": "^7.1.2", | |
"mkdirp": "^0.5.1", | |
"nodemon": "^1.17.5", | |
"npm": "^6.0.1", | |
"nyc": "^11.8.0", | |
"prettier": "^1.12.1", | |
"ts-node": "^6.0.3", | |
"tslint": "^5.10.0", | |
"tslint-config-prettier": "^1.13.0", | |
"typescript": "^3.3.0" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment