diff --git a/.eslintignore b/.eslintignore index 2dcff35f7..62b4cdd85 100644 --- a/.eslintignore +++ b/.eslintignore @@ -863,6 +863,7 @@ packages/tools/update-readme-download.js packages/tools/update-readme-sponsors.js packages/tools/updateMarkdownDoc.js packages/tools/utils/discourse.js +packages/tools/utils/loadSponsors.js packages/tools/utils/translation.js packages/tools/website/build.js packages/tools/website/buildTranslations.js diff --git a/.gitignore b/.gitignore index f072aae6d..07ac8254d 100644 --- a/.gitignore +++ b/.gitignore @@ -850,6 +850,7 @@ packages/tools/update-readme-download.js packages/tools/update-readme-sponsors.js packages/tools/updateMarkdownDoc.js packages/tools/utils/discourse.js +packages/tools/utils/loadSponsors.js packages/tools/utils/translation.js packages/tools/website/build.js packages/tools/website/buildTranslations.js diff --git a/packages/tools/update-readme-sponsors.ts b/packages/tools/update-readme-sponsors.ts index b77e82841..b7f8e449e 100644 --- a/packages/tools/update-readme-sponsors.ts +++ b/packages/tools/update-readme-sponsors.ts @@ -1,43 +1,9 @@ -import { readFile } from 'fs-extra'; import { insertContentIntoFile, rootDir } from './tool-utils'; import markdownUtils, { MarkdownTableHeader, MarkdownTableJustify, MarkdownTableRow } from '@joplin/lib/markdownUtils'; -import { GithubSponsor, GithubUser, OrgSponsor, Sponsors } from './website/utils/types'; -import fetch from 'node-fetch'; +import { GithubSponsor, loadSponsors, OrgSponsor } from './utils/loadSponsors'; const { escapeHtml } = require('@joplin/lib/string-utils'); const readmePath = `${rootDir}/README.md`; -const sponsorsPath = `${rootDir}/packages/tools/sponsors.json`; - -const sleep = (ms: number) => { - return new Promise(resolve => setTimeout(resolve, ms)); -}; - -const fetchWithRetry = async (url: string, opts: any = null) => { - if (!opts) opts = {}; - let retry = opts && opts.retry || 3; - - while (retry > 0) { - try { - return fetch(url, opts); - } catch (e) { - if (opts && opts.callback) { - opts.callback(retry); - } - retry = retry - 1; - if (retry === 0) { - throw e; - } - - if (opts && opts.pause) { - if (opts && !opts.silent) console.log('pausing..'); - await sleep(opts.pause); - if (opts && !opts.silent) console.log('done pausing...'); - } - } - } - - return null; -}; async function createGitHubSponsorTable(sponsors: GithubSponsor[]): Promise { sponsors = sponsors.slice(); @@ -70,9 +36,7 @@ async function createGitHubSponsorTable(sponsors: GithubSponsor[]): Promise
[${sponsor.name}](https://github.com/${sponsor.name})`; + row[`col${colIndex}`] = `
[${sponsor.name}](https://github.com/${sponsor.name})`; } if (Object.keys(row)) rows.push(row); @@ -94,7 +58,7 @@ async function createOrgSponsorTable(sponsors: OrgSponsor[]): Promise { } async function main() { - const sponsors: Sponsors = JSON.parse(await readFile(sponsorsPath, 'utf8')); + const sponsors = await loadSponsors(); await insertContentIntoFile( readmePath, diff --git a/packages/tools/utils/loadSponsors.ts b/packages/tools/utils/loadSponsors.ts new file mode 100644 index 000000000..43c8f130e --- /dev/null +++ b/packages/tools/utils/loadSponsors.ts @@ -0,0 +1,39 @@ +import { readFile } from 'fs-extra'; +import { rootDir } from '@joplin/utils'; +import { fetchWithRetry } from '@joplin/utils/net'; + +const sponsorsPath = `${rootDir}/packages/tools/sponsors.json`; + +export interface GithubSponsor { + name: string; + id: string; +} + +export interface Sponsors { + github: GithubSponsor[]; + orgs: OrgSponsor[]; +} + +export interface OrgSponsor { + url: string; + urlWebsite?: string; + title: string; + imageName: string; +} + +export const loadSponsors = async (): Promise => { + const output: Sponsors = JSON.parse(await readFile(sponsorsPath, 'utf8')); + + output.orgs = output.orgs.map(o => { + if (o.urlWebsite) o.url = o.urlWebsite; + return o; + }); + + for (const ghSponsor of output.github) { + const userResponse = await fetchWithRetry(`https://api.github.com/users/${ghSponsor.name}`); + const user = await userResponse.json(); + ghSponsor.id = user.id; + } + + return output; +}; diff --git a/packages/tools/website/build.ts b/packages/tools/website/build.ts index daa50b277..67604cb73 100644 --- a/packages/tools/website/build.ts +++ b/packages/tools/website/build.ts @@ -2,7 +2,7 @@ import { readFileSync, readFile, mkdirpSync, writeFileSync, remove, copy, pathEx import { rootDir } from '../tool-utils'; import { pressCarouselItems } from './utils/pressCarousel'; import { getMarkdownIt, loadMustachePartials, markdownToPageHtml, renderMustache } from './utils/render'; -import { AssetUrls, Env, Partials, PlanPageParams, Sponsors, TemplateParams } from './utils/types'; +import { AssetUrls, Env, Partials, PlanPageParams, TemplateParams } from './utils/types'; import { createFeatureTableMd, getPlans, loadStripeConfig } from '@joplin/lib/utils/joplinCloud'; import { stripOffFrontMatter } from './utils/frontMatter'; import { dirname, basename } from 'path'; @@ -13,6 +13,7 @@ import { getNewsDateString } from './utils/news'; import { parsePoFile, parseTranslations, Translations } from '../utils/translation'; import { countryCodeOnly, setLocale } from '@joplin/lib/locale'; import applyTranslations from './utils/applyTranslations'; +import { loadSponsors } from '../utils/loadSponsors'; interface BuildConfig { env: Env; @@ -175,16 +176,6 @@ function makeHomePageMd() { return md; } -async function loadSponsors(): Promise { - const sponsorsPath = `${rootDir}/packages/tools/sponsors.json`; - const output: Sponsors = JSON.parse(await readFile(sponsorsPath, 'utf8')); - output.orgs = output.orgs.map(o => { - if (o.urlWebsite) o.url = o.urlWebsite; - return o; - }); - return output; -} - const processNewsMarkdown = (md: string, mdFilePath: string): string => { const info = stripOffFrontMatter(md); md = info.doc.trim(); diff --git a/packages/tools/website/utils/types.ts b/packages/tools/website/utils/types.ts index bbecd0536..a0768a6a0 100644 --- a/packages/tools/website/utils/types.ts +++ b/packages/tools/website/utils/types.ts @@ -1,4 +1,5 @@ import { Plan, StripePublicConfig } from '@joplin/lib/utils/joplinCloud'; +import { Sponsors } from '../../utils/loadSponsors'; import { OpenGraphTags } from './openGraph'; export enum Env { @@ -6,26 +7,10 @@ export enum Env { Prod = 'prod', } -export interface GithubSponsor { - name: string; -} - export interface GithubUser { id: string; } -export interface OrgSponsor { - url: string; - urlWebsite?: string; - title: string; - imageName: string; -} - -export interface Sponsors { - github: GithubSponsor[]; - orgs: OrgSponsor[]; -} - interface PressCarouselItem { active: string; body: string; diff --git a/packages/utils/net.ts b/packages/utils/net.ts new file mode 100644 index 000000000..0cb514d05 --- /dev/null +++ b/packages/utils/net.ts @@ -0,0 +1,28 @@ +/* eslint-disable import/prefer-default-export */ + +import { sleep } from './time'; + +export const fetchWithRetry = async (url: string, opts: any = null) => { + if (!opts) opts = {}; + let retry = opts && opts.retry || 3; + + while (retry > 0) { + try { + return fetch(url, opts); + } catch (e) { + if (opts && opts.callback) { + opts.callback(retry); + } + retry = retry - 1; + if (retry === 0) { + throw e; + } + + if (opts && opts.pause) { + await sleep(opts.pause); + } + } + } + + return null; +}; diff --git a/packages/utils/package.json b/packages/utils/package.json index fc3d6f161..5691b3eae 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -3,7 +3,10 @@ "version": "2.10.0", "description": "Utilities for Joplin", "repository": "https://github.com/laurent22/joplin/tree/dev/packages/utils", - "main": "dist/index.js", + "exports": { + ".": "./dist/index.js", + "./net": "./dist/net.js" + }, "publishConfig": { "access": "public" }, diff --git a/packages/utils/time.ts b/packages/utils/time.ts new file mode 100644 index 000000000..4d4ef70d1 --- /dev/null +++ b/packages/utils/time.ts @@ -0,0 +1,5 @@ +/* eslint-disable import/prefer-default-export */ + +export const sleep = (ms: number) => { + return new Promise(resolve => setTimeout(resolve, ms)); +};