Skip to content

Commit fc225b1

Browse files
committed
feat: first working version
1 parent 3f8b447 commit fc225b1

File tree

11 files changed

+265
-48
lines changed

11 files changed

+265
-48
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ node_modules
22
docs
33
dist
44
coverage
5+
bin
6+
.rpt2_cache

package.json

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
"version": "0.0.0",
44
"description": "",
55
"keywords": [],
6-
"main": "dist/dev-to-git.umd.js",
7-
"module": "dist/dev-to-git.es5.js",
8-
"typings": "dist/types/dev-to-git.d.ts",
6+
"main": "bin/dev-to-git.umd.js",
7+
"module": "bin/dev-to-git.es5.js",
8+
"typings": "bin/types/dev-to-git.d.ts",
99
"files": [
10-
"dist"
10+
"bin"
1111
],
12+
"bin": {
13+
"dev-to-git": "bin/index.js"
14+
},
1215
"author": "Maxime Robert <maxime.robert1992@gmail.com>",
1316
"repository": {
1417
"type": "git",
@@ -19,11 +22,12 @@
1922
"node": ">=6.0.0"
2023
},
2124
"scripts": {
25+
"copy-index": "cp ./src/index.js ./bin",
2226
"prettier:base": "yarn run prettier \"./{src,test}/**/*.ts\" \"./**/*.{yml,md,json}\"",
2327
"prettier:fix": "yarn run prettier:base --write",
2428
"lint": "tslint --project tsconfig.json -t codeFrame 'src/**/*.ts' 'test/**/*.ts'",
25-
"prebuild": "rimraf dist",
26-
"build": "tsc --module commonjs && rollup -c rollup.config.ts && typedoc --out docs --target es6 --theme minimal --mode file src",
29+
"prebuild": "rimraf bin",
30+
"build": "tsc --module commonjs && rollup -c rollup.config.ts && typedoc --out docs --target es6 --theme minimal --mode file src && yarn run copy-index",
2731
"start": "rollup -c rollup.config.ts -w",
2832
"test": "jest --coverage",
2933
"test:watch": "jest --coverage --watch",
@@ -86,7 +90,10 @@
8690
"devDependencies": {
8791
"@commitlint/cli": "^7.1.2",
8892
"@commitlint/config-conventional": "^7.1.2",
93+
"@types/dotenv": "6.1.1",
94+
"@types/got": "9.6.0",
8995
"@types/jest": "^23.3.2",
96+
"@types/minimist": "1.2.0",
9097
"@types/node": "^10.11.0",
9198
"colors": "^1.3.2",
9299
"commitizen": "^3.0.0",
@@ -118,5 +125,10 @@
118125
"tslint-config-standard": "^8.0.1",
119126
"typedoc": "^0.12.0",
120127
"typescript": "^3.0.3"
128+
},
129+
"dependencies": {
130+
"dotenv": "8.0.0",
131+
"got": "9.6.0",
132+
"minimist": "1.2.0"
121133
}
122134
}

src/article.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { ArticleConfig, ArticleApi } from './dev-to-git.interface'
2+
import got from 'got'
3+
import fs from 'fs'
4+
5+
export class Article {
6+
constructor(private articleConfig: ArticleConfig, private token: string) {}
7+
8+
public readArticleOnDisk(): string {
9+
return fs.readFileSync(this.articleConfig.relativePathToArticle).toString()
10+
}
11+
12+
public publishArticle(): got.GotPromise<any> {
13+
const body: ArticleApi = {
14+
title: this.articleConfig.title,
15+
description: this.articleConfig.description,
16+
body_markdown: this.readArticleOnDisk(),
17+
published: this.articleConfig.published,
18+
tags: this.articleConfig.tags,
19+
series: this.articleConfig.series,
20+
publish_under_org: this.articleConfig.publishUnderOrg,
21+
main_image: this.articleConfig.urlToMainImage,
22+
canonical_url: this.articleConfig.canonicalUrl
23+
}
24+
25+
return got(`https://dev.to/api/articles/${this.articleConfig.id}`, {
26+
json: true,
27+
method: 'PUT',
28+
headers: { 'api-key': this.token },
29+
body
30+
})
31+
}
32+
}

src/dev-to-git.interface.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
export interface ArticleConfig {
2+
title: string
3+
description: string
4+
id: string
5+
published: string
6+
urlToMainImage: string
7+
tags: string[]
8+
relativePathToArticle: string
9+
series: string
10+
publishUnderOrg: boolean
11+
canonicalUrl: string
12+
}
13+
14+
// https://dev.to/api#available-json-parameters
15+
export interface ArticleApi {
16+
title: string
17+
description: string
18+
body_markdown: string
19+
published: string
20+
tags: string[]
21+
series: string
22+
publish_under_org: boolean
23+
main_image?: string
24+
canonical_url?: string
25+
}

src/dev-to-git.ts

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,52 @@
1-
// Import here Polyfills if needed. Recommended core-js (npm i -D core-js)
2-
// import "core-js/fn/array.find"
3-
// ...
4-
export default class DummyClass {
1+
import minimist from 'minimist'
2+
import fs from 'fs'
3+
import dotenv from 'dotenv'
4+
import { ArticleConfig, ArticleApi } from './dev-to-git.interface'
5+
import { Article } from './article'
56

7+
export const DEFAULT_CONFIG_PATH: string = './dev-to-git.json'
8+
9+
export class DevToGit {
10+
private configPath: string = DEFAULT_CONFIG_PATH
11+
private token: string = ''
12+
13+
constructor() {
14+
dotenv.config()
15+
16+
const { config } = minimist(process.argv.slice(2))
17+
18+
if (config && typeof config === 'string') {
19+
this.configPath = config
20+
}
21+
22+
if (!process.env.DEV_TO_GIT_TOKEN) {
23+
throw new Error('Token is required')
24+
}
25+
26+
this.token = process.env.DEV_TO_GIT_TOKEN
27+
}
28+
29+
public getConfigPath(): string {
30+
return this.configPath
31+
}
32+
33+
public readConfigFile(): ArticleConfig[] {
34+
// @todo check structure of the object
35+
36+
return JSON.parse(
37+
fs.readFileSync(this.getConfigPath()).toString()
38+
) as ArticleConfig[]
39+
}
40+
41+
public publishArticles() {
42+
const articles = this.readConfigFile()
43+
articles.forEach(articleConf => {
44+
const article = new Article(articleConf, this.token)
45+
article.publishArticle()
46+
})
47+
}
648
}
49+
50+
// @todo move to main file?
51+
const devToGit = new DevToGit()
52+
devToGit.publishArticles()

src/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env node
2+
3+
require('./dev-to-git.umd.js');

test/article.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# This is my awesome article!
2+
3+
Hey, some text!

test/dev-to-git.json

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
[
22
{
3-
"title": "",
4-
"description": "",
5-
"published": "",
6-
"urlToMainImage": "",
7-
"tags": [],
8-
"relativePathToArticle": "",
9-
"series": "",
10-
"publishUnderOrg": "",
11-
"canonicalUrl": ""
3+
"id": 132750,
4+
"title": "Updated title",
5+
"description": "Great description",
6+
"published": "false",
7+
"urlToMainImage": null,
8+
"tags": ["typescript"],
9+
"relativePathToArticle": "./test/article.md",
10+
"series": null,
11+
"publishUnderOrg": false,
12+
"canonicalUrl": null
1213
}
1314
]

test/dev-to-git.test.ts

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,82 @@
1-
import DummyClass from "../src/dev-to-git"
2-
3-
/**
4-
* Dummy test
5-
*/
6-
describe("Dummy test", () => {
7-
it("works if true is truthy", () => {
8-
expect(true).toBeTruthy()
1+
import { DevToGit, DEFAULT_CONFIG_PATH } from '../src/dev-to-git'
2+
3+
describe(`DevToGit`, () => {
4+
beforeEach(() => {
5+
process.argv = ['don-t-care', 'don-t-care']
6+
process.env.DEV_TO_GIT_TOKEN = 'token'
97
})
108

11-
it("DummyClass is instantiable", () => {
12-
expect(new DummyClass()).toBeInstanceOf(DummyClass)
9+
describe(`Config`, () => {
10+
describe(`Get config`, () => {
11+
it(`should have by default a path "./dev-to-git.json"`, () => {
12+
const devToGit = new DevToGit()
13+
expect(devToGit.getConfigPath()).toBe(DEFAULT_CONFIG_PATH)
14+
})
15+
16+
it(`should accept a "config" argument to change the path to the config`, () => {
17+
const CUSTOM_CONFIG_PATH: string = './custom/dev-to-git.json'
18+
process.argv = [
19+
'don-t-care',
20+
'don-t-care',
21+
'--config',
22+
CUSTOM_CONFIG_PATH
23+
]
24+
const devToGit = new DevToGit()
25+
expect(devToGit.getConfigPath()).toBe(CUSTOM_CONFIG_PATH)
26+
})
27+
28+
it(`should use the default path if the "config" flag is passed without nothing`, () => {
29+
process.argv = ['don-t-care', 'don-t-care', '--config']
30+
const devToGit = new DevToGit()
31+
expect(devToGit.getConfigPath()).toBe(DEFAULT_CONFIG_PATH)
32+
})
33+
})
34+
35+
describe(`Read config from file`, () => {
36+
it(`test`, () => {
37+
process.argv = [
38+
'don-t-care',
39+
'don-t-care',
40+
'--config',
41+
'./test/dev-to-git.json'
42+
]
43+
44+
const devToGit = new DevToGit()
45+
46+
expect(devToGit.readConfigFile()).toEqual(require('./dev-to-git.json'))
47+
})
48+
})
1349
})
50+
51+
// describe(`Article`, () => {
52+
// describe(`Read`, () => {
53+
// it(`should read an article from the configuration`, () => {
54+
// const CUSTOM_CONFIG_PATH: string = './test/dev-to-git.json'
55+
// process.argv = [
56+
// 'don-t-care',
57+
// 'don-t-care',
58+
// '--config',
59+
// CUSTOM_CONFIG_PATH
60+
// ]
61+
// const devToGit = new DevToGit()
62+
// expect(devToGit.readArticleOnDisk()).toContain(
63+
// 'This is my awesome article!'
64+
// )
65+
// expect(devToGit.readArticleOnDisk()).toContain('Hey, some text!')
66+
// })
67+
// })
68+
// describe(`Publish`, () => {
69+
// it(`should publish the article`, () => {
70+
// const CUSTOM_CONFIG_PATH: string = './test/dev-to-git.json'
71+
// process.argv = [
72+
// 'don-t-care',
73+
// 'don-t-care',
74+
// '--config',
75+
// CUSTOM_CONFIG_PATH
76+
// ]
77+
// const devToGit = new DevToGit()
78+
// devToGit.publishArticle(devToGit.readConfigFile()[0])
79+
// })
80+
// })
81+
// })
1482
})

tsconfig.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
"allowSyntheticDefaultImports": true,
1111
"experimentalDecorators": true,
1212
"emitDecoratorMetadata": true,
13-
"declarationDir": "dist/types",
14-
"outDir": "dist/lib",
13+
"declarationDir": "bin/types",
14+
"outDir": "bin/lib",
1515
"typeRoots": ["node_modules/@types"]
1616
},
1717
"include": ["src"]

0 commit comments

Comments
 (0)