{"version":3,"file":"command-B5cyFEbQ.mjs","names":[],"sources":["../src/lib/cli/parsers.ts","../src/lib/cli/common-parameters.ts","../src/commands/inventory/pull/command.ts"],"sourcesContent":["import ms, { type StringValue as MsStringValue } from 'ms';\n\n/**\n * Validates and returns a UUID string.\n *\n * @param input - The input string to validate as UUID\n * @returns The validated UUID string\n * @throws Error if input is not a valid UUID\n */\nexport function uuidParser(input: string): string {\n  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n  if (!uuidRegex.test(input)) {\n    throw new Error(`Invalid UUID format: ${input}`);\n  }\n  return input;\n}\n\n/**\n * Validates and returns a URL string.\n *\n * @param input - The input string to validate as URL\n * @returns The validated URL string\n * @throws Error if input is not a valid URL\n */\nexport function urlParser(input: string): string {\n  try {\n    const url = new URL(input);\n    return url.toString().replace(/\\/$/, '');\n  } catch {\n    throw new Error(`Invalid URL format: ${input}`);\n  }\n}\n\n/**\n * Parse a comma-separated string to array.\n * NOTE: Prefer using `variadic` for list arguments instead of this function. This should only be used for arguments which have a default value.\n *\n * @param input - The comma-separated string to parse\n * @returns Array of trimmed, non-empty strings\n */\nexport function arrayParser(input: string): string[] {\n  return input\n    .split(',')\n    .map((s) => s.trim())\n    .filter((s) => s.length > 0);\n}\n\n/**\n * Parse a date string to a Date object.\n *\n * @param input - The date string to parse\n * @returns The parsed Date object\n * @throws TypeError if input is not a valid date\n */\nexport function dateParser(input: string): Date {\n  const date = new Date(input);\n  if (Number.isNaN(date.getTime())) {\n    throw new TypeError(\n      `Invalid date: ${input}. Try using the ISO 8601 format (YYYY-MM-DDTHH:MM:SS.SSSZ)`,\n    );\n  }\n  return date;\n}\n\n/**\n * Parse a duration string to milliseconds.\n * Accepts concise/natural-ish strings (powered by `ms`) and returns milliseconds.\n * Examples: \"3600\", \"2d\", \"1h\", \"90 minutes\", \"10s\".\n *\n * @param input - The duration to parse\n * @returns The parsed duration in milliseconds\n * @throws Error if input is not a valid duration\n */\nexport function parseDurationToMs(input: unknown): number {\n  if (typeof input === 'number' && Number.isFinite(input)) {\n    // backward-compat: numbers => seconds\n    return Math.round(input * 1000);\n  }\n\n  if (typeof input === 'string') {\n    const trimmed = input.trim();\n    // empty string → our standardized error (avoid ms throwing its own)\n    if (trimmed === '') {\n      throw new Error('Invalid duration. Examples: \"45\", \"2d\", \"1h\", \"90 minutes\", \"10s\".');\n    }\n\n    // bare numeric string => seconds (backward-compat)\n    const asNumber = Number(trimmed);\n    if (trimmed !== '' && Number.isFinite(asNumber)) {\n      return Math.round(asNumber * 1000);\n    }\n\n    // let ms parse human strings\n    let parsed: number | undefined;\n    try {\n      parsed = ms(trimmed as MsStringValue);\n    } catch {\n      // normalize ms' error to ours\n      throw new Error('Invalid duration. Examples: \"45\", \"2d\", \"1h\", \"90 minutes\", \"10s\".');\n    }\n    if (typeof parsed === 'number' && Number.isFinite(parsed)) {\n      return parsed;\n    }\n  }\n\n  throw new Error('Invalid duration. Examples: \"45\", \"2d\", \"1h\", \"90 minutes\", \"10s\".');\n}\n","import type { TypedFlagParameter } from '@stricli/core';\nimport { ScopeName, TRANSCEND_SCOPES } from '@transcend-io/privacy-types';\n\nimport {\n  DEFAULT_TRANSCEND_API,\n  DEFAULT_TRANSCEND_API_KEY,\n  DEFAULT_TRANSCEND_CONSENT_API,\n} from '../../constants.js';\nimport type { LocalContext } from '../../context.js';\nimport { urlParser } from './parsers.js';\n\n/**\n * Common parameter builders for CLI commands\n * These reduce duplication and ensure consistency across commands\n */\n\n/**\n * Creates a standard authentication parameter\n *\n * @param root0 - The scopes and whether it requires a silo scope\n * @returns The parameter object\n */\nexport const createAuthParameter = ({\n  scopes,\n  requiresSiloScope = false,\n}: {\n  /** The scopes required for the command */\n  scopes: ScopeName[] | 'Varies';\n  /** Whether the command requires a silo scope */\n  requiresSiloScope?: boolean;\n}): TypedFlagParameter<string, LocalContext> => {\n  const parameter = {\n    kind: 'parsed' as const,\n    parse: String,\n    brief:\n      'The Transcend API key. Defaults to the TRANSCEND_API_KEY environment variable when set, so --auth may be omitted if it is exported.',\n    // When TRANSCEND_API_KEY is exported, make the flag optional by seeding a\n    // default. When it is unset, omit `default` so the flag stays required.\n    ...(DEFAULT_TRANSCEND_API_KEY ? { default: DEFAULT_TRANSCEND_API_KEY } : {}),\n  };\n\n  if (requiresSiloScope) {\n    parameter.brief += ' This key must be associated with the data silo(s) being operated on.';\n  }\n\n  if (scopes === 'Varies') {\n    return {\n      ...parameter,\n      brief: `${\n        parameter.brief\n      } The scopes required will vary depending on the operation performed. If in doubt, the ${\n        TRANSCEND_SCOPES[ScopeName.FullAdmin].title\n      } scope will always work.`,\n    };\n  }\n\n  if (scopes.length === 0) {\n    return {\n      ...parameter,\n      brief: `${parameter.brief} No scopes are required for this command.`,\n    };\n  }\n\n  return {\n    ...parameter,\n    brief: `${parameter.brief} Requires scopes: ${scopes\n      .map((s) => `\"${TRANSCEND_SCOPES[s].title}\"`)\n      .join(', ')}`,\n  };\n};\n\n/**\n * Creates a standard Transcend URL parameter\n *\n * @param defaultUrl - The default URL to use if not provided\n * @returns The parameter object\n */\nexport const createTranscendUrlParameter = (\n  defaultUrl = DEFAULT_TRANSCEND_API,\n): TypedFlagParameter<string, LocalContext> => ({\n  kind: 'parsed',\n  parse: urlParser,\n  brief:\n    'URL of the Transcend backend. Use https://api.us.transcend.io for US hosting. Defaults to the TRANSCEND_API_URL environment variable when set, so --transcendUrl may be omitted if it is exported.',\n  default: defaultUrl,\n});\n\n/**\n * Creates a standard Consent URL parameter\n *\n * @param defaultUrl - The default URL to use if not provided\n * @returns The parameter object\n */\nexport const createConsentUrlParameter = (\n  defaultUrl = DEFAULT_TRANSCEND_CONSENT_API,\n): TypedFlagParameter<string, LocalContext> => ({\n  kind: 'parsed',\n  parse: urlParser,\n  brief:\n    'URL of the Transcend consent backend. Use https://consent.us.transcend.io for US hosting. Defaults to the TRANSCEND_CONSENT_API_URL environment variable when set, so --consentUrl may be omitted if it is exported.',\n  default: defaultUrl,\n});\n\n/**\n * Creates a standard Sombra authentication parameter\n *\n * @returns The parameter object\n */\nexport const createSombraAuthParameter = (): TypedFlagParameter<\n  string | undefined,\n  LocalContext\n> => ({\n  kind: 'parsed',\n  parse: String,\n  brief: 'The Sombra internal key, use for additional authentication when self-hosting Sombra',\n  optional: true,\n});\n","import { buildCommand, numberParser } from '@stricli/core';\nimport { ConsentTrackerStatus } from '@transcend-io/privacy-types';\n\nimport { TranscendPullResource } from '../../../enums.js';\nimport {\n  createAuthParameter,\n  createTranscendUrlParameter,\n} from '../../../lib/cli/common-parameters.js';\n\nexport const DEFAULT_TRANSCEND_PULL_RESOURCES = [\n  TranscendPullResource.DataSilos,\n  TranscendPullResource.Enrichers,\n  TranscendPullResource.Templates,\n  TranscendPullResource.ApiKeys,\n];\n\nexport const DEFAULT_CONSENT_TRACKER_STATUSES = Object.values(ConsentTrackerStatus);\n\nexport const pullCommand = buildCommand({\n  loader: async () => {\n    const { pull } = await import('./impl.js');\n    return pull;\n  },\n  parameters: {\n    flags: {\n      auth: createAuthParameter({\n        scopes: 'Varies',\n      }),\n      resources: {\n        kind: 'enum',\n        values: ['all', ...Object.values(TranscendPullResource)],\n        brief: `The different resource types to pull in. Defaults to ${DEFAULT_TRANSCEND_PULL_RESOURCES.join(\n          ',',\n        )}.`,\n        variadic: ',',\n        optional: true,\n      },\n      file: {\n        kind: 'parsed',\n        parse: String,\n        brief: 'Path to the YAML file to pull into',\n        default: './transcend.yml',\n      },\n      transcendUrl: createTranscendUrlParameter(),\n      dataSiloIds: {\n        kind: 'parsed',\n        parse: String,\n        variadic: ',',\n        brief: 'The UUIDs of the data silos that should be pulled into the YAML file',\n        optional: true,\n      },\n      integrationNames: {\n        kind: 'parsed',\n        parse: String,\n        variadic: ',',\n        brief: 'The types of integrations to pull down',\n        optional: true,\n      },\n      trackerStatuses: {\n        kind: 'enum',\n        values: Object.values(ConsentTrackerStatus),\n        variadic: ',',\n        brief: 'The statuses of consent manager trackers to pull down. Defaults to all statuses.',\n        optional: true,\n      },\n      pageSize: {\n        kind: 'parsed',\n        parse: numberParser,\n        brief: 'The page size to use when paginating over the API',\n        default: '50',\n      },\n      skipDatapoints: {\n        kind: 'boolean',\n        brief: 'When true, skip pulling in datapoints alongside data silo resource',\n        default: false,\n      },\n      skipSubDatapoints: {\n        kind: 'boolean',\n        brief: 'When true, skip pulling in subDatapoints alongside data silo resource',\n        default: false,\n      },\n      includeGuessedCategories: {\n        kind: 'boolean',\n        brief: 'When true, included guessed data categories that came from the content classifier',\n        default: false,\n      },\n      debug: {\n        kind: 'boolean',\n        brief: 'Set to true to include debug logs while pulling the configuration',\n        default: false,\n      },\n    },\n  },\n  docs: {\n    brief: 'Pull metadata from Transcend into transcend.yml',\n    fullDescription: `Generates a transcend.yml by pulling the configuration from your Transcend instance.\n\nThe API key needs various scopes depending on the resources being pulled (see the CLI's README for more details).\n\nThis command can be helpful if you are looking to:\n\n- Copy your data into another instance\n- Generate a transcend.yml file as a starting point to maintain parts of your data inventory in code.`,\n  },\n});\n"],"mappings":"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"}