{"version":3,"file":"pullUnstructuredSubDataPointRecommendations-B9xIDPf2.mjs","names":[],"sources":["../src/lib/graphql/gqls/entry.ts","../src/lib/data-inventory/pullUnstructuredSubDataPointRecommendations.ts"],"sourcesContent":["import { gql } from 'graphql-request';\n\nexport const ENTRY_COUNT = gql`\n  query TranscendCliEntryCount($filterBy: UnstructuredSubDataPointRecommendationsFilterInput) {\n    unstructuredSubDataPointRecommendations(filterBy: $filterBy, useMaster: false) {\n      totalCount\n    }\n  }\n`;\n","import type { UnstructuredSubDataPointRecommendationStatus } from '@transcend-io/privacy-types';\nimport { makeGraphQLRequest } from '@transcend-io/sdk';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\nimport { gql, type GraphQLClient } from 'graphql-request';\nimport { sortBy } from 'lodash-es';\n\nimport type { DataCategoryInput } from '../../codecs.js';\nimport { logger } from '../../logger.js';\nimport { ENTRY_COUNT } from '../graphql/index.js';\n\ninterface UnstructuredSubDataPointRecommendationCsvPreview {\n  /** ID of subDatapoint */\n  id: string;\n  /** Entry or Named Entity recognized by the classifier */\n  name: string;\n  /** Context snippet including entry */\n  contextSnippet: string;\n  /** Scanned object ID */\n  scannedObjectId: string;\n  /** Scanned object path ID */\n  scannedObjectPathId: string;\n  /** The data silo ID */\n  dataSiloId: string;\n  /** Personal data category */\n  dataSubCategory: DataCategoryInput;\n  /** Classification Status */\n  status: UnstructuredSubDataPointRecommendationStatus;\n  /** Confidence */\n  confidence: number;\n  /** Classification method */\n  classificationMethod: string;\n  /** Classifier version */\n  classifierVersion: string;\n}\n\ninterface EntryFilterOptions {\n  /** IDs of data silos to filter down */\n  dataSiloIds?: string[];\n  /** Parent categories to filter down for */\n  status?: UnstructuredSubDataPointRecommendationStatus[];\n  /** Sub categories to filter down for */\n  subCategories?: string[]; // TODO: https://transcend.height.app/T-40482 - do by name not ID\n  /** Include entry and snippet */\n  includeEncryptedSnippets?: boolean;\n  /** Include encryptedSamplesS3Key */\n  includeEncryptedSamplesS3Key?: boolean;\n}\n/**\n * Pull unstructured subdatapoint information\n *\n * @param client - Client to use for the request\n * @param options - Options\n * @param options.dataSiloIds - IDs of data silos to filter down\n * @param options.status - Parent categories to filter down for\n * @param options.subCategories - Sub categories to filter down for\n * @param options.includeEncryptedSnippets - Include entry and snippet\n * @param options.includeEncryptedSamplesS3Key - Include encryptedSamplesS3Key\n * @param options.pageSize - Page size to pull in\n * @returns A promise that resolves to an array of unstructured subdatapoint recommendations\n */\nexport async function pullUnstructuredSubDataPointRecommendations(\n  client: GraphQLClient,\n  {\n    dataSiloIds = [],\n    status,\n    subCategories = [],\n    includeEncryptedSnippets,\n    pageSize = 100,\n  }: EntryFilterOptions & {\n    /** Page size to pull in */\n    pageSize?: number;\n  } = {},\n): Promise<UnstructuredSubDataPointRecommendationCsvPreview[]> {\n  const unstructuredSubDataPointRecommendations: UnstructuredSubDataPointRecommendationCsvPreview[] =\n    [];\n\n  // Time duration\n  const t0 = new Date().getTime();\n\n  // create a new progress bar instance and use shades_classic theme\n  const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n  // Filters\n  const filterBy = {\n    ...(subCategories.length > 0 ? { subCategoryIds: subCategories } : {}),\n    ...(status ? { status } : {}),\n    ...(dataSiloIds.length > 0 ? { dataSilos: dataSiloIds } : {}),\n  };\n\n  // Build a GraphQL client\n  const {\n    unstructuredSubDataPointRecommendations: { totalCount },\n  } = await makeGraphQLRequest<{\n    /** Query response */\n    unstructuredSubDataPointRecommendations: {\n      /** Count */\n      totalCount: number;\n    };\n  }>(client, ENTRY_COUNT, {\n    variables: { filterBy },\n    logger,\n  });\n\n  logger.info(colors.magenta('[Step 1/3] Pulling in all subdatapoints'));\n\n  progressBar.start(totalCount, 0);\n  let total = 0;\n  let shouldContinue = false;\n  let cursor: string | undefined;\n  let offset = 0;\n  do {\n    try {\n      const {\n        unstructuredSubDataPointRecommendations: { nodes },\n      } = await makeGraphQLRequest<{\n        /** Query response */\n        unstructuredSubDataPointRecommendations: {\n          /** List of matches */\n          nodes: UnstructuredSubDataPointRecommendationCsvPreview[];\n        };\n      }>(\n        client,\n        gql`\n          query TranscendCliUnstructuredSubDataPointRecommendationCsvExport(\n            $filterBy: UnstructuredSubDataPointRecommendationsFilterInput\n            $first: Int!\n            $offset: Int!\n          ) {\n            unstructuredSubDataPointRecommendations(\n              filterBy: $filterBy\n              first: $first\n              offset: $offset\n              useMaster: false\n            ) {\n              nodes {\n                id\n                dataSiloId\n                scannedObjectPathId\n                scannedObjectId\n                ${includeEncryptedSnippets ? 'name' : ''}\n                ${includeEncryptedSnippets ? 'contextSnippet' : ''}\n                dataSubCategory {\n                  name\n                  category\n                }\n                status\n                confidence\n                classificationMethod\n                classifierVersion\n              }\n            }\n          }\n        `,\n        {\n          variables: {\n            first: pageSize,\n            offset,\n            filterBy: {\n              ...filterBy,\n            },\n          },\n          logger,\n        },\n      );\n\n      cursor = nodes[nodes.length - 1]?.id as string;\n      unstructuredSubDataPointRecommendations.push(...nodes);\n      shouldContinue = nodes.length === pageSize;\n      total += nodes.length;\n      offset += nodes.length;\n      progressBar.update(total);\n    } catch (err) {\n      logger.error(\n        colors.red(`An error fetching subdatapoints for cursor ${cursor} and offset ${offset}`),\n      );\n      throw err;\n    }\n  } while (shouldContinue);\n\n  progressBar.stop();\n  const t1 = new Date().getTime();\n  const totalTime = t1 - t0;\n\n  const sorted = sortBy(unstructuredSubDataPointRecommendations, 'name');\n\n  logger.info(\n    colors.green(\n      `Successfully pulled in ${sorted.length} subdatapoints in ${totalTime / 1000} seconds!`,\n    ),\n  );\n  return sorted;\n}\n"],"mappings":"4NAEA,MAAa,EAAc,CAAG;;;;;;EC2D9B,eAAsB,EACpB,EACA,CACE,cAAc,EAAE,CAChB,SACA,gBAAgB,EAAE,CAClB,2BACA,WAAW,KAIT,EAAE,CACuD,CAC7D,IAAM,EACJ,EAAE,CAGE,EAAK,IAAI,MAAM,CAAC,SAAS,CAGzB,EAAc,IAAI,EAAY,UAAU,EAAE,CAAE,EAAY,QAAQ,eAAe,CAG/E,EAAW,CACf,GAAI,EAAc,OAAS,EAAI,CAAE,eAAgB,EAAe,CAAG,EAAE,CACrE,GAAI,EAAS,CAAE,SAAQ,CAAG,EAAE,CAC5B,GAAI,EAAY,OAAS,EAAI,CAAE,UAAW,EAAa,CAAG,EAAE,CAC7D,CAGK,CACJ,wCAAyC,CAAE,eACzC,MAAM,EAMP,EAAQ,EAAa,CACtB,UAAW,CAAE,WAAU,CACvB,SACD,CAAC,CAEF,EAAO,KAAK,EAAO,QAAQ,0CAA0C,CAAC,CAEtE,EAAY,MAAM,EAAY,EAAE,CAChC,IAAI,EAAQ,EACR,EAAiB,GACjB,EACA,EAAS,EACb,EACE,IAAI,CACF,GAAM,CACJ,wCAAyC,CAAE,UACzC,MAAM,EAOR,EACA,CAAG;;;;;;;;;;;;;;;;;kBAiBO,EAA2B,OAAS,GAAG;kBACvC,EAA2B,iBAAmB,GAAG;;;;;;;;;;;;UAa3D,CACE,UAAW,CACT,MAAO,EACP,SACA,SAAU,CACR,GAAG,EACJ,CACF,CACD,SACD,CACF,CAED,EAAS,EAAM,EAAM,OAAS,IAAI,GAClC,EAAwC,KAAK,GAAG,EAAM,CACtD,EAAiB,EAAM,SAAW,EAClC,GAAS,EAAM,OACf,GAAU,EAAM,OAChB,EAAY,OAAO,EAAM,OAClB,EAAK,CAIZ,MAHA,EAAO,MACL,EAAO,IAAI,8CAA8C,EAAO,cAAc,IAAS,CACxF,CACK,QAED,GAET,EAAY,MAAM,CAElB,IAAM,EADK,IAAI,MAAM,CAAC,SACF,CAAG,EAEjB,EAAS,EAAO,EAAyC,OAAO,CAOtE,OALA,EAAO,KACL,EAAO,MACL,0BAA0B,EAAO,OAAO,oBAAoB,EAAY,IAAK,WAC9E,CACF,CACM"}