diff --git a/.markdownlint-cli2.jsonc b/.config/.markdownlint-cli2.jsonc similarity index 100% rename from .markdownlint-cli2.jsonc rename to .config/.markdownlint-cli2.jsonc diff --git a/.cspell.json b/.cspell.json index 503a7f3a5..83a11efe1 100644 --- a/.cspell.json +++ b/.cspell.json @@ -33,6 +33,7 @@ "aadname", "aadoid", "aadupn", + "accesslevel", "accountinfo", "accountinformation", "actionperms", @@ -61,6 +62,7 @@ "agreementversion", "alladmins", "allowunlock", + "alreadyrestored", "aosp", "apikey", "APPDIR", @@ -94,6 +96,7 @@ "blockui", "bootswatch", "bootup", + "branchname", "breakingchangereviewrequired", "browserconfig", "builddir", @@ -112,8 +115,8 @@ "CELA", "champscount", "champstatus", - "chromedriver", "checkmarks", + "chromedriver", "citus", "citusdata", "classificationdelegated", @@ -144,6 +147,7 @@ "codespace", "codespaces", "collab", + "collaboratorid", "collabs", "columnbreak", "commitcomment", @@ -162,9 +166,9 @@ "contributionshareoptin", "copilotaccess", "copilotagreement", + "copilotprod", "copilotrequest", "Copybara", - "countuse", "corpnet", "corporatealias", "corporatecount", @@ -176,6 +180,7 @@ "corporatename", "corporateprod", "corporateusername", + "countuse", "createdat", "creategithubaccount", "creds", @@ -213,6 +218,7 @@ "devstaging", "directoryname", "directowners", + "disablewave", "distributeonly", "distro", "divisionid", @@ -347,6 +353,8 @@ "hsts", "Hsts", "HSTS", + "hubber", + "hubbers", "hubot", "IAAD", "ictext", @@ -384,9 +392,9 @@ "issuecomment", "issuesopened", "istest", + "jabberpl", "jeffwilcox", "jitgrants", - "jabberpl", "joblog", "jobname", "json", @@ -395,6 +403,7 @@ "jwilcox", "jwks", "JWTs", + "keybytes", "keyout", "keyvault", "KEYVAULT", @@ -409,6 +418,7 @@ "leftouter", "legalcontact", "legalentities", + "libsodium", "lightup", "linkid", "linkmanager", @@ -506,8 +516,8 @@ "notifiedissueid", "npminitignore", "npminstallignore", - "npmrc", "npmjs", + "npmrc", "nums", "Nunit", "octicon", @@ -674,6 +684,8 @@ "removeothergithubaccount", "REPLYTO", "repocount", + "repodisablebranchprotections", + "repodisableoutsidecollaborators", "repoid", "repoidifyouhaveit", "repolockdown", @@ -724,6 +736,7 @@ "scansummary", "SCIM", "scorecardreprocessrequest", + "secretbox", "secretless", "secretscanningonpush", "secscandata", @@ -774,13 +787,11 @@ "specialteams", "SSIRP", "sslify", - "Sslify", "standardsredirect", "stargazerscount", "startclean", - "StartClean", + "startofday", "startright", - "StartRight", "startswith", "statechecked", "steelblue", @@ -821,6 +832,7 @@ "tlink", "tolower", "Toolset", + "toscalar", "totalcount", "touchedtime", "toupper", @@ -893,9 +905,9 @@ "welcomeemailsent", "whois", "Whois", - "withsource", "withmaintainers", "withservicetree", + "withsource", "wixtoolset", "xamarinhq", "Xcache", diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6f1f143ea..2eb6669f6 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -19,7 +19,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 # Override language selection by uncommenting this and choosing your languages # with: # languages: go, javascript, csharp, python, cpp, java @@ -27,7 +27,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -41,4 +41,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 350edfea4..65f5bbf4e 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -13,7 +13,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v8 + - uses: actions/stale@v9 with: stale-issue-message: This issue has been identified as stale because it has gone 30 days with no activity. diff --git a/.gitignore b/.gitignore index 1794272f8..d7f45ffdf 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ feedscan feedscan* ..prettierignore.swp scripts/localCodespace.ts +junit.xml diff --git a/.vscode/launch.json b/.vscode/launch.json index 38c56eb00..491b43343 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -18,6 +18,22 @@ "MORE_DEBUG": "appinsights,cache,restapi,pg,querycache,user,redis-cross-org" } }, + { + "type": "node", + "request": "launch", + "name": "Launch site :4000 as-is", + "program": "${workspaceFolder}/dist/bin/www.js", + "cwd": "${workspaceFolder}/dist", + "preLaunchTask": "tsbuild", + "sourceMaps": true, + "console": "integratedTerminal", + "env": { + "NODE_ENV": "development", + "PORT": "4000", + "DEBUG": "startup,g:server,context,*simple-oauth2*,appinsights,insights,appinsights", + "_DEBUG": "cosmosdb,cache" + } + }, { "type": "node", "request": "launch", @@ -138,6 +154,21 @@ "EXIT_IMMEDIATELY": "1" } }, + { + "type": "node", + "request": "launch", + "name": "66: Order 66 Terminations", + "program": "${workspaceRoot}/dist/microsoft/jobs/terminations.js", + "args": ["all"], + "cwd": "${workspaceRoot}/dist", + "preLaunchTask": "tsbuild", + "sourceMaps": true, + "console": "integratedTerminal", + "env": { + "NODE_ENV": "development", + "DEBUG": "startup,appinsights" + } + }, { "type": "node", "request": "launch", @@ -327,6 +358,20 @@ "DEBUG": "startup" } }, + { + "type": "node", + "request": "launch", + "name": "Job: Cleanup team requests (18)", + "program": "${workspaceRoot}/dist/jobs/cleanupTeamRequests.js", + "cwd": "${workspaceRoot}/dist", + "preLaunchTask": "tsbuild", + "sourceMaps": true, + "console": "integratedTerminal", + "env": { + "NODE_ENV": "development", + "DEBUG": "startup" + } + }, { "type": "node", "request": "launch", diff --git a/Dockerfile b/Dockerfile index 43e749481..1994326d1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -61,4 +61,7 @@ COPY --from=build /build/package.json ./package.json # Only if needed, copy our environment # COPY --from=build /build/.environment ./.environment +# Only if needed, binary resources +# COPY --from=build /build/microsoft/assets ./microsoft/assets + ENTRYPOINT ["npm", "run-script", "start-in-container"] diff --git a/api/client/banner.ts b/api/client/banner.ts index 4eeaa24da..a4ccd0f88 100644 --- a/api/client/banner.ts +++ b/api/client/banner.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; import { ReposAppRequest } from '../../interfaces'; import { jsonError } from '../../middleware'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; const router: Router = Router(); diff --git a/api/client/context/administration/app.ts b/api/client/context/administration/app.ts index a965539b7..0734a4385 100644 --- a/api/client/context/administration/app.ts +++ b/api/client/context/administration/app.ts @@ -7,12 +7,12 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; import { ReposAppRequest } from '../../../../interfaces'; -import { CreateError, getProviders } from '../../../../transitional'; +import { CreateError, getProviders } from '../../../../lib/transitional'; import routeIndividualApp from './app'; import GitHubApplication from '../../../../business/application'; -import { OrganizationSetting } from '../../../../entities/organizationSettings/organizationSetting'; -import { sortByCaseInsensitive } from '../../../../utils'; +import { OrganizationSetting } from '../../../../business/entities/organizationSettings/organizationSetting'; +import { sortByCaseInsensitive } from '../../../../lib/utils'; import routeApplicationInstallation from './appInstallation'; import { ApiRequestWithGitHubApplication, RequestWithInstallation } from './types'; diff --git a/api/client/context/administration/appInstallation.ts b/api/client/context/administration/appInstallation.ts index d55991e91..b05c906a1 100644 --- a/api/client/context/administration/appInstallation.ts +++ b/api/client/context/administration/appInstallation.ts @@ -6,8 +6,8 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; -import { CreateError, getProviders } from '../../../../transitional'; -import { OrganizationSetting } from '../../../../entities/organizationSettings/organizationSetting'; +import { CreateError, getProviders } from '../../../../lib/transitional'; +import { OrganizationSetting } from '../../../../business/entities/organizationSettings/organizationSetting'; import { AdministrativeGitHubAppInstallationResponse, RequestWithInstallation } from './types'; const router: Router = Router(); diff --git a/api/client/context/administration/apps.ts b/api/client/context/administration/apps.ts index e0dd06c69..f9f6e3db0 100644 --- a/api/client/context/administration/apps.ts +++ b/api/client/context/administration/apps.ts @@ -7,11 +7,11 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; import { ReposAppRequest } from '../../../../interfaces'; -import { CreateError, getProviders } from '../../../../transitional'; +import { CreateError, getProviders } from '../../../../lib/transitional'; import routeIndividualApp from './app'; import GitHubApplication from '../../../../business/application'; -import { sortByCaseInsensitive } from '../../../../utils'; +import { sortByCaseInsensitive } from '../../../../lib/utils'; import { ApiRequestWithGitHubApplication, ManagedOrganizationAppConfigurationsByOrgView, diff --git a/api/client/context/administration/index.ts b/api/client/context/administration/index.ts index 9a48aee18..cb3e3aab5 100644 --- a/api/client/context/administration/index.ts +++ b/api/client/context/administration/index.ts @@ -10,7 +10,7 @@ import { Organization } from '../../../../business/organization'; import { ReposAppRequest } from '../../../../interfaces'; import { getIsCorporateAdministrator, jsonError } from '../../../../middleware'; import getCompanySpecificDeployment from '../../../../middleware/companySpecificDeployment'; -import { ErrorHelper, getProviders } from '../../../../transitional'; +import { ErrorHelper, getProviders } from '../../../../lib/transitional'; import routeIndividualOrganization from './organization'; import routeApps from './apps'; diff --git a/api/client/context/administration/organization/settings.ts b/api/client/context/administration/organization/settings.ts index ca54b8086..4c3201fa1 100644 --- a/api/client/context/administration/organization/settings.ts +++ b/api/client/context/administration/organization/settings.ts @@ -6,10 +6,10 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; -import { OrganizationSetting } from '../../../../../entities/organizationSettings/organizationSetting'; +import { OrganizationSetting } from '../../../../../business/entities/organizationSettings/organizationSetting'; import { ReposAppRequest } from '../../../../../interfaces'; import { jsonError } from '../../../../../middleware'; -import { CreateError, ErrorHelper, getProviders } from '../../../../../transitional'; +import { CreateError, ErrorHelper, getProviders } from '../../../../../lib/transitional'; const router: Router = Router(); diff --git a/api/client/context/administration/types.ts b/api/client/context/administration/types.ts index ad0d1eb4a..710a2a63b 100644 --- a/api/client/context/administration/types.ts +++ b/api/client/context/administration/types.ts @@ -4,7 +4,7 @@ // import GitHubApplication, { type GitHubAppDefinition } from '../../../../business/application'; -import { OrganizationSetting } from '../../../../entities/organizationSettings/organizationSetting'; +import { OrganizationSetting } from '../../../../business/entities/organizationSettings/organizationSetting'; import type { IGitHubAppInstallation, ReposAppRequest } from '../../../../interfaces'; export type ApiRequestWithGitHubApplication = ReposAppRequest & { diff --git a/api/client/context/approvals.ts b/api/client/context/approvals.ts index 493d666e3..4d7a5b817 100644 --- a/api/client/context/approvals.ts +++ b/api/client/context/approvals.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; import { Team, Organization } from '../../../business'; -import { TeamJoinApprovalEntity } from '../../../entities/teamJoinApproval/teamJoinApproval'; +import { TeamJoinApprovalEntity } from '../../../business/entities/teamJoinApproval/teamJoinApproval'; import { TeamJsonFormat, ReposAppRequest } from '../../../interfaces'; import { jsonError } from '../../../middleware'; import { @@ -16,7 +16,7 @@ import { Approvals_getUserRequests, closeOldRequest, } from '../../../routes/settings/approvals'; -import { getProviders } from '../../../transitional'; +import { getProviders } from '../../../lib/transitional'; import { IndividualContext } from '../../../business/user'; const router: Router = Router(); diff --git a/api/client/context/index.ts b/api/client/context/index.ts index 6cbe7fba0..775716054 100644 --- a/api/client/context/index.ts +++ b/api/client/context/index.ts @@ -11,7 +11,7 @@ import { IProviders, ReposAppRequest } from '../../../interfaces'; import { jsonError } from '../../../middleware'; import getCompanySpecificDeployment from '../../../middleware/companySpecificDeployment'; -import { ErrorHelper, getProviders } from '../../../transitional'; +import { ErrorHelper, getProviders } from '../../../lib/transitional'; import { IndividualContext } from '../../../business/user'; import routeApprovals from './approvals'; diff --git a/api/client/context/organization/index.ts b/api/client/context/organization/index.ts index f410aa286..323e6f483 100644 --- a/api/client/context/organization/index.ts +++ b/api/client/context/organization/index.ts @@ -19,7 +19,7 @@ import { IndividualContext } from '../../../../business/user'; import routeRepos from './repos'; import routeTeams from './teams'; -import { CreateError } from '../../../../transitional'; +import { CreateError } from '../../../../lib/transitional'; const router: Router = Router(); diff --git a/api/client/context/organization/repoForkUnlock.ts b/api/client/context/organization/repoForkUnlock.ts index aa0428ba1..1b7aadd81 100644 --- a/api/client/context/organization/repoForkUnlock.ts +++ b/api/client/context/organization/repoForkUnlock.ts @@ -11,8 +11,8 @@ import { getRepositoryMetadataProvider, ReposAppRequest } from '../../../../inte import { Organization } from '../../../../business'; import { getContextualRepository } from '../../../../middleware/github/repoPermissions'; import { IndividualContext } from '../../../../business/user'; -import { ErrorHelper, getProviders } from '../../../../transitional'; -import NewRepositoryLockdownSystem from '../../../../features/newRepositories/newRepositoryLockdown'; +import { ErrorHelper, getProviders } from '../../../../lib/transitional'; +import NewRepositoryLockdownSystem from '../../../../business/features/newRepositories/newRepositoryLockdown'; const router: Router = Router(); @@ -40,11 +40,12 @@ router.use( router.post( '/approve', asyncHandler(async (req: ReposAppRequest, res: Response, next: NextFunction) => { - const { operations } = getProviders(req); + const { insights, operations } = getProviders(req); const repository = getContextualRepository(req); const repositoryMetadataProvider = getRepositoryMetadataProvider(operations); const organization = repository.organization; const lockdownSystem = new NewRepositoryLockdownSystem({ + insights, operations, organization, repository, diff --git a/api/client/context/organization/team.ts b/api/client/context/organization/team.ts index c30b2c980..649de7635 100644 --- a/api/client/context/organization/team.ts +++ b/api/client/context/organization/team.ts @@ -6,7 +6,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; -import { TeamJoinApprovalEntity } from '../../../../entities/teamJoinApproval/teamJoinApproval'; +import { TeamJoinApprovalEntity } from '../../../../business/entities/teamJoinApproval/teamJoinApproval'; import { ReposAppRequest, OrganizationMembershipState, @@ -24,7 +24,7 @@ import { import { submitTeamJoinRequest } from '../../../../routes/org/team'; import { postActionDecision, TeamApprovalDecision } from '../../../../routes/org/team/approval'; import { PermissionWorkflowEngine } from '../../../../routes/org/team/approvals'; -import { CreateError, getProviders } from '../../../../transitional'; +import { CreateError, getProviders } from '../../../../lib/transitional'; import { IndividualContext } from '../../../../business/user'; import getCompanySpecificDeployment from '../../../../middleware/companySpecificDeployment'; diff --git a/api/client/context/sample.ts b/api/client/context/sample.ts index 42821ae26..687377ea7 100644 --- a/api/client/context/sample.ts +++ b/api/client/context/sample.ts @@ -9,7 +9,7 @@ import asyncHandler from 'express-async-handler'; import { sendLinkedAccountMail } from '../../../business/operations/link'; import { ReposAppRequest } from '../../../interfaces'; import { jsonError } from '../../../middleware'; -import { CreateError, getProviders } from '../../../transitional'; +import { CreateError, getProviders } from '../../../lib/transitional'; import { IndividualContext } from '../../../business/user'; const router: Router = Router(); diff --git a/api/client/context/settings.ts b/api/client/context/settings.ts index 5c6199793..86a72a256 100644 --- a/api/client/context/settings.ts +++ b/api/client/context/settings.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; import { ReposAppRequest } from '../../../interfaces'; -import { CreateError, getProviders } from '../../../transitional'; +import { CreateError, getProviders } from '../../../lib/transitional'; import { getUserSettings } from '../../../middleware/business/userSettings'; import type { ReposAppRequestWithUserSettings } from '../../../interfaces/middleware'; diff --git a/api/client/index.ts b/api/client/index.ts index a662e58a4..db0e86073 100644 --- a/api/client/index.ts +++ b/api/client/index.ts @@ -14,7 +14,7 @@ import { jsonError, requireAuthenticatedUserOrSignIn, } from '../../middleware'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import getCompanySpecificDeployment from '../../middleware/companySpecificDeployment'; diff --git a/api/client/linking.ts b/api/client/linking.ts index dca173a36..c3188b951 100644 --- a/api/client/linking.ts +++ b/api/client/linking.ts @@ -8,7 +8,7 @@ import asyncHandler from 'express-async-handler'; import { IndividualContext } from '../../business/user'; import { jsonError } from '../../middleware'; -import { ErrorHelper, getProviders } from '../../transitional'; +import { ErrorHelper, getProviders } from '../../lib/transitional'; import { unlinkInteractive } from '../../routes/unlink'; import { interactiveLinkUser } from '../../routes/link'; import { ReposAppRequest } from '../../interfaces'; diff --git a/api/client/newOrgRepo.ts b/api/client/newOrgRepo.ts index f4dd18efe..0984312b3 100644 --- a/api/client/newOrgRepo.ts +++ b/api/client/newOrgRepo.ts @@ -9,7 +9,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import { jsonError } from '../../middleware/jsonError'; import { IndividualContext } from '../../business/user'; import { Organization } from '../../business/organization'; diff --git a/api/client/newRepo.ts b/api/client/newRepo.ts index a81000e8d..8d28cae1c 100644 --- a/api/client/newRepo.ts +++ b/api/client/newRepo.ts @@ -6,7 +6,7 @@ import { NextFunction, Response, Router } from 'express'; const router: Router = Router(); -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import { jsonError } from '../../middleware/jsonError'; import newOrgRepo from './newOrgRepo'; diff --git a/api/client/news.ts b/api/client/news.ts index 0253c49b0..24cb920a0 100644 --- a/api/client/news.ts +++ b/api/client/news.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; import { jsonError } from '../../middleware'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import { ReposAppRequest } from '../../interfaces'; const router: Router = Router(); diff --git a/api/client/organization/annotations.ts b/api/client/organization/annotations.ts index ad9d28758..764ac8b63 100644 --- a/api/client/organization/annotations.ts +++ b/api/client/organization/annotations.ts @@ -20,8 +20,8 @@ import { IOrganizationAnnotationChange, OrganizationAnnotation, getOrganizationAnnotationRestrictedPropertyNames, -} from '../../../entities/organizationAnnotation'; -import { CreateError, ErrorHelper, getProviders } from '../../../transitional'; +} from '../../../business/entities/organizationAnnotation'; +import { CreateError, ErrorHelper, getProviders } from '../../../lib/transitional'; import { IndividualContext } from '../../../business/user'; import { IProviders } from '../../../interfaces'; import { ensureOrganizationProfileMiddleware } from '../../../middleware/github/ensureOrganizationProfile'; diff --git a/api/client/organization/index.ts b/api/client/organization/index.ts index 6b662cac2..6cc49a116 100644 --- a/api/client/organization/index.ts +++ b/api/client/organization/index.ts @@ -9,7 +9,7 @@ import asyncHandler from 'express-async-handler'; import { ReposAppRequest } from '../../../interfaces'; import { jsonError } from '../../../middleware'; import getCompanySpecificDeployment from '../../../middleware/companySpecificDeployment'; -import { getProviders } from '../../../transitional'; +import { getProviders } from '../../../lib/transitional'; import { blockIfUnmanagedOrganization, IReposAppRequestWithOrganizationManagementType, diff --git a/api/client/organization/people.ts b/api/client/organization/people.ts index 7784707bb..5d75ab5c4 100644 --- a/api/client/organization/people.ts +++ b/api/client/organization/people.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; import { jsonError } from '../../../middleware'; -import { getProviders } from '../../../transitional'; +import { getProviders } from '../../../lib/transitional'; import LeakyLocalCache, { getLinksLightCache } from '../leakyLocalCache'; import JsonPager from '../jsonPager'; import { diff --git a/api/client/organization/repo.ts b/api/client/organization/repo.ts index 5ca09bce9..635105e2d 100644 --- a/api/client/organization/repo.ts +++ b/api/client/organization/repo.ts @@ -7,9 +7,9 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; import { jsonError } from '../../../middleware'; -import { CreateError, ErrorHelper, getProviders } from '../../../transitional'; +import { CreateError, ErrorHelper, getProviders } from '../../../lib/transitional'; import { IndividualContext } from '../../../business/user'; -import NewRepositoryLockdownSystem from '../../../features/newRepositories/newRepositoryLockdown'; +import NewRepositoryLockdownSystem from '../../../business/features/newRepositories/newRepositoryLockdown'; import { AddRepositoryPermissionsToRequest, getContextualRepositoryPermissions, @@ -45,8 +45,8 @@ router.get( try { await repository.getDetails({ backgroundRefresh: false }); const clone = Object.assign({}, repository.getEntity()); - delete clone.temp_clone_token; // never share this back - delete clone.cost; + delete (clone as any).temp_clone_token; // never share this back + delete (clone as any).cost; return res.json(repository.getEntity()) as unknown as void; } catch (repoError) { @@ -330,6 +330,7 @@ router.delete( const { operations } = getProviders(req); const repositoryMetadataProvider = getRepositoryMetadataProvider(operations); const lockdownSystem = new NewRepositoryLockdownSystem({ + insights, operations, organization, repository, diff --git a/api/client/organization/repos.ts b/api/client/organization/repos.ts index 24efe5ae3..2a32f163b 100644 --- a/api/client/organization/repos.ts +++ b/api/client/organization/repos.ts @@ -7,12 +7,12 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; import { jsonError } from '../../../middleware'; -import { CreateError, getProviders } from '../../../transitional'; +import { CreateError, getProviders } from '../../../lib/transitional'; import { Repository } from '../../../business'; import JsonPager from '../jsonPager'; import { ReposAppRequest, IProviders } from '../../../interfaces'; -import { sortRepositoriesByNameCaseInsensitive } from '../../../utils'; +import { sortRepositoriesByNameCaseInsensitive } from '../../../lib/utils'; import { apiMiddlewareRepositoriesToRepository } from '../../../middleware/business/repository'; import routeRepo from './repo'; diff --git a/api/client/organization/team.ts b/api/client/organization/team.ts index 5458a9767..73e44e323 100644 --- a/api/client/organization/team.ts +++ b/api/client/organization/team.ts @@ -9,13 +9,13 @@ import asyncHandler from 'express-async-handler'; import { getContextualTeam } from '../../../middleware/github/teamPermissions'; import { jsonError } from '../../../middleware'; -import { getProviders } from '../../../transitional'; +import { getProviders } from '../../../lib/transitional'; import JsonPager from '../jsonPager'; import { getLinksLightCache } from '../leakyLocalCache'; import { equivalentLegacyPeopleSearch } from './people'; import { TeamRepositoryPermission, OrganizationMember, corporateLinkToJson } from '../../../business'; import { ReposAppRequest, TeamJsonFormat, NoCacheNoBackground, ICorporateLink } from '../../../interfaces'; -import { sortRepositoriesByNameCaseInsensitive } from '../../../utils'; +import { sortRepositoriesByNameCaseInsensitive } from '../../../lib/utils'; import getCompanySpecificDeployment from '../../../middleware/companySpecificDeployment'; const router: Router = Router(); diff --git a/api/client/organizations.ts b/api/client/organizations.ts index 7a289400f..2c26e165c 100644 --- a/api/client/organizations.ts +++ b/api/client/organizations.ts @@ -8,7 +8,7 @@ import asyncHandler from 'express-async-handler'; import throat from 'throat'; import { getIsCorporateAdministrator, jsonError } from '../../middleware'; -import { CreateError, getProviders } from '../../transitional'; +import { CreateError, getProviders } from '../../lib/transitional'; import { ReposAppRequest } from '../../interfaces'; import RouteOrganization from './organization'; @@ -18,7 +18,7 @@ import { OrganizationAnnotation, OrganizationAnnotationProperty, getOrganizationAnnotationRestrictedPropertyNames, -} from '../../entities/organizationAnnotation'; +} from '../../business/entities/organizationAnnotation'; import { getOrganizationProfileViaMemoryCache } from '../../middleware/github/ensureOrganizationProfile'; const router: Router = Router(); diff --git a/api/client/peopleSearch.ts b/api/client/peopleSearch.ts index 1c55e6d16..82ae5c27f 100644 --- a/api/client/peopleSearch.ts +++ b/api/client/peopleSearch.ts @@ -5,7 +5,7 @@ import { Organization, MemberSearch, ICrossOrganizationMembersResult, Operations } from '../../business'; import { ReposAppRequest } from '../../interfaces'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import LeakyLocalCache, { getLinksLightCache } from './leakyLocalCache'; // BAD PRACTICE: leaky local cache diff --git a/api/client/person.ts b/api/client/person.ts index 1df8919b8..61369456a 100644 --- a/api/client/person.ts +++ b/api/client/person.ts @@ -10,7 +10,7 @@ import { ReposAppRequest, AccountJsonFormat } from '../../interfaces'; import { IGraphEntry } from '../../lib/graphProvider'; import { jsonError } from '../../middleware'; -import { CreateError, ErrorHelper, getProviders } from '../../transitional'; +import { CreateError, ErrorHelper, getProviders } from '../../lib/transitional'; const getPerson = asyncHandler(async (req: ReposAppRequest, res: Response, next: NextFunction) => { const providers = getProviders(req); diff --git a/api/client/repos.ts b/api/client/repos.ts index debe8cf02..ca1675f2a 100644 --- a/api/client/repos.ts +++ b/api/client/repos.ts @@ -9,7 +9,7 @@ import asyncHandler from 'express-async-handler'; import { Repository } from '../../business'; import { ReposAppRequest } from '../../interfaces'; import { jsonError } from '../../middleware'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import JsonPager from './jsonPager'; import { RepositorySearchSortOrder, searchRepos } from './organization/repos'; diff --git a/api/client/session.ts b/api/client/session.ts index 201d4605b..35f98dd2a 100644 --- a/api/client/session.ts +++ b/api/client/session.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; import { jsonError } from '../../middleware/jsonError'; import { IAppSession, ReposAppRequest } from '../../interfaces'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; const router: Router = Router(); diff --git a/api/client/teams.ts b/api/client/teams.ts index 93eac9dfc..089fa240b 100644 --- a/api/client/teams.ts +++ b/api/client/teams.ts @@ -13,7 +13,7 @@ import { TeamJsonFormat, } from '../../interfaces'; import { jsonError } from '../../middleware'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import JsonPager from './jsonPager'; const router: Router = Router(); diff --git a/api/client/users.ts b/api/client/users.ts index a794d5306..940789452 100644 --- a/api/client/users.ts +++ b/api/client/users.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; import { ReposAppRequest, AccountJsonFormat } from '../../interfaces'; -import { CreateError, getProviders } from '../../transitional'; +import { CreateError, getProviders } from '../../lib/transitional'; const router: Router = Router(); diff --git a/api/createRepo.ts b/api/createRepo.ts index bb7b39f10..585949c25 100644 --- a/api/createRepo.ts +++ b/api/createRepo.ts @@ -17,9 +17,9 @@ import { ICustomizedNewRepositoryLogic, INewRepositoryContext, splitSemiColonCommas, -} from '../transitional'; +} from '../lib/transitional'; import { Organization, Repository } from '../business'; -import { RepositoryMetadataEntity } from '../entities/repositoryMetadata/repositoryMetadata'; +import { RepositoryMetadataEntity } from '../business/entities/repositoryMetadata/repositoryMetadata'; import RenderHtmlMail from '../lib/emailRender'; import { @@ -29,7 +29,7 @@ import { } from '../routes/org/repoWorkflowEngine'; import { IMailProvider } from '../lib/mailProvider'; import { IndividualContext } from '../business/user'; -import NewRepositoryLockdownSystem from '../features/newRepositories/newRepositoryLockdown'; +import NewRepositoryLockdownSystem from '../business/features/newRepositories/newRepositoryLockdown'; import { ICreateRepositoryResult, ICorporateLink, @@ -176,7 +176,7 @@ export async function CreateRepository( try { createResult = await organization.createRepository(parameters.name, parameters); if (createResult && createResult.repository) { - repository = organization.repositoryFromEntity(createResult.repository); + repository = organization.repositoryFromEntity(createResult.repository.getEntity()); } } catch (error) { providers.insights?.trackEvent({ diff --git a/api/extension.ts b/api/extension.ts index fefd43b91..4e9e2f1b0 100644 --- a/api/extension.ts +++ b/api/extension.ts @@ -7,15 +7,15 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; import { setIdentity } from '../middleware/business/authentication'; -import { AddLinkToRequest } from '../middleware/links'; +import { AddLinkToRequest } from '../middleware/business/links'; import { jsonError } from '../middleware'; import { apiContextMiddleware } from '../middleware/business/setContext'; -import { ILocalExtensionKeyProvider } from '../entities/localExtensionKey'; -import { LocalExtensionKey } from '../entities/localExtensionKey/localExtensionKey'; +import { ILocalExtensionKeyProvider } from '../business/entities/localExtensionKey'; +import { LocalExtensionKey } from '../business/entities/localExtensionKey/localExtensionKey'; import { IApiRequest } from '../middleware/apiReposAuth'; -import { PersonalAccessToken } from '../entities/token/token'; +import { PersonalAccessToken } from '../business/entities/token/token'; const thisApiScopeName = 'extension'; diff --git a/api/index.ts b/api/index.ts index bd309f1c5..a4f5c58ba 100644 --- a/api/index.ts +++ b/api/index.ts @@ -9,7 +9,7 @@ const router: Router = Router(); import cors from 'cors'; -import { CreateError, getProviders } from '../transitional'; +import { CreateError, getProviders } from '../lib/transitional'; import { jsonError } from '../middleware'; import { IApiRequest } from '../middleware/apiReposAuth'; diff --git a/api/jsonErrorHandler.ts b/api/jsonErrorHandler.ts index 67e192cb0..9fa874805 100644 --- a/api/jsonErrorHandler.ts +++ b/api/jsonErrorHandler.ts @@ -4,7 +4,7 @@ // import { NextFunction, Response } from 'express'; -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; export default function JsonErrorHandler(err, req, res: Response, next: NextFunction) { if (err && err['json']) { diff --git a/api/people/link.ts b/api/people/link.ts index 04d171ccf..3202e00f3 100644 --- a/api/people/link.ts +++ b/api/people/link.ts @@ -5,7 +5,7 @@ import { NextFunction, Response } from 'express'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import { jsonError } from '../../middleware'; import { IApiRequest } from '../../middleware/apiReposAuth'; import { ICorporateLink, LinkOperationSource } from '../../interfaces'; diff --git a/api/people/links.ts b/api/people/links.ts index 9e6d8d315..3ea4caa59 100644 --- a/api/people/links.ts +++ b/api/people/links.ts @@ -11,8 +11,8 @@ import { ICrossOrganizationMembersResult, MemberSearch, Operations } from '../.. import { ICorporateLink, VoidedExpressRoute } from '../../interfaces'; import { IApiRequest } from '../../middleware/apiReposAuth'; import postLinkApi from './link'; -import { CreateError, ErrorHelper, getProviders } from '../../transitional'; -import { wrapError } from '../../utils'; +import { CreateError, ErrorHelper, getProviders } from '../../lib/transitional'; +import { wrapError } from '../../lib/utils'; const router: Router = Router(); diff --git a/api/people/unlink.ts b/api/people/unlink.ts index 5d78020b0..dbaa25e72 100644 --- a/api/people/unlink.ts +++ b/api/people/unlink.ts @@ -9,7 +9,7 @@ import asyncHandler from 'express-async-handler'; import { ICorporateLink, UnlinkPurpose } from '../../interfaces'; import { jsonError } from '../../middleware'; import { IApiRequest } from '../../middleware/apiReposAuth'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; const router: Router = Router(); diff --git a/api/webhook.ts b/api/webhook.ts index f93d09380..c7531a8ce 100644 --- a/api/webhook.ts +++ b/api/webhook.ts @@ -10,9 +10,9 @@ import moment from 'moment'; import { ReposAppRequest } from '../interfaces'; import { jsonError } from '../middleware'; -import { getProviders, isWebhookIngestionEndpointEnabled } from '../transitional'; +import { getProviders, isWebhookIngestionEndpointEnabled } from '../lib/transitional'; -import OrganizationWebhookProcessor from '../webhooks/organizationProcessor'; +import OrganizationWebhookProcessor from '../business/webhooks/organizationProcessor'; const router: Router = Router(); diff --git a/business/account.ts b/business/account.ts index b35dff849..990c52a49 100644 --- a/business/account.ts +++ b/business/account.ts @@ -7,12 +7,12 @@ import _ from 'lodash'; import * as common from './common'; -import { wrapError } from '../utils'; +import { wrapError } from '../lib/utils'; import { corporateLinkToJson } from './corporateLink'; import { Organization } from './organization'; import { AppPurpose } from '../lib/github/appPurposes'; import { ILinkProvider } from '../lib/linkProviders'; -import { CacheDefault, getMaxAgeSeconds } from '.'; +import { CacheDefault, Operations, getMaxAgeSeconds } from '.'; import { AccountJsonFormat, CoreCapability, @@ -29,7 +29,7 @@ import { throwIfNotCapable, throwIfNotGitHubCapable, } from '../interfaces'; -import { ErrorHelper } from '../transitional'; +import { ErrorHelper } from '../lib/transitional'; interface IRemoveOrganizationMembershipsResult { error?: IReposError; @@ -358,8 +358,10 @@ export class Account { cacheOptions.backgroundRefresh = options.backgroundRefresh; } try { + const ops = operations as Operations; const entity = (await operations.github.request( - this.authorize(AppPurpose.Data), + ops.getPublicAuthorizationToken(), + // this.authorize(AppPurpose.Data), 'GET /user/:id', parameters, cacheOptions @@ -418,7 +420,7 @@ export class Account { }; const eventData = { github: { - id: id, + id, login: this._login, }, aad: aadIdentity, diff --git a/business/application.ts b/business/application.ts index cd8c37ce3..de134a1dc 100644 --- a/business/application.ts +++ b/business/application.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { OrganizationSetting } from '../entities/organizationSettings/organizationSetting'; +import { OrganizationSetting } from './entities/organizationSettings/organizationSetting'; import { IOperationsGitHubRestLibrary, IOperationsDefaultCacheTimes, @@ -11,7 +11,7 @@ import { IGitHubAppInstallation, ICacheOptions, } from '../interfaces'; -import { wrapError } from '../utils'; +import { wrapError } from '../lib/utils'; const primaryInstallationProperties = [ 'id', diff --git a/business/collaborator.ts b/business/collaborator.ts index cd389c34b..ed745527d 100644 --- a/business/collaborator.ts +++ b/business/collaborator.ts @@ -4,7 +4,7 @@ // import { GitHubRepositoryPermission, IGitHubCollaboratorPermissions } from '../interfaces'; -import { projectCollaboratorPermissionsObjectToGitHubRepositoryPermission } from '../transitional'; +import { projectCollaboratorPermissionsObjectToGitHubRepositoryPermission } from '../lib/transitional'; import * as common from './common'; // prettier-ignore diff --git a/business/domains.ts b/business/domains.ts index db5f42f5b..73d211f3a 100644 --- a/business/domains.ts +++ b/business/domains.ts @@ -17,7 +17,7 @@ import { IteratorResponse, PaginationPageSizeOptions, } from './iterable'; -import { DefaultGraphqlPageSize } from '../transitional'; +import { DefaultGraphqlPageSize } from '../lib/transitional'; type DomainResponse = { id: string; diff --git a/entities/auditLogRecord/auditLogRecord.ts b/business/entities/auditLogRecord/auditLogRecord.ts similarity index 94% rename from entities/auditLogRecord/auditLogRecord.ts rename to business/entities/auditLogRecord/auditLogRecord.ts index a80b77e0a..08f2311ea 100644 --- a/entities/auditLogRecord/auditLogRecord.ts +++ b/business/entities/auditLogRecord/auditLogRecord.ts @@ -5,23 +5,23 @@ import { randomUUID } from 'crypto'; -import { EntityField } from '../../lib/entityMetadataProvider/entityMetadataProvider'; -import { IEntityMetadata } from '../../lib/entityMetadataProvider/entityMetadata'; -import { IEntityMetadataFixedQuery, FixedQueryType } from '../../lib/entityMetadataProvider/query'; +import { EntityField } from '../../../lib/entityMetadataProvider/entityMetadataProvider'; +import { IEntityMetadata } from '../../../lib/entityMetadataProvider/entityMetadata'; +import { IEntityMetadataFixedQuery, FixedQueryType } from '../../../lib/entityMetadataProvider/query'; import { EntityMetadataMappings, MetadataMappingDefinition, -} from '../../lib/entityMetadataProvider/declarations'; +} from '../../../lib/entityMetadataProvider/declarations'; import { Type } from './type'; import { PostgresJsonEntityQuery, PostgresSettings, PostgresConfiguration, -} from '../../lib/entityMetadataProvider/postgres'; -import { IDictionary } from '../../interfaces'; +} from '../../../lib/entityMetadataProvider/postgres'; +import { IDictionary } from '../../../interfaces'; import { AuditLogSource } from '.'; -import { stringOrNumberAsString } from '../../utils'; -import { MemoryConfiguration, MemorySettings } from '../../lib/entityMetadataProvider/memory'; +import { stringOrNumberAsString } from '../../../lib/utils'; +import { MemoryConfiguration, MemorySettings } from '../../../lib/entityMetadataProvider/memory'; const type = Type; diff --git a/entities/auditLogRecord/auditLogRecordProvider.ts b/business/entities/auditLogRecord/auditLogRecordProvider.ts similarity index 98% rename from entities/auditLogRecord/auditLogRecordProvider.ts rename to business/entities/auditLogRecord/auditLogRecordProvider.ts index df7b7647a..709df08c9 100644 --- a/entities/auditLogRecord/auditLogRecordProvider.ts +++ b/business/entities/auditLogRecord/auditLogRecordProvider.ts @@ -7,7 +7,7 @@ import { IEntityMetadata, EntityMetadataBase, IEntityMetadataBaseOptions, -} from '../../lib/entityMetadataProvider/entityMetadata'; +} from '../../../lib/entityMetadataProvider/entityMetadata'; import { AuditLogRecord, AuditLogRecordQueryUndoCandidatesByThirdPartyId, diff --git a/entities/auditLogRecord/index.ts b/business/entities/auditLogRecord/index.ts similarity index 100% rename from entities/auditLogRecord/index.ts rename to business/entities/auditLogRecord/index.ts diff --git a/entities/auditLogRecord/type.ts b/business/entities/auditLogRecord/type.ts similarity index 69% rename from entities/auditLogRecord/type.ts rename to business/entities/auditLogRecord/type.ts index de552af45..fb9ba2b8f 100644 --- a/entities/auditLogRecord/type.ts +++ b/business/entities/auditLogRecord/type.ts @@ -3,6 +3,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityMetadataType } from '../../lib/entityMetadataProvider/entityMetadata'; +import { EntityMetadataType } from '../../../lib/entityMetadataProvider/entityMetadata'; export const Type = new EntityMetadataType('AuditLogRecord'); diff --git a/entities/localExtensionKey/index.ts b/business/entities/localExtensionKey/index.ts similarity index 91% rename from entities/localExtensionKey/index.ts rename to business/entities/localExtensionKey/index.ts index 0aff67b8e..015a8b11f 100644 --- a/entities/localExtensionKey/index.ts +++ b/business/entities/localExtensionKey/index.ts @@ -5,7 +5,7 @@ import { LocalExtensionKeyProvider } from './localExtensionKeyProvider'; import { LocalExtensionKey } from './localExtensionKey'; -import { IEntityMetadataProvider } from '../../lib/entityMetadataProvider/entityMetadataProvider'; +import { IEntityMetadataProvider } from '../../../lib/entityMetadataProvider/entityMetadataProvider'; export interface ILocalExtensionKeyProvider { initialize(): Promise; diff --git a/entities/localExtensionKey/localExtensionKey.ts b/business/entities/localExtensionKey/localExtensionKey.ts similarity index 90% rename from entities/localExtensionKey/localExtensionKey.ts rename to business/entities/localExtensionKey/localExtensionKey.ts index 0a0adb6ac..62dc3dd7c 100644 --- a/entities/localExtensionKey/localExtensionKey.ts +++ b/business/entities/localExtensionKey/localExtensionKey.ts @@ -5,15 +5,15 @@ import crypto from 'crypto'; -import { IObjectWithDefinedKeys } from '../../lib/entityMetadataProvider/entityMetadataProvider'; -import { EntityMetadataType, IEntityMetadata } from '../../lib/entityMetadataProvider/entityMetadata'; +import { IObjectWithDefinedKeys } from '../../../lib/entityMetadataProvider/entityMetadataProvider'; +import { EntityMetadataType, IEntityMetadata } from '../../../lib/entityMetadataProvider/entityMetadata'; import { MetadataMappingDefinition, EntityMetadataMappings, -} from '../../lib/entityMetadataProvider/declarations'; -import { IEntityMetadataFixedQuery, FixedQueryType } from '../../lib/entityMetadataProvider/query'; -import { TableSettings } from '../../lib/entityMetadataProvider/table'; -import { MemorySettings } from '../../lib/entityMetadataProvider/memory'; +} from '../../../lib/entityMetadataProvider/declarations'; +import { IEntityMetadataFixedQuery, FixedQueryType } from '../../../lib/entityMetadataProvider/query'; +import { TableSettings } from '../../../lib/entityMetadataProvider/table'; +import { MemorySettings } from '../../../lib/entityMetadataProvider/memory'; import { odata, TableEntityQueryOptions } from '@azure/data-tables'; const type = new EntityMetadataType('LocalExtensionKey'); diff --git a/entities/localExtensionKey/localExtensionKeyProvider.ts b/business/entities/localExtensionKey/localExtensionKeyProvider.ts similarity index 94% rename from entities/localExtensionKey/localExtensionKeyProvider.ts rename to business/entities/localExtensionKey/localExtensionKeyProvider.ts index 8b3c99097..adb37e2fd 100644 --- a/entities/localExtensionKey/localExtensionKeyProvider.ts +++ b/business/entities/localExtensionKey/localExtensionKeyProvider.ts @@ -3,10 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityMetadataBase } from '../../lib/entityMetadataProvider/entityMetadata'; +import { EntityMetadataBase } from '../../../lib/entityMetadataProvider/entityMetadata'; import { LocalExtensionKey, EntityImplementation } from './localExtensionKey'; import { ILocalExtensionKeyProvider, ILocalExtensionKeyProviderOptions } from '.'; -import { IEntityMetadataFixedQuery, FixedQueryType } from '../../lib/entityMetadataProvider/query'; +import { IEntityMetadataFixedQuery, FixedQueryType } from '../../../lib/entityMetadataProvider/query'; const thisProviderType = EntityImplementation.Type; diff --git a/entities/organizationAnnotation.ts b/business/entities/organizationAnnotation.ts similarity index 94% rename from entities/organizationAnnotation.ts rename to business/entities/organizationAnnotation.ts index c2e08fcfa..61b428b77 100644 --- a/entities/organizationAnnotation.ts +++ b/business/entities/organizationAnnotation.ts @@ -22,16 +22,16 @@ import { EntityMetadataType, IEntityMetadataBaseOptions, EntityMetadataBase, -} from '../lib/entityMetadataProvider/entityMetadata'; -import { IEntityMetadataFixedQuery, QueryBase } from '../lib/entityMetadataProvider/query'; +} from '../../lib/entityMetadataProvider/entityMetadata'; +import { IEntityMetadataFixedQuery, QueryBase } from '../../lib/entityMetadataProvider/query'; import { EntityMetadataMappings, MetadataMappingDefinition, -} from '../lib/entityMetadataProvider/declarations'; -import { PostgresSettings, PostgresConfiguration } from '../lib/entityMetadataProvider/postgres'; -import { IDictionary } from '../interfaces'; -import { CreateError, ErrorHelper } from '../transitional'; -import { MemoryConfiguration, TableConfiguration } from '../lib/entityMetadataProvider'; +} from '../../lib/entityMetadataProvider/declarations'; +import { PostgresSettings, PostgresConfiguration } from '../../lib/entityMetadataProvider/postgres'; +import { IDictionary } from '../../interfaces'; +import { CreateError, ErrorHelper } from '../../lib/transitional'; +import { MemoryConfiguration, TableConfiguration } from '../../lib/entityMetadataProvider'; const type = new EntityMetadataType('OrganizationAnnotation'); const thisProviderType = type; diff --git a/entities/organizationMemberCache/index.ts b/business/entities/organizationMemberCache/index.ts similarity index 100% rename from entities/organizationMemberCache/index.ts rename to business/entities/organizationMemberCache/index.ts diff --git a/entities/organizationMemberCache/organizationMemberCache.ts b/business/entities/organizationMemberCache/organizationMemberCache.ts similarity index 93% rename from entities/organizationMemberCache/organizationMemberCache.ts rename to business/entities/organizationMemberCache/organizationMemberCache.ts index 87a2e5b27..98d9506a5 100644 --- a/entities/organizationMemberCache/organizationMemberCache.ts +++ b/business/entities/organizationMemberCache/organizationMemberCache.ts @@ -3,25 +3,25 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityField } from '../../lib/entityMetadataProvider/entityMetadataProvider'; -import { EntityMetadataType, IEntityMetadata } from '../../lib/entityMetadataProvider/entityMetadata'; -import { IEntityMetadataFixedQuery, FixedQueryType } from '../../lib/entityMetadataProvider/query'; +import { EntityField } from '../../../lib/entityMetadataProvider/entityMetadataProvider'; +import { EntityMetadataType, IEntityMetadata } from '../../../lib/entityMetadataProvider/entityMetadata'; +import { IEntityMetadataFixedQuery, FixedQueryType } from '../../../lib/entityMetadataProvider/query'; import { EntityMetadataMappings, MetadataMappingDefinition, -} from '../../lib/entityMetadataProvider/declarations'; -import { OrganizationMembershipRole } from '../../interfaces'; -import { stringOrNumberAsString } from '../../utils'; +} from '../../../lib/entityMetadataProvider/declarations'; +import { OrganizationMembershipRole } from '../../../interfaces'; +import { stringOrNumberAsString } from '../../../lib/utils'; import { PostgresJsonEntityQuery, PostgresGetAllEntities, PostgresSettings, PostgresConfiguration, -} from '../../lib/entityMetadataProvider/postgres'; -import { MemoryConfiguration, MemorySettings } from '../../lib/entityMetadataProvider/memory'; -import { TableConfiguration, TableSettings } from '../../lib/entityMetadataProvider'; +} from '../../../lib/entityMetadataProvider/postgres'; +import { MemoryConfiguration, MemorySettings } from '../../../lib/entityMetadataProvider/memory'; +import { TableConfiguration, TableSettings } from '../../../lib/entityMetadataProvider'; import { odata, TableEntityQueryOptions } from '@azure/data-tables'; -import { CreateError } from '../../transitional'; +import { CreateError } from '../../../lib/transitional'; const type = new EntityMetadataType('OrganizationMemberCache'); diff --git a/entities/organizationMemberCache/organizationMemberCacheProvider.ts b/business/entities/organizationMemberCache/organizationMemberCacheProvider.ts similarity index 98% rename from entities/organizationMemberCache/organizationMemberCacheProvider.ts rename to business/entities/organizationMemberCache/organizationMemberCacheProvider.ts index 66e789707..2aa1bdcb4 100644 --- a/entities/organizationMemberCache/organizationMemberCacheProvider.ts +++ b/business/entities/organizationMemberCache/organizationMemberCacheProvider.ts @@ -7,7 +7,7 @@ import { IEntityMetadata, EntityMetadataBase, IEntityMetadataBaseOptions, -} from '../../lib/entityMetadataProvider/entityMetadata'; +} from '../../../lib/entityMetadataProvider/entityMetadata'; import { OrganizationMemberCacheEntity, EntityImplementation, diff --git a/entities/organizationSettings/index.ts b/business/entities/organizationSettings/index.ts similarity index 100% rename from entities/organizationSettings/index.ts rename to business/entities/organizationSettings/index.ts diff --git a/entities/organizationSettings/organizationSetting.ts b/business/entities/organizationSettings/organizationSetting.ts similarity index 96% rename from entities/organizationSettings/organizationSetting.ts rename to business/entities/organizationSettings/organizationSetting.ts index d49cf7b89..5ce2cee28 100644 --- a/entities/organizationSettings/organizationSetting.ts +++ b/business/entities/organizationSettings/organizationSetting.ts @@ -3,15 +3,15 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityField } from '../../lib/entityMetadataProvider/entityMetadataProvider'; -import { IEntityMetadata } from '../../lib/entityMetadataProvider/entityMetadata'; -import { IEntityMetadataFixedQuery, FixedQueryType } from '../../lib/entityMetadataProvider/query'; +import { EntityField } from '../../../lib/entityMetadataProvider/entityMetadataProvider'; +import { IEntityMetadata } from '../../../lib/entityMetadataProvider/entityMetadata'; +import { IEntityMetadataFixedQuery, FixedQueryType } from '../../../lib/entityMetadataProvider/query'; import { EntityMetadataMappings, MetadataMappingDefinition, -} from '../../lib/entityMetadataProvider/declarations'; +} from '../../../lib/entityMetadataProvider/declarations'; import { Type } from './type'; -import { PostgresGetAllEntities } from '../../lib/entityMetadataProvider/postgres'; +import { PostgresGetAllEntities } from '../../../lib/entityMetadataProvider/postgres'; import { MemoryConfiguration, MemorySettings, @@ -19,8 +19,8 @@ import { PostgresConfiguration, TableConfiguration, TableSettings, -} from '../../lib/entityMetadataProvider'; -import { ConfigGitHubOrganization } from '../../config/github.organizations.types'; +} from '../../../lib/entityMetadataProvider'; +import { ConfigGitHubOrganization } from '../../../config/github.organizations.types'; import { odata, TableEntityQueryOptions } from '@azure/data-tables'; export interface IBasicGitHubAppInstallation { diff --git a/entities/organizationSettings/organizationSettingProvider.ts b/business/entities/organizationSettings/organizationSettingProvider.ts similarity index 97% rename from entities/organizationSettings/organizationSettingProvider.ts rename to business/entities/organizationSettings/organizationSettingProvider.ts index 6cbf908cc..c7b7944dd 100644 --- a/entities/organizationSettings/organizationSettingProvider.ts +++ b/business/entities/organizationSettings/organizationSettingProvider.ts @@ -7,7 +7,7 @@ import { IEntityMetadata, EntityMetadataBase, IEntityMetadataBaseOptions, -} from '../../lib/entityMetadataProvider/entityMetadata'; +} from '../../../lib/entityMetadataProvider/entityMetadata'; import { OrganizationSetting, OrganizationSettingFixedQueryAll } from './organizationSetting'; import { EntityImplementation } from './organizationSetting'; diff --git a/entities/organizationSettings/type.ts b/business/entities/organizationSettings/type.ts similarity index 69% rename from entities/organizationSettings/type.ts rename to business/entities/organizationSettings/type.ts index 6f3cd7419..0d4bc1a6c 100644 --- a/entities/organizationSettings/type.ts +++ b/business/entities/organizationSettings/type.ts @@ -3,6 +3,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityMetadataType } from '../../lib/entityMetadataProvider/entityMetadata'; +import { EntityMetadataType } from '../../../lib/entityMetadataProvider/entityMetadata'; export const Type = new EntityMetadataType('OrganizationSetting'); diff --git a/entities/repository.ts b/business/entities/repository.ts similarity index 97% rename from entities/repository.ts rename to business/entities/repository.ts index 5d5ca8535..bb1b5bd5a 100644 --- a/entities/repository.ts +++ b/business/entities/repository.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { GitHubRepositoryVisibility } from '../interfaces'; +import { GitHubRepositoryVisibility } from '../../interfaces'; import { EntityMetadataBase, EntityMetadataMappings, @@ -14,9 +14,9 @@ import { keyValueMetadataField, MetadataMappingDefinition, QueryBase, -} from '../lib/entityMetadataProvider'; -import { PostgresConfiguration, PostgresSettings } from '../lib/entityMetadataProvider/postgres'; -import { ErrorHelper } from '../transitional'; +} from '../../lib/entityMetadataProvider'; +import { PostgresConfiguration, PostgresSettings } from '../../lib/entityMetadataProvider/postgres'; +import { ErrorHelper } from '../../lib/transitional'; const type = new EntityMetadataType('RepositoryDetails'); const typeColumnValue = 'repositorydetails'; diff --git a/entities/repositoryCache/index.ts b/business/entities/repositoryCache/index.ts similarity index 100% rename from entities/repositoryCache/index.ts rename to business/entities/repositoryCache/index.ts diff --git a/entities/repositoryCache/repositoryCache.ts b/business/entities/repositoryCache/repositoryCache.ts similarity index 91% rename from entities/repositoryCache/repositoryCache.ts rename to business/entities/repositoryCache/repositoryCache.ts index 78da4fe3d..f88af3a4b 100644 --- a/entities/repositoryCache/repositoryCache.ts +++ b/business/entities/repositoryCache/repositoryCache.ts @@ -3,23 +3,23 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityField } from '../../lib/entityMetadataProvider/entityMetadataProvider'; -import { EntityMetadataType, IEntityMetadata } from '../../lib/entityMetadataProvider/entityMetadata'; -import { IEntityMetadataFixedQuery, FixedQueryType } from '../../lib/entityMetadataProvider/query'; +import { EntityField } from '../../../lib/entityMetadataProvider/entityMetadataProvider'; +import { EntityMetadataType, IEntityMetadata } from '../../../lib/entityMetadataProvider/entityMetadata'; +import { IEntityMetadataFixedQuery, FixedQueryType } from '../../../lib/entityMetadataProvider/query'; import { EntityMetadataMappings, MetadataMappingDefinition, -} from '../../lib/entityMetadataProvider/declarations'; +} from '../../../lib/entityMetadataProvider/declarations'; import { PostgresGetAllEntities, PostgresJsonEntityQuery, PostgresSettings, PostgresConfiguration, -} from '../../lib/entityMetadataProvider/postgres'; -import { stringOrNumberAsString } from '../../utils'; -import { MemoryConfiguration, MemorySettings } from '../../lib/entityMetadataProvider/memory'; -import { Operations } from '../../business/operations'; -import { TableConfiguration } from '../../lib/entityMetadataProvider'; +} from '../../../lib/entityMetadataProvider/postgres'; +import { stringOrNumberAsString } from '../../../lib/utils'; +import { MemoryConfiguration, MemorySettings } from '../../../lib/entityMetadataProvider/memory'; +import { Operations } from '../../operations'; +import { TableConfiguration } from '../../../lib/entityMetadataProvider'; const type = new EntityMetadataType('RepositoryCache'); diff --git a/entities/repositoryCache/repositoryCacheProvider.ts b/business/entities/repositoryCache/repositoryCacheProvider.ts similarity index 98% rename from entities/repositoryCache/repositoryCacheProvider.ts rename to business/entities/repositoryCache/repositoryCacheProvider.ts index 9109917d2..08b868c62 100644 --- a/entities/repositoryCache/repositoryCacheProvider.ts +++ b/business/entities/repositoryCache/repositoryCacheProvider.ts @@ -7,7 +7,7 @@ import { IEntityMetadata, EntityMetadataBase, IEntityMetadataBaseOptions, -} from '../../lib/entityMetadataProvider/entityMetadata'; +} from '../../../lib/entityMetadataProvider/entityMetadata'; import { RepositoryCacheEntity, EntityImplementation, diff --git a/entities/repositoryCollaboratorCache/index.ts b/business/entities/repositoryCollaboratorCache/index.ts similarity index 100% rename from entities/repositoryCollaboratorCache/index.ts rename to business/entities/repositoryCollaboratorCache/index.ts diff --git a/entities/repositoryCollaboratorCache/repositoryCollaboratorCache.ts b/business/entities/repositoryCollaboratorCache/repositoryCollaboratorCache.ts similarity index 94% rename from entities/repositoryCollaboratorCache/repositoryCollaboratorCache.ts rename to business/entities/repositoryCollaboratorCache/repositoryCollaboratorCache.ts index 72e3c7a53..c701be627 100644 --- a/entities/repositoryCollaboratorCache/repositoryCollaboratorCache.ts +++ b/business/entities/repositoryCollaboratorCache/repositoryCollaboratorCache.ts @@ -3,23 +3,23 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityField } from '../../lib/entityMetadataProvider/entityMetadataProvider'; -import { EntityMetadataType, IEntityMetadata } from '../../lib/entityMetadataProvider/entityMetadata'; -import { IEntityMetadataFixedQuery, FixedQueryType } from '../../lib/entityMetadataProvider/query'; +import { EntityField } from '../../../lib/entityMetadataProvider/entityMetadataProvider'; +import { EntityMetadataType, IEntityMetadata } from '../../../lib/entityMetadataProvider/entityMetadata'; +import { IEntityMetadataFixedQuery, FixedQueryType } from '../../../lib/entityMetadataProvider/query'; import { EntityMetadataMappings, MetadataMappingDefinition, -} from '../../lib/entityMetadataProvider/declarations'; -import { GitHubCollaboratorType, GitHubRepositoryPermission } from '../../interfaces'; +} from '../../../lib/entityMetadataProvider/declarations'; +import { GitHubCollaboratorType, GitHubRepositoryPermission } from '../../../interfaces'; import { PostgresGetAllEntities, PostgresJsonEntityQuery, PostgresSettings, PostgresConfiguration, -} from '../../lib/entityMetadataProvider/postgres'; -import { stringOrNumberAsString } from '../../utils'; -import { MemoryConfiguration, MemorySettings } from '../../lib/entityMetadataProvider/memory'; -import { TableConfiguration } from '../../lib/entityMetadataProvider'; +} from '../../../lib/entityMetadataProvider/postgres'; +import { stringOrNumberAsString } from '../../../lib/utils'; +import { MemoryConfiguration, MemorySettings } from '../../../lib/entityMetadataProvider/memory'; +import { TableConfiguration } from '../../../lib/entityMetadataProvider'; const type = new EntityMetadataType('RepositoryCollaboratorCache'); diff --git a/entities/repositoryCollaboratorCache/repositoryCollaboratorCacheProvider.ts b/business/entities/repositoryCollaboratorCache/repositoryCollaboratorCacheProvider.ts similarity index 99% rename from entities/repositoryCollaboratorCache/repositoryCollaboratorCacheProvider.ts rename to business/entities/repositoryCollaboratorCache/repositoryCollaboratorCacheProvider.ts index b7da8d4d3..93dd18710 100644 --- a/entities/repositoryCollaboratorCache/repositoryCollaboratorCacheProvider.ts +++ b/business/entities/repositoryCollaboratorCache/repositoryCollaboratorCacheProvider.ts @@ -7,7 +7,7 @@ import { IEntityMetadata, EntityMetadataBase, IEntityMetadataBaseOptions, -} from '../../lib/entityMetadataProvider/entityMetadata'; +} from '../../../lib/entityMetadataProvider/entityMetadata'; import { RepositoryCollaboratorCacheEntity, EntityImplementation, diff --git a/entities/repositoryMetadata/index.ts b/business/entities/repositoryMetadata/index.ts similarity index 100% rename from entities/repositoryMetadata/index.ts rename to business/entities/repositoryMetadata/index.ts diff --git a/entities/repositoryMetadata/repositoryMetadata.ts b/business/entities/repositoryMetadata/repositoryMetadata.ts similarity index 95% rename from entities/repositoryMetadata/repositoryMetadata.ts rename to business/entities/repositoryMetadata/repositoryMetadata.ts index 791057a69..015290fb0 100644 --- a/entities/repositoryMetadata/repositoryMetadata.ts +++ b/business/entities/repositoryMetadata/repositoryMetadata.ts @@ -3,28 +3,28 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityField } from '../../lib/entityMetadataProvider/entityMetadataProvider'; -import type { IEntityMetadata } from '../../lib/entityMetadataProvider/entityMetadata'; -import { type IEntityMetadataFixedQuery, FixedQueryType } from '../../lib/entityMetadataProvider/query'; +import { EntityField } from '../../../lib/entityMetadataProvider/entityMetadataProvider'; +import type { IEntityMetadata } from '../../../lib/entityMetadataProvider/entityMetadata'; +import { type IEntityMetadataFixedQuery, FixedQueryType } from '../../../lib/entityMetadataProvider/query'; import { EntityMetadataMappings, MetadataMappingDefinition, -} from '../../lib/entityMetadataProvider/declarations'; +} from '../../../lib/entityMetadataProvider/declarations'; import { Type } from './type'; import { PostgresGetAllEntities, PostgresGetByID, PostgresSettings, PostgresConfiguration, -} from '../../lib/entityMetadataProvider/postgres'; -import { TableSettings } from '../../lib/entityMetadataProvider/table'; -import { MemoryConfiguration, MemorySettings } from '../../lib/entityMetadataProvider/memory'; +} from '../../../lib/entityMetadataProvider/postgres'; +import { TableSettings } from '../../../lib/entityMetadataProvider/table'; +import { MemoryConfiguration, MemorySettings } from '../../../lib/entityMetadataProvider/memory'; import { odata, TableEntityQueryOptions } from '@azure/data-tables'; import { GitHubRepositoryVisibility, IInitialTeamPermission, RepositoryLockdownState, -} from '../../interfaces/github/repos'; +} from '../../../interfaces/github/repos'; const type = Type; diff --git a/entities/repositoryMetadata/repositoryMetadataProvider.ts b/business/entities/repositoryMetadata/repositoryMetadataProvider.ts similarity index 98% rename from entities/repositoryMetadata/repositoryMetadataProvider.ts rename to business/entities/repositoryMetadata/repositoryMetadataProvider.ts index 9cd0d39b2..754486fb6 100644 --- a/entities/repositoryMetadata/repositoryMetadataProvider.ts +++ b/business/entities/repositoryMetadata/repositoryMetadataProvider.ts @@ -7,7 +7,7 @@ import { IEntityMetadata, EntityMetadataBase, IEntityMetadataBaseOptions, -} from '../../lib/entityMetadataProvider/entityMetadata'; +} from '../../../lib/entityMetadataProvider/entityMetadata'; import { RepositoryMetadataEntity, RepositoryMetadataFixedQueryAll, diff --git a/entities/repositoryMetadata/type.ts b/business/entities/repositoryMetadata/type.ts similarity index 68% rename from entities/repositoryMetadata/type.ts rename to business/entities/repositoryMetadata/type.ts index d86789e50..3c560ca42 100644 --- a/entities/repositoryMetadata/type.ts +++ b/business/entities/repositoryMetadata/type.ts @@ -3,6 +3,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityMetadataType } from '../../lib/entityMetadataProvider/entityMetadata'; +import { EntityMetadataType } from '../../../lib/entityMetadataProvider/entityMetadata'; export const Type = new EntityMetadataType('Repository'); diff --git a/entities/repositoryTeamCache/index.ts b/business/entities/repositoryTeamCache/index.ts similarity index 100% rename from entities/repositoryTeamCache/index.ts rename to business/entities/repositoryTeamCache/index.ts diff --git a/entities/repositoryTeamCache/repositoryTeamCache.ts b/business/entities/repositoryTeamCache/repositoryTeamCache.ts similarity index 93% rename from entities/repositoryTeamCache/repositoryTeamCache.ts rename to business/entities/repositoryTeamCache/repositoryTeamCache.ts index 2d4147517..c6a0cf66e 100644 --- a/entities/repositoryTeamCache/repositoryTeamCache.ts +++ b/business/entities/repositoryTeamCache/repositoryTeamCache.ts @@ -3,24 +3,24 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityField } from '../../lib/entityMetadataProvider/entityMetadataProvider'; -import { EntityMetadataType, IEntityMetadata } from '../../lib/entityMetadataProvider/entityMetadata'; -import { IEntityMetadataFixedQuery, FixedQueryType } from '../../lib/entityMetadataProvider/query'; +import { EntityField } from '../../../lib/entityMetadataProvider/entityMetadataProvider'; +import { EntityMetadataType, IEntityMetadata } from '../../../lib/entityMetadataProvider/entityMetadata'; +import { IEntityMetadataFixedQuery, FixedQueryType } from '../../../lib/entityMetadataProvider/query'; import { EntityMetadataMappings, MetadataMappingDefinition, -} from '../../lib/entityMetadataProvider/declarations'; +} from '../../../lib/entityMetadataProvider/declarations'; import { PostgresGetAllEntities, PostgresJsonEntityQuery, PostgresJsonEntityQueryMultiple, PostgresSettings, PostgresConfiguration, -} from '../../lib/entityMetadataProvider/postgres'; -import { stringOrNumberAsString } from '../../utils'; -import { GitHubRepositoryPermission } from '../../interfaces/github/repos'; -import { MemoryConfiguration, MemorySettings } from '../../lib/entityMetadataProvider/memory'; -import { TableConfiguration } from '../../lib/entityMetadataProvider'; +} from '../../../lib/entityMetadataProvider/postgres'; +import { stringOrNumberAsString } from '../../../lib/utils'; +import { GitHubRepositoryPermission } from '../../../interfaces/github/repos'; +import { MemoryConfiguration, MemorySettings } from '../../../lib/entityMetadataProvider/memory'; +import { TableConfiguration } from '../../../lib/entityMetadataProvider'; const type = new EntityMetadataType('RepositoryTeamCache'); diff --git a/entities/repositoryTeamCache/repositoryTeamCacheProvider.ts b/business/entities/repositoryTeamCache/repositoryTeamCacheProvider.ts similarity index 98% rename from entities/repositoryTeamCache/repositoryTeamCacheProvider.ts rename to business/entities/repositoryTeamCache/repositoryTeamCacheProvider.ts index 72fb0a38a..f22fd79d4 100644 --- a/entities/repositoryTeamCache/repositoryTeamCacheProvider.ts +++ b/business/entities/repositoryTeamCache/repositoryTeamCacheProvider.ts @@ -7,7 +7,7 @@ import { IEntityMetadata, EntityMetadataBase, IEntityMetadataBaseOptions, -} from '../../lib/entityMetadataProvider/entityMetadata'; +} from '../../../lib/entityMetadataProvider/entityMetadata'; import { RepositoryTeamCacheEntity, EntityImplementation, diff --git a/entities/teamCache/index.ts b/business/entities/teamCache/index.ts similarity index 97% rename from entities/teamCache/index.ts rename to business/entities/teamCache/index.ts index 57d9f81a8..aef008643 100644 --- a/entities/teamCache/index.ts +++ b/business/entities/teamCache/index.ts @@ -4,7 +4,7 @@ // import { ITeamCacheProvider, ITeamCacheCreateOptions, TeamCacheProvider } from './teamCacheProvider'; -import { FixedQueryType, IEntityMetadataFixedQuery } from '../../lib/entityMetadataProvider/query'; +import { FixedQueryType, IEntityMetadataFixedQuery } from '../../../lib/entityMetadataProvider/query'; export async function CreateTeamCacheProviderInstance( options?: ITeamCacheCreateOptions diff --git a/entities/teamCache/teamCache.ts b/business/entities/teamCache/teamCache.ts similarity index 89% rename from entities/teamCache/teamCache.ts rename to business/entities/teamCache/teamCache.ts index f5f3f3ffb..99bb3592c 100644 --- a/entities/teamCache/teamCache.ts +++ b/business/entities/teamCache/teamCache.ts @@ -3,23 +3,23 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityField } from '../../lib/entityMetadataProvider/entityMetadataProvider'; -import { EntityMetadataType, IEntityMetadata } from '../../lib/entityMetadataProvider/entityMetadata'; -import { IEntityMetadataFixedQuery, FixedQueryType } from '../../lib/entityMetadataProvider/query'; +import { EntityField } from '../../../lib/entityMetadataProvider/entityMetadataProvider'; +import { EntityMetadataType, IEntityMetadata } from '../../../lib/entityMetadataProvider/entityMetadata'; +import { IEntityMetadataFixedQuery, FixedQueryType } from '../../../lib/entityMetadataProvider/query'; import { EntityMetadataMappings, MetadataMappingDefinition, -} from '../../lib/entityMetadataProvider/declarations'; +} from '../../../lib/entityMetadataProvider/declarations'; import { PostgresJsonEntityQuery, PostgresGetAllEntities, PostgresSettings, PostgresConfiguration, -} from '../../lib/entityMetadataProvider/postgres'; +} from '../../../lib/entityMetadataProvider/postgres'; import { TeamCacheFixedQueryByOrganizationId, TeamCacheDeleteByOrganizationId } from '.'; -import { stringOrNumberAsString } from '../../utils'; -import { MemoryConfiguration, MemorySettings } from '../../lib/entityMetadataProvider/memory'; -import { TableConfiguration } from '../../lib/entityMetadataProvider'; +import { stringOrNumberAsString } from '../../../lib/utils'; +import { MemoryConfiguration, MemorySettings } from '../../../lib/entityMetadataProvider/memory'; +import { TableConfiguration } from '../../../lib/entityMetadataProvider'; const type = new EntityMetadataType('TeamCache'); diff --git a/entities/teamCache/teamCacheProvider.ts b/business/entities/teamCache/teamCacheProvider.ts similarity index 98% rename from entities/teamCache/teamCacheProvider.ts rename to business/entities/teamCache/teamCacheProvider.ts index dc29686b8..326aca957 100644 --- a/entities/teamCache/teamCacheProvider.ts +++ b/business/entities/teamCache/teamCacheProvider.ts @@ -7,7 +7,7 @@ import { IEntityMetadata, EntityMetadataBase, IEntityMetadataBaseOptions, -} from '../../lib/entityMetadataProvider/entityMetadata'; +} from '../../../lib/entityMetadataProvider/entityMetadata'; import { TeamCacheEntity } from './teamCache'; import { TeamCacheFixedQueryAll, diff --git a/entities/teamJoinApproval/approvalProvider.ts b/business/entities/teamJoinApproval/approvalProvider.ts similarity index 90% rename from entities/teamJoinApproval/approvalProvider.ts rename to business/entities/teamJoinApproval/approvalProvider.ts index 95a9acaad..7e3988fc6 100644 --- a/entities/teamJoinApproval/approvalProvider.ts +++ b/business/entities/teamJoinApproval/approvalProvider.ts @@ -4,7 +4,7 @@ // import { TeamJoinApprovalEntity } from './teamJoinApproval'; -import { IEntityMetadataProvider } from '../../lib/entityMetadataProvider/entityMetadataProvider'; +import { IEntityMetadataProvider } from '../../../lib/entityMetadataProvider/entityMetadataProvider'; export interface IApprovalProvider { initialize(): Promise; diff --git a/entities/teamJoinApproval/index.ts b/business/entities/teamJoinApproval/index.ts similarity index 63% rename from entities/teamJoinApproval/index.ts rename to business/entities/teamJoinApproval/index.ts index a7936f8bd..ec378ba3c 100644 --- a/entities/teamJoinApproval/index.ts +++ b/business/entities/teamJoinApproval/index.ts @@ -3,11 +3,8 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { - IApprovalProvider, - IApprovalProviderCreateOptions, -} from '../../entities/teamJoinApproval/approvalProvider'; -import { TeamJoinApprovalProvider } from '../../entities/teamJoinApproval/teamJoinApprovalProvider'; +import { IApprovalProvider, IApprovalProviderCreateOptions } from './approvalProvider'; +import { TeamJoinApprovalProvider } from './teamJoinApprovalProvider'; export async function createAndInitializeApprovalProviderInstance( options: IApprovalProviderCreateOptions diff --git a/entities/teamJoinApproval/teamJoinApproval.ts b/business/entities/teamJoinApproval/teamJoinApproval.ts similarity index 96% rename from entities/teamJoinApproval/teamJoinApproval.ts rename to business/entities/teamJoinApproval/teamJoinApproval.ts index e9a049b2b..443d39372 100644 --- a/entities/teamJoinApproval/teamJoinApproval.ts +++ b/business/entities/teamJoinApproval/teamJoinApproval.ts @@ -5,22 +5,22 @@ import { randomUUID } from 'crypto'; -import { IObjectWithDefinedKeys } from '../../lib/entityMetadataProvider/entityMetadataProvider'; -import { EntityMetadataType, IEntityMetadata } from '../../lib/entityMetadataProvider/entityMetadata'; +import { IObjectWithDefinedKeys } from '../../../lib/entityMetadataProvider/entityMetadataProvider'; +import { EntityMetadataType, IEntityMetadata } from '../../../lib/entityMetadataProvider/entityMetadata'; import { MetadataMappingDefinition, EntityMetadataMappings, -} from '../../lib/entityMetadataProvider/declarations'; -import { FixedQueryType, IEntityMetadataFixedQuery } from '../../lib/entityMetadataProvider/query'; -import { stringOrNumberAsString, stringOrNumberArrayAsStringArray } from '../../utils'; +} from '../../../lib/entityMetadataProvider/declarations'; +import { FixedQueryType, IEntityMetadataFixedQuery } from '../../../lib/entityMetadataProvider/query'; +import { stringOrNumberAsString, stringOrNumberArrayAsStringArray } from '../../../lib/utils'; import { PostgresGetAllEntities, PostgresJsonEntityQuery, PostgresSettings, PostgresConfiguration, -} from '../../lib/entityMetadataProvider/postgres'; -import { TableSettings } from '../../lib/entityMetadataProvider/table'; -import { MemorySettings } from '../../lib/entityMetadataProvider/memory'; +} from '../../../lib/entityMetadataProvider/postgres'; +import { TableSettings } from '../../../lib/entityMetadataProvider/table'; +import { MemorySettings } from '../../../lib/entityMetadataProvider/memory'; import { odata, TableEntityQueryOptions } from '@azure/data-tables'; const type = new EntityMetadataType('TeamJoinRequest'); diff --git a/entities/teamJoinApproval/teamJoinApprovalProvider.ts b/business/entities/teamJoinApproval/teamJoinApprovalProvider.ts similarity index 98% rename from entities/teamJoinApproval/teamJoinApprovalProvider.ts rename to business/entities/teamJoinApproval/teamJoinApprovalProvider.ts index 2cf004b0f..1a5bb4691 100644 --- a/entities/teamJoinApproval/teamJoinApprovalProvider.ts +++ b/business/entities/teamJoinApproval/teamJoinApprovalProvider.ts @@ -7,7 +7,7 @@ import { IApprovalProvider } from './approvalProvider'; import { IEntityMetadataBaseOptions, EntityMetadataBase, -} from '../../lib/entityMetadataProvider/entityMetadata'; +} from '../../../lib/entityMetadataProvider/entityMetadata'; import { TeamJoinApprovalEntity, TeamJoinRequestFixedQueryByTeam, diff --git a/entities/teamMemberCache/index.ts b/business/entities/teamMemberCache/index.ts similarity index 98% rename from entities/teamMemberCache/index.ts rename to business/entities/teamMemberCache/index.ts index ebd0efadd..d799cc026 100644 --- a/entities/teamMemberCache/index.ts +++ b/business/entities/teamMemberCache/index.ts @@ -8,7 +8,7 @@ import { ITeamMemberCacheCreateOptions, TeamMemberCacheProvider, } from './teamMemberCacheProvider'; -import { FixedQueryType, IEntityMetadataFixedQuery } from '../../lib/entityMetadataProvider/query'; +import { FixedQueryType, IEntityMetadataFixedQuery } from '../../../lib/entityMetadataProvider/query'; export async function CreateTeamMemberCacheProviderInstance( options?: ITeamMemberCacheCreateOptions diff --git a/entities/teamMemberCache/teamMemberCache.ts b/business/entities/teamMemberCache/teamMemberCache.ts similarity index 91% rename from entities/teamMemberCache/teamMemberCache.ts rename to business/entities/teamMemberCache/teamMemberCache.ts index 2cffaaa20..3a7c107a6 100644 --- a/entities/teamMemberCache/teamMemberCache.ts +++ b/business/entities/teamMemberCache/teamMemberCache.ts @@ -3,13 +3,13 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityField } from '../../lib/entityMetadataProvider/entityMetadataProvider'; -import { EntityMetadataType, IEntityMetadata } from '../../lib/entityMetadataProvider/entityMetadata'; -import { IEntityMetadataFixedQuery, FixedQueryType } from '../../lib/entityMetadataProvider/query'; +import { EntityField } from '../../../lib/entityMetadataProvider/entityMetadataProvider'; +import { EntityMetadataType, IEntityMetadata } from '../../../lib/entityMetadataProvider/entityMetadata'; +import { IEntityMetadataFixedQuery, FixedQueryType } from '../../../lib/entityMetadataProvider/query'; import { EntityMetadataMappings, MetadataMappingDefinition, -} from '../../lib/entityMetadataProvider/declarations'; +} from '../../../lib/entityMetadataProvider/declarations'; import { TeamMemberCacheFixedQueryByOrganizationId, TeamMemberCacheFixedQueryByUserId, @@ -17,16 +17,16 @@ import { TeamMemberCacheFixedQueryByOrganizationIdAndUserId, TeamMemberCacheDeleteByOrganizationId, } from '.'; -import { GitHubTeamRole } from '../../interfaces'; +import { GitHubTeamRole } from '../../../interfaces'; import { PostgresGetAllEntities, PostgresJsonEntityQuery, PostgresSettings, PostgresConfiguration, -} from '../../lib/entityMetadataProvider/postgres'; -import { stringOrNumberAsString } from '../../utils'; -import { MemoryConfiguration, MemorySettings } from '../../lib/entityMetadataProvider/memory'; -import { TableConfiguration } from '../../lib/entityMetadataProvider'; +} from '../../../lib/entityMetadataProvider/postgres'; +import { stringOrNumberAsString } from '../../../lib/utils'; +import { MemoryConfiguration, MemorySettings } from '../../../lib/entityMetadataProvider/memory'; +import { TableConfiguration } from '../../../lib/entityMetadataProvider'; const type = new EntityMetadataType('TeamMemberCache'); diff --git a/entities/teamMemberCache/teamMemberCacheProvider.ts b/business/entities/teamMemberCache/teamMemberCacheProvider.ts similarity index 99% rename from entities/teamMemberCache/teamMemberCacheProvider.ts rename to business/entities/teamMemberCache/teamMemberCacheProvider.ts index c9083fe39..dc109276a 100644 --- a/entities/teamMemberCache/teamMemberCacheProvider.ts +++ b/business/entities/teamMemberCache/teamMemberCacheProvider.ts @@ -7,7 +7,7 @@ import { IEntityMetadata, EntityMetadataBase, IEntityMetadataBaseOptions, -} from '../../lib/entityMetadataProvider/entityMetadata'; +} from '../../../lib/entityMetadataProvider/entityMetadata'; import { TeamMemberCacheEntity, EntityImplementation } from './teamMemberCache'; import { TeamMemberCacheFixedQueryAll, diff --git a/entities/token/index.ts b/business/entities/token/index.ts similarity index 90% rename from entities/token/index.ts rename to business/entities/token/index.ts index 98f14a4b0..5d152e2b7 100644 --- a/entities/token/index.ts +++ b/business/entities/token/index.ts @@ -5,7 +5,7 @@ import { TokenProvider } from './tokenProvider'; import { PersonalAccessToken } from './token'; -import { IEntityMetadataBaseOptions } from '../../lib/entityMetadataProvider/entityMetadata'; +import { IEntityMetadataBaseOptions } from '../../../lib/entityMetadataProvider/entityMetadata'; export interface ITokenProvider { initialize(): Promise; diff --git a/entities/token/token.ts b/business/entities/token/token.ts similarity index 94% rename from entities/token/token.ts rename to business/entities/token/token.ts index c036d1a1e..518dbe6db 100644 --- a/entities/token/token.ts +++ b/business/entities/token/token.ts @@ -5,25 +5,28 @@ import crypto from 'crypto'; -import { EntityField, IObjectWithDefinedKeys } from '../../lib/entityMetadataProvider/entityMetadataProvider'; -import { EntityMetadataType, IEntityMetadata } from '../../lib/entityMetadataProvider/entityMetadata'; +import { + EntityField, + IObjectWithDefinedKeys, +} from '../../../lib/entityMetadataProvider/entityMetadataProvider'; +import { EntityMetadataType, IEntityMetadata } from '../../../lib/entityMetadataProvider/entityMetadata'; import { MetadataMappingDefinition, EntityMetadataMappings, -} from '../../lib/entityMetadataProvider/declarations'; -import { IEntityMetadataFixedQuery, FixedQueryType } from '../../lib/entityMetadataProvider/query'; +} from '../../../lib/entityMetadataProvider/declarations'; +import { IEntityMetadataFixedQuery, FixedQueryType } from '../../../lib/entityMetadataProvider/query'; import { TokenGenerator } from './tokenGenerator'; import { QueryTokensByCorporateID } from './tokenProvider'; import { Type } from './type'; -import { TableSettings } from '../../lib/entityMetadataProvider/table'; -import { MemorySettings } from '../../lib/entityMetadataProvider/memory'; +import { TableSettings } from '../../../lib/entityMetadataProvider/table'; +import { MemorySettings } from '../../../lib/entityMetadataProvider/memory'; import { odata, TableEntityQueryOptions } from '@azure/data-tables'; import { PostgresConfiguration, PostgresJsonEntityQuery, PostgresSettings, -} from '../../lib/entityMetadataProvider/postgres'; -import type { ApiClientGroupDisplay } from '../../interfaces/api'; +} from '../../../lib/entityMetadataProvider/postgres'; +import type { ApiClientGroupDisplay } from '../../../interfaces/api'; const type = Type; diff --git a/entities/token/tokenGenerator.ts b/business/entities/token/tokenGenerator.ts similarity index 100% rename from entities/token/tokenGenerator.ts rename to business/entities/token/tokenGenerator.ts diff --git a/entities/token/tokenProvider.ts b/business/entities/token/tokenProvider.ts similarity index 95% rename from entities/token/tokenProvider.ts rename to business/entities/token/tokenProvider.ts index 19f61926d..6ad5b13bb 100644 --- a/entities/token/tokenProvider.ts +++ b/business/entities/token/tokenProvider.ts @@ -3,10 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityMetadataBase } from '../../lib/entityMetadataProvider/entityMetadata'; +import { EntityMetadataBase } from '../../../lib/entityMetadataProvider/entityMetadata'; import { PersonalAccessToken, EntityImplementation } from './token'; import { ITokenProvider, ITokenProviderCreateOptions } from '.'; -import { IEntityMetadataFixedQuery, FixedQueryType } from '../../lib/entityMetadataProvider/query'; +import { IEntityMetadataFixedQuery, FixedQueryType } from '../../../lib/entityMetadataProvider/query'; import { Type } from './type'; const thisProviderType = Type; diff --git a/entities/token/type.ts b/business/entities/token/type.ts similarity index 68% rename from entities/token/type.ts rename to business/entities/token/type.ts index 8d70d2f71..a0ca4ea4e 100644 --- a/entities/token/type.ts +++ b/business/entities/token/type.ts @@ -3,6 +3,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { EntityMetadataType } from '../../lib/entityMetadataProvider/entityMetadata'; +import { EntityMetadataType } from '../../../lib/entityMetadataProvider/entityMetadata'; export const Type = new EntityMetadataType('Token'); diff --git a/entities/userSettings.ts b/business/entities/userSettings.ts similarity index 93% rename from entities/userSettings.ts rename to business/entities/userSettings.ts index 503809745..a8756c1c8 100644 --- a/entities/userSettings.ts +++ b/business/entities/userSettings.ts @@ -8,13 +8,13 @@ import { IEntityMetadataBaseOptions, EntityMetadataBase, IEntityMetadata, -} from '../lib/entityMetadataProvider/entityMetadata'; -import { QueryBase, IEntityMetadataFixedQuery } from '../lib/entityMetadataProvider/query'; +} from '../../lib/entityMetadataProvider/entityMetadata'; +import { QueryBase, IEntityMetadataFixedQuery } from '../../lib/entityMetadataProvider/query'; import { EntityMetadataMappings, MetadataMappingDefinition, -} from '../lib/entityMetadataProvider/declarations'; -import { PostgresConfiguration, PostgresSettings } from '../lib/entityMetadataProvider/postgres'; +} from '../../lib/entityMetadataProvider/declarations'; +import { PostgresConfiguration, PostgresSettings } from '../../lib/entityMetadataProvider/postgres'; const type = new EntityMetadataType('UserSettings'); const thisProviderType = type; diff --git a/features/index.ts b/business/features/index.ts similarity index 100% rename from features/index.ts rename to business/features/index.ts diff --git a/features/newRepositories/actions/createReadme.ts b/business/features/newRepositories/actions/createReadme.ts similarity index 93% rename from features/newRepositories/actions/createReadme.ts rename to business/features/newRepositories/actions/createReadme.ts index 738600562..1fb6fc636 100644 --- a/features/newRepositories/actions/createReadme.ts +++ b/business/features/newRepositories/actions/createReadme.ts @@ -3,8 +3,8 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { Repository } from '../../../business'; -import { ErrorHelper } from '../../../transitional'; +import { Repository } from '../../..'; +import { ErrorHelper } from '../../../../lib/transitional'; import { setupRepositoryReadmeSubstring } from '../strings'; export async function tryCreateReadme(repository: Repository, log: string[]): Promise { diff --git a/features/newRepositories/actions/deleteFork.ts b/business/features/newRepositories/actions/deleteFork.ts similarity index 93% rename from features/newRepositories/actions/deleteFork.ts rename to business/features/newRepositories/actions/deleteFork.ts index e68aa7cef..a15ff479a 100644 --- a/features/newRepositories/actions/deleteFork.ts +++ b/business/features/newRepositories/actions/deleteFork.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { Repository } from '../../../business'; +import { Repository } from '../../..'; export async function immediatelyDeleteFork(log: string[], repository: Repository): Promise { const organization = repository.organization; diff --git a/features/newRepositories/actions/downgradeCollaborator.ts b/business/features/newRepositories/actions/downgradeCollaborator.ts similarity index 87% rename from features/newRepositories/actions/downgradeCollaborator.ts rename to business/features/newRepositories/actions/downgradeCollaborator.ts index 127826cf6..ad1698e02 100644 --- a/features/newRepositories/actions/downgradeCollaborator.ts +++ b/business/features/newRepositories/actions/downgradeCollaborator.ts @@ -3,8 +3,8 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { Repository } from '../../../business'; -import { GitHubRepositoryPermission } from '../../../interfaces'; +import { Repository } from '../../..'; +import { GitHubRepositoryPermission } from '../../../../interfaces'; export async function tryDowngradeCollaborator( repository: Repository, diff --git a/features/newRepositories/actions/dropCollaborator.ts b/business/features/newRepositories/actions/dropCollaborator.ts similarity index 93% rename from features/newRepositories/actions/dropCollaborator.ts rename to business/features/newRepositories/actions/dropCollaborator.ts index 2382c1b3a..508aef375 100644 --- a/features/newRepositories/actions/dropCollaborator.ts +++ b/business/features/newRepositories/actions/dropCollaborator.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { Repository } from '../../../business'; +import { Repository } from '../../..'; export async function tryDropCollaborator( repository: Repository, diff --git a/features/newRepositories/actions/dropTeam.ts b/business/features/newRepositories/actions/dropTeam.ts similarity index 93% rename from features/newRepositories/actions/dropTeam.ts rename to business/features/newRepositories/actions/dropTeam.ts index 186a73566..62af1b5ef 100644 --- a/features/newRepositories/actions/dropTeam.ts +++ b/business/features/newRepositories/actions/dropTeam.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { Repository, Team } from '../../../business'; +import { Repository, Team } from '../../..'; export async function tryDropTeam(repository: Repository, team: Team, log: string[]): Promise { const organization = repository.organization; diff --git a/features/newRepositories/actions/index.ts b/business/features/newRepositories/actions/index.ts similarity index 100% rename from features/newRepositories/actions/index.ts rename to business/features/newRepositories/actions/index.ts diff --git a/features/newRepositories/actions/lockdown.ts b/business/features/newRepositories/actions/lockdown.ts similarity index 91% rename from features/newRepositories/actions/lockdown.ts rename to business/features/newRepositories/actions/lockdown.ts index a3331be07..de6d28b23 100644 --- a/features/newRepositories/actions/lockdown.ts +++ b/business/features/newRepositories/actions/lockdown.ts @@ -3,8 +3,8 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { Repository } from '../../../business'; -import { GitHubCollaboratorAffiliationQuery } from '../../../interfaces'; +import { Repository } from '../../..'; +import { GitHubCollaboratorAffiliationQuery } from '../../../../interfaces'; import { tryDowngradeCollaborator } from './downgradeCollaborator'; import { tryDropCollaborator } from './dropCollaborator'; import { tryDropTeam } from './dropTeam'; @@ -42,7 +42,7 @@ export async function lockdownRepository( if (collaborator.login.toLowerCase() !== creatorLogin.toLowerCase()) { await tryDropCollaborator(repository, collaborator.login, log); } else { - // Downgrade the creator to only having READ access (V2) + // Downgrade the creator to only having READ access if (collaborator.permissions.admin || collaborator.permissions.push) { await tryDowngradeCollaborator(repository, collaborator.login, log); } else { diff --git a/features/newRepositories/approve.ts b/business/features/newRepositories/approve.ts similarity index 97% rename from features/newRepositories/approve.ts rename to business/features/newRepositories/approve.ts index 051711e10..ec731b651 100644 --- a/features/newRepositories/approve.ts +++ b/business/features/newRepositories/approve.ts @@ -3,10 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { Operations, Repository } from '../../business'; +import { Operations, Repository } from '../..'; import { IRepositoryMetadataProvider } from '../../entities/repositoryMetadata/repositoryMetadataProvider'; -import { ICachedEmployeeInformation, RepositoryLockdownState } from '../../interfaces'; -import { IMail } from '../../lib/mailProvider'; +import { ICachedEmployeeInformation, RepositoryLockdownState } from '../../../interfaces'; +import { IMail } from '../../../lib/mailProvider'; import { IMailToRemoveAdministrativeLock } from './interfaces'; export async function administrativeApproval( diff --git a/features/newRepositories/initializeMetadata.ts b/business/features/newRepositories/initializeMetadata.ts similarity index 84% rename from features/newRepositories/initializeMetadata.ts rename to business/features/newRepositories/initializeMetadata.ts index ef6217d42..fd53feef0 100644 --- a/features/newRepositories/initializeMetadata.ts +++ b/business/features/newRepositories/initializeMetadata.ts @@ -4,7 +4,8 @@ // import { RepositoryMetadataEntity } from '../../entities/repositoryMetadata/repositoryMetadata'; -import { GitHubRepositoryVisibility, ICorporateLink } from '../../interfaces'; +import { GitHubRepositoryVisibility, ICorporateLink } from '../../../interfaces'; +import { ErrorHelper } from '../../../lib/transitional'; import { RepositoryLockdownCreateOptions } from './interfaces'; export async function initializeRepositoryMetadata(parameters: RepositoryLockdownCreateOptions) { @@ -19,7 +20,7 @@ export async function initializeRepositoryMetadata(parameters: RepositoryLockdow instances, } = parameters; const { repository } = instances; - const { repositoryMetadataProvider } = providers; + const { insights, repositoryMetadataProvider } = providers; const { organization } = repository; try { // Repository metadata is used to lock down the security of the repository setup system. Only @@ -28,8 +29,20 @@ export async function initializeRepositoryMetadata(parameters: RepositoryLockdow let repositoryMetadata: RepositoryMetadataEntity = null; try { repositoryMetadata = await repositoryMetadataProvider.getRepositoryMetadata(String(repository.id)); - } catch (doesNotExist) { - // ignore: 404 is standard here + } catch (error) { + if (!ErrorHelper.IsNotFound(error)) { + insights?.trackException({ + exception: error, + properties: { + content: 'RepositoryMetadataProviderGetRepositoryMetadataError', + message: error.message, + repositoryId: repository.id.toString(), + repositoryName: repository.name, + organizationName: organization.name, + organizationId: organization.id.toString(), + }, + }); + } } if (repositoryMetadata) { lockdownLog.push(`Repository metadata already exists for repository ID ${repository.id}`); diff --git a/features/newRepositories/interfaces.ts b/business/features/newRepositories/interfaces.ts similarity index 86% rename from features/newRepositories/interfaces.ts rename to business/features/newRepositories/interfaces.ts index 7d5a19cea..d4c07f067 100644 --- a/features/newRepositories/interfaces.ts +++ b/business/features/newRepositories/interfaces.ts @@ -3,9 +3,11 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { Operations, Organization, Repository } from '../../business'; +import { TelemetryClient } from 'applicationinsights'; + +import { Operations, Organization, Repository } from '../..'; import { IRepositoryMetadataProvider } from '../../entities/repositoryMetadata/repositoryMetadataProvider'; -import { ICorporateLink, RepositoryLockdownState } from '../../interfaces'; +import { ICorporateLink, RepositoryLockdownState } from '../../../interfaces'; export enum RepositoryLockdownCreateType { Created = 'created', @@ -13,6 +15,7 @@ export enum RepositoryLockdownCreateType { } export type RepositoryLockdownCreateProviders = { + insights: TelemetryClient; operations: Operations; repositoryMetadataProvider: IRepositoryMetadataProvider; }; @@ -73,9 +76,10 @@ export interface IMailToLockdownRepo { isForkDeleted: boolean; } -export interface INewRepositoryLockdownSystemOptions { +export type NewRepositoryLockdownSystemOptions = { + insights: TelemetryClient; operations: Operations; organization: Organization; repository: Repository; repositoryMetadataProvider: IRepositoryMetadataProvider; -} +}; diff --git a/features/newRepositories/lockdownMail.ts b/business/features/newRepositories/lockdownMail.ts similarity index 97% rename from features/newRepositories/lockdownMail.ts rename to business/features/newRepositories/lockdownMail.ts index 0fba395dc..ce4a9edbe 100644 --- a/features/newRepositories/lockdownMail.ts +++ b/business/features/newRepositories/lockdownMail.ts @@ -3,10 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { Operations, Repository } from '../../business'; -import { ICachedEmployeeInformation, ICorporateLink, RepositoryLockdownState } from '../../interfaces'; -import { IMail } from '../../lib/mailProvider'; -import getCompanySpecificDeployment from '../../middleware/companySpecificDeployment'; +import { Operations, Repository } from '../..'; +import { ICachedEmployeeInformation, ICorporateLink, RepositoryLockdownState } from '../../../interfaces'; +import { IMail } from '../../../lib/mailProvider'; +import getCompanySpecificDeployment from '../../../middleware/companySpecificDeployment'; import { ILockdownResult, IMailToLockdownRepo, RepositoryLockdownCreateType } from './interfaces'; const defaultMailTemplate = 'newrepolockdown'; diff --git a/features/newRepositories/newRepositoryLockdown.ts b/business/features/newRepositories/newRepositoryLockdown.ts similarity index 85% rename from features/newRepositories/newRepositoryLockdown.ts rename to business/features/newRepositories/newRepositoryLockdown.ts index 3ae9829de..4a5dfe90c 100644 --- a/features/newRepositories/newRepositoryLockdown.ts +++ b/business/features/newRepositories/newRepositoryLockdown.ts @@ -3,20 +3,20 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { Operations, Organization, Repository } from '../../business'; +import { Operations, Organization, Repository } from '../..'; import { IRepositoryMetadataProvider } from '../../entities/repositoryMetadata/repositoryMetadataProvider'; -import { botBracket } from '../../utils'; +import { botBracket } from '../../../lib/utils'; import { ICorporateLink, RepositoryLockdownState, NoCacheNoBackground, OrganizationMembershipState, OrganizationMembershipRole, -} from '../../interfaces'; -import { CreateError } from '../../transitional'; +} from '../../../interfaces'; +import { CreateError } from '../../../lib/transitional'; import { ILockdownResult, - INewRepositoryLockdownSystemOptions, + NewRepositoryLockdownSystemOptions, IRepoPatch, RepositoryLockdownCreateOptions, RepositoryLockdownCreateType, @@ -29,8 +29,10 @@ import { setupRepositorySubstring } from './strings'; import { immediatelyDeleteFork, tryCreateReadme } from './actions'; import { repositoryLockdownStatics } from './staticFunctions'; import { lockdownRepository } from './actions/lockdown'; +import { TelemetryClient } from 'applicationinsights'; export default class NewRepositoryLockdownSystem { + insights: TelemetryClient; organization: Organization; operations: Operations; repository: Repository; @@ -40,7 +42,8 @@ export default class NewRepositoryLockdownSystem { private readonly lockdownForks: boolean; private readonly lockdownTransfers: boolean; - constructor(options: INewRepositoryLockdownSystemOptions) { + constructor(options: NewRepositoryLockdownSystemOptions) { + this.insights = options.insights; this.organization = options.organization; this.operations = options.operations; this.repository = options.repository; @@ -108,6 +111,7 @@ export default class NewRepositoryLockdownSystem { repository: this.repository, }, providers: { + insights: this.insights, repositoryMetadataProvider: this.repositoryMetadataProvider, operations: this.operations, }, @@ -162,20 +166,22 @@ export default class NewRepositoryLockdownSystem { if (!this.organization.isNewRepositoryLockdownSystemEnabled()) { return { wasLocked: false, notifyOperations: false }; } - lockdownLog.push( - `Confirmed that the ${this.organization.name} organization has opted into the new repository lockdown system` - ); - if (this.deleteForks) { - lockdownLog.push( - 'Confirmed that the delete fork feature is enabled for this org. It will supersede fork lockdown capabilities.' - ); - } - if (this.lockdownForks) { - lockdownLog.push('Confirmed that the additional fork lockdown feature is enabled for this org'); - } - if (this.lockdownTransfers) { - lockdownLog.push('Confirmed that the additional transfer lockdown feature is enabled for this org'); - } + // informationalLog.push( + // `Confirmed that the ${this.organization.name} organization has opted into the new repository lockdown system` + // ); + // if (this.deleteForks) { + // informationalLog.push( + // 'Confirmed that the delete fork feature is enabled for this org. It will supersede fork lockdown capabilities.' + // ); + // } + // if (this.lockdownForks) { + // informationalLog.push('Confirmed that the additional fork lockdown feature is enabled for this org'); + // } + // if (this.lockdownTransfers) { + // informationalLog.push( + // 'Confirmed that the additional transfer lockdown feature is enabled for this org' + // ); + // } const setupUrl = `${this.organization.absoluteBaseUrl}wizard?existingreponame=${this.repository.name}&existingrepoid=${this.repository.id}`; const isTransfer = action === RepositoryLockdownCreateType.Transferred; if (isTransfer && !this.lockdownTransfers) { @@ -198,7 +204,7 @@ export default class NewRepositoryLockdownSystem { lockdownLog.push(`Created by a bot or GitHub App: ${username}`); return { wasLocked: false, log: lockdownLog, notifyOperations: false }; } - lockdownLog.push(`Confirmed that the repository was not ${action} by a bot`); + // informationalLog.push(`Confirmed that the repository was not ${action} by a bot`); // a repository created by one of the operations accounts in the allowed list is OK and will not be locked down const systemAccounts = new Set( this.operations.systemAccountsByUsername.map((username) => username.toLowerCase()) @@ -207,11 +213,11 @@ export default class NewRepositoryLockdownSystem { lockdownLog.push(`Created by a system account: ${username}`); return { wasLocked: false, log: lockdownLog, notifyOperations: true }; } - lockdownLog.push( - `Confirmed that the repository was not ${action} by any of the system accounts: ${Array.from( - systemAccounts.values() - ).join(', ')}` - ); + // informationalLog.push( + // `Confirmed that the repository was not ${action} by any of the system accounts: ${Array.from( + // systemAccounts.values() + // ).join(', ')}` + // ); const userMembership = await this.organization.getMembership(username, NoCacheNoBackground); let userIsOrganizationOwner = false; if ( @@ -261,13 +267,13 @@ export default class NewRepositoryLockdownSystem { const patchChanges: IRepoPatch = {}; if (!isFork && !isTransfer && !this.repository.private) { - lockdownLog.push('Preparing to hide the public repository pending setup (V2)'); + // informationalLog.push('Preparing to hide the public repository pending setup'); patchChanges.private = true; } if (!isFork) { - lockdownLog.push('Updating the description and web site to point at the setup wizard (V2)'); - lockdownLog.push(`Will direct the user to ${setupUrl}`); - patchChanges.description = `${setupRepositorySubstring} ${setupUrl}`; + // informationalLog.push('Updating the description and web site to point at the setup wizard'); + // informationalLog.push(`Will direct the user to ${setupUrl}`); + patchChanges.description = setupRepositorySubstring; patchChanges.homepage = setupUrl; } if (Object.getOwnPropertyNames(patchChanges).length > 0) { @@ -280,7 +286,7 @@ export default class NewRepositoryLockdownSystem { lockdownLog.push(`Updating repository with patch ${descriptiveUpdate}`); await this.repository.update(patchChanges); } catch (hideError) { - lockdownLog.push(`Error while trying to update the new repo: ${hideError} (V2)`); + lockdownLog.push(`Error while trying to update the new repo: ${hideError}`); } } } diff --git a/features/newRepositories/selfServiceDelete.ts b/business/features/newRepositories/selfServiceDelete.ts similarity index 97% rename from features/newRepositories/selfServiceDelete.ts rename to business/features/newRepositories/selfServiceDelete.ts index 9d4374c6d..9e5fbbdb2 100644 --- a/features/newRepositories/selfServiceDelete.ts +++ b/business/features/newRepositories/selfServiceDelete.ts @@ -3,10 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { Operations, Repository } from '../../business'; +import { Operations, Repository } from '../..'; import { IRepositoryMetadataProvider } from '../../entities/repositoryMetadata/repositoryMetadataProvider'; -import { ICachedEmployeeInformation, RepositoryLockdownState } from '../../interfaces'; -import { IMail } from '../../lib/mailProvider'; +import { ICachedEmployeeInformation, RepositoryLockdownState } from '../../../interfaces'; +import { IMail } from '../../../lib/mailProvider'; export async function selfServiceDeleteLockedRepository( operations: Operations, diff --git a/features/newRepositories/staticFunctions.ts b/business/features/newRepositories/staticFunctions.ts similarity index 90% rename from features/newRepositories/staticFunctions.ts rename to business/features/newRepositories/staticFunctions.ts index 2044ce2c3..d5e225f6b 100644 --- a/features/newRepositories/staticFunctions.ts +++ b/business/features/newRepositories/staticFunctions.ts @@ -3,9 +3,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { Repository } from '../../business'; +import { Repository } from '../..'; import { RepositoryMetadataEntity } from '../../entities/repositoryMetadata/repositoryMetadata'; -import { IndividualContext } from '../../business/user'; +import { IndividualContext } from '../../user'; import { validateUserCanSelfDeleteRepository } from './validateSelfServiceDelete'; import { validateUserCanConfigureRepository } from './validateSelfServiceSetup'; diff --git a/features/newRepositories/strings.ts b/business/features/newRepositories/strings.ts similarity index 100% rename from features/newRepositories/strings.ts rename to business/features/newRepositories/strings.ts diff --git a/features/newRepositories/validateSelfServiceDelete.ts b/business/features/newRepositories/validateSelfServiceDelete.ts similarity index 90% rename from features/newRepositories/validateSelfServiceDelete.ts rename to business/features/newRepositories/validateSelfServiceDelete.ts index d16bf6be3..e1f3cc714 100644 --- a/features/newRepositories/validateSelfServiceDelete.ts +++ b/business/features/newRepositories/validateSelfServiceDelete.ts @@ -5,11 +5,11 @@ import { DateTime } from 'luxon'; -import { Repository } from '../../business'; +import { Repository } from '../..'; import { RepositoryMetadataEntity } from '../../entities/repositoryMetadata/repositoryMetadata'; -import { RepositoryLockdownState } from '../../interfaces'; -import { IndividualContext } from '../../business/user'; -import { daysInMilliseconds } from '../../utils'; +import { RepositoryLockdownState } from '../../../interfaces'; +import { IndividualContext } from '../../user'; +import { daysInMilliseconds } from '../../../lib/utils'; export async function validateUserCanSelfDeleteRepository( repository: Repository, diff --git a/features/newRepositories/validateSelfServiceSetup.ts b/business/features/newRepositories/validateSelfServiceSetup.ts similarity index 94% rename from features/newRepositories/validateSelfServiceSetup.ts rename to business/features/newRepositories/validateSelfServiceSetup.ts index dcb08455e..edbd2cd04 100644 --- a/features/newRepositories/validateSelfServiceSetup.ts +++ b/business/features/newRepositories/validateSelfServiceSetup.ts @@ -4,8 +4,8 @@ // import { RepositoryMetadataEntity } from '../../entities/repositoryMetadata/repositoryMetadata'; -import { RepositoryLockdownState } from '../../interfaces'; -import { IndividualContext } from '../../business/user'; +import { RepositoryLockdownState } from '../../../interfaces'; +import { IndividualContext } from '../../user'; export async function validateUserCanConfigureRepository( metadata: RepositoryMetadataEntity, diff --git a/features/publicReposFastFilter.ts b/business/features/publicReposFastFilter.ts similarity index 94% rename from features/publicReposFastFilter.ts rename to business/features/publicReposFastFilter.ts index b876c57f2..e481faf57 100644 --- a/features/publicReposFastFilter.ts +++ b/business/features/publicReposFastFilter.ts @@ -3,8 +3,8 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { IProviders } from '../interfaces'; -import { Repository } from '../business'; +import { IProviders } from '../../interfaces'; +import { Repository } from '..'; // TODO: refresh occasionally. diff --git a/features/sudo/index.ts b/business/features/sudo/index.ts similarity index 93% rename from features/sudo/index.ts rename to business/features/sudo/index.ts index 839434bf5..f6eddcbcd 100644 --- a/features/sudo/index.ts +++ b/business/features/sudo/index.ts @@ -3,9 +3,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import type { Organization } from '../../business'; -import getCompanySpecificDeployment from '../../middleware/companySpecificDeployment'; -import { ICorporateLink, IProviders } from '../../interfaces'; +import type { Organization } from '../..'; +import getCompanySpecificDeployment from '../../../middleware/companySpecificDeployment'; +import { ICorporateLink, IProviders } from '../../../interfaces'; export interface IOrganizationSudo { isSudoer(githubLogin: string, link?: ICorporateLink): Promise; diff --git a/features/sudo/noop.ts b/business/features/sudo/noop.ts similarity index 81% rename from features/sudo/noop.ts rename to business/features/sudo/noop.ts index f81adeea2..8db9f7c00 100644 --- a/features/sudo/noop.ts +++ b/business/features/sudo/noop.ts @@ -4,8 +4,8 @@ // import { OrganizationSudo } from '.'; -import { Organization } from '../../business'; -import { ICorporateLink, IProviders } from '../../interfaces'; +import { Organization } from '../..'; +import { ICorporateLink, IProviders } from '../../../interfaces'; export class OrganizationSudoNoop extends OrganizationSudo { constructor( diff --git a/features/sudo/portal.ts b/business/features/sudo/portal.ts similarity index 94% rename from features/sudo/portal.ts rename to business/features/sudo/portal.ts index b87cd0635..dec705167 100644 --- a/features/sudo/portal.ts +++ b/business/features/sudo/portal.ts @@ -4,10 +4,10 @@ // import { IPortalSudo } from '.'; -import { Organization } from '../../business'; -import { IProviders, ICorporateLink } from '../../interfaces'; -import getCompanySpecificDeployment from '../../middleware/companySpecificDeployment'; -import { ErrorHelper } from '../../transitional'; +import { Organization } from '../..'; +import { IProviders, ICorporateLink } from '../../../interfaces'; +import getCompanySpecificDeployment from '../../../middleware/companySpecificDeployment'; +import { ErrorHelper } from '../../../lib/transitional'; abstract class PortalSudoBase { constructor(private providers: IProviders) {} diff --git a/features/sudo/securityGroup.ts b/business/features/sudo/securityGroup.ts similarity index 93% rename from features/sudo/securityGroup.ts rename to business/features/sudo/securityGroup.ts index c650ed480..81b7fdc39 100644 --- a/features/sudo/securityGroup.ts +++ b/business/features/sudo/securityGroup.ts @@ -4,9 +4,9 @@ // import { OrganizationSudo } from '.'; -import { Organization } from '../../business'; -import { IProviders, ICorporateLink } from '../../interfaces'; -import { ErrorHelper } from '../../transitional'; +import { Organization } from '../..'; +import { IProviders, ICorporateLink } from '../../../interfaces'; +import { ErrorHelper } from '../../../lib/transitional'; export const OrganizationFeatureSecurityGroupProperty = 'orgsudosecuritygroup'; diff --git a/features/sudo/sudo.md b/business/features/sudo/sudo.md similarity index 90% rename from features/sudo/sudo.md rename to business/features/sudo/sudo.md index ff567cde5..fca93b503 100644 --- a/features/sudo/sudo.md +++ b/business/features/sudo/sudo.md @@ -33,11 +33,6 @@ Overrides are available to allow the company-specific system to provide the org sudo instance for an organization, if you wish to implement a different approach, or use a different company-internal system for these decisions. -### Debug flags - -There is an environmental off-switch enabled that can turn off sudo, allowing for testing -as a regular user in local environments. That env variable name is `DEBUG_GITHUB_ORG_SUDO_OFF`. - ## portal sudo Portal sudo applies sudo for all organizations configured within the application. @@ -46,7 +41,7 @@ Used by system administrators typically. The original design was to use the sudo configuration from the first/primary GitHub org that was configured in the environment. -### Feature flag: FEATURE_FLAG_ALLOW_PORTAL_SUDO +## Feature flag: FEATURE_FLAG_ALLOW_PORTAL_SUDO > This feature is not on by default. @@ -63,7 +58,7 @@ Can be: For the security group provider, configuration should set `SUDO_PORTAL_SECURITY_GROUP_ID` to the security group ID to use. -### Debug flags +## Debug flags: portal sudo Two environment variables designed for development work exist: diff --git a/features/sudo/teams.ts b/business/features/sudo/teams.ts similarity index 91% rename from features/sudo/teams.ts rename to business/features/sudo/teams.ts index f15a48536..ed4758cbb 100644 --- a/features/sudo/teams.ts +++ b/business/features/sudo/teams.ts @@ -4,9 +4,9 @@ // import { OrganizationSudo } from '.'; -import { Organization } from '../../business'; -import { IProviders, ICorporateLink, GitHubTeamRole, ITeamMembershipRoleState } from '../../interfaces'; -import { ErrorHelper } from '../../transitional'; +import { Organization } from '../..'; +import { IProviders, ICorporateLink, GitHubTeamRole, ITeamMembershipRoleState } from '../../../interfaces'; +import { ErrorHelper } from '../../../lib/transitional'; export class OrganizationSudoGitHubTeams extends OrganizationSudo { constructor(providers: IProviders, organization: Organization) { diff --git a/features/teamMemberToMaintainerUpgrade.ts b/business/features/teamMemberToMaintainerUpgrade.ts similarity index 96% rename from features/teamMemberToMaintainerUpgrade.ts rename to business/features/teamMemberToMaintainerUpgrade.ts index f3f3f0d68..5ed5daff4 100644 --- a/features/teamMemberToMaintainerUpgrade.ts +++ b/business/features/teamMemberToMaintainerUpgrade.ts @@ -3,18 +3,18 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { Team } from '../business'; -import { Operations } from '../business'; -import { IndividualContext } from '../business/user'; -import { addArrayToSet } from '../utils'; -import { IMail } from '../lib/mailProvider'; +import { Team } from '..'; +import { Operations } from '..'; +import { IndividualContext } from '../user'; +import { addArrayToSet } from '../../lib/utils'; +import { IMail } from '../../lib/mailProvider'; import { NoCacheNoBackground, ITeamMembershipRoleState, OrganizationMembershipState, GitHubTeamRole, -} from '../interfaces'; -import { ErrorHelper } from '../transitional'; +} from '../../interfaces'; +import { ErrorHelper } from '../../lib/transitional'; interface ISelfServiceAllowedResult { currentMaintainerCount: number; diff --git a/business/graphManager.ts b/business/graphManager.ts index eb3624736..a0e0cdc2c 100644 --- a/business/graphManager.ts +++ b/business/graphManager.ts @@ -18,7 +18,7 @@ import { IPagedCrossOrganizationCacheOptions, GitHubRepositoryPermission, } from '../interfaces'; -import { isPermissionBetterThan } from '../transitional'; +import { isPermissionBetterThan } from '../lib/transitional'; interface ILocalLinksCache { updated: moment.Moment; diff --git a/business/operations/administration.ts b/business/operations/administration.ts index 6cc984d31..139f7e830 100644 --- a/business/operations/administration.ts +++ b/business/operations/administration.ts @@ -4,7 +4,7 @@ // import { IProviders } from '../../interfaces'; -import { ErrorHelper } from '../../transitional'; +import { ErrorHelper } from '../../lib/transitional'; export async function isAuthorizedSystemAdministrator( providers: IProviders, diff --git a/business/operations/core.ts b/business/operations/core.ts index 4a56d132f..161e2164e 100644 --- a/business/operations/core.ts +++ b/business/operations/core.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { OrganizationSetting } from '../../entities/organizationSettings/organizationSetting'; +import { OrganizationSetting } from '../entities/organizationSettings/organizationSetting'; import { GitHubAppAuthenticationType, AppPurpose, @@ -31,8 +31,8 @@ import { ICacheOptionsWithPurpose, } from '../../interfaces'; import { RestLibrary } from '../../lib/github'; -import { CreateError } from '../../transitional'; -import { wrapError } from '../../utils'; +import { CreateError } from '../../lib/transitional'; +import { wrapError } from '../../lib/utils'; import { Account } from '../account'; import GitHubApplication from '../application'; diff --git a/business/operations/index.ts b/business/operations/index.ts index 62cf38a1d..7040e423c 100644 --- a/business/operations/index.ts +++ b/business/operations/index.ts @@ -12,10 +12,11 @@ import { GraphManager } from '../graphManager'; import { GitHubOrganizationResponse, Organization } from '../organization'; import { GitHubTokenManager } from '../../lib/github/tokenManager'; import RenderHtmlMail from '../../lib/emailRender'; -import { wrapError, sortByCaseInsensitive } from '../../utils'; +import { wrapError, sortByCaseInsensitive } from '../../lib/utils'; import { Repository } from '../repository'; import { RestLibrary } from '../../lib/github'; import { + AppPurpose, AppPurposeTypes, getAppPurposeId, GitHubAppAuthenticationType, @@ -25,12 +26,12 @@ import { import { OrganizationFeature, OrganizationSetting, -} from '../../entities/organizationSettings/organizationSetting'; -import { OrganizationSettingProvider } from '../../entities/organizationSettings/organizationSettingProvider'; +} from '../entities/organizationSettings/organizationSetting'; +import { OrganizationSettingProvider } from '../entities/organizationSettings/organizationSettingProvider'; import { IMail } from '../../lib/mailProvider'; import { ILinkProvider } from '../../lib/linkProviders'; import { ICacheHelper } from '../../lib/caching'; -import { createPortalSudoInstance, IPortalSudo } from '../../features'; +import { createPortalSudoInstance, IPortalSudo } from '../features'; import { CacheDefault, getMaxAgeSeconds, IOperationsCoreOptions, OperationsCore } from './core'; import { linkAccounts as linkAccountsMethod } from './link'; import { sendTerminatedAccountMail as sendTerminatedAccountMailMethod } from './unlinkMail'; @@ -63,13 +64,16 @@ import { NoCacheNoBackground, SupportedLinkType, UnlinkPurpose, + type LinkEvent, + type UnlinkEvent, } from '../../interfaces'; -import { CreateError, ErrorHelper } from '../../transitional'; +import { CreateError, ErrorHelper } from '../../lib/transitional'; import { Team } from '../team'; -import { IRepositoryMetadataProvider } from '../../entities/repositoryMetadata/repositoryMetadataProvider'; +import { IRepositoryMetadataProvider } from '../entities/repositoryMetadata/repositoryMetadataProvider'; import { isAuthorizedSystemAdministrator } from './administration'; import type { ConfigGitHubOrganizationsSpecializedList } from '../../config/github.organizations.types'; import { type GitHubTokenType, getGitHubTokenTypeFromValue } from '../../lib/github/appTokens'; +import getCompanySpecificDeployment from '../../middleware/companySpecificDeployment'; export * from './core'; @@ -608,7 +612,7 @@ export class Operations if (entry.active && !visited.has(lowercase) && !entry.hasFeature(OrganizationFeature.Invisible)) { visited.add(lowercase); const orgInstance = this.getOrganization(lowercase); - const token = orgInstance.getAuthorizationHeader(); + const token = orgInstance.getAuthorizationHeader(AppPurpose.Data); tokens.set(lowercase, token); } } @@ -976,7 +980,7 @@ export class Operations const organization = this._organizationIds.get(lookupUsingIdOrCentralToken); let header: GetAuthorizationHeader = null; if (organization) { - header = organization.getAuthorizationHeader() as GetAuthorizationHeader; // fallback will happen + header = organization.getAuthorizationHeader(AppPurpose.Data) as GetAuthorizationHeader; } else { header = this.getPublicAuthorizationToken(); } @@ -1294,11 +1298,17 @@ export class Operations // Eventually link/unlink should move from context into operations here to centralize more than just the events - async fireLinkEvent(value): Promise { + async fireLinkEvent(value: LinkEvent): Promise { + const companySpecific = getCompanySpecificDeployment(); + companySpecific?.events?.linking?.onLink && companySpecific.events.linking.onLink(this.providers, value); await fireEvent(this.config, 'link', value); } - async fireUnlinkEvent(value): Promise { + async fireUnlinkEvent(value: UnlinkEvent): Promise { + const corporateId = value?.aad?.id; + const companySpecific = getCompanySpecificDeployment(); + companySpecific?.events?.linking?.onUnlink && + companySpecific.events.linking.onUnlink(this.providers, corporateId); await fireEvent(this.config, 'unlink', value); } diff --git a/business/operations/link.ts b/business/operations/link.ts index b41e2a6c2..d4a269857 100644 --- a/business/operations/link.ts +++ b/business/operations/link.ts @@ -12,7 +12,7 @@ import { ICorporateLink, } from '../../interfaces'; import getCompanySpecificDeployment from '../../middleware/companySpecificDeployment'; -import { CreateError, ErrorHelper, setImmediateAsync } from '../../transitional'; +import { CreateError, ErrorHelper, setImmediateAsync } from '../../lib/transitional'; export async function linkAccounts( operations: Operations, diff --git a/business/operations/unlinkMail.ts b/business/operations/unlinkMail.ts index e21709858..50522e05f 100644 --- a/business/operations/unlinkMail.ts +++ b/business/operations/unlinkMail.ts @@ -7,7 +7,7 @@ import { Operations } from '.'; import { Account } from '../account'; import { UnlinkPurpose, IUnlinkMailStatus, ICachedEmployeeInformation } from '../../interfaces'; import getCompanySpecificDeployment from '../../middleware/companySpecificDeployment'; -import { assertUnreachable } from '../../transitional'; +import { assertUnreachable } from '../../lib/transitional'; export async function sendTerminatedAccountMail( operations: Operations, diff --git a/business/organization.ts b/business/organization.ts index e05b92f29..ef8fa2b65 100644 --- a/business/organization.ts +++ b/business/organization.ts @@ -10,7 +10,7 @@ import { OrganizationMember } from './organizationMember'; import { Team } from './team'; import { Repository } from './repository'; -import { wrapError } from '../utils'; +import { wrapError } from '../lib/utils'; import { StripGitHubEntity } from '../lib/github/restApi'; import { GitHubResponseType } from '../lib/github/endpointEntities'; import { AppPurpose, AppPurposeTypes } from '../lib/github/appPurposes'; @@ -18,8 +18,8 @@ import { OrganizationFeature, OrganizationSetting, SystemTeam, -} from '../entities/organizationSettings/organizationSetting'; -import { createOrganizationSudoInstance, IOrganizationSudo } from '../features'; +} from './entities/organizationSettings/organizationSetting'; +import { createOrganizationSudoInstance, IOrganizationSudo } from './features'; import { CacheDefault, getMaxAgeSeconds, getPageSize, OperationsCore } from './operations/core'; import { CoreCapability, @@ -59,8 +59,9 @@ import { OrganizationMembershipTwoFactorFilter, throwIfNotCapable, throwIfNotGitHubCapable, + GitHubRepositoryDetails, } from '../interfaces'; -import { CreateError, ErrorHelper } from '../transitional'; +import { CreateError, ErrorHelper } from '../lib/transitional'; import { jsonError } from '../middleware'; import getCompanySpecificDeployment from '../middleware/companySpecificDeployment'; import { ConfigGitHubTemplates } from '../config/github.templates.types'; @@ -201,6 +202,9 @@ export interface IGitHubOrganizationRunners { total_count: number; runners: RunnerData[]; } +type CreateRepositoryEntityById = Partial & Pick; +type CreateRepositoryEntityByName = Partial & Pick; +type CreateRepositoryEntity = CreateRepositoryEntityById | CreateRepositoryEntityByName; export class Organization { private _name: string; @@ -415,7 +419,7 @@ export class Organization { return tokenManager.getRateLimitInformation(purpose, this); } - repository(name: string, optionalEntity?) { + repository(name: string, optionalEntity?: CreateRepositoryEntity) { const entity = Object.assign({}, optionalEntity || {}, { name, }); @@ -446,15 +450,24 @@ export class Organization { cacheOptions.backgroundRefresh = options.backgroundRefresh; } try { - const entity = await operations.github.request( - this.authorize(AppPurpose.Data), - 'GET /repositories/:id', - parameters, - cacheOptions - ); + let entity: any = null; + if ((cacheOptions as any)?.noConditionalRequests === true) { + entity = await operations.github.requestAsPost( + this.authorize(AppPurpose.Data), + 'GET /repositories/:id', + parameters + ); + } else { + entity = await operations.github.request( + this.authorize(AppPurpose.Data), + 'GET /repositories/:id', + parameters, + cacheOptions + ); + } if (entity.owner.id !== this.id) { throw CreateError.NotFound( - `Repository ID ${parameters.id} has a different owner of ${entity.owner.login} instead of ${this.name}. It has been relocated and will be treated as a 404.` + `Repository ID ${id} has a different owner of ${entity.owner.login} instead of ${this.name}. It has been relocated and will be treated as a 404.` ); } return this.repositoryFromEntity(entity); @@ -631,8 +644,8 @@ export class Organization { }; } - getAuthorizationHeader(): PurposefulGetAuthorizationHeader { - return this._getAuthorizationHeader; + getAuthorizationHeader(purpose: AppPurposeTypes): PurposefulGetAuthorizationHeader { + return purpose ? this._getAuthorizationHeader.bind(this, purpose) : this._getAuthorizationHeader; } async getUserDetailsByLogin(login: string, purpose?: AppPurposeTypes): Promise { @@ -1600,7 +1613,7 @@ export class Organization { return this.team(entity.id, entity); } - repositoryFromEntity(entity): Repository { + repositoryFromEntity(entity: CreateRepositoryEntity): Repository { return this.repository(entity.name, entity); } diff --git a/business/organizationCopilot.ts b/business/organizationCopilot.ts index fb837d520..8081ba09f 100644 --- a/business/organizationCopilot.ts +++ b/business/organizationCopilot.ts @@ -5,6 +5,7 @@ import { GetAuthorizationHeader, + ICacheOptions, IOperationsInstance, IPagedCacheOptions, PurposefulGetAuthorizationHeader, @@ -12,8 +13,9 @@ import { } from '../interfaces'; import type { CollectionCopilotSeatsOptions } from '../lib/github/collections'; import { AppPurpose, AppPurposeTypes } from '../lib/github/appPurposes'; -import { CacheDefault, getMaxAgeSeconds, getPageSize } from './operations/core'; +import { CacheDefault, getMaxAgeSeconds, getPageSize, symbolizeApiResponse } from './operations/core'; import { Organization } from './organization'; +import { HttpMethod } from '../lib/github'; export type CopilotSeatData = { assignee: { @@ -27,6 +29,28 @@ export type CopilotSeatData = { last_activity_editor: string; }; +export type CopilotDailyBreakdown = { + language: string; + editor: string; + suggestions_count: number; + acceptances_count: number; + lines_suggested: number; + lines_accepted: number; + active_users: number; +}; + +export type CopilotDailySummary = { + day: string; + total_suggestions_count: number; + total_acceptances_count: number; + total_lines_suggested: number; + total_lines_accepted: number; + total_active_users: number; + breakdown: CopilotDailyBreakdown[]; +}; + +export type OrganizationCopilotSummary = CopilotDailySummary[]; + export class OrganizationCopilot { constructor( private organization: Organization, @@ -57,7 +81,7 @@ export class OrganizationCopilot { if (options && options.backgroundRefresh === false) { caching.backgroundRefresh = false; } - (caching as any).pageLimit = 10; + // (caching as any).pageLimit = 10; const seats = (await github.collections.getOrganizationCopilotSeats( getAuthorizationHeader, parameters, @@ -65,4 +89,38 @@ export class OrganizationCopilot { )) as CopilotSeatData[]; return seats; } + + async getDailyActivitySummary( + options?: ICacheOptions, + appPurpose: AppPurposeTypes = AppPurpose.Data + ): Promise { + options = options || {}; + const operations = throwIfNotGitHubCapable(this.operations); + const getAuthorizationHeader = this.getSpecificAuthorizationHeader.bind( + this, + appPurpose + ) as GetAuthorizationHeader; + const github = operations.github; + const parameters = { + org: this.organization.name, + }; + const caching = { + maxAgeSeconds: getMaxAgeSeconds(operations, CacheDefault.orgMembersStaleSeconds, options), + backgroundRefresh: true, + }; + if (options && options.backgroundRefresh === false) { + caching.backgroundRefresh = false; + } + try { + const result: OrganizationCopilotSummary = await github.request( + getAuthorizationHeader, + 'GET /orgs/:org/copilot/usage', + parameters, + caching + ); + return symbolizeApiResponse(result); + } catch (error) { + throw error; + } + } } diff --git a/business/organizationProperties.ts b/business/organizationProperties.ts index 9f4ac1d57..36080e05b 100644 --- a/business/organizationProperties.ts +++ b/business/organizationProperties.ts @@ -13,7 +13,7 @@ import { throwIfNotGitHubCapable, } from '../interfaces'; import { HttpMethod } from '../lib/github'; -import { CreateError } from '../transitional'; +import { CreateError } from '../lib/transitional'; import { AppPurpose, AppPurposeTypes } from '../lib/github/appPurposes'; import { CacheDefault, @@ -172,9 +172,9 @@ export class OrganizationProperties { ); } const parameters = { - repository_names: organizationRepositoryNames, org: this.organization.name, properties: setPropertiesRecordToArray(propertiesAndValues), + repository_names: organizationRepositoryNames, }; (await operations.github.restApi( this.authorize(purpose || this._defaultPurpose), diff --git a/business/project.ts b/business/project.ts index cc0187ce7..54571be82 100644 --- a/business/project.ts +++ b/business/project.ts @@ -17,7 +17,7 @@ import { IteratorResponse, PaginationPageSizeOptions, } from './iterable'; -import { CreateError, DefaultGraphqlPageSize } from '../transitional'; +import { CreateError, DefaultGraphqlPageSize } from '../lib/transitional'; import { OrganizationProjects } from './projects'; import { OrganizationProjectView } from './projectView'; diff --git a/business/projectView.ts b/business/projectView.ts index c90e6181b..b4386b4ec 100644 --- a/business/projectView.ts +++ b/business/projectView.ts @@ -17,7 +17,7 @@ import { IteratorResponse, PaginationPageSizeOptions, } from './iterable'; -import { DefaultGraphqlPageSize } from '../transitional'; +import { DefaultGraphqlPageSize } from '../lib/transitional'; import { OrganizationProject, ProjectViewEssentials } from './project'; type ProjectViewDetails = { diff --git a/business/projects.ts b/business/projects.ts index 3842c383b..60cc6b8e6 100644 --- a/business/projects.ts +++ b/business/projects.ts @@ -17,7 +17,7 @@ import { IteratorResponse, PaginationPageSizeOptions, } from './iterable'; -import { DefaultGraphqlPageSize } from '../transitional'; +import { DefaultGraphqlPageSize } from '../lib/transitional'; import { OrganizationProject } from './project'; type ProjectResponse = { diff --git a/business/queryCache.ts b/business/queryCache.ts index 9ad133cd4..d1610530d 100644 --- a/business/queryCache.ts +++ b/business/queryCache.ts @@ -16,15 +16,15 @@ import Debug from 'debug'; -import { projectCollaboratorPermissionToGitHubRepositoryPermission } from '../transitional'; -import { OrganizationMemberCacheEntity } from '../entities/organizationMemberCache/organizationMemberCache'; +import { projectCollaboratorPermissionToGitHubRepositoryPermission } from '../lib/transitional'; +import { OrganizationMemberCacheEntity } from './entities/organizationMemberCache/organizationMemberCache'; import { Operations } from './operations'; -import { TeamMemberCacheEntity } from '../entities/teamMemberCache/teamMemberCache'; +import { TeamMemberCacheEntity } from './entities/teamMemberCache/teamMemberCache'; -import { TeamCacheEntity } from '../entities/teamCache/teamCache'; -import { RepositoryTeamCacheEntity } from '../entities/repositoryTeamCache/repositoryTeamCache'; -import { RepositoryCacheEntity } from '../entities/repositoryCache/repositoryCache'; -import { RepositoryCollaboratorCacheEntity } from '../entities/repositoryCollaboratorCache/repositoryCollaboratorCache'; +import { TeamCacheEntity } from './entities/teamCache/teamCache'; +import { RepositoryTeamCacheEntity } from './entities/repositoryTeamCache/repositoryTeamCache'; +import { RepositoryCacheEntity } from './entities/repositoryCache/repositoryCache'; +import { RepositoryCollaboratorCacheEntity } from './entities/repositoryCollaboratorCache/repositoryCollaboratorCache'; import { Repository } from '.'; import { IProviders, @@ -665,9 +665,10 @@ export default class QueryCache { try { const organization = this.operations.getOrganizationById(Number(cacheEntity.organizationId)); const team = organization.team(Number(cacheEntity.teamId)); - const iid = cacheEntity.repositoryId; + const idAsStringOrNumber = cacheEntity.repositoryId; + const repositoryIdAsNumber = Number(idAsStringOrNumber); const repository = organization.repository(cacheEntity.repositoryName, { - id: cacheEntity.repositoryId, // a string version of repositoryId FYI + id: repositoryIdAsNumber, private: cacheEntity.repositoryPrivate, }); return { @@ -893,9 +894,10 @@ export default class QueryCache { cacheEntity: RepositoryCollaboratorCacheEntity ): IQueryCacheRepositoryCollaborator { const organization = this.operations.getOrganizationById(Number(cacheEntity.organizationId)); - const iid = cacheEntity.repositoryId; + const idAsStringOrNumber = cacheEntity.repositoryId; + const repositoryIdAsNumber = Number(idAsStringOrNumber); const repository = organization.repository(cacheEntity.repositoryName, { - id: cacheEntity.repositoryId, + id: repositoryIdAsNumber, private: cacheEntity.repositoryPrivate, }); // a string version of repositoryId FYI return { diff --git a/business/repoSearch.ts b/business/repoSearch.ts index 310f89ec8..945e54691 100644 --- a/business/repoSearch.ts +++ b/business/repoSearch.ts @@ -7,10 +7,10 @@ import querystring from 'querystring'; import { Repository } from './repository'; import { IPersonalizedUserAggregateRepositoryPermission } from './graphManager'; -import { RepositoryMetadataEntity } from '../entities/repositoryMetadata/repositoryMetadata'; -import { IRepositoryMetadataProvider } from '../entities/repositoryMetadata/repositoryMetadataProvider'; +import { RepositoryMetadataEntity } from './entities/repositoryMetadata/repositoryMetadata'; +import { IRepositoryMetadataProvider } from './entities/repositoryMetadata/repositoryMetadataProvider'; import { TeamRepositoryPermission } from './teamRepositoryPermission'; -import { sortRepositoriesByNameCaseInsensitive } from '../utils'; +import { sortRepositoriesByNameCaseInsensitive } from '../lib/utils'; import { GitHubRepositoryPermission, IRepositorySearchOptions, RepositoryLockdownState } from '../interfaces'; const defaultPageSize = 20; // GitHub.com seems to use a value around 33 diff --git a/business/repository.ts b/business/repository.ts index f5dd53427..1b601c459 100644 --- a/business/repository.ts +++ b/business/repository.ts @@ -18,7 +18,7 @@ import { TeamMember, OrganizationMember, } from '.'; -import { RepositoryMetadataEntity } from '../entities/repositoryMetadata/repositoryMetadata'; +import { RepositoryMetadataEntity } from './entities/repositoryMetadata/repositoryMetadata'; import { AppPurpose, AppPurposeTypes } from '../lib/github/appPurposes'; import { PurposefulGetAuthorizationHeader, @@ -33,7 +33,7 @@ import { ITemporaryCommandOutput, NoCacheNoBackground, IGitHubProtectedBranchConfiguration, - IRepositoryBranchAccessProtections, + RepositoryBranchAccessProtections as RepositoryBranchAccessProtections, IListContributorsOptions, IGetCollaboratorsOptions, GitHubCollaboratorAffiliationQuery, @@ -50,16 +50,18 @@ import { IOperationsUrls, GitHubRepositoryPermission, GitHubRepositoryVisibility, + GitHubRepositoryDetails, } from '../interfaces'; import { IListPullsParameters, GitHubPullRequestState } from '../lib/github/collections'; -import { wrapError } from '../utils'; +import { wrapError } from '../lib/utils'; import { RepositoryActions } from './repositoryActions'; import { RepositoryPullRequest } from './repositoryPullRequest'; -import { ErrorHelper } from '../transitional'; +import { CreateError, ErrorHelper } from '../lib/transitional'; import { augmentInertiaPreview, RepositoryProject } from './repositoryProject'; import { RepositoryInvitation } from './repositoryInvitation'; import { RepositoryProperties } from './repositoryProperties'; +import { WithGitHubRestHeaders } from '../lib/github/core'; interface IRepositoryMoments { created?: moment.Moment; @@ -163,6 +165,46 @@ interface IUnarchiveResponse { }; } +export type GitHubBranchProtectionParameters = { + owner: string; + repo: string; + branch: string; + required_status_checks: { + strict: boolean; + contexts: string[]; + checks?: string[]; + } | null; + enforce_admins: boolean | null; + required_pull_request_reviews: { + dismissal_restrictions: { + users: string[]; + teams: string[]; + apps: string[]; + }; + dismiss_stale_reviews: boolean; + require_code_owner_reviews: boolean; + required_approving_review_count: number; + require_last_push_approval: boolean; + bypass_pull_request_allowances: { + users: string[]; + teams: string[]; + apps: string[]; + }; + } | null; + restrictions: { + users: string[]; + teams: string[]; + apps: string[]; + }; + required_linear_history: boolean; + allow_force_pushes: boolean | null; + allow_deletions: boolean; + block_creations: boolean; + required_conversation_resolution: boolean; + lock_branch: boolean; + allow_fork_syncing: boolean; +}; + export type GitHubPagesResponse = { status: string; cname: string; @@ -221,7 +263,7 @@ const sortByLogin = (list) => { }; export class Repository { - private _entity: any; + private _entity: WithGitHubRestHeaders; private _baseUrl: string; private _absoluteBaseUrl: string; private _nativeUrl: string; @@ -240,7 +282,7 @@ export class Repository { private _moments: IRepositoryMoments; - getEntity(): any { + getEntity(): WithGitHubRestHeaders { return this._entity; } @@ -292,13 +334,13 @@ export class Repository { get archived(): boolean { return this._entity ? this._entity.archived : false; } - get created_at(): Date { + get created_at(): string { return this._entity ? this._entity.created_at : null; } - get updated_at(): Date { + get updated_at(): string { return this._entity ? this._entity.updated_at : null; } - get pushed_at(): Date { + get pushed_at(): string { return this._entity ? this._entity.pushed_at : null; } get git_url(): string { @@ -466,12 +508,22 @@ export class Repository { ); } - async getDetails(options?: ICacheOptions): Promise { + async getDetails(options?: ICacheOptions): Promise> { options = options || {}; const operations = throwIfNotGitHubCapable(this._operations); - if (this.id && !this.name) { + const cacheOptions: ICacheOptions = { + maxAgeSeconds: getMaxAgeSeconds(operations, CacheDefault.orgRepoDetailsStaleSeconds, options), + }; + if (options.backgroundRefresh !== undefined) { + cacheOptions.backgroundRefresh = options.backgroundRefresh; + } + if ((options as any).noConditionalRequests === true) { + (cacheOptions as any).noConditionalRequests = true; + } + // always prefer ID over name + if (this.id) { try { - const lookupById = await this.organization.getRepositoryById(this.id); + const lookupById = await this.organization.getRepositoryById(this.id, cacheOptions); this._entity = lookupById.getEntity(); this._name = this._entity.name; } catch (getByIdError) { @@ -489,17 +541,8 @@ export class Repository { if (mediaType) { (parameters as any).mediaType = mediaType; } - const cacheOptions: ICacheOptions = { - maxAgeSeconds: getMaxAgeSeconds(operations, CacheDefault.orgRepoDetailsStaleSeconds, options), - }; - if (options.backgroundRefresh !== undefined) { - cacheOptions.backgroundRefresh = options.backgroundRefresh; - } - if ((options as any).noConditionalRequests === true) { - (cacheOptions as any).noConditionalRequests = true; - } try { - let entity: any = undefined; + let entity: WithGitHubRestHeaders = undefined; if ((cacheOptions as any)?.noConditionalRequests === true) { entity = await operations.github.post(this.authorize(AppPurpose.Data), 'repos.get', parameters); } else { @@ -787,6 +830,27 @@ export class Repository { } } + async updateBranchProtectionRule2( + parameters: GitHubBranchProtectionParameters, + cacheOptions?: ICacheOptions + ): Promise { + cacheOptions = cacheOptions || {}; + const operations = throwIfNotGitHubCapable(this._operations); + const github = operations.github; + + Object.assign(parameters, cacheOptions); + // PUT /repos/{owner}/{repo}/branches/{branch}/protection + const protections = await github.call( + this.authorize(AppPurpose.Data), + 'repos.updateBranchProtection', + parameters + ); + if (protections.length >= 100) { + console.warn('This API does not support pagination currently... there may be more items'); + } + return protections as RepositoryBranchAccessProtections; + } + async listBranchProtectionRules(): Promise { await this.organization.requireUpdatesApp('listBranchProtectionRules'); const query = `query($owner: String!, $repo: String!) { @@ -839,7 +903,7 @@ export class Repository { async getProtectedBranchAccessRestrictions( branchName: string, cacheOptions?: ICacheOptions - ): Promise { + ): Promise { // NOTE: GitHub has a "100-item limit" currently. This is an object response and not // technically paginated. cacheOptions = cacheOptions || {}; @@ -863,7 +927,31 @@ export class Repository { 'repos.getBranchProtection', parameters ); - return protections as IRepositoryBranchAccessProtections; + return protections as RepositoryBranchAccessProtections; + } + + async getAdminProtectedBranchAccessRestrictions( + branchName: string, + cacheOptions?: ICacheOptions + ): Promise { + // NOTE: GitHub has a "100-item limit" currently. This is an object response and not + // technically paginated. + cacheOptions = cacheOptions || {}; + const operations = throwIfNotGitHubCapable(this._operations); + const github = operations.github; + const parameters = { + owner: this.organization.name, + repo: this.name, + branch: branchName, + }; + Object.assign(parameters, cacheOptions); + // GET /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins + const protections = await github.call( + this.authorize(AppPurpose.Data), + 'repos.getAdminBranchProtection', + parameters + ); + return protections as RepositoryBranchAccessProtections; } async setDefaultBranch(defaultBranchName: string): Promise { diff --git a/business/repositoryIssue.ts b/business/repositoryIssue.ts index adb8f4ac7..3e80750e0 100644 --- a/business/repositoryIssue.ts +++ b/business/repositoryIssue.ts @@ -4,7 +4,7 @@ // import { Repository } from './repository'; -import { wrapError } from '../utils'; +import { wrapError } from '../lib/utils'; import { AppPurpose } from '../lib/github/appPurposes'; import { CacheDefault, getMaxAgeSeconds, Operations } from '.'; import { @@ -18,7 +18,7 @@ import { GitHubIssuePatchParameters, GitHubStateReason, } from '../interfaces'; -import { CreateError, ErrorHelper } from '../transitional'; +import { CreateError, ErrorHelper } from '../lib/transitional'; export class RepositoryIssue { private _operations: IOperationsInstance; diff --git a/business/repositoryProject.ts b/business/repositoryProject.ts index 4f30cb193..034eea1d9 100644 --- a/business/repositoryProject.ts +++ b/business/repositoryProject.ts @@ -4,7 +4,7 @@ // import { Repository } from './repository'; -import { wrapError } from '../utils'; +import { wrapError } from '../lib/utils'; import { AppPurpose, AppPurposeTypes } from '../lib/github/appPurposes'; import { CacheDefault, getMaxAgeSeconds } from '.'; import { @@ -16,7 +16,7 @@ import { GetAuthorizationHeader, ICacheOptionsWithPurpose, } from '../interfaces'; -import { ErrorHelper } from '../transitional'; +import { ErrorHelper } from '../lib/transitional'; import { RepositoryProjectColumn } from './repositoryProjectColumn'; import * as common from './common'; diff --git a/business/repositoryProjectColumn.ts b/business/repositoryProjectColumn.ts index 79417335a..d0dd408d2 100644 --- a/business/repositoryProjectColumn.ts +++ b/business/repositoryProjectColumn.ts @@ -16,7 +16,7 @@ import { import { augmentInertiaPreview, RepositoryProject } from './repositoryProject'; import { RepositoryProjectCard } from './repositoryProjectCard'; import * as common from './common'; -import { CreateError } from '../transitional'; +import { CreateError } from '../lib/transitional'; export class RepositoryProjectColumn { private _operations: IOperationsInstance; diff --git a/business/repositoryPullRequest.ts b/business/repositoryPullRequest.ts index c8af3f180..41fad1c01 100644 --- a/business/repositoryPullRequest.ts +++ b/business/repositoryPullRequest.ts @@ -4,7 +4,7 @@ // import { Repository } from './repository'; -import { wrapError } from '../utils'; +import { wrapError } from '../lib/utils'; import { AppPurpose } from '../lib/github/appPurposes'; import { CacheDefault, getMaxAgeSeconds } from '.'; import { @@ -16,7 +16,7 @@ import { ICacheOptions, GetAuthorizationHeader, } from '../interfaces'; -import { ErrorHelper } from '../transitional'; +import { ErrorHelper } from '../lib/transitional'; // Pull requests are issues but not all issues are pull requests. So this is mostly a clone of repositoryIssue.ts // right now, with slightly different endpoints. diff --git a/business/team.ts b/business/team.ts index 1232b043e..33e17002f 100644 --- a/business/team.ts +++ b/business/team.ts @@ -8,11 +8,11 @@ import _ from 'lodash'; import * as common from './common'; -import { wrapError } from '../utils'; +import { wrapError } from '../lib/utils'; import { TeamMember } from './teamMember'; import { TeamRepositoryPermission } from './teamRepositoryPermission'; -import { IApprovalProvider } from '../entities/teamJoinApproval/approvalProvider'; -import { TeamJoinApprovalEntity } from '../entities/teamJoinApproval/teamJoinApproval'; +import { IApprovalProvider } from './entities/teamJoinApproval/approvalProvider'; +import { TeamJoinApprovalEntity } from './entities/teamJoinApproval/teamJoinApproval'; import { AppPurpose } from '../lib/github/appPurposes'; import { CacheDefault, getMaxAgeSeconds, getPageSize, Organization } from '.'; import { @@ -36,8 +36,9 @@ import { IGetTeamRepositoriesOptions, GitHubRepositoryType, IOperationsProviders, + GitHubTeamDetails, } from '../interfaces'; -import { validateGitHubLogin, ErrorHelper } from '../transitional'; +import { validateGitHubLogin, ErrorHelper } from '../lib/transitional'; const teamPrimaryProperties = [ 'id', @@ -217,7 +218,7 @@ export class Team { if (this._name && this._slug) { return; } - return await this.getDetails(); + await this.getDetails(); } async isDeleted(options?: ICacheOptions): Promise { @@ -231,7 +232,7 @@ export class Team { return false; } - async getDetails(options?: ICacheOptions): Promise { + async getDetails(options?: ICacheOptions): Promise { options = options || {}; const operations = throwIfNotGitHubCapable(this._operations); const cacheOptions = { diff --git a/business/teamPermission.ts b/business/teamPermission.ts index f05f49d28..3fd781410 100644 --- a/business/teamPermission.ts +++ b/business/teamPermission.ts @@ -9,24 +9,61 @@ import { Organization } from './organization'; import { TeamMember } from './teamMember'; import { Team } from '.'; import { - IOperationsInstance, + type IOperationsInstance, GitHubTeamPrivacy, TeamJsonFormat, - IGetMembersOptions, + type IGetMembersOptions, GitHubRepositoryPermission, + type IGitHubTeamBasics, } from '../interfaces'; +import { projectCollaboratorPermissionsObjectToGitHubRepositoryPermission } from '../lib/transitional'; + +export interface ITeamRepositoryPermission { + pull: boolean; + triage: boolean; + push: boolean; + maintain: boolean; + admin: boolean; +} + +export function isStandardGitHubTeamPermission(val: string | GitHubRepositoryPermission) { + switch (val) { + case GitHubRepositoryPermission.Pull: + case GitHubRepositoryPermission.Triage: + case GitHubRepositoryPermission.Push: + case GitHubRepositoryPermission.Maintain: + case GitHubRepositoryPermission.Admin: + return true; + default: + return false; + } +} + +type TeamPermissionIncomingEntity = { + name: string; + id: number; + // node_id: we remove this currently + slug: string; + description: string; + privacy: GitHubTeamPrivacy; + permission: GitHubRepositoryPermission | string; + permissions: ITeamRepositoryPermission; + parent: IGitHubTeamBasics; +}; export class TeamPermission { + // private _operations: IOperationsInstance; private _organization: Organization; - private _operations: IOperationsInstance; private _team: Team; - private _permission: GitHubRepositoryPermission; + private _permission: GitHubRepositoryPermission | string; private _privacy: GitHubTeamPrivacy; private _teamMembersIfSet: TeamMember[]; + private _entity: TeamPermissionIncomingEntity; + [util.inspect.custom](depth, options) { return `GitHub Team Permission: team=${this.team?.slug || this.team?.id} permission=${this._permission}`; } @@ -41,7 +78,7 @@ export class TeamPermission { }; } - get permission(): GitHubRepositoryPermission { + get permission(): string | GitHubRepositoryPermission { return this._permission; } @@ -53,8 +90,13 @@ export class TeamPermission { return this._team; } - constructor(organization: Organization, entity: any, operations: IOperationsInstance) { + constructor( + organization: Organization, + entity: TeamPermissionIncomingEntity, + operations: IOperationsInstance + ) { this._organization = organization; + this._entity = entity; this._permission = entity.permission; this._privacy = entity.privacy; @@ -65,7 +107,7 @@ export class TeamPermission { const id = entity.id; this._team = organization.team(id, entity); - this._operations = operations; + // this._operations = operations; } get relativeJoinLink() { @@ -82,6 +124,20 @@ export class TeamPermission { } } + get customRoleName() { + if (!isStandardGitHubTeamPermission(this._entity.permission)) { + return this._entity.permission; + } + } + + get permissions(): ITeamRepositoryPermission { + return this._entity.permissions; + } + + getAsPermission(): GitHubRepositoryPermission { + return projectCollaboratorPermissionsObjectToGitHubRepositoryPermission(this._entity.permissions); + } + async resolveTeamMembers(options?: IGetMembersOptions): Promise { this._teamMembersIfSet = await this.team.getMembers(options); } diff --git a/business/teamRepositoryPermission.ts b/business/teamRepositoryPermission.ts index 1ed650604..972d8e51d 100644 --- a/business/teamRepositoryPermission.ts +++ b/business/teamRepositoryPermission.ts @@ -5,29 +5,48 @@ import { Team } from './team'; import { Repository } from './repository'; -import { IOperationsInstance } from '../interfaces'; + +import type { GitHubRepositoryPermission, IOperationsInstance } from '../interfaces'; +import { isStandardGitHubTeamPermission, type ITeamRepositoryPermission } from './teamPermission'; +import { projectCollaboratorPermissionsObjectToGitHubRepositoryPermission } from '../lib/transitional'; + +// this is used when a team returns the repositories it can work with; +// the GitHub API is pretty inconsistent. The actual entities are a combination of +// repository AND permission here. + +type RepositoryWithTeamPermissionsEntity = { + id: number; + name: string; + full_name: string; + private: boolean; + description: string; + fork: boolean; + permissions: ITeamRepositoryPermission; + role_name: string; +}; export class TeamRepositoryPermission { + // private _operations: IOperationsInstance; + + private _entity: RepositoryWithTeamPermissionsEntity; + private _team: Team; - private _operations: IOperationsInstance; - private _permissions: any; private _repository: Repository; private _id: number; - constructor(team: Team, entity: any, operations: IOperationsInstance) { + constructor(team: Team, entity: RepositoryWithTeamPermissionsEntity, operations: IOperationsInstance) { this._team = team; if (!entity) { throw new Error('TeamRepositoryPermission: requires entity'); } - this._permissions = entity.permissions; + this._entity = entity; this._repository = team.organization.repositoryFromEntity(entity); this._id = this._repository.id; - this._operations = operations; } asJson() { const repo = this._repository.asJson(); - const permissions = this._permissions; + const permissions = this.permissions; const combined = { ...repo, permissions }; return combined; } @@ -44,8 +63,18 @@ export class TeamRepositoryPermission { return this._id; } - get permissions(): any { - return this._permissions; + get customRoleName() { + if (!isStandardGitHubTeamPermission(this._entity.role_name)) { + return this._entity.role_name; + } + } + + get permissions(): ITeamRepositoryPermission { + return this._entity.permissions; + } + + getAsPermission(): GitHubRepositoryPermission { + return projectCollaboratorPermissionsObjectToGitHubRepositoryPermission(this._entity.permissions); } get name(): string { diff --git a/business/user/aggregate.ts b/business/user/aggregate.ts index 30aabe83f..63116e9e5 100644 --- a/business/user/aggregate.ts +++ b/business/user/aggregate.ts @@ -19,7 +19,7 @@ import { OrganizationMembershipRoleQuery, GitHubRepositoryPermission, } from '../../interfaces'; -import { SettleToStateValue, isPermissionBetterThan, ErrorHelper } from '../../transitional'; +import { SettleToStateValue, isPermissionBetterThan, ErrorHelper } from '../../lib/transitional'; import LinkManager from './linkManager'; // PLANNING once consolidated @@ -267,7 +267,11 @@ export class UserContext { const permission = tp.permission; const entity = { ...team.toSimpleJsonObject() }; entity['permission'] = permission; - const teamRepositoryPermission = new TeamRepositoryPermission(team, entity, this._operations); + const teamRepositoryPermission = new TeamRepositoryPermission( + team, + entity as any /* RepositoryWithTeamPermissionsEntity */, + this._operations + ); if (isPermissionBetterThan(bestPermission, permission)) { bestPermission = permission; } diff --git a/business/user/index.ts b/business/user/index.ts index c791cd8c4..e74c64fdd 100644 --- a/business/user/index.ts +++ b/business/user/index.ts @@ -10,7 +10,7 @@ import objectPath from 'object-path'; import Debug from 'debug'; const debug = Debug.debug('context'); -import { addBreadcrumb, isCodespacesAuthenticating } from '../../utils'; +import { addBreadcrumb, isCodespacesAuthenticating } from '../../lib/utils'; import { Operations } from '../operations'; import { UserContext } from './aggregate'; import { diff --git a/webhooks/organizationProcessor.ts b/business/webhooks/organizationProcessor.ts similarity index 88% rename from webhooks/organizationProcessor.ts rename to business/webhooks/organizationProcessor.ts index a84150a9a..d20905548 100644 --- a/webhooks/organizationProcessor.ts +++ b/business/webhooks/organizationProcessor.ts @@ -6,18 +6,21 @@ import crypto from 'crypto'; import secureCompare from 'secure-compare'; -import { Operations } from '../business'; -import { Organization } from '../business'; +import { Organization } from '..'; -import Tasks from './tasks'; -import { sleep } from '../utils'; -import { type IProviders } from '../interfaces'; +import { sleep } from '../../lib/utils'; +import { type IProviders } from '../../interfaces'; + +import defaultWebhookTasks from './tasks'; +import getCompanySpecificDeployment from '../../middleware/companySpecificDeployment'; interface IValidationError extends Error { statusCode?: number; computedHash?: string; } +let companySpecificWebhookTasks: WebhookProcessor[] = null; + export abstract class WebhookProcessor { abstract filter(data: any): boolean; abstract run(providers: IProviders, organization: Organization, data: any): Promise; @@ -50,6 +53,14 @@ export default async function ProcessOrganizationWebhook( if (!providers) { throw new Error('No providers provided'); } + const companySpecific = getCompanySpecificDeployment(); + if ( + companySpecific?.features?.firehose?.getAdditionalWebhookTasks && + companySpecificWebhookTasks === null + ) { + companySpecificWebhookTasks = + await companySpecific.features.firehose.getAdditionalWebhookTasks(providers); + } const organization = options.organization; const event = options.event; if (!organization || !organization.name) { @@ -110,7 +121,8 @@ export default async function ProcessOrganizationWebhook( options.acknowledgeValidEvent(); } let interestingEvents = 0; - const work = Tasks.filter((task) => task.filter(event)); + const availableTasks = [...defaultWebhookTasks, ...(companySpecificWebhookTasks || [])]; + const work = availableTasks.filter((task) => task.filter(event)); if (work.length > 0) { ++interestingEvents; console.log(`[* interesting event: ${event.properties.event} (${work.length} interested tasks)]`); diff --git a/webhooks/tasks/auditLog.ts b/business/webhooks/tasks/auditLog.ts similarity index 97% rename from webhooks/tasks/auditLog.ts rename to business/webhooks/tasks/auditLog.ts index c8c7d37e1..8aff9f335 100644 --- a/webhooks/tasks/auditLog.ts +++ b/business/webhooks/tasks/auditLog.ts @@ -9,10 +9,10 @@ // for organizations, and also to import JSON-based audit export files. import { WebhookProcessor } from '../organizationProcessor'; -import { Organization } from '../../business'; +import { Organization } from '../..'; import { AuditLogRecord } from '../../entities/auditLogRecord/auditLogRecord'; import { MapWebhookEventsToAuditEvents, AuditLogSource } from '../../entities/auditLogRecord'; -import type { IProviders } from '../../interfaces'; +import type { IProviders } from '../../../interfaces'; // prettier-ignore const eventTypes = new Set([ @@ -28,6 +28,7 @@ const knownEventTypesToIgnore = new Set([ 'fork', 'watch', 'star', + 'installation_repositories', ]); async function runAsync(providers: IProviders, organization: Organization, data: any) { diff --git a/webhooks/tasks/automaticTeams.ts b/business/webhooks/tasks/automaticTeams.ts similarity index 97% rename from webhooks/tasks/automaticTeams.ts rename to business/webhooks/tasks/automaticTeams.ts index 4cceedcc5..76df95476 100644 --- a/webhooks/tasks/automaticTeams.ts +++ b/business/webhooks/tasks/automaticTeams.ts @@ -7,13 +7,13 @@ const teamTypes = ['read', 'write', 'admin']; const defaultLargeAdminTeamSize = 250; import { WebhookProcessor } from '../organizationProcessor'; -import { Operations } from '../../business'; -import { Organization } from '../../business'; +import { Operations } from '../..'; +import { Organization } from '../..'; -import RenderHtmlMail from '../../lib/emailRender'; -import { IMailProvider } from '../../lib/mailProvider'; -import getCompanySpecificDeployment from '../../middleware/companySpecificDeployment'; -import { GitHubRepositoryPermission, IProviders } from '../../interfaces'; +import RenderHtmlMail from '../../../lib/emailRender'; +import { IMailProvider } from '../../../lib/mailProvider'; +import getCompanySpecificDeployment from '../../../middleware/companySpecificDeployment'; +import { GitHubRepositoryPermission, IProviders } from '../../../interfaces'; interface IAutomaticTeamsMail { to: string; diff --git a/webhooks/tasks/index.ts b/business/webhooks/tasks/index.ts similarity index 100% rename from webhooks/tasks/index.ts rename to business/webhooks/tasks/index.ts diff --git a/webhooks/tasks/member.ts b/business/webhooks/tasks/member.ts similarity index 95% rename from webhooks/tasks/member.ts rename to business/webhooks/tasks/member.ts index 6373cd8ff..f5c49f79b 100644 --- a/webhooks/tasks/member.ts +++ b/business/webhooks/tasks/member.ts @@ -6,9 +6,9 @@ // COLLABORATOR on a repository import { WebhookProcessor } from '../organizationProcessor'; -import { Operations, Organization } from '../../business'; -import { IProviders, GitHubCollaboratorType } from '../../interfaces'; -import { ErrorHelper } from '../../transitional'; +import { Operations, Organization } from '../..'; +import { IProviders, GitHubCollaboratorType } from '../../../interfaces'; +import { ErrorHelper } from '../../../lib/transitional'; export default class MemberWebhookProcessor implements WebhookProcessor { filter(data: any) { diff --git a/webhooks/tasks/membership.ts b/business/webhooks/tasks/membership.ts similarity index 96% rename from webhooks/tasks/membership.ts rename to business/webhooks/tasks/membership.ts index 730bb3645..6a1dca5a2 100644 --- a/webhooks/tasks/membership.ts +++ b/business/webhooks/tasks/membership.ts @@ -4,8 +4,8 @@ // import { WebhookProcessor } from '../organizationProcessor'; -import { Operations, Organization } from '../../business'; -import { IProviders, GitHubTeamRole } from '../../interfaces'; +import { Operations, Organization } from '../..'; +import { IProviders, GitHubTeamRole } from '../../../interfaces'; export default class MembershipWebhookProcessor implements WebhookProcessor { filter(data: any) { diff --git a/webhooks/tasks/organization.ts b/business/webhooks/tasks/organization.ts similarity index 98% rename from webhooks/tasks/organization.ts rename to business/webhooks/tasks/organization.ts index b2a49039f..03b9e2d4d 100644 --- a/webhooks/tasks/organization.ts +++ b/business/webhooks/tasks/organization.ts @@ -5,13 +5,13 @@ // ORGANIZATION membership and ownership -import { Organization } from '../../business'; +import { Organization } from '../..'; import { OrganizationMembershipRole, type IProviders, NoCacheNoBackground, OrganizationMembershipState, -} from '../../interfaces'; +} from '../../../interfaces'; import { WebhookProcessor } from '../organizationProcessor'; // NOTE: unfortunately role changes from admin->member or member->admin do not fire GitHub hooks diff --git a/webhooks/tasks/repository.ts b/business/webhooks/tasks/repository.ts similarity index 93% rename from webhooks/tasks/repository.ts rename to business/webhooks/tasks/repository.ts index eda134063..76a31f571 100644 --- a/webhooks/tasks/repository.ts +++ b/business/webhooks/tasks/repository.ts @@ -6,9 +6,9 @@ // REPOSITORY created or updated import { WebhookProcessor } from '../organizationProcessor'; -import { Organization } from '../../business'; +import { Organization } from '../..'; import NewRepositoryLockdownSystem from '../../features/newRepositories/newRepositoryLockdown'; -import { getRepositoryMetadataProvider, RepositoryLockdownState, type IProviders } from '../../interfaces'; +import { getRepositoryMetadataProvider, RepositoryLockdownState, type IProviders } from '../../../interfaces'; export default class RepositoryWebhookProcessor implements WebhookProcessor { filter(data: any) { @@ -17,7 +17,7 @@ export default class RepositoryWebhookProcessor implements WebhookProcessor { } async run(providers: IProviders, organization: Organization, data: any): Promise { - const { immutable, operations } = providers; + const { immutable, insights, operations } = providers; const event = data.body; const queryCache = operations.providers.queryCache; let update = false; @@ -26,6 +26,9 @@ export default class RepositoryWebhookProcessor implements WebhookProcessor { let transferSourceLogin: string = null; const action = event.action; const organizationId = event.organization.id as number; + const repositoryId = event?.repository?.id as number; + const repositoryIdAsString = String(repositoryId); + const organizationIdAsString = String(organizationId); if (!operations.isOrganizationManagedById(organizationId)) { console.log( `skipping organization ID ${organizationId} which is not directly managed: ${event.organization.login}` @@ -57,8 +60,6 @@ export default class RepositoryWebhookProcessor implements WebhookProcessor { } by ${event.sender.login}` ); update = true; - const repositoryIdAsString = event.repository.id.toString(); - const organizationIdAsString = event.organization.id.toString(); try { if ( organizationIdAsString === organization.id.toString() && @@ -88,8 +89,6 @@ export default class RepositoryWebhookProcessor implements WebhookProcessor { console.log(`repository event not being intercepted: ${action}`); } if (addOrUpdateRepositoryQueryCache) { - const repositoryIdAsString = event.repository.id.toString(); - const organizationIdAsString = event.organization.id.toString(); try { if ( organizationIdAsString === organization.id.toString() && @@ -132,6 +131,7 @@ export default class RepositoryWebhookProcessor implements WebhookProcessor { const repository = organization.repository(event.repository.name, event.repository); const repositoryMetadataProvider = getRepositoryMetadataProvider(organization.operations); const lockdownSystem = new NewRepositoryLockdownSystem({ + insights, operations, organization, repository, diff --git a/webhooks/tasks/team.ts b/business/webhooks/tasks/team.ts similarity index 93% rename from webhooks/tasks/team.ts rename to business/webhooks/tasks/team.ts index 7e80da851..bdbfd249f 100644 --- a/webhooks/tasks/team.ts +++ b/business/webhooks/tasks/team.ts @@ -5,20 +5,15 @@ // TEAM changes -import moment from 'moment'; - import { WebhookProcessor } from '../organizationProcessor'; -import { Operations } from '../../business'; -import { Organization } from '../../business'; -import { projectCollaboratorPermissionsObjectToGitHubRepositoryPermission } from '../../transitional'; -import type { IProviders } from '../../interfaces'; +import { Operations } from '../..'; +import { Organization } from '../..'; +import { projectCollaboratorPermissionsObjectToGitHubRepositoryPermission } from '../../../lib/transitional'; +import type { IProviders } from '../../../interfaces'; // When teams are added or removed on GitHub, refresh the organization's list of // teams as well as the cross-organization view of the teams. -// TODO: connect to query cache -// TODO: consider whether to slowly kick off Redis cache updates, too - export default class TeamWebhookProcessor implements WebhookProcessor { filter(data: any) { const eventType = data.properties.event; @@ -32,7 +27,7 @@ export default class TeamWebhookProcessor implements WebhookProcessor { let refresh = false; let expectedAfterRefresh = false; const teamId = event.team.id; - const teamIdAsString = event.team.id.toString(); + const teamIdAsString = String(teamId); const organizationIdAsString = event.organization.id.toString(); let addOrUpdate = false; if (event.action === 'created') { @@ -133,7 +128,6 @@ export default class TeamWebhookProcessor implements WebhookProcessor { } if (refresh) { - const startingRefresh = moment(); // organization.getTeams(immediateRefreshOptions, () => { // console.log('refreshing teams list after add or remove operations'); // const now = moment(); diff --git a/pg.sql b/data/pg.sql similarity index 100% rename from pg.sql rename to data/pg.sql diff --git a/docker-compose.yml b/docker-compose.yml index 52c7929cd..a4d057139 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,7 +29,7 @@ services: - portal volumes: - portal_postgres_data:/var/lib/postgresql/data - - ./pg.sql:/docker-entrypoint-initdb.d/pg.sql + - ./data/pg.sql:/docker-entrypoint-initdb.d/pg.sql environment: POSTGRES_DB: portal-repos POSTGRES_USER: portal diff --git a/docs/api.md b/docs/api.md index 44d5869f4..b912d44a9 100644 --- a/docs/api.md +++ b/docs/api.md @@ -147,7 +147,7 @@ This API will retrieve information about a specific user. The first API version Where `login` is a GitHub username, case insensitive. -##### Response +##### Response: by GitHub username If a link is not found for the GitHub user @@ -188,7 +188,7 @@ This API returns an array if there is at least one matching account or accounts. Where `id` is an AAD ID. -##### Response +##### Response: by AAD ID If a link is not registered for this user @@ -233,7 +233,7 @@ Required API scope: `link` > POST /api/people/links -#### Request +#### Request: create a link ```text BODY @@ -249,7 +249,7 @@ BODY > If the account is a Service Account, the `corporate` object should also include a field called `serviceAccountMail` that points to a contact for the service account. -#### Response +#### Response: create a link ```http Status: 201 OK diff --git a/docs/configuration.md b/docs/configuration.md index bab72f661..a2ce8965a 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -125,13 +125,13 @@ The opensource-portal can also be configured to read organization configurations ## PostgreSQL Configuration -To run the opensource-portal with a postgres database, you need to [setup postgres](https://www.postgresql.org/docs/11/runtime.html) and initialize the database by running the `pg.sql`-file in the psql-terminal. +To run the opensource-portal with a postgres database, you need to [setup postgres](https://www.postgresql.org/docs/11/runtime.html) and initialize the database by running the `data/pg.sql`-file in the psql-terminal. It's recommended to [run postgres in a docker container](https://hub.docker.com/_/postgres), there is also an official docker image called `postgres` for building. Once the setup is done, set the `host`, `database`, `user`, `password`, `ssl` (as boolean) and `port` of the postgres in the `config/data.postgres.json`-file. -Additionally set the name of the linking-table (`tableName` parameter), if the tables were created with the `pg.sql`-file, the name for this table is `links`. +Additionally set the name of the linking-table (`tableName` parameter), if the tables were created with the `data/pg.sql`-file, the name for this table is `links`. -There is also a script in the `scripts` folder that can blast the `pg.sql` insertions into a new database. Be +There is also a script in the `scripts` folder that can blast the `data/pg.sql` insertions into a new database. Be sure to configure grants and your user accounts with the concept of least privilege required. ## Cache Configuration diff --git a/interfaces/app.ts b/interfaces/app.ts index 2b3bda593..ba5d2f2d0 100644 --- a/interfaces/app.ts +++ b/interfaces/app.ts @@ -4,12 +4,12 @@ // import { Application, Response, NextFunction } from 'express'; -import { IProviders } from './providers'; -import type { RuntimeConfiguration } from './config'; -import { ReposAppRequest } from './web'; +import type { IProviders } from './providers'; +import type { RuntimeConfiguration, SiteConfiguration } from './config'; +import type { ReposAppRequest } from './web'; -export interface IApplicationProfile { +export type ApplicationProfile = { applicationName: string; customErrorHandlerRender?: ( errorView: unknown, @@ -26,7 +26,7 @@ export interface IApplicationProfile { startup?: (providers: IProviders) => Promise; sessions: boolean; webServer: boolean; -} +}; export interface IReposApplication extends Application { // Standard Express @@ -34,7 +34,7 @@ export interface IReposApplication extends Application { // Local things providers: IProviders; - config: any; + config: SiteConfiguration; isBackgroundJob: boolean; enableAllGitHubApps: boolean; runtimeConfiguration: RuntimeConfiguration; @@ -45,7 +45,7 @@ export interface IReposApplication extends Application { initializeApplication: ( executionEnvironment: ExecutionEnvironment, - config: any, + config: SiteConfiguration, configurationError: Error ) => Promise; diff --git a/interfaces/companySpecific/events/index.ts b/interfaces/companySpecific/events/index.ts new file mode 100644 index 000000000..016caa017 --- /dev/null +++ b/interfaces/companySpecific/events/index.ts @@ -0,0 +1,12 @@ +// +// Copyright (c) Microsoft. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +import type { ICompanySpecificEventsLinking } from './linking'; + +export * from './linking'; + +export interface ICompanySpecificEvents { + linking?: ICompanySpecificEventsLinking; +} diff --git a/interfaces/companySpecific/events/linking.ts b/interfaces/companySpecific/events/linking.ts new file mode 100644 index 000000000..6f6a55f99 --- /dev/null +++ b/interfaces/companySpecific/events/linking.ts @@ -0,0 +1,11 @@ +// +// Copyright (c) Microsoft. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +import type { ICorporateLink, IProviders } from '../..'; + +export interface ICompanySpecificEventsLinking { + onLink?: (providers: IProviders, link: ICorporateLink) => Promise; + onUnlink?: (providers: IProviders, corporateId: string) => Promise; +} diff --git a/interfaces/companySpecific/features/firehose.ts b/interfaces/companySpecific/features/firehose.ts index 90c3213f0..63656249c 100644 --- a/interfaces/companySpecific/features/firehose.ts +++ b/interfaces/companySpecific/features/firehose.ts @@ -4,9 +4,10 @@ // import { IGitHubAppInstallation, IGitHubWebhookEnterprise, IProviders } from '../../../interfaces'; +import type { WebhookProcessor } from '../../../business/webhooks/organizationProcessor'; export interface ICompanySpecificFeatureFirehose { - processWebhook: ( + processWebhook?: ( providers: IProviders, body: any, eventType: string, @@ -14,4 +15,6 @@ export interface ICompanySpecificFeatureFirehose { installation: IGitHubAppInstallation, acknowledgeEvent: () => void ) => Promise; + + getAdditionalWebhookTasks?: (providers: IProviders) => Promise; } diff --git a/interfaces/companySpecific/features/index.ts b/interfaces/companySpecific/features/index.ts index 1e2a4695c..1a3ca4f66 100644 --- a/interfaces/companySpecific/features/index.ts +++ b/interfaces/companySpecific/features/index.ts @@ -3,14 +3,14 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { ICompanySpecificAugmentApiMetadata } from './augmentApiMetadata'; -import { ICompanySpecificFeatureDemo } from './demo'; -import { ICompanySpecificFeatureFirehose } from './firehose'; -import { ICompanySpecificFeatureMailProvider } from './mailProvider'; -import { ICompanySpecificFeatureOrganizationJoinAcl } from './organizationJoinAcl'; -import { ICompanySpecificFeatureOrganizationSudo } from './organizationSudo'; -import { ICompanySpecificFeaturePortalSudo } from './portalSudo'; -import { ICompanySpecificFeatureRepositoryState } from './repositoryActions'; +import type { ICompanySpecificAugmentApiMetadata } from './augmentApiMetadata'; +import type { ICompanySpecificFeatureDemo } from './demo'; +import type { ICompanySpecificFeatureFirehose } from './firehose'; +import type { ICompanySpecificFeatureMailProvider } from './mailProvider'; +import type { ICompanySpecificFeatureOrganizationJoinAcl } from './organizationJoinAcl'; +import type { ICompanySpecificFeatureOrganizationSudo } from './organizationSudo'; +import type { ICompanySpecificFeaturePortalSudo } from './portalSudo'; +import type { ICompanySpecificFeatureRepositoryState } from './repositoryActions'; export * from './organizationSudo'; export * from './portalSudo'; diff --git a/interfaces/companySpecific/features/organizationSudo.ts b/interfaces/companySpecific/features/organizationSudo.ts index c7c25bc29..292df91e6 100644 --- a/interfaces/companySpecific/features/organizationSudo.ts +++ b/interfaces/companySpecific/features/organizationSudo.ts @@ -4,7 +4,7 @@ // import { Organization } from '../../../business'; -import { IOrganizationSudo } from '../../../features'; +import { IOrganizationSudo } from '../../../business/features'; import { IProviders } from '../../../interfaces'; export interface ICompanySpecificFeatureOrganizationSudo { diff --git a/interfaces/companySpecific/features/portalSudo.ts b/interfaces/companySpecific/features/portalSudo.ts index 71f6c25ad..07a704eb7 100644 --- a/interfaces/companySpecific/features/portalSudo.ts +++ b/interfaces/companySpecific/features/portalSudo.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { IPortalSudo } from '../../../features'; +import { IPortalSudo } from '../../../business/features'; import { IProviders } from '../../../interfaces'; export interface ICompanySpecificFeaturePortalSudo { diff --git a/interfaces/companySpecific/index.ts b/interfaces/companySpecific/index.ts index 3bf21513e..fb311f15b 100644 --- a/interfaces/companySpecific/index.ts +++ b/interfaces/companySpecific/index.ts @@ -11,3 +11,4 @@ export * from './administration'; export * from './passport'; export * from './views'; export * from './urls'; +export * from './events'; diff --git a/interfaces/github/operations.ts b/interfaces/github/operations.ts index 3c567e446..4ac9c3ee8 100644 --- a/interfaces/github/operations.ts +++ b/interfaces/github/operations.ts @@ -11,7 +11,7 @@ import { GetAuthorizationHeader, } from '.'; import { IProviders, ICorporateLink, ICachedEmployeeInformation } from '..'; -import { IRepositoryMetadataProvider } from '../../entities/repositoryMetadata/repositoryMetadataProvider'; +import { IRepositoryMetadataProvider } from '../../business/entities/repositoryMetadata/repositoryMetadataProvider'; import { RestLibrary } from '../../lib/github'; import { Account } from '../../business'; @@ -32,13 +32,30 @@ export interface IOperationsProviders { providers: IProviders; } +export type LinkEvent = ICorporateLink & { + linkId: string; + correlationId: string; +}; + +export type UnlinkEvent = { + github: { + id: number; + login: string; + }; + aad: { + preferredName: string; + userPrincipalName: string; + id: string; + }; +}; + export interface IOperationsLinks { getLinks(options?: any): Promise; getLinkByThirdPartyId(thirdPartyId: string): Promise; getLinkByThirdPartyUsername(username: string): Promise; tryGetLink(login: string): Promise; - fireLinkEvent(value): Promise; - fireUnlinkEvent(value): Promise; + fireLinkEvent(value: LinkEvent): Promise; + fireUnlinkEvent(value: UnlinkEvent): Promise; } export interface IOperationsNotifications { diff --git a/interfaces/github/repos.ts b/interfaces/github/repos.ts index 37ceaf7c1..828af3ba5 100644 --- a/interfaces/github/repos.ts +++ b/interfaces/github/repos.ts @@ -4,19 +4,20 @@ // import type { ICacheOptions, IPagedCacheOptions, IAccountBasics, IGitHubTeamBasics } from '.'; +import type { IGitHubWebhookEnterprise } from './apps'; import { IPersonalizedUserAggregateRepositoryPermission, TeamRepositoryPermission, GraphManager, } from '../../business'; -import type { IRepositoryMetadataProvider } from '../../entities/repositoryMetadata/repositoryMetadataProvider'; +import type { IRepositoryMetadataProvider } from '../../business/entities/repositoryMetadata/repositoryMetadataProvider'; import { GitHubPullRequestState, GitHubPullRequestSort, GitHubSortDirection, } from '../../lib/github/collections'; import type { IRequestTeamPermissions } from '../../middleware/github/teamPermissions'; -import { CreateError } from '../../transitional'; +import { CreateError } from '../../lib/transitional'; export enum GitHubRepositoryPermission { Pull = 'pull', @@ -175,7 +176,49 @@ export interface IGitHubBranchDetailed { }; } -export interface IRepositoryBranchAccessProtections { +export type RepositoryBranchAccessProtections = { + required_signatures: { + enabled: boolean; + }; + allow_fork_syncing: { + enabled: boolean; + }; + lock_branch: { + enabled: boolean; + }; + required_conversation_resolution: { + enabled: boolean; + }; + block_creations: { + enabled: boolean; + }; + required_pull_request_reviews: { + dismissal_restrictions: + | { + users: IAccountBasics[]; + teams: IGitHubTeamBasics[]; + apps: IGitHubWebhookEnterprise[]; + } + | Record; + dismiss_stale_reviews: boolean; + require_code_owner_reviews: boolean; + required_approving_review_count: number; + require_last_push_approval: boolean; + bypass_pull_request_allowances: { + users: IAccountBasics[]; + teams: IGitHubTeamBasics[]; + apps: IGitHubWebhookEnterprise[]; + }; + } | null; + required_status_checks: { + strict: boolean; + contexts: string[]; + checks: { + context: string; + app_id: number; + }[]; + } | null; + branch?: string; allow_deletions: { enabled: boolean; }; @@ -195,7 +238,7 @@ export interface IRepositoryBranchAccessProtections { apps: unknown[]; }; url: string; -} +}; export interface ITemporaryCommandOutput { error?: Error; @@ -249,3 +292,105 @@ export function ConvertGitHubCollaboratorPermissionLevelToGitHubRepositoryPermis ); } } + +export enum GitHubAdvancedSecurityFeatureState { + Enabled = 'enabled', + Disabled = 'disabled', +} + +export type GitHubAdvancedSecurityFeatureStatusValue = { + status: GitHubAdvancedSecurityFeatureState; +}; + +export type GitHubSecurityAnalysisFeatures = { + advanced_security: GitHubAdvancedSecurityFeatureStatusValue; + secret_scanning: GitHubAdvancedSecurityFeatureStatusValue; + secret_scanning_push_protection: GitHubAdvancedSecurityFeatureStatusValue; + dependabot_security_updates: GitHubAdvancedSecurityFeatureStatusValue; + secret_scanning_validity_checks: GitHubAdvancedSecurityFeatureStatusValue; +}; + +export enum GitHubRepositoryOwnerType { + Organization = 'Organization', + User = 'User', +} + +export type GitHubRepositoryOwner = { + login: string; + id: number; + node_id: string; + avatar_url: string; + url: string; + type: GitHubRepositoryOwnerType; +}; + +export type GitHubRepositoryLicense = { + key: string; + name: string; + spdx_id: string; + url: string; + node_id: string; +}; + +export type GitHubRepositoryDetails = { + id: number; + node_id: string; + name: string; + full_name: string; + private: boolean; + owner: GitHubRepositoryOwner; + html_url: string; + description: string; + fork: boolean; + url: string; + created_at: string; + updated_at: string; + pushed_at: string; + git_url: string; + ssh_url: string; + clone_url: string; + homepage: string | null; + size: number; + stargazers_count: number; + watchers_count: number; + language: string; + has_issues: boolean; + has_projects: boolean; + has_downloads: boolean; + has_wiki: boolean; + has_pages: boolean; + has_discussions: boolean; + forks_count: number; + archived: boolean; + disabled: boolean; + open_issues_count: number; + license?: GitHubRepositoryLicense; + allow_forking: boolean; + is_template: boolean; + web_commit_signoff_required: boolean; + topics: string[]; + visibility?: GitHubRepositoryVisibility; + forks: number; + open_issues: number; + watchers: number; + default_branch: string; + // permissions: admin / maintain / push / triage / pull + // temp_clone_token: ... + allow_squash_merge: boolean; + allow_merge_commit: boolean; + allow_rebase_merge: boolean; + allow_auto_merge: boolean; + delete_branch_on_merge: boolean; + allow_update_branch: boolean; + use_squash_pr_title_as_default: boolean; + squash_merge_commit_message: string; + squash_merge_commit_title: string; + merge_commit_message: string; + merge_commit_title: string; + template_repository: GitHubRepositoryDetails; + organization?: GitHubRepositoryOwner; + security_and_analysis?: GitHubSecurityAnalysisFeatures; + network_count: number; + subscribers_count: number; + parent?: GitHubRepositoryDetails; +}; diff --git a/interfaces/github/teams.ts b/interfaces/github/teams.ts index 110ddb0f7..e6d8a417a 100644 --- a/interfaces/github/teams.ts +++ b/interfaces/github/teams.ts @@ -22,6 +22,29 @@ export interface IGitHubTeamBasics { slug: string; } +export enum GitHubTeamNotificationSetting { + Enabled = 'notification_enabled', + Disabled = 'notification_disabled', +} + +export type GitHubTeamDetails = IGitHubTeamBasics & { + node_id: string; + description: string; + privacy: GitHubTeamPrivacy; + notification_setting: GitHubTeamNotificationSetting; + url: string; + html_url: string; + members_url: string; + repositories_url: string; + // permission: ... + created_at: string; + updated_at: string; + members_count: number; + repos_count: number; + // organization: ... + parent: IGitHubTeamBasics; +}; + export enum GitHubRepositoryType { Sources = 'sources', } diff --git a/interfaces/index.ts b/interfaces/index.ts index e06868081..4d0713adc 100644 --- a/interfaces/index.ts +++ b/interfaces/index.ts @@ -23,6 +23,7 @@ import type { ICorporationAdministrationSection, IAttachCompanySpecificStrings, ICompanySpecificFeatures, + ICompanySpecificEvents, IAttachCompanySpecificViews, IAttachCompanySpecificUrls, } from './companySpecific'; @@ -34,6 +35,7 @@ import type { IProviders } from './providers'; export interface ICompanySpecificStartupProperties { isCompanySpecific: true; + events?: ICompanySpecificEvents; routes?: IAttachCompanySpecificRoutes; middleware?: IAttachCompanySpecificMiddleware; administrationSection?: ICorporationAdministrationSection; diff --git a/interfaces/middleware.ts b/interfaces/middleware.ts index 098541d7b..8b8b44b2f 100644 --- a/interfaces/middleware.ts +++ b/interfaces/middleware.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { UserSettings } from '../entities/userSettings'; +import { UserSettings } from '../business/entities/userSettings'; import type { ReposAppRequest } from './web'; export type ReposAppRequestWithUserSettings = ReposAppRequest & { diff --git a/interfaces/providers.ts b/interfaces/providers.ts index fbe0ae2e5..d438fbb1e 100644 --- a/interfaces/providers.ts +++ b/interfaces/providers.ts @@ -9,25 +9,25 @@ import redis, { RedisClientType } from 'redis'; import { Pool as PostgresPool } from 'pg'; import { - IApplicationProfile, + ApplicationProfile, ICorporationAdministrationSection, IReposApplication, SiteConfiguration, } from '.'; import { Operations } from '../business'; import QueryCache from '../business/queryCache'; -import { IAuditLogRecordProvider } from '../entities/auditLogRecord/auditLogRecordProvider'; -import { ILocalExtensionKeyProvider } from '../entities/localExtensionKey'; -import { IOrganizationMemberCacheProvider } from '../entities/organizationMemberCache/organizationMemberCacheProvider'; -import { IOrganizationSettingProvider } from '../entities/organizationSettings/organizationSettingProvider'; -import { IRepositoryCacheProvider } from '../entities/repositoryCache/repositoryCacheProvider'; -import { IRepositoryCollaboratorCacheProvider } from '../entities/repositoryCollaboratorCache/repositoryCollaboratorCacheProvider'; -import { IRepositoryTeamCacheProvider } from '../entities/repositoryTeamCache/repositoryTeamCacheProvider'; -import { ITeamCacheProvider } from '../entities/teamCache/teamCacheProvider'; -import { IApprovalProvider } from '../entities/teamJoinApproval/approvalProvider'; -import { ITeamMemberCacheProvider } from '../entities/teamMemberCache/teamMemberCacheProvider'; -import { ITokenProvider } from '../entities/token'; -import { IUserSettingsProvider } from '../entities/userSettings'; +import { IAuditLogRecordProvider } from '../business/entities/auditLogRecord/auditLogRecordProvider'; +import { ILocalExtensionKeyProvider } from '../business/entities/localExtensionKey'; +import { IOrganizationMemberCacheProvider } from '../business/entities/organizationMemberCache/organizationMemberCacheProvider'; +import { IOrganizationSettingProvider } from '../business/entities/organizationSettings/organizationSettingProvider'; +import { IRepositoryCacheProvider } from '../business/entities/repositoryCache/repositoryCacheProvider'; +import { IRepositoryCollaboratorCacheProvider } from '../business/entities/repositoryCollaboratorCache/repositoryCollaboratorCacheProvider'; +import { IRepositoryTeamCacheProvider } from '../business/entities/repositoryTeamCache/repositoryTeamCacheProvider'; +import { ITeamCacheProvider } from '../business/entities/teamCache/teamCacheProvider'; +import { IApprovalProvider } from '../business/entities/teamJoinApproval/approvalProvider'; +import { ITeamMemberCacheProvider } from '../business/entities/teamMemberCache/teamMemberCacheProvider'; +import { ITokenProvider } from '../business/entities/token'; +import { IUserSettingsProvider } from '../business/entities/userSettings'; import { ICacheHelper } from '../lib/caching'; import BlobCache from '../lib/caching/blob'; import { ICampaignHelper } from '../lib/campaigns'; @@ -37,18 +37,18 @@ import { ILinkProvider } from '../lib/linkProviders'; import { IMailAddressProvider } from '../lib/mailAddressProvider'; import { IMailProvider } from '../lib/mailProvider'; import { IQueueProcessor } from '../lib/queues'; -import { ICustomizedNewRepositoryLogic, ICustomizedTeamPermissionsWebhookLogic } from '../transitional'; +import { ICustomizedNewRepositoryLogic, ICustomizedTeamPermissionsWebhookLogic } from '../lib/transitional'; import { IEntityMetadataProvider } from '../lib/entityMetadataProvider'; -import { IRepositoryProvider } from '../entities/repository'; +import { IRepositoryProvider } from '../business/entities/repository'; import { IKeyVaultSecretResolver } from '../lib/keyVaultResolver'; -import { IOrganizationAnnotationMetadataProvider } from '../entities/organizationAnnotation'; +import { IOrganizationAnnotationMetadataProvider } from '../business/entities/organizationAnnotation'; import type { IImmutableStorageProvider } from '../lib/immutable'; type ProviderGenerator = (value: string) => IEntityMetadataProvider; export interface IProviders { app: IReposApplication; - applicationProfile: IApplicationProfile; + applicationProfile: ApplicationProfile; authorizationCodeClient?: AuthorizationCode; corporateAdministrationProfile?: ICorporationAdministrationSection; corporateViews?: any; diff --git a/interfaces/queryCache.ts b/interfaces/queryCache.ts index 658775053..9a8486eca 100644 --- a/interfaces/queryCache.ts +++ b/interfaces/queryCache.ts @@ -10,11 +10,11 @@ import { GitHubRepositoryPermission, } from '.'; import { Team, Repository, Organization } from '../business'; -import { RepositoryCacheEntity } from '../entities/repositoryCache/repositoryCache'; -import { RepositoryCollaboratorCacheEntity } from '../entities/repositoryCollaboratorCache/repositoryCollaboratorCache'; -import { RepositoryTeamCacheEntity } from '../entities/repositoryTeamCache/repositoryTeamCache'; -import { TeamCacheEntity } from '../entities/teamCache/teamCache'; -import { TeamMemberCacheEntity } from '../entities/teamMemberCache/teamMemberCache'; +import { RepositoryCacheEntity } from '../business/entities/repositoryCache/repositoryCache'; +import { RepositoryCollaboratorCacheEntity } from '../business/entities/repositoryCollaboratorCache/repositoryCollaboratorCache'; +import { RepositoryTeamCacheEntity } from '../business/entities/repositoryTeamCache/repositoryTeamCache'; +import { TeamCacheEntity } from '../business/entities/teamCache/teamCache'; +import { TeamMemberCacheEntity } from '../business/entities/teamMemberCache/teamMemberCache'; export enum QueryCacheOperation { New = 'new', diff --git a/job.ts b/job.ts index 268428c6d..24e77ef08 100644 --- a/job.ts +++ b/job.ts @@ -15,7 +15,7 @@ import type { SiteConfiguration, } from './interfaces'; import { commonStartup } from '.'; -import { quitInTenSeconds } from './utils'; +import { quitInTenSeconds } from './lib/utils'; import initialize from './middleware/initialize'; export async function runJob( @@ -154,7 +154,7 @@ function initializeJob( ); } -const job = { +export const job = { runBackgroundJob: async ( script: (providers: IProviders, jobParameters?: IReposJob) => Promise, options?: IReposJobOptions diff --git a/jobs/cleanupInvites.ts b/jobs/cleanupInvites.ts index e912ce399..8d538c7f2 100644 --- a/jobs/cleanupInvites.ts +++ b/jobs/cleanupInvites.ts @@ -10,7 +10,7 @@ import { GitHubOrganizationInvite, IProviders } from '../interfaces'; import job from '../job'; -import { daysInMilliseconds } from '../utils'; +import { daysInMilliseconds } from '../lib/utils'; const defaultMaximumInvitationAgeDays = 4; diff --git a/jobs/cleanupTeamRequests.ts b/jobs/cleanupTeamRequests.ts new file mode 100644 index 000000000..99bbc59db --- /dev/null +++ b/jobs/cleanupTeamRequests.ts @@ -0,0 +1,65 @@ +// +// Copyright (c) Microsoft. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +// Job 18: cleanup team requests + +// Remove any team requests made by people who are no longer linked. + +import { IProviders } from '../interfaces'; +import job from '../job'; +import { TeamApprovalDecision } from '../routes/org/team/approval'; +import { CreateError } from '../lib/transitional'; + +job.runBackgroundJob(cleanup, { + timeoutMinutes: 5, + insightsPrefix: 'JobTeamRequestsCleanup', +}); + +async function cleanup(providers: IProviders) { + const { approvalProvider, insights, linkProvider } = providers; + if (!approvalProvider) { + throw CreateError.InvalidParameters('No approval provider instance available'); + } + + const linkedCorporateIds = await linkProvider.getAllCorporateIds(); + + let approvals = await approvalProvider.queryAllApprovals(); + approvals = approvals.filter((approval) => approval.active === true && approval.corporateId); + + const orphanApprovals = approvals.filter((approval) => !linkedCorporateIds.includes(approval.corporateId)); + + let removedRequests = 0; + let i = 0; + for (const approval of orphanApprovals) { + ++i; + try { + approval.active = false; + approval.decision = TeamApprovalDecision.Deny; + approval.decisionMessage = 'Requestor not linked'; + await approvalProvider.updateTeamApprovalEntity(approval); + insights?.trackEvent({ + name: 'JobTeamRequestsCleanupApprovalUpdate', + properties: { + approvalId: approval.approvalId, + }, + }); + console.log( + `Denied former linked user request ${approval.approvalId} (${i} of ${orphanApprovals.length})` + ); + ++removedRequests; + } catch (error) { + insights?.trackException({ + exception: error, + properties: { + eventName: 'JobTeamRequestsCleanupApprovalUpdateFailed', + approvalId: approval.approvalId, + }, + }); + console.warn(`Error ${error.message} updating approval ${approval.approvalId}`); + } + } + console.log(`Job finishing. Removed ${removedRequests} requests from former linked users.`); + insights?.trackMetric({ name: 'JobFormerRequestsDenied', value: removedRequests }); +} diff --git a/jobs/deletedRepositoriesCache.ts b/jobs/deletedRepositoriesCache.ts index ca3e84496..d68573113 100644 --- a/jobs/deletedRepositoriesCache.ts +++ b/jobs/deletedRepositoriesCache.ts @@ -7,11 +7,11 @@ import job from '../job'; import { Organization } from '../business/organization'; -import { RepositoryCollaboratorCacheEntity } from '../entities/repositoryCollaboratorCache/repositoryCollaboratorCache'; -import { RepositoryTeamCacheEntity } from '../entities/repositoryTeamCache/repositoryTeamCache'; +import { RepositoryCollaboratorCacheEntity } from '../business/entities/repositoryCollaboratorCache/repositoryCollaboratorCache'; +import { RepositoryTeamCacheEntity } from '../business/entities/repositoryTeamCache/repositoryTeamCache'; import { IProviders, IReposJobResult } from '../interfaces'; -import { ErrorHelper } from '../transitional'; -import { sleep } from '../utils'; +import { ErrorHelper } from '../lib/transitional'; +import { sleep } from '../lib/utils'; const killBitHours = 8; diff --git a/jobs/firehose.ts b/jobs/firehose.ts index c9f562b0c..6f4db5af7 100644 --- a/jobs/firehose.ts +++ b/jobs/firehose.ts @@ -8,7 +8,9 @@ import os from 'os'; import { DateTime } from 'luxon'; -import ProcessOrganizationWebhook, { IGitHubWebhookProperties } from '../webhooks/organizationProcessor'; +import ProcessOrganizationWebhook, { + IGitHubWebhookProperties, +} from '../business/webhooks/organizationProcessor'; import { IGitHubAppInstallation, IGitHubWebhookEnterprise, @@ -16,7 +18,7 @@ import { IReposJob, IReposJobResult, } from '../interfaces'; -import { sleep } from '../utils'; +import { sleep } from '../lib/utils'; import { IQueueMessage } from '../lib/queues'; import getCompanySpecificDeployment from '../middleware/companySpecificDeployment'; import job from '../job'; diff --git a/jobs/permissions.ts b/jobs/permissions.ts index 96b5865e3..93031a4fc 100644 --- a/jobs/permissions.ts +++ b/jobs/permissions.ts @@ -11,9 +11,9 @@ import throat from 'throat'; import job from '../job'; import { TeamPermission } from '../business/teamPermission'; import { GitHubRepositoryPermission, IProviders, IReposJobResult } from '../interfaces'; -import AutomaticTeamsWebhookProcessor from '../webhooks/tasks/automaticTeams'; -import { sleep } from '../utils'; -import { ErrorHelper } from '../transitional'; +import AutomaticTeamsWebhookProcessor from '../business/webhooks/tasks/automaticTeams'; +import { sleep } from '../lib/utils'; +import { ErrorHelper } from '../lib/transitional'; import { Organization } from '../business'; // Permissions processing: visit all repos and make sure that any designated read, write, admin @@ -108,7 +108,7 @@ async function reviewOrganizationSystemTeams( } const currentPermissions = new Map(); permissions.forEach((entry) => { - currentPermissions.set(Number(entry.team.id), entry.permission); + currentPermissions.set(Number(entry.team.id), entry.getAsPermission()); }); const teamsToSet = new Set(); specialTeamIds.forEach((specialTeamId) => { diff --git a/jobs/refreshQueryCache.ts b/jobs/refreshQueryCache.ts index e49908789..c4d589fda 100644 --- a/jobs/refreshQueryCache.ts +++ b/jobs/refreshQueryCache.ts @@ -16,7 +16,7 @@ job.runBackgroundJob(refreshQueryCache, { insightsPrefix: 'JobRefreshQueryCache', }); -import { projectCollaboratorPermissionsObjectToGitHubRepositoryPermission } from '../transitional'; +import { projectCollaboratorPermissionsObjectToGitHubRepositoryPermission } from '../lib/transitional'; import { Collaborator, Operations, @@ -27,7 +27,7 @@ import { TeamMember, TeamPermission, } from '../business'; -import { sleep, addArrayToSet } from '../utils'; +import { sleep, addArrayToSet } from '../lib/utils'; import QueryCache from '../business/queryCache'; import { IPagedCacheOptions, @@ -385,7 +385,7 @@ async function cacheRepositoryTeams( const repositoryId = repository.id.toString(); for (const teamPermission of repoTeamPermissions) { const teamId = teamPermission.team.id.toString(); - const permission = teamPermission.permission; + const permission = teamPermission.getAsPermission(); const isPrivate = repository.private as boolean; const repoName = repository.name as string; ops.push( diff --git a/jobs/refreshUsernames.ts b/jobs/refreshUsernames.ts index fc3e3837f..275edc1d8 100644 --- a/jobs/refreshUsernames.ts +++ b/jobs/refreshUsernames.ts @@ -11,9 +11,9 @@ import job from '../job'; import throat from 'throat'; import { shuffle } from 'lodash'; -import { sleep } from '../utils'; +import { sleep } from '../lib/utils'; import { IProviders, IReposJobResult, UnlinkPurpose } from '../interfaces'; -import { ErrorHelper } from '../transitional'; +import { ErrorHelper } from '../lib/transitional'; job.runBackgroundJob(refresh, { insightsPrefix: 'JobRefreshUsernames', diff --git a/jobs/repositories.ts b/jobs/repositories.ts index 6c71dc65e..f8e86427e 100644 --- a/jobs/repositories.ts +++ b/jobs/repositories.ts @@ -14,11 +14,11 @@ import throat from 'throat'; import job from '../job'; import { Organization, sortByRepositoryDate } from '../business'; -import { RepositoryEntity, tryGetRepositoryEntity } from '../entities/repository'; +import { RepositoryEntity, tryGetRepositoryEntity } from '../business/entities/repository'; import { IProviders, IReposJobResult } from '../interfaces'; -import { sleep } from '../utils'; +import { sleep } from '../lib/utils'; -const sleepBetweenReposMs = 125; +const sleepBetweenReposMs = 110; const maxParallel = 6; const shouldUpdateCached = true; @@ -31,7 +31,7 @@ async function refreshRepositories(providers: IProviders): Promise 0; } if (updatedFields.length === 0 && shouldUpdateCached) { replace = true; @@ -317,7 +317,7 @@ function setFields(repositoryEntity: RepositoryEntity, entity: any, isNew: boole const updatedAt = new Date(entity.updated_at); const currentUpdatedAt = repositoryEntity.updatedAt ? new Date(repositoryEntity.updatedAt) : null; if (currentUpdatedAt && updatedAt && currentUpdatedAt.toISOString() !== updatedAt.toISOString()) { - repositoryEntity.pushedAt = updatedAt; + repositoryEntity.updatedAt = updatedAt; changed.push('updated_at'); } else if (!currentUpdatedAt && updatedAt) { repositoryEntity.updatedAt = updatedAt; @@ -345,6 +345,6 @@ function setFields(repositoryEntity: RepositoryEntity, entity: any, isNew: boole } job.run(refreshRepositories, { - timeoutMinutes: 320, + timeoutMinutes: 600, insightsPrefix: 'JobRefreshRepositories', }); diff --git a/lib/caching/blob.ts b/lib/caching/blob.ts index 71c49a90b..7dfeada39 100644 --- a/lib/caching/blob.ts +++ b/lib/caching/blob.ts @@ -14,7 +14,7 @@ import { } from '@azure/storage-blob'; import { ICacheHelper } from '.'; -import { gunzipBuffer, gzipString } from '../../utils'; +import { gunzipBuffer, gzipString } from '../utils'; import Debug from 'debug'; const debug = Debug.debug('cache'); diff --git a/lib/caching/cosmosdb.ts b/lib/caching/cosmosdb.ts index 7007d7326..4406daa51 100644 --- a/lib/caching/cosmosdb.ts +++ b/lib/caching/cosmosdb.ts @@ -6,8 +6,8 @@ import { ICacheHelper } from '.'; import { CosmosClient, Database, Container } from '@azure/cosmos'; import BlobCache, { IBlobCacheOptions } from './blob'; -import { sleep } from '../../utils'; -import { ErrorHelper, getSafeCosmosResourceKey, sha256 } from '../../transitional'; +import { sleep } from '../utils'; +import { ErrorHelper, getSafeCosmosResourceKey, sha256 } from '../transitional'; import Debug from 'debug'; const debug = Debug.debug('cache'); diff --git a/lib/caching/redis.ts b/lib/caching/redis.ts index f758c516a..0b6b8035e 100644 --- a/lib/caching/redis.ts +++ b/lib/caching/redis.ts @@ -11,7 +11,7 @@ const debug = Debug.debug('redis'); const debugCrossOrganization = Debug.debug('redis-cross-org'); import type { ICacheHelper } from '.'; -import { gunzipBuffer, gzipString } from '../../utils'; +import { gunzipBuffer, gzipString } from '../utils'; export interface ISetCompressedOptions { minutesToExpire?: number; diff --git a/lib/campaigns.ts b/lib/campaigns.ts index a65a91d12..5835611cc 100644 --- a/lib/campaigns.ts +++ b/lib/campaigns.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { getSafeCosmosResourceKey } from '../transitional'; +import { getSafeCosmosResourceKey } from './transitional'; import CosmosHelper from './cosmosHelper'; export interface ICampaignUserState { diff --git a/lib/config/painlessConfigAsCode.ts b/lib/config/painlessConfigAsCode.ts index 10e32d226..998ef8c67 100644 --- a/lib/config/painlessConfigAsCode.ts +++ b/lib/config/painlessConfigAsCode.ts @@ -10,7 +10,7 @@ import path from 'path'; import walkBack from 'walk-back'; import { InnerError, IPainlessConfigGet, IProviderOptions } from '.'; import { processEnvironmentProvider } from './environmentConfigurationResolver'; -import { CreateError } from '../../transitional'; +import { CreateError } from '../transitional'; const debug = Debug.debug('config'); diff --git a/lib/cosmosSession/index.ts b/lib/cosmosSession/index.ts index d1eb0a313..a457a8da3 100644 --- a/lib/cosmosSession/index.ts +++ b/lib/cosmosSession/index.ts @@ -7,7 +7,7 @@ import { CosmosClient, Database, Container } from '@azure/cosmos'; import { Store } from 'express-session'; import { IAppSession } from '../../interfaces'; -import { ErrorHelper } from '../../transitional'; +import { ErrorHelper } from '../transitional'; export interface ICosmosSessionProviderOptions { endpoint: string; diff --git a/lib/entityMetadataProvider/entityMetadataProvider.ts b/lib/entityMetadataProvider/entityMetadataProvider.ts index 2a0c11cb1..6693c9ff0 100644 --- a/lib/entityMetadataProvider/entityMetadataProvider.ts +++ b/lib/entityMetadataProvider/entityMetadataProvider.ts @@ -5,7 +5,7 @@ import { type IEntityMetadata, EntityMetadataType } from './entityMetadata'; import type { IEntityMetadataFixedQuery } from './query'; -import { swapMap } from '../../utils'; +import { swapMap } from '../utils'; export enum EntityField { Type = 'entityType', diff --git a/lib/entityMetadataProvider/postgres.ts b/lib/entityMetadataProvider/postgres.ts index 22ab16add..3a274c165 100644 --- a/lib/entityMetadataProvider/postgres.ts +++ b/lib/entityMetadataProvider/postgres.ts @@ -22,7 +22,7 @@ import { MetadataMappingDefinition, MetadataMappingDefinitionBase, } from './declarations'; -import { CreateError } from '../../transitional'; +import { CreateError } from '../transitional'; import { IDictionary } from '../../interfaces'; const MetadataColumnName = 'metadata'; diff --git a/lib/entityMetadataProvider/table.ts b/lib/entityMetadataProvider/table.ts index 4ec002995..5980472ec 100644 --- a/lib/entityMetadataProvider/table.ts +++ b/lib/entityMetadataProvider/table.ts @@ -50,7 +50,7 @@ import { MetadataMappingDefinitionBase, } from './declarations'; import { encryptTableEntity, decryptTableEntity, ITableEncryptionOperationOptions } from './tableEncryption'; -import { CreateError, ErrorHelper } from '../../transitional'; +import { CreateError, ErrorHelper } from '../transitional'; import { IKeyVaultSecretResolver } from '../keyVaultResolver'; export interface ITableEncryptionOptions { diff --git a/lib/github/appPurposes.ts b/lib/github/appPurposes.ts index f91b08bf2..4373de395 100644 --- a/lib/github/appPurposes.ts +++ b/lib/github/appPurposes.ts @@ -4,7 +4,7 @@ // import { ExecutionEnvironment } from '../../interfaces'; -import { CreateError } from '../../transitional'; +import { CreateError } from '../transitional'; import Debug from 'debug'; import { GitHubTokenManager } from './tokenManager'; diff --git a/lib/github/appTokens.ts b/lib/github/appTokens.ts index 6fe19afb2..6e75bf780 100644 --- a/lib/github/appTokens.ts +++ b/lib/github/appTokens.ts @@ -11,7 +11,7 @@ import { AppPurposeTypes, ICustomAppPurpose } from './appPurposes'; import { AuthorizationHeaderValue } from '../../interfaces'; import Debug from 'debug'; -import { CreateError } from '../../transitional'; +import { CreateError } from '../transitional'; const debug = Debug('github:tokens'); interface IInstallationToken { @@ -259,7 +259,9 @@ function tokenValidFilter(timeTokenMustBeValid: Date, token: IInstallationToken) const header = token.headerValue.substr(6); const subset = (header.length > 12 ? header.substr(0, 8) : '') + '*'.repeat(4); console.log( - `token expired: redacted=${subset}, expires=${token.expires}, install_id=${token.installationId}, org=${token.organizationName}` + `token expired: redacted=${subset}, expires=${token.expires.toISOString()}, install_id=${ + token.installationId + }, org=${token.organizationName}` ); return false; } diff --git a/lib/github/collections.ts b/lib/github/collections.ts index d0fb364a9..228ac649c 100644 --- a/lib/github/collections.ts +++ b/lib/github/collections.ts @@ -9,13 +9,13 @@ import Debug from 'debug'; const debug = Debug.debug('restapi'); import cost from './cost'; -import { IRestResponse, flattenData } from './core'; +import { RestResponse, flattenData } from './core'; import { CompositeApiContext, CompositeIntelligentEngine } from './composite'; import { Collaborator } from '../../business/collaborator'; import { Team } from '../../business/team'; import { IPagedCacheOptions, GetAuthorizationHeader, IDictionary } from '../../interfaces'; import { RestLibrary } from '.'; -import { sleep } from '../../utils'; +import { sleep } from '../utils'; import GitHubApplication from '../../business/application'; import { RepositoryPrimaryProperties } from '../../business/primaryProperties'; import { RepositoryInvitation } from '../../business/repositoryInvitation'; @@ -86,15 +86,18 @@ copilotSeatPropertiesToCopy.subPropertiesToReduce = { assignee: mostBasicAccountProperties, }; -const teamPermissionsToCopy = [ - 'id', +const teamPermissionsToCopyForRepository = [ 'name', + 'id', 'slug', 'description', - 'members_count', - 'repos_count', + // 'members_count', + // 'repos_count', 'privacy', - 'permission', + // 'notification_setting', + 'permission', // custom role name at times + 'permissions', // array of booleans for admin, maintain, push, triage, pull + 'parent', // large object for a parent team, if present ]; const teamRepoPermissionsToCopy = [ @@ -105,6 +108,7 @@ const teamRepoPermissionsToCopy = [ 'private', 'fork', 'permissions', + 'role_name', ]; const pullDetailsToCopy = [ @@ -360,7 +364,7 @@ export class RestCollections { return this.generalizedCollectionWithFilter( 'repoTeamPermissions', 'repos.listTeams', - teamPermissionsToCopy, + teamPermissionsToCopyForRepository, token, options, cacheOptions @@ -636,7 +640,7 @@ export class RestCollections { cacheOptions: IPagedCacheOptions, propertiesToKeep: string[], arrayReducePropertyName?: string - ): Promise { + ): Promise { const collectionResults = await this.getFilteredGithubCollection( token, methodName, @@ -645,7 +649,7 @@ export class RestCollections { propertiesToKeep, arrayReducePropertyName ); - const results = collectionResults.data as IRestResponse; + const results = collectionResults.data as RestResponse; const requests = collectionResults.requests; const pages = []; let dirty = false; @@ -687,7 +691,7 @@ export class RestCollections { method, options, cacheOptions: IPagedCacheOptions - ): Promise { + ): Promise { const apiContext = new CompositeApiContext(apiName, method, options); apiContext.maxAgeSeconds = cacheOptions.maxAgeSeconds || 600; apiContext.overrideToken(token); diff --git a/lib/github/composite.ts b/lib/github/composite.ts index aca88d167..21bfa9551 100644 --- a/lib/github/composite.ts +++ b/lib/github/composite.ts @@ -13,14 +13,14 @@ import Debug from 'debug'; const debug = Debug.debug('restapi'); import { - IShouldServeCache, + ShouldServeCache, ApiContext, IntelligentEngine, IApiContextRedisKeys, IApiContextCacheValues, ApiContextType, - IRestMetadata, - IRestResponse, + RestMetadata, + RestResponse, } from './core'; import { GetAuthorizationHeader } from '../../interfaces'; @@ -98,12 +98,12 @@ export class CompositeApiContext extends ApiContext { export class CompositeIntelligentEngine extends IntelligentEngine { withMetadataShouldCacheBeServed( apiContext: ApiContext, - metadata: IRestMetadata - ): boolean | IShouldServeCache { + metadata: RestMetadata + ): boolean | ShouldServeCache { // result can be falsy OR an object; { cache: true, refresh: true } // cache: whether to use the cache, if available // refresh: whether to refresh in the background for a newer value - let shouldServeCache: IShouldServeCache | boolean = false; + let shouldServeCache: ShouldServeCache | boolean = false; const maxAgeSeconds = apiContext.maxAgeSeconds; const updatedIso = metadata ? metadata.updated : null; const refreshingIso = metadata ? metadata.refreshing : null; @@ -173,7 +173,7 @@ export class CompositeIntelligentEngine extends IntelligentEngine { return shouldServeCache; } - withResponseShouldCacheBeServed(apiContext: ApiContext, response: IRestResponse) { + withResponseShouldCacheBeServed(apiContext: ApiContext, response: RestResponse) { if (typeof response === 'function') { throw new Error('The response must not be a function'); } @@ -198,16 +198,16 @@ export class CompositeIntelligentEngine extends IntelligentEngine { return shouldUseCache; } - optionalStripResponse(apiContext: ApiContext, response: IRestResponse): IRestResponse { + optionalStripResponse(apiContext: ApiContext, response: RestResponse): RestResponse { // Composite does not strip any results further before caching return response; } - withResponseUpdateMetadata(apiContext: ApiContext, response: IRestResponse) { + withResponseUpdateMetadata(apiContext: ApiContext, response: RestResponse) { return response; } - reduceMetadataToCacheFromResponse(apiContext: ApiContext, response: IRestResponse) { + reduceMetadataToCacheFromResponse(apiContext: ApiContext, response: RestResponse) { // No reduction for object type metadata. // Store the app version in case it is needed for a future // schema update or cache invalidation @@ -217,7 +217,7 @@ export class CompositeIntelligentEngine extends IntelligentEngine { } } - async callApi(apiContext: CompositeApiContext): Promise { + async callApi(apiContext: CompositeApiContext): Promise { const args = []; const apiMethod = apiContext.apiMethod; if (apiContext.token) { @@ -232,10 +232,10 @@ export class CompositeIntelligentEngine extends IntelligentEngine { } catch (applyError) { throw applyError; } - return unknown as IRestResponse; + return unknown as RestResponse; } - getResponseMetadata(apiContext: CompositeApiContext, response: IRestResponse): IRestMetadata { + getResponseMetadata(apiContext: CompositeApiContext, response: RestResponse): RestMetadata { const headers = response.headers || {}; const calledTime = apiContext.calledTime ? apiContext.calledTime.toISOString() : new Date().toISOString(); headers.updated = calledTime; @@ -251,7 +251,7 @@ export class CompositeIntelligentEngine extends IntelligentEngine { return headers; } - processMetadataBeforeCall(apiContext: CompositeApiContext, metadata: IRestMetadata) { + processMetadataBeforeCall(apiContext: CompositeApiContext, metadata: RestMetadata) { if (metadata && !metadata.av) { // Old version of metadata, no package version, which is required for all composite metadata now metadata = undefined; diff --git a/lib/github/core.ts b/lib/github/core.ts index f00843b44..2dbc8cd43 100644 --- a/lib/github/core.ts +++ b/lib/github/core.ts @@ -9,10 +9,10 @@ import moment from 'moment'; import { RestLibrary } from '.'; import { AuthorizationHeaderValue } from '../../interfaces'; -import { sleep } from '../../utils'; +import { sleep } from '../utils'; import cost from './cost'; -import { ErrorHelper } from '../../transitional'; +import { ErrorHelper } from '../transitional'; import Debug from 'debug'; const debug = Debug.debug('restapi'); @@ -43,7 +43,7 @@ const headerKeysWanted = [ 'x-ratelimit-used', ]; -export interface IInterestingHeaders { +export type GitHubRestInterestingHeaders = { etag?: string; ['last-modified']?: string; ['x-github-request-id']?: string; @@ -51,9 +51,13 @@ export interface IInterestingHeaders { ['x-ratelimit-remaining']?: string; ['x-ratelimit-reset']?: string; ['x-ratelimit-used']?: string; -} +}; + +export type WithGitHubRestHeaders = T & { + headers?: GitHubRestInterestingHeaders; +}; -export interface ISpecializedCollectionHeaders { +export type GitHubRestSpecializedCollectionHeaders = { // really, these are the metadata fields, no headers at all... dirty?: boolean; pages?: string[]; @@ -63,34 +67,34 @@ export interface ISpecializedCollectionHeaders { updated?: string; changed?: string; ['last-modified']?: string; -} +}; -export interface IRestMetadata { +export type RestMetadata = { etag?: string; av?: string; updated?: string; changed?: string; refreshing?: string; - headers?: ISpecializedCollectionHeaders; // IDictionary; + headers?: GitHubRestSpecializedCollectionHeaders; // IDictionary; status?: number; pages?: string[]; -} +}; -export interface IRestResponse { - headers?: ISpecializedCollectionHeaders; +export type RestResponse = { + headers?: GitHubRestSpecializedCollectionHeaders; status?: number; data: unknown; cost?: unknown; notModified?: boolean; -} +}; -export interface IIntelligentCacheResponseArray extends Array, IRestResponse {} +export interface IIntelligentCacheResponseArray extends Array, RestResponse {} -export interface IShouldServeCache { +export type ShouldServeCache = { cache?: boolean; remaining?: string; refresh?: boolean; -} +}; export abstract class ApiContext { private _log: string[]; @@ -138,7 +142,7 @@ export abstract class ApiContext { maxAgeSeconds?: number; backgroundRefresh?: boolean; - metadata?: IRestMetadata; + metadata?: RestMetadata; generatedRefreshId?: string; } @@ -167,23 +171,23 @@ export abstract class IntelligentEngine { } // was in api context: - abstract processMetadataBeforeCall(apiContext: ApiContext, metadata: IRestMetadata): IRestMetadata; - abstract callApi(apiContext: ApiContext, optionalMessage?: string): Promise; - abstract withResponseUpdateMetadata(apiContext: ApiContext, response: IRestResponse): IRestResponse; + abstract processMetadataBeforeCall(apiContext: ApiContext, metadata: RestMetadata): RestMetadata; + abstract callApi(apiContext: ApiContext, optionalMessage?: string): Promise; + abstract withResponseUpdateMetadata(apiContext: ApiContext, response: RestResponse): RestResponse; abstract withResponseShouldCacheBeServed( apiContext: ApiContext, - response: IRestResponse - ): boolean | IShouldServeCache; + response: RestResponse + ): boolean | ShouldServeCache; abstract withMetadataShouldCacheBeServed( apiContext: ApiContext, - metadata: IRestMetadata - ): boolean | IShouldServeCache; - abstract reduceMetadataToCacheFromResponse(apiContext: ApiContext, response: IRestResponse): IRestMetadata; - abstract getResponseMetadata(apiContext: ApiContext, response: IRestResponse): IRestMetadata; - abstract optionalStripResponse(apiContext: ApiContext, response: IRestResponse): IRestResponse; + metadata: RestMetadata + ): boolean | ShouldServeCache; + abstract reduceMetadataToCacheFromResponse(apiContext: ApiContext, response: RestResponse): RestMetadata; + abstract getResponseMetadata(apiContext: ApiContext, response: RestResponse): RestMetadata; + abstract optionalStripResponse(apiContext: ApiContext, response: RestResponse): RestResponse; - protected async cacheResponseAsync(apiContext: ApiContext, response: IRestResponse) { + protected async cacheResponseAsync(apiContext: ApiContext, response: RestResponse) { const backgroundAsyncWork = async () => { try { await this.storeResult(apiContext, response); @@ -200,7 +204,7 @@ export abstract class IntelligentEngine { return this.finalizeResult(apiContext, response); } - protected finalizeResult(apiContext: ApiContext, response: IRestResponse): IRestResponse { + protected finalizeResult(apiContext: ApiContext, response: RestResponse): RestResponse { if (!response || !response.data) { // This was a warning in the past, but to try and improve the underlying library, this should be an error if (response.headers.av) { @@ -221,11 +225,9 @@ export abstract class IntelligentEngine { return response; } - protected async tryGetCachedResult(apiContext: ApiContext): Promise { + protected async tryGetCachedResult(apiContext: ApiContext): Promise { const key = this.redisKeyBodyVersion(apiContext); - const response = (await apiContext.libraryContext.cacheProvider.getObjectCompressed( - key - )) as IRestResponse; + const response = (await apiContext.libraryContext.cacheProvider.getObjectCompressed(key)) as RestResponse; this.recordRedisCost(apiContext, 'get', response); return response; } @@ -233,8 +235,8 @@ export abstract class IntelligentEngine { protected async getCachedResult( apiContext: ApiContext, optionalCacheDecisions?, - notModifiedHeaders?: IInterestingHeaders - ): Promise { + notModifiedHeaders?: GitHubRestInterestingHeaders + ): Promise { const result = await this.tryGetCachedResult(apiContext); if (result && result.data) { // use the context metadata over any headers in the stored response, + any headers from 304 @@ -313,7 +315,7 @@ export abstract class IntelligentEngine { protected async reduceObjectExpirationWindow( apiContext: ApiContext, - response: IRestResponse + response: RestResponse ): Promise { if (!apiContext.etag || (apiContext.etag && apiContext.etag === response.headers.etag)) { return; @@ -348,7 +350,7 @@ export abstract class IntelligentEngine { this.recordRedisCost(apiContext, 'expire', cost); } - protected async storeMetadata(apiContext: ApiContext, response: IRestResponse): Promise { + protected async storeMetadata(apiContext: ApiContext, response: RestResponse): Promise { const reducedMetadata = this.reduceMetadataToCacheFromResponse(apiContext, response); const cost = await apiContext.libraryContext.cacheProvider.setObjectWithExpire( apiContext.redisKey.metadata, @@ -358,7 +360,7 @@ export abstract class IntelligentEngine { this.recordRedisCost(apiContext, 'set', cost); } - protected async storeResult(apiContext: ApiContext, response: IRestResponse): Promise { + protected async storeResult(apiContext: ApiContext, response: RestResponse): Promise { let key = null; try { key = this.redisKeyBodyVersion(apiContext, response.headers.etag); @@ -402,23 +404,23 @@ export abstract class IntelligentEngine { return object; } - public async execute(apiContext: ApiContext): Promise { + public async execute(apiContext: ApiContext): Promise { let metadata = await this.getCachedMetadata(apiContext); metadata = this.processMetadataBeforeCall(apiContext, metadata); - const shouldCacheBeServedImmediately: boolean | IShouldServeCache = this.withMetadataShouldCacheBeServed( + const shouldCacheBeServedImmediately: boolean | ShouldServeCache = this.withMetadataShouldCacheBeServed( apiContext, metadata ); const displayKey = apiContext.redisKey ? apiContext.redisKey.root + ' ' : ''; if ( shouldCacheBeServedImmediately === true || - (shouldCacheBeServedImmediately as IShouldServeCache).cache === true + (shouldCacheBeServedImmediately as ShouldServeCache).cache === true ) { debug('Cache should be served immediately.'); if (metadata) { const innerMessage = - shouldCacheBeServedImmediately && (shouldCacheBeServedImmediately as IShouldServeCache).remaining - ? (shouldCacheBeServedImmediately as IShouldServeCache).remaining + shouldCacheBeServedImmediately && (shouldCacheBeServedImmediately as ShouldServeCache).remaining + ? (shouldCacheBeServedImmediately as ShouldServeCache).remaining : ''; debug(`Cache ${displayKey}data: ${innerMessage}`); } @@ -432,9 +434,9 @@ export abstract class IntelligentEngine { await sleep(delayBeforeRefreshMilliseconds); } debug('Directly calling the function or REST API'); - let response: IRestResponse = undefined; + let response: RestResponse = undefined; try { - response = (await this.callApi(apiContext, `GET: ${displayKey}`)) as IRestResponse; + response = (await this.callApi(apiContext, `GET: ${displayKey}`)) as RestResponse; } catch (error) { if (error && error.status && error.status === 304) { const liveHeaders = error.response?.headers || {}; @@ -455,7 +457,7 @@ export abstract class IntelligentEngine { return response; } - private async processResponse(apiContext: ApiContext, response: IRestResponse): Promise { + private async processResponse(apiContext: ApiContext, response: RestResponse): Promise { this.withResponseUpdateMetadata(apiContext, response); const isCacheOk = this.withResponseShouldCacheBeServed(apiContext, response); if (isCacheOk === true) { @@ -477,7 +479,7 @@ export abstract class IntelligentEngine { } } - private async getCachedMetadata(apiContext: ApiContext): Promise { + private async getCachedMetadata(apiContext: ApiContext): Promise { if (apiContext.metadata || apiContext.etag) { debug('Shortcut: apiContext.metadata or apiContext.etag are set'); return; @@ -486,9 +488,9 @@ export abstract class IntelligentEngine { if (!redisKey) { throw new Error('No Redis key provided in apiContext.redisKey.metadata'); } - const cachedMetadata: IRestMetadata = (await apiContext.libraryContext.cacheProvider.getObject( + const cachedMetadata: RestMetadata = (await apiContext.libraryContext.cacheProvider.getObject( redisKey - )) as IRestMetadata; + )) as RestMetadata; // debug('Cached metadata retrieved'); this.recordRedisCost(apiContext, 'get', cachedMetadata); return cachedMetadata; diff --git a/lib/github/crossOrganization.ts b/lib/github/crossOrganization.ts index 7aa58b534..4024d0d17 100644 --- a/lib/github/crossOrganization.ts +++ b/lib/github/crossOrganization.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { IRestResponse, IIntelligentCacheResponseArray, flattenData } from './core'; +import { RestResponse, IIntelligentCacheResponseArray, flattenData } from './core'; import { CompositeApiContext } from './composite'; import { RestLibrary } from '.'; import { RestCollections } from './collections'; @@ -16,11 +16,11 @@ import { } from '../../interfaces'; import { AppPurpose } from './appPurposes'; -interface IOrganizationsResponse extends IRestResponse { +interface IOrganizationsResponse extends RestResponse { orgs?: any; } -interface ICrossOrganizationDataResponse extends IRestResponse { +interface ICrossOrganizationDataResponse extends RestResponse { // data?: any; } diff --git a/lib/github/index.ts b/lib/github/index.ts index 38fb781b0..f9269ca6a 100644 --- a/lib/github/index.ts +++ b/lib/github/index.ts @@ -16,7 +16,7 @@ import { LinkMethods } from './links'; import { GetAuthorizationHeader, AuthorizationHeaderValue } from '../../interfaces'; import { ICacheHelper } from '../caching'; import { ICustomAppPurpose } from './appPurposes'; -import { CreateError } from '../../transitional'; +import { CreateError } from '../transitional'; export enum CacheMode { ValidateCache = 'ValidateCache', diff --git a/lib/github/restApi.ts b/lib/github/restApi.ts index 7cb46ac0f..0c1e3f2e7 100644 --- a/lib/github/restApi.ts +++ b/lib/github/restApi.ts @@ -14,19 +14,19 @@ const debugShowStandardBehavior = false; const debugOutputUnregisteredEntityApis = true; import { - IShouldServeCache, + ShouldServeCache, IntelligentEngine, ApiContext, IApiContextCacheValues, IApiContextRedisKeys, ApiContextType, - IRestResponse, - IRestMetadata, + RestResponse, + RestMetadata, } from './core'; import { getEntityDefinitions, GitHubResponseType, ResponseBodyType } from './endpointEntities'; import appPackage from '../../package.json'; -import { ErrorHelper } from '../../transitional'; +import { ErrorHelper } from '../transitional'; import type { GetAuthorizationHeader, AuthorizationHeaderValue } from '../../interfaces'; import { @@ -77,7 +77,7 @@ export class IntelligentGitHubEngine extends IntelligentEngine { return method; } - async callApi(apiContext: GitHubApiContext, optionalMessage?: string): Promise { + async callApi(apiContext: GitHubApiContext, optionalMessage?: string): Promise { const token = apiContext.token; // CONSIDER: rename apiContext.token *to* something like apiContext.authorization if ( @@ -181,7 +181,7 @@ export class IntelligentGitHubEngine extends IntelligentEngine { } } - processMetadataBeforeCall(apiContext: ApiContext, metadata: IRestMetadata) { + processMetadataBeforeCall(apiContext: ApiContext, metadata: RestMetadata) { if ( metadata && metadata.av && @@ -203,11 +203,11 @@ export class IntelligentGitHubEngine extends IntelligentEngine { return metadata; } - withResponseUpdateMetadata(apiContext: ApiContext, response: IRestResponse) { + withResponseUpdateMetadata(apiContext: ApiContext, response: RestResponse) { return response; } - optionalStripResponse(apiContext: ApiContext, response: IRestResponse): IRestResponse { + optionalStripResponse(apiContext: ApiContext, response: RestResponse): RestResponse { const clonedResponse = Object.assign({}, response); if (response.headers) { const clonedHeaders = StripGitHubEntity( @@ -295,7 +295,7 @@ export class IntelligentGitHubEngine extends IntelligentEngine { return clonedResponse; } - reduceMetadataToCacheFromResponse(apiContext: ApiContext, response: IRestResponse): any { + reduceMetadataToCacheFromResponse(apiContext: ApiContext, response: RestResponse): any { const headers = response ? response.headers : null; if (headers?.etag) { const reduced: IReducedGitHubMetadata = { @@ -320,8 +320,8 @@ export class IntelligentGitHubEngine extends IntelligentEngine { withResponseShouldCacheBeServed( apiContext: ApiContext, - response: IRestResponse - ): boolean | IShouldServeCache { + response: RestResponse + ): boolean | ShouldServeCache { if (response === undefined) { throw new Error('The response was undefined and unable to process.'); } @@ -358,8 +358,8 @@ export class IntelligentGitHubEngine extends IntelligentEngine { return cacheOk; } - getResponseMetadata(apiContext: ApiContext, response: IRestResponse): IRestMetadata { - const md: IRestMetadata = { + getResponseMetadata(apiContext: ApiContext, response: RestResponse): RestMetadata { + const md: RestMetadata = { headers: response.headers, status: response.status, }; @@ -368,12 +368,12 @@ export class IntelligentGitHubEngine extends IntelligentEngine { withMetadataShouldCacheBeServed( apiContext: ApiContext, - metadata: IRestMetadata - ): boolean | IShouldServeCache { + metadata: RestMetadata + ): boolean | ShouldServeCache { // result can be falsy OR an object; { cache: true, refresh: true } // cache: whether to use the cache, if available // refresh: whether to refresh in the background for a newer value - let shouldServeCache: IShouldServeCache | boolean = false; + let shouldServeCache: ShouldServeCache | boolean = false; const maxAgeSeconds = apiContext.maxAgeSeconds; const updatedIso = metadata ? metadata.updated : null; const refreshingIso = metadata ? metadata.refreshing : null; diff --git a/lib/github/tokenManager.ts b/lib/github/tokenManager.ts index 54f0057f6..413b4940e 100644 --- a/lib/github/tokenManager.ts +++ b/lib/github/tokenManager.ts @@ -18,10 +18,11 @@ import { } from './appPurposes'; import { GitHubAppTokens } from './appTokens'; import { AuthorizationHeaderValue, GetAuthorizationHeader, NoCacheNoBackground } from '../../interfaces'; -import { OrganizationSetting } from '../../entities/organizationSettings/organizationSetting'; -import { readFileToText } from '../../utils'; +import { OrganizationSetting } from '../../business/entities/organizationSettings/organizationSetting'; +import { readFileToText } from '../utils'; import { Operations, OperationsCore, Organization } from '../../business'; -import { CreateError } from '../../transitional'; +import { CreateError } from '../transitional'; +import { shuffle } from 'lodash'; export type GitHubRateLimit = { limit: number; @@ -273,7 +274,7 @@ export class GitHubTokenManager { return value; } - async getInstallationAuthorizationHeader( + getInstallationAuthorizationHeader( appId: number, installationId: number, organizationName: string @@ -318,11 +319,13 @@ export class GitHubTokenManager { } getAnyConfiguredInstallationIdForAnyApp(operations: Operations) { - const orgs = operations.getOrganizations(); + const orgs = shuffle(operations.getOrganizations()); for (const org of orgs) { const settings = org.getDynamicSettings(); if (settings?.installations) { - for (const { installationId, appId } of settings.installations) { + const installs = shuffle(settings.installations); + const configuredInstalls = installs.filter((i) => this._appsById.has(i.appId)); + for (const { installationId, appId } of configuredInstalls) { return { installationId, organizationName: org.name, appId }; } } @@ -358,11 +361,10 @@ export class GitHubTokenManager { } } - getAuthorizationHeaderForAnyApp(): AuthorizationHeaderValue { + getAuthorizationHeaderForAnyApp(): Promise { const anyConfigured = this.getAnyConfiguredInstallationIdForAnyApp(this.operations()); if (anyConfigured) { - return this.getInstallationAuthorizationHeader.bind( - this, + return this.getInstallationAuthorizationHeader( anyConfigured.appId, anyConfigured.installationId, anyConfigured.organizationName diff --git a/lib/graphProvider/microsoftGraphProvider.ts b/lib/graphProvider/microsoftGraphProvider.ts index a95ee8c51..0d5922e91 100644 --- a/lib/graphProvider/microsoftGraphProvider.ts +++ b/lib/graphProvider/microsoftGraphProvider.ts @@ -18,7 +18,7 @@ import { IGraphGroup, GraphUserType, } from '.'; -import { ErrorHelper, CreateError, splitSemiColonCommas } from '../../transitional'; +import { ErrorHelper, CreateError, splitSemiColonCommas } from '../transitional'; import { ICacheHelper } from '../caching'; const axios12BufferDecompressionBugHeaderAddition = true; @@ -65,6 +65,14 @@ export function microsoftGraphUserTypeFromString(type: string): GraphUserType { } } +type GraphCheckMembersRequest = { + ids: string[]; +}; + +type GraphCheckMembersResponse = { + value: string[]; +}; + const graphBaseUrl = 'https://graph.microsoft.com/v1.0/'; const odataNextLink = '@odata.nextLink'; const defaultCachePeriodMinutes = 60 * 36; // 36 hours @@ -121,9 +129,26 @@ export class MicrosoftGraphProvider implements IGraphProvider { } async isUserInGroup(corporateId: string, securityGroupId: string): Promise { - // TODO: refactor for efficient use of Microsoft Graph's checkMemberObjects https://docs.microsoft.com/en-us/graph/api/group-checkmemberobjects?view=graph-rest-1.0&tabs=http - const members = await this.getGroupMembers(securityGroupId); - return members.filter((m) => m.id === corporateId).length > 0; + // Formerly used a very inefficient approach: + // const members = await this.getGroupMembers(securityGroupId); + // return members.filter((m) => m.id === corporateId).length > 0; + return await this.checkMemberObjectsForUserId(corporateId, securityGroupId); + } + + private async checkMemberObjectsForUserId(corporateId: string, securityGroupId: string): Promise { + const requestBody: GraphCheckMembersRequest = { + ids: [securityGroupId], + }; + const url = `${graphBaseUrl}users/${corporateId}/checkMemberObjects`; + const response = await this.request( + url, + requestBody, + null, + true + ); /* no cache */ + const foundGroupIds = response.value; + const found = foundGroupIds.includes(securityGroupId); + return found; } private async getTokenThenEntity(aadId: string, resource: string): Promise { @@ -281,8 +306,8 @@ export class MicrosoftGraphProvider implements IGraphProvider { ], { filterValues: `mail eq '${mail}'`, // encodeURIComponent( selectValues: 'id', - count: true, - consistencyLevel: 'eventual', + // count: true, + // consistencyLevel: 'eventual', })) as any[]; if (!response || response.length === 0) { return null; @@ -416,14 +441,14 @@ export class MicrosoftGraphProvider implements IGraphProvider { const graphOptions: GraphOptions = { selectValues: Array.from(selectValuesSet.values()).join(','), }; - if (options?.getCount) { + if (options?.getCount !== undefined) { graphOptions.count = true; graphOptions.consistencyLevel = 'eventual'; } - if (options?.maximumPages) { + if (options?.maximumPages !== undefined) { graphOptions.maximumPages = options.maximumPages; } - if (options?.throwOnMaximumPages) { + if (options?.throwOnMaximumPages !== undefined) { graphOptions.throwOnMaximumPages = options.throwOnMaximumPages; } const lookupType = options?.membership || MicrosoftGraphGroupMembershipType.Transitive; @@ -606,7 +631,7 @@ export class MicrosoftGraphProvider implements IGraphProvider { const maximumPages = options?.maximumPages; do { const consistencyLevel = options.consistencyLevel; - const body = await this.request(url, options.body, consistencyLevel, skipCache); + const body = await this.request(url, options.body, consistencyLevel, skipCache); if (body.value && pages === 0) { hasArray = body && body.value && Array.isArray(body.value); if (hasArray) { @@ -621,6 +646,11 @@ export class MicrosoftGraphProvider implements IGraphProvider { } else { throw new Error(`Page ${pages} in response is not an array type but had a link: ${url}`); } + if (body && body['@odata.count'] !== undefined) { + const count = body['@odata.count']; + // NOTE: we don't store or cache or return this today + console.log(`Total objects in response: ${count}`); + } ++pages; url = body && body[odataNextLink] ? body[odataNextLink] : null; } while (url && (maximumPages ? pages < maximumPages : true)); @@ -628,7 +658,7 @@ export class MicrosoftGraphProvider implements IGraphProvider { if (options.throwOnMaximumPages) { throw CreateError.InvalidParameters('Maximum pages exceeded for this resource'); } - console.warn(`Maximum pages exceeded for this resource: ${originalUrl}`); + console.warn(`WARN: Maximum pages exceeded for this resource: ${originalUrl}`); } if (this.#_cache) { try { @@ -645,12 +675,12 @@ export class MicrosoftGraphProvider implements IGraphProvider { return value; } - private async request( + private async request( url: string, body?: any, eventualConsistency?: string, skipCache?: boolean - ): Promise { + ): Promise { const token = await this.getToken(); const method = body ? 'post' : 'get'; if (this.#_cache && attemptCacheGet && method === 'get' && !skipCache) { @@ -677,7 +707,7 @@ export class MicrosoftGraphProvider implements IGraphProvider { } if (eventualConsistency) { - // headers.ConsistencyLevel = eventualConsistency; + headers['ConsistencyLevel'] = eventualConsistency; } const response = await axios({ url, diff --git a/lib/linkProviders/table/tableLinkProvider.ts b/lib/linkProviders/table/tableLinkProvider.ts index 6e4d1c6dc..282a034c4 100644 --- a/lib/linkProviders/table/tableLinkProvider.ts +++ b/lib/linkProviders/table/tableLinkProvider.ts @@ -28,7 +28,7 @@ import { CorporateTableLink } from './tableLink'; import { ILinkProvider } from '..'; import tableEntity from '../../tableEntity'; -import { ErrorHelper } from '../../../transitional'; +import { ErrorHelper } from '../../transitional'; import { decryptEntityAsync, encryptEntityAsync, IEncryptionOptions } from '../../encryption'; import { IKeyVaultSecretResolver } from '../../keyVaultResolver'; diff --git a/lib/mailProvider/index.ts b/lib/mailProvider/index.ts index 3d461e36d..6ddac4228 100644 --- a/lib/mailProvider/index.ts +++ b/lib/mailProvider/index.ts @@ -50,6 +50,21 @@ export async function createMailAttachment( }; } +export function createMailAttachmentFromBase64( + base64contents: string, + name: string, + contentType: string, + contentId?: string +): MailAttachment { + const realContentId = contentId || randomUUID(); + return { + name, + contentId: realContentId, + contentType, + base64Value: base64contents, + }; +} + export interface IMailProvider { info: string; sendMail(mail: IMail): Promise; diff --git a/transitional.ts b/lib/transitional.ts similarity index 94% rename from transitional.ts rename to lib/transitional.ts index e23cdb8ed..e0806ba54 100644 --- a/transitional.ts +++ b/lib/transitional.ts @@ -7,9 +7,9 @@ import crypto from 'crypto'; import githubUsernameRegex from 'github-username-regex'; import { AxiosError } from 'axios'; -import appPackage from './package.json'; -import type { ICreateRepositoryApiResult } from './api/createRepo'; -import { Repository } from './business/repository'; +import appPackage from '../package.json'; +import type { ICreateRepositoryApiResult } from '../api/createRepo'; +import { Repository } from '../business/repository'; import { GitHubRepositoryPermission, type ICorporateLink, @@ -20,9 +20,9 @@ import { type ISettledValue, type ReposAppRequest, SettledState, -} from './interfaces'; -import { Organization } from './business'; -import { ILinkProvider } from './lib/linkProviders'; +} from '../interfaces'; +import { ITeamRepositoryPermission, Organization } from '../business'; +import { ILinkProvider } from './linkProviders'; const packageVariableName = 'static-react-package-name'; export function hasStaticReactClientApp() { @@ -57,20 +57,20 @@ export function SettleToStateValue(promise: Promise): Promise { @@ -217,6 +217,11 @@ export class ErrorHelper { return statusNumber && statusNumber === 404; } + public static IsServerError(error: Error): boolean { + const statusNumber = ErrorHelper.GetStatus(error); + return statusNumber && statusNumber >= 500; + } + public static IsNotAuthorized(error: Error): boolean { const statusNumber = ErrorHelper.GetStatus(error); return statusNumber && statusNumber === 403; diff --git a/utils.ts b/lib/utils.ts similarity index 99% rename from utils.ts rename to lib/utils.ts index 5409fc99a..d1935884c 100644 --- a/utils.ts +++ b/lib/utils.ts @@ -9,8 +9,8 @@ import path from 'path'; import { URL } from 'url'; import zlib from 'zlib'; -import { type Repository } from './business/repository'; -import type { ReposAppRequest, IAppSession, IReposError, SiteConfiguration } from './interfaces'; +import { type Repository } from '../business/repository'; +import type { ReposAppRequest, IAppSession, IReposError, SiteConfiguration } from '../interfaces'; import { getProviders } from './transitional'; export function daysInMilliseconds(days: number): number { diff --git a/middleware/alternateApps.ts b/middleware/alternateApps.ts index 9f6ec74ae..76e783e49 100644 --- a/middleware/alternateApps.ts +++ b/middleware/alternateApps.ts @@ -8,13 +8,13 @@ const debug = Debug.debug('startup'); import path from 'path'; -import { IApplicationProfile, IReposApplication } from '../interfaces'; +import type { ApplicationProfile, IReposApplication, SiteConfiguration } from '../interfaces'; export default async function initializeAlternateApps( - config, + config: SiteConfiguration, app: IReposApplication, appName: string -): Promise { +): Promise { const appPath = path.resolve(path.join(__dirname, '..', appName, '/')); debug(`Alternate app requested: name=${appName}, path=${appPath}`); try { diff --git a/middleware/apiAad.ts b/middleware/apiAad.ts index 0a566f909..6968e4e49 100644 --- a/middleware/apiAad.ts +++ b/middleware/apiAad.ts @@ -9,8 +9,8 @@ import jwksClient from 'jwks-rsa'; import { isJsonError, jsonError } from './jsonError'; import { IApiRequest, wrapErrorForImmediateUserError } from './apiReposAuth'; -import { PersonalAccessToken } from '../entities/token/token'; -import { CreateError, getProviders } from '../transitional'; +import { PersonalAccessToken } from '../business/entities/token/token'; +import { CreateError, getProviders } from '../lib/transitional'; import getCompanySpecificDeployment from './companySpecificDeployment'; // CONSIDER: Caching of signing keys diff --git a/middleware/apiReposAuth.ts b/middleware/apiReposAuth.ts index d13f037f5..ff26109de 100644 --- a/middleware/apiReposAuth.ts +++ b/middleware/apiReposAuth.ts @@ -14,8 +14,8 @@ import crypto from 'crypto'; import { NextFunction, Response } from 'express'; import { jsonError } from './jsonError'; -import { getProviders } from '../transitional'; -import { PersonalAccessToken } from '../entities/token/token'; +import { getProviders } from '../lib/transitional'; +import { PersonalAccessToken } from '../business/entities/token/token'; import { ReposAppRequest } from '../interfaces'; export const wrapErrorForImmediateUserError = (err: Error) => { diff --git a/middleware/apiVstsAuth.ts b/middleware/apiVstsAuth.ts index fa1d3cd9f..d34b6f67d 100644 --- a/middleware/apiVstsAuth.ts +++ b/middleware/apiVstsAuth.ts @@ -9,8 +9,8 @@ import { NextFunction, Response } from 'express'; import { jsonError } from './jsonError'; import { IApiRequest } from './apiReposAuth'; -import { PersonalAccessToken } from '../entities/token/token'; -import { getProviders } from '../transitional'; +import { PersonalAccessToken } from '../business/entities/token/token'; +import { getProviders } from '../lib/transitional'; // TODO: consider better caching const localMemoryCacheVstsToAadId = new Map(); diff --git a/middleware/business/administration.ts b/middleware/business/administration.ts index b2ff44558..7b192cd09 100644 --- a/middleware/business/administration.ts +++ b/middleware/business/administration.ts @@ -4,13 +4,12 @@ // import { NextFunction, Response, Router } from 'express'; -const router: Router = Router(); import { ReposAppRequest } from '../../interfaces'; -import { wrapError } from '../../utils'; +import { wrapError } from '../../lib/utils'; -function denyRoute(next) { +function denyRoute(next: NextFunction) { next( wrapError( null, diff --git a/middleware/business/allLinks.ts b/middleware/business/allLinks.ts index b1ab796f2..ece49af9a 100644 --- a/middleware/business/allLinks.ts +++ b/middleware/business/allLinks.ts @@ -6,8 +6,8 @@ import { NextFunction, Response } from 'express'; import { ReposAppRequest } from '../../interfaces'; -import { getProviders } from '../../transitional'; -import { wrapError } from '../../utils'; +import { getProviders } from '../../lib/transitional'; +import { wrapError } from '../../lib/utils'; const cachedLinksRequestKeyName = 'cachedLinks'; diff --git a/middleware/business/authentication.ts b/middleware/business/authentication.ts index 695897d17..b0efa15a7 100644 --- a/middleware/business/authentication.ts +++ b/middleware/business/authentication.ts @@ -3,27 +3,28 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +import { Response, NextFunction } from 'express'; + import { ReposAppRequest, IAppSession } from '../../interfaces'; import Debug from 'debug'; const debug = Debug.debug('user'); -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import { ICorporateIdentity, IGitHubIdentity, IndividualContext, GitHubIdentitySource, } from '../../business/user'; -import { storeOriginalUrlAsReferrer } from '../../utils'; +import { storeOriginalUrlAsReferrer } from '../../lib/utils'; import getCompanySpecificDeployment from '../companySpecificDeployment'; -import { Response, NextFunction } from 'express'; export async function requireAuthenticatedUserOrSignInExcluding( exclusionPaths: string[], req: ReposAppRequest, - res, - next + res: Response, + next: NextFunction ) { const url = req.url; for (let i = 0; i < exclusionPaths.length; i++) { @@ -64,7 +65,7 @@ export async function requireAccessTokenClient(req: ReposAppRequest, res: Respon return next(); } -function signoutThenSignIn(req: ReposAppRequest, res) { +function signoutThenSignIn(req: ReposAppRequest, res: Response) { const { insights } = getProviders(req); req.logout({ keepSessionInfo: false }, (err) => { if (err) { @@ -74,7 +75,7 @@ function signoutThenSignIn(req: ReposAppRequest, res) { }); } -function redirectToSignIn(req, res) { +function redirectToSignIn(req: ReposAppRequest, res: Response) { const config = getProviders(req).config; storeOriginalUrlAsReferrer( req, diff --git a/middleware/business/corporateAdministrators.ts b/middleware/business/corporateAdministrators.ts index 99b985047..07e2f5795 100644 --- a/middleware/business/corporateAdministrators.ts +++ b/middleware/business/corporateAdministrators.ts @@ -9,16 +9,16 @@ import { NextFunction, Response } from 'express'; import { ReposAppRequest } from '../../interfaces'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import { IndividualContext } from '../../business/user'; -import { wrapError } from '../../utils'; +import { wrapError } from '../../lib/utils'; import { jsonError } from '../jsonError'; export interface IReposAppRequestWithSystemAdministration extends ReposAppRequest { isSystemAdministrator: boolean; } -function denyRoute(next, isApi: boolean) { +function denyRoute(next: NextFunction, isApi: boolean) { if (isApi) { return next(jsonError('This API is unavailable for you', 403)); } @@ -48,8 +48,8 @@ export async function AuthorizeOnlyCorporateAdministrators( export async function checkIsCorporateAdministrator( req: IReposAppRequestWithSystemAdministration, - res, - next + res: Response, + next: NextFunction ) { await getIsCorporateAdministrator(req); return next(); diff --git a/middleware/business/corporateAlias.ts b/middleware/business/corporateAlias.ts index 7221975ff..78b451f82 100644 --- a/middleware/business/corporateAlias.ts +++ b/middleware/business/corporateAlias.ts @@ -5,7 +5,7 @@ import { jsonError } from '..'; import { IProviders, ReposAppRequest } from '../../interfaces'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import { IndividualContext } from '../../business/user'; const cachedCorporateAliasRequestKey = '__corporateAlias'; diff --git a/middleware/business/corporateHierarchy.ts b/middleware/business/corporateHierarchy.ts index 77b0e40fc..ed38c588d 100644 --- a/middleware/business/corporateHierarchy.ts +++ b/middleware/business/corporateHierarchy.ts @@ -6,7 +6,7 @@ import { jsonError } from '..'; import { IProviders, ReposAppRequest } from '../../interfaces'; import { IGraphEntry } from '../../lib/graphProvider'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import { IndividualContext } from '../../business/user'; const cachedCorporateHierarchyRequestKey = '__corporateTree'; diff --git a/middleware/business/corporateMail.ts b/middleware/business/corporateMail.ts index 2c93d198e..72b294801 100644 --- a/middleware/business/corporateMail.ts +++ b/middleware/business/corporateMail.ts @@ -5,7 +5,7 @@ import { jsonError } from '..'; import { IProviders, ReposAppRequest } from '../../interfaces'; -import { ErrorHelper, getProviders } from '../../transitional'; +import { ErrorHelper, getProviders } from '../../lib/transitional'; import { IndividualContext } from '../../business/user'; const cachedCorporateMailRequestKey = '__corporateMail'; diff --git a/middleware/links/index.ts b/middleware/business/links.ts similarity index 97% rename from middleware/links/index.ts rename to middleware/business/links.ts index 61993b94d..2ff7e2a68 100644 --- a/middleware/links/index.ts +++ b/middleware/business/links.ts @@ -6,8 +6,8 @@ // Within the context, tries to resolve a link if it _can_. It does not force that a user is linked! import { IndividualContext } from '../../business/user'; -import { getProviders } from '../../transitional'; -import { wrapError } from '../../utils'; +import { getProviders } from '../../lib/transitional'; +import { wrapError } from '../../lib/utils'; import { ReposAppRequest, IReposError } from '../../interfaces'; import { NextFunction, Response } from 'express'; diff --git a/middleware/business/organization.ts b/middleware/business/organization.ts index 5f0889ad7..b5872dc00 100644 --- a/middleware/business/organization.ts +++ b/middleware/business/organization.ts @@ -7,7 +7,7 @@ import { NextFunction, Response } from 'express'; import { ReposAppRequest } from '../../interfaces/web'; import { jsonError } from '../jsonError'; -import { CreateError, ErrorHelper, getProviders } from '../../transitional'; +import { CreateError, ErrorHelper, getProviders } from '../../lib/transitional'; import { setOrganizationProfileForRequest } from '../github/ensureOrganizationProfile'; export enum OrganizationManagementType { diff --git a/middleware/business/repository.ts b/middleware/business/repository.ts index 387f298f8..d93618313 100644 --- a/middleware/business/repository.ts +++ b/middleware/business/repository.ts @@ -7,7 +7,7 @@ import { NextFunction, Response } from 'express'; import { Repository } from '../../business/repository'; import type { ReposAppRequest } from '../../interfaces/web'; -import { CreateError } from '../../transitional'; +import { CreateError } from '../../lib/transitional'; export type RequestWithRepo = ReposAppRequest & { repository: Repository; diff --git a/middleware/business/setContext.ts b/middleware/business/setContext.ts index 8108cd1a4..37d8a34e2 100644 --- a/middleware/business/setContext.ts +++ b/middleware/business/setContext.ts @@ -13,7 +13,7 @@ import { WebApiContext, } from '../../business/user'; import { ReposAppRequest } from '../../interfaces'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; export function webContextMiddleware(req: ReposAppRequest, res: Response, next: NextFunction) { const { operations, insights } = getProviders(req); diff --git a/middleware/business/userSettings.ts b/middleware/business/userSettings.ts index f8f2593f9..8ab028405 100644 --- a/middleware/business/userSettings.ts +++ b/middleware/business/userSettings.ts @@ -7,8 +7,8 @@ import type { NextFunction, Response } from 'express'; import type { ReposAppRequestWithUserSettings } from '../../interfaces/middleware'; -import { UserSettings } from '../../entities/userSettings'; -import { ErrorHelper, getProviders } from '../../transitional'; +import { UserSettings } from '../../business/entities/userSettings'; +import { ErrorHelper, getProviders } from '../../lib/transitional'; import { IndividualContext } from '../../business/user'; export async function getUserSettings( diff --git a/middleware/campaign.ts b/middleware/campaign.ts index cacab0244..2d8fd77da 100644 --- a/middleware/campaign.ts +++ b/middleware/campaign.ts @@ -5,7 +5,7 @@ import { NextFunction, Response } from 'express'; -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; interface ICampaignData { uri?: any; diff --git a/middleware/corporateViews.ts b/middleware/corporateViews.ts index 4f16ef7f0..24b53f8bb 100644 --- a/middleware/corporateViews.ts +++ b/middleware/corporateViews.ts @@ -7,7 +7,7 @@ import { constants as fsConstants, promises as fs } from 'fs'; import path from 'path'; import { IProviders } from '../interfaces'; -import { stripDistFolderName } from '../transitional'; +import { stripDistFolderName } from '../lib/transitional'; // providers.corporateViews: // --- diff --git a/middleware/correlationId.ts b/middleware/correlationId.ts index 4ceaf7a50..9f491d1a5 100644 --- a/middleware/correlationId.ts +++ b/middleware/correlationId.ts @@ -3,11 +3,15 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { NextFunction, Response } from 'express'; +import { NextFunction, Request, Response } from 'express'; import { randomUUID } from 'crypto'; +export type WithCorrelationId = T & { + correlationId?: string; +}; + // Generate a correlation ID -export default function (req, res: Response, next: NextFunction) { +export default function (req: WithCorrelationId, res: Response, next: NextFunction) { req.correlationId = randomUUID(); return next(); } diff --git a/middleware/errorHandler.ts b/middleware/errorHandler.ts index 0fc57a33d..dcfd64194 100644 --- a/middleware/errorHandler.ts +++ b/middleware/errorHandler.ts @@ -6,8 +6,8 @@ import querystring from 'querystring'; import { AxiosError } from 'axios'; -import { wrapError } from '../utils'; -import { getProviders } from '../transitional'; +import { wrapError } from '../lib/utils'; +import { getProviders } from '../lib/transitional'; import { isJsonError } from '.'; import { NextFunction, Response } from 'express'; import { ReposAppRequest } from '../interfaces'; diff --git a/middleware/error-routes.ts b/middleware/errorRoutes.ts similarity index 77% rename from middleware/error-routes.ts rename to middleware/errorRoutes.ts index a4bb9134f..f0b92c709 100644 --- a/middleware/error-routes.ts +++ b/middleware/errorRoutes.ts @@ -3,10 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { NextFunction, Response } from 'express'; +import { NextFunction, Request, Response } from 'express'; import { IReposApplication, IReposError } from '../interfaces'; -import RouteErrorHandler from './errorHandler'; +import routeErrorHandler from './errorHandler'; export default async function configureErrorRoutes(app: IReposApplication, initializationError: Error) { if (!app) { @@ -19,7 +19,7 @@ export default async function configureErrorRoutes(app: IReposApplication, initi // for any request. Should evaluate whether to hide for // production scenarios or if there is a risk of the // error message leaking sensitive data. - app.use((req, res: Response, next: NextFunction) => { + app.use((req: Request, res: Response, next: NextFunction) => { const error: IReposError = new Error('Application initialization error', { cause: initializationError, }); @@ -28,12 +28,12 @@ export default async function configureErrorRoutes(app: IReposApplication, initi }); } - app.use(function (req, res: Response, next: NextFunction) { + app.use(function (req: Request, res: Response, next: NextFunction) { const err: IReposError = new Error('Not Found'); err.status = 404; err.skipLog = true; - next(err); + return next(err); }); - app.use(RouteErrorHandler); + app.use(routeErrorHandler); } diff --git a/middleware/github/blockEnterpriseManagedUsers.ts b/middleware/github/blockEnterpriseManagedUsers.ts index 7b2795677..b9d13c50f 100644 --- a/middleware/github/blockEnterpriseManagedUsers.ts +++ b/middleware/github/blockEnterpriseManagedUsers.ts @@ -6,7 +6,7 @@ import { NextFunction, Response } from 'express'; import { ReposAppRequest, IReposError } from '../../interfaces'; -import { isEnterpriseManagedUserLogin } from '../../utils'; +import { isEnterpriseManagedUserLogin } from '../../lib/utils'; export function blockEnterpriseManagedUsersAuthentication( req: ReposAppRequest, diff --git a/middleware/github/ensureOrganizationProfile.ts b/middleware/github/ensureOrganizationProfile.ts index 974f2e206..7dbec0828 100644 --- a/middleware/github/ensureOrganizationProfile.ts +++ b/middleware/github/ensureOrganizationProfile.ts @@ -8,7 +8,7 @@ import memoryCache from 'memory-cache'; import { NextFunction, Response } from 'express'; import type { IReposAppRequestWithOrganizationManagementType } from '../business/organization'; -import { CreateError, getProviders } from '../../transitional'; +import { CreateError, getProviders } from '../../lib/transitional'; import { getOrganizationDetailsSanitized, type GitHubOrganizationResponseSanitized, diff --git a/middleware/github/orgPermissions.ts b/middleware/github/orgPermissions.ts index 9e6942f04..d3a4a63a0 100644 --- a/middleware/github/orgPermissions.ts +++ b/middleware/github/orgPermissions.ts @@ -6,7 +6,7 @@ import { NextFunction, Response } from 'express'; import { OrganizationMembershipState, ReposAppRequest } from '../../interfaces'; -import { wrapError } from '../../utils'; +import { wrapError } from '../../lib/utils'; const orgPermissionsCacheKeyName = 'orgPermissions'; const orgOwnersCacheKeyName = 'orgOwners'; diff --git a/middleware/github/repoPermissions.ts b/middleware/github/repoPermissions.ts index ec3a6071f..d6c06a63a 100644 --- a/middleware/github/repoPermissions.ts +++ b/middleware/github/repoPermissions.ts @@ -5,7 +5,7 @@ import { NextFunction, Response } from 'express'; -import { ErrorHelper, getProviders } from '../../transitional'; +import { ErrorHelper, getProviders } from '../../lib/transitional'; import { Repository } from '../../business/repository'; import { GitHubIdentitySource, IIndividualContextOptions, IndividualContext } from '../../business/user'; import getCompanySpecificDeployment from '../companySpecificDeployment'; diff --git a/middleware/github/requireActiveSession.ts b/middleware/github/requireActiveSession.ts index ac099e1ba..a0b46b553 100644 --- a/middleware/github/requireActiveSession.ts +++ b/middleware/github/requireActiveSession.ts @@ -5,8 +5,8 @@ import { NextFunction, Response } from 'express'; import { ReposAppRequest } from '../../interfaces'; -import { getProviders } from '../../transitional'; -import { isCodespacesAuthenticating, storeOriginalUrlAsReferrer } from '../../utils'; +import { getProviders } from '../../lib/transitional'; +import { isCodespacesAuthenticating, storeOriginalUrlAsReferrer } from '../../lib/utils'; export default function RequireActiveGitHubSession(req: ReposAppRequest, res: Response, next: NextFunction) { const { config } = getProviders(req); diff --git a/middleware/github/teamPermissions.ts b/middleware/github/teamPermissions.ts index 92ae3c334..0061260e5 100644 --- a/middleware/github/teamPermissions.ts +++ b/middleware/github/teamPermissions.ts @@ -13,7 +13,7 @@ import { OrganizationMembershipState, ReposAppRequest, } from '../../interfaces'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import { IndividualContext } from '../../business/user'; import getCompanySpecificDeployment from '../companySpecificDeployment'; diff --git a/middleware/healthCheck.ts b/middleware/healthCheck.ts index 693121212..858057919 100644 --- a/middleware/healthCheck.ts +++ b/middleware/healthCheck.ts @@ -13,7 +13,7 @@ import type { ConfiguredProbeBase, } from '../config/webHealthProbes.types'; import { IReposApplication, ReposAppRequest, SiteConfiguration } from '../interfaces'; -import { CreateError } from '../transitional'; +import { CreateError } from '../lib/transitional'; const dbg = Debug.debug('health'); diff --git a/middleware/index.ts b/middleware/index.ts index f784b5f4b..32e2605c8 100644 --- a/middleware/index.ts +++ b/middleware/index.ts @@ -6,21 +6,23 @@ import bodyParser from 'body-parser'; import compression from 'compression'; import path from 'path'; +import { Express } from 'express'; +import passport from 'passport'; import Debug from 'debug'; const debug = Debug.debug('startup'); export * from './react'; -export * from './links'; +export * from './business/links'; export * from './business'; export * from './jsonError'; -import { hasStaticReactClientApp, stripDistFolderName } from '../transitional'; +import { hasStaticReactClientApp, stripDistFolderName } from '../lib/transitional'; import { StaticClientApp } from './staticClientApp'; import { StaticReactClientApp } from './staticClientApp2'; import { StaticSiteFavIcon, StaticSiteAssets } from './staticSiteAssets'; import connectSession from './session'; -import passportConfig from './passport-config'; +import passportConfig from './passportConfig'; import onboard from './onboarding'; import viewServices from '../lib/pugViewServices'; @@ -35,12 +37,13 @@ import routePassport from './passport-routes'; import routeApi from '../api'; -import { IProviders, IReposApplication, SiteConfiguration } from '../interfaces'; +import type { IProviders, IReposApplication, SiteConfiguration } from '../interfaces'; import { codespacesDevAssistant } from './codespaces'; +import { ExpressWithStatic } from './types'; export default async function initMiddleware( app: IReposApplication, - express, + express: Express, providers: IProviders, config: SiteConfiguration, dirname: string, @@ -78,14 +81,15 @@ export default async function initMiddleware( if (applicationProfile.serveStaticAssets) { StaticSiteAssets(app, express); } + const expressWithStatic = express as ExpressWithStatic; if (hasStaticReactClientApp()) { - StaticReactClientApp(app, express, config); + StaticReactClientApp(app, expressWithStatic, config); } if (applicationProfile.serveClientAssets) { - StaticClientApp(app, express); + StaticClientApp(app, expressWithStatic); } providers.campaign = campaign(app); - let passport; + let passport: passport.PassportStatic; if (!initializationError) { if (config.containers && config.containers.deployment) { app.enable('trust proxy'); diff --git a/middleware/initialize.ts b/middleware/initialize.ts index d5d79ffb6..4422f6271 100644 --- a/middleware/initialize.ts +++ b/middleware/initialize.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { NextFunction, Response } from 'express'; +import { Express, NextFunction, Response } from 'express'; import path from 'path'; import CosmosSessionStore from '../lib/cosmosSession'; @@ -15,11 +15,11 @@ import { createAndInitializeEntityMetadataProviderInstance, IEntityMetadataProvidersOptions, } from '../lib/entityMetadataProvider'; -import { createAndInitializeRepositoryMetadataProviderInstance } from '../entities/repositoryMetadata'; -import createAndInitializeOrganizationAnnotationProviderInstance from '../entities/organizationAnnotation'; +import { createAndInitializeRepositoryMetadataProviderInstance } from '../business/entities/repositoryMetadata'; +import createAndInitializeOrganizationAnnotationProviderInstance from '../business/entities/organizationAnnotation'; import { createMailAddressProviderInstance, IMailAddressProvider } from '../lib/mailAddressProvider'; -import ErrorRoutes from './error-routes'; +import ErrorRoutes from './errorRoutes'; import { createClient, RedisClientType } from 'redis'; import { Pool as PostgresPool } from 'pg'; @@ -38,9 +38,9 @@ import expressRoutes from '../routes/'; import alternateRoutes from './alternateApps'; import RedisHelper from '../lib/caching/redis'; -import { createTokenProvider } from '../entities/token'; -import { createAndInitializeApprovalProviderInstance } from '../entities/teamJoinApproval'; -import { CreateLocalExtensionKeyProvider } from '../entities/localExtensionKey'; +import { createTokenProvider } from '../business/entities/token'; +import { createAndInitializeApprovalProviderInstance } from '../business/entities/teamJoinApproval'; +import { CreateLocalExtensionKeyProvider } from '../business/entities/localExtensionKey'; import { CreateGraphProviderInstance, IGraphProvider } from '../lib/graphProvider/'; import initializeCorporateViews from './corporateViews'; @@ -48,16 +48,16 @@ import keyVaultResolver, { IKeyVaultSecretResolver } from '../lib/keyVaultResolv import { createMailProviderInstance } from '../lib/mailProvider/'; import { RestLibrary } from '../lib/github'; -import { CreateRepositoryCacheProviderInstance } from '../entities/repositoryCache'; -import { CreateRepositoryCollaboratorCacheProviderInstance } from '../entities/repositoryCollaboratorCache'; -import { CreateTeamCacheProviderInstance } from '../entities/teamCache'; -import { CreateTeamMemberCacheProviderInstance } from '../entities/teamMemberCache'; -import { CreateRepositoryTeamCacheProviderInstance } from '../entities/repositoryTeamCache'; -import { CreateOrganizationMemberCacheProviderInstance } from '../entities/organizationMemberCache'; +import { CreateRepositoryCacheProviderInstance } from '../business/entities/repositoryCache'; +import { CreateRepositoryCollaboratorCacheProviderInstance } from '../business/entities/repositoryCollaboratorCache'; +import { CreateTeamCacheProviderInstance } from '../business/entities/teamCache'; +import { CreateTeamMemberCacheProviderInstance } from '../business/entities/teamMemberCache'; +import { CreateRepositoryTeamCacheProviderInstance } from '../business/entities/repositoryTeamCache'; +import { CreateOrganizationMemberCacheProviderInstance } from '../business/entities/organizationMemberCache'; import QueryCache from '../business/queryCache'; -import { createAndInitializeOrganizationSettingProviderInstance } from '../entities/organizationSettings'; +import { createAndInitializeOrganizationSettingProviderInstance } from '../business/entities/organizationSettings'; import { IEntityMetadataProvider } from '../lib/entityMetadataProvider/entityMetadataProvider'; -import { createAndInitializeAuditLogRecordProviderInstance } from '../entities/auditLogRecord'; +import { createAndInitializeAuditLogRecordProviderInstance } from '../business/entities/auditLogRecord'; import CosmosCache from '../lib/caching/cosmosdb'; import BlobCache from '../lib/caching/blob'; import { StatefulCampaignProvider } from '../lib/campaigns'; @@ -65,7 +65,7 @@ import CosmosHelper from '../lib/cosmosHelper'; import { IQueueProcessor } from '../lib/queues'; import ServiceBusQueueProcessor from '../lib/queues/servicebus'; import AzureQueuesProcessor from '../lib/queues/azurequeue'; -import { UserSettingsProvider } from '../entities/userSettings'; +import { UserSettingsProvider } from '../business/entities/userSettings'; import getCompanySpecificDeployment from './companySpecificDeployment'; import routeCorrelationId from './correlationId'; @@ -76,16 +76,16 @@ import middlewareIndex from '.'; import type { ICacheHelper } from '../lib/caching'; import type { ExecutionEnvironment, - IApplicationProfile, + ApplicationProfile, IProviders, IReposApplication, SiteConfiguration, } from '../interfaces'; -import initializeRepositoryProvider from '../entities/repository'; +import initializeRepositoryProvider from '../business/entities/repository'; import { tryGetImmutableStorageProvider } from '../lib/immutable'; import { GitHubAppPurposes } from '../lib/github/appPurposes'; -const DefaultApplicationProfile: IApplicationProfile = { +const DefaultApplicationProfile: ApplicationProfile = { applicationName: 'Open Source Management Portal', serveStaticAssets: true, serveClientAssets: true, @@ -121,7 +121,6 @@ async function initializeAsync( } else if (config.github.cache.provider === 'redis') { const redisClient = await connectRedis(config, config.redis, 'cache'); const redisHelper = new RedisHelper({ redisClient, prefix: config.redis.prefix }); - // providers.redisClient = redisClient; providers.cacheProvider = redisHelper; } else { throw new Error('No cache provider available'); @@ -318,7 +317,7 @@ async function initializeAsync( } } -function configureGitHubLibrary(cacheProvider: ICacheHelper, config): RestLibrary { +function configureGitHubLibrary(cacheProvider: ICacheHelper, config: SiteConfiguration): RestLibrary { const libraryContext = new RestLibrary({ config, cacheProvider, @@ -330,7 +329,7 @@ function configureGitHubLibrary(cacheProvider: ICacheHelper, config): RestLibrar export default async function initialize( executionEnvironment: ExecutionEnvironment, app: IReposApplication, - express, + express: Express, rootdir: string, config: SiteConfiguration, exception: Error @@ -362,6 +361,10 @@ export default async function initialize( } debug(`${containerPurpose} profile: ${applicationProfile.applicationName}`); debug(`environment: ${config?.debug?.environmentName || 'Unknown'}`); + if (config?.continuousDeployment) { + const values = Object.values(config.continuousDeployment).filter((x) => x); + values.length > 0 && debug(`build: ${values.join(', ')}`); + } const codespacesConfig = (config as SiteConfiguration)?.github?.codespaces; if (codespacesConfig?.connected === true && codespacesConfig.block === true) { @@ -541,7 +544,7 @@ export default async function initialize( return executionEnvironment; } -function createGraphProvider(providers: IProviders, config: any): Promise { +function createGraphProvider(providers: IProviders, config: SiteConfiguration): Promise { return new Promise((resolve, reject) => { // The graph provider is optional. A graph provider can connect to a // corporate directory to validate or lookup employees and other @@ -639,7 +642,10 @@ async function connectRedis( return redisClient; } -async function createMailAddressProvider(config: any, providers: IProviders): Promise { +async function createMailAddressProvider( + config: SiteConfiguration, + providers: IProviders +): Promise { const options = { config: config, providers: providers, diff --git a/middleware/keyVault.ts b/middleware/keyVault.ts index f03629d5d..77c90a60b 100644 --- a/middleware/keyVault.ts +++ b/middleware/keyVault.ts @@ -4,7 +4,7 @@ // import { ClientSecretCredential } from '@azure/identity'; -import { KeyVaultSecret, SecretClient } from '@azure/keyvault-secrets'; +import { SecretClient } from '@azure/keyvault-secrets'; export interface IKeyVaultConfigurationOptions { tenantId: string; diff --git a/middleware/locals.ts b/middleware/locals.ts index 8c6372e54..59ed4772f 100644 --- a/middleware/locals.ts +++ b/middleware/locals.ts @@ -7,7 +7,7 @@ import os from 'os'; import { NextFunction, Response } from 'express'; import { ReposAppRequest } from '../interfaces'; -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; export default function (req: ReposAppRequest, res: Response, next: NextFunction) { const { config, viewServices } = getProviders(req); diff --git a/middleware/logger.ts b/middleware/logger.ts index ef63838d3..7a3689a08 100644 --- a/middleware/logger.ts +++ b/middleware/logger.ts @@ -6,7 +6,7 @@ import logger from 'morgan'; import { ReposAppRequest } from '../interfaces'; -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; const encryptionMetadataKey = '_ClientEncryptionMetadata2'; const piiFormat = diff --git a/middleware/officeHyperlinks.ts b/middleware/officeHyperlinks.ts index aec69eb3f..5a0d6daf3 100644 --- a/middleware/officeHyperlinks.ts +++ b/middleware/officeHyperlinks.ts @@ -6,7 +6,7 @@ // I no longer believe this file FYI... I don't think we need this any longer. import { NextFunction, Response } from 'express'; -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; // Office uses a specialized pre-fetch to learn more about hyperlinks before // opening. As a result, if the Office user agent is in use, and the diff --git a/middleware/onboarding.ts b/middleware/onboarding.ts index 225bbbe2b..6a6b34535 100644 --- a/middleware/onboarding.ts +++ b/middleware/onboarding.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { IProviders } from '../interfaces'; +import { IProviders, IReposApplication, SiteConfiguration } from '../interfaces'; // ---------------------------------------------------------------------------- // Onboarding helper @@ -14,7 +14,7 @@ import { IProviders } from '../interfaces'; // rather a configuration/app initialization method just stored here to keep it // out of the way. // ---------------------------------------------------------------------------- -export default async function Onboard(app, config) { +export default async function Onboard(app: IReposApplication, config: SiteConfiguration) { const { operations } = app.settings.providers as IProviders; const onboardingOrganizations = config.github.organizations?.onboarding || []; for (const orgEntry of onboardingOrganizations) { diff --git a/middleware/passport-routes.ts b/middleware/passport-routes.ts index 1a8eeadea..a0bb18142 100644 --- a/middleware/passport-routes.ts +++ b/middleware/passport-routes.ts @@ -5,8 +5,8 @@ import type { Response, NextFunction } from 'express'; -import { redirectToReferrer, storeReferrer } from '../utils'; -import { getProviders } from '../transitional'; +import { redirectToReferrer, storeReferrer } from '../lib/utils'; +import { getProviders } from '../lib/transitional'; import type { ReposAppRequest, IAppSession } from '../interfaces'; import getCompanySpecificDeployment from './companySpecificDeployment'; import { attachAadPassportRoutes } from './passport/aadRoutes'; diff --git a/middleware/passport/aadRoutes.ts b/middleware/passport/aadRoutes.ts index 2c0e3b845..10fa64010 100644 --- a/middleware/passport/aadRoutes.ts +++ b/middleware/passport/aadRoutes.ts @@ -6,8 +6,8 @@ import { NextFunction, Response } from 'express'; import { PassportStatic } from 'passport'; import { type IReposApplication, type IReposError, ReposAppRequest } from '../../interfaces'; -import { getProviders } from '../../transitional'; -import { isCodespacesAuthenticating } from '../../utils'; +import { getProviders } from '../../lib/transitional'; +import { isCodespacesAuthenticating } from '../../lib/utils'; import { IPrimaryAuthenticationHelperMethods } from '../passport-routes'; import { aadStrategyUserPropertyName } from './aadStrategy'; diff --git a/middleware/passport/aadStrategy.ts b/middleware/passport/aadStrategy.ts index ed08debe3..9d1db1af8 100644 --- a/middleware/passport/aadStrategy.ts +++ b/middleware/passport/aadStrategy.ts @@ -12,7 +12,7 @@ import { OIDCStrategy } from 'passport-azure-ad'; import type { IProviders, IReposApplication, SiteConfiguration } from '../../interfaces'; import { GraphUserType } from '../../lib/graphProvider'; -import { getCodespacesHostname, isCodespacesAuthenticating } from '../../utils'; +import { getCodespacesHostname, isCodespacesAuthenticating } from '../../lib/utils'; export const aadStrategyName = 'azure-active-directory'; export const aadStrategyUserPropertyName = 'azure'; diff --git a/middleware/passport/encryptionSerializer.ts b/middleware/passport/encryptionSerializer.ts index b87cff659..c35cfb106 100644 --- a/middleware/passport/encryptionSerializer.ts +++ b/middleware/passport/encryptionSerializer.ts @@ -4,7 +4,7 @@ // import { decryptEntityAsync, encryptEntityAsync, IEncryptionOptions } from '../../lib/encryption'; -import { wrapError } from '../../utils'; +import { wrapError } from '../../lib/utils'; import { LegacySerializer } from './serializer'; // NOTE TO DEVELOPERS: we are no longer using encrypted sessions at our company diff --git a/middleware/passport/githubRoutes.ts b/middleware/passport/githubRoutes.ts index 07e0a287c..03f441ca7 100644 --- a/middleware/passport/githubRoutes.ts +++ b/middleware/passport/githubRoutes.ts @@ -5,10 +5,11 @@ import { NextFunction, Response } from 'express'; import querystring from 'querystring'; +import { PassportStatic } from 'passport'; -import { ReposAppRequest } from '../../interfaces'; -import { getProviders } from '../../transitional'; -import { isCodespacesAuthenticating } from '../../utils'; +import { IReposApplication, ReposAppRequest, SiteConfiguration } from '../../interfaces'; +import { getProviders } from '../../lib/transitional'; +import { isCodespacesAuthenticating } from '../../lib/utils'; import { IAuthenticationHelperMethods } from '../passport-routes'; import { getGithubAppConfigurationOptions, @@ -19,9 +20,9 @@ import { } from '../passport/githubStrategy'; export function attachGitHubPassportRoutes( - app, - config: any, - passport, + app: IReposApplication, + config: SiteConfiguration, + passport: PassportStatic, helpers: IAuthenticationHelperMethods ) { const signinPath = isCodespacesAuthenticating(config, 'github') ? 'sign-in' : 'signin'; diff --git a/middleware/passport/githubStrategy.ts b/middleware/passport/githubStrategy.ts index ff98687dd..fd056d788 100644 --- a/middleware/passport/githubStrategy.ts +++ b/middleware/passport/githubStrategy.ts @@ -5,10 +5,21 @@ import { Strategy as GithubStrategy } from 'passport-github'; -import { IGitHubAccountDetails, IProviders } from '../../interfaces'; -import { getCodespacesHostname, isCodespacesAuthenticating, isEnterpriseManagedUserLogin } from '../../utils'; +import { + getCodespacesHostname, + isCodespacesAuthenticating, + isEnterpriseManagedUserLogin, +} from '../../lib/utils'; +import type { + IGitHubAccountDetails, + IProviders, + IReposApplication, + SiteConfiguration, +} from '../../interfaces'; +import type { ConfigGitHubCodespaces } from '../../config/github.codespaces.types'; import Debug from 'debug'; +import { ConfigGitHubOAuth2 } from '../../config/github.oauth2.types'; const debug = Debug.debug('startup'); export const githubStrategyName = 'github'; @@ -55,7 +66,7 @@ function impersonatedIdentityFromDetails( } function githubResponseToSubset( - app, + app: IReposApplication, modernAppInUse: boolean, accessToken: string, refreshToken: string, @@ -73,7 +84,7 @@ function githubResponseToSubset( } async function githubResponseToSubsetEx( - app, + app: IReposApplication, modernAppInUse: boolean, accessToken: string, refreshToken: string, @@ -142,7 +153,7 @@ function githubResponseToIncreasedScopeSubset( return done(null, subset); } -export function getGithubAppConfigurationOptions(config) { +export function getGithubAppConfigurationOptions(config: SiteConfiguration) { let legacyOAuthApp = config?.github?.oauth2?.clientId && config?.github?.oauth2?.clientSecret ? config.github.oauth2 : null; const customerFacingApp = @@ -168,9 +179,9 @@ export function getGithubAppConfigurationOptions(config) { }; } -export default function createGithubStrategy(app, config) { +export default function createGithubStrategy(app: IReposApplication, config: SiteConfiguration) { const strategies = {}; - const codespaces = config?.github?.codespaces || {}; + const codespaces = config?.github?.codespaces || ({} as ConfigGitHubCodespaces); const { modernAppInUse, githubAppConfiguration, useIncreasedScopeLegacyAppIfNeeded } = getGithubAppConfigurationOptions(config); if (!githubAppConfiguration?.clientId) { @@ -183,7 +194,7 @@ export default function createGithubStrategy(app, config) { const finalCallbackUrl = isCodespacesAuthenticating(config, 'github') && !codespaces?.block ? getCodespacesHostname(config) + redirectSuffix - : githubAppConfiguration.callbackUrl; + : (githubAppConfiguration as ConfigGitHubOAuth2)?.callbackUrl; let clientId = githubAppConfiguration.clientId; let clientSecret = githubAppConfiguration.clientSecret; let codespacesOverrideText = ''; diff --git a/middleware/passport-config.ts b/middleware/passportConfig.ts similarity index 100% rename from middleware/passport-config.ts rename to middleware/passportConfig.ts diff --git a/middleware/rawBodyParser.ts b/middleware/rawBodyParser.ts index b90e7ff7c..1ef2e395a 100644 --- a/middleware/rawBodyParser.ts +++ b/middleware/rawBodyParser.ts @@ -5,7 +5,7 @@ import { NextFunction, Response } from 'express'; import { ReposAppRequest } from '../interfaces'; -import { isWebhookIngestionEndpointEnabled } from '../transitional'; +import { isWebhookIngestionEndpointEnabled } from '../lib/transitional'; export default function rawBodyParser(req: ReposAppRequest, res: Response, next: NextFunction) { if (!isWebhookIngestionEndpointEnabled(req)) { diff --git a/middleware/react.ts b/middleware/react.ts index c21749b1d..8738e76fd 100644 --- a/middleware/react.ts +++ b/middleware/react.ts @@ -10,8 +10,8 @@ import path from 'path'; import appPackage from '../package.json'; import { getStaticBlobCacheFallback } from '../lib/staticBlobCacheFallback'; -import { getProviders, splitSemiColonCommas } from '../transitional'; -import { ReposAppRequest } from '../interfaces'; +import { getProviders, splitSemiColonCommas } from '../lib/transitional'; +import type { ReposAppRequest, SiteConfiguration } from '../interfaces'; import { IndividualContext } from '../business/user'; const staticReactPackageNameKey = 'static-react-package-name'; @@ -169,7 +169,7 @@ function evaluateFlightConditions(req: ReposAppRequest): FlightingOptions | Basi }; } -function getUserClientFeatureFlags(config: any, corporateId: string) { +function getUserClientFeatureFlags(config: SiteConfiguration, corporateId: string) { const featureFlagList = config?.client?.flighting?.featureFlagUsers; if (featureFlagList && typeof featureFlagList === 'object') { const flights = []; diff --git a/middleware/scrubbedUrl.ts b/middleware/scrubbedUrl.ts index d498a6cdd..1600724a8 100644 --- a/middleware/scrubbedUrl.ts +++ b/middleware/scrubbedUrl.ts @@ -19,5 +19,5 @@ export default function (req: ReposAppRequest, res: Response, next: NextFunction } } req.scrubbedUrl = url; - next(); + return next(); } diff --git a/middleware/sslify.ts b/middleware/sslify.ts index 4fd121d2d..2b7a83dc5 100644 --- a/middleware/sslify.ts +++ b/middleware/sslify.ts @@ -4,6 +4,7 @@ // import sslify from 'express-sslify'; + import type { ConfigWebServer } from '../config/webServer.types'; export default function (webServerConfig: ConfigWebServer) { diff --git a/middleware/staticClientApp.ts b/middleware/staticClientApp.ts index 14af5da60..2cebc2dbe 100644 --- a/middleware/staticClientApp.ts +++ b/middleware/staticClientApp.ts @@ -8,10 +8,13 @@ import appPackage from '../package.json'; const packageVariableName = 'static-client-package-name'; const otherPackageVariableName = 'static-react-package-name'; +import type { IReposApplication } from '../interfaces'; +import type { ExpressWithStatic } from './types'; + import Debug from 'debug'; const debug = Debug.debug('startup'); -export function StaticClientApp(app, express) { +export function StaticClientApp(app: IReposApplication, express: ExpressWithStatic) { // Serve/host the static client app from the location reported by the private // NPM module for the Ember app. Assumes that the inclusion of the package // returns the path to host. diff --git a/middleware/staticClientApp2.ts b/middleware/staticClientApp2.ts index 7fdc795bd..73112124d 100644 --- a/middleware/staticClientApp2.ts +++ b/middleware/staticClientApp2.ts @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -import { hasStaticReactClientApp } from '../transitional'; +import { hasStaticReactClientApp } from '../lib/transitional'; import appPackage from '../package.json'; @@ -16,6 +16,7 @@ const staticReactFlightingPackageNameKey = 'static-react-flight-package-name'; const staticClientFlightingPackageName = appPackage[staticReactFlightingPackageNameKey]; import Debug from 'debug'; +import { ExpressWithStatic } from './types'; const debug = Debug.debug('startup'); export type RuntimeConfigurationClient = { @@ -31,7 +32,11 @@ export type RootRuntimeConfigurationClient = { client?: RuntimeConfigurationClient; }; -export function StaticReactClientApp(app: IReposApplication, express, config: SiteConfiguration) { +export function StaticReactClientApp( + app: IReposApplication, + express: ExpressWithStatic, + config: SiteConfiguration +) { const clientRuntimeConfiguration: RuntimeConfigurationClient = {}; app.runtimeConfiguration.client = clientRuntimeConfiguration; diff --git a/middleware/staticSiteAssets.ts b/middleware/staticSiteAssets.ts index 155e0c41d..5d56d4e50 100644 --- a/middleware/staticSiteAssets.ts +++ b/middleware/staticSiteAssets.ts @@ -12,7 +12,7 @@ const debug = Debug.debug('startup'); import favicon from 'serve-favicon'; import path from 'path'; -import { CreateError } from '../transitional'; +import { CreateError } from '../lib/transitional'; const appRootPath = appRoot.toString(); diff --git a/middleware/supportMultipleAuthProviders.ts b/middleware/supportMultipleAuthProviders.ts index cf0a8278f..0905cbab0 100644 --- a/middleware/supportMultipleAuthProviders.ts +++ b/middleware/supportMultipleAuthProviders.ts @@ -7,7 +7,7 @@ import { NextFunction, Response } from 'express'; import { jsonError } from './jsonError'; import { IApiRequest } from './apiReposAuth'; -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; // We have made a decision to not use Passport for the API routes, which is why this // performs some passport-like functionality... diff --git a/middleware/types.ts b/middleware/types.ts new file mode 100644 index 000000000..50b8e1de7 --- /dev/null +++ b/middleware/types.ts @@ -0,0 +1,10 @@ +// +// Copyright (c) Microsoft. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +import { Express } from 'express'; + +export type ExpressWithStatic = Express & { + static: (path: string, options?: any) => Express; +}; diff --git a/package-lock.json b/package-lock.json index 18b1a81b4..c791a2020 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,15 +16,15 @@ "@azure/service-bus": "7.9.3", "@azure/storage-blob": "12.17.0", "@azure/storage-queue": "12.16.0", - "@octokit/auth-app": "6.0.1", + "@octokit/auth-app": "6.0.3", "@octokit/plugin-paginate-graphql": "4.0.0", "@octokit/request": "8.1.6", "@octokit/rest": "20.0.2", "@primer/octicons": "19.8.0", "app-root-path": "3.1.0", - "applicationinsights": "2.9.1", + "applicationinsights": "2.9.2", "async-prompt": "1.0.1", - "axios": "1.6.2", + "axios": "1.6.5", "basic-auth": "2.0.1", "body-parser": "1.20.2", "color-contrast-checker": "2.1.0", @@ -50,10 +50,10 @@ "lodash": "4.17.21", "luxon": "3.4.4", "memory-cache": "0.2.0", - "moment": "2.29.4", + "moment": "2.30.1", "morgan": "1.10.0", "node-jose": "2.2.0", - "nodemailer": "6.9.7", + "nodemailer": "6.9.8", "object-path": "0.11.8", "passport": "0.7.0", "passport-azure-ad": "4.3.5", @@ -63,7 +63,7 @@ "pug": "3.0.2", "pug-load": "3.0.0", "recursive-readdir": "2.2.3", - "redis": "4.6.11", + "redis": "4.6.12", "secure-compare": "3.0.1", "semver": "7.5.4", "serve-favicon": "2.5.0", @@ -80,10 +80,10 @@ "@types/express-session": "1.17.10", "@types/jest": "29.5.11", "@types/lodash": "4.14.202", - "@types/luxon": "3.3.7", + "@types/luxon": "3.4.0", "@types/memory-cache": "0.2.5", "@types/morgan": "1.9.9", - "@types/node": "20.10.4", + "@types/node": "20.11.0", "@types/node-jose": "1.1.13", "@types/object-path": "0.11.4", "@types/passport": "1.0.16", @@ -94,22 +94,22 @@ "@types/recursive-readdir": "2.2.4", "@types/semver": "7.5.6", "@types/simple-oauth2": "5.0.7", - "@types/validator": "13.11.7", - "@typescript-eslint/eslint-plugin": "6.13.2", - "@typescript-eslint/parser": "6.13.2", - "cspell": "8.1.3", - "eslint": "8.55.0", + "@types/validator": "13.11.8", + "@typescript-eslint/eslint-plugin": "6.18.1", + "@typescript-eslint/parser": "6.18.1", + "cspell": "8.3.2", + "eslint": "8.56.0", "eslint-config-prettier": "9.1.0", - "eslint-plugin-n": "16.3.1", - "eslint-plugin-prettier": "5.0.1", + "eslint-plugin-n": "16.6.2", + "eslint-plugin-prettier": "5.1.3", "husky": "8.0.3", "jest": "29.7.0", "jest-junit": "16.0.0", "lint-staged": "15.2.0", - "markdownlint-cli2": "0.11.0", - "prettier": "3.1.0", + "markdownlint-cli2": "0.12.0", + "prettier": "3.1.1", "ts-jest": "29.1.1", - "ts-node": "10.9.1", + "ts-node": "10.9.2", "ts-prune": "0.10.3", "typescript": "5.3.3" }, @@ -1199,17 +1199,17 @@ "dev": true }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.1.3.tgz", - "integrity": "sha512-TwLyL2bCtetXGhMudjOIgFPAsWF2UkT0E7T+DAZG8aUBfHoC/eco/sTmR6UJVpi6Crjs0YOQkFUBGrQ2pxJPcA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.3.2.tgz", + "integrity": "sha512-3ubOgz1/MDixJbq//0rQ2omB3cSdhVJDviERZeiREGz4HOq84aaK1Fqbw5SjNZHvhpoq+AYXm6kJbIAH8YhKgg==", "dev": true, "dependencies": { "@cspell/dict-ada": "^4.0.2", - "@cspell/dict-aws": "^4.0.0", + "@cspell/dict-aws": "^4.0.1", "@cspell/dict-bash": "^4.1.3", - "@cspell/dict-companies": "^3.0.28", + "@cspell/dict-companies": "^3.0.29", "@cspell/dict-cpp": "^5.0.10", - "@cspell/dict-cryptocurrencies": "^4.0.0", + "@cspell/dict-cryptocurrencies": "^5.0.0", "@cspell/dict-csharp": "^4.0.2", "@cspell/dict-css": "^4.0.12", "@cspell/dict-dart": "^2.0.3", @@ -1217,15 +1217,15 @@ "@cspell/dict-docker": "^1.1.7", "@cspell/dict-dotnet": "^5.0.0", "@cspell/dict-elixir": "^4.0.3", - "@cspell/dict-en_us": "^4.3.12", - "@cspell/dict-en-common-misspellings": "^1.0.2", + "@cspell/dict-en_us": "^4.3.13", + "@cspell/dict-en-common-misspellings": "^2.0.0", "@cspell/dict-en-gb": "1.1.33", "@cspell/dict-filetypes": "^3.0.3", "@cspell/dict-fonts": "^4.0.0", "@cspell/dict-fsharp": "^1.0.1", "@cspell/dict-fullstack": "^3.1.5", "@cspell/dict-gaming-terms": "^1.0.4", - "@cspell/dict-git": "^2.0.0", + "@cspell/dict-git": "^3.0.0", "@cspell/dict-golang": "^6.0.5", "@cspell/dict-haskell": "^4.0.1", "@cspell/dict-html": "^4.0.5", @@ -1237,17 +1237,17 @@ "@cspell/dict-lua": "^4.0.3", "@cspell/dict-makefile": "^1.0.0", "@cspell/dict-node": "^4.0.3", - "@cspell/dict-npm": "^5.0.13", - "@cspell/dict-php": "^4.0.4", - "@cspell/dict-powershell": "^5.0.2", + "@cspell/dict-npm": "^5.0.14", + "@cspell/dict-php": "^4.0.5", + "@cspell/dict-powershell": "^5.0.3", "@cspell/dict-public-licenses": "^2.0.5", - "@cspell/dict-python": "^4.1.10", + "@cspell/dict-python": "^4.1.11", "@cspell/dict-r": "^2.0.1", - "@cspell/dict-ruby": "^5.0.1", + "@cspell/dict-ruby": "^5.0.2", "@cspell/dict-rust": "^4.0.1", "@cspell/dict-scala": "^5.0.0", - "@cspell/dict-software-terms": "^3.3.11", - "@cspell/dict-sql": "^2.1.2", + "@cspell/dict-software-terms": "^3.3.15", + "@cspell/dict-sql": "^2.1.3", "@cspell/dict-svelte": "^1.0.2", "@cspell/dict-swift": "^2.0.1", "@cspell/dict-typescript": "^3.1.2", @@ -1258,30 +1258,30 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.1.3.tgz", - "integrity": "sha512-9iOU0Y733XuF0cqC7xwzJkOKFdJ65rYGnHFdUHzr5lxEqeG9X/jhlkzyHuGGOhPxkUeFP1x9XoLhXo1isMDbKA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.3.2.tgz", + "integrity": "sha512-gHSz4jXMJPcxx+lOGfXhHuoyenAWQ8PVA/atHFrWYKo1LzKTbpkEkrsDnlX8QNJubc3EMH63Uy+lOIaFDVyHiQ==", "dev": true, "dependencies": { - "@cspell/cspell-types": "8.1.3" + "@cspell/cspell-types": "8.3.2" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.1.3.tgz", - "integrity": "sha512-/dcnyLDeyFuoX4seZv7VsDQyRpt3ZY0vjZiDpqFul8hPydM8czLyRPPMD6Za+Gqg6dZmh9+VsQWK52hVsqc0QA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.3.2.tgz", + "integrity": "sha512-GZmDwvQGOjQi3IjD4k9xXeVTDANczksOsgVKb3v2QZk9mR4Qj8c6Uarjd4AgSiIhu/wBliJfzr5rWFJu4X2VfQ==", "dev": true, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.1.3.tgz", - "integrity": "sha512-bGyJYqkHRilqhyKGL/NvODN5U+UvCuQo7kxgt0i3Vd7m7k6XYLsSLYZ4w6r1S5IQ/ybU8I5lh6/6fNqKwvo9eg==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.3.2.tgz", + "integrity": "sha512-w2Tmb95bzdEz9L4W5qvsP5raZbyEzKL7N2ksU/+yh8NEJcTuExmAl/nMnb3aIk7m2b+kPHnMOcJuwfUMLmyv4A==", "dev": true, "dependencies": { "global-directory": "^4.0.1" @@ -1291,18 +1291,18 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.1.3.tgz", - "integrity": "sha512-8E5ZveQKneNfK+cuFMy0y6tDsho71UPppEHNoLZsEFDbIxDdtQcAfs0pk4nwEzxPBt+dBB+Yl8KExQ6x2FAYQw==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.3.2.tgz", + "integrity": "sha512-skTHNyVi74//W/O+f4IauDhm6twA9S2whkylonsIzPxEl4Pn3y2ZEMXNki/MWUwZfDIzKKSxlcREH61g7zCvhg==", "dev": true, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-types": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.1.3.tgz", - "integrity": "sha512-j14FENj+DzWu6JjzTl+0X5/OJv9AEckpEp6Jaw9YglxirrBBzTkZGfoLePe/AWo/MlIYp0asl92C1UHEjgz+FQ==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.3.2.tgz", + "integrity": "sha512-qS/gWd9ItOrN6ZX5pwC9lJjnBoyiAyhxYq0GUXuV892LQvwrBmECGk6KhsA1lPW7JJS7o57YTAS1jmXnmXMEpg==", "dev": true, "engines": { "node": ">=18" @@ -1315,9 +1315,9 @@ "dev": true }, "node_modules/@cspell/dict-aws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.0.tgz", - "integrity": "sha512-1YkCMWuna/EGIDN/zKkW+j98/55mxigftrSFgsehXhPld+ZMJM5J9UuBA88YfL7+/ETvBdd7mwW6IwWsC+/ltQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.1.tgz", + "integrity": "sha512-NXO+kTPQGqaaJKa4kO92NAXoqS+i99dQzf3/L1BxxWVSBS3/k1f3uhmqIh7Crb/n22W793lOm0D9x952BFga3Q==", "dev": true }, "node_modules/@cspell/dict-bash": { @@ -1327,21 +1327,21 @@ "dev": true }, "node_modules/@cspell/dict-companies": { - "version": "3.0.28", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.0.28.tgz", - "integrity": "sha512-UinHkMYB/1pUkLKm1PGIm9PBFYxeAa6YvbB1Rq/RAAlrs0WDwiDBr3BAYdxydukG1IqqwT5z9WtU+8D/yV/5lw==", + "version": "3.0.29", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.0.29.tgz", + "integrity": "sha512-F/8XnkqjU7jmSDAcD3LSSX+WxCVUWPssqlO4lzGMIK3MNIUt+d48eSIt3pFAIB/Z9y0ojoLHUtWX9HJ1ZtGrXQ==", "dev": true }, "node_modules/@cspell/dict-cpp": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.0.10.tgz", - "integrity": "sha512-WCRuDrkFdpmeIR6uXQYKU9loMQKNFS4bUhtHdv5fu4qVyJSh3k/kgmtTm1h1BDTj8EwPRc/RGxS+9Z3b2mnabA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.1.0.tgz", + "integrity": "sha512-23gd41gsFhXYvVMYXiXOQlYp8othU2JjB6JbH2sWHlmwokiCG9yuWwrN/nVfrt45fzq/VyAurl58AXfx7ctAJA==", "dev": true }, "node_modules/@cspell/dict-cryptocurrencies": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-4.0.0.tgz", - "integrity": "sha512-EiZp91ATyRxTmauIQfOX9adLYCunKjHEh092rrM7o2eMXP9n7zpXAL9BK7LviL+LbB8VDOm21q+s83cKrrRrsg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.0.tgz", + "integrity": "sha512-Z4ARIw5+bvmShL+4ZrhDzGhnc9znaAGHOEMaB/GURdS/jdoreEDY34wdN0NtdLHDO5KO7GduZnZyqGdRoiSmYA==", "dev": true }, "node_modules/@cspell/dict-csharp": { @@ -1393,15 +1393,15 @@ "dev": true }, "node_modules/@cspell/dict-en_us": { - "version": "4.3.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.12.tgz", - "integrity": "sha512-1bsUxFjgxF30FTzcU5uvmCvH3lyqVKR9dbwsJhomBlUM97f0edrd6590SiYBXDm7ruE68m3lJd4vs0Ev2D6FtQ==", + "version": "4.3.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.13.tgz", + "integrity": "sha512-T6lHiGCjloGNE0d8CogF+efJZPCAP8zdzn+KnlI0Bmjaz5nvG2LTX7CXl1zkOl1nYYev0FuIk9WJ9YPVRjcFbQ==", "dev": true }, "node_modules/@cspell/dict-en-common-misspellings": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-1.0.2.tgz", - "integrity": "sha512-jg7ZQZpZH7+aAxNBlcAG4tGhYF6Ksy+QS5Df73Oo+XyckBjC9QS+PrRwLTeYoFIgXy5j3ICParK5r3MSSoL4gw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.0.tgz", + "integrity": "sha512-NOg8dlv37/YqLkCfBs5OXeJm/Wcfb/CzeOmOZJ2ZXRuxwsNuolb4TREUce0yAXRqMhawahY5TSDRJJBgKjBOdw==", "dev": true }, "node_modules/@cspell/dict-en-gb": { @@ -1441,9 +1441,9 @@ "dev": true }, "node_modules/@cspell/dict-git": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-2.0.0.tgz", - "integrity": "sha512-n1AxyX5Kgxij/sZFkxFJlzn3K9y/sCcgVPg/vz4WNJ4K9YeTsUmyGLA2OQI7d10GJeiuAo2AP1iZf2A8j9aj2w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.0.tgz", + "integrity": "sha512-simGS/lIiXbEaqJu9E2VPoYW1OTC2xrwPPXNXFMa2uo/50av56qOuaxDrZ5eH1LidFXwoc8HROCHYeKoNrDLSw==", "dev": true }, "node_modules/@cspell/dict-golang": { @@ -1513,15 +1513,15 @@ "dev": true }, "node_modules/@cspell/dict-npm": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.0.13.tgz", - "integrity": "sha512-uPb3DlQA/FvlmzT5RjZoy7fy91mxMRZW1B+K3atVM5A/cmP1QlDaSW/iCtde5kHET1MOV7uxz+vy0Yha2OI5pQ==", + "version": "5.0.14", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.0.14.tgz", + "integrity": "sha512-k0kC7/W2qG5YII+SW6s+JtvKrkZg651vizi5dv/5G2HmJaeLNgDqBVeeDk/uV+ntBorM66XG4BPMjSxoaIlC5w==", "dev": true }, "node_modules/@cspell/dict-php": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.4.tgz", - "integrity": "sha512-fRlLV730fJbulDsLIouZxXoxHt3KIH6hcLFwxaupHL+iTXDg0lo7neRpbqD5MScr/J3idEr7i9G8XWzIikKFug==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.5.tgz", + "integrity": "sha512-9r8ao7Z/mH9Z8pSB7yLtyvcCJWw+/MnQpj7xGVYzIV7V2ZWDRjXZAMgteHMJ37m8oYz64q5d4tiipD300QSetQ==", "dev": true }, "node_modules/@cspell/dict-powershell": { @@ -1537,9 +1537,9 @@ "dev": true }, "node_modules/@cspell/dict-python": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.1.10.tgz", - "integrity": "sha512-ErF/Ohcu6Xk4QVNzFgo8p7CxkxvAKAmFszvso41qOOhu8CVpB35ikBRpGVDw9gsCUtZzi15Yl0izi4do6WcLkA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.1.11.tgz", + "integrity": "sha512-XG+v3PumfzUW38huSbfT15Vqt3ihNb462ulfXifpQllPok5OWynhszCLCRQjQReV+dgz784ST4ggRxW452/kVg==", "dev": true, "dependencies": { "@cspell/dict-data-science": "^1.0.11" @@ -1552,9 +1552,9 @@ "dev": true }, "node_modules/@cspell/dict-ruby": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.1.tgz", - "integrity": "sha512-rruTm7Emhty/BSYavSm8ZxRuVw0OBqzJkwIFXcV0cX7To8D1qbmS9HFHRuRg8IL11+/nJvtdDz+lMFBSmPUagQ==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.2.tgz", + "integrity": "sha512-cIh8KTjpldzFzKGgrqUX4bFyav5lC52hXDKo4LbRuMVncs3zg4hcSf4HtURY+f2AfEZzN6ZKzXafQpThq3dl2g==", "dev": true }, "node_modules/@cspell/dict-rust": { @@ -1570,15 +1570,15 @@ "dev": true }, "node_modules/@cspell/dict-software-terms": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-3.3.12.tgz", - "integrity": "sha512-6aa4T9VqOMc0SFNBt6gxp0CWjvRqMg/uxvgpRbil+ToHWcU+Q+As0WKhPLaOniuTdCM85WWzRouD0O1XUGqg5Q==", + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-3.3.15.tgz", + "integrity": "sha512-1qqMGFi1TUNq9gQj4FTLPTlqVzQLXrj80MsKoXVpysr+823kMWesQAjqHiPg+MYsQ3DlTcpGWcjq/EbYonqueQ==", "dev": true }, "node_modules/@cspell/dict-sql": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.2.tgz", - "integrity": "sha512-Pi0hAcvsSGtZZeyyAN1VfGtQJbrXos5x2QjJU0niAQKhmITSOrXU/1II1Gogk+FYDjWyV9wP2De0U2f7EWs6oQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.3.tgz", + "integrity": "sha512-SEyTNKJrjqD6PAzZ9WpdSu6P7wgdNtGV2RV8Kpuw1x6bV+YsSptuClYG+JSdRExBTE6LwIe1bTklejUp3ZP8TQ==", "dev": true }, "node_modules/@cspell/dict-svelte": { @@ -1606,9 +1606,9 @@ "dev": true }, "node_modules/@cspell/dynamic-import": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.1.3.tgz", - "integrity": "sha512-/lXFLa92v4oOcZ2PbdRpOqBvnqWlYmGaV7iCy8+QhIWlMdzi+7tBX3LVTm9Jzvt/rJseVHQQ6RvfTsSmhbUMFQ==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.3.2.tgz", + "integrity": "sha512-4t0xM5luA3yQhar2xWvYK4wQSDB2r0u8XkpzzJqd57MnJXd7uIAxI0awGUrDXukadRaCo0tDIlMUBemH48SNVg==", "dev": true, "dependencies": { "import-meta-resolve": "^4.0.0" @@ -1618,9 +1618,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.1.3.tgz", - "integrity": "sha512-GhWyximzk8tumo0zhrDV3+nFYiETYefiTBWAEVbXJMibuvitFocVZwddqN85J0UdZ2M7q6tvBleEaI9ME/16gA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.3.2.tgz", + "integrity": "sha512-Mte/2000ap278kRYOUhiGWI7MNr1+A7WSWJmlcdP4CAH5SO20sZI3/cyZLjJJEyapdhK5vaP1L5J9sUcVDHd3A==", "dev": true, "engines": { "node": ">=18" @@ -1693,9 +1693,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", - "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1776,6 +1776,102 @@ "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "dev": true, @@ -2246,9 +2342,9 @@ } }, "node_modules/@octokit/auth-app": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-6.0.1.tgz", - "integrity": "sha512-tjCD4nzQNZgmLH62+PSnTF6eGerisFgV4v6euhqJik6yWV96e1ZiiGj+NXIqbgnpjLmtnBqVUrNyGKu3DoGEGA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-6.0.3.tgz", + "integrity": "sha512-9N7IlBAKEJR3tJgPSubCxIDYGXSdc+2xbkjYpk9nCyqREnH8qEMoMhiEB1WgoA9yTFp91El92XNXAi+AjuKnfw==", "dependencies": { "@octokit/auth-oauth-app": "^7.0.0", "@octokit/auth-oauth-user": "^4.0.0", @@ -2257,7 +2353,7 @@ "@octokit/types": "^12.0.0", "deprecation": "^2.3.1", "lru-cache": "^10.0.0", - "universal-github-app-jwt": "^1.1.1", + "universal-github-app-jwt": "^1.1.2", "universal-user-agent": "^6.0.0" }, "engines": { @@ -2504,11 +2600,19 @@ } }, "node_modules/@opentelemetry/core": { +<<<<<<< HEAD "version": "1.18.1", "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.18.1.tgz", "integrity": "sha512-kvnUqezHMhsQvdsnhnqTNfAJs3ox/isB0SVrM1dhVFw7SsB7TstuVa6fgWnN2GdPyilIFLUvvbTZoVRmx6eiRg==", "dependencies": { "@opentelemetry/semantic-conventions": "1.18.1" +======= + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.19.0.tgz", + "integrity": "sha512-w42AukJh3TP8R0IZZOVJVM/kMWu8g+lm4LzT70WtuKqhwq7KVhcDzZZuZinWZa6TtQCl7Smt2wolEYzpHabOgw==", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.19.0" +>>>>>>> upstream/main }, "engines": { "node": ">=14" @@ -2536,12 +2640,21 @@ } }, "node_modules/@opentelemetry/resources": { +<<<<<<< HEAD "version": "1.18.1", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.18.1.tgz", "integrity": "sha512-JjbcQLYMttXcIabflLRuaw5oof5gToYV9fuXbcsoOeQ0BlbwUn6DAZi++PNsSz2jjPeASfDls10iaO/8BRIPRA==", "dependencies": { "@opentelemetry/core": "1.18.1", "@opentelemetry/semantic-conventions": "1.18.1" +======= + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.19.0.tgz", + "integrity": "sha512-RgxvKuuMOf7nctOeOvpDjt2BpZvZGr9Y0vf7eGtY5XYZPkh2p7e2qub1S2IArdBMf9kEbz0SfycqCviOu9isqg==", + "dependencies": { + "@opentelemetry/core": "1.19.0", + "@opentelemetry/semantic-conventions": "1.19.0" +>>>>>>> upstream/main }, "engines": { "node": ">=14" @@ -2551,6 +2664,7 @@ } }, "node_modules/@opentelemetry/sdk-trace-base": { +<<<<<<< HEAD "version": "1.18.1", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.18.1.tgz", "integrity": "sha512-tRHfDxN5dO+nop78EWJpzZwHsN1ewrZRVVwo03VJa3JQZxToRDH29/+MB24+yoa+IArerdr7INFJiX/iN4gjqg==", @@ -2558,6 +2672,15 @@ "@opentelemetry/core": "1.18.1", "@opentelemetry/resources": "1.18.1", "@opentelemetry/semantic-conventions": "1.18.1" +======= + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.19.0.tgz", + "integrity": "sha512-+IRvUm+huJn2KqfFW3yW/cjvRwJ8Q7FzYHoUNx5Fr0Lws0LxjMJG1uVB8HDpLwm7mg5XXH2M5MF+0jj5cM8BpQ==", + "dependencies": { + "@opentelemetry/core": "1.19.0", + "@opentelemetry/resources": "1.19.0", + "@opentelemetry/semantic-conventions": "1.19.0" +>>>>>>> upstream/main }, "engines": { "node": ">=14" @@ -2567,61 +2690,39 @@ } }, "node_modules/@opentelemetry/semantic-conventions": { +<<<<<<< HEAD "version": "1.18.1", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.18.1.tgz", "integrity": "sha512-+NLGHr6VZwcgE/2lw8zDIufOCGnzsA5CbQIMleXZTrgkBd0TanCX+MiDYJ1TOS4KL/Tqk0nFRxawnaYr6pkZkA==", +======= + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.19.0.tgz", + "integrity": "sha512-14jRpC8f5c0gPSwoZ7SbEJni1PqI+AhAE8m1bMz6v+RPM4OlP1PT2UHBJj5Qh/ALLPjhVU/aZUK3YyjTUqqQVg==", +>>>>>>> upstream/main "engines": { "node": ">=14" } }, - "node_modules/@pkgr/utils": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", - "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "fast-glob": "^3.3.0", - "is-glob": "^4.0.3", - "open": "^9.1.0", - "picocolors": "^1.0.0", - "tslib": "^2.6.0" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@pkgr/utils/node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, + "optional": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=14" } }, - "node_modules/@pkgr/utils/node_modules/open": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", - "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "node_modules/@pkgr/core": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", + "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", "dev": true, - "dependencies": { - "default-browser": "^4.0.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" - }, "engines": { - "node": ">=14.16" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/unts" } }, "node_modules/@primer/octicons": { @@ -2640,9 +2741,9 @@ } }, "node_modules/@redis/client": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.12.tgz", - "integrity": "sha512-/ZjE18HRzMd80eXIIUIPcH81UoZpwulbo8FmbElrjPqH0QC0SeIKu1BOU49bO5trM5g895kAjhvalt5h77q+4A==", + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.13.tgz", + "integrity": "sha512-epkUM9D0Sdmt93/8Ozk43PNjLi36RZzG+d/T1Gdu5AI8jvghonTeLYV69WVWdilvFo+PYxbP0TZ0saMvr6nscQ==", "dependencies": { "cluster-key-slot": "1.1.2", "generic-pool": "3.9.0", @@ -2953,9 +3054,9 @@ "dev": true }, "node_modules/@types/luxon": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.7.tgz", - "integrity": "sha512-gKc9P2d4g5uYwmy4s/MO/yOVPmvHyvzka1YH6i5dM03UrFofHSmgc0D0ymbDRStFWHusk6cwwF6nhLm/ckBbbQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.0.tgz", + "integrity": "sha512-PEVoA4MOfSsFNaPrZjIUGUZujBDxnO/tj2A2N9KfzlR+pNgpBdDuk0TmRvSMAVUP5q4q8IkMEZ8UOp3MIr+QgA==", "dev": true }, "node_modules/@types/memory-cache": { @@ -2983,9 +3084,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.10.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", - "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "version": "20.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz", + "integrity": "sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==", "dependencies": { "undici-types": "~5.26.4" } @@ -3210,9 +3311,9 @@ } }, "node_modules/@types/validator": { - "version": "13.11.7", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.7.tgz", - "integrity": "sha512-q0JomTsJ2I5Mv7dhHhQLGjMvX0JJm5dyZ1DXQySIUzU1UlwzB8bt+R6+LODUbz0UDIOvEzGc28tk27gBJw2N8Q==", + "version": "13.11.8", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz", + "integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ==", "dev": true }, "node_modules/@types/yargs": { @@ -3229,16 +3330,16 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", - "integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.1.tgz", + "integrity": "sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/type-utils": "6.13.2", - "@typescript-eslint/utils": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/type-utils": "6.18.1", + "@typescript-eslint/utils": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -3264,15 +3365,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", - "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.1.tgz", + "integrity": "sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4" }, "engines": { @@ -3292,13 +3393,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", - "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", + "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2" + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -3309,13 +3410,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", - "integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz", + "integrity": "sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.13.2", - "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/utils": "6.18.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -3336,9 +3437,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", - "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", + "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -3349,16 +3450,17 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", - "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", + "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -3375,18 +3477,42 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/utils": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", - "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz", + "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/typescript-estree": "6.18.1", "semver": "^7.5.4" }, "engines": { @@ -3401,12 +3527,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", - "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", + "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/types": "6.18.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3566,23 +3692,23 @@ } }, "node_modules/applicationinsights": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-2.9.1.tgz", - "integrity": "sha512-hrpe/OvHFZlq+SQERD1fxaYICyunxzEBh9SolJebzYnIXkyA9zxIR87dZAh+F3+weltbqdIP8W038cvtpMNhQg==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-2.9.2.tgz", + "integrity": "sha512-wlDiD7v0BQNM8oNzsf9C836R5ze25u+CuCEZsbA5xMIXYYBxkqkWE/mo9GFJM7rsKaiGqpxEwWmePHKD2Lwy2w==", "dependencies": { "@azure/core-auth": "^1.5.0", "@azure/core-rest-pipeline": "1.10.1", "@azure/core-util": "1.2.0", "@azure/opentelemetry-instrumentation-azure-sdk": "^1.0.0-beta.5", "@microsoft/applicationinsights-web-snippet": "^1.0.1", - "@opentelemetry/api": "^1.4.1", - "@opentelemetry/core": "^1.15.2", - "@opentelemetry/sdk-trace-base": "^1.15.2", - "@opentelemetry/semantic-conventions": "^1.15.2", + "@opentelemetry/api": "^1.7.0", + "@opentelemetry/core": "^1.19.0", + "@opentelemetry/sdk-trace-base": "^1.19.0", + "@opentelemetry/semantic-conventions": "^1.19.0", "cls-hooked": "^4.2.2", "continuation-local-storage": "^3.2.1", "diagnostic-channel": "1.1.1", - "diagnostic-channel-publishers": "1.0.7" + "diagnostic-channel-publishers": "1.0.8" }, "engines": { "node": ">=8.0.0" @@ -3596,6 +3722,49 @@ } } }, +<<<<<<< HEAD +======= + "node_modules/applicationinsights/node_modules/@azure/core-rest-pipeline": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz", + "integrity": "sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA==", + "dependencies": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-auth": "^1.4.0", + "@azure/core-tracing": "^1.0.1", + "@azure/core-util": "^1.0.0", + "@azure/logger": "^1.0.0", + "form-data": "^4.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "tslib": "^2.2.0", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/applicationinsights/node_modules/@azure/core-util": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.2.0.tgz", + "integrity": "sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng==", + "dependencies": { + "@azure/abort-controller": "^1.0.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/applicationinsights/node_modules/@opentelemetry/api": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.7.0.tgz", + "integrity": "sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw==", + "engines": { + "node": ">=8.0.0" + } + }, +>>>>>>> upstream/main "node_modules/arg": { "version": "4.1.3", "dev": true, @@ -3686,11 +3855,11 @@ } }, "node_modules/axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", + "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -3837,6 +4006,7 @@ "version": "2.2.2", "license": "Apache-2.0" }, +<<<<<<< HEAD "node_modules/big-integer": { "version": "1.6.52", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", @@ -3846,6 +4016,8 @@ "node": ">=0.6" } }, +======= +>>>>>>> upstream/main "node_modules/body-parser": { "version": "1.20.2", "license": "MIT", @@ -3889,18 +4061,6 @@ "node": ">= 0.8" } }, - "node_modules/bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.44" - }, - "engines": { - "node": ">= 5.10.0" - } - }, "node_modules/brace-expansion": { "version": "1.1.11", "license": "MIT", @@ -4031,21 +4191,6 @@ "semver": "^7.0.0" } }, - "node_modules/bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, - "dependencies": { - "run-applescript": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/bunyan": { "version": "1.8.15", "engines": [ @@ -4663,25 +4808,25 @@ } }, "node_modules/cspell": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.1.3.tgz", - "integrity": "sha512-SU4Su6002bPoJYaiMeNV4wwLoS8TwaOgIwaTxhys3GDbJIxZV6CrDgwksezHcG7TZrC4yrveDVsdpnrzmQ7T5Q==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.3.2.tgz", + "integrity": "sha512-V8Ub3RO/a5lwSsltW/ib3Z3G/sczKtSpBBN1JChzbSCfEgaY2mJY8JW0BpkSV+Ug6uJitpXNOOaxa3Xr489i7g==", "dev": true, "dependencies": { - "@cspell/cspell-json-reporter": "8.1.3", - "@cspell/cspell-pipe": "8.1.3", - "@cspell/cspell-types": "8.1.3", - "@cspell/dynamic-import": "8.1.3", + "@cspell/cspell-json-reporter": "8.3.2", + "@cspell/cspell-pipe": "8.3.2", + "@cspell/cspell-types": "8.3.2", + "@cspell/dynamic-import": "8.3.2", "chalk": "^5.3.0", "chalk-template": "^1.1.0", "commander": "^11.1.0", - "cspell-gitignore": "8.1.3", - "cspell-glob": "8.1.3", - "cspell-io": "8.1.3", - "cspell-lib": "8.1.3", + "cspell-gitignore": "8.3.2", + "cspell-glob": "8.3.2", + "cspell-io": "8.3.2", + "cspell-lib": "8.3.2", "fast-glob": "^3.3.2", "fast-json-stable-stringify": "^2.1.0", - "file-entry-cache": "^7.0.2", + "file-entry-cache": "^8.0.0", "get-stdin": "^9.0.0", "semver": "^7.5.4", "strip-ansi": "^7.1.0", @@ -4699,12 +4844,12 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.1.3.tgz", - "integrity": "sha512-whzJYxcxos3vnywn0alCFZ+Myc0K/C62pUurfOGhgvIba7ArmlXhNRaL2r5noBxWARtpBOtzz3vrzSBK7Lq6jg==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.3.2.tgz", + "integrity": "sha512-Wc98XhBNLwDxnxCzMtgRJALI9a69cu3C5Gf1rGjNTKSFo9JYiQmju0Ur3z25Pkx9Sa86f+2IjvNCf33rUDSoBQ==", "dev": true, "dependencies": { - "@cspell/cspell-types": "8.1.3", + "@cspell/cspell-types": "8.3.2", "comment-json": "^4.2.3", "yaml": "^2.3.4" }, @@ -4713,14 +4858,14 @@ } }, "node_modules/cspell-dictionary": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.1.3.tgz", - "integrity": "sha512-nkRQDPNnA6tw+hJFBqq26M0nK306q5rtyv/AUIWa8ZHhQkwzACnpMSpuJA7/DV5GVvPKltMK5M4A6vgfpoaFHw==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.3.2.tgz", + "integrity": "sha512-xyK95hO2BMPFxIo8zBwGml8035qOxSBdga1BMhwW/p2wDrQP8S4Cdm/54//tCDmKn6uRkFQvyOfWGaX2l8WMEg==", "dev": true, "dependencies": { - "@cspell/cspell-pipe": "8.1.3", - "@cspell/cspell-types": "8.1.3", - "cspell-trie-lib": "8.1.3", + "@cspell/cspell-pipe": "8.3.2", + "@cspell/cspell-types": "8.3.2", + "cspell-trie-lib": "8.3.2", "fast-equals": "^5.0.1", "gensequence": "^6.0.0" }, @@ -4729,12 +4874,12 @@ } }, "node_modules/cspell-gitignore": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.1.3.tgz", - "integrity": "sha512-NHx5lg44eCKb6yJmUPOCz4prcuYowzoo5GJ5hOcCfbk7ZEBWV1E2/kDRuQMOK2W0y1hNGr45CSxO3UxWJlYg7w==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.3.2.tgz", + "integrity": "sha512-3Qc9P5BVvl/cg//s2s+zIMGKcoH5v7oOtRgwn4UQry8yiyo19h0tiTKkSR574FMhF5NtcShTnwIwPSIXVBPFHA==", "dev": true, "dependencies": { - "cspell-glob": "8.1.3", + "cspell-glob": "8.3.2", "find-up-simple": "^1.0.0" }, "bin": { @@ -4745,9 +4890,9 @@ } }, "node_modules/cspell-glob": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.1.3.tgz", - "integrity": "sha512-Likr7UVUXBpthQnM5r6yao3X0YBNRbJ9AHWXTC2RJfzwZOFKF+pKPfeo3FU+Px8My96M4RC2bVMbrbZUwN5NJw==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.3.2.tgz", + "integrity": "sha512-KtIFxE+3l5dGEofND4/CdZffXP8XN1+XGQKxJ96lIzWsc01mkotfhxTkla6mgvfH039t7BsY/SWv0460KyGslQ==", "dev": true, "dependencies": { "micromatch": "^4.0.5" @@ -4757,13 +4902,13 @@ } }, "node_modules/cspell-grammar": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.1.3.tgz", - "integrity": "sha512-dTOwNq6a5wcVzOsi4xY5/tq2r2w/+wLVU+WfyySTsPe66Rjqx/QceFl4OinImks/ZMKF7Zyjd3WGyQ5TcSsJFQ==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.3.2.tgz", + "integrity": "sha512-tYCkOmRzJe1a6/R+8QGSwG7TwTgznLPqsHtepKzLmnS4YX54VXjKRI9zMARxXDzUVfyCSVdW5MyiY/0WTNoy+A==", "dev": true, "dependencies": { - "@cspell/cspell-pipe": "8.1.3", - "@cspell/cspell-types": "8.1.3" + "@cspell/cspell-pipe": "8.3.2", + "@cspell/cspell-types": "8.3.2" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4773,38 +4918,38 @@ } }, "node_modules/cspell-io": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.1.3.tgz", - "integrity": "sha512-QkcFeYd79oIl7PgSqFSZyvwXnZQhXmdCI733n54IN2+iXDcf7W0mwptxoC/cE19RkEwAwEFLG81UAy6L/BXI6A==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.3.2.tgz", + "integrity": "sha512-WYpKsyBCQP0SY4gXnhW5fPuxcYchKYKG1PIXVV3ezFU4muSgW6GuLNbGuSfwv/8YNXRgFSN0e3hYH0rdBK2Aow==", "dev": true, "dependencies": { - "@cspell/cspell-service-bus": "8.1.3" + "@cspell/cspell-service-bus": "8.3.2" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.1.3.tgz", - "integrity": "sha512-Kk8bpHVkDZO4MEiPkDvRf/LgJ0h5mufbKLTWModq6k0Ca8EkZ/qgQlZ0ve0rIivbleSqebuWjpJHKDM+IHmzHA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.3.2.tgz", + "integrity": "sha512-wTvdaev/TyGB/ln6CVD1QbVs2D7/+QiajQ67S7yj1suLHM6YcNQQb/5sPAM8VPtj0E7PgwgPXf3bq18OtPvnFg==", "dev": true, "dependencies": { - "@cspell/cspell-bundled-dicts": "8.1.3", - "@cspell/cspell-pipe": "8.1.3", - "@cspell/cspell-resolver": "8.1.3", - "@cspell/cspell-types": "8.1.3", - "@cspell/dynamic-import": "8.1.3", - "@cspell/strong-weak-map": "8.1.3", + "@cspell/cspell-bundled-dicts": "8.3.2", + "@cspell/cspell-pipe": "8.3.2", + "@cspell/cspell-resolver": "8.3.2", + "@cspell/cspell-types": "8.3.2", + "@cspell/dynamic-import": "8.3.2", + "@cspell/strong-weak-map": "8.3.2", "clear-module": "^4.1.2", "comment-json": "^4.2.3", "configstore": "^6.0.0", - "cspell-config-lib": "8.1.3", - "cspell-dictionary": "8.1.3", - "cspell-glob": "8.1.3", - "cspell-grammar": "8.1.3", - "cspell-io": "8.1.3", - "cspell-trie-lib": "8.1.3", + "cspell-config-lib": "8.3.2", + "cspell-dictionary": "8.3.2", + "cspell-glob": "8.3.2", + "cspell-grammar": "8.3.2", + "cspell-io": "8.3.2", + "cspell-trie-lib": "8.3.2", "fast-equals": "^5.0.1", "gensequence": "^6.0.0", "import-fresh": "^3.3.0", @@ -4817,13 +4962,13 @@ } }, "node_modules/cspell-trie-lib": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.1.3.tgz", - "integrity": "sha512-EDSYU9MCtzPSJDrfvDrTKmc0rzl50Ehjg1c5rUCqn33p2LCRe/G8hW0FxXe0mxrZxrMO2b8l0PVSGlrCXCQ8RQ==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.3.2.tgz", + "integrity": "sha512-8qh2FqzkLMwzlTlvO/5Z+89fhi30rrfekocpight/BmqKbE2XFJQD7wS2ml24e7q/rdHJLXVpJbY/V5mByucCA==", "dev": true, "dependencies": { - "@cspell/cspell-pipe": "8.1.3", - "@cspell/cspell-types": "8.1.3", + "@cspell/cspell-pipe": "8.3.2", + "@cspell/cspell-types": "8.3.2", "gensequence": "^6.0.0" }, "engines": { @@ -4842,6 +4987,15 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, + "node_modules/cspell/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/cspell/node_modules/chalk": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", @@ -4855,15 +5009,84 @@ } }, "node_modules/cspell/node_modules/file-entry-cache": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-7.0.2.tgz", - "integrity": "sha512-TfW7/1iI4Cy7Y8L6iqNdZQVvdXn0f8B4QcIXmkIbtTIe/Okm/nSlHb4IwGzRVOd3WfSieCgvf5cMzEfySAIl0g==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.2.0" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=16.0.0" + } + }, + "node_modules/cspell/node_modules/flat-cache": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.0.tgz", + "integrity": "sha512-EryKbCE/wxpxKniQlyas6PY1I9vwtF3uCBweX+N8KYTCn3Y12RTGtQAJ/bd5pl7kxUAc8v/R3Ake/N17OZiFqA==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4", + "rimraf": "^5.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/cspell/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cspell/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cspell/node_modules/rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/cspell/node_modules/strip-ansi": { @@ -4930,6 +5153,7 @@ "node": ">=0.10.0" } }, +<<<<<<< HEAD "node_modules/default-browser": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", @@ -5074,6 +5298,8 @@ "url": "https://github.com/sponsors/sindresorhus" } }, +======= +>>>>>>> upstream/main "node_modules/define-data-property": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", @@ -5138,9 +5364,9 @@ } }, "node_modules/diagnostic-channel-publishers": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.7.tgz", - "integrity": "sha512-SEECbY5AiVt6DfLkhkaHNeshg1CogdLLANA8xlG/TKvS+XUgvIKl7VspJGYiEdL5OUyzMVnr7o0AwB7f+/Mjtg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.8.tgz", + "integrity": "sha512-HmSm9hXxSPxA9BaLGY98QU1zsdjeCk113KjAYGPCen1ZP6mhVaTPzHd6UYv5r21DnWANi+f+NyPOHruGT9jpqQ==", "peerDependencies": { "diagnostic-channel": "*" } @@ -5234,6 +5460,12 @@ "node": ">=0.10" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "license": "Apache-2.0", @@ -5283,9 +5515,9 @@ } }, "node_modules/entities": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", - "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, "engines": { "node": ">=0.12" @@ -5329,15 +5561,15 @@ } }, "node_modules/eslint": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", - "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.55.0", + "@eslint/js": "8.56.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -5428,15 +5660,16 @@ } }, "node_modules/eslint-plugin-n": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.3.1.tgz", - "integrity": "sha512-w46eDIkxQ2FaTHcey7G40eD+FhTXOdKudDXPUO2n9WNcslze/i/HT2qJ3GXjHngYSGDISIgPNhwGtgoix4zeOw==", + "version": "16.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.6.2.tgz", + "integrity": "sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "builtins": "^5.0.1", - "eslint-plugin-es-x": "^7.1.0", + "eslint-plugin-es-x": "^7.5.0", "get-tsconfig": "^4.7.0", + "globals": "^13.24.0", "ignore": "^5.2.4", "is-builtin-module": "^3.2.1", "is-core-module": "^2.12.1", @@ -5455,23 +5688,24 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz", - "integrity": "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.5" + "synckit": "^0.8.6" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/prettier" + "url": "https://opencollective.com/eslint-plugin-prettier" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", + "eslint-config-prettier": "*", "prettier": ">=3.0.0" }, "peerDependenciesMeta": { @@ -6033,7 +6267,13 @@ "dev": true }, "node_modules/follow-redirects": { +<<<<<<< HEAD "version": "1.15.2", +======= + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", + "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", +>>>>>>> upstream/main "funding": [ { "type": "individual", @@ -6058,6 +6298,34 @@ "is-callable": "^1.1.3" } }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { "version": "4.0.0", "license": "MIT", @@ -6750,61 +7018,28 @@ } }, "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=14.16" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-inside-container/node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "node_modules/is-glob": { + "version": "4.0.3", "dev": true, - "bin": { - "is-docker": "cli.js" + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, "node_modules/is-number": { @@ -6969,6 +7204,24 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -7832,12 +8085,12 @@ "license": "MIT" }, "node_modules/linkify-it": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", - "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dev": true, "dependencies": { - "uc.micro": "^1.0.1" + "uc.micro": "^2.0.0" } }, "node_modules/lint-staged": { @@ -8288,29 +8541,30 @@ } }, "node_modules/markdown-it": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.2.tgz", - "integrity": "sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.0.0.tgz", + "integrity": "sha512-seFjF0FIcPt4P9U39Bq1JYblX0KZCjDLFFQPHpL5AzHpqPEKtosxmdq/LTVZnjfH7tjt9BxStm+wXcDBNuYmzw==", "dev": true, "dependencies": { "argparse": "^2.0.1", - "entities": "~3.0.1", - "linkify-it": "^4.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.0.0" }, "bin": { - "markdown-it": "bin/markdown-it.js" + "markdown-it": "bin/markdown-it.mjs" } }, "node_modules/markdownlint": { - "version": "0.32.1", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.32.1.tgz", - "integrity": "sha512-3sx9xpi4xlHlokGyHO9k0g3gJbNY4DI6oNEeEYq5gQ4W7UkiJ90VDAnuDl2U+yyXOUa6BX+0gf69ZlTUGIBp6A==", + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.33.0.tgz", + "integrity": "sha512-4lbtT14A3m0LPX1WS/3d1m7Blg+ZwiLq36WvjQqFGsX3Gik99NV+VXp/PW3n+Q62xyPdbvGOCfjPqjW+/SKMig==", "dev": true, "dependencies": { - "markdown-it": "13.0.2", - "markdownlint-micromark": "0.1.7" + "markdown-it": "14.0.0", + "markdownlint-micromark": "0.1.8" }, "engines": { "node": ">=18" @@ -8320,22 +8574,20 @@ } }, "node_modules/markdownlint-cli2": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.11.0.tgz", - "integrity": "sha512-RmFpr+My5in8KT+H/A6ozKIVYVzZtL5t9c8DYdv0YJdljl385z44CcCVBrclpHxCGMY2tr0hZ/ca+meGGvgdnQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.12.0.tgz", + "integrity": "sha512-5nddNaPY1WC7BE1mkF8fiEkRDW8XbODwqYBPL3eyvFh7tLk74no+P8JRbCjghF7ozahCW5pF0TZ3ZS30m9H1Eg==", "dev": true, "dependencies": { "globby": "14.0.0", - "markdownlint": "0.32.1", + "markdownlint": "0.33.0", "markdownlint-cli2-formatter-default": "0.0.4", "micromatch": "4.0.5", "strip-json-comments": "5.0.1", "yaml": "2.3.4" }, "bin": { - "markdownlint-cli2": "markdownlint-cli2.js", - "markdownlint-cli2-config": "markdownlint-cli2-config.js", - "markdownlint-cli2-fix": "markdownlint-cli2-fix.js" + "markdownlint-cli2": "markdownlint-cli2.js" }, "engines": { "node": ">=18" @@ -8409,18 +8661,21 @@ } }, "node_modules/markdownlint-micromark": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.7.tgz", - "integrity": "sha512-BbRPTC72fl5vlSKv37v/xIENSRDYL/7X/XoFzZ740FGEbs9vZerLrIkFRY0rv7slQKxDczToYuMmqQFN61fi4Q==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.8.tgz", + "integrity": "sha512-1ouYkMRo9/6gou9gObuMDnvZM8jC/ly3QCFQyoSPCS2XV1ZClU0xpKbL1Ar3bWWRT1RnBZkWUEiNKrI2CwiBQA==", "dev": true, "engines": { "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" } }, "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", "dev": true }, "node_modules/media-typer": { @@ -8521,6 +8776,15 @@ "version": "1.2.6", "license": "MIT" }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp": { "version": "1.0.4", "dev": true, @@ -8538,8 +8802,14 @@ "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" }, "node_modules/moment": { +<<<<<<< HEAD "version": "2.29.4", "license": "MIT", +======= + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", +>>>>>>> upstream/main "engines": { "node": "*" } @@ -8727,9 +8997,9 @@ "license": "MIT" }, "node_modules/nodemailer": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", - "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==", + "version": "6.9.8", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.8.tgz", + "integrity": "sha512-cfrYUk16e67Ks051i4CntM9kshRYei1/o/Gi8K1d+R34OIs21xdFnW7Pt7EucmVKA0LKtqUGNcjMZ7ehjl49mQ==", "engines": { "node": ">=6.0.0" } @@ -9077,6 +9347,31 @@ "version": "1.0.7", "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "license": "MIT" @@ -9328,9 +9623,9 @@ } }, "node_modules/prettier": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", - "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -9538,6 +9833,15 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/pure-rand": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", @@ -9629,12 +9933,12 @@ } }, "node_modules/redis": { - "version": "4.6.11", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.11.tgz", - "integrity": "sha512-kg1Lt4NZLYkAjPOj/WcyIGWfZfnyfKo1Wg9YKVSlzhFwxpFIl3LYI8BWy1Ab963LLDsTz2+OwdsesHKljB3WMQ==", + "version": "4.6.12", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.12.tgz", + "integrity": "sha512-41Xuuko6P4uH4VPe5nE3BqXHB7a9lkFL0J29AlxKaIfD6eWO8VO/5PDF9ad2oS+mswMsfFxaM5DlE3tnXT+P8Q==", "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.12", + "@redis/client": "1.5.13", "@redis/graph": "1.1.1", "@redis/json": "1.0.6", "@redis/search": "1.1.6", @@ -9795,21 +10099,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "dev": true, @@ -10172,6 +10461,36 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/string-width/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -10210,6 +10529,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "license": "MIT", @@ -10262,12 +10594,21 @@ } }, "node_modules/synckit": { +<<<<<<< HEAD "version": "0.8.6", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.6.tgz", "integrity": "sha512-laHF2savN6sMeHCjLRkheIU4wo3Zg9Ln5YOjOo7sZ5dVQW8yF5pPE5SIw1dsPhq3TRp1jisKRCdPhfs/1WMqDA==", "dev": true, "dependencies": { "@pkgr/utils": "^2.4.2", +======= + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", +>>>>>>> upstream/main "tslib": "^2.6.2" }, "engines": { @@ -10299,18 +10640,6 @@ "version": "6.0.2", "license": "MIT" }, - "node_modules/titleize": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", - "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/tmp": { "version": "0.2.1", "license": "MIT", @@ -10436,7 +10765,13 @@ } }, "node_modules/ts-node": { +<<<<<<< HEAD "version": "10.9.1", +======= + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", +>>>>>>> upstream/main "dev": true, "license": "MIT", "dependencies": { @@ -10603,9 +10938,9 @@ } }, "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.0.0.tgz", + "integrity": "sha512-DffL94LsNOccVn4hyfRe5rdKa273swqeA5DJpMOeFmEn1wCDc7nAbbB0gXlgBCL7TNzeTv6G7XVWzan7iJtfig==", "dev": true }, "node_modules/uid-safe": { @@ -10655,11 +10990,17 @@ } }, "node_modules/universal-github-app-jwt": { +<<<<<<< HEAD "version": "1.1.1", "license": "MIT", +======= + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-1.1.2.tgz", + "integrity": "sha512-t1iB2FmLFE+yyJY9+3wMx0ejB+MQpEVkH0gQv7dR6FZyltyq+ZZO0uDpbopxhrZ3SLEO4dCEkIujOMldEQ2iOA==", +>>>>>>> upstream/main "dependencies": { "@types/jsonwebtoken": "^9.0.0", - "jsonwebtoken": "^9.0.0" + "jsonwebtoken": "^9.0.2" } }, "node_modules/universal-user-agent": { @@ -10673,15 +11014,6 @@ "node": ">= 0.8" } }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/update-browserslist-db": { "version": "1.0.11", "dev": true, @@ -10880,6 +11212,53 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -11836,17 +12215,17 @@ "dev": true }, "@cspell/cspell-bundled-dicts": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.1.3.tgz", - "integrity": "sha512-TwLyL2bCtetXGhMudjOIgFPAsWF2UkT0E7T+DAZG8aUBfHoC/eco/sTmR6UJVpi6Crjs0YOQkFUBGrQ2pxJPcA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.3.2.tgz", + "integrity": "sha512-3ubOgz1/MDixJbq//0rQ2omB3cSdhVJDviERZeiREGz4HOq84aaK1Fqbw5SjNZHvhpoq+AYXm6kJbIAH8YhKgg==", "dev": true, "requires": { "@cspell/dict-ada": "^4.0.2", - "@cspell/dict-aws": "^4.0.0", + "@cspell/dict-aws": "^4.0.1", "@cspell/dict-bash": "^4.1.3", - "@cspell/dict-companies": "^3.0.28", + "@cspell/dict-companies": "^3.0.29", "@cspell/dict-cpp": "^5.0.10", - "@cspell/dict-cryptocurrencies": "^4.0.0", + "@cspell/dict-cryptocurrencies": "^5.0.0", "@cspell/dict-csharp": "^4.0.2", "@cspell/dict-css": "^4.0.12", "@cspell/dict-dart": "^2.0.3", @@ -11854,15 +12233,15 @@ "@cspell/dict-docker": "^1.1.7", "@cspell/dict-dotnet": "^5.0.0", "@cspell/dict-elixir": "^4.0.3", - "@cspell/dict-en_us": "^4.3.12", - "@cspell/dict-en-common-misspellings": "^1.0.2", + "@cspell/dict-en_us": "^4.3.13", + "@cspell/dict-en-common-misspellings": "^2.0.0", "@cspell/dict-en-gb": "1.1.33", "@cspell/dict-filetypes": "^3.0.3", "@cspell/dict-fonts": "^4.0.0", "@cspell/dict-fsharp": "^1.0.1", "@cspell/dict-fullstack": "^3.1.5", "@cspell/dict-gaming-terms": "^1.0.4", - "@cspell/dict-git": "^2.0.0", + "@cspell/dict-git": "^3.0.0", "@cspell/dict-golang": "^6.0.5", "@cspell/dict-haskell": "^4.0.1", "@cspell/dict-html": "^4.0.5", @@ -11874,17 +12253,17 @@ "@cspell/dict-lua": "^4.0.3", "@cspell/dict-makefile": "^1.0.0", "@cspell/dict-node": "^4.0.3", - "@cspell/dict-npm": "^5.0.13", - "@cspell/dict-php": "^4.0.4", - "@cspell/dict-powershell": "^5.0.2", + "@cspell/dict-npm": "^5.0.14", + "@cspell/dict-php": "^4.0.5", + "@cspell/dict-powershell": "^5.0.3", "@cspell/dict-public-licenses": "^2.0.5", - "@cspell/dict-python": "^4.1.10", + "@cspell/dict-python": "^4.1.11", "@cspell/dict-r": "^2.0.1", - "@cspell/dict-ruby": "^5.0.1", + "@cspell/dict-ruby": "^5.0.2", "@cspell/dict-rust": "^4.0.1", "@cspell/dict-scala": "^5.0.0", - "@cspell/dict-software-terms": "^3.3.11", - "@cspell/dict-sql": "^2.1.2", + "@cspell/dict-software-terms": "^3.3.15", + "@cspell/dict-sql": "^2.1.3", "@cspell/dict-svelte": "^1.0.2", "@cspell/dict-swift": "^2.0.1", "@cspell/dict-typescript": "^3.1.2", @@ -11892,39 +12271,39 @@ } }, "@cspell/cspell-json-reporter": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.1.3.tgz", - "integrity": "sha512-9iOU0Y733XuF0cqC7xwzJkOKFdJ65rYGnHFdUHzr5lxEqeG9X/jhlkzyHuGGOhPxkUeFP1x9XoLhXo1isMDbKA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.3.2.tgz", + "integrity": "sha512-gHSz4jXMJPcxx+lOGfXhHuoyenAWQ8PVA/atHFrWYKo1LzKTbpkEkrsDnlX8QNJubc3EMH63Uy+lOIaFDVyHiQ==", "dev": true, "requires": { - "@cspell/cspell-types": "8.1.3" + "@cspell/cspell-types": "8.3.2" } }, "@cspell/cspell-pipe": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.1.3.tgz", - "integrity": "sha512-/dcnyLDeyFuoX4seZv7VsDQyRpt3ZY0vjZiDpqFul8hPydM8czLyRPPMD6Za+Gqg6dZmh9+VsQWK52hVsqc0QA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.3.2.tgz", + "integrity": "sha512-GZmDwvQGOjQi3IjD4k9xXeVTDANczksOsgVKb3v2QZk9mR4Qj8c6Uarjd4AgSiIhu/wBliJfzr5rWFJu4X2VfQ==", "dev": true }, "@cspell/cspell-resolver": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.1.3.tgz", - "integrity": "sha512-bGyJYqkHRilqhyKGL/NvODN5U+UvCuQo7kxgt0i3Vd7m7k6XYLsSLYZ4w6r1S5IQ/ybU8I5lh6/6fNqKwvo9eg==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.3.2.tgz", + "integrity": "sha512-w2Tmb95bzdEz9L4W5qvsP5raZbyEzKL7N2ksU/+yh8NEJcTuExmAl/nMnb3aIk7m2b+kPHnMOcJuwfUMLmyv4A==", "dev": true, "requires": { "global-directory": "^4.0.1" } }, "@cspell/cspell-service-bus": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.1.3.tgz", - "integrity": "sha512-8E5ZveQKneNfK+cuFMy0y6tDsho71UPppEHNoLZsEFDbIxDdtQcAfs0pk4nwEzxPBt+dBB+Yl8KExQ6x2FAYQw==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.3.2.tgz", + "integrity": "sha512-skTHNyVi74//W/O+f4IauDhm6twA9S2whkylonsIzPxEl4Pn3y2ZEMXNki/MWUwZfDIzKKSxlcREH61g7zCvhg==", "dev": true }, "@cspell/cspell-types": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.1.3.tgz", - "integrity": "sha512-j14FENj+DzWu6JjzTl+0X5/OJv9AEckpEp6Jaw9YglxirrBBzTkZGfoLePe/AWo/MlIYp0asl92C1UHEjgz+FQ==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.3.2.tgz", + "integrity": "sha512-qS/gWd9ItOrN6ZX5pwC9lJjnBoyiAyhxYq0GUXuV892LQvwrBmECGk6KhsA1lPW7JJS7o57YTAS1jmXnmXMEpg==", "dev": true }, "@cspell/dict-ada": { @@ -11934,9 +12313,9 @@ "dev": true }, "@cspell/dict-aws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.0.tgz", - "integrity": "sha512-1YkCMWuna/EGIDN/zKkW+j98/55mxigftrSFgsehXhPld+ZMJM5J9UuBA88YfL7+/ETvBdd7mwW6IwWsC+/ltQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.1.tgz", + "integrity": "sha512-NXO+kTPQGqaaJKa4kO92NAXoqS+i99dQzf3/L1BxxWVSBS3/k1f3uhmqIh7Crb/n22W793lOm0D9x952BFga3Q==", "dev": true }, "@cspell/dict-bash": { @@ -11946,21 +12325,21 @@ "dev": true }, "@cspell/dict-companies": { - "version": "3.0.28", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.0.28.tgz", - "integrity": "sha512-UinHkMYB/1pUkLKm1PGIm9PBFYxeAa6YvbB1Rq/RAAlrs0WDwiDBr3BAYdxydukG1IqqwT5z9WtU+8D/yV/5lw==", + "version": "3.0.29", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.0.29.tgz", + "integrity": "sha512-F/8XnkqjU7jmSDAcD3LSSX+WxCVUWPssqlO4lzGMIK3MNIUt+d48eSIt3pFAIB/Z9y0ojoLHUtWX9HJ1ZtGrXQ==", "dev": true }, "@cspell/dict-cpp": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.0.10.tgz", - "integrity": "sha512-WCRuDrkFdpmeIR6uXQYKU9loMQKNFS4bUhtHdv5fu4qVyJSh3k/kgmtTm1h1BDTj8EwPRc/RGxS+9Z3b2mnabA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.1.0.tgz", + "integrity": "sha512-23gd41gsFhXYvVMYXiXOQlYp8othU2JjB6JbH2sWHlmwokiCG9yuWwrN/nVfrt45fzq/VyAurl58AXfx7ctAJA==", "dev": true }, "@cspell/dict-cryptocurrencies": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-4.0.0.tgz", - "integrity": "sha512-EiZp91ATyRxTmauIQfOX9adLYCunKjHEh092rrM7o2eMXP9n7zpXAL9BK7LviL+LbB8VDOm21q+s83cKrrRrsg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.0.tgz", + "integrity": "sha512-Z4ARIw5+bvmShL+4ZrhDzGhnc9znaAGHOEMaB/GURdS/jdoreEDY34wdN0NtdLHDO5KO7GduZnZyqGdRoiSmYA==", "dev": true }, "@cspell/dict-csharp": { @@ -12012,15 +12391,15 @@ "dev": true }, "@cspell/dict-en_us": { - "version": "4.3.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.12.tgz", - "integrity": "sha512-1bsUxFjgxF30FTzcU5uvmCvH3lyqVKR9dbwsJhomBlUM97f0edrd6590SiYBXDm7ruE68m3lJd4vs0Ev2D6FtQ==", + "version": "4.3.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.13.tgz", + "integrity": "sha512-T6lHiGCjloGNE0d8CogF+efJZPCAP8zdzn+KnlI0Bmjaz5nvG2LTX7CXl1zkOl1nYYev0FuIk9WJ9YPVRjcFbQ==", "dev": true }, "@cspell/dict-en-common-misspellings": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-1.0.2.tgz", - "integrity": "sha512-jg7ZQZpZH7+aAxNBlcAG4tGhYF6Ksy+QS5Df73Oo+XyckBjC9QS+PrRwLTeYoFIgXy5j3ICParK5r3MSSoL4gw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.0.tgz", + "integrity": "sha512-NOg8dlv37/YqLkCfBs5OXeJm/Wcfb/CzeOmOZJ2ZXRuxwsNuolb4TREUce0yAXRqMhawahY5TSDRJJBgKjBOdw==", "dev": true }, "@cspell/dict-en-gb": { @@ -12060,9 +12439,9 @@ "dev": true }, "@cspell/dict-git": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-2.0.0.tgz", - "integrity": "sha512-n1AxyX5Kgxij/sZFkxFJlzn3K9y/sCcgVPg/vz4WNJ4K9YeTsUmyGLA2OQI7d10GJeiuAo2AP1iZf2A8j9aj2w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.0.tgz", + "integrity": "sha512-simGS/lIiXbEaqJu9E2VPoYW1OTC2xrwPPXNXFMa2uo/50av56qOuaxDrZ5eH1LidFXwoc8HROCHYeKoNrDLSw==", "dev": true }, "@cspell/dict-golang": { @@ -12132,15 +12511,15 @@ "dev": true }, "@cspell/dict-npm": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.0.13.tgz", - "integrity": "sha512-uPb3DlQA/FvlmzT5RjZoy7fy91mxMRZW1B+K3atVM5A/cmP1QlDaSW/iCtde5kHET1MOV7uxz+vy0Yha2OI5pQ==", + "version": "5.0.14", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.0.14.tgz", + "integrity": "sha512-k0kC7/W2qG5YII+SW6s+JtvKrkZg651vizi5dv/5G2HmJaeLNgDqBVeeDk/uV+ntBorM66XG4BPMjSxoaIlC5w==", "dev": true }, "@cspell/dict-php": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.4.tgz", - "integrity": "sha512-fRlLV730fJbulDsLIouZxXoxHt3KIH6hcLFwxaupHL+iTXDg0lo7neRpbqD5MScr/J3idEr7i9G8XWzIikKFug==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.5.tgz", + "integrity": "sha512-9r8ao7Z/mH9Z8pSB7yLtyvcCJWw+/MnQpj7xGVYzIV7V2ZWDRjXZAMgteHMJ37m8oYz64q5d4tiipD300QSetQ==", "dev": true }, "@cspell/dict-powershell": { @@ -12156,9 +12535,9 @@ "dev": true }, "@cspell/dict-python": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.1.10.tgz", - "integrity": "sha512-ErF/Ohcu6Xk4QVNzFgo8p7CxkxvAKAmFszvso41qOOhu8CVpB35ikBRpGVDw9gsCUtZzi15Yl0izi4do6WcLkA==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.1.11.tgz", + "integrity": "sha512-XG+v3PumfzUW38huSbfT15Vqt3ihNb462ulfXifpQllPok5OWynhszCLCRQjQReV+dgz784ST4ggRxW452/kVg==", "dev": true, "requires": { "@cspell/dict-data-science": "^1.0.11" @@ -12171,9 +12550,9 @@ "dev": true }, "@cspell/dict-ruby": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.1.tgz", - "integrity": "sha512-rruTm7Emhty/BSYavSm8ZxRuVw0OBqzJkwIFXcV0cX7To8D1qbmS9HFHRuRg8IL11+/nJvtdDz+lMFBSmPUagQ==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.2.tgz", + "integrity": "sha512-cIh8KTjpldzFzKGgrqUX4bFyav5lC52hXDKo4LbRuMVncs3zg4hcSf4HtURY+f2AfEZzN6ZKzXafQpThq3dl2g==", "dev": true }, "@cspell/dict-rust": { @@ -12189,15 +12568,15 @@ "dev": true }, "@cspell/dict-software-terms": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-3.3.12.tgz", - "integrity": "sha512-6aa4T9VqOMc0SFNBt6gxp0CWjvRqMg/uxvgpRbil+ToHWcU+Q+As0WKhPLaOniuTdCM85WWzRouD0O1XUGqg5Q==", + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-3.3.15.tgz", + "integrity": "sha512-1qqMGFi1TUNq9gQj4FTLPTlqVzQLXrj80MsKoXVpysr+823kMWesQAjqHiPg+MYsQ3DlTcpGWcjq/EbYonqueQ==", "dev": true }, "@cspell/dict-sql": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.2.tgz", - "integrity": "sha512-Pi0hAcvsSGtZZeyyAN1VfGtQJbrXos5x2QjJU0niAQKhmITSOrXU/1II1Gogk+FYDjWyV9wP2De0U2f7EWs6oQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.3.tgz", + "integrity": "sha512-SEyTNKJrjqD6PAzZ9WpdSu6P7wgdNtGV2RV8Kpuw1x6bV+YsSptuClYG+JSdRExBTE6LwIe1bTklejUp3ZP8TQ==", "dev": true }, "@cspell/dict-svelte": { @@ -12225,18 +12604,18 @@ "dev": true }, "@cspell/dynamic-import": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.1.3.tgz", - "integrity": "sha512-/lXFLa92v4oOcZ2PbdRpOqBvnqWlYmGaV7iCy8+QhIWlMdzi+7tBX3LVTm9Jzvt/rJseVHQQ6RvfTsSmhbUMFQ==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.3.2.tgz", + "integrity": "sha512-4t0xM5luA3yQhar2xWvYK4wQSDB2r0u8XkpzzJqd57MnJXd7uIAxI0awGUrDXukadRaCo0tDIlMUBemH48SNVg==", "dev": true, "requires": { "import-meta-resolve": "^4.0.0" } }, "@cspell/strong-weak-map": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.1.3.tgz", - "integrity": "sha512-GhWyximzk8tumo0zhrDV3+nFYiETYefiTBWAEVbXJMibuvitFocVZwddqN85J0UdZ2M7q6tvBleEaI9ME/16gA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.3.2.tgz", + "integrity": "sha512-Mte/2000ap278kRYOUhiGWI7MNr1+A7WSWJmlcdP4CAH5SO20sZI3/cyZLjJJEyapdhK5vaP1L5J9sUcVDHd3A==", "dev": true }, "@cspotcode/source-map-support": { @@ -12287,9 +12666,9 @@ } }, "@eslint/js": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", - "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true }, "@hapi/boom": { @@ -12344,16 +12723,81 @@ "minimatch": "^3.0.5" } }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true - }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "dev": true, @@ -12709,9 +13153,9 @@ } }, "@octokit/auth-app": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-6.0.1.tgz", - "integrity": "sha512-tjCD4nzQNZgmLH62+PSnTF6eGerisFgV4v6euhqJik6yWV96e1ZiiGj+NXIqbgnpjLmtnBqVUrNyGKu3DoGEGA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-6.0.3.tgz", + "integrity": "sha512-9N7IlBAKEJR3tJgPSubCxIDYGXSdc+2xbkjYpk9nCyqREnH8qEMoMhiEB1WgoA9yTFp91El92XNXAi+AjuKnfw==", "requires": { "@octokit/auth-oauth-app": "^7.0.0", "@octokit/auth-oauth-user": "^4.0.0", @@ -12720,7 +13164,7 @@ "@octokit/types": "^12.0.0", "deprecation": "^2.3.1", "lru-cache": "^10.0.0", - "universal-github-app-jwt": "^1.1.1", + "universal-github-app-jwt": "^1.1.2", "universal-user-agent": "^6.0.0" }, "dependencies": { @@ -12901,11 +13345,19 @@ "version": "1.4.1" }, "@opentelemetry/core": { +<<<<<<< HEAD "version": "1.18.1", "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.18.1.tgz", "integrity": "sha512-kvnUqezHMhsQvdsnhnqTNfAJs3ox/isB0SVrM1dhVFw7SsB7TstuVa6fgWnN2GdPyilIFLUvvbTZoVRmx6eiRg==", "requires": { "@opentelemetry/semantic-conventions": "1.18.1" +======= + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.19.0.tgz", + "integrity": "sha512-w42AukJh3TP8R0IZZOVJVM/kMWu8g+lm4LzT70WtuKqhwq7KVhcDzZZuZinWZa6TtQCl7Smt2wolEYzpHabOgw==", + "requires": { + "@opentelemetry/semantic-conventions": "1.19.0" +>>>>>>> upstream/main } }, "@opentelemetry/instrumentation": { @@ -12921,6 +13373,7 @@ } }, "@opentelemetry/resources": { +<<<<<<< HEAD "version": "1.18.1", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.18.1.tgz", "integrity": "sha512-JjbcQLYMttXcIabflLRuaw5oof5gToYV9fuXbcsoOeQ0BlbwUn6DAZi++PNsSz2jjPeASfDls10iaO/8BRIPRA==", @@ -12943,41 +13396,44 @@ "version": "1.18.1", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.18.1.tgz", "integrity": "sha512-+NLGHr6VZwcgE/2lw8zDIufOCGnzsA5CbQIMleXZTrgkBd0TanCX+MiDYJ1TOS4KL/Tqk0nFRxawnaYr6pkZkA==" +======= + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.19.0.tgz", + "integrity": "sha512-RgxvKuuMOf7nctOeOvpDjt2BpZvZGr9Y0vf7eGtY5XYZPkh2p7e2qub1S2IArdBMf9kEbz0SfycqCviOu9isqg==", + "requires": { + "@opentelemetry/core": "1.19.0", + "@opentelemetry/semantic-conventions": "1.19.0" + } }, - "@pkgr/utils": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", - "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", - "dev": true, + "@opentelemetry/sdk-trace-base": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.19.0.tgz", + "integrity": "sha512-+IRvUm+huJn2KqfFW3yW/cjvRwJ8Q7FzYHoUNx5Fr0Lws0LxjMJG1uVB8HDpLwm7mg5XXH2M5MF+0jj5cM8BpQ==", "requires": { - "cross-spawn": "^7.0.3", - "fast-glob": "^3.3.0", - "is-glob": "^4.0.3", - "open": "^9.1.0", - "picocolors": "^1.0.0", - "tslib": "^2.6.0" - }, - "dependencies": { - "define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true - }, - "open": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", - "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", - "dev": true, - "requires": { - "default-browser": "^4.0.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" - } - } + "@opentelemetry/core": "1.19.0", + "@opentelemetry/resources": "1.19.0", + "@opentelemetry/semantic-conventions": "1.19.0" } }, + "@opentelemetry/semantic-conventions": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.19.0.tgz", + "integrity": "sha512-14jRpC8f5c0gPSwoZ7SbEJni1PqI+AhAE8m1bMz6v+RPM4OlP1PT2UHBJj5Qh/ALLPjhVU/aZUK3YyjTUqqQVg==" +>>>>>>> upstream/main + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, + "@pkgr/core": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", + "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", + "dev": true + }, "@primer/octicons": { "version": "19.8.0", "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-19.8.0.tgz", @@ -12991,9 +13447,9 @@ "requires": {} }, "@redis/client": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.12.tgz", - "integrity": "sha512-/ZjE18HRzMd80eXIIUIPcH81UoZpwulbo8FmbElrjPqH0QC0SeIKu1BOU49bO5trM5g895kAjhvalt5h77q+4A==", + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.13.tgz", + "integrity": "sha512-epkUM9D0Sdmt93/8Ozk43PNjLi36RZzG+d/T1Gdu5AI8jvghonTeLYV69WVWdilvFo+PYxbP0TZ0saMvr6nscQ==", "requires": { "cluster-key-slot": "1.1.2", "generic-pool": "3.9.0", @@ -13268,9 +13724,9 @@ "dev": true }, "@types/luxon": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.7.tgz", - "integrity": "sha512-gKc9P2d4g5uYwmy4s/MO/yOVPmvHyvzka1YH6i5dM03UrFofHSmgc0D0ymbDRStFWHusk6cwwF6nhLm/ckBbbQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.0.tgz", + "integrity": "sha512-PEVoA4MOfSsFNaPrZjIUGUZujBDxnO/tj2A2N9KfzlR+pNgpBdDuk0TmRvSMAVUP5q4q8IkMEZ8UOp3MIr+QgA==", "dev": true }, "@types/memory-cache": { @@ -13296,9 +13752,9 @@ "dev": true }, "@types/node": { - "version": "20.10.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", - "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "version": "20.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz", + "integrity": "sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==", "requires": { "undici-types": "~5.26.4" } @@ -13493,9 +13949,9 @@ } }, "@types/validator": { - "version": "13.11.7", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.7.tgz", - "integrity": "sha512-q0JomTsJ2I5Mv7dhHhQLGjMvX0JJm5dyZ1DXQySIUzU1UlwzB8bt+R6+LODUbz0UDIOvEzGc28tk27gBJw2N8Q==", + "version": "13.11.8", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz", + "integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ==", "dev": true }, "@types/yargs": { @@ -13510,16 +13966,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", - "integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.1.tgz", + "integrity": "sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/type-utils": "6.13.2", - "@typescript-eslint/utils": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/type-utils": "6.18.1", + "@typescript-eslint/utils": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -13529,83 +13985,104 @@ } }, "@typescript-eslint/parser": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", - "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.1.tgz", + "integrity": "sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", - "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", + "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2" + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1" } }, "@typescript-eslint/type-utils": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", - "integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz", + "integrity": "sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.13.2", - "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/utils": "6.18.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" } }, "@typescript-eslint/types": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", - "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", + "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", - "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", + "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/visitor-keys": "6.18.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "@typescript-eslint/utils": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", - "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz", + "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/scope-manager": "6.18.1", + "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/typescript-estree": "6.18.1", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", - "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", + "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/types": "6.18.1", "eslint-visitor-keys": "^3.4.1" } }, @@ -13704,23 +14181,60 @@ "version": "3.1.0" }, "applicationinsights": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-2.9.1.tgz", - "integrity": "sha512-hrpe/OvHFZlq+SQERD1fxaYICyunxzEBh9SolJebzYnIXkyA9zxIR87dZAh+F3+weltbqdIP8W038cvtpMNhQg==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-2.9.2.tgz", + "integrity": "sha512-wlDiD7v0BQNM8oNzsf9C836R5ze25u+CuCEZsbA5xMIXYYBxkqkWE/mo9GFJM7rsKaiGqpxEwWmePHKD2Lwy2w==", "requires": { "@azure/core-auth": "^1.5.0", "@azure/core-rest-pipeline": "1.10.1", "@azure/core-util": "1.2.0", "@azure/opentelemetry-instrumentation-azure-sdk": "^1.0.0-beta.5", "@microsoft/applicationinsights-web-snippet": "^1.0.1", - "@opentelemetry/api": "^1.4.1", - "@opentelemetry/core": "^1.15.2", - "@opentelemetry/sdk-trace-base": "^1.15.2", - "@opentelemetry/semantic-conventions": "^1.15.2", + "@opentelemetry/api": "^1.7.0", + "@opentelemetry/core": "^1.19.0", + "@opentelemetry/sdk-trace-base": "^1.19.0", + "@opentelemetry/semantic-conventions": "^1.19.0", "cls-hooked": "^4.2.2", "continuation-local-storage": "^3.2.1", "diagnostic-channel": "1.1.1", +<<<<<<< HEAD "diagnostic-channel-publishers": "1.0.7" +======= + "diagnostic-channel-publishers": "1.0.8" + }, + "dependencies": { + "@azure/core-rest-pipeline": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz", + "integrity": "sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA==", + "requires": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-auth": "^1.4.0", + "@azure/core-tracing": "^1.0.1", + "@azure/core-util": "^1.0.0", + "@azure/logger": "^1.0.0", + "form-data": "^4.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "tslib": "^2.2.0", + "uuid": "^8.3.0" + } + }, + "@azure/core-util": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.2.0.tgz", + "integrity": "sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng==", + "requires": { + "@azure/abort-controller": "^1.0.0", + "tslib": "^2.2.0" + } + }, + "@opentelemetry/api": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.7.0.tgz", + "integrity": "sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw==" + } +>>>>>>> upstream/main } }, "arg": { @@ -13784,11 +14298,11 @@ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" }, "axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", + "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", "requires": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -13883,12 +14397,15 @@ "before-after-hook": { "version": "2.2.2" }, +<<<<<<< HEAD "big-integer": { "version": "1.6.52", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", "dev": true }, +======= +>>>>>>> upstream/main "body-parser": { "version": "1.20.2", "requires": { @@ -13923,15 +14440,6 @@ } } }, - "bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, - "requires": { - "big-integer": "^1.6.44" - } - }, "brace-expansion": { "version": "1.1.11", "requires": { @@ -14009,15 +14517,6 @@ "semver": "^7.0.0" } }, - "bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, - "requires": { - "run-applescript": "^5.0.0" - } - }, "bunyan": { "version": "1.8.15", "requires": { @@ -14429,25 +14928,25 @@ } }, "cspell": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.1.3.tgz", - "integrity": "sha512-SU4Su6002bPoJYaiMeNV4wwLoS8TwaOgIwaTxhys3GDbJIxZV6CrDgwksezHcG7TZrC4yrveDVsdpnrzmQ7T5Q==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.3.2.tgz", + "integrity": "sha512-V8Ub3RO/a5lwSsltW/ib3Z3G/sczKtSpBBN1JChzbSCfEgaY2mJY8JW0BpkSV+Ug6uJitpXNOOaxa3Xr489i7g==", "dev": true, "requires": { - "@cspell/cspell-json-reporter": "8.1.3", - "@cspell/cspell-pipe": "8.1.3", - "@cspell/cspell-types": "8.1.3", - "@cspell/dynamic-import": "8.1.3", + "@cspell/cspell-json-reporter": "8.3.2", + "@cspell/cspell-pipe": "8.3.2", + "@cspell/cspell-types": "8.3.2", + "@cspell/dynamic-import": "8.3.2", "chalk": "^5.3.0", "chalk-template": "^1.1.0", "commander": "^11.1.0", - "cspell-gitignore": "8.1.3", - "cspell-glob": "8.1.3", - "cspell-io": "8.1.3", - "cspell-lib": "8.1.3", + "cspell-gitignore": "8.3.2", + "cspell-glob": "8.3.2", + "cspell-io": "8.3.2", + "cspell-lib": "8.3.2", "fast-glob": "^3.3.2", "fast-json-stable-stringify": "^2.1.0", - "file-entry-cache": "^7.0.2", + "file-entry-cache": "^8.0.0", "get-stdin": "^9.0.0", "semver": "^7.5.4", "strip-ansi": "^7.1.0", @@ -14460,6 +14959,15 @@ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, "chalk": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", @@ -14467,12 +14975,54 @@ "dev": true }, "file-entry-cache": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-7.0.2.tgz", - "integrity": "sha512-TfW7/1iI4Cy7Y8L6iqNdZQVvdXn0f8B4QcIXmkIbtTIe/Okm/nSlHb4IwGzRVOd3WfSieCgvf5cMzEfySAIl0g==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "requires": { + "flat-cache": "^4.0.0" + } + }, + "flat-cache": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.0.tgz", + "integrity": "sha512-EryKbCE/wxpxKniQlyas6PY1I9vwtF3uCBweX+N8KYTCn3Y12RTGtQAJ/bd5pl7kxUAc8v/R3Ake/N17OZiFqA==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.4", + "rimraf": "^5.0.5" + } + }, + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", "dev": true, "requires": { - "flat-cache": "^3.2.0" + "glob": "^10.3.7" } }, "strip-ansi": { @@ -14487,88 +15037,88 @@ } }, "cspell-config-lib": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.1.3.tgz", - "integrity": "sha512-whzJYxcxos3vnywn0alCFZ+Myc0K/C62pUurfOGhgvIba7ArmlXhNRaL2r5noBxWARtpBOtzz3vrzSBK7Lq6jg==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.3.2.tgz", + "integrity": "sha512-Wc98XhBNLwDxnxCzMtgRJALI9a69cu3C5Gf1rGjNTKSFo9JYiQmju0Ur3z25Pkx9Sa86f+2IjvNCf33rUDSoBQ==", "dev": true, "requires": { - "@cspell/cspell-types": "8.1.3", + "@cspell/cspell-types": "8.3.2", "comment-json": "^4.2.3", "yaml": "^2.3.4" } }, "cspell-dictionary": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.1.3.tgz", - "integrity": "sha512-nkRQDPNnA6tw+hJFBqq26M0nK306q5rtyv/AUIWa8ZHhQkwzACnpMSpuJA7/DV5GVvPKltMK5M4A6vgfpoaFHw==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.3.2.tgz", + "integrity": "sha512-xyK95hO2BMPFxIo8zBwGml8035qOxSBdga1BMhwW/p2wDrQP8S4Cdm/54//tCDmKn6uRkFQvyOfWGaX2l8WMEg==", "dev": true, "requires": { - "@cspell/cspell-pipe": "8.1.3", - "@cspell/cspell-types": "8.1.3", - "cspell-trie-lib": "8.1.3", + "@cspell/cspell-pipe": "8.3.2", + "@cspell/cspell-types": "8.3.2", + "cspell-trie-lib": "8.3.2", "fast-equals": "^5.0.1", "gensequence": "^6.0.0" } }, "cspell-gitignore": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.1.3.tgz", - "integrity": "sha512-NHx5lg44eCKb6yJmUPOCz4prcuYowzoo5GJ5hOcCfbk7ZEBWV1E2/kDRuQMOK2W0y1hNGr45CSxO3UxWJlYg7w==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.3.2.tgz", + "integrity": "sha512-3Qc9P5BVvl/cg//s2s+zIMGKcoH5v7oOtRgwn4UQry8yiyo19h0tiTKkSR574FMhF5NtcShTnwIwPSIXVBPFHA==", "dev": true, "requires": { - "cspell-glob": "8.1.3", + "cspell-glob": "8.3.2", "find-up-simple": "^1.0.0" } }, "cspell-glob": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.1.3.tgz", - "integrity": "sha512-Likr7UVUXBpthQnM5r6yao3X0YBNRbJ9AHWXTC2RJfzwZOFKF+pKPfeo3FU+Px8My96M4RC2bVMbrbZUwN5NJw==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.3.2.tgz", + "integrity": "sha512-KtIFxE+3l5dGEofND4/CdZffXP8XN1+XGQKxJ96lIzWsc01mkotfhxTkla6mgvfH039t7BsY/SWv0460KyGslQ==", "dev": true, "requires": { "micromatch": "^4.0.5" } }, "cspell-grammar": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.1.3.tgz", - "integrity": "sha512-dTOwNq6a5wcVzOsi4xY5/tq2r2w/+wLVU+WfyySTsPe66Rjqx/QceFl4OinImks/ZMKF7Zyjd3WGyQ5TcSsJFQ==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.3.2.tgz", + "integrity": "sha512-tYCkOmRzJe1a6/R+8QGSwG7TwTgznLPqsHtepKzLmnS4YX54VXjKRI9zMARxXDzUVfyCSVdW5MyiY/0WTNoy+A==", "dev": true, "requires": { - "@cspell/cspell-pipe": "8.1.3", - "@cspell/cspell-types": "8.1.3" + "@cspell/cspell-pipe": "8.3.2", + "@cspell/cspell-types": "8.3.2" } }, "cspell-io": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.1.3.tgz", - "integrity": "sha512-QkcFeYd79oIl7PgSqFSZyvwXnZQhXmdCI733n54IN2+iXDcf7W0mwptxoC/cE19RkEwAwEFLG81UAy6L/BXI6A==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.3.2.tgz", + "integrity": "sha512-WYpKsyBCQP0SY4gXnhW5fPuxcYchKYKG1PIXVV3ezFU4muSgW6GuLNbGuSfwv/8YNXRgFSN0e3hYH0rdBK2Aow==", "dev": true, "requires": { - "@cspell/cspell-service-bus": "8.1.3" + "@cspell/cspell-service-bus": "8.3.2" } }, "cspell-lib": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.1.3.tgz", - "integrity": "sha512-Kk8bpHVkDZO4MEiPkDvRf/LgJ0h5mufbKLTWModq6k0Ca8EkZ/qgQlZ0ve0rIivbleSqebuWjpJHKDM+IHmzHA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.3.2.tgz", + "integrity": "sha512-wTvdaev/TyGB/ln6CVD1QbVs2D7/+QiajQ67S7yj1suLHM6YcNQQb/5sPAM8VPtj0E7PgwgPXf3bq18OtPvnFg==", "dev": true, "requires": { - "@cspell/cspell-bundled-dicts": "8.1.3", - "@cspell/cspell-pipe": "8.1.3", - "@cspell/cspell-resolver": "8.1.3", - "@cspell/cspell-types": "8.1.3", - "@cspell/dynamic-import": "8.1.3", - "@cspell/strong-weak-map": "8.1.3", + "@cspell/cspell-bundled-dicts": "8.3.2", + "@cspell/cspell-pipe": "8.3.2", + "@cspell/cspell-resolver": "8.3.2", + "@cspell/cspell-types": "8.3.2", + "@cspell/dynamic-import": "8.3.2", + "@cspell/strong-weak-map": "8.3.2", "clear-module": "^4.1.2", "comment-json": "^4.2.3", "configstore": "^6.0.0", - "cspell-config-lib": "8.1.3", - "cspell-dictionary": "8.1.3", - "cspell-glob": "8.1.3", - "cspell-grammar": "8.1.3", - "cspell-io": "8.1.3", - "cspell-trie-lib": "8.1.3", + "cspell-config-lib": "8.3.2", + "cspell-dictionary": "8.3.2", + "cspell-glob": "8.3.2", + "cspell-grammar": "8.3.2", + "cspell-io": "8.3.2", + "cspell-trie-lib": "8.3.2", "fast-equals": "^5.0.1", "gensequence": "^6.0.0", "import-fresh": "^3.3.0", @@ -14578,13 +15128,13 @@ } }, "cspell-trie-lib": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.1.3.tgz", - "integrity": "sha512-EDSYU9MCtzPSJDrfvDrTKmc0rzl50Ehjg1c5rUCqn33p2LCRe/G8hW0FxXe0mxrZxrMO2b8l0PVSGlrCXCQ8RQ==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.3.2.tgz", + "integrity": "sha512-8qh2FqzkLMwzlTlvO/5Z+89fhi30rrfekocpight/BmqKbE2XFJQD7wS2ml24e7q/rdHJLXVpJbY/V5mByucCA==", "dev": true, "requires": { - "@cspell/cspell-pipe": "8.1.3", - "@cspell/cspell-types": "8.1.3", + "@cspell/cspell-pipe": "8.3.2", + "@cspell/cspell-types": "8.3.2", "gensequence": "^6.0.0" } }, @@ -14613,6 +15163,7 @@ "deepmerge": { "version": "4.3.1" }, +<<<<<<< HEAD "default-browser": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", @@ -14702,6 +15253,8 @@ "untildify": "^4.0.0" } }, +======= +>>>>>>> upstream/main "define-data-property": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", @@ -14742,9 +15295,9 @@ } }, "diagnostic-channel-publishers": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.7.tgz", - "integrity": "sha512-SEECbY5AiVt6DfLkhkaHNeshg1CogdLLANA8xlG/TKvS+XUgvIKl7VspJGYiEdL5OUyzMVnr7o0AwB7f+/Mjtg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.8.tgz", + "integrity": "sha512-HmSm9hXxSPxA9BaLGY98QU1zsdjeCk113KjAYGPCen1ZP6mhVaTPzHd6UYv5r21DnWANi+f+NyPOHruGT9jpqQ==", "requires": {} }, "diff": { @@ -14800,6 +15353,12 @@ "nan": "^2.14.0" } }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "ecdsa-sig-formatter": { "version": "1.0.11", "requires": { @@ -14835,9 +15394,9 @@ "version": "1.0.2" }, "entities": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", - "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true }, "error-ex": { @@ -14861,15 +15420,15 @@ "dev": true }, "eslint": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", - "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.55.0", + "@eslint/js": "8.56.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -14932,15 +15491,16 @@ } }, "eslint-plugin-n": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.3.1.tgz", - "integrity": "sha512-w46eDIkxQ2FaTHcey7G40eD+FhTXOdKudDXPUO2n9WNcslze/i/HT2qJ3GXjHngYSGDISIgPNhwGtgoix4zeOw==", + "version": "16.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.6.2.tgz", + "integrity": "sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "builtins": "^5.0.1", - "eslint-plugin-es-x": "^7.1.0", + "eslint-plugin-es-x": "^7.5.0", "get-tsconfig": "^4.7.0", + "globals": "^13.24.0", "ignore": "^5.2.4", "is-builtin-module": "^3.2.1", "is-core-module": "^2.12.1", @@ -14950,13 +15510,13 @@ } }, "eslint-plugin-prettier": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz", - "integrity": "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.5" + "synckit": "^0.8.6" } }, "eslint-scope": { @@ -15334,7 +15894,13 @@ "dev": true }, "follow-redirects": { +<<<<<<< HEAD "version": "1.15.2" +======= + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", + "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==" +>>>>>>> upstream/main }, "for-each": { "version": "0.3.3", @@ -15344,6 +15910,24 @@ "is-callable": "^1.1.3" } }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + } + } + }, "form-data": { "version": "4.0.0", "requires": { @@ -15758,23 +16342,6 @@ "is-extglob": "^2.1.1" } }, - "is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "requires": { - "is-docker": "^3.0.0" - }, - "dependencies": { - "is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true - } - } - }, "is-number": { "version": "7.0.0", "dev": true @@ -15882,6 +16449,16 @@ "istanbul-lib-report": "^3.0.0" } }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, "jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -16543,12 +17120,12 @@ "dev": true }, "linkify-it": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", - "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dev": true, "requires": { - "uc.micro": "^1.0.1" + "uc.micro": "^2.0.0" } }, "lint-staged": { @@ -16856,36 +17433,37 @@ } }, "markdown-it": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.2.tgz", - "integrity": "sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.0.0.tgz", + "integrity": "sha512-seFjF0FIcPt4P9U39Bq1JYblX0KZCjDLFFQPHpL5AzHpqPEKtosxmdq/LTVZnjfH7tjt9BxStm+wXcDBNuYmzw==", "dev": true, "requires": { "argparse": "^2.0.1", - "entities": "~3.0.1", - "linkify-it": "^4.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.0.0" } }, "markdownlint": { - "version": "0.32.1", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.32.1.tgz", - "integrity": "sha512-3sx9xpi4xlHlokGyHO9k0g3gJbNY4DI6oNEeEYq5gQ4W7UkiJ90VDAnuDl2U+yyXOUa6BX+0gf69ZlTUGIBp6A==", + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.33.0.tgz", + "integrity": "sha512-4lbtT14A3m0LPX1WS/3d1m7Blg+ZwiLq36WvjQqFGsX3Gik99NV+VXp/PW3n+Q62xyPdbvGOCfjPqjW+/SKMig==", "dev": true, "requires": { - "markdown-it": "13.0.2", - "markdownlint-micromark": "0.1.7" + "markdown-it": "14.0.0", + "markdownlint-micromark": "0.1.8" } }, "markdownlint-cli2": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.11.0.tgz", - "integrity": "sha512-RmFpr+My5in8KT+H/A6ozKIVYVzZtL5t9c8DYdv0YJdljl385z44CcCVBrclpHxCGMY2tr0hZ/ca+meGGvgdnQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.12.0.tgz", + "integrity": "sha512-5nddNaPY1WC7BE1mkF8fiEkRDW8XbODwqYBPL3eyvFh7tLk74no+P8JRbCjghF7ozahCW5pF0TZ3ZS30m9H1Eg==", "dev": true, "requires": { "globby": "14.0.0", - "markdownlint": "0.32.1", + "markdownlint": "0.33.0", "markdownlint-cli2-formatter-default": "0.0.4", "micromatch": "4.0.5", "strip-json-comments": "5.0.1", @@ -16932,15 +17510,15 @@ "requires": {} }, "markdownlint-micromark": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.7.tgz", - "integrity": "sha512-BbRPTC72fl5vlSKv37v/xIENSRDYL/7X/XoFzZ740FGEbs9vZerLrIkFRY0rv7slQKxDczToYuMmqQFN61fi4Q==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.8.tgz", + "integrity": "sha512-1ouYkMRo9/6gou9gObuMDnvZM8jC/ly3QCFQyoSPCS2XV1ZClU0xpKbL1Ar3bWWRT1RnBZkWUEiNKrI2CwiBQA==", "dev": true }, "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", "dev": true }, "media-typer": { @@ -17000,6 +17578,12 @@ "minimist": { "version": "1.2.6" }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + }, "mkdirp": { "version": "1.0.4", "dev": true @@ -17010,7 +17594,13 @@ "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" }, "moment": { +<<<<<<< HEAD "version": "2.29.4" +======= + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" +>>>>>>> upstream/main }, "morgan": { "version": "1.10.0", @@ -17144,9 +17734,9 @@ "dev": true }, "nodemailer": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz", - "integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw==" + "version": "6.9.8", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.8.tgz", + "integrity": "sha512-cfrYUk16e67Ks051i4CntM9kshRYei1/o/Gi8K1d+R34OIs21xdFnW7Pt7EucmVKA0LKtqUGNcjMZ7ehjl49mQ==" }, "normalize-path": { "version": "3.0.0", @@ -17364,6 +17954,24 @@ "path-parse": { "version": "1.0.7" }, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "dev": true + } + } + }, "path-to-regexp": { "version": "0.1.7" }, @@ -17525,9 +18133,9 @@ "dev": true }, "prettier": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", - "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", "dev": true }, "prettier-linter-helpers": { @@ -17685,6 +18293,12 @@ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true }, + "punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true + }, "pure-rand": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", @@ -17727,12 +18341,12 @@ } }, "redis": { - "version": "4.6.11", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.11.tgz", - "integrity": "sha512-kg1Lt4NZLYkAjPOj/WcyIGWfZfnyfKo1Wg9YKVSlzhFwxpFIl3LYI8BWy1Ab963LLDsTz2+OwdsesHKljB3WMQ==", + "version": "4.6.12", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.12.tgz", + "integrity": "sha512-41Xuuko6P4uH4VPe5nE3BqXHB7a9lkFL0J29AlxKaIfD6eWO8VO/5PDF9ad2oS+mswMsfFxaM5DlE3tnXT+P8Q==", "requires": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.12", + "@redis/client": "1.5.13", "@redis/graph": "1.1.1", "@redis/json": "1.0.6", "@redis/search": "1.1.6", @@ -17848,15 +18462,6 @@ "glob": "^7.1.3" } }, - "run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, - "requires": { - "execa": "^5.0.0" - } - }, "run-parallel": { "version": "1.2.0", "dev": true, @@ -18122,6 +18727,31 @@ } } }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + } + } + }, "strip-ansi": { "version": "6.0.1", "dev": true, @@ -18129,6 +18759,15 @@ "ansi-regex": "^5.0.1" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, "strip-bom": { "version": "4.0.0" }, @@ -18155,12 +18794,21 @@ "version": "1.0.0" }, "synckit": { +<<<<<<< HEAD "version": "0.8.6", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.6.tgz", "integrity": "sha512-laHF2savN6sMeHCjLRkheIU4wo3Zg9Ln5YOjOo7sZ5dVQW8yF5pPE5SIw1dsPhq3TRp1jisKRCdPhfs/1WMqDA==", "dev": true, "requires": { "@pkgr/utils": "^2.4.2", +======= + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "requires": { + "@pkgr/core": "^0.1.0", +>>>>>>> upstream/main "tslib": "^2.6.2" } }, @@ -18180,12 +18828,6 @@ "throat": { "version": "6.0.2" }, - "titleize": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", - "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", - "dev": true - }, "tmp": { "version": "0.2.1", "requires": { @@ -18256,7 +18898,13 @@ } }, "ts-node": { +<<<<<<< HEAD "version": "10.9.1", +======= + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", +>>>>>>> upstream/main "dev": true, "requires": { "@cspotcode/source-map-support": "^0.8.0", @@ -18359,9 +19007,9 @@ "dev": true }, "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.0.0.tgz", + "integrity": "sha512-DffL94LsNOccVn4hyfRe5rdKa273swqeA5DJpMOeFmEn1wCDc7nAbbB0gXlgBCL7TNzeTv6G7XVWzan7iJtfig==", "dev": true }, "uid-safe": { @@ -18394,10 +19042,16 @@ } }, "universal-github-app-jwt": { +<<<<<<< HEAD "version": "1.1.1", +======= + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-1.1.2.tgz", + "integrity": "sha512-t1iB2FmLFE+yyJY9+3wMx0ejB+MQpEVkH0gQv7dR6FZyltyq+ZZO0uDpbopxhrZ3SLEO4dCEkIujOMldEQ2iOA==", +>>>>>>> upstream/main "requires": { "@types/jsonwebtoken": "^9.0.0", - "jsonwebtoken": "^9.0.0" + "jsonwebtoken": "^9.0.2" } }, "universal-user-agent": { @@ -18406,12 +19060,6 @@ "unpipe": { "version": "1.0.0" }, - "untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true - }, "update-browserslist-db": { "version": "1.0.11", "dev": true, @@ -18562,6 +19210,42 @@ } } }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, "wrappy": { "version": "1.0.2" }, diff --git a/package.json b/package.json index c35492f1d..1b2d5c589 100644 --- a/package.json +++ b/package.json @@ -21,19 +21,19 @@ "find-deadcode": "ts-prune", "find-circular-dependencies": "npx madge --circular --extensions ts .", "fix:js": "eslint --fix .", - "fix:md": "markdownlint-cli2-fix \"**/*.md\"", + "fix:md": "markdownlint-cli2 --config ./.config/.markdownlint-cli2.jsonc --fix \"**/*.md\"", "fix": "npm run fix:js && npm run fix:md", "lint:js": "eslint .", "lint:json": "echo OK", - "lint:md": "markdownlint-cli2 \"**/*.md\"", - "lint:spell": "cspell --no-progress \"**\"", + "lint:md": "markdownlint-cli2 --config ./.config/.markdownlint-cli2.jsonc \"**/*.md\"", + "lint:spell": "cspell --config ./.cspell.json --no-progress \"**\"", "lint": "npm run lint:json && npm run lint:js && npm run lint:md && npm run lint:spell", "prepare": "husky install || echo No Husky.", "start-4000": "PORT=4000 DEBUG=startup node ./dist/bin/www", "start-in-container": "node ./bin/www", "start": "node ./dist/bin/www", - "test:ci": "jest --watchAll=false --reporters=default --reporters=jest-junit", - "test": "jest" + "test:ci": "jest --config ./test/jest.config.ts --watchAll=false --reporters=default --reporters=jest-junit", + "test": "jest --config ./test/jest.config.ts" }, "lint-staged": { "*": [ @@ -41,7 +41,7 @@ "cspell --no-must-find-files" ], "*.{js,ts}": "eslint --fix", - "*.md": "markdownlint-cli2-fix" + "*.md": "markdownlint-cli2 --fix --config ./.config/.markdownlint-cli2.jsonc" }, "jest-junit": { "suiteNameTemplate": "{filepath}", @@ -74,13 +74,13 @@ "@azure/storage-queue": "12.16.0", "@octokit/plugin-paginate-graphql": "4.0.0", "@octokit/request": "8.1.6", - "@octokit/auth-app": "6.0.1", + "@octokit/auth-app": "6.0.3", "@octokit/rest": "20.0.2", "@primer/octicons": "19.8.0", "app-root-path": "3.1.0", - "applicationinsights": "2.9.1", + "applicationinsights": "2.9.2", "async-prompt": "1.0.1", - "axios": "1.6.2", + "axios": "1.6.5", "basic-auth": "2.0.1", "body-parser": "1.20.2", "color-contrast-checker": "2.1.0", @@ -106,10 +106,10 @@ "lodash": "4.17.21", "luxon": "3.4.4", "memory-cache": "0.2.0", - "moment": "2.29.4", + "moment": "2.30.1", "morgan": "1.10.0", "node-jose": "2.2.0", - "nodemailer": "6.9.7", + "nodemailer": "6.9.8", "object-path": "0.11.8", "passport": "0.7.0", "passport-azure-ad": "4.3.5", @@ -119,7 +119,7 @@ "pug": "3.0.2", "pug-load": "3.0.0", "recursive-readdir": "2.2.3", - "redis": "4.6.11", + "redis": "4.6.12", "secure-compare": "3.0.1", "semver": "7.5.4", "serve-favicon": "2.5.0", @@ -136,10 +136,10 @@ "@types/express-session": "1.17.10", "@types/jest": "29.5.11", "@types/lodash": "4.14.202", - "@types/luxon": "3.3.7", + "@types/luxon": "3.4.0", "@types/memory-cache": "0.2.5", "@types/morgan": "1.9.9", - "@types/node": "20.10.4", + "@types/node": "20.11.0", "@types/node-jose": "1.1.13", "@types/object-path": "0.11.4", "@types/passport": "1.0.16", @@ -150,22 +150,22 @@ "@types/recursive-readdir": "2.2.4", "@types/semver": "7.5.6", "@types/simple-oauth2": "5.0.7", - "@types/validator": "13.11.7", - "@typescript-eslint/eslint-plugin": "6.13.2", - "@typescript-eslint/parser": "6.13.2", - "cspell": "8.1.3", - "eslint": "8.55.0", + "@types/validator": "13.11.8", + "@typescript-eslint/eslint-plugin": "6.18.1", + "@typescript-eslint/parser": "6.18.1", + "cspell": "8.3.2", + "eslint": "8.56.0", "eslint-config-prettier": "9.1.0", - "eslint-plugin-n": "16.3.1", - "eslint-plugin-prettier": "5.0.1", + "eslint-plugin-n": "16.6.2", + "eslint-plugin-prettier": "5.1.3", "husky": "8.0.3", "jest": "29.7.0", "jest-junit": "16.0.0", "lint-staged": "15.2.0", - "markdownlint-cli2": "0.11.0", - "prettier": "3.1.0", + "markdownlint-cli2": "0.12.0", + "prettier": "3.1.1", "ts-jest": "29.1.1", - "ts-node": "10.9.1", + "ts-node": "10.9.2", "ts-prune": "0.10.3", "typescript": "5.3.3" }, diff --git a/routes/administration/app.ts b/routes/administration/app.ts index 846777056..b5add5da4 100644 --- a/routes/administration/app.ts +++ b/routes/administration/app.ts @@ -7,12 +7,12 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import { OrganizationSetting, IBasicGitHubAppInstallation, SystemTeam, -} from '../../entities/organizationSettings/organizationSetting'; +} from '../../business/entities/organizationSettings/organizationSetting'; import { IndividualContext } from '../../business/user'; import { Operations, Organization } from '../../business'; import GitHubApplication, { isInstallationConfigured } from '../../business/application'; diff --git a/routes/administration/apps.ts b/routes/administration/apps.ts index fde8a42e7..8221d430d 100644 --- a/routes/administration/apps.ts +++ b/routes/administration/apps.ts @@ -7,8 +7,8 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { getProviders } from '../../transitional'; -import { sortByCaseInsensitive } from '../../utils'; +import { getProviders } from '../../lib/transitional'; +import { sortByCaseInsensitive } from '../../lib/utils'; import GitHubApplication from '../../business/application'; import { ReposAppRequest, UserAlertType } from '../../interfaces'; import { diff --git a/routes/administration/index.ts b/routes/administration/index.ts index 79ccf9572..605915110 100644 --- a/routes/administration/index.ts +++ b/routes/administration/index.ts @@ -8,7 +8,7 @@ import asyncHandler from 'express-async-handler'; const router: Router = Router(); import { ReposAppRequest } from '../../interfaces'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import getCompanySpecificDeployment from '../../middleware/companySpecificDeployment'; diff --git a/routes/diagnostics.ts b/routes/diagnostics.ts index 4d6072360..b3e09342b 100644 --- a/routes/diagnostics.ts +++ b/routes/diagnostics.ts @@ -8,7 +8,7 @@ import asyncHandler from 'express-async-handler'; const router: Router = Router(); import { IAppSession, ReposAppRequest } from '../interfaces'; -import { CreateError, getProviders } from '../transitional'; +import { CreateError, getProviders } from '../lib/transitional'; const redacted = '*****'; diff --git a/routes/explore.ts b/routes/explore.ts index 2b29f5dea..efeee696f 100644 --- a/routes/explore.ts +++ b/routes/explore.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; const router: Router = Router(); import { ReposAppRequest } from '../interfaces'; -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; router.get('/', (req: ReposAppRequest, res) => { const config = getProviders(req).config; diff --git a/routes/index-authenticated.ts b/routes/index-authenticated.ts index 01df492c7..a5ee54b79 100644 --- a/routes/index-authenticated.ts +++ b/routes/index-authenticated.ts @@ -9,7 +9,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { hasStaticReactClientApp, getProviders } from '../transitional'; +import { hasStaticReactClientApp, getProviders } from '../lib/transitional'; import { Organization } from '../business/organization'; diff --git a/routes/index-linked.ts b/routes/index-linked.ts index c70002cb6..5c064e058 100644 --- a/routes/index-linked.ts +++ b/routes/index-linked.ts @@ -7,9 +7,9 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { CreateError, hasStaticReactClientApp, getProviders } from '../transitional'; +import { CreateError, hasStaticReactClientApp, getProviders } from '../lib/transitional'; import { IndividualContext } from '../business/user'; -import { storeOriginalUrlAsVariable } from '../utils'; +import { storeOriginalUrlAsVariable } from '../lib/utils'; import { AuthorizeOnlyCorporateAdministrators } from '../middleware/business/corporateAdministrators'; import RouteAdministration from './administration'; diff --git a/routes/index.ts b/routes/index.ts index eb122d2a3..16cc579aa 100644 --- a/routes/index.ts +++ b/routes/index.ts @@ -16,7 +16,7 @@ import ExploreRoute from './explore'; import ApprovalsRoute from './approvals'; import AuthenticatedRoute from './index-authenticated'; -import { hasStaticReactClientApp } from '../transitional'; +import { hasStaticReactClientApp } from '../lib/transitional'; import { injectReactClient } from '../middleware'; router.use('/api/client', clientApiRoute); diff --git a/routes/link.ts b/routes/link.ts index 7a3535aec..eab59a277 100644 --- a/routes/link.ts +++ b/routes/link.ts @@ -14,9 +14,9 @@ import { ICorporateLink, LinkOperationSource, } from '../interfaces'; -import { getProviders, splitSemiColonCommas } from '../transitional'; +import { getProviders, splitSemiColonCommas } from '../lib/transitional'; import { IndividualContext } from '../business/user'; -import { isCodespacesAuthenticating, storeOriginalUrlAsReferrer, wrapError } from '../utils'; +import { isCodespacesAuthenticating, storeOriginalUrlAsReferrer, wrapError } from '../lib/utils'; import validator from 'validator'; diff --git a/routes/org/2fa.ts b/routes/org/2fa.ts index 230a31087..b4b1b8ac9 100644 --- a/routes/org/2fa.ts +++ b/routes/org/2fa.ts @@ -10,7 +10,7 @@ const router: Router = Router(); import moment from 'moment'; import { NoCacheNoBackground, ReposAppRequest } from '../../interfaces'; -import { wrapError } from '../../utils'; +import { wrapError } from '../../lib/utils'; router.get( '/', diff --git a/routes/org/index.ts b/routes/org/index.ts index 237b5e95b..94bf433c4 100644 --- a/routes/org/index.ts +++ b/routes/org/index.ts @@ -6,9 +6,14 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); +<<<<<<< HEAD import { getProviders } from '../../transitional'; +======= + +import { getProviders } from '../../lib/transitional'; +>>>>>>> upstream/main import { IAggregateUserSummary } from '../../business/user/aggregate'; -import { TeamJoinApprovalEntity } from '../../entities/teamJoinApproval/teamJoinApproval'; +import { TeamJoinApprovalEntity } from '../../business/entities/teamJoinApproval/teamJoinApproval'; import { Team } from '../../business'; import { ReposAppRequest, OrganizationMembershipState } from '../../interfaces'; import { diff --git a/routes/org/join.ts b/routes/org/join.ts index caa17a938..b18f40eb1 100644 --- a/routes/org/join.ts +++ b/routes/org/join.ts @@ -10,9 +10,14 @@ import asyncHandler from 'express-async-handler'; const router: Router = Router(); import querystring from 'querystring'; +<<<<<<< HEAD import { CreateError, getProviders } from '../../transitional'; +======= + +import { CreateError, getProviders } from '../../lib/transitional'; +>>>>>>> upstream/main import { IndividualContext } from '../../business/user'; -import { sleep, storeOriginalUrlAsReferrer, wrapError } from '../../utils'; +import { sleep, storeOriginalUrlAsReferrer, wrapError } from '../../lib/utils'; import RequireActiveGitHubSession from '../../middleware/github/requireActiveSession'; import { jsonError } from '../../middleware/jsonError'; import { Organization, Team } from '../../business'; diff --git a/routes/org/leave.ts b/routes/org/leave.ts index d38c394fd..60b3b654f 100644 --- a/routes/org/leave.ts +++ b/routes/org/leave.ts @@ -7,8 +7,8 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { getProviders } from '../../transitional'; -import { wrapError } from '../../utils'; +import { getProviders } from '../../lib/transitional'; +import { wrapError } from '../../lib/utils'; import { Organization } from '../../business'; import { OrganizationMembershipState, ReposAppRequest, UserAlertType } from '../../interfaces'; diff --git a/routes/org/membership.ts b/routes/org/membership.ts index 83003c8e6..1ab72ab62 100644 --- a/routes/org/membership.ts +++ b/routes/org/membership.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; import { ReposAppRequest, UserAlertType } from '../../interfaces'; -import { wrapError } from '../../utils'; +import { wrapError } from '../../lib/utils'; import RequireActiveGitHubSession from '../../middleware/github/requireActiveSession'; const router: Router = Router(); diff --git a/routes/org/newRepoSpa.ts b/routes/org/newRepoSpa.ts index a2047d54a..715c45aa5 100644 --- a/routes/org/newRepoSpa.ts +++ b/routes/org/newRepoSpa.ts @@ -8,9 +8,9 @@ import asyncHandler from 'express-async-handler'; const router: Router = Router(); import { getRepositoryMetadataProvider, ReposAppRequest } from '../../interfaces'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import { Organization } from '../../business/organization'; -import NewRepositoryLockdownSystem from '../../features/newRepositories/newRepositoryLockdown'; +import NewRepositoryLockdownSystem from '../../business/features/newRepositories/newRepositoryLockdown'; router.get( '/', diff --git a/routes/org/profileReview.ts b/routes/org/profileReview.ts index b0cde768c..ab65d191f 100644 --- a/routes/org/profileReview.ts +++ b/routes/org/profileReview.ts @@ -8,7 +8,7 @@ const router: Router = Router(); import asyncHandler from 'express-async-handler'; import { ReposAppRequest } from '../../interfaces'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; interface IUserProfileWarnings { company?: string; diff --git a/routes/org/repoAdministrativeLock.ts b/routes/org/repoAdministrativeLock.ts index 3a7edc74b..a0dcd5d5e 100644 --- a/routes/org/repoAdministrativeLock.ts +++ b/routes/org/repoAdministrativeLock.ts @@ -7,11 +7,11 @@ import asyncHandler from 'express-async-handler'; import { NextFunction, Response, Router } from 'express'; const router: Router = Router(); -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import { Repository } from '../../business/repository'; -import { RepositoryMetadataEntity } from '../../entities/repositoryMetadata/repositoryMetadata'; +import { RepositoryMetadataEntity } from '../../business/entities/repositoryMetadata/repositoryMetadata'; import { Organization } from '../../business/organization'; -import NewRepositoryLockdownSystem from '../../features/newRepositories/newRepositoryLockdown'; +import NewRepositoryLockdownSystem from '../../business/features/newRepositories/newRepositoryLockdown'; import { getRepositoryMetadataProvider, ReposAppRequest, UserAlertType } from '../../interfaces'; router.use( @@ -53,7 +53,7 @@ router.post( '/', asyncHandler(async (req: ReposAppRequest, res: Response, next: NextFunction) => { const providers = getProviders(req); - const operations = providers.operations; + const { insights, operations } = providers; const repository = req['repository'] as Repository; const entity = repository.getEntity(); if (!entity.parent) { @@ -68,6 +68,7 @@ router.post( const repositoryMetadataProvider = getRepositoryMetadataProvider(operations); const organization = repository.organization; const lockdownSystem = new NewRepositoryLockdownSystem({ + insights, operations, organization, repository, diff --git a/routes/org/repoWorkflowEngine.ts b/routes/org/repoWorkflowEngine.ts index 9f23594fa..4a79b069d 100644 --- a/routes/org/repoWorkflowEngine.ts +++ b/routes/org/repoWorkflowEngine.ts @@ -8,9 +8,9 @@ import fs from 'fs'; import path from 'path'; import recursiveReadDirectory from 'recursive-readdir'; -import { wrapError, sleep } from '../../utils'; +import { wrapError, sleep } from '../../lib/utils'; import { Organization } from '../../business'; -import { RepositoryMetadataEntity } from '../../entities/repositoryMetadata/repositoryMetadata'; +import { RepositoryMetadataEntity } from '../../business/entities/repositoryMetadata/repositoryMetadata'; import { Repository } from '../../business'; import { CreateRepositoryEntrypoint, ICreateRepositoryApiResult } from '../../api/createRepo'; import { @@ -24,11 +24,11 @@ import { IReposAppWithTeam, throwIfNotCapable, } from '../../interfaces'; -import { ErrorHelper } from '../../transitional'; +import { ErrorHelper } from '../../lib/transitional'; import { setupRepositoryReadmeSubstring, setupRepositorySubstring, -} from '../../features/newRepositories/strings'; +} from '../../business/features/newRepositories/strings'; export interface IApprovalPackage { id: string; diff --git a/routes/org/repos.ts b/routes/org/repos.ts index b69b9d553..c3560ffff 100644 --- a/routes/org/repos.ts +++ b/routes/org/repos.ts @@ -13,13 +13,13 @@ import moment from 'moment'; import lowercaser from '../../middleware/lowercaser'; import routeAdministrativeLock from './repoAdministrativeLock'; -import NewRepositoryLockdownSystem from '../../features/newRepositories/newRepositoryLockdown'; +import NewRepositoryLockdownSystem from '../../business/features/newRepositories/newRepositoryLockdown'; import { IGraphEntry } from '../../lib/graphProvider'; import { IMail } from '../../lib/mailProvider'; import { IndividualContext } from '../../business/user'; import { Repository, Collaborator, TeamPermission, Organization, OrganizationMember } from '../../business'; -import { RepositoryMetadataEntity } from '../../entities/repositoryMetadata/repositoryMetadata'; +import { RepositoryMetadataEntity } from '../../business/entities/repositoryMetadata/repositoryMetadata'; import { ReposAppRequest, GitHubCollaboratorAffiliationQuery, @@ -35,7 +35,7 @@ import { getContextualRepositoryPermissions, IContextualRepositoryPermissions, } from '../../middleware/github/repoPermissions'; -import { getProviders, CreateError, ErrorHelper } from '../../transitional'; +import { getProviders, CreateError, ErrorHelper } from '../../lib/transitional'; import RouteReposPager from '../reposPager'; @@ -221,10 +221,11 @@ router.post( asyncHandler(async function (req: ILocalRequest, res: Response, next: NextFunction) { // NOTE: this code is also duplicated for now in the client/internal/* folder // CONSIDER: de-duplicate - const { operations } = getProviders(req); + const { insights, operations } = getProviders(req); const { organization, repository } = req; const repositoryMetadataProvider = getRepositoryMetadataProvider(operations); const lockdownSystem = new NewRepositoryLockdownSystem({ + insights, operations, organization, repository, diff --git a/routes/org/team/approval/index.ts b/routes/org/team/approval/index.ts index b7bc3d285..33e06c147 100644 --- a/routes/org/team/approval/index.ts +++ b/routes/org/team/approval/index.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { ErrorHelper, getProviders } from '../../../../transitional'; +import { ErrorHelper, getProviders } from '../../../../lib/transitional'; import { Team } from '../../../../business'; import { PermissionWorkflowEngine } from '../approvals'; import RenderHtmlMail from '../../../../lib/emailRender'; diff --git a/routes/org/team/approvals.ts b/routes/org/team/approvals.ts index 184b3ad36..7420ee162 100644 --- a/routes/org/team/approvals.ts +++ b/routes/org/team/approvals.ts @@ -9,10 +9,10 @@ const router: Router = Router(); import RouteApproval from './approval'; -import { getProviders } from '../../../transitional'; -import { wrapError } from '../../../utils'; +import { getProviders } from '../../../lib/transitional'; +import { wrapError } from '../../../lib/utils'; import { Team } from '../../../business'; -import { TeamJoinApprovalEntity } from '../../../entities/teamJoinApproval/teamJoinApproval'; +import { TeamJoinApprovalEntity } from '../../../business/entities/teamJoinApproval/teamJoinApproval'; import { Account } from '../../../business'; import { ReposAppRequest, IRequestTeams } from '../../../interfaces'; diff --git a/routes/org/team/index-maintainer.ts b/routes/org/team/index-maintainer.ts index 2b0ef2a45..ef935c7c9 100644 --- a/routes/org/team/index-maintainer.ts +++ b/routes/org/team/index-maintainer.ts @@ -6,7 +6,7 @@ import { NextFunction, Response, Router } from 'express'; import { ReposAppRequest } from '../../../interfaces'; -import { wrapError } from '../../../utils'; +import { wrapError } from '../../../lib/utils'; const router: Router = Router(); import RouteApprovals from './approvals'; diff --git a/routes/org/team/index.ts b/routes/org/team/index.ts index 86183f82b..2b9def6f5 100644 --- a/routes/org/team/index.ts +++ b/routes/org/team/index.ts @@ -9,10 +9,10 @@ const router: Router = Router(); import throat from 'throat'; -import { getProviders } from '../../../transitional'; -import { sortRepositoriesByNameCaseInsensitive, wrapError } from '../../../utils'; -import { TeamJoinApprovalEntity } from '../../../entities/teamJoinApproval/teamJoinApproval'; -import SelfServiceTeamMemberToMaintainerUpgrades from '../../../features/teamMemberToMaintainerUpgrade'; +import { getProviders } from '../../../lib/transitional'; +import { sortRepositoriesByNameCaseInsensitive, wrapError } from '../../../lib/utils'; +import { TeamJoinApprovalEntity } from '../../../business/entities/teamJoinApproval/teamJoinApproval'; +import SelfServiceTeamMemberToMaintainerUpgrades from '../../../business/features/teamMemberToMaintainerUpgrade'; import RouteMembers from './members'; import RouteReposPager from '../../reposPager'; import RouteDelete from './delete'; diff --git a/routes/org/team/maintainers.ts b/routes/org/team/maintainers.ts index c52996020..e4a42e22d 100644 --- a/routes/org/team/maintainers.ts +++ b/routes/org/team/maintainers.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { getProviders, validateGitHubLogin } from '../../../transitional'; +import { getProviders, validateGitHubLogin } from '../../../lib/transitional'; import { ReposAppRequest, RequestTeamMemberAddType, diff --git a/routes/org/team/members.ts b/routes/org/team/members.ts index 6268c3647..68339a928 100644 --- a/routes/org/team/members.ts +++ b/routes/org/team/members.ts @@ -9,7 +9,7 @@ const router: Router = Router(); import { Team, TeamMember } from '../../../business'; import { ReposAppRequest, RequestTeamMemberAddType, UserAlertType } from '../../../interfaces'; -import { getProviders, validateGitHubLogin } from '../../../transitional'; +import { getProviders, validateGitHubLogin } from '../../../lib/transitional'; import RoutePeopleSearch from '../../peopleSearch'; import MiddlewareTeamAdminRequired from './teamAdminRequired'; diff --git a/routes/org/team/properties.ts b/routes/org/team/properties.ts index bb7d8686c..63f792b36 100644 --- a/routes/org/team/properties.ts +++ b/routes/org/team/properties.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; const router: Router = Router(); import { ReposAppRequest, UserAlertType } from '../../../interfaces'; -import { wrapError } from '../../../utils'; +import { wrapError } from '../../../lib/utils'; import MiddlewareTeamAdminRequired from './teamAdminRequired'; diff --git a/routes/org/teams.ts b/routes/org/teams.ts index ef1212d09..936e5ae5d 100644 --- a/routes/org/teams.ts +++ b/routes/org/teams.ts @@ -8,7 +8,7 @@ import asyncHandler from 'express-async-handler'; const router: Router = Router(); import { ReposAppRequest } from '../../interfaces'; -import { popSessionVariable } from '../../utils'; +import { popSessionVariable } from '../../lib/utils'; import lowercaser from '../../middleware/lowercaser'; import RouteTeam from './team/'; diff --git a/routes/orgAdmin.ts b/routes/orgAdmin.ts index a8bc2b7bc..9cc992d03 100644 --- a/routes/orgAdmin.ts +++ b/routes/orgAdmin.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; import { requirePortalAdministrationPermission } from '../middleware/business/administration'; import { PostgresLinkProvider } from '../lib/linkProviders/postgres/postgresLinkProvider'; @@ -16,7 +16,7 @@ import { Organization } from '../business'; import { Account } from '../business'; import { ILinkProvider } from '../lib/linkProviders'; import { ICorporateLink, ReposAppRequest, IProviders, UnlinkPurpose } from '../interfaces'; -import { isCodespacesAuthenticating } from '../utils'; +import { isCodespacesAuthenticating } from '../lib/utils'; // - - - Middleware: require that the user isa portal administrator to continue router.use(requirePortalAdministrationPermission); diff --git a/routes/orgs.ts b/routes/orgs.ts index 5d8bfc6fb..08e812639 100644 --- a/routes/orgs.ts +++ b/routes/orgs.ts @@ -11,8 +11,8 @@ const router: Router = Router(); import { IReposRequestWithOrganization } from '../interfaces'; import { injectReactClient, TryFallbackToBlob } from '../middleware'; -import { getProviders, hasStaticReactClientApp } from '../transitional'; -import { wrapError } from '../utils'; +import { getProviders, hasStaticReactClientApp } from '../lib/transitional'; +import { wrapError } from '../lib/utils'; import orgRoute from './org/'; diff --git a/routes/people.ts b/routes/people.ts index 7ca1b99c6..b2592cadb 100644 --- a/routes/people.ts +++ b/routes/people.ts @@ -6,7 +6,7 @@ import { NextFunction, Response, Router } from 'express'; const router: Router = Router(); -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; import { ReposAppRequest } from '../interfaces'; import RoutePeopleSearch from './peopleSearch'; diff --git a/routes/peopleSearch.ts b/routes/peopleSearch.ts index f18016415..023c08b60 100644 --- a/routes/peopleSearch.ts +++ b/routes/peopleSearch.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; import { RequestWithSystemwidePermissions, RequestTeamMemberAddType } from '../interfaces'; import { ensureAllLinksInMemory, getAllLinksFromRequest } from '../middleware/business/allLinks'; diff --git a/routes/placeholders.ts b/routes/placeholders.ts index 4dc23b940..bb566fa43 100644 --- a/routes/placeholders.ts +++ b/routes/placeholders.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; const router: Router = Router(); import { ReposAppRequest } from '../interfaces'; -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; // These are Microsoft-specific, we'll remove these eventually. // TODO: remove from open source version since not helpful having random routes in place diff --git a/routes/reposPager.ts b/routes/reposPager.ts index a44500fb9..74156a51c 100644 --- a/routes/reposPager.ts +++ b/routes/reposPager.ts @@ -7,7 +7,7 @@ import asyncHandler from 'express-async-handler'; import { NextFunction, Response } from 'express'; import _ from 'lodash'; -import { daysInMilliseconds } from '../utils'; +import { daysInMilliseconds } from '../lib/utils'; import { Repository, IPersonalizedUserAggregateRepositoryPermission, @@ -20,7 +20,7 @@ import { import QueryCache from '../business/queryCache'; import { GitHubRepositoryType, IReposAppWithTeam } from '../interfaces'; import { IRequestTeamPermissions } from '../middleware/github/teamPermissions'; -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; import { UserContext } from '../business/user/aggregate'; interface IGetReposAndOptionalTeamPermissionsResponse { diff --git a/routes/settings/approvals.ts b/routes/settings/approvals.ts index 6dfd2a2e7..e71c73bbc 100644 --- a/routes/settings/approvals.ts +++ b/routes/settings/approvals.ts @@ -7,15 +7,15 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { IApprovalProvider } from '../../entities/teamJoinApproval/approvalProvider'; -import { TeamJoinApprovalEntity } from '../../entities/teamJoinApproval/teamJoinApproval'; -import { safeLocalRedirectUrl } from '../../utils'; +import { IApprovalProvider } from '../../business/entities/teamJoinApproval/approvalProvider'; +import { TeamJoinApprovalEntity } from '../../business/entities/teamJoinApproval/teamJoinApproval'; +import { safeLocalRedirectUrl } from '../../lib/utils'; import { Operations } from '../../business'; import { Team } from '../../business'; import { Organization } from '../../business'; import { IAggregateUserTeams } from '../../business/user/aggregate'; import { ReposAppRequest, IReposError, UserAlertType } from '../../interfaces'; -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; export interface ApprovalPair { team: Team; diff --git a/routes/settings/authorizations.ts b/routes/settings/authorizations.ts index 74cce7977..17aae9bec 100644 --- a/routes/settings/authorizations.ts +++ b/routes/settings/authorizations.ts @@ -7,7 +7,7 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { getProviders } from '../../transitional'; +import { getProviders } from '../../lib/transitional'; import { Operations } from '../../business'; import { ReposAppRequest, ICorporateLink } from '../../interfaces'; diff --git a/routes/settings/campaigns.ts b/routes/settings/campaigns.ts index 116bd0920..f2c8cb7aa 100644 --- a/routes/settings/campaigns.ts +++ b/routes/settings/campaigns.ts @@ -8,7 +8,7 @@ import asyncHandler from 'express-async-handler'; const router: Router = Router(); import { ReposAppRequest, UserAlertType } from '../../interfaces'; -import { CreateError, getProviders } from '../../transitional'; +import { CreateError, getProviders } from '../../lib/transitional'; router.use('/:campaignGroupId', (req: ReposAppRequest, res: any, next) => { const { config } = getProviders(req); diff --git a/routes/settings/contributionData.ts b/routes/settings/contributionData.ts index a401ee71a..c68fc70b4 100644 --- a/routes/settings/contributionData.ts +++ b/routes/settings/contributionData.ts @@ -7,8 +7,8 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { ErrorHelper, getProviders } from '../../transitional'; -import { UserSettings } from '../../entities/userSettings'; +import { ErrorHelper, getProviders } from '../../lib/transitional'; +import { UserSettings } from '../../business/entities/userSettings'; import { UserAlertType } from '../../interfaces'; import type { ReposAppRequestWithUserSettings } from '../../interfaces/middleware'; import { getUserSettings } from '../../middleware/business/userSettings'; diff --git a/routes/settings/personalAccessTokens.ts b/routes/settings/personalAccessTokens.ts index eac9a8b54..303345a1a 100644 --- a/routes/settings/personalAccessTokens.ts +++ b/routes/settings/personalAccessTokens.ts @@ -7,8 +7,8 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { getProviders } from '../../transitional'; -import { PersonalAccessToken } from '../../entities/token/token'; +import { getProviders } from '../../lib/transitional'; +import { PersonalAccessToken } from '../../business/entities/token/token'; import { ReposAppRequest } from '../../interfaces'; type ResponseWithNewKey = Response & { diff --git a/routes/teamsPager.ts b/routes/teamsPager.ts index 8dc93f1ab..d4225c2c6 100644 --- a/routes/teamsPager.ts +++ b/routes/teamsPager.ts @@ -7,7 +7,7 @@ import _ from 'lodash'; import asyncHandler from 'express-async-handler'; import { NextFunction, Response } from 'express'; -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; import { Operations } from '../business'; import { Team } from '../business'; import { UserContext } from '../business/user/aggregate'; diff --git a/routes/thanks.ts b/routes/thanks.ts index 04d7df55a..ff95bcfe6 100644 --- a/routes/thanks.ts +++ b/routes/thanks.ts @@ -5,7 +5,7 @@ import { ReposAppRequest } from '../interfaces'; import thisPackage from '../package.json'; -import { getProviders } from '../transitional'; +import { getProviders } from '../lib/transitional'; const express = require('express'); const router = express.Router(); diff --git a/routes/undo.ts b/routes/undo.ts index 148191e16..a08e527ff 100644 --- a/routes/undo.ts +++ b/routes/undo.ts @@ -8,10 +8,10 @@ import asyncHandler from 'express-async-handler'; const router: Router = Router(); import { Operations, Repository } from '../business'; -import { ErrorHelper, getProviders } from '../transitional'; -import { AuditLogRecord } from '../entities/auditLogRecord/auditLogRecord'; -import { daysInMilliseconds } from '../utils'; -import { AuditEvents } from '../entities/auditLogRecord'; +import { ErrorHelper, getProviders } from '../lib/transitional'; +import { AuditLogRecord } from '../business/entities/auditLogRecord/auditLogRecord'; +import { daysInMilliseconds } from '../lib/utils'; +import { AuditEvents } from '../business/entities/auditLogRecord'; import { IGitHubIdentity, IndividualContext } from '../business/user'; import { IMail } from '../lib/mailProvider'; import { GitHubRepositoryPermission, ReposAppRequest, UserAlertType } from '../interfaces'; diff --git a/routes/unlink.ts b/routes/unlink.ts index e16b38c8b..3e79266a6 100644 --- a/routes/unlink.ts +++ b/routes/unlink.ts @@ -7,8 +7,8 @@ import { NextFunction, Response, Router } from 'express'; import asyncHandler from 'express-async-handler'; const router: Router = Router(); -import { getProviders } from '../transitional'; -import { wrapError } from '../utils'; +import { getProviders } from '../lib/transitional'; +import { wrapError } from '../lib/utils'; import { IndividualContext } from '../business/user'; import { jsonError } from '../middleware'; import { ReposAppRequest, OrganizationMembershipState, UnlinkPurpose } from '../interfaces'; diff --git a/scripts/migrateLinks.ts b/scripts/migrateLinks.ts index 66dc52539..316a702af 100644 --- a/scripts/migrateLinks.ts +++ b/scripts/migrateLinks.ts @@ -18,7 +18,7 @@ import throat from 'throat'; import job from '../job'; import { ICorporateLink, IProviders } from '../interfaces'; import { createAndInitializeLinkProviderInstance } from '../lib/linkProviders'; -import { getThirdPartyLinkById } from '../transitional'; +import { getThirdPartyLinkById } from '../lib/transitional'; const parallelWorkLimit = 5; diff --git a/scripts/postgres/setup.ts b/scripts/postgres/setup.ts index 7bcf5fe3f..7adb4968c 100644 --- a/scripts/postgres/setup.ts +++ b/scripts/postgres/setup.ts @@ -12,7 +12,7 @@ import path from 'path'; initialize(); async function setup() { - const sql = fs.readFileSync(path.join(__dirname, '../../../pg.sql'), 'utf8'); + const sql = fs.readFileSync(path.join(__dirname, '../../data/pg.sql'), 'utf8'); const server = await prompt('postgres server: '); const adminUsername = await prompt('admin user: '); diff --git a/jest.config.ts b/test/jest.config.ts similarity index 100% rename from jest.config.ts rename to test/jest.config.ts diff --git a/tsconfig.json b/tsconfig.json index 192dd361d..b04ed2bd9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,12 +1,12 @@ { "compilerOptions": { - "module": "commonjs", + "module": "NodeNext", "sourceMap": true, "outDir": "./dist", "incremental": true, "allowJs": true, "declaration": true, - "moduleResolution": "node", + "moduleResolution": "nodenext", "resolveJsonModule": true, "esModuleInterop": true, "skipLibCheck": true, @@ -23,8 +23,8 @@ "./business/**/*", "./config/**/*", "./data/**/*", - "./entities/**/*", - "./features/**/*", + "business/entities/**/*", + "business/features/**/*", "./interfaces/**/*", "./jobs/**/*", "./lib/**/*", @@ -33,6 +33,6 @@ "./routes/**/*", "./scripts/**/*", "./test/**/*", - "./webhooks/**/*" + "business/webhooks/**/*" ] } diff --git a/views/contributions/voting/elections.pug b/views/contributions/voting/elections.pug index 206373832..5bff6d1fa 100644 --- a/views/contributions/voting/elections.pug +++ b/views/contributions/voting/elections.pug @@ -5,14 +5,32 @@ extends ../../layout +//- @cspell: ignore microsoftfossfund + block content .container - h2 Active Elections + h2 FOSS Fund Rounds + p. + The FOSS Fund is a way for Microsoft employees who contribute to open source + to support open source projects that they use and love. Public information + about this fund is available to be shared at #[a(href='https://aka.ms/microsoftfossfund') aka.ms/microsoftfossfund]. The + fund is distributed to projects based on the votes of Microsoft employees. if activeElections && activeElections.length + - var election1 = activeElections[0] + h3 Most recent funding round + h4: strong: a(href='/contributions/voting/' + election1.slug)= election1.title + p= election1.description + + h3 Past rounds each election in activeElections - //-pre= JSON.stringify(election, undefined, 2) - h2: a(href='/contributions/voting/' + election.slug)= election.title - p= election.description + if election.slug == election1.slug + //- nothing + else + //-pre= JSON.stringify(election, undefined, 2) + p + a(href='/contributions/voting/' + election.slug)= election.title + br + = election.description else - p No active voting opportunities. + p No voting opportunities.