@stats-forge/github-stats-forge-core 0.4.0 → 0.5.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cards/organization/index.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AA6BpE,UAAU,cAAe,SAAQ,iBAAiB;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;CACpB;AAkCD;;;;GAIG;AACH,QAAA,MAAM,UAAU,iBACA,gBAAgB,YACrB,WAAW,CAAC,cAAc,CAAC,KACnC,MA+OF,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,sBAAsB;;QAExB,IAAI;QACJ,IAAI;QACJ,aAAa;;CAEf,CAAC;AAEH,OAAO,EAAE,sBAAsB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cards/organization/index.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AA6BpE,UAAU,cAAe,SAAQ,iBAAiB;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;CACpB;AAkCD;;;;GAIG;AACH,QAAA,MAAM,UAAU,iBACA,gBAAgB,YACrB,WAAW,CAAC,cAAc,CAAC,KACnC,MAgPF,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,sBAAsB;;QAExB,IAAI;QACJ,IAAI;QACJ,aAAa;;CAEf,CAAC;AAEH,OAAO,EAAE,sBAAsB,EAAE,CAAC"}
@@ -118,7 +118,8 @@ const renderCard = (organization, options = {}) => {
118
118
  id: 'commits',
119
119
  };
120
120
  }
121
- if (shows('members')) {
121
+ // A refused member count is `null`, and no row is better than a row reading "0".
122
+ if (shows('members') && publicMembers !== null) {
122
123
  STATS['members'] = {
123
124
  icon: icons.people,
124
125
  label: t.members(),
@@ -37,6 +37,8 @@ type GraphQLResponse<TResult> = HttpResponse<{
37
37
  errors?: Array<{
38
38
  type?: string;
39
39
  message?: string;
40
+ /** The field the error is about, from the operation root: `['organization', 'membersWithRole']`. */
41
+ path?: Array<string | number>;
40
42
  }>;
41
43
  }>;
42
44
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/common/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAIrE;;;GAGG;AACH,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE1E;;;GAGG;AACH,QAAA,MAAM,YAAY,EAAE,SAA+C,CAAC;AAEpE;;;;GAIG;AACH,UAAU,YAAY,CAAC,KAAK;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,KAAK,CAAC;CACb;AAED,wDAAwD;AACxD,UAAU,cAAc;IACtB,0CAA0C;IAC1C,KAAK,EAAE,SAAS,CAAC;IACjB,oFAAoF;IACpF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,QAAA,MAAM,WAAW,GAAU,KAAK,aACnB,SAAS,OACf,MAAM,SACJ,WAAW,KACjB,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAiB7B,CAAC;AAEF,gFAAgF;AAChF,KAAK,eAAe,CAAC,OAAO,IAAI,YAAY,CAAC;IAC3C,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrD,CAAC,CAAC;AAEH;;GAEG;AACH,QAAA,MAAM,oBAAoB,GACvB,OAAO,EAAE,UAAU,YACR,eAAe,CAAC,OAAO,EAAE,UAAU,CAAC,UACtC,QAAQ,GAAG,OAAO,iBAGf,UAAU,SACd,MAAM,aACF,cAAc,KACxB,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAQ/B,CAAC;AAEP,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;AAC3D,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/common/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAIrE;;;GAGG;AACH,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE1E;;;GAGG;AACH,QAAA,MAAM,YAAY,EAAE,SAA+C,CAAC;AAEpE;;;;GAIG;AACH,UAAU,YAAY,CAAC,KAAK;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,KAAK,CAAC;CACb;AAED,wDAAwD;AACxD,UAAU,cAAc;IACtB,0CAA0C;IAC1C,KAAK,EAAE,SAAS,CAAC;IACjB,oFAAoF;IACpF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,QAAA,MAAM,WAAW,GAAU,KAAK,aACnB,SAAS,OACf,MAAM,SACJ,WAAW,KACjB,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAiB7B,CAAC;AAEF,gFAAgF;AAChF,KAAK,eAAe,CAAC,OAAO,IAAI,YAAY,CAAC;IAC3C,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,KAAK,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,oGAAoG;QACpG,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;KAC/B,CAAC,CAAC;CACJ,CAAC,CAAC;AAEH;;GAEG;AACH,QAAA,MAAM,oBAAoB,GACvB,OAAO,EAAE,UAAU,YACR,eAAe,CAAC,OAAO,EAAE,UAAU,CAAC,UACtC,QAAQ,GAAG,OAAO,iBAGf,UAAU,SACd,MAAM,aACF,cAAc,KACxB,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAQ/B,CAAC;AAEP,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;AAC3D,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC"}
@@ -33,6 +33,7 @@
33
33
  "Apollo Guidance Computer": "#0B3D91",
34
34
  "AppleScript": "#101F1F",
35
35
  "Arc": "#aa2afe",
36
+ "ArkTS": "#0080ff",
36
37
  "AsciiDoc": "#73a0c5",
37
38
  "AspectJ": "#a957b0",
38
39
  "Assembly": "#6E4C13",
@@ -322,6 +323,7 @@
322
323
  "Kotlin": "#A97BFF",
323
324
  "LFE": "#4C3023",
324
325
  "LLVM": "#185619",
326
+ "LLVM TableGen": "#6E8B3D",
325
327
  "LOLCODE": "#cc9900",
326
328
  "LSL": "#3d9970",
327
329
  "LabVIEW": "#fede06",
@@ -1 +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"}
1
+ {"version":3,"file":"organization.d.ts","sourceRoot":"","sources":["../../src/fetchers/organization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AActD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA+DnD;;;;;;;GAOG;AACH,QAAA,MAAM,iBAAiB,YACZ;IAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,UAC5B,UAAU,KACjB,OAAO,CAAC,gBAAgB,CAiF1B,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { GITHUB_USERNAME_PATTERN } from '../common/constants.js';
2
2
  import { CardError, ORGANIZATION_NOT_FOUND } from '../common/error.js';
3
3
  import { createGraphQLFetcher } from '../common/http.js';
4
+ import { logger } from '../common/log.js';
4
5
  import { retryer } from '../common/retryer.js';
5
6
  import { GetOrganizationDocument } from '../graphql/generated/organization.js';
6
7
  import { graphqlError } from './graphql-error.js';
@@ -38,6 +39,15 @@ const topLanguage = (repos) => {
38
39
  }
39
40
  return top;
40
41
  };
42
+ /**
43
+ * The member count is the one field here a token can be refused:
44
+ * it needs the organization `Members` permission, which an app installation token rarely carries.
45
+ * GitHub answers `FORBIDDEN` on that field alone and still returns the organization,
46
+ * so the card drops the stat instead of failing whole.
47
+ *
48
+ * @returns Whether the member count is all the response was refused.
49
+ */
50
+ const onlyMembersForbidden = (errors) => errors.every((error) => error.type === 'FORBIDDEN' && error.path?.at(-1) === 'membersWithRole');
41
51
  /**
42
52
  * Fetch an organization and the totals of its public repositories.
43
53
  *
@@ -61,6 +71,7 @@ const fetchOrganization = async ({ org }, config) => {
61
71
  let organization;
62
72
  let after = null;
63
73
  let pages = 0;
74
+ let membersForbidden = false;
64
75
  do {
65
76
  // Annotated because the walk feeds its own cursor back in, which TypeScript reads as circular.
66
77
  const res = await retryer(fetcher, { login: org, after }, config);
@@ -73,7 +84,11 @@ const fetchOrganization = async ({ org }, config) => {
73
84
  secondaryMessage: ORGANIZATION_NOT_FOUND,
74
85
  });
75
86
  }
76
- throw graphqlError(res.data.errors, res.statusText, ORGANIZATION_ERROR);
87
+ if (!onlyMembersForbidden(res.data.errors)) {
88
+ throw graphqlError(res.data.errors, res.statusText, ORGANIZATION_ERROR);
89
+ }
90
+ logger.log(res.data.errors[0]?.message);
91
+ membersForbidden = true;
77
92
  }
78
93
  organization = res.data.data.organization ?? undefined;
79
94
  if (!organization) {
@@ -107,7 +122,7 @@ const fetchOrganization = async ({ org }, config) => {
107
122
  ? target.history.totalCount
108
123
  : 0;
109
124
  }),
110
- publicMembers: organization.membersWithRole.totalCount,
125
+ publicMembers: membersForbidden ? null : organization.membersWithRole.totalCount,
111
126
  topLanguage: topLanguage(repos),
112
127
  truncated: after !== null,
113
128
  };
@@ -55,8 +55,9 @@ export interface OrganizationData {
55
55
  /**
56
56
  * Members GitHub shows publicly.
57
57
  * Membership is private by default, so this counts fewer people than the organization has.
58
+ * `null` when the token may not read them, which is the card's cue to leave the stat out.
58
59
  */
59
- publicMembers: number;
60
+ publicMembers: number | null;
60
61
  /** The language most of those repositories name as their primary one, `null` when none do. */
61
62
  topLanguage: {
62
63
  name: string;
@@ -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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stats-forge/github-stats-forge-core",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Dynamically generate stats for your GitHub readme",
5
5
  "keywords": [
6
6
  "card-generator",
@@ -211,7 +211,8 @@ const renderCard = (
211
211
  };
212
212
  }
213
213
 
214
- if (shows('members')) {
214
+ // A refused member count is `null`, and no row is better than a row reading "0".
215
+ if (shows('members') && publicMembers !== null) {
215
216
  STATS['members'] = {
216
217
  icon: icons.people,
217
218
  label: t.members(),
@@ -63,7 +63,12 @@ const httpRequest = async <TData>(
63
63
  /** Response of a GraphQL call: the envelope the GitHub API wraps results in. */
64
64
  type GraphQLResponse<TResult> = HttpResponse<{
65
65
  data: TResult;
66
- errors?: Array<{ type?: string; message?: string }>;
66
+ errors?: Array<{
67
+ type?: string;
68
+ message?: string;
69
+ /** The field the error is about, from the operation root: `['organization', 'membersWithRole']`. */
70
+ path?: Array<string | number>;
71
+ }>;
67
72
  }>;
68
73
 
69
74
  /**
@@ -33,6 +33,7 @@
33
33
  "Apollo Guidance Computer": "#0B3D91",
34
34
  "AppleScript": "#101F1F",
35
35
  "Arc": "#aa2afe",
36
+ "ArkTS": "#0080ff",
36
37
  "AsciiDoc": "#73a0c5",
37
38
  "AspectJ": "#a957b0",
38
39
  "Assembly": "#6E4C13",
@@ -322,6 +323,7 @@
322
323
  "Kotlin": "#A97BFF",
323
324
  "LFE": "#4C3023",
324
325
  "LLVM": "#185619",
326
+ "LLVM TableGen": "#6E8B3D",
325
327
  "LOLCODE": "#cc9900",
326
328
  "LSL": "#3d9970",
327
329
  "LabVIEW": "#fede06",
@@ -3,6 +3,7 @@ import { GITHUB_USERNAME_PATTERN } from '../common/constants.ts';
3
3
  import { CardError, ORGANIZATION_NOT_FOUND } from '../common/error.ts';
4
4
  import { createGraphQLFetcher } from '../common/http.ts';
5
5
  import type { GraphQLResponse } from '../common/http.ts';
6
+ import { logger } from '../common/log.ts';
6
7
  import { retryer } from '../common/retryer.ts';
7
8
  import { GetOrganizationDocument } from '../graphql/generated/organization.ts';
8
9
  import type {
@@ -61,6 +62,19 @@ const topLanguage = (
61
62
  return top;
62
63
  };
63
64
 
65
+ /**
66
+ * The member count is the one field here a token can be refused:
67
+ * it needs the organization `Members` permission, which an app installation token rarely carries.
68
+ * GitHub answers `FORBIDDEN` on that field alone and still returns the organization,
69
+ * so the card drops the stat instead of failing whole.
70
+ *
71
+ * @returns Whether the member count is all the response was refused.
72
+ */
73
+ const onlyMembersForbidden = (
74
+ errors: NonNullable<GraphQLResponse<unknown>['data']['errors']>,
75
+ ): boolean =>
76
+ errors.every((error) => error.type === 'FORBIDDEN' && error.path?.at(-1) === 'membersWithRole');
77
+
64
78
  /**
65
79
  * Fetch an organization and the totals of its public repositories.
66
80
  *
@@ -88,6 +102,7 @@ const fetchOrganization = async (
88
102
  let organization: Organization | undefined;
89
103
  let after: string | null = null;
90
104
  let pages = 0;
105
+ let membersForbidden = false;
91
106
 
92
107
  do {
93
108
  // Annotated because the walk feeds its own cursor back in, which TypeScript reads as circular.
@@ -105,7 +120,11 @@ const fetchOrganization = async (
105
120
  secondaryMessage: ORGANIZATION_NOT_FOUND,
106
121
  });
107
122
  }
108
- throw graphqlError(res.data.errors, res.statusText, ORGANIZATION_ERROR);
123
+ if (!onlyMembersForbidden(res.data.errors)) {
124
+ throw graphqlError(res.data.errors, res.statusText, ORGANIZATION_ERROR);
125
+ }
126
+ logger.log(res.data.errors[0]?.message);
127
+ membersForbidden = true;
109
128
  }
110
129
 
111
130
  organization = res.data.data.organization ?? undefined;
@@ -144,7 +163,7 @@ const fetchOrganization = async (
144
163
  ? target.history.totalCount
145
164
  : 0;
146
165
  }),
147
- publicMembers: organization.membersWithRole.totalCount,
166
+ publicMembers: membersForbidden ? null : organization.membersWithRole.totalCount,
148
167
  topLanguage: topLanguage(repos),
149
168
  truncated: after !== null,
150
169
  };
@@ -61,8 +61,9 @@ export interface OrganizationData {
61
61
  /**
62
62
  * Members GitHub shows publicly.
63
63
  * Membership is private by default, so this counts fewer people than the organization has.
64
+ * `null` when the token may not read them, which is the card's cue to leave the stat out.
64
65
  */
65
- publicMembers: number;
66
+ publicMembers: number | null;
66
67
  /** The language most of those repositories name as their primary one, `null` when none do. */
67
68
  topLanguage: { name: string; color: string | null } | null;
68
69
  /** Whether the repository walk stopped at its page cap, leaving the totals short. */