@stats-forge/github-stats-forge-core 0.1.0 → 0.2.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.
Files changed (142) hide show
  1. package/build/api/contributed-to.d.ts +23 -0
  2. package/build/api/contributed-to.d.ts.map +1 -0
  3. package/build/api/contributed-to.js +43 -0
  4. package/build/api/gist.d.ts +8 -15
  5. package/build/api/gist.d.ts.map +1 -1
  6. package/build/api/gist.js +14 -29
  7. package/build/api/handler.d.ts +16 -0
  8. package/build/api/handler.d.ts.map +1 -0
  9. package/build/api/handler.js +29 -0
  10. package/build/api/index.d.ts +1 -0
  11. package/build/api/index.d.ts.map +1 -1
  12. package/build/api/index.js +1 -0
  13. package/build/api/params.d.ts +11 -5
  14. package/build/api/params.d.ts.map +1 -1
  15. package/build/api/params.js +26 -6
  16. package/build/api/pin.d.ts +11 -15
  17. package/build/api/pin.d.ts.map +1 -1
  18. package/build/api/pin.js +34 -46
  19. package/build/api/stats.d.ts +15 -22
  20. package/build/api/stats.d.ts.map +1 -1
  21. package/build/api/stats.js +59 -72
  22. package/build/api/top-langs.d.ts +11 -22
  23. package/build/api/top-langs.d.ts.map +1 -1
  24. package/build/api/top-langs.js +34 -51
  25. package/build/api/wakatime.d.ts +10 -24
  26. package/build/api/wakatime.d.ts.map +1 -1
  27. package/build/api/wakatime.js +27 -47
  28. package/build/cards/contributed-to.d.ts +19 -0
  29. package/build/cards/contributed-to.d.ts.map +1 -0
  30. package/build/cards/contributed-to.js +242 -0
  31. package/build/cards/gist.d.ts +1 -0
  32. package/build/cards/gist.d.ts.map +1 -1
  33. package/build/cards/gist.js +13 -9
  34. package/build/cards/repo.d.ts +12 -1
  35. package/build/cards/repo.d.ts.map +1 -1
  36. package/build/cards/repo.js +40 -18
  37. package/build/cards/stats.d.ts +15 -3
  38. package/build/cards/stats.d.ts.map +1 -1
  39. package/build/cards/stats.js +91 -76
  40. package/build/cards/top-languages.d.ts +13 -2
  41. package/build/cards/top-languages.d.ts.map +1 -1
  42. package/build/cards/top-languages.js +26 -9
  43. package/build/cards/wakatime.d.ts +13 -2
  44. package/build/cards/wakatime.d.ts.map +1 -1
  45. package/build/cards/wakatime.js +22 -9
  46. package/build/common/Card.d.ts +9 -0
  47. package/build/common/Card.d.ts.map +1 -1
  48. package/build/common/Card.js +44 -9
  49. package/build/common/I18n.d.ts +1 -1
  50. package/build/common/I18n.d.ts.map +1 -1
  51. package/build/common/I18n.js +4 -2
  52. package/build/common/brand.d.ts +76 -0
  53. package/build/common/brand.d.ts.map +1 -0
  54. package/build/common/brand.js +73 -0
  55. package/build/common/constants.d.ts +3 -1
  56. package/build/common/constants.d.ts.map +1 -1
  57. package/build/common/constants.js +3 -1
  58. package/build/common/date.d.ts +50 -3
  59. package/build/common/date.d.ts.map +1 -1
  60. package/build/common/date.js +104 -2
  61. package/build/common/icons.d.ts +4 -2
  62. package/build/common/icons.d.ts.map +1 -1
  63. package/build/common/icons.js +10 -5
  64. package/build/common/ops.d.ts +8 -3
  65. package/build/common/ops.d.ts.map +1 -1
  66. package/build/common/ops.js +8 -14
  67. package/build/common/render.d.ts +7 -1
  68. package/build/common/render.d.ts.map +1 -1
  69. package/build/common/render.js +60 -58
  70. package/build/fetchers/contributed-to.d.ts +62 -0
  71. package/build/fetchers/contributed-to.d.ts.map +1 -0
  72. package/build/fetchers/contributed-to.js +184 -0
  73. package/build/fetchers/graphql-error.d.ts +13 -0
  74. package/build/fetchers/graphql-error.d.ts.map +1 -0
  75. package/build/fetchers/graphql-error.js +29 -0
  76. package/build/fetchers/index.d.ts +2 -1
  77. package/build/fetchers/index.d.ts.map +1 -1
  78. package/build/fetchers/index.js +1 -0
  79. package/build/fetchers/stats.d.ts +14 -8
  80. package/build/fetchers/stats.d.ts.map +1 -1
  81. package/build/fetchers/stats.js +72 -195
  82. package/build/fetchers/top-languages.d.ts.map +1 -1
  83. package/build/fetchers/top-languages.js +3 -18
  84. package/build/fetchers/types.d.ts +24 -0
  85. package/build/fetchers/types.d.ts.map +1 -1
  86. package/build/graphql/contributionsCollection.d.ts +9 -0
  87. package/build/graphql/contributionsCollection.d.ts.map +1 -0
  88. package/build/graphql/contributionsCollection.js +12 -0
  89. package/build/graphql/contributionsDocument.d.ts +5 -5
  90. package/build/graphql/contributionsDocument.d.ts.map +1 -1
  91. package/build/graphql/contributionsDocument.js +8 -15
  92. package/build/graphql/generated/contributed-to.d.ts +22 -0
  93. package/build/graphql/generated/contributed-to.d.ts.map +1 -0
  94. package/build/graphql/generated/contributed-to.js +11 -0
  95. package/build/graphql/generated/stats.d.ts +13 -1
  96. package/build/graphql/generated/stats.d.ts.map +1 -1
  97. package/build/graphql/generated/stats.js +2 -2
  98. package/build/graphql/graphqlDocument.d.ts +1 -1
  99. package/build/graphql/reposContributedToDocument.d.ts.map +1 -1
  100. package/build/graphql/reposContributedToDocument.js +11 -5
  101. package/build/translations.d.ts +64 -1
  102. package/build/translations.d.ts.map +1 -1
  103. package/build/translations.js +65 -1
  104. package/package.json +1 -1
  105. package/src/api/contributed-to.ts +84 -0
  106. package/src/api/gist.ts +20 -37
  107. package/src/api/handler.ts +42 -0
  108. package/src/api/index.ts +1 -0
  109. package/src/api/params.ts +48 -9
  110. package/src/api/pin.ts +33 -45
  111. package/src/api/stats.ts +78 -89
  112. package/src/api/top-langs.ts +34 -56
  113. package/src/api/wakatime.ts +33 -54
  114. package/src/cards/contributed-to.ts +373 -0
  115. package/src/cards/gist.ts +17 -8
  116. package/src/cards/repo.ts +44 -20
  117. package/src/cards/stats.ts +119 -90
  118. package/src/cards/top-languages.ts +27 -18
  119. package/src/cards/wakatime.ts +23 -13
  120. package/src/common/Card.ts +56 -11
  121. package/src/common/I18n.ts +4 -2
  122. package/src/common/brand.ts +109 -0
  123. package/src/common/constants.ts +4 -1
  124. package/src/common/date.ts +135 -3
  125. package/src/common/icons.ts +10 -5
  126. package/src/common/ops.ts +10 -19
  127. package/src/common/render.ts +65 -62
  128. package/src/fetchers/contributed-to.ts +271 -0
  129. package/src/fetchers/graphql-error.ts +36 -0
  130. package/src/fetchers/index.ts +3 -0
  131. package/src/fetchers/stats.ts +123 -274
  132. package/src/fetchers/top-languages.ts +5 -19
  133. package/src/fetchers/types.ts +26 -0
  134. package/src/graphql/contributionsCollection.ts +18 -0
  135. package/src/graphql/contributionsDocument.ts +11 -18
  136. package/src/graphql/generated/contributed-to.ts +25 -0
  137. package/src/graphql/generated/stats.ts +19 -6
  138. package/src/graphql/graphqlDocument.ts +1 -1
  139. package/src/graphql/queries/contributed-to.graphql +8 -0
  140. package/src/graphql/queries/stats.graphql +14 -2
  141. package/src/graphql/reposContributedToDocument.ts +11 -9
  142. package/src/translations.ts +77 -0
@@ -1,6 +1,7 @@
1
- import { getGitHubYearRange, toGitHubDateTime } from '../common/date.ts';
1
+ import type { GitHubDateRange } from '../common/date.ts';
2
2
 
3
- import type { YearContributionsFragment } from './generated/stats.ts';
3
+ import { aliasedRanges } from './contributionsCollection.ts';
4
+ import type { RangeContributionsFragment } from './generated/stats.ts';
4
5
  import type { GraphQLDocument } from './graphqlDocument.ts';
5
6
  import { graphqlDocument } from './graphqlDocument.ts';
6
7
 
@@ -9,38 +10,30 @@ interface ContributionsQueryVariables {
9
10
  }
10
11
 
11
12
  interface ContributionsQuery {
12
- user: Record<`year_${number}`, YearContributionsFragment> | null;
13
+ user: Record<`range_${number}`, RangeContributionsFragment> | null;
13
14
  }
14
15
 
15
16
  /**
16
- * Build the all-time contributions query, one aliased `contributionsCollection` field per year.
17
- * The shape is only known at runtime.
17
+ * Build the contributions query for a set of ranges. The shape is only known at runtime.
18
18
  *
19
19
  * @returns Document for `createGraphQLFetcher`.
20
20
  */
21
21
  const buildContributionsDocument = (
22
- years: Array<number>,
23
- ): GraphQLDocument<ContributionsQuery, ContributionsQueryVariables> => {
24
- const yearFields = years
25
- .map((year) => {
26
- const { from, to } = getGitHubYearRange(year);
27
- return `year_${year}: contributionsCollection(from: "${toGitHubDateTime(from)}", to: "${toGitHubDateTime(to)}") { ...YearContributions }`;
28
- })
29
- .join('\n');
30
-
22
+ ranges: Array<GitHubDateRange>,
23
+ ): GraphQLDocument<ContributionsQuery, ContributionsQueryVariables> =>
31
24
  // fragment must match queries/stats.graphql, which generates its type
32
- return graphqlDocument<ContributionsQuery, ContributionsQueryVariables>(`
25
+ graphqlDocument<ContributionsQuery, ContributionsQueryVariables>(`
33
26
  query userContributions($login: String!) {
34
27
  user(login: $login) {
35
- ${yearFields}
28
+ ${aliasedRanges(ranges, 'RangeContributions')}
36
29
  }
37
30
  }
38
- fragment YearContributions on ContributionsCollection {
31
+ fragment RangeContributions on ContributionsCollection {
32
+ totalCommitContributions
39
33
  contributionCalendar {
40
34
  totalContributions
41
35
  }
42
36
  }`);
43
- };
44
37
 
45
38
  export { buildContributionsDocument };
46
39
  export type { ContributionsQuery };
@@ -0,0 +1,25 @@
1
+ // Generated file — see .github/CONTRIBUTING.md
2
+
3
+ /** Internal type. DO NOT USE DIRECTLY. */
4
+ type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
5
+ import { graphqlDocument } from '../graphqlDocument.ts';
6
+ export type UserContributionYearsQueryVariables = Exact<{
7
+ login: string;
8
+ }>;
9
+
10
+ export type UserContributionYearsQuery = {
11
+ user: { login: string; contributionsCollection: { contributionYears: Array<number> } } | null;
12
+ };
13
+
14
+ export const UserContributionYearsDocument = graphqlDocument<
15
+ UserContributionYearsQuery,
16
+ UserContributionYearsQueryVariables
17
+ >(`
18
+ query userContributionYears($login: String!) {
19
+ user(login: $login) {
20
+ login
21
+ contributionsCollection {
22
+ contributionYears
23
+ }
24
+ }
25
+ }`);
@@ -42,6 +42,7 @@ export type UserInfoQueryVariables = Exact<{
42
42
  includeDiscussions: boolean;
43
43
  includeDiscussionsAnswers: boolean;
44
44
  startTime?: string | null | undefined;
45
+ endTime?: string | null | undefined;
45
46
  ownerAffiliations?:
46
47
  | Array<Types.RepositoryAffiliation | null | undefined>
47
48
  | Types.RepositoryAffiliation
@@ -73,12 +74,24 @@ export type UserInfoQuery = {
73
74
  } | null;
74
75
  };
75
76
 
76
- export type YearContributionsFragment = { contributionCalendar: { totalContributions: number } };
77
+ export type RangeContributionsFragment = {
78
+ totalCommitContributions: number;
79
+ contributionCalendar: { totalContributions: number };
80
+ };
77
81
 
78
82
  export type RangeContributionsByRepoFragment = {
79
- commitContributionsByRepository: Array<{ repository: { nameWithOwner: string } }>;
80
- issueContributionsByRepository: Array<{ repository: { nameWithOwner: string } }>;
81
- pullRequestContributionsByRepository: Array<{ repository: { nameWithOwner: string } }>;
83
+ commitContributionsByRepository: Array<{
84
+ repository: { nameWithOwner: string };
85
+ contributions: { totalCount: number };
86
+ }>;
87
+ issueContributionsByRepository: Array<{
88
+ repository: { nameWithOwner: string };
89
+ contributions: { totalCount: number };
90
+ }>;
91
+ pullRequestContributionsByRepository: Array<{
92
+ repository: { nameWithOwner: string };
93
+ contributions: { totalCount: number };
94
+ }>;
82
95
  repositoryContributions?: {
83
96
  nodes: Array<{ repository: { nameWithOwner: string } } | null> | null;
84
97
  };
@@ -113,11 +126,11 @@ fragment RepoNode on Repository {
113
126
  }`);
114
127
 
115
128
  export const UserInfoDocument = graphqlDocument<UserInfoQuery, UserInfoQueryVariables>(`
116
- query userInfo($login: String!, $after: String, $includeMergedPullRequests: Boolean!, $includeDiscussions: Boolean!, $includeDiscussionsAnswers: Boolean!, $startTime: DateTime = null, $ownerAffiliations: [RepositoryAffiliation], $includeUserRepositories: Boolean!) {
129
+ query userInfo($login: String!, $after: String, $includeMergedPullRequests: Boolean!, $includeDiscussions: Boolean!, $includeDiscussionsAnswers: Boolean!, $startTime: DateTime = null, $endTime: DateTime = null, $ownerAffiliations: [RepositoryAffiliation], $includeUserRepositories: Boolean!) {
117
130
  user(login: $login) {
118
131
  name
119
132
  login
120
- commits: contributionsCollection(from: $startTime) {
133
+ commits: contributionsCollection(from: $startTime, to: $endTime) {
121
134
  totalCommitContributions
122
135
  }
123
136
  reviews: contributionsCollection {
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * `text` is what goes over the wire; the other two members only carry types and are never assigned.
5
5
  * Documents are generated from `queries/*.graphql`
6
- * See `scripts/generate-graphql-types.js`.
6
+ * See `scripts/generate-graphql-types.ts`.
7
7
  */
8
8
  interface GraphQLDocument<TResult, TVariables> {
9
9
  readonly text: string;
@@ -0,0 +1,8 @@
1
+ query userContributionYears($login: String!) {
2
+ user(login: $login) {
3
+ login
4
+ contributionsCollection {
5
+ contributionYears
6
+ }
7
+ }
8
+ }
@@ -34,13 +34,14 @@ query userInfo(
34
34
  $includeDiscussions: Boolean!
35
35
  $includeDiscussionsAnswers: Boolean!
36
36
  $startTime: DateTime = null
37
+ $endTime: DateTime = null
37
38
  $ownerAffiliations: [RepositoryAffiliation]
38
39
  $includeUserRepositories: Boolean!
39
40
  ) {
40
41
  user(login: $login) {
41
42
  name
42
43
  login
43
- commits: contributionsCollection(from: $startTime) {
44
+ commits: contributionsCollection(from: $startTime, to: $endTime) {
44
45
  totalCommitContributions
45
46
  }
46
47
  reviews: contributionsCollection {
@@ -81,27 +82,38 @@ query userInfo(
81
82
  }
82
83
  }
83
84
 
84
- fragment YearContributions on ContributionsCollection {
85
+ fragment RangeContributions on ContributionsCollection {
86
+ totalCommitContributions
85
87
  contributionCalendar {
86
88
  totalContributions
87
89
  }
88
90
  }
89
91
 
92
+ # `contributions` takes no slicing argument on purpose: `totalCount` alone costs no nodes.
90
93
  fragment RangeContributionsByRepo on ContributionsCollection {
91
94
  commitContributionsByRepository(maxRepositories: $maxRepositories) {
92
95
  repository {
93
96
  nameWithOwner
94
97
  }
98
+ contributions {
99
+ totalCount
100
+ }
95
101
  }
96
102
  issueContributionsByRepository(maxRepositories: $maxRepositories) {
97
103
  repository {
98
104
  nameWithOwner
99
105
  }
106
+ contributions {
107
+ totalCount
108
+ }
100
109
  }
101
110
  pullRequestContributionsByRepository(maxRepositories: $maxRepositories) {
102
111
  repository {
103
112
  nameWithOwner
104
113
  }
114
+ contributions {
115
+ totalCount
116
+ }
105
117
  }
106
118
  repositoryContributions(first: $maxRepositories) @include(if: $includeOwnRepos) {
107
119
  nodes {
@@ -1,6 +1,6 @@
1
1
  import type { GitHubDateRange } from '../common/date.ts';
2
- import { toGitHubDateTime } from '../common/date.ts';
3
2
 
3
+ import { aliasedRanges } from './contributionsCollection.ts';
4
4
  import type { RangeContributionsByRepoFragment } from './generated/stats.ts';
5
5
  import type { GraphQLDocument } from './graphqlDocument.ts';
6
6
  import { graphqlDocument } from './graphqlDocument.ts';
@@ -31,13 +31,6 @@ const buildReposContributedToDocument = (
31
31
  ranges: Array<GitHubDateRange>,
32
32
  includeOwnRepos: boolean,
33
33
  ): GraphQLDocument<ReposContributedToQuery, ReposContributedToQueryVariables> => {
34
- const rangeFields = ranges
35
- .map(
36
- ({ from, to }, index) =>
37
- `range_${index}: contributionsCollection(from: "${toGitHubDateTime(from)}", to: "${toGitHubDateTime(to)}") { ...RangeContributionsByRepo }`,
38
- )
39
- .join('\n');
40
-
41
34
  // `repositoryContributions` only ever returns repos the user owns,
42
35
  // so it is left out rather than gated with @include: an excluded field still counts toward the query's node cost.
43
36
  // stats.graphql carries the directive so the generated type marks the field optional.
@@ -55,7 +48,7 @@ const buildReposContributedToDocument = (
55
48
  return graphqlDocument<ReposContributedToQuery, ReposContributedToQueryVariables>(`
56
49
  query userReposContributedTo($login: String!, $maxRepositories: Int!) {
57
50
  user(login: $login) {
58
- ${rangeFields}
51
+ ${aliasedRanges(ranges, 'RangeContributionsByRepo')}
59
52
  }
60
53
  }
61
54
  fragment RangeContributionsByRepo on ContributionsCollection {
@@ -63,16 +56,25 @@ fragment RangeContributionsByRepo on ContributionsCollection {
63
56
  repository {
64
57
  nameWithOwner
65
58
  }
59
+ contributions {
60
+ totalCount
61
+ }
66
62
  }
67
63
  issueContributionsByRepository(maxRepositories: $maxRepositories) {
68
64
  repository {
69
65
  nameWithOwner
70
66
  }
67
+ contributions {
68
+ totalCount
69
+ }
71
70
  }
72
71
  pullRequestContributionsByRepository(maxRepositories: $maxRepositories) {
73
72
  repository {
74
73
  nameWithOwner
75
74
  }
75
+ contributions {
76
+ totalCount
77
+ }
76
78
  }
77
79
  ${ownRepoField}
78
80
  }`);
@@ -355,6 +355,9 @@ const statCardLocales = ({ name, apostrophe }: { name: string; apostrophe: strin
355
355
  'statcard.all-time-contribs': {
356
356
  en: 'Contributed to (all time)',
357
357
  },
358
+ 'statcard.rank': {
359
+ en: 'Rank',
360
+ },
358
361
  'statcard.reviews': {
359
362
  en: 'Total PRs Reviewed',
360
363
  ar: 'طلبات السحب التي تم مراجعتها',
@@ -625,6 +628,12 @@ const statCardLocales = ({ name, apostrophe }: { name: string; apostrophe: strin
625
628
  });
626
629
 
627
630
  const repoCardLocales = {
631
+ 'repocard.no-description': {
632
+ en: 'No description provided',
633
+ },
634
+ 'repocard.unspecified-language': {
635
+ en: 'Unspecified',
636
+ },
628
637
  'repocard.template': {
629
638
  en: 'Template',
630
639
  ar: 'قالب',
@@ -1143,6 +1152,72 @@ const wakatimeCardLocales = {
1143
1152
  },
1144
1153
  };
1145
1154
 
1155
+ const gistCardLocales = {
1156
+ 'gistcard.no-description': {
1157
+ en: 'No description provided',
1158
+ },
1159
+ 'gistcard.unspecified-language': {
1160
+ en: 'Unspecified',
1161
+ },
1162
+ 'gistcard.language': {
1163
+ en: 'Language',
1164
+ },
1165
+ 'gistcard.stars': {
1166
+ en: 'Stars',
1167
+ },
1168
+ 'gistcard.forks': {
1169
+ en: 'Forks',
1170
+ },
1171
+ };
1172
+
1173
+ /** The values the contributed-to card's strings interpolate. */
1174
+ interface ContributedToValues {
1175
+ login: string;
1176
+ /** How many repositories the card draws, which is at most `totalRepos`. */
1177
+ shown: number;
1178
+ totalRepos: number;
1179
+ }
1180
+
1181
+ /**
1182
+ * Retrieves contributed-to card labels in the available locales.
1183
+ *
1184
+ * @see https://www.andiamo.co.uk/resources/iso-language-codes/ for language codes.
1185
+ *
1186
+ * @returns The locales object.
1187
+ */
1188
+ // The literal key union is what `I18n#t` checks a card's `t('…')` call against, so the
1189
+ // return type is left to inference.
1190
+ // oxlint-disable-next-line typescript/explicit-function-return-type, typescript/explicit-module-boundary-types
1191
+ const contributedToCardLocales = ({ login, shown, totalRepos }: ContributedToValues) => {
1192
+ // English's own plural rule; another locale picks its wording inside its own entry.
1193
+ const repoWord = totalRepos === 1 ? 'repository' : 'repositories';
1194
+
1195
+ return {
1196
+ 'contributedtocard.title': {
1197
+ en: `Repositories ${login} contributed to`,
1198
+ },
1199
+ // Drawn instead of the title above when naming the account overruns the card.
1200
+ 'contributedtocard.title-unnamed': {
1201
+ en: 'Repositories contributed to',
1202
+ },
1203
+ 'contributedtocard.no-contributions': {
1204
+ en: 'No contributions found',
1205
+ },
1206
+ 'contributedtocard.footer-all': {
1207
+ en: `${totalRepos} ${repoWord}`,
1208
+ },
1209
+ 'contributedtocard.footer-top': {
1210
+ en: `top ${shown} of ${totalRepos} ${repoWord}`,
1211
+ },
1212
+ 'contributedtocard.contributions': {
1213
+ en: 'contributions',
1214
+ },
1215
+ 'contributedtocard.years': {
1216
+ en: 'years',
1217
+ },
1218
+ };
1219
+ };
1220
+
1146
1221
  const availableLocales = Object.keys(repoCardLocales['repocard.archived']);
1147
1222
 
1148
1223
  /**
@@ -1154,6 +1229,8 @@ const isLocaleAvailable = (locale: string): boolean =>
1154
1229
  availableLocales.includes(locale.toLowerCase());
1155
1230
 
1156
1231
  export {
1232
+ contributedToCardLocales,
1233
+ gistCardLocales,
1157
1234
  isLocaleAvailable,
1158
1235
  langCardLocales,
1159
1236
  repoCardLocales,