Last active
September 25, 2018 07:07
-
-
Save antho1404/576642a12f07f09f853a42ecf67a45f3 to your computer and use it in GitHub Desktop.
A script to be able to execute some data migrations with graphcool framework
This file contains hidden or 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
| const fs = require('fs') | |
| const os = require('os') | |
| const vm = require('vm') | |
| const yaml = require('js-yaml') | |
| const { paramCase } = require('change-case') | |
| const { GraphQLClient } = require('graphql-request') | |
| const cmd = process.argv[2] | |
| const MIGRATION_PATH = `./db/migrations` | |
| const isLocalTarget = target => target.startsWith('local/') | |
| const endpoint = (target, defaultConf) => isLocalTarget(target) ? defaultConf.clusters.local.host : 'https://api.graph.cool' | |
| const projectId = target => target.split('/')[1] | |
| const authorization = (target, defaultConf) => isLocalTarget(target) | |
| ? defaultConf.clusters.local.clusterSecret | |
| : defaultConf.platformToken | |
| const migrationName = file => file.replace(/.[jt]s$/, '') | |
| const checkMigration = async (file, client) => { | |
| const { allMigrations } = await client.request(`{ | |
| allMigrations(first: 1, filter: { migrationName: "${migrationName(file)}" }) { | |
| id | |
| } | |
| }`) | |
| return allMigrations.length > 0 | |
| } | |
| const migrateFile = async (filename, client) => { | |
| const code = fs.readFileSync(`${MIGRATION_PATH}/${filename}`, 'utf8') | |
| const sandboxedFunc = vm.runInContext(code, vm.createContext({ | |
| console, | |
| require, | |
| module | |
| })) | |
| await sandboxedFunc(client) | |
| const { createMigration } = await client.request(`mutation { | |
| createMigration(migrationName: "${migrationName(filename)}") { | |
| id | |
| migrationName | |
| } | |
| }`) | |
| return createMigration | |
| } | |
| const migrateFiles = async (files, client) => { | |
| for (let i = 0; i < files.length; i++) { | |
| const file = files[i] | |
| const migrated = await checkMigration(file, client) | |
| if (!migrated) { | |
| const { migrationName } = await migrateFile(file, client) | |
| console.log(`Migrations ${migrationName} applied`) | |
| } | |
| } | |
| } | |
| const migrate = () => { | |
| const { targets } = yaml.safeLoad(fs.readFileSync('./.graphcoolrc', 'utf8')) | |
| const defaultConf = yaml.safeLoad(fs.readFileSync(`${os.homedir()}/.graphcoolrc`, 'utf8')) | |
| const target = targets[process.argv[3] || 'dev'] | |
| const api = `${endpoint(target, defaultConf)}/simple/v1/${projectId(target)}` | |
| const client = new GraphQLClient(api, { headers: { 'Authorization': `Bearer ${authorization(target, defaultConf)}` } }) | |
| console.log(`Migration in progress for ${api}`) | |
| fs.readdir(MIGRATION_PATH, (err, files) => err | |
| ? console.error(err) | |
| : migrateFiles(files, client) | |
| ) | |
| } | |
| const create = () => { | |
| const name = process.argv[3] | |
| if (!name) throw new Error('You should give a name to your migration') | |
| const time = (new Date()).toISOString() | |
| const filename = [time, paramCase(name)].join('_') | |
| const content = `module.exports = async client => {}` | |
| const path = `${MIGRATION_PATH}/${filename}.js` | |
| fs.writeFile(path, content, err => err | |
| ? console.error(err) | |
| : console.log(`migration file written at ${path}`) | |
| ) | |
| } | |
| ;({ | |
| create, | |
| migrate | |
| }[cmd] || migrate)() |
Author
You may be able to simplify this using umzug which is a really nice unopinionated migration runner.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In your project just add a
db/migrationsfolder and put this file indbAlso you need to add in your
types.graphqla new model that will ensure that your migration run only one timethen you can run the following commands
node db/migration create migration-name: This will create a new file indb/migrationsand you can write your migration in it, the client given in parameter will be configured to access the graphcool project according to your.graphcoolrcfilenode db/migration migrate [target]: This will run all the migrations that hasn't been deployed yet, you can give thetargetin parameter and it will by default use thedefaultyou have in your.graphcoolrcfile