@stats-forge/github-stats-forge-core 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/api/contributed-to.js +1 -1
- package/build/api/gist.js +1 -1
- package/build/api/index.d.ts +1 -0
- package/build/api/index.d.ts.map +1 -1
- package/build/api/index.js +1 -0
- package/build/api/organization.d.ts +29 -0
- package/build/api/organization.d.ts.map +1 -0
- package/build/api/organization.js +53 -0
- package/build/api/params.js +1 -1
- package/build/api/pin.js +1 -1
- package/build/api/stats.js +1 -1
- package/build/api/top-langs.js +1 -1
- package/build/api/wakatime.js +1 -1
- package/build/cards/{contributed-to.d.ts → contributed-to/index.d.ts} +3 -3
- package/build/cards/contributed-to/index.d.ts.map +1 -0
- package/build/cards/{contributed-to.js → contributed-to/index.js} +31 -30
- package/build/cards/contributed-to/locales.d.ts +38 -0
- package/build/cards/contributed-to/locales.d.ts.map +1 -0
- package/build/cards/contributed-to/locales.js +39 -0
- package/build/cards/{gist.d.ts → gist/index.d.ts} +3 -3
- package/build/cards/gist/index.d.ts.map +1 -0
- package/build/cards/{gist.js → gist/index.js} +20 -15
- package/build/cards/gist/locales.d.ts +14 -0
- package/build/cards/gist/locales.d.ts.map +1 -0
- package/build/cards/gist/locales.js +15 -0
- package/build/cards/organization/index.d.ts +36 -0
- package/build/cards/organization/index.d.ts.map +1 -0
- package/build/cards/organization/index.js +225 -0
- package/build/cards/organization/locales.d.ts +47 -0
- package/build/cards/organization/locales.d.ts.map +1 -0
- package/build/cards/organization/locales.js +47 -0
- package/build/cards/{repo.d.ts → repo/index.d.ts} +3 -3
- package/build/cards/repo/index.d.ts.map +1 -0
- package/build/cards/{repo.js → repo/index.js} +20 -23
- package/build/cards/repo/locales.d.ts +129 -0
- package/build/cards/repo/locales.d.ts.map +1 -0
- package/build/cards/repo/locales.js +129 -0
- package/build/cards/{stats.d.ts → stats/index.d.ts} +3 -3
- package/build/cards/stats/index.d.ts.map +1 -0
- package/build/cards/{stats.js → stats/index.js} +38 -42
- package/build/cards/stats/locales.d.ts +621 -0
- package/build/cards/stats/locales.d.ts.map +1 -0
- package/build/cards/stats/locales.js +623 -0
- package/build/cards/{top-languages.d.ts → top-languages/index.d.ts} +3 -3
- package/build/cards/top-languages/index.d.ts.map +1 -0
- package/build/cards/{top-languages.js → top-languages/index.js} +13 -16
- package/build/cards/top-languages/locales.d.ts +103 -0
- package/build/cards/top-languages/locales.d.ts.map +1 -0
- package/build/cards/top-languages/locales.js +103 -0
- package/build/cards/{wakatime.d.ts → wakatime/index.d.ts} +3 -3
- package/build/cards/wakatime/index.d.ts.map +1 -0
- package/build/cards/{wakatime.js → wakatime/index.js} +22 -23
- package/build/cards/wakatime/locales.d.ts +250 -0
- package/build/cards/wakatime/locales.d.ts.map +1 -0
- package/build/cards/wakatime/locales.js +250 -0
- package/build/common/brand.d.ts +1 -0
- package/build/common/brand.d.ts.map +1 -1
- package/build/common/brand.js +1 -0
- package/build/common/error.d.ts +3 -1
- package/build/common/error.d.ts.map +1 -1
- package/build/common/error.js +3 -1
- package/build/common/icons.d.ts +5 -0
- package/build/common/icons.d.ts.map +1 -1
- package/build/common/icons.js +19 -4
- package/build/common/locales.d.ts +59 -0
- package/build/common/locales.d.ts.map +1 -0
- package/build/common/locales.js +59 -0
- package/build/common/localize.d.ts +60 -0
- package/build/common/localize.d.ts.map +1 -0
- package/build/common/localize.js +163 -0
- package/build/fetchers/index.d.ts +2 -1
- package/build/fetchers/index.d.ts.map +1 -1
- package/build/fetchers/index.js +1 -0
- package/build/fetchers/organization.d.ts +15 -0
- package/build/fetchers/organization.d.ts.map +1 -0
- package/build/fetchers/organization.js +115 -0
- package/build/fetchers/types.d.ts +38 -0
- package/build/fetchers/types.d.ts.map +1 -1
- package/build/graphql/generated/organization.d.ts +88 -0
- package/build/graphql/generated/organization.d.ts.map +1 -0
- package/build/graphql/generated/organization.js +59 -0
- package/package.json +1 -1
- package/src/api/contributed-to.ts +1 -1
- package/src/api/gist.ts +1 -1
- package/src/api/index.ts +1 -0
- package/src/api/organization.ts +90 -0
- package/src/api/params.ts +1 -1
- package/src/api/pin.ts +1 -1
- package/src/api/stats.ts +1 -1
- package/src/api/top-langs.ts +1 -1
- package/src/api/wakatime.ts +1 -1
- package/src/cards/{contributed-to.ts → contributed-to/index.ts} +42 -39
- package/src/cards/contributed-to/locales.ts +41 -0
- package/src/cards/{gist.ts → gist/index.ts} +23 -20
- package/src/cards/gist/locales.ts +17 -0
- package/src/cards/organization/index.ts +358 -0
- package/src/cards/organization/locales.ts +49 -0
- package/src/cards/{repo.ts → repo/index.ts} +23 -26
- package/src/cards/repo/locales.ts +131 -0
- package/src/cards/{stats.ts → stats/index.ts} +48 -56
- package/src/cards/stats/locales.ts +625 -0
- package/src/cards/{top-languages.ts → top-languages/index.ts} +17 -20
- package/src/cards/top-languages/locales.ts +105 -0
- package/src/cards/{wakatime.ts → wakatime/index.ts} +26 -27
- package/src/cards/wakatime/locales.ts +252 -0
- package/src/common/brand.ts +1 -0
- package/src/common/error.ts +4 -0
- package/src/common/icons.ts +20 -4
- package/src/common/locales.ts +61 -0
- package/src/common/localize.ts +251 -0
- package/src/fetchers/index.ts +2 -0
- package/src/fetchers/organization.ts +153 -0
- package/src/fetchers/types.ts +36 -0
- package/src/graphql/generated/organization.ts +109 -0
- package/src/graphql/queries/organization.graphql +57 -0
- package/build/cards/contributed-to.d.ts.map +0 -1
- package/build/cards/gist.d.ts.map +0 -1
- package/build/cards/repo.d.ts.map +0 -1
- package/build/cards/stats.d.ts.map +0 -1
- package/build/cards/top-languages.d.ts.map +0 -1
- package/build/cards/wakatime.d.ts.map +0 -1
- package/build/common/I18n.d.ts +0 -21
- package/build/common/I18n.d.ts.map +0 -1
- package/build/common/I18n.js +0 -34
- package/build/translations.d.ts +0 -1212
- package/build/translations.d.ts.map +0 -1
- package/build/translations.js +0 -1213
- package/src/common/I18n.ts +0 -50
- package/src/translations.ts +0 -1239
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every locale a card can be asked for.
|
|
3
|
+
*
|
|
4
|
+
* A key is written in `en` first and translated afterwards, so a card's table need not
|
|
5
|
+
* carry every locale — a wording falls back to `en`. This list is what the api accepts.
|
|
6
|
+
*
|
|
7
|
+
* @see https://www.andiamo.co.uk/resources/iso-language-codes/ for language codes.
|
|
8
|
+
*/
|
|
9
|
+
const AVAILABLE_LOCALES = [
|
|
10
|
+
'en',
|
|
11
|
+
'ar',
|
|
12
|
+
'az',
|
|
13
|
+
'bg',
|
|
14
|
+
'bn',
|
|
15
|
+
'ca',
|
|
16
|
+
'cn',
|
|
17
|
+
'zh-tw',
|
|
18
|
+
'cs',
|
|
19
|
+
'de',
|
|
20
|
+
'sw',
|
|
21
|
+
'ur',
|
|
22
|
+
'es',
|
|
23
|
+
'fa',
|
|
24
|
+
'fi',
|
|
25
|
+
'fr',
|
|
26
|
+
'hi',
|
|
27
|
+
'sa',
|
|
28
|
+
'hu',
|
|
29
|
+
'it',
|
|
30
|
+
'ja',
|
|
31
|
+
'kr',
|
|
32
|
+
'nl',
|
|
33
|
+
'pt-pt',
|
|
34
|
+
'pt-br',
|
|
35
|
+
'np',
|
|
36
|
+
'el',
|
|
37
|
+
'ro',
|
|
38
|
+
'ru',
|
|
39
|
+
'uk-ua',
|
|
40
|
+
'id',
|
|
41
|
+
'ml',
|
|
42
|
+
'my',
|
|
43
|
+
'ta',
|
|
44
|
+
'sk',
|
|
45
|
+
'tr',
|
|
46
|
+
'pl',
|
|
47
|
+
'uz',
|
|
48
|
+
'vi',
|
|
49
|
+
'se',
|
|
50
|
+
'he',
|
|
51
|
+
'fil',
|
|
52
|
+
'th',
|
|
53
|
+
'sr',
|
|
54
|
+
'sr-latn',
|
|
55
|
+
'no',
|
|
56
|
+
'be',
|
|
57
|
+
];
|
|
58
|
+
const FALLBACK_LOCALE = 'en';
|
|
59
|
+
/**
|
|
60
|
+
* Checks whether the locale is available or not.
|
|
61
|
+
*
|
|
62
|
+
* @returns Boolean specifying whether the locale is available or not.
|
|
63
|
+
*/
|
|
64
|
+
const isLocaleAvailable = (locale) => AVAILABLE_LOCALES.includes(locale.toLowerCase());
|
|
65
|
+
/**
|
|
66
|
+
* Declares a card's translations, keeping every string's literal type so `localize` knows
|
|
67
|
+
* which `{placeholder}` values each key needs.
|
|
68
|
+
*
|
|
69
|
+
* @returns The table it was given.
|
|
70
|
+
*/
|
|
71
|
+
const defineLocales = (table) => table;
|
|
72
|
+
/** `{name}` — a placeholder in a phrase. */
|
|
73
|
+
const PLACEHOLDER = /\{(?<name>\w+)\}/g;
|
|
74
|
+
/**
|
|
75
|
+
* Substitutes a phrase's `{name}` placeholders. Only the phrase is scanned, so a value
|
|
76
|
+
* that itself looks like a placeholder is left alone.
|
|
77
|
+
*
|
|
78
|
+
* @returns The wording as the card draws it.
|
|
79
|
+
*/
|
|
80
|
+
const interpolate = (phrase, key, values) => phrase.replace(PLACEHOLDER, (_placeholder, name) => {
|
|
81
|
+
const value = values?.[name];
|
|
82
|
+
if (value === undefined) {
|
|
83
|
+
throw new Error(`'${key}' needs a value for '{${name}}'`);
|
|
84
|
+
}
|
|
85
|
+
return String(value);
|
|
86
|
+
});
|
|
87
|
+
const pluralRules = new Map();
|
|
88
|
+
/**
|
|
89
|
+
* The plural rules of the locale that supplied the phrase. Several of the locale names
|
|
90
|
+
* here are not language tags `Intl` knows (`cn`, `kr`, `np`), and resolve to the runtime's
|
|
91
|
+
* own locale — which only matters once such a locale writes plural forms of its own.
|
|
92
|
+
*
|
|
93
|
+
* @returns The rules, built once per locale.
|
|
94
|
+
*/
|
|
95
|
+
const rulesFor = (locale) => {
|
|
96
|
+
const cached = pluralRules.get(locale);
|
|
97
|
+
if (cached) {
|
|
98
|
+
return cached;
|
|
99
|
+
}
|
|
100
|
+
const rules = new Intl.PluralRules(locale);
|
|
101
|
+
pluralRules.set(locale, rules);
|
|
102
|
+
return rules;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Picks the form a count calls for, by the rules of the locale the phrase came from.
|
|
106
|
+
*
|
|
107
|
+
* @returns The chosen form, or `other` for a category that locale has not written.
|
|
108
|
+
*/
|
|
109
|
+
const selectPlural = (forms, locale, key, values) => {
|
|
110
|
+
const count = values?.['count'];
|
|
111
|
+
if (typeof count !== 'number') {
|
|
112
|
+
throw new TypeError(`'${key}' has plural forms and needs a numeric 'count'`);
|
|
113
|
+
}
|
|
114
|
+
return forms[rulesFor(locale).select(count)] ?? forms.other;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Reads a wording in the locale asked for, falling back to English when that locale has
|
|
118
|
+
* no entry for it.
|
|
119
|
+
*
|
|
120
|
+
* @returns The wording, and the locale it actually came from.
|
|
121
|
+
*/
|
|
122
|
+
const readPhrase = (phrases, key, locale) => {
|
|
123
|
+
const written = phrases[locale];
|
|
124
|
+
if (written !== undefined) {
|
|
125
|
+
return { phrase: written, locale };
|
|
126
|
+
}
|
|
127
|
+
// The english wording the type requires can still be missing at runtime: a card can pass
|
|
128
|
+
// a table it built, and `i18n.test.ts` covers exactly that.
|
|
129
|
+
const english = phrases[FALLBACK_LOCALE];
|
|
130
|
+
// oxlint-disable-next-line typescript/no-unnecessary-condition
|
|
131
|
+
if (english === undefined) {
|
|
132
|
+
throw new Error(`'${key}' translation not found for locale '${locale}'`);
|
|
133
|
+
}
|
|
134
|
+
return { phrase: english, locale: FALLBACK_LOCALE };
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Draws a key's wording: the locale's own if it has one and English otherwise, in the
|
|
138
|
+
* plural form its count calls for, with its `{name}` placeholders substituted.
|
|
139
|
+
*
|
|
140
|
+
* @returns The wording as the card draws it.
|
|
141
|
+
*/
|
|
142
|
+
const draw = (phrases, key, locale, values) => {
|
|
143
|
+
const { phrase, locale: from } = readPhrase(phrases, key, locale);
|
|
144
|
+
const wording = typeof phrase === 'string' ? phrase : selectPlural(phrase, from, key, values);
|
|
145
|
+
return interpolate(wording, key, values);
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Binds a card's translations to one locale, so a card names a wording where it draws it
|
|
149
|
+
* — `t.title({ login })` — rather than naming a key. That is what lets an editor follow a
|
|
150
|
+
* wording to where it is written, and why a key carries no card name in front of it.
|
|
151
|
+
*
|
|
152
|
+
* @returns One function per key the table declares.
|
|
153
|
+
*/
|
|
154
|
+
const localize = (table, locale) => {
|
|
155
|
+
const asked = locale || FALLBACK_LOCALE;
|
|
156
|
+
const wordings = {};
|
|
157
|
+
for (const [key, phrases] of Object.entries(table)) {
|
|
158
|
+
wordings[key] = (values) => draw(phrases, key, asked, values);
|
|
159
|
+
}
|
|
160
|
+
// A mapped type over a table known only as a type parameter needs the assertion.
|
|
161
|
+
return wordings;
|
|
162
|
+
};
|
|
163
|
+
export { defineLocales, isLocaleAvailable, localize };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export { fetchContributedTo } from './contributed-to.ts';
|
|
2
2
|
export { fetchGist } from './gist.ts';
|
|
3
|
+
export { fetchOrganization } from './organization.ts';
|
|
3
4
|
export { fetchRepo } from './repo.ts';
|
|
4
5
|
export { fetchRepoUserStats, fetchStats } from './stats.ts';
|
|
5
6
|
export { fetchTopLanguages } from './top-languages.ts';
|
|
6
7
|
export { fetchWakatimeStats } from './wakatime.ts';
|
|
7
|
-
export type { ContributedRepo, ContributedToData, GistData, Lang, RepoUserStats, RepositoryData, StatsData, TopLangData, WakaTimeData, WakaTimeLang, } from './types.ts';
|
|
8
|
+
export type { ContributedRepo, ContributedToData, GistData, Lang, OrganizationData, RepoUserStats, RepositoryData, StatsData, TopLangData, WakaTimeData, WakaTimeLang, } from './types.ts';
|
|
8
9
|
export { CardConfig } from '../common/config.ts';
|
|
9
10
|
export type { CardConfigInit, PersonalAccessToken } from '../common/config.ts';
|
|
10
11
|
export type { FetchLike } from '../common/http.ts';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fetchers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEnD,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,QAAQ,EACR,IAAI,EACJ,aAAa,EACb,cAAc,EACd,SAAS,EACT,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fetchers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEnD,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,QAAQ,EACR,IAAI,EACJ,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,SAAS,EACT,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC"}
|
package/build/fetchers/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { fetchContributedTo } from './contributed-to.js';
|
|
2
2
|
export { fetchGist } from './gist.js';
|
|
3
|
+
export { fetchOrganization } from './organization.js';
|
|
3
4
|
export { fetchRepo } from './repo.js';
|
|
4
5
|
export { fetchRepoUserStats, fetchStats } from './stats.js';
|
|
5
6
|
export { fetchTopLanguages } from './top-languages.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CardConfig } from '../common/config.ts';
|
|
2
|
+
import type { OrganizationData } from './types.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Fetch an organization and the totals of its public repositories.
|
|
5
|
+
*
|
|
6
|
+
* Only public, non-fork repositories are counted, most-starred first,
|
|
7
|
+
* and at most five pages of 100 — `truncated` says when the walk stopped early.
|
|
8
|
+
*
|
|
9
|
+
* @returns The organization data.
|
|
10
|
+
*/
|
|
11
|
+
declare const fetchOrganization: ({ org }: {
|
|
12
|
+
org: string | undefined;
|
|
13
|
+
}, config: CardConfig) => Promise<OrganizationData>;
|
|
14
|
+
export { fetchOrganization };
|
|
15
|
+
//# sourceMappingURL=organization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization.d.ts","sourceRoot":"","sources":["../../src/fetchers/organization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAatD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAkDnD;;;;;;;GAOG;AACH,QAAA,MAAM,iBAAiB,YACZ;IAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,UAC5B,UAAU,KACjB,OAAO,CAAC,gBAAgB,CA4E1B,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { GITHUB_USERNAME_PATTERN } from '../common/constants.js';
|
|
2
|
+
import { CardError, ORGANIZATION_NOT_FOUND } from '../common/error.js';
|
|
3
|
+
import { createGraphQLFetcher } from '../common/http.js';
|
|
4
|
+
import { retryer } from '../common/retryer.js';
|
|
5
|
+
import { GetOrganizationDocument } from '../graphql/generated/organization.js';
|
|
6
|
+
import { graphqlError } from './graphql-error.js';
|
|
7
|
+
const fetcher = createGraphQLFetcher(GetOrganizationDocument, 'token');
|
|
8
|
+
const urlExample = '/api/org?org=ORG_NAME';
|
|
9
|
+
const ORGANIZATION_ERROR = 'Something went wrong while trying to retrieve the organization data using the GraphQL API.';
|
|
10
|
+
/**
|
|
11
|
+
* Pages of repositories the walk asks for, 100 each.
|
|
12
|
+
* Named in the doc comments below as the number it is, so the constant stays internal.
|
|
13
|
+
* The totals are sums over what it saw and the repositories arrive most-starred first,
|
|
14
|
+
* so the cap costs an organization past it the tail of its list rather than its headline figures.
|
|
15
|
+
*/
|
|
16
|
+
const MAX_REPO_PAGES = 5;
|
|
17
|
+
/**
|
|
18
|
+
* @returns The language most of those repositories name as their primary one, `null` when none do.
|
|
19
|
+
*/
|
|
20
|
+
const topLanguage = (repos) => {
|
|
21
|
+
const counts = new Map();
|
|
22
|
+
for (const { primaryLanguage } of repos) {
|
|
23
|
+
if (primaryLanguage) {
|
|
24
|
+
const seen = counts.get(primaryLanguage.name);
|
|
25
|
+
counts.set(primaryLanguage.name, {
|
|
26
|
+
color: primaryLanguage.color,
|
|
27
|
+
count: (seen?.count ?? 0) + 1,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
let top = null;
|
|
32
|
+
let max = 0;
|
|
33
|
+
for (const [name, { color, count }] of counts) {
|
|
34
|
+
if (count > max) {
|
|
35
|
+
max = count;
|
|
36
|
+
top = { name, color };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return top;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Fetch an organization and the totals of its public repositories.
|
|
43
|
+
*
|
|
44
|
+
* Only public, non-fork repositories are counted, most-starred first,
|
|
45
|
+
* and at most five pages of 100 — `truncated` says when the walk stopped early.
|
|
46
|
+
*
|
|
47
|
+
* @returns The organization data.
|
|
48
|
+
*/
|
|
49
|
+
const fetchOrganization = async ({ org }, config) => {
|
|
50
|
+
if (!org) {
|
|
51
|
+
throw CardError.missingParam(['org'], urlExample);
|
|
52
|
+
}
|
|
53
|
+
// `./fetchers` is a public export, so the login is checked here as well as at the api boundary.
|
|
54
|
+
if (!GITHUB_USERNAME_PATTERN.test(org)) {
|
|
55
|
+
throw new CardError('Invalid organization provided.', {
|
|
56
|
+
code: 'invalid_param',
|
|
57
|
+
param: 'org',
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
const repos = [];
|
|
61
|
+
let organization;
|
|
62
|
+
let after = null;
|
|
63
|
+
let pages = 0;
|
|
64
|
+
do {
|
|
65
|
+
// Annotated because the walk feeds its own cursor back in, which TypeScript reads as circular.
|
|
66
|
+
const res = await retryer(fetcher, { login: org, after }, config);
|
|
67
|
+
if (res.data.errors) {
|
|
68
|
+
// A login that is a user, or nothing at all, answers NOT_FOUND — which `graphqlError`
|
|
69
|
+
// words for a user query, so this endpoint's own wording is thrown instead.
|
|
70
|
+
if (res.data.errors[0]?.type === 'NOT_FOUND') {
|
|
71
|
+
throw new CardError('Organization not found', {
|
|
72
|
+
code: 'not_found',
|
|
73
|
+
secondaryMessage: ORGANIZATION_NOT_FOUND,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
throw graphqlError(res.data.errors, res.statusText, ORGANIZATION_ERROR);
|
|
77
|
+
}
|
|
78
|
+
organization = res.data.data.organization ?? undefined;
|
|
79
|
+
if (!organization) {
|
|
80
|
+
throw new CardError('Organization not found', {
|
|
81
|
+
code: 'not_found',
|
|
82
|
+
secondaryMessage: ORGANIZATION_NOT_FOUND,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
repos.push(...(organization.repositories.nodes ?? []).filter((node) => node !== null));
|
|
86
|
+
const { hasNextPage, endCursor } = organization.repositories.pageInfo;
|
|
87
|
+
after = hasNextPage ? endCursor : null;
|
|
88
|
+
pages += 1;
|
|
89
|
+
} while (after !== null && pages < MAX_REPO_PAGES);
|
|
90
|
+
const sum = (count) => repos.reduce((total, repo) => total + count(repo), 0);
|
|
91
|
+
return {
|
|
92
|
+
login: organization.login,
|
|
93
|
+
name: organization.name || organization.login,
|
|
94
|
+
description: organization.description,
|
|
95
|
+
createdAt: organization.createdAt,
|
|
96
|
+
publicRepos: organization.repositories.totalCount,
|
|
97
|
+
totalStars: sum((repo) => repo.stargazerCount),
|
|
98
|
+
totalForks: sum((repo) => repo.forkCount),
|
|
99
|
+
totalWatchers: sum((repo) => repo.watchers.totalCount),
|
|
100
|
+
openIssues: sum((repo) => repo.issues.totalCount),
|
|
101
|
+
openPRs: sum((repo) => repo.pullRequests.totalCount),
|
|
102
|
+
totalReleases: sum((repo) => repo.releases.totalCount),
|
|
103
|
+
// An empty repository has no default branch, and a branch pointing at a tag has no history.
|
|
104
|
+
totalCommits: sum((repo) => {
|
|
105
|
+
const target = repo.defaultBranchRef?.target;
|
|
106
|
+
return target !== null && target !== undefined && 'history' in target
|
|
107
|
+
? target.history.totalCount
|
|
108
|
+
: 0;
|
|
109
|
+
}),
|
|
110
|
+
publicMembers: organization.membersWithRole.totalCount,
|
|
111
|
+
topLanguage: topLanguage(repos),
|
|
112
|
+
truncated: after !== null,
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
export { fetchOrganization };
|
|
@@ -27,6 +27,44 @@ export interface RepoUserStats {
|
|
|
27
27
|
totalIssuesCommented?: number;
|
|
28
28
|
}
|
|
29
29
|
export type RepositoryData = RepoInfo & RepoUserStats;
|
|
30
|
+
/**
|
|
31
|
+
* An organization, with its public repositories aggregated.
|
|
32
|
+
* Every total is summed over the repositories the walk saw — public, non-fork ones,
|
|
33
|
+
* most-starred first — so `truncated` says whether that was all of them.
|
|
34
|
+
*/
|
|
35
|
+
export interface OrganizationData {
|
|
36
|
+
login: string;
|
|
37
|
+
/** The organization's display name, or its login when it has none. */
|
|
38
|
+
name: string;
|
|
39
|
+
description: string | null;
|
|
40
|
+
/** When the organization was created, as GitHub's own ISO 8601 instant. */
|
|
41
|
+
createdAt: string;
|
|
42
|
+
/** Public, non-fork repositories: the whole count, whether or not the walk saw them all. */
|
|
43
|
+
publicRepos: number;
|
|
44
|
+
totalStars: number;
|
|
45
|
+
totalForks: number;
|
|
46
|
+
totalWatchers: number;
|
|
47
|
+
openIssues: number;
|
|
48
|
+
openPRs: number;
|
|
49
|
+
totalReleases: number;
|
|
50
|
+
/**
|
|
51
|
+
* Commits on the default branch of every repository counted: every author, merges included,
|
|
52
|
+
* and whatever history a repository was imported with.
|
|
53
|
+
*/
|
|
54
|
+
totalCommits: number;
|
|
55
|
+
/**
|
|
56
|
+
* Members GitHub shows publicly.
|
|
57
|
+
* Membership is private by default, so this counts fewer people than the organization has.
|
|
58
|
+
*/
|
|
59
|
+
publicMembers: number;
|
|
60
|
+
/** The language most of those repositories name as their primary one, `null` when none do. */
|
|
61
|
+
topLanguage: {
|
|
62
|
+
name: string;
|
|
63
|
+
color: string | null;
|
|
64
|
+
} | null;
|
|
65
|
+
/** Whether the repository walk stopped at its page cap, leaving the totals short. */
|
|
66
|
+
truncated: boolean;
|
|
67
|
+
}
|
|
30
68
|
export interface StatsData {
|
|
31
69
|
name: string;
|
|
32
70
|
totalPRs: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/fetchers/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/fetchers/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/** Internal type. DO NOT USE DIRECTLY. */
|
|
2
|
+
type Exact<T extends {
|
|
3
|
+
[key: string]: unknown;
|
|
4
|
+
}> = {
|
|
5
|
+
[K in keyof T]: T[K];
|
|
6
|
+
};
|
|
7
|
+
export type OrgRepoInfoFragment = {
|
|
8
|
+
stargazerCount: number;
|
|
9
|
+
forkCount: number;
|
|
10
|
+
primaryLanguage: {
|
|
11
|
+
color: string | null;
|
|
12
|
+
name: string;
|
|
13
|
+
} | null;
|
|
14
|
+
watchers: {
|
|
15
|
+
totalCount: number;
|
|
16
|
+
};
|
|
17
|
+
issues: {
|
|
18
|
+
totalCount: number;
|
|
19
|
+
};
|
|
20
|
+
pullRequests: {
|
|
21
|
+
totalCount: number;
|
|
22
|
+
};
|
|
23
|
+
releases: {
|
|
24
|
+
totalCount: number;
|
|
25
|
+
};
|
|
26
|
+
defaultBranchRef: {
|
|
27
|
+
target: {
|
|
28
|
+
history: {
|
|
29
|
+
totalCount: number;
|
|
30
|
+
};
|
|
31
|
+
} | Record<PropertyKey, never> | null;
|
|
32
|
+
} | null;
|
|
33
|
+
};
|
|
34
|
+
export type GetOrganizationQueryVariables = Exact<{
|
|
35
|
+
login: string;
|
|
36
|
+
after?: string | null | undefined;
|
|
37
|
+
}>;
|
|
38
|
+
export type GetOrganizationQuery = {
|
|
39
|
+
organization: {
|
|
40
|
+
login: string;
|
|
41
|
+
name: string | null;
|
|
42
|
+
description: string | null;
|
|
43
|
+
createdAt: string;
|
|
44
|
+
membersWithRole: {
|
|
45
|
+
totalCount: number;
|
|
46
|
+
};
|
|
47
|
+
repositories: {
|
|
48
|
+
totalCount: number;
|
|
49
|
+
pageInfo: {
|
|
50
|
+
hasNextPage: boolean;
|
|
51
|
+
endCursor: string | null;
|
|
52
|
+
};
|
|
53
|
+
nodes: Array<{
|
|
54
|
+
stargazerCount: number;
|
|
55
|
+
forkCount: number;
|
|
56
|
+
primaryLanguage: {
|
|
57
|
+
color: string | null;
|
|
58
|
+
name: string;
|
|
59
|
+
} | null;
|
|
60
|
+
watchers: {
|
|
61
|
+
totalCount: number;
|
|
62
|
+
};
|
|
63
|
+
issues: {
|
|
64
|
+
totalCount: number;
|
|
65
|
+
};
|
|
66
|
+
pullRequests: {
|
|
67
|
+
totalCount: number;
|
|
68
|
+
};
|
|
69
|
+
releases: {
|
|
70
|
+
totalCount: number;
|
|
71
|
+
};
|
|
72
|
+
defaultBranchRef: {
|
|
73
|
+
target: {
|
|
74
|
+
history: {
|
|
75
|
+
totalCount: number;
|
|
76
|
+
};
|
|
77
|
+
} | Record<PropertyKey, never> | null;
|
|
78
|
+
} | null;
|
|
79
|
+
} | null> | null;
|
|
80
|
+
};
|
|
81
|
+
} | null;
|
|
82
|
+
};
|
|
83
|
+
export declare const GetOrganizationDocument: import("../graphqlDocument.ts").GraphQLDocument<GetOrganizationQuery, Exact<{
|
|
84
|
+
login: string;
|
|
85
|
+
after?: string | null | undefined;
|
|
86
|
+
}>>;
|
|
87
|
+
export {};
|
|
88
|
+
//# sourceMappingURL=organization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization.d.ts","sourceRoot":"","sources":["../../../src/graphql/generated/organization.ts"],"names":[],"mappings":"AAEA,0CAA0C;AAC1C,KAAK,KAAK,CAAC,CAAC,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC;AAE5E,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/D,QAAQ,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,YAAY,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,QAAQ,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,gBAAgB,EAAE;QAChB,MAAM,EAAE;YAAE,OAAO,EAAE;gBAAE,UAAU,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,GAAG,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC;KACjF,GAAG,IAAI,CAAC;CACV,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,KAAK,CAAC;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACnC,CAAC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG;IACjC,YAAY,EAAE;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,SAAS,EAAE,MAAM,CAAC;QAClB,eAAe,EAAE;YAAE,UAAU,EAAE,MAAM,CAAA;SAAE,CAAC;QACxC,YAAY,EAAE;YACZ,UAAU,EAAE,MAAM,CAAC;YACnB,QAAQ,EAAE;gBAAE,WAAW,EAAE,OAAO,CAAC;gBAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;aAAE,CAAC;YAC7D,KAAK,EAAE,KAAK,CAAC;gBACX,cAAc,EAAE,MAAM,CAAC;gBACvB,SAAS,EAAE,MAAM,CAAC;gBAClB,eAAe,EAAE;oBAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;oBAAC,IAAI,EAAE,MAAM,CAAA;iBAAE,GAAG,IAAI,CAAC;gBAC/D,QAAQ,EAAE;oBAAE,UAAU,EAAE,MAAM,CAAA;iBAAE,CAAC;gBACjC,MAAM,EAAE;oBAAE,UAAU,EAAE,MAAM,CAAA;iBAAE,CAAC;gBAC/B,YAAY,EAAE;oBAAE,UAAU,EAAE,MAAM,CAAA;iBAAE,CAAC;gBACrC,QAAQ,EAAE;oBAAE,UAAU,EAAE,MAAM,CAAA;iBAAE,CAAC;gBACjC,gBAAgB,EAAE;oBAChB,MAAM,EAAE;wBAAE,OAAO,EAAE;4BAAE,UAAU,EAAE,MAAM,CAAA;yBAAE,CAAA;qBAAE,GAAG,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC;iBACjF,GAAG,IAAI,CAAC;aACV,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;SAClB,CAAC;KACH,GAAG,IAAI,CAAC;CACV,CAAC;AAEF,eAAO,MAAM,uBAAuB;WA9B3B,MAAM;YACL,MAAM,GAAG,IAAI,GAAG,SAAS;GAwFhC,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Generated file — see .github/CONTRIBUTING.md
|
|
2
|
+
import { graphqlDocument } from '../graphqlDocument.js';
|
|
3
|
+
export const GetOrganizationDocument = graphqlDocument(`
|
|
4
|
+
query getOrganization($login: String!, $after: String) {
|
|
5
|
+
organization(login: $login) {
|
|
6
|
+
login
|
|
7
|
+
name
|
|
8
|
+
description
|
|
9
|
+
createdAt
|
|
10
|
+
membersWithRole {
|
|
11
|
+
totalCount
|
|
12
|
+
}
|
|
13
|
+
repositories(
|
|
14
|
+
first: 100
|
|
15
|
+
after: $after
|
|
16
|
+
privacy: PUBLIC
|
|
17
|
+
isFork: false
|
|
18
|
+
orderBy: {field: STARGAZERS, direction: DESC}
|
|
19
|
+
) {
|
|
20
|
+
totalCount
|
|
21
|
+
pageInfo {
|
|
22
|
+
hasNextPage
|
|
23
|
+
endCursor
|
|
24
|
+
}
|
|
25
|
+
nodes {
|
|
26
|
+
...OrgRepoInfo
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
fragment OrgRepoInfo on Repository {
|
|
32
|
+
stargazerCount
|
|
33
|
+
forkCount
|
|
34
|
+
primaryLanguage {
|
|
35
|
+
color
|
|
36
|
+
name
|
|
37
|
+
}
|
|
38
|
+
watchers {
|
|
39
|
+
totalCount
|
|
40
|
+
}
|
|
41
|
+
issues(states: OPEN) {
|
|
42
|
+
totalCount
|
|
43
|
+
}
|
|
44
|
+
pullRequests(states: OPEN) {
|
|
45
|
+
totalCount
|
|
46
|
+
}
|
|
47
|
+
releases {
|
|
48
|
+
totalCount
|
|
49
|
+
}
|
|
50
|
+
defaultBranchRef {
|
|
51
|
+
target {
|
|
52
|
+
... on Commit {
|
|
53
|
+
history {
|
|
54
|
+
totalCount
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as z from 'zod/mini';
|
|
2
2
|
|
|
3
|
-
import { renderContributedToCard } from '../cards/contributed-to.ts';
|
|
3
|
+
import { renderContributedToCard } from '../cards/contributed-to/index.ts';
|
|
4
4
|
import { fetchContributedTo } from '../fetchers/contributed-to.ts';
|
|
5
5
|
|
|
6
6
|
import { cardHandler } from './handler.ts';
|
package/src/api/gist.ts
CHANGED
package/src/api/index.ts
CHANGED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import * as z from 'zod/mini';
|
|
2
|
+
|
|
3
|
+
import { renderOrganizationCard } from '../cards/organization/index.ts';
|
|
4
|
+
import { fetchOrganization } from '../fetchers/organization.ts';
|
|
5
|
+
|
|
6
|
+
import { cardHandler } from './handler.ts';
|
|
7
|
+
import {
|
|
8
|
+
booleanParam,
|
|
9
|
+
listParam,
|
|
10
|
+
localeParam,
|
|
11
|
+
looseIntParam,
|
|
12
|
+
numberParam,
|
|
13
|
+
rawParam,
|
|
14
|
+
usernameParam,
|
|
15
|
+
} from './params.ts';
|
|
16
|
+
|
|
17
|
+
/** What the organization endpoint accepts, on top of the shared color params. */
|
|
18
|
+
const orgQuery = z.object({
|
|
19
|
+
org: usernameParam,
|
|
20
|
+
hide: listParam,
|
|
21
|
+
show: listParam,
|
|
22
|
+
show_icons: booleanParam,
|
|
23
|
+
hide_title: booleanParam,
|
|
24
|
+
hide_border: booleanParam,
|
|
25
|
+
hide_description: booleanParam,
|
|
26
|
+
card_width: looseIntParam,
|
|
27
|
+
line_height: rawParam,
|
|
28
|
+
custom_title: rawParam,
|
|
29
|
+
disable_animations: booleanParam,
|
|
30
|
+
number_format: rawParam,
|
|
31
|
+
text_bold: booleanParam,
|
|
32
|
+
locale: localeParam,
|
|
33
|
+
border_radius: numberParam,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Render the organization card for a set of query params.
|
|
38
|
+
*
|
|
39
|
+
* @returns The rendered card, or a rendered error.
|
|
40
|
+
*/
|
|
41
|
+
const renderOrg = cardHandler(
|
|
42
|
+
orgQuery,
|
|
43
|
+
async (
|
|
44
|
+
{
|
|
45
|
+
org,
|
|
46
|
+
hide,
|
|
47
|
+
show,
|
|
48
|
+
show_icons,
|
|
49
|
+
hide_title,
|
|
50
|
+
hide_border,
|
|
51
|
+
hide_description,
|
|
52
|
+
card_width,
|
|
53
|
+
line_height,
|
|
54
|
+
custom_title,
|
|
55
|
+
disable_animations,
|
|
56
|
+
number_format,
|
|
57
|
+
text_bold,
|
|
58
|
+
locale,
|
|
59
|
+
border_radius,
|
|
60
|
+
},
|
|
61
|
+
colors,
|
|
62
|
+
config,
|
|
63
|
+
) => {
|
|
64
|
+
const organizationData = await fetchOrganization({ org }, config);
|
|
65
|
+
|
|
66
|
+
return renderOrganizationCard(organizationData, {
|
|
67
|
+
...colors,
|
|
68
|
+
hide,
|
|
69
|
+
show,
|
|
70
|
+
show_icons,
|
|
71
|
+
hide_title,
|
|
72
|
+
hide_border,
|
|
73
|
+
hide_description,
|
|
74
|
+
card_width,
|
|
75
|
+
line_height,
|
|
76
|
+
custom_title,
|
|
77
|
+
disable_animations,
|
|
78
|
+
number_format,
|
|
79
|
+
text_bold,
|
|
80
|
+
locale,
|
|
81
|
+
border_radius,
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The card, and the values each of its options accepts, keyed by the option's own name.
|
|
88
|
+
* A UI reads them off the function it calls: `org.OPTIONS.show`.
|
|
89
|
+
*/
|
|
90
|
+
export const org = Object.assign(renderOrg, { OPTIONS: renderOrganizationCard.OPTIONS });
|