-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial implementation of docs syncing to rdme!
- Loading branch information
Dom Harrington
committed
May 2, 2018
1 parent
4d76dab
commit d4e312d
Showing
7 changed files
with
195 additions
and
1 deletion.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
const request = require('request-promise-native'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const config = require('config'); | ||
const frontMatter = require('gray-matter'); | ||
const { promisify } = require('util'); | ||
|
||
const readFile = promisify(fs.readFile); | ||
|
||
exports.desc = 'Sync a folder of markdown files to your ReadMe project'; | ||
exports.category = 'services'; | ||
exports.weight = 2; | ||
|
||
exports.run = function({ args, opts }) { | ||
const { key, version } = opts; | ||
|
||
if (!key) { | ||
return Promise.reject(new Error('No api key provided. Please use --key')); | ||
} | ||
|
||
if (!version) { | ||
return Promise.reject(new Error('No version provided. Please use --version')); | ||
} | ||
|
||
if (!args[0]) { | ||
return Promise.reject(new Error('No folder provided. Usage `rdme docs <folder>`')); | ||
} | ||
|
||
const files = fs | ||
.readdirSync(args[0]) | ||
.filter(file => file.endsWith('.md') || file.endsWith('.markdown')); | ||
|
||
const options = { | ||
auth: { user: key }, | ||
headers: { | ||
'x-readme-version': version, | ||
}, | ||
}; | ||
|
||
function validationErrors(err) { | ||
if (err.statusCode === 400) { | ||
console.log(err.error); | ||
return Promise.reject(); | ||
}; | ||
|
||
return Promise.reject(err); | ||
} | ||
|
||
function createDoc(slug, file, err) { | ||
if (err.statusCode !== 404) return Promise.reject(err.error); | ||
|
||
return request.post(`${config.host}/api/v1/docs`, { | ||
json: { slug, body: file.content, ...file.data }, | ||
...options, | ||
}).catch(validationErrors); | ||
} | ||
|
||
function updateDoc(slug, file, existingDoc) { | ||
return request.put(`${config.host}/api/v1/docs/${slug}`, { | ||
json: Object.assign(existingDoc, { body: file.content, ...file.data }), | ||
...options, | ||
}).catch(validationErrors); | ||
} | ||
|
||
return Promise.all( | ||
files.map(async filename => { | ||
const file = frontMatter(await readFile(path.join(args[0], filename), 'utf8')); | ||
// Stripping the markdown extension from the filename | ||
const slug = filename.replace(path.extname(filename), ''); | ||
|
||
return request.get(`${config.host}/api/v1/docs/${slug}`, { | ||
json: true, | ||
...options, | ||
}).then(updateDoc.bind(null, slug, file), createDoc.bind(null, slug, file)); | ||
}), | ||
); | ||
}; |
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
const nock = require('nock'); | ||
const config = require('config'); | ||
const assert = require('assert'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const frontMatter = require('gray-matter'); | ||
|
||
const docs = require('../cli').bind(null, 'docs'); | ||
|
||
const key = 'Xmw4bGctRVIQz7R7dQXqH9nQe5d0SPQs'; | ||
const version = '1.0.0'; | ||
|
||
describe('docs command', () => { | ||
beforeAll(() => nock.disableNetConnect()); | ||
afterAll(() => nock.cleanAll()); | ||
|
||
it('should error if no api key provided', () => | ||
docs([], {}).catch(err => { | ||
assert.equal(err.message, 'No api key provided. Please use --key'); | ||
})); | ||
|
||
it('should error if no version provided', () => | ||
docs([], { key }).catch(err => { | ||
assert.equal(err.message, 'No version provided. Please use --version'); | ||
})); | ||
|
||
it('should error if no folder provided', () => | ||
docs([], { key, version: '1.0.0' }).catch(err => { | ||
assert.equal(err.message, 'No folder provided. Usage `rdme docs <folder>`'); | ||
})); | ||
|
||
it('should error if the argument isnt a folder'); | ||
it('should error if the folder contains no markdown files'); | ||
|
||
describe('existing docs', () => { | ||
it('should fetch doc and merge with what is returned', () => { | ||
const slug = 'simple-doc'; | ||
const doc = frontMatter( | ||
fs.readFileSync(path.join(__dirname, `./fixtures/existing-docs/${slug}.md`)), | ||
); | ||
|
||
const getMock = nock(config.host, { | ||
reqheaders: { | ||
'x-readme-version': version, | ||
}, | ||
}) | ||
.get(`/api/v1/docs/${slug}`) | ||
.basicAuth({ user: key }) | ||
.reply(200, { category: '5ae9ece93a685f47efb9a97c', slug }); | ||
|
||
const putMock = nock(config.host, { | ||
reqheaders: { | ||
'x-readme-version': version, | ||
}, | ||
}) | ||
.put(`/api/v1/docs/${slug}`, { | ||
category: '5ae9ece93a685f47efb9a97c', | ||
slug, | ||
body: doc.content, | ||
...doc.data, | ||
}) | ||
.basicAuth({ user: key }) | ||
.reply(200); | ||
|
||
return docs(['./test/fixtures/existing-docs'], { key, version }).then(() => { | ||
getMock.done(); | ||
putMock.done(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('new docs', () => { | ||
it('should create new doc', () => { | ||
const slug = 'new-doc'; | ||
const doc = frontMatter( | ||
fs.readFileSync(path.join(__dirname, `./fixtures/new-docs/${slug}.md`)), | ||
); | ||
|
||
const getMock = nock(config.host, { | ||
reqheaders: { | ||
'x-readme-version': version, | ||
}, | ||
}) | ||
.get(`/api/v1/docs/${slug}`) | ||
.basicAuth({ user: key }) | ||
.reply(404, { | ||
description: 'No doc found with that slug', | ||
error: 'Not Found', | ||
}); | ||
|
||
const postMock = nock(config.host, { | ||
reqheaders: { | ||
'x-readme-version': version, | ||
}, | ||
}) | ||
.post(`/api/v1/docs`, { slug, body: doc.content, ...doc.data }) | ||
.basicAuth({ user: key }) | ||
.reply(201); | ||
|
||
return docs(['./test/fixtures/new-docs'], { key, version }).then(() => { | ||
getMock.done(); | ||
postMock.done(); | ||
}); | ||
}); | ||
}); | ||
}); |
Empty file.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
--- | ||
title: This is the document title | ||
--- | ||
Body |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
category: 5ae122e10fdf4e39bb34db6f | ||
title: This is the document title | ||
--- | ||
|
||
Body |