├── .deepsource.toml ├── .editorconfig ├── .eslintrc.json ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── chore.md │ ├── documentation_proposal.md │ ├── feature_request.md │ ├── question.md │ └── regression_report.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── auto-deployments.yml │ ├── build-analytics-service.yml │ ├── build-api-catalog-service.yml │ ├── build-api-gateway.yml │ ├── build-apps-service.yml │ ├── build-feedback-service.yml │ ├── build-lighthouse-service.yml │ ├── build-notifications-service.yml │ ├── build-reverse-proxy-service.yml │ ├── build-search-service.yml │ ├── build-user-group-service.yml │ ├── codeql-analysis.yml │ ├── manual-deployment.yml │ ├── notify.yml │ └── test-and-build.yml ├── .gitignore ├── .nvmrc ├── .vscode ├── extensions.json └── settings.json ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── catalog-info.yaml ├── catalog ├── doc-spa.yaml ├── resources │ ├── CouchDB.yaml │ ├── NativeMongoDB.yaml │ └── NonNativeMongoDB.yaml └── systems │ ├── OnePlatform.yaml │ ├── docs │ ├── code-of-conduct.md │ ├── how-to-contribute.md │ ├── index.md │ ├── op-architecture.md │ ├── service-deployment-guideline.md │ └── spa-deployment-guidelines.md │ └── mkdocs.yaml ├── cypress.json ├── cypress ├── plugins │ └── index.js └── support │ ├── commands.js │ └── index.js ├── docker-compose.yml ├── e2e ├── helper │ └── apps.list.js ├── integration │ ├── apicatalogtests.js │ ├── devconsoletests.js │ ├── errorpagetests.js │ ├── feedbacktests.js │ ├── homepagetests.js │ ├── lighthousetests.js │ ├── searchtests.js │ ├── ssitests.js │ └── usergrouptests.js ├── pageObject │ ├── Footer.js │ ├── HomePage.js │ └── Sidebar.js └── summarize.js ├── lerna.json ├── nx.json ├── one-platform.code-workspace ├── package-lock.json ├── package.json ├── packages ├── analytics-service │ ├── .dockerignore │ ├── .env.example │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc │ ├── .test.env │ ├── Dockerfile │ ├── README.md │ ├── catalog-info.yaml │ ├── docs │ │ └── index.md │ ├── esbuild.config.js │ ├── jest.config.js │ ├── mkdocs.yml │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── @types │ │ │ ├── graph.d.ts │ │ │ ├── types.d.ts │ │ │ └── user.d.ts │ │ ├── __tests__ │ │ │ ├── app.spec.ts │ │ │ ├── mocks │ │ │ │ ├── data.ts │ │ │ │ └── mockDatabase.ts │ │ │ └── query.gql.ts │ │ ├── app.ts │ │ ├── config.ts │ │ ├── dataloader │ │ │ └── userLoader.ts │ │ ├── datasource │ │ │ ├── analyticConfigDB.ts │ │ │ ├── matomoAPI.ts │ │ │ ├── sentryAPI.ts │ │ │ └── types.ts │ │ ├── db │ │ │ ├── analytics.ts │ │ │ └── types.ts │ │ ├── graph │ │ │ ├── analyticsConfig │ │ │ │ ├── resolver.ts │ │ │ │ ├── typedef.graphql │ │ │ │ └── types.ts │ │ │ ├── crashlytics │ │ │ │ ├── resolver.ts │ │ │ │ ├── typedef.graphql │ │ │ │ └── types.ts │ │ │ ├── errors.ts │ │ │ ├── matomo │ │ │ │ ├── resolver.ts │ │ │ │ ├── typedef.graphql │ │ │ │ └── types.ts │ │ │ └── types.ts │ │ ├── helpers │ │ │ ├── buildUserQuery.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ └── logger.ts │ └── tsconfig.json ├── api-catalog-service │ ├── .dockerignore │ ├── .env.example │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc │ ├── .test.env │ ├── Dockerfile │ ├── README.md │ ├── catalog-info.yaml │ ├── docs │ │ ├── api-reference.md │ │ ├── faqs.md │ │ ├── index.md │ │ ├── onboarding-guide.md │ │ └── overview.md │ ├── esbuild.config.js │ ├── jest.config.js │ ├── mkdocs.yml │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── @types │ │ │ ├── graph.d.ts │ │ │ ├── types.d.ts │ │ │ └── user.d.ts │ │ ├── app.ts │ │ ├── config.ts │ │ ├── dataloaders │ │ │ ├── index.ts │ │ │ ├── outageStatusLoader.ts │ │ │ ├── subscriptionStatusLoader.ts │ │ │ └── userLoader.ts │ │ ├── datasources │ │ │ ├── cmdbDatasourceAPI.ts │ │ │ ├── namespaceDB.ts │ │ │ ├── outageStatusAPI.ts │ │ │ ├── specstoreDB.ts │ │ │ ├── subscriptionDB.ts │ │ │ └── types.ts │ │ ├── db │ │ │ ├── namespace.ts │ │ │ ├── specSheet.ts │ │ │ ├── specStore.ts │ │ │ ├── subscription.ts │ │ │ └── types.ts │ │ ├── e2e │ │ │ ├── api-catalog.spec.ts │ │ │ └── mock.ts │ │ ├── graph │ │ │ ├── namespace │ │ │ │ ├── resolver.ts │ │ │ │ ├── typedef.graphql │ │ │ │ └── updateSearch.ts │ │ │ ├── subscription │ │ │ │ ├── resolver.ts │ │ │ │ └── typedef.graphql │ │ │ ├── typedef.graphql │ │ │ └── types.ts │ │ ├── index.ts │ │ ├── logger.ts │ │ ├── mailer.ts │ │ ├── specsheet │ │ │ ├── fetchSchema.ts │ │ │ ├── index.ts │ │ │ ├── isValidGraphqlSchema.ts │ │ │ ├── isValidOpenAPI.ts │ │ │ └── validateSpecSheet.ts │ │ ├── subscriptions │ │ │ ├── diffGraphql.ts │ │ │ ├── diffOpenAPI.ts │ │ │ ├── index.ts │ │ │ ├── setupCronTask.ts │ │ │ ├── subscriptionDAL.ts │ │ │ ├── templates │ │ │ │ ├── gql-api-changes.hbs │ │ │ │ └── rest-api-changes.hbs │ │ │ └── types.ts │ │ └── utils │ │ │ ├── arrayPartition.ts │ │ │ ├── deepMergeByKey.ts │ │ │ ├── encryption.ts │ │ │ ├── index.ts │ │ │ └── jsonOrYamlFormat.ts │ └── tsconfig.json ├── api-catalog-spa │ ├── .env.example │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc │ ├── .test.env │ ├── README.md │ ├── babel.config.js │ ├── catalog-info.yaml │ ├── index.html │ ├── jest.config.ts │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── images │ │ │ ├── all-api-logo.svg │ │ │ ├── gql-playground-logo.svg │ │ │ ├── graphql-logo.svg │ │ │ ├── info-circle.svg │ │ │ ├── op-containers.svg │ │ │ ├── redoc-logo.png │ │ │ ├── rest-logo.svg │ │ │ ├── swagger-black-logo.svg │ │ │ ├── swagger-logo.svg │ │ │ └── voyager-logo.svg │ │ ├── manifest.json │ │ └── robots.txt │ ├── spaship.yaml │ ├── src │ │ ├── App.tsx │ │ ├── api │ │ │ └── types.ts │ │ ├── app.scss │ │ ├── components │ │ │ ├── CatalogBigButton │ │ │ │ ├── CatalogBigButton.test.tsx │ │ │ │ ├── CatalogBigButton.tsx │ │ │ │ └── index.tsx │ │ │ ├── ConditionalWrapper │ │ │ │ ├── ConditionalWrapper.test.tsx │ │ │ │ ├── ConditionalWrapper.tsx │ │ │ │ └── index.tsx │ │ │ ├── Loader │ │ │ │ ├── Loader.test.tsx │ │ │ │ ├── Loader.tsx │ │ │ │ └── index.tsx │ │ │ ├── ReadMore │ │ │ │ ├── ReadMore.test.tsx │ │ │ │ ├── ReadMore.tsx │ │ │ │ └── index.tsx │ │ │ ├── forms │ │ │ │ ├── AsyncSelect │ │ │ │ │ ├── AsyncSelect.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── Select │ │ │ │ │ ├── Select.tsx │ │ │ │ │ └── index.tsx │ │ │ └── index.tsx │ │ ├── config.ts │ │ ├── context │ │ │ ├── BreadcrumbContext │ │ │ │ ├── BreadcrumbContext.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── lookupTable.ts │ │ │ │ └── types.ts │ │ │ └── RecentVisitContext │ │ │ │ ├── RecentVisitContext.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ ├── hooks │ │ │ ├── index.tsx │ │ │ ├── useDebounce │ │ │ │ ├── index.tsx │ │ │ │ ├── useDebounce.test.tsx │ │ │ │ └── useDebounce.tsx │ │ │ ├── usePagination │ │ │ │ ├── index.tsx │ │ │ │ └── usePagination.tsx │ │ │ ├── useQuery │ │ │ │ ├── index.tsx │ │ │ │ ├── types.ts │ │ │ │ └── useQuery.tsx │ │ │ ├── useQueryParams │ │ │ │ ├── index.tsx │ │ │ │ ├── useQueryParams.test.tsx │ │ │ │ └── useQueryParams.tsx │ │ │ ├── useRegisterRecentVisit │ │ │ │ ├── index.tsx │ │ │ │ └── useRegisterRecentVisit.tsx │ │ │ ├── useToggle │ │ │ │ ├── UseToggle.test.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── useToggle.tsx │ │ │ ├── useURLParser │ │ │ │ ├── index.tsx │ │ │ │ ├── useURLParser.test.tsx │ │ │ │ └── useURLParser.tsx │ │ │ └── useURQL │ │ │ │ ├── index.tsx │ │ │ │ └── useURQL.ts │ │ ├── layouts │ │ │ └── AppLayout │ │ │ │ ├── AppLayout.tsx │ │ │ │ ├── appLayout.helper.ts │ │ │ │ ├── appLayout.module.scss │ │ │ │ ├── components │ │ │ │ ├── Footer │ │ │ │ │ ├── Footer.test.tsx │ │ │ │ │ ├── Footer.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── Sidebar │ │ │ │ │ ├── Sidebar.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── sidebar.module.scss │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ ├── main.tsx │ │ ├── pages │ │ │ ├── APICUDPage │ │ │ │ ├── APICUDPage.helpers.ts │ │ │ │ ├── APICUDPage.tsx │ │ │ │ ├── APICUDPage.types.ts │ │ │ │ ├── components │ │ │ │ │ ├── APIBasicDetailsForm │ │ │ │ │ │ ├── APIBasicDetailsForm.test.tsx │ │ │ │ │ │ ├── APIBasicDetailsForm.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── APIReview │ │ │ │ │ │ ├── APIReview.tsx │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ └── Description │ │ │ │ │ │ │ │ ├── Description.test.tsx │ │ │ │ │ │ │ │ ├── Description.tsx │ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── APISchemaForm │ │ │ │ │ │ ├── APISchemaForm.tsx │ │ │ │ │ │ ├── components │ │ │ │ │ │ ├── ApiTypeSelector │ │ │ │ │ │ │ ├── ApiTypeSelector.tsx │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ └── EnvironmentFormSection │ │ │ │ │ │ │ ├── EnvironmentFormSection.test.tsx │ │ │ │ │ │ │ ├── EnvironmentFormSection.tsx │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ ├── EnvHeaderFormSection │ │ │ │ │ │ │ │ ├── EnvHeaderFormSection.test.tsx │ │ │ │ │ │ │ │ ├── EnvHeaderFormSection.tsx │ │ │ │ │ │ │ │ ├── headerForm.module.scss │ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ │ └── EnvSchemaField │ │ │ │ │ │ │ │ ├── EnvSchemaField.test.tsx │ │ │ │ │ │ │ │ ├── EnvSchemaField.tsx │ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ │ ├── environmentFormSection.module.scss │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ ├── hooks │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── types.ts │ │ │ │ │ ├── useCreateNamespace.tsx │ │ │ │ │ ├── useDeleteANamespace.tsx │ │ │ │ │ ├── useGetANamespaceBySlug.tsx │ │ │ │ │ ├── useGetOutages.tsx │ │ │ │ │ └── useUpdateNamespace.tsx │ │ │ │ └── index.tsx │ │ │ ├── APIDescriptionPage │ │ │ │ ├── APIDescriptionPage.tsx │ │ │ │ ├── apiDescriptionPage.module.scss │ │ │ │ ├── components │ │ │ │ │ ├── ApiEnvironmentSection │ │ │ │ │ │ ├── ApiEnvironmentSection.tsx │ │ │ │ │ │ ├── apiEnvironmentSection.module.scss │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── ApiOwnersCard │ │ │ │ │ │ ├── ApiOwnerCard.test.tsx │ │ │ │ │ │ ├── ApiOwnersCard.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── ApiSchemaList │ │ │ │ │ │ ├── ApiSchemaList.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── ApiTypeCard │ │ │ │ │ │ ├── ApiTypeCard.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── DetailsSection │ │ │ │ │ │ ├── DetailsSection.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── hooks │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── useGetANamespaceBySlug.ts │ │ │ │ │ └── useSubscribeSchema.tsx │ │ │ │ └── index.tsx │ │ │ ├── APIListPage │ │ │ │ ├── APIListPage.tsx │ │ │ │ ├── apiListPage.helper.ts │ │ │ │ ├── apiListPage.module.scss │ │ │ │ ├── components │ │ │ │ │ ├── ApiDetailsCard │ │ │ │ │ │ ├── ApiDetailsCard.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Header │ │ │ │ │ │ ├── Header.test.tsx │ │ │ │ │ │ ├── Header.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── StatCard │ │ │ │ │ │ ├── StatCard.test.tsx │ │ │ │ │ │ ├── StatCard.tsx │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── statCard.module.scss │ │ │ │ │ └── index.tsx │ │ │ │ ├── hooks │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── useGetNamespaceList.tsx │ │ │ │ │ └── useGetNamespaceStats.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ │ ├── GQLPlaygroundToolboxPage │ │ │ │ ├── GQLPlaygroundToolboxPage.tsx │ │ │ │ ├── hooks │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── useGetAPISchemaFile.tsx │ │ │ │ └── index.tsx │ │ │ ├── HomePage │ │ │ │ ├── HomePage.tsx │ │ │ │ ├── components │ │ │ │ │ └── SearchBar │ │ │ │ │ │ ├── SearchBar.test.tsx │ │ │ │ │ │ ├── SearchBar.tsx │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── searchBar.module.scss │ │ │ │ ├── homePage.module.scss │ │ │ │ ├── hooks │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── useGetNamespaceList.tsx │ │ │ │ └── index.tsx │ │ │ ├── RedocToolboxPage │ │ │ │ ├── RedocToolboxPage.tsx │ │ │ │ ├── hooks │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── useGetAPISchemaFile.tsx │ │ │ │ └── index.tsx │ │ │ └── SwaggerToolboxPage │ │ │ │ ├── SwaggerToolboxPage.tsx │ │ │ │ ├── hooks │ │ │ │ ├── index.tsx │ │ │ │ └── useGetAPISchemaFile.tsx │ │ │ │ └── index.tsx │ │ ├── router │ │ │ ├── Router.tsx │ │ │ ├── index.tsx │ │ │ ├── links.ts │ │ │ └── routes.tsx │ │ ├── utils │ │ │ ├── callbackify.test.ts │ │ │ ├── callbackify.ts │ │ │ ├── debounce.test.ts │ │ │ ├── debounce.ts │ │ │ ├── debouncePromise.ts │ │ │ ├── errorMessage.test.ts │ │ │ ├── errorMessages.ts │ │ │ ├── hasUserApiEditAccess.test.ts │ │ │ ├── hasUserApiEditAccess.ts │ │ │ ├── index.ts │ │ │ ├── isValidURL.test.ts │ │ │ ├── isValidURL.ts │ │ │ ├── loadThirdPartyScripts.ts │ │ │ ├── slugify.test.ts │ │ │ ├── slugify.ts │ │ │ ├── urlProtocolRemover.test.ts │ │ │ └── urlProtocolRemover.ts │ │ └── vite-env.d.ts │ ├── tsconfig.json │ ├── tsconfig.node.json │ └── vite.config.ts ├── api-gateway-service │ ├── .dockerignore │ ├── .env.example │ ├── .gitignore │ ├── .test.env │ ├── Dockerfile │ ├── README.md │ ├── catalog-info.yaml │ ├── config.json │ ├── docs │ │ └── index.md │ ├── e2e │ │ └── api-gateway.spec.ts │ ├── jest.config.js │ ├── mkdocs.yml │ ├── package-lock.json │ ├── package.json │ ├── service.ts │ ├── src │ │ ├── remote-schema.ts │ │ ├── stitch-schema.ts │ │ ├── types.d.ts │ │ └── verify-token.ts │ ├── tsconfig.json │ ├── tslint.json │ ├── webpack.common.js │ ├── webpack.dev.js │ └── webpack.prod.js ├── apps-service │ ├── .dockerignore │ ├── .env.example │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc │ ├── .test.env │ ├── Dockerfile │ ├── README.md │ ├── catalog-info.yaml │ ├── docs │ │ ├── api-reference.md │ │ ├── faqs.md │ │ ├── index.md │ │ ├── onboarding-guide.md │ │ └── overview.md │ ├── jest.config.js │ ├── mkdocs.yml │ ├── nodemon.json │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── @types │ │ │ ├── application-drawer-entry │ │ │ │ └── index.d.ts │ │ │ ├── common │ │ │ │ └── index.d.ts │ │ │ └── projects │ │ │ │ └── index.d.ts │ │ ├── __tests__ │ │ │ ├── app-drawer-entrys-queries.gql.ts │ │ │ ├── app-drawer-entrys.spec.ts │ │ │ ├── mocks │ │ │ │ └── mockDatabase.ts │ │ │ ├── projects-queries.gql.ts │ │ │ └── projects.spec.ts │ │ ├── app.ts │ │ ├── index.ts │ │ ├── lib │ │ │ └── logger.ts │ │ ├── modules │ │ │ ├── application-drawer-entry │ │ │ │ ├── model.ts │ │ │ │ ├── resolver.ts │ │ │ │ └── schema.gql.ts │ │ │ ├── common │ │ │ │ ├── index.ts │ │ │ │ └── schema.gql.ts │ │ │ └── projects │ │ │ │ ├── model.ts │ │ │ │ ├── resolver.ts │ │ │ │ └── schema.gql.ts │ │ ├── services │ │ │ ├── couchdb.ts │ │ │ └── user-group.ts │ │ ├── setup │ │ │ ├── database.ts │ │ │ └── env.ts │ │ └── utils │ │ │ ├── apps-helper.ts │ │ │ ├── auth-directive.ts │ │ │ ├── gql-queries │ │ │ └── getUser.ts │ │ │ ├── not-found-error.ts │ │ │ └── unique-id-from-path.ts │ ├── tsconfig.json │ └── tsconfig.prod.json ├── component-catalog-spa │ ├── .env.example │ ├── .gitignore │ ├── .test.env │ ├── README.md │ ├── catalog-info.yaml │ ├── docs │ │ └── index.md │ ├── mkdocs.yml │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── manifest.json │ │ └── robots.txt │ ├── spaship.yaml │ └── src │ │ ├── App.jsx │ │ ├── App.scss │ │ ├── Components │ │ ├── Description.jsx │ │ ├── Description.scss │ │ ├── Main.jsx │ │ ├── Main.scss │ │ ├── Navbar.jsx │ │ └── Navbar.scss │ │ ├── Configs │ │ ├── component-libraries.js │ │ ├── footer.js │ │ └── repositoryConfig.js │ │ ├── Hooks │ │ └── useFetchReadme.js │ │ ├── Pages │ │ └── Home.jsx │ │ ├── assets │ │ └── images │ │ │ ├── card-bg.svg │ │ │ ├── chapeaux-logo.svg │ │ │ ├── druplicon-vector.svg │ │ │ ├── github-icon.svg │ │ │ ├── op-logo.svg │ │ │ ├── patternfly-logo.svg │ │ │ └── pfe-logo.svg │ │ ├── constants.js │ │ ├── index.jsx │ │ ├── index.scss │ │ ├── reportWebVitals.js │ │ ├── setupTests.js │ │ └── tests │ │ ├── Description.test.js │ │ ├── Home.test.js │ │ ├── Main.test.js │ │ └── Navbar.test.js ├── developer-console-spa │ ├── .env.example │ ├── .gitignore │ ├── .prettierrc │ ├── .test.env │ ├── README.md │ ├── catalog-info.yaml │ ├── lighthouserc.js │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ ├── robots.txt │ │ └── static │ │ │ └── icons │ │ │ ├── analytics.svg │ │ │ ├── auth.svg │ │ │ ├── database.svg │ │ │ ├── feedback.svg │ │ │ ├── hosting.svg │ │ │ ├── lighthouse.svg │ │ │ ├── notifications.svg │ │ │ ├── op-components.svg │ │ │ ├── reporting-monitoring.svg │ │ │ ├── search.svg │ │ │ └── serverless.svg │ ├── spaship.yaml │ ├── src │ │ ├── @types │ │ │ ├── Database │ │ │ │ └── types.d.ts │ │ │ ├── Feedback │ │ │ │ └── types.d.ts │ │ │ ├── Lighthouse │ │ │ │ └── types.d.ts │ │ │ ├── Project │ │ │ │ └── types.d.ts │ │ │ ├── Search │ │ │ │ └── types.d.ts │ │ │ ├── User │ │ │ │ └── types.d.ts │ │ │ └── types.d.ts │ │ ├── App.css │ │ ├── App.spec.tsx │ │ ├── App.tsx │ │ ├── assets │ │ │ ├── hero-bg.png │ │ │ ├── images │ │ │ │ ├── ssi_default.png │ │ │ │ ├── ssi_feedback.png │ │ │ │ └── ssi_nav_only.png │ │ │ ├── lighthouse_illust.png │ │ │ └── storage_black_24dp.svg │ │ ├── common │ │ │ ├── components │ │ │ │ ├── Header │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.module.css │ │ │ │ ├── Loader │ │ │ │ │ └── index.tsx │ │ │ │ ├── NewProjectForm │ │ │ │ │ └── index.tsx │ │ │ │ ├── ProjectCard │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.css │ │ │ │ ├── Sidebar │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.css │ │ │ │ └── UnderDevelopment │ │ │ │ │ └── index.tsx │ │ │ ├── context │ │ │ │ ├── HeaderContext.tsx │ │ │ │ └── ProjectContext.tsx │ │ │ ├── hooks │ │ │ │ ├── useDatabaseConfig.ts │ │ │ │ ├── useDebounce.ts │ │ │ │ ├── useDebounceEffect.ts │ │ │ │ ├── useDynamicScrollSpy.ts │ │ │ │ ├── useFeedbackConfig.ts │ │ │ │ ├── useLighthouseConfig.ts │ │ │ │ ├── useMyProjectsAPI.ts │ │ │ │ ├── usePagination.tsx │ │ │ │ ├── useProjectAPI.ts │ │ │ │ ├── useProjectPermissions.ts │ │ │ │ ├── useQueryParams.ts │ │ │ │ ├── useSearchConfig.ts │ │ │ │ └── useToggle.ts │ │ │ ├── services │ │ │ │ ├── feedback.ts │ │ │ │ ├── feedbackConfig.ts │ │ │ │ ├── lighthouse.ts │ │ │ │ ├── project.ts │ │ │ │ ├── searchConfig.ts │ │ │ │ └── userGroup.ts │ │ │ └── utils │ │ │ │ ├── formErrorMsg.ts │ │ │ │ ├── gql-queries │ │ │ │ ├── create-feedback-config.ts │ │ │ │ ├── create-lh-projects.ts │ │ │ │ ├── create-lh-spa-config.ts │ │ │ │ ├── create-project-database.ts │ │ │ │ ├── delete-lh-spa-config.ts │ │ │ │ ├── delete-project-database.ts │ │ │ │ ├── delete-project.ts │ │ │ │ ├── get-project-feedbacks.ts │ │ │ │ ├── get-search-config.ts │ │ │ │ ├── get-user-by.ts │ │ │ │ ├── index.ts │ │ │ │ ├── lh-spa-config-by-appId.ts │ │ │ │ ├── list-lh-projects-branches.ts │ │ │ │ ├── list-lh-projects.ts │ │ │ │ ├── manage-app-database.ts │ │ │ │ ├── my-projects.ts │ │ │ │ ├── new-project.ts │ │ │ │ ├── project-by-projectid.ts │ │ │ │ ├── project-database-config.ts │ │ │ │ ├── project-feedback-config.ts │ │ │ │ ├── project-permissions-query.ts │ │ │ │ ├── search-users.ts │ │ │ │ ├── transfer-project-ownership.ts │ │ │ │ ├── update-feedback-config.ts │ │ │ │ ├── update-project-permissions.ts │ │ │ │ ├── update-project.ts │ │ │ │ └── update-search-config.ts │ │ │ │ └── gqlClient.ts │ │ ├── config.ts │ │ ├── declarations.d.ts │ │ ├── index.css │ │ ├── index.tsx │ │ ├── modules.d.ts │ │ ├── pages │ │ │ ├── ConfigureSearch │ │ │ │ ├── SearchWizardForm.tsx │ │ │ │ ├── Steps │ │ │ │ │ ├── Step1.tsx │ │ │ │ │ ├── Step2.tsx │ │ │ │ │ ├── Step3.tsx │ │ │ │ │ ├── store.ts │ │ │ │ │ └── types.d.ts │ │ │ │ ├── global.d.ts │ │ │ │ └── index.tsx │ │ │ ├── Database │ │ │ │ ├── AddUserForm.tsx │ │ │ │ ├── CreateDBForm.tsx │ │ │ │ ├── DeleteDBForm.tsx │ │ │ │ ├── UpdateDBConfig.tsx │ │ │ │ ├── UsersTable.tsx │ │ │ │ └── index.tsx │ │ │ ├── Feedback │ │ │ │ ├── ConfigureFeedback.tsx │ │ │ │ └── FeedbackList.tsx │ │ │ ├── Home │ │ │ │ ├── app-services.json │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.css │ │ │ ├── Hosting │ │ │ │ ├── ManageHosting │ │ │ │ │ └── index.tsx │ │ │ │ ├── components │ │ │ │ │ ├── ApplicationCard │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── styles.css │ │ │ │ │ ├── DeleteAppForm │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── NewAppForm │ │ │ │ │ │ └── index.tsx │ │ │ │ ├── hooks │ │ │ │ │ └── use-hosting.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── services │ │ │ │ │ ├── authenticate-app │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── query.gql.ts │ │ │ │ │ ├── new-app │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── query.gql.ts │ │ │ │ │ └── show-app-in-drawer │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── query.gql.ts │ │ │ │ ├── styles.module.css │ │ │ │ └── utils.tsx │ │ │ ├── Lighthouse │ │ │ │ ├── CreateProjectForm.tsx │ │ │ │ ├── LinkProjectForm.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.css │ │ │ ├── NotFound │ │ │ │ └── index.tsx │ │ │ ├── OPNavbar │ │ │ │ ├── ConfigureOPCBase.module.css │ │ │ │ ├── ConfigureOPNavbar.test.tsx │ │ │ │ ├── ConsoleCodeBlock.test.tsx │ │ │ │ ├── ConsoleCodeBlock.tsx │ │ │ │ ├── consoleCodeBlock.module.css │ │ │ │ └── index.tsx │ │ │ ├── Overview │ │ │ │ ├── index.tsx │ │ │ │ └── styles.css │ │ │ ├── ProjectConsoleShell │ │ │ │ └── index.tsx │ │ │ └── ProjectSettings │ │ │ │ ├── APIKeys.tsx │ │ │ │ ├── General.tsx │ │ │ │ ├── Permissions.tsx │ │ │ │ ├── components │ │ │ │ ├── AddMemberForm.tsx │ │ │ │ └── TransferOwnershipForm.tsx │ │ │ │ └── index.tsx │ │ ├── react-app-env.d.ts │ │ ├── reportWebVitals.ts │ │ └── setupTests.ts │ └── tsconfig.json ├── feedback-service │ ├── .dockerignore │ ├── .env.example │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc │ ├── .test.env │ ├── Dockerfile │ ├── README.md │ ├── catalog-info.yaml │ ├── docs │ │ ├── api-reference.md │ │ ├── faqs.md │ │ ├── index.md │ │ ├── onboarding-guide.md │ │ └── overview.md │ ├── jest.config.js │ ├── mkdocs.yml │ ├── package-lock.json │ ├── package.json │ ├── service.ts │ ├── src │ │ ├── e2e │ │ │ ├── feedback.spec.ts │ │ │ └── mock.js │ │ ├── feedback-config │ │ │ ├── resolver.ts │ │ │ ├── schema.ts │ │ │ └── typedef.graphql │ │ ├── feedbacks │ │ │ ├── resolver.ts │ │ │ ├── schema.ts │ │ │ └── typedef.graphql │ │ ├── helpers.ts │ │ ├── jobs │ │ │ ├── createGithubIssue.ts │ │ │ ├── createGitlabIssue.ts │ │ │ ├── createJira.ts │ │ │ └── index.ts │ │ ├── lib │ │ │ ├── bullboard.ts │ │ │ ├── logger.ts │ │ │ ├── queue.ts │ │ │ └── redis.ts │ │ └── types.d.ts │ ├── tsconfig.json │ ├── webpack.common.js │ ├── webpack.dev.js │ └── webpack.prod.js ├── feedback-spa │ ├── .env.example │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc.js │ ├── .test.env │ ├── README.md │ ├── babel.config.js │ ├── catalog-info.yaml │ ├── index.html │ ├── jest-setup.ts │ ├── jest.config.js │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── manifest.json │ │ └── robots.txt │ ├── spaship.yaml │ ├── src │ │ ├── App.tsx │ │ ├── app.css │ │ ├── assets │ │ │ └── images │ │ │ │ ├── bug.svg │ │ │ │ └── feedback.svg │ │ ├── components │ │ │ ├── Loader │ │ │ │ ├── Loader.test.tsx │ │ │ │ ├── Loader.tsx │ │ │ │ └── index.tsx │ │ │ ├── ReadMore │ │ │ │ ├── ReadMore.tsx │ │ │ │ └── index.tsx │ │ │ └── index.tsx │ │ ├── hooks │ │ │ ├── index.tsx │ │ │ ├── useDebounce │ │ │ │ ├── index.tsx │ │ │ │ ├── useDebounce.test.tsx │ │ │ │ └── useDebounce.tsx │ │ │ ├── usePagination │ │ │ │ ├── index.tsx │ │ │ │ └── usePagination.tsx │ │ │ ├── usePopUp │ │ │ │ ├── index.tsx │ │ │ │ └── usePopUp.tsx │ │ │ ├── useQueryParams │ │ │ │ ├── index.tsx │ │ │ │ ├── useQueryParams.test.tsx │ │ │ │ └── useQueryParams.tsx │ │ │ └── useToggle │ │ │ │ ├── index.tsx │ │ │ │ └── useToggle.tsx │ │ ├── layouts │ │ │ └── AppLayout │ │ │ │ ├── AppLayout.test.tsx │ │ │ │ ├── AppLayout.tsx │ │ │ │ └── index.tsx │ │ ├── main.tsx │ │ ├── pages │ │ │ └── HomePage │ │ │ │ ├── HomePage.tsx │ │ │ │ ├── components │ │ │ │ ├── AppListCard │ │ │ │ │ ├── AppListCard.test.tsx │ │ │ │ │ ├── AppListCard.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── FeedbackCard │ │ │ │ │ ├── FeedbackCard.tsx │ │ │ │ │ ├── feedbackCard.module.css │ │ │ │ │ ├── feedbackCard.test.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── FeedbackDetailCard │ │ │ │ │ ├── FeedbackDetailCard.tsx │ │ │ │ │ ├── feedbackDetailCard.test.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── FilterTitle │ │ │ │ │ ├── FilterTitle.tsx │ │ │ │ │ ├── filterTitle.test.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── gql │ │ │ │ ├── GetApps.ts │ │ │ │ ├── GetFeedback.ts │ │ │ │ └── GetFeedbackList.ts │ │ │ │ ├── homePage.helper.ts │ │ │ │ ├── homePage.mocks.ts │ │ │ │ ├── index.tsx │ │ │ │ └── types.ts │ │ ├── routes │ │ │ ├── Router.tsx │ │ │ ├── index.tsx │ │ │ └── routes.tsx │ │ ├── types.ts │ │ └── vite-env.d.ts │ ├── tsconfig.json │ └── vite.config.ts ├── home-spa │ ├── .dockerignore │ ├── .eleventy.js │ ├── .env.example │ ├── .gitignore │ ├── .htaccess │ ├── .test.env │ ├── Dockerfile │ ├── catalog-info.yaml │ ├── favicon.ico │ ├── lighthouserc.js │ ├── package-lock.json │ ├── package.json │ ├── spaship.yaml │ └── src │ │ ├── 404.njk │ │ ├── _data │ │ ├── applications.json │ │ ├── env.js │ │ ├── footer.json │ │ ├── microservices.json │ │ └── pageText.json │ │ ├── _includes │ │ ├── components │ │ │ ├── applications.njk │ │ │ ├── deliver.njk │ │ │ ├── deploy.njk │ │ │ ├── hero.njk │ │ │ ├── illustration.njk │ │ │ └── services.njk │ │ ├── layout │ │ │ └── base.njk │ │ └── partials │ │ │ ├── footer.njk │ │ │ ├── header.njk │ │ │ └── service.njk │ │ ├── contact-us.njk │ │ ├── favicon.ico │ │ ├── index.njk │ │ ├── scss │ │ ├── 404.scss │ │ ├── contact-us.scss │ │ ├── home.scss │ │ └── style.scss │ │ ├── static │ │ ├── img │ │ │ ├── 1checklist.svg │ │ │ ├── 2build.svg │ │ │ ├── 3deploy.svg │ │ │ ├── 404.svg │ │ │ ├── Auth-illustration.svg │ │ │ ├── Feedback-illustration.svg │ │ │ ├── Notification-illustration.svg │ │ │ ├── Red Hat logo.svg │ │ │ ├── Search-illustration.svg │ │ │ ├── app-cube-white.svg │ │ │ ├── appCubes.svg │ │ │ ├── auth.svg │ │ │ ├── avatar.svg │ │ │ ├── blog_illustration.png │ │ │ ├── co-working.svg │ │ │ ├── components_illustration.png │ │ │ ├── cube.svg │ │ │ ├── external-link-icon.svg │ │ │ ├── faq_illustration.png │ │ │ ├── feedback.svg │ │ │ ├── gateway.svg │ │ │ ├── illustration.svg │ │ │ ├── left-footer-cubes.svg │ │ │ ├── login.svg │ │ │ ├── magnifying-glass.svg │ │ │ ├── microservices_illustration.png │ │ │ ├── notification.svg │ │ │ ├── opCore.svg │ │ │ ├── quotes.svg │ │ │ ├── redcube.svg │ │ │ ├── right-footer-cubes.svg │ │ │ ├── search.svg │ │ │ ├── spaship.svg │ │ │ ├── user-female.svg │ │ │ ├── user-male.svg │ │ │ ├── user.svg │ │ │ └── user_group.svg │ │ └── js │ │ │ └── home.js │ │ └── tests │ │ ├── 404.spec.js │ │ ├── contact-us.spec.js │ │ └── home.spec.js ├── lighthouse-service │ ├── .dockerignore │ ├── .env.example │ ├── .eslintrc.js │ ├── .gitignore │ ├── .test.env │ ├── Dockerfile │ ├── README.md │ ├── catalog-info.yaml │ ├── docs │ │ ├── api-reference.md │ │ ├── faqs.md │ │ ├── index.md │ │ ├── onboarding-guide.md │ │ └── overview.md │ ├── jest.config.js │ ├── mkdocs.yml │ ├── package-lock.json │ ├── package.json │ ├── service.ts │ ├── src │ │ ├── audit-manager │ │ │ ├── resolver.ts │ │ │ └── typedef.graphql │ │ ├── e2e │ │ │ ├── lighthouse.spec.ts │ │ │ └── mock.json │ │ ├── helpers.ts │ │ ├── lib │ │ │ └── logger.ts │ │ ├── lighthouse-db-manager │ │ │ ├── README.md │ │ │ ├── index.ts │ │ │ ├── lighthouse-db-manager.ts │ │ │ ├── models │ │ │ │ ├── build.ts │ │ │ │ ├── project.ts │ │ │ │ └── statistic.ts │ │ │ ├── sequelize.ts │ │ │ └── types.ts │ │ ├── lighthouse-spa-config │ │ │ ├── helpers.ts │ │ │ ├── resolver.ts │ │ │ ├── schema.ts │ │ │ └── typedef.graphql │ │ └── types.d.ts │ ├── tsconfig.json │ ├── webpack.common.js │ ├── webpack.dev.js │ └── webpack.prod.js ├── lighthouse-spa │ ├── .browserslistrc │ ├── .editorconfig │ ├── .gitignore │ ├── .test.env │ ├── README.md │ ├── angular.json │ ├── babel.config.js │ ├── catalog-info.yaml │ ├── e2e │ │ ├── protractor.conf.js │ │ ├── src │ │ │ ├── app.e2e-spec.ts │ │ │ └── app.po.ts │ │ └── tsconfig.json │ ├── jest.config.js │ ├── karma.conf.js │ ├── lighthouserc.js │ ├── package-lock.json │ ├── package.json │ ├── set-env.ts │ ├── spaship.yaml │ ├── src │ │ ├── app │ │ │ ├── app-routing.module.ts │ │ │ ├── app.component.html │ │ │ ├── app.component.scss │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ ├── app.module.ts │ │ │ ├── dashboard │ │ │ │ ├── components │ │ │ │ │ └── property-card │ │ │ │ │ │ ├── property-card.component.html │ │ │ │ │ │ ├── property-card.component.scss │ │ │ │ │ │ ├── property-card.component.spec.ts │ │ │ │ │ │ └── property-card.component.ts │ │ │ │ ├── dashboard-routing.module.ts │ │ │ │ ├── dashboard.gql.ts │ │ │ │ ├── dashboard.module.ts │ │ │ │ ├── dashboard.service.spec.ts │ │ │ │ ├── dashboard.service.ts │ │ │ │ ├── mock-dashboard.ts │ │ │ │ ├── pages │ │ │ │ │ ├── analysis │ │ │ │ │ │ ├── analysis.component.html │ │ │ │ │ │ ├── analysis.component.scss │ │ │ │ │ │ ├── analysis.component.spec.ts │ │ │ │ │ │ └── analysis.component.ts │ │ │ │ │ └── home │ │ │ │ │ │ ├── home.component.html │ │ │ │ │ │ ├── home.component.scss │ │ │ │ │ │ ├── home.component.spec.ts │ │ │ │ │ │ └── home.component.ts │ │ │ │ ├── pipes │ │ │ │ │ ├── timeline-score-formater.pipe.spec.ts │ │ │ │ │ └── timeline-score-formater.pipe.ts │ │ │ │ └── types.d.ts │ │ │ ├── graphql.module.ts │ │ │ ├── leaderboard │ │ │ │ ├── components │ │ │ │ │ └── leaderboard-card │ │ │ │ │ │ ├── leaderboard-card.component.html │ │ │ │ │ │ ├── leaderboard-card.component.scss │ │ │ │ │ │ ├── leaderboard-card.component.spec.ts │ │ │ │ │ │ └── leaderboard-card.component.ts │ │ │ │ ├── enum.ts │ │ │ │ ├── leaderboard-routing.module.ts │ │ │ │ ├── leaderboard.gql.ts │ │ │ │ ├── leaderboard.module.ts │ │ │ │ ├── leaderboard.service.spec.ts │ │ │ │ ├── leaderboard.service.ts │ │ │ │ ├── mock-leaderboard.ts │ │ │ │ ├── pages │ │ │ │ │ └── leaderboard │ │ │ │ │ │ ├── leaderboard.component.html │ │ │ │ │ │ ├── leaderboard.component.scss │ │ │ │ │ │ ├── leaderboard.component.spec.ts │ │ │ │ │ │ └── leaderboard.component.ts │ │ │ │ ├── pipes │ │ │ │ │ ├── leaderboard-label-formater.pipe.spec.ts │ │ │ │ │ └── leaderboard-label-formater.pipe.ts │ │ │ │ └── types.d.ts │ │ │ ├── playground │ │ │ │ ├── components │ │ │ │ │ └── home │ │ │ │ │ │ ├── home.component.html │ │ │ │ │ │ ├── home.component.scss │ │ │ │ │ │ ├── home.component.spec.ts │ │ │ │ │ │ └── home.component.ts │ │ │ │ ├── mock-playground.ts │ │ │ │ ├── playground-routing.module.ts │ │ │ │ ├── playground.gql.ts │ │ │ │ ├── playground.module.ts │ │ │ │ ├── playground.service.spec.ts │ │ │ │ └── playground.service.ts │ │ │ ├── shared │ │ │ │ ├── components │ │ │ │ │ ├── avatar │ │ │ │ │ │ ├── avatar.component.html │ │ │ │ │ │ ├── avatar.component.scss │ │ │ │ │ │ ├── avatar.component.spec.ts │ │ │ │ │ │ └── avatar.component.ts │ │ │ │ │ ├── context-selector │ │ │ │ │ │ ├── context-selector.component.html │ │ │ │ │ │ ├── context-selector.component.scss │ │ │ │ │ │ ├── context-selector.component.spec.ts │ │ │ │ │ │ └── context-selector.component.ts │ │ │ │ │ ├── empty-state │ │ │ │ │ │ ├── empty-state.component.html │ │ │ │ │ │ ├── empty-state.component.scss │ │ │ │ │ │ ├── empty-state.component.spec.ts │ │ │ │ │ │ └── empty-state.component.ts │ │ │ │ │ ├── form-error-message │ │ │ │ │ │ ├── form-error-message.component.html │ │ │ │ │ │ ├── form-error-message.component.scss │ │ │ │ │ │ ├── form-error-message.component.spec.ts │ │ │ │ │ │ └── form-error-message.component.ts │ │ │ │ │ ├── lhcard-legend │ │ │ │ │ │ ├── lhcard-legend.component.html │ │ │ │ │ │ ├── lhcard-legend.component.scss │ │ │ │ │ │ ├── lhcard-legend.component.spec.ts │ │ │ │ │ │ └── lhcard-legend.component.ts │ │ │ │ │ ├── loader │ │ │ │ │ │ ├── loader.component.html │ │ │ │ │ │ ├── loader.component.scss │ │ │ │ │ │ ├── loader.component.spec.ts │ │ │ │ │ │ └── loader.component.ts │ │ │ │ │ ├── outlined-pie-graph │ │ │ │ │ │ ├── outlined-pie-graph.component.html │ │ │ │ │ │ ├── outlined-pie-graph.component.scss │ │ │ │ │ │ ├── outlined-pie-graph.component.spec.ts │ │ │ │ │ │ └── outlined-pie-graph.component.ts │ │ │ │ │ └── table │ │ │ │ │ │ ├── table.component.html │ │ │ │ │ │ ├── table.component.scss │ │ │ │ │ │ ├── table.component.spec.ts │ │ │ │ │ │ └── table.component.ts │ │ │ │ ├── directive │ │ │ │ │ ├── url-validator.directive.spec.ts │ │ │ │ │ └── url-validator.directive.ts │ │ │ │ ├── layouts │ │ │ │ │ └── app-layout │ │ │ │ │ │ ├── app-layout.component.html │ │ │ │ │ │ ├── app-layout.component.scss │ │ │ │ │ │ ├── app-layout.component.spec.ts │ │ │ │ │ │ └── app-layout.component.ts │ │ │ │ ├── pipes │ │ │ │ │ ├── filter-list.pipe.spec.ts │ │ │ │ │ ├── filter-list.pipe.ts │ │ │ │ │ ├── floor.pipe.spec.ts │ │ │ │ │ ├── floor.pipe.ts │ │ │ │ │ ├── get-decimal.pipe.spec.ts │ │ │ │ │ ├── get-decimal.pipe.ts │ │ │ │ │ ├── lhscore-label-formater.pipe.spec.ts │ │ │ │ │ └── lhscore-label-formater.pipe.ts │ │ │ │ └── shared.module.ts │ │ │ └── utils │ │ │ │ ├── csvExport.ts │ │ │ │ └── leaderboardTable.ts │ │ ├── assets │ │ │ ├── .gitkeep │ │ │ └── containers.svg │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ ├── polyfills.ts │ │ ├── setup-jest.ts │ │ ├── styles.scss │ │ └── types.d.ts │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ └── tslint.json ├── notifications-service │ ├── .dockerignore │ ├── .env.example │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc │ ├── Dockerfile │ ├── README.md │ ├── nodemon.json │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── @types │ │ │ ├── Banner │ │ │ │ └── types.d.ts │ │ │ ├── Notification │ │ │ │ └── types.d.ts │ │ │ ├── Subscriber │ │ │ │ └── types.d.ts │ │ │ └── types.d.ts │ │ ├── index.ts │ │ ├── lib │ │ │ ├── email-queue.ts │ │ │ └── push-queue.ts │ │ ├── modules │ │ │ ├── Banner │ │ │ │ ├── resolver.ts │ │ │ │ └── typedef.gql │ │ │ ├── Notification │ │ │ │ ├── resolver.ts │ │ │ │ └── typedef.gql │ │ │ ├── Subscriber │ │ │ │ ├── resolver.ts │ │ │ │ └── typedef.gql │ │ │ └── common │ │ │ │ ├── resolver.ts │ │ │ │ └── typedef.gql │ │ ├── schema.ts │ │ ├── server.ts │ │ ├── setup │ │ │ ├── database.ts │ │ │ ├── env.ts │ │ │ └── queue.ts │ │ └── utils │ │ │ ├── NotFoundError.ts │ │ │ ├── emails.ts │ │ │ ├── findNotificationsForUser.ts │ │ │ ├── getGqlTypeDefs.ts │ │ │ ├── prepareList.ts │ │ │ └── pubsub.ts │ ├── tsconfig.json │ └── tsconfig.prod.json ├── opc-base │ ├── .gitignore │ ├── README.md │ ├── babel.config.js │ ├── catalog-info.yaml │ ├── dev │ │ ├── config.es.example.js │ │ ├── config.example.js │ │ ├── es.html │ │ └── index.html │ ├── docs │ │ ├── index.md │ │ ├── opc-base.md │ │ └── opc-provider.md │ ├── mkdocs.yml │ ├── package-lock.json │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── assets │ │ │ └── logo.svg │ │ ├── components │ │ │ ├── opc-drawer-footer │ │ │ │ ├── opc-drawer-footer.styles.ts │ │ │ │ ├── opc-drawer-footer.test.ts │ │ │ │ └── opc-drawer-footer.ts │ │ │ ├── opc-loader │ │ │ │ ├── opc-loader.styles.ts │ │ │ │ ├── opc-loader.test.ts │ │ │ │ └── opc-loader.ts │ │ │ ├── opc-menu-drawer │ │ │ │ └── opc-avatar │ │ │ │ │ ├── opc-avatar.styles.ts │ │ │ │ │ ├── opc-avatar.test.ts │ │ │ │ │ └── opc-avatar.ts │ │ │ ├── opc-notification-drawer │ │ │ │ └── opc-filter-chip │ │ │ │ │ ├── opc-filter-chip.styles.ts │ │ │ │ │ ├── opc-filter-chip.test.ts │ │ │ │ │ └── opc-filter-chip.ts │ │ │ └── opc-toast │ │ │ │ ├── opc-toast.styles.ts │ │ │ │ ├── opc-toast.test.ts │ │ │ │ ├── opc-toast.ts │ │ │ │ └── types.ts │ │ ├── config │ │ │ ├── graphql.ts │ │ │ └── types.ts │ │ ├── custom.d.ts │ │ ├── gql │ │ │ ├── opc-app-layout.ts │ │ │ └── types.ts │ │ ├── keycloakAuthProvider │ │ │ ├── keycloakAuthProvider.ts │ │ │ └── types.ts │ │ ├── opc-base │ │ │ ├── opc-base.test.ts │ │ │ ├── opc-base.ts │ │ │ └── types.ts │ │ ├── opc-provider │ │ │ ├── opc-provider.helper.ts │ │ │ ├── opc-provider.styles.ts │ │ │ ├── opc-provider.test.ts │ │ │ ├── opc-provider.ts │ │ │ └── types.ts │ │ └── types.d.ts │ ├── tsconfig.json │ └── web-test-runner.config.js ├── reverse-proxy-service │ ├── .env.example │ ├── .gitignore │ ├── .prettierrc │ ├── Dockerfile │ ├── README.md │ ├── catalog-info.yaml │ ├── docs │ │ └── index.md │ ├── jest.config.js │ ├── mkdocs.yml │ ├── nodemon.json │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── couchdb │ │ │ ├── index.ts │ │ │ └── resolver.ts │ │ ├── index.ts │ │ ├── middleware │ │ │ ├── checkSSO.ts │ │ │ ├── jwtAuth.ts │ │ │ └── oidcAuth.ts │ │ ├── no-cors-proxy │ │ │ ├── index.ts │ │ │ └── resolver.ts │ │ ├── restricted-spas │ │ │ ├── index.ts │ │ │ └── resolver.ts │ │ ├── server.ts │ │ ├── setup │ │ │ ├── database.ts │ │ │ ├── env.ts │ │ │ ├── logger.ts │ │ │ └── store.ts │ │ ├── spec │ │ │ ├── app.spec.ts │ │ │ ├── couchdb.spec.ts │ │ │ ├── jwtAuth.spec.ts │ │ │ └── restricted-spas.spec.ts │ │ └── utils │ │ │ ├── applicationCache.ts │ │ │ └── verifyJwtToken.ts │ └── tsconfig.json ├── search-service │ ├── .dockerignore │ ├── .env.example │ ├── .eslintrc.js │ ├── .gitignore │ ├── .test.env │ ├── Dockerfile │ ├── README.md │ ├── catalog-info.yaml │ ├── docs │ │ ├── api-reference.md │ │ ├── faqs.md │ │ ├── index.md │ │ ├── onboarding-guide.md │ │ └── overview.md │ ├── jest.config.js │ ├── mkdocs.yml │ ├── package-lock.json │ ├── package.json │ ├── service.ts │ ├── src │ │ ├── e2e │ │ │ ├── mock.js │ │ │ └── search.spec.ts │ │ ├── lib │ │ │ └── logger.ts │ │ ├── scripts │ │ │ ├── index.ts │ │ │ └── search-indexing.ts │ │ ├── search-config │ │ │ ├── resolver.ts │ │ │ └── typedef.graphql │ │ ├── search-mapping │ │ │ ├── helpers.ts │ │ │ ├── resolver.ts │ │ │ ├── schema.ts │ │ │ ├── typedef.graphql │ │ │ └── types.d.ts │ │ ├── search-sitemap │ │ │ ├── resolver.ts │ │ │ ├── schema.ts │ │ │ └── types.d.ts │ │ ├── services │ │ │ ├── search.ts │ │ │ └── types.d.ts │ │ ├── setup │ │ │ ├── database.ts │ │ │ └── env.ts │ │ ├── types.d.ts │ │ └── utils │ │ │ └── search-map-getter.ts │ ├── tsconfig.json │ ├── webpack.common.js │ ├── webpack.dev.js │ └── webpack.prod.js ├── search-spa │ ├── .browserslistrc │ ├── .editorconfig │ ├── .gitignore │ ├── .test.env │ ├── README.md │ ├── angular.json │ ├── catalog-info.yaml │ ├── e2e │ │ ├── protractor.conf.js │ │ ├── src │ │ │ ├── app.e2e-spec.ts │ │ │ └── app.po.ts │ │ └── tsconfig.json │ ├── jest.config.js │ ├── karma.conf.js │ ├── lighthouserc.js │ ├── package-lock.json │ ├── package.json │ ├── set-env.ts │ ├── spaship.yaml │ ├── src │ │ ├── app │ │ │ ├── app-routing.module.ts │ │ │ ├── app.component.html │ │ │ ├── app.component.scss │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ ├── app.gql.ts │ │ │ ├── app.module.ts │ │ │ ├── app.service.spec.ts │ │ │ ├── app.service.ts │ │ │ ├── graphql.module.ts │ │ │ ├── search │ │ │ │ ├── search.component.html │ │ │ │ ├── search.component.scss │ │ │ │ ├── search.component.spec.ts │ │ │ │ └── search.component.ts │ │ │ ├── testing │ │ │ │ └── mocks │ │ │ │ │ └── result.mock.ts │ │ │ ├── types.d.ts │ │ │ └── utils │ │ │ │ └── pagination.ts │ │ ├── assets │ │ │ ├── .gitkeep │ │ │ ├── app-cube.svg │ │ │ └── no_search_result.svg │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ ├── module.d.ts │ │ ├── polyfills.ts │ │ ├── setup-jest.ts │ │ └── styles.scss │ ├── tsconfig.app.json │ ├── tsconfig.base.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ └── tslint.json ├── user-group-service │ ├── .dockerignore │ ├── .env.example │ ├── .eslintrc.js │ ├── .gitignore │ ├── .test.env │ ├── Dockerfile │ ├── README.md │ ├── catalog-info.yaml │ ├── docs │ │ ├── api-reference.md │ │ ├── faqs.md │ │ ├── index.md │ │ ├── onboarding-guide.md │ │ └── overview.md │ ├── jest.config.js │ ├── mkdocs.yaml │ ├── package-lock.json │ ├── package.json │ ├── service.ts │ ├── src │ │ ├── api-keys │ │ │ ├── resolver.ts │ │ │ ├── schema.ts │ │ │ ├── typedef.graphql │ │ │ └── util.ts │ │ ├── e2e │ │ │ ├── mock.js │ │ │ ├── rover.mock.js │ │ │ └── user.spec.ts │ │ ├── groups │ │ │ ├── resolver.ts │ │ │ ├── schema.ts │ │ │ └── typedef.graphql │ │ ├── helpers.ts │ │ ├── lib │ │ │ └── logger.ts │ │ ├── types.d.ts │ │ └── users │ │ │ ├── cron.ts │ │ │ ├── resolver.ts │ │ │ ├── schema.ts │ │ │ └── typedef.graphql │ ├── tsconfig.json │ ├── webpack.common.js │ ├── webpack.dev.js │ └── webpack.prod.js └── user-group-spa │ ├── .env.example │ ├── .gitignore │ ├── .test.env │ ├── README.md │ ├── lighthouserc.js │ ├── package-lock.json │ ├── package.json │ ├── public │ ├── .htaccess │ ├── index.html │ └── mockServiceWorker.js │ ├── spaship.yaml │ └── src │ ├── App.css │ ├── App.jsx │ ├── App.test.js │ ├── components │ ├── Form.jsx │ ├── Form.test.js │ ├── Group.jsx │ ├── Group.test.js │ ├── Home.jsx │ ├── Home.test.js │ ├── NotFound.jsx │ ├── NotFound.test.js │ ├── User.jsx │ └── User.test.js │ ├── context │ └── BreadcrumbContext.jsx │ ├── index.css │ ├── index.js │ ├── mocks │ ├── browser.js │ ├── data.js │ ├── handlers.js │ └── server.js │ ├── serviceWorker.js │ ├── services │ ├── FetchClient.js │ ├── GqlQueries.js │ └── GroupsAPI.js │ └── setupTests.js ├── puppeteerScript.js └── renovate.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "node": true 6 | }, 7 | "extends": [ 8 | "standard", 9 | "plugin:jest/recommended" 10 | ], 11 | "globals": { 12 | "Atomics": "readonly", 13 | "SharedArrayBuffer": "readonly" 14 | }, 15 | "parser": "@typescript-eslint/parser", 16 | "parserOptions": { 17 | "ecmaVersion": 2018, 18 | "sourceType": "module" 19 | }, 20 | "plugins": [ 21 | "@typescript-eslint", 22 | "jest" 23 | ], 24 | "rules": { 25 | "semi": "off" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.github/workflows/notify.yml: -------------------------------------------------------------------------------- 1 | name: Notify the Gchat Group 2 | on: 3 | pull_request_target: 4 | types: [opened] 5 | jobs: 6 | notify: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Google Chat Notification 10 | uses: associate-run-projects/google-chat-notification@master 11 | with: 12 | url: ${{ secrets.GOOGLE_CHAT_WEBHOOK }} 13 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v16 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "bierner.lit-html", 8 | "dbaeumer.vscode-eslint" 9 | ], 10 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 11 | "unwantedRecommendations": [] 12 | } 13 | -------------------------------------------------------------------------------- /catalog/doc-spa.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: backstage.io/v1alpha1 3 | kind: Location 4 | metadata: 5 | name: one-platform-docs-spa 6 | spec: 7 | target: https://gitlab.cee.redhat.com/one-platform/docs-spa/-/blob/main/catalog-info.yml 8 | presence: optional 9 | -------------------------------------------------------------------------------- /catalog/resources/NativeMongoDB.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: backstage.io/v1alpha1 3 | kind: Resource 4 | metadata: 5 | name: native-apps-mongodb 6 | title: Native Apps MongoDB 7 | namespace: devex 8 | description: Stores data for one platform native apps 9 | tags: 10 | - mongodb 11 | - one-platform 12 | - native 13 | spec: 14 | type: database 15 | owner: group:redhat/one-platform-devs 16 | system: devex/one-platform 17 | lifecycle: production 18 | -------------------------------------------------------------------------------- /catalog/resources/NonNativeMongoDB.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: backstage.io/v1alpha1 3 | kind: Resource 4 | metadata: 5 | name: non-native-apps-mongodb 6 | title: Non Native Apps MongoDB 7 | namespace: devex 8 | description: Stores data for one platform Non native apps 9 | tags: 10 | - mongodb 11 | - one-platform 12 | - native 13 | spec: 14 | type: database 15 | owner: group:redhat/one-platform-devs 16 | system: devex/one-platform 17 | lifecycle: production 18 | -------------------------------------------------------------------------------- /catalog/systems/docs/spa-deployment-guidelines.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: spa-deployment-guidelines 3 | title: SPA Deployment Guidelines 4 | slug: /deployments/spa 5 | sidebar_label: SPA Guidelines 6 | --- 7 | 8 | ## Guide 9 | 10 | #### Please head over to [SPAship quickstart deployment guide](https://spaship.io/docs/guide/user-guide/Quickstart/) 11 | -------------------------------------------------------------------------------- /catalog/systems/mkdocs.yaml: -------------------------------------------------------------------------------- 1 | site_name: 'One Platform' 2 | 3 | nav: 4 | - What's One Platform: index.md 5 | - One Platform Architecture: op-architecture.md 6 | - OP Service Deployment Guideline: service-deployment-guideline.md 7 | - SPA Deployment Guideline: spa-deployment-guidelines.md 8 | - How to Contribute: how-to-contribute.md 9 | - Code Of Conduct: code-of-conduct.md 10 | 11 | 12 | plugins: 13 | - techdocs-core 14 | -------------------------------------------------------------------------------- /e2e/pageObject/Footer.js: -------------------------------------------------------------------------------- 1 | class Footer { 2 | footerLinks () { 3 | return cy.get( '#darkFooterWithLinks' ); 4 | 5 | } 6 | } 7 | export default Footer; 8 | -------------------------------------------------------------------------------- /e2e/pageObject/Sidebar.js: -------------------------------------------------------------------------------- 1 | class Sidebar{ 2 | 3 | 4 | getApplicationSearchResults () { 5 | return cy.get('.opc-menu-drawer-link-group:nth-child(2)') 6 | } 7 | 8 | getBuiltInServiceSearchResults () { 9 | return cy.get('.opc-menu-drawer-link-group:nth-child(3)') 10 | } 11 | getAllApplicationSearchResults () { 12 | return cy.get('.opc-menu-drawer-link-group:nth-child(2) a ') 13 | 14 | } 15 | getAllBuiltInServiceSearchResults () { 16 | return cy.get('.opc-menu-drawer-link-group:nth-child(3) a ') 17 | 18 | } 19 | } 20 | export default Sidebar; 21 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*" 4 | ], 5 | "useNx": true, 6 | "version": "independent" 7 | } 8 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "nx/presets/npm.json", 3 | "tasksRunnerOptions": { 4 | "default": { 5 | "runner": "nx/tasks-runners/default", 6 | "options": { 7 | "cacheableOperations": [ 8 | "build", 9 | "test" 10 | ] 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/analytics-service/.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | README.md -------------------------------------------------------------------------------- /packages/analytics-service/.env.example: -------------------------------------------------------------------------------- 1 | # PORT= 2 | # NODE_ENV= 3 | # SENTRY_API_TOKEN= 4 | # SENTRY_API_URL= 5 | # SENTRY_API_ORG= 6 | # SENTRY_API_TEAM= 7 | # MATOMO_API_URL= 8 | # MATOMO_API_TOKEN= 9 | 10 | MONGO_URI= 11 | API_GATEWAY_URL= 12 | API_GATEWAY_TOKEN= 13 | -------------------------------------------------------------------------------- /packages/analytics-service/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true, 5 | es2021: true, 6 | }, 7 | extends: ['airbnb-base', 'airbnb-typescript/base', 'plugin:prettier/recommended'], 8 | parser: '@typescript-eslint/parser', 9 | parserOptions: { 10 | ecmaVersion: 12, 11 | sourceType: 'module', 12 | project: './tsconfig.json', 13 | tsconfigRootDir: __dirname, 14 | }, 15 | plugins: ['@typescript-eslint', 'prettier'], 16 | rules: { 17 | 'import/prefer-default-export': 'off', 18 | 'class-methods-use-this': 'off', 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /packages/analytics-service/.gitignore: -------------------------------------------------------------------------------- 1 | # Development files 2 | node_modules 3 | .env 4 | .DS_Store 5 | 6 | # ignore dist 7 | dist 8 | 9 | # Logs 10 | npm-debug.log* 11 | -------------------------------------------------------------------------------- /packages/analytics-service/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "all", 4 | "singleQuote": true, 5 | "printWidth": 100, 6 | "tabWidth": 2 7 | } 8 | -------------------------------------------------------------------------------- /packages/analytics-service/.test.env: -------------------------------------------------------------------------------- 1 | MONGO_URI="mongodb://testserver/testdb" 2 | API_GATEWAY_URL="https://localhost:8080/graphql" 3 | API_GATEWAY_TOKEN="test_token" 4 | -------------------------------------------------------------------------------- /packages/analytics-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16-alpine 2 | LABEL Name=one-platform-api-catalog-service \ 3 | Version=0.4.3 \ 4 | maintainer="mdeshmuk@redhat.com" 5 | 6 | # Building the user-group microservice 7 | ADD . /app 8 | WORKDIR /app 9 | RUN npm install --silent && \ 10 | npm run build 11 | 12 | ENV PORT 8080 13 | EXPOSE 8080 14 | 15 | CMD [ "node", "dist/index.js"] 16 | -------------------------------------------------------------------------------- /packages/analytics-service/esbuild.config.js: -------------------------------------------------------------------------------- 1 | const { build } = require('esbuild'); 2 | const graphqlLoaderPlugin = require('@luckycatfactory/esbuild-graphql-loader').default; 3 | 4 | build({ 5 | entryPoints: ['./src/index.ts'], 6 | minify: true, 7 | platform: 'node', 8 | bundle: true, 9 | target: 'node16', 10 | outfile: 'dist/index.js', 11 | plugins: [graphqlLoaderPlugin()], 12 | }).catch(() => { 13 | process.exit(1); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/analytics-service/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | testMatch: ['/src/**/*.spec.ts'], 6 | verbose: true, 7 | transform: { 8 | '^.+\\.(ts|tsx|js)$': 'ts-jest', 9 | '\\.(gql|graphql)$': 'jest-transform-graphql', 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /packages/analytics-service/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: 'Analytics Service' 2 | 3 | nav: 4 | - Getting Started: index.md 5 | 6 | plugins: 7 | - techdocs-core 8 | -------------------------------------------------------------------------------- /packages/analytics-service/src/@types/graph.d.ts: -------------------------------------------------------------------------------- 1 | import DataLoader from 'dataloader'; 2 | 3 | import { AnalyticsConfig } from 'datasource/analyticConfigDB'; 4 | import { MatomoAPI } from 'datasource/matomoAPI'; 5 | import { SentryAPI } from 'datasource/sentryAPI'; 6 | 7 | declare global { 8 | type IContext = { 9 | dataSources: { 10 | analyticsConfig: AnalyticsConfig; 11 | sentryAPI: SentryAPI; 12 | matomoAPI: MatomoAPI; 13 | }; 14 | loaders: { 15 | user: DataLoader; 16 | }; 17 | user: { id?: string }; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /packages/analytics-service/src/@types/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.graphql'; 2 | -------------------------------------------------------------------------------- /packages/analytics-service/src/@types/user.d.ts: -------------------------------------------------------------------------------- 1 | type User = { 2 | cn: string; 3 | mail: string; 4 | uid: string; 5 | rhatUUID: string; 6 | rhatJobTitle: string; 7 | }; 8 | -------------------------------------------------------------------------------- /packages/analytics-service/src/__tests__/mocks/mockDatabase.ts: -------------------------------------------------------------------------------- 1 | import { MongoMemoryServer } from 'mongodb-memory-server'; 2 | import mongoose from 'mongoose'; 3 | 4 | const mongod = MongoMemoryServer.create(); 5 | 6 | export async function setupMockDatabase() { 7 | const uri = (await mongod).getUri(); 8 | 9 | await mongoose.connect(uri); 10 | } 11 | 12 | export async function disconnectMockDatabase() { 13 | await mongoose.disconnect(); 14 | } 15 | -------------------------------------------------------------------------------- /packages/analytics-service/src/db/types.ts: -------------------------------------------------------------------------------- 1 | export type AnalyticsDoc = { 2 | appId: string; 3 | sentryProjectId: string; 4 | sentryTeamId: string; 5 | matomoSiteId: string; 6 | createdBy: string; 7 | updatedBy: string; 8 | }; 9 | -------------------------------------------------------------------------------- /packages/analytics-service/src/graph/analyticsConfig/typedef.graphql: -------------------------------------------------------------------------------- 1 | scalar DateTime 2 | 3 | type User { 4 | cn: String 5 | mail: String 6 | uid: String 7 | rhatUUID: String 8 | rhatJobTitle: String 9 | } 10 | 11 | type AnalyticsConfig { 12 | id: ID 13 | appId: String 14 | crashlytics: Crashlytics 15 | userAnalytics: UserAnalytics 16 | createdBy: User 17 | createdOn: DateTime 18 | updatedBy: User 19 | updatedOn: DateTime 20 | } 21 | 22 | type Query { 23 | getAnalyticsConfigByAppId(appId: String!): AnalyticsConfig 24 | } 25 | -------------------------------------------------------------------------------- /packages/analytics-service/src/graph/errors.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLError } from 'graphql'; 2 | 3 | export const ErrUnauthorizedAccess = new GraphQLError('Unauthorized access', { 4 | extensions: { code: 'FORBIDDEN' }, 5 | }); 6 | -------------------------------------------------------------------------------- /packages/analytics-service/src/graph/types.ts: -------------------------------------------------------------------------------- 1 | export type Maybe = T | null; 2 | -------------------------------------------------------------------------------- /packages/analytics-service/src/helpers/index.ts: -------------------------------------------------------------------------------- 1 | export { buildUserQuery } from './buildUserQuery'; 2 | -------------------------------------------------------------------------------- /packages/analytics-service/src/index.ts: -------------------------------------------------------------------------------- 1 | import 'graphql-import-node'; 2 | 3 | import { graphqlSchema, setupMongoose, startApolloServer } from './app'; 4 | 5 | (async function main() { 6 | await setupMongoose(); 7 | await startApolloServer(graphqlSchema); 8 | })(); 9 | -------------------------------------------------------------------------------- /packages/analytics-service/src/logger.ts: -------------------------------------------------------------------------------- 1 | import pino, { Logger, LoggerOptions } from 'pino'; 2 | 3 | export const setupLogger = (): Logger => { 4 | const logger = pino(); 5 | 6 | return logger; 7 | }; 8 | -------------------------------------------------------------------------------- /packages/api-catalog-service/.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | README.md -------------------------------------------------------------------------------- /packages/api-catalog-service/.env.example: -------------------------------------------------------------------------------- 1 | ## Uncomment the lines as needed 2 | 3 | NODE_ENV=local 4 | PORT=8080 5 | 6 | ## Database 7 | MONGO_URI= 8 | 9 | ## Authorization Token 10 | API_GATEWAY_URL="http://api-gateway:8080/graphql" 11 | API_GATEWAY_TOKEN= 12 | NAMESPACE_ENCRYPTION_KEY= 13 | 14 | # Email Config 15 | # SMTP_HOST= 16 | 17 | # OUTAGE_STATUS_URL 18 | # RHAT_SERVICE_NOW_URL 19 | # RHAT_SERVICE_NOW_USERNAME 20 | # RHAT_SERVICE_NOW_PASSWORD 21 | -------------------------------------------------------------------------------- /packages/api-catalog-service/.gitignore: -------------------------------------------------------------------------------- 1 | # Development files 2 | node_modules 3 | .env 4 | .DS_Store 5 | 6 | # ignore dist 7 | dist 8 | 9 | # Logs 10 | npm-debug.log* 11 | -------------------------------------------------------------------------------- /packages/api-catalog-service/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "all", 4 | "singleQuote": true, 5 | "printWidth": 100, 6 | "tabWidth": 2 7 | } 8 | -------------------------------------------------------------------------------- /packages/api-catalog-service/.test.env: -------------------------------------------------------------------------------- 1 | NODE_ENV=local 2 | PORT=8080 3 | 4 | ## Database 5 | MONGO_URL="mongodb://mongo:27017/api-catalog" 6 | 7 | NODE_TLS_REJECT_UNAUTHORIZED=0 8 | 9 | ## Authorization Token 10 | API_GATEWAY="http://api-gateway:8080/api/graphql" 11 | GATEWAY_AUTH_TOKEN=# Api Key generated from api gateway 12 | 13 | # Client URLs 14 | SPA_URL="http://localhost:5500/developers/api-catalog" 15 | 16 | # Email Config 17 | SMTP_HOST="smtp.test.test.com" 18 | -------------------------------------------------------------------------------- /packages/api-catalog-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16-alpine 2 | LABEL Name=one-platform-api-catalog-service \ 3 | Version=0.4.3 \ 4 | maintainer="mdeshmuk@redhat.com" 5 | 6 | # Building the user-group microservice 7 | ADD . /app 8 | WORKDIR /app 9 | RUN npm install --silent && \ 10 | npm run build 11 | 12 | ENV PORT 8080 13 | EXPOSE 8080 8443 14 | 15 | CMD [ "node", "dist/index.js"] 16 | -------------------------------------------------------------------------------- /packages/api-catalog-service/docs/api-reference.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: api-ref 3 | title: API Reference 4 | slug: /api-catalog/api-ref 5 | sidebar_label: API Reference 6 | --- 7 | 8 | # API Reference 9 | 10 | Coming soon!!! 11 | -------------------------------------------------------------------------------- /packages/api-catalog-service/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: ['js', 'ts', 'tsx'], 3 | transform: { 4 | '^.+\\.(ts|tsx|js)$': 'ts-jest', 5 | '\\.(gql|graphql)$': 'jest-transform-graphql', 6 | }, 7 | globals: { 8 | 'ts-jest': { 9 | tsconfig: 'tsconfig.json', 10 | }, 11 | }, 12 | collectCoverage: true, 13 | testMatch: ['**/src/e2e/*.spec.(ts|tsx|js)'], 14 | testEnvironment: 'node', 15 | preset: 'ts-jest/presets/js-with-ts', 16 | }; 17 | -------------------------------------------------------------------------------- /packages/api-catalog-service/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: 'API Catalog Service' 2 | 3 | nav: 4 | - Getting Started: index.md 5 | - API Reference: api-reference.md 6 | - Guide: onboarding-guide.md 7 | - Overview: overview.md 8 | - FAQs: faqs.md 9 | 10 | plugins: 11 | - techdocs-core 12 | -------------------------------------------------------------------------------- /packages/api-catalog-service/src/@types/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.graphql'; 2 | declare module '*.json'; 3 | 4 | /* 5 | * Global Type Definitions. 6 | */ 7 | type ApiUserType = { 8 | cn?: string; 9 | mail?: string; 10 | uid?: string; 11 | rhatUUID?: string; 12 | rhatJobTitle?: string; 13 | }; 14 | /* 15 | * Namespace Type Definitions. 16 | */ 17 | 18 | type Pagination = { 19 | count: number; 20 | data: T; 21 | }; 22 | -------------------------------------------------------------------------------- /packages/api-catalog-service/src/@types/user.d.ts: -------------------------------------------------------------------------------- 1 | type IUser = { 2 | cn: string; 3 | mail: string; 4 | uid: string; 5 | rhatUUID: string; 6 | rhatJobTitle: string; 7 | }; 8 | -------------------------------------------------------------------------------- /packages/api-catalog-service/src/dataloaders/index.ts: -------------------------------------------------------------------------------- 1 | export { setupUserDataLoader } from './userLoader'; 2 | export { setupSubscriptionStatusLoader } from './subscriptionStatusLoader'; 3 | export { setupOutageStatusLoader } from './outageStatusLoader'; 4 | -------------------------------------------------------------------------------- /packages/api-catalog-service/src/datasources/specstoreDB.ts: -------------------------------------------------------------------------------- 1 | import { MongoDataSource } from 'apollo-datasource-mongodb'; 2 | import { Types } from 'mongoose'; 3 | import { SpecStoreModel } from 'db/specStore'; 4 | 5 | export class SpecStoreDB extends MongoDataSource { 6 | async deleteSpecsOfANamespace(namespaceId: string) { 7 | return this.model.deleteMany({ namespaceId: new Types.ObjectId(namespaceId) }); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/api-catalog-service/src/graph/subscription/typedef.graphql: -------------------------------------------------------------------------------- 1 | input SubscribeSchema { 2 | namespaceID: ID! 3 | schemaID: ID! 4 | envIDs: [String]! 5 | email: String! 6 | } 7 | 8 | type Mutation { 9 | subscribeApiSchema(config: SubscribeSchema!): NamespaceType 10 | } 11 | -------------------------------------------------------------------------------- /packages/api-catalog-service/src/logger.ts: -------------------------------------------------------------------------------- 1 | import pino, { Logger, LoggerOptions } from 'pino'; 2 | 3 | export const setupLogger = (): Logger => { 4 | const logger = pino(); 5 | 6 | return logger; 7 | }; 8 | -------------------------------------------------------------------------------- /packages/api-catalog-service/src/mailer.ts: -------------------------------------------------------------------------------- 1 | import nodemailer from 'nodemailer'; 2 | import SMTPTransport from 'nodemailer/lib/smtp-transport'; 3 | 4 | export const setupNodeMailer = (options: SMTPTransport.Options) => { 5 | return nodemailer.createTransport(options); 6 | }; 7 | -------------------------------------------------------------------------------- /packages/api-catalog-service/src/specsheet/index.ts: -------------------------------------------------------------------------------- 1 | export { fetchSchema } from './fetchSchema'; 2 | export { isValidGraphqlSchema } from './isValidGraphqlSchema'; 3 | export { isValidOpenAPI } from './isValidOpenAPI'; 4 | export { validateSpecSheet } from './validateSpecSheet'; 5 | -------------------------------------------------------------------------------- /packages/api-catalog-service/src/specsheet/isValidGraphqlSchema.ts: -------------------------------------------------------------------------------- 1 | export const isValidGraphqlSchema = (introspectionData: string): boolean => { 2 | try { 3 | JSON.parse(introspectionData); 4 | return true; 5 | } catch { 6 | return false; 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /packages/api-catalog-service/src/subscriptions/index.ts: -------------------------------------------------------------------------------- 1 | export { setupCronTask } from './setupCronTask'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-service/src/utils/arrayPartition.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This function is used to filter an array and based on filtering 3 | * Obtain two array of passing and failing condition 4 | */ 5 | export const arrayPartition = ( 6 | arr: T[], 7 | cb: (arg0: T) => boolean, 8 | ): [T[], T[]] => { 9 | const pass: T[] = []; 10 | const fail: T[] = []; 11 | arr.forEach((el) => (cb(el) ? pass.push(el) : fail.push(el))); 12 | 13 | return [pass, fail]; 14 | }; 15 | -------------------------------------------------------------------------------- /packages/api-catalog-service/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { arrayPartition } from './arrayPartition'; 2 | export { deepMergeByKey } from './deepMergeByKey'; 3 | export { jsonOrYamlFormat } from './jsonOrYamlFormat'; 4 | export { encrypt, decrypt } from './encryption'; 5 | -------------------------------------------------------------------------------- /packages/api-catalog-service/src/utils/jsonOrYamlFormat.ts: -------------------------------------------------------------------------------- 1 | import yaml from 'js-yaml'; 2 | 3 | export const jsonOrYamlFormat = (file: string): string => { 4 | try { 5 | JSON.parse(file); 6 | return 'json'; 7 | } catch { 8 | try { 9 | yaml.load(file); 10 | return 'yaml'; 11 | } catch (error) { 12 | throw Error('Invalid format'); 13 | } 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/.env.example: -------------------------------------------------------------------------------- 1 | VITE_API_URL= 2 | 3 | VITE_OPC_BASE_API_URL= 4 | VITE_OPC_BASE_SUBSCRIPTION_URL= 5 | VITE_OPC_BASE_KEYCLOAK_IDP_URL= 6 | VITE_OPC_BASE_KEYCLOAK_CLIENT_ID= 7 | VITE_OPC_BASE_KEYCLOAK_REALM= 8 | 9 | # VITE_SENTRY_DSN= 10 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "tabWidth": 2, 4 | "semi": true, 5 | "printWidth": 100 6 | } 7 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/.test.env: -------------------------------------------------------------------------------- 1 | 2 | VITE_API_URL='http://test.com/api/graphql' 3 | VITE_OPC_BASE_API_URL='http://test/api/graphql' 4 | VITE_OPC_BASE_SUBSCRIPTION_URL='wss://qa.test.com/api/graphql/subscriptions' 5 | VITE_OPC_BASE_KEYCLOAK_IDP_URL='https://auth.test.test.com/auth' 6 | VITE_OPC_BASE_KEYCLOAK_CLIENT_ID='one-portal' 7 | VITE_OPC_BASE_KEYCLOAK_REALM='EmployeeIDP' 8 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@babel/preset-env'], 3 | }; 4 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1-Platform/one-platform/d6fb518a8b9c9d94847ab168a0baf6ffea5cfe33/packages/api-catalog-spa/public/favicon.ico -------------------------------------------------------------------------------- /packages/api-catalog-spa/public/images/info-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/public/images/redoc-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1-Platform/one-platform/d6fb518a8b9c9d94847ab168a0baf6ffea5cfe33/packages/api-catalog-spa/public/images/redoc-logo.png -------------------------------------------------------------------------------- /packages/api-catalog-spa/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "API Catalog", 3 | "name": "One Platform | API Catalog", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/spaship.yaml: -------------------------------------------------------------------------------- 1 | # SPAship config file 2 | # generated by @spaship/common.config v0.14.0 3 | 4 | name: op-api-catalog 5 | path: /developers/api-catalog 6 | single: true 7 | buildDir: dist 8 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/components/CatalogBigButton/index.tsx: -------------------------------------------------------------------------------- 1 | export { CatalogBigButton } from './CatalogBigButton'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/components/ConditionalWrapper/ConditionalWrapper.tsx: -------------------------------------------------------------------------------- 1 | interface Props { 2 | children: JSX.Element; 3 | isWrapped: boolean; 4 | wrapper: (child: JSX.Element) => JSX.Element; 5 | } 6 | 7 | export const ConditionalWrapper = ({ isWrapped, wrapper, children }: Props) => 8 | isWrapped ? wrapper(children) : children; 9 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/components/ConditionalWrapper/index.tsx: -------------------------------------------------------------------------------- 1 | export { ConditionalWrapper } from './ConditionalWrapper'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/components/Loader/Loader.test.tsx: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import { Loader } from './Loader'; 3 | 4 | test('renders Loader', () => { 5 | render(); 6 | const linkElement = screen.getByText(/Loading.../i); 7 | expect(linkElement).toBeDefined(); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/components/Loader/Loader.tsx: -------------------------------------------------------------------------------- 1 | import { EmptyState, EmptyStateIcon, Spinner, Text } from '@patternfly/react-core'; 2 | 3 | export const Loader = (): JSX.Element => { 4 | return ( 5 | 6 | 7 | Loading... 8 | 9 | ); 10 | }; 11 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/components/Loader/index.tsx: -------------------------------------------------------------------------------- 1 | export { Loader } from './Loader'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/components/ReadMore/ReadMore.test.tsx: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import { ReadMore } from './ReadMore'; 3 | 4 | describe('Readmore Button', () => { 5 | test('When text is under a limit', () => { 6 | render(Hello world); 7 | expect(screen.queryByText(/...Read more/i)).toBeNull(); 8 | expect(screen.queryByText(/Show less/i)).toBeNull(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/components/ReadMore/index.tsx: -------------------------------------------------------------------------------- 1 | export { ReadMore } from './ReadMore'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/components/forms/AsyncSelect/index.tsx: -------------------------------------------------------------------------------- 1 | export { AsyncSelect } from './AsyncSelect'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/components/forms/Select/index.tsx: -------------------------------------------------------------------------------- 1 | export { Select } from './Select'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/components/index.tsx: -------------------------------------------------------------------------------- 1 | export { Loader } from './Loader'; 2 | export { CatalogBigButton } from './CatalogBigButton'; 3 | export { Select } from './forms/Select'; 4 | export { AsyncSelect } from './forms/AsyncSelect'; 5 | export { ReadMore } from './ReadMore'; 6 | export { ConditionalWrapper } from './ConditionalWrapper'; 7 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/context/BreadcrumbContext/index.tsx: -------------------------------------------------------------------------------- 1 | export { BreadcrumbProvider, useBreadcrumb } from './BreadcrumbContext'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/context/BreadcrumbContext/types.ts: -------------------------------------------------------------------------------- 1 | export type Breadcrumb = { 2 | label: string; 3 | url: string; 4 | }; 5 | 6 | export type BreadcrumbContextProps = { 7 | handleDynamicCrumbs: (crumb: Record) => void; 8 | breadcrumbs: Breadcrumb[]; 9 | }; 10 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/context/RecentVisitContext/index.tsx: -------------------------------------------------------------------------------- 1 | export { RecentVisitProvider, useRecentVisit } from './RecentVisitContext'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/context/RecentVisitContext/types.ts: -------------------------------------------------------------------------------- 1 | export type RecentVisitLog = { 2 | title: string; 3 | tool: string; 4 | url: string; 5 | id: string; 6 | }; 7 | 8 | export type QuickLink = { 9 | id: string; 10 | name: string; 11 | envSlug: string; 12 | }; 13 | 14 | export type RecentVisitContextProps = { 15 | logs: RecentVisitLog[]; 16 | handleAddNewLog: (log: RecentVisitLog & { envSlug: string }) => void; 17 | handleRemoveLog: (logId: string) => void; 18 | quickLink: QuickLink; 19 | }; 20 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/hooks/index.tsx: -------------------------------------------------------------------------------- 1 | export { useToggle } from './useToggle'; 2 | export { useQuery } from './useQuery'; 3 | export { usePagination } from './usePagination'; 4 | export { useDebounce } from './useDebounce'; 5 | export { useQueryParams } from './useQueryParams'; 6 | export { useURQL } from './useURQL'; 7 | export { useURLParser } from './useURLParser'; 8 | export { useRegisterRecentVisit } from './useRegisterRecentVisit'; 9 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/hooks/useDebounce/index.tsx: -------------------------------------------------------------------------------- 1 | export { useDebounce } from './useDebounce'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/hooks/usePagination/index.tsx: -------------------------------------------------------------------------------- 1 | export { usePagination } from './usePagination'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/hooks/useQuery/index.tsx: -------------------------------------------------------------------------------- 1 | export { useQuery } from './useQuery'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/hooks/useQuery/types.ts: -------------------------------------------------------------------------------- 1 | import { CombinedError, OperationContext } from 'urql'; 2 | 3 | export type Props = { 4 | gql: string; 5 | variables?: T; 6 | }; 7 | 8 | export type UseQueryReturn = { 9 | isLoading: boolean; 10 | data?: T; 11 | error?: CombinedError; 12 | isError: boolean; 13 | reFetchQuery: (opts?: Partial | undefined) => void; 14 | }; 15 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/hooks/useQueryParams/index.tsx: -------------------------------------------------------------------------------- 1 | export { useQueryParams } from './useQueryParams'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/hooks/useQueryParams/useQueryParams.tsx: -------------------------------------------------------------------------------- 1 | import { useLocation } from 'react-router-dom'; 2 | 3 | export const useQueryParams = (): URLSearchParams => { 4 | return new URLSearchParams(useLocation().search); 5 | }; 6 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/hooks/useRegisterRecentVisit/index.tsx: -------------------------------------------------------------------------------- 1 | export { useRegisterRecentVisit } from './useRegisterRecentVisit'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/hooks/useToggle/index.tsx: -------------------------------------------------------------------------------- 1 | export { useToggle } from './useToggle'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/hooks/useURLParser/index.tsx: -------------------------------------------------------------------------------- 1 | export { useURLParser } from './useURLParser'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/hooks/useURLParser/useURLParser.test.tsx: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import { useURLParser } from './useURLParser'; 3 | 4 | const UseURLParser = () => { 5 | const parse = useURLParser(); 6 | 7 | return
{parse('https://test.com')}
; 8 | }; 9 | 10 | describe('useURLParser tests', () => { 11 | test('should remove protocol', () => { 12 | render(); 13 | expect(screen.getByText(/test.com/i)).toBeDefined(); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/hooks/useURQL/index.tsx: -------------------------------------------------------------------------------- 1 | export { useURQL } from './useURQL'; 2 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/hooks/useURQL/useURQL.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react'; 2 | import { Client, Context } from 'urql'; 3 | 4 | export const useURQL = (): Client => { 5 | return useContext(Context); 6 | }; 7 | -------------------------------------------------------------------------------- /packages/api-catalog-spa/src/layouts/AppLayout/components/Footer/Footer.test.tsx: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import { Footer } from './Footer'; 3 | 4 | describe('Footer tests', () => { 5 | test('should render footer', () => { 6 | render(