{"version":3,"file":"fetchAllRequests-DP24WqrP.mjs","names":[],"sources":["../src/lib/graphql/fetchAllRequests.ts"],"sourcesContent":["import { LOCALE_KEY } from '@transcend-io/internationalization';\nimport {\n  RequestAction,\n  RequestOrigin,\n  RequestStatus,\n  IsoCountryCode,\n  IsoCountrySubdivisionCode,\n} from '@transcend-io/privacy-types';\nimport { makeGraphQLRequest } from '@transcend-io/sdk';\nimport { valuesOf } from '@transcend-io/type-utils';\nimport cliProgress from 'cli-progress';\nimport colors from 'colors';\nimport { GraphQLClient } from 'graphql-request';\nimport * as t from 'io-ts';\n\nimport { logger } from '../../logger.js';\nimport { REQUESTS, REQUESTS_COUNT } from './gqls/index.js';\n\nexport const RequestPurposeTrigger = t.type({\n  title: t.string,\n  name: t.string,\n  consent: t.boolean,\n  enrichedPreferences: t.array(\n    t.type({\n      topic: t.string,\n      selectValues: t.array(\n        t.type({\n          id: t.string,\n          name: t.string,\n          preferenceOption: t.type({\n            id: t.string,\n            slug: t.string,\n            title: t.type({\n              defaultMessage: t.string,\n            }),\n          }),\n        }),\n      ),\n      selectValue: t.type({\n        id: t.string,\n        name: t.string,\n      }),\n      preferenceTopic: t.type({\n        title: t.type({\n          defaultMessage: t.string,\n        }),\n        id: t.string,\n        slug: t.string,\n      }),\n      name: t.string,\n      id: t.string,\n      booleanValue: t.boolean,\n    }),\n  ),\n});\n\n/** Override type */\nexport type RequestPurposeTrigger = t.TypeOf<typeof RequestPurposeTrigger>;\n\nexport const PrivacyRequest = t.intersection([\n  t.type({\n    /** Request ID */\n    id: t.string,\n    /** Time request was made */\n    createdAt: t.string,\n    /** Email of request */\n    email: t.string,\n    /** The type of request */\n    type: valuesOf(RequestAction),\n    /** Link to request in Transcend dashboard */\n    link: t.string,\n    /** Whether request is in silent mode */\n    isSilent: t.boolean,\n    /** Where request was made */\n    origin: valuesOf(RequestOrigin),\n    /** Whether request is a test request */\n    isTest: t.boolean,\n    /** The core identifier of the request */\n    coreIdentifier: t.string,\n    /** Request details */\n    details: t.string,\n    /** Locale of request */\n    locale: valuesOf(LOCALE_KEY),\n    /** Status of request */\n    status: valuesOf(RequestStatus),\n    /** Type of data subject */\n    subjectType: t.string,\n    /** Country of request */\n    country: t.union([t.null, valuesOf(IsoCountryCode)]),\n    /** Subdivision of request */\n    countrySubDivision: t.union([t.null, valuesOf(IsoCountrySubdivisionCode)]),\n    /** Request attributes */\n    attributeValues: t.array(\n      t.type({\n        id: t.string,\n        attributeKey: t.type({ name: t.string, id: t.string }),\n        name: t.string,\n      }),\n    ),\n  }),\n  t.partial({\n    /** Days remaining until expired */\n    daysRemaining: t.union([t.null, t.number]),\n    /** Time when request was successfully completed */\n    successfullyCompletedAt: t.union([t.null, t.string]),\n    /** Purpose */\n    purpose: RequestPurposeTrigger,\n  }),\n]);\n\n/** Type override */\nexport type PrivacyRequest = t.TypeOf<typeof PrivacyRequest>;\n\nconst PAGE_SIZE = 100;\n\n/**\n * Fetch just the total count of requests matching a set of filters.\n * Useful for setting up a progress bar before streaming pages.\n *\n * @param client - GraphQL client\n * @param filterBy - Filter object (already serialized to ISO strings)\n * @returns The total count\n */\nexport async function fetchRequestsTotalCount(\n  client: GraphQLClient,\n  filterBy: Record<string, unknown>,\n): Promise<number> {\n  const {\n    requests: { totalCount },\n  } = await makeGraphQLRequest<{\n    /** Requests */\n    requests: {\n      /** Total count */\n      totalCount: number;\n    };\n  }>(client, REQUESTS_COUNT, { variables: { filterBy }, logger });\n  return totalCount;\n}\n\n/**\n * Fetch all requests matching a set of filters.\n *\n * When `onPage` is provided the function streams pages to the callback\n * and never accumulates nodes in memory — ideal for very large exports.\n * Without `onPage` the function returns all nodes in a single array\n * (existing behaviour, kept for backward compatibility).\n *\n * @param client - GraphQL client\n * @param options - Filter options\n * @returns List of requests (empty when using onPage)\n */\nexport async function fetchAllRequests(\n  client: GraphQLClient,\n  {\n    actions = [],\n    statuses = [],\n    origins = [],\n    text,\n    createdAtBefore,\n    createdAtAfter,\n    updatedAtBefore,\n    updatedAtAfter,\n    isTest,\n    isSilent,\n    isClosed,\n    requestIds = [],\n    onPage,\n  }: {\n    /** Actions to filter on */\n    actions?: RequestAction[];\n    /** Origins to filter on */\n    origins?: RequestOrigin[];\n    /** Statuses to filter on */\n    statuses?: RequestStatus[];\n    /** Filter for requests created before this date */\n    createdAtBefore?: Date;\n    /** Filter for requests created after this date */\n    createdAtAfter?: Date;\n    /** Filter for requests updated before this date */\n    updatedAtBefore?: Date;\n    /** Filter for requests updated after this date */\n    updatedAtAfter?: Date;\n    /** Filter for requests with a specific identifier */\n    text?: string;\n    /** Return test requests */\n    isTest?: boolean;\n    /** Return silent mode requests */\n    isSilent?: boolean;\n    /** Filter by whether request is active */\n    isClosed?: boolean;\n    /**\n     * Filter the list of requests for a set of IDs - these are applied\n     * at runtime while other filters are applied at the GraphQL level.\n     */\n    requestIds?: string[];\n    /** When provided, called with each page of nodes instead of accumulating in memory */\n    onPage?: (nodes: PrivacyRequest[]) => void | Promise<void>;\n  } = {},\n): Promise<PrivacyRequest[]> {\n  const streaming = !!onPage;\n\n  const filterBy = {\n    text,\n    type: actions.length > 0 ? actions : undefined,\n    status: statuses.length > 0 ? statuses : undefined,\n    origin: origins.length > 0 ? origins : undefined,\n    isTest,\n    isSilent,\n    isClosed,\n    createdAtBefore: createdAtBefore ? createdAtBefore.toISOString() : undefined,\n    createdAtAfter: createdAtAfter ? createdAtAfter.toISOString() : undefined,\n    updatedAtBefore: updatedAtBefore ? updatedAtBefore.toISOString() : undefined,\n    updatedAtAfter: updatedAtAfter ? updatedAtAfter.toISOString() : undefined,\n  };\n\n  // When streaming, the caller manages progress/logging — skip count query & bar\n  const t0 = new Date().getTime();\n  const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);\n\n  if (!streaming) {\n    logger.info(colors.magenta('Fetching requests...'));\n    const {\n      requests: { totalCount },\n    } = await makeGraphQLRequest<{\n      /** Requests */\n      requests: {\n        /** Total count */\n        totalCount: number;\n      };\n    }>(client, REQUESTS_COUNT, { variables: { filterBy }, logger });\n\n    if (totalCount > PAGE_SIZE) {\n      logger.info(colors.magenta(`Fetching ${totalCount} requests`));\n      progressBar.start(totalCount, 0);\n    }\n  }\n\n  const requests: PrivacyRequest[] = [];\n  let fetchedCount = 0;\n\n  // Paginate through all results\n  let cursor: string | undefined;\n  let shouldContinue = false;\n  do {\n    const {\n      requests: { nodes, pageInfo },\n    } = await makeGraphQLRequest<{\n      /** Requests */\n      requests: {\n        /** List */\n        nodes: PrivacyRequest[];\n        /** Pagination info */\n        pageInfo: {\n          /** Cursor for the last item */\n          endCursor: string | null;\n          /** Whether more pages exist */\n          hasNextPage: boolean;\n        };\n      };\n    }>(client, REQUESTS, {\n      variables: { first: PAGE_SIZE, after: cursor, filterBy },\n      logger,\n    });\n\n    if (streaming) {\n      await onPage!(nodes);\n    } else {\n      requests.push(...nodes);\n    }\n\n    fetchedCount += nodes.length;\n    cursor = pageInfo.endCursor ?? undefined;\n    if (!streaming) {\n      progressBar.update(fetchedCount);\n    }\n    shouldContinue = pageInfo.hasNextPage;\n  } while (shouldContinue);\n\n  if (!streaming) {\n    progressBar.stop();\n    const t1 = new Date().getTime();\n    const totalTime = t1 - t0;\n\n    logger.info(\n      colors.green(\n        `Completed fetching of ${fetchedCount} request in \"${totalTime / 1000}\" seconds.`,\n      ),\n    );\n  }\n\n  if (streaming) {\n    return [];\n  }\n\n  // Filter down requests by request ID\n  let allRequests = requests;\n  if (requestIds && requestIds.length > 0) {\n    allRequests = allRequests.filter((request) => requestIds.includes(request.id));\n    logger.info(\n      colors.green(\n        `Filtered down to ${allRequests.length} requests based on ${requestIds.length} provided IDs.`,\n      ),\n    );\n  }\n\n  return allRequests;\n}\n"],"mappings":"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"}