From 38cd215c7ceeb02e5128eca468258801d17a6310 Mon Sep 17 00:00:00 2001 From: blevine-transcend Date: Wed, 15 Jan 2025 23:34:11 +0000 Subject: [PATCH] Some infra, need to format graphql call --- src/codecs.ts | 55 ++++++++++++++++++- src/constants.ts | 6 ++ src/enums.ts | 1 + .../fetchAllSiloDiscoveryRecommendations.ts | 45 +++++++++++++++ src/graphql/gqls/index.ts | 1 + .../gqls/siloDiscoveryRecommendation.ts | 45 +++++++++++++++ 6 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 src/graphql/fetchAllSiloDiscoveryRecommendations.ts create mode 100644 src/graphql/gqls/siloDiscoveryRecommendation.ts diff --git a/src/codecs.ts b/src/codecs.ts index ae052b36..423e35f6 100644 --- a/src/codecs.ts +++ b/src/codecs.ts @@ -174,7 +174,7 @@ export const EnricherInput = t.intersection([ */ 'input-identifier': t.string, /** - * A regular expression that can be used to match on for cancelation + * A regular expression that can be used to match on for cancellation */ testRegex: t.string, /** @@ -1744,6 +1744,55 @@ export const AssessmentInput = t.intersection([ /** Type override */ export type AssessmentInput = t.TypeOf; +/** + * Input to define a silo discovery recommendation + * + * @see https://docs.transcend.io/docs/silo-discovery + */ +export const SiloDiscoveryRecommendation = t.intersection([ + t.type({ + /** The ID of the plugin that found this recommendation */ + pluginId: t.string, + /** The unique identifier for the resource */ + resourceId: t.string, + /** Timestamp of the plugin run that found this silo recommendation */ + lastDiscoveredAt: t.string, + /** The plugin that found this recommendation */ + plugin: t.string, // Assuming Plugin is a string, replace with appropriate type if necessary + /** The suggested catalog for this recommendation */ + suggestedCatalog: t.string, // Assuming Catalog is a string, replace with appropriate type if necessary + /** The raw inputs that were provided by the plugin as additionalContext and fed into our classifier */ + rawInputs: t.array(t.string), // Assuming PlaintextContext is a string, replace with appropriate type if necessary + }), + t.partial({ + /** The ISO country code for the AWS Region if applicable */ + country: t.string, + /** The ISO country subdivision code for the AWS Region if applicable */ + countrySubDivision: t.string, + /** The plaintext that we will pass into recommendation */ + plaintextContext: t.string, + /** The plugin configurations for the recommendation */ + pluginConfigurations: t.string, // Assuming DataSiloPluginConfigurations is a string + /** The AWS Region for data silo if applicable */ + region: t.string, + /** The custom title of the data silo recommendation */ + title: t.string, + /** The URL for more information about the recommendation */ + url: t.string, + /** The list of tags associated with the recommendation */ + tags: t.array(t.string), + /** The date the recommendation was created */ + createdAt: t.string, + /** The date the recommendation was last updated */ + updatedAt: t.string, + }), +]); + +/** Type override */ +export type SiloDiscoveryRecommendation = t.TypeOf< + typeof SiloDiscoveryRecommendation +>; + export const TranscendInput = t.partial({ /** * Action items @@ -1861,6 +1910,10 @@ export const TranscendInput = t.partial({ * The full list of assessment results */ assessments: t.array(AssessmentInput), + /** + * The full list of silo discovery recommendations + */ + siloDiscoveryRecommendations: t.array(SiloDiscoveryRecommendation), }); /** Type override */ diff --git a/src/constants.ts b/src/constants.ts index 6285342c..2d2a56ab 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -71,6 +71,9 @@ export const TR_PUSH_RESOURCE_SCOPE_MAP: { [TranscendPullResource.Policies]: [ScopeName.ManagePolicies], [TranscendPullResource.Assessments]: [ScopeName.ManageAssessments], [TranscendPullResource.AssessmentTemplates]: [ScopeName.ManageAssessments], + [TranscendPullResource.SiloDiscoveryRecommendations]: [ + ScopeName.ManageDataMap, + ], }; /** @@ -114,6 +117,7 @@ export const TR_PULL_RESOURCE_SCOPE_MAP: { [TranscendPullResource.Policies]: [ScopeName.ViewPolicies], [TranscendPullResource.Assessments]: [ScopeName.ViewAssessments], [TranscendPullResource.AssessmentTemplates]: [ScopeName.ViewAssessments], + [TranscendPullResource.SiloDiscoveryRecommendations]: [ScopeName.ViewDataMap], }; export const TR_YML_RESOURCE_TO_FIELD_NAME: Record< @@ -150,4 +154,6 @@ export const TR_YML_RESOURCE_TO_FIELD_NAME: Record< [TranscendPullResource.Policies]: 'policies', [TranscendPullResource.Assessments]: 'assessments', [TranscendPullResource.AssessmentTemplates]: 'assessment-templates', + [TranscendPullResource.SiloDiscoveryRecommendations]: + 'siloDiscoveryRecommendations', }; diff --git a/src/enums.ts b/src/enums.ts index b5aca7de..72de8e1b 100644 --- a/src/enums.ts +++ b/src/enums.ts @@ -47,6 +47,7 @@ export enum TranscendPullResource { Messages = 'messages', Assessments = 'assessments', AssessmentTemplates = 'assessmentTemplates', + SiloDiscoveryRecommendations = 'siloDiscoveryRecommendations', } /** diff --git a/src/graphql/fetchAllSiloDiscoveryRecommendations.ts b/src/graphql/fetchAllSiloDiscoveryRecommendations.ts new file mode 100644 index 00000000..e51d1797 --- /dev/null +++ b/src/graphql/fetchAllSiloDiscoveryRecommendations.ts @@ -0,0 +1,45 @@ +import { GraphQLClient } from 'graphql-request'; +import { SILO_DISCOVERY_RECOMMENDATIONS } from './gqls'; +import { makeGraphQLRequest } from './makeGraphQLRequest'; + +export interface SiloDiscoveryRecommendation {} + +const PAGE_SIZE = 20; + +/** + * Fetch all silo discovery recommendations in the organization + * + * @param client - GraphQL client + * @returns All silo discovery recommendations in the organization + */ +export async function fetchAllSiloDiscoveryRecommendations( + client: GraphQLClient, +): Promise { + const siloDiscoveryRecommendations: SiloDiscoveryRecommendation[] = []; + let offset = 0; + + // Whether to continue looping + let shouldContinue = false; + do { + const { + siloDiscoveryRecommendations: { nodes }, + // eslint-disable-next-line no-await-in-loop + } = await makeGraphQLRequest<{ + /** Silo Discovery Recommendations */ + siloDiscoveryRecommendations: { + /** List */ + nodes: SiloDiscoveryRecommendation[]; + }; + }>(client, SILO_DISCOVERY_RECOMMENDATIONS, { + first: PAGE_SIZE, + offset, + }); + siloDiscoveryRecommendations.push(...nodes); + offset += PAGE_SIZE; + shouldContinue = nodes.length === PAGE_SIZE; + } while (shouldContinue); + + return siloDiscoveryRecommendations.sort((a, b) => + a.title.localeCompare(b.title), + ); +} diff --git a/src/graphql/gqls/index.ts b/src/graphql/gqls/index.ts index 24b61da2..6e781305 100644 --- a/src/graphql/gqls/index.ts +++ b/src/graphql/gqls/index.ts @@ -46,3 +46,4 @@ export * from './vendor'; export * from './dataCategory'; export * from './processingPurpose'; export * from './sombraVersion'; +export * from './siloDiscoveryRecommendation'; diff --git a/src/graphql/gqls/siloDiscoveryRecommendation.ts b/src/graphql/gqls/siloDiscoveryRecommendation.ts new file mode 100644 index 00000000..111e36ba --- /dev/null +++ b/src/graphql/gqls/siloDiscoveryRecommendation.ts @@ -0,0 +1,45 @@ +import { gql } from 'graphql-request'; + +export const SILO_DISCOVERY_RECOMMENDATIONS = gql` + query TranscendCliVendors($first: Int!, $offset: Int!) { + vendors( + first: $first + offset: $offset + useMaster: false + isExportCsv: true + orderBy: [ + { field: createdAt, direction: ASC } + { field: title, direction: ASC } + ] + ) { + nodes { + id + title + description + dataProcessingAgreementLink + contactName + contactEmail + contactPhone + address + headquarterCountry + headquarterSubDivision + websiteUrl + businessEntity { + title + } + teams { + name + } + owners { + email + } + attributeValues { + attributeKey { + name + } + name + } + } + } + } +`;