@backstage/plugin-catalog-backend-module-github 0.11.2-next.0 → 0.11.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # @backstage/plugin-catalog-backend-module-github
2
2
 
3
+ ## 0.11.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 999d1c1: Added configurable `pageSizes` for GitHub GraphQL API queries to prevent `RESOURCE_LIMITS_EXCEEDED` errors with organizations with large number of repositories. Please see the [GitHub Discovery documentation](https://backstage.io/docs/integrations/github/discovery#configuration) for new configuration options.
8
+ - Updated dependencies
9
+ - @backstage/plugin-catalog-node@1.20.0
10
+ - @backstage/integration@1.18.2
11
+ - @backstage/backend-plugin-api@1.5.0
12
+ - @backstage/plugin-events-node@0.4.17
13
+ - @backstage/config@1.3.6
14
+ - @backstage/catalog-model@1.7.6
15
+ - @backstage/plugin-catalog-common@1.1.7
16
+
17
+ ## 0.11.2-next.1
18
+
19
+ ### Patch Changes
20
+
21
+ - 999d1c1: Added configurable `pageSizes` for GitHub GraphQL API queries to prevent `RESOURCE_LIMITS_EXCEEDED` errors with organizations with large number of repositories. Please see the [GitHub Discovery documentation](https://backstage.io/docs/integrations/github/discovery#configuration) for new configuration options.
22
+ - Updated dependencies
23
+ - @backstage/plugin-catalog-node@1.20.0-next.1
24
+ - @backstage/backend-plugin-api@1.5.0-next.1
25
+ - @backstage/plugin-events-node@0.4.17-next.1
26
+
3
27
  ## 0.11.2-next.0
4
28
 
5
29
  ### Patch Changes
package/config.d.ts CHANGED
@@ -131,6 +131,18 @@ export interface Config {
131
131
  * (Optional) TaskScheduleDefinition for the refresh.
132
132
  */
133
133
  schedule?: SchedulerServiceTaskScheduleDefinitionConfig;
134
+
135
+ /**
136
+ * (Optional) Page sizes for GitHub GraphQL API queries.
137
+ * Reduce these values if hitting RESOURCE_LIMITS_EXCEEDED errors.
138
+ */
139
+ pageSizes?: {
140
+ /**
141
+ * (Optional) Number of repositories to fetch per page when querying repositories.
142
+ * Default: `25`.
143
+ */
144
+ repositories?: number;
145
+ };
134
146
  }
135
147
  | {
136
148
  [name: string]: {
@@ -209,6 +221,18 @@ export interface Config {
209
221
  * (Optional) TaskScheduleDefinition for the refresh.
210
222
  */
211
223
  schedule?: SchedulerServiceTaskScheduleDefinitionConfig;
224
+
225
+ /**
226
+ * (Optional) Page sizes for GitHub GraphQL API queries.
227
+ * Reduce these values if hitting RESOURCE_LIMITS_EXCEEDED errors.
228
+ */
229
+ pageSizes?: {
230
+ /**
231
+ * (Optional) Number of repositories to fetch per page when querying repositories.
232
+ * Default: `25`.
233
+ */
234
+ repositories?: number;
235
+ };
212
236
  };
213
237
  };
214
238
 
@@ -244,6 +268,28 @@ export interface Config {
244
268
  * The refresh schedule to use.
245
269
  */
246
270
  schedule: SchedulerServiceTaskScheduleDefinitionConfig;
271
+
272
+ /**
273
+ * (Optional) Page sizes for GitHub GraphQL API queries.
274
+ * Reduce these values if hitting RESOURCE_LIMITS_EXCEEDED errors.
275
+ */
276
+ pageSizes?: {
277
+ /**
278
+ * (Optional) Number of teams to fetch per page when querying organization teams.
279
+ * Default: `25`.
280
+ */
281
+ teams?: number;
282
+ /**
283
+ * (Optional) Number of team members to fetch per page when querying team members.
284
+ * Default: `50`.
285
+ */
286
+ teamMembers?: number;
287
+ /**
288
+ * (Optional) Number of organization members to fetch per page when querying org members.
289
+ * Default: `50`.
290
+ */
291
+ organizationMembers?: number;
292
+ };
247
293
  }
248
294
  | Array<{
249
295
  /**
@@ -273,6 +319,28 @@ export interface Config {
273
319
  * The refresh schedule to use.
274
320
  */
275
321
  schedule: SchedulerServiceTaskScheduleDefinitionConfig;
322
+
323
+ /**
324
+ * (Optional) Page sizes for GitHub GraphQL API queries.
325
+ * Reduce these values if hitting RESOURCE_LIMITS_EXCEEDED errors.
326
+ */
327
+ pageSizes?: {
328
+ /**
329
+ * (Optional) Number of teams to fetch per page when querying organization teams.
330
+ * Default: `25`.
331
+ */
332
+ teams?: number;
333
+ /**
334
+ * (Optional) Number of team members to fetch per page when querying team members.
335
+ * Default: `50`.
336
+ */
337
+ teamMembers?: number;
338
+ /**
339
+ * (Optional) Number of organization members to fetch per page when querying org members.
340
+ * Default: `50`.
341
+ */
342
+ organizationMembers?: number;
343
+ };
276
344
  }>;
277
345
  };
278
346
  };
package/dist/index.d.ts CHANGED
@@ -129,6 +129,33 @@ declare const defaultUserTransformer: (item: GithubUser, _ctx: TransformerContex
129
129
  */
130
130
  declare const defaultOrganizationTeamTransformer: TeamTransformer;
131
131
 
132
+ /**
133
+ * Configuration for GitHub GraphQL API page sizes.
134
+ *
135
+ * @public
136
+ */
137
+ type GithubPageSizes = {
138
+ /**
139
+ * Number of teams to fetch per page when querying organization teams.
140
+ * Default: 25
141
+ */
142
+ teams: number;
143
+ /**
144
+ * Number of team members to fetch per page when querying team members.
145
+ * Default: 50
146
+ */
147
+ teamMembers: number;
148
+ /**
149
+ * Number of organization members to fetch per page when querying org members.
150
+ * Default: 50
151
+ */
152
+ organizationMembers: number;
153
+ /**
154
+ * Number of repositories to fetch per page when querying repositories.
155
+ * Default: 25
156
+ */
157
+ repositories: number;
158
+ };
132
159
  /**
133
160
  * Github User
134
161
  *
@@ -388,6 +415,11 @@ interface GithubMultiOrgEntityProviderOptions {
388
415
  * By default, groups will be namespaced according to their GitHub org.
389
416
  */
390
417
  teamTransformer?: TeamTransformer;
418
+ /**
419
+ * Optionally configure page sizes for GitHub GraphQL API queries.
420
+ * Reduce these values if hitting RESOURCE_LIMITS_EXCEEDED errors.
421
+ */
422
+ pageSizes?: Partial<GithubPageSizes>;
391
423
  }
392
424
  /**
393
425
  * Ingests org data (users and groups) from GitHub.
@@ -410,9 +442,11 @@ declare class GithubMultiOrgEntityProvider implements EntityProvider {
410
442
  userTransformer?: UserTransformer;
411
443
  teamTransformer?: TeamTransformer;
412
444
  alwaysUseDefaultNamespace?: boolean;
445
+ pageSizes?: Partial<GithubPageSizes>;
413
446
  });
414
447
  /** {@inheritdoc @backstage/plugin-catalog-node#EntityProvider.getProviderName} */
415
448
  getProviderName(): string;
449
+ private getPageSizes;
416
450
  /** {@inheritdoc @backstage/plugin-catalog-node#EntityProvider.connect} */
417
451
  connect(connection: EntityProviderConnection): Promise<void>;
418
452
  /**
@@ -557,4 +591,4 @@ declare class GitHubEntityProvider implements EntityProvider {
557
591
  refresh(logger: LoggerService): Promise<void>;
558
592
  }
559
593
 
560
- export { GitHubEntityProvider, GitHubOrgEntityProvider, type GitHubOrgEntityProviderOptions, GithubDiscoveryProcessor, GithubEntityProvider, GithubLocationAnalyzer, type GithubLocationAnalyzerOptions, type GithubMultiOrgConfig, GithubMultiOrgEntityProvider, type GithubMultiOrgEntityProviderOptions, GithubMultiOrgReaderProcessor, GithubOrgEntityProvider, type GithubOrgEntityProviderOptions, GithubOrgReaderProcessor, type GithubTeam, type GithubUser, type TeamTransformer, type TransformerContext, type UserTransformer, githubCatalogModule as default, defaultOrganizationTeamTransformer, defaultUserTransformer };
594
+ export { GitHubEntityProvider, GitHubOrgEntityProvider, type GitHubOrgEntityProviderOptions, GithubDiscoveryProcessor, GithubEntityProvider, GithubLocationAnalyzer, type GithubLocationAnalyzerOptions, type GithubMultiOrgConfig, GithubMultiOrgEntityProvider, type GithubMultiOrgEntityProviderOptions, GithubMultiOrgReaderProcessor, GithubOrgEntityProvider, type GithubOrgEntityProviderOptions, GithubOrgReaderProcessor, type GithubPageSizes, type GithubTeam, type GithubUser, type TeamTransformer, type TransformerContext, type UserTransformer, githubCatalogModule as default, defaultOrganizationTeamTransformer, defaultUserTransformer };
@@ -5,11 +5,17 @@ var withLocations = require('./withLocations.cjs.js');
5
5
  var core = require('@octokit/core');
6
6
  var pluginThrottling = require('@octokit/plugin-throttling');
7
7
 
8
- async function getOrganizationUsers(client, org, tokenType, userTransformer = defaultTransformers.defaultUserTransformer) {
8
+ const DEFAULT_PAGE_SIZES = {
9
+ teams: 25,
10
+ teamMembers: 50,
11
+ organizationMembers: 50,
12
+ repositories: 25
13
+ };
14
+ async function getOrganizationUsers(client, org, tokenType, userTransformer = defaultTransformers.defaultUserTransformer, pageSizes = DEFAULT_PAGE_SIZES) {
9
15
  const query = `
10
- query users($org: String!, $email: Boolean!, $cursor: String) {
16
+ query users($org: String!, $email: Boolean!, $cursor: String, $organizationMembersPageSize: Int!) {
11
17
  organization(login: $org) {
12
- membersWithRole(first: 100, after: $cursor) {
18
+ membersWithRole(first: $organizationMembersPageSize, after: $cursor) {
13
19
  pageInfo { hasNextPage, endCursor }
14
20
  nodes {
15
21
  avatarUrl,
@@ -30,16 +36,17 @@ async function getOrganizationUsers(client, org, tokenType, userTransformer = de
30
36
  userTransformer,
31
37
  {
32
38
  org,
33
- email: tokenType === "token"
39
+ email: tokenType === "token",
40
+ organizationMembersPageSize: pageSizes.organizationMembers
34
41
  }
35
42
  );
36
43
  return { users };
37
44
  }
38
- async function getOrganizationTeams(client, org, teamTransformer = defaultTransformers.defaultOrganizationTeamTransformer) {
45
+ async function getOrganizationTeams(client, org, teamTransformer = defaultTransformers.defaultOrganizationTeamTransformer, pageSizes = DEFAULT_PAGE_SIZES) {
39
46
  const query = `
40
- query teams($org: String!, $cursor: String) {
47
+ query teams($org: String!, $cursor: String, $teamsPageSize: Int!, $membersPageSize: Int!) {
41
48
  organization(login: $org) {
42
- teams(first: 50, after: $cursor) {
49
+ teams(first: $teamsPageSize, after: $cursor) {
43
50
  pageInfo { hasNextPage, endCursor }
44
51
  nodes {
45
52
  slug
@@ -49,7 +56,7 @@ async function getOrganizationTeams(client, org, teamTransformer = defaultTransf
49
56
  avatarUrl
50
57
  editTeamUrl
51
58
  parentTeam { slug }
52
- members(first: 100, membership: IMMEDIATE) {
59
+ members(first: $membersPageSize, membership: IMMEDIATE) {
53
60
  pageInfo { hasNextPage }
54
61
  nodes {
55
62
  avatarUrl,
@@ -71,7 +78,12 @@ async function getOrganizationTeams(client, org, teamTransformer = defaultTransf
71
78
  memberNames.push(user);
72
79
  }
73
80
  } else {
74
- const { members } = await getTeamMembers(ctx.client, ctx.org, item.slug);
81
+ const { members } = await getTeamMembers(
82
+ ctx.client,
83
+ ctx.org,
84
+ item.slug,
85
+ pageSizes
86
+ );
75
87
  for (const userLogin of members) {
76
88
  memberNames.push(userLogin);
77
89
  }
@@ -88,15 +100,19 @@ async function getOrganizationTeams(client, org, teamTransformer = defaultTransf
88
100
  org,
89
101
  (r) => r.organization?.teams,
90
102
  materialisedTeams,
91
- { org }
103
+ {
104
+ org,
105
+ teamsPageSize: pageSizes.teams,
106
+ membersPageSize: pageSizes.teamMembers
107
+ }
92
108
  );
93
109
  return { teams };
94
110
  }
95
- async function getOrganizationTeamsFromUsers(client, org, userLogins, teamTransformer = defaultTransformers.defaultOrganizationTeamTransformer) {
111
+ async function getOrganizationTeamsFromUsers(client, org, userLogins, teamTransformer = defaultTransformers.defaultOrganizationTeamTransformer, pageSizes = DEFAULT_PAGE_SIZES) {
96
112
  const query = `
97
- query teams($org: String!, $cursor: String, $userLogins: [String!] = "") {
113
+ query teams($org: String!, $cursor: String, $userLogins: [String!] = "", $teamsPageSize: Int!, $membersPageSize: Int!) {
98
114
  organization(login: $org) {
99
- teams(first: 100, after: $cursor, userLogins: $userLogins) {
115
+ teams(first: $teamsPageSize, after: $cursor, userLogins: $userLogins) {
100
116
  pageInfo {
101
117
  hasNextPage
102
118
  endCursor
@@ -111,7 +127,7 @@ async function getOrganizationTeamsFromUsers(client, org, userLogins, teamTransf
111
127
  parentTeam {
112
128
  slug
113
129
  }
114
- members(first: 100, membership: IMMEDIATE) {
130
+ members(first: $membersPageSize, membership: IMMEDIATE) {
115
131
  pageInfo {
116
132
  hasNextPage
117
133
  }
@@ -135,7 +151,12 @@ async function getOrganizationTeamsFromUsers(client, org, userLogins, teamTransf
135
151
  memberNames.push(user);
136
152
  }
137
153
  } else {
138
- const { members } = await getTeamMembers(ctx.client, ctx.org, item.slug);
154
+ const { members } = await getTeamMembers(
155
+ ctx.client,
156
+ ctx.org,
157
+ item.slug,
158
+ pageSizes
159
+ );
139
160
  for (const userLogin of members) {
140
161
  memberNames.push(userLogin);
141
162
  }
@@ -152,15 +173,20 @@ async function getOrganizationTeamsFromUsers(client, org, userLogins, teamTransf
152
173
  org,
153
174
  (r) => r.organization?.teams,
154
175
  materialisedTeams,
155
- { org, userLogins }
176
+ {
177
+ org,
178
+ userLogins,
179
+ teamsPageSize: pageSizes.teams,
180
+ membersPageSize: pageSizes.teamMembers
181
+ }
156
182
  );
157
183
  return { teams };
158
184
  }
159
- async function getOrganizationTeamsForUser(client, org, userLogin, teamTransformer) {
185
+ async function getOrganizationTeamsForUser(client, org, userLogin, teamTransformer, pageSizes = DEFAULT_PAGE_SIZES) {
160
186
  const query = `
161
- query teams($org: String!, $cursor: String, $userLogins: [String!] = "") {
187
+ query teams($org: String!, $cursor: String, $userLogins: [String!] = "", $teamsPageSize: Int!) {
162
188
  organization(login: $org) {
163
- teams(first: 100, after: $cursor, userLogins: $userLogins) {
189
+ teams(first: $teamsPageSize, after: $cursor, userLogins: $userLogins) {
164
190
  pageInfo {
165
191
  hasNextPage
166
192
  endCursor
@@ -192,7 +218,7 @@ async function getOrganizationTeamsForUser(client, org, userLogin, teamTransform
192
218
  org,
193
219
  (r) => r.organization?.teams,
194
220
  materialisedTeams,
195
- { org, userLogins: [userLogin] }
221
+ { org, userLogins: [userLogin], teamsPageSize: pageSizes.teams }
196
222
  );
197
223
  return { teams };
198
224
  }
@@ -216,9 +242,9 @@ async function getOrganizationsFromUser(client, user) {
216
242
  );
217
243
  return { orgs };
218
244
  }
219
- async function getOrganizationTeam(client, org, teamSlug, teamTransformer = defaultTransformers.defaultOrganizationTeamTransformer) {
245
+ async function getOrganizationTeam(client, org, teamSlug, teamTransformer = defaultTransformers.defaultOrganizationTeamTransformer, pageSizes = DEFAULT_PAGE_SIZES) {
220
246
  const query = `
221
- query teams($org: String!, $teamSlug: String!) {
247
+ query teams($org: String!, $teamSlug: String!, $membersPageSize: Int!) {
222
248
  organization(login: $org) {
223
249
  team(slug:$teamSlug) {
224
250
  slug
@@ -228,7 +254,7 @@ async function getOrganizationTeam(client, org, teamSlug, teamTransformer = defa
228
254
  avatarUrl
229
255
  editTeamUrl
230
256
  parentTeam { slug }
231
- members(first: 100, membership: IMMEDIATE) {
257
+ members(first: $membersPageSize, membership: IMMEDIATE) {
232
258
  pageInfo { hasNextPage }
233
259
  nodes { login }
234
260
  }
@@ -242,7 +268,12 @@ async function getOrganizationTeam(client, org, teamSlug, teamTransformer = defa
242
268
  memberNames.push(user);
243
269
  }
244
270
  } else {
245
- const { members } = await getTeamMembers(ctx.client, ctx.org, item.slug);
271
+ const { members } = await getTeamMembers(
272
+ ctx.client,
273
+ ctx.org,
274
+ item.slug,
275
+ pageSizes
276
+ );
246
277
  for (const userLogin of members) {
247
278
  memberNames.push(userLogin);
248
279
  }
@@ -255,7 +286,8 @@ async function getOrganizationTeam(client, org, teamSlug, teamTransformer = defa
255
286
  };
256
287
  const response = await client(query, {
257
288
  org,
258
- teamSlug
289
+ teamSlug,
290
+ membersPageSize: pageSizes.teamMembers
259
291
  });
260
292
  if (!response.organization?.team)
261
293
  throw new Error(`Found no match for team ${teamSlug}`);
@@ -267,7 +299,7 @@ async function getOrganizationTeam(client, org, teamSlug, teamTransformer = defa
267
299
  if (!team) throw new Error(`Can't transform for team ${teamSlug}`);
268
300
  return { team };
269
301
  }
270
- async function getOrganizationRepositories(client, org, catalogPath) {
302
+ async function getOrganizationRepositories(client, org, catalogPath, pageSizes = DEFAULT_PAGE_SIZES) {
271
303
  let relativeCatalogPathRef;
272
304
  if (catalogPath.startsWith("/")) {
273
305
  relativeCatalogPathRef = catalogPath.substring(1);
@@ -276,10 +308,10 @@ async function getOrganizationRepositories(client, org, catalogPath) {
276
308
  }
277
309
  const catalogPathRef = `HEAD:${relativeCatalogPathRef}`;
278
310
  const query = `
279
- query repositories($org: String!, $catalogPathRef: String!, $cursor: String) {
311
+ query repositories($org: String!, $catalogPathRef: String!, $cursor: String, $repositoriesPageSize: Int!) {
280
312
  repositoryOwner(login: $org) {
281
313
  login
282
- repositories(first: 50, after: $cursor) {
314
+ repositories(first: $repositoriesPageSize, after: $cursor) {
283
315
  nodes {
284
316
  name
285
317
  catalogInfoFile: object(expression: $catalogPathRef) {
@@ -319,7 +351,7 @@ async function getOrganizationRepositories(client, org, catalogPath) {
319
351
  org,
320
352
  (r) => r.repositoryOwner?.repositories,
321
353
  async (x) => x,
322
- { org, catalogPathRef }
354
+ { org, catalogPathRef, repositoriesPageSize: pageSizes.repositories }
323
355
  );
324
356
  return { repositories };
325
357
  }
@@ -369,12 +401,12 @@ async function getOrganizationRepository(client, org, repoName, catalogPath) {
369
401
  });
370
402
  return response.repositoryOwner?.repository || null;
371
403
  }
372
- async function getTeamMembers(client, org, teamSlug) {
404
+ async function getTeamMembers(client, org, teamSlug, pageSizes = DEFAULT_PAGE_SIZES) {
373
405
  const query = `
374
- query members($org: String!, $teamSlug: String!, $cursor: String) {
406
+ query members($org: String!, $teamSlug: String!, $cursor: String, $membersPageSize: Int!) {
375
407
  organization(login: $org) {
376
408
  team(slug: $teamSlug) {
377
- members(first: 100, after: $cursor, membership: IMMEDIATE) {
409
+ members(first: $membersPageSize, after: $cursor, membership: IMMEDIATE) {
378
410
  pageInfo { hasNextPage, endCursor }
379
411
  nodes { login }
380
412
  }
@@ -387,7 +419,7 @@ async function getTeamMembers(client, org, teamSlug) {
387
419
  org,
388
420
  (r) => r.organization?.team?.members,
389
421
  async (user) => user,
390
- { org, teamSlug }
422
+ { org, teamSlug, membersPageSize: pageSizes.teamMembers }
391
423
  );
392
424
  return { members };
393
425
  }
@@ -485,6 +517,7 @@ const createGraphqlClient = (args) => {
485
517
  return client;
486
518
  };
487
519
 
520
+ exports.DEFAULT_PAGE_SIZES = DEFAULT_PAGE_SIZES;
488
521
  exports.createAddEntitiesOperation = createAddEntitiesOperation;
489
522
  exports.createGraphqlClient = createGraphqlClient;
490
523
  exports.createRemoveEntitiesOperation = createRemoveEntitiesOperation;
@@ -1 +1 @@
1
- {"version":3,"file":"github.cjs.js","sources":["../../src/lib/github.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport { GithubCredentialType } from '@backstage/integration';\nimport { graphql } from '@octokit/graphql';\nimport {\n defaultOrganizationTeamTransformer,\n defaultUserTransformer,\n TeamTransformer,\n TransformerContext,\n UserTransformer,\n} from './defaultTransformers';\nimport { withLocations } from './withLocations';\n\nimport { DeferredEntity } from '@backstage/plugin-catalog-node';\nimport { Octokit } from '@octokit/core';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { throttling } from '@octokit/plugin-throttling';\n// Graphql types\n\nexport type QueryResponse = {\n organization?: OrganizationResponse;\n repositoryOwner?: RepositoryOwnerResponse;\n user?: UserResponse;\n};\n\ntype RepositoryOwnerResponse = {\n repositories?: Connection<RepositoryResponse>;\n repository?: RepositoryResponse;\n};\n\nexport type OrganizationResponse = {\n membersWithRole?: Connection<GithubUser>;\n team?: GithubTeamResponse;\n teams?: Connection<GithubTeamResponse>;\n repositories?: Connection<RepositoryResponse>;\n};\n\nexport type UserResponse = {\n organizations?: Connection<GithubOrg>;\n};\n\nexport type PageInfo = {\n hasNextPage: boolean;\n endCursor?: string;\n};\n\nexport type GithubOrg = {\n login: string;\n};\n\n/**\n * Github User\n *\n * @public\n */\nexport type GithubUser = {\n login: string;\n bio?: string;\n avatarUrl?: string;\n email?: string;\n name?: string;\n organizationVerifiedDomainEmails?: string[];\n};\n\n/**\n * Github Team\n *\n * @public\n */\nexport type GithubTeam = {\n slug: string;\n combinedSlug: string;\n name?: string;\n description?: string;\n avatarUrl?: string;\n editTeamUrl?: string;\n parentTeam?: GithubTeam;\n members: GithubUser[];\n};\n\nexport type GithubTeamResponse = Omit<GithubTeam, 'members'> & {\n members: Connection<GithubUser>;\n};\n\nexport type RepositoryResponse = {\n name: string;\n url: string;\n isArchived: boolean;\n isFork: boolean;\n repositoryTopics: RepositoryTopics;\n defaultBranchRef: {\n name: string;\n } | null;\n catalogInfoFile: {\n __typename: string;\n id: string;\n text: string;\n } | null;\n visibility: string;\n};\n\ntype RepositoryTopics = {\n nodes: TopicNodes[];\n};\n\ntype TopicNodes = {\n topic: {\n name: string;\n };\n};\n\nexport type Connection<T> = {\n pageInfo: PageInfo;\n nodes: T[];\n};\n\n/**\n * Gets all the users out of a Github organization.\n *\n * Note that the users will not have their memberships filled in.\n *\n * @param client - An octokit graphql client\n * @param org - The slug of the org to read\n */\nexport async function getOrganizationUsers(\n client: typeof graphql,\n org: string,\n tokenType: GithubCredentialType,\n userTransformer: UserTransformer = defaultUserTransformer,\n): Promise<{ users: Entity[] }> {\n const query = `\n query users($org: String!, $email: Boolean!, $cursor: String) {\n organization(login: $org) {\n membersWithRole(first: 100, after: $cursor) {\n pageInfo { hasNextPage, endCursor }\n nodes {\n avatarUrl,\n bio,\n email @include(if: $email),\n login,\n name,\n organizationVerifiedDomainEmails(login: $org)\n }\n }\n }\n }`;\n\n // There is no user -> teams edge, so we leave the memberships empty for\n // now and let the team iteration handle it instead\n\n const users = await queryWithPaging(\n client,\n query,\n org,\n r => r.organization?.membersWithRole,\n userTransformer,\n {\n org,\n email: tokenType === 'token',\n },\n );\n\n return { users };\n}\n\n/**\n * Gets all the teams out of a Github organization.\n *\n * Note that the teams will not have any relations apart from parent filled in.\n *\n * @param client - An octokit graphql client\n * @param org - The slug of the org to read\n */\nexport async function getOrganizationTeams(\n client: typeof graphql,\n org: string,\n teamTransformer: TeamTransformer = defaultOrganizationTeamTransformer,\n): Promise<{\n teams: Entity[];\n}> {\n const query = `\n query teams($org: String!, $cursor: String) {\n organization(login: $org) {\n teams(first: 50, after: $cursor) {\n pageInfo { hasNextPage, endCursor }\n nodes {\n slug\n combinedSlug\n name\n description\n avatarUrl\n editTeamUrl\n parentTeam { slug }\n members(first: 100, membership: IMMEDIATE) {\n pageInfo { hasNextPage }\n nodes {\n avatarUrl,\n bio,\n email,\n login,\n name,\n organizationVerifiedDomainEmails(login: $org)\n }\n }\n }\n }\n }\n }`;\n\n const materialisedTeams = async (\n item: GithubTeamResponse,\n ctx: TransformerContext,\n ): Promise<Entity | undefined> => {\n const memberNames: GithubUser[] = [];\n\n if (!item.members.pageInfo.hasNextPage) {\n // We got all the members in one go, run the fast path\n for (const user of item.members.nodes) {\n memberNames.push(user);\n }\n } else {\n // There were more than a hundred immediate members - run the slow\n // path of fetching them explicitly\n const { members } = await getTeamMembers(ctx.client, ctx.org, item.slug);\n for (const userLogin of members) {\n memberNames.push(userLogin);\n }\n }\n\n const team: GithubTeam = {\n ...item,\n members: memberNames,\n };\n\n return await teamTransformer(team, ctx);\n };\n\n const teams = await queryWithPaging(\n client,\n query,\n org,\n r => r.organization?.teams,\n materialisedTeams,\n { org },\n );\n\n return { teams };\n}\n\nexport async function getOrganizationTeamsFromUsers(\n client: typeof graphql,\n org: string,\n userLogins: string[],\n teamTransformer: TeamTransformer = defaultOrganizationTeamTransformer,\n): Promise<{\n teams: Entity[];\n}> {\n const query = `\n query teams($org: String!, $cursor: String, $userLogins: [String!] = \"\") {\n organization(login: $org) {\n teams(first: 100, after: $cursor, userLogins: $userLogins) {\n pageInfo {\n hasNextPage\n endCursor\n }\n nodes {\n slug\n combinedSlug\n name\n description\n avatarUrl\n editTeamUrl\n parentTeam {\n slug\n }\n members(first: 100, membership: IMMEDIATE) {\n pageInfo {\n hasNextPage\n }\n nodes {\n avatarUrl,\n bio,\n email,\n login,\n name,\n organizationVerifiedDomainEmails(login: $org)\n }\n }\n }\n }\n }\n}`;\n\n const materialisedTeams = async (\n item: GithubTeamResponse,\n ctx: TransformerContext,\n ): Promise<Entity | undefined> => {\n const memberNames: GithubUser[] = [];\n\n if (!item.members.pageInfo.hasNextPage) {\n // We got all the members in one go, run the fast path\n for (const user of item.members.nodes) {\n memberNames.push(user);\n }\n } else {\n // There were more than a hundred immediate members - run the slow\n // path of fetching them explicitly\n const { members } = await getTeamMembers(ctx.client, ctx.org, item.slug);\n for (const userLogin of members) {\n memberNames.push(userLogin);\n }\n }\n\n const team: GithubTeam = {\n ...item,\n members: memberNames,\n };\n\n return await teamTransformer(team, ctx);\n };\n\n const teams = await queryWithPaging(\n client,\n query,\n org,\n r => r.organization?.teams,\n materialisedTeams,\n { org, userLogins },\n );\n\n return { teams };\n}\n\nexport async function getOrganizationTeamsForUser(\n client: typeof graphql,\n org: string,\n userLogin: string,\n teamTransformer: TeamTransformer,\n): Promise<{ teams: Entity[] }> {\n const query = `\n query teams($org: String!, $cursor: String, $userLogins: [String!] = \"\") {\n organization(login: $org) {\n teams(first: 100, after: $cursor, userLogins: $userLogins) {\n pageInfo {\n hasNextPage\n endCursor\n }\n nodes {\n slug\n combinedSlug\n name\n description\n avatarUrl\n editTeamUrl\n parentTeam {\n slug\n }\n }\n }\n }\n}`;\n\n const materialisedTeams = async (\n item: GithubTeamResponse,\n ctx: TransformerContext,\n ): Promise<Entity | undefined> => {\n const team: GithubTeam = {\n ...item,\n members: [{ login: userLogin }],\n };\n\n return await teamTransformer(team, ctx);\n };\n\n const teams = await queryWithPaging(\n client,\n query,\n org,\n r => r.organization?.teams,\n materialisedTeams,\n { org, userLogins: [userLogin] },\n );\n\n return { teams };\n}\n\nexport async function getOrganizationsFromUser(\n client: typeof graphql,\n user: string,\n): Promise<{\n orgs: string[];\n}> {\n const query = `\n query orgs($user: String!) {\n user(login: $user) {\n organizations(first: 100) {\n nodes { login }\n pageInfo { hasNextPage, endCursor }\n }\n }\n }`;\n\n const orgs = await queryWithPaging(\n client,\n query,\n '',\n r => r.user?.organizations,\n async o => o.login,\n { user },\n );\n\n return { orgs };\n}\n\nexport async function getOrganizationTeam(\n client: typeof graphql,\n org: string,\n teamSlug: string,\n teamTransformer: TeamTransformer = defaultOrganizationTeamTransformer,\n): Promise<{\n team: Entity;\n}> {\n const query = `\n query teams($org: String!, $teamSlug: String!) {\n organization(login: $org) {\n team(slug:$teamSlug) {\n slug\n combinedSlug\n name\n description\n avatarUrl\n editTeamUrl\n parentTeam { slug }\n members(first: 100, membership: IMMEDIATE) {\n pageInfo { hasNextPage }\n nodes { login }\n }\n }\n }\n }`;\n\n const materialisedTeam = async (\n item: GithubTeamResponse,\n ctx: TransformerContext,\n ): Promise<Entity | undefined> => {\n const memberNames: GithubUser[] = [];\n\n if (!item.members.pageInfo.hasNextPage) {\n // We got all the members in one go, run the fast path\n for (const user of item.members.nodes) {\n memberNames.push(user);\n }\n } else {\n // There were more than a hundred immediate members - run the slow\n // path of fetching them explicitly\n const { members } = await getTeamMembers(ctx.client, ctx.org, item.slug);\n for (const userLogin of members) {\n memberNames.push(userLogin);\n }\n }\n\n const team: GithubTeam = {\n ...item,\n members: memberNames,\n };\n\n return await teamTransformer(team, ctx);\n };\n\n const response: QueryResponse = await client(query, {\n org,\n teamSlug,\n });\n\n if (!response.organization?.team)\n throw new Error(`Found no match for team ${teamSlug}`);\n\n const team = await materialisedTeam(response.organization?.team, {\n query,\n client,\n org,\n });\n\n if (!team) throw new Error(`Can't transform for team ${teamSlug}`);\n\n return { team };\n}\n\nexport async function getOrganizationRepositories(\n client: typeof graphql,\n org: string,\n catalogPath: string,\n): Promise<{ repositories: RepositoryResponse[] }> {\n let relativeCatalogPathRef: string;\n // We must strip the leading slash or the query for objects does not work\n if (catalogPath.startsWith('/')) {\n relativeCatalogPathRef = catalogPath.substring(1);\n } else {\n relativeCatalogPathRef = catalogPath;\n }\n const catalogPathRef = `HEAD:${relativeCatalogPathRef}`;\n const query = `\n query repositories($org: String!, $catalogPathRef: String!, $cursor: String) {\n repositoryOwner(login: $org) {\n login\n repositories(first: 50, after: $cursor) {\n nodes {\n name\n catalogInfoFile: object(expression: $catalogPathRef) {\n __typename\n ... on Blob {\n id\n text\n }\n }\n url\n isArchived\n isFork\n visibility\n repositoryTopics(first: 100) {\n nodes {\n ... on RepositoryTopic {\n topic {\n name\n }\n }\n }\n }\n defaultBranchRef {\n name\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n }`;\n\n const repositories = await queryWithPaging(\n client,\n query,\n org,\n r => r.repositoryOwner?.repositories,\n async x => x,\n { org, catalogPathRef },\n );\n\n return { repositories };\n}\n\nexport async function getOrganizationRepository(\n client: typeof graphql,\n org: string,\n repoName: string,\n catalogPath: string,\n): Promise<RepositoryResponse | null> {\n let relativeCatalogPathRef: string;\n // We must strip the leading slash or the query for objects does not work\n if (catalogPath.startsWith('/')) {\n relativeCatalogPathRef = catalogPath.substring(1);\n } else {\n relativeCatalogPathRef = catalogPath;\n }\n const catalogPathRef = `HEAD:${relativeCatalogPathRef}`;\n const query = `\n query repository($org: String!, $repoName: String!, $catalogPathRef: String!) {\n repositoryOwner(login: $org) {\n repository(name: $repoName) {\n name\n catalogInfoFile: object(expression: $catalogPathRef) {\n __typename\n ... on Blob {\n id\n text\n }\n }\n url\n isArchived\n isFork\n visibility\n repositoryTopics(first: 100) {\n nodes {\n ... on RepositoryTopic {\n topic {\n name\n }\n }\n }\n }\n defaultBranchRef {\n name\n }\n }\n }\n }`;\n\n const response: QueryResponse = await client(query, {\n org,\n repoName,\n catalogPathRef,\n });\n\n return response.repositoryOwner?.repository || null;\n}\n\n/**\n * Gets all the users out of a Github organization.\n *\n * Note that the users will not have their memberships filled in.\n *\n * @param client - An octokit graphql client\n * @param org - The slug of the org to read\n * @param teamSlug - The slug of the team to read\n */\nexport async function getTeamMembers(\n client: typeof graphql,\n org: string,\n teamSlug: string,\n): Promise<{ members: GithubUser[] }> {\n const query = `\n query members($org: String!, $teamSlug: String!, $cursor: String) {\n organization(login: $org) {\n team(slug: $teamSlug) {\n members(first: 100, after: $cursor, membership: IMMEDIATE) {\n pageInfo { hasNextPage, endCursor }\n nodes { login }\n }\n }\n }\n }`;\n\n const members = await queryWithPaging(\n client,\n query,\n org,\n r => r.organization?.team?.members,\n async user => user,\n { org, teamSlug },\n );\n\n return { members };\n}\n\n//\n// Helpers\n//\n\n/**\n * Assists in repeatedly executing a query with a paged response.\n *\n * Requires that the query accepts a $cursor variable.\n *\n * @param client - The octokit client\n * @param query - The query to execute\n * @param org - The slug of the org to read\n * @param connection - A function that, given the response, picks out the actual\n * Connection object that's being iterated\n * @param transformer - A function that, given one of the nodes in the Connection,\n * returns the model mapped form of it\n * @param variables - The variable values that the query needs, minus the cursor\n */\nexport async function queryWithPaging<\n GraphqlType,\n OutputType,\n Variables extends {},\n Response = QueryResponse,\n>(\n client: typeof graphql,\n query: string,\n org: string,\n connection: (response: Response) => Connection<GraphqlType> | undefined,\n transformer: (\n item: GraphqlType,\n ctx: TransformerContext,\n ) => Promise<OutputType | undefined>,\n variables: Variables,\n): Promise<OutputType[]> {\n const result: OutputType[] = [];\n const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));\n\n let cursor: string | undefined = undefined;\n for (let j = 0; j < 1000 /* just for sanity */; ++j) {\n const response: Response = await client(query, {\n ...variables,\n cursor,\n });\n\n const conn = connection(response);\n if (!conn) {\n throw new Error(`Found no match for ${JSON.stringify(variables)}`);\n }\n\n for (const node of conn.nodes) {\n const transformedNode = await transformer(node, {\n client,\n query,\n org,\n });\n\n if (transformedNode) {\n result.push(transformedNode);\n }\n }\n\n if (!conn.pageInfo.hasNextPage) {\n break;\n } else {\n await sleep(1000);\n cursor = conn.pageInfo.endCursor;\n }\n }\n\n return result;\n}\n\nexport type DeferredEntitiesBuilder = (\n org: string,\n entities: Entity[],\n) => { added: DeferredEntity[]; removed: DeferredEntity[] };\n\nexport const createAddEntitiesOperation =\n (id: string, host: string) => (org: string, entities: Entity[]) => ({\n removed: [],\n added: entities.map(entity => ({\n locationKey: `github-org-provider:${id}`,\n entity: withLocations(`https://${host}`, org, entity),\n })),\n });\n\nexport const createRemoveEntitiesOperation =\n (id: string, host: string) => (org: string, entities: Entity[]) => ({\n added: [],\n removed: entities.map(entity => ({\n locationKey: `github-org-provider:${id}`,\n entity: withLocations(`https://${host}`, org, entity),\n })),\n });\n\nexport const createReplaceEntitiesOperation =\n (id: string, host: string) => (org: string, entities: Entity[]) => {\n const entitiesToReplace = entities.map(entity => ({\n locationKey: `github-org-provider:${id}`,\n entity: withLocations(`https://${host}`, org, entity),\n }));\n\n return {\n removed: entitiesToReplace,\n added: entitiesToReplace,\n };\n };\n\n/**\n * Creates a GraphQL Client with Throttling\n */\nexport const createGraphqlClient = (args: {\n headers:\n | {\n [name: string]: string;\n }\n | undefined;\n baseUrl: string;\n logger: LoggerService;\n}): typeof graphql => {\n const { headers, baseUrl, logger } = args;\n const ThrottledOctokit = Octokit.plugin(throttling);\n const octokit = new ThrottledOctokit({\n throttle: {\n onRateLimit: (retryAfter, rateLimitData, _, retryCount) => {\n logger.warn(\n `Request quota exhausted for request ${rateLimitData?.method} ${rateLimitData?.url}`,\n );\n\n if (retryCount < 2) {\n logger.warn(\n `Retrying after ${retryAfter} seconds for the ${retryCount} time due to Rate Limit!`,\n );\n return true;\n }\n\n return false;\n },\n onSecondaryRateLimit: (retryAfter, rateLimitData, _, retryCount) => {\n logger.warn(\n `Secondary Rate Limit Exhausted for request ${rateLimitData?.method} ${rateLimitData?.url}`,\n );\n\n if (retryCount < 2) {\n logger.warn(\n `Retrying after ${retryAfter} seconds for the ${retryCount} time due to Secondary Rate Limit!`,\n );\n return true;\n }\n\n return false;\n },\n },\n });\n\n const client = octokit.graphql.defaults({\n headers,\n baseUrl,\n });\n\n return client;\n};\n"],"names":["defaultUserTransformer","defaultOrganizationTeamTransformer","team","withLocations","Octokit","throttling"],"mappings":";;;;;;;AA2IA,eAAsB,oBAAA,CACpB,MAAA,EACA,GAAA,EACA,SAAA,EACA,kBAAmCA,0CAAA,EACL;AAC9B,EAAA,MAAM,KAAA,GAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAAA,CAAA;AAoBd,EAAA,MAAM,QAAQ,MAAM,eAAA;AAAA,IAClB,MAAA;AAAA,IACA,KAAA;AAAA,IACA,GAAA;AAAA,IACA,CAAA,CAAA,KAAK,EAAE,YAAA,EAAc,eAAA;AAAA,IACrB,eAAA;AAAA,IACA;AAAA,MACE,GAAA;AAAA,MACA,OAAO,SAAA,KAAc;AAAA;AACvB,GACF;AAEA,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;AAUA,eAAsB,oBAAA,CACpB,MAAA,EACA,GAAA,EACA,eAAA,GAAmCC,sDAAA,EAGlC;AACD,EAAA,MAAM,KAAA,GAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAAA,CAAA;AA6Bd,EAAA,MAAM,iBAAA,GAAoB,OACxB,IAAA,EACA,GAAA,KACgC;AAChC,IAAA,MAAM,cAA4B,EAAC;AAEnC,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,WAAA,EAAa;AAEtC,MAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAO;AACrC,QAAA,WAAA,CAAY,KAAK,IAAI,CAAA;AAAA,MACvB;AAAA,IACF,CAAA,MAAO;AAGL,MAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,MAAM,cAAA,CAAe,IAAI,MAAA,EAAQ,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,IAAI,CAAA;AACvE,MAAA,KAAA,MAAW,aAAa,OAAA,EAAS;AAC/B,QAAA,WAAA,CAAY,KAAK,SAAS,CAAA;AAAA,MAC5B;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,GAAmB;AAAA,MACvB,GAAG,IAAA;AAAA,MACH,OAAA,EAAS;AAAA,KACX;AAEA,IAAA,OAAO,MAAM,eAAA,CAAgB,IAAA,EAAM,GAAG,CAAA;AAAA,EACxC,CAAA;AAEA,EAAA,MAAM,QAAQ,MAAM,eAAA;AAAA,IAClB,MAAA;AAAA,IACA,KAAA;AAAA,IACA,GAAA;AAAA,IACA,CAAA,CAAA,KAAK,EAAE,YAAA,EAAc,KAAA;AAAA,IACrB,iBAAA;AAAA,IACA,EAAE,GAAA;AAAI,GACR;AAEA,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;AAEA,eAAsB,6BAAA,CACpB,MAAA,EACA,GAAA,EACA,UAAA,EACA,kBAAmCA,sDAAA,EAGlC;AACD,EAAA,MAAM,KAAA,GAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AAoCd,EAAA,MAAM,iBAAA,GAAoB,OACxB,IAAA,EACA,GAAA,KACgC;AAChC,IAAA,MAAM,cAA4B,EAAC;AAEnC,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,WAAA,EAAa;AAEtC,MAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAO;AACrC,QAAA,WAAA,CAAY,KAAK,IAAI,CAAA;AAAA,MACvB;AAAA,IACF,CAAA,MAAO;AAGL,MAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,MAAM,cAAA,CAAe,IAAI,MAAA,EAAQ,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,IAAI,CAAA;AACvE,MAAA,KAAA,MAAW,aAAa,OAAA,EAAS;AAC/B,QAAA,WAAA,CAAY,KAAK,SAAS,CAAA;AAAA,MAC5B;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,GAAmB;AAAA,MACvB,GAAG,IAAA;AAAA,MACH,OAAA,EAAS;AAAA,KACX;AAEA,IAAA,OAAO,MAAM,eAAA,CAAgB,IAAA,EAAM,GAAG,CAAA;AAAA,EACxC,CAAA;AAEA,EAAA,MAAM,QAAQ,MAAM,eAAA;AAAA,IAClB,MAAA;AAAA,IACA,KAAA;AAAA,IACA,GAAA;AAAA,IACA,CAAA,CAAA,KAAK,EAAE,YAAA,EAAc,KAAA;AAAA,IACrB,iBAAA;AAAA,IACA,EAAE,KAAK,UAAA;AAAW,GACpB;AAEA,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;AAEA,eAAsB,2BAAA,CACpB,MAAA,EACA,GAAA,EACA,SAAA,EACA,eAAA,EAC8B;AAC9B,EAAA,MAAM,KAAA,GAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AAuBd,EAAA,MAAM,iBAAA,GAAoB,OACxB,IAAA,EACA,GAAA,KACgC;AAChC,IAAA,MAAM,IAAA,GAAmB;AAAA,MACvB,GAAG,IAAA;AAAA,MACH,OAAA,EAAS,CAAC,EAAE,KAAA,EAAO,WAAW;AAAA,KAChC;AAEA,IAAA,OAAO,MAAM,eAAA,CAAgB,IAAA,EAAM,GAAG,CAAA;AAAA,EACxC,CAAA;AAEA,EAAA,MAAM,QAAQ,MAAM,eAAA;AAAA,IAClB,MAAA;AAAA,IACA,KAAA;AAAA,IACA,GAAA;AAAA,IACA,CAAA,CAAA,KAAK,EAAE,YAAA,EAAc,KAAA;AAAA,IACrB,iBAAA;AAAA,IACA,EAAE,GAAA,EAAK,UAAA,EAAY,CAAC,SAAS,CAAA;AAAE,GACjC;AAEA,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;AAEA,eAAsB,wBAAA,CACpB,QACA,IAAA,EAGC;AACD,EAAA,MAAM,KAAA,GAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAAA,CAAA;AAUd,EAAA,MAAM,OAAO,MAAM,eAAA;AAAA,IACjB,MAAA;AAAA,IACA,KAAA;AAAA,IACA,EAAA;AAAA,IACA,CAAA,CAAA,KAAK,EAAE,IAAA,EAAM,aAAA;AAAA,IACb,OAAM,MAAK,CAAA,CAAE,KAAA;AAAA,IACb,EAAE,IAAA;AAAK,GACT;AAEA,EAAA,OAAO,EAAE,IAAA,EAAK;AAChB;AAEA,eAAsB,mBAAA,CACpB,MAAA,EACA,GAAA,EACA,QAAA,EACA,kBAAmCA,sDAAA,EAGlC;AACD,EAAA,MAAM,KAAA,GAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAAA,CAAA;AAmBd,EAAA,MAAM,gBAAA,GAAmB,OACvB,IAAA,EACA,GAAA,KACgC;AAChC,IAAA,MAAM,cAA4B,EAAC;AAEnC,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,WAAA,EAAa;AAEtC,MAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAO;AACrC,QAAA,WAAA,CAAY,KAAK,IAAI,CAAA;AAAA,MACvB;AAAA,IACF,CAAA,MAAO;AAGL,MAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,MAAM,cAAA,CAAe,IAAI,MAAA,EAAQ,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,IAAI,CAAA;AACvE,MAAA,KAAA,MAAW,aAAa,OAAA,EAAS;AAC/B,QAAA,WAAA,CAAY,KAAK,SAAS,CAAA;AAAA,MAC5B;AAAA,IACF;AAEA,IAAA,MAAMC,KAAAA,GAAmB;AAAA,MACvB,GAAG,IAAA;AAAA,MACH,OAAA,EAAS;AAAA,KACX;AAEA,IAAA,OAAO,MAAM,eAAA,CAAgBA,KAAAA,EAAM,GAAG,CAAA;AAAA,EACxC,CAAA;AAEA,EAAA,MAAM,QAAA,GAA0B,MAAM,MAAA,CAAO,KAAA,EAAO;AAAA,IAClD,GAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,YAAA,EAAc,IAAA;AAC1B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,QAAQ,CAAA,CAAE,CAAA;AAEvD,EAAA,MAAM,IAAA,GAAO,MAAM,gBAAA,CAAiB,QAAA,CAAS,cAAc,IAAA,EAAM;AAAA,IAC/D,KAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,IAAI,CAAC,IAAA,EAAM,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,QAAQ,CAAA,CAAE,CAAA;AAEjE,EAAA,OAAO,EAAE,IAAA,EAAK;AAChB;AAEA,eAAsB,2BAAA,CACpB,MAAA,EACA,GAAA,EACA,WAAA,EACiD;AACjD,EAAA,IAAI,sBAAA;AAEJ,EAAA,IAAI,WAAA,CAAY,UAAA,CAAW,GAAG,CAAA,EAAG;AAC/B,IAAA,sBAAA,GAAyB,WAAA,CAAY,UAAU,CAAC,CAAA;AAAA,EAClD,CAAA,MAAO;AACL,IAAA,sBAAA,GAAyB,WAAA;AAAA,EAC3B;AACA,EAAA,MAAM,cAAA,GAAiB,QAAQ,sBAAsB,CAAA,CAAA;AACrD,EAAA,MAAM,KAAA,GAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAAA,CAAA;AAuCd,EAAA,MAAM,eAAe,MAAM,eAAA;AAAA,IACzB,MAAA;AAAA,IACA,KAAA;AAAA,IACA,GAAA;AAAA,IACA,CAAA,CAAA,KAAK,EAAE,eAAA,EAAiB,YAAA;AAAA,IACxB,OAAM,CAAA,KAAK,CAAA;AAAA,IACX,EAAE,KAAK,cAAA;AAAe,GACxB;AAEA,EAAA,OAAO,EAAE,YAAA,EAAa;AACxB;AAEA,eAAsB,yBAAA,CACpB,MAAA,EACA,GAAA,EACA,QAAA,EACA,WAAA,EACoC;AACpC,EAAA,IAAI,sBAAA;AAEJ,EAAA,IAAI,WAAA,CAAY,UAAA,CAAW,GAAG,CAAA,EAAG;AAC/B,IAAA,sBAAA,GAAyB,WAAA,CAAY,UAAU,CAAC,CAAA;AAAA,EAClD,CAAA,MAAO;AACL,IAAA,sBAAA,GAAyB,WAAA;AAAA,EAC3B;AACA,EAAA,MAAM,cAAA,GAAiB,QAAQ,sBAAsB,CAAA,CAAA;AACrD,EAAA,MAAM,KAAA,GAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAAA,CAAA;AAgCd,EAAA,MAAM,QAAA,GAA0B,MAAM,MAAA,CAAO,KAAA,EAAO;AAAA,IAClD,GAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,OAAO,QAAA,CAAS,iBAAiB,UAAA,IAAc,IAAA;AACjD;AAWA,eAAsB,cAAA,CACpB,MAAA,EACA,GAAA,EACA,QAAA,EACoC;AACpC,EAAA,MAAM,KAAA,GAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAAA,CAAA;AAYd,EAAA,MAAM,UAAU,MAAM,eAAA;AAAA,IACpB,MAAA;AAAA,IACA,KAAA;AAAA,IACA,GAAA;AAAA,IACA,CAAA,CAAA,KAAK,CAAA,CAAE,YAAA,EAAc,IAAA,EAAM,OAAA;AAAA,IAC3B,OAAM,IAAA,KAAQ,IAAA;AAAA,IACd,EAAE,KAAK,QAAA;AAAS,GAClB;AAEA,EAAA,OAAO,EAAE,OAAA,EAAQ;AACnB;AAoBA,eAAsB,gBAMpB,MAAA,EACA,KAAA,EACA,GAAA,EACA,UAAA,EACA,aAIA,SAAA,EACuB;AACvB,EAAA,MAAM,SAAuB,EAAC;AAC9B,EAAA,MAAM,KAAA,GAAQ,CAAC,EAAA,KAAe,IAAI,QAAQ,CAAA,CAAA,KAAK,UAAA,CAAW,CAAA,EAAG,EAAE,CAAC,CAAA;AAEhE,EAAA,IAAI,MAAA,GAA6B,MAAA;AACjC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,EAA4B,EAAE,CAAA,EAAG;AACnD,IAAA,MAAM,QAAA,GAAqB,MAAM,MAAA,CAAO,KAAA,EAAO;AAAA,MAC7C,GAAG,SAAA;AAAA,MACH;AAAA,KACD,CAAA;AAED,IAAA,MAAM,IAAA,GAAO,WAAW,QAAQ,CAAA;AAChC,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,KAAK,SAAA,CAAU,SAAS,CAAC,CAAA,CAAE,CAAA;AAAA,IACnE;AAEA,IAAA,KAAA,MAAW,IAAA,IAAQ,KAAK,KAAA,EAAO;AAC7B,MAAA,MAAM,eAAA,GAAkB,MAAM,WAAA,CAAY,IAAA,EAAM;AAAA,QAC9C,MAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAA,IAAI,eAAA,EAAiB;AACnB,QAAA,MAAA,CAAO,KAAK,eAAe,CAAA;AAAA,MAC7B;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,WAAA,EAAa;AAC9B,MAAA;AAAA,IACF,CAAA,MAAO;AACL,MAAA,MAAM,MAAM,GAAI,CAAA;AAChB,MAAA,MAAA,GAAS,KAAK,QAAA,CAAS,SAAA;AAAA,IACzB;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAOO,MAAM,6BACX,CAAC,EAAA,EAAY,IAAA,KAAiB,CAAC,KAAa,QAAA,MAAwB;AAAA,EAClE,SAAS,EAAC;AAAA,EACV,KAAA,EAAO,QAAA,CAAS,GAAA,CAAI,CAAA,MAAA,MAAW;AAAA,IAC7B,WAAA,EAAa,uBAAuB,EAAE,CAAA,CAAA;AAAA,IACtC,QAAQC,2BAAA,CAAc,CAAA,QAAA,EAAW,IAAI,CAAA,CAAA,EAAI,KAAK,MAAM;AAAA,GACtD,CAAE;AACJ,CAAA;AAEK,MAAM,gCACX,CAAC,EAAA,EAAY,IAAA,KAAiB,CAAC,KAAa,QAAA,MAAwB;AAAA,EAClE,OAAO,EAAC;AAAA,EACR,OAAA,EAAS,QAAA,CAAS,GAAA,CAAI,CAAA,MAAA,MAAW;AAAA,IAC/B,WAAA,EAAa,uBAAuB,EAAE,CAAA,CAAA;AAAA,IACtC,QAAQA,2BAAA,CAAc,CAAA,QAAA,EAAW,IAAI,CAAA,CAAA,EAAI,KAAK,MAAM;AAAA,GACtD,CAAE;AACJ,CAAA;AAEK,MAAM,iCACX,CAAC,EAAA,EAAY,IAAA,KAAiB,CAAC,KAAa,QAAA,KAAuB;AACjE,EAAA,MAAM,iBAAA,GAAoB,QAAA,CAAS,GAAA,CAAI,CAAA,MAAA,MAAW;AAAA,IAChD,WAAA,EAAa,uBAAuB,EAAE,CAAA,CAAA;AAAA,IACtC,QAAQA,2BAAA,CAAc,CAAA,QAAA,EAAW,IAAI,CAAA,CAAA,EAAI,KAAK,MAAM;AAAA,GACtD,CAAE,CAAA;AAEF,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,iBAAA;AAAA,IACT,KAAA,EAAO;AAAA,GACT;AACF;AAKK,MAAM,mBAAA,GAAsB,CAAC,IAAA,KAQd;AACpB,EAAA,MAAM,EAAE,OAAA,EAAS,OAAA,EAAS,MAAA,EAAO,GAAI,IAAA;AACrC,EAAA,MAAM,gBAAA,GAAmBC,YAAA,CAAQ,MAAA,CAAOC,2BAAU,CAAA;AAClD,EAAA,MAAM,OAAA,GAAU,IAAI,gBAAA,CAAiB;AAAA,IACnC,QAAA,EAAU;AAAA,MACR,WAAA,EAAa,CAAC,UAAA,EAAY,aAAA,EAAe,GAAG,UAAA,KAAe;AACzD,QAAA,MAAA,CAAO,IAAA;AAAA,UACL,CAAA,oCAAA,EAAuC,aAAA,EAAe,MAAM,CAAA,CAAA,EAAI,eAAe,GAAG,CAAA;AAAA,SACpF;AAEA,QAAA,IAAI,aAAa,CAAA,EAAG;AAClB,UAAA,MAAA,CAAO,IAAA;AAAA,YACL,CAAA,eAAA,EAAkB,UAAU,CAAA,iBAAA,EAAoB,UAAU,CAAA,wBAAA;AAAA,WAC5D;AACA,UAAA,OAAO,IAAA;AAAA,QACT;AAEA,QAAA,OAAO,KAAA;AAAA,MACT,CAAA;AAAA,MACA,oBAAA,EAAsB,CAAC,UAAA,EAAY,aAAA,EAAe,GAAG,UAAA,KAAe;AAClE,QAAA,MAAA,CAAO,IAAA;AAAA,UACL,CAAA,2CAAA,EAA8C,aAAA,EAAe,MAAM,CAAA,CAAA,EAAI,eAAe,GAAG,CAAA;AAAA,SAC3F;AAEA,QAAA,IAAI,aAAa,CAAA,EAAG;AAClB,UAAA,MAAA,CAAO,IAAA;AAAA,YACL,CAAA,eAAA,EAAkB,UAAU,CAAA,iBAAA,EAAoB,UAAU,CAAA,kCAAA;AAAA,WAC5D;AACA,UAAA,OAAO,IAAA;AAAA,QACT;AAEA,QAAA,OAAO,KAAA;AAAA,MACT;AAAA;AACF,GACD,CAAA;AAED,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,OAAA,CAAQ,QAAA,CAAS;AAAA,IACtC,OAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,OAAO,MAAA;AACT;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"github.cjs.js","sources":["../../src/lib/github.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport { GithubCredentialType } from '@backstage/integration';\nimport { graphql } from '@octokit/graphql';\nimport {\n defaultOrganizationTeamTransformer,\n defaultUserTransformer,\n TeamTransformer,\n TransformerContext,\n UserTransformer,\n} from './defaultTransformers';\nimport { withLocations } from './withLocations';\n\nimport { DeferredEntity } from '@backstage/plugin-catalog-node';\nimport { Octokit } from '@octokit/core';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { throttling } from '@octokit/plugin-throttling';\n\n/**\n * Configuration for GitHub GraphQL API page sizes.\n *\n * @public\n */\nexport type GithubPageSizes = {\n /**\n * Number of teams to fetch per page when querying organization teams.\n * Default: 25\n */\n teams: number;\n /**\n * Number of team members to fetch per page when querying team members.\n * Default: 50\n */\n teamMembers: number;\n /**\n * Number of organization members to fetch per page when querying org members.\n * Default: 50\n */\n organizationMembers: number;\n /**\n * Number of repositories to fetch per page when querying repositories.\n * Default: 25\n */\n repositories: number;\n};\n\n/**\n * Default page sizes for GitHub GraphQL API queries.\n * These values are reduced to prevent RESOURCE_LIMITS_EXCEEDED errors with large organizations.\n *\n * @public\n */\nexport const DEFAULT_PAGE_SIZES: GithubPageSizes = {\n teams: 25,\n teamMembers: 50,\n organizationMembers: 50,\n repositories: 25,\n};\n\n// Graphql types\n\nexport type QueryResponse = {\n organization?: OrganizationResponse;\n repositoryOwner?: RepositoryOwnerResponse;\n user?: UserResponse;\n};\n\ntype RepositoryOwnerResponse = {\n repositories?: Connection<RepositoryResponse>;\n repository?: RepositoryResponse;\n};\n\nexport type OrganizationResponse = {\n membersWithRole?: Connection<GithubUser>;\n team?: GithubTeamResponse;\n teams?: Connection<GithubTeamResponse>;\n repositories?: Connection<RepositoryResponse>;\n};\n\nexport type UserResponse = {\n organizations?: Connection<GithubOrg>;\n};\n\nexport type PageInfo = {\n hasNextPage: boolean;\n endCursor?: string;\n};\n\nexport type GithubOrg = {\n login: string;\n};\n\n/**\n * Github User\n *\n * @public\n */\nexport type GithubUser = {\n login: string;\n bio?: string;\n avatarUrl?: string;\n email?: string;\n name?: string;\n organizationVerifiedDomainEmails?: string[];\n};\n\n/**\n * Github Team\n *\n * @public\n */\nexport type GithubTeam = {\n slug: string;\n combinedSlug: string;\n name?: string;\n description?: string;\n avatarUrl?: string;\n editTeamUrl?: string;\n parentTeam?: GithubTeam;\n members: GithubUser[];\n};\n\nexport type GithubTeamResponse = Omit<GithubTeam, 'members'> & {\n members: Connection<GithubUser>;\n};\n\nexport type RepositoryResponse = {\n name: string;\n url: string;\n isArchived: boolean;\n isFork: boolean;\n repositoryTopics: RepositoryTopics;\n defaultBranchRef: {\n name: string;\n } | null;\n catalogInfoFile: {\n __typename: string;\n id: string;\n text: string;\n } | null;\n visibility: string;\n};\n\ntype RepositoryTopics = {\n nodes: TopicNodes[];\n};\n\ntype TopicNodes = {\n topic: {\n name: string;\n };\n};\n\nexport type Connection<T> = {\n pageInfo: PageInfo;\n nodes: T[];\n};\n\n/**\n * Gets all the users out of a Github organization.\n *\n * Note that the users will not have their memberships filled in.\n *\n * @param client - An octokit graphql client\n * @param org - The slug of the org to read\n * @param tokenType - The type of GitHub credential\n * @param userTransformer - Optional transformer for user entities\n * @param pageSizes - Optional page sizes configuration\n */\nexport async function getOrganizationUsers(\n client: typeof graphql,\n org: string,\n tokenType: GithubCredentialType,\n userTransformer: UserTransformer = defaultUserTransformer,\n pageSizes: GithubPageSizes = DEFAULT_PAGE_SIZES,\n): Promise<{ users: Entity[] }> {\n const query = `\n query users($org: String!, $email: Boolean!, $cursor: String, $organizationMembersPageSize: Int!) {\n organization(login: $org) {\n membersWithRole(first: $organizationMembersPageSize, after: $cursor) {\n pageInfo { hasNextPage, endCursor }\n nodes {\n avatarUrl,\n bio,\n email @include(if: $email),\n login,\n name,\n organizationVerifiedDomainEmails(login: $org)\n }\n }\n }\n }`;\n\n // There is no user -> teams edge, so we leave the memberships empty for\n // now and let the team iteration handle it instead\n\n const users = await queryWithPaging(\n client,\n query,\n org,\n r => r.organization?.membersWithRole,\n userTransformer,\n {\n org,\n email: tokenType === 'token',\n organizationMembersPageSize: pageSizes.organizationMembers,\n },\n );\n\n return { users };\n}\n\n/**\n * Gets all the teams out of a Github organization.\n *\n * Note that the teams will not have any relations apart from parent filled in.\n *\n * @param client - An octokit graphql client\n * @param org - The slug of the org to read\n * @param teamTransformer - Optional transformer for team entities\n * @param pageSizes - Optional page sizes configuration\n */\nexport async function getOrganizationTeams(\n client: typeof graphql,\n org: string,\n teamTransformer: TeamTransformer = defaultOrganizationTeamTransformer,\n pageSizes: GithubPageSizes = DEFAULT_PAGE_SIZES,\n): Promise<{\n teams: Entity[];\n}> {\n const query = `\n query teams($org: String!, $cursor: String, $teamsPageSize: Int!, $membersPageSize: Int!) {\n organization(login: $org) {\n teams(first: $teamsPageSize, after: $cursor) {\n pageInfo { hasNextPage, endCursor }\n nodes {\n slug\n combinedSlug\n name\n description\n avatarUrl\n editTeamUrl\n parentTeam { slug }\n members(first: $membersPageSize, membership: IMMEDIATE) {\n pageInfo { hasNextPage }\n nodes {\n avatarUrl,\n bio,\n email,\n login,\n name,\n organizationVerifiedDomainEmails(login: $org)\n }\n }\n }\n }\n }\n }`;\n\n const materialisedTeams = async (\n item: GithubTeamResponse,\n ctx: TransformerContext,\n ): Promise<Entity | undefined> => {\n const memberNames: GithubUser[] = [];\n\n if (!item.members.pageInfo.hasNextPage) {\n // We got all the members in one go, run the fast path\n for (const user of item.members.nodes) {\n memberNames.push(user);\n }\n } else {\n // There were more immediate members than page size - run the slow\n // path of fetching them explicitly\n const { members } = await getTeamMembers(\n ctx.client,\n ctx.org,\n item.slug,\n pageSizes,\n );\n for (const userLogin of members) {\n memberNames.push(userLogin);\n }\n }\n\n const team: GithubTeam = {\n ...item,\n members: memberNames,\n };\n\n return await teamTransformer(team, ctx);\n };\n\n const teams = await queryWithPaging(\n client,\n query,\n org,\n r => r.organization?.teams,\n materialisedTeams,\n {\n org,\n teamsPageSize: pageSizes.teams,\n membersPageSize: pageSizes.teamMembers,\n },\n );\n\n return { teams };\n}\n\nexport async function getOrganizationTeamsFromUsers(\n client: typeof graphql,\n org: string,\n userLogins: string[],\n teamTransformer: TeamTransformer = defaultOrganizationTeamTransformer,\n pageSizes: GithubPageSizes = DEFAULT_PAGE_SIZES,\n): Promise<{\n teams: Entity[];\n}> {\n const query = `\n query teams($org: String!, $cursor: String, $userLogins: [String!] = \"\", $teamsPageSize: Int!, $membersPageSize: Int!) {\n organization(login: $org) {\n teams(first: $teamsPageSize, after: $cursor, userLogins: $userLogins) {\n pageInfo {\n hasNextPage\n endCursor\n }\n nodes {\n slug\n combinedSlug\n name\n description\n avatarUrl\n editTeamUrl\n parentTeam {\n slug\n }\n members(first: $membersPageSize, membership: IMMEDIATE) {\n pageInfo {\n hasNextPage\n }\n nodes {\n avatarUrl,\n bio,\n email,\n login,\n name,\n organizationVerifiedDomainEmails(login: $org)\n }\n }\n }\n }\n }\n}`;\n\n const materialisedTeams = async (\n item: GithubTeamResponse,\n ctx: TransformerContext,\n ): Promise<Entity | undefined> => {\n const memberNames: GithubUser[] = [];\n\n if (!item.members.pageInfo.hasNextPage) {\n // We got all the members in one go, run the fast path\n for (const user of item.members.nodes) {\n memberNames.push(user);\n }\n } else {\n // There were more immediate members than page size - run the slow\n // path of fetching them explicitly\n const { members } = await getTeamMembers(\n ctx.client,\n ctx.org,\n item.slug,\n pageSizes,\n );\n for (const userLogin of members) {\n memberNames.push(userLogin);\n }\n }\n\n const team: GithubTeam = {\n ...item,\n members: memberNames,\n };\n\n return await teamTransformer(team, ctx);\n };\n\n const teams = await queryWithPaging(\n client,\n query,\n org,\n r => r.organization?.teams,\n materialisedTeams,\n {\n org,\n userLogins,\n teamsPageSize: pageSizes.teams,\n membersPageSize: pageSizes.teamMembers,\n },\n );\n\n return { teams };\n}\n\nexport async function getOrganizationTeamsForUser(\n client: typeof graphql,\n org: string,\n userLogin: string,\n teamTransformer: TeamTransformer,\n pageSizes: GithubPageSizes = DEFAULT_PAGE_SIZES,\n): Promise<{ teams: Entity[] }> {\n const query = `\n query teams($org: String!, $cursor: String, $userLogins: [String!] = \"\", $teamsPageSize: Int!) {\n organization(login: $org) {\n teams(first: $teamsPageSize, after: $cursor, userLogins: $userLogins) {\n pageInfo {\n hasNextPage\n endCursor\n }\n nodes {\n slug\n combinedSlug\n name\n description\n avatarUrl\n editTeamUrl\n parentTeam {\n slug\n }\n }\n }\n }\n}`;\n\n const materialisedTeams = async (\n item: GithubTeamResponse,\n ctx: TransformerContext,\n ): Promise<Entity | undefined> => {\n const team: GithubTeam = {\n ...item,\n members: [{ login: userLogin }],\n };\n\n return await teamTransformer(team, ctx);\n };\n\n const teams = await queryWithPaging(\n client,\n query,\n org,\n r => r.organization?.teams,\n materialisedTeams,\n { org, userLogins: [userLogin], teamsPageSize: pageSizes.teams },\n );\n\n return { teams };\n}\n\nexport async function getOrganizationsFromUser(\n client: typeof graphql,\n user: string,\n): Promise<{\n orgs: string[];\n}> {\n const query = `\n query orgs($user: String!) {\n user(login: $user) {\n organizations(first: 100) {\n nodes { login }\n pageInfo { hasNextPage, endCursor }\n }\n }\n }`;\n\n const orgs = await queryWithPaging(\n client,\n query,\n '',\n r => r.user?.organizations,\n async o => o.login,\n { user },\n );\n\n return { orgs };\n}\n\nexport async function getOrganizationTeam(\n client: typeof graphql,\n org: string,\n teamSlug: string,\n teamTransformer: TeamTransformer = defaultOrganizationTeamTransformer,\n pageSizes: GithubPageSizes = DEFAULT_PAGE_SIZES,\n): Promise<{\n team: Entity;\n}> {\n const query = `\n query teams($org: String!, $teamSlug: String!, $membersPageSize: Int!) {\n organization(login: $org) {\n team(slug:$teamSlug) {\n slug\n combinedSlug\n name\n description\n avatarUrl\n editTeamUrl\n parentTeam { slug }\n members(first: $membersPageSize, membership: IMMEDIATE) {\n pageInfo { hasNextPage }\n nodes { login }\n }\n }\n }\n }`;\n\n const materialisedTeam = async (\n item: GithubTeamResponse,\n ctx: TransformerContext,\n ): Promise<Entity | undefined> => {\n const memberNames: GithubUser[] = [];\n\n if (!item.members.pageInfo.hasNextPage) {\n // We got all the members in one go, run the fast path\n for (const user of item.members.nodes) {\n memberNames.push(user);\n }\n } else {\n // There were more immediate members than page size - run the slow\n // path of fetching them explicitly\n const { members } = await getTeamMembers(\n ctx.client,\n ctx.org,\n item.slug,\n pageSizes,\n );\n for (const userLogin of members) {\n memberNames.push(userLogin);\n }\n }\n\n const team: GithubTeam = {\n ...item,\n members: memberNames,\n };\n\n return await teamTransformer(team, ctx);\n };\n\n const response: QueryResponse = await client(query, {\n org,\n teamSlug,\n membersPageSize: pageSizes.teamMembers,\n });\n\n if (!response.organization?.team)\n throw new Error(`Found no match for team ${teamSlug}`);\n\n const team = await materialisedTeam(response.organization?.team, {\n query,\n client,\n org,\n });\n\n if (!team) throw new Error(`Can't transform for team ${teamSlug}`);\n\n return { team };\n}\n\nexport async function getOrganizationRepositories(\n client: typeof graphql,\n org: string,\n catalogPath: string,\n pageSizes: GithubPageSizes = DEFAULT_PAGE_SIZES,\n): Promise<{ repositories: RepositoryResponse[] }> {\n let relativeCatalogPathRef: string;\n // We must strip the leading slash or the query for objects does not work\n if (catalogPath.startsWith('/')) {\n relativeCatalogPathRef = catalogPath.substring(1);\n } else {\n relativeCatalogPathRef = catalogPath;\n }\n const catalogPathRef = `HEAD:${relativeCatalogPathRef}`;\n const query = `\n query repositories($org: String!, $catalogPathRef: String!, $cursor: String, $repositoriesPageSize: Int!) {\n repositoryOwner(login: $org) {\n login\n repositories(first: $repositoriesPageSize, after: $cursor) {\n nodes {\n name\n catalogInfoFile: object(expression: $catalogPathRef) {\n __typename\n ... on Blob {\n id\n text\n }\n }\n url\n isArchived\n isFork\n visibility\n repositoryTopics(first: 100) {\n nodes {\n ... on RepositoryTopic {\n topic {\n name\n }\n }\n }\n }\n defaultBranchRef {\n name\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n }`;\n\n const repositories = await queryWithPaging(\n client,\n query,\n org,\n r => r.repositoryOwner?.repositories,\n async x => x,\n { org, catalogPathRef, repositoriesPageSize: pageSizes.repositories },\n );\n\n return { repositories };\n}\n\nexport async function getOrganizationRepository(\n client: typeof graphql,\n org: string,\n repoName: string,\n catalogPath: string,\n): Promise<RepositoryResponse | null> {\n let relativeCatalogPathRef: string;\n // We must strip the leading slash or the query for objects does not work\n if (catalogPath.startsWith('/')) {\n relativeCatalogPathRef = catalogPath.substring(1);\n } else {\n relativeCatalogPathRef = catalogPath;\n }\n const catalogPathRef = `HEAD:${relativeCatalogPathRef}`;\n const query = `\n query repository($org: String!, $repoName: String!, $catalogPathRef: String!) {\n repositoryOwner(login: $org) {\n repository(name: $repoName) {\n name\n catalogInfoFile: object(expression: $catalogPathRef) {\n __typename\n ... on Blob {\n id\n text\n }\n }\n url\n isArchived\n isFork\n visibility\n repositoryTopics(first: 100) {\n nodes {\n ... on RepositoryTopic {\n topic {\n name\n }\n }\n }\n }\n defaultBranchRef {\n name\n }\n }\n }\n }`;\n\n const response: QueryResponse = await client(query, {\n org,\n repoName,\n catalogPathRef,\n });\n\n return response.repositoryOwner?.repository || null;\n}\n\n/**\n * Gets all the users out of a Github organization team.\n *\n * Note that the users will not have their memberships filled in.\n *\n * @param client - An octokit graphql client\n * @param org - The slug of the org to read\n * @param teamSlug - The slug of the team to read\n * @param pageSizes - Optional page sizes configuration\n */\nexport async function getTeamMembers(\n client: typeof graphql,\n org: string,\n teamSlug: string,\n pageSizes: GithubPageSizes = DEFAULT_PAGE_SIZES,\n): Promise<{ members: GithubUser[] }> {\n const query = `\n query members($org: String!, $teamSlug: String!, $cursor: String, $membersPageSize: Int!) {\n organization(login: $org) {\n team(slug: $teamSlug) {\n members(first: $membersPageSize, after: $cursor, membership: IMMEDIATE) {\n pageInfo { hasNextPage, endCursor }\n nodes { login }\n }\n }\n }\n }`;\n\n const members = await queryWithPaging(\n client,\n query,\n org,\n r => r.organization?.team?.members,\n async user => user,\n { org, teamSlug, membersPageSize: pageSizes.teamMembers },\n );\n\n return { members };\n}\n\n//\n// Helpers\n//\n\n/**\n * Assists in repeatedly executing a query with a paged response.\n *\n * Requires that the query accepts a $cursor variable.\n *\n * @param client - The octokit client\n * @param query - The query to execute\n * @param org - The slug of the org to read\n * @param connection - A function that, given the response, picks out the actual\n * Connection object that's being iterated\n * @param transformer - A function that, given one of the nodes in the Connection,\n * returns the model mapped form of it\n * @param variables - The variable values that the query needs, minus the cursor\n */\nexport async function queryWithPaging<\n GraphqlType,\n OutputType,\n Variables extends {},\n Response = QueryResponse,\n>(\n client: typeof graphql,\n query: string,\n org: string,\n connection: (response: Response) => Connection<GraphqlType> | undefined,\n transformer: (\n item: GraphqlType,\n ctx: TransformerContext,\n ) => Promise<OutputType | undefined>,\n variables: Variables,\n): Promise<OutputType[]> {\n const result: OutputType[] = [];\n const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));\n\n let cursor: string | undefined = undefined;\n for (let j = 0; j < 1000 /* just for sanity */; ++j) {\n const response: Response = await client(query, {\n ...variables,\n cursor,\n });\n\n const conn = connection(response);\n if (!conn) {\n throw new Error(`Found no match for ${JSON.stringify(variables)}`);\n }\n\n for (const node of conn.nodes) {\n const transformedNode = await transformer(node, {\n client,\n query,\n org,\n });\n\n if (transformedNode) {\n result.push(transformedNode);\n }\n }\n\n if (!conn.pageInfo.hasNextPage) {\n break;\n } else {\n await sleep(1000);\n cursor = conn.pageInfo.endCursor;\n }\n }\n\n return result;\n}\n\nexport type DeferredEntitiesBuilder = (\n org: string,\n entities: Entity[],\n) => { added: DeferredEntity[]; removed: DeferredEntity[] };\n\nexport const createAddEntitiesOperation =\n (id: string, host: string) => (org: string, entities: Entity[]) => ({\n removed: [],\n added: entities.map(entity => ({\n locationKey: `github-org-provider:${id}`,\n entity: withLocations(`https://${host}`, org, entity),\n })),\n });\n\nexport const createRemoveEntitiesOperation =\n (id: string, host: string) => (org: string, entities: Entity[]) => ({\n added: [],\n removed: entities.map(entity => ({\n locationKey: `github-org-provider:${id}`,\n entity: withLocations(`https://${host}`, org, entity),\n })),\n });\n\nexport const createReplaceEntitiesOperation =\n (id: string, host: string) => (org: string, entities: Entity[]) => {\n const entitiesToReplace = entities.map(entity => ({\n locationKey: `github-org-provider:${id}`,\n entity: withLocations(`https://${host}`, org, entity),\n }));\n\n return {\n removed: entitiesToReplace,\n added: entitiesToReplace,\n };\n };\n\n/**\n * Creates a GraphQL Client with Throttling\n */\nexport const createGraphqlClient = (args: {\n headers:\n | {\n [name: string]: string;\n }\n | undefined;\n baseUrl: string;\n logger: LoggerService;\n}): typeof graphql => {\n const { headers, baseUrl, logger } = args;\n const ThrottledOctokit = Octokit.plugin(throttling);\n const octokit = new ThrottledOctokit({\n throttle: {\n onRateLimit: (retryAfter, rateLimitData, _, retryCount) => {\n logger.warn(\n `Request quota exhausted for request ${rateLimitData?.method} ${rateLimitData?.url}`,\n );\n\n if (retryCount < 2) {\n logger.warn(\n `Retrying after ${retryAfter} seconds for the ${retryCount} time due to Rate Limit!`,\n );\n return true;\n }\n\n return false;\n },\n onSecondaryRateLimit: (retryAfter, rateLimitData, _, retryCount) => {\n logger.warn(\n `Secondary Rate Limit Exhausted for request ${rateLimitData?.method} ${rateLimitData?.url}`,\n );\n\n if (retryCount < 2) {\n logger.warn(\n `Retrying after ${retryAfter} seconds for the ${retryCount} time due to Secondary Rate Limit!`,\n );\n return true;\n }\n\n return false;\n },\n },\n });\n\n const client = octokit.graphql.defaults({\n headers,\n baseUrl,\n });\n\n return client;\n};\n"],"names":["defaultUserTransformer","defaultOrganizationTeamTransformer","team","withLocations","Octokit","throttling"],"mappings":"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"}
@@ -151,7 +151,16 @@ class GithubEntityProvider {
151
151
  let repositories = [];
152
152
  for (const organization of organizations) {
153
153
  const client = await this.createGraphqlClient(organization);
154
- const { repositories: repositoriesFromGithub } = await github.getOrganizationRepositories(client, organization, catalogPath);
154
+ const pageSizes = {
155
+ ...github.DEFAULT_PAGE_SIZES,
156
+ ...this.config.pageSizes
157
+ };
158
+ const { repositories: repositoriesFromGithub } = await github.getOrganizationRepositories(
159
+ client,
160
+ organization,
161
+ catalogPath,
162
+ pageSizes
163
+ );
155
164
  repositories = repositories.concat(
156
165
  repositoriesFromGithub.map(
157
166
  (r) => this.createRepoFromGithubResponse(r, organization)