Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
884fc90171 | ||
|
b97833f7c5 | ||
|
1d6848cd17 | ||
|
0e016f41d3 | ||
|
8f9b4ccf8d | ||
|
51da6c20db | ||
|
f7a8341bb1 | ||
|
c361d6e2b6 | ||
|
ef137b518e |
43
CHANGELOG.md
43
CHANGELOG.md
@@ -1,5 +1,28 @@
|
||||
## <small>1.0.41 (2021-10-14)</small>
|
||||
|
||||
* test: fixs suite ([b97833f](https://github.com/simonecorsi/mawesome/commit/b97833f))
|
||||
* fix: should avoid index lock ([1d6848c](https://github.com/simonecorsi/mawesome/commit/1d6848c))
|
||||
|
||||
|
||||
|
||||
## <small>1.0.40 (2021-10-13)</small>
|
||||
|
||||
* chore(release): v1.0.40 ([0e016f4](https://github.com/simonecorsi/mawesome/commit/0e016f4))
|
||||
* fix: fixes while exit condition ([8f9b4cc](https://github.com/simonecorsi/mawesome/commit/8f9b4cc))
|
||||
* feat: paginates using async generator ([51da6c2](https://github.com/simonecorsi/mawesome/commit/51da6c2))
|
||||
|
||||
|
||||
|
||||
## <small>1.0.39 (2021-08-31)</small>
|
||||
|
||||
* chore(release): v1.0.39 ([f7a8341](https://github.com/simonecorsi/mawesome/commit/f7a8341))
|
||||
* build(deps): bump path-parse from 1.0.6 to 1.0.7 ([ef137b5](https://github.com/simonecorsi/mawesome/commit/ef137b5))
|
||||
|
||||
|
||||
|
||||
## <small>1.0.38 (2021-06-23)</small>
|
||||
|
||||
* chore(release): v1.0.38 ([3e66d85](https://github.com/simonecorsi/mawesome/commit/3e66d85))
|
||||
|
||||
|
||||
|
||||
@@ -12,23 +35,3 @@
|
||||
|
||||
|
||||
|
||||
## <small>1.0.36 (2021-06-23)</small>
|
||||
|
||||
* chore(release): v1.0.36 ([9c0b622](https://github.com/simonecorsi/mawesome/commit/9c0b622))
|
||||
* feat: saving json data for future use ([7ceb9cb](https://github.com/simonecorsi/mawesome/commit/7ceb9cb))
|
||||
|
||||
|
||||
|
||||
## <small>1.0.35 (2021-06-22)</small>
|
||||
|
||||
* chore(release): v1.0.35 ([cee1906](https://github.com/simonecorsi/mawesome/commit/cee1906))
|
||||
* build(deps): bump set-getter from 0.1.0 to 0.1.1 ([970d603](https://github.com/simonecorsi/mawesome/commit/970d603))
|
||||
|
||||
|
||||
|
||||
## <small>1.0.34 (2021-05-19)</small>
|
||||
|
||||
* chore(release): v1.0.34 ([ab02c0d](https://github.com/simonecorsi/mawesome/commit/ab02c0d))
|
||||
|
||||
|
||||
|
||||
|
114
index.js
114
index.js
@@ -21356,12 +21356,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
||||
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
||||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
||||
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
||||
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
|
||||
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
|
||||
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
||||
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
||||
function fulfill(value) { resume("next", value); }
|
||||
function reject(value) { resume("throw", value); }
|
||||
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
||||
};
|
||||
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
||||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
||||
var m = o[Symbol.asyncIterator], i;
|
||||
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
||||
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
||||
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
var _a;
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.pushNewFiles = exports.MARKDOWN_FILENAME = exports.generateMd = exports.paginate = exports.API_STARRED_URL = exports.REPO_USERNAME = exports.apiGetStar = exports.renderer = exports.isLastPage = exports.wait = void 0;
|
||||
exports.pushNewFiles = exports.MARKDOWN_FILENAME = exports.generateMd = exports.apiGetStar = exports.getNextPage = exports.renderer = exports.wait = exports.API_STARRED_URL = exports.REPO_USERNAME = void 0;
|
||||
const fs_1 = __importDefault(__nccwpck_require__(5747));
|
||||
const ejs_1 = __importDefault(__nccwpck_require__(8431));
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const remark_1 = __importDefault(__nccwpck_require__(2081));
|
||||
@@ -21370,16 +21390,13 @@ const template_1 = __importDefault(__nccwpck_require__(3932));
|
||||
const api_1 = __importDefault(__nccwpck_require__(8229));
|
||||
const link_1 = __importDefault(__nccwpck_require__(9338));
|
||||
const git_1 = __importDefault(__nccwpck_require__(6350));
|
||||
const fs_1 = __importDefault(__nccwpck_require__(5747));
|
||||
exports.REPO_USERNAME = (_a = process.env.GITHUB_REPOSITORY) === null || _a === void 0 ? void 0 : _a.split('/')[0];
|
||||
exports.API_STARRED_URL = `${process.env.GITHUB_API_URL}/users/${exports.REPO_USERNAME}/starred`;
|
||||
const fsp = fs_1.default.promises;
|
||||
function wait(time = 200) {
|
||||
return new Promise((resolve) => setTimeout(resolve, time));
|
||||
}
|
||||
exports.wait = wait;
|
||||
function isLastPage(links) {
|
||||
return links.next === links.last;
|
||||
}
|
||||
exports.isLastPage = isLastPage;
|
||||
function renderer(data, templateString = template_1.default) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
@@ -21392,32 +21409,62 @@ function renderer(data, templateString = template_1.default) {
|
||||
});
|
||||
}
|
||||
exports.renderer = renderer;
|
||||
function apiGetStar(url) {
|
||||
function getNextPage(links) {
|
||||
const next = links.find((l) => l.rel === 'next');
|
||||
const last = links.find((l) => l.rel === 'last');
|
||||
if (!next || !last)
|
||||
return null;
|
||||
const matchNext = next.uri.match(/page=([0-9]*)/);
|
||||
const matchLast = next.uri.match(/page=([0-9]*)/);
|
||||
if (!matchNext || !matchLast)
|
||||
return null;
|
||||
if (matchNext[1] === matchLast[1])
|
||||
return null;
|
||||
return matchNext[1];
|
||||
}
|
||||
exports.getNextPage = getNextPage;
|
||||
function paginateStars(url) {
|
||||
return __asyncGenerator(this, arguments, function* paginateStars_1() {
|
||||
let nextPage = '1';
|
||||
while (nextPage) {
|
||||
try {
|
||||
const { headers, body } = yield __await(api_1.default.get(url, {
|
||||
searchParams: {
|
||||
page: nextPage,
|
||||
},
|
||||
}));
|
||||
yield yield __await(body);
|
||||
nextPage = getNextPage(link_1.default.parse(headers.link).refs);
|
||||
yield __await(wait(1000)); // avoid limits
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function apiGetStar(url = exports.API_STARRED_URL) {
|
||||
var e_1, _a;
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const { headers, body } = yield api_1.default.get(url);
|
||||
return {
|
||||
data: body,
|
||||
links: link_1.default.parse(headers.link).refs.reduce((acc, val) => (Object.assign(Object.assign({}, acc), { [val.rel]: val.uri })), {}),
|
||||
};
|
||||
let data = [];
|
||||
try {
|
||||
for (var _b = __asyncValues(paginateStars(url)), _c; _c = yield _b.next(), !_c.done;) {
|
||||
const stars = _c.value;
|
||||
data = data.concat(stars);
|
||||
}
|
||||
}
|
||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
|
||||
}
|
||||
finally { if (e_1) throw e_1.error; }
|
||||
}
|
||||
return data;
|
||||
});
|
||||
}
|
||||
exports.apiGetStar = apiGetStar;
|
||||
exports.REPO_USERNAME = (_a = process.env.GITHUB_REPOSITORY) === null || _a === void 0 ? void 0 : _a.split('/')[0];
|
||||
exports.API_STARRED_URL = `${process.env.GITHUB_API_URL}/users/${exports.REPO_USERNAME}/starred`;
|
||||
let links = {
|
||||
next: exports.API_STARRED_URL,
|
||||
last: undefined,
|
||||
};
|
||||
function paginate() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (isLastPage(links))
|
||||
return null;
|
||||
const r = yield apiGetStar(links.next);
|
||||
links = r.links;
|
||||
return r;
|
||||
});
|
||||
}
|
||||
exports.paginate = paginate;
|
||||
function generateMd(data) {
|
||||
return new Promise((resolve) => {
|
||||
remark_1.default()
|
||||
@@ -21442,8 +21489,8 @@ function pushNewFiles(files = []) {
|
||||
yield Promise.all(files.map(({ filename, data }) => __awaiter(this, void 0, void 0, function* () {
|
||||
yield fsp.writeFile(filename, data);
|
||||
yield git_1.default.add(filename);
|
||||
yield git_1.default.commit(`chore(${filename}): updated ${filename}`);
|
||||
})));
|
||||
yield git_1.default.commit(`chore(updates): updated entries in files`);
|
||||
yield git_1.default.push();
|
||||
});
|
||||
}
|
||||
@@ -21491,14 +21538,7 @@ const core = __importStar(__nccwpck_require__(2186));
|
||||
const helpers_1 = __nccwpck_require__(3015);
|
||||
function main() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let results = [];
|
||||
while (true) {
|
||||
// sorry.
|
||||
const r = yield helpers_1.paginate();
|
||||
if (!r || r === null)
|
||||
break;
|
||||
results = results.concat(r.data);
|
||||
}
|
||||
const results = yield helpers_1.apiGetStar();
|
||||
const sortedByLanguages = results.reduce((acc, val) => {
|
||||
const language = val.language || 'generic';
|
||||
if (!acc[language]) {
|
||||
|
8
package-lock.json
generated
8
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mawesome",
|
||||
"version": "1.0.36",
|
||||
"version": "1.0.38",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -6668,9 +6668,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true
|
||||
},
|
||||
"path-to-regexp": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mawesome",
|
||||
"version": "1.0.38",
|
||||
"version": "1.0.41",
|
||||
"description": "Generate awesome list from user starred repositories",
|
||||
"main": "index.js",
|
||||
"author": "Simone Corsi<simonecorsi.dev@gmail.com>",
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import fs from 'fs';
|
||||
import ejs from 'ejs';
|
||||
import * as core from '@actions/core';
|
||||
import remark from 'remark';
|
||||
@@ -8,9 +9,10 @@ import GithubApi from './api';
|
||||
import link from './link';
|
||||
import git from './git';
|
||||
|
||||
import type { PaginationLink, ApiGetStarResponse } from './types';
|
||||
import type { PaginationLink, ApiGetStarResponse, Stars } from './types';
|
||||
|
||||
import fs from 'fs';
|
||||
export const REPO_USERNAME = process.env.GITHUB_REPOSITORY?.split('/')[0];
|
||||
export const API_STARRED_URL = `${process.env.GITHUB_API_URL}/users/${REPO_USERNAME}/starred`;
|
||||
|
||||
const fsp = fs.promises;
|
||||
|
||||
@@ -18,10 +20,6 @@ export function wait(time = 200): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, time));
|
||||
}
|
||||
|
||||
export function isLastPage(links: PaginationLink): boolean {
|
||||
return links.next === links.last;
|
||||
}
|
||||
|
||||
export async function renderer(
|
||||
data: { [key: string]: any },
|
||||
templateString = MD_TEMPLATE
|
||||
@@ -34,32 +32,45 @@ export async function renderer(
|
||||
}
|
||||
}
|
||||
|
||||
export async function apiGetStar(url: string): Promise<ApiGetStarResponse> {
|
||||
const { headers, body }: any = await GithubApi.get(url);
|
||||
return {
|
||||
data: body,
|
||||
links: link.parse(headers.link).refs.reduce(
|
||||
(acc, val) => ({
|
||||
...acc,
|
||||
[val.rel]: val.uri,
|
||||
}),
|
||||
{}
|
||||
),
|
||||
};
|
||||
export function getNextPage(links: PaginationLink[]): string | null {
|
||||
const next = links.find((l) => l.rel === 'next');
|
||||
const last = links.find((l) => l.rel === 'last');
|
||||
if (!next || !last) return null;
|
||||
const matchNext = next.uri.match(/page=([0-9]*)/);
|
||||
const matchLast = next.uri.match(/page=([0-9]*)/);
|
||||
|
||||
if (!matchNext || !matchLast) return null;
|
||||
if (matchNext[1] === matchLast[1]) return null;
|
||||
return matchNext[1];
|
||||
}
|
||||
|
||||
export const REPO_USERNAME = process.env.GITHUB_REPOSITORY?.split('/')[0];
|
||||
export const API_STARRED_URL = `${process.env.GITHUB_API_URL}/users/${REPO_USERNAME}/starred`;
|
||||
async function* paginateStars(url: string): AsyncGenerator<Stars> {
|
||||
let nextPage: string | null = '1';
|
||||
while (nextPage) {
|
||||
try {
|
||||
const { headers, body } = await GithubApi.get(url, {
|
||||
searchParams: {
|
||||
page: nextPage,
|
||||
},
|
||||
});
|
||||
yield (body as unknown) as Stars;
|
||||
nextPage = getNextPage(link.parse(headers.link).refs);
|
||||
await wait(1000); // avoid limits
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let links: PaginationLink = {
|
||||
next: API_STARRED_URL,
|
||||
last: undefined,
|
||||
};
|
||||
export async function paginate(): Promise<ApiGetStarResponse | null> {
|
||||
if (isLastPage(links)) return null;
|
||||
const r = await apiGetStar(links.next);
|
||||
links = r.links;
|
||||
return r;
|
||||
export async function apiGetStar(
|
||||
url: string = API_STARRED_URL
|
||||
): Promise<ApiGetStarResponse> {
|
||||
let data: Stars[] = [];
|
||||
for await (const stars of paginateStars(url)) {
|
||||
data = data.concat(stars);
|
||||
}
|
||||
return (data as unknown) as Stars;
|
||||
}
|
||||
|
||||
export function generateMd(data: string): Promise<string> {
|
||||
@@ -94,9 +105,9 @@ export async function pushNewFiles(files: File[] = []): Promise<any> {
|
||||
files.map(async ({ filename, data }) => {
|
||||
await fsp.writeFile(filename, data);
|
||||
await git.add(filename);
|
||||
await git.commit(`chore(${filename}): updated ${filename}`);
|
||||
})
|
||||
);
|
||||
|
||||
await git.commit(`chore(updates): updated entries in files`);
|
||||
await git.push();
|
||||
}
|
||||
|
12
src/index.ts
12
src/index.ts
@@ -1,26 +1,18 @@
|
||||
import * as core from '@actions/core';
|
||||
import { data } from 'remark';
|
||||
|
||||
import {
|
||||
renderer,
|
||||
paginate,
|
||||
REPO_USERNAME,
|
||||
generateMd,
|
||||
pushNewFiles,
|
||||
MARKDOWN_FILENAME,
|
||||
apiGetStar,
|
||||
} from './helpers';
|
||||
|
||||
import type { SortedLanguageList, Stars, Star } from './types';
|
||||
|
||||
export async function main(): Promise<any> {
|
||||
let results: Stars = [];
|
||||
|
||||
while (true) {
|
||||
// sorry.
|
||||
const r = await paginate();
|
||||
if (!r || r === null) break;
|
||||
results = results.concat(r.data);
|
||||
}
|
||||
const results: Stars = await apiGetStar();
|
||||
|
||||
const sortedByLanguages = results.reduce(
|
||||
(acc: SortedLanguageList, val: Star) => {
|
||||
|
@@ -5,14 +5,11 @@ export type SortedLanguageList = {
|
||||
};
|
||||
|
||||
export type PaginationLink = {
|
||||
next: string;
|
||||
last: string | undefined | null;
|
||||
uri: string;
|
||||
rel: 'next' | 'last' | 'prev' | 'first';
|
||||
};
|
||||
|
||||
export type Stars = Endpoints['GET /user/starred']['response']['data'];
|
||||
export type Star = Stars[number] | { language: string };
|
||||
|
||||
export type ApiGetStarResponse = {
|
||||
links: PaginationLink;
|
||||
data: Stars;
|
||||
};
|
||||
export type ApiGetStarResponse = Stars;
|
||||
|
@@ -7,7 +7,7 @@ sinon.replace(core, 'getInput', sinon.fake());
|
||||
|
||||
import GithubApi from '../src/api';
|
||||
const GithubApiFake = sinon.fake((rul) => ({
|
||||
body: 'data',
|
||||
body: [],
|
||||
headers: {
|
||||
link:
|
||||
'<https://api.github.com/user/5617452/starred?page=2>; rel="next", <https://api.github.com/user/5617452/starred?page=2>; rel="last"',
|
||||
@@ -32,11 +32,9 @@ const writeFile = sinon.fake();
|
||||
sinon.replace(fsp, 'writeFile', writeFile);
|
||||
|
||||
import {
|
||||
isLastPage,
|
||||
wait,
|
||||
renderer,
|
||||
apiGetStar,
|
||||
paginate,
|
||||
generateMd,
|
||||
pushNewFiles,
|
||||
} from '../src/helpers';
|
||||
@@ -46,40 +44,15 @@ test('wait should wait', async (t) => {
|
||||
t.pass();
|
||||
});
|
||||
|
||||
test('isLastPage', (t) => {
|
||||
t.true(
|
||||
isLastPage({
|
||||
next: 'last',
|
||||
last: 'last',
|
||||
})
|
||||
);
|
||||
t.false(
|
||||
isLastPage({
|
||||
next: 'last',
|
||||
last: undefined,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test('renderer should render', async (t) => {
|
||||
const output = await renderer({ variable: 123 }, 'Test: <%= variable %>');
|
||||
t.is(output, 'Test: 123');
|
||||
});
|
||||
|
||||
test('apiGetStar', async (t) => {
|
||||
let { data, links } = await apiGetStar('url');
|
||||
let stars = await apiGetStar('url');
|
||||
t.true(GithubApiFake.called);
|
||||
t.is(data, 'data');
|
||||
t.deepEqual(links, {
|
||||
last: 'https://api.github.com/user/5617452/starred?page=2',
|
||||
next: 'https://api.github.com/user/5617452/starred?page=2',
|
||||
});
|
||||
});
|
||||
|
||||
test('paginate', async (t) => {
|
||||
await paginate();
|
||||
const res = await paginate();
|
||||
t.is(res, null);
|
||||
t.true(Array.isArray(stars));
|
||||
});
|
||||
|
||||
test('generateMd should create TOC', async (t) => {
|
||||
@@ -97,10 +70,10 @@ test('generateMd should create TOC', async (t) => {
|
||||
});
|
||||
|
||||
test('should push', async (t) => {
|
||||
await pushNewFiles([{filename: "README.md", data: '# title'}]);
|
||||
t.true(writeFile.calledWith('README.md', '# title'));
|
||||
await pushNewFiles([{ filename: 'README.md', data: '# title' }]);
|
||||
t.true(writeFile.called);
|
||||
t.true(pull.called);
|
||||
t.true(add.calledWith('README.md'));
|
||||
t.true(commit.calledWith('chore(README.md): updated README.md'));
|
||||
t.true(add.called);
|
||||
t.true(commit.called);
|
||||
t.true(push.called);
|
||||
});
|
||||
|
Reference in New Issue
Block a user