feat: paginates using async generator
This commit is contained in:
parent
f7a8341bb1
commit
51da6c20db
@ -1,3 +1,4 @@
|
|||||||
|
import fs from 'fs';
|
||||||
import ejs from 'ejs';
|
import ejs from 'ejs';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import remark from 'remark';
|
import remark from 'remark';
|
||||||
@ -8,9 +9,10 @@ import GithubApi from './api';
|
|||||||
import link from './link';
|
import link from './link';
|
||||||
import git from './git';
|
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;
|
const fsp = fs.promises;
|
||||||
|
|
||||||
@ -18,10 +20,6 @@ export function wait(time = 200): Promise<void> {
|
|||||||
return new Promise((resolve) => setTimeout(resolve, time));
|
return new Promise((resolve) => setTimeout(resolve, time));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isLastPage(links: PaginationLink): boolean {
|
|
||||||
return links.next === links.last;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function renderer(
|
export async function renderer(
|
||||||
data: { [key: string]: any },
|
data: { [key: string]: any },
|
||||||
templateString = MD_TEMPLATE
|
templateString = MD_TEMPLATE
|
||||||
@ -34,32 +32,43 @@ export async function renderer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function apiGetStar(url: string): Promise<ApiGetStarResponse> {
|
export function getNextPage(links: PaginationLink[]): string | null {
|
||||||
const { headers, body }: any = await GithubApi.get(url);
|
const link = links.find((l) => l.rel === 'next');
|
||||||
return {
|
if (!link) return null;
|
||||||
data: body,
|
const match = link.uri.match(/page=([0-9]*)/);
|
||||||
links: link.parse(headers.link).refs.reduce(
|
if (!match) return null;
|
||||||
(acc, val) => ({
|
return match[1];
|
||||||
...acc,
|
|
||||||
[val.rel]: val.uri,
|
|
||||||
}),
|
|
||||||
{}
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const REPO_USERNAME = process.env.GITHUB_REPOSITORY?.split('/')[0];
|
async function* paginateStars(url: string): AsyncGenerator<Stars> {
|
||||||
export const API_STARRED_URL = `${process.env.GITHUB_API_URL}/users/${REPO_USERNAME}/starred`;
|
let nextPage: string | null = '1';
|
||||||
|
while (nextPage) {
|
||||||
|
try {
|
||||||
|
const { headers, body } = await GithubApi.get(url, {
|
||||||
|
searchParams: {
|
||||||
|
page: nextPage,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log('body, typeof body :>> ', body, typeof body);
|
||||||
|
yield (body as unknown) as Stars;
|
||||||
|
nextPage = getNextPage(link.parse(headers.link).refs);
|
||||||
|
console.log('sleeping 1second to avoid rate-limit');
|
||||||
|
await wait(1000); // avoid limits
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let links: PaginationLink = {
|
export async function apiGetStar(
|
||||||
next: API_STARRED_URL,
|
url: string = API_STARRED_URL
|
||||||
last: undefined,
|
): Promise<ApiGetStarResponse> {
|
||||||
};
|
let data: Stars[] = [];
|
||||||
export async function paginate(): Promise<ApiGetStarResponse | null> {
|
for await (const stars of paginateStars(url)) {
|
||||||
if (isLastPage(links)) return null;
|
data = data.concat(stars);
|
||||||
const r = await apiGetStar(links.next);
|
}
|
||||||
links = r.links;
|
return (data as unknown) as Stars;
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateMd(data: string): Promise<string> {
|
export function generateMd(data: string): Promise<string> {
|
||||||
|
12
src/index.ts
12
src/index.ts
@ -1,26 +1,18 @@
|
|||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import { data } from 'remark';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
renderer,
|
renderer,
|
||||||
paginate,
|
|
||||||
REPO_USERNAME,
|
REPO_USERNAME,
|
||||||
generateMd,
|
generateMd,
|
||||||
pushNewFiles,
|
pushNewFiles,
|
||||||
MARKDOWN_FILENAME,
|
MARKDOWN_FILENAME,
|
||||||
|
apiGetStar,
|
||||||
} from './helpers';
|
} from './helpers';
|
||||||
|
|
||||||
import type { SortedLanguageList, Stars, Star } from './types';
|
import type { SortedLanguageList, Stars, Star } from './types';
|
||||||
|
|
||||||
export async function main(): Promise<any> {
|
export async function main(): Promise<any> {
|
||||||
let results: Stars = [];
|
const results: Stars = await apiGetStar();
|
||||||
|
|
||||||
while (true) {
|
|
||||||
// sorry.
|
|
||||||
const r = await paginate();
|
|
||||||
if (!r || r === null) break;
|
|
||||||
results = results.concat(r.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const sortedByLanguages = results.reduce(
|
const sortedByLanguages = results.reduce(
|
||||||
(acc: SortedLanguageList, val: Star) => {
|
(acc: SortedLanguageList, val: Star) => {
|
||||||
|
@ -5,14 +5,11 @@ export type SortedLanguageList = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type PaginationLink = {
|
export type PaginationLink = {
|
||||||
next: string;
|
uri: string;
|
||||||
last: string | undefined | null;
|
rel: 'next' | 'last' | 'prev' | 'first';
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Stars = Endpoints['GET /user/starred']['response']['data'];
|
export type Stars = Endpoints['GET /user/starred']['response']['data'];
|
||||||
export type Star = Stars[number] | { language: string };
|
export type Star = Stars[number] | { language: string };
|
||||||
|
|
||||||
export type ApiGetStarResponse = {
|
export type ApiGetStarResponse = Stars;
|
||||||
links: PaginationLink;
|
|
||||||
data: Stars;
|
|
||||||
};
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user