Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: fetch data from Github API + cache
- Loading branch information
1 parent
cc66d56
commit 14ac2e5
Showing
9 changed files
with
432 additions
and
86 deletions.
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 |
---|---|---|
|
@@ -2,3 +2,4 @@ | |
node_modules/ | ||
config.js | ||
dist/ | ||
cache/ |
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,60 @@ | ||
/* eslint-disable */ | ||
'use strict' | ||
|
||
module.exports = { | ||
|
||
/** | ||
* The value is the name of the folder, all templates | ||
* you can find by the current path: | ||
* ./src/templates | ||
* You can also create your own template, which is | ||
* described in this file: | ||
* README.md | ||
* @var {string} | ||
* @default default | ||
*/ | ||
template: 'default', | ||
|
||
/** | ||
* Set your login from github, after the build we will receive | ||
* data from this profile (name, projects, etc.) | ||
* @var {string} | ||
* @example | ||
* You can find the login from the address bar, for example: | ||
* https://github.com/alexeykhr | ||
* The value will be: | ||
* alexeykhr | ||
*/ | ||
username: 'nwtgck', | ||
|
||
/** | ||
* Various configurations are stored that will filter | ||
* the received data with the Github API. | ||
* @var {Object} | ||
*/ | ||
parseGithub: { | ||
|
||
/** | ||
* @see https://developer.github.com/v3/repos/#list-user-repositories docs | ||
*/ | ||
repositories: { | ||
/** | ||
* @var {string} - all, owner, member | ||
* @default owner | ||
*/ | ||
type: 'owner', | ||
|
||
/** | ||
* @var {string} - created, updated, pushed, full_name | ||
* @default full_name | ||
*/ | ||
sort: 'full_name', | ||
|
||
/** | ||
* @var {string} - asc, desc | ||
* @default asc when using full_name, otherwise desc | ||
*/ | ||
direction: 'asc' | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,64 @@ | ||
'use strict' | ||
|
||
const path = require('path') | ||
const fs = require('fs') | ||
|
||
/** @type {string} */ | ||
const BASE_PATH = path.resolve(__dirname, '../cache') + '/' | ||
|
||
/** | ||
* Create cache folder if not exists | ||
*/ | ||
if (!fs.existsSync(BASE_PATH)) { | ||
try { | ||
console.log('Create cache folder') | ||
fs.mkdirSync(BASE_PATH) | ||
} catch (e) { | ||
console.warn(e) | ||
} | ||
} | ||
|
||
module.exports = { | ||
|
||
/** | ||
* Get data from .json file if exists | ||
* @param {string} fileName - path in <root>/data folder (ext is required) | ||
* @return {{}} | ||
*/ | ||
tryReadJsonFile(fileName) { | ||
const path = BASE_PATH + fileName | ||
|
||
if (!fs.existsSync(path)) { | ||
return {} | ||
} | ||
|
||
const data = fs.readFileSync(path, { encoding: 'UTF-8' }) | ||
|
||
try { | ||
return JSON.parse(data) | ||
} catch (e) { | ||
console.warn(e) | ||
return {} | ||
} | ||
}, | ||
|
||
/** | ||
* Set data to .json file | ||
* @param {string} fileName - path in <root>/data folder (ext is required) | ||
* @param {object} data | ||
*/ | ||
writeJsonFile(fileName, data) { | ||
const path = BASE_PATH + fileName | ||
|
||
fs.writeFileSync(path, JSON.stringify(data)) | ||
}, | ||
|
||
/** | ||
* Check if .json file exists | ||
* @param {string} fileName - path in <root>/data folder (ext is required) | ||
* @return {boolean} | ||
*/ | ||
existsJsonFile(fileName) { | ||
return fs.existsSync(BASE_PATH + fileName) | ||
} | ||
} |
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,68 @@ | ||
'use strict' | ||
|
||
const jsonHelper = require('./jsonHelper') | ||
const variables = require('./variables') | ||
const config = require('../config') | ||
const axios = require('axios') | ||
|
||
/** | ||
* Waiting before the next request to the API. | ||
* 1 hour | ||
* @type {number} - milliseconds | ||
*/ | ||
const TIME_WAIT = 1000 * 60 * 60 | ||
|
||
/** | ||
* How to save in timestamp | ||
* @type {string} | ||
*/ | ||
const CACHE_NAME = 'profile' | ||
|
||
/** | ||
* @return {Promise<?object>} | ||
* null - failed | ||
* {} - success | ||
*/ | ||
module.exports = async () => { | ||
|
||
const timestamp = jsonHelper.tryReadJsonFile(variables.FILE_TIMESTAMP_JSON) | ||
const profileFileExists = jsonHelper.existsJsonFile(variables.FILE_PROFILE_JSON) | ||
const canRepeatRequestByTimestamp = (+timestamp[CACHE_NAME] || 0) + TIME_WAIT <= Date.now() | ||
|
||
/** @type {?object} - data from API */ | ||
let githubUser = null | ||
|
||
if (canRepeatRequestByTimestamp || !profileFileExists) { | ||
|
||
/** | ||
* Make a Github API request to get user data. | ||
* @see https://developer.github.com/v3/users/#get-a-single-user docs | ||
*/ | ||
try { | ||
console.log(`[Profile] Fetching data from api.. | ${config.username} username`) | ||
const fetchGithubData = await axios(`${variables.API_GITHUB}/users/${config.username}`) | ||
githubUser = fetchGithubData.data | ||
console.log(`[Profile] Complete, ${githubUser.name}`) | ||
} catch (e) { | ||
console.warn(`[Profile]: ${e}`) | ||
return null | ||
} | ||
|
||
/* | ||
* Update cache | ||
*/ | ||
jsonHelper.writeJsonFile(variables.FILE_PROFILE_JSON, githubUser) | ||
|
||
/* | ||
* Update timestamp | ||
*/ | ||
jsonHelper.writeJsonFile(variables.FILE_TIMESTAMP_JSON, | ||
Object.assign({}, timestamp, { [CACHE_NAME]: Date.now() }) | ||
) | ||
} else { | ||
githubUser = jsonHelper.tryReadJsonFile(variables.FILE_PROFILE_JSON) | ||
console.log(`[Profile] Get profile from cache, ${githubUser.name}`) | ||
} | ||
|
||
return githubUser | ||
} |
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,81 @@ | ||
'use strict' | ||
|
||
const jsonHelper = require('./jsonHelper') | ||
const variables = require('./variables') | ||
const config = require('../config') | ||
const axios = require('axios') | ||
|
||
/** | ||
* Waiting before the next request to the API. | ||
* 2 hours | ||
* @type {number} - milliseconds | ||
*/ | ||
const TIME_WAIT = 1000 * 60 * 60 * 2 | ||
|
||
/** | ||
* How to save in timestamp | ||
* @type {string} | ||
*/ | ||
const CACHE_NAME = 'repositories' | ||
|
||
/** | ||
* @return {Promise<?array>} | ||
* null - failed | ||
* [] - success | ||
*/ | ||
module.exports = async () => { | ||
|
||
const timestamp = jsonHelper.tryReadJsonFile(variables.FILE_TIMESTAMP_JSON) | ||
const repositoriesFileExists = jsonHelper.existsJsonFile(variables.FILE_REPOSITORIES_JSON) | ||
const canRepeatRequestByTimestamp = (+timestamp[CACHE_NAME] || 0) + TIME_WAIT <= Date.now() | ||
|
||
/** @type {array} - data from API */ | ||
let repositories = [] | ||
|
||
if (canRepeatRequestByTimestamp || !repositoriesFileExists) { | ||
|
||
/** | ||
* Make a Github API request to get user repositories. | ||
* @see https://developer.github.com/v3/repos/#list-user-repositories docs | ||
*/ | ||
try { | ||
let fetchRepositories | ||
let page = 1 | ||
|
||
do { | ||
console.log(`[Repositories] Fetching data from API.. | ${page} page`) | ||
fetchRepositories = await axios(`${variables.API_GITHUB}/users/${config.username}/repos`, { | ||
params: { | ||
...config.parseGithub.repositories, | ||
per_page: 100, | ||
page: page++ | ||
} | ||
}) | ||
repositories.push(...fetchRepositories.data) | ||
|
||
} while (fetchRepositories.data.length === 100) | ||
|
||
console.log(`[Repositories] Complete, ${repositories.length} length`) | ||
} catch (e) { | ||
console.warn(`[Repositories]: ${e}`) | ||
return null | ||
} | ||
|
||
/* | ||
* Update repositories cache | ||
*/ | ||
jsonHelper.writeJsonFile(variables.FILE_REPOSITORIES_JSON, repositories) | ||
|
||
/* | ||
* Update timestamp cache | ||
*/ | ||
jsonHelper.writeJsonFile(variables.FILE_TIMESTAMP_JSON, | ||
Object.assign({}, timestamp, { [CACHE_NAME]: Date.now() }) | ||
) | ||
} else { | ||
repositories = jsonHelper.tryReadJsonFile(variables.FILE_REPOSITORIES_JSON) | ||
console.log(`[Repositories] Get repositories from cache, ${repositories.length} length`) | ||
} | ||
|
||
return Array.isArray(repositories) ? repositories : null | ||
} |
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,17 @@ | ||
'use strict' | ||
|
||
module.exports = { | ||
|
||
/** | ||
* @var {string} | ||
*/ | ||
API_GITHUB: 'https://api.github.com', | ||
|
||
/** | ||
* Files in <root>/data folder | ||
* @var {string} | ||
*/ | ||
FILE_PROFILE_JSON: 'profile.json', | ||
FILE_TIMESTAMP_JSON: 'timestamp.json', | ||
FILE_REPOSITORIES_JSON: 'repositories.json' | ||
} |
Oops, something went wrong.