@red-hat-developer-hub/backstage-plugin-bulk-import-backend 5.0.1

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 (56) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +161 -0
  3. package/app-config.yaml +0 -0
  4. package/config.d.ts +17 -0
  5. package/dist/catalog/catalogHttpClient.cjs.js +284 -0
  6. package/dist/catalog/catalogHttpClient.cjs.js.map +1 -0
  7. package/dist/catalog/catalogInfoGenerator.cjs.js +60 -0
  8. package/dist/catalog/catalogInfoGenerator.cjs.js.map +1 -0
  9. package/dist/catalog/catalogUtils.cjs.js +34 -0
  10. package/dist/catalog/catalogUtils.cjs.js.map +1 -0
  11. package/dist/generated/openapidocument.cjs.js +1168 -0
  12. package/dist/generated/openapidocument.cjs.js.map +1 -0
  13. package/dist/github/GithubAppManager.cjs.js +395 -0
  14. package/dist/github/GithubAppManager.cjs.js.map +1 -0
  15. package/dist/github/githubApiService.cjs.js +659 -0
  16. package/dist/github/githubApiService.cjs.js.map +1 -0
  17. package/dist/github/types.cjs.js +8 -0
  18. package/dist/github/types.cjs.js.map +1 -0
  19. package/dist/github/utils/ghUtils.cjs.js +103 -0
  20. package/dist/github/utils/ghUtils.cjs.js.map +1 -0
  21. package/dist/github/utils/orgUtils.cjs.js +151 -0
  22. package/dist/github/utils/orgUtils.cjs.js.map +1 -0
  23. package/dist/github/utils/prUtils.cjs.js +85 -0
  24. package/dist/github/utils/prUtils.cjs.js.map +1 -0
  25. package/dist/github/utils/repoUtils.cjs.js +307 -0
  26. package/dist/github/utils/repoUtils.cjs.js.map +1 -0
  27. package/dist/github/utils/utils.cjs.js +206 -0
  28. package/dist/github/utils/utils.cjs.js.map +1 -0
  29. package/dist/helpers/auditLogUtils.cjs.js +112 -0
  30. package/dist/helpers/auditLogUtils.cjs.js.map +1 -0
  31. package/dist/helpers/auth.cjs.js +36 -0
  32. package/dist/helpers/auth.cjs.js.map +1 -0
  33. package/dist/helpers/loggingUtils.cjs.js +19 -0
  34. package/dist/helpers/loggingUtils.cjs.js.map +1 -0
  35. package/dist/helpers/pagination.cjs.js +19 -0
  36. package/dist/helpers/pagination.cjs.js.map +1 -0
  37. package/dist/index.cjs.js +12 -0
  38. package/dist/index.cjs.js.map +1 -0
  39. package/dist/index.d.ts +25 -0
  40. package/dist/plugin.cjs.js +54 -0
  41. package/dist/plugin.cjs.js.map +1 -0
  42. package/dist/service/handlers/handlers.cjs.js +8 -0
  43. package/dist/service/handlers/handlers.cjs.js.map +1 -0
  44. package/dist/service/handlers/import/bulkImports.cjs.js +551 -0
  45. package/dist/service/handlers/import/bulkImports.cjs.js.map +1 -0
  46. package/dist/service/handlers/import/importStatus.cjs.js +49 -0
  47. package/dist/service/handlers/import/importStatus.cjs.js.map +1 -0
  48. package/dist/service/handlers/organization/organizations.cjs.js +77 -0
  49. package/dist/service/handlers/organization/organizations.cjs.js.map +1 -0
  50. package/dist/service/handlers/ping/ping.cjs.js +12 -0
  51. package/dist/service/handlers/ping/ping.cjs.js.map +1 -0
  52. package/dist/service/handlers/repository/repositories.cjs.js +99 -0
  53. package/dist/service/handlers/repository/repositories.cjs.js.map +1 -0
  54. package/dist/service/router.cjs.js +324 -0
  55. package/dist/service/router.cjs.js.map +1 -0
  56. package/package.json +110 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"importStatus.cjs.js","sources":["../../../../src/service/handlers/import/importStatus.ts"],"sourcesContent":["/*\n * Copyright 2024 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 type { LoggerService } from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\n\nimport { CatalogHttpClient } from '../../../catalog/catalogHttpClient';\nimport {\n getCatalogFilename,\n getCatalogUrl,\n} from '../../../catalog/catalogUtils';\nimport type { Components } from '../../../generated/openapi';\nimport type { GithubApiService } from '../../../github';\n\nexport async function getImportStatusFromLocations(\n deps: {\n logger: LoggerService;\n config: Config;\n githubApiService: GithubApiService;\n catalogHttpClient: CatalogHttpClient;\n },\n repoUrl: string,\n catalogUrlLocations: string[],\n defaultBranch?: string,\n): Promise<{\n status: Components.Schemas.ImportStatus;\n lastUpdate?: string;\n} | null> {\n return getImportStatusWithCheckerFn(\n deps,\n repoUrl,\n async (catalogUrl: string) => {\n for (const loc of catalogUrlLocations) {\n if (catalogUrl === loc) {\n return true;\n }\n }\n return false;\n },\n defaultBranch,\n );\n}\n\nasync function getImportStatusWithCheckerFn(\n deps: {\n logger: LoggerService;\n config: Config;\n githubApiService: GithubApiService;\n catalogHttpClient: CatalogHttpClient;\n },\n repoUrl: string,\n catalogExistenceCheckFn: (catalogUrl: string) => Promise<boolean>,\n defaultBranch?: string,\n): Promise<{\n status: Components.Schemas.ImportStatus;\n lastUpdate?: string;\n} | null> {\n // Check to see if there are any PR\n const openImportPr = await deps.githubApiService.findImportOpenPr(\n deps.logger,\n {\n repoUrl,\n },\n );\n if (!openImportPr.prUrl) {\n const existsInCatalog = await catalogExistenceCheckFn(\n getCatalogUrl(deps.config, repoUrl, defaultBranch),\n );\n const existsInRepo = await deps.githubApiService.hasFileInRepo({\n repoUrl,\n defaultBranch,\n fileName: getCatalogFilename(deps.config),\n });\n if (existsInCatalog && existsInRepo) {\n // Force a refresh of the Location, so that the entities from the catalog-info.yaml can show up quickly (not guaranteed however).\n await deps.catalogHttpClient.refreshLocationByRepoUrl(\n repoUrl,\n defaultBranch,\n );\n return { status: 'ADDED' };\n }\n return null;\n }\n return { status: 'WAIT_PR_APPROVAL', lastUpdate: openImportPr.lastUpdate };\n}\n"],"names":["getCatalogUrl","getCatalogFilename"],"mappings":";;;;AA2BA,eAAsB,4BACpB,CAAA,IAAA,EAMA,OACA,EAAA,mBAAA,EACA,aAIQ,EAAA;AACR,EAAO,OAAA,4BAAA;AAAA,IACL,IAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAO,UAAuB,KAAA;AAC5B,MAAA,KAAA,MAAW,OAAO,mBAAqB,EAAA;AACrC,QAAA,IAAI,eAAe,GAAK,EAAA;AACtB,UAAO,OAAA,IAAA,CAAA;AAAA,SACT;AAAA,OACF;AACA,MAAO,OAAA,KAAA,CAAA;AAAA,KACT;AAAA,IACA,aAAA;AAAA,GACF,CAAA;AACF,CAAA;AAEA,eAAe,4BACb,CAAA,IAAA,EAMA,OACA,EAAA,uBAAA,EACA,aAIQ,EAAA;AAER,EAAM,MAAA,YAAA,GAAe,MAAM,IAAA,CAAK,gBAAiB,CAAA,gBAAA;AAAA,IAC/C,IAAK,CAAA,MAAA;AAAA,IACL;AAAA,MACE,OAAA;AAAA,KACF;AAAA,GACF,CAAA;AACA,EAAI,IAAA,CAAC,aAAa,KAAO,EAAA;AACvB,IAAA,MAAM,kBAAkB,MAAM,uBAAA;AAAA,MAC5BA,0BAAc,CAAA,IAAA,CAAK,MAAQ,EAAA,OAAA,EAAS,aAAa,CAAA;AAAA,KACnD,CAAA;AACA,IAAA,MAAM,YAAe,GAAA,MAAM,IAAK,CAAA,gBAAA,CAAiB,aAAc,CAAA;AAAA,MAC7D,OAAA;AAAA,MACA,aAAA;AAAA,MACA,QAAA,EAAUC,+BAAmB,CAAA,IAAA,CAAK,MAAM,CAAA;AAAA,KACzC,CAAA,CAAA;AACD,IAAA,IAAI,mBAAmB,YAAc,EAAA;AAEnC,MAAA,MAAM,KAAK,iBAAkB,CAAA,wBAAA;AAAA,QAC3B,OAAA;AAAA,QACA,aAAA;AAAA,OACF,CAAA;AACA,MAAO,OAAA,EAAE,QAAQ,OAAQ,EAAA,CAAA;AAAA,KAC3B;AACA,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AACA,EAAA,OAAO,EAAE,MAAA,EAAQ,kBAAoB,EAAA,UAAA,EAAY,aAAa,UAAW,EAAA,CAAA;AAC3E;;;;"}
@@ -0,0 +1,77 @@
1
+ 'use strict';
2
+
3
+ var handlers = require('../handlers.cjs.js');
4
+
5
+ async function findAllOrganizations(logger, githubApiService, search, pageNumber = handlers.DefaultPageNumber, pageSize = handlers.DefaultPageSize) {
6
+ logger.debug(
7
+ `Getting all organizations (search,page,size)=('${search ?? ""}',${pageNumber},${pageSize})..`
8
+ );
9
+ const allOrgsAccessible = await githubApiService.getOrganizationsFromIntegrations(
10
+ search,
11
+ pageNumber,
12
+ pageSize
13
+ );
14
+ const errorList = [];
15
+ for (const err of allOrgsAccessible.errors ?? []) {
16
+ if (err.error?.message) {
17
+ errorList.push(err.error.message);
18
+ }
19
+ }
20
+ if (allOrgsAccessible.organizations?.length === 0 && errorList.length > 0) {
21
+ return {
22
+ statusCode: 500,
23
+ responseBody: {
24
+ errors: errorList
25
+ }
26
+ };
27
+ }
28
+ const orgMap = extractOrgMap(allOrgsAccessible);
29
+ const organizations = sortOrgs(orgMap);
30
+ return {
31
+ statusCode: 200,
32
+ responseBody: {
33
+ errors: errorList,
34
+ organizations,
35
+ totalCount: allOrgsAccessible.totalCount,
36
+ pagePerIntegration: pageNumber,
37
+ sizePerIntegration: pageSize
38
+ }
39
+ };
40
+ }
41
+ function extractOrgMap(allOrgsAccessible) {
42
+ const orgMap = /* @__PURE__ */ new Map();
43
+ for (const org of allOrgsAccessible.organizations ?? []) {
44
+ let totalRepoCount;
45
+ if (org.public_repos !== void 0 || org.total_private_repos !== void 0 || org.owned_private_repos !== void 0) {
46
+ totalRepoCount = (org.public_repos ?? 0) + (org.owned_private_repos ?? org.total_private_repos ?? 0);
47
+ }
48
+ orgMap.set(org.name, {
49
+ id: `${org.id}`,
50
+ name: org.name,
51
+ description: org.description,
52
+ url: org.url,
53
+ totalRepoCount,
54
+ errors: []
55
+ });
56
+ }
57
+ return orgMap;
58
+ }
59
+ function sortOrgs(orgMap) {
60
+ const organizations = Array.from(orgMap.values());
61
+ organizations.sort((a, b) => {
62
+ if (a.name === void 0 && b.name === void 0) {
63
+ return 0;
64
+ }
65
+ if (a.name === void 0) {
66
+ return -1;
67
+ }
68
+ if (b.name === void 0) {
69
+ return 1;
70
+ }
71
+ return a.name.localeCompare(b.name);
72
+ });
73
+ return organizations;
74
+ }
75
+
76
+ exports.findAllOrganizations = findAllOrganizations;
77
+ //# sourceMappingURL=organizations.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organizations.cjs.js","sources":["../../../../src/service/handlers/organization/organizations.ts"],"sourcesContent":["/*\n * Copyright 2024 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 type { LoggerService } from '@backstage/backend-plugin-api';\n\nimport type { Components } from '../../../generated/openapi';\nimport type {\n GithubApiService,\n GithubOrganizationResponse,\n} from '../../../github';\nimport {\n DefaultPageNumber,\n DefaultPageSize,\n type HandlerResponse,\n} from '../handlers';\n\nexport async function findAllOrganizations(\n logger: LoggerService,\n githubApiService: GithubApiService,\n search?: string,\n pageNumber: number = DefaultPageNumber,\n pageSize: number = DefaultPageSize,\n): Promise<HandlerResponse<Components.Schemas.OrganizationList>> {\n logger.debug(\n `Getting all organizations (search,page,size)=('${\n search ?? ''\n }',${pageNumber},${pageSize})..`,\n );\n const allOrgsAccessible =\n await githubApiService.getOrganizationsFromIntegrations(\n search,\n pageNumber,\n pageSize,\n );\n const errorList: string[] = [];\n for (const err of allOrgsAccessible.errors ?? []) {\n if (err.error?.message) {\n errorList.push(err.error.message);\n }\n }\n if (allOrgsAccessible.organizations?.length === 0 && errorList.length > 0) {\n return {\n statusCode: 500,\n responseBody: {\n errors: errorList,\n },\n };\n }\n\n const orgMap = extractOrgMap(allOrgsAccessible);\n\n // sorting the output to make it deterministic and easy to navigate in the UI\n const organizations = sortOrgs(orgMap);\n\n return {\n statusCode: 200,\n responseBody: {\n errors: errorList,\n organizations,\n totalCount: allOrgsAccessible.totalCount,\n pagePerIntegration: pageNumber,\n sizePerIntegration: pageSize,\n },\n };\n}\n\nfunction extractOrgMap(allOrgsAccessible: GithubOrganizationResponse) {\n const orgMap = new Map<string, Components.Schemas.Organization>();\n for (const org of allOrgsAccessible.organizations ?? []) {\n let totalRepoCount: number | undefined;\n if (\n org.public_repos !== undefined ||\n org.total_private_repos !== undefined ||\n org.owned_private_repos !== undefined\n ) {\n totalRepoCount =\n (org.public_repos ?? 0) +\n (org.owned_private_repos ?? org.total_private_repos ?? 0);\n }\n orgMap.set(org.name, {\n id: `${org.id}`,\n name: org.name,\n description: org.description,\n url: org.url,\n totalRepoCount,\n errors: [],\n });\n }\n return orgMap;\n}\n\nfunction sortOrgs(orgMap: Map<string, Components.Schemas.Organization>) {\n const organizations = Array.from(orgMap.values());\n organizations.sort((a, b) => {\n if (a.name === undefined && b.name === undefined) {\n return 0;\n }\n if (a.name === undefined) {\n return -1;\n }\n if (b.name === undefined) {\n return 1;\n }\n return a.name.localeCompare(b.name);\n });\n return organizations;\n}\n"],"names":["DefaultPageNumber","DefaultPageSize"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ async function ping(logger) {
4
+ logger.debug("PONG!");
5
+ return {
6
+ statusCode: 200,
7
+ responseBody: { status: "ok" }
8
+ };
9
+ }
10
+
11
+ exports.ping = ping;
12
+ //# sourceMappingURL=ping.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ping.cjs.js","sources":["../../../../src/service/handlers/ping/ping.ts"],"sourcesContent":["/*\n * Copyright 2024 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 type { LoggerService } from '@backstage/backend-plugin-api';\n\nimport type { Paths } from '../../../generated/openapi';\nimport type { HandlerResponse } from '../handlers';\n\nexport async function ping(\n logger: LoggerService,\n): Promise<HandlerResponse<Paths.Ping.Responses.$200>> {\n logger.debug('PONG!');\n return {\n statusCode: 200,\n responseBody: { status: 'ok' },\n };\n}\n"],"names":[],"mappings":";;AAqBA,eAAsB,KACpB,MACqD,EAAA;AACrD,EAAA,MAAA,CAAO,MAAM,OAAO,CAAA,CAAA;AACpB,EAAO,OAAA;AAAA,IACL,UAAY,EAAA,GAAA;AAAA,IACZ,YAAA,EAAc,EAAE,MAAA,EAAQ,IAAK,EAAA;AAAA,GAC/B,CAAA;AACF;;;;"}
@@ -0,0 +1,99 @@
1
+ 'use strict';
2
+
3
+ var gitUrlParse = require('git-url-parse');
4
+ var handlers = require('../handlers.cjs.js');
5
+ require('@backstage/errors');
6
+ require('@backstage/plugin-permission-common');
7
+ require('@red-hat-developer-hub/backstage-plugin-bulk-import-common');
8
+ var importStatus = require('../import/importStatus.cjs.js');
9
+
10
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
11
+
12
+ var gitUrlParse__default = /*#__PURE__*/_interopDefaultCompat(gitUrlParse);
13
+
14
+ async function findAllRepositories(deps, reqParams) {
15
+ const search = reqParams?.search;
16
+ const checkStatus = reqParams?.checkStatus ?? false;
17
+ const pageNumber = reqParams?.pageNumber ?? handlers.DefaultPageNumber;
18
+ const pageSize = reqParams?.pageSize ?? handlers.DefaultPageSize;
19
+ deps.logger.debug(
20
+ `Getting all repositories - (search,page,size)=('${search ?? ""}',${pageNumber},${pageSize})..`
21
+ );
22
+ return deps.githubApiService.getRepositoriesFromIntegrations(search, pageNumber, pageSize).then((response) => formatResponse(deps, response, checkStatus));
23
+ }
24
+ async function findRepositoriesByOrganization(deps, orgName, search, checkStatus = false, pageNumber = handlers.DefaultPageNumber, pageSize = handlers.DefaultPageSize) {
25
+ deps.logger.debug(
26
+ `Getting all repositories for org "${orgName}" - (search,page,size)=(${search},${pageNumber},${pageSize})..`
27
+ );
28
+ return deps.githubApiService.getOrgRepositoriesFromIntegrations(orgName, search, pageNumber, pageSize).then((response) => formatResponse(deps, response, checkStatus));
29
+ }
30
+ function sortRepos(repoList) {
31
+ repoList.sort((a, b) => {
32
+ if (a.name === void 0 && b.name === void 0) {
33
+ return 0;
34
+ }
35
+ if (a.name === void 0) {
36
+ return -1;
37
+ }
38
+ if (b.name === void 0) {
39
+ return 1;
40
+ }
41
+ return a.name.localeCompare(b.name);
42
+ });
43
+ }
44
+ async function formatResponse(deps, allReposAccessible, checkStatus) {
45
+ const errorList = allReposAccessible.errors?.map((err) => err.error?.message)?.filter((msg) => msg) ?? [];
46
+ if (allReposAccessible.repositories?.length === 0 && errorList.length > 0) {
47
+ return {
48
+ statusCode: 500,
49
+ responseBody: {
50
+ errors: errorList
51
+ }
52
+ };
53
+ }
54
+ let catalogLocations = [];
55
+ if (checkStatus) {
56
+ catalogLocations = (await deps.catalogHttpClient.listCatalogUrlLocations()).targetUrls;
57
+ }
58
+ const repoList = [];
59
+ for (const repo of allReposAccessible.repositories) {
60
+ const gitUrl = gitUrlParse__default.default(repo.html_url);
61
+ const errors = [];
62
+ let importStatus$1;
63
+ if (checkStatus) {
64
+ importStatus$1 = await importStatus.getImportStatusFromLocations(
65
+ deps,
66
+ repo.html_url,
67
+ catalogLocations,
68
+ repo.default_branch
69
+ ).catch((error) => {
70
+ errors.push(error.message);
71
+ return void 0;
72
+ });
73
+ }
74
+ const repoUpdatedAt = repo.updated_at ?? void 0;
75
+ repoList.push({
76
+ id: `${gitUrl.organization}/${repo.name}`,
77
+ name: repo.name,
78
+ organization: gitUrl.organization,
79
+ url: repo.html_url,
80
+ defaultBranch: repo.default_branch,
81
+ importStatus: importStatus$1?.status,
82
+ lastUpdate: importStatus$1?.lastUpdate ?? repoUpdatedAt,
83
+ errors
84
+ });
85
+ }
86
+ sortRepos(repoList);
87
+ return {
88
+ statusCode: 200,
89
+ responseBody: {
90
+ errors: errorList,
91
+ repositories: repoList,
92
+ totalCount: allReposAccessible.totalCount
93
+ }
94
+ };
95
+ }
96
+
97
+ exports.findAllRepositories = findAllRepositories;
98
+ exports.findRepositoriesByOrganization = findRepositoriesByOrganization;
99
+ //# sourceMappingURL=repositories.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositories.cjs.js","sources":["../../../../src/service/handlers/repository/repositories.ts"],"sourcesContent":["/*\n * Copyright 2024 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 type { LoggerService } from '@backstage/backend-plugin-api';\nimport type { Config } from '@backstage/config';\n\nimport gitUrlParse from 'git-url-parse';\n\nimport { CatalogHttpClient } from '../../../catalog/catalogHttpClient';\nimport type { Components } from '../../../generated/openapi';\nimport type {\n GithubApiService,\n GithubRepositoryResponse,\n} from '../../../github';\nimport {\n DefaultPageNumber,\n DefaultPageSize,\n type HandlerResponse,\n} from '../handlers';\nimport { getImportStatusFromLocations } from '../import';\n\nexport async function findAllRepositories(\n deps: {\n logger: LoggerService;\n config: Config;\n githubApiService: GithubApiService;\n catalogHttpClient: CatalogHttpClient;\n },\n reqParams?: {\n search?: string;\n checkStatus?: boolean;\n pageNumber?: number;\n pageSize?: number;\n },\n): Promise<HandlerResponse<Components.Schemas.RepositoryList>> {\n const search = reqParams?.search;\n const checkStatus = reqParams?.checkStatus ?? false;\n const pageNumber = reqParams?.pageNumber ?? DefaultPageNumber;\n const pageSize = reqParams?.pageSize ?? DefaultPageSize;\n deps.logger.debug(\n `Getting all repositories - (search,page,size)=('${\n search ?? ''\n }',${pageNumber},${pageSize})..`,\n );\n return deps.githubApiService\n .getRepositoriesFromIntegrations(search, pageNumber, pageSize)\n .then(response => formatResponse(deps, response, checkStatus));\n}\n\nexport async function findRepositoriesByOrganization(\n deps: {\n logger: LoggerService;\n config: Config;\n githubApiService: GithubApiService;\n catalogHttpClient: CatalogHttpClient;\n },\n orgName: string,\n search?: string,\n checkStatus: boolean = false,\n pageNumber: number = DefaultPageNumber,\n pageSize: number = DefaultPageSize,\n): Promise<HandlerResponse<Components.Schemas.RepositoryList>> {\n deps.logger.debug(\n `Getting all repositories for org \"${orgName}\" - (search,page,size)=(${search},${pageNumber},${pageSize})..`,\n );\n return deps.githubApiService\n .getOrgRepositoriesFromIntegrations(orgName, search, pageNumber, pageSize)\n .then(response => formatResponse(deps, response, checkStatus));\n}\n\nfunction sortRepos(repoList: Components.Schemas.Repository[]) {\n // sorting the output to make it deterministic and easy to navigate in the UI\n repoList.sort((a, b) => {\n if (a.name === undefined && b.name === undefined) {\n return 0;\n }\n if (a.name === undefined) {\n return -1;\n }\n if (b.name === undefined) {\n return 1;\n }\n return a.name.localeCompare(b.name);\n });\n}\n\ntype ImportStatus =\n | { status: Components.Schemas.ImportStatus; lastUpdate?: string }\n | null\n | undefined;\n\nasync function formatResponse(\n deps: {\n logger: LoggerService;\n config: Config;\n githubApiService: GithubApiService;\n catalogHttpClient: CatalogHttpClient;\n },\n allReposAccessible: GithubRepositoryResponse,\n checkStatus: boolean,\n) {\n const errorList =\n allReposAccessible.errors\n ?.map(err => err.error?.message)\n ?.filter(msg => msg) ?? [];\n if (allReposAccessible.repositories?.length === 0 && errorList.length > 0) {\n return {\n statusCode: 500,\n responseBody: {\n errors: errorList,\n },\n };\n }\n\n let catalogLocations: string[] = [];\n if (checkStatus) {\n catalogLocations = (await deps.catalogHttpClient.listCatalogUrlLocations())\n .targetUrls;\n }\n const repoList: Components.Schemas.Repository[] = [];\n for (const repo of allReposAccessible.repositories) {\n const gitUrl = gitUrlParse(repo.html_url);\n const errors: string[] = [];\n let importStatus: ImportStatus;\n if (checkStatus) {\n importStatus = await getImportStatusFromLocations(\n deps,\n repo.html_url,\n catalogLocations,\n repo.default_branch,\n ).catch((error: any) => {\n errors.push(error.message);\n return undefined;\n });\n }\n const repoUpdatedAt = repo.updated_at ?? undefined;\n repoList.push({\n id: `${gitUrl.organization}/${repo.name}`,\n name: repo.name,\n organization: gitUrl.organization,\n url: repo.html_url,\n defaultBranch: repo.default_branch,\n importStatus: importStatus?.status,\n lastUpdate: importStatus?.lastUpdate ?? repoUpdatedAt,\n errors: errors,\n });\n }\n\n sortRepos(repoList);\n\n return {\n statusCode: 200,\n responseBody: {\n errors: errorList,\n repositories: repoList,\n totalCount: allReposAccessible.totalCount,\n },\n };\n}\n"],"names":["DefaultPageNumber","DefaultPageSize","gitUrlParse","importStatus","getImportStatusFromLocations"],"mappings":"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"}
@@ -0,0 +1,324 @@
1
+ 'use strict';
2
+
3
+ var rootHttpRouter = require('@backstage/backend-defaults/rootHttpRouter');
4
+ var pluginPermissionNode = require('@backstage/plugin-permission-node');
5
+ var backstagePluginAuditLogNode = require('@janus-idp/backstage-plugin-audit-log-node');
6
+ var formats = require('ajv-formats/dist/formats');
7
+ var express = require('express');
8
+ var openapiBackend = require('openapi-backend');
9
+ var backstagePluginBulkImportCommon = require('@red-hat-developer-hub/backstage-plugin-bulk-import-common');
10
+ var catalogHttpClient = require('../catalog/catalogHttpClient.cjs.js');
11
+ var catalogInfoGenerator = require('../catalog/catalogInfoGenerator.cjs.js');
12
+ var openapidocument = require('../generated/openapidocument.cjs.js');
13
+ require('@octokit/auth-app');
14
+ require('@octokit/rest');
15
+ require('git-url-parse');
16
+ require('luxon');
17
+ var githubApiService = require('../github/githubApiService.cjs.js');
18
+ var auth = require('../helpers/auth.cjs.js');
19
+ require('@backstage/errors');
20
+ var auditLogUtils = require('../helpers/auditLogUtils.cjs.js');
21
+ var bulkImports = require('./handlers/import/bulkImports.cjs.js');
22
+ var organizations = require('./handlers/organization/organizations.cjs.js');
23
+ var ping = require('./handlers/ping/ping.cjs.js');
24
+ var repositories = require('./handlers/repository/repositories.cjs.js');
25
+
26
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
27
+
28
+ var express__default = /*#__PURE__*/_interopDefaultCompat(express);
29
+
30
+ async function createRouter(options) {
31
+ const {
32
+ logger,
33
+ httpAuth,
34
+ auth: auth$1,
35
+ permissions,
36
+ config,
37
+ cache,
38
+ discovery,
39
+ catalogApi
40
+ } = options;
41
+ const auditLogger = new backstagePluginAuditLogNode.DefaultAuditLogger({
42
+ logger,
43
+ authService: auth$1,
44
+ httpAuthService: httpAuth
45
+ });
46
+ const githubApiService$1 = new githubApiService.GithubApiService(logger, config, cache);
47
+ const catalogHttpClient$1 = new catalogHttpClient.CatalogHttpClient({
48
+ logger,
49
+ config,
50
+ discovery,
51
+ auth: auth$1,
52
+ catalogApi
53
+ });
54
+ const catalogInfoGenerator$1 = new catalogInfoGenerator.CatalogInfoGenerator(
55
+ logger,
56
+ catalogHttpClient$1
57
+ );
58
+ const api = new openapiBackend.OpenAPIBackend({
59
+ ajvOpts: {
60
+ verbose: true,
61
+ formats: formats.fullFormats
62
+ // open issue: https://github.com/openapistack/openapi-backend/issues/280
63
+ },
64
+ validate: true,
65
+ definition: openapidocument.openApiDocument,
66
+ handlers: {
67
+ validationFail: async (c, _req, res) => res.status(400).json({ err: c.validation.errors }),
68
+ notFound: async (_c, req, res) => res.status(404).json({ err: `'${req.method} ${req.path}' not found` }),
69
+ notImplemented: async (_c, req, res) => res.status(500).json({ err: `'${req.method} ${req.path}' not implemented` })
70
+ }
71
+ });
72
+ await api.init();
73
+ api.register("ping", async (_c, _req, res) => {
74
+ const result = await ping.ping(logger);
75
+ return res.status(result.statusCode).json(result.responseBody);
76
+ });
77
+ api.register(
78
+ "findAllOrganizations",
79
+ async (c, _req, res) => {
80
+ const q = {
81
+ ...c.request.query
82
+ };
83
+ q.pagePerIntegration = stringToNumber(q.pagePerIntegration);
84
+ q.sizePerIntegration = stringToNumber(q.sizePerIntegration);
85
+ const response = await organizations.findAllOrganizations(
86
+ logger,
87
+ githubApiService$1,
88
+ q.search,
89
+ q.pagePerIntegration,
90
+ q.sizePerIntegration
91
+ );
92
+ return res.status(response.statusCode).json({
93
+ errors: response.responseBody?.errors,
94
+ organizations: response.responseBody?.organizations,
95
+ totalCount: response.responseBody?.totalCount,
96
+ pagePerIntegration: response.responseBody?.pagePerIntegration,
97
+ sizePerIntegration: response.responseBody?.sizePerIntegration
98
+ });
99
+ }
100
+ );
101
+ api.register(
102
+ "findAllRepositories",
103
+ async (c, _req, res) => {
104
+ const q = {
105
+ ...c.request.query
106
+ };
107
+ q.pagePerIntegration = stringToNumber(q.pagePerIntegration);
108
+ q.sizePerIntegration = stringToNumber(q.sizePerIntegration);
109
+ q.checkImportStatus = stringToBoolean(q.checkImportStatus);
110
+ const response = await repositories.findAllRepositories(
111
+ {
112
+ logger,
113
+ config,
114
+ githubApiService: githubApiService$1,
115
+ catalogHttpClient: catalogHttpClient$1
116
+ },
117
+ {
118
+ search: q.search,
119
+ checkStatus: q.checkImportStatus,
120
+ pageNumber: q.pagePerIntegration,
121
+ pageSize: q.sizePerIntegration
122
+ }
123
+ );
124
+ const repos = response.responseBody?.repositories;
125
+ return res.status(response.statusCode).json({
126
+ errors: response.responseBody?.errors,
127
+ repositories: repos,
128
+ totalCount: response.responseBody?.totalCount,
129
+ pagePerIntegration: q.pagePerIntegration,
130
+ sizePerIntegration: q.sizePerIntegration
131
+ });
132
+ }
133
+ );
134
+ api.register(
135
+ "findRepositoriesByOrganization",
136
+ async (c, _req, res) => {
137
+ const q = {
138
+ ...c.request.query
139
+ };
140
+ q.pagePerIntegration = stringToNumber(q.pagePerIntegration);
141
+ q.sizePerIntegration = stringToNumber(q.sizePerIntegration);
142
+ q.checkImportStatus = stringToBoolean(q.checkImportStatus);
143
+ const response = await repositories.findRepositoriesByOrganization(
144
+ {
145
+ logger,
146
+ config,
147
+ githubApiService: githubApiService$1,
148
+ catalogHttpClient: catalogHttpClient$1
149
+ },
150
+ c.request.params.organizationName?.toString(),
151
+ q.search,
152
+ q.checkImportStatus,
153
+ q.pagePerIntegration,
154
+ q.sizePerIntegration
155
+ );
156
+ const repos = response.responseBody?.repositories;
157
+ return res.status(response.statusCode).json({
158
+ errors: response.responseBody?.errors,
159
+ repositories: repos,
160
+ totalCount: response.responseBody?.totalCount,
161
+ pagePerIntegration: q.pagePerIntegration,
162
+ sizePerIntegration: q.sizePerIntegration
163
+ });
164
+ }
165
+ );
166
+ api.register(
167
+ "findAllImports",
168
+ async (c, _req, res) => {
169
+ const h = {
170
+ ...c.request.headers
171
+ };
172
+ const apiVersion = h["api-version"];
173
+ const q = {
174
+ ...c.request.query
175
+ };
176
+ let page;
177
+ let size;
178
+ if (apiVersion === void 0 || apiVersion === "v1") {
179
+ page = stringToNumber(q.page || q.pagePerIntegration);
180
+ size = stringToNumber(q.size || q.sizePerIntegration);
181
+ } else {
182
+ page = stringToNumber(q.page);
183
+ size = stringToNumber(q.size);
184
+ }
185
+ const response = await bulkImports.findAllImports(
186
+ {
187
+ logger,
188
+ config,
189
+ githubApiService: githubApiService$1,
190
+ catalogHttpClient: catalogHttpClient$1
191
+ },
192
+ {
193
+ apiVersion
194
+ },
195
+ {
196
+ search: q.search,
197
+ pageNumber: page,
198
+ pageSize: size
199
+ }
200
+ );
201
+ return res.status(response.statusCode).json(response.responseBody);
202
+ }
203
+ );
204
+ api.register(
205
+ "createImportJobs",
206
+ async (c, _req, res) => {
207
+ const q = {
208
+ ...c.request.query
209
+ };
210
+ q.dryRun = stringToBoolean(q.dryRun);
211
+ const response = await bulkImports.createImportJobs(
212
+ {
213
+ logger,
214
+ config,
215
+ auth: auth$1,
216
+ catalogApi,
217
+ githubApiService: githubApiService$1,
218
+ catalogInfoGenerator: catalogInfoGenerator$1,
219
+ catalogHttpClient: catalogHttpClient$1
220
+ },
221
+ {
222
+ importRequests: c.request.requestBody,
223
+ dryRun: q.dryRun
224
+ }
225
+ );
226
+ return res.status(response.statusCode).json(response.responseBody);
227
+ }
228
+ );
229
+ api.register(
230
+ "findImportStatusByRepo",
231
+ async (c, _req, res) => {
232
+ const q = {
233
+ ...c.request.query
234
+ };
235
+ if (!q.repo?.trim()) {
236
+ throw new Error("missing or blank parameter");
237
+ }
238
+ const response = await bulkImports.findImportStatusByRepo(
239
+ {
240
+ logger,
241
+ config,
242
+ githubApiService: githubApiService$1,
243
+ catalogHttpClient: catalogHttpClient$1
244
+ },
245
+ q.repo,
246
+ q.defaultBranch,
247
+ true
248
+ );
249
+ return res.status(response.statusCode).json(response.responseBody);
250
+ }
251
+ );
252
+ api.register(
253
+ "deleteImportByRepo",
254
+ async (c, _req, res) => {
255
+ const q = {
256
+ ...c.request.query
257
+ };
258
+ if (!q.repo?.trim()) {
259
+ throw new Error('missing or blank "repo" parameter');
260
+ }
261
+ const response = await bulkImports.deleteImportByRepo(
262
+ {
263
+ logger,
264
+ config,
265
+ githubApiService: githubApiService$1,
266
+ catalogHttpClient: catalogHttpClient$1
267
+ },
268
+ q.repo,
269
+ q.defaultBranch
270
+ );
271
+ return res.status(response.statusCode).json(response.responseBody);
272
+ }
273
+ );
274
+ const router = express.Router();
275
+ router.use(express__default.default.json());
276
+ const permissionIntegrationRouter = pluginPermissionNode.createPermissionIntegrationRouter({
277
+ permissions: [backstagePluginBulkImportCommon.bulkImportPermission]
278
+ });
279
+ router.use(permissionIntegrationRouter);
280
+ router.use(async (req, _res, next) => {
281
+ if (req.path !== "/ping") {
282
+ await auth.permissionCheck(
283
+ auditLogger,
284
+ api.matchOperation(req)?.operationId,
285
+ permissions,
286
+ httpAuth,
287
+ req
288
+ ).catch(next);
289
+ }
290
+ next();
291
+ });
292
+ router.use(async (req, res, next) => {
293
+ const reqCast = req;
294
+ const operationId = api.matchOperation(reqCast)?.operationId;
295
+ try {
296
+ const response = await api.handleRequest(reqCast, req, res);
297
+ auditLogUtils.auditLogRequestSuccess(
298
+ auditLogger,
299
+ operationId,
300
+ req,
301
+ response.statusCode
302
+ );
303
+ next();
304
+ } catch (err) {
305
+ auditLogUtils.auditLogRequestError(auditLogger, operationId, req, err);
306
+ next(err);
307
+ }
308
+ });
309
+ const middleware = rootHttpRouter.MiddlewareFactory.create({ logger, config });
310
+ router.use(middleware.error());
311
+ return router;
312
+ }
313
+ function stringToNumber(s) {
314
+ return s ? Number.parseInt(s.toString(), 10) : void 0;
315
+ }
316
+ function stringToBoolean(s) {
317
+ if (!s) {
318
+ return void 0;
319
+ }
320
+ return s.toString() === "true";
321
+ }
322
+
323
+ exports.createRouter = createRouter;
324
+ //# sourceMappingURL=router.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport type {\n AuthService,\n CacheService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport type { CatalogApi } from '@backstage/catalog-client';\nimport type { Config } from '@backstage/config';\nimport type { PermissionEvaluator } from '@backstage/plugin-permission-common';\nimport { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node';\n\nimport {\n DefaultAuditLogger,\n type AuditLogger,\n} from '@janus-idp/backstage-plugin-audit-log-node';\nimport { fullFormats } from 'ajv-formats/dist/formats';\nimport express, { Router, type Request, type Response } from 'express';\nimport {\n OpenAPIBackend,\n type Context,\n type Request as OpenAPIRequest,\n} from 'openapi-backend';\n\nimport { bulkImportPermission } from '@red-hat-developer-hub/backstage-plugin-bulk-import-common';\n\nimport { CatalogHttpClient } from '../catalog/catalogHttpClient';\nimport { CatalogInfoGenerator } from '../catalog/catalogInfoGenerator';\nimport type { Components, Paths } from '../generated/openapi.d';\nimport { openApiDocument } from '../generated/openapidocument';\nimport { GithubApiService } from '../github';\nimport { permissionCheck } from '../helpers';\nimport {\n auditLogRequestError,\n auditLogRequestSuccess,\n} from '../helpers/auditLogUtils';\nimport {\n createImportJobs,\n deleteImportByRepo,\n findAllImports,\n findImportStatusByRepo,\n} from './handlers/import';\nimport { findAllOrganizations } from './handlers/organization';\nimport { ping } from './handlers/ping';\nimport {\n findAllRepositories,\n findRepositoriesByOrganization,\n} from './handlers/repository';\n\nexport interface RouterOptions {\n logger: LoggerService;\n permissions: PermissionEvaluator;\n config: Config;\n cache: CacheService;\n discovery: DiscoveryService;\n httpAuth: HttpAuthService;\n auth: AuthService;\n catalogApi: CatalogApi;\n}\n\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const {\n logger,\n httpAuth,\n auth,\n permissions,\n config,\n cache,\n discovery,\n catalogApi,\n } = options;\n\n const auditLogger: AuditLogger = new DefaultAuditLogger({\n logger: logger,\n authService: auth,\n httpAuthService: httpAuth,\n });\n\n const githubApiService = new GithubApiService(logger, config, cache);\n const catalogHttpClient = new CatalogHttpClient({\n logger,\n config,\n discovery,\n auth,\n catalogApi,\n });\n const catalogInfoGenerator = new CatalogInfoGenerator(\n logger,\n catalogHttpClient,\n );\n\n // create openapi requests handler\n const api = new OpenAPIBackend({\n ajvOpts: {\n verbose: true,\n formats: fullFormats, // open issue: https://github.com/openapistack/openapi-backend/issues/280\n },\n validate: true,\n definition: openApiDocument,\n handlers: {\n validationFail: async (c, _req: Request, res: Response) =>\n res.status(400).json({ err: c.validation.errors }),\n notFound: async (_c, req: Request, res: Response) =>\n res.status(404).json({ err: `'${req.method} ${req.path}' not found` }),\n notImplemented: async (_c, req: Request, res: Response) =>\n res\n .status(500)\n .json({ err: `'${req.method} ${req.path}' not implemented` }),\n },\n });\n\n await api.init();\n\n api.register('ping', async (_c: Context, _req: Request, res: Response) => {\n const result = await ping(logger);\n return res.status(result.statusCode).json(result.responseBody);\n });\n\n api.register(\n 'findAllOrganizations',\n async (c: Context, _req: Request, res: Response) => {\n const q: Paths.FindAllOrganizations.QueryParameters = {\n ...c.request.query,\n };\n // we need to convert strings to real types due to open PR https://github.com/openapistack/openapi-backend/pull/571\n q.pagePerIntegration = stringToNumber(q.pagePerIntegration);\n q.sizePerIntegration = stringToNumber(q.sizePerIntegration);\n const response = await findAllOrganizations(\n logger,\n githubApiService,\n q.search,\n q.pagePerIntegration,\n q.sizePerIntegration,\n );\n return res.status(response.statusCode).json({\n errors: response.responseBody?.errors,\n organizations: response.responseBody?.organizations,\n totalCount: response.responseBody?.totalCount,\n pagePerIntegration: response.responseBody?.pagePerIntegration,\n sizePerIntegration: response.responseBody?.sizePerIntegration,\n } as Components.Schemas.OrganizationList);\n },\n );\n\n api.register(\n 'findAllRepositories',\n async (c: Context, _req: Request, res: Response) => {\n const q: Paths.FindAllRepositories.QueryParameters = {\n ...c.request.query,\n };\n // we need to convert strings to real types due to open PR https://github.com/openapistack/openapi-backend/pull/571\n q.pagePerIntegration = stringToNumber(q.pagePerIntegration);\n q.sizePerIntegration = stringToNumber(q.sizePerIntegration);\n q.checkImportStatus = stringToBoolean(q.checkImportStatus);\n const response = await findAllRepositories(\n {\n logger,\n config,\n githubApiService,\n catalogHttpClient,\n },\n {\n search: q.search,\n checkStatus: q.checkImportStatus,\n pageNumber: q.pagePerIntegration,\n pageSize: q.sizePerIntegration,\n },\n );\n const repos = response.responseBody?.repositories;\n return res.status(response.statusCode).json({\n errors: response.responseBody?.errors,\n repositories: repos,\n totalCount: response.responseBody?.totalCount,\n pagePerIntegration: q.pagePerIntegration,\n sizePerIntegration: q.sizePerIntegration,\n } as Components.Schemas.RepositoryList);\n },\n );\n\n api.register(\n 'findRepositoriesByOrganization',\n async (c: Context, _req: Request, res: Response) => {\n const q: Paths.FindRepositoriesByOrganization.QueryParameters = {\n ...c.request.query,\n };\n // we need to convert strings to real types due to open PR https://github.com/openapistack/openapi-backend/pull/571\n q.pagePerIntegration = stringToNumber(q.pagePerIntegration);\n q.sizePerIntegration = stringToNumber(q.sizePerIntegration);\n q.checkImportStatus = stringToBoolean(q.checkImportStatus);\n const response = await findRepositoriesByOrganization(\n {\n logger,\n config,\n githubApiService,\n catalogHttpClient,\n },\n c.request.params.organizationName?.toString(),\n q.search,\n q.checkImportStatus,\n q.pagePerIntegration,\n q.sizePerIntegration,\n );\n const repos = response.responseBody?.repositories;\n return res.status(response.statusCode).json({\n errors: response.responseBody?.errors,\n repositories: repos,\n totalCount: response.responseBody?.totalCount,\n pagePerIntegration: q.pagePerIntegration,\n sizePerIntegration: q.sizePerIntegration,\n } as Components.Schemas.RepositoryList);\n },\n );\n\n api.register(\n 'findAllImports',\n async (c: Context, _req: Request, res: Response) => {\n const h: Paths.FindAllImports.HeaderParameters = {\n ...c.request.headers,\n };\n const apiVersion = h['api-version'];\n const q: Paths.FindAllImports.QueryParameters = {\n ...c.request.query,\n };\n // we need to convert strings to real types due to open PR https://github.com/openapistack/openapi-backend/pull/571\n let page: number | undefined;\n let size: number | undefined;\n if (apiVersion === undefined || apiVersion === 'v1') {\n // pagePerIntegration and sizePerIntegration deprecated in v1. 'page' and 'size' take precedence.\n page = stringToNumber(q.page || q.pagePerIntegration);\n size = stringToNumber(q.size || q.sizePerIntegration);\n } else {\n // pagePerIntegration and sizePerIntegration removed in v2+ and replaced by 'page' and 'size'.\n page = stringToNumber(q.page);\n size = stringToNumber(q.size);\n }\n const response = await findAllImports(\n {\n logger,\n config,\n githubApiService,\n catalogHttpClient,\n },\n {\n apiVersion,\n },\n {\n search: q.search,\n pageNumber: page,\n pageSize: size,\n },\n );\n return res.status(response.statusCode).json(response.responseBody);\n },\n );\n\n api.register(\n 'createImportJobs',\n async (\n c: Context<Paths.CreateImportJobs.RequestBody>,\n _req: Request,\n res: Response,\n ) => {\n const q: Paths.CreateImportJobs.QueryParameters = {\n ...c.request.query,\n };\n q.dryRun = stringToBoolean(q.dryRun);\n const response = await createImportJobs(\n {\n logger,\n config,\n auth,\n catalogApi,\n githubApiService,\n catalogInfoGenerator,\n catalogHttpClient,\n },\n {\n importRequests: c.request.requestBody,\n dryRun: q.dryRun,\n },\n );\n return res.status(response.statusCode).json(response.responseBody);\n },\n );\n\n api.register(\n 'findImportStatusByRepo',\n async (c: Context, _req: Request, res: Response) => {\n const q: Paths.FindImportStatusByRepo.QueryParameters = {\n ...c.request.query,\n };\n if (!q.repo?.trim()) {\n throw new Error('missing or blank parameter');\n }\n const response = await findImportStatusByRepo(\n {\n logger,\n config,\n githubApiService,\n catalogHttpClient,\n },\n q.repo,\n q.defaultBranch,\n true,\n );\n return res.status(response.statusCode).json(response.responseBody);\n },\n );\n\n api.register(\n 'deleteImportByRepo',\n async (c: Context, _req: Request, res: Response) => {\n const q: Paths.DeleteImportByRepo.QueryParameters = {\n ...c.request.query,\n };\n if (!q.repo?.trim()) {\n throw new Error('missing or blank \"repo\" parameter');\n }\n const response = await deleteImportByRepo(\n {\n logger,\n config,\n githubApiService,\n catalogHttpClient,\n },\n q.repo,\n q.defaultBranch,\n );\n return res.status(response.statusCode).json(response.responseBody);\n },\n );\n\n const router = Router();\n router.use(express.json());\n\n const permissionIntegrationRouter = createPermissionIntegrationRouter({\n permissions: [bulkImportPermission],\n });\n router.use(permissionIntegrationRouter);\n\n router.use(async (req, _res, next) => {\n if (req.path !== '/ping') {\n await permissionCheck(\n auditLogger,\n api.matchOperation(req as OpenAPIRequest)?.operationId,\n permissions,\n httpAuth,\n req,\n ).catch(next);\n }\n next();\n });\n\n router.use(async (req, res, next) => {\n const reqCast = req as OpenAPIRequest;\n const operationId = api.matchOperation(reqCast)?.operationId;\n try {\n const response = (await api.handleRequest(reqCast, req, res)) as Response;\n auditLogRequestSuccess(\n auditLogger,\n operationId,\n req,\n response.statusCode,\n );\n next();\n } catch (err: any) {\n auditLogRequestError(auditLogger, operationId, req, err);\n next(err);\n }\n });\n\n const middleware = MiddlewareFactory.create({ logger, config });\n router.use(middleware.error());\n\n return router;\n}\n\nfunction stringToNumber(s: number | undefined): number | undefined {\n return s ? Number.parseInt(s.toString(), 10) : undefined;\n}\n\nfunction stringToBoolean(s: boolean | undefined): boolean | undefined {\n if (!s) {\n return undefined;\n }\n return s.toString() === 'true';\n}\n"],"names":["auth","DefaultAuditLogger","githubApiService","GithubApiService","catalogHttpClient","CatalogHttpClient","catalogInfoGenerator","CatalogInfoGenerator","OpenAPIBackend","fullFormats","openApiDocument","ping","findAllOrganizations","findAllRepositories","findRepositoriesByOrganization","findAllImports","createImportJobs","findImportStatusByRepo","deleteImportByRepo","Router","express","createPermissionIntegrationRouter","bulkImportPermission","permissionCheck","auditLogRequestSuccess","auditLogRequestError","MiddlewareFactory"],"mappings":"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"}