Skip to content
This repository was archived by the owner on Oct 1, 2021. It is now read-only.

Commit d9311b0

Browse files
committed
'add' command for CLI
License: MIT Signed-off-by: Adam Uhlir <[email protected]>
1 parent 3b18eba commit d9311b0

File tree

5 files changed

+148
-4
lines changed

5 files changed

+148
-4
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ build
2525
dist
2626

2727
# Dependency directory
28-
node_modules/
28+
/node_modules

migrations/index.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
1+
'use strict'
2+
3+
// Do not modify this file manually as it will be overridden when running 'add' CLI command.
4+
// Modify migration-templates.js file
5+
6+
const emptyMigration = {
7+
description: 'Empty migration.',
8+
reversible: true,
9+
migrate: () => {},
10+
revert: () => {},
11+
empty: true,
12+
}
113

214
module.exports = [
3-
// Place to hook up migrations
15+
require('./migration-8'),
416
]

src/cli.js

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ async function main(args) {
3131
.command(commands.migrate)
3232
.command(commands.revert)
3333
.command(commands.status)
34+
.command(commands.add)
3435
.demandCommand(1, 'You need at least one command before continuing')
3536
.strict()
3637
.fail((msg, err, yargs) => {

src/commands.js

+58-2
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,28 @@
22

33
const os = require('os')
44
const path = require('path')
5+
const fs = require('fs')
56
const process = require('process')
7+
const util = require('util');
8+
9+
const writeFile = util.promisify(fs.writeFile)
10+
const mkdir = util.promisify(fs.mkdir)
11+
const exec = util.promisify(require('child_process').exec);
612

713
const chalk = require('chalk')
814

915
const repoVersion = require('./repo/version')
1016
const migrator = require('./index')
17+
const templates = require('./migration-templates')
18+
const migrations = require('../migrations')
1119

1220
function asyncClosure(fnc) {
1321
return function asyncWrapper({resolve, ...options}) {
1422
resolve(fnc(options))
1523
}
1624
}
1725

18-
function reportingClosure(action){
26+
function reportingClosure(action) {
1927
return (migration, currentlyMigrated, totalToMigrate) =>
2028
process.stdout.write(`${chalk.green(`[${currentlyMigrated}/${totalToMigrate}]`)} Successfully ${action} ${chalk.bold(migration.version)}: ${migration.description}\n`)
2129
}
@@ -41,6 +49,44 @@ async function status({repoPath}) {
4149
return `${statusString}\nCurrent repo version: ${version}\nLast migration's version: ${lastMigrationVersion}`
4250
}
4351

52+
async function getAuthor() {
53+
try {
54+
const name = (await exec('git config --get user.name'))['stdout']
55+
const email = (await exec('git config --get user.email'))['stdout']
56+
return `${name.replace('\n', '')} <${email.replace('\n', '')}>`
57+
} catch (e) {
58+
return ''
59+
}
60+
}
61+
62+
async function add({repoPath, empty}) {
63+
const newMigrationVersion = migrator.getLatestMigrationVersion() + 1
64+
const newMigrationFolder = path.join(__dirname, '..', 'migrations', 'migration-' + newMigrationVersion)
65+
66+
const migrationsImport = migrations.map((migration) => migration.empty ? ` Object.assign({version: ${migration.version}}, emptyMigration),` : ` require('./migration-${migration.version}'),`)
67+
if (empty) {
68+
migrationsImport.push(` Object.assign({version: ${newMigrationVersion}}, emptyMigration),`)
69+
} else {
70+
migrationsImport.push(` require('./migration-${newMigrationVersion}'),`)
71+
}
72+
const migrationsIndexJsContent = templates.migrationsIndexJs
73+
.replace('{{imports}}', migrationsImport.join('\n'))
74+
;await writeFile(path.join(newMigrationFolder, '..', 'index.js'), migrationsIndexJsContent)
75+
76+
if (empty) return
77+
78+
await mkdir(newMigrationFolder)
79+
80+
const packageJsonContent = templates.packageJson
81+
.replace(/{{version}}/gi, newMigrationVersion)
82+
.replace(/{{author}}/gi, await getAuthor())
83+
;await writeFile(path.join(newMigrationFolder, 'package.json'), packageJsonContent)
84+
85+
const indexJsContent = templates.indexJs
86+
.replace(/{{version}}/gi, newMigrationVersion)
87+
;await writeFile(path.join(newMigrationFolder, 'index.js'), indexJsContent)
88+
}
89+
4490
module.exports = {
4591
migrate: {
4692
command: 'migrate',
@@ -74,5 +120,15 @@ module.exports = {
74120
command: 'status',
75121
describe: 'Display status of IPFS repo',
76122
handler: asyncClosure(status),
77-
}
123+
},
124+
add: {
125+
command: 'add',
126+
describe: 'Bootstrap new migration',
127+
handler: asyncClosure(add),
128+
builder: yargv => yargv
129+
.option('empty', {
130+
describe: 'Creates empty migration',
131+
type: 'boolean'
132+
})
133+
},
78134
}

src/migration-templates.js

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
'use strict'
2+
3+
module.exports = {
4+
packageJson: `{
5+
"name": "ipfs-repo-migration-{{version}}",
6+
"version": "0.1.0",
7+
"description": "Migration",
8+
"author": "{{author}}",
9+
"main": "index.js",
10+
"files": [
11+
"index.js",
12+
"node_modules"
13+
],
14+
"engines": {
15+
"node": ">=10.0.0",
16+
"npm": ">=3.0.0"
17+
},
18+
"dependencies": {
19+
},
20+
"license": "MIT"
21+
}`,
22+
23+
indexJs: `'use strict'
24+
25+
const Dastore = require('datastore-fs')
26+
const log = require('debug')('jsipfs-repo-migrations:migration-{{version}}')
27+
28+
async function migrate(repoPath, isBrowser) {
29+
const store = new Dastore(repoPath, {extension: '', createIfMissing: false})
30+
store.open()
31+
32+
try {
33+
// Your migration
34+
} finally {
35+
await store.close()
36+
}
37+
}
38+
39+
async function revert(repoPath, isBrowser) {
40+
const store = new Dastore(repoPath, {extension: '', createIfMissing: false})
41+
store.open()
42+
43+
try {
44+
// Your reversion of migration (if supported)
45+
} finally {
46+
await store.close()
47+
}
48+
}
49+
50+
module.exports = {
51+
version: {{version}},
52+
description: '', // <--- Fill in your description here
53+
reversible: true,
54+
migrate,
55+
revert,
56+
}`,
57+
58+
migrationsIndexJs: `'use strict'
59+
60+
// Do not modify this file manually as it will be overridden when running 'add' CLI command.
61+
// Modify migration-templates.js file
62+
63+
const emptyMigration = {
64+
description: 'Empty migration.',
65+
reversible: true,
66+
migrate: () => {},
67+
revert: () => {},
68+
empty: true,
69+
}
70+
71+
module.exports = [
72+
{{imports}}
73+
]
74+
`
75+
}

0 commit comments

Comments
 (0)