socket 0.14.48 → 0.14.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +6 -3
- package/dist/constants.js +2 -2
- package/dist/constants.js.map +1 -1
- package/dist/module-sync/cli.js +397 -299
- package/dist/module-sync/cli.js.map +1 -1
- package/dist/module-sync/npm.d.ts +5 -3
- package/dist/module-sync/npm.js +23 -9
- package/dist/module-sync/npm.js.map +1 -1
- package/dist/require/cli.js +397 -299
- package/dist/require/cli.js.map +1 -1
- package/package.json +6 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../../src/commands/action/core/classes.ts","../../src/commands/action/core/index.ts","../../src/commands/action/core/scm_comments.ts","../../src/commands/action/core/github.ts","../../src/commands/action/core/messages.ts","../../src/commands/action/run-action.ts","../../src/utils/output-formatting.ts","../../src/flags.ts","../../src/utils/meow-with-subcommands.ts","../../src/commands/action/cmd-action.ts","../../src/utils/api.ts","../../src/commands/analytics/display-analytics.ts","../../src/commands/analytics/cmd-analytics.ts","../../src/commands/audit-log/get-audit-log.ts","../../src/commands/audit-log/cmd-audit-log.ts","../../src/commands/cdxgen/run-cyclonedx.ts","../../src/commands/cdxgen/cmd-cdxgen.ts","../../src/commands/dependencies/find-dependencies.ts","../../src/commands/dependencies/cmd-dependencies.ts","../../src/commands/diff-scan/get-diff-scan.ts","../../src/commands/diff-scan/cmd-diff-scan-get.ts","../../src/commands/diff-scan/cmd-diff-scan.ts","../../src/commands/fix/run-fix.ts","../../src/commands/fix/cmd-fix.ts","../../src/utils/objects.ts","../../src/utils/strings.ts","../../src/utils/alert/severity.ts","../../src/commands/info/fetch-package-info.ts","../../src/commands/info/format-package-info.ts","../../src/commands/info/get-package-info.ts","../../src/commands/info/cmd-info.ts","../../src/commands/login/apply-login.ts","../../src/commands/login/attempt-login.ts","../../src/commands/login/cmd-login.ts","../../src/commands/logout/apply-logout.ts","../../src/commands/logout/attempt-logout.ts","../../src/commands/logout/cmd-logout.ts","../../src/commands/manifest/convert_gradle_to_maven.ts","../../src/commands/manifest/cmd-manifest-gradle.ts","../../src/commands/manifest/convert_sbt_to_maven.ts","../../src/commands/manifest/cmd-manifest-scala.ts","../../src/commands/manifest/cmd-manifest-auto.ts","../../src/commands/manifest/cmd-manifest-kotlin.ts","../../src/commands/manifest/cmd-manifest.ts","../../src/commands/npm/wrap-npm.ts","../../src/commands/npm/cmd-npm.ts","../../src/commands/npx/wrap-npx.ts","../../src/commands/npx/cmd-npx.ts","../../src/commands/oops/cmd-oops.ts","../../src/commands/optimize/deps-includes-by-agent.ts","../../src/utils/package-manager-detector.ts","../../src/commands/optimize/detect-and-validate-package-manager.ts","../../src/commands/optimize/get-dependency-entries.ts","../../src/commands/optimize/get-overrides-by-agent.ts","../../src/commands/optimize/get-workspace-globs.ts","../../src/commands/optimize/lock-includes-by-agent.ts","../../src/commands/optimize/ls-by-agent.ts","../../src/commands/optimize/update-manifest-by-agent.ts","../../src/commands/optimize/update-package-lock-json.ts","../../src/commands/optimize/apply-optimization.ts","../../src/commands/optimize/cmd-optimize.ts","../../src/commands/organizations/get-organizations.ts","../../src/commands/organizations/cmd-organizations.ts","../../src/commands/raw-npm/run-raw-npm.ts","../../src/commands/raw-npm/cmd-raw-npm.ts","../../src/commands/raw-npx/run-raw-npx.ts","../../src/commands/raw-npx/cmd-raw-npx.ts","../../src/commands/report/create-report.ts","../../src/commands/report/get-socket-config.ts","../../src/commands/report/fetch-report-data.ts","../../src/commands/report/format-report-data.ts","../../src/commands/report/view-report.ts","../../src/commands/report/cmd-report-create.ts","../../src/commands/report/cmd-report-view.ts","../../src/commands/report/cmd-report.ts","../../src/commands/repos/create-repo.ts","../../src/commands/repos/cmd-repos-create.ts","../../src/commands/repos/delete-repo.ts","../../src/commands/repos/cmd-repos-del.ts","../../src/commands/repos/list-repos.ts","../../src/commands/repos/cmd-repos-list.ts","../../src/commands/repos/update-repo.ts","../../src/commands/repos/cmd-repos-update.ts","../../src/commands/repos/view-repo.ts","../../src/commands/repos/cmd-repos-view.ts","../../src/commands/repos/cmd-repos.ts","../../src/commands/scan/create-full-scan.ts","../../src/commands/scan/cmd-scan-create.ts","../../src/commands/scan/delete-full-scan.ts","../../src/commands/scan/cmd-scan-del.ts","../../src/commands/scan/list-full-scans.ts","../../src/commands/scan/cmd-scan-list.ts","../../src/commands/scan/get-full-scan-metadata.ts","../../src/commands/scan/cmd-scan-metadata.ts","../../src/commands/scan/get-full-scan.ts","../../src/commands/scan/cmd-scan-stream.ts","../../src/commands/scan/cmd-scan.ts","../../src/commands/threat-feed/get-threat-feed.ts","../../src/commands/threat-feed/cmd-threat-feed.ts","../../src/commands/wrapper/add-socket-wrapper.ts","../../src/commands/wrapper/check-socket-wrapper-setup.ts","../../src/commands/wrapper/postinstall-wrapper.ts","../../src/commands/wrapper/remove-socket-wrapper.ts","../../src/commands/wrapper/cmd-wrapper.ts","../../src/cli.ts"],"sourcesContent":["// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/core/classes.py\nimport { components } from '@socketsecurity/sdk/types/api'\n\ntype IntroducedBy = [string, string][]\n\nexport class Alert {\n key = ''\n type = ''\n severity = ''\n category = ''\n props = {}\n\n constructor(arg: Partial<Alert> = {}) {\n this.key = arg.key ?? this.key\n this.type = arg.type ?? this.type\n this.severity = arg.severity ?? this.severity\n this.category = arg.category ?? this.category\n this.props = arg.props ?? this.props\n }\n}\n\nexport class Comment {\n id = 0\n body = ''\n body_list: string[] = []\n\n constructor(arg: Comment) {\n this.id = arg.id ?? this.id\n this.body = arg.body ?? this.body\n this.body_list = arg.body_list ?? this.body_list\n }\n}\n\nexport class Diff {\n newPackages: Purl[] = []\n newCapabilities: Record<string, any> = {}\n removedPackages: Purl[] = []\n newAlerts: Issue[] = []\n id = ''\n sbom = ''\n packages: Record<string, Package> = {}\n reportUrl = ''\n diffUrl = ''\n}\n\nexport class FullScan {\n id = ''\n created_at = ''\n updated_at = ''\n organizationId = ''\n repositoryId = ''\n branch = ''\n commit_message = ''\n commit_hash = ''\n pull_request = 0\n sbom_artifacts: components['schemas']['SocketArtifact'][] = []\n packages = {}\n\n constructor(obj: Partial<FullScan> = {}) {\n this.id = obj.id ?? this.id\n this.created_at = obj.created_at ?? this.created_at\n this.updated_at = obj.updated_at ?? this.updated_at\n this.organizationId = obj.organizationId ?? this.organizationId\n this.repositoryId = obj.repositoryId ?? this.repositoryId\n this.branch = obj.branch ?? this.branch\n this.commit_message = obj.commit_message ?? this.commit_message\n this.commit_hash = obj.commit_hash ?? this.commit_hash\n this.pull_request = obj.pull_request ?? this.pull_request\n this.sbom_artifacts = obj.sbom_artifacts ?? this.sbom_artifacts\n this.packages = obj.packages ?? this.packages\n }\n}\n\nexport class Issue {\n pkg_type = ''\n pkg_name = ''\n pkg_version = ''\n category = ''\n type = ''\n severity = ''\n pkg_id = ''\n props = {}\n key = ''\n error = false\n warn = false\n ignore = false\n monitor = false\n description = ''\n title = ''\n emoji = ''\n next_step_title = ''\n suggestion = ''\n introduced_by: IntroducedBy = []\n manifests = ''\n url = ''\n purl = ''\n\n constructor(arg: {\n pkg_type: string | undefined\n pkg_name: string | undefined\n pkg_version: string | undefined\n type: string | undefined\n severity: string | undefined\n pkg_id: string | undefined\n props: Record<string, any> | undefined\n key: string | undefined\n error: boolean | undefined\n warn: boolean | undefined\n ignore: boolean | undefined\n monitor: boolean | undefined\n description: string | undefined\n title: string | undefined\n next_step_title: string | undefined\n suggestion: string | undefined\n introduced_by: IntroducedBy | undefined\n url: string | undefined\n purl: string | undefined\n }) {\n this.pkg_type = arg.pkg_type ?? this.pkg_type\n this.pkg_name = arg.pkg_name ?? this.pkg_name\n this.pkg_version = arg.pkg_version ?? this.pkg_version\n this.type = arg.type ?? this.type\n this.severity = arg.severity ?? this.severity\n this.pkg_id = arg.pkg_id ?? this.pkg_id\n this.props = arg.props ?? this.props\n this.key = arg.key ?? this.key\n this.error = arg.error ?? this.error\n this.warn = arg.warn ?? this.warn\n this.ignore = arg.ignore ?? this.ignore\n this.monitor = arg.monitor ?? this.monitor\n this.description = arg.description ?? this.description\n this.title = arg.title ?? this.title\n this.next_step_title = arg.next_step_title ?? this.next_step_title\n this.suggestion = arg.suggestion ?? this.suggestion\n\n if (arg.introduced_by) {\n const arr = []\n for (const item of arg.introduced_by) {\n const [, manifest] = item\n arr.push(manifest)\n }\n this.manifests = arr.join(';')\n }\n }\n}\n\nexport class Package {\n type = ''\n name = ''\n version = ''\n release = ''\n id = ''\n direct = false\n manifestFiles: { file: string }[] = []\n author: string[] = []\n size = 0\n score: Score\n scores = {}\n alerts: NonNullable<components['schemas']['SocketArtifact']['alerts']> = []\n alert_counts = {}\n topLevelAncestors: string[] = []\n url = ''\n transitives = 0\n license = 'NoLicenseFound'\n license_text = ''\n purl = ''\n\n constructor(arg: {\n type: string | undefined\n name: string | undefined\n version: string | undefined\n release: string | undefined\n id: string | undefined\n direct: boolean | undefined\n manifestFiles: { file: string }[] | undefined\n author: string[] | undefined\n size: number | undefined\n score: Score | undefined\n alerts: components['schemas']['SocketArtifact']['alerts'] | undefined\n topLevelAncestors: string[] | undefined\n license: string | undefined\n }) {\n this.type = arg.type ?? this.type\n this.name = arg.name ?? this.name\n this.version = arg.version ?? this.version\n this.release = arg.release ?? this.release\n this.id = arg.id ?? this.id\n this.manifestFiles = arg.manifestFiles ?? this.manifestFiles\n this.author = arg.author ?? this.author\n this.size = arg.size ?? this.size\n this.alerts = arg.alerts ?? this.alerts\n this.topLevelAncestors = arg.topLevelAncestors ?? this.topLevelAncestors\n this.license = arg.license ?? this.license\n\n this.url = `https://socket.dev/${this.type}/package/${this.name}/overview/${this.version}`\n this.score = new Score(\n arg.score ?? {\n supplyChain: 0,\n quality: 0,\n license: 0,\n overall: 0,\n vulnerability: 0\n }\n )\n this.alert_counts = {\n critical: 0,\n high: 0,\n middle: 0,\n low: 0\n }\n this.purl = `${this.type}/${this.name}@${this.version}`\n }\n}\n\nexport class Purl {\n id = ''\n name = ''\n version = ''\n ecosystem = ''\n direct = false\n author: string[] = []\n size = 0\n transitives = 0\n introduced_by: IntroducedBy = []\n capabilities: string[] = []\n // is_new = false\n author_url = ''\n url = ''\n purl = ''\n\n constructor(arg: {\n id: string | undefined\n name: string | undefined\n version: string | undefined\n ecosystem: string | undefined\n direct: boolean | undefined\n introduced_by: IntroducedBy | undefined\n author: string[] | undefined\n size: number | undefined\n transitives: number | undefined\n url: string | undefined\n purl: string | undefined\n }) {\n this.id = arg.id ?? this.id\n this.name = arg.name ?? this.name\n this.version = arg.version ?? this.version\n this.ecosystem = arg.ecosystem ?? this.ecosystem\n this.direct = arg.direct ?? this.direct\n this.author = arg.author ?? this.author\n this.size = arg.size ?? this.size\n this.transitives = arg.transitives ?? this.transitives\n this.introduced_by = arg.introduced_by ?? this.introduced_by\n this.url = arg.url ?? this.url\n this.purl = arg.purl ?? this.purl\n\n this.author_url = this.generateAuthorData(this.author, this.ecosystem)\n }\n\n private generateAuthorData(authors: string[], ecosystem: string): string {\n const arr = []\n for (const author of authors) {\n const url = `https://socket.dev/${ecosystem}/user/${author}`\n arr.push(`[${author}](${url})`)\n }\n return arr.join(',')\n }\n}\n\nexport class Score {\n supplyChain = 0\n quality = 0\n license = 0\n overall = 0\n vulnerability = 0\n\n constructor(arg: Score) {\n this.supplyChain = (arg.supplyChain ?? 0) * 100\n this.quality = (arg.quality ?? 0) * 100\n this.license = (arg.license ?? 0) * 100\n this.overall = (arg.overall ?? 0) * 100\n this.vulnerability = (arg.vulnerability ?? 0) * 100\n }\n}\n","// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/core/__init__.py\n/* eslint-disable no-await-in-loop */\nimport { once } from 'node:events'\nimport fs from 'node:fs'\nimport path from 'node:path'\n\nimport ndjson from 'ndjson'\n\nimport { SocketSdk } from '@socketsecurity/sdk'\n\nimport { Diff, FullScan, Issue, Package, Purl } from './classes'\n\nimport type { components, operations } from '@socketsecurity/sdk/types/api.d'\n\nexport class Core {\n socket: SocketSdk\n owner: string\n repo: string\n files: string[]\n securityPolicy: Record<\n string,\n { action: 'error' | 'ignore' | 'warn' | 'monitor' }\n > = {}\n\n constructor({\n owner,\n repo,\n socket\n }: Pick<Core, 'socket' | 'owner' | 'repo' | 'files'>) {\n this.socket = socket\n this.owner = owner\n this.repo = repo\n this.files = []\n }\n\n async getSbomData({\n fullScanId\n }: {\n fullScanId: string\n }): Promise<components['schemas']['SocketArtifact'][]> {\n const orgFullScanResponse = await this.socket.getOrgFullScan(\n this.owner,\n fullScanId,\n undefined\n )\n if (!orgFullScanResponse.success) {\n return []\n }\n\n const { data: readStream }: { data: any } = orgFullScanResponse\n const sbomArtifacts: any = []\n\n readStream\n .pipe(ndjson.parse())\n .on('data', (sbomArtifact: any) => sbomArtifacts.push(sbomArtifact))\n\n await once(readStream, 'end')\n\n return sbomArtifacts\n }\n\n async createFullScan({\n params\n }: {\n params: Omit<operations['CreateOrgFullScan']['parameters']['query'], 'repo'>\n }): Promise<FullScan> {\n const orgFullScanResponse = await this.socket.createOrgFullScan(\n this.owner,\n // Ignoring because pull_request is of type number but URLSearchParams will convert it to a string\n // @ts-ignore\n new URLSearchParams({ repo: this.repo, ...params }),\n this.files\n )\n\n if (!orgFullScanResponse.success) {\n return new FullScan()\n }\n\n const { id: fullScanId } = orgFullScanResponse.data\n const fullScan = new FullScan(orgFullScanResponse.data)\n if (fullScanId !== undefined) {\n fullScan.sbom_artifacts = await this.getSbomData({ fullScanId })\n }\n return fullScan\n }\n\n getSourceData({\n packages,\n pkg\n }: {\n pkg: Package\n packages: Record<string, Package>\n }): [string, string][] {\n const introducedBy: [string, string][] = []\n\n if (pkg.direct) {\n let manifests = pkg.manifestFiles.map(({ file }) => file).join(';')\n\n introducedBy.push(['direct', manifests])\n } else {\n for (const topId of pkg.topLevelAncestors) {\n const topPackage = packages[topId]\n\n if (!topPackage) {\n continue\n }\n\n const topPurl = `${topPackage.type}/${topPackage.name}@${topPackage.version}`\n let manifests = topPackage.manifestFiles\n .map(({ file }) => file)\n .join(';')\n\n introducedBy.push([topPurl, manifests])\n }\n }\n\n return introducedBy\n }\n\n createPurl({\n packageId,\n packages\n }: {\n packageId: string\n packages: Record<string, Package>\n }): { purl: Purl; pkg: Package } {\n const pkg = packages[packageId]!\n const introducedBy = this.getSourceData({ pkg, packages })\n const purl = new Purl({\n id: pkg.id,\n name: pkg.name,\n version: pkg.version,\n ecosystem: pkg.type,\n direct: pkg.direct,\n introduced_by: introducedBy,\n author: pkg.author,\n size: pkg.size,\n transitives: pkg.transitives,\n url: pkg.url,\n purl: pkg.purl\n })\n return { purl, pkg }\n }\n\n async createIssueAlerts({\n alerts,\n packages,\n pkg\n }: {\n pkg: Package\n alerts: Record<string, Issue[]>\n packages: Record<string, Package>\n }): Promise<Record<string, Issue[]>> {\n const issues = JSON.parse(\n fs.readFileSync(path.join(import.meta.dirname, 'issues.json'), 'utf8')\n ) as Record<string, Record<string, string>>\n\n for (const alert of pkg.alerts) {\n const issue = issues[alert.type]\n\n let description = ''\n let title = ''\n let suggestion = ''\n let nextStepTitle = ''\n\n if (issue !== undefined) {\n description = issue['description'] ?? ''\n title = issue['title'] ?? ''\n suggestion = issue['suggestion'] ?? ''\n nextStepTitle = issue['nextStepTitle'] ?? ''\n }\n\n const introducedBy = this.getSourceData({ pkg, packages })\n\n const issueAlert = new Issue({\n pkg_type: pkg.type,\n pkg_name: pkg.name,\n pkg_version: pkg.version,\n pkg_id: pkg.id,\n type: alert.type,\n severity: alert.severity,\n key: alert.key,\n props: alert.props,\n description,\n title,\n suggestion,\n next_step_title: nextStepTitle,\n introduced_by: introducedBy,\n purl: pkg.purl,\n url: pkg.url,\n error: false,\n ignore: false,\n warn: false,\n monitor: false\n })\n\n if (alert.type in this.securityPolicy) {\n const action = this.securityPolicy[alert.type]?.action\n if (action !== undefined) {\n issueAlert[action] = true\n }\n }\n\n if (issueAlert.type !== 'licenseSpdxDisj') {\n if (!(issueAlert.key in alerts)) {\n alerts[issueAlert.key] = [issueAlert]\n } else {\n alerts[issueAlert.key]!.push(issueAlert)\n }\n }\n }\n\n return alerts\n }\n\n compareIssueAlerts({\n alerts,\n headScanAlerts,\n newScanAlerts\n }: {\n newScanAlerts: Record<string, Issue[]>\n headScanAlerts: Record<string, Issue[]>\n alerts: Issue[]\n }) {\n const consolidatedAlerts = new Set()\n\n for (const alertKey in newScanAlerts) {\n if (!(alertKey in headScanAlerts)) {\n const newAlerts = newScanAlerts[alertKey]!\n\n for (const alert of newAlerts) {\n const alertStr = `${alert.purl},${alert.manifests},${alert.type}`\n\n if (alert.error || alert.warn) {\n if (!consolidatedAlerts.has(alertStr)) {\n alerts.push(alert)\n consolidatedAlerts.add(alertStr)\n }\n }\n }\n } else {\n const newAlerts = newScanAlerts[alertKey]!\n const headAlerts = headScanAlerts[alertKey]!\n\n for (const alert of newAlerts) {\n const alertStr = `${alert.purl},${alert.manifests},${alert.type}`\n if (\n !headAlerts.includes(alert) &&\n !consolidatedAlerts.has(alertStr)\n ) {\n if (alert.error || alert.warn) {\n alerts.push(alert)\n consolidatedAlerts.add(alertStr)\n }\n }\n }\n }\n }\n\n return alerts\n }\n\n checkAlertCapabilities({\n capabilities,\n headPackage,\n packageId,\n pkg\n }: {\n pkg: Package\n capabilities: Record<string, string[]>\n packageId: string\n headPackage?: Package\n }): Record<string, string[]> {\n const alertTypes = {\n envVars: 'Environment',\n networkAccess: 'Network',\n filesystemAccess: 'File System',\n shellAccess: 'Shell'\n }\n\n for (const alert of pkg.alerts) {\n let newAlert = true\n if (headPackage !== undefined && headPackage.alerts.includes(alert)) {\n newAlert = false\n }\n if (alert.type in alertTypes && newAlert) {\n const value = alertTypes[alert.type as keyof typeof alertTypes]\n if (!(packageId in capabilities)) {\n capabilities[packageId] = [value]\n } else {\n if (!capabilities[packageId]!.includes(value)) {\n capabilities[packageId]!.push(value)\n }\n }\n }\n }\n\n return capabilities\n }\n\n compareCapabilities({\n headPackages,\n newPackages\n }: {\n newPackages: Record<string, Package>\n headPackages: Record<string, Package>\n }) {\n let capabilities: Record<string, string[]> = {}\n\n for (const packageId in newPackages) {\n const pkg = newPackages[packageId]!\n\n if (packageId in headPackages) {\n const headPackage = headPackages[packageId]!\n for (const alert of pkg.alerts) {\n if (!headPackage.alerts.includes(alert)) {\n capabilities = this.checkAlertCapabilities({\n pkg,\n capabilities,\n packageId,\n headPackage\n })\n }\n }\n } else {\n capabilities = this.checkAlertCapabilities({\n pkg,\n capabilities,\n packageId\n })\n }\n }\n\n return capabilities\n }\n\n addCapabilitiesToPurl(diff: Diff): Diff {\n const newPackages: Purl[] = []\n\n for (const purl of diff.newPackages) {\n if (purl.id in diff.newCapabilities) {\n const capabilities =\n diff.newCapabilities[purl.id as keyof typeof diff.newCapabilities]!\n if (capabilities.length > 0) {\n purl.capabilities = capabilities\n newPackages.push(purl)\n }\n } else {\n newPackages.push(purl)\n }\n }\n diff.newPackages = newPackages\n\n return diff\n }\n\n async compareSBOMs({\n headScan,\n newScan\n }: {\n newScan: Awaited<ReturnType<Core['getSbomData']>>\n headScan: Awaited<ReturnType<Core['getSbomData']>>\n }): Promise<Diff> {\n let diff = new Diff()\n const newPackages = this.createSbomDict(newScan)\n const headPackages = this.createSbomDict(headScan)\n\n let newScanAlerts: Record<string, Issue[]> = {}\n let headScanAlerts: Record<string, Issue[]> = {}\n const consolidated = new Set()\n\n for (const packageId in newPackages) {\n const { pkg, purl } = this.createPurl({\n packageId,\n packages: newPackages\n })\n const basePurl = `${purl.ecosystem}/${purl.name}@${purl.version}`\n\n if (\n !(packageId in headPackages) &&\n pkg.direct &&\n !consolidated.has(basePurl)\n ) {\n diff.newPackages.push(purl)\n consolidated.add(basePurl)\n }\n\n newScanAlerts = await this.createIssueAlerts({\n pkg,\n alerts: newScanAlerts,\n packages: newPackages\n })\n }\n\n for (const packageId in headPackages) {\n const { pkg, purl } = this.createPurl({\n packageId,\n packages: headPackages\n })\n\n if (!(packageId in newPackages) && pkg.direct) {\n diff.removedPackages.push(purl)\n }\n\n headScanAlerts = await this.createIssueAlerts({\n pkg,\n alerts: headScanAlerts,\n packages: headPackages\n })\n }\n\n diff.newAlerts = this.compareIssueAlerts({\n newScanAlerts,\n headScanAlerts,\n alerts: diff.newAlerts\n })\n diff.newCapabilities = this.compareCapabilities({\n newPackages,\n headPackages\n })\n diff = this.addCapabilitiesToPurl(diff)\n\n return diff\n }\n\n createPackageFromSbomArtifact(\n sbomArtifact: components['schemas']['SocketArtifact'][]\n ): Package[] {\n return sbomArtifact.map(\n sbomArtifact =>\n new Package({\n type: sbomArtifact.type,\n name: sbomArtifact.name,\n version: sbomArtifact.version,\n release: sbomArtifact.release,\n id: sbomArtifact.id,\n direct: sbomArtifact.direct,\n manifestFiles: sbomArtifact.manifestFiles,\n author: sbomArtifact.author,\n size: sbomArtifact.size,\n score: sbomArtifact.score,\n alerts: sbomArtifact.alerts,\n topLevelAncestors: sbomArtifact.topLevelAncestors,\n license: sbomArtifact.license\n })\n )\n }\n\n getLicenseDetails({ package: pkg }: { package: Package }): Package {\n const licenseText = JSON.parse(\n fs.readFileSync(\n path.join(import.meta.dirname, 'license_texts.json'),\n 'utf8'\n )\n ) as Record<string, string>\n const licenseStr = licenseText[pkg.license]\n if (licenseStr !== undefined) {\n pkg.license_text = licenseStr\n }\n return pkg\n }\n\n createSbomDict(\n sbomArtifacts: Awaited<ReturnType<typeof this.getSbomData>>\n ): Record<string, Package> {\n const packages: Record<string, Package> = {}\n const topLevelCount: Record<string, number> = {}\n\n for (const sbomArtifact of sbomArtifacts) {\n let pkg = new Package({\n type: sbomArtifact.type,\n name: sbomArtifact.name,\n version: sbomArtifact.version,\n release: sbomArtifact.release,\n id: sbomArtifact.id,\n direct: sbomArtifact.direct,\n manifestFiles: sbomArtifact.manifestFiles,\n author: sbomArtifact.author,\n size: sbomArtifact.size,\n score: sbomArtifact.score,\n alerts: sbomArtifact.alerts,\n topLevelAncestors: sbomArtifact.topLevelAncestors,\n license: sbomArtifact.license\n })\n\n if (pkg.id in packages) {\n console.log('Duplicate package?')\n } else {\n pkg = this.getLicenseDetails({ package: pkg })\n packages[pkg.id] = pkg\n\n for (const topId in sbomArtifact.topLevelAncestors ?? []) {\n if (!(topId in topLevelCount)) {\n topLevelCount[topId] = 1\n } else {\n topLevelCount[topId] += 1\n }\n }\n }\n }\n\n if (Object.keys(topLevelCount).length > 0) {\n for (const packageId in topLevelCount) {\n const pkg = packages[packageId]\n if (pkg) {\n pkg.transitives = topLevelCount[packageId] ?? 0\n }\n }\n }\n\n return packages\n }\n\n async createNewDiff({\n params = {}\n }: {\n params?: Omit<\n operations['CreateOrgFullScan']['parameters']['query'],\n 'repo'\n >\n }): Promise<Diff> {\n let headFullScanId: string = ''\n let headFullScan: Awaited<ReturnType<typeof this.getSbomData>> = []\n\n try {\n const orgRepoResponse = await this.socket.getOrgRepo(\n this.owner,\n this.repo\n )\n if (orgRepoResponse.success) {\n headFullScanId = orgRepoResponse.data.head_full_scan_id ?? ''\n if (headFullScanId !== '') {\n headFullScan = await this.getSbomData({ fullScanId: headFullScanId })\n }\n }\n } catch (error) {\n console.error(error)\n }\n\n const newFullScan = await this.createFullScan({ params })\n newFullScan.packages = this.createSbomDict(newFullScan.sbom_artifacts)\n\n const diffReport = await this.compareSBOMs({\n newScan: newFullScan.sbom_artifacts,\n headScan: headFullScan\n })\n diffReport.packages = newFullScan.packages\n\n const baseSocket = 'https://socket.dev/dashboard/org'\n diffReport.id = newFullScan.id\n diffReport.reportUrl = `${baseSocket}/${this.owner}/sbom/${diffReport.id}`\n if (headFullScanId !== '') {\n diffReport.diffUrl = `${baseSocket}/${this.owner}/diff/${diffReport.id}/${headFullScanId}`\n } else {\n diffReport.diffUrl = diffReport.reportUrl\n }\n\n return diffReport\n }\n}\n","// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/core/scm_comments.py\nimport { Comment, Issue } from './classes'\n\nexport type SocketComments = {\n security: Comment | undefined\n overview: Comment | undefined\n ignore: Comment[]\n}\n\nexport function checkForSocketComments({\n comments\n}: {\n comments: Record<string, Comment>\n}): SocketComments {\n const socketComments: {\n security: Comment | undefined\n overview: Comment | undefined\n ignore: Comment[]\n } = {\n security: undefined,\n overview: undefined,\n ignore: []\n }\n\n for (const commentId in comments) {\n const comment = comments[commentId]!\n\n if (comment.body.includes('socket-security-comment-actions')) {\n socketComments.security = comment\n } else if (comment.body.includes('socket-overview-comment-actions')) {\n socketComments.overview = comment\n } else if (\n // Based on:\n // To ignore an alert, reply with a comment starting with @SocketSecurity ignore\n // followed by a space separated list of ecosystem/package-name@version specifiers.\n // e.g. @SocketSecurity ignore npm/foo@1.0.0 or ignore all packages with @SocketSecurity ignore-all\n comment.body\n .split('\\n')\n .at(0)\n ?.includes('SocketSecurity ignore')\n ) {\n socketComments.ignore.push(comment)\n }\n }\n\n return socketComments\n}\n\n// Parses the ignore command\n// @SocketSecurity ignore pkg1 pkg2 ...\n// @SocketSecurity ignore ignore-all\nexport function parseIgnoreCommand(line: string) {\n const result = { packages: [] as string[], ignoreAll: false }\n const words = line.trim().replace(/\\s+/g, ' ').split(' ')\n if (words.at(1) === 'ignore-all') {\n result.ignoreAll = true\n return result\n }\n if (words.at(1) === 'ignore') {\n for (let i = 2; i < words.length; i++) {\n const pkg = words[i] as string\n result.packages.push(pkg)\n }\n return result\n }\n return result\n}\n\n// Ref: https://github.com/socketdev-demo/javascript-threats/pull/89#issuecomment-2456015512\nexport function processSecurityComment({\n ignore: ignoreComments,\n security: securityComment\n}: Pick<SocketComments, 'security' | 'ignore'>): string {\n const result: string[] = []\n let start = false\n\n let ignoreAll = false\n let ignoredPackages = []\n for (const ignoreComment of ignoreComments) {\n const parsed = parseIgnoreCommand(\n ignoreComment.body?.split('\\n').at(0) ?? ''\n )\n if (parsed.ignoreAll) {\n ignoreAll = true\n break\n }\n ignoredPackages.push(parsed.packages)\n }\n\n // Split the comment body into lines and update them\n // to generate a new comment body\n for (let line of securityComment?.body?.split('\\n') ?? []) {\n line = line.trim()\n\n if (line.includes('start-socket-alerts-table')) {\n start = true\n result.push(line)\n } else if (\n start &&\n !line.includes('end-socket-alerts-table') &&\n // is not heading line?\n !(\n line === '|Alert|Package|Introduced by|Manifest File|CI|' ||\n line.includes(':---')\n ) &&\n line !== ''\n ) {\n // Parsing Markdown data colunms\n const [_, _title, packageLink, _introducedBy, _manifest, _ci] =\n line.split('|') as [string, string, string, string, string, string]\n\n // Parsing package link [npm/pkg](url)\n let [_ecosystem, pkg] = packageLink\n .slice(1, packageLink.indexOf(']'))\n .split('/', 2) as [string, string]\n const [pkgName, pkgVersion] = pkg.split('@')\n\n // Checking if this package should be ignored\n let ignore = false\n if (ignoreAll) {\n ignore = true\n } else {\n for (const [ignoredPkgName, ignorePkgVersion] of ignoredPackages) {\n if (\n pkgName === ignoredPkgName &&\n (ignorePkgVersion === '*' || pkgVersion === ignorePkgVersion)\n ) {\n ignore = true\n break\n }\n }\n }\n\n if (ignore) {\n break\n }\n result.push(line)\n } else if (line.includes('end-socket-alerts-table')) {\n start = false\n result.push(line)\n } else {\n result.push(line)\n }\n }\n\n return result.join('\\n')\n}\n\nexport function getIgnoreOptions({ comments }: { comments: SocketComments }) {\n const ignoreCommands: string[] = []\n let ignoreAll = false\n\n for (const comment of comments.ignore) {\n let firstLine = comment.body_list[0]!\n if (!ignoreAll && firstLine.includes('SocketSecurity ignore')) {\n try {\n firstLine = firstLine.replace(/@/, '')\n let [, command] = firstLine.split('SocketSecurity ')\n command = command!.trim()\n if (command === 'ignore-all') {\n ignoreAll = true\n } else {\n command = command.replace(/ignore/, '').trim()\n const [name, version] = command.split('@')\n const data = `${name}/${version}`\n ignoreCommands.push(data)\n }\n } catch (error) {\n console.error(`Unable to process ignore command for ${comment}`)\n console.error(error)\n }\n }\n }\n return { ignoreAll, ignoreCommands }\n}\n\nexport function removeAlerts({\n comments,\n newAlerts\n}: {\n comments: SocketComments\n newAlerts: Issue[]\n}) {\n const alerts: Issue[] = []\n\n if (comments.ignore.length === 0) {\n return newAlerts\n }\n\n const { ignoreAll, ignoreCommands } = getIgnoreOptions({\n comments\n })\n\n for (const alert of newAlerts) {\n if (ignoreAll) {\n break\n } else {\n const fullName = `${alert.pkg_type}/${alert.pkg_name}`\n const purl = `${fullName}/${alert.pkg_version}`\n const purlStar = `${fullName}/*`\n if (ignoreCommands.includes(purl) || ignoreCommands.includes(purlStar)) {\n console.log(`Alerts for ${alert.pkg_name}@${alert.pkg_version} ignored`)\n } else {\n console.log(\n `Adding alert ${alert.type} for ${alert.pkg_name}@${alert.pkg_version}`\n )\n alerts.push(alert)\n }\n }\n }\n\n return alerts\n}\n","// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/core/github.py\n/* eslint-disable no-await-in-loop */\nimport { Octokit } from '@octokit/rest'\n\nimport { Comment } from './classes'\nimport * as SCMComments from './scm_comments'\n\nexport class GitHub {\n octokit: Octokit = new Octokit()\n owner: string\n repo: string\n prNumber: number\n\n constructor() {\n const [owner = '', repo = ''] = (\n process.env['GITHUB_REPOSITORY'] ?? ''\n ).split('/')\n // https://github.com/actions/checkout/issues/58#issuecomment-2264361099\n const prNumber = parseInt(\n process.env['GITHUB_REF']?.match(/refs\\/pull\\/(\\d+)\\/merge/)?.at(1) ?? ''\n )\n this.owner = owner\n this.repo = repo\n this.prNumber = prNumber\n }\n\n checkEventType(): 'main' | 'diff' | 'comment' | 'unsupported' {\n switch (process.env['GITHUB_EVENT_NAME']) {\n case 'push':\n return this.prNumber ? 'diff' : 'main'\n case 'pull_request':\n // This env variable needs to be set in the GitHub action.\n // Add this code below to GitHub action:\n // - steps:\n // - name: Get PR State\n // if: github.event_name == 'pull_request'\n // run: echo \"EVENT_ACTION=${{ github.event.action }}\" >> $GITHUB_ENV\n const eventAction = process.env['EVENT_ACTION']\n if (!eventAction) {\n throw new Error('Missing event action')\n }\n if (['opened', 'synchronize'].includes(eventAction)) {\n return 'diff'\n } else {\n console.log(`Pull request action: ${eventAction} is not supported`)\n process.exit()\n }\n case 'issue_comment':\n return 'comment'\n default:\n throw new Error(\n `Unknown event type: ${process.env['GITHUB_EVENT_NAME']}`\n )\n }\n }\n\n async getCommentsForPR(): Promise<SCMComments.SocketComments> {\n const { data: githubComments } =\n await this.octokit.rest.issues.listComments({\n owner: this.owner,\n repo: this.repo,\n issue_number: this.prNumber\n })\n const comments: Record<string, Comment> = {}\n for (const githubComment of githubComments) {\n comments[githubComment.id] = new Comment({\n id: githubComment.id,\n body: githubComment.body ?? '',\n body_list: (githubComment.body ?? '').split('\\n')\n })\n }\n return SCMComments.checkForSocketComments({ comments })\n }\n\n async commentReactionExists({\n commentId\n }: {\n commentId: number\n }): Promise<boolean> {\n const { data } = await this.octokit.reactions.listForIssueComment({\n owner: this.owner,\n repo: this.repo,\n comment_id: commentId\n })\n return data.some(reaction => reaction.content === '+1')\n }\n\n async postReaction({ commentId }: { commentId: number }) {\n await this.octokit.reactions.createForIssueComment({\n owner: this.owner,\n repo: this.repo,\n comment_id: commentId,\n content: '+1'\n })\n }\n\n async handleIgnoreReactons({\n comments\n }: {\n comments: SCMComments.SocketComments\n }) {\n for (const ignoreComment of comments.ignore) {\n if (\n ignoreComment.body?.includes('SocketSecurity ignore') &&\n !(await this.commentReactionExists({\n commentId: ignoreComment.id\n }))\n ) {\n await this.postReaction({ commentId: ignoreComment.id })\n }\n }\n }\n\n async updateComment({ body, id }: { id: number; body: string }) {\n await this.octokit.issues.updateComment({\n owner: this.owner,\n repo: this.repo,\n comment_id: id,\n body\n })\n }\n\n async removeCommentAlerts({\n comments\n }: {\n comments: SCMComments.SocketComments\n }) {\n const securityAlert = comments.security\n if (securityAlert !== undefined) {\n const newBody = SCMComments.processSecurityComment({\n security: comments.security,\n ignore: comments.ignore\n })\n await this.handleIgnoreReactons({ comments })\n await this.updateComment({ id: securityAlert.id, body: newBody })\n }\n }\n\n async postComment({ body }: { body: string }) {\n await this.octokit.issues.createComment({\n owner: this.owner,\n repo: this.repo,\n issue_number: this.prNumber,\n body\n })\n }\n\n async addSocketComments({\n comments,\n newOverviewComment,\n newSecurityComment,\n overviewComment,\n securityComment\n }: {\n securityComment: string\n overviewComment: string\n comments: SCMComments.SocketComments\n newSecurityComment: boolean\n newOverviewComment: boolean\n }): Promise<void> {\n const {\n overview: existingOverviewComment,\n security: existingSecurityComment\n } = comments\n if (newOverviewComment) {\n console.log('New Dependency Overview comment')\n if (existingOverviewComment !== undefined) {\n console.log('Previous version of Dependency Overview, updating')\n await this.updateComment({\n body: overviewComment,\n id: existingOverviewComment.id\n })\n } else {\n console.log('No previous version of Dependency Overview, posting')\n await this.postComment({ body: overviewComment })\n }\n }\n if (newSecurityComment) {\n console.log('New Security Issue Comment')\n if (existingSecurityComment !== undefined) {\n console.log('Previous version of Security Issue comment, updating')\n await this.updateComment({\n body: securityComment,\n id: existingSecurityComment.id\n })\n } else {\n console.log('No Previous version of Security Issue comment, posting')\n await this.postComment({ body: securityComment })\n }\n }\n }\n}\n","// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/core/messages.py\nimport { Diff, Issue, Purl } from './classes'\n\nexport function createSecurityCommentJSON({ diff }: { diff: Diff }) {\n let scanFailed = false\n\n // Not porting this code because it's unreachable\n // https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/core/messages.py#L13-L18\n\n const output: {\n scanFailed: boolean\n newAlerts: Issue[]\n fullScanId: string\n } = {\n scanFailed,\n newAlerts: [],\n fullScanId: diff.id\n }\n for (const alert of diff.newAlerts) {\n output.newAlerts.push(alert)\n }\n\n return output\n}\n\nexport function createPurlLink(purl: Purl): string {\n const packageUrl = `[${purl.purl}](${purl.url})`\n return packageUrl\n}\n\nexport function createAddedTable(diff: Diff): string {\n const overviewTable = [\n 'Package',\n 'Direct',\n 'Capabilities',\n 'Transitives',\n 'Size',\n 'Author'\n ]\n const rows = []\n for (const added of diff.newPackages) {\n const packageUrl = createPurlLink(added)\n const capabilities = added.capabilities.join(', ')\n const row = [\n packageUrl,\n added.direct,\n capabilities,\n added.transitives,\n `${added.size} KB`,\n added.author_url\n ]\n rows.push(row)\n }\n\n let md = ''\n md += `|${overviewTable.join('|')}|\\n`\n md += '|---|---|---|---|---|---|\\n'\n for (const row of rows) {\n md += `|${row.join('|')}|\\n`\n }\n\n return md\n}\n\nexport function createRemoveLine(diff: Diff): string {\n const removedLine = ['Removed packages:']\n for (const removed of diff.removedPackages) {\n const packageUrl = createPurlLink(removed)\n removedLine.push(packageUrl)\n }\n return removedLine.join(', ')\n}\n\nexport function dependencyOverviewTemplate(diff: Diff): string {\n let md = ''\n md += '<!-- socket-overview-comment-actions -->\\n'\n md += '# Socket Security: Dependency Overview\\n'\n md +=\n 'New and removed dependencies detected. Learn more about [socket.dev](https://socket.dev)\\n\\n'\n md += createAddedTable(diff)\n if (diff.removedPackages.length > 0) {\n md += createRemoveLine(diff)\n }\n return md\n}\n\nexport function createSources(alert: Issue): [string, string] {\n const sources: string[] = []\n const manifests: string[] = []\n for (const [source, manifest] of alert.introduced_by) {\n const addStr = `<li>${manifest}</li>`\n const sourceStr = `<li>${source}</li>`\n if (!sources.includes(sourceStr)) {\n sources.push(sourceStr)\n }\n if (!manifests.includes(addStr)) {\n manifests.push(addStr)\n }\n }\n let manifestList = manifests.join('')\n let sourceList = sources.join('')\n const manifestStr = `<ul>${manifestList}</ul>`\n const sourcesStr = `<ul>${sourceList}</ul>`\n return [manifestStr, sourcesStr]\n}\n\nexport function createSecurityAlertTable(diff: Diff): {\n ignoreCommands: string[]\n nextSteps: Record<string, string[]>\n mdTable: string\n} {\n const alertTable = [\n 'Alert',\n 'Package',\n 'Introduced by',\n 'Manifest File',\n 'CI'\n ]\n const nextSteps: Record<string, string[]> = {}\n const ignoreCommands: string[] = []\n\n const rows: string[][] = []\n for (const alert of diff.newAlerts) {\n if (!(alert.next_step_title in nextSteps)) {\n nextSteps[alert.next_step_title] = [alert.description, alert.suggestion]\n }\n const ignore = `\\`SocketSecurity ignore ${alert.purl}\\``\n if (!ignoreCommands.includes(ignore)) {\n ignoreCommands.push(ignore)\n }\n const [manifestStr, sourceStr] = createSources(alert)\n const purlUrl = `[${alert.purl}](${alert.url})`\n if (alert.error) {\n alert.emoji = ':no_entry_sign:'\n } else {\n alert.emoji = ':warning:'\n }\n const row = [alert.title, purlUrl, sourceStr, manifestStr, alert.emoji]\n if (!rows.some(r => r.join() === row.join())) {\n rows.push(row)\n }\n }\n\n let md = ''\n md += `|${alertTable.join('|')}|\\n`\n md += '|---|---|---|---|---|\\n'\n for (const row of rows) {\n md += `|${row.join('|')}|\\n`\n }\n\n return { ignoreCommands, nextSteps, mdTable: md }\n}\n\nexport function createNextSteps(nextSteps: Record<string, string[]>): string {\n let md = ''\n for (const step in nextSteps) {\n const detail = nextSteps[step]!\n md += '<details>\\n'\n md += `<summary>${step}</summary>\\n`\n for (const line of detail) {\n md += `${line}\\n`\n }\n md += '</details>\\n'\n }\n return md\n}\n\nexport function createDeeperLook(): string {\n let md = ''\n md += '<details>\\n'\n md += '<summary>Take a deeper look at the dependency</summary>\\n'\n md +=\n \"Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support [AT] socket [DOT] dev.\\n\"\n md += '</details>\\n'\n return md\n}\n\nexport function createRemovePackage(): string {\n let md = ''\n md += '<details>\\n'\n md += '<summary>Remove the package</summary>\\n'\n md +=\n 'If you happen to install a dependency that Socket reports as [https://socket.dev/npm/issue/malware](Known Malware) you should immediately remove it and select a different dependency. For other alert types, you may may wish to investigate alternative packages or consider if there are other ways to mitigate the specific risk posed by the dependency.\\n'\n md += '</details>\\n'\n return md\n}\n\nexport function createAcceptableRisk(ignoreCommands: string[]): string {\n let md = ''\n md += '<details>\\n'\n md += '<summary>Mark a package as acceptable risk</summary>\\n'\n md +=\n 'To ignore an alert, reply with a comment starting with `SocketSecurity ignore` followed by a space separated list of `ecosystem/package-name@version` specifiers. e.g. `SocketSecurity ignore npm/foo@1.0.0` or ignore all packages with `SocketSecurity ignore-all`\\n'\n md += '<ul>\\n'\n for (const ignore of ignoreCommands) {\n md += `<li>${ignore}</li>\\n`\n }\n md += '</ul>\\n'\n md += '</details>\\n'\n return md\n}\n\nexport function securityCommentTemplate(diff: Diff): string {\n let md = ''\n md += '<!-- socket-security-comment-actions -->\\n'\n md += '# Socket Security: Issues Report\\n'\n md +=\n 'Potential security issues detected. Learn more about [socket.dev](https://socket.dev)\\n'\n md +=\n 'To accept the risk, merge this PR and you will not be notified again.\\n\\n'\n md += '<!-- start-socket-alerts-table -->\\n'\n const { ignoreCommands, mdTable, nextSteps } = createSecurityAlertTable(diff)\n md += mdTable\n md += '<!-- end-socket-alerts-table -->\\n\\n'\n md += createNextSteps(nextSteps)\n md += createDeeperLook()\n md += createRemovePackage()\n md += createAcceptableRisk(ignoreCommands)\n return md.trim()\n}\n","// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/socketcli.py\n\nimport micromatch from 'micromatch'\nimport { simpleGit } from 'simple-git'\n\nimport { SocketSdk } from '@socketsecurity/sdk'\n\nimport { Core } from './core'\nimport { GitHub } from './core/github'\nimport * as Messages from './core/messages'\nimport * as SCMComments from './core/scm_comments'\nimport { getDefaultToken } from '../../utils/sdk'\n\n// TODO: is this a github action handler?\nexport async function runAction(\n githubEventBefore: string,\n githubEventAfter: string\n) {\n //TODO\n const socket = new SocketSdk(getDefaultToken()!)\n\n const git = simpleGit()\n const changedFiles = (\n await git.diff(\n process.env['GITHUB_EVENT_NAME'] === 'pull_request'\n ? ['--name-only', 'HEAD^1', 'HEAD']\n : ['--name-only', githubEventBefore, githubEventAfter]\n )\n ).split('\\n')\n\n console.log({ changedFiles })\n // supportedFiles have 3-level deep globs\n const patterns = Object.values(await socket.getReportSupportedFiles())\n .flatMap((i: Record<string, any>) => Object.values(i))\n .flatMap((i: Record<string, any>) => Object.values(i))\n .flatMap((i: Record<string, any>) => Object.values(i))\n\n const files = micromatch(changedFiles, patterns)\n\n const scm = new GitHub()\n\n if (scm.checkEventType() === 'comment') {\n console.log('Comment initiated flow')\n const comments = await scm.getCommentsForPR()\n await scm.removeCommentAlerts({ comments })\n } else if (scm.checkEventType() === 'diff') {\n console.log('Push initiated flow')\n const core = new Core({ owner: scm.owner, repo: scm.repo, files, socket })\n const diff = await core.createNewDiff({})\n const comments = await scm.getCommentsForPR()\n diff.newAlerts = SCMComments.removeAlerts({\n comments,\n newAlerts: diff.newAlerts\n })\n const overviewComment = Messages.dependencyOverviewTemplate(diff)\n const securityComment = Messages.securityCommentTemplate(diff)\n let newSecurityComment = true\n let newOverviewComment = true\n let updateOldSecurityComment = comments.security !== undefined\n let updateOldOverviewComment = comments.overview !== undefined\n if (diff.newAlerts.length === 0) {\n if (!updateOldSecurityComment) {\n newSecurityComment = false\n console.log('No new alerts or security issue comment disabled')\n } else {\n console.log('Updated security comment with no new alerts')\n }\n }\n if (diff.newPackages.length === 0 && diff.removedPackages.length === 0) {\n if (!updateOldOverviewComment) {\n newOverviewComment = false\n console.log(\n 'No new/removed packages or Dependency Overview comment disabled'\n )\n } else {\n console.log('Updated overview comment with no dependencies')\n }\n }\n await scm.addSocketComments({\n securityComment,\n overviewComment,\n comments,\n newSecurityComment,\n newOverviewComment\n })\n }\n}\n","type HelpListOptions = {\n keyPrefix: string\n padName: number\n}\n\ntype ListDescription = string | { description: string }\n\nexport function getFlagListOutput(\n list: Record<string, ListDescription>,\n indent: number,\n { keyPrefix = '--', padName } = <HelpListOptions>{}\n): string {\n return getHelpListOutput(\n {\n ...list\n },\n indent,\n { keyPrefix, padName }\n )\n}\n\nexport function getHelpListOutput(\n list: Record<string, ListDescription>,\n indent: number,\n { keyPrefix = '', padName = 18 } = <HelpListOptions>{}\n): string {\n let result = ''\n const names = Object.keys(list).sort()\n for (const name of names) {\n const rawDescription = list[name]\n const description =\n (typeof rawDescription === 'object'\n ? rawDescription.description\n : rawDescription) || ''\n result +=\n ''.padEnd(indent) +\n (keyPrefix + name).padEnd(padName) +\n description +\n '\\n'\n }\n return result.trim()\n}\n","import type { Flag } from 'meow'\n\n// TODO: not sure if I'm missing something but meow doesn't seem to expose this?\ntype StringFlag = Flag<'string', string> | Flag<'string', string[], true>\ntype BooleanFlag = Flag<'boolean', boolean> | Flag<'boolean', boolean[], true>\ntype NumberFlag = Flag<'number', number> | Flag<'number', number[], true>\ntype AnyFlag = StringFlag | BooleanFlag | NumberFlag\n\n// Note: we use this description in getFlagListOutput, meow doesn't care\nexport type MeowFlags = Record<string, AnyFlag & { description: string }>\n\nexport const commonFlags: MeowFlags = {\n help: {\n type: 'boolean',\n default: false,\n shortFlag: 'h',\n description: 'Print this help.'\n },\n dryRun: {\n type: 'boolean',\n default: false,\n description: 'Do input validation for a command and exit 0 when input is ok'\n }\n}\n\nexport const outputFlags: MeowFlags = {\n json: {\n type: 'boolean',\n shortFlag: 'j',\n default: false,\n description: 'Output result as json'\n },\n markdown: {\n type: 'boolean',\n shortFlag: 'm',\n default: false,\n description: 'Output result as markdown'\n }\n}\n\nexport const validationFlags: MeowFlags = {\n all: {\n type: 'boolean',\n default: false,\n description: 'Include all issues'\n },\n strict: {\n type: 'boolean',\n default: false,\n description: 'Exits with an error code if any matching issues are found'\n }\n}\n","import meow from 'meow'\n\nimport { toSortedObject } from '@socketsecurity/registry/lib/objects'\nimport { escapeRegExp } from '@socketsecurity/registry/lib/regexps'\n\nimport { getFlagListOutput, getHelpListOutput } from './output-formatting'\nimport { getSetting } from './settings'\nimport constants from '../constants'\nimport { MeowFlags, commonFlags } from '../flags'\n\nimport type { Options } from 'meow'\n\nconst { SOCKET_CLI_SHOW_BANNER } = constants\n\nconst REDACTED = '<redacted>'\n\ninterface CliAlias {\n description: string\n argv: readonly string[]\n hidden?: boolean\n}\n\ntype CliAliases = Record<string, CliAlias>\n\ntype CliSubcommandRun = (\n argv: readonly string[],\n importMeta: ImportMeta,\n context: { parentName: string }\n) => Promise<void> | void\n\nexport interface CliSubcommand {\n description: string\n hidden?: boolean\n run: CliSubcommandRun\n}\n\n// Property names are picked such that the name is at the top when the props\n// get ordered by alphabet while flags is near the bottom and the help text\n// at the bottom, because they tend ot occupy the most lines of code.\nexport interface CliCommandConfig {\n commandName: string // tmp optional while we migrate\n description: string\n hidden: boolean\n flags: MeowFlags // tmp optional while we migrate\n help: (command: string, config: CliCommandConfig) => string\n}\n\ninterface MeowOptions extends Options<any> {\n aliases?: CliAliases\n argv: readonly string[]\n name: string\n}\n\n// For debugging. Whenever you call meowOrExit it will store the command here\n// This module exports a getter that returns the current value.\nlet lastSeenCommand = ''\n\nexport function getLastSeenCommand(): string {\n return lastSeenCommand\n}\n\nexport async function meowWithSubcommands(\n subcommands: Record<string, CliSubcommand>,\n options: MeowOptions\n): Promise<void> {\n const {\n aliases = {},\n argv,\n importMeta,\n name,\n ...additionalOptions\n } = { __proto__: null, ...options }\n const [commandOrAliasName, ...rawCommandArgv] = argv\n // If we got at least some args, then lets find out if we can find a command.\n if (commandOrAliasName) {\n const alias = aliases[commandOrAliasName]\n // First: Resolve argv data from alias if its an alias that's been given.\n const [commandName, ...commandArgv] = alias\n ? [...alias.argv, ...rawCommandArgv]\n : [commandOrAliasName, ...rawCommandArgv]\n // Second: Find a command definition using that data.\n const commandDefinition = commandName ? subcommands[commandName] : undefined\n // Third: If a valid command has been found, then we run it...\n if (commandDefinition) {\n return await commandDefinition.run(commandArgv, importMeta, {\n parentName: name\n })\n }\n }\n const flags = {\n ...commonFlags,\n ...additionalOptions.flags\n }\n // ...else we provide basic instructions and help.\n\n // Temp disable until we clear the --json and --markdown usage\n // Lazily access constants.ENV[SOCKET_CLI_SHOW_BANNER].\n if (constants.ENV[SOCKET_CLI_SHOW_BANNER]) {\n console.log(getAsciiHeader(name))\n }\n const cli = meow(\n `\n Usage\n $ ${name} <command>\n\n Commands\n ${getHelpListOutput(\n {\n ...toSortedObject(\n Object.fromEntries(\n Object.entries(subcommands).filter(\n ({ 1: subcommand }) => !subcommand.hidden\n )\n )\n ),\n ...toSortedObject(\n Object.fromEntries(\n Object.entries(aliases).filter(({ 1: alias }) => {\n const { hidden } = alias\n const cmdName = hidden ? '' : alias.argv[0]\n const subcommand = cmdName ? subcommands[cmdName] : undefined\n return subcommand && !subcommand.hidden\n })\n )\n )\n },\n 6\n )}\n\n Options\n ${getFlagListOutput(flags, 6)}\n\n Examples\n $ ${name} --help\n `,\n {\n argv,\n importMeta,\n ...additionalOptions,\n flags,\n autoHelp: false // otherwise we can't exit(0)\n }\n )\n if (!cli.flags['help'] && cli.flags['dryRun']) {\n console.log('[DryRun]: noop, call a sub-command; ok')\n process.exitCode = 0\n } else {\n cli.showHelp()\n }\n}\n\n/**\n * Note: meow will exit immediately if it calls its .showHelp()\n */\nexport function meowOrExit({\n allowUnknownFlags, // commands that pass-through args need to allow this\n argv,\n config,\n importMeta,\n parentName\n}: {\n allowUnknownFlags?: boolean\n argv: ReadonlyArray<string>\n config: CliCommandConfig\n parentName: string\n importMeta: ImportMeta\n}) {\n const command = `${parentName} ${config.commandName}`\n lastSeenCommand = command\n // Temp disable until we clear the --json and --markdown usage.\n // Lazily access constants.ENV[SOCKET_CLI_SHOW_BANNER].\n if (constants.ENV[SOCKET_CLI_SHOW_BANNER]) {\n console.log(getAsciiHeader(command))\n }\n // This exits if .printHelp() is called either by meow itself or by us.\n const cli = meow({\n argv,\n description: config.description,\n help: config.help(command, config),\n importMeta,\n flags: config.flags,\n allowUnknownFlags: Boolean(allowUnknownFlags),\n autoHelp: false // otherwise we can't exit(0)\n })\n if (cli.flags['help']) {\n cli.showHelp()\n }\n return cli\n}\n\nfunction getAsciiHeader(command: string) {\n // Note: In tests we return <redacted> because otherwise snapshots will fail.\n // The '@rollup/plugin-replace' will replace \"process.env['SOCKET_CLI_VERSION_HASH']\".\n const redacting = process.env['VITEST']\n const cliVersion = redacting\n ? REDACTED\n : // The '@rollup/plugin-replace' will replace \"process.env['SOCKET_CLI_VERSION_HASH']\".\n process.env['SOCKET_CLI_VERSION_HASH']\n const nodeVersion = redacting ? REDACTED : process.version\n // Get the last 5 characters of the API token before the trailing \"_api\".\n const lastFiveCharsOfApiToken = redacting\n ? REDACTED\n : getSetting('apiToken')?.slice(-9, -4) || 'no'\n const relCwd = redacting\n ? REDACTED\n : process\n .cwd()\n .replace(new RegExp(`^${escapeRegExp(constants.homePath)}`, 'i'), '~/')\n const body = `\n _____ _ _ /---------------\n | __|___ ___| |_ ___| |_ | Socket.dev CLI ver ${cliVersion}\n |__ | . | _| '_| -_| _| | Node: ${nodeVersion}, API token set: ${lastFiveCharsOfApiToken}\n |_____|___|___|_,_|___|_|.dev | Command: \\`${command}\\`, cwd: ${relCwd}`.trimStart()\n return ` ${body}\\n`\n}\n","// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/socketcli.py\n\nimport { runAction } from './run-action'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'action',\n description: 'Socket action command', // GitHub Action ?\n hidden: true,\n flags: {\n // This flag is unused\n // socketSecurityApiKey: { // deprecate this asap.\n // type: 'string',\n // default: 'env var SOCKET_SECURITY_API_KEY',\n // description: 'Socket API token'\n // },\n githubEventBefore: {\n type: 'string',\n default: '',\n description: 'Before marker'\n },\n githubEventAfter: {\n type: 'string',\n default: '',\n description: 'After marker'\n }\n },\n help: (command, { flags }) => `\n Usage\n $ ${command} [options]\n\n Options\n ${getFlagListOutput(flags, 6)}\n `\n}\n\nexport const cmdAction = {\n description: config.description,\n hidden: config.hidden,\n run: run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const githubEventBefore = String(cli.flags['githubEventBefore'] || '')\n const githubEventAfter = String(cli.flags['githubEventAfter'] || '')\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await runAction(githubEventBefore, githubEventAfter)\n}\n","import process from 'node:process'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { AuthError } from './errors'\nimport constants from '../constants'\n\nimport type { Spinner } from '@socketsecurity/registry/lib/spinner'\nimport type {\n SocketSdkErrorType,\n SocketSdkOperations\n} from '@socketsecurity/sdk'\n\nconst { API_V0_URL } = constants\n\nexport function handleUnsuccessfulApiResponse<T extends SocketSdkOperations>(\n _name: T,\n result: SocketSdkErrorType<T>,\n spinner: Spinner\n) {\n // SocketSdkErrorType['error'] is not typed.\n const resultErrorMessage = (<{ error?: Error }>result).error?.message\n const message =\n typeof resultErrorMessage === 'string'\n ? resultErrorMessage\n : 'No error message returned'\n if (result.status === 401 || result.status === 403) {\n spinner.stop()\n throw new AuthError(message)\n }\n spinner.error(\n `${colors.bgRed(colors.white('API returned an error:'))} ${message}`\n )\n process.exit(1)\n}\n\nexport async function handleApiCall<T>(\n value: T,\n description: string\n): Promise<T> {\n let result: T\n try {\n result = await value\n } catch (cause) {\n throw new Error(`Failed ${description}`, { cause })\n }\n return result\n}\n\nexport async function handleAPIError(code: number) {\n if (code === 400) {\n return 'One of the options passed might be incorrect.'\n } else if (code === 403) {\n return 'You might be trying to access an organization that is not linked to the API key you are logged in with.'\n }\n}\n\nexport async function queryAPI(path: string, apiToken: string) {\n return await fetch(`${API_V0_URL}/${path}`, {\n method: 'GET',\n headers: {\n Authorization: `Basic ${btoa(`${apiToken}:${apiToken}`)}`\n }\n })\n}\n","import fs from 'node:fs/promises'\n\n// @ts-ignore\nimport ScreenWidget from 'blessed/lib/widgets/screen'\nimport contrib from 'blessed-contrib'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nimport type { Widgets } from 'blessed' // Note: Widgets does not seem to actually work as code :'(\n\ntype FormattedData = {\n top_five_alert_types: { [key: string]: number }\n total_critical_alerts: { [key: string]: number }\n total_high_alerts: { [key: string]: number }\n total_medium_alerts: { [key: string]: number }\n total_low_alerts: { [key: string]: number }\n total_critical_added: { [key: string]: number }\n total_medium_added: { [key: string]: number }\n total_low_added: { [key: string]: number }\n total_high_added: { [key: string]: number }\n total_critical_prevented: { [key: string]: number }\n total_high_prevented: { [key: string]: number }\n total_medium_prevented: { [key: string]: number }\n total_low_prevented: { [key: string]: number }\n}\n\n// Note: This maps `new Date(date).getMonth()` to English three letters\nexport const Months = [\n 'Jan',\n 'Feb',\n 'Mar',\n 'Apr',\n 'May',\n 'Jun',\n 'Jul',\n 'Aug',\n 'Sep',\n 'Oct',\n 'Nov',\n 'Dec'\n] as const\n\nconst METRICS = [\n 'total_critical_alerts',\n 'total_high_alerts',\n 'total_medium_alerts',\n 'total_low_alerts',\n 'total_critical_added',\n 'total_medium_added',\n 'total_low_added',\n 'total_high_added',\n 'total_critical_prevented',\n 'total_high_prevented',\n 'total_medium_prevented',\n 'total_low_prevented'\n] as const\n\nexport async function displayAnalytics({\n apiToken,\n filePath,\n outputJson,\n repo,\n scope,\n time\n}: {\n apiToken: string\n scope: string\n time: number\n repo: string\n outputJson: boolean\n filePath: string\n}): Promise<void> {\n const spinner = new Spinner({ text: 'Fetching analytics data' }).start()\n\n let data: undefined | { [key: string]: any }[]\n if (scope === 'org') {\n data = await fetchOrgAnalyticsData(time, spinner, apiToken)\n } else if (repo) {\n data = await fetchRepoAnalyticsData(repo, time, spinner, apiToken)\n }\n\n if (data) {\n if (outputJson && !filePath) {\n console.log(data)\n } else if (filePath) {\n try {\n await fs.writeFile(filePath, JSON.stringify(data), 'utf8')\n console.log(`Data successfully written to ${filePath}`)\n } catch (e: any) {\n console.error(e)\n }\n } else {\n const fdata =\n scope === 'org' ? formatData(data, 'org') : formatData(data, 'repo')\n displayAnalyticsScreen(fdata)\n }\n }\n}\n\nfunction displayAnalyticsScreen(data: FormattedData): void {\n const screen: Widgets.Screen = new ScreenWidget({})\n const grid = new contrib.grid({ rows: 5, cols: 4, screen })\n\n renderLineCharts(\n grid,\n screen,\n 'Total critical alerts',\n [0, 0, 1, 2],\n data['total_critical_alerts']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total high alerts',\n [0, 2, 1, 2],\n data['total_high_alerts']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total critical alerts added to the main branch',\n [1, 0, 1, 2],\n data['total_critical_added']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total high alerts added to the main branch',\n [1, 2, 1, 2],\n data['total_high_added']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total critical alerts prevented from the main branch',\n [2, 0, 1, 2],\n data['total_critical_prevented']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total high alerts prevented from the main branch',\n [2, 2, 1, 2],\n data['total_high_prevented']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total medium alerts prevented from the main branch',\n [3, 0, 1, 2],\n data['total_medium_prevented']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total low alerts prevented from the main branch',\n [3, 2, 1, 2],\n data['total_low_prevented']\n )\n\n const bar = grid.set(4, 0, 1, 2, contrib.bar, {\n label: 'Top 5 alert types',\n barWidth: 10,\n barSpacing: 17,\n xOffset: 0,\n maxHeight: 9,\n barBgColor: 'magenta'\n })\n\n screen.append(bar) //must append before setting data\n\n bar.setData({\n titles: Object.keys(data.top_five_alert_types),\n data: Object.values(data.top_five_alert_types)\n })\n\n screen.render()\n\n screen.key(['escape', 'q', 'C-c'], () => process.exit(0))\n}\n\nasync function fetchOrgAnalyticsData(\n time: number,\n spinner: Spinner,\n apiToken: string\n): Promise<{ [key: string]: any }[] | undefined> {\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getOrgAnalytics(time.toString()),\n 'fetching analytics data'\n )\n\n if (result.success === false) {\n handleUnsuccessfulApiResponse('getOrgAnalytics', result, spinner)\n return undefined\n }\n\n spinner.stop()\n\n if (!result.data.length) {\n console.log('No analytics data is available for this organization yet.')\n return undefined\n }\n\n return result.data\n}\n\nasync function fetchRepoAnalyticsData(\n repo: string,\n time: number,\n spinner: Spinner,\n apiToken: string\n): Promise<{ [key: string]: any }[] | undefined> {\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getRepoAnalytics(repo, time.toString()),\n 'fetching analytics data'\n )\n\n if (result.success === false) {\n handleUnsuccessfulApiResponse('getRepoAnalytics', result, spinner)\n return undefined\n }\n\n spinner.stop()\n\n if (!result.data.length) {\n console.log('No analytics data is available for this organization yet.')\n return undefined\n }\n\n return result.data\n}\n\nfunction formatData(\n data: { [key: string]: any }[],\n scope: string\n): FormattedData {\n const formattedData = <Omit<FormattedData, 'top_five_alert_types'>>{}\n const sortedTopFiveAlerts: { [key: string]: number } = {}\n const totalTopAlerts: { [key: string]: number } = {}\n\n for (const metric of METRICS) {\n formattedData[metric] = {}\n }\n if (scope === 'org') {\n for (const entry of data) {\n const topFiveAlertTypes = entry['top_five_alert_types']\n for (const type of Object.keys(topFiveAlertTypes)) {\n const count = topFiveAlertTypes[type] ?? 0\n if (!totalTopAlerts[type]) {\n totalTopAlerts[type] = count\n } else {\n totalTopAlerts[type] += count\n }\n }\n }\n for (const metric of METRICS) {\n const formatted = formattedData[metric]\n for (const entry of data) {\n const date = formatDate(entry['created_at'])\n if (!formatted[date]) {\n formatted[date] = entry[metric]!\n } else {\n formatted[date] += entry[metric]!\n }\n }\n }\n } else if (scope === 'repo') {\n for (const entry of data) {\n const topFiveAlertTypes = entry['top_five_alert_types']\n for (const type of Object.keys(topFiveAlertTypes)) {\n const count = topFiveAlertTypes[type] ?? 0\n if (!totalTopAlerts[type]) {\n totalTopAlerts[type] = count\n } else if (count > (totalTopAlerts[type] ?? 0)) {\n totalTopAlerts[type] = count\n }\n }\n }\n for (const entry of data) {\n for (const metric of METRICS) {\n formattedData[metric]![formatDate(entry['created_at'])] = entry[metric]\n }\n }\n }\n\n const topFiveAlertEntries = Object.entries(totalTopAlerts)\n .sort(({ 1: a }, { 1: b }) => b - a)\n .slice(0, 5)\n for (const { 0: key, 1: value } of topFiveAlertEntries) {\n sortedTopFiveAlerts[key] = value\n }\n\n return {\n ...formattedData,\n top_five_alert_types: sortedTopFiveAlerts\n }\n}\nfunction formatDate(date: string): string {\n return `${Months[new Date(date).getMonth()]} ${new Date(date).getDate()}`\n}\n\nfunction renderLineCharts(\n grid: contrib.grid,\n screen: any,\n title: string,\n coords: number[],\n data: { [key: string]: number }\n): void {\n const line = grid.set(...coords, contrib.line, {\n style: { line: 'cyan', text: 'cyan', baseline: 'black' },\n xLabelPadding: 0,\n xPadding: 0,\n xOffset: 0,\n wholeNumbersOnly: true,\n legend: {\n width: 1\n },\n label: title\n })\n\n screen.append(line)\n\n const lineData = {\n x: Object.keys(data),\n y: Object.values(data)\n }\n\n line.setData([lineData])\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { displayAnalytics } from './display-analytics'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'analytics',\n description: `Look up analytics data`,\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n scope: {\n type: 'string',\n shortFlag: 's',\n default: 'org',\n description:\n \"Scope of the analytics data - either 'org' or 'repo', default: org\"\n },\n time: {\n type: 'number',\n shortFlag: 't',\n default: 7,\n description: 'Time filter - either 7, 30 or 90, default: 7'\n },\n repo: {\n type: 'string',\n shortFlag: 'r',\n default: '',\n description: 'Name of the repository'\n },\n file: {\n type: 'string',\n shortFlag: 'f',\n default: '',\n description: 'Path to a local file to save the output'\n }\n },\n help: (command, { flags }) => `\n Usage\n $ ${command} --scope=<scope> --time=<time filter>\n\n Default parameters are set to show the organization-level analytics over the\n last 7 days.\n\n Options\n ${getFlagListOutput(flags, 6)}\n\n Examples\n $ ${command} --scope=org --time=7\n $ ${command} --scope=org --time=30\n $ ${command} --scope=repo --repo=test-repo --time=30\n `\n}\n\nexport const cmdAnalytics = {\n description: config.description,\n hidden: config.hidden,\n run: run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const { repo, scope, time } = cli.flags\n\n const badScope = scope !== 'org' && scope !== 'repo'\n const badTime = time !== 7 && time !== 30 && time !== 90\n const badRepo = scope === 'repo' && !repo\n\n if (badScope || badTime || badRepo) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Scope must be \"repo\" or \"org\" ${badScope ? colors.red('(bad!)') : colors.green('(ok)')}\\n\n - The time filter must either be 7, 30 or 90 ${badTime ? colors.red('(bad!)') : colors.green('(ok)')}\\n\n - Repository name using --repo when scope is \"repo\" ${badRepo ? colors.red('(bad!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API token.'\n )\n }\n\n return await displayAnalytics({\n apiToken,\n scope,\n time,\n repo: String(repo || ''),\n outputJson: Boolean(cli.flags['json']),\n filePath: String(cli.flags['file'] || '')\n })\n}\n","import { Separator, select } from '@socketsecurity/registry/lib/prompts'\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\ntype Choice<Value> = {\n description?: string\n disabled?: boolean | string\n name?: string\n type?: never\n value: Value\n}\n\ntype AuditChoice = Choice<string>\n\ntype AuditChoices = (Separator | AuditChoice)[]\n\nexport async function getAuditLog({\n apiToken,\n orgSlug,\n outputJson,\n outputMarkdown,\n page,\n perPage,\n type\n}: {\n apiToken: string\n outputJson: boolean\n outputMarkdown: boolean\n orgSlug: string\n page: number\n perPage: number\n type: string\n}): Promise<void> {\n const spinner = new Spinner({\n text: `Looking up audit log for ${orgSlug}\\n`\n }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getAuditLogEvents(orgSlug, {\n outputJson,\n outputMarkdown,\n orgSlug,\n type,\n page,\n per_page: perPage\n }),\n `Looking up audit log for ${orgSlug}\\n`\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('getAuditLogEvents', result, spinner)\n return\n }\n\n spinner.stop()\n\n const data: AuditChoices = []\n const logDetails: { [key: string]: string } = {}\n\n for (const d of result.data.results) {\n const { created_at } = d\n if (created_at) {\n const name = `${new Date(created_at).toLocaleDateString('en-us', { year: 'numeric', month: 'numeric', day: 'numeric' })} - ${d.user_email} - ${d.type} - ${d.ip_address} - ${d.user_agent}`\n data.push(<AuditChoice>{ name }, new Separator())\n logDetails[name] = JSON.stringify(d.payload)\n }\n }\n\n console.log(\n logDetails[\n (await select({\n message: type\n ? `\\n Audit log for: ${orgSlug} with type: ${type}\\n`\n : `\\n Audit log for: ${orgSlug}\\n`,\n choices: data,\n pageSize: 30\n })) as any\n ]\n )\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { getAuditLog } from './get-audit-log'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'audit-log',\n description: 'Look up the audit log for an organization',\n hidden: false,\n flags: {\n type: {\n type: 'string',\n shortFlag: 't',\n default: '',\n description: 'Type of log event'\n },\n perPage: {\n type: 'number',\n shortFlag: 'pp',\n default: 30,\n description: 'Results per page - default is 30'\n },\n page: {\n type: 'number',\n shortFlag: 'p',\n default: 1,\n description: 'Page number - default is 1'\n },\n ...commonFlags,\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg\n `\n}\n\nexport const cmdAuditLog = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const type = String(cli.flags['type'] || '')\n const [orgSlug = ''] = cli.input\n\n if (!orgSlug) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await getAuditLog({\n apiToken,\n orgSlug,\n outputJson: Boolean(cli.flags['json']),\n outputMarkdown: Boolean(cli.flags['markdown']),\n page: Number(cli.flags['page'] || 0),\n perPage: Number(cli.flags['perPage'] || 0),\n type: type.charAt(0).toUpperCase() + type.slice(1)\n })\n}\n","import { promises as fs } from 'fs'\nimport { existsSync } from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { runBin } from '@socketsecurity/registry/lib/npm'\n\nimport constants from '../../constants'\n\nconst {\n SBOM_SIGN_ALGORITHM, // Algorithm. Example: RS512\n SBOM_SIGN_PRIVATE_KEY, // Location to the RSA private key\n SBOM_SIGN_PUBLIC_KEY // Optional. Location to the RSA public key\n} = process.env\n\nconst { NPM, PNPM, cdxgenBinPath, synpBinPath } = constants\n\nconst nodejsPlatformTypes = new Set([\n 'javascript',\n 'js',\n 'nodejs',\n NPM,\n PNPM,\n 'ts',\n 'tsx',\n 'typescript'\n])\n\nexport async function runCycloneDX(yargv: any) {\n let cleanupPackageLock = false\n if (\n yargv.type !== 'yarn' &&\n nodejsPlatformTypes.has(yargv.type) &&\n existsSync('./yarn.lock')\n ) {\n if (existsSync('./package-lock.json')) {\n yargv.type = NPM\n } else {\n // Use synp to create a package-lock.json from the yarn.lock,\n // based on the node_modules folder, for a more accurate SBOM.\n try {\n await runBin(await fs.realpath(synpBinPath), [\n '--source-file',\n './yarn.lock'\n ])\n yargv.type = NPM\n cleanupPackageLock = true\n } catch {}\n }\n }\n\n await runBin(await fs.realpath(cdxgenBinPath), argvToArray(yargv), {\n env: {\n NODE_ENV: '',\n SBOM_SIGN_ALGORITHM,\n SBOM_SIGN_PRIVATE_KEY,\n SBOM_SIGN_PUBLIC_KEY\n },\n stdio: 'inherit'\n })\n if (cleanupPackageLock) {\n try {\n await fs.rm('./package-lock.json')\n } catch {}\n }\n const fullOutputPath = path.join(process.cwd(), yargv.output)\n if (existsSync(fullOutputPath)) {\n console.log(colors.cyanBright(`${yargv.output} created!`))\n }\n}\n\nfunction argvToArray(argv: {\n [key: string]: boolean | null | number | string | (string | number)[]\n}): string[] {\n if (argv['help']) return ['--help']\n const result = []\n for (const { 0: key, 1: value } of Object.entries(argv)) {\n if (key === '_' || key === '--') continue\n if (key === 'babel' || key === 'install-deps' || key === 'validate') {\n // cdxgen documents no-babel, no-install-deps, and no-validate flags so\n // use them when relevant.\n result.push(`--${value ? key : `no-${key}`}`)\n } else if (value === true) {\n result.push(`--${key}`)\n } else if (typeof value === 'string') {\n result.push(`--${key}`, String(value))\n } else if (Array.isArray(value)) {\n result.push(`--${key}`, ...value.map(String))\n }\n }\n if (argv['--']) {\n result.push('--', ...(argv as any)['--'])\n }\n return result\n}\n","// import { meowOrExit } from '../../utils/meow-with-subcommands'\nimport process from 'node:process'\n\nimport yargsParse from 'yargs-parser'\n\nimport { pluralize } from '@socketsecurity/registry/lib/words'\n\nimport { runCycloneDX } from './run-cyclonedx'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\n// TODO: convert yargs to meow. Or convert all the other things to yargs.\nconst toLower = (arg: string) => arg.toLowerCase()\nconst arrayToLower = (arg: string[]) => arg.map(toLower)\nconst yargsConfig = {\n configuration: {\n 'camel-case-expansion': false,\n 'strip-aliased': true,\n 'parse-numbers': false,\n 'populate--': true,\n 'unknown-options-as-args': true\n },\n coerce: {\n author: arrayToLower,\n filter: arrayToLower,\n only: arrayToLower,\n profile: toLower,\n standard: arrayToLower,\n type: toLower\n },\n default: {\n //author: ['OWASP Foundation'],\n //'auto-compositions': true,\n //babel: true,\n //evidence: false,\n //'include-crypto': false,\n //'include-formulation': false,\n\n // Default 'install-deps' to `false` and 'lifecycle' to 'pre-build' to\n // sidestep arbitrary code execution during a cdxgen scan.\n // https://github.com/CycloneDX/cdxgen/issues/1328\n 'install-deps': false,\n lifecycle: 'pre-build',\n\n //output: 'bom.json',\n //profile: 'generic',\n //'project-version': '',\n //recurse: true,\n //'server-host': '127.0.0.1',\n //'server-port': '9090',\n //'spec-version': '1.5',\n type: 'js'\n //validate: true,\n },\n alias: {\n help: ['h'],\n output: ['o'],\n print: ['p'],\n recurse: ['r'],\n 'resolve-class': ['c'],\n type: ['t'],\n version: ['v']\n },\n array: [\n { key: 'author', type: 'string' },\n { key: 'exclude', type: 'string' },\n { key: 'filter', type: 'string' },\n { key: 'only', type: 'string' },\n { key: 'standard', type: 'string' }\n ],\n boolean: [\n 'auto-compositions',\n 'babel',\n 'deep',\n 'evidence',\n 'fail-on-error',\n 'generate-key-and-sign',\n 'help',\n 'include-formulation',\n 'include-crypto',\n 'install-deps',\n 'print',\n 'required-only',\n 'server',\n 'validate',\n 'version'\n ],\n string: [\n 'api-key',\n 'lifecycle',\n 'output',\n 'parent-project-id',\n 'profile',\n 'project-group',\n 'project-name',\n 'project-version',\n 'project-id',\n 'server-host',\n 'server-port',\n 'server-url',\n 'spec-version'\n ]\n}\n\nconst config: CliCommandConfig = {\n commandName: 'cdxgen',\n description: 'Create an SBOM with CycloneDX generator (cdxgen)',\n hidden: false,\n flags: {\n // TODO: convert from yargsConfig\n },\n help: (command, config) => `\n Usage\n $ ${command} [options]\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n `\n}\n\nexport const cmdCdxgen = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n allowUnknownFlags: true,\n argv: argv.filter(s => s !== '--help' && s !== '-h'), // Don't let meow take over --help\n config,\n importMeta,\n parentName\n })\n //\n //\n // if (cli.input.length)\n // console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n // - Unexpected arguments\\n\n // `)\n // config.help(parentName, config)\n // return\n // }\n\n // TODO: convert to meow\n const yargv = {\n ...yargsParse(argv as Array<string>, yargsConfig)\n } as any // as Record<string, unknown>;\n\n const unknown: Array<string> = yargv._\n const { length: unknownLength } = unknown\n if (unknownLength) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `Unknown ${pluralize('argument', unknownLength)}: ${yargv._.join(', ')}`\n )\n return\n }\n\n if (yargv.output === undefined) {\n yargv.output = 'socket-cdx.json'\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await runCycloneDX(yargv)\n}\n","// @ts-ignore\nimport chalkTable from 'chalk-table'\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { AuthError } from '../../utils/errors'\nimport { getDefaultToken, setupSdk } from '../../utils/sdk'\n\nexport async function findDependencies({\n limit,\n offset,\n outputJson\n}: {\n outputJson: boolean\n limit: number\n offset: number\n}): Promise<void> {\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n const spinner = new Spinner({ text: 'Searching dependencies...' }).start()\n const socketSdk = await setupSdk(apiToken)\n\n const result = await handleApiCall(\n socketSdk.searchDependencies({ limit, offset }),\n 'Searching dependencies'\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('searchDependencies', result, spinner)\n return\n }\n\n spinner.stop('Organization dependencies:')\n\n if (outputJson) {\n console.log(result.data)\n return\n }\n\n const options = {\n columns: [\n { field: 'namespace', name: colors.cyan('Namespace') },\n { field: 'name', name: colors.cyan('Name') },\n { field: 'version', name: colors.cyan('Version') },\n { field: 'repository', name: colors.cyan('Repository') },\n { field: 'branch', name: colors.cyan('Branch') },\n { field: 'type', name: colors.cyan('Type') },\n { field: 'direct', name: colors.cyan('Direct') }\n ]\n }\n\n console.log(chalkTable(options, result.data.rows))\n}\n","import { findDependencies } from './find-dependencies'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'dependencies',\n description:\n 'Search for any dependency that is being used in your organization',\n hidden: false,\n flags: {\n ...commonFlags,\n limit: {\n type: 'number',\n shortFlag: 'l',\n default: 50,\n description: 'Maximum number of dependencies returned'\n },\n offset: {\n type: 'number',\n shortFlag: 'o',\n default: 0,\n description: 'Page number'\n },\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n ${command}\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n ${command} --limit 20 --offset 10\n `\n}\n\nexport const cmdScanCreate = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n // TODO: markdown flag is ignored\n await findDependencies({\n limit: Number(cli.flags['limit'] || 0) || 0,\n offset: Number(cli.flags['offset'] || 0) || 0,\n outputJson: Boolean(cli.flags['json'])\n })\n}\n","import fs from 'node:fs'\nimport util from 'node:util'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleAPIError, queryAPI } from '../../utils/api'\n\nexport async function getDiffScan(\n {\n after,\n before,\n file,\n orgSlug,\n outputJson\n }: {\n outputJson: boolean\n outputMarkdown: boolean\n before: string\n after: string\n preview: boolean\n orgSlug: string\n file: string\n },\n apiToken: string\n): Promise<void> {\n const spinnerText = 'Getting diff scan... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const response = await queryAPI(\n `${orgSlug}/full-scans/diff?before=${before}&after=${after}&preview`,\n apiToken\n )\n const data = await response.json()\n\n if (!response.ok) {\n const err = await handleAPIError(response.status)\n spinner.error(`${colors.bgRed(colors.white(response.statusText))}: ${err}`)\n return\n }\n\n spinner.stop()\n\n if (file && !outputJson) {\n fs.writeFile(file, JSON.stringify(data), err => {\n err\n ? console.error(err)\n : console.log(`Data successfully written to ${file}`)\n })\n return\n }\n\n if (outputJson) {\n console.log(`\\n Diff scan result: \\n`)\n console.log(\n util.inspect(data, { showHidden: false, depth: null, colors: true })\n )\n console.log(\n `\\n View this diff scan in the Socket dashboard: ${colors.cyan((data as any)?.['diff_report_url'])}`\n )\n return\n }\n\n console.log('Diff scan result:')\n console.log(data)\n console.log(\n `\\n 📝 To display the detailed report in the terminal, use the --json flag \\n`\n )\n console.log(\n `\\n View this diff scan in the Socket dashboard: ${colors.cyan((data as any)?.['diff_report_url'])}`\n )\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { getDiffScan } from './get-diff-scan'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'get',\n description: 'Get a diff scan for an organization',\n hidden: false,\n flags: {\n ...commonFlags,\n before: {\n type: 'string',\n shortFlag: 'b',\n default: '',\n description: 'The full scan ID of the base scan'\n },\n after: {\n type: 'string',\n shortFlag: 'a',\n default: '',\n description: 'The full scan ID of the head scan'\n },\n preview: {\n type: 'boolean',\n shortFlag: 'p',\n default: true,\n description: 'A boolean flag to persist or not the diff scan result'\n },\n file: {\n type: 'string',\n shortFlag: 'f',\n default: '',\n description: 'Path to a local file where the output should be saved'\n },\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug> --before=<before> --after=<after>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeCorp --before=aaa0aa0a-aaaa-0000-0a0a-0000000a00a0 --after=aaa1aa1a-aaaa-1111-1a1a-1111111a11a1\n `\n}\n\nexport const cmdDiffScanGet = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const before = String(cli.flags['before'] || '')\n const after = String(cli.flags['after'] || '')\n const [orgSlug = ''] = cli.input\n\n if (!before || !after || cli.input.length < 1) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Specify a before and after full scan ID ${!before && !after ? colors.red('(missing before and after!)') : !before ? colors.red('(missing before!)') : !after ? colors.red('(missing after!)') : colors.green('(ok)')}\\n\n - To get full scans IDs, you can run the command \"socket scan list <your org slug>\".\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await getDiffScan(\n {\n outputJson: Boolean(cli.flags['json']),\n outputMarkdown: Boolean(cli.flags['markdown']),\n before,\n after,\n preview: Boolean(cli.flags['preview']),\n orgSlug,\n file: String(cli.flags['file'] || '')\n },\n apiToken\n )\n}\n","import { cmdDiffScanGet } from './cmd-diff-scan-get'\nimport { meowWithSubcommands } from '../../utils/meow-with-subcommands'\n\nimport type { CliSubcommand } from '../../utils/meow-with-subcommands'\n\nconst description = 'Diff scans related commands'\n\nexport const cmdDiffScan: CliSubcommand = {\n description,\n async run(argv, importMeta, { parentName }) {\n await meowWithSubcommands(\n {\n get: cmdDiffScanGet\n },\n {\n argv,\n description,\n importMeta,\n name: parentName + ' diff-scan'\n }\n )\n }\n}\n","import { getManifestData } from '@socketsecurity/registry'\nimport { runScript } from '@socketsecurity/registry/lib/npm'\nimport {\n fetchPackagePackument,\n readPackageJson\n} from '@socketsecurity/registry/lib/packages'\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport constants from '../../constants'\nimport {\n Arborist,\n SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES,\n SafeArborist\n} from '../../shadow/arborist/lib/arborist'\nimport {\n findPackageNodes,\n getCveInfoByPackage,\n getPackagesAlerts,\n updateNode\n} from '../../shadow/arborist/lib/arborist/reify'\n// import { detect } from '../../utils/package-manager-detector'\n\nimport type { SafeNode } from '../../shadow/arborist/lib/node'\n\nconst { NPM } = constants\n\nfunction isTopLevel(tree: SafeNode, node: SafeNode): boolean {\n return tree.children.get(node.name) === node\n}\n\nexport async function runFix() {\n const spinner = new Spinner().start()\n const cwd = process.cwd()\n const editablePkgJson = await readPackageJson(cwd, { editable: true })\n // const agentDetails = await detect()\n\n const arb = new SafeArborist({\n path: cwd,\n ...SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES\n })\n await arb.reify()\n const alerts = await getPackagesAlerts(arb as any, {\n consolidate: true,\n includeExisting: true,\n includeUnfixable: false\n })\n const infoByPkg = getCveInfoByPackage(alerts)\n await arb.buildIdealTree()\n if (infoByPkg) {\n for (const { 0: name, 1: infos } of infoByPkg) {\n let revertToIdealTree = arb.idealTree!\n arb.idealTree = null\n // eslint-disable-next-line no-await-in-loop\n await arb.buildIdealTree()\n const tree = arb.idealTree!\n const hasUpgrade = !!getManifestData(NPM, name)\n if (hasUpgrade) {\n spinner.stop()\n console.log(`Skipping ${name}. Socket Optimize package exists.`)\n spinner.start()\n continue\n }\n const nodes = findPackageNodes(tree, name)\n const packument =\n nodes.length && infos.length\n ? // eslint-disable-next-line no-await-in-loop\n await fetchPackagePackument(name)\n : null\n if (packument) {\n for (\n let i = 0, { length: nodesLength } = nodes;\n i < nodesLength;\n i += 1\n ) {\n const node = nodes[i]!\n for (\n let j = 0, { length: infosLength } = infos;\n j < infosLength;\n j += 1\n ) {\n const { firstPatchedVersionIdentifier, vulnerableVersionRange } =\n infos[j]!\n const { version: oldVersion } = node\n if (\n updateNode(\n node,\n packument,\n vulnerableVersionRange,\n firstPatchedVersionIdentifier\n )\n ) {\n try {\n // eslint-disable-next-line no-await-in-loop\n await runScript('test', [], { stdio: 'pipe' })\n spinner.info(`Patched ${name} ${oldVersion} -> ${node.version}`)\n spinner.start()\n if (isTopLevel(tree, node)) {\n for (const depField of [\n 'dependencies',\n 'optionalDependencies',\n 'peerDependencies'\n ]) {\n const oldVersion = (\n editablePkgJson.content[depField] as any\n )?.[name]\n if (oldVersion) {\n const decorator = /^[~^]/.exec(oldVersion)?.[0] ?? ''\n ;(editablePkgJson as any).content[depField][name] =\n `${decorator}${node.version}`\n }\n }\n }\n // eslint-disable-next-line no-await-in-loop\n await editablePkgJson.save()\n } catch {\n spinner.error(`Reverting ${name} to ${oldVersion}`)\n spinner.start()\n arb.idealTree = revertToIdealTree\n }\n } else {\n spinner.stop()\n console.log(`Could not patch ${name} ${oldVersion}`)\n spinner.start()\n }\n }\n }\n }\n }\n }\n const arb2 = new Arborist({ path: cwd })\n arb2.idealTree = arb.idealTree\n await arb2.reify()\n spinner.stop()\n}\n","import { runFix } from './run-fix'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'fix',\n description: 'Fix \"fixable\" Socket alerts',\n hidden: true,\n flags: {\n ...commonFlags\n },\n help: (command, config) => `\n Usage\n $ ${command}\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n `\n}\n\nexport const cmdFix = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await runFix()\n}\n","export function objectSome(obj: Record<string, any>): boolean {\n for (const key in obj) {\n if (obj[key]) {\n return true\n }\n }\n return false\n}\n\nexport function pick<T extends Record<string, any>, K extends keyof T>(\n input: T,\n keys: K[] | ReadonlyArray<K>\n): Pick<T, K> {\n const result: Partial<Pick<T, K>> = {}\n for (const key of keys) {\n result[key] = input[key]\n }\n return result as Pick<T, K>\n}\n","export function stringJoinWithSeparateFinalSeparator(\n list: string[],\n separator: string = ' and '\n): string {\n const values = list.filter(Boolean)\n const { length } = values\n if (!length) {\n return ''\n }\n if (length === 1) {\n return values[0]!\n }\n const finalValue = values.pop()\n return `${values.join(', ')}${separator}${finalValue}`\n}\n","import { pick } from '../objects'\nimport { stringJoinWithSeparateFinalSeparator } from '../strings'\n\nimport type { SocketSdkReturnType } from '@socketsecurity/sdk'\n\nexport type SocketSdkAlertList =\n SocketSdkReturnType<'getIssuesByNPMPackage'>['data']\n\nexport type SocketSdkAlert = SocketSdkAlertList[number]['value'] extends\n | infer U\n | undefined\n ? U\n : never\n\n// Ordered from most severe to least.\nconst SEVERITIES_BY_ORDER: SocketSdkAlert['severity'][] = [\n 'critical',\n 'high',\n 'middle',\n 'low'\n]\n\nfunction getDesiredSeverities(\n lowestToInclude: SocketSdkAlert['severity'] | undefined\n): SocketSdkAlert['severity'][] {\n const result: SocketSdkAlert['severity'][] = []\n for (const severity of SEVERITIES_BY_ORDER) {\n result.push(severity)\n if (severity === lowestToInclude) {\n break\n }\n }\n return result\n}\n\nexport function formatSeverityCount(\n severityCount: Record<SocketSdkAlert['severity'], number>\n): string {\n const summary: string[] = []\n for (const severity of SEVERITIES_BY_ORDER) {\n if (severityCount[severity]) {\n summary.push(`${severityCount[severity]} ${severity}`)\n }\n }\n return stringJoinWithSeparateFinalSeparator(summary)\n}\n\nexport function getSeverityCount(\n issues: SocketSdkAlertList,\n lowestToInclude: SocketSdkAlert['severity'] | undefined\n): Record<SocketSdkAlert['severity'], number> {\n const severityCount = pick(\n { low: 0, middle: 0, high: 0, critical: 0 },\n getDesiredSeverities(lowestToInclude)\n ) as Record<SocketSdkAlert['severity'], number>\n\n for (const issue of issues) {\n const { value } = issue\n if (!value) {\n continue\n }\n if (severityCount[value.severity] !== undefined) {\n severityCount[value.severity] += 1\n }\n }\n return severityCount\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { PackageData } from './get-package-info'\nimport { getSeverityCount } from '../../utils/alert/severity'\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { getPublicToken, setupSdk } from '../../utils/sdk'\n\nexport async function fetchPackageInfo(\n pkgName: string,\n pkgVersion: string,\n includeAllIssues: boolean,\n spinner: Spinner\n): Promise<void | PackageData> {\n const socketSdk = await setupSdk(getPublicToken())\n const result = await handleApiCall(\n socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion),\n 'looking up package'\n )\n const scoreResult = await handleApiCall(\n socketSdk.getScoreByNPMPackage(pkgName, pkgVersion),\n 'looking up package score'\n )\n\n if (result.success === false) {\n return handleUnsuccessfulApiResponse(\n 'getIssuesByNPMPackage',\n result,\n spinner\n )\n }\n\n if (scoreResult.success === false) {\n return handleUnsuccessfulApiResponse(\n 'getScoreByNPMPackage',\n scoreResult,\n spinner\n )\n }\n\n const severityCount = getSeverityCount(\n result.data,\n includeAllIssues ? undefined : 'high'\n )\n\n return {\n data: result.data,\n severityCount,\n score: scoreResult.data\n }\n}\n","import process from 'node:process'\n\nimport colors from 'yoctocolors-cjs'\n\nimport constants from '@socketsecurity/registry/lib/constants'\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { PackageData } from './get-package-info'\nimport { formatSeverityCount } from '../../utils/alert/severity'\nimport { ColorOrMarkdown } from '../../utils/color-or-markdown'\nimport { objectSome } from '../../utils/objects'\nimport {\n getSocketDevAlertUrl,\n getSocketDevPackageOverviewUrl\n} from '../../utils/socket-url'\n\nimport type { SocketSdkReturnType } from '@socketsecurity/sdk'\n\nconst { NPM } = constants\n\nexport function formatPackageInfo(\n { data, score, severityCount }: PackageData,\n {\n name,\n outputJson,\n outputMarkdown,\n pkgName,\n pkgVersion,\n strict\n }: {\n includeAllIssues: boolean\n outputJson: boolean\n outputMarkdown: boolean\n pkgName: string\n pkgVersion: string\n strict: boolean\n } & { name: string },\n spinner: Spinner\n): void {\n if (outputJson) {\n console.log(JSON.stringify(data, undefined, 2))\n } else {\n console.log('\\nPackage report card:')\n const scoreResult = {\n 'Supply Chain Risk': Math.floor(score.supplyChainRisk.score * 100),\n Maintenance: Math.floor(score.maintenance.score * 100),\n Quality: Math.floor(score.quality.score * 100),\n Vulnerabilities: Math.floor(score.vulnerability.score * 100),\n License: Math.floor(score.license.score * 100)\n }\n Object.entries(scoreResult).map(score =>\n console.log(`- ${score[0]}: ${formatScore(score[1])}`)\n )\n console.log('\\n')\n if (objectSome(severityCount)) {\n spinner[strict ? 'error' : 'success'](\n `Package has these issues: ${formatSeverityCount(severityCount)}`\n )\n formatPackageIssuesDetails(data, outputMarkdown)\n } else {\n spinner.success('Package has no issues')\n }\n\n const format = new ColorOrMarkdown(!!outputMarkdown)\n const url = getSocketDevPackageOverviewUrl(NPM, pkgName, pkgVersion)\n\n console.log('\\n')\n if (pkgVersion === 'latest') {\n console.log(\n `Detailed info on socket.dev: ${format.hyperlink(`${pkgName}`, url, { fallbackToUrl: true })}`\n )\n } else {\n console.log(\n `Detailed info on socket.dev: ${format.hyperlink(`${pkgName} v${pkgVersion}`, url, { fallbackToUrl: true })}`\n )\n }\n if (!outputMarkdown) {\n console.log(\n colors.dim(\n `\\nOr rerun ${colors.italic(name)} using the ${colors.italic('--json')} flag to get full JSON output`\n )\n )\n }\n }\n\n if (strict && objectSome(severityCount)) {\n process.exit(1)\n }\n}\n\nfunction formatPackageIssuesDetails(\n packageData: SocketSdkReturnType<'getIssuesByNPMPackage'>['data'],\n outputMarkdown: boolean\n) {\n const issueDetails = packageData.filter(\n d => d.value?.severity === 'high' || d.value?.severity === 'critical'\n )\n\n const uniqueIssues = issueDetails.reduce(\n (\n acc: { [key: string]: { count: number; label: string | undefined } },\n issue\n ) => {\n const { type } = issue\n if (type) {\n if (acc[type] === undefined) {\n acc[type] = {\n label: issue.value?.label,\n count: 1\n }\n } else {\n acc[type]!.count += 1\n }\n }\n return acc\n },\n {}\n )\n\n const format = new ColorOrMarkdown(!!outputMarkdown)\n for (const issue of Object.keys(uniqueIssues)) {\n const issueWithLink = format.hyperlink(\n `${uniqueIssues[issue]?.label}`,\n getSocketDevAlertUrl(issue),\n { fallbackToUrl: true }\n )\n if (uniqueIssues[issue]?.count === 1) {\n console.log(`- ${issueWithLink}`)\n } else {\n console.log(`- ${issueWithLink}: ${uniqueIssues[issue]?.count}`)\n }\n }\n}\n\nfunction formatScore(score: number): string {\n if (score > 80) {\n return colors.green(`${score}`)\n } else if (score < 80 && score > 60) {\n return colors.yellow(`${score}`)\n }\n return colors.red(`${score}`)\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { fetchPackageInfo } from './fetch-package-info'\nimport { formatPackageInfo } from './format-package-info'\n\nimport type { SocketSdkAlert } from '../../utils/alert/severity'\nimport type { SocketSdkReturnType } from '@socketsecurity/sdk'\n\nexport interface PackageData {\n data: SocketSdkReturnType<'getIssuesByNPMPackage'>['data']\n severityCount: Record<SocketSdkAlert['severity'], number>\n score: SocketSdkReturnType<'getScoreByNPMPackage'>['data']\n}\n\nexport async function getPackageInfo({\n commandName,\n includeAllIssues,\n outputJson,\n outputMarkdown,\n pkgName,\n pkgVersion,\n strict\n}: {\n commandName: string\n includeAllIssues: boolean\n outputJson: boolean\n outputMarkdown: boolean\n pkgName: string\n pkgVersion: string\n strict: boolean\n}) {\n const spinnerText =\n pkgVersion === 'latest'\n ? `Looking up data for the latest version of ${pkgName}`\n : `Looking up data for version ${pkgVersion} of ${pkgName}`\n const spinner = new Spinner({ text: spinnerText }).start()\n const packageData = await fetchPackageInfo(\n pkgName,\n pkgVersion,\n includeAllIssues,\n spinner\n )\n if (packageData) {\n formatPackageInfo(\n packageData,\n {\n name: commandName,\n includeAllIssues,\n outputJson,\n outputMarkdown,\n pkgName,\n pkgVersion,\n strict\n },\n spinner\n )\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { getPackageInfo } from './get-package-info'\nimport { commonFlags, outputFlags, validationFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'info',\n description: 'Look up info regarding a package',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n ...validationFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <name>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} webtorrent\n $ ${command} webtorrent@1.9.1\n `\n}\n\nexport const cmdInfo = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [rawPkgName = ''] = cli.input\n\n if (!rawPkgName || cli.input.length > 1) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Expecting a package name ${!rawPkgName ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Can only accept one package at a time ${cli.input.length > 1 ? colors.red('(got ' + cli.input.length + '!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n const versionSeparator = rawPkgName.lastIndexOf('@')\n const pkgName =\n versionSeparator < 1 ? rawPkgName : rawPkgName.slice(0, versionSeparator)\n const pkgVersion =\n versionSeparator < 1 ? 'latest' : rawPkgName.slice(versionSeparator + 1)\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await getPackageInfo({\n commandName: `${parentName} ${config.commandName}`,\n includeAllIssues: Boolean(cli.flags['all']),\n outputJson: Boolean(cli.flags['json']),\n outputMarkdown: Boolean(cli.flags['markdown']),\n pkgName,\n pkgVersion,\n strict: Boolean(cli.flags['strict'])\n })\n}\n","import { updateSetting } from '../../utils/settings'\n\nexport function applyLogin(\n apiToken: string,\n enforcedOrgs: Array<string>,\n apiBaseUrl: string | undefined,\n apiProxy: string | undefined\n) {\n updateSetting('enforcedOrgs', enforcedOrgs)\n updateSetting('apiToken', apiToken)\n updateSetting('apiBaseUrl', apiBaseUrl)\n updateSetting('apiProxy', apiProxy)\n}\n","import terminalLink from 'terminal-link'\n\nimport {\n type Separator,\n confirm,\n password,\n select\n} from '@socketsecurity/registry/lib/prompts'\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { applyLogin } from './apply-login'\nimport constants from '../../constants'\nimport { AuthError } from '../../utils/errors'\nimport { setupSdk } from '../../utils/sdk'\nimport { getSetting } from '../../utils/settings'\n\nimport type { SocketSdkReturnType } from '@socketsecurity/sdk'\n\n// TODO: this type should come from a general Socket REST API type doc\ntype Choice<Value> = {\n value: Value\n name?: string\n description?: string\n disabled?: boolean | string\n type?: never\n}\ntype OrgChoice = Choice<string>\ntype OrgChoices = Array<Separator | OrgChoice>\nconst { SOCKET_PUBLIC_API_TOKEN } = constants\n\nexport async function attemptLogin(\n apiBaseUrl: string | undefined,\n apiProxy: string | undefined\n) {\n const apiToken =\n (await password({\n message: `Enter your ${terminalLink(\n 'Socket.dev API key',\n 'https://docs.socket.dev/docs/api-keys'\n )} (leave blank for a public key)`\n })) || SOCKET_PUBLIC_API_TOKEN\n\n apiBaseUrl ??= getSetting('apiBaseUrl') ?? undefined\n apiProxy ??= getSetting('apiProxy') ?? undefined\n\n const spinner = new Spinner({ text: 'Verifying API key...' }).start()\n\n let orgs: SocketSdkReturnType<'getOrganizations'>['data']\n try {\n const sdk = await setupSdk(apiToken, apiBaseUrl, apiProxy)\n const result = await sdk.getOrganizations()\n if (!result.success) {\n throw new AuthError()\n }\n orgs = result.data\n spinner.success('API key verified')\n } catch {\n spinner.error('Invalid API key')\n return\n }\n\n const enforcedChoices: OrgChoices = Object.values(orgs.organizations)\n .filter(org => org?.plan === 'enterprise')\n .map(org => ({\n name: org.name,\n value: org.id\n }))\n\n let enforcedOrgs: Array<string> = []\n\n if (enforcedChoices.length > 1) {\n const id = <string | null>await select({\n message:\n \"Which organization's policies should Socket enforce system-wide?\",\n choices: enforcedChoices.concat({\n name: 'None',\n value: '',\n description: 'Pick \"None\" if this is a personal device'\n })\n })\n if (id) {\n enforcedOrgs = [id]\n }\n } else if (enforcedChoices.length) {\n const confirmOrg = await confirm({\n message: `Should Socket enforce ${(enforcedChoices[0] as OrgChoice)?.name}'s security policies system-wide?`,\n default: true\n })\n if (confirmOrg) {\n const existing = <OrgChoice>enforcedChoices[0]\n if (existing) {\n enforcedOrgs = [existing.value]\n }\n }\n }\n\n const oldToken = getSetting('apiToken')\n try {\n applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy)\n spinner.success(`API credentials ${oldToken ? 'updated' : 'set'}`)\n } catch {\n spinner.error(`API login failed`)\n }\n}\n","import isInteractive from '@socketregistry/is-interactive/index.cjs'\n\nimport { attemptLogin } from './attempt-login'\nimport { commonFlags } from '../../flags'\nimport { InputError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'login',\n description: 'Socket API login',\n hidden: false,\n flags: {\n ...commonFlags,\n apiBaseUrl: {\n type: 'string',\n description: 'API server to connect to for login'\n },\n apiProxy: {\n type: 'string',\n description: 'Proxy to use when making connection to API server'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command}\n\n Logs into the Socket API by prompting for an API key\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command}\n $ ${command} --api-proxy=http://localhost:1234\n `\n}\n\nexport const cmdLogin = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n let apiBaseUrl = cli.flags['apiBaseUrl'] as string | undefined\n let apiProxy = cli.flags['apiProxy'] as string | undefined\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n if (!isInteractive()) {\n throw new InputError(\n 'Cannot prompt for credentials in a non-interactive shell'\n )\n }\n\n await attemptLogin(apiBaseUrl, apiProxy)\n}\n","import { updateSetting } from '../../utils/settings'\n\nexport function applyLogout() {\n updateSetting('apiToken', null)\n updateSetting('apiBaseUrl', null)\n updateSetting('apiProxy', null)\n updateSetting('enforcedOrgs', null)\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { applyLogout } from './apply-logout'\n\nexport function attemptLogout() {\n try {\n applyLogout()\n new Spinner().success('Successfully logged out')\n } catch {\n new Spinner().success('Failed to complete logout steps')\n }\n}\n","import { attemptLogout } from './attempt-logout'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'logout',\n description: 'Socket API logout',\n hidden: false,\n flags: {\n ...commonFlags\n },\n help: (command, _config) => `\n Usage\n $ ${command}\n\n Logs out of the Socket API and clears all Socket credentials from disk\n `\n}\n\nexport const cmdLogout = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n attemptLogout()\n}\n","import path from 'node:path'\n\nimport spawn from '@npmcli/promise-spawn'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport constants from '../../constants'\n\nexport async function convertGradleToMaven(\n target: string,\n bin: string,\n _out: string,\n verbose: boolean,\n gradleOpts: Array<string>\n) {\n const rbin = path.resolve(bin)\n const rtarget = path.resolve(target)\n // const rout = out === '-' ? '-' : path.resolve(out)\n\n if (verbose) {\n console.group('gradle2maven:')\n console.log(`[VERBOSE] - Absolute bin path: \\`${rbin}\\``)\n console.log(`[VERBOSE] - Absolute target path: \\`${rtarget}\\``)\n // console.log(`[VERBOSE] - Absolute out path: \\`${rout}\\``)\n console.groupEnd()\n } else {\n console.group('gradle2maven:')\n console.log(`- executing: \\`${bin}\\``)\n console.log(`- src dir: \\`${target}\\``)\n // console.log(`- dst dir: \\`${out}\\``)\n console.groupEnd()\n }\n\n const spinner = new Spinner()\n\n spinner.start(\n `Converting gradle to maven from \\`${bin}\\` on \\`${target}\\`...`\n )\n\n try {\n // Run sbt with the init script we provide which should yield zero or more pom files.\n // We have to figure out where to store those pom files such that we can upload them and predict them through the GitHub API.\n // We could do a .socket folder. We could do a socket.pom.gz with all the poms, although I'd prefer something plain-text if it is to be committed.\n\n // Note: init.gradle will be exported by .config/rollup.dist.config.mjs\n const initLocation = path.join(constants.rootDistPath, 'init.gradle')\n const commandArgs = ['--init-script', initLocation, ...gradleOpts, 'pom']\n\n if (verbose) {\n console.log('\\n[VERBOSE] Executing:', bin, commandArgs)\n }\n\n const output = await spawn(bin, commandArgs, {\n cwd: target || '.'\n })\n spinner.success()\n if (verbose) {\n console.group('[VERBOSE] gradle stdout:')\n console.log(output)\n console.groupEnd()\n }\n\n if (output.stderr) {\n spinner.error('There were errors while running gradle')\n // (In verbose mode, stderr was printed above, no need to repeat it)\n if (!verbose) {\n console.group('[VERBOSE] stderr:')\n console.error(output.stderr)\n console.groupEnd()\n }\n process.exit(1)\n }\n\n console.log('Reported exports:')\n output.stdout.replace(\n /^POM file copied to: (.*)/gm,\n (_all: string, fn: string) => {\n console.log('- ', fn)\n return fn\n }\n )\n\n // const loc = output.stdout?.match(/Wrote (.*?.pom)\\n/)?.[1]?.trim()\n // if (!loc) {\n // spinner.error(\n // 'There were no errors from sbt but could not find the location of resulting .pom file either'\n // )\n // process.exit(1)\n // }\n //\n // // Move the pom file to ...? initial cwd? loc will be an absolute path, or dump to stdout\n // if (out === '-') {\n // spinner.start('Result:\\n```').success()\n // console.log(await safeReadFile(loc, 'utf8'))\n // console.log('```')\n // spinner.start().success(`OK`)\n // } else {\n // if (verbose) {\n // spinner.start(\n // `Moving manifest file from \\`${loc.replace(/^\\/home\\/[^/]*?\\//, '~/')}\\` to \\`${out}\\``\n // )\n // } else {\n // spinner.start('Moving output pom file')\n // }\n // // TODO: do we prefer fs-extra? renaming can be gnarly on windows and fs-extra's version is better\n // await renamep(loc, out)\n // spinner.success()\n // spinner.start().success(`OK. File should be available in \\`${out}\\``)\n // }\n } catch (e) {\n spinner.error(\n 'There was an unexpected error while running this' +\n (verbose ? '' : ' (use --verbose for details)')\n )\n if (verbose) {\n console.group('[VERBOSE] error:')\n console.log(e)\n console.groupEnd()\n }\n process.exit(1)\n }\n}\n","import path from 'node:path'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { convertGradleToMaven } from './convert_gradle_to_maven'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'gradle',\n description:\n '[beta] Use Gradle to generate a manifest file (`pom.xml`) for a Gradle/Java/Kotlin/etc project',\n hidden: false,\n flags: {\n ...commonFlags,\n bin: {\n type: 'string',\n description: 'Location of gradlew binary to use, default: CWD/gradlew'\n },\n cwd: {\n type: 'string',\n description: 'Set the cwd, defaults to process.cwd()'\n },\n gradleOpts: {\n type: 'string',\n default: '',\n description:\n 'Additional options to pass on to ./gradlew, see `./gradlew --help`'\n },\n out: {\n type: 'string',\n default: './socket.pom.xml',\n description:\n 'Path of output file; where to store the resulting manifest, see also --stdout'\n },\n stdout: {\n type: 'boolean',\n description: 'Print resulting pom.xml to stdout (supersedes --out)'\n },\n task: {\n type: 'string',\n default: 'all',\n description: 'Task to target. By default targets all.'\n },\n verbose: {\n type: 'boolean',\n description: 'Print debug messages'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} [--gradle=path/to/gradle/binary] [--out=path/to/result] DIR\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Uses gradle, preferably through your local project \\`gradlew\\`, to generate a\n \\`pom.xml\\` file for each task. If you have no \\`gradlew\\` you can try the\n global \\`gradle\\` binary but that may not work (hard to predict).\n\n The \\`pom.xml\\` is a manifest file similar to \\`package.json\\` for npm or\n or requirements.txt for PyPi), but specifically for Maven, which is Java's\n dependency repository. Languages like Kotlin and Scala piggy back on it too.\n\n There are some caveats with the gradle to \\`pom.xml\\` conversion:\n\n - each task will generate its own xml file and by default it generates one xml\n for every task.\n\n - it's possible certain features don't translate well into the xml. If you\n think something is missing that could be supported please reach out.\n\n - it works with your \\`gradlew\\` from your repo and local settings and config\n\n Support is beta. Please report issues or give us feedback on what's missing.\n\n Examples\n\n $ ${command} .\n $ ${command} --gradlew=../gradlew .\n `\n}\n\nexport const cmdManifestGradle = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const verbose = Boolean(cli.flags['verbose'])\n\n if (verbose) {\n console.group('- ', parentName, config.commandName, ':')\n console.group('- flags:', cli.flags)\n console.groupEnd()\n console.log('- input:', cli.input)\n console.groupEnd()\n }\n\n const target = cli.input[0]\n\n // TODO: I'm not sure it's feasible to parse source file from stdin. We could try, store contents in a file in some folder, target that folder... what would the file name be?\n\n if (!target || target === '-' || cli.input.length > 1) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}\\n\n - Can only accept one DIR (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}\\n`\n )\n return\n }\n\n let bin: string\n if (cli.flags['bin']) {\n bin = cli.flags['bin'] as string\n } else {\n bin = path.join(target, 'gradlew')\n }\n\n let out: string = './socket.pom.xml'\n if (cli.flags['out']) {\n out = cli.flags['out'] as string\n }\n if (cli.flags['stdout']) {\n out = '-'\n }\n\n if (verbose) {\n console.group()\n console.log('- target:', target)\n console.log('- gradle bin:', bin)\n console.log('- out:', out)\n console.groupEnd()\n }\n\n let gradleOpts: Array<string> = []\n if (cli.flags['gradleOpts']) {\n gradleOpts = (cli.flags['gradleOpts'] as string)\n .split(' ')\n .map(s => s.trim())\n .filter(Boolean)\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await convertGradleToMaven(target, bin, out, verbose, gradleOpts)\n}\n","import path from 'node:path'\n\nimport spawn from '@npmcli/promise-spawn'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { safeReadFile } from '../../utils/fs'\n\nexport async function convertSbtToMaven(\n target: string,\n bin: string,\n out: string,\n verbose: boolean,\n sbtOpts: Array<string>\n) {\n const rbin = path.resolve(bin)\n const rtarget = path.resolve(target)\n // const rout = out === '-' ? '-' : path.resolve(out)\n\n if (verbose) {\n console.group('sbt2maven:')\n console.log(`[VERBOSE] - Absolute bin path: \\`${rbin}\\``)\n console.log(`[VERBOSE] - Absolute target path: \\`${rtarget}\\``)\n // console.log(`[VERBOSE] - Absolute out path: \\`${rout}\\``)\n console.groupEnd()\n } else {\n console.group('sbt2maven:')\n console.log(`- executing: \\`${bin}\\``)\n console.log(`- src dir: \\`${target}\\``)\n // console.log(`- dst dir: \\`${out}\\``)\n console.groupEnd()\n }\n\n const spinner = new Spinner()\n\n spinner.start(`Converting sbt to maven from \\`${bin}\\` on \\`${target}\\`...`)\n\n try {\n // Run sbt with the init script we provide which should yield zero or more pom files.\n // We have to figure out where to store those pom files such that we can upload them and predict them through the GitHub API.\n // We could do a .socket folder. We could do a socket.pom.gz with all the poms, although I'd prefer something plain-text if it is to be committed.\n\n const output = await spawn(bin, ['makePom'].concat(sbtOpts), {\n cwd: target || '.'\n })\n spinner.success()\n if (verbose) {\n console.group('[VERBOSE] sbt stdout:')\n console.log(output)\n console.groupEnd()\n }\n\n if (output.stderr) {\n spinner.error('There were errors while running sbt')\n // (In verbose mode, stderr was printed above, no need to repeat it)\n if (!verbose) {\n console.group('[VERBOSE] stderr:')\n console.error(output.stderr)\n console.groupEnd()\n }\n process.exit(1)\n }\n\n const poms: Array<string> = []\n output.stdout.replace(/Wrote (.*?.pom)\\n/g, (_all: string, fn: string) => {\n poms.push(fn)\n return fn\n })\n\n if (!poms.length) {\n spinner.error(\n 'There were no errors from sbt but it seems to not have generated any poms either'\n )\n process.exit(1)\n }\n\n // Move the pom file to ...? initial cwd? loc will be an absolute path, or dump to stdout\n // TODO: what to do with multiple output files? Do we want to dump them to stdout? Raw or with separators or ?\n // TODO: maybe we can add an option to target a specific file to dump to stdout\n if (out === '-' && poms.length === 1) {\n spinner.start('Result:\\n```').success()\n console.log(await safeReadFile(poms[0] as string, 'utf8'))\n console.log('```')\n spinner.start().success(`OK`)\n } else if (out === '-') {\n spinner\n .start()\n .error(\n 'Requested out target was stdout but there are multiple generated files'\n )\n poms.forEach(fn => console.error('-', fn))\n console.error('Exiting now...')\n process.exit(1)\n } else {\n // if (verbose) {\n // spinner.start(\n // `Moving manifest file from \\`${loc.replace(/^\\/home\\/[^/]*?\\//, '~/')}\\` to \\`${out}\\``\n // )\n // } else {\n // spinner.start('Moving output pom file')\n // }\n // TODO: do we prefer fs-extra? renaming can be gnarly on windows and fs-extra's version is better\n // await renamep(loc, out)\n spinner.start().success(`Generated ${poms.length} pom files`)\n poms.forEach(fn => console.log('-', fn))\n spinner.start().success(`OK`)\n }\n } catch (e) {\n spinner.error(\n 'There was an unexpected error while running this' +\n (verbose ? '' : ' (use --verbose for details)')\n )\n if (verbose) {\n console.group('[VERBOSE] error:')\n console.log(e)\n console.groupEnd()\n }\n process.exit(1)\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { convertSbtToMaven } from './convert_sbt_to_maven'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'scala',\n description:\n \"[beta] Generate a manifest file (`pom.xml`) from Scala's `build.sbt` file\",\n hidden: false,\n flags: {\n ...commonFlags,\n bin: {\n type: 'string',\n default: 'sbt',\n description: 'Location of sbt binary to use'\n },\n cwd: {\n type: 'string',\n description: 'Set the cwd, defaults to process.cwd()'\n },\n out: {\n type: 'string',\n default: './socket.pom.xml',\n description:\n 'Path of output file; where to store the resulting manifest, see also --stdout'\n },\n stdout: {\n type: 'boolean',\n description: 'Print resulting pom.xml to stdout (supersedes --out)'\n },\n sbtOpts: {\n type: 'string',\n default: '',\n description: 'Additional options to pass on to sbt, as per `sbt --help`'\n },\n verbose: {\n type: 'boolean',\n description: 'Print debug messages'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} [--sbt=path/to/sbt/binary] [--out=path/to/result] FILE|DIR\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Uses \\`sbt makePom\\` to generate a \\`pom.xml\\` from your \\`build.sbt\\` file.\n This xml file is the dependency manifest (like a package.json\n for Node.js or requirements.txt for PyPi), but specifically for Scala.\n\n There are some caveats with \\`build.sbt\\` to \\`pom.xml\\` conversion:\n\n - the xml is exported as socket.pom.xml as to not confuse existing build tools\n but it will first hit your /target/sbt<version> folder (as a different name)\n\n - the pom.xml format (standard by Scala) does not support certain sbt features\n - \\`excludeAll()\\`, \\`dependencyOverrides\\`, \\`force()\\`, \\`relativePath\\`\n - For details: https://www.scala-sbt.org/1.x/docs/Library-Management.html\n\n - it uses your sbt settings and local configuration verbatim\n\n - it can only export one target per run, so if you have multiple targets like\n development and production, you must run them separately.\n\n You can optionally configure the path to the \\`sbt\\` bin to invoke.\n\n Support is beta. Please report issues or give us feedback on what's missing.\n\n Examples\n\n $ ${command} ./build.sbt\n $ ${command} --bin=/usr/bin/sbt ./build.sbt\n `\n}\n\nexport const cmdManifestScala = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n // console.log('scala', argv, parentName)\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const verbose = Boolean(cli.flags['verbose'])\n\n if (verbose) {\n console.group('- ', parentName, config.commandName, ':')\n console.group('- flags:', cli.flags)\n console.groupEnd()\n console.log('- input:', cli.input)\n console.groupEnd()\n }\n\n const target = cli.input[0]\n\n // TODO: I'm not sure it's feasible to parse source file from stdin. We could try, store contents in a file in some folder, target that folder... what would the file name be?\n\n if (!target || target === '-' || cli.input.length > 1) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - The DIR or FILE arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}\\n\n - Can only accept one DIR or FILE (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}\\n`\n )\n return\n }\n\n let bin: string = 'sbt'\n if (cli.flags['bin']) {\n bin = cli.flags['bin'] as string\n }\n\n let out: string = './socket.pom.xml'\n if (cli.flags['out']) {\n out = cli.flags['out'] as string\n }\n if (cli.flags['stdout']) {\n out = '-'\n }\n\n if (verbose) {\n console.group()\n console.log('- target:', target)\n console.log('- gradle bin:', bin)\n console.log('- out:', out)\n console.groupEnd()\n }\n\n let sbtOpts: Array<string> = []\n if (cli.flags['sbtOpts']) {\n sbtOpts = (cli.flags['sbtOpts'] as string)\n .split(' ')\n .map(s => s.trim())\n .filter(Boolean)\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await convertSbtToMaven(target, bin, out, verbose, sbtOpts)\n}\n","import { existsSync } from 'node:fs'\nimport path from 'node:path'\n\nimport meow from 'meow'\n\nimport { cmdManifestGradle } from './cmd-manifest-gradle'\nimport { cmdManifestScala } from './cmd-manifest-scala'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'auto',\n description: 'Auto-detect build and attempt to generate manifest file',\n hidden: false,\n flags: {\n ...commonFlags,\n cwd: {\n type: 'string',\n description: 'Set the cwd, defaults to process.cwd()'\n },\n verbose: {\n type: 'boolean',\n default: false,\n description: 'Enable debug output, may help when running into errors'\n }\n // TODO: support output flags\n },\n help: (command, config) => `\n Usage\n $ ${command}\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Tries to figure out what language your current repo uses. If it finds a\n supported case then it will try to generate the manifest file for that\n language with the default or detected settings.\n `\n}\n\nexport const cmdManifestAuto = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const verbose = !!cli.flags['verbose']\n const cwd = <string>cli.flags['cwd'] ?? process.cwd()\n if (verbose) {\n console.group('- ', parentName, config.commandName, ':')\n console.group('- flags:', cli.flags)\n console.groupEnd()\n console.log('- input:', cli.input)\n console.log('- cwd:', cwd)\n console.groupEnd()\n }\n const subArgs = []\n if (verbose) {\n subArgs.push('--verbose')\n }\n\n const dir = cwd\n\n if (existsSync(path.join(dir, 'build.sbt'))) {\n console.log(\n 'Detected a Scala sbt build, running default Scala generator...'\n )\n if (cwd) {\n subArgs.push('--cwd', cwd)\n }\n subArgs.push(dir)\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await cmdManifestScala.run(subArgs, importMeta, { parentName })\n return\n }\n\n if (existsSync(path.join(dir, 'gradlew'))) {\n console.log('Detected a gradle build, running default gradle generator...')\n if (cwd) {\n // This command takes the cwd as first arg.\n subArgs.push(cwd)\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await cmdManifestGradle.run(subArgs, importMeta, { parentName })\n return\n }\n\n // Show new help screen and exit.\n meow(\n `\n $ ${parentName} ${config.commandName}\n\n Unfortunately this script did not discover a supported language in the\n current folder.\n\n - Make sure this script would work with your target build\n - Make sure to run it from the correct folder\n - Make sure the necessary build tools are available (\\`PATH\\`)\n\n If that doesn't work, see \\`${parentName} <lang> --help\\` for config details for\n your target language.\n `,\n {\n argv: [],\n description: config.description,\n importMeta\n }\n ).showHelp()\n}\n","import path from 'node:path'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { convertGradleToMaven } from './convert_gradle_to_maven'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\n// TODO: we may want to dedupe some pieces for all gradle languages. I think it\n// makes sense to have separate commands for them and I think it makes\n// sense for the help panels to note the requested language, rather than\n// `socket manifest kotlin` to print help screens with `gradle` as the\n// command. Room for improvement.\nconst config: CliCommandConfig = {\n commandName: 'kotlin',\n description:\n '[beta] Use Gradle to generate a manifest file (`pom.xml`) for a Kotlin project',\n hidden: false,\n flags: {\n ...commonFlags,\n bin: {\n type: 'string',\n description: 'Location of gradlew binary to use, default: CWD/gradlew'\n },\n cwd: {\n type: 'string',\n description: 'Set the cwd, defaults to process.cwd()'\n },\n gradleOpts: {\n type: 'string',\n default: '',\n description:\n 'Additional options to pass on to ./gradlew, see `./gradlew --help`'\n },\n out: {\n type: 'string',\n default: './socket.pom.xml',\n description:\n 'Path of output file; where to store the resulting manifest, see also --stdout'\n },\n stdout: {\n type: 'boolean',\n description: 'Print resulting pom.xml to stdout (supersedes --out)'\n },\n task: {\n type: 'string',\n default: 'all',\n description: 'Task to target. By default targets all.'\n },\n verbose: {\n type: 'boolean',\n description: 'Print debug messages'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} [--gradle=path/to/gradle/binary] [--out=path/to/result] DIR\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Uses gradle, preferably through your local project \\`gradlew\\`, to generate a\n \\`pom.xml\\` file for each task. If you have no \\`gradlew\\` you can try the\n global \\`gradle\\` binary but that may not work (hard to predict).\n\n The \\`pom.xml\\` is a manifest file similar to \\`package.json\\` for npm or\n or requirements.txt for PyPi), but specifically for Maven, which is Java's\n dependency repository. Languages like Kotlin and Scala piggy back on it too.\n\n There are some caveats with the gradle to \\`pom.xml\\` conversion:\n\n - each task will generate its own xml file and by default it generates one xml\n for every task. (This may be a good thing!)\n\n - it's possible certain features don't translate well into the xml. If you\n think something is missing that could be supported please reach out.\n\n - it works with your \\`gradlew\\` from your repo and local settings and config\n\n Support is beta. Please report issues or give us feedback on what's missing.\n\n Examples\n\n $ ${command} .\n $ ${command} --gradlew=../gradlew .\n `\n}\n\nexport const cmdManifestKotlin = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const verbose = Boolean(cli.flags['verbose'])\n\n if (verbose) {\n console.group('- ', parentName, config.commandName, ':')\n console.group('- flags:', cli.flags)\n console.groupEnd()\n console.log('- input:', cli.input)\n console.groupEnd()\n }\n\n const target = cli.input[0]\n\n // TODO: I'm not sure it's feasible to parse source file from stdin. We could try, store contents in a file in some folder, target that folder... what would the file name be?\n\n if (!target || target === '-' || cli.input.length > 1) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}\\n\n - Can only accept one DIR (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}\\n`\n )\n return\n }\n\n let bin: string\n if (cli.flags['bin']) {\n bin = cli.flags['bin'] as string\n } else {\n bin = path.join(target, 'gradlew')\n }\n\n let out: string = './socket.pom.xml'\n if (cli.flags['out']) {\n out = cli.flags['out'] as string\n }\n if (cli.flags['stdout']) {\n out = '-'\n }\n\n if (verbose) {\n console.group()\n console.log('- target:', target)\n console.log('- gradle bin:', bin)\n console.log('- out:', out)\n console.groupEnd()\n }\n\n let gradleOpts: Array<string> = []\n if (cli.flags['gradleOpts']) {\n gradleOpts = (cli.flags['gradleOpts'] as string)\n .split(' ')\n .map(s => s.trim())\n .filter(Boolean)\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await convertGradleToMaven(target, bin, out, verbose, gradleOpts)\n}\n","import { cmdManifestAuto } from './cmd-manifest-auto'\nimport { cmdManifestGradle } from './cmd-manifest-gradle'\nimport { cmdManifestKotlin } from './cmd-manifest-kotlin'\nimport { cmdManifestScala } from './cmd-manifest-scala'\nimport { commonFlags } from '../../flags'\nimport { meowWithSubcommands } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'manifest',\n description: 'Generate a dependency manifest for given file or dir',\n hidden: false,\n flags: {\n ...commonFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <language> <target>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Generates a declarative dependency manifest (like a package.json for Node.JS\n or requirements.txt for PyPi), but for certain supported ecosystems\n where it's common to use a dynamic manifest, like Scala's sbt.\n\n Only certain languages are supported and there may be language specific\n configurations available. See \\`manifest <language> --help\\` for usage details\n per language.\n\n Currently supported language: scala [beta], gradle [beta], kotlin (through\n gradle) [beta].\n\n Examples\n\n $ ${command} scala .\n\n To have it auto-detect and attempt to run:\n\n $ ${command} yolo\n `\n}\n\nexport const cmdManifest = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n await meowWithSubcommands(\n {\n auto: cmdManifestAuto,\n scala: cmdManifestScala,\n gradle: cmdManifestGradle,\n kotlin: cmdManifestKotlin\n },\n {\n argv,\n aliases: {\n yolo: {\n description: config.description,\n hidden: true,\n argv: ['auto']\n }\n },\n description: config.description,\n importMeta,\n flags: config.flags,\n name: `${parentName} ${config.commandName}`\n }\n )\n}\n","import constants from '../../constants'\n\nconst { NPM, SHADOW_BIN } = constants\n\nexport async function wrapNpm(argv: readonly string[]) {\n // Lazily access constants.distPath.\n const shadowBin = require(`${constants.distPath}/${SHADOW_BIN}.js`)\n await shadowBin(NPM, argv)\n}\n","import { wrapNpm } from './wrap-npm'\nimport constants from '../../constants'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst { NPM } = constants\n\nconst config: CliCommandConfig = {\n commandName: 'npm',\n description: `${NPM} wrapper functionality`,\n hidden: false,\n flags: {},\n help: (command, _config) => `\n Usage\n $ ${command}\n `\n}\n\nexport const cmdNpm = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n allowUnknownFlags: true,\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await wrapNpm(argv)\n}\n","import constants from '../../constants'\n\nconst { NPX, SHADOW_BIN } = constants\n\nexport async function wrapNpx(argv: readonly string[]) {\n // Lazily access constants.distPath.\n const shadowBin = require(`${constants.distPath}/${SHADOW_BIN}.js`)\n await shadowBin(NPX, argv)\n}\n","import { wrapNpx } from './wrap-npx'\nimport constants from '../../constants'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst { NPX } = constants\n\nconst config: CliCommandConfig = {\n commandName: 'npx',\n description: `${NPX} wrapper functionality`,\n hidden: false,\n flags: {},\n help: (command, _config) => `\n Usage\n $ ${command}\n `\n}\n\nexport const cmdNpx = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n allowUnknownFlags: true,\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await wrapNpx(argv)\n}\n","import { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'oops',\n description: 'Trigger an intentional error (for development)',\n hidden: true,\n flags: {\n ...commonFlags\n },\n help: (parentName, config) => `\n Usage\n $ ${parentName} ${config.commandName}\n\n Don't run me.\n `\n}\n\nexport const cmdOops = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n throw new Error('This error was intentionally left blank')\n}\n","import constants from '../../constants'\n\nimport type { Agent } from '../../utils/package-manager-detector'\n\ntype AgentDepsIncludesFn = (stdout: string, name: string) => boolean\n\nconst { BUN, NPM, PNPM, VLT, YARN_BERRY, YARN_CLASSIC } = constants\n\nfunction matchHumanStdout(stdout: string, name: string) {\n return stdout.includes(` ${name}@`)\n}\n\nfunction matchQueryStdout(stdout: string, name: string) {\n return stdout.includes(`\"${name}\"`)\n}\n\nexport const depsIncludesByAgent: Record<Agent, AgentDepsIncludesFn> = {\n // @ts-ignore\n __proto__: null,\n\n [BUN]: matchHumanStdout,\n [NPM]: matchQueryStdout,\n [PNPM]: matchQueryStdout,\n [VLT]: matchQueryStdout,\n [YARN_BERRY]: matchHumanStdout,\n [YARN_CLASSIC]: matchHumanStdout\n}\n","import { existsSync } from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\n\nimport spawn from '@npmcli/promise-spawn'\nimport browserslist from 'browserslist'\nimport semver from 'semver'\nimport which from 'which'\n\nimport { parse as parseBunLockb } from '@socketregistry/hyrious__bun.lockb/index.cjs'\nimport { isObjectObject } from '@socketsecurity/registry/lib/objects'\nimport { readPackageJson } from '@socketsecurity/registry/lib/packages'\nimport { naturalCompare } from '@socketsecurity/registry/lib/sorts'\nimport { isNonEmptyString } from '@socketsecurity/registry/lib/strings'\n\nimport { findUp, readFileBinary, readFileUtf8 } from './fs'\nimport constants from '../constants'\n\nimport type { EditablePackageJson } from '@socketsecurity/registry/lib/packages'\nimport type { SemVer } from 'semver'\n\nconst {\n BINARY_LOCK_EXT,\n BUN,\n LOCK_EXT,\n NPM,\n PNPM,\n VLT,\n YARN,\n YARN_BERRY,\n YARN_CLASSIC\n} = constants\n\nexport const AGENTS = [BUN, NPM, PNPM, YARN_BERRY, YARN_CLASSIC, VLT] as const\nexport type Agent = (typeof AGENTS)[number]\nexport type StringKeyValueObject = { [key: string]: string }\n\nconst binByAgent = {\n __proto__: null,\n [BUN]: BUN,\n [NPM]: NPM,\n [PNPM]: PNPM,\n [YARN_BERRY]: YARN,\n [YARN_CLASSIC]: YARN,\n [VLT]: VLT\n}\n\nasync function getAgentExecPath(agent: Agent): Promise<string> {\n const binName = binByAgent[agent]\n return (await which(binName, { nothrow: true })) ?? binName\n}\n\nasync function getAgentVersion(\n agentExecPath: string,\n cwd: string\n): Promise<SemVer | undefined> {\n let result\n try {\n result =\n semver.coerce(\n // All package managers support the \"--version\" flag.\n (await spawn(agentExecPath, ['--version'], { cwd })).stdout\n ) ?? undefined\n } catch {}\n return result\n}\n\n// The order of LOCKS properties IS significant as it affects iteration order.\nconst LOCKS: Record<string, Agent> = {\n [`bun${LOCK_EXT}`]: BUN,\n [`bun${BINARY_LOCK_EXT}`]: BUN,\n // If both package-lock.json and npm-shrinkwrap.json are present in the root\n // of a project, npm-shrinkwrap.json will take precedence and package-lock.json\n // will be ignored.\n // https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#package-lockjson-vs-npm-shrinkwrapjson\n 'npm-shrinkwrap.json': NPM,\n 'package-lock.json': NPM,\n 'pnpm-lock.yaml': PNPM,\n 'pnpm-lock.yml': PNPM,\n [`yarn${LOCK_EXT}`]: YARN_CLASSIC,\n 'vlt-lock.json': VLT,\n // Lastly, look for a hidden lock file which is present if .npmrc has package-lock=false:\n // https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#hidden-lockfiles\n //\n // Unlike the other LOCKS keys this key contains a directory AND filename so\n // it has to be handled differently.\n 'node_modules/.package-lock.json': NPM\n}\n\ntype ReadLockFile =\n | ((lockPath: string) => Promise<string | undefined>)\n | ((lockPath: string, agentExecPath: string) => Promise<string | undefined>)\n\nconst readLockFileByAgent: Record<Agent, ReadLockFile> = (() => {\n function wrapReader<T extends (...args: any[]) => Promise<any>>(\n reader: T\n ): (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>> | undefined> {\n return async (...args: any[]): Promise<any> => {\n try {\n return await reader(...args)\n } catch {}\n return undefined\n }\n }\n\n const binaryReader = wrapReader(readFileBinary)\n\n const defaultReader = wrapReader(\n async (lockPath: string) => await readFileUtf8(lockPath)\n )\n\n return {\n [BUN]: wrapReader(async (lockPath: string, agentExecPath: string) => {\n const ext = path.extname(lockPath)\n if (ext === LOCK_EXT) {\n return await defaultReader(lockPath)\n }\n if (ext === BINARY_LOCK_EXT) {\n const lockBuffer = await binaryReader(lockPath)\n if (lockBuffer) {\n try {\n return parseBunLockb(lockBuffer)\n } catch {}\n }\n // To print a Yarn lockfile to your console without writing it to disk\n // use `bun bun.lockb`.\n // https://bun.sh/guides/install/yarnlock\n return (await spawn(agentExecPath, [lockPath])).stdout.trim()\n }\n return undefined\n }),\n [NPM]: defaultReader,\n [PNPM]: defaultReader,\n [VLT]: defaultReader,\n [YARN_BERRY]: defaultReader,\n [YARN_CLASSIC]: defaultReader\n }\n})()\n\nexport type DetectOptions = {\n cwd?: string\n onUnknown?: (pkgManager: string | undefined) => void\n}\n\nexport type DetectResult = Readonly<{\n agent: Agent\n agentExecPath: string\n agentVersion: SemVer | undefined\n lockBasename: string | undefined\n lockPath: string | undefined\n lockSrc: string | undefined\n minimumNodeVersion: string\n npmExecPath: string\n pkgJson: EditablePackageJson | undefined\n pkgPath: string | undefined\n supported: boolean\n targets: {\n browser: boolean\n node: boolean\n }\n}>\n\nexport async function detect({\n cwd = process.cwd(),\n onUnknown\n}: DetectOptions = {}): Promise<DetectResult> {\n let lockPath = await findUp(Object.keys(LOCKS), { cwd })\n let lockBasename = lockPath ? path.basename(lockPath) : undefined\n const isHiddenLockFile = lockBasename === '.package-lock.json'\n const pkgJsonPath = lockPath\n ? path.resolve(lockPath, `${isHiddenLockFile ? '../' : ''}../package.json`)\n : await findUp('package.json', { cwd })\n const pkgPath =\n pkgJsonPath && existsSync(pkgJsonPath)\n ? path.dirname(pkgJsonPath)\n : undefined\n const editablePkgJson = pkgPath\n ? await readPackageJson(pkgPath, { editable: true })\n : undefined\n const pkgJson = editablePkgJson?.content\n // Read Corepack `packageManager` field in package.json:\n // https://nodejs.org/api/packages.html#packagemanager\n const pkgManager = isNonEmptyString(pkgJson?.packageManager)\n ? pkgJson.packageManager\n : undefined\n\n let agent: Agent | undefined\n let agentVersion: SemVer | undefined\n if (pkgManager) {\n const atSignIndex = pkgManager.lastIndexOf('@')\n if (atSignIndex !== -1) {\n const name = <Agent>pkgManager.slice(0, atSignIndex)\n const version = pkgManager.slice(atSignIndex + 1)\n if (version && AGENTS.includes(name)) {\n agent = name\n agentVersion = semver.coerce(version) ?? undefined\n }\n }\n }\n if (\n agent === undefined &&\n !isHiddenLockFile &&\n typeof pkgJsonPath === 'string' &&\n typeof lockBasename === 'string'\n ) {\n agent = <Agent>LOCKS[lockBasename]\n }\n if (agent === undefined) {\n agent = NPM\n onUnknown?.(pkgManager)\n }\n const agentExecPath = await getAgentExecPath(agent)\n\n const npmExecPath =\n agent === NPM ? agentExecPath : await getAgentExecPath(NPM)\n if (agentVersion === undefined) {\n agentVersion = await getAgentVersion(agentExecPath, cwd)\n }\n if (agent === YARN_CLASSIC && (agentVersion?.major ?? 0) > 1) {\n agent = YARN_BERRY\n }\n const targets = {\n browser: false,\n node: true\n }\n let lockSrc: string | undefined\n // Lazily access constants.maintainedNodeVersions.\n let minimumNodeVersion = constants.maintainedNodeVersions.previous\n if (pkgJson) {\n const browserField = pkgJson.browser\n if (isNonEmptyString(browserField) || isObjectObject(browserField)) {\n targets.browser = true\n }\n const nodeRange = pkgJson.engines?.['node']\n if (isNonEmptyString(nodeRange)) {\n const coerced = semver.coerce(nodeRange)\n if (coerced && semver.lt(coerced, minimumNodeVersion)) {\n minimumNodeVersion = coerced.version\n }\n }\n const browserslistQuery = <string[] | undefined>pkgJson['browserslist']\n if (Array.isArray(browserslistQuery)) {\n const browserslistTargets = browserslist(browserslistQuery)\n .map(s => s.toLowerCase())\n .sort(naturalCompare)\n const browserslistNodeTargets = browserslistTargets\n .filter(v => v.startsWith('node '))\n .map(v => v.slice(5 /*'node '.length*/))\n if (!targets.browser && browserslistTargets.length) {\n targets.browser =\n browserslistTargets.length !== browserslistNodeTargets.length\n }\n if (browserslistNodeTargets.length) {\n const coerced = semver.coerce(browserslistNodeTargets[0])\n if (coerced && semver.lt(coerced, minimumNodeVersion)) {\n minimumNodeVersion = coerced.version\n }\n }\n }\n // Lazily access constants.maintainedNodeVersions.\n targets.node = constants.maintainedNodeVersions.some(v =>\n semver.satisfies(v, `>=${minimumNodeVersion}`)\n )\n lockSrc =\n typeof lockPath === 'string'\n ? await readLockFileByAgent[agent](lockPath, agentExecPath)\n : undefined\n } else {\n lockBasename = undefined\n lockPath = undefined\n }\n return <DetectResult>{\n agent,\n agentExecPath,\n agentVersion,\n lockBasename,\n lockPath,\n lockSrc,\n minimumNodeVersion,\n npmExecPath,\n pkgJson: editablePkgJson,\n pkgPath,\n supported: targets.browser || targets.node,\n targets\n }\n}\n","import path from 'node:path'\n\nimport semver from 'semver'\n\nimport { ManifestEntry, getManifestData } from '@socketsecurity/registry'\n\nimport constants from '../../constants'\nimport { detect } from '../../utils/package-manager-detector'\n\nconst { BUN, NPM, VLT, YARN_BERRY } = constants\n\nconst COMMAND_TITLE = 'Socket Optimize'\n\nconst manifestNpmOverrides = getManifestData(NPM)\n\nexport async function detectAndValidatePackageManager(\n cwd: string,\n prod: boolean\n): Promise<\n | void\n | (Pick<\n Awaited<ReturnType<typeof detect>>,\n | 'agent'\n | 'agentExecPath'\n | 'lockBasename'\n | 'lockSrc'\n | 'npmExecPath'\n | 'pkgJson'\n | 'pkgPath'\n > & {\n lockName: string\n manifestEntries: Array<ManifestEntry>\n lockBasename: string\n lockSrc: string\n pkgPath: string\n })\n> {\n const {\n agent,\n agentExecPath,\n agentVersion,\n lockBasename,\n lockPath,\n lockSrc,\n minimumNodeVersion,\n npmExecPath,\n pkgJson,\n pkgPath,\n supported\n } = await detect({\n cwd,\n onUnknown(pkgManager: string | undefined) {\n console.warn(\n `⚠️ ${COMMAND_TITLE}: Unknown package manager${pkgManager ? ` ${pkgManager}` : ''}, defaulting to npm`\n )\n }\n })\n if (!supported) {\n console.error(\n `✖️ ${COMMAND_TITLE}: No supported Node or browser range detected`\n )\n return\n }\n if (agent === VLT) {\n console.error(\n `✖️ ${COMMAND_TITLE}: ${agent} does not support overrides. Soon, though ⚡`\n )\n return\n }\n const lockName = lockPath && lockBasename ? lockBasename : 'lock file'\n if (lockBasename === undefined || lockSrc === undefined) {\n console.error(`✖️ ${COMMAND_TITLE}: No ${lockName} found`)\n return\n }\n if (lockSrc.trim() === '') {\n console.error(`✖️ ${COMMAND_TITLE}: ${lockName} is empty`)\n return\n }\n if (pkgPath === undefined) {\n console.error(`✖️ ${COMMAND_TITLE}: No package.json found`)\n return\n }\n if (prod && (agent === BUN || agent === YARN_BERRY)) {\n console.error(\n `✖️ ${COMMAND_TITLE}: --prod not supported for ${agent}${agentVersion ? `@${agentVersion.toString()}` : ''}`\n )\n return\n }\n if (lockPath && path.relative(cwd, lockPath).startsWith('.')) {\n console.warn(`⚠️ ${COMMAND_TITLE}: Package ${lockName} found at ${lockPath}`)\n }\n\n const nodeRange = `>=${minimumNodeVersion}`\n const manifestEntries = manifestNpmOverrides.filter(({ 1: data }) =>\n semver.satisfies(semver.coerce(data.engines.node)!, nodeRange)\n )\n\n return {\n agent,\n agentExecPath,\n lockBasename,\n lockName,\n lockSrc,\n manifestEntries,\n npmExecPath,\n pkgJson,\n pkgPath\n }\n}\n","import { readPackageJson } from '@socketsecurity/registry/lib/packages'\n\ntype PackageJson = Awaited<ReturnType<typeof readPackageJson>>\n\nexport function getDependencyEntries(pkgJson: PackageJson) {\n const {\n dependencies,\n devDependencies,\n optionalDependencies,\n peerDependencies\n } = pkgJson\n return <[string, NonNullable<typeof dependencies>][]>[\n [\n 'dependencies',\n dependencies ? { __proto__: null, ...dependencies } : undefined\n ],\n [\n 'devDependencies',\n devDependencies ? { __proto__: null, ...devDependencies } : undefined\n ],\n [\n 'peerDependencies',\n peerDependencies ? { __proto__: null, ...peerDependencies } : undefined\n ],\n [\n 'optionalDependencies',\n optionalDependencies\n ? { __proto__: null, ...optionalDependencies }\n : undefined\n ]\n ].filter(({ 1: o }) => o)\n}\n","import { readPackageJson } from '@socketsecurity/registry/lib/packages'\n\nimport constants from '../../constants'\n\nimport type {\n Agent,\n StringKeyValueObject\n} from '../../utils/package-manager-detector'\n\ntype PackageJson = Awaited<ReturnType<typeof readPackageJson>>\ntype NpmOverrides = { [key: string]: string | StringKeyValueObject }\ntype PnpmOrYarnOverrides = { [key: string]: string }\ntype Overrides = NpmOverrides | PnpmOrYarnOverrides\ntype GetOverrides = (pkgJson: PackageJson) => GetOverridesResult\ntype GetOverridesResult = { type: Agent; overrides: Overrides }\n\nconst {\n BUN,\n NPM,\n OVERRIDES,\n PNPM,\n RESOLUTIONS,\n VLT,\n YARN_BERRY,\n YARN_CLASSIC\n} = constants\n\nfunction getOverridesDataBun(pkgJson: PackageJson) {\n const overrides = (pkgJson as any)?.[RESOLUTIONS] ?? {}\n return { type: YARN_BERRY, overrides }\n}\n\n// npm overrides documentation:\n// https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides\nfunction getOverridesDataNpm(pkgJson: PackageJson) {\n const overrides = (pkgJson as any)?.[OVERRIDES] ?? {}\n return { type: NPM, overrides }\n}\n\n// pnpm overrides documentation:\n// https://pnpm.io/package_json#pnpmoverrides\nfunction getOverridesDataPnpm(pkgJson: PackageJson) {\n const overrides = (pkgJson as any)?.pnpm?.[OVERRIDES] ?? {}\n return { type: PNPM, overrides }\n}\n\nfunction getOverridesDataVlt(pkgJson: PackageJson) {\n const overrides = (pkgJson as any)?.[OVERRIDES] ?? {}\n return { type: VLT, overrides }\n}\n\n// Yarn resolutions documentation:\n// https://yarnpkg.com/configuration/manifest#resolutions\nfunction getOverridesDataYarn(pkgJson: PackageJson) {\n const overrides = (pkgJson as any)?.[RESOLUTIONS] ?? {}\n return { type: YARN_BERRY, overrides }\n}\n\n// Yarn resolutions documentation:\n// https://classic.yarnpkg.com/en/docs/selective-version-resolutions\nfunction getOverridesDataClassic(pkgJson: PackageJson) {\n const overrides = (pkgJson as any)?.[RESOLUTIONS] ?? {}\n return { type: YARN_CLASSIC, overrides }\n}\n\nexport const getOverridesDataByAgent: Record<Agent, GetOverrides> = {\n // @ts-ignore\n __proto__: null,\n\n [BUN]: getOverridesDataBun,\n [NPM]: getOverridesDataNpm,\n [PNPM]: getOverridesDataPnpm,\n [VLT]: getOverridesDataVlt,\n [YARN_BERRY]: getOverridesDataYarn,\n [YARN_CLASSIC]: getOverridesDataClassic\n}\n","import path from 'node:path'\n\nimport { parse as yamlParse } from 'yaml'\n\nimport { readPackageJson } from '@socketsecurity/registry/lib/packages'\nimport { isNonEmptyString } from '@socketsecurity/registry/lib/strings'\n\nimport constants from '../../constants'\nimport { safeReadFile } from '../../utils/fs'\n\nimport type { Agent } from '../../utils/package-manager-detector'\n\ntype PackageJson = Awaited<ReturnType<typeof readPackageJson>>\n\nconst { PNPM } = constants\n\nconst PNPM_WORKSPACE = `${PNPM}-workspace`\n\nexport async function getWorkspaceGlobs(\n agent: Agent,\n pkgPath: string,\n pkgJson: PackageJson\n): Promise<string[] | undefined> {\n let workspacePatterns\n if (agent === PNPM) {\n for (const workspacePath of [\n path.join(pkgPath, `${PNPM_WORKSPACE}.yaml`),\n path.join(pkgPath, `${PNPM_WORKSPACE}.yml`)\n ]) {\n // eslint-disable-next-line no-await-in-loop\n const yml = <string | undefined>await safeReadFile(workspacePath, 'utf8')\n if (yml) {\n try {\n workspacePatterns = yamlParse(yml)?.packages\n } catch {}\n if (workspacePatterns) {\n break\n }\n }\n }\n } else {\n workspacePatterns = pkgJson['workspaces']\n }\n return Array.isArray(workspacePatterns)\n ? workspacePatterns\n .filter(isNonEmptyString)\n .map(workspacePatternToGlobPattern)\n : undefined\n}\n\nfunction workspacePatternToGlobPattern(workspace: string): string {\n const { length } = workspace\n if (!length) {\n return ''\n }\n // If the workspace ends with \"/\"\n if (workspace.charCodeAt(length - 1) === 47 /*'/'*/) {\n return `${workspace}/*/package.json`\n }\n // If the workspace ends with \"/**\"\n if (\n workspace.charCodeAt(length - 1) === 42 /*'*'*/ &&\n workspace.charCodeAt(length - 2) === 42 /*'*'*/ &&\n workspace.charCodeAt(length - 3) === 47 /*'/'*/\n ) {\n return `${workspace}/*/**/package.json`\n }\n // Things like \"packages/a\" or \"packages/*\"\n return `${workspace}/package.json`\n}\n","import { escapeRegExp } from '@socketsecurity/registry/lib/regexps'\n\nimport constants from '../../constants'\n\nimport type { Agent } from '../../utils/package-manager-detector'\n\nexport type AgentLockIncludesFn = (\n lockSrc: string,\n name: string,\n ext?: string\n) => boolean\n\nconst { BUN, LOCK_EXT, NPM, PNPM, VLT, YARN_BERRY, YARN_CLASSIC } = constants\n\nfunction lockIncludesNpm(lockSrc: string, name: string) {\n // Detects the package name in the following cases:\n // \"name\":\n return lockSrc.includes(`\"${name}\":`)\n}\n\nfunction lockIncludesBun(lockSrc: string, name: string, lockBasename?: string) {\n // This is a bit counterintuitive. When lockBasename ends with a .lockb\n // we treat it as a yarn.lock. When lockBasename ends with a .lock we\n // treat it as a package-lock.json. The bun.lock format is not identical\n // package-lock.json, however it close enough for npmLockIncludes to work.\n const lockScanner = lockBasename?.endsWith(LOCK_EXT)\n ? lockIncludesNpm\n : lockIncludesYarn\n return lockScanner(lockSrc, name)\n}\n\nfunction lockIncludesPnpm(lockSrc: string, name: string) {\n const escapedName = escapeRegExp(name)\n return new RegExp(\n // Detects the package name in the following cases:\n // /name/\n // 'name'\n // name:\n // name@\n `(?<=^\\\\s*)(?:(['/])${escapedName}\\\\1|${escapedName}(?=[:@]))`,\n 'm'\n ).test(lockSrc)\n}\n\nfunction lockIncludesVlt(lockSrc: string, name: string) {\n // Detects the package name in the following cases:\n // \"name\"\n return lockSrc.includes(`\"${name}\"`)\n}\n\nfunction lockIncludesYarn(lockSrc: string, name: string) {\n const escapedName = escapeRegExp(name)\n return new RegExp(\n // Detects the package name in the following cases:\n // \"name@\n // , \"name@\n // name@\n // , name@\n `(?<=(?:^\\\\s*|,\\\\s*)\"?)${escapedName}(?=@)`,\n 'm'\n ).test(lockSrc)\n}\n\nexport const lockIncludesByAgent: Record<Agent, AgentLockIncludesFn> = {\n // @ts-ignore\n __proto__: null,\n\n [BUN]: lockIncludesBun,\n [NPM]: lockIncludesNpm,\n [PNPM]: lockIncludesPnpm,\n [VLT]: lockIncludesVlt,\n [YARN_BERRY]: lockIncludesYarn,\n [YARN_CLASSIC]: lockIncludesYarn\n}\n","import spawn from '@npmcli/promise-spawn'\n\nimport constants from '../../constants'\n\nimport type { Agent } from '../../utils/package-manager-detector'\n\ntype AgentListDepsOptions = { npmExecPath?: string }\n\ntype AgentListDepsFn = (\n agentExecPath: string,\n cwd: string,\n options?: AgentListDepsOptions\n) => Promise<string>\n\nconst { BUN, NPM, PNPM, VLT, YARN_BERRY, YARN_CLASSIC } = constants\n\nfunction cleanupQueryStdout(stdout: string): string {\n if (stdout === '') {\n return ''\n }\n let pkgs\n try {\n pkgs = JSON.parse(stdout)\n } catch {}\n if (!Array.isArray(pkgs)) {\n return ''\n }\n const names = new Set<string>()\n for (const { _id, name, pkgid } of pkgs) {\n // `npm query` results may not have a \"name\" property, in which case we\n // fallback to \"_id\" and then \"pkgid\".\n // `vlt ls --view json` results always have a \"name\" property.\n const fallback = _id ?? pkgid ?? ''\n const resolvedName = name ?? fallback.slice(0, fallback.indexOf('@', 1))\n // Add package names, except for those under the `@types` scope as those\n // are known to only be dev dependencies.\n if (resolvedName && !resolvedName.startsWith('@types/')) {\n names.add(resolvedName)\n }\n }\n return JSON.stringify([...names], null, 2)\n}\n\nfunction parseableToQueryStdout(stdout: string) {\n if (stdout === '') {\n return ''\n }\n // Convert the parseable stdout into a json array of unique names.\n // The matchAll regexp looks for a forward (posix) or backward (win32) slash\n // and matches one or more non-slashes until the newline.\n const names = new Set(stdout.matchAll(/(?<=[/\\\\])[^/\\\\]+(?=\\n)/g))\n return JSON.stringify([...names], null, 2)\n}\n\nasync function npmQuery(npmExecPath: string, cwd: string): Promise<string> {\n let stdout = ''\n try {\n stdout = (await spawn(npmExecPath, ['query', ':not(.dev)'], { cwd })).stdout\n } catch {}\n return cleanupQueryStdout(stdout)\n}\n\nasync function lsBun(agentExecPath: string, cwd: string): Promise<string> {\n try {\n // Bun does not support filtering by production packages yet.\n // https://github.com/oven-sh/bun/issues/8283\n return (await spawn(agentExecPath!, ['pm', 'ls', '--all'], { cwd })).stdout\n } catch {}\n return ''\n}\n\nasync function lsNpm(agentExecPath: string, cwd: string): Promise<string> {\n return await npmQuery(agentExecPath, cwd)\n}\n\nasync function lsPnpm(\n agentExecPath: string,\n cwd: string,\n options?: AgentListDepsOptions\n): Promise<string> {\n const npmExecPath = options?.npmExecPath\n if (npmExecPath && npmExecPath !== NPM) {\n const result = await npmQuery(npmExecPath, cwd)\n if (result) {\n return result\n }\n }\n let stdout = ''\n try {\n stdout = (\n await spawn(\n agentExecPath,\n ['ls', '--parseable', '--prod', '--depth', 'Infinity'],\n { cwd }\n )\n ).stdout\n } catch {}\n return parseableToQueryStdout(stdout)\n}\n\nasync function lsVlt(agentExecPath: string, cwd: string): Promise<string> {\n let stdout = ''\n try {\n stdout = (\n await spawn(agentExecPath, ['ls', '--view', 'human', ':not(.dev)'], {\n cwd\n })\n ).stdout\n } catch {}\n return cleanupQueryStdout(stdout)\n}\n\nasync function lsYarnBerry(\n agentExecPath: string,\n cwd: string\n): Promise<string> {\n try {\n return (\n // Yarn Berry does not support filtering by production packages yet.\n // https://github.com/yarnpkg/berry/issues/5117\n (\n await spawn(agentExecPath, ['info', '--recursive', '--name-only'], {\n cwd\n })\n ).stdout.trim()\n )\n } catch {}\n return ''\n}\n\nasync function lsYarnClassic(\n agentExecPath: string,\n cwd: string\n): Promise<string> {\n try {\n // However, Yarn Classic does support it.\n // https://github.com/yarnpkg/yarn/releases/tag/v1.0.0\n // > Fix: Excludes dev dependencies from the yarn list output when the\n // environment is production\n return (\n await spawn(agentExecPath, ['list', '--prod'], { cwd })\n ).stdout.trim()\n } catch {}\n return ''\n}\n\nexport const lsByAgent: Record<Agent, AgentListDepsFn> = {\n // @ts-ignore\n __proto__: null,\n\n [BUN]: lsBun,\n [NPM]: lsNpm,\n [PNPM]: lsPnpm,\n [VLT]: lsVlt,\n [YARN_BERRY]: lsYarnBerry,\n [YARN_CLASSIC]: lsYarnClassic\n}\n","import { hasKeys, isObject } from '@socketsecurity/registry/lib/objects'\n\nimport constants from '../../constants'\n\nimport type {\n Agent,\n StringKeyValueObject\n} from '../../utils/package-manager-detector'\nimport type { EditablePackageJson } from '@socketsecurity/registry/lib/packages'\n\ntype NpmOverrides = { [key: string]: string | StringKeyValueObject }\ntype PnpmOrYarnOverrides = { [key: string]: string }\ntype Overrides = NpmOverrides | PnpmOrYarnOverrides\ntype AgentModifyManifestFn = (\n pkgJson: EditablePackageJson,\n overrides: Overrides\n) => void\n\nconst {\n BUN,\n NPM,\n OVERRIDES,\n PNPM,\n RESOLUTIONS,\n VLT,\n YARN_BERRY,\n YARN_CLASSIC\n} = constants\n\nconst PNPM_FIELD_NAME = PNPM\n\nconst depFields = [\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'peerDependenciesMeta',\n 'optionalDependencies',\n 'bundleDependencies'\n]\n\nfunction getEntryIndexes(\n entries: [string | symbol, any][],\n keys: (string | symbol)[]\n): number[] {\n return keys\n .map(n => entries.findIndex(p => p[0] === n))\n .filter(n => n !== -1)\n .sort((a, b) => a - b)\n}\n\nfunction getLowestEntryIndex(\n entries: [string | symbol, any][],\n keys: (string | symbol)[]\n) {\n return getEntryIndexes(entries, keys)?.[0] ?? -1\n}\n\nfunction getHighestEntryIndex(\n entries: [string | symbol, any][],\n keys: (string | symbol)[]\n) {\n return getEntryIndexes(entries, keys).at(-1) ?? -1\n}\n\nfunction updatePkgJson(\n editablePkgJson: EditablePackageJson,\n field: string,\n value: any\n) {\n const pkgJson = editablePkgJson.content\n const oldValue = pkgJson[field]\n if (oldValue) {\n // The field already exists so we simply update the field value.\n if (field === PNPM_FIELD_NAME) {\n if (hasKeys(value)) {\n editablePkgJson.update({\n [field]: {\n ...(isObject(oldValue) ? oldValue : {}),\n overrides: value\n }\n })\n } else {\n // Properties with undefined values are omitted when saved as JSON.\n editablePkgJson.update(<typeof pkgJson>(hasKeys(pkgJson[field])\n ? {\n [field]: {\n ...(isObject(oldValue) ? oldValue : {}),\n overrides: undefined\n }\n }\n : { [field]: undefined }))\n }\n } else if (field === OVERRIDES || field === RESOLUTIONS) {\n // Properties with undefined values are omitted when saved as JSON.\n editablePkgJson.update(<typeof pkgJson>{\n [field]: hasKeys(value) ? value : undefined\n })\n } else {\n editablePkgJson.update({ [field]: value })\n }\n return\n }\n if (\n (field === OVERRIDES ||\n field === PNPM_FIELD_NAME ||\n field === RESOLUTIONS) &&\n !hasKeys(value)\n ) {\n return\n }\n // Since the field doesn't exist we want to insert it into the package.json\n // in a place that makes sense, e.g. close to the \"dependencies\" field. If\n // we can't find a place to insert the field we'll add it to the bottom.\n const entries = Object.entries(pkgJson)\n let insertIndex = -1\n let isPlacingHigher = false\n if (field === OVERRIDES) {\n insertIndex = getLowestEntryIndex(entries, [RESOLUTIONS])\n if (insertIndex === -1) {\n isPlacingHigher = true\n insertIndex = getHighestEntryIndex(entries, [...depFields, PNPM])\n }\n } else if (field === RESOLUTIONS) {\n isPlacingHigher = true\n insertIndex = getHighestEntryIndex(entries, [...depFields, OVERRIDES, PNPM])\n } else if (field === PNPM_FIELD_NAME) {\n insertIndex = getLowestEntryIndex(entries, [OVERRIDES, RESOLUTIONS])\n if (insertIndex === -1) {\n isPlacingHigher = true\n insertIndex = getHighestEntryIndex(entries, depFields)\n }\n }\n if (insertIndex === -1) {\n insertIndex = getLowestEntryIndex(entries, ['engines', 'files'])\n }\n if (insertIndex === -1) {\n isPlacingHigher = true\n insertIndex = getHighestEntryIndex(entries, ['exports', 'imports', 'main'])\n }\n if (insertIndex === -1) {\n insertIndex = entries.length\n } else if (isPlacingHigher) {\n insertIndex += 1\n }\n entries.splice(insertIndex, 0, [field, value])\n editablePkgJson.fromJSON(\n `${JSON.stringify(Object.fromEntries(entries), null, 2)}\\n`\n )\n}\n\nfunction updateOverrides(\n editablePkgJson: EditablePackageJson,\n overrides: Overrides\n) {\n updatePkgJson(editablePkgJson, OVERRIDES, overrides)\n}\n\nfunction updateResolutions(\n editablePkgJson: EditablePackageJson,\n overrides: Overrides\n) {\n updatePkgJson(editablePkgJson, RESOLUTIONS, <PnpmOrYarnOverrides>overrides)\n}\n\nfunction pnpmUpdatePkgJson(\n editablePkgJson: EditablePackageJson,\n overrides: Overrides\n) {\n updatePkgJson(editablePkgJson, PNPM_FIELD_NAME, overrides)\n}\n\nexport const updateManifestByAgent: Record<Agent, AgentModifyManifestFn> = {\n // @ts-ignore\n __proto__: null,\n\n [BUN]: updateResolutions,\n [NPM]: updateOverrides,\n [PNPM]: pnpmUpdatePkgJson,\n [VLT]: updateOverrides,\n [YARN_BERRY]: updateResolutions,\n [YARN_CLASSIC]: updateResolutions\n}\n","import spawn from '@npmcli/promise-spawn'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport constants from '../../constants'\nimport { safeNpmInstall } from '../../utils/npm'\n\nimport type { Agent } from '../../utils/package-manager-detector'\n\nconst { NPM, SOCKET_CLI_SAFE_WRAPPER, abortSignal } = constants\n\nconst COMMAND_TITLE = 'Socket Optimize'\nconst NPM_OVERRIDE_PR_URL = 'https://github.com/npm/cli/pull/8089'\n\nexport async function updatePackageLockJson(\n lockName: string,\n agentExecPath: string,\n agent: Agent,\n spinner: Spinner\n) {\n spinner.start(`Updating ${lockName}...`)\n try {\n if (agent === NPM) {\n const ipc = {\n [SOCKET_CLI_SAFE_WRAPPER]: true\n }\n await safeNpmInstall({ ipc })\n // TODO: This is a temporary workaround for a `npm ci` bug where it\n // will error out after Socket Optimize generates a lock file.\n // More investigation is needed.\n await safeNpmInstall({\n args: ['--ignore-scripts', '--package-lock-only'],\n ipc\n })\n } else {\n // All package managers support the \"install\" command.\n await spawn(agentExecPath, ['install'], {\n signal: abortSignal,\n stdio: 'ignore'\n })\n }\n spinner.stop()\n if (agent === NPM) {\n console.log(\n `💡 Re-run ${COMMAND_TITLE} whenever ${lockName} changes.\\n This can be skipped once npm ships ${NPM_OVERRIDE_PR_URL}.`\n )\n }\n } catch (e: any) {\n spinner.error(\n `${COMMAND_TITLE}: ${agent} install failed to update ${lockName}`\n )\n console.error(e)\n }\n}\n","import path from 'node:path'\n\nimport npa from 'npm-package-arg'\nimport semver from 'semver'\nimport { glob as tinyGlob } from 'tinyglobby'\n\nimport { type ManifestEntry } from '@socketsecurity/registry'\nimport { hasOwn, toSortedObject } from '@socketsecurity/registry/lib/objects'\nimport {\n fetchPackageManifest,\n readPackageJson\n} from '@socketsecurity/registry/lib/packages'\nimport { type EditablePackageJson } from '@socketsecurity/registry/lib/packages'\nimport { pEach } from '@socketsecurity/registry/lib/promises'\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\nimport { pluralize } from '@socketsecurity/registry/lib/words'\n\nimport { depsIncludesByAgent } from './deps-includes-by-agent'\nimport { detectAndValidatePackageManager } from './detect-and-validate-package-manager'\nimport { getDependencyEntries } from './get-dependency-entries'\nimport { getOverridesDataByAgent } from './get-overrides-by-agent'\nimport { getWorkspaceGlobs } from './get-workspace-globs'\nimport {\n AgentLockIncludesFn,\n lockIncludesByAgent\n} from './lock-includes-by-agent'\nimport { lsByAgent } from './ls-by-agent'\nimport { updateManifestByAgent } from './update-manifest-by-agent'\nimport { updatePackageLockJson } from './update-package-lock-json'\nimport constants from '../../constants'\n\nimport type {\n Agent,\n StringKeyValueObject\n} from '../../utils/package-manager-detector'\n\ntype PackageJson = Awaited<ReturnType<typeof readPackageJson>>\n\ntype AddOverridesConfig = {\n agent: Agent\n agentExecPath: string\n lockBasename: string\n lockSrc: string\n manifestEntries: ManifestEntry[]\n npmExecPath: string\n pkgJson?: EditablePackageJson | undefined\n pkgPath: string\n pin?: boolean | undefined\n prod?: boolean | undefined\n rootPath: string\n}\n\ntype AddOverridesState = {\n added: Set<string>\n addedInWorkspaces: Set<string>\n spinner: Spinner\n updated: Set<string>\n updatedInWorkspaces: Set<string>\n warnedPnpmWorkspaceRequiresNpm: boolean\n}\n\ntype NpmOverrides = { [key: string]: string | StringKeyValueObject }\ntype PnpmOrYarnOverrides = { [key: string]: string }\ntype Overrides = NpmOverrides | PnpmOrYarnOverrides\ntype GetOverridesResult = { type: Agent; overrides: Overrides }\n\nconst { NPM, PNPM, YARN_CLASSIC } = constants\n\nconst COMMAND_TITLE = 'Socket Optimize'\n\nexport async function applyOptimization(\n cwd: string,\n pin: boolean,\n prod: boolean\n) {\n const pkgMgrData = await detectAndValidatePackageManager(cwd, prod)\n if (!pkgMgrData) return\n\n const {\n agent,\n agentExecPath,\n lockBasename,\n lockName,\n lockSrc,\n manifestEntries,\n npmExecPath,\n pkgJson,\n pkgPath\n } = pkgMgrData\n\n const spinner = new Spinner({ text: 'Socket optimizing...' })\n spinner.start()\n\n const state = await addOverrides(\n {\n agent,\n agentExecPath,\n lockBasename,\n lockSrc,\n manifestEntries,\n npmExecPath,\n pin,\n pkgJson,\n pkgPath,\n prod,\n rootPath: pkgPath\n },\n createAddOverridesState(spinner)\n )\n\n spinner.stop()\n\n const addedCount = state.added.size\n const updatedCount = state.updated.size\n const pkgJsonChanged = addedCount > 0 || updatedCount > 0\n if (pkgJsonChanged) {\n if (updatedCount > 0) {\n console.log(\n `${createActionMessage('Updated', updatedCount, state.updatedInWorkspaces.size)}${addedCount ? '.' : '🚀'}`\n )\n }\n if (addedCount > 0) {\n console.log(\n `${createActionMessage('Added', addedCount, state.addedInWorkspaces.size)} 🚀`\n )\n }\n } else {\n console.log('Congratulations! Already Socket.dev optimized 🎉')\n }\n\n if (agent === NPM || pkgJsonChanged) {\n // Always update package-lock.json until the npm overrides PR lands:\n // https://github.com/npm/cli/pull/8089\n await updatePackageLockJson(lockName, agentExecPath, agent, spinner)\n }\n}\n\nfunction createActionMessage(\n verb: string,\n overrideCount: number,\n workspaceCount: number\n): string {\n return `${verb} ${overrideCount} Socket.dev optimized ${pluralize('override', overrideCount)}${workspaceCount ? ` in ${workspaceCount} ${pluralize('workspace', workspaceCount)}` : ''}`\n}\n\nfunction createAddOverridesState(spinner: Spinner): AddOverridesState {\n return {\n added: new Set(),\n addedInWorkspaces: new Set(),\n spinner,\n updated: new Set(),\n updatedInWorkspaces: new Set(),\n warnedPnpmWorkspaceRequiresNpm: false\n }\n}\n\nasync function addOverrides(\n {\n agent,\n agentExecPath,\n lockBasename,\n lockSrc,\n manifestEntries,\n npmExecPath,\n pin,\n pkgJson: editablePkgJson,\n pkgPath,\n prod,\n rootPath\n }: AddOverridesConfig,\n state: AddOverridesState\n): Promise<AddOverridesState> {\n if (editablePkgJson === undefined) {\n editablePkgJson = await readPackageJson(pkgPath, { editable: true })\n }\n const { spinner } = state\n const { content: pkgJson } = editablePkgJson\n const isRoot = pkgPath === rootPath\n const isLockScanned = isRoot && !prod\n const workspaceName = path.relative(rootPath, pkgPath)\n const workspaceGlobs = await getWorkspaceGlobs(agent, pkgPath, pkgJson)\n const isWorkspace = !!workspaceGlobs\n if (\n isWorkspace &&\n agent === PNPM &&\n npmExecPath === NPM &&\n !state.warnedPnpmWorkspaceRequiresNpm\n ) {\n state.warnedPnpmWorkspaceRequiresNpm = true\n console.warn(\n `⚠️ ${COMMAND_TITLE}: pnpm workspace support requires \\`npm ls\\`, falling back to \\`pnpm list\\``\n )\n }\n const thingToScan = isLockScanned\n ? lockSrc\n : await lsByAgent[agent](agentExecPath, pkgPath, { npmExecPath })\n // The AgentDepsIncludesFn and AgentLockIncludesFn types overlap in their\n // first two parameters. AgentLockIncludesFn accepts an optional third\n // parameter which AgentDepsIncludesFn will ignore so we cast thingScanner\n // as an AgentLockIncludesFn type.\n const thingScanner = <AgentLockIncludesFn>(\n (isLockScanned ? lockIncludesByAgent[agent] : depsIncludesByAgent[agent])\n )\n const depEntries = getDependencyEntries(pkgJson)\n\n const overridesDataObjects = <GetOverridesResult[]>[]\n if (pkgJson['private'] || isWorkspace) {\n overridesDataObjects.push(getOverridesDataByAgent[agent](pkgJson))\n } else {\n overridesDataObjects.push(\n getOverridesDataByAgent[NPM](pkgJson),\n getOverridesDataByAgent[YARN_CLASSIC](pkgJson)\n )\n }\n if (spinner) {\n spinner.text = `Adding overrides${workspaceName ? ` to ${workspaceName}` : ''}...`\n }\n const depAliasMap = new Map<string, string>()\n // Chunk package names to process them in parallel 3 at a time.\n await pEach(manifestEntries, 3, async ({ 1: data }) => {\n const { name: sockRegPkgName, package: origPkgName, version } = data\n const major = semver.major(version)\n const sockOverridePrefix = `${NPM}:${sockRegPkgName}@`\n const sockOverrideSpec = `${sockOverridePrefix}${pin ? version : `^${major}`}`\n for (const { 1: depObj } of depEntries) {\n const sockSpec = hasOwn(depObj, sockRegPkgName)\n ? depObj[sockRegPkgName]\n : undefined\n if (sockSpec) {\n depAliasMap.set(sockRegPkgName, sockSpec)\n }\n const origSpec = hasOwn(depObj, origPkgName)\n ? depObj[origPkgName]\n : undefined\n if (origSpec) {\n let thisSpec = origSpec\n // Add package aliases for direct dependencies to avoid npm EOVERRIDE errors.\n // https://docs.npmjs.com/cli/v8/using-npm/package-spec#aliases\n if (\n !(\n thisSpec.startsWith(sockOverridePrefix) &&\n semver.coerce(npa(thisSpec).rawSpec)?.version\n )\n ) {\n thisSpec = sockOverrideSpec\n depObj[origPkgName] = thisSpec\n state.added.add(sockRegPkgName)\n if (workspaceName) {\n state.addedInWorkspaces.add(workspaceName)\n }\n }\n depAliasMap.set(origPkgName, thisSpec)\n }\n }\n if (isRoot) {\n // Chunk package names to process them in parallel 3 at a time.\n await pEach(overridesDataObjects, 3, async ({ overrides, type }) => {\n const overrideExists = hasOwn(overrides, origPkgName)\n if (\n overrideExists ||\n thingScanner(thingToScan, origPkgName, lockBasename)\n ) {\n const oldSpec = overrideExists ? overrides[origPkgName]! : undefined\n const origDepAlias = depAliasMap.get(origPkgName)\n const sockRegDepAlias = depAliasMap.get(sockRegPkgName)\n const depAlias = sockRegDepAlias ?? origDepAlias\n let newSpec = sockOverrideSpec\n if (type === NPM && depAlias) {\n // With npm one may not set an override for a package that one directly\n // depends on unless both the dependency and the override itself share\n // the exact same spec. To make this limitation easier to deal with,\n // overrides may also be defined as a reference to a spec for a direct\n // dependency by prefixing the name of the package to match the version\n // of with a $.\n // https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides\n newSpec = `$${sockRegDepAlias ? sockRegPkgName : origPkgName}`\n } else if (typeof oldSpec === 'string') {\n const thisSpec = oldSpec.startsWith('$')\n ? depAlias || newSpec\n : oldSpec || newSpec\n if (thisSpec.startsWith(sockOverridePrefix)) {\n if (\n pin &&\n semver.major(\n semver.coerce(npa(thisSpec).rawSpec)?.version ?? version\n ) !== major\n ) {\n const otherVersion = (await fetchPackageManifest(thisSpec))\n ?.version\n if (otherVersion && otherVersion !== version) {\n newSpec = `${sockOverridePrefix}${pin ? otherVersion : `^${semver.major(otherVersion)}`}`\n }\n }\n } else {\n newSpec = oldSpec\n }\n }\n if (newSpec !== oldSpec) {\n overrides[origPkgName] = newSpec\n const addedOrUpdated = overrideExists ? 'updated' : 'added'\n state[addedOrUpdated].add(sockRegPkgName)\n }\n }\n })\n }\n })\n if (workspaceGlobs) {\n const workspacePkgJsonPaths = await tinyGlob(workspaceGlobs, {\n absolute: true,\n cwd: pkgPath!,\n ignore: ['**/node_modules/**', '**/bower_components/**']\n })\n // Chunk package names to process them in parallel 3 at a time.\n await pEach(workspacePkgJsonPaths, 3, async workspacePkgJsonPath => {\n const otherState = await addOverrides(\n {\n agent,\n agentExecPath,\n lockBasename,\n lockSrc,\n manifestEntries,\n npmExecPath,\n pin,\n pkgPath: path.dirname(workspacePkgJsonPath),\n prod,\n rootPath\n },\n createAddOverridesState(spinner)\n )\n for (const key of [\n 'added',\n 'addedInWorkspaces',\n 'updated',\n 'updatedInWorkspaces'\n ] satisfies\n // Here we're just telling TS that we're looping over key names\n // of the type and that they're all Set<string> props. This allows\n // us to do the SetA.add(setB.get) pump type-safe without casts.\n Array<\n keyof Pick<\n AddOverridesState,\n 'added' | 'addedInWorkspaces' | 'updated' | 'updatedInWorkspaces'\n >\n >) {\n for (const value of otherState[key]) {\n state[key].add(value)\n }\n }\n })\n }\n if (state.added.size > 0 || state.updated.size > 0) {\n editablePkgJson.update(<PackageJson>Object.fromEntries(depEntries))\n for (const { overrides, type } of overridesDataObjects) {\n updateManifestByAgent[type](editablePkgJson, toSortedObject(overrides))\n }\n await editablePkgJson.save()\n }\n return state\n}\n","import process from 'node:process'\n\nimport { applyOptimization } from './apply-optimization'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'optimize',\n description: 'Optimize dependencies with @socketregistry overrides',\n hidden: false,\n flags: {\n ...commonFlags,\n pin: {\n type: 'boolean',\n default: false,\n description: 'Pin overrides to their latest version'\n },\n prod: {\n type: 'boolean',\n default: false,\n description: 'Only add overrides for production dependencies'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command}\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command}\n $ ${command} --pin\n `\n}\n\nexport const cmdOptimize = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const cwd = process.cwd()\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await applyOptimization(\n cwd,\n Boolean(cli.flags['pin']),\n Boolean(cli.flags['prod'])\n )\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { AuthError } from '../../utils/errors'\nimport { getDefaultToken, setupSdk } from '../../utils/sdk'\n\nexport async function getOrganizations(): Promise<void> {\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n const spinner = new Spinner({ text: 'Fetching organizations...' }).start()\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getOrganizations(),\n 'looking up organizations'\n )\n\n if (result.success === false) {\n handleUnsuccessfulApiResponse('getOrganizations', result, spinner)\n return\n }\n\n spinner.stop(\n `List of organizations associated with your API key: ${colors.italic(apiToken)}`\n )\n\n const organizations = Object.values(result.data.organizations)\n for (const o of organizations) {\n console.log(`\nName: ${o?.name}\nID: ${o?.id}\nPlan: ${o?.plan}\n `)\n }\n}\n","import { getOrganizations } from './get-organizations'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'organizations',\n description: 'List organizations associated with the API key used',\n hidden: false,\n flags: {},\n help: (command, _config) => `\n Usage\n $ ${command}\n `\n}\n\nexport const cmdOrganizations = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await getOrganizations()\n}\n","import process from 'node:process'\n\nimport spawn from '@npmcli/promise-spawn'\n\nimport constants from '../../constants'\nimport { getNpmBinPath } from '../../shadow/npm-paths'\n\nconst { abortSignal } = constants\n\nexport async function runRawNpm(argv: ReadonlyArray<string>): Promise<void> {\n const spawnPromise = spawn(getNpmBinPath(), argv.slice(0), {\n signal: abortSignal,\n stdio: 'inherit'\n })\n // See https://nodejs.org/api/all.html#all_child_process_event-exit.\n spawnPromise.process.on('exit', (code, signalName) => {\n if (abortSignal.aborted) {\n return\n }\n if (signalName) {\n process.kill(process.pid, signalName)\n } else if (code !== null) {\n process.exit(code)\n }\n })\n await spawnPromise\n}\n","import { runRawNpm } from './run-raw-npm'\nimport constants from '../../constants'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst { NPM } = constants\n\nconst config: CliCommandConfig = {\n commandName: 'raw-npm',\n description: `Temporarily disable the Socket ${NPM} wrapper`,\n hidden: false,\n flags: {},\n help: (command, config) => `\n Usage\n $ ${command} <command>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} install\n `\n}\n\nexport const cmdRawNpm = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: ReadonlyArray<string>,\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n allowUnknownFlags: true,\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await runRawNpm(argv)\n}\n","import process from 'node:process'\n\nimport spawn from '@npmcli/promise-spawn'\n\nimport constants from '../../constants'\nimport { getNpxBinPath } from '../../shadow/npm-paths'\n\nconst { abortSignal } = constants\n\nexport async function runRawNpx(argv: ReadonlyArray<string>): Promise<void> {\n const spawnPromise = spawn(getNpxBinPath(), <string[]>argv, {\n signal: abortSignal,\n stdio: 'inherit'\n })\n // See https://nodejs.org/api/all.html#all_child_process_event-exit.\n spawnPromise.process.on('exit', (code, signalName) => {\n if (abortSignal.aborted) {\n return\n }\n if (signalName) {\n process.kill(process.pid, signalName)\n } else if (code !== null) {\n process.exit(code)\n }\n })\n await spawnPromise\n}\n","import { runRawNpx } from './run-raw-npx'\nimport constants from '../../constants'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst { NPX } = constants\n\nconst config: CliCommandConfig = {\n commandName: 'raw-npx',\n description: `Temporarily disable the Socket ${NPX} wrapper`,\n hidden: false,\n flags: {},\n help: (command, config) => `\n Usage\n $ ${command} <command>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} install\n `\n}\n\nexport const cmdRawNpx = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: ReadonlyArray<string>,\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n allowUnknownFlags: true,\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await runRawNpx(argv)\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { debugLog } from '../../utils/debug'\nimport { getLogSymbols } from '../../utils/logging'\nimport { getPackageFiles } from '../../utils/path-resolve'\nimport { setupSdk } from '../../utils/sdk'\n\nimport type { SocketYml } from '@socketsecurity/config'\nimport type {\n SocketSdkResultType,\n SocketSdkReturnType\n} from '@socketsecurity/sdk'\n\nexport async function createReport(\n socketConfig: SocketYml | undefined,\n inputPaths: Array<string>,\n {\n cwd,\n dryRun\n }: {\n cwd: string\n dryRun: boolean\n }\n): Promise<undefined | SocketSdkResultType<'createReport'>> {\n const socketSdk = await setupSdk()\n const supportedFiles = await socketSdk\n .getReportSupportedFiles()\n .then(res => {\n if (!res.success)\n handleUnsuccessfulApiResponse(\n 'getReportSupportedFiles',\n res,\n new Spinner()\n )\n return (res as SocketSdkReturnType<'getReportSupportedFiles'>).data\n })\n .catch((cause: Error) => {\n throw new Error('Failed getting supported files for report', {\n cause\n })\n })\n\n const packagePaths = await getPackageFiles(\n cwd,\n inputPaths,\n socketConfig,\n supportedFiles\n )\n\n debugLog(\n 'Uploading:',\n packagePaths.join(`\\n${getLogSymbols().info} Uploading: `)\n )\n\n if (dryRun) {\n debugLog('[dryRun] Skipped actual upload')\n return undefined\n } else {\n const socketSdk = await setupSdk()\n const spinner = new Spinner({\n text: `Creating report with ${packagePaths.length} package files`\n }).start()\n\n const apiCall = socketSdk.createReportFromFilePaths(\n packagePaths,\n cwd,\n socketConfig?.issueRules\n )\n const result = await handleApiCall(apiCall, 'creating report')\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('createReport', result, spinner)\n return undefined\n }\n spinner.success()\n return result\n }\n}\n","import { betterAjvErrors } from '@apideck/better-ajv-errors'\n\nimport { SocketValidationError, readSocketConfig } from '@socketsecurity/config'\n\nimport { InputError } from '../../utils/errors'\n\nexport async function getSocketConfig(absoluteConfigPath: string) {\n const socketConfig = await readSocketConfig(absoluteConfigPath).catch(\n (cause: unknown) => {\n if (\n cause &&\n typeof cause === 'object' &&\n cause instanceof SocketValidationError\n ) {\n // Inspired by workbox-build:\n // https://github.com/GoogleChrome/workbox/blob/95f97a207fd51efb3f8a653f6e3e58224183a778/packages/workbox-build/src/lib/validate-options.ts#L68-L71\n const betterErrors = betterAjvErrors({\n basePath: 'config',\n data: cause.data,\n errors: cause.validationErrors,\n schema: cause.schema as Parameters<\n typeof betterAjvErrors\n >[0]['schema']\n })\n throw new InputError(\n 'The socket.yml config is not valid',\n betterErrors\n .map(\n err =>\n `[${err.path}] ${err.message}.${err.suggestion ? err.suggestion : ''}`\n )\n .join('\\n')\n )\n } else {\n throw new Error('Failed to read socket.yml config', { cause })\n }\n }\n )\n\n return socketConfig\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport {\n formatSeverityCount,\n getSeverityCount\n} from '../../utils/alert/severity'\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nimport type {\n SocketSdkResultType,\n SocketSdkReturnType\n} from '@socketsecurity/sdk'\n\nexport type ReportData = SocketSdkReturnType<'getReport'>['data']\n\nconst MAX_TIMEOUT_RETRY = 5\nconst HTTP_CODE_TIMEOUT = 524\n\nexport async function fetchReportData(\n reportId: string,\n includeAllIssues: boolean,\n strict: boolean\n): Promise<void | ReportData> {\n const socketSdk = await setupSdk()\n const spinner = new Spinner({\n text: `Fetching report with ID ${reportId} (this could take a while)`\n }).start()\n\n let result: SocketSdkResultType<'getReport'> | undefined\n for (let retry = 1; !result; ++retry) {\n try {\n // eslint-disable-next-line no-await-in-loop\n result = await handleApiCall(\n socketSdk.getReport(reportId),\n 'fetching report'\n )\n } catch (err) {\n if (\n retry >= MAX_TIMEOUT_RETRY ||\n !(err instanceof Error) ||\n (err.cause as any)?.cause?.response?.statusCode !== HTTP_CODE_TIMEOUT\n ) {\n throw err\n }\n }\n }\n\n if (!result.success) {\n return handleUnsuccessfulApiResponse('getReport', result, spinner)\n }\n\n // Conclude the status of the API call\n\n if (strict) {\n if (result.data.healthy) {\n spinner.success('Report result is healthy and great!')\n } else {\n spinner.error('Report result deemed unhealthy for project')\n }\n } else if (!result.data.healthy) {\n const severityCount = getSeverityCount(\n result.data.issues,\n includeAllIssues ? undefined : 'high'\n )\n const issueSummary = formatSeverityCount(severityCount)\n spinner.success(`Report has these issues: ${issueSummary}`)\n } else {\n spinner.success('Report has no issues')\n }\n\n return result.data\n}\n","import process from 'node:process'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { ColorOrMarkdown } from '../../utils/color-or-markdown'\n\nimport type { ReportData } from './fetch-report-data'\n\nexport function formatReportDataOutput(\n reportId: string,\n data: ReportData,\n commandName: string,\n outputJson: boolean,\n outputMarkdown: boolean,\n strict: boolean\n): void {\n if (outputJson) {\n console.log(JSON.stringify(data, undefined, 2))\n } else {\n const format = new ColorOrMarkdown(outputMarkdown)\n console.log(\n '\\nDetailed info on socket.dev: ' +\n format.hyperlink(reportId, data.url, { fallbackToUrl: true })\n )\n if (!outputMarkdown) {\n console.log(\n colors.dim(\n `\\nOr rerun ${colors.italic(commandName)} using the ${colors.italic('--json')} flag to get full JSON output`\n )\n )\n }\n }\n\n if (strict && !data.healthy) {\n process.exit(1)\n }\n}\n","import { fetchReportData } from './fetch-report-data'\nimport { formatReportDataOutput } from './format-report-data'\n\nexport async function viewReport(\n reportId: string,\n {\n all,\n commandName,\n json,\n markdown,\n strict\n }: {\n commandName: string\n all: boolean\n json: boolean\n markdown: boolean\n strict: boolean\n }\n) {\n const result = await fetchReportData(reportId, all, strict)\n if (result) {\n formatReportDataOutput(\n reportId,\n result,\n commandName,\n json,\n markdown,\n strict\n )\n }\n}\n","import path from 'node:path'\nimport process from 'node:process'\n\nimport { createReport } from './create-report'\nimport { getSocketConfig } from './get-socket-config'\nimport { viewReport } from './view-report'\nimport { commonFlags, outputFlags, validationFlags } from '../../flags'\nimport { ColorOrMarkdown } from '../../utils/color-or-markdown'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'create',\n description: 'Create a project report',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n ...validationFlags,\n dryRun: {\n type: 'boolean',\n default: false,\n description: 'Only output what will be done without actually doing it'\n },\n view: {\n type: 'boolean',\n shortFlag: 'v',\n default: false,\n description: 'Will wait for and return the created report'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} <paths-to-package-folders-and-files>\n\n Uploads the specified \"package.json\" and lock files for JavaScript, Python, and Go dependency manifests.\n If any folder is specified, the ones found in there recursively are uploaded.\n\n Supports globbing such as \"**/package.json\", \"**/requirements.txt\", \"**/pyproject.toml\", and \"**/go.mod\".\n\n Ignores any file specified in your project's \".gitignore\", your project's\n \"socket.yml\" file's \"projectIgnorePaths\" and also has a sensible set of\n default ignores from the \"ignore-by-default\" module.\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} .\n $ ${command} '**/package.json'\n $ ${command} /path/to/a/package.json /path/to/another/package.json\n $ ${command} . --view --json\n `\n}\n\nexport const cmdReportCreate = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n // TODO: Allow setting a custom cwd and/or configFile path?\n const cwd = process.cwd()\n const absoluteConfigPath = path.join(cwd, 'socket.yml')\n\n const dryRun = Boolean(cli.flags['dryRun'])\n const json = Boolean(cli.flags['json'])\n const markdown = Boolean(cli.flags['markdown'])\n const strict = Boolean(cli.flags['strict'])\n const includeAllIssues = Boolean(cli.flags['all'])\n const view = Boolean(cli.flags['view'])\n\n // Note exiting earlier to skirt a hidden auth requirement\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const socketConfig = await getSocketConfig(absoluteConfigPath)\n\n const result = await createReport(socketConfig, cli.input, { cwd, dryRun })\n\n const commandName = `${parentName} ${config.commandName}`\n\n if (result?.success) {\n if (view) {\n const reportId = result.data.id\n await viewReport(reportId, {\n all: includeAllIssues,\n commandName,\n json,\n markdown,\n strict\n })\n } else if (json) {\n console.log(JSON.stringify(result.data, undefined, 2))\n return\n } else {\n const format = new ColorOrMarkdown(markdown)\n console.log(\n `New report: ${format.hyperlink(result.data.id, result.data.url, { fallbackToUrl: true })}`\n )\n }\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { viewReport } from './view-report'\nimport { commonFlags, outputFlags, validationFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'view',\n description: 'View a project report',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n ...validationFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <report-identifier>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} QXU8PmK7LfH608RAwfIKdbcHgwEd_ZeWJ9QEGv05FJUQ\n `\n}\n\nexport const cmdReportView = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [reportId, ...extraInput] = cli.input\n\n // Validate the input.\n if (extraInput.length || !reportId) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Need at least one report ID ${!reportId ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Can only handle a single report ID ${extraInput.length < 2 ? colors.red(`(received ${extraInput.length}!)`) : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n await viewReport(reportId, {\n all: Boolean(cli.flags['all']),\n commandName: `${parentName} ${config.commandName}`,\n json: Boolean(cli.flags['json']),\n markdown: Boolean(cli.flags['markdown']),\n strict: Boolean(cli.flags['strict'])\n })\n}\n","import { cmdReportCreate } from './cmd-report-create'\nimport { cmdReportView } from './cmd-report-view'\nimport { meowWithSubcommands } from '../../utils/meow-with-subcommands'\n\nimport type { CliSubcommand } from '../../utils/meow-with-subcommands'\n\nconst description = '[Deprecated] Project report related commands'\n\nexport const cmdReport: CliSubcommand = {\n description,\n async run(argv, importMeta, { parentName }) {\n await meowWithSubcommands(\n {\n create: cmdReportCreate,\n view: cmdReportView\n },\n {\n argv,\n description,\n importMeta,\n name: parentName + ' report'\n }\n )\n }\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function createRepo({\n apiToken,\n default_branch,\n description,\n homepage,\n orgSlug,\n outputJson,\n outputMarkdown,\n repoName,\n visibility\n}: {\n apiToken: string\n outputJson: boolean\n outputMarkdown: boolean\n orgSlug: string\n repoName: string\n description: string\n homepage: string\n default_branch: string\n visibility: string\n}): Promise<void> {\n const spinnerText = 'Creating repository... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.createOrgRepo(orgSlug, {\n outputJson,\n outputMarkdown,\n orgSlug,\n name: repoName,\n description,\n homepage,\n default_branch,\n visibility\n }),\n 'creating repository'\n )\n\n if (result.success) {\n spinner.success('Repository created successfully')\n } else {\n handleUnsuccessfulApiResponse('createOrgRepo', result, spinner)\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { createRepo } from './create-repo'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'create',\n description: 'Create a repository in an organization',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n repoName: {\n type: 'string',\n shortFlag: 'n',\n default: '',\n description: 'Repository name'\n },\n repoDescription: {\n type: 'string',\n shortFlag: 'd',\n default: '',\n description: 'Repository description'\n },\n homepage: {\n type: 'string',\n shortFlag: 'h',\n default: '',\n description: 'Repository url'\n },\n defaultBranch: {\n type: 'string',\n shortFlag: 'b',\n default: 'main',\n description: 'Repository default branch'\n },\n visibility: {\n type: 'string',\n shortFlag: 'v',\n default: 'private',\n description: 'Repository visibility (Default Private)'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg --repoName=test-repo\n `\n}\n\nexport const cmdReposCreate = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const repoName = cli.flags['repoName']\n const [orgSlug = ''] = cli.input\n\n if (!repoName || typeof repoName !== 'string' || !orgSlug) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await createRepo({\n outputJson: Boolean(cli.flags['json']),\n outputMarkdown: Boolean(cli.flags['markdown']),\n orgSlug,\n repoName,\n description: String(cli.flags['repoDescription'] || ''),\n homepage: String(cli.flags['homepage'] || ''),\n default_branch: String(cli.flags['defaultBranch'] || ''),\n visibility: String(cli.flags['visibility'] || 'private'),\n apiToken\n })\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function deleteRepo(\n orgSlug: string,\n repoName: string,\n apiToken: string\n): Promise<void> {\n const spinnerText = 'Deleting repository... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.deleteOrgRepo(orgSlug, repoName),\n 'deleting repository'\n )\n\n if (result.success) {\n spinner.success('Repository deleted successfully')\n } else {\n handleUnsuccessfulApiResponse('deleteOrgRepo', result, spinner)\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { deleteRepo } from './delete-repo'\nimport { commonFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'del',\n description: 'Delete a repository in an organization',\n hidden: false,\n flags: {\n ...commonFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug> <repo slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg test-repo\n `\n}\n\nexport const cmdReposDel = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [orgSlug = '', repoName = ''] = cli.input\n\n if (!orgSlug || !repoName) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Repository name as the second argument ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\\n\n - At least one TARGET (e.g. \\`.\\` or \\`./package.json\\`\\n`)\n return\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await deleteRepo(orgSlug, repoName, apiToken)\n}\n","// @ts-ignore\nimport chalkTable from 'chalk-table'\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function listRepos({\n apiToken,\n direction,\n orgSlug,\n outputJson,\n outputMarkdown,\n page,\n per_page,\n sort\n}: {\n outputJson: boolean\n outputMarkdown: boolean\n orgSlug: string\n sort: string\n direction: string\n per_page: number\n page: number\n apiToken: string\n}): Promise<void> {\n const spinnerText = 'Listing repositories... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getOrgRepoList(orgSlug, {\n outputJson,\n outputMarkdown,\n orgSlug,\n sort,\n direction,\n per_page,\n page\n }),\n 'listing repositories'\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('getOrgRepoList', result, spinner)\n return\n }\n\n const options = {\n columns: [\n { field: 'id', name: colors.magenta('ID') },\n { field: 'name', name: colors.magenta('Name') },\n { field: 'visibility', name: colors.magenta('Visibility') },\n { field: 'default_branch', name: colors.magenta('Default branch') },\n { field: 'archived', name: colors.magenta('Archived') }\n ]\n }\n\n spinner.stop(chalkTable(options, result.data.results))\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { listRepos } from './list-repos'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'list',\n description: 'List repositories in an organization',\n hidden: false,\n flags: {\n ...commonFlags,\n sort: {\n type: 'string',\n shortFlag: 's',\n default: 'created_at',\n description: 'Sorting option'\n },\n direction: {\n type: 'string',\n default: 'desc',\n description: 'Direction option'\n },\n perPage: {\n type: 'number',\n shortFlag: 'pp',\n default: 30,\n description: 'Number of results per page'\n },\n page: {\n type: 'number',\n shortFlag: 'p',\n default: 1,\n description: 'Page number'\n },\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg\n `\n}\n\nexport const cmdReposList = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [orgSlug = ''] = cli.input\n\n if (!orgSlug) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - At least one TARGET (e.g. \\`.\\` or \\`./package.json\\`\\n`)\n return\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await listRepos({\n apiToken,\n outputJson: Boolean(cli.flags['json']),\n outputMarkdown: Boolean(cli.flags['markdown']),\n orgSlug,\n sort: String(cli.flags['sort'] || 'created_at'),\n direction: cli.flags['direction'] === 'asc' ? 'asc' : 'desc',\n page: Number(cli.flags['page']) || 1,\n per_page: Number(cli.flags['perPage']) || 30\n })\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function updateRepo({\n apiToken,\n default_branch,\n description,\n homepage,\n orgSlug,\n outputJson,\n outputMarkdown,\n repoName,\n visibility\n}: {\n apiToken: string\n outputJson: boolean\n outputMarkdown: boolean\n orgSlug: string\n repoName: string\n description: string\n homepage: string\n default_branch: string\n visibility: string\n}): Promise<void> {\n const spinnerText = 'Updating repository... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.updateOrgRepo(orgSlug, repoName, {\n outputJson,\n outputMarkdown,\n orgSlug,\n name: repoName,\n description,\n homepage,\n default_branch,\n visibility\n }),\n 'updating repository'\n )\n\n if (result.success) {\n spinner.success('Repository updated successfully')\n } else {\n handleUnsuccessfulApiResponse('updateOrgRepo', result, spinner)\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { updateRepo } from './update-repo'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'update',\n description: 'Update a repository in an organization',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n repoName: {\n type: 'string',\n shortFlag: 'n',\n default: '',\n description: 'Repository name'\n },\n repoDescription: {\n type: 'string',\n shortFlag: 'd',\n default: '',\n description: 'Repository description'\n },\n homepage: {\n type: 'string',\n shortFlag: 'h',\n default: '',\n description: 'Repository url'\n },\n defaultBranch: {\n type: 'string',\n shortFlag: 'b',\n default: 'main',\n description: 'Repository default branch'\n },\n visibility: {\n type: 'string',\n shortFlag: 'v',\n default: 'private',\n description: 'Repository visibility (Default Private)'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg\n `\n}\n\nexport const cmdReposUpdate = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const repoName = cli.flags['repoName']\n const [orgSlug = ''] = cli.input\n\n if (!repoName || typeof repoName !== 'string' || !orgSlug) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\\n\n - At least one TARGET (e.g. \\`.\\` or \\`./package.json\\`\\n`)\n return\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await updateRepo({\n apiToken,\n outputJson: Boolean(cli.flags['json']),\n outputMarkdown: Boolean(cli.flags['markdown']),\n orgSlug,\n repoName,\n description: String(cli.flags['repoDescription'] || ''),\n homepage: String(cli.flags['homepage'] || ''),\n default_branch: String(cli.flags['defaultBranch'] || ''),\n visibility: String(cli.flags['visibility'] || 'private')\n })\n}\n","// @ts-ignore\nimport chalkTable from 'chalk-table'\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function viewRepo(\n orgSlug: string,\n repoName: string,\n apiToken: string\n): Promise<void> {\n const spinnerText = 'Fetching repository... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getOrgRepo(orgSlug, repoName),\n 'fetching repository'\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('getOrgRepo', result, spinner)\n return\n }\n\n const options = {\n columns: [\n { field: 'id', name: colors.magenta('ID') },\n { field: 'name', name: colors.magenta('Name') },\n { field: 'visibility', name: colors.magenta('Visibility') },\n { field: 'default_branch', name: colors.magenta('Default branch') },\n { field: 'homepage', name: colors.magenta('Homepage') },\n { field: 'archived', name: colors.magenta('Archived') },\n { field: 'created_at', name: colors.magenta('Created at') }\n ]\n }\n\n spinner.stop(chalkTable(options, [result.data]))\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { viewRepo } from './view-repo'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'view',\n description: 'View repositories in an organization',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg\n `\n}\n\nexport const cmdReposView = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const repoName = cli.flags['repoName']\n const [orgSlug = ''] = cli.input\n\n if (!repoName || typeof repoName !== 'string' || !orgSlug) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await viewRepo(orgSlug, repoName, apiToken)\n}\n","import { cmdReposCreate } from './cmd-repos-create'\nimport { cmdReposDel } from './cmd-repos-del'\nimport { cmdReposList } from './cmd-repos-list'\nimport { cmdReposUpdate } from './cmd-repos-update'\nimport { cmdReposView } from './cmd-repos-view'\nimport { meowWithSubcommands } from '../../utils/meow-with-subcommands'\n\nimport type { CliSubcommand } from '../../utils/meow-with-subcommands'\n\nconst description = 'Repositories related commands'\n\nexport const cmdRepos: CliSubcommand = {\n description,\n async run(argv, importMeta, { parentName }) {\n await meowWithSubcommands(\n {\n create: cmdReposCreate,\n view: cmdReposView,\n list: cmdReposList,\n del: cmdReposDel,\n update: cmdReposUpdate\n },\n {\n argv,\n description,\n importMeta,\n name: `${parentName} repos`\n }\n )\n }\n}\n","import process from 'node:process'\nimport readline from 'node:readline/promises'\n\nimport open from 'open'\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function createFullScan({\n apiToken,\n branchName,\n commitHash: _commitHash,\n commitMessage,\n committers: _committers,\n cwd,\n defaultBranch,\n orgSlug,\n packagePaths,\n pendingHead,\n pullRequest: _pullRequest,\n repoName,\n tmp\n}: {\n apiToken: string\n orgSlug: string\n repoName: string\n branchName: string\n committers: string\n commitMessage: string\n commitHash: string\n pullRequest: number | undefined\n defaultBranch: boolean\n pendingHead: boolean\n tmp: boolean\n packagePaths: string[]\n cwd: string\n}): Promise<void> {\n const spinnerText = 'Creating a scan... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.createOrgFullScan(\n orgSlug,\n {\n repo: repoName,\n branch: branchName,\n commit_message: commitMessage,\n make_default_branch: defaultBranch,\n set_as_pending_head: pendingHead,\n tmp\n },\n packagePaths,\n cwd\n ),\n 'Creating scan'\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('CreateOrgFullScan', result, spinner)\n return\n }\n\n spinner.success('Scan created successfully')\n\n const link = colors.underline(colors.cyan(`${result.data.html_report_url}`))\n console.log(`Available at: ${link}`)\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n })\n\n const answer = await rl.question(\n 'Would you like to open it in your browser? (y/n)'\n )\n\n if (answer.toLowerCase() === 'y') {\n await open(`${result.data.html_report_url}`)\n }\n rl.close()\n}\n","import process from 'node:process'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { createFullScan } from './create-full-scan'\nimport { handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getPackageFilesFullScans } from '../../utils/path-resolve'\nimport { getDefaultToken, setupSdk } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'create',\n description: 'Create a scan',\n hidden: false,\n flags: {\n repo: {\n type: 'string',\n shortFlag: 'r',\n default: '',\n description: 'Repository name'\n },\n branch: {\n type: 'string',\n shortFlag: 'b',\n default: '',\n description: 'Branch name'\n },\n commitMessage: {\n type: 'string',\n shortFlag: 'm',\n default: '',\n description: 'Commit message'\n },\n commitHash: {\n type: 'string',\n shortFlag: 'ch',\n default: '',\n description: 'Commit hash'\n },\n cwd: {\n type: 'string',\n description: 'working directory, defaults to process.cwd()'\n },\n dryRun: {\n type: 'boolean',\n description:\n 'run input validation part of command without any concrete side effects'\n },\n pullRequest: {\n type: 'number',\n shortFlag: 'pr',\n description: 'Commit hash'\n },\n committers: {\n type: 'string',\n shortFlag: 'c',\n default: '',\n description: 'Committers'\n },\n defaultBranch: {\n type: 'boolean',\n shortFlag: 'db',\n default: false,\n description: 'Make default branch'\n },\n pendingHead: {\n type: 'boolean',\n shortFlag: 'ph',\n default: false,\n description: 'Set as pending head'\n },\n tmp: {\n type: 'boolean',\n shortFlag: 't',\n default: false,\n description:\n 'Set the visibility (true/false) of the scan in your dashboard'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} [...options] <org> <TARGET> [TARGET...]\n\n Where TARGET is a FILE or DIR that _must_ be inside the CWD.\n\n When a FILE is given only that FILE is targeted. Otherwise any eligible\n files in the given DIR will be considered.\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} --repo=test-repo --branch=main FakeOrg ./package.json\n `\n}\n\nexport const cmdScanCreate = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [orgSlug = '', ...targets] = cli.input\n\n const cwd =\n cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()'\n ? String(cli.flags['cwd'])\n : process.cwd()\n\n // Note exiting earlier to skirt a hidden auth requirement\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const socketSdk = await setupSdk()\n const supportedFiles = await socketSdk\n .getReportSupportedFiles()\n .then(res => {\n if (!res.success)\n handleUnsuccessfulApiResponse(\n 'getReportSupportedFiles',\n res,\n new Spinner()\n )\n // TODO: verify type at runtime? Consider it trusted data and assume type?\n return (res as any).data\n })\n .catch((cause: Error) => {\n throw new Error('Failed getting supported files for report', { cause })\n })\n\n const packagePaths = await getPackageFilesFullScans(\n cwd,\n targets,\n supportedFiles\n )\n\n const { branch: branchName, repo: repoName } = cli.flags\n\n if (!orgSlug || !repoName || !branchName || !packagePaths.length) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - At least one TARGET (e.g. \\`.\\` or \\`./package.json\\`) ${\n !packagePaths.length\n ? colors.red(\n targets.length > 0\n ? '(TARGET' +\n (targets.length ? 's' : '') +\n ' contained no matching/supported files!)'\n : '(missing)'\n )\n : colors.green('(ok)')\n }\\n`)\n return\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await createFullScan({\n apiToken,\n orgSlug,\n repoName: repoName as string,\n branchName: branchName as string,\n commitMessage: (cli.flags['commitMessage'] as string) ?? '',\n defaultBranch: Boolean(cli.flags['defaultBranch']),\n pendingHead: Boolean(cli.flags['pendingHead']),\n tmp: Boolean(cli.flags['tmp']),\n packagePaths,\n cwd,\n commitHash: (cli.flags['commitHash'] as string) ?? '',\n committers: (cli.flags['committers'] as string) ?? '',\n pullRequest: (cli.flags['pullRequest'] as number) ?? undefined\n })\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function deleteOrgFullScan(\n orgSlug: string,\n fullScanId: string,\n apiToken: string\n): Promise<void> {\n const spinnerText = 'Deleting scan...'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.deleteOrgFullScan(orgSlug, fullScanId),\n 'Deleting scan'\n )\n\n if (result.success) {\n spinner.success('Scan deleted successfully')\n } else {\n handleUnsuccessfulApiResponse('deleteOrgFullScan', result, spinner)\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { deleteOrgFullScan } from './delete-full-scan'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'del',\n description: 'Delete a scan',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug> <scan ID>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg 000aaaa1-0000-0a0a-00a0-00a0000000a0\n `\n}\n\nexport const cmdScanDel = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [orgSlug = '', fullScanId = ''] = cli.input\n\n if (!orgSlug || !fullScanId) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Full Scan ID to delete as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}\\n`\n )\n return\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await deleteOrgFullScan(orgSlug, fullScanId, apiToken)\n}\n","// @ts-ignore\nimport chalkTable from 'chalk-table'\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function listFullScans(\n orgSlug: string,\n input: {\n // TODO: what do we actually need for getOrgFullScanList ?\n outputJson: boolean\n outputMarkdown: boolean\n orgSlug: string\n sort: string\n direction: string\n per_page: number\n page: number\n from_time: string\n until_time: string\n },\n apiToken: string\n): Promise<void> {\n const spinnerText = 'Listing scans... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getOrgFullScanList(orgSlug, input),\n 'Listing scans'\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('getOrgFullScanList', result, spinner)\n return\n }\n\n const options = {\n columns: [\n { field: 'id', name: colors.magenta('ID') },\n { field: 'report_url', name: colors.magenta('Scan URL') },\n { field: 'branch', name: colors.magenta('Branch') },\n { field: 'created_at', name: colors.magenta('Created at') }\n ]\n }\n\n const formattedResults = result.data.results.map(d => {\n return {\n id: d.id,\n report_url: colors.underline(`${d.html_report_url}`),\n created_at: d.created_at\n ? new Date(d.created_at).toLocaleDateString('en-us', {\n year: 'numeric',\n month: 'numeric',\n day: 'numeric'\n })\n : '',\n branch: d.branch\n }\n })\n\n spinner.stop(`Listing scans for: ${orgSlug}`)\n console.log(chalkTable(options, formattedResults))\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { listFullScans } from './list-full-scans'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type {\n CliCommandConfig,\n CliSubcommand\n} from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'list',\n description: 'List the full scans for an organization',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n sort: {\n type: 'string',\n shortFlag: 's',\n default: 'created_at',\n description:\n 'Sorting option (`name` or `created_at`) - default is `created_at`'\n },\n direction: {\n type: 'string',\n shortFlag: 'd',\n default: 'desc',\n description: 'Direction option (`desc` or `asc`) - Default is `desc`'\n },\n perPage: {\n type: 'number',\n shortFlag: 'pp',\n default: 30,\n description: 'Results per page - Default is 30'\n },\n page: {\n type: 'number',\n shortFlag: 'p',\n default: 1,\n description: 'Page number - Default is 1'\n },\n fromTime: {\n type: 'string',\n shortFlag: 'f',\n default: '',\n description: 'From time - as a unix timestamp'\n },\n untilTime: {\n type: 'string',\n shortFlag: 'u',\n default: '',\n description: 'Until time - as a unix timestamp'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg\n `\n}\n\nexport const cmdScanList: CliSubcommand = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n) {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const orgSlug = cli.input[0]\n\n if (!orgSlug) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await listFullScans(\n orgSlug,\n // TODO: refine this object to what we need\n {\n outputJson: cli.flags['json'],\n outputMarkdown: cli.flags['markdown'],\n orgSlug,\n sort: cli.flags['sort'],\n direction: cli.flags['direction'],\n per_page: cli.flags['perPage'],\n page: cli.flags['page'],\n from_time: cli.flags['fromTime'],\n until_time: cli.flags['untilTime']\n } as {\n outputJson: boolean\n outputMarkdown: boolean\n orgSlug: string\n sort: string\n direction: string\n per_page: number\n page: number\n from_time: string\n until_time: string\n },\n apiToken\n )\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function getOrgScanMetadata(\n orgSlug: string,\n scanId: string,\n apiToken: string\n): Promise<void> {\n const spinnerText = \"Getting scan's metadata... \\n\"\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getOrgFullScanMetadata(orgSlug, scanId),\n 'Listing scans'\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('getOrgFullScanMetadata', result, spinner)\n return\n }\n\n spinner.stop('Scan metadata:')\n console.log(result.data)\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { getOrgScanMetadata } from './get-full-scan-metadata'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type {\n CliCommandConfig,\n CliSubcommand\n} from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'metadata',\n description: \"Get a full scan's metadata\",\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug> <scan id>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg 000aaaa1-0000-0a0a-00a0-00a0000000a0\n `\n}\n\nexport const cmdScanMetadata: CliSubcommand = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [orgSlug = '', fullScanId = ''] = cli.input\n\n if (!orgSlug || !fullScanId) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Full Scan ID to inspect as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}\\n`\n )\n return\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await getOrgScanMetadata(orgSlug, fullScanId, apiToken)\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nimport type { SocketSdkResultType } from '@socketsecurity/sdk'\n\nexport async function getFullScan(\n orgSlug: string,\n fullScanId: string,\n file: string | undefined,\n apiToken: string\n): Promise<SocketSdkResultType<'getOrgFullScan'>> {\n const spinner = new Spinner({ text: 'Streaming scan...' }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const data = await handleApiCall(\n socketSdk.getOrgFullScan(\n orgSlug,\n fullScanId,\n file === '-' ? undefined : file\n ),\n 'Streaming a scan'\n )\n\n if (data?.success) {\n spinner.stop(file ? `Full scan details written to ${file}` : '')\n } else {\n handleUnsuccessfulApiResponse('getOrgFullScan', data, spinner)\n }\n\n return data\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { getFullScan } from './get-full-scan'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type {\n CliCommandConfig,\n CliSubcommand\n} from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'stream',\n description: 'Stream the output of a scan',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug> <scan ID> [path to output file]\n\n When no output path is given the contents is sent to stdout.\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg 000aaaa1-0000-0a0a-00a0-00a0000000a0 ./stream.txt\n `\n}\n\nexport const cmdScanStream: CliSubcommand = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [orgSlug = '', fullScanId = '', file = '-'] = cli.input\n\n if (!orgSlug || !fullScanId) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Full Scan ID to fetch as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}\\n`\n )\n return\n }\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await getFullScan(orgSlug, fullScanId, file, apiToken)\n}\n","import { cmdScanCreate } from './cmd-scan-create'\nimport { cmdScanDel } from './cmd-scan-del'\nimport { cmdScanList } from './cmd-scan-list'\nimport { cmdScanMetadata } from './cmd-scan-metadata'\nimport { cmdScanStream } from './cmd-scan-stream'\nimport { meowWithSubcommands } from '../../utils/meow-with-subcommands'\n\nimport type { CliSubcommand } from '../../utils/meow-with-subcommands'\n\nconst description = 'Scans related commands'\n\nexport const cmdScan: CliSubcommand = {\n description,\n async run(argv, importMeta, { parentName }) {\n await meowWithSubcommands(\n {\n create: cmdScanCreate,\n stream: cmdScanStream,\n list: cmdScanList,\n del: cmdScanDel,\n metadata: cmdScanMetadata\n },\n {\n argv,\n description,\n importMeta,\n name: parentName + ' scan'\n }\n )\n }\n}\n","import process from 'node:process'\n\n// @ts-ignore\nimport ScreenWidget from 'blessed/lib/widgets/screen'\n// @ts-ignore\nimport TableWidget from 'blessed-contrib/lib/widget/table'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { queryAPI } from '../../utils/api'\n\ntype ThreatResult = {\n createdAt: string\n description: string\n id: number\n locationHtmlUrl: string\n packageHtmlUrl: string\n purl: string\n removedAt: string\n threatType: string\n}\n\nexport async function getThreatFeed({\n apiToken,\n direction,\n filter,\n outputJson,\n page,\n perPage\n}: {\n apiToken: string\n outputJson: boolean\n perPage: number\n page: string\n direction: string\n filter: string\n}): Promise<void> {\n const spinner = new Spinner({\n text: 'Looking up the threat feed'\n }).start()\n\n const formattedQueryParams = formatQueryParams({\n per_page: perPage,\n page,\n direction,\n filter\n }).join('&')\n const response = await queryAPI(\n `threat-feed?${formattedQueryParams}`,\n apiToken\n )\n const data = <{ results: ThreatResult[]; nextPage: string }>(\n await response.json()\n )\n\n spinner.stop()\n\n if (outputJson) {\n console.log(data)\n return\n }\n\n const screen = new ScreenWidget()\n\n const table = new TableWidget({\n keys: 'true',\n fg: 'white',\n selectedFg: 'white',\n selectedBg: 'magenta',\n interactive: 'true',\n label: 'Threat feed',\n width: '100%',\n height: '100%',\n border: {\n type: 'line',\n fg: 'cyan'\n },\n columnSpacing: 3, //in chars\n columnWidth: [9, 30, 10, 17, 13, 100] /*in chars*/\n })\n\n // allow control the table with the keyboard\n table.focus()\n\n screen.append(table)\n\n const formattedOutput = formatResults(data.results)\n\n table.setData({\n headers: [\n 'Ecosystem',\n 'Name',\n 'Version',\n 'Threat type',\n 'Detected at',\n 'Details'\n ],\n data: formattedOutput\n })\n\n screen.render()\n\n screen.key(['escape', 'q', 'C-c'], () => process.exit(0))\n}\n\nfunction formatResults(data: ThreatResult[]) {\n return data.map(d => {\n const ecosystem = d.purl.split('pkg:')[1]!.split('/')[0]!\n const name = d.purl.split('/')[1]!.split('@')[0]!\n const version = d.purl.split('@')[1]!\n\n const timeStart = new Date(d.createdAt).getMilliseconds()\n const timeEnd = Date.now()\n\n const diff = getHourDiff(timeStart, timeEnd)\n const hourDiff =\n diff > 0\n ? `${diff} hours ago`\n : `${getMinDiff(timeStart, timeEnd)} minutes ago`\n\n return [\n ecosystem,\n decodeURIComponent(name),\n version,\n d.threatType,\n hourDiff,\n d.locationHtmlUrl\n ]\n })\n}\n\nfunction formatQueryParams(params: object) {\n return Object.entries(params).map(entry => `${entry[0]}=${entry[1]}`)\n}\n\nfunction getHourDiff(start: number, end: number) {\n return Math.floor((end - start) / 3600000)\n}\n\nfunction getMinDiff(start: number, end: number) {\n return Math.floor((end - start) / 60000)\n}\n","import { getThreatFeed } from './get-threat-feed'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'threat-feed',\n description: 'Look up the threat feed',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n perPage: {\n type: 'number',\n shortFlag: 'pp',\n default: 30,\n description: 'Number of items per page'\n },\n page: {\n type: 'string',\n shortFlag: 'p',\n default: '1',\n description: 'Page token'\n },\n direction: {\n type: 'string',\n shortFlag: 'd',\n default: 'desc',\n description: 'Order asc or desc by the createdAt attribute.'\n },\n filter: {\n type: 'string',\n shortFlag: 'f',\n default: 'mal',\n description: 'Filter what type of threats to return'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command}\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command}\n $ ${command} --perPage=5 --page=2 --direction=asc --filter=joke\n `\n}\n\nexport const cmdThreatFeed = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: ReadonlyArray<string>,\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await getThreatFeed({\n apiToken,\n direction: String(cli.flags['direction'] || 'desc'),\n filter: String(cli.flags['filter'] || 'mal'),\n outputJson: Boolean(cli.flags['json']),\n page: String(cli.flags['filter'] || '1'),\n perPage: Number(cli.flags['per_page'] || 0)\n })\n}\n","import fs from 'node:fs'\n\nexport function addSocketWrapper(file: string): void {\n return fs.appendFile(\n file,\n 'alias npm=\"socket npm\"\\nalias npx=\"socket npx\"\\n',\n err => {\n if (err) {\n return new Error(`There was an error setting up the alias: ${err}`)\n }\n // TODO: pretty sure you need to source the file or restart\n // any terminal session before changes are reflected.\n console.log(`\nThe alias was added to ${file}. Running 'npm install' will now be wrapped in Socket's \"safe npm\" 🎉\nIf you want to disable it at any time, run \\`socket wrapper --disable\\`\n`)\n }\n )\n}\n","import fs from 'node:fs'\n\nexport function checkSocketWrapperSetup(file: string): boolean {\n const fileContent = fs.readFileSync(file, 'utf8')\n const linesWithSocketAlias = fileContent\n .split('\\n')\n .filter(\n l => l === 'alias npm=\"socket npm\"' || l === 'alias npx=\"socket npx\"'\n )\n\n if (linesWithSocketAlias.length) {\n console.log(\n `The Socket npm/npx wrapper is set up in your bash profile (${file}).`\n )\n return true\n }\n return false\n}\n","import { existsSync } from 'node:fs'\nimport process from 'node:process'\nimport readline from 'node:readline'\n\nimport { addSocketWrapper } from './add-socket-wrapper'\nimport { checkSocketWrapperSetup } from './check-socket-wrapper-setup'\nimport constants from '../../constants'\n\nexport function postinstallWrapper() {\n // Lazily access constants.bashRcPath and constants.zshRcPath.\n const { bashRcPath, zshRcPath } = constants\n const socketWrapperEnabled =\n (existsSync(bashRcPath) && checkSocketWrapperSetup(bashRcPath)) ||\n (existsSync(zshRcPath) && checkSocketWrapperSetup(zshRcPath))\n\n if (!socketWrapperEnabled) {\n installSafeNpm(`The Socket CLI is now successfully installed! 🎉\n\n To better protect yourself against supply-chain attacks, our \"safe npm\" wrapper can warn you about malicious packages whenever you run 'npm install'.\n\n Do you want to install \"safe npm\" (this will create an alias to the socket-npm command)? (y/n)`)\n }\n}\n\nfunction installSafeNpm(query: string): void {\n console.log(`\n _____ _ _\n| __|___ ___| |_ ___| |_\n|__ | . | _| '_| -_| _|\n|_____|___|___|_,_|___|_|\n\n`)\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n })\n return askQuestion(rl, query)\n}\n\nfunction askQuestion(rl: readline.Interface, query: string): void {\n rl.question(query, (ans: string) => {\n if (ans.toLowerCase() === 'y') {\n // Lazily access constants.bashRcPath and constants.zshRcPath.\n const { bashRcPath, zshRcPath } = constants\n try {\n if (existsSync(bashRcPath)) {\n addSocketWrapper(bashRcPath)\n }\n if (existsSync(zshRcPath)) {\n addSocketWrapper(zshRcPath)\n }\n } catch (e) {\n throw new Error(`There was an issue setting up the alias: ${e}`)\n }\n rl.close()\n } else if (ans.toLowerCase() !== 'n') {\n askQuestion(\n rl,\n 'Incorrect input: please enter either y (yes) or n (no): '\n )\n } else {\n rl.close()\n }\n })\n}\n","import fs from 'node:fs'\n\nexport function removeSocketWrapper(file: string): void {\n return fs.readFile(file, 'utf8', function (err, data) {\n if (err) {\n console.error(`There was an error removing the alias: ${err}`)\n return\n }\n const linesWithoutSocketAlias = data\n .split('\\n')\n .filter(\n l => l !== 'alias npm=\"socket npm\"' && l !== 'alias npx=\"socket npx\"'\n )\n\n const updatedFileContent = linesWithoutSocketAlias.join('\\n')\n\n fs.writeFile(file, updatedFileContent, function (err) {\n if (err) {\n console.log(err)\n return\n } else {\n // TODO: pretty sure you need to source the file or restart\n // any terminal session before changes are reflected.\n console.log(\n `\\nThe alias was removed from ${file}. Running 'npm install' will now run the standard npm command.\\n`\n )\n }\n })\n })\n}\n","import { existsSync } from 'node:fs'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { addSocketWrapper } from './add-socket-wrapper'\nimport { checkSocketWrapperSetup } from './check-socket-wrapper-setup'\nimport { postinstallWrapper } from './postinstall-wrapper'\nimport { removeSocketWrapper } from './remove-socket-wrapper'\nimport constants from '../../constants'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'wrapper',\n description: 'Enable or disable the Socket npm/npx wrapper',\n hidden: false,\n flags: {\n ...commonFlags,\n enable: {\n type: 'boolean',\n default: false,\n description: 'Enables the Socket npm/npx wrapper'\n },\n disable: {\n type: 'boolean',\n default: false,\n description: 'Disables the Socket npm/npx wrapper'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} <flag>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} --enable\n $ ${command} --disable\n `\n}\n\nexport const cmdWrapper = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: ReadonlyArray<string>,\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n // I don't think meow would mess with this but ...\n if (argv[0] === '--postinstall') {\n postinstallWrapper()\n return\n }\n\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const { enable } = cli.flags\n if (!enable && !cli.flags['disable']) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required flags:\\n\n - Must use --enabled or --disabled\\n`)\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n // Lazily access constants.bashRcPath and constants.zshRcPath.\n const { bashRcPath, zshRcPath } = constants\n if (enable) {\n if (existsSync(bashRcPath) && !checkSocketWrapperSetup(bashRcPath)) {\n addSocketWrapper(bashRcPath)\n }\n if (existsSync(zshRcPath) && !checkSocketWrapperSetup(zshRcPath)) {\n addSocketWrapper(zshRcPath)\n }\n } else {\n if (existsSync(bashRcPath)) {\n removeSocketWrapper(bashRcPath)\n }\n if (existsSync(zshRcPath)) {\n removeSocketWrapper(zshRcPath)\n }\n }\n if (!existsSync(bashRcPath) && !existsSync(zshRcPath)) {\n console.error(\n 'There was an issue setting up the alias in your bash profile'\n )\n }\n}\n","#!/usr/bin/env node\n\nimport process from 'node:process'\nimport { pathToFileURL } from 'node:url'\n\nimport { messageWithCauses, stackWithCauses } from 'pony-cause'\nimport updateNotifier from 'tiny-updater'\nimport colors from 'yoctocolors-cjs'\n\nimport { cmdAction } from './commands/action/cmd-action'\nimport { cmdAnalytics } from './commands/analytics/cmd-analytics'\nimport { cmdAuditLog } from './commands/audit-log/cmd-audit-log'\nimport { cmdCdxgen } from './commands/cdxgen/cmd-cdxgen'\nimport { cmdScanCreate } from './commands/dependencies/cmd-dependencies'\nimport { cmdDiffScan } from './commands/diff-scan/cmd-diff-scan'\nimport { cmdFix } from './commands/fix/cmd-fix'\nimport { cmdInfo } from './commands/info/cmd-info'\nimport { cmdLogin } from './commands/login/cmd-login'\nimport { cmdLogout } from './commands/logout/cmd-logout'\nimport { cmdManifest } from './commands/manifest/cmd-manifest'\nimport { cmdNpm } from './commands/npm/cmd-npm'\nimport { cmdNpx } from './commands/npx/cmd-npx'\nimport { cmdOops } from './commands/oops/cmd-oops'\nimport { cmdOptimize } from './commands/optimize/cmd-optimize'\nimport { cmdOrganizations } from './commands/organizations/cmd-organizations'\nimport { cmdRawNpm } from './commands/raw-npm/cmd-raw-npm'\nimport { cmdRawNpx } from './commands/raw-npx/cmd-raw-npx'\nimport { cmdReport } from './commands/report/cmd-report'\nimport { cmdRepos } from './commands/repos/cmd-repos'\nimport { cmdScan } from './commands/scan/cmd-scan'\nimport { cmdThreatFeed } from './commands/threat-feed/cmd-threat-feed'\nimport { cmdWrapper } from './commands/wrapper/cmd-wrapper'\nimport constants from './constants'\nimport { AuthError, InputError, captureException } from './utils/errors'\nimport { getLogSymbols } from './utils/logging'\nimport { meowWithSubcommands } from './utils/meow-with-subcommands'\n\nconst { SOCKET, rootPkgJsonPath } = constants\n\n// TODO: Add autocompletion using https://socket.dev/npm/package/omelette\nvoid (async () => {\n await updateNotifier({\n name: SOCKET,\n version: require(rootPkgJsonPath).version,\n ttl: 86_400_000 /* 24 hours in milliseconds */\n })\n\n try {\n await meowWithSubcommands(\n {\n action: cmdAction,\n cdxgen: cmdCdxgen,\n fix: cmdFix,\n info: cmdInfo,\n login: cmdLogin,\n logout: cmdLogout,\n npm: cmdNpm,\n npx: cmdNpx,\n oops: cmdOops,\n optimize: cmdOptimize,\n organization: cmdOrganizations,\n 'raw-npm': cmdRawNpm,\n 'raw-npx': cmdRawNpx,\n report: cmdReport,\n wrapper: cmdWrapper,\n scan: cmdScan,\n 'audit-log': cmdAuditLog,\n repos: cmdRepos,\n dependencies: cmdScanCreate,\n analytics: cmdAnalytics,\n 'diff-scan': cmdDiffScan,\n 'threat-feed': cmdThreatFeed,\n manifest: cmdManifest\n },\n {\n aliases: {\n ci: {\n description: 'Alias for \"report create --view --strict\"',\n argv: ['report', 'create', '--view', '--strict']\n }\n },\n argv: process.argv.slice(2),\n name: SOCKET,\n importMeta: { url: `${pathToFileURL(__filename)}` } as ImportMeta\n }\n )\n } catch (e: any) {\n process.exitCode = 1\n let errorBody: string | undefined\n let errorTitle: string\n let errorMessage = ''\n if (e instanceof AuthError) {\n errorTitle = 'Authentication error'\n errorMessage = e.message\n } else if (e instanceof InputError) {\n errorTitle = 'Invalid input'\n errorMessage = e.message\n errorBody = e.body\n } else if (e instanceof Error) {\n errorTitle = 'Unexpected error'\n errorMessage = messageWithCauses(e)\n errorBody = stackWithCauses(e)\n } else {\n errorTitle = 'Unexpected error with no details'\n }\n console.error(\n `${getLogSymbols().error} ${colors.bgRed(colors.white(errorTitle + ':'))} ${errorMessage}`\n )\n if (errorBody) {\n console.error(`\\n${errorBody}`)\n }\n await captureException(e)\n }\n})()\n"],"names":["id","body","body_list","newPackages","removedPackages","newAlerts","sbom","reportUrl","diffUrl","created_at","updated_at","organizationId","repositoryId","branch","commit_message","commit_hash","pull_request","sbom_artifacts","constructor","pkg_type","pkg_name","pkg_version","category","type","severity","pkg_id","key","error","warn","ignore","monitor","description","title","emoji","next_step_title","suggestion","introduced_by","manifests","url","purl","arr","name","version","release","direct","manifestFiles","author","size","alerts","topLevelAncestors","transitives","license","license_text","supplyChain","quality","overall","vulnerability","critical","high","middle","low","ecosystem","capabilities","author_url","generateAuthorData","socket","fullScanId","data","params","fullScan","getSourceData","pkg","file","createPurl","packages","nextStepTitle","issueAlert","compareIssueAlerts","newScanAlerts","consolidatedAlerts","checkAlertCapabilities","envVars","networkAccess","filesystemAccess","shellAccess","newAlert","compareCapabilities","headPackage","packageId","newScan","diff","consolidated","headScanAlerts","headPackages","getLicenseDetails","package","console","topLevelCount","headFullScanId","headFullScan","headScan","diffReport","comments","security","overview","comment","socketComments","ignoreAll","result","ignoredPackages","line","start","command","ignoreCommands","octokit","checkEventType","commentId","comment_id","content","securityComment","rows","md","removedLine","sources","nextSteps","mdTable","changedFiles","newSecurityComment","newOverviewComment","keyPrefix","padName","help","default","shortFlag","dryRun","json","markdown","all","strict","SOCKET_CLI_SHOW_BANNER","__proto__","parentName","hidden","allowUnknownFlags","process","commandName","flags","githubEventBefore","githubEventAfter","run","API_V0_URL","spinner","cause","method","headers","time","text","cols","screen","label","barWidth","barSpacing","xOffset","maxHeight","barBgColor","handleUnsuccessfulApiResponse","formattedData","totalTopAlerts","formatted","sortedTopFiveAlerts","top_five_alert_types","style","baseline","xLabelPadding","xPadding","wholeNumbersOnly","legend","width","x","y","scope","repo","per_page","year","month","day","choices","pageSize","perPage","page","SBOM_SIGN_PUBLIC_KEY","synpBinPath","cleanupPackageLock","env","NODE_ENV","stdio","configuration","coerce","filter","only","profile","standard","lifecycle","alias","array","boolean","argv","length","outputJson","offset","columns","field","limit","fs","err","showHidden","depth","colors","before","after","preview","get","NPM","editable","path","consolidate","includeExisting","includeUnfixable","vulnerableVersionRange","editablePkgJson","arb2","value","severityCount","Maintenance","Quality","Vulnerabilities","Object","formatPackageIssuesDetails","fallbackToUrl","count","acc","updateSetting","SOCKET_PUBLIC_API_TOKEN","message","apiBaseUrl","apiProxy","enforcedOrgs","applyLogout","attemptLogout","bin","cwd","gradleOpts","out","stdout","task","verbose","poms","sbtOpts","subArgs","meow","importMeta","auto","scala","gradle","kotlin","aliases","yolo","SHADOW_BIN","NPX","YARN_CLASSIC","nothrow","onUnknown","agent","agentVersion","browser","node","lockSrc","lockBasename","lockPath","pkgJson","supported","targets","YARN_BERRY","pkgPath","peerDependencies","overrides","PNPM","workspacePatterns","pkgs","pkgid","names","isPlacingHigher","insertIndex","entries","updatePkgJson","abortSignal","ipc","args","signal","rootPath","added","addedInWorkspaces","updated","updatedInWorkspaces","warnedPnpmWorkspaceRequiresNpm","npmExecPath","overridesDataObjects","depAliasMap","thisSpec","depObj","state","newSpec","absolute","pin","prod","debugLog","basePath","formatReportDataOutput","view","create","visibility","repoName","repoDescription","homepage","defaultBranch","apiToken","sort","direction","list","del","update","commitHash","committers","pullRequest","tmp","make_default_branch","set_as_pending_head","commitMessage","pendingHead","branchName","fromTime","untilTime","outputMarkdown","from_time","until_time","stream","metadata","keys","fg","selectedFg","selectedBg","interactive","height","border","columnSpacing","columnWidth","zshRcPath","installSafeNpm","rl","askQuestion","enable","disable","postinstallWrapper","rootPkgJsonPath","action","cdxgen","fix","info","login","logout","npm","npx","oops","optimize","organization","report","wrapper","scan","repos","dependencies","analytics","manifest","ci","errorTitle","errorMessage","errorBody"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AAqBO;AACLA;AACAC;AACAC;;;;;AAMA;AACF;AAEO;AACLC;;AAEAC;AACAC;AACAL;AACAM;;AAEAC;AACAC;AACF;AAEO;AACLR;AACAS;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;;AAGAC;;;;;;;;;;;;AAYA;AACF;AAEO;AACLC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;;AAEAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;;;;;;;;;;;;;;;;;;;;AA0CI;AACE;AACAC;AACF;;AAEF;AACF;AACF;AAEO;AACLjB;AACAkB;AACAC;AACAC;AACA3C;AACA4C;AACAC;AACAC;AACAC;;AAGAC;;AAEAC;AACAX;AACAY;AACAC;AACAC;AACAb;;;;;;;;;;;;;AA6BE;;AAGIc;AACAC;AACAH;AACAI;AACAC;AACF;;AAGAC;AACAC;AACAC;AACAC;;AAEF;AACF;AACF;AAEO;AACL5D;AACAyC;AACAC;AACAmB;AACAjB;AACAE;AACAC;AACAG;AACAd;AACA0B;AACA;AACAC;AACAzB;AACAC;;;;;;;;;;;;;AA2BE;AACF;AAEQyB;;AAEN;AACE;;AAEF;AACA;AACF;AACF;AAEO;AACLX;AACAC;AACAH;AACAI;AACAC;;;;;;;AAQA;AACF;;AC1RA;AACA;AAaO;;AAULtC;;;AAGE+C;AACiD;;;;;AAKnD;AAEA;AACEC;AAGF;AACE;AAKA;AACE;AACF;;AAEQC;AAAgC;;;AAOxC;AAEA;AACF;AAEA;AACEC;AAGF;;AAGI;AACA;AACA;;;AAAiD;AAInD;;AAEA;;AAEQpE;;;;AAGNqE;AAAmDH;AAAW;AAChE;AACA;AACF;AAEAI;;AAEEC;AAIF;;;;AAI6CC;AAAK;;AAGhD;AACE;AACE;;AAGE;AACF;AAEA;;AAEUA;AAAK;;AAIjB;AACF;AAEA;AACF;AAEAC;;AAEEC;AAIF;AACE;AACA;;AAA+CA;AAAS;AACxD;;;;;;AAMEtC;;;;;;AAMF;;;AACemC;;AACjB;AAEA;;;AAGEA;AAKF;;AAKE;AACE;;;;;;AAQExC;AACAC;AACAG;AACAwC;AACF;AAEA;;AAA+CD;AAAS;AAExD;;;;;;;;;;;;AAYExC;AACAE;;;AAGAT;AACAE;AACAD;AACAE;AACF;AAEA;;;AAGI8C;AACF;AACF;AAEA;AACE;;AAEA;;AAEA;AACF;AACF;AAEA;AACF;AAEAC;;;AAGEC;AAKF;AACE;AAEA;AACE;AACE;AAEA;AACE;AAEA;AACE;AACE9B;AACA+B;AACF;AACF;AACF;AACF;AACE;AACA;AAEA;AACE;AACA;AAIE;AACE/B;AACA+B;AACF;AACF;AACF;AACF;AACF;AAEA;AACF;AAEAC;;;;AAIET;AAMF;AACE;AACEU;AACAC;AACAC;AACAC;;AAGF;;AAEE;AACEC;AACF;AACA;AACE;AACA;AACEvB;AACF;;AAEIA;AACF;AACF;AACF;AACF;AAEA;AACF;AAEAwB;;AAEEnF;AAIF;;AAGE;AACE;;AAGE;AACA;;AAEI2D;;;;AAIEyB;AACF;AACF;AACF;AACF;AACEzB;;;AAGE0B;AACF;AACF;AACF;AAEA;AACF;;;AAKE;AACE;;AAGE;;AAEErF;AACF;AACF;AACEA;AACF;AACF;;AAGA;AACF;AAEA;;AAEEsF;AAIF;AACE;AACA;AACA;;;AAIA;AAEA;;;AACelD;AAAK;;AAEhBmC;AACF;AACA;AAEA;AAKEgB;AACAC;AACF;AAEAb;;AAEE9B;AACA0B;AACF;AACF;AAEA;;;AACenC;AAAK;;AAEhBmC;AACF;;AAGEgB;AACF;AAEAE;;AAEE5C;AACA0B;AACF;AACF;AAEAgB;;;;AAIA;AACAA;;AAEEG;AACF;AACAH;AAEA;AACF;;;;;;;;;;;;;;;;AAqBM;AAEN;AAEAI;AAAoBC;AAAmC;;AAOrD;;;AAGA;AACA;AACF;;;;AAQE;AACE;;;;;;;;;;;;;;AAcA;AAEA;AACEC;AACF;AACEzB;AAA+BwB;AAAa;AAC5CrB;;AAGE;AACEuB;AACF;AACEA;AACF;AACF;AACF;AACF;;AAGE;AACE;AACA;;AAEA;AACF;AACF;AAEA;AACF;AAEA;AACE7B;AAMF;;;;AAKI;;AAKE8B;;AAEEC;AAAwCjC;AAA2B;AACrE;AACF;;AAEA8B;AACF;AAEA;AAAgD5B;AAAO;;AAGvD;;AAEEgC;AACF;AACAC;;AAGAA;AACAA;;AAEEA;AACF;AACEA;AACF;AAEA;AACF;AACF;;AC/iBA;;AASO;AACLC;AAGF;AACE;AAKEC;AACAC;AACA3E;;AAGF;AACE;;;;;AAMA;AACE;AACA;AACA;AACA;AACA4E;AAKAC;AACF;AACF;AAEA;AACF;;AAEA;AACA;AACA;AACO;AACL;AAAiBhC;AAA0BiC;;AAC3C;;;AAGE;AACF;;AAEE;AACE;AACAC;AACF;AACA;AACF;AACA;AACF;;AAEA;AACO;AACL/E;AACA0E;AAC2C;;;;;AAM3C;AACE;;AAIEI;AACA;AACF;AACAE;AACF;;AAEA;AACA;AACA;AACEC;AAEA;AACEC;AACAH;;AAIA;AACA;AAMA;AACA;;AAGA;;;;AAMA;;AAEA;AACE/E;AACF;;AAEI;AAIEA;AACA;AACF;AACF;AACF;AAEA;AACE;AACF;AACA+E;;AAEAG;AACAH;AACF;AACEA;AACF;AACF;AAEA;AACF;AAEO;AAA4BN;AAAuC;;;AAIxE;AACE;;;;;AAKIU;;AAEEL;AACF;AACEK;;AAEA;AACAC;AACF;;AAEAjB;AACAA;AACF;AACF;AACF;;;AACoBiB;;AACtB;AAEO;;AAEL5G;AAIF;;AAGE;AACE;AACF;;;AAEmB4G;;AACjBX;AACF;AAEA;AACE;AACE;AACF;;;AAGE;AACA;AACEN;AACF;AACEA;AAGAhD;AACF;AACF;AACF;AAEA;AACF;;ACpNA;AACA;AAMO;AACLkE;AAKAhG;;AAIE;;;;;AAOF;AAEAiG;AACE;AACE;AACE;AACF;AACE;AACA;AACA;AACA;AACA;AACA;AACA;;AAEE;AACF;;AAEE;AACF;AACEnB;;AAEF;AACF;AACE;AACF;;AAIF;AACF;;;AAGU7B;;;;;AAKN;;AAEF;;;AAGIlE;;AAEF;AACF;;AAC4CqG;AAAS;AACvD;AAEA;AACEc;AAGF;;AACUjD;;;;AAGNkD;AACF;;AAEF;AAEA;AAAqBD;AAAiC;AACpD;;;AAGEC;AACAC;AACF;AACF;AAEA;AACEhB;AAGF;AACE;AACE;;;;;AAMwD;AACxD;AACF;AACF;AAEA;;AAA4BtG;AAAiC;AAC3D;;;AAGEqH;AACApH;AACF;AACF;AAEA;AACEqG;AAGF;AACE;;AAEE;;;AAGA;;AACkCA;AAAS;;;AACMrG;AAAc;AACjE;AACF;AAEA;AAAoBA;AAAuB;AACzC;;;;AAIEA;AACF;AACF;AAEA;;;;;AAKEsH;AAOF;;AAEIf;AACAD;AACF;AACA;AACEP;;AAEEA;;AAEE/F;;AAEF;AACF;AACE+F;;AACyB/F;AAAsB;AACjD;AACF;AACA;AACE+F;;AAEEA;;AAEE/F;;AAEF;AACF;AACE+F;;AACyB/F;AAAsB;AACjD;AACF;AACF;AACF;;AC/LA;;AAyBO;;AAEL;AACF;AAEO;AACL;;AASA;AACE;;;AAUAuH;AACF;;;AAIAC;AACA;;AAEA;AAEA;AACF;AAEO;AACL;AACA;AACE;AACAC;AACF;AACA;AACF;AAEO;;AAELD;AACAA;AACAA;AAEAA;AACA;AACEA;AACF;AACA;AACF;AAEO;;;;AAIH;AACA;AACA;AACEE;AACF;AACA;AACEtF;AACF;AACF;AACA;AACA;AACA;AACA;AACA;AACF;AAEO;AAKL;;;;AAWA;AACE;AACEuF;AACF;AACA;AACA;AACEX;AACF;;;;;AAKA;;AAEA;AACA;AACA;AACEO;AACF;AACF;;;AAIAC;AACA;;AAEA;;;;AAEoCI;;AACtC;AAEO;;AAEL;AACE;AACAJ;;AAEA;;AAEA;AACAA;AACF;AACA;AACF;AAEO;;AAELA;AACAA;AACAA;AAEAA;AACA;AACF;AAEO;;AAELA;AACAA;AACAA;AAEAA;AACA;AACF;AAEO;;AAELA;AACAA;AACAA;AAEAA;AACA;;AAEA;AACAA;AACAA;AACA;AACF;AAEO;;AAELA;AACAA;AACAA;AAEAA;AAEAA;;;;AACiCG;AAAU;AAC3CH;AACAA;AACAA;;;AAGAA;AACA;AACF;;AC3NA;;;AAaA;AACO;AAIL;;AAGA;AACA;;AAQcK;AAAa;AAC3B;;AAMA;AAEA;AAEA;AACE9B;AACA;;AACgCM;AAAS;;AAEzCN;AACA;;;;AAAiE/B;AAAO;;AAExE;AACAyB;;;AAGA;AACA;AACA;;;AAGA;AACA;AACA;;AAEIqC;AACA/B;AACF;AACEA;AACF;AACF;AACA;;AAEIgC;AACAhC;AAGF;AACEA;AACF;AACF;;;;;;AAMEgC;AACF;AACF;AACF;;AC/EO;AAGHC;AAAkBC;AAAQ;AAE5B;;;;AAKeA;AAAQ;AAEzB;AAEO;AAGHD;AAAgBC;AAAa;;;AAI/B;AACE;AACA;;AASF;AACA;AACF;;ACvCA;;AAMA;;AAGO;AACLC;AACE5G;AACA6G;AACAC;AACAtG;;AAEFuG;AACE/G;AACA6G;AACArG;AACF;AACF;AAEO;AACLwG;AACEhH;AACA8G;AACAD;AACArG;;AAEFyG;AACEjH;AACA8G;AACAD;AACArG;AACF;AACF;AAEO;AACL0G;AACElH;AACA6G;AACArG;;AAEF2G;AACEnH;AACA6G;AACArG;AACF;AACF;;ACvCA;AAAQ4G;AAAuB;AAiDxB;;;;;;;AAUL;AAAMC;;;AACN;AACA;AACA;AACE;AACA;;AAIA;;AAEA;AACA;;AAEIC;AACF;AACF;AACF;AACA;AACE;AACA;;AAEF;;AAEA;AACA;AACA;AACE7C;AACF;;AAGF;AACA;;AAEA;AACA;AAEU;AAGS;AAAc;AAIvB;AAEsC;AAAS;;AACjC8C;AAAO;;;AAGf;AACF;;;AAOd;AACA;;AAEA;AACA;AACA;;;AAIM;;;AAGF;AAEF;AACE9C;;AAEF;;AAEA;AACF;;AAEA;AACA;AACA;AACO;;AACc;;;;AAInB6C;AAOF;;AAGE;AACA;AACA;AACE7C;AACF;AACA;;;;;;;AAOE+C;;AAEF;AACA;;AAEA;AACA;AACF;AAEA;AAIE;AAGIC;;AAEJ;;AAIA;AAKA;AACF;AACA;AACA;AACA;;AAEA;;ACtNA;;AAQA;AACEC;AACAlH;AAAsC;AACtC+G;AACAI;AACE;AACA;AACA;AACA;AACA;AACA;AACAC;AACE5H;AACA6G;AACArG;;AAEFqH;AACE7H;AACA6G;AACArG;AACF;;;AAEgBmH;AAAM;AAC1B;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLG;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;AACA;AAEA;AAEA;AACF;;AClDA;AAAQS;AAAW;AAEZ;AAKL;AACA;;;;AAOE;AACF;AACAC;AAGAP;AACF;AAEO;AAIL;;;;AAIE;AAA2CQ;AAAM;AACnD;AACA;AACF;AAEO;;AAEH;AACF;AACE;AACF;AACF;AAEO;;AAEHC;AACAC;;AAEA;AACF;AACF;;ACrDuC;;AAkBvC;AACO;AAeP;AAeO;;;;;;AAMLC;AAQF;AACE;AAA8BC;AAAgC;AAE9D;;;;;AAKA;AAEA;AACE;AACE5D;;;AAGE;AACAA;;AAEAA;AACF;AACF;AACE;;AAGF;AACF;AACF;AAEA;AACE;AACA;AAAgCwB;AAASqC;AAASC;AAAO;;;;;;;;;AA2DzD;AACEC;AACAC;AACAC;AACAC;AACAC;AACAC;AACF;AAEAN;;;;AAIE3F;AACF;;AAIA2F;AACF;AAEA;AAKE;AACA;AAKA;AACEO;AACA;AACF;;AAIA;AACErE;AACA;AACF;;AAGF;AAEA;AAME;AACA;AAKA;AACEqE;AACA;AACF;;AAIA;AACErE;AACA;AACF;;AAGF;AAEA;;;;AAQE;AACEsE;AACF;;AAEE;AACE;;AAEE;AACA;AACEC;AACF;AACEA;AACF;AACF;AACF;AACA;AACE;AACA;;AAEE;AACEC;AACF;AACEA;AACF;AACF;AACF;AACF;AACE;AACE;;AAEE;AACA;AACED;;AAEAA;AACF;AACF;AACF;AACA;AACE;AACED;AACF;AACF;AACF;;AAGW;AAAK;AAAK;;AAErB;AAAa;AAAQ;;AACnBG;AACF;;AAGE;AACAC;;AAEJ;AACA;;AAEA;AAEA;AAOE;AACEC;AAAS7D;AAAc8C;AAAcgB;;AACrCC;AACAC;AACAZ;AACAa;AACAC;AACEC;;AAEFlB;AACF;AAEAD;AAEA;AACEoB;AACAC;;AAGFrE;AACF;;AClUA;AACEmC;AACAlH;AACA+G;AACAI;AACE;AACA;AACAkC;AACE7J;AACA8G;AACAD;AACArG;;AAGF4H;AACEpI;AACA8G;AACAD;AACArG;;AAEFsJ;AACE9J;AACA8G;AACAD;AACArG;;AAEFyC;AACEjD;AACA8G;AACAD;AACArG;AACF;;;AAEgBmH;AAAM;AAC1B;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AAEO;;;AAGLG;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;;;;AAEqBc;;;AAGrB;AACA;AAEA;AACE;AACA;AACA;;AAEA3D;AACJ;AACA;AACA;AACI;AACF;AAEA;AAEA;;AAEE;AAGF;;;;;AAMEqF;;;AAGF;AACF;;AChGO;;;;;;;AAOL9J;AASF;AACE;;AAEA;AAEA;;;;;;;AAQI+J;AACF;AAIF;AACEjB;AACA;AACF;;;;;;AAQU5J;AAAW;AACnB;AACE;AAAmE8K;AAAiBC;AAAkBC;AAAe;;AAC5FhJ;AAAK;;AAEhC;AACF;AAEAuD;;AAMM0F;AACAC;;AAIR;;ACvEA;AACE1C;AACAlH;AACA+G;AACAI;AACE3H;AACEA;AACA8G;AACAD;AACArG;;AAEF6J;AACErK;AACA8G;AACAD;AACArG;;AAEF8J;AACEtK;AACA8G;AACAD;AACArG;;AAEF;;;AAGFoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;;;AAIE;AACA;AACA;;AAEA7C;AACJ;AACI;AACF;AAEA;AAEA;;AAEE;AAGF;AAEA;;;;;;;AAOEzE;AACF;AACF;;ACvFA;;AACuB;;AACE;AACvBuK;AACF;AAEA;;;;AAAkCC;AAAY;AAE9C;AAWO;;AAEL;AAKE;;AAEA;AACE;AACA;;AAEE;;AAKAC;;AAEJ;AACF;AAEA;AACEC;AACEC;;;AAGAJ;;AAEFK;AACF;AACA;;AAEI;;AAEJ;AACA;AACA;AACEnG;AACF;AACF;AAEA;;;AAKE;AAAa;AAAQ;AAAS;AAC5B;;AAEE;AACA;AACAY;AACF;AACEA;AACF;;;AAGEA;AACF;AACF;AACA;;AAEA;AACA;AACF;;AChGA;AAaA;AACA;AACA;AACA;AACEwF;AACE;AACA;AACA;AACA;AACA;;AAEFC;AACEvJ;AACAwJ;AACAC;AACAC;AACAC;AACAlL;;AAEF6G;AACE;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACAsE;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACAnL;AACA;;AAEFoL;;;;;;;;;AASAC;AACIlL;AAAeH;AAAe;AAC9BG;AAAgBH;AAAe;AAC/BG;AAAeH;AAAe;AAC9BG;AAAaH;AAAe;AAC5BG;AAAiBH;AAAe;AAEpCsL;;AAgCF;AAEA;AACE5D;AACAlH;AACA+G;AACAI;AACE;;AAEFf;AACF;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;AAGnCE;AACA+D;AAAsD;;;AAGtDjE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACE;AACF;;AAEA;;AACQkE;AAAsB;AAC9B;AACE;AACA;AACA;;;AAKA;AACF;AAEA;;AAEA;AAEA;;AAGF;;AC/KA;AAUO;;;AAGLC;AAKF;AACE;;AAEE;AAGF;AACA;AAA8BpD;AAAkC;AAChE;;;AAGwCqD;;AAIxC;AACE5C;AACA;AACF;AAEAd;AAEA;AACEvD;AACA;AACF;AAEA;AACEkH;AACIC;AAAoB1K;AAA+B;AACnD0K;AAAe1K;AAA0B;AACzC0K;AAAkB1K;AAA6B;AAC/C0K;AAAqB1K;AAAgC;AACrD0K;AAAiB1K;AAA4B;AAC7C0K;AAAe1K;AAA0B;AACzC0K;AAAiB1K;;;AAIvBuD;AACF;;ACnDA;AACEiD;AACAlH;AAEA+G;AACAI;AACE;AACAkE;AACE7L;AACA8G;AACAD;AACArG;;AAEFkL;AACE1L;AACA8G;AACAD;AACArG;;;;AAIJoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;;AAEA;AACA;AACEuE;AACAH;;AAEF;AACF;;ACzDO;;;;;AAMHD;AASF;;AAIA;AAA8BpD;AAAkB;AAEhD;AAIA;AAEA;;;AAGE;AACF;;AAIA;AACEyD;AACEC;AAGF;AACA;AACF;AAEA;AACEtH;;AAEuBuH;AAAmBC;AAAaC;AAAa;AAEpEzH;AAGA;AACF;AAEAA;AACAA;AACAA;AAGAA;AAGF;;AC7DA;AACEiD;AACAlH;AACA+G;AACAI;AACE;AACAwE;AACEnM;AACA8G;AACAD;AACArG;;AAEF4L;AACEpM;AACA8G;AACAD;AACArG;;AAEF6L;AACErM;AACA8G;AACAD;AACArG;;AAEFyC;AACEjD;AACA8G;AACAD;AACArG;;;;AAIJoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;AACA;;AAGA;AACE;AACA;AACA;;AAEA7C;AACJ;AACA;AACA;AACI;AACF;AAEA;AAEA;;AAEE;AAGF;AAEA;;;;;;;;;AAYF;;ACzGA;AAEO;;AAEL;AAA8B6C;AAAW;AACvC;AAEIgF;AACF;;;;;AAMA;AAEJ;AACF;;ACFA;;AAIA;AAAQC;AAAI;AAEZ;;AAEA;AAEO;;AAEL;AACA;AAAqDC;AAAe;AACpE;;AAEA;AACEC;;AAEF;AACA;AACA;AACEC;AACAC;AACAC;AACF;AACA;AACA;AACA;AACE;AAAa;AAAS;;AACpB;;AAEA;AACA;AACA;;AAEA;;AAEEnI;;AAEA;AACF;AACA;;AAGM;AACA;AAEN;AACE;AACe+G;;AAIb;AACA;AACeA;;;;AAI0BqB;AAAuB;;AAEtD1L;AAAoB;;;AAUxB;AACA;AAA8ByJ;AAAc;AAC5C5C;;AAEA;;;AASI;AACE;AACE8E;AAEJ;AACF;AACF;AACA;AACA;AACF;;;;AAIA;AACF;;;;AAIA;AACF;AACF;AACF;AACF;AACF;AACA;AAA4BL;AAAU;AACtCM;AACA;;AAEF;;AC9HA;AACErF;AACAlH;AACA+G;AACAI;;;AAGAf;AACF;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;;AAGF;;AC5CO;AACL;AACE;AACE;AACF;AACF;AACA;AACF;AAEO;;AAKL;AACEjC;AACF;AACA;AACF;;AClBO;AAIL;;AACQmG;AAAO;;AAEb;AACF;;;AAGA;AACA;;AAEF;;ACAA;AACA;AAOA;;AAIE;AACEnG;;AAEE;AACF;AACF;AACA;AACF;AAEO;;AAIL;AACE;;AAEA;AACF;;AAEF;AAEO;;AAKDhD;AAAQD;AAAWD;AAASD;AAAY;AAI5C;;AACU8K;AAAM;;AAEZ;AACF;;AAEEC;AACF;AACF;AACA;AACF;;AC3DO;;AAOL;AAIA;AAKA;AACE;AAKF;AAEA;AACE;AAKF;AAEA;;;;;;AAUF;;AC/BA;AAAQV;AAAI;AAEL;;;AACUU;AAA2B;;;;;;AAOxC9F;AAQiB;AAGnB;AACE1C;AACF;AACEA;AACA;AACE;AACAyI;AACAC;AACAC;;;AAGFC;AAGA5I;AACA;AACEuD;AAGAsF;AACF;AACEtF;AACF;;;AAKAvD;;AAEEA;AACwE8I;;AAE1E;AACE9I;AACuF8I;;AAEzF;;;AAOA;AACF;AAEA;AACE9F;AACF;AACF;AAEA;;;;AAaczH;AAAK;AACb;AACE;;AAEIwI;AACAgF;;AAEJ;AACEC;AACF;AACF;AACA;;;;AAOF;AAGIF;AAAoB;;AAGtB9I;AACF;AACEA;AACF;AACF;AACF;AAEA;;AAEI;;AAEA;AACF;AACA;AACF;;AC/HO;;;;;;;AAOL0C;AASF;AACE;AAIA;AAA8BkB;AAAkB;AAChD;AAMA;;AAIMnH;;;;;AAMAiG;;AAIN;AACF;;AChDA;AACEO;AACAlH;AACA+G;AACAI;AACE;AACA;;;AAGFf;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;;;AAKE;AACA;AACA;;AAEA7C;AACJ;AACA;AACI;AACF;AAEA;AACA;AAEA;AAGA;AAEA;AACEiD;;;;;;;AAOF;AACF;;AC7EO;AAMLgG;AACAA;AACAA;AACAA;AACF;;ACMA;;AAUA;AAAQC;AAAwB;AAEzB;AAIL;AAEIC;;AAMJC;AACAC;AAEA;AAA8BzF;AAA6B;AAE3D;;;AAGE;AACA;;AAEA;;AAEAL;AACF;AACEA;AACA;AACF;;;;AAOE;;AAIF;AACE;AACE4F;AAEAzD;AACEjJ;AACA8L;AACAxM;;AAEJ;AACA;;AAEA;AACF;AACE;;AAEEqG;AACF;AACA;AACE;AACA;AACEkH;AACF;AACF;AACF;AAEA;;;;AAIA;AACE/F;AACF;AACF;;AC7FA;AACEN;AACAlH;AACA+G;AACAI;AACE;AACAkG;AACE7N;AACAQ;;AAEFsN;AACE9N;AACAQ;AACF;;AAEFoG;AACF;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;AACA;AAEA;AAEA;AACE;AAGF;AAEA;AACF;;ACpEO;AACLoG;AACAA;AACAA;AACAA;AACF;;ACHO;;AAEHM;AACA;AACF;AACE;AACF;AACF;;ACLA;AACEtG;AACAlH;AACA+G;AACAI;;;AAGAf;AACF;AACA;;AAEA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;AAEA2G;AACF;;AClCO;AAOL;AACA;AACA;;AAEA;AACExJ;AACAA;AACAA;AACA;;AAEF;AACEA;AACAA;AACAA;AACA;;AAEF;AAEA;;;AAOE;AACA;AACA;;AAEA;;;AAIA;;AAEA;;;AAIA;;AAEA;AACEA;AACAA;;AAEF;;AAGEuD;AACA;;AAEEvD;AACAA;;AAEF;AACAgD;AACF;AAEAhD;;AAIIA;AACA;AACF;;AAGF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAMA;AACEA;AACAA;;AAEF;AACAgD;AACF;AACF;;AC9GA;AACEC;AACAlH;AAEA+G;AACAI;AACE;AACAuG;AACElO;AACAQ;;AAEF2N;AACEnO;AACAQ;;AAEF4N;AACEpO;AACA6G;AACArG;;AAGF6N;AACErO;AACA6G;AACArG;;AAGF8N;AACEtO;AACAQ;;AAEF+N;AACEvO;AACA6G;AACArG;;AAEFgO;AACExO;AACAQ;AACF;;AAEFoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;;AAIA;AACE7C;;;;;AAKF;AAEA;;AAEA;;AAEA;AACE;AACA;AACA;;AAEAA;AAEJ;AACA;AAEI;AACF;AAEA;AACA;AACEyJ;AACF;;AAEA;;AAGA;AACEG;AACF;AACA;AACEA;AACF;AAEA;;AAEE5J;AACAA;AACAA;;AAEF;;AAGA;;AAKA;AAEA;;AAGF;;AC7JO;AAOL;AACA;AACA;;AAEA;AACEA;AACAA;AACAA;AACA;;AAEF;AACEA;AACAA;AACAA;AACA;;AAEF;AAEA;;;AAKE;AACA;AACA;;AAEA;;AAEA;;AAEA;AACEA;AACAA;;AAEF;;AAGEuD;AACA;;AAEEvD;AACAA;;AAEF;AACAgD;AACF;;;AAIEgH;AACA;AACF;AAEA;AACEzG;AAGAP;AACF;;AAEA;AACA;AACA;;;AAGEhD;AACAA;;AAEF;;AAMEgK;AACAhK;AACAgD;AACF;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACAO;AACAyG;;AAEF;;;AAMA;AACEhK;AACAA;;AAEF;AACAgD;AACF;AACF;;AC9GA;AACEC;AACAlH;AAEA+G;AACAI;AACE;AACAuG;AACElO;AACA6G;AACArG;;AAEF2N;AACEnO;AACAQ;;AAEF6N;AACErO;AACA6G;AACArG;;AAGF8N;AACEtO;AACAQ;;AAEFkO;AACE1O;AACA6G;AACArG;;AAEFgO;AACExO;AACAQ;AACF;;AAEFoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;AAErC;;;;;AAKEA;AACF;;AAIA;AACE7C;;;;;AAKF;AAEA;;AAEA;;AAEA;AACE;AACA;AACA;;AAEAA;AAEJ;AACA;AAEI;AACF;;AAGA;AACEyJ;AACF;;AAGA;AACEG;AACF;AACA;AACEA;AACF;AAEA;;AAEE5J;AACAA;AACAA;;AAEF;;AAGA;;AAKA;AAEA;;AAGF;;AClJA;AACEiD;AACAlH;AACA+G;AACAI;AACE;AACAwG;AACEnO;AACAQ;;AAEFgO;AACExO;AACA6G;AACArG;AACF;AACA;;AAEFoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;;AAGA;AACA;AACE7C;;;;AAIAA;;AAEF;;AAEA;AACEkK;AACF;;;AAKElK;AAGA;AACEkK;AACF;AACAA;AAEA;AAEA;AAAkDrH;AAAW;AAC7D;AACF;;AAGE7C;AACA;AACE;AACAkK;AACF;AAEA;AAEA;AAAmDrH;AAAW;AAC9D;AACF;;AAEA;AACAsH;AAEF;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AAEMrD;;AAEAsD;AACF;AAEJ;;ACpHA;AACA;AACA;AACA;AACA;AACA;AACEnH;AACAlH;AAEA+G;AACAI;AACE;AACAuG;AACElO;AACAQ;;AAEF2N;AACEnO;AACAQ;;AAEF4N;AACEpO;AACA6G;AACArG;;AAGF6N;AACErO;AACA6G;AACArG;;AAGF8N;AACEtO;AACAQ;;AAEF+N;AACEvO;AACA6G;AACArG;;AAEFgO;AACExO;AACAQ;AACF;;AAEFoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;;AAIA;AACE7C;;;;;AAKF;AAEA;;AAEA;;AAEA;AACE;AACA;AACA;;AAEAA;AAEJ;AACA;AAEI;AACF;AAEA;AACA;AACEyJ;AACF;;AAEA;;AAGA;AACEG;AACF;AACA;AACEA;AACF;AAEA;;AAEE5J;AACAA;AACAA;;AAEF;;AAGA;;AAKA;AAEA;;AAGF;;AChKA;AACEiD;AACAlH;AACA+G;AACAI;;;AA+BK;;;AAGLG;AACF;AAEA;AAGIR;AAAmC;AAErC;AAEIwH;AACAC;AACAC;AACAC;AACF;;AAGEC;AACEC;;AAEE5H;;AAEF;;;;;AAKFrG;AACF;AAEJ;;AC5EA;;AAAakO;AAAW;AAEjB;AACL;;AAEA;AACF;;ACFA;AAAQ7C;AAAI;AAEZ;AACE7E;;AAEAH;;AAEAX;AACF;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;AAGnCE;;;;AAIAF;AACF;AAEA;;AAGF;;ACvCA;;AAAa8H;AAAW;AAEjB;AACL;;AAEA;AACF;;ACFA;AAAQC;AAAI;AAEZ;AACE3H;;AAEAH;;AAEAX;AACF;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;AAGnCE;;;;AAIAF;AACF;AAEA;;AAGF;;ACpCA;AACEI;AACAlH;AACA+G;AACAI;;;AAGAf;AACF;AACA;;AAEA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;AAEA;AACF;;ACnCA;;;;;;AAAyCgI;AAAa;AAEtD;AACE;AACF;AAEA;AACE;AACF;AAEO;AACL;AACAjI;;;;;;AAOA;AACF;;ACLA;;;;;;;;;AASEiI;AACF;AAEO;AAIP;AACEjI;;;;;;AAMA;AACF;AAEA;AACE;AACA;AAA+BkI;;AACjC;AAEA;AAIE;;;AAIM;;AAC6CpB;AAAI;;AAGvD;AACF;;AAEA;AACA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF;AAMA;;;;AAMQ;;AAEF;;AAEJ;AAEA;AAEA;;;AAMI;;AAEE;AACF;;AAEE;AACA;;;;AAIA;AACA;AACA;AACA;AACA;AACF;AACA;AACF;;;;;AAKA;;AAEJ;AAyBO;AACLA;AACAqB;AACa;;AACqCrB;AAAI;;AAEtD;;AAGmCA;AAAI;AACvC;;AAKqC3B;;AAErC;AACA;AACA;AACA;AAIA;AACA;AACA;AACE;AACA;;;;AAIIiD;;AAEF;AACF;AACF;AACA;AAMEA;AACF;;AAEEA;;AAEF;AACA;AAEA;;AAGEC;AACF;AACA;AACED;AACF;AACA;AACEE;AACAC;;AAEF;AACA;AACA;AACA;AACE;;;AAGA;AACA;AACA;AACE;;;AAGA;AACF;AACA;AACA;;AAIE;;;AAMA;;;;;AAKE;AACF;AACF;AACA;;AAIAC;AAIF;AACEC;AACAC;AACF;;;;;;;;;;AAUEC;;AAEAC;AACAC;;AAEJ;;ACpRA;;;;AAAuBC;AAAW;AAElC;AAEA;AAEO;;;;;;;;;;;;AAiCHF;;;;AAIExL;AAGF;AACF;;AAEEA;AAGA;AACF;;;AAKE;AACF;;AAEA;;AAEE;AACF;AACA;;AAEE;AACF;;AAEEA;AACA;AACF;;;AAKE;AACF;AACA;;AAEA;AAEA;AACA;AAAuD;AAAQ;;;;;;;;;;AAa7D2L;;AAEJ;;ACxGO;;;;;AAKHC;AACF;AACA;AAGqBhJ;;;AAIGA;;;AAICA;;;AAKfA;;AAAyC;AAGvC;;AACd;;ACfA;;;;;;;;AAQEiI;AACF;AAEA;;;AAEWtP;AAAkBsQ;;AAC7B;;AAEA;AACA;AACA;;;AAEWtQ;AAAWsQ;;AACtB;;AAEA;AACA;AACA;;;AAEWtQ;AAAYsQ;;AACvB;AAEA;;;AAEWtQ;AAAWsQ;;AACtB;;AAEA;AACA;AACA;;;AAEWtQ;AAAkBsQ;;AAC7B;;AAEA;AACA;AACA;;;AAEWtQ;AAAoBsQ;;AAC/B;AAEO;AACL;AACAjJ;;;;;;AAOA;AACF;;AC7DA;AAAQkJ;AAAK;AAEb;AAEO;AAKL;;;AAMI;;AAEA;;AAEIC;;AAEF;AACE;AACF;AACF;AACF;AACF;AACEA;AACF;AACA;AAKF;AAEA;;AACUhF;AAAO;;AAEb;AACF;AACA;;;AAGA;AACA;AACA;;AAMA;AACA;;AAEF;;ACzDA;;;;;;;AAAmD8D;AAAa;AAEhE;AACE;AACA;AACA;AACF;AAEA;AACE;AACA;AACA;AACA;;AAIA;AACF;AAEA;AACE;AACA;AACE;AACA;AACA;AACA;AACA;;AAIJ;AAEA;AACE;AACA;AACA;AACF;AAEA;AACE;AACA;AACE;AACA;AACA;AACA;AACA;;AAIJ;AAEO;AACL;AACAjI;;;;;;AAOA;AACF;;AC3DA;;;;;;AAAyCiI;AAAa;AAEtD;;AAEI;AACF;AACA;;AAEEmB;;AAEF;AACE;AACF;AACA;AACA;;;AAAwBC;;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEEC;AACF;AACF;AACA;AACF;AAEA;;AAEI;AACF;AACA;AACA;AACA;;AAEA;AACF;AAEA;;;AAGIrC;AAA8DH;;;;AAGlE;AAEA;;AAEI;AACA;AACA;AAA6DA;;;AAE/D;AACF;AAEA;AACE;AACF;AAEA;AAKE;AACA;;AAEE;AACE;AACF;AACF;;;AAGEG;AAIMH;;;;AAKV;AAEA;;;AAGIG;AAEIH;;;;AAKR;AAEA;;AAKI;AACE;AACA;AACA;AAEIA;AACF;AACa;;AAGnB;AACF;AAEA;;AAKI;AACA;AACA;AACA;;AAEmDA;AAAI;;AAGzD;AACF;AAEO;AACL;AACA9G;;;;;;AAOA;AACF;;AC1IA;;;;;;;;AAQEiI;AACF;AAEA;AAEA;AASA;AAIE;AAIF;AAEA;;AAKA;AAEA;AAIE;AACF;AAEA;AAKE;AACA;AACA;AACE;;AAEE;;AAEI;;AAEEgB;AACF;AACF;AACF;AACE;;AAGQ;;AAEEA;AACF;AACF;AACE;AAAmB;AAC7B;;AAEA;;;AAGA;AACF;;AAC2B;AAAe;AAC1C;AACA;AACF;AACA;AAME;AACF;AACA;AACA;AACA;AACA;;;;;AAKE;AACEM;;AAEF;AACF;AACEA;AACAC;AACF;;AAEE;AACED;AACAC;AACF;AACF;AACA;;AAEA;AACA;AACED;AACAC;AACF;AACA;;;AAGEA;AACF;AACAC;;AAIF;AAEA;AAIEC;AACF;AAEA;AAIEA;AACF;AAEA;AAIEA;AACF;AAEO;AACL;AACA1J;;;;;;AAOA;AACF;;AC5KA;;;AAAsC2J;AAAY;AAElD;AACA;AAEO;AAMLhJ;;;AAGI;AACE;;AAEF;AAAuBiJ;AAAI;AAC3B;AACA;AACA;AACA;AACEC;AACAD;AACF;AACF;AACE;AACA;AACEE;AACAvG;AACF;AACF;;;;AAMA;;;AAKAnG;AACF;AACF;;ACaA;;;AAAmB6K;AAAa;AAEhC;AAEO;;;;;;;;;;;;AAiBHc;AACF;AAEA;AAA8B/H;AAA6B;;AAG3D;;;;;;;;;;;AAYI+I;AACF;;AAMF;AACA;;AAEA;;;AAKE;;AAEE3M;AAGF;AACF;AACEA;AACF;AAEA;AACE;AACA;;AAEF;AACF;AAEA;;AAMA;AAEA;;AAEI4M;AACAC;;AAEAC;AACAC;AACAC;;AAEJ;AAEA;;;;;;;;AASIzB;;;AAGAoB;AACkB;;AAIlBtE;AAAmDN;AAAe;AACpE;;AACQxE;AAAQ;;AACRjC;AAAiB;AACzB;AACA;;;AAGA;AACA;;AAOEtB;AAGF;AACA;AAEqDiN;AAAY;AACjE;AACA;AACA;AACA;AACA;AAGA;;AAGA;;AAEA;AACEC;AAIF;AACA;;AAEA;AACA;AACA;AACA;AAAyC;AAAQ;;AACvCzQ;AAAsBsD;AAAsBrD;AAAQ;AAC5D;AACA;AACA;AACA;AAAa;;AACX;AAGA;AACEyQ;AACF;AACA;AAGA;;AAEE;AACA;;AAOEC;AACAC;AACAC;AACA;AACEA;AACF;AACF;AACAH;AACF;AACF;AACA;AACE;AACA;;AAAyD5R;AAAK;AAC5D;;;AAME;AACA;AACA;;AAEA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACAgS;AACF;AACE;AAGA;;;AASI;AACEA;AACF;AACF;AACF;AACEA;AACF;AACF;;AAEE1B;AACA;AACAyB;AACF;AACF;AACF;AACF;AACF;AACA;AACE;AACEE;AACA9D;AACA7N;AACF;AACA;;AAEE;;;;;;;;AASI8P;;AAEAgB;AACF;AAGF;AAeE;AACEW;AACF;AACF;AACF;AACF;AACA;;AAEE;;AAAwB/R;;;AAExB;AACA;AACF;AACA;AACF;;AC7VA;AACE0H;AACAlH;AACA+G;AACAI;AACE;AACAuK;AACElS;AACA6G;AACArG;;AAEF2R;AACEnS;AACA6G;AACArG;AACF;;AAEFoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;AAEA;;AAOF;;AC1DO;AACL;;AAEE;AAGF;AACA;AAA8Be;AAAkC;AAChE;AACA;AAKA;AACES;AACA;AACF;;;AAOA;;AAEF;AACA;AACA;AACA;AACE;AACF;;AClCA;AACEpB;AACAlH;AACA+G;;AAEAX;AACF;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;;AAGF;;AC9BA;AAAQ0J;AAAY;AAEb;AACL;AACEG;AACAvG;AACF;AACA;;;AAGI;AACF;AACA;;AAEA;AACEnD;AACF;AACF;AACA;AACF;;ACnBA;AAAQ8E;AAAI;AAEZ;AACE7E;;AAEAH;;AAEAX;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;AAGnCE;;;;AAIAF;AACF;AAEA;;AAGF;;ACzCA;AAAQ0J;AAAY;AAEb;;AAEHG;AACAvG;AACF;AACA;;;AAGI;AACF;AACA;;AAEA;AACEnD;AACF;AACF;AACA;AACF;;ACnBA;AAAQ4H;AAAI;AAEZ;AACE3H;;AAEAH;;AAEAX;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;AAGnCE;;;;AAIAF;AACF;AAEA;;AAGF;;AClCO;;AAKHP;AAIF;AAEA;AACA;AAGI;;AAOF;AAEE;AACEkB;AACF;AACF;AAEF;AAOAmK;AAKA;;AAEE;AACF;AACE;AACA;AACE/J;AACF;AAEA;;AAOA;AACES;AACA;AACF;;AAEA;AACF;AACF;;ACxEO;;;AAQC;AACA;;AAEEuJ;;;;AAMF;AACA;AASF;AACE;AAAsDpK;AAAM;AAC9D;AACF;AAGF;AACF;;ACxBA;AACA;AAEO;AAKL;AACA;;AAEA;AAEA;;;AAGI;AACA5C;;;AAUE;AACF;AACF;AACF;AAEA;AACE;AACF;;AAEA;;AAEA;AACE;AACE2C;AACF;AACEA;AACF;;AAEA;AAIA;AACAA;AACF;AACEA;AACF;;AAGF;;AChEO;AAQL;AACEvD;AACF;AACE;AACAA;AAE2C8I;AAAoB;;;AAQ/D;AACF;AAEA;AACE9F;AACF;AACF;;ACjCO;;;;;AAOHN;AAOF;;AAGA;AACEmL;AAQF;AACF;;ACjBA;AACE5K;AACAlH;AACA+G;AACAI;AACE;AACA;AACA;AACAZ;AACE/G;AACA6G;AACArG;;AAEF+R;AACEvS;AACA8G;AACAD;AACArG;AACF;;AAEFoG;AACF;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;;AAEA;AACA;;;;;;;;;AAUA;AACA;AAEA;;;AAEkEP;AAAO;;;AAKvE;AACE;;AAEEG;;;;AAIAC;AACF;;AAEA1C;AACA;AACF;AACE;AACAA;AACqE8I;;AAEvE;AACF;AACF;;AC1GA;AACE7F;AACAlH;AACA+G;AACAI;AACE;AACA;;;AAGFf;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;;;AAIA;AACA;AACE;AACA;AACA;;AAEA7C;AACJ;AACA;AACI;AACF;AAEA;;;AAIEiD;;;;AAIF;AACF;;ACjEA;AAEO;;AAEL;AAA8BJ;AAAW;AACvC;AAEIkL;AACAD;AACF;;;;;AAMA;AAEJ;AACF;;ACnBO;;;;;;;;;AASLE;AAWF;;AAEE;AAA8BpK;AAAkB;AAEhD;;;;;AAMInH;;;;AAIAuR;;;AAMFzK;AACF;AACEc;AACF;AACF;;ACtCA;AACEpB;AACAlH;AACA+G;AACAI;AACE;AACA;AACA+K;AACE1S;AACA8G;AACAD;AACArG;;AAEFmS;AACE3S;AACA8G;AACAD;AACArG;;AAEFoS;AACE5S;AACA8G;AACAD;AACArG;;AAEFqS;AACE7S;AACA8G;AACAD;AACArG;;AAEFiS;AACEzS;AACA8G;AACAD;AACArG;AACF;;AAEFoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;;;AAIE;AACA;AACA;;AAEA7C;AACJ;AACA;AACI;AACF;AAEA;AAEA;;AAEE;AAGF;AAEA;;;;;;;;;AASEqO;AACF;AACF;;AC5GO;;AAML;AAA8BzK;AAAkB;AAEhD;AACA;;AAMEL;AACF;AACEc;AACF;AACF;;ACbA;AACEpB;AACAlH;AACA+G;AACAI;;;AAGAf;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;AAEA;AACE;AACA;AACA;;AAEA7C;AACJ;AACA;AACA;AACI;AACF;AAEA;AAEA;;AAEE;AAGF;AAEA;AACF;;ACxEA;AASO;;;;;;;;AAQLsO;AAUF;;AAEE;AAA8B1K;AAAkB;AAEhD;;;;;;;;AASIiC;;AAKJ;AACExB;AACA;AACF;AAEA;AACE6C;AACIC;AAAa1K;AAA2B;AACxC0K;AAAe1K;AAA6B;AAC5C0K;AAAqB1K;AAAmC;AACxD0K;AAAyB1K;AAAuC;AAChE0K;AAAmB1K;;;AAIzB8G;AACF;;AClDA;AACEN;AACAlH;AACA+G;AACAI;AACE;AACAoL;AACE/S;AACA8G;AACAD;AACArG;;AAEFwS;AACEhT;AACA6G;AACArG;;AAEF6J;AACErK;AACA8G;AACAD;AACArG;;AAEF8J;AACEtK;AACA8G;AACAD;AACArG;;;;AAIJoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;;;AAKE;AACA;AACA;;AAEA7C;AACJ;AACA;AACI;AACF;AAEA;AAEA;;AAEE;AAGF;AAEA;;;;;;AAMEuO;;;AAGF;AACF;;ACnGO;;;;;;;;;AASLP;AAWF;;AAEE;AAA8BpK;AAAkB;AAEhD;AACA;;;;AAKInH;;;;AAIAuR;;;AAMFzK;AACF;AACEc;AACF;AACF;;ACtCA;AACEpB;AACAlH;AACA+G;AACAI;AACE;AACA;AACA+K;AACE1S;AACA8G;AACAD;AACArG;;AAEFmS;AACE3S;AACA8G;AACAD;AACArG;;AAEFoS;AACE5S;AACA8G;AACAD;AACArG;;AAEFqS;AACE7S;AACA8G;AACAD;AACArG;;AAEFiS;AACEzS;AACA8G;AACAD;AACArG;AACF;;AAEFoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;;;AAIE;AACA;AACA;;AAEA7C;AACJ;AACA;AACA;AACI;AACF;AAEA;AAEA;;AAEE;AAGF;AAEA;;;;;;;;;;AAUA;AACF;;AClHA;AASO;;AAML;AAA8B4D;AAAkB;AAEhD;AACA;AAKA;AACES;AACA;AACF;AAEA;AACE6C;AACIC;AAAa1K;AAA2B;AACxC0K;AAAe1K;AAA6B;AAC5C0K;AAAqB1K;AAAmC;AACxD0K;AAAyB1K;AAAuC;AAChE0K;AAAmB1K;AAAiC;AACpD0K;AAAmB1K;AAAiC;AACpD0K;AAAqB1K;;;AAI3B8G;AACF;;AC9BA;AACEN;AACAlH;AACA+G;AACAI;AACE;;;AAGFf;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;;;AAIE;AACA;AACA;;AAEA7C;AACJ;AACA;AACI;AACF;AAEA;AAEA;;AAEE;AAGF;AAEA;AACF;;AChEA;AAEO;;AAEL;AAA8B6C;AAAW;AACvC;AAEIkL;AACAD;AACAU;AACAC;AACAC;AACF;;;;;AAMA;AAEJ;AACF;;ACnBO;;;AAGLC;;AAEAC;;;;;;AAMAC;;AAEAC;AAeF;;AAEE;AAA8BlL;AAAkB;AAEhD;;AAKMyB;AACAxK;AACAC;AACAiU;AACAC;AACAF;AACF;AAOJ;AACEzK;AACA;AACF;AAEAd;AAEA;AACAvD;AAEA;;;AAGA;;AAMA;;AAEA;;AAEF;;ACpEA;AACEiD;AACAlH;AACA+G;AACAI;AACEmC;AACE9J;AACA8G;AACAD;AACArG;;AAEFlB;AACEU;AACA8G;AACAD;AACArG;;AAEFkT;AACE1T;AACA8G;AACAD;AACArG;;AAEF4S;AACEpT;AACA8G;AACAD;AACArG;;AAEF2N;AACEnO;AACAQ;;AAEFuG;AACE/G;AACAQ;;AAGF8S;AACEtT;AACA8G;AACAtG;;AAEF6S;AACErT;AACA8G;AACAD;AACArG;;AAEFqS;AACE7S;AACA8G;AACAD;AACArG;;AAEFmT;AACE3T;AACA8G;AACAD;AACArG;;AAEF+S;AACEvT;AACA8G;AACAD;AACArG;AAEF;;AAEFoG;AACF;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;;AAIA;;AAKA;AACA;AAEA;AACA;AAGI;AAMA;;AAEF;AAEE;AAA+DW;AAAM;AACvE;;;AAQM3I;AAAoBwK;;AAE5B;AACE;AACA;AACA;;AAEArF;AACJ;AACA;AACA;AACA;AAWI;AACF;AAEA;;AAEE;AAGF;AAEA;;;AAGEiO;AACAkB;;;;;;;;;AASAN;AACF;AACF;;ACnMO;;AAML;AAA8BjL;AAAkB;AAEhD;AACA;;AAMEL;AACF;AACEc;AACF;AACF;;ACbA;AACEpB;AACAlH;AACA+G;AACAI;AACE;;;AAGFf;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;AAEA;AACE;AACA;AACA;;AAEA7C;AAEJ;AACA;AAEI;AACF;AAEA;AAEA;;AAEE;AAGF;AAEA;AACF;;AC1EA;AASO;;AAiBL;AAA8B4D;AAAkB;AAEhD;AACA;AAKA;AACES;AACA;AACF;AAEA;AACE6C;AACIC;AAAa1K;AAA2B;AACxC0K;AAAqB1K;AAAiC;AACtD0K;AAAiB1K;AAA+B;AAChD0K;AAAqB1K;;;;;;;AAQvBhC;AAEM8K;AACAC;AACAC;;;;AAKV;AAEAlC;;AAEF;;ACnDA;AACEN;AACAlH;AACA+G;AACAI;AACE;AACA;AACAoL;AACE/S;AACA8G;AACAD;AACArG;;AAGFwS;AACEhT;AACA8G;AACAD;AACArG;;AAEF6J;AACErK;AACA8G;AACAD;AACArG;;AAEF8J;AACEtK;AACA8G;AACAD;AACArG;;AAEFqT;AACE7T;AACA8G;AACAD;AACArG;;AAEFsT;AACE9T;AACA8G;AACAD;AACArG;AACF;;AAEFoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;;AAGE;AACA;AACA;;AAEA7C;AACJ;AACI;AACF;AAEA;AAEA;;AAEE;AAGF;;AAIE;AACA;AACEgH;AACAsI;;AAEAhB;AACAC;AACAjJ;AACAO;AACA0J;AACAC;;AAcN;;ACnIO;;AAML;AAA8B5L;AAAkB;AAEhD;AACA;AAKA;AACES;AACA;AACF;AAEAd;AACAvD;AACF;;ACZA;AACEiD;AACAlH;AACA+G;AACAI;AACE;;;AAGFf;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;AAEA;AACE;AACA;AACA;;AAEA7C;AAEJ;AACA;AAEI;AACF;AAEA;AAEA;;AAEE;AAGF;AAEA;AACF;;ACtEO;AAML;AAA8B4D;AAA0B;AAExD;;;;AAYA;AACES;AACF;AAEA;AACF;;AClBA;AACEpB;AACAlH;AACA+G;AACAI;AACE;;;AAGFf;AACF;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;AAEA;AACE;AACA;AACA;;AAEA7C;AAEJ;AACA;AAEI;AACF;AAEA;AAEA;;AAEE;AAGF;;AAGF;;ACtEA;AAEO;;AAEL;AAA8B6C;AAAW;AACvC;AAEIkL;AACA0B;AACAjB;AACAC;AACAiB;AACF;;;;;AAMA;AAEJ;AACF;;ACRO;;;;;;AAML9J;AAQF;AACE;AACEhC;AACF;;AAGE0B;;;AAGAgB;AACF;;AAKA;;AAMA;AACEtG;AACA;AACF;AAEA;AAEA;AACE2P;AACAC;AACAC;AACAC;AACAC;AACAhM;AACAkB;AACA+K;AACAC;AACE1U;AACAqU;;AAEFM;AAAkB;AAClBC;AACF;;AAEA;;AAGArM;AAEA;;AAGEJ;AAQAvF;AACF;;AAIA2F;AACF;AAEA;AACE;;;AAGE;AAEA;AACA;AAEA;AACA;AAKA;AAQF;AACF;AAEA;;AAEA;AAEA;;AAEA;AAEA;;AAEA;;ACpIA;AACEb;AACAlH;AACA+G;AACAI;AACE;AACA;AACA0C;AACErK;AACA8G;AACAD;AACArG;;AAEF8J;AACEtK;AACA8G;AACAD;AACArG;;AAEFwS;AACEhT;AACA8G;AACAD;AACArG;;AAEFuK;AACE/K;AACA8G;AACAD;AACArG;AACF;;AAEFoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;;;;;AAMnCA;AACF;AAEA;AAEA;;AAEE;AAGF;AAEA;;;;;;;AAOA;AACF;;ACvFO;;AAKD;AACE;AACF;AACA;AACA;;AAEN;AACA;AACA;AACI;AAEJ;;AChBO;;;;AASH7C;AAGA;AACF;AACA;AACF;;ACTO;AACL;;;AACoBoQ;AAAU;;;AAM5BC;;AAEJ;;AAEA;AACE;AACF;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AAEE;;;AAGA;AACA;AACF;AAEA;AACEC;AACE;AACE;;;AACoBF;AAAU;;AAE5B;;AAEA;AACA;;AAEA;;AAEA;AACF;;;AAGAG;AAIF;;AAEA;AACF;AACF;;AC/DO;AACL;AACE;AACEvQ;AACA;AACF;;AAOA;;AAGE;AACEA;AACA;AACF;AACE;AACA;AACAA;AAGF;AACF;AACF;AACF;;ACdA;AACEiD;AACAlH;AACA+G;AACAI;AACE;AACAsN;AACEjV;AACA6G;AACArG;;AAEF0U;AACElV;AACA6G;AACArG;AACF;;AAEFoG;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAEO;;;AAGLkB;AACF;AAEA;AAGIR;AAAmC;AAErC;AACA;AACE6N;AACA;AACF;;;;;AAME7N;AACF;;AAEQ2N;;;AAEN;AACA;AACA;;AAEAxQ;AACJ;AACI;AACF;AAEA;AACE;AACF;;AAEA;;;AACoBoQ;AAAU;AAC9B;;;AAGE;;;AAGA;AACF;AACE;;AAEA;AACA;;AAEA;AACF;;AAEEpQ;AAGF;AACF;;ACrEA;;AAAgB2Q;AAAgB;;AAEhC;AACA;AACE;AACElU;AACAC;;AAEF;;AAGE;AAEIkU;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACA;AACA;AACAC;AACAC;AACAC;AACA;AACAC;AACAC;AACAC;AACA;AACA;AACAC;AACF;AAEEpH;AACEqH;AACE/V;;AAEF;;;AAGFU;AACA2N;AAAc9N;AAAoC;AACpD;;;AAIF;AACA;;;AAGEyV;;AAEF;AACEA;;;AAGF;AACEA;AACAC;AACAC;AACF;AACEF;AACF;;AAIA;AACE/R;AACF;;AAEF;AACF","debugId":"2303041b-c570-4dda-ac6a-10845950c7af"}
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../../src/commands/action/core/classes.ts","../../src/commands/action/core/index.ts","../../src/commands/action/core/scm_comments.ts","../../src/commands/action/core/github.ts","../../src/commands/action/core/messages.ts","../../src/commands/action/run-action.ts","../../src/utils/api.ts","../../src/utils/output-formatting.ts","../../src/flags.ts","../../src/utils/meow-with-subcommands.ts","../../src/commands/action/cmd-action.ts","../../src/commands/analytics/display-analytics.ts","../../src/commands/analytics/cmd-analytics.ts","../../src/commands/audit-log/get-audit-log.ts","../../src/commands/audit-log/cmd-audit-log.ts","../../src/commands/cdxgen/run-cyclonedx.ts","../../src/commands/cdxgen/cmd-cdxgen.ts","../../src/commands/dependencies/find-dependencies.ts","../../src/commands/dependencies/cmd-dependencies.ts","../../src/commands/diff-scan/get-diff-scan.ts","../../src/commands/diff-scan/cmd-diff-scan-get.ts","../../src/commands/diff-scan/cmd-diff-scan.ts","../../src/commands/fix/run-fix.ts","../../src/commands/fix/cmd-fix.ts","../../src/utils/objects.ts","../../src/utils/strings.ts","../../src/utils/alert/severity.ts","../../src/commands/info/fetch-package-info.ts","../../src/commands/info/format-package-info.ts","../../src/commands/info/get-package-info.ts","../../src/commands/info/cmd-info.ts","../../src/commands/login/apply-login.ts","../../src/commands/login/attempt-login.ts","../../src/commands/login/cmd-login.ts","../../src/commands/logout/apply-logout.ts","../../src/commands/logout/attempt-logout.ts","../../src/commands/logout/cmd-logout.ts","../../src/commands/manifest/convert_gradle_to_maven.ts","../../src/commands/manifest/cmd-manifest-gradle.ts","../../src/commands/manifest/convert_sbt_to_maven.ts","../../src/commands/manifest/cmd-manifest-scala.ts","../../src/commands/manifest/cmd-manifest-auto.ts","../../src/commands/manifest/cmd-manifest-kotlin.ts","../../src/commands/manifest/cmd-manifest.ts","../../src/commands/npm/wrap-npm.ts","../../src/commands/npm/cmd-npm.ts","../../src/commands/npx/wrap-npx.ts","../../src/commands/npx/cmd-npx.ts","../../src/commands/oops/cmd-oops.ts","../../src/commands/optimize/deps-includes-by-agent.ts","../../src/utils/package-environment-detector.ts","../../src/commands/optimize/detect-and-validate-package-environment.ts","../../src/commands/optimize/get-dependency-entries.ts","../../src/commands/optimize/get-overrides-by-agent.ts","../../src/commands/optimize/get-workspace-globs.ts","../../src/commands/optimize/lock-includes-by-agent.ts","../../src/commands/optimize/ls-by-agent.ts","../../src/commands/optimize/update-manifest-by-agent.ts","../../src/commands/optimize/run-agent.ts","../../src/commands/optimize/update-package-lock-json.ts","../../src/commands/optimize/apply-optimization.ts","../../src/commands/optimize/cmd-optimize.ts","../../src/commands/organization/get-organization.ts","../../src/commands/organization/cmd-organization.ts","../../src/commands/raw-npm/run-raw-npm.ts","../../src/commands/raw-npm/cmd-raw-npm.ts","../../src/commands/raw-npx/run-raw-npx.ts","../../src/commands/raw-npx/cmd-raw-npx.ts","../../src/commands/report/create-report.ts","../../src/commands/report/get-socket-config.ts","../../src/commands/report/fetch-report-data.ts","../../src/commands/report/format-report-data.ts","../../src/commands/report/view-report.ts","../../src/commands/report/cmd-report-create.ts","../../src/commands/report/cmd-report-view.ts","../../src/commands/report/cmd-report.ts","../../src/commands/repos/create-repo.ts","../../src/commands/repos/cmd-repos-create.ts","../../src/commands/repos/delete-repo.ts","../../src/commands/repos/cmd-repos-del.ts","../../src/commands/repos/list-repos.ts","../../src/commands/repos/cmd-repos-list.ts","../../src/commands/repos/update-repo.ts","../../src/commands/repos/cmd-repos-update.ts","../../src/commands/repos/view-repo.ts","../../src/commands/repos/cmd-repos-view.ts","../../src/commands/repos/cmd-repos.ts","../../src/commands/scan/create-full-scan.ts","../../src/commands/scan/cmd-scan-create.ts","../../src/commands/scan/delete-full-scan.ts","../../src/commands/scan/cmd-scan-del.ts","../../src/commands/scan/list-full-scans.ts","../../src/commands/scan/cmd-scan-list.ts","../../src/commands/scan/get-full-scan-metadata.ts","../../src/commands/scan/cmd-scan-metadata.ts","../../src/commands/scan/get-full-scan.ts","../../src/commands/scan/cmd-scan-stream.ts","../../src/commands/scan/cmd-scan.ts","../../src/commands/threat-feed/get-threat-feed.ts","../../src/commands/threat-feed/cmd-threat-feed.ts","../../src/commands/wrapper/add-socket-wrapper.ts","../../src/commands/wrapper/check-socket-wrapper-setup.ts","../../src/commands/wrapper/postinstall-wrapper.ts","../../src/commands/wrapper/remove-socket-wrapper.ts","../../src/commands/wrapper/cmd-wrapper.ts","../../src/cli.ts"],"sourcesContent":["// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/core/classes.py\nimport { components } from '@socketsecurity/sdk/types/api'\n\ntype IntroducedBy = [string, string][]\n\nexport class Alert {\n key = ''\n type = ''\n severity = ''\n category = ''\n props = {}\n\n constructor(arg: Partial<Alert> = {}) {\n this.key = arg.key ?? this.key\n this.type = arg.type ?? this.type\n this.severity = arg.severity ?? this.severity\n this.category = arg.category ?? this.category\n this.props = arg.props ?? this.props\n }\n}\n\nexport class Comment {\n id = 0\n body = ''\n body_list: string[] = []\n\n constructor(arg: Comment) {\n this.id = arg.id ?? this.id\n this.body = arg.body ?? this.body\n this.body_list = arg.body_list ?? this.body_list\n }\n}\n\nexport class Diff {\n newPackages: Purl[] = []\n newCapabilities: Record<string, any> = {}\n removedPackages: Purl[] = []\n newAlerts: Issue[] = []\n id = ''\n sbom = ''\n packages: Record<string, Package> = {}\n reportUrl = ''\n diffUrl = ''\n}\n\nexport class FullScan {\n id = ''\n created_at = ''\n updated_at = ''\n organizationId = ''\n repositoryId = ''\n branch = ''\n commit_message = ''\n commit_hash = ''\n pull_request = 0\n sbom_artifacts: components['schemas']['SocketArtifact'][] = []\n packages = {}\n\n constructor(obj: Partial<FullScan> = {}) {\n this.id = obj.id ?? this.id\n this.created_at = obj.created_at ?? this.created_at\n this.updated_at = obj.updated_at ?? this.updated_at\n this.organizationId = obj.organizationId ?? this.organizationId\n this.repositoryId = obj.repositoryId ?? this.repositoryId\n this.branch = obj.branch ?? this.branch\n this.commit_message = obj.commit_message ?? this.commit_message\n this.commit_hash = obj.commit_hash ?? this.commit_hash\n this.pull_request = obj.pull_request ?? this.pull_request\n this.sbom_artifacts = obj.sbom_artifacts ?? this.sbom_artifacts\n this.packages = obj.packages ?? this.packages\n }\n}\n\nexport class Issue {\n pkg_type = ''\n pkg_name = ''\n pkg_version = ''\n category = ''\n type = ''\n severity = ''\n pkg_id = ''\n props = {}\n key = ''\n error = false\n warn = false\n ignore = false\n monitor = false\n description = ''\n title = ''\n emoji = ''\n next_step_title = ''\n suggestion = ''\n introduced_by: IntroducedBy = []\n manifests = ''\n url = ''\n purl = ''\n\n constructor(arg: {\n pkg_type: string | undefined\n pkg_name: string | undefined\n pkg_version: string | undefined\n type: string | undefined\n severity: string | undefined\n pkg_id: string | undefined\n props: Record<string, any> | undefined\n key: string | undefined\n error: boolean | undefined\n warn: boolean | undefined\n ignore: boolean | undefined\n monitor: boolean | undefined\n description: string | undefined\n title: string | undefined\n next_step_title: string | undefined\n suggestion: string | undefined\n introduced_by: IntroducedBy | undefined\n url: string | undefined\n purl: string | undefined\n }) {\n this.pkg_type = arg.pkg_type ?? this.pkg_type\n this.pkg_name = arg.pkg_name ?? this.pkg_name\n this.pkg_version = arg.pkg_version ?? this.pkg_version\n this.type = arg.type ?? this.type\n this.severity = arg.severity ?? this.severity\n this.pkg_id = arg.pkg_id ?? this.pkg_id\n this.props = arg.props ?? this.props\n this.key = arg.key ?? this.key\n this.error = arg.error ?? this.error\n this.warn = arg.warn ?? this.warn\n this.ignore = arg.ignore ?? this.ignore\n this.monitor = arg.monitor ?? this.monitor\n this.description = arg.description ?? this.description\n this.title = arg.title ?? this.title\n this.next_step_title = arg.next_step_title ?? this.next_step_title\n this.suggestion = arg.suggestion ?? this.suggestion\n\n if (arg.introduced_by) {\n const arr = []\n for (const item of arg.introduced_by) {\n const [, manifest] = item\n arr.push(manifest)\n }\n this.manifests = arr.join(';')\n }\n }\n}\n\nexport class Package {\n type = ''\n name = ''\n version = ''\n release = ''\n id = ''\n direct = false\n manifestFiles: { file: string }[] = []\n author: string[] = []\n size = 0\n score: Score\n scores = {}\n alerts: NonNullable<components['schemas']['SocketArtifact']['alerts']> = []\n alert_counts = {}\n topLevelAncestors: string[] = []\n url = ''\n transitives = 0\n license = 'NoLicenseFound'\n license_text = ''\n purl = ''\n\n constructor(arg: {\n type: string | undefined\n name: string | undefined\n version: string | undefined\n release: string | undefined\n id: string | undefined\n direct: boolean | undefined\n manifestFiles: { file: string }[] | undefined\n author: string[] | undefined\n size: number | undefined\n score: Score | undefined\n alerts: components['schemas']['SocketArtifact']['alerts'] | undefined\n topLevelAncestors: string[] | undefined\n license: string | undefined\n }) {\n this.type = arg.type ?? this.type\n this.name = arg.name ?? this.name\n this.version = arg.version ?? this.version\n this.release = arg.release ?? this.release\n this.id = arg.id ?? this.id\n this.manifestFiles = arg.manifestFiles ?? this.manifestFiles\n this.author = arg.author ?? this.author\n this.size = arg.size ?? this.size\n this.alerts = arg.alerts ?? this.alerts\n this.topLevelAncestors = arg.topLevelAncestors ?? this.topLevelAncestors\n this.license = arg.license ?? this.license\n\n this.url = `https://socket.dev/${this.type}/package/${this.name}/overview/${this.version}`\n this.score = new Score(\n arg.score ?? {\n supplyChain: 0,\n quality: 0,\n license: 0,\n overall: 0,\n vulnerability: 0\n }\n )\n this.alert_counts = {\n critical: 0,\n high: 0,\n middle: 0,\n low: 0\n }\n this.purl = `${this.type}/${this.name}@${this.version}`\n }\n}\n\nexport class Purl {\n id = ''\n name = ''\n version = ''\n ecosystem = ''\n direct = false\n author: string[] = []\n size = 0\n transitives = 0\n introduced_by: IntroducedBy = []\n capabilities: string[] = []\n // is_new = false\n author_url = ''\n url = ''\n purl = ''\n\n constructor(arg: {\n id: string | undefined\n name: string | undefined\n version: string | undefined\n ecosystem: string | undefined\n direct: boolean | undefined\n introduced_by: IntroducedBy | undefined\n author: string[] | undefined\n size: number | undefined\n transitives: number | undefined\n url: string | undefined\n purl: string | undefined\n }) {\n this.id = arg.id ?? this.id\n this.name = arg.name ?? this.name\n this.version = arg.version ?? this.version\n this.ecosystem = arg.ecosystem ?? this.ecosystem\n this.direct = arg.direct ?? this.direct\n this.author = arg.author ?? this.author\n this.size = arg.size ?? this.size\n this.transitives = arg.transitives ?? this.transitives\n this.introduced_by = arg.introduced_by ?? this.introduced_by\n this.url = arg.url ?? this.url\n this.purl = arg.purl ?? this.purl\n\n this.author_url = this.generateAuthorData(this.author, this.ecosystem)\n }\n\n private generateAuthorData(authors: string[], ecosystem: string): string {\n const arr = []\n for (const author of authors) {\n const url = `https://socket.dev/${ecosystem}/user/${author}`\n arr.push(`[${author}](${url})`)\n }\n return arr.join(',')\n }\n}\n\nexport class Score {\n supplyChain = 0\n quality = 0\n license = 0\n overall = 0\n vulnerability = 0\n\n constructor(arg: Score) {\n this.supplyChain = (arg.supplyChain ?? 0) * 100\n this.quality = (arg.quality ?? 0) * 100\n this.license = (arg.license ?? 0) * 100\n this.overall = (arg.overall ?? 0) * 100\n this.vulnerability = (arg.vulnerability ?? 0) * 100\n }\n}\n","// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/core/__init__.py\n/* eslint-disable no-await-in-loop */\nimport { once } from 'node:events'\nimport fs from 'node:fs'\nimport path from 'node:path'\n\nimport ndjson from 'ndjson'\n\nimport { SocketSdk } from '@socketsecurity/sdk'\n\nimport { Diff, FullScan, Issue, Package, Purl } from './classes'\n\nimport type { components, operations } from '@socketsecurity/sdk/types/api.d'\n\nexport class Core {\n socket: SocketSdk\n owner: string\n repo: string\n files: string[]\n securityPolicy: Record<\n string,\n { action: 'error' | 'ignore' | 'warn' | 'monitor' }\n > = {}\n\n constructor({\n owner,\n repo,\n socket\n }: Pick<Core, 'socket' | 'owner' | 'repo' | 'files'>) {\n this.socket = socket\n this.owner = owner\n this.repo = repo\n this.files = []\n }\n\n async getSbomData({\n fullScanId\n }: {\n fullScanId: string\n }): Promise<components['schemas']['SocketArtifact'][]> {\n const orgFullScanResponse = await this.socket.getOrgFullScan(\n this.owner,\n fullScanId,\n undefined\n )\n if (!orgFullScanResponse.success) {\n return []\n }\n\n const { data: readStream }: { data: any } = orgFullScanResponse\n const sbomArtifacts: any = []\n\n readStream\n .pipe(ndjson.parse())\n .on('data', (sbomArtifact: any) => sbomArtifacts.push(sbomArtifact))\n\n await once(readStream, 'end')\n\n return sbomArtifacts\n }\n\n async createFullScan({\n params\n }: {\n params: Omit<operations['CreateOrgFullScan']['parameters']['query'], 'repo'>\n }): Promise<FullScan> {\n const orgFullScanResponse = await this.socket.createOrgFullScan(\n this.owner,\n // Ignoring because pull_request is of type number but URLSearchParams will convert it to a string\n // @ts-ignore\n new URLSearchParams({ repo: this.repo, ...params }),\n this.files\n )\n\n if (!orgFullScanResponse.success) {\n return new FullScan()\n }\n\n const { id: fullScanId } = orgFullScanResponse.data\n const fullScan = new FullScan(orgFullScanResponse.data)\n if (fullScanId !== undefined) {\n fullScan.sbom_artifacts = await this.getSbomData({ fullScanId })\n }\n return fullScan\n }\n\n getSourceData({\n packages,\n pkg\n }: {\n pkg: Package\n packages: Record<string, Package>\n }): [string, string][] {\n const introducedBy: [string, string][] = []\n\n if (pkg.direct) {\n let manifests = pkg.manifestFiles.map(({ file }) => file).join(';')\n\n introducedBy.push(['direct', manifests])\n } else {\n for (const topId of pkg.topLevelAncestors) {\n const topPackage = packages[topId]\n\n if (!topPackage) {\n continue\n }\n\n const topPurl = `${topPackage.type}/${topPackage.name}@${topPackage.version}`\n let manifests = topPackage.manifestFiles\n .map(({ file }) => file)\n .join(';')\n\n introducedBy.push([topPurl, manifests])\n }\n }\n\n return introducedBy\n }\n\n createPurl({\n packageId,\n packages\n }: {\n packageId: string\n packages: Record<string, Package>\n }): { purl: Purl; pkg: Package } {\n const pkg = packages[packageId]!\n const introducedBy = this.getSourceData({ pkg, packages })\n const purl = new Purl({\n id: pkg.id,\n name: pkg.name,\n version: pkg.version,\n ecosystem: pkg.type,\n direct: pkg.direct,\n introduced_by: introducedBy,\n author: pkg.author,\n size: pkg.size,\n transitives: pkg.transitives,\n url: pkg.url,\n purl: pkg.purl\n })\n return { purl, pkg }\n }\n\n async createIssueAlerts({\n alerts,\n packages,\n pkg\n }: {\n pkg: Package\n alerts: Record<string, Issue[]>\n packages: Record<string, Package>\n }): Promise<Record<string, Issue[]>> {\n const issues = JSON.parse(\n fs.readFileSync(path.join(import.meta.dirname, 'issues.json'), 'utf8')\n ) as Record<string, Record<string, string>>\n\n for (const alert of pkg.alerts) {\n const issue = issues[alert.type]\n\n let description = ''\n let title = ''\n let suggestion = ''\n let nextStepTitle = ''\n\n if (issue !== undefined) {\n description = issue['description'] ?? ''\n title = issue['title'] ?? ''\n suggestion = issue['suggestion'] ?? ''\n nextStepTitle = issue['nextStepTitle'] ?? ''\n }\n\n const introducedBy = this.getSourceData({ pkg, packages })\n\n const issueAlert = new Issue({\n pkg_type: pkg.type,\n pkg_name: pkg.name,\n pkg_version: pkg.version,\n pkg_id: pkg.id,\n type: alert.type,\n severity: alert.severity,\n key: alert.key,\n props: alert.props,\n description,\n title,\n suggestion,\n next_step_title: nextStepTitle,\n introduced_by: introducedBy,\n purl: pkg.purl,\n url: pkg.url,\n error: false,\n ignore: false,\n warn: false,\n monitor: false\n })\n\n if (alert.type in this.securityPolicy) {\n const action = this.securityPolicy[alert.type]?.action\n if (action !== undefined) {\n issueAlert[action] = true\n }\n }\n\n if (issueAlert.type !== 'licenseSpdxDisj') {\n if (!(issueAlert.key in alerts)) {\n alerts[issueAlert.key] = [issueAlert]\n } else {\n alerts[issueAlert.key]!.push(issueAlert)\n }\n }\n }\n\n return alerts\n }\n\n compareIssueAlerts({\n alerts,\n headScanAlerts,\n newScanAlerts\n }: {\n newScanAlerts: Record<string, Issue[]>\n headScanAlerts: Record<string, Issue[]>\n alerts: Issue[]\n }) {\n const consolidatedAlerts = new Set()\n\n for (const alertKey in newScanAlerts) {\n if (!(alertKey in headScanAlerts)) {\n const newAlerts = newScanAlerts[alertKey]!\n\n for (const alert of newAlerts) {\n const alertStr = `${alert.purl},${alert.manifests},${alert.type}`\n\n if (alert.error || alert.warn) {\n if (!consolidatedAlerts.has(alertStr)) {\n alerts.push(alert)\n consolidatedAlerts.add(alertStr)\n }\n }\n }\n } else {\n const newAlerts = newScanAlerts[alertKey]!\n const headAlerts = headScanAlerts[alertKey]!\n\n for (const alert of newAlerts) {\n const alertStr = `${alert.purl},${alert.manifests},${alert.type}`\n if (\n !headAlerts.includes(alert) &&\n !consolidatedAlerts.has(alertStr)\n ) {\n if (alert.error || alert.warn) {\n alerts.push(alert)\n consolidatedAlerts.add(alertStr)\n }\n }\n }\n }\n }\n\n return alerts\n }\n\n checkAlertCapabilities({\n capabilities,\n headPackage,\n packageId,\n pkg\n }: {\n pkg: Package\n capabilities: Record<string, string[]>\n packageId: string\n headPackage?: Package\n }): Record<string, string[]> {\n const alertTypes = {\n envVars: 'Environment',\n networkAccess: 'Network',\n filesystemAccess: 'File System',\n shellAccess: 'Shell'\n }\n\n for (const alert of pkg.alerts) {\n let newAlert = true\n if (headPackage !== undefined && headPackage.alerts.includes(alert)) {\n newAlert = false\n }\n if (alert.type in alertTypes && newAlert) {\n const value = alertTypes[alert.type as keyof typeof alertTypes]\n if (!(packageId in capabilities)) {\n capabilities[packageId] = [value]\n } else {\n if (!capabilities[packageId]!.includes(value)) {\n capabilities[packageId]!.push(value)\n }\n }\n }\n }\n\n return capabilities\n }\n\n compareCapabilities({\n headPackages,\n newPackages\n }: {\n newPackages: Record<string, Package>\n headPackages: Record<string, Package>\n }) {\n let capabilities: Record<string, string[]> = {}\n\n for (const packageId in newPackages) {\n const pkg = newPackages[packageId]!\n\n if (packageId in headPackages) {\n const headPackage = headPackages[packageId]!\n for (const alert of pkg.alerts) {\n if (!headPackage.alerts.includes(alert)) {\n capabilities = this.checkAlertCapabilities({\n pkg,\n capabilities,\n packageId,\n headPackage\n })\n }\n }\n } else {\n capabilities = this.checkAlertCapabilities({\n pkg,\n capabilities,\n packageId\n })\n }\n }\n\n return capabilities\n }\n\n addCapabilitiesToPurl(diff: Diff): Diff {\n const newPackages: Purl[] = []\n\n for (const purl of diff.newPackages) {\n if (purl.id in diff.newCapabilities) {\n const capabilities =\n diff.newCapabilities[purl.id as keyof typeof diff.newCapabilities]!\n if (capabilities.length > 0) {\n purl.capabilities = capabilities\n newPackages.push(purl)\n }\n } else {\n newPackages.push(purl)\n }\n }\n diff.newPackages = newPackages\n\n return diff\n }\n\n async compareSBOMs({\n headScan,\n newScan\n }: {\n newScan: Awaited<ReturnType<Core['getSbomData']>>\n headScan: Awaited<ReturnType<Core['getSbomData']>>\n }): Promise<Diff> {\n let diff = new Diff()\n const newPackages = this.createSbomDict(newScan)\n const headPackages = this.createSbomDict(headScan)\n\n let newScanAlerts: Record<string, Issue[]> = {}\n let headScanAlerts: Record<string, Issue[]> = {}\n const consolidated = new Set()\n\n for (const packageId in newPackages) {\n const { pkg, purl } = this.createPurl({\n packageId,\n packages: newPackages\n })\n const basePurl = `${purl.ecosystem}/${purl.name}@${purl.version}`\n\n if (\n !(packageId in headPackages) &&\n pkg.direct &&\n !consolidated.has(basePurl)\n ) {\n diff.newPackages.push(purl)\n consolidated.add(basePurl)\n }\n\n newScanAlerts = await this.createIssueAlerts({\n pkg,\n alerts: newScanAlerts,\n packages: newPackages\n })\n }\n\n for (const packageId in headPackages) {\n const { pkg, purl } = this.createPurl({\n packageId,\n packages: headPackages\n })\n\n if (!(packageId in newPackages) && pkg.direct) {\n diff.removedPackages.push(purl)\n }\n\n headScanAlerts = await this.createIssueAlerts({\n pkg,\n alerts: headScanAlerts,\n packages: headPackages\n })\n }\n\n diff.newAlerts = this.compareIssueAlerts({\n newScanAlerts,\n headScanAlerts,\n alerts: diff.newAlerts\n })\n diff.newCapabilities = this.compareCapabilities({\n newPackages,\n headPackages\n })\n diff = this.addCapabilitiesToPurl(diff)\n\n return diff\n }\n\n createPackageFromSbomArtifact(\n sbomArtifact: components['schemas']['SocketArtifact'][]\n ): Package[] {\n return sbomArtifact.map(\n sbomArtifact =>\n new Package({\n type: sbomArtifact.type,\n name: sbomArtifact.name,\n version: sbomArtifact.version,\n release: sbomArtifact.release,\n id: sbomArtifact.id,\n direct: sbomArtifact.direct,\n manifestFiles: sbomArtifact.manifestFiles,\n author: sbomArtifact.author,\n size: sbomArtifact.size,\n score: sbomArtifact.score,\n alerts: sbomArtifact.alerts,\n topLevelAncestors: sbomArtifact.topLevelAncestors,\n license: sbomArtifact.license\n })\n )\n }\n\n getLicenseDetails({ package: pkg }: { package: Package }): Package {\n const licenseText = JSON.parse(\n fs.readFileSync(\n path.join(import.meta.dirname, 'license_texts.json'),\n 'utf8'\n )\n ) as Record<string, string>\n const licenseStr = licenseText[pkg.license]\n if (licenseStr !== undefined) {\n pkg.license_text = licenseStr\n }\n return pkg\n }\n\n createSbomDict(\n sbomArtifacts: Awaited<ReturnType<typeof this.getSbomData>>\n ): Record<string, Package> {\n const packages: Record<string, Package> = {}\n const topLevelCount: Record<string, number> = {}\n\n for (const sbomArtifact of sbomArtifacts) {\n let pkg = new Package({\n type: sbomArtifact.type,\n name: sbomArtifact.name,\n version: sbomArtifact.version,\n release: sbomArtifact.release,\n id: sbomArtifact.id,\n direct: sbomArtifact.direct,\n manifestFiles: sbomArtifact.manifestFiles,\n author: sbomArtifact.author,\n size: sbomArtifact.size,\n score: sbomArtifact.score,\n alerts: sbomArtifact.alerts,\n topLevelAncestors: sbomArtifact.topLevelAncestors,\n license: sbomArtifact.license\n })\n\n if (pkg.id in packages) {\n console.log('Duplicate package?')\n } else {\n pkg = this.getLicenseDetails({ package: pkg })\n packages[pkg.id] = pkg\n\n for (const topId in sbomArtifact.topLevelAncestors ?? []) {\n if (!(topId in topLevelCount)) {\n topLevelCount[topId] = 1\n } else {\n topLevelCount[topId] += 1\n }\n }\n }\n }\n\n if (Object.keys(topLevelCount).length > 0) {\n for (const packageId in topLevelCount) {\n const pkg = packages[packageId]\n if (pkg) {\n pkg.transitives = topLevelCount[packageId] ?? 0\n }\n }\n }\n\n return packages\n }\n\n async createNewDiff({\n params = {}\n }: {\n params?: Omit<\n operations['CreateOrgFullScan']['parameters']['query'],\n 'repo'\n >\n }): Promise<Diff> {\n let headFullScanId: string = ''\n let headFullScan: Awaited<ReturnType<typeof this.getSbomData>> = []\n\n try {\n const orgRepoResponse = await this.socket.getOrgRepo(\n this.owner,\n this.repo\n )\n if (orgRepoResponse.success) {\n headFullScanId = orgRepoResponse.data.head_full_scan_id ?? ''\n if (headFullScanId !== '') {\n headFullScan = await this.getSbomData({ fullScanId: headFullScanId })\n }\n }\n } catch (error) {\n console.error(error)\n }\n\n const newFullScan = await this.createFullScan({ params })\n newFullScan.packages = this.createSbomDict(newFullScan.sbom_artifacts)\n\n const diffReport = await this.compareSBOMs({\n newScan: newFullScan.sbom_artifacts,\n headScan: headFullScan\n })\n diffReport.packages = newFullScan.packages\n\n const baseSocket = 'https://socket.dev/dashboard/org'\n diffReport.id = newFullScan.id\n diffReport.reportUrl = `${baseSocket}/${this.owner}/sbom/${diffReport.id}`\n if (headFullScanId !== '') {\n diffReport.diffUrl = `${baseSocket}/${this.owner}/diff/${diffReport.id}/${headFullScanId}`\n } else {\n diffReport.diffUrl = diffReport.reportUrl\n }\n\n return diffReport\n }\n}\n","// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/core/scm_comments.py\nimport { Comment, Issue } from './classes'\n\nexport type SocketComments = {\n security: Comment | undefined\n overview: Comment | undefined\n ignore: Comment[]\n}\n\nexport function checkForSocketComments({\n comments\n}: {\n comments: Record<string, Comment>\n}): SocketComments {\n const socketComments: {\n security: Comment | undefined\n overview: Comment | undefined\n ignore: Comment[]\n } = {\n security: undefined,\n overview: undefined,\n ignore: []\n }\n\n for (const commentId in comments) {\n const comment = comments[commentId]!\n\n if (comment.body.includes('socket-security-comment-actions')) {\n socketComments.security = comment\n } else if (comment.body.includes('socket-overview-comment-actions')) {\n socketComments.overview = comment\n } else if (\n // Based on:\n // To ignore an alert, reply with a comment starting with @SocketSecurity ignore\n // followed by a space separated list of ecosystem/package-name@version specifiers.\n // e.g. @SocketSecurity ignore npm/foo@1.0.0 or ignore all packages with @SocketSecurity ignore-all\n comment.body\n .split('\\n')\n .at(0)\n ?.includes('SocketSecurity ignore')\n ) {\n socketComments.ignore.push(comment)\n }\n }\n\n return socketComments\n}\n\n// Parses the ignore command\n// @SocketSecurity ignore pkg1 pkg2 ...\n// @SocketSecurity ignore ignore-all\nexport function parseIgnoreCommand(line: string) {\n const result = { packages: [] as string[], ignoreAll: false }\n const words = line.trim().replace(/\\s+/g, ' ').split(' ')\n if (words.at(1) === 'ignore-all') {\n result.ignoreAll = true\n return result\n }\n if (words.at(1) === 'ignore') {\n for (let i = 2; i < words.length; i++) {\n const pkg = words[i] as string\n result.packages.push(pkg)\n }\n return result\n }\n return result\n}\n\n// Ref: https://github.com/socketdev-demo/javascript-threats/pull/89#issuecomment-2456015512\nexport function processSecurityComment({\n ignore: ignoreComments,\n security: securityComment\n}: Pick<SocketComments, 'security' | 'ignore'>): string {\n const result: string[] = []\n let start = false\n\n let ignoreAll = false\n let ignoredPackages = []\n for (const ignoreComment of ignoreComments) {\n const parsed = parseIgnoreCommand(\n ignoreComment.body?.split('\\n').at(0) ?? ''\n )\n if (parsed.ignoreAll) {\n ignoreAll = true\n break\n }\n ignoredPackages.push(parsed.packages)\n }\n\n // Split the comment body into lines and update them\n // to generate a new comment body\n for (let line of securityComment?.body?.split('\\n') ?? []) {\n line = line.trim()\n\n if (line.includes('start-socket-alerts-table')) {\n start = true\n result.push(line)\n } else if (\n start &&\n !line.includes('end-socket-alerts-table') &&\n // is not heading line?\n !(\n line === '|Alert|Package|Introduced by|Manifest File|CI|' ||\n line.includes(':---')\n ) &&\n line !== ''\n ) {\n // Parsing Markdown data colunms\n const [_, _title, packageLink, _introducedBy, _manifest, _ci] =\n line.split('|') as [string, string, string, string, string, string]\n\n // Parsing package link [npm/pkg](url)\n let [_ecosystem, pkg] = packageLink\n .slice(1, packageLink.indexOf(']'))\n .split('/', 2) as [string, string]\n const [pkgName, pkgVersion] = pkg.split('@')\n\n // Checking if this package should be ignored\n let ignore = false\n if (ignoreAll) {\n ignore = true\n } else {\n for (const [ignoredPkgName, ignorePkgVersion] of ignoredPackages) {\n if (\n pkgName === ignoredPkgName &&\n (ignorePkgVersion === '*' || pkgVersion === ignorePkgVersion)\n ) {\n ignore = true\n break\n }\n }\n }\n\n if (ignore) {\n break\n }\n result.push(line)\n } else if (line.includes('end-socket-alerts-table')) {\n start = false\n result.push(line)\n } else {\n result.push(line)\n }\n }\n\n return result.join('\\n')\n}\n\nexport function getIgnoreOptions({ comments }: { comments: SocketComments }) {\n const ignoreCommands: string[] = []\n let ignoreAll = false\n\n for (const comment of comments.ignore) {\n let firstLine = comment.body_list[0]!\n if (!ignoreAll && firstLine.includes('SocketSecurity ignore')) {\n try {\n firstLine = firstLine.replace(/@/, '')\n let [, command] = firstLine.split('SocketSecurity ')\n command = command!.trim()\n if (command === 'ignore-all') {\n ignoreAll = true\n } else {\n command = command.replace(/ignore/, '').trim()\n const [name, version] = command.split('@')\n const data = `${name}/${version}`\n ignoreCommands.push(data)\n }\n } catch (error) {\n console.error(`Unable to process ignore command for ${comment}`)\n console.error(error)\n }\n }\n }\n return { ignoreAll, ignoreCommands }\n}\n\nexport function removeAlerts({\n comments,\n newAlerts\n}: {\n comments: SocketComments\n newAlerts: Issue[]\n}) {\n const alerts: Issue[] = []\n\n if (comments.ignore.length === 0) {\n return newAlerts\n }\n\n const { ignoreAll, ignoreCommands } = getIgnoreOptions({\n comments\n })\n\n for (const alert of newAlerts) {\n if (ignoreAll) {\n break\n } else {\n const fullName = `${alert.pkg_type}/${alert.pkg_name}`\n const purl = `${fullName}/${alert.pkg_version}`\n const purlStar = `${fullName}/*`\n if (ignoreCommands.includes(purl) || ignoreCommands.includes(purlStar)) {\n console.log(`Alerts for ${alert.pkg_name}@${alert.pkg_version} ignored`)\n } else {\n console.log(\n `Adding alert ${alert.type} for ${alert.pkg_name}@${alert.pkg_version}`\n )\n alerts.push(alert)\n }\n }\n }\n\n return alerts\n}\n","// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/core/github.py\n/* eslint-disable no-await-in-loop */\nimport { Octokit } from '@octokit/rest'\n\nimport { Comment } from './classes'\nimport * as SCMComments from './scm_comments'\n\nexport class GitHub {\n octokit: Octokit = new Octokit()\n owner: string\n repo: string\n prNumber: number\n\n constructor() {\n const [owner = '', repo = ''] = (\n process.env['GITHUB_REPOSITORY'] ?? ''\n ).split('/')\n // https://github.com/actions/checkout/issues/58#issuecomment-2264361099\n const prNumber = parseInt(\n process.env['GITHUB_REF']?.match(/refs\\/pull\\/(\\d+)\\/merge/)?.at(1) ?? ''\n )\n this.owner = owner\n this.repo = repo\n this.prNumber = prNumber\n }\n\n checkEventType(): 'main' | 'diff' | 'comment' | 'unsupported' {\n switch (process.env['GITHUB_EVENT_NAME']) {\n case 'push':\n return this.prNumber ? 'diff' : 'main'\n case 'pull_request':\n // This env variable needs to be set in the GitHub action.\n // Add this code below to GitHub action:\n // - steps:\n // - name: Get PR State\n // if: github.event_name == 'pull_request'\n // run: echo \"EVENT_ACTION=${{ github.event.action }}\" >> $GITHUB_ENV\n const eventAction = process.env['EVENT_ACTION']\n if (!eventAction) {\n throw new Error('Missing event action')\n }\n if (['opened', 'synchronize'].includes(eventAction)) {\n return 'diff'\n } else {\n console.log(`Pull request action: ${eventAction} is not supported`)\n process.exit()\n }\n case 'issue_comment':\n return 'comment'\n default:\n throw new Error(\n `Unknown event type: ${process.env['GITHUB_EVENT_NAME']}`\n )\n }\n }\n\n async getCommentsForPR(): Promise<SCMComments.SocketComments> {\n const { data: githubComments } =\n await this.octokit.rest.issues.listComments({\n owner: this.owner,\n repo: this.repo,\n issue_number: this.prNumber\n })\n const comments: Record<string, Comment> = {}\n for (const githubComment of githubComments) {\n comments[githubComment.id] = new Comment({\n id: githubComment.id,\n body: githubComment.body ?? '',\n body_list: (githubComment.body ?? '').split('\\n')\n })\n }\n return SCMComments.checkForSocketComments({ comments })\n }\n\n async commentReactionExists({\n commentId\n }: {\n commentId: number\n }): Promise<boolean> {\n const { data } = await this.octokit.reactions.listForIssueComment({\n owner: this.owner,\n repo: this.repo,\n comment_id: commentId\n })\n return data.some(reaction => reaction.content === '+1')\n }\n\n async postReaction({ commentId }: { commentId: number }) {\n await this.octokit.reactions.createForIssueComment({\n owner: this.owner,\n repo: this.repo,\n comment_id: commentId,\n content: '+1'\n })\n }\n\n async handleIgnoreReactons({\n comments\n }: {\n comments: SCMComments.SocketComments\n }) {\n for (const ignoreComment of comments.ignore) {\n if (\n ignoreComment.body?.includes('SocketSecurity ignore') &&\n !(await this.commentReactionExists({\n commentId: ignoreComment.id\n }))\n ) {\n await this.postReaction({ commentId: ignoreComment.id })\n }\n }\n }\n\n async updateComment({ body, id }: { id: number; body: string }) {\n await this.octokit.issues.updateComment({\n owner: this.owner,\n repo: this.repo,\n comment_id: id,\n body\n })\n }\n\n async removeCommentAlerts({\n comments\n }: {\n comments: SCMComments.SocketComments\n }) {\n const securityAlert = comments.security\n if (securityAlert !== undefined) {\n const newBody = SCMComments.processSecurityComment({\n security: comments.security,\n ignore: comments.ignore\n })\n await this.handleIgnoreReactons({ comments })\n await this.updateComment({ id: securityAlert.id, body: newBody })\n }\n }\n\n async postComment({ body }: { body: string }) {\n await this.octokit.issues.createComment({\n owner: this.owner,\n repo: this.repo,\n issue_number: this.prNumber,\n body\n })\n }\n\n async addSocketComments({\n comments,\n newOverviewComment,\n newSecurityComment,\n overviewComment,\n securityComment\n }: {\n securityComment: string\n overviewComment: string\n comments: SCMComments.SocketComments\n newSecurityComment: boolean\n newOverviewComment: boolean\n }): Promise<void> {\n const {\n overview: existingOverviewComment,\n security: existingSecurityComment\n } = comments\n if (newOverviewComment) {\n console.log('New Dependency Overview comment')\n if (existingOverviewComment !== undefined) {\n console.log('Previous version of Dependency Overview, updating')\n await this.updateComment({\n body: overviewComment,\n id: existingOverviewComment.id\n })\n } else {\n console.log('No previous version of Dependency Overview, posting')\n await this.postComment({ body: overviewComment })\n }\n }\n if (newSecurityComment) {\n console.log('New Security Issue Comment')\n if (existingSecurityComment !== undefined) {\n console.log('Previous version of Security Issue comment, updating')\n await this.updateComment({\n body: securityComment,\n id: existingSecurityComment.id\n })\n } else {\n console.log('No Previous version of Security Issue comment, posting')\n await this.postComment({ body: securityComment })\n }\n }\n }\n}\n","// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/core/messages.py\nimport { Diff, Issue, Purl } from './classes'\n\nexport function createSecurityCommentJSON({ diff }: { diff: Diff }) {\n let scanFailed = false\n\n // Not porting this code because it's unreachable\n // https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/core/messages.py#L13-L18\n\n const output: {\n scanFailed: boolean\n newAlerts: Issue[]\n fullScanId: string\n } = {\n scanFailed,\n newAlerts: [],\n fullScanId: diff.id\n }\n for (const alert of diff.newAlerts) {\n output.newAlerts.push(alert)\n }\n\n return output\n}\n\nexport function createPurlLink(purl: Purl): string {\n const packageUrl = `[${purl.purl}](${purl.url})`\n return packageUrl\n}\n\nexport function createAddedTable(diff: Diff): string {\n const overviewTable = [\n 'Package',\n 'Direct',\n 'Capabilities',\n 'Transitives',\n 'Size',\n 'Author'\n ]\n const rows = []\n for (const added of diff.newPackages) {\n const packageUrl = createPurlLink(added)\n const capabilities = added.capabilities.join(', ')\n const row = [\n packageUrl,\n added.direct,\n capabilities,\n added.transitives,\n `${added.size} KB`,\n added.author_url\n ]\n rows.push(row)\n }\n\n let md = ''\n md += `|${overviewTable.join('|')}|\\n`\n md += '|---|---|---|---|---|---|\\n'\n for (const row of rows) {\n md += `|${row.join('|')}|\\n`\n }\n\n return md\n}\n\nexport function createRemoveLine(diff: Diff): string {\n const removedLine = ['Removed packages:']\n for (const removed of diff.removedPackages) {\n const packageUrl = createPurlLink(removed)\n removedLine.push(packageUrl)\n }\n return removedLine.join(', ')\n}\n\nexport function dependencyOverviewTemplate(diff: Diff): string {\n let md = ''\n md += '<!-- socket-overview-comment-actions -->\\n'\n md += '# Socket Security: Dependency Overview\\n'\n md +=\n 'New and removed dependencies detected. Learn more about [socket.dev](https://socket.dev)\\n\\n'\n md += createAddedTable(diff)\n if (diff.removedPackages.length > 0) {\n md += createRemoveLine(diff)\n }\n return md\n}\n\nexport function createSources(alert: Issue): [string, string] {\n const sources: string[] = []\n const manifests: string[] = []\n for (const [source, manifest] of alert.introduced_by) {\n const addStr = `<li>${manifest}</li>`\n const sourceStr = `<li>${source}</li>`\n if (!sources.includes(sourceStr)) {\n sources.push(sourceStr)\n }\n if (!manifests.includes(addStr)) {\n manifests.push(addStr)\n }\n }\n let manifestList = manifests.join('')\n let sourceList = sources.join('')\n const manifestStr = `<ul>${manifestList}</ul>`\n const sourcesStr = `<ul>${sourceList}</ul>`\n return [manifestStr, sourcesStr]\n}\n\nexport function createSecurityAlertTable(diff: Diff): {\n ignoreCommands: string[]\n nextSteps: Record<string, string[]>\n mdTable: string\n} {\n const alertTable = [\n 'Alert',\n 'Package',\n 'Introduced by',\n 'Manifest File',\n 'CI'\n ]\n const nextSteps: Record<string, string[]> = {}\n const ignoreCommands: string[] = []\n\n const rows: string[][] = []\n for (const alert of diff.newAlerts) {\n if (!(alert.next_step_title in nextSteps)) {\n nextSteps[alert.next_step_title] = [alert.description, alert.suggestion]\n }\n const ignore = `\\`SocketSecurity ignore ${alert.purl}\\``\n if (!ignoreCommands.includes(ignore)) {\n ignoreCommands.push(ignore)\n }\n const [manifestStr, sourceStr] = createSources(alert)\n const purlUrl = `[${alert.purl}](${alert.url})`\n if (alert.error) {\n alert.emoji = ':no_entry_sign:'\n } else {\n alert.emoji = ':warning:'\n }\n const row = [alert.title, purlUrl, sourceStr, manifestStr, alert.emoji]\n if (!rows.some(r => r.join() === row.join())) {\n rows.push(row)\n }\n }\n\n let md = ''\n md += `|${alertTable.join('|')}|\\n`\n md += '|---|---|---|---|---|\\n'\n for (const row of rows) {\n md += `|${row.join('|')}|\\n`\n }\n\n return { ignoreCommands, nextSteps, mdTable: md }\n}\n\nexport function createNextSteps(nextSteps: Record<string, string[]>): string {\n let md = ''\n for (const step in nextSteps) {\n const detail = nextSteps[step]!\n md += '<details>\\n'\n md += `<summary>${step}</summary>\\n`\n for (const line of detail) {\n md += `${line}\\n`\n }\n md += '</details>\\n'\n }\n return md\n}\n\nexport function createDeeperLook(): string {\n let md = ''\n md += '<details>\\n'\n md += '<summary>Take a deeper look at the dependency</summary>\\n'\n md +=\n \"Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support [AT] socket [DOT] dev.\\n\"\n md += '</details>\\n'\n return md\n}\n\nexport function createRemovePackage(): string {\n let md = ''\n md += '<details>\\n'\n md += '<summary>Remove the package</summary>\\n'\n md +=\n 'If you happen to install a dependency that Socket reports as [https://socket.dev/npm/issue/malware](Known Malware) you should immediately remove it and select a different dependency. For other alert types, you may may wish to investigate alternative packages or consider if there are other ways to mitigate the specific risk posed by the dependency.\\n'\n md += '</details>\\n'\n return md\n}\n\nexport function createAcceptableRisk(ignoreCommands: string[]): string {\n let md = ''\n md += '<details>\\n'\n md += '<summary>Mark a package as acceptable risk</summary>\\n'\n md +=\n 'To ignore an alert, reply with a comment starting with `SocketSecurity ignore` followed by a space separated list of `ecosystem/package-name@version` specifiers. e.g. `SocketSecurity ignore npm/foo@1.0.0` or ignore all packages with `SocketSecurity ignore-all`\\n'\n md += '<ul>\\n'\n for (const ignore of ignoreCommands) {\n md += `<li>${ignore}</li>\\n`\n }\n md += '</ul>\\n'\n md += '</details>\\n'\n return md\n}\n\nexport function securityCommentTemplate(diff: Diff): string {\n let md = ''\n md += '<!-- socket-security-comment-actions -->\\n'\n md += '# Socket Security: Issues Report\\n'\n md +=\n 'Potential security issues detected. Learn more about [socket.dev](https://socket.dev)\\n'\n md +=\n 'To accept the risk, merge this PR and you will not be notified again.\\n\\n'\n md += '<!-- start-socket-alerts-table -->\\n'\n const { ignoreCommands, mdTable, nextSteps } = createSecurityAlertTable(diff)\n md += mdTable\n md += '<!-- end-socket-alerts-table -->\\n\\n'\n md += createNextSteps(nextSteps)\n md += createDeeperLook()\n md += createRemovePackage()\n md += createAcceptableRisk(ignoreCommands)\n return md.trim()\n}\n","// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/socketcli.py\n\nimport micromatch from 'micromatch'\nimport { simpleGit } from 'simple-git'\n\nimport { SocketSdk } from '@socketsecurity/sdk'\n\nimport { Core } from './core'\nimport { GitHub } from './core/github'\nimport * as Messages from './core/messages'\nimport * as SCMComments from './core/scm_comments'\nimport { getDefaultToken } from '../../utils/sdk'\n\n// TODO: is this a github action handler?\nexport async function runAction(\n githubEventBefore: string,\n githubEventAfter: string\n) {\n //TODO\n const socket = new SocketSdk(getDefaultToken()!)\n\n const git = simpleGit()\n const changedFiles = (\n await git.diff(\n process.env['GITHUB_EVENT_NAME'] === 'pull_request'\n ? ['--name-only', 'HEAD^1', 'HEAD']\n : ['--name-only', githubEventBefore, githubEventAfter]\n )\n ).split('\\n')\n\n console.log({ changedFiles })\n // supportedFiles have 3-level deep globs\n const patterns = Object.values(await socket.getReportSupportedFiles())\n .flatMap((i: Record<string, any>) => Object.values(i))\n .flatMap((i: Record<string, any>) => Object.values(i))\n .flatMap((i: Record<string, any>) => Object.values(i))\n\n const files = micromatch(changedFiles, patterns)\n\n const scm = new GitHub()\n\n if (scm.checkEventType() === 'comment') {\n console.log('Comment initiated flow')\n const comments = await scm.getCommentsForPR()\n await scm.removeCommentAlerts({ comments })\n } else if (scm.checkEventType() === 'diff') {\n console.log('Push initiated flow')\n const core = new Core({ owner: scm.owner, repo: scm.repo, files, socket })\n const diff = await core.createNewDiff({})\n const comments = await scm.getCommentsForPR()\n diff.newAlerts = SCMComments.removeAlerts({\n comments,\n newAlerts: diff.newAlerts\n })\n const overviewComment = Messages.dependencyOverviewTemplate(diff)\n const securityComment = Messages.securityCommentTemplate(diff)\n let newSecurityComment = true\n let newOverviewComment = true\n let updateOldSecurityComment = comments.security !== undefined\n let updateOldOverviewComment = comments.overview !== undefined\n if (diff.newAlerts.length === 0) {\n if (!updateOldSecurityComment) {\n newSecurityComment = false\n console.log('No new alerts or security issue comment disabled')\n } else {\n console.log('Updated security comment with no new alerts')\n }\n }\n if (diff.newPackages.length === 0 && diff.removedPackages.length === 0) {\n if (!updateOldOverviewComment) {\n newOverviewComment = false\n console.log(\n 'No new/removed packages or Dependency Overview comment disabled'\n )\n } else {\n console.log('Updated overview comment with no dependencies')\n }\n }\n await scm.addSocketComments({\n securityComment,\n overviewComment,\n comments,\n newSecurityComment,\n newOverviewComment\n })\n }\n}\n","import process from 'node:process'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { AuthError } from './errors'\nimport constants from '../constants'\n\nimport type { Spinner } from '@socketsecurity/registry/lib/spinner'\nimport type {\n SocketSdkErrorType,\n SocketSdkOperations\n} from '@socketsecurity/sdk'\n\nconst { API_V0_URL } = constants\n\nexport function handleUnsuccessfulApiResponse<T extends SocketSdkOperations>(\n _name: T,\n result: SocketSdkErrorType<T>,\n spinner: Spinner\n) {\n // SocketSdkErrorType['error'] is not typed.\n const resultErrorMessage = (<{ error?: Error }>result).error?.message\n const message =\n typeof resultErrorMessage === 'string'\n ? resultErrorMessage\n : 'No error message returned'\n if (result.status === 401 || result.status === 403) {\n spinner.stop()\n throw new AuthError(message)\n }\n spinner.error(\n `${colors.bgRed(colors.white('API returned an error:'))} ${message}`\n )\n process.exit(1)\n}\n\nexport async function handleApiCall<T>(\n value: T,\n description: string\n): Promise<T> {\n let result: T\n try {\n result = await value\n } catch (cause) {\n throw new Error(`Failed ${description}`, { cause })\n }\n return result\n}\n\nexport async function handleAPIError(code: number) {\n if (code === 400) {\n return 'One of the options passed might be incorrect.'\n } else if (code === 403) {\n return 'You might be trying to access an organization that is not linked to the API key you are logged in with.'\n }\n}\n\nexport function getLastFiveOfApiToken(token: string): string {\n // Get the last 5 characters of the API token before the trailing \"_api\".\n return token.slice(-9, -4)\n}\n\nexport async function queryAPI(path: string, apiToken: string) {\n return await fetch(`${API_V0_URL}/${path}`, {\n method: 'GET',\n headers: {\n Authorization: `Basic ${btoa(`${apiToken}:${apiToken}`)}`\n }\n })\n}\n","type HelpListOptions = {\n keyPrefix: string\n padName: number\n}\n\ntype ListDescription = string | { description: string }\n\nexport function getFlagListOutput(\n list: Record<string, ListDescription>,\n indent: number,\n { keyPrefix = '--', padName } = <HelpListOptions>{}\n): string {\n return getHelpListOutput(\n {\n ...list\n },\n indent,\n { keyPrefix, padName }\n )\n}\n\nexport function getHelpListOutput(\n list: Record<string, ListDescription>,\n indent: number,\n { keyPrefix = '', padName = 18 } = <HelpListOptions>{}\n): string {\n let result = ''\n const names = Object.keys(list).sort()\n for (const name of names) {\n const rawDescription = list[name]\n const description =\n (typeof rawDescription === 'object'\n ? rawDescription.description\n : rawDescription) || ''\n result +=\n ''.padEnd(indent) +\n (keyPrefix + name).padEnd(padName) +\n description +\n '\\n'\n }\n return result.trim()\n}\n","import type { Flag } from 'meow'\n\n// TODO: not sure if I'm missing something but meow doesn't seem to expose this?\ntype StringFlag = Flag<'string', string> | Flag<'string', string[], true>\ntype BooleanFlag = Flag<'boolean', boolean> | Flag<'boolean', boolean[], true>\ntype NumberFlag = Flag<'number', number> | Flag<'number', number[], true>\ntype AnyFlag = StringFlag | BooleanFlag | NumberFlag\n\n// Note: we use this description in getFlagListOutput, meow doesn't care\nexport type MeowFlags = Record<string, AnyFlag & { description: string }>\n\nexport const commonFlags: MeowFlags = {\n help: {\n type: 'boolean',\n default: false,\n shortFlag: 'h',\n description: 'Print this help.'\n },\n dryRun: {\n type: 'boolean',\n default: false,\n description: 'Do input validation for a command and exit 0 when input is ok'\n }\n}\n\nexport const outputFlags: MeowFlags = {\n json: {\n type: 'boolean',\n shortFlag: 'j',\n default: false,\n description: 'Output result as json'\n },\n markdown: {\n type: 'boolean',\n shortFlag: 'm',\n default: false,\n description: 'Output result as markdown'\n }\n}\n\nexport const validationFlags: MeowFlags = {\n all: {\n type: 'boolean',\n default: false,\n description: 'Include all issues'\n },\n strict: {\n type: 'boolean',\n default: false,\n description: 'Exits with an error code if any matching issues are found'\n }\n}\n","import meow from 'meow'\n\nimport { toSortedObject } from '@socketsecurity/registry/lib/objects'\nimport { escapeRegExp } from '@socketsecurity/registry/lib/regexps'\n\nimport { getLastFiveOfApiToken } from './api'\nimport { getFlagListOutput, getHelpListOutput } from './output-formatting'\nimport { getSetting } from './settings'\nimport constants from '../constants'\nimport { MeowFlags, commonFlags } from '../flags'\n\nimport type { Options } from 'meow'\n\nconst { SOCKET_CLI_SHOW_BANNER } = constants\n\nconst REDACTED = '<redacted>'\n\ninterface CliAlias {\n description: string\n argv: readonly string[]\n hidden?: boolean\n}\n\ntype CliAliases = Record<string, CliAlias>\n\ntype CliSubcommandRun = (\n argv: readonly string[],\n importMeta: ImportMeta,\n context: { parentName: string }\n) => Promise<void> | void\n\nexport interface CliSubcommand {\n description: string\n hidden?: boolean\n run: CliSubcommandRun\n}\n\n// Property names are picked such that the name is at the top when the props\n// get ordered by alphabet while flags is near the bottom and the help text\n// at the bottom, because they tend ot occupy the most lines of code.\nexport interface CliCommandConfig {\n commandName: string // tmp optional while we migrate\n description: string\n hidden: boolean\n flags: MeowFlags // tmp optional while we migrate\n help: (command: string, config: CliCommandConfig) => string\n}\n\ninterface MeowOptions extends Options<any> {\n aliases?: CliAliases\n argv: readonly string[]\n name: string\n}\n\n// For debugging. Whenever you call meowOrExit it will store the command here\n// This module exports a getter that returns the current value.\nlet lastSeenCommand = ''\n\nexport function getLastSeenCommand(): string {\n return lastSeenCommand\n}\n\nexport async function meowWithSubcommands(\n subcommands: Record<string, CliSubcommand>,\n options: MeowOptions\n): Promise<void> {\n const {\n aliases = {},\n argv,\n importMeta,\n name,\n ...additionalOptions\n } = { __proto__: null, ...options }\n const [commandOrAliasName, ...rawCommandArgv] = argv\n // If we got at least some args, then lets find out if we can find a command.\n if (commandOrAliasName) {\n const alias = aliases[commandOrAliasName]\n // First: Resolve argv data from alias if its an alias that's been given.\n const [commandName, ...commandArgv] = alias\n ? [...alias.argv, ...rawCommandArgv]\n : [commandOrAliasName, ...rawCommandArgv]\n // Second: Find a command definition using that data.\n const commandDefinition = commandName ? subcommands[commandName] : undefined\n // Third: If a valid command has been found, then we run it...\n if (commandDefinition) {\n return await commandDefinition.run(commandArgv, importMeta, {\n parentName: name\n })\n }\n }\n const flags = {\n ...commonFlags,\n ...additionalOptions.flags\n }\n // ...else we provide basic instructions and help.\n\n // Temp disable until we clear the --json and --markdown usage\n // Lazily access constants.ENV[SOCKET_CLI_SHOW_BANNER].\n if (constants.ENV[SOCKET_CLI_SHOW_BANNER]) {\n console.log(getAsciiHeader(name))\n }\n const cli = meow(\n `\n Usage\n $ ${name} <command>\n\n Commands\n ${getHelpListOutput(\n {\n ...toSortedObject(\n Object.fromEntries(\n Object.entries(subcommands).filter(\n ({ 1: subcommand }) => !subcommand.hidden\n )\n )\n ),\n ...toSortedObject(\n Object.fromEntries(\n Object.entries(aliases).filter(({ 1: alias }) => {\n const { hidden } = alias\n const cmdName = hidden ? '' : alias.argv[0]\n const subcommand = cmdName ? subcommands[cmdName] : undefined\n return subcommand && !subcommand.hidden\n })\n )\n )\n },\n 6\n )}\n\n Options\n ${getFlagListOutput(flags, 6)}\n\n Examples\n $ ${name} --help\n `,\n {\n argv,\n importMeta,\n ...additionalOptions,\n flags,\n autoHelp: false // otherwise we can't exit(0)\n }\n )\n if (!cli.flags['help'] && cli.flags['dryRun']) {\n console.log('[DryRun]: noop, call a sub-command; ok')\n process.exitCode = 0\n } else {\n cli.showHelp()\n }\n}\n\n/**\n * Note: meow will exit immediately if it calls its .showHelp()\n */\nexport function meowOrExit({\n allowUnknownFlags, // commands that pass-through args need to allow this\n argv,\n config,\n importMeta,\n parentName\n}: {\n allowUnknownFlags?: boolean\n argv: ReadonlyArray<string>\n config: CliCommandConfig\n parentName: string\n importMeta: ImportMeta\n}) {\n const command = `${parentName} ${config.commandName}`\n lastSeenCommand = command\n // Temp disable until we clear the --json and --markdown usage.\n // Lazily access constants.ENV[SOCKET_CLI_SHOW_BANNER].\n if (constants.ENV[SOCKET_CLI_SHOW_BANNER]) {\n console.log(getAsciiHeader(command))\n }\n\n // This exits if .printHelp() is called either by meow itself or by us.\n const cli = meow({\n argv,\n description: config.description,\n help: config.help(command, config),\n importMeta,\n flags: config.flags,\n allowUnknownFlags: Boolean(allowUnknownFlags),\n autoHelp: false // otherwise we can't exit(0)\n })\n if (cli.flags['help']) {\n cli.showHelp()\n }\n return cli\n}\n\nfunction getAsciiHeader(command: string) {\n // Note: In tests we return <redacted> because otherwise snapshots will fail.\n // The '@rollup/plugin-replace' will replace \"process.env['SOCKET_CLI_VERSION_HASH']\".\n const redacting = process.env['VITEST']\n const cliVersion = redacting\n ? REDACTED\n : // The '@rollup/plugin-replace' will replace \"process.env['SOCKET_CLI_VERSION_HASH']\".\n process.env['SOCKET_CLI_VERSION_HASH']\n const nodeVersion = redacting ? REDACTED : process.version\n const apiToken = getSetting('apiToken')\n const shownToken = redacting\n ? REDACTED\n : apiToken\n ? getLastFiveOfApiToken(apiToken)\n : 'no'\n const relCwd = redacting\n ? REDACTED\n : process\n .cwd()\n .replace(new RegExp(`^${escapeRegExp(constants.homePath)}`, 'i'), '~/')\n const body = `\n _____ _ _ /---------------\n | __|___ ___| |_ ___| |_ | Socket.dev CLI ver ${cliVersion}\n |__ | . | _| '_| -_| _| | Node: ${nodeVersion}, API token set: ${shownToken}\n |_____|___|___|_,_|___|_|.dev | Command: \\`${command}\\`, cwd: ${relCwd}`.trimStart()\n return ` ${body}\\n`\n}\n","// https://github.com/SocketDev/socket-python-cli/blob/6d4fc56faee68d3a4764f1f80f84710635bdaf05/socketsecurity/socketcli.py\n\nimport { runAction } from './run-action'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'action',\n description: 'Socket action command', // GitHub Action ?\n hidden: true,\n flags: {\n // This flag is unused\n // socketSecurityApiKey: { // deprecate this asap.\n // type: 'string',\n // default: 'env var SOCKET_SECURITY_API_KEY',\n // description: 'Socket API token'\n // },\n githubEventBefore: {\n type: 'string',\n default: '',\n description: 'Before marker'\n },\n githubEventAfter: {\n type: 'string',\n default: '',\n description: 'After marker'\n }\n },\n help: (command, { flags }) => `\n Usage\n $ ${command} [options]\n\n Options\n ${getFlagListOutput(flags, 6)}\n `\n}\n\nexport const cmdAction = {\n description: config.description,\n hidden: config.hidden,\n run: run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const githubEventBefore = String(cli.flags['githubEventBefore'] || '')\n const githubEventAfter = String(cli.flags['githubEventAfter'] || '')\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await runAction(githubEventBefore, githubEventAfter)\n}\n","import fs from 'node:fs/promises'\n\n// @ts-ignore\nimport ScreenWidget from 'blessed/lib/widgets/screen'\nimport contrib from 'blessed-contrib'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nimport type { Widgets } from 'blessed' // Note: Widgets does not seem to actually work as code :'(\n\ntype FormattedData = {\n top_five_alert_types: { [key: string]: number }\n total_critical_alerts: { [key: string]: number }\n total_high_alerts: { [key: string]: number }\n total_medium_alerts: { [key: string]: number }\n total_low_alerts: { [key: string]: number }\n total_critical_added: { [key: string]: number }\n total_medium_added: { [key: string]: number }\n total_low_added: { [key: string]: number }\n total_high_added: { [key: string]: number }\n total_critical_prevented: { [key: string]: number }\n total_high_prevented: { [key: string]: number }\n total_medium_prevented: { [key: string]: number }\n total_low_prevented: { [key: string]: number }\n}\n\n// Note: This maps `new Date(date).getMonth()` to English three letters\nexport const Months = [\n 'Jan',\n 'Feb',\n 'Mar',\n 'Apr',\n 'May',\n 'Jun',\n 'Jul',\n 'Aug',\n 'Sep',\n 'Oct',\n 'Nov',\n 'Dec'\n] as const\n\nconst METRICS = [\n 'total_critical_alerts',\n 'total_high_alerts',\n 'total_medium_alerts',\n 'total_low_alerts',\n 'total_critical_added',\n 'total_medium_added',\n 'total_low_added',\n 'total_high_added',\n 'total_critical_prevented',\n 'total_high_prevented',\n 'total_medium_prevented',\n 'total_low_prevented'\n] as const\n\nexport async function displayAnalytics({\n apiToken,\n filePath,\n outputJson,\n repo,\n scope,\n time\n}: {\n apiToken: string\n scope: string\n time: number\n repo: string\n outputJson: boolean\n filePath: string\n}): Promise<void> {\n const spinner = new Spinner({ text: 'Fetching analytics data' }).start()\n\n let data: undefined | { [key: string]: any }[]\n if (scope === 'org') {\n data = await fetchOrgAnalyticsData(time, spinner, apiToken)\n } else if (repo) {\n data = await fetchRepoAnalyticsData(repo, time, spinner, apiToken)\n }\n\n if (data) {\n if (outputJson && !filePath) {\n console.log(data)\n } else if (filePath) {\n try {\n await fs.writeFile(filePath, JSON.stringify(data), 'utf8')\n console.log(`Data successfully written to ${filePath}`)\n } catch (e: any) {\n console.error(e)\n }\n } else {\n const fdata =\n scope === 'org' ? formatData(data, 'org') : formatData(data, 'repo')\n displayAnalyticsScreen(fdata)\n }\n }\n}\n\nfunction displayAnalyticsScreen(data: FormattedData): void {\n const screen: Widgets.Screen = new ScreenWidget({})\n const grid = new contrib.grid({ rows: 5, cols: 4, screen })\n\n renderLineCharts(\n grid,\n screen,\n 'Total critical alerts',\n [0, 0, 1, 2],\n data['total_critical_alerts']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total high alerts',\n [0, 2, 1, 2],\n data['total_high_alerts']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total critical alerts added to the main branch',\n [1, 0, 1, 2],\n data['total_critical_added']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total high alerts added to the main branch',\n [1, 2, 1, 2],\n data['total_high_added']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total critical alerts prevented from the main branch',\n [2, 0, 1, 2],\n data['total_critical_prevented']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total high alerts prevented from the main branch',\n [2, 2, 1, 2],\n data['total_high_prevented']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total medium alerts prevented from the main branch',\n [3, 0, 1, 2],\n data['total_medium_prevented']\n )\n renderLineCharts(\n grid,\n screen,\n 'Total low alerts prevented from the main branch',\n [3, 2, 1, 2],\n data['total_low_prevented']\n )\n\n const bar = grid.set(4, 0, 1, 2, contrib.bar, {\n label: 'Top 5 alert types',\n barWidth: 10,\n barSpacing: 17,\n xOffset: 0,\n maxHeight: 9,\n barBgColor: 'magenta'\n })\n\n screen.append(bar) //must append before setting data\n\n bar.setData({\n titles: Object.keys(data.top_five_alert_types),\n data: Object.values(data.top_five_alert_types)\n })\n\n screen.render()\n\n screen.key(['escape', 'q', 'C-c'], () => process.exit(0))\n}\n\nasync function fetchOrgAnalyticsData(\n time: number,\n spinner: Spinner,\n apiToken: string\n): Promise<{ [key: string]: any }[] | undefined> {\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getOrgAnalytics(time.toString()),\n 'fetching analytics data'\n )\n\n if (result.success === false) {\n handleUnsuccessfulApiResponse('getOrgAnalytics', result, spinner)\n return undefined\n }\n\n spinner.stop()\n\n if (!result.data.length) {\n console.log('No analytics data is available for this organization yet.')\n return undefined\n }\n\n return result.data\n}\n\nasync function fetchRepoAnalyticsData(\n repo: string,\n time: number,\n spinner: Spinner,\n apiToken: string\n): Promise<{ [key: string]: any }[] | undefined> {\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getRepoAnalytics(repo, time.toString()),\n 'fetching analytics data'\n )\n\n if (result.success === false) {\n handleUnsuccessfulApiResponse('getRepoAnalytics', result, spinner)\n return undefined\n }\n\n spinner.stop()\n\n if (!result.data.length) {\n console.log('No analytics data is available for this organization yet.')\n return undefined\n }\n\n return result.data\n}\n\nfunction formatData(\n data: { [key: string]: any }[],\n scope: string\n): FormattedData {\n const formattedData = <Omit<FormattedData, 'top_five_alert_types'>>{}\n const sortedTopFiveAlerts: { [key: string]: number } = {}\n const totalTopAlerts: { [key: string]: number } = {}\n\n for (const metric of METRICS) {\n formattedData[metric] = {}\n }\n if (scope === 'org') {\n for (const entry of data) {\n const topFiveAlertTypes = entry['top_five_alert_types']\n for (const type of Object.keys(topFiveAlertTypes)) {\n const count = topFiveAlertTypes[type] ?? 0\n if (!totalTopAlerts[type]) {\n totalTopAlerts[type] = count\n } else {\n totalTopAlerts[type] += count\n }\n }\n }\n for (const metric of METRICS) {\n const formatted = formattedData[metric]\n for (const entry of data) {\n const date = formatDate(entry['created_at'])\n if (!formatted[date]) {\n formatted[date] = entry[metric]!\n } else {\n formatted[date] += entry[metric]!\n }\n }\n }\n } else if (scope === 'repo') {\n for (const entry of data) {\n const topFiveAlertTypes = entry['top_five_alert_types']\n for (const type of Object.keys(topFiveAlertTypes)) {\n const count = topFiveAlertTypes[type] ?? 0\n if (!totalTopAlerts[type]) {\n totalTopAlerts[type] = count\n } else if (count > (totalTopAlerts[type] ?? 0)) {\n totalTopAlerts[type] = count\n }\n }\n }\n for (const entry of data) {\n for (const metric of METRICS) {\n formattedData[metric]![formatDate(entry['created_at'])] = entry[metric]\n }\n }\n }\n\n const topFiveAlertEntries = Object.entries(totalTopAlerts)\n .sort(({ 1: a }, { 1: b }) => b - a)\n .slice(0, 5)\n for (const { 0: key, 1: value } of topFiveAlertEntries) {\n sortedTopFiveAlerts[key] = value\n }\n\n return {\n ...formattedData,\n top_five_alert_types: sortedTopFiveAlerts\n }\n}\nfunction formatDate(date: string): string {\n return `${Months[new Date(date).getMonth()]} ${new Date(date).getDate()}`\n}\n\nfunction renderLineCharts(\n grid: contrib.grid,\n screen: any,\n title: string,\n coords: number[],\n data: { [key: string]: number }\n): void {\n const line = grid.set(...coords, contrib.line, {\n style: { line: 'cyan', text: 'cyan', baseline: 'black' },\n xLabelPadding: 0,\n xPadding: 0,\n xOffset: 0,\n wholeNumbersOnly: true,\n legend: {\n width: 1\n },\n label: title\n })\n\n screen.append(line)\n\n const lineData = {\n x: Object.keys(data),\n y: Object.values(data)\n }\n\n line.setData([lineData])\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { displayAnalytics } from './display-analytics'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'analytics',\n description: `Look up analytics data`,\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n scope: {\n type: 'string',\n shortFlag: 's',\n default: 'org',\n description:\n \"Scope of the analytics data - either 'org' or 'repo', default: org\"\n },\n time: {\n type: 'number',\n shortFlag: 't',\n default: 7,\n description: 'Time filter - either 7, 30 or 90, default: 7'\n },\n repo: {\n type: 'string',\n shortFlag: 'r',\n default: '',\n description: 'Name of the repository'\n },\n file: {\n type: 'string',\n shortFlag: 'f',\n default: '',\n description: 'Path to a local file to save the output'\n }\n },\n help: (command, { flags }) => `\n Usage\n $ ${command} --scope=<scope> --time=<time filter>\n\n Default parameters are set to show the organization-level analytics over the\n last 7 days.\n\n Options\n ${getFlagListOutput(flags, 6)}\n\n Examples\n $ ${command} --scope=org --time=7\n $ ${command} --scope=org --time=30\n $ ${command} --scope=repo --repo=test-repo --time=30\n `\n}\n\nexport const cmdAnalytics = {\n description: config.description,\n hidden: config.hidden,\n run: run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const { repo, scope, time } = cli.flags\n\n const badScope = scope !== 'org' && scope !== 'repo'\n const badTime = time !== 7 && time !== 30 && time !== 90\n const badRepo = scope === 'repo' && !repo\n\n if (badScope || badTime || badRepo) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Scope must be \"repo\" or \"org\" ${badScope ? colors.red('(bad!)') : colors.green('(ok)')}\\n\n - The time filter must either be 7, 30 or 90 ${badTime ? colors.red('(bad!)') : colors.green('(ok)')}\\n\n - Repository name using --repo when scope is \"repo\" ${badRepo ? colors.red('(bad!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API token.'\n )\n }\n\n return await displayAnalytics({\n apiToken,\n scope,\n time,\n repo: String(repo || ''),\n outputJson: Boolean(cli.flags['json']),\n filePath: String(cli.flags['file'] || '')\n })\n}\n","import { Separator, select } from '@socketsecurity/registry/lib/prompts'\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\ntype Choice<Value> = {\n description?: string\n disabled?: boolean | string\n name?: string\n type?: never\n value: Value\n}\n\ntype AuditChoice = Choice<string>\n\ntype AuditChoices = (Separator | AuditChoice)[]\n\nexport async function getAuditLog({\n apiToken,\n orgSlug,\n outputJson,\n outputMarkdown,\n page,\n perPage,\n type\n}: {\n apiToken: string\n outputJson: boolean\n outputMarkdown: boolean\n orgSlug: string\n page: number\n perPage: number\n type: string\n}): Promise<void> {\n const spinner = new Spinner({\n text: `Looking up audit log for ${orgSlug}\\n`\n }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getAuditLogEvents(orgSlug, {\n outputJson,\n outputMarkdown,\n orgSlug,\n type,\n page,\n per_page: perPage\n }),\n `Looking up audit log for ${orgSlug}\\n`\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('getAuditLogEvents', result, spinner)\n return\n }\n\n spinner.stop()\n\n const data: AuditChoices = []\n const logDetails: { [key: string]: string } = {}\n\n for (const d of result.data.results) {\n const { created_at } = d\n if (created_at) {\n const name = `${new Date(created_at).toLocaleDateString('en-us', { year: 'numeric', month: 'numeric', day: 'numeric' })} - ${d.user_email} - ${d.type} - ${d.ip_address} - ${d.user_agent}`\n data.push(<AuditChoice>{ name }, new Separator())\n logDetails[name] = JSON.stringify(d.payload)\n }\n }\n\n console.log(\n logDetails[\n (await select({\n message: type\n ? `\\n Audit log for: ${orgSlug} with type: ${type}\\n`\n : `\\n Audit log for: ${orgSlug}\\n`,\n choices: data,\n pageSize: 30\n })) as any\n ]\n )\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { getAuditLog } from './get-audit-log'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'audit-log',\n description: 'Look up the audit log for an organization',\n hidden: false,\n flags: {\n type: {\n type: 'string',\n shortFlag: 't',\n default: '',\n description: 'Type of log event'\n },\n perPage: {\n type: 'number',\n shortFlag: 'pp',\n default: 30,\n description: 'Results per page - default is 30'\n },\n page: {\n type: 'number',\n shortFlag: 'p',\n default: 1,\n description: 'Page number - default is 1'\n },\n ...commonFlags,\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg\n `\n}\n\nexport const cmdAuditLog = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const type = String(cli.flags['type'] || '')\n const [orgSlug = ''] = cli.input\n\n if (!orgSlug) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await getAuditLog({\n apiToken,\n orgSlug,\n outputJson: Boolean(cli.flags['json']),\n outputMarkdown: Boolean(cli.flags['markdown']),\n page: Number(cli.flags['page'] || 0),\n perPage: Number(cli.flags['perPage'] || 0),\n type: type.charAt(0).toUpperCase() + type.slice(1)\n })\n}\n","import { promises as fs } from 'fs'\nimport { existsSync } from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { runBin } from '@socketsecurity/registry/lib/npm'\n\nimport constants from '../../constants'\n\nconst {\n SBOM_SIGN_ALGORITHM, // Algorithm. Example: RS512\n SBOM_SIGN_PRIVATE_KEY, // Location to the RSA private key\n SBOM_SIGN_PUBLIC_KEY // Optional. Location to the RSA public key\n} = process.env\n\nconst { NPM, PNPM, cdxgenBinPath, synpBinPath } = constants\n\nconst nodejsPlatformTypes = new Set([\n 'javascript',\n 'js',\n 'nodejs',\n NPM,\n PNPM,\n 'ts',\n 'tsx',\n 'typescript'\n])\n\nexport async function runCycloneDX(yargv: any) {\n let cleanupPackageLock = false\n if (\n yargv.type !== 'yarn' &&\n nodejsPlatformTypes.has(yargv.type) &&\n existsSync('./yarn.lock')\n ) {\n if (existsSync('./package-lock.json')) {\n yargv.type = NPM\n } else {\n // Use synp to create a package-lock.json from the yarn.lock,\n // based on the node_modules folder, for a more accurate SBOM.\n try {\n await runBin(await fs.realpath(synpBinPath), [\n '--source-file',\n './yarn.lock'\n ])\n yargv.type = NPM\n cleanupPackageLock = true\n } catch {}\n }\n }\n\n await runBin(await fs.realpath(cdxgenBinPath), argvToArray(yargv), {\n env: {\n NODE_ENV: '',\n SBOM_SIGN_ALGORITHM,\n SBOM_SIGN_PRIVATE_KEY,\n SBOM_SIGN_PUBLIC_KEY\n },\n stdio: 'inherit'\n })\n if (cleanupPackageLock) {\n try {\n await fs.rm('./package-lock.json')\n } catch {}\n }\n const fullOutputPath = path.join(process.cwd(), yargv.output)\n if (existsSync(fullOutputPath)) {\n console.log(colors.cyanBright(`${yargv.output} created!`))\n }\n}\n\nfunction argvToArray(argv: {\n [key: string]: boolean | null | number | string | (string | number)[]\n}): string[] {\n if (argv['help']) return ['--help']\n const result = []\n for (const { 0: key, 1: value } of Object.entries(argv)) {\n if (key === '_' || key === '--') continue\n if (key === 'babel' || key === 'install-deps' || key === 'validate') {\n // cdxgen documents no-babel, no-install-deps, and no-validate flags so\n // use them when relevant.\n result.push(`--${value ? key : `no-${key}`}`)\n } else if (value === true) {\n result.push(`--${key}`)\n } else if (typeof value === 'string') {\n result.push(`--${key}`, String(value))\n } else if (Array.isArray(value)) {\n result.push(`--${key}`, ...value.map(String))\n }\n }\n if (argv['--']) {\n result.push('--', ...(argv as any)['--'])\n }\n return result\n}\n","// import { meowOrExit } from '../../utils/meow-with-subcommands'\nimport process from 'node:process'\n\nimport yargsParse from 'yargs-parser'\n\nimport { pluralize } from '@socketsecurity/registry/lib/words'\n\nimport { runCycloneDX } from './run-cyclonedx'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\n// TODO: convert yargs to meow. Or convert all the other things to yargs.\nconst toLower = (arg: string) => arg.toLowerCase()\nconst arrayToLower = (arg: string[]) => arg.map(toLower)\nconst yargsConfig = {\n configuration: {\n 'camel-case-expansion': false,\n 'strip-aliased': true,\n 'parse-numbers': false,\n 'populate--': true,\n 'unknown-options-as-args': true\n },\n coerce: {\n author: arrayToLower,\n filter: arrayToLower,\n only: arrayToLower,\n profile: toLower,\n standard: arrayToLower,\n type: toLower\n },\n default: {\n //author: ['OWASP Foundation'],\n //'auto-compositions': true,\n //babel: true,\n //evidence: false,\n //'include-crypto': false,\n //'include-formulation': false,\n\n // Default 'install-deps' to `false` and 'lifecycle' to 'pre-build' to\n // sidestep arbitrary code execution during a cdxgen scan.\n // https://github.com/CycloneDX/cdxgen/issues/1328\n 'install-deps': false,\n lifecycle: 'pre-build',\n\n //output: 'bom.json',\n //profile: 'generic',\n //'project-version': '',\n //recurse: true,\n //'server-host': '127.0.0.1',\n //'server-port': '9090',\n //'spec-version': '1.5',\n type: 'js'\n //validate: true,\n },\n alias: {\n help: ['h'],\n output: ['o'],\n print: ['p'],\n recurse: ['r'],\n 'resolve-class': ['c'],\n type: ['t'],\n version: ['v']\n },\n array: [\n { key: 'author', type: 'string' },\n { key: 'exclude', type: 'string' },\n { key: 'filter', type: 'string' },\n { key: 'only', type: 'string' },\n { key: 'standard', type: 'string' }\n ],\n boolean: [\n 'auto-compositions',\n 'babel',\n 'deep',\n 'evidence',\n 'fail-on-error',\n 'generate-key-and-sign',\n 'help',\n 'include-formulation',\n 'include-crypto',\n 'install-deps',\n 'print',\n 'required-only',\n 'server',\n 'validate',\n 'version'\n ],\n string: [\n 'api-key',\n 'lifecycle',\n 'output',\n 'parent-project-id',\n 'profile',\n 'project-group',\n 'project-name',\n 'project-version',\n 'project-id',\n 'server-host',\n 'server-port',\n 'server-url',\n 'spec-version'\n ]\n}\n\nconst config: CliCommandConfig = {\n commandName: 'cdxgen',\n description: 'Create an SBOM with CycloneDX generator (cdxgen)',\n hidden: false,\n flags: {\n // TODO: convert from yargsConfig\n },\n help: (command, config) => `\n Usage\n $ ${command} [options]\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n `\n}\n\nexport const cmdCdxgen = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n allowUnknownFlags: true,\n argv: argv.filter(s => s !== '--help' && s !== '-h'), // Don't let meow take over --help\n config,\n importMeta,\n parentName\n })\n //\n //\n // if (cli.input.length)\n // console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n // - Unexpected arguments\\n\n // `)\n // config.help(parentName, config)\n // return\n // }\n\n // TODO: convert to meow\n const yargv = {\n ...yargsParse(argv as Array<string>, yargsConfig)\n } as any // as Record<string, unknown>;\n\n const unknown: Array<string> = yargv._\n const { length: unknownLength } = unknown\n if (unknownLength) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `Unknown ${pluralize('argument', unknownLength)}: ${yargv._.join(', ')}`\n )\n return\n }\n\n if (yargv.output === undefined) {\n yargv.output = 'socket-cdx.json'\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await runCycloneDX(yargv)\n}\n","// @ts-ignore\nimport chalkTable from 'chalk-table'\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { AuthError } from '../../utils/errors'\nimport { getDefaultToken, setupSdk } from '../../utils/sdk'\n\nexport async function findDependencies({\n limit,\n offset,\n outputJson\n}: {\n outputJson: boolean\n limit: number\n offset: number\n}): Promise<void> {\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n const spinner = new Spinner({ text: 'Searching dependencies...' }).start()\n const socketSdk = await setupSdk(apiToken)\n\n const result = await handleApiCall(\n socketSdk.searchDependencies({ limit, offset }),\n 'Searching dependencies'\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('searchDependencies', result, spinner)\n return\n }\n\n spinner.stop('Organization dependencies:')\n\n if (outputJson) {\n console.log(result.data)\n return\n }\n\n const options = {\n columns: [\n { field: 'namespace', name: colors.cyan('Namespace') },\n { field: 'name', name: colors.cyan('Name') },\n { field: 'version', name: colors.cyan('Version') },\n { field: 'repository', name: colors.cyan('Repository') },\n { field: 'branch', name: colors.cyan('Branch') },\n { field: 'type', name: colors.cyan('Type') },\n { field: 'direct', name: colors.cyan('Direct') }\n ]\n }\n\n console.log(chalkTable(options, result.data.rows))\n}\n","import { findDependencies } from './find-dependencies'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'dependencies',\n description:\n 'Search for any dependency that is being used in your organization',\n hidden: false,\n flags: {\n ...commonFlags,\n limit: {\n type: 'number',\n shortFlag: 'l',\n default: 50,\n description: 'Maximum number of dependencies returned'\n },\n offset: {\n type: 'number',\n shortFlag: 'o',\n default: 0,\n description: 'Page number'\n },\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n ${command}\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n ${command} --limit 20 --offset 10\n `\n}\n\nexport const cmdScanCreate = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n // TODO: markdown flag is ignored\n await findDependencies({\n limit: Number(cli.flags['limit'] || 0) || 0,\n offset: Number(cli.flags['offset'] || 0) || 0,\n outputJson: Boolean(cli.flags['json'])\n })\n}\n","import fs from 'node:fs'\nimport util from 'node:util'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleAPIError, queryAPI } from '../../utils/api'\n\nexport async function getDiffScan(\n {\n after,\n before,\n file,\n orgSlug,\n outputJson\n }: {\n outputJson: boolean\n outputMarkdown: boolean\n before: string\n after: string\n preview: boolean\n orgSlug: string\n file: string\n },\n apiToken: string\n): Promise<void> {\n const spinnerText = 'Getting diff scan... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const response = await queryAPI(\n `${orgSlug}/full-scans/diff?before=${before}&after=${after}&preview`,\n apiToken\n )\n const data = await response.json()\n\n if (!response.ok) {\n const err = await handleAPIError(response.status)\n spinner.error(`${colors.bgRed(colors.white(response.statusText))}: ${err}`)\n return\n }\n\n spinner.stop()\n\n if (file && !outputJson) {\n fs.writeFile(file, JSON.stringify(data), err => {\n err\n ? console.error(err)\n : console.log(`Data successfully written to ${file}`)\n })\n return\n }\n\n if (outputJson) {\n console.log(`\\n Diff scan result: \\n`)\n console.log(\n util.inspect(data, { showHidden: false, depth: null, colors: true })\n )\n console.log(\n `\\n View this diff scan in the Socket dashboard: ${colors.cyan((data as any)?.['diff_report_url'])}`\n )\n return\n }\n\n console.log('Diff scan result:')\n console.log(data)\n console.log(\n `\\n 📝 To display the detailed report in the terminal, use the --json flag \\n`\n )\n console.log(\n `\\n View this diff scan in the Socket dashboard: ${colors.cyan((data as any)?.['diff_report_url'])}`\n )\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { getDiffScan } from './get-diff-scan'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'get',\n description: 'Get a diff scan for an organization',\n hidden: false,\n flags: {\n ...commonFlags,\n before: {\n type: 'string',\n shortFlag: 'b',\n default: '',\n description: 'The full scan ID of the base scan'\n },\n after: {\n type: 'string',\n shortFlag: 'a',\n default: '',\n description: 'The full scan ID of the head scan'\n },\n preview: {\n type: 'boolean',\n shortFlag: 'p',\n default: true,\n description: 'A boolean flag to persist or not the diff scan result'\n },\n file: {\n type: 'string',\n shortFlag: 'f',\n default: '',\n description: 'Path to a local file where the output should be saved'\n },\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug> --before=<before> --after=<after>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeCorp --before=aaa0aa0a-aaaa-0000-0a0a-0000000a00a0 --after=aaa1aa1a-aaaa-1111-1a1a-1111111a11a1\n `\n}\n\nexport const cmdDiffScanGet = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const before = String(cli.flags['before'] || '')\n const after = String(cli.flags['after'] || '')\n const [orgSlug = ''] = cli.input\n\n if (!before || !after || cli.input.length < 1) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Specify a before and after full scan ID ${!before && !after ? colors.red('(missing before and after!)') : !before ? colors.red('(missing before!)') : !after ? colors.red('(missing after!)') : colors.green('(ok)')}\\n\n - To get full scans IDs, you can run the command \"socket scan list <your org slug>\".\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await getDiffScan(\n {\n outputJson: Boolean(cli.flags['json']),\n outputMarkdown: Boolean(cli.flags['markdown']),\n before,\n after,\n preview: Boolean(cli.flags['preview']),\n orgSlug,\n file: String(cli.flags['file'] || '')\n },\n apiToken\n )\n}\n","import { cmdDiffScanGet } from './cmd-diff-scan-get'\nimport { meowWithSubcommands } from '../../utils/meow-with-subcommands'\n\nimport type { CliSubcommand } from '../../utils/meow-with-subcommands'\n\nconst description = 'Diff scans related commands'\n\nexport const cmdDiffScan: CliSubcommand = {\n description,\n async run(argv, importMeta, { parentName }) {\n await meowWithSubcommands(\n {\n get: cmdDiffScanGet\n },\n {\n argv,\n description,\n importMeta,\n name: parentName + ' diff-scan'\n }\n )\n }\n}\n","import { getManifestData } from '@socketsecurity/registry'\nimport { runScript } from '@socketsecurity/registry/lib/npm'\nimport {\n fetchPackagePackument,\n readPackageJson\n} from '@socketsecurity/registry/lib/packages'\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport constants from '../../constants'\nimport {\n Arborist,\n SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES,\n SafeArborist\n} from '../../shadow/arborist/lib/arborist'\nimport {\n findPackageNodes,\n getCveInfoByPackage,\n getPackagesAlerts,\n updateNode\n} from '../../shadow/arborist/lib/arborist/reify'\n// import { detect } from '../../utils/package-environment-detector'\n\nimport type { SafeNode } from '../../shadow/arborist/lib/node'\n\nconst { NPM } = constants\n\nfunction isTopLevel(tree: SafeNode, node: SafeNode): boolean {\n return tree.children.get(node.name) === node\n}\n\nexport async function runFix() {\n const spinner = new Spinner().start()\n const cwd = process.cwd()\n const editablePkgJson = await readPackageJson(cwd, { editable: true })\n // const agentDetails = await detect()\n\n const arb = new SafeArborist({\n path: cwd,\n ...SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES\n })\n await arb.reify()\n const alerts = await getPackagesAlerts(arb as any, {\n consolidate: true,\n includeExisting: true,\n includeUnfixable: false\n })\n const infoByPkg = getCveInfoByPackage(alerts)\n await arb.buildIdealTree()\n if (infoByPkg) {\n for (const { 0: name, 1: infos } of infoByPkg) {\n let revertToIdealTree = arb.idealTree!\n arb.idealTree = null\n // eslint-disable-next-line no-await-in-loop\n await arb.buildIdealTree()\n const tree = arb.idealTree!\n const hasUpgrade = !!getManifestData(NPM, name)\n if (hasUpgrade) {\n spinner.stop()\n console.log(`Skipping ${name}. Socket Optimize package exists.`)\n spinner.start()\n continue\n }\n const nodes = findPackageNodes(tree, name)\n const packument =\n nodes.length && infos.length\n ? // eslint-disable-next-line no-await-in-loop\n await fetchPackagePackument(name)\n : null\n if (packument) {\n for (\n let i = 0, { length: nodesLength } = nodes;\n i < nodesLength;\n i += 1\n ) {\n const node = nodes[i]!\n for (\n let j = 0, { length: infosLength } = infos;\n j < infosLength;\n j += 1\n ) {\n const { firstPatchedVersionIdentifier, vulnerableVersionRange } =\n infos[j]!\n const { version: oldVersion } = node\n if (\n updateNode(\n node,\n packument,\n vulnerableVersionRange,\n firstPatchedVersionIdentifier\n )\n ) {\n try {\n // eslint-disable-next-line no-await-in-loop\n await runScript('test', [], { stdio: 'pipe' })\n spinner.info(`Patched ${name} ${oldVersion} -> ${node.version}`)\n spinner.start()\n if (isTopLevel(tree, node)) {\n for (const depField of [\n 'dependencies',\n 'optionalDependencies',\n 'peerDependencies'\n ]) {\n const oldVersion = (\n editablePkgJson.content[depField] as any\n )?.[name]\n if (oldVersion) {\n const decorator = /^[~^]/.exec(oldVersion)?.[0] ?? ''\n ;(editablePkgJson as any).content[depField][name] =\n `${decorator}${node.version}`\n }\n }\n }\n // eslint-disable-next-line no-await-in-loop\n await editablePkgJson.save()\n } catch {\n spinner.error(`Reverting ${name} to ${oldVersion}`)\n spinner.start()\n arb.idealTree = revertToIdealTree\n }\n } else {\n spinner.stop()\n console.log(`Could not patch ${name} ${oldVersion}`)\n spinner.start()\n }\n }\n }\n }\n }\n }\n const arb2 = new Arborist({ path: cwd })\n arb2.idealTree = arb.idealTree\n await arb2.reify()\n spinner.stop()\n}\n","import { runFix } from './run-fix'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'fix',\n description: 'Fix \"fixable\" Socket alerts',\n hidden: true,\n flags: {\n ...commonFlags\n },\n help: (command, config) => `\n Usage\n $ ${command}\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n `\n}\n\nexport const cmdFix = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await runFix()\n}\n","export function objectSome(obj: Record<string, any>): boolean {\n for (const key in obj) {\n if (obj[key]) {\n return true\n }\n }\n return false\n}\n\nexport function pick<T extends Record<string, any>, K extends keyof T>(\n input: T,\n keys: K[] | ReadonlyArray<K>\n): Pick<T, K> {\n const result: Partial<Pick<T, K>> = {}\n for (const key of keys) {\n result[key] = input[key]\n }\n return result as Pick<T, K>\n}\n","export function stringJoinWithSeparateFinalSeparator(\n list: string[],\n separator: string = ' and '\n): string {\n const values = list.filter(Boolean)\n const { length } = values\n if (!length) {\n return ''\n }\n if (length === 1) {\n return values[0]!\n }\n const finalValue = values.pop()\n return `${values.join(', ')}${separator}${finalValue}`\n}\n","import { pick } from '../objects'\nimport { stringJoinWithSeparateFinalSeparator } from '../strings'\n\nimport type { SocketSdkReturnType } from '@socketsecurity/sdk'\n\nexport type SocketSdkAlertList =\n SocketSdkReturnType<'getIssuesByNPMPackage'>['data']\n\nexport type SocketSdkAlert = SocketSdkAlertList[number]['value'] extends\n | infer U\n | undefined\n ? U\n : never\n\n// Ordered from most severe to least.\nconst SEVERITIES_BY_ORDER: SocketSdkAlert['severity'][] = [\n 'critical',\n 'high',\n 'middle',\n 'low'\n]\n\nfunction getDesiredSeverities(\n lowestToInclude: SocketSdkAlert['severity'] | undefined\n): SocketSdkAlert['severity'][] {\n const result: SocketSdkAlert['severity'][] = []\n for (const severity of SEVERITIES_BY_ORDER) {\n result.push(severity)\n if (severity === lowestToInclude) {\n break\n }\n }\n return result\n}\n\nexport function formatSeverityCount(\n severityCount: Record<SocketSdkAlert['severity'], number>\n): string {\n const summary: string[] = []\n for (const severity of SEVERITIES_BY_ORDER) {\n if (severityCount[severity]) {\n summary.push(`${severityCount[severity]} ${severity}`)\n }\n }\n return stringJoinWithSeparateFinalSeparator(summary)\n}\n\nexport function getSeverityCount(\n issues: SocketSdkAlertList,\n lowestToInclude: SocketSdkAlert['severity'] | undefined\n): Record<SocketSdkAlert['severity'], number> {\n const severityCount = pick(\n { low: 0, middle: 0, high: 0, critical: 0 },\n getDesiredSeverities(lowestToInclude)\n ) as Record<SocketSdkAlert['severity'], number>\n\n for (const issue of issues) {\n const { value } = issue\n if (!value) {\n continue\n }\n if (severityCount[value.severity] !== undefined) {\n severityCount[value.severity] += 1\n }\n }\n return severityCount\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { PackageData } from './get-package-info'\nimport { getSeverityCount } from '../../utils/alert/severity'\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { getPublicToken, setupSdk } from '../../utils/sdk'\n\nexport async function fetchPackageInfo(\n pkgName: string,\n pkgVersion: string,\n includeAllIssues: boolean,\n spinner: Spinner\n): Promise<void | PackageData> {\n const socketSdk = await setupSdk(getPublicToken())\n const result = await handleApiCall(\n socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion),\n 'looking up package'\n )\n const scoreResult = await handleApiCall(\n socketSdk.getScoreByNPMPackage(pkgName, pkgVersion),\n 'looking up package score'\n )\n\n if (result.success === false) {\n return handleUnsuccessfulApiResponse(\n 'getIssuesByNPMPackage',\n result,\n spinner\n )\n }\n\n if (scoreResult.success === false) {\n return handleUnsuccessfulApiResponse(\n 'getScoreByNPMPackage',\n scoreResult,\n spinner\n )\n }\n\n const severityCount = getSeverityCount(\n result.data,\n includeAllIssues ? undefined : 'high'\n )\n\n return {\n data: result.data,\n severityCount,\n score: scoreResult.data\n }\n}\n","import process from 'node:process'\n\nimport colors from 'yoctocolors-cjs'\n\nimport constants from '@socketsecurity/registry/lib/constants'\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { PackageData } from './get-package-info'\nimport { formatSeverityCount } from '../../utils/alert/severity'\nimport { ColorOrMarkdown } from '../../utils/color-or-markdown'\nimport { objectSome } from '../../utils/objects'\nimport {\n getSocketDevAlertUrl,\n getSocketDevPackageOverviewUrl\n} from '../../utils/socket-url'\n\nimport type { SocketSdkReturnType } from '@socketsecurity/sdk'\n\nconst { NPM } = constants\n\nexport function formatPackageInfo(\n { data, score, severityCount }: PackageData,\n {\n name,\n outputJson,\n outputMarkdown,\n pkgName,\n pkgVersion,\n strict\n }: {\n includeAllIssues: boolean\n outputJson: boolean\n outputMarkdown: boolean\n pkgName: string\n pkgVersion: string\n strict: boolean\n } & { name: string },\n spinner: Spinner\n): void {\n if (outputJson) {\n console.log(JSON.stringify(data, undefined, 2))\n } else {\n console.log('\\nPackage report card:')\n const scoreResult = {\n 'Supply Chain Risk': Math.floor(score.supplyChainRisk.score * 100),\n Maintenance: Math.floor(score.maintenance.score * 100),\n Quality: Math.floor(score.quality.score * 100),\n Vulnerabilities: Math.floor(score.vulnerability.score * 100),\n License: Math.floor(score.license.score * 100)\n }\n Object.entries(scoreResult).map(score =>\n console.log(`- ${score[0]}: ${formatScore(score[1])}`)\n )\n console.log('\\n')\n if (objectSome(severityCount)) {\n spinner[strict ? 'error' : 'success'](\n `Package has these issues: ${formatSeverityCount(severityCount)}`\n )\n formatPackageIssuesDetails(data, outputMarkdown)\n } else {\n spinner.success('Package has no issues')\n }\n\n const format = new ColorOrMarkdown(!!outputMarkdown)\n const url = getSocketDevPackageOverviewUrl(NPM, pkgName, pkgVersion)\n\n console.log('\\n')\n if (pkgVersion === 'latest') {\n console.log(\n `Detailed info on socket.dev: ${format.hyperlink(`${pkgName}`, url, { fallbackToUrl: true })}`\n )\n } else {\n console.log(\n `Detailed info on socket.dev: ${format.hyperlink(`${pkgName} v${pkgVersion}`, url, { fallbackToUrl: true })}`\n )\n }\n if (!outputMarkdown) {\n console.log(\n colors.dim(\n `\\nOr rerun ${colors.italic(name)} using the ${colors.italic('--json')} flag to get full JSON output`\n )\n )\n }\n }\n\n if (strict && objectSome(severityCount)) {\n process.exit(1)\n }\n}\n\nfunction formatPackageIssuesDetails(\n packageData: SocketSdkReturnType<'getIssuesByNPMPackage'>['data'],\n outputMarkdown: boolean\n) {\n const issueDetails = packageData.filter(\n d => d.value?.severity === 'high' || d.value?.severity === 'critical'\n )\n\n const uniqueIssues = issueDetails.reduce(\n (\n acc: { [key: string]: { count: number; label: string | undefined } },\n issue\n ) => {\n const { type } = issue\n if (type) {\n if (acc[type] === undefined) {\n acc[type] = {\n label: issue.value?.label,\n count: 1\n }\n } else {\n acc[type]!.count += 1\n }\n }\n return acc\n },\n {}\n )\n\n const format = new ColorOrMarkdown(!!outputMarkdown)\n for (const issue of Object.keys(uniqueIssues)) {\n const issueWithLink = format.hyperlink(\n `${uniqueIssues[issue]?.label}`,\n getSocketDevAlertUrl(issue),\n { fallbackToUrl: true }\n )\n if (uniqueIssues[issue]?.count === 1) {\n console.log(`- ${issueWithLink}`)\n } else {\n console.log(`- ${issueWithLink}: ${uniqueIssues[issue]?.count}`)\n }\n }\n}\n\nfunction formatScore(score: number): string {\n if (score > 80) {\n return colors.green(`${score}`)\n } else if (score < 80 && score > 60) {\n return colors.yellow(`${score}`)\n }\n return colors.red(`${score}`)\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { fetchPackageInfo } from './fetch-package-info'\nimport { formatPackageInfo } from './format-package-info'\n\nimport type { SocketSdkAlert } from '../../utils/alert/severity'\nimport type { SocketSdkReturnType } from '@socketsecurity/sdk'\n\nexport interface PackageData {\n data: SocketSdkReturnType<'getIssuesByNPMPackage'>['data']\n severityCount: Record<SocketSdkAlert['severity'], number>\n score: SocketSdkReturnType<'getScoreByNPMPackage'>['data']\n}\n\nexport async function getPackageInfo({\n commandName,\n includeAllIssues,\n outputJson,\n outputMarkdown,\n pkgName,\n pkgVersion,\n strict\n}: {\n commandName: string\n includeAllIssues: boolean\n outputJson: boolean\n outputMarkdown: boolean\n pkgName: string\n pkgVersion: string\n strict: boolean\n}) {\n const spinnerText =\n pkgVersion === 'latest'\n ? `Looking up data for the latest version of ${pkgName}`\n : `Looking up data for version ${pkgVersion} of ${pkgName}`\n const spinner = new Spinner({ text: spinnerText }).start()\n const packageData = await fetchPackageInfo(\n pkgName,\n pkgVersion,\n includeAllIssues,\n spinner\n )\n if (packageData) {\n formatPackageInfo(\n packageData,\n {\n name: commandName,\n includeAllIssues,\n outputJson,\n outputMarkdown,\n pkgName,\n pkgVersion,\n strict\n },\n spinner\n )\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { getPackageInfo } from './get-package-info'\nimport { commonFlags, outputFlags, validationFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'info',\n description: 'Look up info regarding a package',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n ...validationFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <name>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} webtorrent\n $ ${command} webtorrent@1.9.1\n `\n}\n\nexport const cmdInfo = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [rawPkgName = ''] = cli.input\n\n if (!rawPkgName || cli.input.length > 1) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Expecting a package name ${!rawPkgName ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Can only accept one package at a time ${cli.input.length > 1 ? colors.red('(got ' + cli.input.length + '!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n const versionSeparator = rawPkgName.lastIndexOf('@')\n const pkgName =\n versionSeparator < 1 ? rawPkgName : rawPkgName.slice(0, versionSeparator)\n const pkgVersion =\n versionSeparator < 1 ? 'latest' : rawPkgName.slice(versionSeparator + 1)\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await getPackageInfo({\n commandName: `${parentName} ${config.commandName}`,\n includeAllIssues: Boolean(cli.flags['all']),\n outputJson: Boolean(cli.flags['json']),\n outputMarkdown: Boolean(cli.flags['markdown']),\n pkgName,\n pkgVersion,\n strict: Boolean(cli.flags['strict'])\n })\n}\n","import { updateSetting } from '../../utils/settings'\n\nexport function applyLogin(\n apiToken: string,\n enforcedOrgs: Array<string>,\n apiBaseUrl: string | undefined,\n apiProxy: string | undefined\n) {\n updateSetting('enforcedOrgs', enforcedOrgs)\n updateSetting('apiToken', apiToken)\n updateSetting('apiBaseUrl', apiBaseUrl)\n updateSetting('apiProxy', apiProxy)\n}\n","import terminalLink from 'terminal-link'\n\nimport {\n type Separator,\n confirm,\n password,\n select\n} from '@socketsecurity/registry/lib/prompts'\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { applyLogin } from './apply-login'\nimport constants from '../../constants'\nimport { AuthError } from '../../utils/errors'\nimport { setupSdk } from '../../utils/sdk'\nimport { getSetting } from '../../utils/settings'\n\nimport type { SocketSdkReturnType } from '@socketsecurity/sdk'\n\n// TODO: this type should come from a general Socket REST API type doc\ntype Choice<Value> = {\n value: Value\n name?: string\n description?: string\n disabled?: boolean | string\n type?: never\n}\ntype OrgChoice = Choice<string>\ntype OrgChoices = Array<Separator | OrgChoice>\nconst { SOCKET_PUBLIC_API_TOKEN } = constants\n\nexport async function attemptLogin(\n apiBaseUrl: string | undefined,\n apiProxy: string | undefined\n) {\n const apiToken =\n (await password({\n message: `Enter your ${terminalLink(\n 'Socket.dev API key',\n 'https://docs.socket.dev/docs/api-keys'\n )} (leave blank for a public key)`\n })) || SOCKET_PUBLIC_API_TOKEN\n\n apiBaseUrl ??= getSetting('apiBaseUrl') ?? undefined\n apiProxy ??= getSetting('apiProxy') ?? undefined\n\n const spinner = new Spinner({ text: 'Verifying API key...' }).start()\n\n let orgs: SocketSdkReturnType<'getOrganizations'>['data']\n try {\n const sdk = await setupSdk(apiToken, apiBaseUrl, apiProxy)\n const result = await sdk.getOrganizations()\n if (!result.success) {\n throw new AuthError()\n }\n orgs = result.data\n spinner.success('API key verified')\n } catch {\n spinner.error('Invalid API key')\n return\n }\n\n const enforcedChoices: OrgChoices = Object.values(orgs.organizations)\n .filter(org => org?.plan === 'enterprise')\n .map(org => ({\n name: org.name,\n value: org.id\n }))\n\n let enforcedOrgs: Array<string> = []\n\n if (enforcedChoices.length > 1) {\n const id = <string | null>await select({\n message:\n \"Which organization's policies should Socket enforce system-wide?\",\n choices: enforcedChoices.concat({\n name: 'None',\n value: '',\n description: 'Pick \"None\" if this is a personal device'\n })\n })\n if (id) {\n enforcedOrgs = [id]\n }\n } else if (enforcedChoices.length) {\n const confirmOrg = await confirm({\n message: `Should Socket enforce ${(enforcedChoices[0] as OrgChoice)?.name}'s security policies system-wide?`,\n default: true\n })\n if (confirmOrg) {\n const existing = <OrgChoice>enforcedChoices[0]\n if (existing) {\n enforcedOrgs = [existing.value]\n }\n }\n }\n\n const oldToken = getSetting('apiToken')\n try {\n applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy)\n spinner.success(`API credentials ${oldToken ? 'updated' : 'set'}`)\n } catch {\n spinner.error(`API login failed`)\n }\n}\n","import isInteractive from '@socketregistry/is-interactive/index.cjs'\n\nimport { attemptLogin } from './attempt-login'\nimport { commonFlags } from '../../flags'\nimport { InputError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'login',\n description: 'Socket API login',\n hidden: false,\n flags: {\n ...commonFlags,\n apiBaseUrl: {\n type: 'string',\n description: 'API server to connect to for login'\n },\n apiProxy: {\n type: 'string',\n description: 'Proxy to use when making connection to API server'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command}\n\n Logs into the Socket API by prompting for an API key\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command}\n $ ${command} --api-proxy=http://localhost:1234\n `\n}\n\nexport const cmdLogin = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n let apiBaseUrl = cli.flags['apiBaseUrl'] as string | undefined\n let apiProxy = cli.flags['apiProxy'] as string | undefined\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n if (!isInteractive()) {\n throw new InputError(\n 'Cannot prompt for credentials in a non-interactive shell'\n )\n }\n\n await attemptLogin(apiBaseUrl, apiProxy)\n}\n","import { updateSetting } from '../../utils/settings'\n\nexport function applyLogout() {\n updateSetting('apiToken', null)\n updateSetting('apiBaseUrl', null)\n updateSetting('apiProxy', null)\n updateSetting('enforcedOrgs', null)\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { applyLogout } from './apply-logout'\n\nexport function attemptLogout() {\n try {\n applyLogout()\n new Spinner().success('Successfully logged out')\n } catch {\n new Spinner().success('Failed to complete logout steps')\n }\n}\n","import { attemptLogout } from './attempt-logout'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'logout',\n description: 'Socket API logout',\n hidden: false,\n flags: {\n ...commonFlags\n },\n help: (command, _config) => `\n Usage\n $ ${command}\n\n Logs out of the Socket API and clears all Socket credentials from disk\n `\n}\n\nexport const cmdLogout = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n attemptLogout()\n}\n","import path from 'node:path'\n\nimport spawn from '@npmcli/promise-spawn'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport constants from '../../constants'\n\nexport async function convertGradleToMaven(\n target: string,\n bin: string,\n _out: string,\n verbose: boolean,\n gradleOpts: Array<string>\n) {\n const rbin = path.resolve(bin)\n const rtarget = path.resolve(target)\n // const rout = out === '-' ? '-' : path.resolve(out)\n\n if (verbose) {\n console.group('gradle2maven:')\n console.log(`[VERBOSE] - Absolute bin path: \\`${rbin}\\``)\n console.log(`[VERBOSE] - Absolute target path: \\`${rtarget}\\``)\n // console.log(`[VERBOSE] - Absolute out path: \\`${rout}\\``)\n console.groupEnd()\n } else {\n console.group('gradle2maven:')\n console.log(`- executing: \\`${bin}\\``)\n console.log(`- src dir: \\`${target}\\``)\n // console.log(`- dst dir: \\`${out}\\``)\n console.groupEnd()\n }\n\n const spinner = new Spinner()\n\n spinner.start(\n `Converting gradle to maven from \\`${bin}\\` on \\`${target}\\`...`\n )\n\n try {\n // Run sbt with the init script we provide which should yield zero or more pom files.\n // We have to figure out where to store those pom files such that we can upload them and predict them through the GitHub API.\n // We could do a .socket folder. We could do a socket.pom.gz with all the poms, although I'd prefer something plain-text if it is to be committed.\n\n // Note: init.gradle will be exported by .config/rollup.dist.config.mjs\n const initLocation = path.join(constants.rootDistPath, 'init.gradle')\n const commandArgs = ['--init-script', initLocation, ...gradleOpts, 'pom']\n\n if (verbose) {\n console.log('\\n[VERBOSE] Executing:', bin, commandArgs)\n }\n\n const output = await spawn(bin, commandArgs, {\n cwd: target || '.'\n })\n spinner.success()\n if (verbose) {\n console.group('[VERBOSE] gradle stdout:')\n console.log(output)\n console.groupEnd()\n }\n\n if (output.stderr) {\n spinner.error('There were errors while running gradle')\n // (In verbose mode, stderr was printed above, no need to repeat it)\n if (!verbose) {\n console.group('[VERBOSE] stderr:')\n console.error(output.stderr)\n console.groupEnd()\n }\n process.exit(1)\n }\n\n console.log('Reported exports:')\n output.stdout.replace(\n /^POM file copied to: (.*)/gm,\n (_all: string, fn: string) => {\n console.log('- ', fn)\n return fn\n }\n )\n\n // const loc = output.stdout?.match(/Wrote (.*?.pom)\\n/)?.[1]?.trim()\n // if (!loc) {\n // spinner.error(\n // 'There were no errors from sbt but could not find the location of resulting .pom file either'\n // )\n // process.exit(1)\n // }\n //\n // // Move the pom file to ...? initial cwd? loc will be an absolute path, or dump to stdout\n // if (out === '-') {\n // spinner.start('Result:\\n```').success()\n // console.log(await safeReadFile(loc, 'utf8'))\n // console.log('```')\n // spinner.start().success(`OK`)\n // } else {\n // if (verbose) {\n // spinner.start(\n // `Moving manifest file from \\`${loc.replace(/^\\/home\\/[^/]*?\\//, '~/')}\\` to \\`${out}\\``\n // )\n // } else {\n // spinner.start('Moving output pom file')\n // }\n // // TODO: do we prefer fs-extra? renaming can be gnarly on windows and fs-extra's version is better\n // await renamep(loc, out)\n // spinner.success()\n // spinner.start().success(`OK. File should be available in \\`${out}\\``)\n // }\n } catch (e) {\n spinner.error(\n 'There was an unexpected error while running this' +\n (verbose ? '' : ' (use --verbose for details)')\n )\n if (verbose) {\n console.group('[VERBOSE] error:')\n console.log(e)\n console.groupEnd()\n }\n process.exit(1)\n }\n}\n","import path from 'node:path'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { convertGradleToMaven } from './convert_gradle_to_maven'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'gradle',\n description:\n '[beta] Use Gradle to generate a manifest file (`pom.xml`) for a Gradle/Java/Kotlin/etc project',\n hidden: false,\n flags: {\n ...commonFlags,\n bin: {\n type: 'string',\n description: 'Location of gradlew binary to use, default: CWD/gradlew'\n },\n cwd: {\n type: 'string',\n description: 'Set the cwd, defaults to process.cwd()'\n },\n gradleOpts: {\n type: 'string',\n default: '',\n description:\n 'Additional options to pass on to ./gradlew, see `./gradlew --help`'\n },\n out: {\n type: 'string',\n default: './socket.pom.xml',\n description:\n 'Path of output file; where to store the resulting manifest, see also --stdout'\n },\n stdout: {\n type: 'boolean',\n description: 'Print resulting pom.xml to stdout (supersedes --out)'\n },\n task: {\n type: 'string',\n default: 'all',\n description: 'Task to target. By default targets all.'\n },\n verbose: {\n type: 'boolean',\n description: 'Print debug messages'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} [--gradle=path/to/gradle/binary] [--out=path/to/result] DIR\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Uses gradle, preferably through your local project \\`gradlew\\`, to generate a\n \\`pom.xml\\` file for each task. If you have no \\`gradlew\\` you can try the\n global \\`gradle\\` binary but that may not work (hard to predict).\n\n The \\`pom.xml\\` is a manifest file similar to \\`package.json\\` for npm or\n or requirements.txt for PyPi), but specifically for Maven, which is Java's\n dependency repository. Languages like Kotlin and Scala piggy back on it too.\n\n There are some caveats with the gradle to \\`pom.xml\\` conversion:\n\n - each task will generate its own xml file and by default it generates one xml\n for every task.\n\n - it's possible certain features don't translate well into the xml. If you\n think something is missing that could be supported please reach out.\n\n - it works with your \\`gradlew\\` from your repo and local settings and config\n\n Support is beta. Please report issues or give us feedback on what's missing.\n\n Examples\n\n $ ${command} .\n $ ${command} --gradlew=../gradlew .\n `\n}\n\nexport const cmdManifestGradle = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const verbose = Boolean(cli.flags['verbose'])\n\n if (verbose) {\n console.group('- ', parentName, config.commandName, ':')\n console.group('- flags:', cli.flags)\n console.groupEnd()\n console.log('- input:', cli.input)\n console.groupEnd()\n }\n\n const target = cli.input[0]\n\n // TODO: I'm not sure it's feasible to parse source file from stdin. We could try, store contents in a file in some folder, target that folder... what would the file name be?\n\n if (!target || target === '-' || cli.input.length > 1) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}\\n\n - Can only accept one DIR (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}\\n`\n )\n return\n }\n\n let bin: string\n if (cli.flags['bin']) {\n bin = cli.flags['bin'] as string\n } else {\n bin = path.join(target, 'gradlew')\n }\n\n let out: string = './socket.pom.xml'\n if (cli.flags['out']) {\n out = cli.flags['out'] as string\n }\n if (cli.flags['stdout']) {\n out = '-'\n }\n\n if (verbose) {\n console.group()\n console.log('- target:', target)\n console.log('- gradle bin:', bin)\n console.log('- out:', out)\n console.groupEnd()\n }\n\n let gradleOpts: Array<string> = []\n if (cli.flags['gradleOpts']) {\n gradleOpts = (cli.flags['gradleOpts'] as string)\n .split(' ')\n .map(s => s.trim())\n .filter(Boolean)\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await convertGradleToMaven(target, bin, out, verbose, gradleOpts)\n}\n","import path from 'node:path'\n\nimport spawn from '@npmcli/promise-spawn'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { safeReadFile } from '../../utils/fs'\n\nexport async function convertSbtToMaven(\n target: string,\n bin: string,\n out: string,\n verbose: boolean,\n sbtOpts: Array<string>\n) {\n const rbin = path.resolve(bin)\n const rtarget = path.resolve(target)\n // const rout = out === '-' ? '-' : path.resolve(out)\n\n if (verbose) {\n console.group('sbt2maven:')\n console.log(`[VERBOSE] - Absolute bin path: \\`${rbin}\\``)\n console.log(`[VERBOSE] - Absolute target path: \\`${rtarget}\\``)\n // console.log(`[VERBOSE] - Absolute out path: \\`${rout}\\``)\n console.groupEnd()\n } else {\n console.group('sbt2maven:')\n console.log(`- executing: \\`${bin}\\``)\n console.log(`- src dir: \\`${target}\\``)\n // console.log(`- dst dir: \\`${out}\\``)\n console.groupEnd()\n }\n\n const spinner = new Spinner()\n\n spinner.start(`Converting sbt to maven from \\`${bin}\\` on \\`${target}\\`...`)\n\n try {\n // Run sbt with the init script we provide which should yield zero or more pom files.\n // We have to figure out where to store those pom files such that we can upload them and predict them through the GitHub API.\n // We could do a .socket folder. We could do a socket.pom.gz with all the poms, although I'd prefer something plain-text if it is to be committed.\n\n const output = await spawn(bin, ['makePom'].concat(sbtOpts), {\n cwd: target || '.'\n })\n spinner.success()\n if (verbose) {\n console.group('[VERBOSE] sbt stdout:')\n console.log(output)\n console.groupEnd()\n }\n\n if (output.stderr) {\n spinner.error('There were errors while running sbt')\n // (In verbose mode, stderr was printed above, no need to repeat it)\n if (!verbose) {\n console.group('[VERBOSE] stderr:')\n console.error(output.stderr)\n console.groupEnd()\n }\n process.exit(1)\n }\n\n const poms: Array<string> = []\n output.stdout.replace(/Wrote (.*?.pom)\\n/g, (_all: string, fn: string) => {\n poms.push(fn)\n return fn\n })\n\n if (!poms.length) {\n spinner.error(\n 'There were no errors from sbt but it seems to not have generated any poms either'\n )\n process.exit(1)\n }\n\n // Move the pom file to ...? initial cwd? loc will be an absolute path, or dump to stdout\n // TODO: what to do with multiple output files? Do we want to dump them to stdout? Raw or with separators or ?\n // TODO: maybe we can add an option to target a specific file to dump to stdout\n if (out === '-' && poms.length === 1) {\n spinner.start('Result:\\n```').success()\n console.log(await safeReadFile(poms[0] as string, 'utf8'))\n console.log('```')\n spinner.start().success(`OK`)\n } else if (out === '-') {\n spinner\n .start()\n .error(\n 'Requested out target was stdout but there are multiple generated files'\n )\n poms.forEach(fn => console.error('-', fn))\n console.error('Exiting now...')\n process.exit(1)\n } else {\n // if (verbose) {\n // spinner.start(\n // `Moving manifest file from \\`${loc.replace(/^\\/home\\/[^/]*?\\//, '~/')}\\` to \\`${out}\\``\n // )\n // } else {\n // spinner.start('Moving output pom file')\n // }\n // TODO: do we prefer fs-extra? renaming can be gnarly on windows and fs-extra's version is better\n // await renamep(loc, out)\n spinner.start().success(`Generated ${poms.length} pom files`)\n poms.forEach(fn => console.log('-', fn))\n spinner.start().success(`OK`)\n }\n } catch (e) {\n spinner.error(\n 'There was an unexpected error while running this' +\n (verbose ? '' : ' (use --verbose for details)')\n )\n if (verbose) {\n console.group('[VERBOSE] error:')\n console.log(e)\n console.groupEnd()\n }\n process.exit(1)\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { convertSbtToMaven } from './convert_sbt_to_maven'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'scala',\n description:\n \"[beta] Generate a manifest file (`pom.xml`) from Scala's `build.sbt` file\",\n hidden: false,\n flags: {\n ...commonFlags,\n bin: {\n type: 'string',\n default: 'sbt',\n description: 'Location of sbt binary to use'\n },\n cwd: {\n type: 'string',\n description: 'Set the cwd, defaults to process.cwd()'\n },\n out: {\n type: 'string',\n default: './socket.pom.xml',\n description:\n 'Path of output file; where to store the resulting manifest, see also --stdout'\n },\n stdout: {\n type: 'boolean',\n description: 'Print resulting pom.xml to stdout (supersedes --out)'\n },\n sbtOpts: {\n type: 'string',\n default: '',\n description: 'Additional options to pass on to sbt, as per `sbt --help`'\n },\n verbose: {\n type: 'boolean',\n description: 'Print debug messages'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} [--sbt=path/to/sbt/binary] [--out=path/to/result] FILE|DIR\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Uses \\`sbt makePom\\` to generate a \\`pom.xml\\` from your \\`build.sbt\\` file.\n This xml file is the dependency manifest (like a package.json\n for Node.js or requirements.txt for PyPi), but specifically for Scala.\n\n There are some caveats with \\`build.sbt\\` to \\`pom.xml\\` conversion:\n\n - the xml is exported as socket.pom.xml as to not confuse existing build tools\n but it will first hit your /target/sbt<version> folder (as a different name)\n\n - the pom.xml format (standard by Scala) does not support certain sbt features\n - \\`excludeAll()\\`, \\`dependencyOverrides\\`, \\`force()\\`, \\`relativePath\\`\n - For details: https://www.scala-sbt.org/1.x/docs/Library-Management.html\n\n - it uses your sbt settings and local configuration verbatim\n\n - it can only export one target per run, so if you have multiple targets like\n development and production, you must run them separately.\n\n You can optionally configure the path to the \\`sbt\\` bin to invoke.\n\n Support is beta. Please report issues or give us feedback on what's missing.\n\n Examples\n\n $ ${command} ./build.sbt\n $ ${command} --bin=/usr/bin/sbt ./build.sbt\n `\n}\n\nexport const cmdManifestScala = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n // console.log('scala', argv, parentName)\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const verbose = Boolean(cli.flags['verbose'])\n\n if (verbose) {\n console.group('- ', parentName, config.commandName, ':')\n console.group('- flags:', cli.flags)\n console.groupEnd()\n console.log('- input:', cli.input)\n console.groupEnd()\n }\n\n const target = cli.input[0]\n\n // TODO: I'm not sure it's feasible to parse source file from stdin. We could try, store contents in a file in some folder, target that folder... what would the file name be?\n\n if (!target || target === '-' || cli.input.length > 1) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - The DIR or FILE arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}\\n\n - Can only accept one DIR or FILE (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}\\n`\n )\n return\n }\n\n let bin: string = 'sbt'\n if (cli.flags['bin']) {\n bin = cli.flags['bin'] as string\n }\n\n let out: string = './socket.pom.xml'\n if (cli.flags['out']) {\n out = cli.flags['out'] as string\n }\n if (cli.flags['stdout']) {\n out = '-'\n }\n\n if (verbose) {\n console.group()\n console.log('- target:', target)\n console.log('- gradle bin:', bin)\n console.log('- out:', out)\n console.groupEnd()\n }\n\n let sbtOpts: Array<string> = []\n if (cli.flags['sbtOpts']) {\n sbtOpts = (cli.flags['sbtOpts'] as string)\n .split(' ')\n .map(s => s.trim())\n .filter(Boolean)\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await convertSbtToMaven(target, bin, out, verbose, sbtOpts)\n}\n","import { existsSync } from 'node:fs'\nimport path from 'node:path'\n\nimport meow from 'meow'\n\nimport { cmdManifestGradle } from './cmd-manifest-gradle'\nimport { cmdManifestScala } from './cmd-manifest-scala'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'auto',\n description: 'Auto-detect build and attempt to generate manifest file',\n hidden: false,\n flags: {\n ...commonFlags,\n cwd: {\n type: 'string',\n description: 'Set the cwd, defaults to process.cwd()'\n },\n verbose: {\n type: 'boolean',\n default: false,\n description: 'Enable debug output, may help when running into errors'\n }\n // TODO: support output flags\n },\n help: (command, config) => `\n Usage\n $ ${command}\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Tries to figure out what language your current repo uses. If it finds a\n supported case then it will try to generate the manifest file for that\n language with the default or detected settings.\n `\n}\n\nexport const cmdManifestAuto = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const verbose = !!cli.flags['verbose']\n const cwd = <string>cli.flags['cwd'] ?? process.cwd()\n if (verbose) {\n console.group('- ', parentName, config.commandName, ':')\n console.group('- flags:', cli.flags)\n console.groupEnd()\n console.log('- input:', cli.input)\n console.log('- cwd:', cwd)\n console.groupEnd()\n }\n const subArgs = []\n if (verbose) {\n subArgs.push('--verbose')\n }\n\n const dir = cwd\n\n if (existsSync(path.join(dir, 'build.sbt'))) {\n console.log(\n 'Detected a Scala sbt build, running default Scala generator...'\n )\n if (cwd) {\n subArgs.push('--cwd', cwd)\n }\n subArgs.push(dir)\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await cmdManifestScala.run(subArgs, importMeta, { parentName })\n return\n }\n\n if (existsSync(path.join(dir, 'gradlew'))) {\n console.log('Detected a gradle build, running default gradle generator...')\n if (cwd) {\n // This command takes the cwd as first arg.\n subArgs.push(cwd)\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await cmdManifestGradle.run(subArgs, importMeta, { parentName })\n return\n }\n\n // Show new help screen and exit.\n meow(\n `\n $ ${parentName} ${config.commandName}\n\n Unfortunately this script did not discover a supported language in the\n current folder.\n\n - Make sure this script would work with your target build\n - Make sure to run it from the correct folder\n - Make sure the necessary build tools are available (\\`PATH\\`)\n\n If that doesn't work, see \\`${parentName} <lang> --help\\` for config details for\n your target language.\n `,\n {\n argv: [],\n description: config.description,\n importMeta\n }\n ).showHelp()\n}\n","import path from 'node:path'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { convertGradleToMaven } from './convert_gradle_to_maven'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\n// TODO: we may want to dedupe some pieces for all gradle languages. I think it\n// makes sense to have separate commands for them and I think it makes\n// sense for the help panels to note the requested language, rather than\n// `socket manifest kotlin` to print help screens with `gradle` as the\n// command. Room for improvement.\nconst config: CliCommandConfig = {\n commandName: 'kotlin',\n description:\n '[beta] Use Gradle to generate a manifest file (`pom.xml`) for a Kotlin project',\n hidden: false,\n flags: {\n ...commonFlags,\n bin: {\n type: 'string',\n description: 'Location of gradlew binary to use, default: CWD/gradlew'\n },\n cwd: {\n type: 'string',\n description: 'Set the cwd, defaults to process.cwd()'\n },\n gradleOpts: {\n type: 'string',\n default: '',\n description:\n 'Additional options to pass on to ./gradlew, see `./gradlew --help`'\n },\n out: {\n type: 'string',\n default: './socket.pom.xml',\n description:\n 'Path of output file; where to store the resulting manifest, see also --stdout'\n },\n stdout: {\n type: 'boolean',\n description: 'Print resulting pom.xml to stdout (supersedes --out)'\n },\n task: {\n type: 'string',\n default: 'all',\n description: 'Task to target. By default targets all.'\n },\n verbose: {\n type: 'boolean',\n description: 'Print debug messages'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} [--gradle=path/to/gradle/binary] [--out=path/to/result] DIR\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Uses gradle, preferably through your local project \\`gradlew\\`, to generate a\n \\`pom.xml\\` file for each task. If you have no \\`gradlew\\` you can try the\n global \\`gradle\\` binary but that may not work (hard to predict).\n\n The \\`pom.xml\\` is a manifest file similar to \\`package.json\\` for npm or\n or requirements.txt for PyPi), but specifically for Maven, which is Java's\n dependency repository. Languages like Kotlin and Scala piggy back on it too.\n\n There are some caveats with the gradle to \\`pom.xml\\` conversion:\n\n - each task will generate its own xml file and by default it generates one xml\n for every task. (This may be a good thing!)\n\n - it's possible certain features don't translate well into the xml. If you\n think something is missing that could be supported please reach out.\n\n - it works with your \\`gradlew\\` from your repo and local settings and config\n\n Support is beta. Please report issues or give us feedback on what's missing.\n\n Examples\n\n $ ${command} .\n $ ${command} --gradlew=../gradlew .\n `\n}\n\nexport const cmdManifestKotlin = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const verbose = Boolean(cli.flags['verbose'])\n\n if (verbose) {\n console.group('- ', parentName, config.commandName, ':')\n console.group('- flags:', cli.flags)\n console.groupEnd()\n console.log('- input:', cli.input)\n console.groupEnd()\n }\n\n const target = cli.input[0]\n\n // TODO: I'm not sure it's feasible to parse source file from stdin. We could try, store contents in a file in some folder, target that folder... what would the file name be?\n\n if (!target || target === '-' || cli.input.length > 1) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - The DIR arg is required ${!target ? colors.red('(missing!)') : target === '-' ? colors.red('(stdin is not supported)') : colors.green('(ok)')}\\n\n - Can only accept one DIR (make sure to escape spaces!) ${cli.input.length > 1 ? colors.red(`(received ${cli.input.length}!)`) : colors.green('(ok)')}\\n`\n )\n return\n }\n\n let bin: string\n if (cli.flags['bin']) {\n bin = cli.flags['bin'] as string\n } else {\n bin = path.join(target, 'gradlew')\n }\n\n let out: string = './socket.pom.xml'\n if (cli.flags['out']) {\n out = cli.flags['out'] as string\n }\n if (cli.flags['stdout']) {\n out = '-'\n }\n\n if (verbose) {\n console.group()\n console.log('- target:', target)\n console.log('- gradle bin:', bin)\n console.log('- out:', out)\n console.groupEnd()\n }\n\n let gradleOpts: Array<string> = []\n if (cli.flags['gradleOpts']) {\n gradleOpts = (cli.flags['gradleOpts'] as string)\n .split(' ')\n .map(s => s.trim())\n .filter(Boolean)\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await convertGradleToMaven(target, bin, out, verbose, gradleOpts)\n}\n","import { cmdManifestAuto } from './cmd-manifest-auto'\nimport { cmdManifestGradle } from './cmd-manifest-gradle'\nimport { cmdManifestKotlin } from './cmd-manifest-kotlin'\nimport { cmdManifestScala } from './cmd-manifest-scala'\nimport { commonFlags } from '../../flags'\nimport { meowWithSubcommands } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'manifest',\n description: 'Generate a dependency manifest for given file or dir',\n hidden: false,\n flags: {\n ...commonFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <language> <target>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Generates a declarative dependency manifest (like a package.json for Node.JS\n or requirements.txt for PyPi), but for certain supported ecosystems\n where it's common to use a dynamic manifest, like Scala's sbt.\n\n Only certain languages are supported and there may be language specific\n configurations available. See \\`manifest <language> --help\\` for usage details\n per language.\n\n Currently supported language: scala [beta], gradle [beta], kotlin (through\n gradle) [beta].\n\n Examples\n\n $ ${command} scala .\n\n To have it auto-detect and attempt to run:\n\n $ ${command} yolo\n `\n}\n\nexport const cmdManifest = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n await meowWithSubcommands(\n {\n auto: cmdManifestAuto,\n scala: cmdManifestScala,\n gradle: cmdManifestGradle,\n kotlin: cmdManifestKotlin\n },\n {\n argv,\n aliases: {\n yolo: {\n description: config.description,\n hidden: true,\n argv: ['auto']\n }\n },\n description: config.description,\n importMeta,\n flags: config.flags,\n name: `${parentName} ${config.commandName}`\n }\n )\n}\n","import constants from '../../constants'\n\nconst { NPM, SHADOW_BIN } = constants\n\nexport async function wrapNpm(argv: readonly string[]) {\n // Lazily access constants.distPath.\n const shadowBin = require(`${constants.distPath}/${SHADOW_BIN}.js`)\n await shadowBin(NPM, argv)\n}\n","import { wrapNpm } from './wrap-npm'\nimport constants from '../../constants'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst { NPM } = constants\n\nconst config: CliCommandConfig = {\n commandName: 'npm',\n description: `${NPM} wrapper functionality`,\n hidden: false,\n flags: {},\n help: (command, _config) => `\n Usage\n $ ${command}\n `\n}\n\nexport const cmdNpm = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n allowUnknownFlags: true,\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await wrapNpm(argv)\n}\n","import constants from '../../constants'\n\nconst { NPX, SHADOW_BIN } = constants\n\nexport async function wrapNpx(argv: readonly string[]) {\n // Lazily access constants.distPath.\n const shadowBin = require(`${constants.distPath}/${SHADOW_BIN}.js`)\n await shadowBin(NPX, argv)\n}\n","import { wrapNpx } from './wrap-npx'\nimport constants from '../../constants'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst { NPX } = constants\n\nconst config: CliCommandConfig = {\n commandName: 'npx',\n description: `${NPX} wrapper functionality`,\n hidden: false,\n flags: {},\n help: (command, _config) => `\n Usage\n $ ${command}\n `\n}\n\nexport const cmdNpx = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n allowUnknownFlags: true,\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await wrapNpx(argv)\n}\n","import { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'oops',\n description: 'Trigger an intentional error (for development)',\n hidden: true,\n flags: {\n ...commonFlags\n },\n help: (parentName, config) => `\n Usage\n $ ${parentName} ${config.commandName}\n\n Don't run me.\n `\n}\n\nexport const cmdOops = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n throw new Error('This error was intentionally left blank')\n}\n","import constants from '../../constants'\n\nimport type { Agent } from '../../utils/package-environment-detector'\n\ntype AgentDepsIncludesFn = (stdout: string, name: string) => boolean\n\nconst { BUN, NPM, PNPM, VLT, YARN_BERRY, YARN_CLASSIC } = constants\n\nfunction matchHumanStdout(stdout: string, name: string) {\n return stdout.includes(` ${name}@`)\n}\n\nfunction matchQueryStdout(stdout: string, name: string) {\n return stdout.includes(`\"${name}\"`)\n}\n\nexport const depsIncludesByAgent = new Map<Agent, AgentDepsIncludesFn>([\n [BUN, matchHumanStdout],\n [NPM, matchQueryStdout],\n [PNPM, matchQueryStdout],\n [VLT, matchQueryStdout],\n [YARN_BERRY, matchHumanStdout],\n [YARN_CLASSIC, matchHumanStdout]\n])\n","import { existsSync } from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\n\nimport spawn from '@npmcli/promise-spawn'\nimport browserslist from 'browserslist'\nimport semver from 'semver'\nimport which from 'which'\n\nimport { parse as parseBunLockb } from '@socketregistry/hyrious__bun.lockb/index.cjs'\nimport { isObjectObject } from '@socketsecurity/registry/lib/objects'\nimport { readPackageJson } from '@socketsecurity/registry/lib/packages'\nimport { naturalCompare } from '@socketsecurity/registry/lib/sorts'\nimport { isNonEmptyString } from '@socketsecurity/registry/lib/strings'\n\nimport { findUp, readFileBinary, readFileUtf8 } from './fs'\nimport constants from '../constants'\n\nimport type { EditablePackageJson } from '@socketsecurity/registry/lib/packages'\nimport type { SemVer } from 'semver'\n\nconst {\n BINARY_LOCK_EXT,\n BUN,\n LOCK_EXT,\n NPM,\n PNPM,\n VLT,\n YARN,\n YARN_BERRY,\n YARN_CLASSIC\n} = constants\n\nexport const AGENTS = [BUN, NPM, PNPM, YARN_BERRY, YARN_CLASSIC, VLT] as const\nexport type Agent = (typeof AGENTS)[number]\nexport type StringKeyValueObject = { [key: string]: string }\n\nconst binByAgent = {\n __proto__: null,\n [BUN]: BUN,\n [NPM]: NPM,\n [PNPM]: PNPM,\n [YARN_BERRY]: YARN,\n [YARN_CLASSIC]: YARN,\n [VLT]: VLT\n}\n\nasync function getAgentExecPath(agent: Agent): Promise<string> {\n const binName = binByAgent[agent]\n return (await which(binName, { nothrow: true })) ?? binName\n}\n\nasync function getAgentVersion(\n agentExecPath: string,\n cwd: string\n): Promise<SemVer | undefined> {\n let result\n try {\n result =\n semver.coerce(\n // All package managers support the \"--version\" flag.\n (await spawn(agentExecPath, ['--version'], { cwd })).stdout\n ) ?? undefined\n } catch {}\n return result\n}\n\n// The order of LOCKS properties IS significant as it affects iteration order.\nconst LOCKS: Record<string, Agent> = {\n [`bun${LOCK_EXT}`]: BUN,\n [`bun${BINARY_LOCK_EXT}`]: BUN,\n // If both package-lock.json and npm-shrinkwrap.json are present in the root\n // of a project, npm-shrinkwrap.json will take precedence and package-lock.json\n // will be ignored.\n // https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#package-lockjson-vs-npm-shrinkwrapjson\n 'npm-shrinkwrap.json': NPM,\n 'package-lock.json': NPM,\n 'pnpm-lock.yaml': PNPM,\n 'pnpm-lock.yml': PNPM,\n [`yarn${LOCK_EXT}`]: YARN_CLASSIC,\n 'vlt-lock.json': VLT,\n // Lastly, look for a hidden lock file which is present if .npmrc has package-lock=false:\n // https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#hidden-lockfiles\n //\n // Unlike the other LOCKS keys this key contains a directory AND filename so\n // it has to be handled differently.\n 'node_modules/.package-lock.json': NPM\n}\n\ntype ReadLockFile =\n | ((lockPath: string) => Promise<string | undefined>)\n | ((lockPath: string, agentExecPath: string) => Promise<string | undefined>)\n\nconst readLockFileByAgent: Record<Agent, ReadLockFile> = (() => {\n function wrapReader<T extends (...args: any[]) => Promise<any>>(\n reader: T\n ): (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>> | undefined> {\n return async (...args: any[]): Promise<any> => {\n try {\n return await reader(...args)\n } catch {}\n return undefined\n }\n }\n\n const binaryReader = wrapReader(readFileBinary)\n\n const defaultReader = wrapReader(\n async (lockPath: string) => await readFileUtf8(lockPath)\n )\n\n return {\n [BUN]: wrapReader(async (lockPath: string, agentExecPath: string) => {\n const ext = path.extname(lockPath)\n if (ext === LOCK_EXT) {\n return await defaultReader(lockPath)\n }\n if (ext === BINARY_LOCK_EXT) {\n const lockBuffer = await binaryReader(lockPath)\n if (lockBuffer) {\n try {\n return parseBunLockb(lockBuffer)\n } catch {}\n }\n // To print a Yarn lockfile to your console without writing it to disk\n // use `bun bun.lockb`.\n // https://bun.sh/guides/install/yarnlock\n return (await spawn(agentExecPath, [lockPath])).stdout.trim()\n }\n return undefined\n }),\n [NPM]: defaultReader,\n [PNPM]: defaultReader,\n [VLT]: defaultReader,\n [YARN_BERRY]: defaultReader,\n [YARN_CLASSIC]: defaultReader\n }\n})()\n\nexport type GetPackageEnvironmentOptions = {\n cwd?: string\n onUnknown?: (pkgManager: string | undefined) => void\n}\n\nexport type PartialPackageEnvironmentDetails = Readonly<{\n agent: Agent\n agentExecPath: string\n agentVersion: SemVer | undefined\n lockName: string | undefined\n lockPath: string | undefined\n lockSrc: string | undefined\n minimumNodeVersion: string\n npmExecPath: string\n pkgJson: EditablePackageJson | undefined\n pkgPath: string | undefined\n supported: boolean\n targets: {\n browser: boolean\n node: boolean\n }\n}>\n\nexport type PackageEnvironmentDetails = Readonly<{\n agent: Agent\n agentExecPath: string\n agentVersion: SemVer\n lockName: string\n lockPath: string\n lockSrc: string\n minimumNodeVersion: string\n npmExecPath: string\n pkgJson: EditablePackageJson\n pkgPath: string\n supported: boolean\n targets: {\n browser: boolean\n node: boolean\n }\n}>\n\nexport async function detectPackageEnvironment({\n cwd = process.cwd(),\n onUnknown\n}: GetPackageEnvironmentOptions = {}): Promise<\n PackageEnvironmentDetails | PartialPackageEnvironmentDetails\n> {\n let lockPath = await findUp(Object.keys(LOCKS), { cwd })\n let lockName = lockPath ? path.basename(lockPath) : undefined\n const isHiddenLockFile = lockName === '.package-lock.json'\n const pkgJsonPath = lockPath\n ? path.resolve(lockPath, `${isHiddenLockFile ? '../' : ''}../package.json`)\n : await findUp('package.json', { cwd })\n const pkgPath =\n pkgJsonPath && existsSync(pkgJsonPath)\n ? path.dirname(pkgJsonPath)\n : undefined\n const editablePkgJson = pkgPath\n ? await readPackageJson(pkgPath, { editable: true })\n : undefined\n const pkgJson = editablePkgJson?.content\n // Read Corepack `packageManager` field in package.json:\n // https://nodejs.org/api/packages.html#packagemanager\n const pkgManager = isNonEmptyString(pkgJson?.packageManager)\n ? pkgJson.packageManager\n : undefined\n\n let agent: Agent | undefined\n let agentVersion: SemVer | undefined\n if (pkgManager) {\n const atSignIndex = pkgManager.lastIndexOf('@')\n if (atSignIndex !== -1) {\n const name = <Agent>pkgManager.slice(0, atSignIndex)\n const version = pkgManager.slice(atSignIndex + 1)\n if (version && AGENTS.includes(name)) {\n agent = name\n agentVersion = semver.coerce(version) ?? undefined\n }\n }\n }\n if (\n agent === undefined &&\n !isHiddenLockFile &&\n typeof pkgJsonPath === 'string' &&\n typeof lockName === 'string'\n ) {\n agent = <Agent>LOCKS[lockName]\n }\n if (agent === undefined) {\n agent = NPM\n onUnknown?.(pkgManager)\n }\n const agentExecPath = await getAgentExecPath(agent)\n\n const npmExecPath =\n agent === NPM ? agentExecPath : await getAgentExecPath(NPM)\n if (agentVersion === undefined) {\n agentVersion = await getAgentVersion(agentExecPath, cwd)\n }\n if (agent === YARN_CLASSIC && (agentVersion?.major ?? 0) > 1) {\n agent = YARN_BERRY\n }\n const targets = {\n browser: false,\n node: true\n }\n let lockSrc: string | undefined\n // Lazily access constants.maintainedNodeVersions.\n let minimumNodeVersion = constants.maintainedNodeVersions.previous\n if (pkgJson) {\n const browserField = pkgJson.browser\n if (isNonEmptyString(browserField) || isObjectObject(browserField)) {\n targets.browser = true\n }\n const nodeRange = pkgJson.engines?.['node']\n if (isNonEmptyString(nodeRange)) {\n const coerced = semver.coerce(nodeRange)\n if (coerced && semver.lt(coerced, minimumNodeVersion)) {\n minimumNodeVersion = coerced.version\n }\n }\n const browserslistQuery = <string[] | undefined>pkgJson['browserslist']\n if (Array.isArray(browserslistQuery)) {\n const browserslistTargets = browserslist(browserslistQuery)\n .map(s => s.toLowerCase())\n .sort(naturalCompare)\n const browserslistNodeTargets = browserslistTargets\n .filter(v => v.startsWith('node '))\n .map(v => v.slice(5 /*'node '.length*/))\n if (!targets.browser && browserslistTargets.length) {\n targets.browser =\n browserslistTargets.length !== browserslistNodeTargets.length\n }\n if (browserslistNodeTargets.length) {\n const coerced = semver.coerce(browserslistNodeTargets[0])\n if (coerced && semver.lt(coerced, minimumNodeVersion)) {\n minimumNodeVersion = coerced.version\n }\n }\n }\n // Lazily access constants.maintainedNodeVersions.\n targets.node = constants.maintainedNodeVersions.some(v =>\n semver.satisfies(v, `>=${minimumNodeVersion}`)\n )\n lockSrc =\n typeof lockPath === 'string'\n ? await readLockFileByAgent[agent](lockPath, agentExecPath)\n : undefined\n } else {\n lockName = undefined\n lockPath = undefined\n }\n return {\n agent,\n agentExecPath,\n agentVersion,\n lockName,\n lockPath,\n lockSrc,\n minimumNodeVersion,\n npmExecPath,\n pkgJson: editablePkgJson,\n pkgPath,\n supported: targets.browser || targets.node,\n targets\n }\n}\n","import path from 'node:path'\n\nimport constants from '../../constants'\nimport { detectPackageEnvironment } from '../../utils/package-environment-detector'\n\nimport type { PackageEnvironmentDetails } from '../../utils/package-environment-detector'\n\nconst { BUN, VLT, YARN_BERRY } = constants\n\nconst COMMAND_TITLE = 'Socket Optimize'\n\nexport type DetectAndValidateOptions = {\n logger?: Console | undefined\n prod?: boolean\n}\nexport async function detectAndValidatePackageEnvironment(\n cwd: string,\n options?: DetectAndValidateOptions | undefined\n): Promise<void | PackageEnvironmentDetails> {\n const { logger, prod } = <DetectAndValidateOptions>{\n __proto__: null,\n ...options\n }\n const details = await detectPackageEnvironment({\n cwd,\n onUnknown(pkgManager: string | undefined) {\n logger?.warn(\n `⚠️ ${COMMAND_TITLE}: Unknown package manager${pkgManager ? ` ${pkgManager}` : ''}, defaulting to npm`\n )\n }\n })\n if (!details.supported) {\n logger?.error(\n `✖️ ${COMMAND_TITLE}: No supported Node or browser range detected`\n )\n return\n }\n if (details.agent === VLT) {\n logger?.error(\n `✖️ ${COMMAND_TITLE}: ${details.agent} does not support overrides. Soon, though ⚡`\n )\n return\n }\n const lockName = details.lockName ?? 'lock file'\n if (details.lockName === undefined || details.lockSrc === undefined) {\n logger?.error(`✖️ ${COMMAND_TITLE}: No ${lockName} found`)\n return\n }\n if (details.lockSrc.trim() === '') {\n logger?.error(`✖️ ${COMMAND_TITLE}: ${lockName} is empty`)\n return\n }\n if (details.pkgPath === undefined) {\n logger?.error(`✖️ ${COMMAND_TITLE}: No package.json found`)\n return\n }\n if (prod && (details.agent === BUN || details.agent === YARN_BERRY)) {\n logger?.error(\n `✖️ ${COMMAND_TITLE}: --prod not supported for ${details.agent}${details.agentVersion ? `@${details.agentVersion.toString()}` : ''}`\n )\n return\n }\n if (\n details.lockPath &&\n path.relative(cwd, details.lockPath).startsWith('.')\n ) {\n logger?.warn(\n `⚠️ ${COMMAND_TITLE}: Package ${lockName} found at ${details.lockPath}`\n )\n }\n return <PackageEnvironmentDetails>details\n}\n","import { readPackageJson } from '@socketsecurity/registry/lib/packages'\n\ntype PackageJson = Awaited<ReturnType<typeof readPackageJson>>\n\nexport function getDependencyEntries(pkgJson: PackageJson) {\n const {\n dependencies,\n devDependencies,\n optionalDependencies,\n peerDependencies\n } = pkgJson\n return <[string, NonNullable<typeof dependencies>][]>[\n [\n 'dependencies',\n dependencies ? { __proto__: null, ...dependencies } : undefined\n ],\n [\n 'devDependencies',\n devDependencies ? { __proto__: null, ...devDependencies } : undefined\n ],\n [\n 'peerDependencies',\n peerDependencies ? { __proto__: null, ...peerDependencies } : undefined\n ],\n [\n 'optionalDependencies',\n optionalDependencies\n ? { __proto__: null, ...optionalDependencies }\n : undefined\n ]\n ].filter(({ 1: o }) => o)\n}\n","import { readPackageJson } from '@socketsecurity/registry/lib/packages'\n\nimport constants from '../../constants'\n\nimport type {\n Agent,\n StringKeyValueObject\n} from '../../utils/package-environment-detector'\n\ntype PackageJson = Awaited<ReturnType<typeof readPackageJson>>\ntype NpmOverrides = { [key: string]: string | StringKeyValueObject }\ntype PnpmOrYarnOverrides = { [key: string]: string }\ntype Overrides = NpmOverrides | PnpmOrYarnOverrides\ntype GetOverrides = (pkgJson: PackageJson) => GetOverridesResult\ntype GetOverridesResult = { type: Agent; overrides: Overrides }\n\nconst {\n BUN,\n NPM,\n OVERRIDES,\n PNPM,\n RESOLUTIONS,\n VLT,\n YARN_BERRY,\n YARN_CLASSIC\n} = constants\n\nfunction getOverridesDataBun(pkgJson: PackageJson) {\n const overrides = (pkgJson as any)?.[RESOLUTIONS] ?? {}\n return { type: YARN_BERRY, overrides }\n}\n\n// npm overrides documentation:\n// https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides\nfunction getOverridesDataNpm(pkgJson: PackageJson) {\n const overrides = (pkgJson as any)?.[OVERRIDES] ?? {}\n return { type: NPM, overrides }\n}\n\n// pnpm overrides documentation:\n// https://pnpm.io/package_json#pnpmoverrides\nfunction getOverridesDataPnpm(pkgJson: PackageJson) {\n const overrides = (pkgJson as any)?.pnpm?.[OVERRIDES] ?? {}\n return { type: PNPM, overrides }\n}\n\nfunction getOverridesDataVlt(pkgJson: PackageJson) {\n const overrides = (pkgJson as any)?.[OVERRIDES] ?? {}\n return { type: VLT, overrides }\n}\n\n// Yarn resolutions documentation:\n// https://yarnpkg.com/configuration/manifest#resolutions\nfunction getOverridesDataYarn(pkgJson: PackageJson) {\n const overrides = (pkgJson as any)?.[RESOLUTIONS] ?? {}\n return { type: YARN_BERRY, overrides }\n}\n\n// Yarn resolutions documentation:\n// https://classic.yarnpkg.com/en/docs/selective-version-resolutions\nfunction getOverridesDataClassic(pkgJson: PackageJson) {\n const overrides = (pkgJson as any)?.[RESOLUTIONS] ?? {}\n return { type: YARN_CLASSIC, overrides }\n}\n\nexport const overridesDataByAgent = new Map<Agent, GetOverrides>([\n [BUN, getOverridesDataBun],\n [NPM, getOverridesDataNpm],\n [PNPM, getOverridesDataPnpm],\n [VLT, getOverridesDataVlt],\n [YARN_BERRY, getOverridesDataYarn],\n [YARN_CLASSIC, getOverridesDataClassic]\n])\n","import path from 'node:path'\n\nimport { parse as yamlParse } from 'yaml'\n\nimport { readPackageJson } from '@socketsecurity/registry/lib/packages'\nimport { isNonEmptyString } from '@socketsecurity/registry/lib/strings'\n\nimport constants from '../../constants'\nimport { safeReadFile } from '../../utils/fs'\n\nimport type { Agent } from '../../utils/package-environment-detector'\n\ntype PackageJson = Awaited<ReturnType<typeof readPackageJson>>\n\nconst { PNPM } = constants\n\nconst PNPM_WORKSPACE = `${PNPM}-workspace`\n\nexport async function getWorkspaceGlobs(\n agent: Agent,\n pkgPath: string,\n pkgJson: PackageJson\n): Promise<string[] | undefined> {\n let workspacePatterns\n if (agent === PNPM) {\n for (const workspacePath of [\n path.join(pkgPath, `${PNPM_WORKSPACE}.yaml`),\n path.join(pkgPath, `${PNPM_WORKSPACE}.yml`)\n ]) {\n // eslint-disable-next-line no-await-in-loop\n const yml = <string | undefined>await safeReadFile(workspacePath, 'utf8')\n if (yml) {\n try {\n workspacePatterns = yamlParse(yml)?.packages\n } catch {}\n if (workspacePatterns) {\n break\n }\n }\n }\n } else {\n workspacePatterns = pkgJson['workspaces']\n }\n return Array.isArray(workspacePatterns)\n ? workspacePatterns\n .filter(isNonEmptyString)\n .map(workspacePatternToGlobPattern)\n : undefined\n}\n\nfunction workspacePatternToGlobPattern(workspace: string): string {\n const { length } = workspace\n if (!length) {\n return ''\n }\n // If the workspace ends with \"/\"\n if (workspace.charCodeAt(length - 1) === 47 /*'/'*/) {\n return `${workspace}/*/package.json`\n }\n // If the workspace ends with \"/**\"\n if (\n workspace.charCodeAt(length - 1) === 42 /*'*'*/ &&\n workspace.charCodeAt(length - 2) === 42 /*'*'*/ &&\n workspace.charCodeAt(length - 3) === 47 /*'/'*/\n ) {\n return `${workspace}/*/**/package.json`\n }\n // Things like \"packages/a\" or \"packages/*\"\n return `${workspace}/package.json`\n}\n","import { escapeRegExp } from '@socketsecurity/registry/lib/regexps'\n\nimport constants from '../../constants'\n\nimport type { Agent } from '../../utils/package-environment-detector'\n\nexport type AgentLockIncludesFn = (\n lockSrc: string,\n name: string,\n ext?: string\n) => boolean\n\nconst { BUN, LOCK_EXT, NPM, PNPM, VLT, YARN_BERRY, YARN_CLASSIC } = constants\n\nfunction lockIncludesNpm(lockSrc: string, name: string) {\n // Detects the package name in the following cases:\n // \"name\":\n return lockSrc.includes(`\"${name}\":`)\n}\n\nfunction lockIncludesBun(lockSrc: string, name: string, lockName?: string) {\n // This is a bit counterintuitive. When lockName ends with a .lockb\n // we treat it as a yarn.lock. When lockName ends with a .lock we\n // treat it as a package-lock.json. The bun.lock format is not identical\n // package-lock.json, however it close enough for npmLockIncludes to work.\n const lockScanner = lockName?.endsWith(LOCK_EXT)\n ? lockIncludesNpm\n : lockIncludesYarn\n return lockScanner(lockSrc, name)\n}\n\nfunction lockIncludesPnpm(lockSrc: string, name: string) {\n const escapedName = escapeRegExp(name)\n return new RegExp(\n // Detects the package name in the following cases:\n // /name/\n // 'name'\n // name:\n // name@\n `(?<=^\\\\s*)(?:(['/])${escapedName}\\\\1|${escapedName}(?=[:@]))`,\n 'm'\n ).test(lockSrc)\n}\n\nfunction lockIncludesVlt(lockSrc: string, name: string) {\n // Detects the package name in the following cases:\n // \"name\"\n return lockSrc.includes(`\"${name}\"`)\n}\n\nfunction lockIncludesYarn(lockSrc: string, name: string) {\n const escapedName = escapeRegExp(name)\n return new RegExp(\n // Detects the package name in the following cases:\n // \"name@\n // , \"name@\n // name@\n // , name@\n `(?<=(?:^\\\\s*|,\\\\s*)\"?)${escapedName}(?=@)`,\n 'm'\n ).test(lockSrc)\n}\n\nexport const lockIncludesByAgent = new Map<Agent, AgentLockIncludesFn>([\n [BUN, lockIncludesBun],\n [NPM, lockIncludesNpm],\n [PNPM, lockIncludesPnpm],\n [VLT, lockIncludesVlt],\n [YARN_BERRY, lockIncludesYarn],\n [YARN_CLASSIC, lockIncludesYarn]\n])\n","import spawn from '@npmcli/promise-spawn'\n\nimport constants from '../../constants'\n\nimport type { Agent } from '../../utils/package-environment-detector'\n\ntype AgentListDepsOptions = { npmExecPath?: string }\n\ntype AgentListDepsFn = (\n agentExecPath: string,\n cwd: string,\n options?: AgentListDepsOptions\n) => Promise<string>\n\nconst { BUN, NPM, PNPM, VLT, YARN_BERRY, YARN_CLASSIC } = constants\n\nfunction cleanupQueryStdout(stdout: string): string {\n if (stdout === '') {\n return ''\n }\n let pkgs\n try {\n pkgs = JSON.parse(stdout)\n } catch {}\n if (!Array.isArray(pkgs)) {\n return ''\n }\n const names = new Set<string>()\n for (const { _id, name, pkgid } of pkgs) {\n // `npm query` results may not have a \"name\" property, in which case we\n // fallback to \"_id\" and then \"pkgid\".\n // `vlt ls --view json` results always have a \"name\" property.\n const fallback = _id ?? pkgid ?? ''\n const resolvedName = name ?? fallback.slice(0, fallback.indexOf('@', 1))\n // Add package names, except for those under the `@types` scope as those\n // are known to only be dev dependencies.\n if (resolvedName && !resolvedName.startsWith('@types/')) {\n names.add(resolvedName)\n }\n }\n return JSON.stringify([...names], null, 2)\n}\n\nfunction parseableToQueryStdout(stdout: string) {\n if (stdout === '') {\n return ''\n }\n // Convert the parseable stdout into a json array of unique names.\n // The matchAll regexp looks for a forward (posix) or backward (win32) slash\n // and matches one or more non-slashes until the newline.\n const names = new Set(stdout.matchAll(/(?<=[/\\\\])[^/\\\\]+(?=\\n)/g))\n return JSON.stringify([...names], null, 2)\n}\n\nasync function npmQuery(npmExecPath: string, cwd: string): Promise<string> {\n let stdout = ''\n try {\n stdout = (await spawn(npmExecPath, ['query', ':not(.dev)'], { cwd })).stdout\n } catch {}\n return cleanupQueryStdout(stdout)\n}\n\nasync function lsBun(agentExecPath: string, cwd: string): Promise<string> {\n try {\n // Bun does not support filtering by production packages yet.\n // https://github.com/oven-sh/bun/issues/8283\n return (await spawn(agentExecPath!, ['pm', 'ls', '--all'], { cwd })).stdout\n } catch {}\n return ''\n}\n\nasync function lsNpm(agentExecPath: string, cwd: string): Promise<string> {\n return await npmQuery(agentExecPath, cwd)\n}\n\nasync function lsPnpm(\n agentExecPath: string,\n cwd: string,\n options?: AgentListDepsOptions\n): Promise<string> {\n const npmExecPath = options?.npmExecPath\n if (npmExecPath && npmExecPath !== NPM) {\n const result = await npmQuery(npmExecPath, cwd)\n if (result) {\n return result\n }\n }\n let stdout = ''\n try {\n stdout = (\n await spawn(\n agentExecPath,\n ['ls', '--parseable', '--prod', '--depth', 'Infinity'],\n { cwd }\n )\n ).stdout\n } catch {}\n return parseableToQueryStdout(stdout)\n}\n\nasync function lsVlt(agentExecPath: string, cwd: string): Promise<string> {\n let stdout = ''\n try {\n stdout = (\n await spawn(agentExecPath, ['ls', '--view', 'human', ':not(.dev)'], {\n cwd\n })\n ).stdout\n } catch {}\n return cleanupQueryStdout(stdout)\n}\n\nasync function lsYarnBerry(\n agentExecPath: string,\n cwd: string\n): Promise<string> {\n try {\n return (\n // Yarn Berry does not support filtering by production packages yet.\n // https://github.com/yarnpkg/berry/issues/5117\n (\n await spawn(agentExecPath, ['info', '--recursive', '--name-only'], {\n cwd\n })\n ).stdout.trim()\n )\n } catch {}\n return ''\n}\n\nasync function lsYarnClassic(\n agentExecPath: string,\n cwd: string\n): Promise<string> {\n try {\n // However, Yarn Classic does support it.\n // https://github.com/yarnpkg/yarn/releases/tag/v1.0.0\n // > Fix: Excludes dev dependencies from the yarn list output when the\n // environment is production\n return (\n await spawn(agentExecPath, ['list', '--prod'], { cwd })\n ).stdout.trim()\n } catch {}\n return ''\n}\n\nexport const lsByAgent: Record<Agent, AgentListDepsFn> = {\n // @ts-ignore\n __proto__: null,\n\n [BUN]: lsBun,\n [NPM]: lsNpm,\n [PNPM]: lsPnpm,\n [VLT]: lsVlt,\n [YARN_BERRY]: lsYarnBerry,\n [YARN_CLASSIC]: lsYarnClassic\n}\n","import { hasKeys, isObject } from '@socketsecurity/registry/lib/objects'\n\nimport constants from '../../constants'\n\nimport type {\n Agent,\n StringKeyValueObject\n} from '../../utils/package-environment-detector'\nimport type { EditablePackageJson } from '@socketsecurity/registry/lib/packages'\n\ntype NpmOverrides = { [key: string]: string | StringKeyValueObject }\ntype PnpmOrYarnOverrides = { [key: string]: string }\ntype Overrides = NpmOverrides | PnpmOrYarnOverrides\ntype AgentModifyManifestFn = (\n pkgJson: EditablePackageJson,\n overrides: Overrides\n) => void\n\nconst {\n BUN,\n NPM,\n OVERRIDES,\n PNPM,\n RESOLUTIONS,\n VLT,\n YARN_BERRY,\n YARN_CLASSIC\n} = constants\n\nconst PNPM_FIELD_NAME = PNPM\n\nconst depFields = [\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'peerDependenciesMeta',\n 'optionalDependencies',\n 'bundleDependencies'\n]\n\nfunction getEntryIndexes(\n entries: [string | symbol, any][],\n keys: (string | symbol)[]\n): number[] {\n return keys\n .map(n => entries.findIndex(p => p[0] === n))\n .filter(n => n !== -1)\n .sort((a, b) => a - b)\n}\n\nfunction getLowestEntryIndex(\n entries: [string | symbol, any][],\n keys: (string | symbol)[]\n) {\n return getEntryIndexes(entries, keys)?.[0] ?? -1\n}\n\nfunction getHighestEntryIndex(\n entries: [string | symbol, any][],\n keys: (string | symbol)[]\n) {\n return getEntryIndexes(entries, keys).at(-1) ?? -1\n}\n\nfunction updatePkgJson(\n editablePkgJson: EditablePackageJson,\n field: string,\n value: any\n) {\n const pkgJson = editablePkgJson.content\n const oldValue = pkgJson[field]\n if (oldValue) {\n // The field already exists so we simply update the field value.\n if (field === PNPM_FIELD_NAME) {\n if (hasKeys(value)) {\n editablePkgJson.update({\n [field]: {\n ...(isObject(oldValue) ? oldValue : {}),\n overrides: value\n }\n })\n } else {\n // Properties with undefined values are omitted when saved as JSON.\n editablePkgJson.update(<typeof pkgJson>(hasKeys(pkgJson[field])\n ? {\n [field]: {\n ...(isObject(oldValue) ? oldValue : {}),\n overrides: undefined\n }\n }\n : { [field]: undefined }))\n }\n } else if (field === OVERRIDES || field === RESOLUTIONS) {\n // Properties with undefined values are omitted when saved as JSON.\n editablePkgJson.update(<typeof pkgJson>{\n [field]: hasKeys(value) ? value : undefined\n })\n } else {\n editablePkgJson.update({ [field]: value })\n }\n return\n }\n if (\n (field === OVERRIDES ||\n field === PNPM_FIELD_NAME ||\n field === RESOLUTIONS) &&\n !hasKeys(value)\n ) {\n return\n }\n // Since the field doesn't exist we want to insert it into the package.json\n // in a place that makes sense, e.g. close to the \"dependencies\" field. If\n // we can't find a place to insert the field we'll add it to the bottom.\n const entries = Object.entries(pkgJson)\n let insertIndex = -1\n let isPlacingHigher = false\n if (field === OVERRIDES) {\n insertIndex = getLowestEntryIndex(entries, [RESOLUTIONS])\n if (insertIndex === -1) {\n isPlacingHigher = true\n insertIndex = getHighestEntryIndex(entries, [...depFields, PNPM])\n }\n } else if (field === RESOLUTIONS) {\n isPlacingHigher = true\n insertIndex = getHighestEntryIndex(entries, [...depFields, OVERRIDES, PNPM])\n } else if (field === PNPM_FIELD_NAME) {\n insertIndex = getLowestEntryIndex(entries, [OVERRIDES, RESOLUTIONS])\n if (insertIndex === -1) {\n isPlacingHigher = true\n insertIndex = getHighestEntryIndex(entries, depFields)\n }\n }\n if (insertIndex === -1) {\n insertIndex = getLowestEntryIndex(entries, ['engines', 'files'])\n }\n if (insertIndex === -1) {\n isPlacingHigher = true\n insertIndex = getHighestEntryIndex(entries, ['exports', 'imports', 'main'])\n }\n if (insertIndex === -1) {\n insertIndex = entries.length\n } else if (isPlacingHigher) {\n insertIndex += 1\n }\n entries.splice(insertIndex, 0, [field, value])\n editablePkgJson.fromJSON(\n `${JSON.stringify(Object.fromEntries(entries), null, 2)}\\n`\n )\n}\n\nfunction updateOverrides(\n editablePkgJson: EditablePackageJson,\n overrides: Overrides\n) {\n updatePkgJson(editablePkgJson, OVERRIDES, overrides)\n}\n\nfunction updateResolutions(\n editablePkgJson: EditablePackageJson,\n overrides: Overrides\n) {\n updatePkgJson(editablePkgJson, RESOLUTIONS, <PnpmOrYarnOverrides>overrides)\n}\n\nfunction pnpmUpdatePkgJson(\n editablePkgJson: EditablePackageJson,\n overrides: Overrides\n) {\n updatePkgJson(editablePkgJson, PNPM_FIELD_NAME, overrides)\n}\n\nexport const updateManifestByAgent = new Map<Agent, AgentModifyManifestFn>([\n [BUN, updateResolutions],\n [NPM, updateOverrides],\n [PNPM, pnpmUpdatePkgJson],\n [VLT, updateOverrides],\n [YARN_BERRY, updateResolutions],\n [YARN_CLASSIC, updateResolutions]\n])\n","import spawn from '@npmcli/promise-spawn'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport constants from '../../constants'\nimport { isDebug } from '../../utils/debug'\nimport { safeNpmInstall } from '../../utils/npm'\n\nimport type { Agent } from '../../utils/package-environment-detector'\n\nconst { NPM, abortSignal } = constants\n\ntype SpawnOption = Exclude<Parameters<typeof spawn>[2], undefined>\ntype SpawnResult = ReturnType<typeof spawn>\n\nexport type AgentInstallOptions = SpawnOption & {\n args?: string[] | undefined\n spinner?: Spinner | undefined\n}\n\nexport function runAgentInstall(\n agent: Agent,\n agentExecPath: string,\n options: AgentInstallOptions\n): SpawnResult {\n // All package managers support the \"install\" command.\n if (agent === NPM) {\n return safeNpmInstall(options)\n }\n const {\n args = [],\n spinner,\n ...spawnOptions\n } = <AgentInstallOptions>{ __proto__: null, ...options }\n const isSilent = !isDebug()\n const isSpinning = spinner?.isSpinning ?? false\n if (!isSilent) {\n spinner?.stop()\n }\n let spawnPromise = spawn(agentExecPath, ['install', ...args], {\n signal: abortSignal,\n stdio: isSilent ? 'ignore' : 'inherit',\n ...spawnOptions,\n env: {\n ...process.env,\n ...spawnOptions.env\n }\n })\n if (!isSilent && isSpinning) {\n const oldSpawnPromise = spawnPromise\n spawnPromise = <typeof oldSpawnPromise>spawnPromise.finally(() => {\n spinner?.start()\n })\n spawnPromise.process = oldSpawnPromise.process\n ;(spawnPromise as any).stdin = (spawnPromise as any).stdin\n }\n return spawnPromise\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { runAgentInstall } from './run-agent'\nimport constants from '../../constants'\n\nimport type { PackageEnvironmentDetails } from '../../utils/package-environment-detector'\n\nconst { NPM } = constants\n\nconst COMMAND_TITLE = 'Socket Optimize'\nconst NPM_OVERRIDE_PR_URL = 'https://github.com/npm/cli/pull/8089'\n\nexport type UpdatePackageLockJsonOptions = {\n logger?: Console | undefined\n spinner?: Spinner | undefined\n}\nexport async function updatePackageLockJson(\n pkgEnvDetails: PackageEnvironmentDetails,\n options: UpdatePackageLockJsonOptions\n) {\n const { logger, spinner } = <UpdatePackageLockJsonOptions>{\n __proto__: null,\n ...options\n }\n spinner?.start(`Updating ${pkgEnvDetails.lockName}...`)\n try {\n await runAgentInstall(pkgEnvDetails.agent, pkgEnvDetails.agentExecPath, {\n spinner\n })\n spinner?.stop()\n if (pkgEnvDetails.agent === NPM) {\n logger?.log(\n `💡 Re-run ${COMMAND_TITLE} whenever ${pkgEnvDetails.lockName} changes.\\n This can be skipped once npm ships ${NPM_OVERRIDE_PR_URL}.`\n )\n }\n } catch (e: any) {\n spinner?.error(\n `${COMMAND_TITLE}: ${pkgEnvDetails.agent} install failed to update ${pkgEnvDetails.lockName}`\n )\n logger?.error(e)\n }\n}\n","import path from 'node:path'\n\nimport npa from 'npm-package-arg'\nimport semver from 'semver'\nimport { glob as tinyGlob } from 'tinyglobby'\n\nimport { getManifestData } from '@socketsecurity/registry'\nimport { hasOwn, toSortedObject } from '@socketsecurity/registry/lib/objects'\nimport {\n fetchPackageManifest,\n readPackageJson\n} from '@socketsecurity/registry/lib/packages'\nimport { pEach } from '@socketsecurity/registry/lib/promises'\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\nimport { pluralize } from '@socketsecurity/registry/lib/words'\n\nimport { depsIncludesByAgent } from './deps-includes-by-agent'\nimport { detectAndValidatePackageEnvironment } from './detect-and-validate-package-environment'\nimport { getDependencyEntries } from './get-dependency-entries'\nimport { overridesDataByAgent } from './get-overrides-by-agent'\nimport { getWorkspaceGlobs } from './get-workspace-globs'\nimport { lockIncludesByAgent } from './lock-includes-by-agent'\nimport { lsByAgent } from './ls-by-agent'\nimport { updateManifestByAgent } from './update-manifest-by-agent'\nimport { updatePackageLockJson } from './update-package-lock-json'\nimport constants from '../../constants'\n\nimport type { AgentLockIncludesFn } from './lock-includes-by-agent'\nimport type {\n Agent,\n PackageEnvironmentDetails,\n StringKeyValueObject\n} from '../../utils/package-environment-detector'\n\ntype AddOverridesOptions = {\n logger?: Console | undefined\n pin?: boolean | undefined\n prod?: boolean | undefined\n spinner?: Spinner | undefined\n state?: AddOverridesState | undefined\n}\ntype AddOverridesState = {\n added: Set<string>\n addedInWorkspaces: Set<string>\n updated: Set<string>\n updatedInWorkspaces: Set<string>\n warnedPnpmWorkspaceRequiresNpm: boolean\n}\ntype GetOverridesResult = { type: Agent; overrides: Overrides }\ntype NpmOverrides = { [key: string]: string | StringKeyValueObject }\ntype PackageJson = Awaited<ReturnType<typeof readPackageJson>>\ntype PnpmOrYarnOverrides = { [key: string]: string }\ntype Overrides = NpmOverrides | PnpmOrYarnOverrides\n\nconst { NPM, PNPM, YARN_CLASSIC } = constants\n\nconst COMMAND_TITLE = 'Socket Optimize'\n\nconst manifestNpmOverrides = getManifestData(NPM)\n\nexport async function applyOptimization(\n cwd: string,\n pin: boolean,\n prod: boolean\n) {\n const logger = console\n const pkgEnvDetails = await detectAndValidatePackageEnvironment(cwd, {\n logger,\n prod\n })\n if (!pkgEnvDetails) {\n return\n }\n const spinner = new Spinner({ text: 'Socket optimizing...' })\n spinner.start()\n\n const state = await addOverrides(pkgEnvDetails.pkgPath, pkgEnvDetails, {\n logger,\n pin,\n prod,\n spinner\n })\n\n spinner.stop()\n\n const addedCount = state.added.size\n const updatedCount = state.updated.size\n const pkgJsonChanged = addedCount > 0 || updatedCount > 0\n if (pkgJsonChanged) {\n if (updatedCount > 0) {\n logger?.log(\n `${createActionMessage('Updated', updatedCount, state.updatedInWorkspaces.size)}${addedCount ? '.' : '🚀'}`\n )\n }\n if (addedCount > 0) {\n logger?.log(\n `${createActionMessage('Added', addedCount, state.addedInWorkspaces.size)} 🚀`\n )\n }\n } else {\n logger?.log('Congratulations! Already Socket.dev optimized 🎉')\n }\n\n if (pkgEnvDetails.agent === NPM || pkgJsonChanged) {\n // Always update package-lock.json until the npm overrides PR lands:\n // https://github.com/npm/cli/pull/8089\n await updatePackageLockJson(pkgEnvDetails, { logger, spinner })\n }\n}\n\nfunction createActionMessage(\n verb: string,\n overrideCount: number,\n workspaceCount: number\n): string {\n return `${verb} ${overrideCount} Socket.dev optimized ${pluralize('override', overrideCount)}${workspaceCount ? ` in ${workspaceCount} ${pluralize('workspace', workspaceCount)}` : ''}`\n}\n\nasync function addOverrides(\n pkgPath: string,\n pkgEnvDetails: PackageEnvironmentDetails,\n options?: AddOverridesOptions | undefined\n): Promise<AddOverridesState> {\n const {\n agent,\n agentExecPath,\n lockName,\n lockSrc,\n npmExecPath,\n pkgPath: rootPath\n } = pkgEnvDetails\n const {\n logger,\n pin,\n prod,\n spinner,\n state = {\n added: new Set(),\n addedInWorkspaces: new Set(),\n updated: new Set(),\n updatedInWorkspaces: new Set(),\n warnedPnpmWorkspaceRequiresNpm: false\n }\n } = <AddOverridesOptions>{ __proto__: null, ...options }\n let { pkgJson: editablePkgJson } = pkgEnvDetails\n if (editablePkgJson === undefined) {\n editablePkgJson = await readPackageJson(pkgPath, { editable: true })\n }\n const { content: pkgJson } = editablePkgJson\n const isRoot = pkgPath === rootPath\n const isLockScanned = isRoot && !prod\n const workspaceName = path.relative(rootPath, pkgPath)\n const workspaceGlobs = await getWorkspaceGlobs(agent, pkgPath, pkgJson)\n const isWorkspace = !!workspaceGlobs\n if (\n isWorkspace &&\n agent === PNPM &&\n npmExecPath === NPM &&\n !state.warnedPnpmWorkspaceRequiresNpm\n ) {\n state.warnedPnpmWorkspaceRequiresNpm = true\n logger?.warn(\n `⚠️ ${COMMAND_TITLE}: pnpm workspace support requires \\`npm ls\\`, falling back to \\`pnpm list\\``\n )\n }\n const thingToScan = isLockScanned\n ? lockSrc\n : await lsByAgent[agent]!(agentExecPath, pkgPath, { npmExecPath })\n // The AgentDepsIncludesFn and AgentLockIncludesFn types overlap in their\n // first two parameters. AgentLockIncludesFn accepts an optional third\n // parameter which AgentDepsIncludesFn will ignore so we cast thingScanner\n // as an AgentLockIncludesFn type.\n const thingScanner = <AgentLockIncludesFn>(\n (isLockScanned\n ? lockIncludesByAgent.get(agent)\n : depsIncludesByAgent.get(agent))\n )\n const depEntries = getDependencyEntries(pkgJson)\n\n const overridesDataObjects = <GetOverridesResult[]>[]\n if (pkgJson['private'] || isWorkspace) {\n overridesDataObjects.push(overridesDataByAgent.get(agent)!(pkgJson))\n } else {\n overridesDataObjects.push(\n overridesDataByAgent.get(NPM)!(pkgJson),\n overridesDataByAgent.get(YARN_CLASSIC)!(pkgJson)\n )\n }\n if (spinner) {\n spinner.text = `Adding overrides${workspaceName ? ` to ${workspaceName}` : ''}...`\n }\n const depAliasMap = new Map<string, string>()\n\n const nodeRange = `>=${pkgEnvDetails.minimumNodeVersion}`\n const manifestEntries = manifestNpmOverrides.filter(({ 1: data }) =>\n semver.satisfies(semver.coerce(data.engines.node)!, nodeRange)\n )\n // Chunk package names to process them in parallel 3 at a time.\n await pEach(manifestEntries, 3, async ({ 1: data }) => {\n const { name: sockRegPkgName, package: origPkgName, version } = data\n const major = semver.major(version)\n const sockOverridePrefix = `${NPM}:${sockRegPkgName}@`\n const sockOverrideSpec = `${sockOverridePrefix}${pin ? version : `^${major}`}`\n for (const { 1: depObj } of depEntries) {\n const sockSpec = hasOwn(depObj, sockRegPkgName)\n ? depObj[sockRegPkgName]\n : undefined\n if (sockSpec) {\n depAliasMap.set(sockRegPkgName, sockSpec)\n }\n const origSpec = hasOwn(depObj, origPkgName)\n ? depObj[origPkgName]\n : undefined\n if (origSpec) {\n let thisSpec = origSpec\n // Add package aliases for direct dependencies to avoid npm EOVERRIDE errors.\n // https://docs.npmjs.com/cli/v8/using-npm/package-spec#aliases\n if (\n !(\n thisSpec.startsWith(sockOverridePrefix) &&\n semver.coerce(npa(thisSpec).rawSpec)?.version\n )\n ) {\n thisSpec = sockOverrideSpec\n depObj[origPkgName] = thisSpec\n state.added.add(sockRegPkgName)\n if (workspaceName) {\n state.addedInWorkspaces.add(workspaceName)\n }\n }\n depAliasMap.set(origPkgName, thisSpec)\n }\n }\n if (isRoot) {\n // Chunk package names to process them in parallel 3 at a time.\n await pEach(overridesDataObjects, 3, async ({ overrides, type }) => {\n const overrideExists = hasOwn(overrides, origPkgName)\n if (\n overrideExists ||\n thingScanner(thingToScan, origPkgName, lockName)\n ) {\n const oldSpec = overrideExists ? overrides[origPkgName]! : undefined\n const origDepAlias = depAliasMap.get(origPkgName)\n const sockRegDepAlias = depAliasMap.get(sockRegPkgName)\n const depAlias = sockRegDepAlias ?? origDepAlias\n let newSpec = sockOverrideSpec\n if (type === NPM && depAlias) {\n // With npm one may not set an override for a package that one directly\n // depends on unless both the dependency and the override itself share\n // the exact same spec. To make this limitation easier to deal with,\n // overrides may also be defined as a reference to a spec for a direct\n // dependency by prefixing the name of the package to match the version\n // of with a $.\n // https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides\n newSpec = `$${sockRegDepAlias ? sockRegPkgName : origPkgName}`\n } else if (typeof oldSpec === 'string') {\n const thisSpec = oldSpec.startsWith('$')\n ? depAlias || newSpec\n : oldSpec || newSpec\n if (thisSpec.startsWith(sockOverridePrefix)) {\n if (\n pin &&\n semver.major(\n semver.coerce(npa(thisSpec).rawSpec)?.version ?? version\n ) !== major\n ) {\n const otherVersion = (await fetchPackageManifest(thisSpec))\n ?.version\n if (otherVersion && otherVersion !== version) {\n newSpec = `${sockOverridePrefix}${pin ? otherVersion : `^${semver.major(otherVersion)}`}`\n }\n }\n } else {\n newSpec = oldSpec\n }\n }\n if (newSpec !== oldSpec) {\n overrides[origPkgName] = newSpec\n const addedOrUpdated = overrideExists ? 'updated' : 'added'\n state[addedOrUpdated].add(sockRegPkgName)\n }\n }\n })\n }\n })\n if (workspaceGlobs) {\n const workspacePkgJsonPaths = await tinyGlob(workspaceGlobs, {\n absolute: true,\n cwd: pkgPath!,\n ignore: ['**/node_modules/**', '**/bower_components/**']\n })\n // Chunk package names to process them in parallel 3 at a time.\n await pEach(workspacePkgJsonPaths, 3, async workspacePkgJsonPath => {\n const otherState = await addOverrides(\n path.dirname(workspacePkgJsonPath),\n pkgEnvDetails,\n {\n logger,\n pin,\n prod,\n spinner\n }\n )\n for (const key of [\n 'added',\n 'addedInWorkspaces',\n 'updated',\n 'updatedInWorkspaces'\n ] satisfies\n // Here we're just telling TS that we're looping over key names\n // of the type and that they're all Set<string> props. This allows\n // us to do the SetA.add(setB.get) pump type-safe without casts.\n Array<\n keyof Pick<\n AddOverridesState,\n 'added' | 'addedInWorkspaces' | 'updated' | 'updatedInWorkspaces'\n >\n >) {\n for (const value of otherState[key]) {\n state[key].add(value)\n }\n }\n })\n }\n if (state.added.size > 0 || state.updated.size > 0) {\n editablePkgJson.update(<PackageJson>Object.fromEntries(depEntries))\n for (const { overrides, type } of overridesDataObjects) {\n updateManifestByAgent.get(type)!(\n editablePkgJson,\n toSortedObject(overrides)\n )\n }\n await editablePkgJson.save()\n }\n return state\n}\n","import process from 'node:process'\n\nimport { applyOptimization } from './apply-optimization'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'optimize',\n description: 'Optimize dependencies with @socketregistry overrides',\n hidden: false,\n flags: {\n ...commonFlags,\n pin: {\n type: 'boolean',\n default: false,\n description: 'Pin overrides to their latest version'\n },\n prod: {\n type: 'boolean',\n default: false,\n description: 'Only add overrides for production dependencies'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command}\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command}\n $ ${command} --pin\n `\n}\n\nexport const cmdOptimize = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const cwd = process.cwd()\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await applyOptimization(\n cwd,\n Boolean(cli.flags['pin']),\n Boolean(cli.flags['prod'])\n )\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport {\n getLastFiveOfApiToken,\n handleApiCall,\n handleUnsuccessfulApiResponse\n} from '../../utils/api'\nimport { AuthError } from '../../utils/errors'\nimport { getDefaultToken, setupSdk } from '../../utils/sdk'\n\nexport async function getOrganization(\n format: 'text' | 'json' | 'markdown' = 'text'\n): Promise<void> {\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n await printOrganizationsFromToken(apiToken, format)\n}\n\nasync function printOrganizationsFromToken(\n apiToken: string,\n format: 'text' | 'json' | 'markdown' = 'text'\n) {\n const spinner = new Spinner({ text: 'Fetching organizations...' }).start()\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getOrganizations(),\n 'looking up organizations'\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('getOrganizations', result, spinner)\n return\n }\n\n spinner.stop()\n\n const organizations = Object.values(result.data.organizations)\n const lastFiveOfApiToken = getLastFiveOfApiToken(apiToken)\n\n switch (format) {\n case 'json': {\n console.log(\n JSON.stringify(\n organizations.map(o => ({\n name: o.name,\n id: o.id,\n plan: o.plan\n })),\n null,\n 2\n )\n )\n return\n }\n case 'markdown': {\n // | Syntax | Description |\n // | ----------- | ----------- |\n // | Header | Title |\n // | Paragraph | Text |\n let mw1 = 4\n let mw2 = 2\n let mw3 = 4\n for (const o of organizations) {\n mw1 = Math.max(mw1, o.name.length)\n mw2 = Math.max(mw2, o.id.length)\n mw3 = Math.max(mw3, o.plan.length)\n }\n console.log('# Organizations\\n')\n console.log(\n `List of organizations associated with your API key, ending with: ${colors.italic(lastFiveOfApiToken)}\\n`\n )\n console.log(\n `| Name${' '.repeat(mw1 - 4)} | ID${' '.repeat(mw2 - 2)} | Plan${' '.repeat(mw3 - 4)} |`\n )\n console.log(\n `| ${'-'.repeat(mw1)} | ${'-'.repeat(mw2)} | ${'-'.repeat(mw3)} |`\n )\n for (const o of organizations) {\n console.log(\n `| ${(o.name || '').padEnd(mw1, ' ')} | ${(o.id || '').padEnd(mw2, ' ')} | ${(o.plan || '').padEnd(mw3, ' ')} |`\n )\n }\n console.log(\n `| ${'-'.repeat(mw1)} | ${'-'.repeat(mw2)} | ${'-'.repeat(mw3)} |`\n )\n return\n }\n default: {\n console.log(\n `List of organizations associated with your API key, ending with: ${colors.italic(lastFiveOfApiToken)}\\n`\n )\n // Just dump\n for (const o of organizations) {\n console.log(\n `- Name: ${colors.bold(o.name)}, ID: ${colors.bold(o.id)}, Plan: ${colors.bold(o.plan)}`\n )\n }\n }\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { getOrganization } from './get-organization.ts'\nimport { commonFlags, outputFlags } from '../../flags.ts'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'organizations',\n description: 'List organizations associated with the API key used',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags\n },\n help: (command, _config) => `\n Usage\n $ ${command}\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n `\n}\n\nexport const cmdOrganization = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const json = Boolean(cli.flags['json'])\n const markdown = Boolean(cli.flags['markdown'])\n if (json && markdown) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`\n ${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - The json and markdown flags cannot be both set, pick one\n `)\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await getOrganization(json ? 'json' : markdown ? 'markdown' : 'text')\n}\n","import process from 'node:process'\n\nimport spawn from '@npmcli/promise-spawn'\n\nimport constants from '../../constants'\nimport { getNpmBinPath } from '../../shadow/npm-paths'\n\nconst { abortSignal } = constants\n\nexport async function runRawNpm(argv: ReadonlyArray<string>): Promise<void> {\n const spawnPromise = spawn(getNpmBinPath(), argv.slice(0), {\n signal: abortSignal,\n stdio: 'inherit'\n })\n // See https://nodejs.org/api/all.html#all_child_process_event-exit.\n spawnPromise.process.on('exit', (code, signalName) => {\n if (abortSignal.aborted) {\n return\n }\n if (signalName) {\n process.kill(process.pid, signalName)\n } else if (code !== null) {\n process.exit(code)\n }\n })\n await spawnPromise\n}\n","import { runRawNpm } from './run-raw-npm'\nimport constants from '../../constants'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst { NPM } = constants\n\nconst config: CliCommandConfig = {\n commandName: 'raw-npm',\n description: `Temporarily disable the Socket ${NPM} wrapper`,\n hidden: false,\n flags: {},\n help: (command, config) => `\n Usage\n $ ${command} <command>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} install\n `\n}\n\nexport const cmdRawNpm = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: ReadonlyArray<string>,\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n allowUnknownFlags: true,\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await runRawNpm(argv)\n}\n","import process from 'node:process'\n\nimport spawn from '@npmcli/promise-spawn'\n\nimport constants from '../../constants'\nimport { getNpxBinPath } from '../../shadow/npm-paths'\n\nconst { abortSignal } = constants\n\nexport async function runRawNpx(argv: ReadonlyArray<string>): Promise<void> {\n const spawnPromise = spawn(getNpxBinPath(), <string[]>argv, {\n signal: abortSignal,\n stdio: 'inherit'\n })\n // See https://nodejs.org/api/all.html#all_child_process_event-exit.\n spawnPromise.process.on('exit', (code, signalName) => {\n if (abortSignal.aborted) {\n return\n }\n if (signalName) {\n process.kill(process.pid, signalName)\n } else if (code !== null) {\n process.exit(code)\n }\n })\n await spawnPromise\n}\n","import { runRawNpx } from './run-raw-npx'\nimport constants from '../../constants'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst { NPX } = constants\n\nconst config: CliCommandConfig = {\n commandName: 'raw-npx',\n description: `Temporarily disable the Socket ${NPX} wrapper`,\n hidden: false,\n flags: {},\n help: (command, config) => `\n Usage\n $ ${command} <command>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} install\n `\n}\n\nexport const cmdRawNpx = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: ReadonlyArray<string>,\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n allowUnknownFlags: true,\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await runRawNpx(argv)\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { debugLog } from '../../utils/debug'\nimport { getLogSymbols } from '../../utils/logging'\nimport { getPackageFiles } from '../../utils/path-resolve'\nimport { setupSdk } from '../../utils/sdk'\n\nimport type { SocketYml } from '@socketsecurity/config'\nimport type {\n SocketSdkResultType,\n SocketSdkReturnType\n} from '@socketsecurity/sdk'\n\nexport async function createReport(\n socketConfig: SocketYml | undefined,\n inputPaths: Array<string>,\n {\n cwd,\n dryRun\n }: {\n cwd: string\n dryRun: boolean\n }\n): Promise<undefined | SocketSdkResultType<'createReport'>> {\n const socketSdk = await setupSdk()\n const supportedFiles = await socketSdk\n .getReportSupportedFiles()\n .then(res => {\n if (!res.success)\n handleUnsuccessfulApiResponse(\n 'getReportSupportedFiles',\n res,\n new Spinner()\n )\n return (res as SocketSdkReturnType<'getReportSupportedFiles'>).data\n })\n .catch((cause: Error) => {\n throw new Error('Failed getting supported files for report', {\n cause\n })\n })\n\n const packagePaths = await getPackageFiles(\n cwd,\n inputPaths,\n socketConfig,\n supportedFiles\n )\n\n debugLog(\n 'Uploading:',\n packagePaths.join(`\\n${getLogSymbols().info} Uploading: `)\n )\n\n if (dryRun) {\n debugLog('[dryRun] Skipped actual upload')\n return undefined\n } else {\n const socketSdk = await setupSdk()\n const spinner = new Spinner({\n text: `Creating report with ${packagePaths.length} package files`\n }).start()\n\n const apiCall = socketSdk.createReportFromFilePaths(\n packagePaths,\n cwd,\n socketConfig?.issueRules\n )\n const result = await handleApiCall(apiCall, 'creating report')\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('createReport', result, spinner)\n return undefined\n }\n spinner.success()\n return result\n }\n}\n","import { betterAjvErrors } from '@apideck/better-ajv-errors'\n\nimport { SocketValidationError, readSocketConfig } from '@socketsecurity/config'\n\nimport { InputError } from '../../utils/errors'\n\nexport async function getSocketConfig(absoluteConfigPath: string) {\n const socketConfig = await readSocketConfig(absoluteConfigPath).catch(\n (cause: unknown) => {\n if (\n cause &&\n typeof cause === 'object' &&\n cause instanceof SocketValidationError\n ) {\n // Inspired by workbox-build:\n // https://github.com/GoogleChrome/workbox/blob/95f97a207fd51efb3f8a653f6e3e58224183a778/packages/workbox-build/src/lib/validate-options.ts#L68-L71\n const betterErrors = betterAjvErrors({\n basePath: 'config',\n data: cause.data,\n errors: cause.validationErrors,\n schema: cause.schema as Parameters<\n typeof betterAjvErrors\n >[0]['schema']\n })\n throw new InputError(\n 'The socket.yml config is not valid',\n betterErrors\n .map(\n err =>\n `[${err.path}] ${err.message}.${err.suggestion ? err.suggestion : ''}`\n )\n .join('\\n')\n )\n } else {\n throw new Error('Failed to read socket.yml config', { cause })\n }\n }\n )\n\n return socketConfig\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport {\n formatSeverityCount,\n getSeverityCount\n} from '../../utils/alert/severity'\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nimport type {\n SocketSdkResultType,\n SocketSdkReturnType\n} from '@socketsecurity/sdk'\n\nexport type ReportData = SocketSdkReturnType<'getReport'>['data']\n\nconst MAX_TIMEOUT_RETRY = 5\nconst HTTP_CODE_TIMEOUT = 524\n\nexport async function fetchReportData(\n reportId: string,\n includeAllIssues: boolean,\n strict: boolean\n): Promise<void | ReportData> {\n const socketSdk = await setupSdk()\n const spinner = new Spinner({\n text: `Fetching report with ID ${reportId} (this could take a while)`\n }).start()\n\n let result: SocketSdkResultType<'getReport'> | undefined\n for (let retry = 1; !result; ++retry) {\n try {\n // eslint-disable-next-line no-await-in-loop\n result = await handleApiCall(\n socketSdk.getReport(reportId),\n 'fetching report'\n )\n } catch (err) {\n if (\n retry >= MAX_TIMEOUT_RETRY ||\n !(err instanceof Error) ||\n (err.cause as any)?.cause?.response?.statusCode !== HTTP_CODE_TIMEOUT\n ) {\n throw err\n }\n }\n }\n\n if (!result.success) {\n return handleUnsuccessfulApiResponse('getReport', result, spinner)\n }\n\n // Conclude the status of the API call\n\n if (strict) {\n if (result.data.healthy) {\n spinner.success('Report result is healthy and great!')\n } else {\n spinner.error('Report result deemed unhealthy for project')\n }\n } else if (!result.data.healthy) {\n const severityCount = getSeverityCount(\n result.data.issues,\n includeAllIssues ? undefined : 'high'\n )\n const issueSummary = formatSeverityCount(severityCount)\n spinner.success(`Report has these issues: ${issueSummary}`)\n } else {\n spinner.success('Report has no issues')\n }\n\n return result.data\n}\n","import process from 'node:process'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { ColorOrMarkdown } from '../../utils/color-or-markdown'\n\nimport type { ReportData } from './fetch-report-data'\n\nexport function formatReportDataOutput(\n reportId: string,\n data: ReportData,\n commandName: string,\n outputJson: boolean,\n outputMarkdown: boolean,\n strict: boolean\n): void {\n if (outputJson) {\n console.log(JSON.stringify(data, undefined, 2))\n } else {\n const format = new ColorOrMarkdown(outputMarkdown)\n console.log(\n '\\nDetailed info on socket.dev: ' +\n format.hyperlink(reportId, data.url, { fallbackToUrl: true })\n )\n if (!outputMarkdown) {\n console.log(\n colors.dim(\n `\\nOr rerun ${colors.italic(commandName)} using the ${colors.italic('--json')} flag to get full JSON output`\n )\n )\n }\n }\n\n if (strict && !data.healthy) {\n process.exit(1)\n }\n}\n","import { fetchReportData } from './fetch-report-data'\nimport { formatReportDataOutput } from './format-report-data'\n\nexport async function viewReport(\n reportId: string,\n {\n all,\n commandName,\n json,\n markdown,\n strict\n }: {\n commandName: string\n all: boolean\n json: boolean\n markdown: boolean\n strict: boolean\n }\n) {\n const result = await fetchReportData(reportId, all, strict)\n if (result) {\n formatReportDataOutput(\n reportId,\n result,\n commandName,\n json,\n markdown,\n strict\n )\n }\n}\n","import path from 'node:path'\nimport process from 'node:process'\n\nimport { createReport } from './create-report'\nimport { getSocketConfig } from './get-socket-config'\nimport { viewReport } from './view-report'\nimport { commonFlags, outputFlags, validationFlags } from '../../flags'\nimport { ColorOrMarkdown } from '../../utils/color-or-markdown'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'create',\n description: 'Create a project report',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n ...validationFlags,\n dryRun: {\n type: 'boolean',\n default: false,\n description: 'Only output what will be done without actually doing it'\n },\n view: {\n type: 'boolean',\n shortFlag: 'v',\n default: false,\n description: 'Will wait for and return the created report'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} <paths-to-package-folders-and-files>\n\n Uploads the specified \"package.json\" and lock files for JavaScript, Python, and Go dependency manifests.\n If any folder is specified, the ones found in there recursively are uploaded.\n\n Supports globbing such as \"**/package.json\", \"**/requirements.txt\", \"**/pyproject.toml\", and \"**/go.mod\".\n\n Ignores any file specified in your project's \".gitignore\", your project's\n \"socket.yml\" file's \"projectIgnorePaths\" and also has a sensible set of\n default ignores from the \"ignore-by-default\" module.\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} .\n $ ${command} '**/package.json'\n $ ${command} /path/to/a/package.json /path/to/another/package.json\n $ ${command} . --view --json\n `\n}\n\nexport const cmdReportCreate = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n // TODO: Allow setting a custom cwd and/or configFile path?\n const cwd = process.cwd()\n const absoluteConfigPath = path.join(cwd, 'socket.yml')\n\n const dryRun = Boolean(cli.flags['dryRun'])\n const json = Boolean(cli.flags['json'])\n const markdown = Boolean(cli.flags['markdown'])\n const strict = Boolean(cli.flags['strict'])\n const includeAllIssues = Boolean(cli.flags['all'])\n const view = Boolean(cli.flags['view'])\n\n // Note exiting earlier to skirt a hidden auth requirement\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const socketConfig = await getSocketConfig(absoluteConfigPath)\n\n const result = await createReport(socketConfig, cli.input, { cwd, dryRun })\n\n const commandName = `${parentName} ${config.commandName}`\n\n if (result?.success) {\n if (view) {\n const reportId = result.data.id\n await viewReport(reportId, {\n all: includeAllIssues,\n commandName,\n json,\n markdown,\n strict\n })\n } else if (json) {\n console.log(JSON.stringify(result.data, undefined, 2))\n return\n } else {\n const format = new ColorOrMarkdown(markdown)\n console.log(\n `New report: ${format.hyperlink(result.data.id, result.data.url, { fallbackToUrl: true })}`\n )\n }\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { viewReport } from './view-report'\nimport { commonFlags, outputFlags, validationFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'view',\n description: 'View a project report',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n ...validationFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <report-identifier>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} QXU8PmK7LfH608RAwfIKdbcHgwEd_ZeWJ9QEGv05FJUQ\n `\n}\n\nexport const cmdReportView = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [reportId, ...extraInput] = cli.input\n\n // Validate the input.\n if (extraInput.length || !reportId) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Need at least one report ID ${!reportId ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Can only handle a single report ID ${extraInput.length < 2 ? colors.red(`(received ${extraInput.length}!)`) : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n await viewReport(reportId, {\n all: Boolean(cli.flags['all']),\n commandName: `${parentName} ${config.commandName}`,\n json: Boolean(cli.flags['json']),\n markdown: Boolean(cli.flags['markdown']),\n strict: Boolean(cli.flags['strict'])\n })\n}\n","import { cmdReportCreate } from './cmd-report-create'\nimport { cmdReportView } from './cmd-report-view'\nimport { meowWithSubcommands } from '../../utils/meow-with-subcommands'\n\nimport type { CliSubcommand } from '../../utils/meow-with-subcommands'\n\nconst description = '[Deprecated] Project report related commands'\n\nexport const cmdReport: CliSubcommand = {\n description,\n async run(argv, importMeta, { parentName }) {\n await meowWithSubcommands(\n {\n create: cmdReportCreate,\n view: cmdReportView\n },\n {\n argv,\n description,\n importMeta,\n name: parentName + ' report'\n }\n )\n }\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function createRepo({\n apiToken,\n default_branch,\n description,\n homepage,\n orgSlug,\n outputJson,\n outputMarkdown,\n repoName,\n visibility\n}: {\n apiToken: string\n outputJson: boolean\n outputMarkdown: boolean\n orgSlug: string\n repoName: string\n description: string\n homepage: string\n default_branch: string\n visibility: string\n}): Promise<void> {\n const spinnerText = 'Creating repository... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.createOrgRepo(orgSlug, {\n outputJson,\n outputMarkdown,\n orgSlug,\n name: repoName,\n description,\n homepage,\n default_branch,\n visibility\n }),\n 'creating repository'\n )\n\n if (result.success) {\n spinner.success('Repository created successfully')\n } else {\n handleUnsuccessfulApiResponse('createOrgRepo', result, spinner)\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { createRepo } from './create-repo'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'create',\n description: 'Create a repository in an organization',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n repoName: {\n type: 'string',\n shortFlag: 'n',\n default: '',\n description: 'Repository name'\n },\n repoDescription: {\n type: 'string',\n shortFlag: 'd',\n default: '',\n description: 'Repository description'\n },\n homepage: {\n type: 'string',\n shortFlag: 'h',\n default: '',\n description: 'Repository url'\n },\n defaultBranch: {\n type: 'string',\n shortFlag: 'b',\n default: 'main',\n description: 'Repository default branch'\n },\n visibility: {\n type: 'string',\n shortFlag: 'v',\n default: 'private',\n description: 'Repository visibility (Default Private)'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg --repoName=test-repo\n `\n}\n\nexport const cmdReposCreate = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const repoName = cli.flags['repoName']\n const [orgSlug = ''] = cli.input\n\n if (!repoName || typeof repoName !== 'string' || !orgSlug) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await createRepo({\n outputJson: Boolean(cli.flags['json']),\n outputMarkdown: Boolean(cli.flags['markdown']),\n orgSlug,\n repoName,\n description: String(cli.flags['repoDescription'] || ''),\n homepage: String(cli.flags['homepage'] || ''),\n default_branch: String(cli.flags['defaultBranch'] || ''),\n visibility: String(cli.flags['visibility'] || 'private'),\n apiToken\n })\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function deleteRepo(\n orgSlug: string,\n repoName: string,\n apiToken: string\n): Promise<void> {\n const spinnerText = 'Deleting repository... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.deleteOrgRepo(orgSlug, repoName),\n 'deleting repository'\n )\n\n if (result.success) {\n spinner.success('Repository deleted successfully')\n } else {\n handleUnsuccessfulApiResponse('deleteOrgRepo', result, spinner)\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { deleteRepo } from './delete-repo'\nimport { commonFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'del',\n description: 'Delete a repository in an organization',\n hidden: false,\n flags: {\n ...commonFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug> <repo slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg test-repo\n `\n}\n\nexport const cmdReposDel = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [orgSlug = '', repoName = ''] = cli.input\n\n if (!orgSlug || !repoName) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Repository name as the second argument ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\\n\n - At least one TARGET (e.g. \\`.\\` or \\`./package.json\\`\\n`)\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await deleteRepo(orgSlug, repoName, apiToken)\n}\n","// @ts-ignore\nimport chalkTable from 'chalk-table'\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function listRepos({\n apiToken,\n direction,\n orgSlug,\n outputJson,\n outputMarkdown,\n page,\n per_page,\n sort\n}: {\n outputJson: boolean\n outputMarkdown: boolean\n orgSlug: string\n sort: string\n direction: string\n per_page: number\n page: number\n apiToken: string\n}): Promise<void> {\n const spinnerText = 'Listing repositories... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getOrgRepoList(orgSlug, {\n outputJson,\n outputMarkdown,\n orgSlug,\n sort,\n direction,\n per_page,\n page\n }),\n 'listing repositories'\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('getOrgRepoList', result, spinner)\n return\n }\n\n const options = {\n columns: [\n { field: 'id', name: colors.magenta('ID') },\n { field: 'name', name: colors.magenta('Name') },\n { field: 'visibility', name: colors.magenta('Visibility') },\n { field: 'default_branch', name: colors.magenta('Default branch') },\n { field: 'archived', name: colors.magenta('Archived') }\n ]\n }\n\n spinner.stop(chalkTable(options, result.data.results))\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { listRepos } from './list-repos'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'list',\n description: 'List repositories in an organization',\n hidden: false,\n flags: {\n ...commonFlags,\n sort: {\n type: 'string',\n shortFlag: 's',\n default: 'created_at',\n description: 'Sorting option'\n },\n direction: {\n type: 'string',\n default: 'desc',\n description: 'Direction option'\n },\n perPage: {\n type: 'number',\n shortFlag: 'pp',\n default: 30,\n description: 'Number of results per page'\n },\n page: {\n type: 'number',\n shortFlag: 'p',\n default: 1,\n description: 'Page number'\n },\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg\n `\n}\n\nexport const cmdReposList = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [orgSlug = ''] = cli.input\n\n if (!orgSlug) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - At least one TARGET (e.g. \\`.\\` or \\`./package.json\\`\\n`)\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await listRepos({\n apiToken,\n outputJson: Boolean(cli.flags['json']),\n outputMarkdown: Boolean(cli.flags['markdown']),\n orgSlug,\n sort: String(cli.flags['sort'] || 'created_at'),\n direction: cli.flags['direction'] === 'asc' ? 'asc' : 'desc',\n page: Number(cli.flags['page']) || 1,\n per_page: Number(cli.flags['perPage']) || 30\n })\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function updateRepo({\n apiToken,\n default_branch,\n description,\n homepage,\n orgSlug,\n outputJson,\n outputMarkdown,\n repoName,\n visibility\n}: {\n apiToken: string\n outputJson: boolean\n outputMarkdown: boolean\n orgSlug: string\n repoName: string\n description: string\n homepage: string\n default_branch: string\n visibility: string\n}): Promise<void> {\n const spinnerText = 'Updating repository... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.updateOrgRepo(orgSlug, repoName, {\n outputJson,\n outputMarkdown,\n orgSlug,\n name: repoName,\n description,\n homepage,\n default_branch,\n visibility\n }),\n 'updating repository'\n )\n\n if (result.success) {\n spinner.success('Repository updated successfully')\n } else {\n handleUnsuccessfulApiResponse('updateOrgRepo', result, spinner)\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { updateRepo } from './update-repo'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'update',\n description: 'Update a repository in an organization',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n repoName: {\n type: 'string',\n shortFlag: 'n',\n default: '',\n description: 'Repository name'\n },\n repoDescription: {\n type: 'string',\n shortFlag: 'd',\n default: '',\n description: 'Repository description'\n },\n homepage: {\n type: 'string',\n shortFlag: 'h',\n default: '',\n description: 'Repository url'\n },\n defaultBranch: {\n type: 'string',\n shortFlag: 'b',\n default: 'main',\n description: 'Repository default branch'\n },\n visibility: {\n type: 'string',\n shortFlag: 'v',\n default: 'private',\n description: 'Repository visibility (Default Private)'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg\n `\n}\n\nexport const cmdReposUpdate = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const repoName = cli.flags['repoName']\n const [orgSlug = ''] = cli.input\n\n if (!repoName || typeof repoName !== 'string' || !orgSlug) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\\n\n - At least one TARGET (e.g. \\`.\\` or \\`./package.json\\`\\n`)\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await updateRepo({\n apiToken,\n outputJson: Boolean(cli.flags['json']),\n outputMarkdown: Boolean(cli.flags['markdown']),\n orgSlug,\n repoName,\n description: String(cli.flags['repoDescription'] || ''),\n homepage: String(cli.flags['homepage'] || ''),\n default_branch: String(cli.flags['defaultBranch'] || ''),\n visibility: String(cli.flags['visibility'] || 'private')\n })\n}\n","// @ts-ignore\nimport chalkTable from 'chalk-table'\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function viewRepo(\n orgSlug: string,\n repoName: string,\n apiToken: string\n): Promise<void> {\n const spinnerText = 'Fetching repository... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getOrgRepo(orgSlug, repoName),\n 'fetching repository'\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('getOrgRepo', result, spinner)\n return\n }\n\n const options = {\n columns: [\n { field: 'id', name: colors.magenta('ID') },\n { field: 'name', name: colors.magenta('Name') },\n { field: 'visibility', name: colors.magenta('Visibility') },\n { field: 'default_branch', name: colors.magenta('Default branch') },\n { field: 'homepage', name: colors.magenta('Homepage') },\n { field: 'archived', name: colors.magenta('Archived') },\n { field: 'created_at', name: colors.magenta('Created at') }\n ]\n }\n\n spinner.stop(chalkTable(options, [result.data]))\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { viewRepo } from './view-repo'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'view',\n description: 'View repositories in an organization',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg\n `\n}\n\nexport const cmdReposView = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const repoName = cli.flags['repoName']\n const [orgSlug = ''] = cli.input\n\n if (!repoName || typeof repoName !== 'string' || !orgSlug) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Repository name using --repoName ${!repoName ? colors.red('(missing!)') : typeof repoName !== 'string' ? colors.red('(invalid!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await viewRepo(orgSlug, repoName, apiToken)\n}\n","import { cmdReposCreate } from './cmd-repos-create'\nimport { cmdReposDel } from './cmd-repos-del'\nimport { cmdReposList } from './cmd-repos-list'\nimport { cmdReposUpdate } from './cmd-repos-update'\nimport { cmdReposView } from './cmd-repos-view'\nimport { meowWithSubcommands } from '../../utils/meow-with-subcommands'\n\nimport type { CliSubcommand } from '../../utils/meow-with-subcommands'\n\nconst description = 'Repositories related commands'\n\nexport const cmdRepos: CliSubcommand = {\n description,\n async run(argv, importMeta, { parentName }) {\n await meowWithSubcommands(\n {\n create: cmdReposCreate,\n view: cmdReposView,\n list: cmdReposList,\n del: cmdReposDel,\n update: cmdReposUpdate\n },\n {\n argv,\n description,\n importMeta,\n name: `${parentName} repos`\n }\n )\n }\n}\n","import process from 'node:process'\nimport readline from 'node:readline/promises'\n\nimport open from 'open'\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function createFullScan({\n apiToken,\n branchName,\n commitHash: _commitHash,\n commitMessage,\n committers: _committers,\n cwd,\n defaultBranch,\n orgSlug,\n packagePaths,\n pendingHead,\n pullRequest: _pullRequest,\n repoName,\n tmp\n}: {\n apiToken: string\n orgSlug: string\n repoName: string\n branchName: string\n committers: string\n commitMessage: string\n commitHash: string\n pullRequest: number | undefined\n defaultBranch: boolean\n pendingHead: boolean\n tmp: boolean\n packagePaths: string[]\n cwd: string\n}): Promise<void> {\n const spinnerText = 'Creating a scan... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.createOrgFullScan(\n orgSlug,\n {\n repo: repoName,\n branch: branchName,\n commit_message: commitMessage,\n make_default_branch: defaultBranch,\n set_as_pending_head: pendingHead,\n tmp\n },\n packagePaths,\n cwd\n ),\n 'Creating scan'\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('CreateOrgFullScan', result, spinner)\n return\n }\n\n spinner.success('Scan created successfully')\n\n const link = colors.underline(colors.cyan(`${result.data.html_report_url}`))\n console.log(`Available at: ${link}`)\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n })\n\n const answer = await rl.question(\n 'Would you like to open it in your browser? (y/n)'\n )\n\n if (answer.toLowerCase() === 'y') {\n await open(`${result.data.html_report_url}`)\n }\n rl.close()\n}\n","import process from 'node:process'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { createFullScan } from './create-full-scan'\nimport { handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getPackageFilesFullScans } from '../../utils/path-resolve'\nimport { getDefaultToken, setupSdk } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'create',\n description: 'Create a scan',\n hidden: false,\n flags: {\n repo: {\n type: 'string',\n shortFlag: 'r',\n default: '',\n description: 'Repository name'\n },\n branch: {\n type: 'string',\n shortFlag: 'b',\n default: '',\n description: 'Branch name'\n },\n commitMessage: {\n type: 'string',\n shortFlag: 'm',\n default: '',\n description: 'Commit message'\n },\n commitHash: {\n type: 'string',\n shortFlag: 'ch',\n default: '',\n description: 'Commit hash'\n },\n cwd: {\n type: 'string',\n description: 'working directory, defaults to process.cwd()'\n },\n dryRun: {\n type: 'boolean',\n description:\n 'run input validation part of command without any concrete side effects'\n },\n pullRequest: {\n type: 'number',\n shortFlag: 'pr',\n description: 'Commit hash'\n },\n committers: {\n type: 'string',\n shortFlag: 'c',\n default: '',\n description: 'Committers'\n },\n defaultBranch: {\n type: 'boolean',\n shortFlag: 'db',\n default: false,\n description: 'Make default branch'\n },\n pendingHead: {\n type: 'boolean',\n shortFlag: 'ph',\n default: false,\n description: 'Set as pending head'\n },\n tmp: {\n type: 'boolean',\n shortFlag: 't',\n default: false,\n description:\n 'Set the visibility (true/false) of the scan in your dashboard'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} [...options] <org> <TARGET> [TARGET...]\n\n Where TARGET is a FILE or DIR that _must_ be inside the CWD.\n\n When a FILE is given only that FILE is targeted. Otherwise any eligible\n files in the given DIR will be considered.\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} --repo=test-repo --branch=main FakeOrg ./package.json\n `\n}\n\nexport const cmdScanCreate = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [orgSlug = '', ...targets] = cli.input\n\n const cwd =\n cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()'\n ? String(cli.flags['cwd'])\n : process.cwd()\n\n // Note exiting earlier to skirt a hidden auth requirement\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const socketSdk = await setupSdk()\n const supportedFiles = await socketSdk\n .getReportSupportedFiles()\n .then(res => {\n if (!res.success)\n handleUnsuccessfulApiResponse(\n 'getReportSupportedFiles',\n res,\n new Spinner()\n )\n // TODO: verify type at runtime? Consider it trusted data and assume type?\n return (res as any).data\n })\n .catch((cause: Error) => {\n throw new Error('Failed getting supported files for report', { cause })\n })\n\n const packagePaths = await getPackageFilesFullScans(\n cwd,\n targets,\n supportedFiles\n )\n\n const { branch: branchName, repo: repoName } = cli.flags\n\n if (!orgSlug || !repoName || !branchName || !packagePaths.length) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - At least one TARGET (e.g. \\`.\\` or \\`./package.json\\`) ${\n !packagePaths.length\n ? colors.red(\n targets.length > 0\n ? '(TARGET' +\n (targets.length ? 's' : '') +\n ' contained no matching/supported files!)'\n : '(missing)'\n )\n : colors.green('(ok)')\n }\\n`)\n return\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await createFullScan({\n apiToken,\n orgSlug,\n repoName: repoName as string,\n branchName: branchName as string,\n commitMessage: (cli.flags['commitMessage'] as string) ?? '',\n defaultBranch: Boolean(cli.flags['defaultBranch']),\n pendingHead: Boolean(cli.flags['pendingHead']),\n tmp: Boolean(cli.flags['tmp']),\n packagePaths,\n cwd,\n commitHash: (cli.flags['commitHash'] as string) ?? '',\n committers: (cli.flags['committers'] as string) ?? '',\n pullRequest: (cli.flags['pullRequest'] as number) ?? undefined\n })\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function deleteOrgFullScan(\n orgSlug: string,\n fullScanId: string,\n apiToken: string\n): Promise<void> {\n const spinnerText = 'Deleting scan...'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.deleteOrgFullScan(orgSlug, fullScanId),\n 'Deleting scan'\n )\n\n if (result.success) {\n spinner.success('Scan deleted successfully')\n } else {\n handleUnsuccessfulApiResponse('deleteOrgFullScan', result, spinner)\n }\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { deleteOrgFullScan } from './delete-full-scan'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'del',\n description: 'Delete a scan',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug> <scan ID>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg 000aaaa1-0000-0a0a-00a0-00a0000000a0\n `\n}\n\nexport const cmdScanDel = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [orgSlug = '', fullScanId = ''] = cli.input\n\n if (!orgSlug || !fullScanId) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Full Scan ID to delete as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}\\n`\n )\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await deleteOrgFullScan(orgSlug, fullScanId, apiToken)\n}\n","// @ts-ignore\nimport chalkTable from 'chalk-table'\nimport colors from 'yoctocolors-cjs'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function listFullScans(\n orgSlug: string,\n input: {\n // TODO: what do we actually need for getOrgFullScanList ?\n outputJson: boolean\n outputMarkdown: boolean\n orgSlug: string\n sort: string\n direction: string\n per_page: number\n page: number\n from_time: string\n until_time: string\n },\n apiToken: string\n): Promise<void> {\n const spinnerText = 'Listing scans... \\n'\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getOrgFullScanList(orgSlug, input),\n 'Listing scans'\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('getOrgFullScanList', result, spinner)\n return\n }\n\n const options = {\n columns: [\n { field: 'id', name: colors.magenta('ID') },\n { field: 'report_url', name: colors.magenta('Scan URL') },\n { field: 'branch', name: colors.magenta('Branch') },\n { field: 'created_at', name: colors.magenta('Created at') }\n ]\n }\n\n const formattedResults = result.data.results.map(d => {\n return {\n id: d.id,\n report_url: colors.underline(`${d.html_report_url}`),\n created_at: d.created_at\n ? new Date(d.created_at).toLocaleDateString('en-us', {\n year: 'numeric',\n month: 'numeric',\n day: 'numeric'\n })\n : '',\n branch: d.branch\n }\n })\n\n spinner.stop(`Listing scans for: ${orgSlug}`)\n console.log(chalkTable(options, formattedResults))\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { listFullScans } from './list-full-scans'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type {\n CliCommandConfig,\n CliSubcommand\n} from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'list',\n description: 'List the full scans for an organization',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n sort: {\n type: 'string',\n shortFlag: 's',\n default: 'created_at',\n description:\n 'Sorting option (`name` or `created_at`) - default is `created_at`'\n },\n direction: {\n type: 'string',\n shortFlag: 'd',\n default: 'desc',\n description: 'Direction option (`desc` or `asc`) - Default is `desc`'\n },\n perPage: {\n type: 'number',\n shortFlag: 'pp',\n default: 30,\n description: 'Results per page - Default is 30'\n },\n page: {\n type: 'number',\n shortFlag: 'p',\n default: 1,\n description: 'Page number - Default is 1'\n },\n fromTime: {\n type: 'string',\n shortFlag: 'f',\n default: '',\n description: 'From time - as a unix timestamp'\n },\n untilTime: {\n type: 'string',\n shortFlag: 'u',\n default: '',\n description: 'Until time - as a unix timestamp'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg\n `\n}\n\nexport const cmdScanList: CliSubcommand = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n) {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const orgSlug = cli.input[0]\n\n if (!orgSlug) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n`)\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await listFullScans(\n orgSlug,\n // TODO: refine this object to what we need\n {\n outputJson: cli.flags['json'],\n outputMarkdown: cli.flags['markdown'],\n orgSlug,\n sort: cli.flags['sort'],\n direction: cli.flags['direction'],\n per_page: cli.flags['perPage'],\n page: cli.flags['page'],\n from_time: cli.flags['fromTime'],\n until_time: cli.flags['untilTime']\n } as {\n outputJson: boolean\n outputMarkdown: boolean\n orgSlug: string\n sort: string\n direction: string\n per_page: number\n page: number\n from_time: string\n until_time: string\n },\n apiToken\n )\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nexport async function getOrgScanMetadata(\n orgSlug: string,\n scanId: string,\n apiToken: string\n): Promise<void> {\n const spinnerText = \"Getting scan's metadata... \\n\"\n const spinner = new Spinner({ text: spinnerText }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const result = await handleApiCall(\n socketSdk.getOrgFullScanMetadata(orgSlug, scanId),\n 'Listing scans'\n )\n\n if (!result.success) {\n handleUnsuccessfulApiResponse('getOrgFullScanMetadata', result, spinner)\n return\n }\n\n spinner.stop('Scan metadata:')\n console.log(result.data)\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { getOrgScanMetadata } from './get-full-scan-metadata'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type {\n CliCommandConfig,\n CliSubcommand\n} from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'metadata',\n description: \"Get a full scan's metadata\",\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug> <scan id>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg 000aaaa1-0000-0a0a-00a0-00a0000000a0\n `\n}\n\nexport const cmdScanMetadata: CliSubcommand = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [orgSlug = '', fullScanId = ''] = cli.input\n\n if (!orgSlug || !fullScanId) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Full Scan ID to inspect as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}\\n`\n )\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await getOrgScanMetadata(orgSlug, fullScanId, apiToken)\n}\n","import { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'\nimport { setupSdk } from '../../utils/sdk'\n\nimport type { SocketSdkResultType } from '@socketsecurity/sdk'\n\nexport async function getFullScan(\n orgSlug: string,\n fullScanId: string,\n file: string | undefined,\n apiToken: string\n): Promise<SocketSdkResultType<'getOrgFullScan'>> {\n const spinner = new Spinner({ text: 'Streaming scan...' }).start()\n\n const socketSdk = await setupSdk(apiToken)\n const data = await handleApiCall(\n socketSdk.getOrgFullScan(\n orgSlug,\n fullScanId,\n file === '-' ? undefined : file\n ),\n 'Streaming a scan'\n )\n\n if (data?.success) {\n spinner.stop(file ? `Full scan details written to ${file}` : '')\n } else {\n handleUnsuccessfulApiResponse('getOrgFullScan', data, spinner)\n }\n\n return data\n}\n","import colors from 'yoctocolors-cjs'\n\nimport { getFullScan } from './get-full-scan'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type {\n CliCommandConfig,\n CliSubcommand\n} from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'stream',\n description: 'Stream the output of a scan',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags\n },\n help: (command, config) => `\n Usage\n $ ${command} <org slug> <scan ID> [path to output file]\n\n When no output path is given the contents is sent to stdout.\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} FakeOrg 000aaaa1-0000-0a0a-00a0-00a0000000a0 ./stream.txt\n `\n}\n\nexport const cmdScanStream: CliSubcommand = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: readonly string[],\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const [orgSlug = '', fullScanId = '', file = '-'] = cli.input\n\n if (!orgSlug || !fullScanId) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(\n `${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\\n\n - Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\\n\n - Full Scan ID to fetch as second argument ${!fullScanId ? colors.red('(missing!)') : colors.green('(ok)')}\\n`\n )\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await getFullScan(orgSlug, fullScanId, file, apiToken)\n}\n","import { cmdScanCreate } from './cmd-scan-create'\nimport { cmdScanDel } from './cmd-scan-del'\nimport { cmdScanList } from './cmd-scan-list'\nimport { cmdScanMetadata } from './cmd-scan-metadata'\nimport { cmdScanStream } from './cmd-scan-stream'\nimport { meowWithSubcommands } from '../../utils/meow-with-subcommands'\n\nimport type { CliSubcommand } from '../../utils/meow-with-subcommands'\n\nconst description = 'Scans related commands'\n\nexport const cmdScan: CliSubcommand = {\n description,\n async run(argv, importMeta, { parentName }) {\n await meowWithSubcommands(\n {\n create: cmdScanCreate,\n stream: cmdScanStream,\n list: cmdScanList,\n del: cmdScanDel,\n metadata: cmdScanMetadata\n },\n {\n argv,\n description,\n importMeta,\n name: parentName + ' scan'\n }\n )\n }\n}\n","import process from 'node:process'\n\n// @ts-ignore\nimport ScreenWidget from 'blessed/lib/widgets/screen'\n// @ts-ignore\nimport TableWidget from 'blessed-contrib/lib/widget/table'\n\nimport { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nimport { queryAPI } from '../../utils/api'\n\ntype ThreatResult = {\n createdAt: string\n description: string\n id: number\n locationHtmlUrl: string\n packageHtmlUrl: string\n purl: string\n removedAt: string\n threatType: string\n}\n\nexport async function getThreatFeed({\n apiToken,\n direction,\n filter,\n outputJson,\n page,\n perPage\n}: {\n apiToken: string\n outputJson: boolean\n perPage: number\n page: string\n direction: string\n filter: string\n}): Promise<void> {\n const spinner = new Spinner({\n text: 'Looking up the threat feed'\n }).start()\n\n const formattedQueryParams = formatQueryParams({\n per_page: perPage,\n page,\n direction,\n filter\n }).join('&')\n const response = await queryAPI(\n `threat-feed?${formattedQueryParams}`,\n apiToken\n )\n const data = <{ results: ThreatResult[]; nextPage: string }>(\n await response.json()\n )\n\n spinner.stop()\n\n if (outputJson) {\n console.log(data)\n return\n }\n\n const screen = new ScreenWidget()\n\n const table = new TableWidget({\n keys: 'true',\n fg: 'white',\n selectedFg: 'white',\n selectedBg: 'magenta',\n interactive: 'true',\n label: 'Threat feed',\n width: '100%',\n height: '100%',\n border: {\n type: 'line',\n fg: 'cyan'\n },\n columnSpacing: 3, //in chars\n columnWidth: [9, 30, 10, 17, 13, 100] /*in chars*/\n })\n\n // allow control the table with the keyboard\n table.focus()\n\n screen.append(table)\n\n const formattedOutput = formatResults(data.results)\n\n table.setData({\n headers: [\n 'Ecosystem',\n 'Name',\n 'Version',\n 'Threat type',\n 'Detected at',\n 'Details'\n ],\n data: formattedOutput\n })\n\n screen.render()\n\n screen.key(['escape', 'q', 'C-c'], () => process.exit(0))\n}\n\nfunction formatResults(data: ThreatResult[]) {\n return data.map(d => {\n const ecosystem = d.purl.split('pkg:')[1]!.split('/')[0]!\n const name = d.purl.split('/')[1]!.split('@')[0]!\n const version = d.purl.split('@')[1]!\n\n const timeStart = new Date(d.createdAt).getMilliseconds()\n const timeEnd = Date.now()\n\n const diff = getHourDiff(timeStart, timeEnd)\n const hourDiff =\n diff > 0\n ? `${diff} hours ago`\n : `${getMinDiff(timeStart, timeEnd)} minutes ago`\n\n return [\n ecosystem,\n decodeURIComponent(name),\n version,\n d.threatType,\n hourDiff,\n d.locationHtmlUrl\n ]\n })\n}\n\nfunction formatQueryParams(params: object) {\n return Object.entries(params).map(entry => `${entry[0]}=${entry[1]}`)\n}\n\nfunction getHourDiff(start: number, end: number) {\n return Math.floor((end - start) / 3600000)\n}\n\nfunction getMinDiff(start: number, end: number) {\n return Math.floor((end - start) / 60000)\n}\n","import { getThreatFeed } from './get-threat-feed'\nimport { commonFlags, outputFlags } from '../../flags'\nimport { AuthError } from '../../utils/errors'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\nimport { getDefaultToken } from '../../utils/sdk'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'threat-feed',\n description: 'Look up the threat feed',\n hidden: false,\n flags: {\n ...commonFlags,\n ...outputFlags,\n perPage: {\n type: 'number',\n shortFlag: 'pp',\n default: 30,\n description: 'Number of items per page'\n },\n page: {\n type: 'string',\n shortFlag: 'p',\n default: '1',\n description: 'Page token'\n },\n direction: {\n type: 'string',\n shortFlag: 'd',\n default: 'desc',\n description: 'Order asc or desc by the createdAt attribute.'\n },\n filter: {\n type: 'string',\n shortFlag: 'f',\n default: 'mal',\n description: 'Filter what type of threats to return'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command}\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command}\n $ ${command} --perPage=5 --page=2 --direction=asc --filter=joke\n `\n}\n\nexport const cmdThreatFeed = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: ReadonlyArray<string>,\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n const apiToken = getDefaultToken()\n if (!apiToken) {\n throw new AuthError(\n 'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'\n )\n }\n\n await getThreatFeed({\n apiToken,\n direction: String(cli.flags['direction'] || 'desc'),\n filter: String(cli.flags['filter'] || 'mal'),\n outputJson: Boolean(cli.flags['json']),\n page: String(cli.flags['filter'] || '1'),\n perPage: Number(cli.flags['per_page'] || 0)\n })\n}\n","import fs from 'node:fs'\n\nexport function addSocketWrapper(file: string): void {\n return fs.appendFile(\n file,\n 'alias npm=\"socket npm\"\\nalias npx=\"socket npx\"\\n',\n err => {\n if (err) {\n return new Error(`There was an error setting up the alias: ${err}`)\n }\n // TODO: pretty sure you need to source the file or restart\n // any terminal session before changes are reflected.\n console.log(`\nThe alias was added to ${file}. Running 'npm install' will now be wrapped in Socket's \"safe npm\" 🎉\nIf you want to disable it at any time, run \\`socket wrapper --disable\\`\n`)\n }\n )\n}\n","import fs from 'node:fs'\n\nexport function checkSocketWrapperSetup(file: string): boolean {\n const fileContent = fs.readFileSync(file, 'utf8')\n const linesWithSocketAlias = fileContent\n .split('\\n')\n .filter(\n l => l === 'alias npm=\"socket npm\"' || l === 'alias npx=\"socket npx\"'\n )\n\n if (linesWithSocketAlias.length) {\n console.log(\n `The Socket npm/npx wrapper is set up in your bash profile (${file}).`\n )\n return true\n }\n return false\n}\n","import { existsSync } from 'node:fs'\nimport process from 'node:process'\nimport readline from 'node:readline'\n\nimport { addSocketWrapper } from './add-socket-wrapper'\nimport { checkSocketWrapperSetup } from './check-socket-wrapper-setup'\nimport constants from '../../constants'\n\nexport function postinstallWrapper() {\n // Lazily access constants.bashRcPath and constants.zshRcPath.\n const { bashRcPath, zshRcPath } = constants\n const socketWrapperEnabled =\n (existsSync(bashRcPath) && checkSocketWrapperSetup(bashRcPath)) ||\n (existsSync(zshRcPath) && checkSocketWrapperSetup(zshRcPath))\n\n if (!socketWrapperEnabled) {\n installSafeNpm(`The Socket CLI is now successfully installed! 🎉\n\n To better protect yourself against supply-chain attacks, our \"safe npm\" wrapper can warn you about malicious packages whenever you run 'npm install'.\n\n Do you want to install \"safe npm\" (this will create an alias to the socket-npm command)? (y/n)`)\n }\n}\n\nfunction installSafeNpm(query: string): void {\n console.log(`\n _____ _ _\n| __|___ ___| |_ ___| |_\n|__ | . | _| '_| -_| _|\n|_____|___|___|_,_|___|_|\n\n`)\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n })\n return askQuestion(rl, query)\n}\n\nfunction askQuestion(rl: readline.Interface, query: string): void {\n rl.question(query, (ans: string) => {\n if (ans.toLowerCase() === 'y') {\n // Lazily access constants.bashRcPath and constants.zshRcPath.\n const { bashRcPath, zshRcPath } = constants\n try {\n if (existsSync(bashRcPath)) {\n addSocketWrapper(bashRcPath)\n }\n if (existsSync(zshRcPath)) {\n addSocketWrapper(zshRcPath)\n }\n } catch (e) {\n throw new Error(`There was an issue setting up the alias: ${e}`)\n }\n rl.close()\n } else if (ans.toLowerCase() !== 'n') {\n askQuestion(\n rl,\n 'Incorrect input: please enter either y (yes) or n (no): '\n )\n } else {\n rl.close()\n }\n })\n}\n","import fs from 'node:fs'\n\nexport function removeSocketWrapper(file: string): void {\n return fs.readFile(file, 'utf8', function (err, data) {\n if (err) {\n console.error(`There was an error removing the alias: ${err}`)\n return\n }\n const linesWithoutSocketAlias = data\n .split('\\n')\n .filter(\n l => l !== 'alias npm=\"socket npm\"' && l !== 'alias npx=\"socket npx\"'\n )\n\n const updatedFileContent = linesWithoutSocketAlias.join('\\n')\n\n fs.writeFile(file, updatedFileContent, function (err) {\n if (err) {\n console.log(err)\n return\n } else {\n // TODO: pretty sure you need to source the file or restart\n // any terminal session before changes are reflected.\n console.log(\n `\\nThe alias was removed from ${file}. Running 'npm install' will now run the standard npm command.\\n`\n )\n }\n })\n })\n}\n","import { existsSync } from 'node:fs'\n\nimport colors from 'yoctocolors-cjs'\n\nimport { addSocketWrapper } from './add-socket-wrapper'\nimport { checkSocketWrapperSetup } from './check-socket-wrapper-setup'\nimport { postinstallWrapper } from './postinstall-wrapper'\nimport { removeSocketWrapper } from './remove-socket-wrapper'\nimport constants from '../../constants'\nimport { commonFlags } from '../../flags'\nimport { meowOrExit } from '../../utils/meow-with-subcommands'\nimport { getFlagListOutput } from '../../utils/output-formatting'\n\nimport type { CliCommandConfig } from '../../utils/meow-with-subcommands'\n\nconst config: CliCommandConfig = {\n commandName: 'wrapper',\n description: 'Enable or disable the Socket npm/npx wrapper',\n hidden: false,\n flags: {\n ...commonFlags,\n enable: {\n type: 'boolean',\n default: false,\n description: 'Enables the Socket npm/npx wrapper'\n },\n disable: {\n type: 'boolean',\n default: false,\n description: 'Disables the Socket npm/npx wrapper'\n }\n },\n help: (command, config) => `\n Usage\n $ ${command} <flag>\n\n Options\n ${getFlagListOutput(config.flags, 6)}\n\n Examples\n $ ${command} --enable\n $ ${command} --disable\n `\n}\n\nexport const cmdWrapper = {\n description: config.description,\n hidden: config.hidden,\n run\n}\n\nasync function run(\n argv: ReadonlyArray<string>,\n importMeta: ImportMeta,\n { parentName }: { parentName: string }\n): Promise<void> {\n // I don't think meow would mess with this but ...\n if (argv[0] === '--postinstall') {\n postinstallWrapper()\n return\n }\n\n const cli = meowOrExit({\n argv,\n config,\n importMeta,\n parentName\n })\n\n const { enable } = cli.flags\n if (!enable && !cli.flags['disable']) {\n // Use exit status of 2 to indicate incorrect usage, generally invalid\n // options or missing arguments.\n // https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html\n process.exitCode = 2\n console.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required flags:\\n\n - Must use --enabled or --disabled\\n`)\n return\n }\n\n if (cli.flags['dryRun']) {\n return console.log('[DryRun] Bailing now')\n }\n\n // Lazily access constants.bashRcPath and constants.zshRcPath.\n const { bashRcPath, zshRcPath } = constants\n if (enable) {\n if (existsSync(bashRcPath) && !checkSocketWrapperSetup(bashRcPath)) {\n addSocketWrapper(bashRcPath)\n }\n if (existsSync(zshRcPath) && !checkSocketWrapperSetup(zshRcPath)) {\n addSocketWrapper(zshRcPath)\n }\n } else {\n if (existsSync(bashRcPath)) {\n removeSocketWrapper(bashRcPath)\n }\n if (existsSync(zshRcPath)) {\n removeSocketWrapper(zshRcPath)\n }\n }\n if (!existsSync(bashRcPath) && !existsSync(zshRcPath)) {\n console.error(\n 'There was an issue setting up the alias in your bash profile'\n )\n }\n}\n","#!/usr/bin/env node\n\nimport process from 'node:process'\nimport { pathToFileURL } from 'node:url'\n\nimport { messageWithCauses, stackWithCauses } from 'pony-cause'\nimport updateNotifier from 'tiny-updater'\nimport colors from 'yoctocolors-cjs'\n\nimport { cmdAction } from './commands/action/cmd-action'\nimport { cmdAnalytics } from './commands/analytics/cmd-analytics'\nimport { cmdAuditLog } from './commands/audit-log/cmd-audit-log'\nimport { cmdCdxgen } from './commands/cdxgen/cmd-cdxgen'\nimport { cmdScanCreate } from './commands/dependencies/cmd-dependencies'\nimport { cmdDiffScan } from './commands/diff-scan/cmd-diff-scan'\nimport { cmdFix } from './commands/fix/cmd-fix'\nimport { cmdInfo } from './commands/info/cmd-info'\nimport { cmdLogin } from './commands/login/cmd-login'\nimport { cmdLogout } from './commands/logout/cmd-logout'\nimport { cmdManifest } from './commands/manifest/cmd-manifest'\nimport { cmdNpm } from './commands/npm/cmd-npm'\nimport { cmdNpx } from './commands/npx/cmd-npx'\nimport { cmdOops } from './commands/oops/cmd-oops'\nimport { cmdOptimize } from './commands/optimize/cmd-optimize'\nimport { cmdOrganization } from './commands/organization/cmd-organization'\nimport { cmdRawNpm } from './commands/raw-npm/cmd-raw-npm'\nimport { cmdRawNpx } from './commands/raw-npx/cmd-raw-npx'\nimport { cmdReport } from './commands/report/cmd-report'\nimport { cmdRepos } from './commands/repos/cmd-repos'\nimport { cmdScan } from './commands/scan/cmd-scan'\nimport { cmdThreatFeed } from './commands/threat-feed/cmd-threat-feed'\nimport { cmdWrapper } from './commands/wrapper/cmd-wrapper'\nimport constants from './constants'\nimport { AuthError, InputError, captureException } from './utils/errors'\nimport { getLogSymbols } from './utils/logging'\nimport { meowWithSubcommands } from './utils/meow-with-subcommands'\n\nconst { SOCKET, rootPkgJsonPath } = constants\n\n// TODO: Add autocompletion using https://socket.dev/npm/package/omelette\nvoid (async () => {\n await updateNotifier({\n name: SOCKET,\n version: require(rootPkgJsonPath).version,\n ttl: 86_400_000 /* 24 hours in milliseconds */\n })\n\n try {\n await meowWithSubcommands(\n {\n action: cmdAction,\n cdxgen: cmdCdxgen,\n fix: cmdFix,\n info: cmdInfo,\n login: cmdLogin,\n logout: cmdLogout,\n npm: cmdNpm,\n npx: cmdNpx,\n oops: cmdOops,\n optimize: cmdOptimize,\n organization: cmdOrganization,\n 'raw-npm': cmdRawNpm,\n 'raw-npx': cmdRawNpx,\n report: cmdReport,\n wrapper: cmdWrapper,\n scan: cmdScan,\n 'audit-log': cmdAuditLog,\n repos: cmdRepos,\n dependencies: cmdScanCreate,\n analytics: cmdAnalytics,\n 'diff-scan': cmdDiffScan,\n 'threat-feed': cmdThreatFeed,\n manifest: cmdManifest\n },\n {\n aliases: {\n ci: {\n description: 'Alias for \"report create --view --strict\"',\n argv: ['report', 'create', '--view', '--strict']\n }\n },\n argv: process.argv.slice(2),\n name: SOCKET,\n importMeta: { url: `${pathToFileURL(__filename)}` } as ImportMeta\n }\n )\n } catch (e: any) {\n process.exitCode = 1\n let errorBody: string | undefined\n let errorTitle: string\n let errorMessage = ''\n if (e instanceof AuthError) {\n errorTitle = 'Authentication error'\n errorMessage = e.message\n } else if (e instanceof InputError) {\n errorTitle = 'Invalid input'\n errorMessage = e.message\n errorBody = e.body\n } else if (e instanceof Error) {\n errorTitle = 'Unexpected error'\n errorMessage = messageWithCauses(e)\n errorBody = stackWithCauses(e)\n } else {\n errorTitle = 'Unexpected error with no details'\n }\n console.error(\n `${getLogSymbols().error} ${colors.bgRed(colors.white(errorTitle + ':'))} ${errorMessage}`\n )\n if (errorBody) {\n console.error(`\\n${errorBody}`)\n }\n await captureException(e)\n }\n})()\n"],"names":["id","body","body_list","newPackages","removedPackages","newAlerts","sbom","reportUrl","diffUrl","created_at","updated_at","organizationId","repositoryId","branch","commit_message","commit_hash","pull_request","sbom_artifacts","constructor","pkg_type","pkg_name","pkg_version","category","type","severity","pkg_id","key","error","warn","ignore","monitor","description","title","emoji","next_step_title","suggestion","introduced_by","manifests","url","purl","arr","name","version","release","direct","manifestFiles","author","size","alerts","topLevelAncestors","transitives","license","license_text","supplyChain","quality","overall","vulnerability","critical","high","middle","low","ecosystem","capabilities","author_url","generateAuthorData","socket","fullScanId","data","params","fullScan","getSourceData","pkg","file","createPurl","packages","nextStepTitle","issueAlert","compareIssueAlerts","newScanAlerts","consolidatedAlerts","checkAlertCapabilities","envVars","networkAccess","filesystemAccess","shellAccess","newAlert","compareCapabilities","headPackage","packageId","newScan","diff","consolidated","headScanAlerts","headPackages","getLicenseDetails","package","console","topLevelCount","headFullScanId","headFullScan","headScan","diffReport","comments","security","overview","comment","socketComments","ignoreAll","result","ignoredPackages","line","start","command","ignoreCommands","octokit","checkEventType","commentId","comment_id","content","securityComment","rows","md","removedLine","sources","nextSteps","mdTable","changedFiles","newSecurityComment","newOverviewComment","API_V0_URL","spinner","process","cause","method","headers","keyPrefix","padName","help","default","shortFlag","dryRun","json","markdown","all","strict","SOCKET_CLI_SHOW_BANNER","__proto__","parentName","hidden","allowUnknownFlags","commandName","flags","githubEventBefore","githubEventAfter","run","time","text","cols","screen","label","barWidth","barSpacing","xOffset","maxHeight","barBgColor","handleUnsuccessfulApiResponse","formattedData","totalTopAlerts","formatted","sortedTopFiveAlerts","top_five_alert_types","style","baseline","xLabelPadding","xPadding","wholeNumbersOnly","legend","width","x","y","scope","repo","per_page","year","month","day","choices","pageSize","perPage","page","SBOM_SIGN_PUBLIC_KEY","synpBinPath","cleanupPackageLock","env","NODE_ENV","stdio","configuration","coerce","filter","only","profile","standard","lifecycle","alias","array","boolean","argv","length","outputJson","offset","columns","field","limit","fs","err","showHidden","depth","colors","before","after","preview","get","NPM","editable","path","consolidate","includeExisting","includeUnfixable","vulnerableVersionRange","editablePkgJson","arb2","value","severityCount","Maintenance","Quality","Vulnerabilities","Object","formatPackageIssuesDetails","fallbackToUrl","count","acc","updateSetting","SOCKET_PUBLIC_API_TOKEN","message","apiBaseUrl","apiProxy","enforcedOrgs","applyLogout","attemptLogout","bin","cwd","gradleOpts","out","stdout","task","verbose","poms","sbtOpts","subArgs","meow","importMeta","auto","scala","gradle","kotlin","aliases","yolo","SHADOW_BIN","NPX","YARN_CLASSIC","nothrow","onUnknown","agent","agentVersion","browser","node","lockSrc","lockName","lockPath","pkgJson","supported","targets","YARN_BERRY","prod","logger","peerDependencies","overrides","PNPM","workspacePatterns","pkgs","pkgid","names","isPlacingHigher","insertIndex","entries","updatePkgJson","abortSignal","args","signal","spawnPromise","pkgPath","state","added","addedInWorkspaces","updated","updatedInWorkspaces","warnedPnpmWorkspaceRequiresNpm","npmExecPath","overridesDataObjects","depAliasMap","thisSpec","depObj","newSpec","absolute","updateManifestByAgent","pin","mw1","mw2","mw3","debugLog","basePath","formatReportDataOutput","view","create","visibility","repoName","repoDescription","homepage","defaultBranch","apiToken","sort","direction","list","del","update","commitHash","committers","pullRequest","tmp","make_default_branch","set_as_pending_head","commitMessage","pendingHead","branchName","fromTime","untilTime","outputMarkdown","from_time","until_time","stream","metadata","keys","fg","selectedFg","selectedBg","interactive","height","border","columnSpacing","columnWidth","zshRcPath","installSafeNpm","rl","askQuestion","enable","disable","postinstallWrapper","rootPkgJsonPath","action","cdxgen","fix","info","login","logout","npm","npx","oops","optimize","organization","report","wrapper","scan","repos","dependencies","analytics","manifest","ci","errorTitle","errorMessage","errorBody"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AAqBO;AACLA;AACAC;AACAC;;;;;AAMA;AACF;AAEO;AACLC;;AAEAC;AACAC;AACAL;AACAM;;AAEAC;AACAC;AACF;AAEO;AACLR;AACAS;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;;AAGAC;;;;;;;;;;;;AAYA;AACF;AAEO;AACLC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;;AAEAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;;;;;;;;;;;;;;;;;;;;AA0CI;AACE;AACAC;AACF;;AAEF;AACF;AACF;AAEO;AACLjB;AACAkB;AACAC;AACAC;AACA3C;AACA4C;AACAC;AACAC;AACAC;;AAGAC;;AAEAC;AACAX;AACAY;AACAC;AACAC;AACAb;;;;;;;;;;;;;AA6BE;;AAGIc;AACAC;AACAH;AACAI;AACAC;AACF;;AAGAC;AACAC;AACAC;AACAC;;AAEF;AACF;AACF;AAEO;AACL5D;AACAyC;AACAC;AACAmB;AACAjB;AACAE;AACAC;AACAG;AACAd;AACA0B;AACA;AACAC;AACAzB;AACAC;;;;;;;;;;;;;AA2BE;AACF;AAEQyB;;AAEN;AACE;;AAEF;AACA;AACF;AACF;AAEO;AACLX;AACAC;AACAH;AACAI;AACAC;;;;;;;AAQA;AACF;;AC1RA;AACA;AAaO;;AAULtC;;;AAGE+C;AACiD;;;;;AAKnD;AAEA;AACEC;AAGF;AACE;AAKA;AACE;AACF;;AAEQC;AAAgC;;;AAOxC;AAEA;AACF;AAEA;AACEC;AAGF;;AAGI;AACA;AACA;;;AAAiD;AAInD;;AAEA;;AAEQpE;;;;AAGNqE;AAAmDH;AAAW;AAChE;AACA;AACF;AAEAI;;AAEEC;AAIF;;;;AAI6CC;AAAK;;AAGhD;AACE;AACE;;AAGE;AACF;AAEA;;AAEUA;AAAK;;AAIjB;AACF;AAEA;AACF;AAEAC;;AAEEC;AAIF;AACE;AACA;;AAA+CA;AAAS;AACxD;;;;;;AAMEtC;;;;;;AAMF;;;AACemC;;AACjB;AAEA;;;AAGEA;AAKF;;AAKE;AACE;;;;;;AAQExC;AACAC;AACAG;AACAwC;AACF;AAEA;;AAA+CD;AAAS;AAExD;;;;;;;;;;;;AAYExC;AACAE;;;AAGAT;AACAE;AACAD;AACAE;AACF;AAEA;;;AAGI8C;AACF;AACF;AAEA;AACE;;AAEA;;AAEA;AACF;AACF;AAEA;AACF;AAEAC;;;AAGEC;AAKF;AACE;AAEA;AACE;AACE;AAEA;AACE;AAEA;AACE;AACE9B;AACA+B;AACF;AACF;AACF;AACF;AACE;AACA;AAEA;AACE;AACA;AAIE;AACE/B;AACA+B;AACF;AACF;AACF;AACF;AACF;AAEA;AACF;AAEAC;;;;AAIET;AAMF;AACE;AACEU;AACAC;AACAC;AACAC;;AAGF;;AAEE;AACEC;AACF;AACA;AACE;AACA;AACEvB;AACF;;AAEIA;AACF;AACF;AACF;AACF;AAEA;AACF;AAEAwB;;AAEEnF;AAIF;;AAGE;AACE;;AAGE;AACA;;AAEI2D;;;;AAIEyB;AACF;AACF;AACF;AACF;AACEzB;;;AAGE0B;AACF;AACF;AACF;AAEA;AACF;;;AAKE;AACE;;AAGE;;AAEErF;AACF;AACF;AACEA;AACF;AACF;;AAGA;AACF;AAEA;;AAEEsF;AAIF;AACE;AACA;AACA;;;AAIA;AAEA;;;AACelD;AAAK;;AAEhBmC;AACF;AACA;AAEA;AAKEgB;AACAC;AACF;AAEAb;;AAEE9B;AACA0B;AACF;AACF;AAEA;;;AACenC;AAAK;;AAEhBmC;AACF;;AAGEgB;AACF;AAEAE;;AAEE5C;AACA0B;AACF;AACF;AAEAgB;;;;AAIA;AACAA;;AAEEG;AACF;AACAH;AAEA;AACF;;;;;;;;;;;;;;;;AAqBM;AAEN;AAEAI;AAAoBC;AAAmC;;AAOrD;;;AAGA;AACA;AACF;;;;AAQE;AACE;;;;;;;;;;;;;;AAcA;AAEA;AACEC;AACF;AACEzB;AAA+BwB;AAAa;AAC5CrB;;AAGE;AACEuB;AACF;AACEA;AACF;AACF;AACF;AACF;;AAGE;AACE;AACA;;AAEA;AACF;AACF;AAEA;AACF;AAEA;AACE7B;AAMF;;;;AAKI;;AAKE8B;;AAEEC;AAAwCjC;AAA2B;AACrE;AACF;;AAEA8B;AACF;AAEA;AAAgD5B;AAAO;;AAGvD;;AAEEgC;AACF;AACAC;;AAGAA;AACAA;;AAEEA;AACF;AACEA;AACF;AAEA;AACF;AACF;;AC/iBA;;AASO;AACLC;AAGF;AACE;AAKEC;AACAC;AACA3E;;AAGF;AACE;;;;;AAMA;AACE;AACA;AACA;AACA;AACA4E;AAKAC;AACF;AACF;AAEA;AACF;;AAEA;AACA;AACA;AACO;AACL;AAAiBhC;AAA0BiC;;AAC3C;;;AAGE;AACF;;AAEE;AACE;AACAC;AACF;AACA;AACF;AACA;AACF;;AAEA;AACO;AACL/E;AACA0E;AAC2C;;;;;AAM3C;AACE;;AAIEI;AACA;AACF;AACAE;AACF;;AAEA;AACA;AACA;AACEC;AAEA;AACEC;AACAH;;AAIA;AACA;AAMA;AACA;;AAGA;;;;AAMA;;AAEA;AACE/E;AACF;;AAEI;AAIEA;AACA;AACF;AACF;AACF;AAEA;AACE;AACF;AACA+E;;AAEAG;AACAH;AACF;AACEA;AACF;AACF;AAEA;AACF;AAEO;AAA4BN;AAAuC;;;AAIxE;AACE;;;;;AAKIU;;AAEEL;AACF;AACEK;;AAEA;AACAC;AACF;;AAEAjB;AACAA;AACF;AACF;AACF;;;AACoBiB;;AACtB;AAEO;;AAEL5G;AAIF;;AAGE;AACE;AACF;;;AAEmB4G;;AACjBX;AACF;AAEA;AACE;AACE;AACF;;;AAGE;AACA;AACEN;AACF;AACEA;AAGAhD;AACF;AACF;AACF;AAEA;AACF;;ACpNA;AACA;AAMO;AACLkE;AAKAhG;;AAIE;;;;;AAOF;AAEAiG;AACE;AACE;AACE;AACF;AACE;AACA;AACA;AACA;AACA;AACA;AACA;;AAEE;AACF;;AAEE;AACF;AACEnB;;AAEF;AACF;AACE;AACF;;AAIF;AACF;;;AAGU7B;;;;;AAKN;;AAEF;;;AAGIlE;;AAEF;AACF;;AAC4CqG;AAAS;AACvD;AAEA;AACEc;AAGF;;AACUjD;;;;AAGNkD;AACF;;AAEF;AAEA;AAAqBD;AAAiC;AACpD;;;AAGEC;AACAC;AACF;AACF;AAEA;AACEhB;AAGF;AACE;AACE;;;;;AAMwD;AACxD;AACF;AACF;AAEA;;AAA4BtG;AAAiC;AAC3D;;;AAGEqH;AACApH;AACF;AACF;AAEA;AACEqG;AAGF;AACE;;AAEE;;;AAGA;;AACkCA;AAAS;;;AACMrG;AAAc;AACjE;AACF;AAEA;AAAoBA;AAAuB;AACzC;;;;AAIEA;AACF;AACF;AAEA;;;;;AAKEsH;AAOF;;AAEIf;AACAD;AACF;AACA;AACEP;;AAEEA;;AAEE/F;;AAEF;AACF;AACE+F;;AACyB/F;AAAsB;AACjD;AACF;AACA;AACE+F;;AAEEA;;AAEE/F;;AAEF;AACF;AACE+F;;AACyB/F;AAAsB;AACjD;AACF;AACF;AACF;;AC/LA;;AAyBO;;AAEL;AACF;AAEO;AACL;;AASA;AACE;;;AAUAuH;AACF;;;AAIAC;AACA;;AAEA;AAEA;AACF;AAEO;AACL;AACA;AACE;AACAC;AACF;AACA;AACF;AAEO;;AAELD;AACAA;AACAA;AAEAA;AACA;AACEA;AACF;AACA;AACF;AAEO;;;;AAIH;AACA;AACA;AACEE;AACF;AACA;AACEtF;AACF;AACF;AACA;AACA;AACA;AACA;AACA;AACF;AAEO;AAKL;;;;AAWA;AACE;AACEuF;AACF;AACA;AACA;AACEX;AACF;;;;;AAKA;;AAEA;AACA;AACA;AACEO;AACF;AACF;;;AAIAC;AACA;;AAEA;;;;AAEoCI;;AACtC;AAEO;;AAEL;AACE;AACAJ;;AAEA;;AAEA;AACAA;AACF;AACA;AACF;AAEO;;AAELA;AACAA;AACAA;AAEAA;AACA;AACF;AAEO;;AAELA;AACAA;AACAA;AAEAA;AACA;AACF;AAEO;;AAELA;AACAA;AACAA;AAEAA;AACA;;AAEA;AACAA;AACAA;AACA;AACF;AAEO;;AAELA;AACAA;AACAA;AAEAA;AAEAA;;;;AACiCG;AAAU;AAC3CH;AACAA;AACAA;;;AAGAA;AACA;AACF;;AC3NA;;;AAaA;AACO;AAIL;;AAGA;AACA;;AAQcK;AAAa;AAC3B;;AAMA;AAEA;AAEA;AACE9B;AACA;;AACgCM;AAAS;;AAEzCN;AACA;;;;AAAiE/B;AAAO;;AAExE;AACAyB;;;AAGA;AACA;AACA;;;AAGA;AACA;AACA;;AAEIqC;AACA/B;AACF;AACEA;AACF;AACF;AACA;;AAEIgC;AACAhC;AAGF;AACEA;AACF;AACF;;;;;;AAMEgC;AACF;AACF;AACF;;ACzEA;AAAQC;AAAW;AAEZ;AAKL;AACA;;;;AAOE;AACF;AACAC;AAGAC;AACF;AAEO;AAIL;;;;AAIE;AAA2CC;AAAM;AACnD;AACA;AACF;AAEO;;AAEH;AACF;AACE;AACF;AACF;AAEO;AACL;;AAEF;AAEO;;AAEHC;AACAC;;AAEA;AACF;AACF;;AC9DO;AAGHC;AAAkBC;AAAQ;AAE5B;;;;AAKeA;AAAQ;AAEzB;AAEO;AAGHD;AAAgBC;AAAa;;;AAI/B;AACE;AACA;;AASF;AACA;AACF;;ACvCA;;AAMA;;AAGO;AACLC;AACElH;AACAmH;AACAC;AACA5G;;AAEF6G;AACErH;AACAmH;AACA3G;AACF;AACF;AAEO;AACL8G;AACEtH;AACAoH;AACAD;AACA3G;;AAEF+G;AACEvH;AACAoH;AACAD;AACA3G;AACF;AACF;AAEO;AACLgH;AACExH;AACAmH;AACA3G;;AAEFiH;AACEzH;AACAmH;AACA3G;AACF;AACF;;ACtCA;AAAQkH;AAAuB;AAiDxB;;;;;;;AAUL;AAAMC;;;AACN;AACA;AACA;AACE;AACA;;AAIA;;AAEA;AACA;;AAEIC;AACF;AACF;AACF;AACA;AACE;AACA;;AAEF;;AAEA;AACA;AACA;AACEnD;AACF;;AAGF;AACA;;AAEA;AACA;AAEU;AAGS;AAAc;AAIvB;AAEsC;AAAS;;AACjCoD;AAAO;;;AAGf;AACF;;;AAOd;AACA;;AAEA;AACA;AACA;;;AAIM;;;AAGF;AAEF;AACEpD;;AAEF;;AAEA;AACF;;AAEA;AACA;AACA;AACO;;AACc;;;;AAInBmD;AAOF;;AAGE;AACA;AACA;AACEnD;AACF;;AAEA;;;;;;;AAOEqD;;AAEF;AACA;;AAEA;AACA;AACF;AAEA;AAIE;AAGIlB;;AAEJ;AACA;AAKA;AAKA;AACF;AACA;AACA;AACA;;AAEA;;AC1NA;;AAQA;AACEmB;AACAvH;AAAsC;AACtCqH;AACAG;AACE;AACA;AACA;AACA;AACA;AACA;AACAC;AACEjI;AACAmH;AACA3G;;AAEF0H;AACElI;AACAmH;AACA3G;AACF;;;AAEgBwH;AAAM;AAC1B;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLG;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;AACA;AAEA;AACE;AACF;AAEA;AACF;;ACtDuC;;AAkBvC;AACO;AAeP;AAeO;;;;;;AAMLQ;AAQF;AACE;AAA8BC;AAAgC;AAE9D;;;;;AAKA;AAEA;AACE;AACE5D;;;AAGE;AACAA;;AAEAA;AACF;AACF;AACE;;AAGF;AACF;AACF;AAEA;AACE;AACA;AAAgCwB;AAASqC;AAASC;AAAO;;;;;;;;;AA2DzD;AACEC;AACAC;AACAC;AACAC;AACAC;AACAC;AACF;AAEAN;;;;AAIE3F;AACF;;AAIA2F;AACF;AAEA;AAKE;AACA;AAKA;AACEO;AACA;AACF;;AAIA;AACErE;AACA;AACF;;AAGF;AAEA;AAME;AACA;AAKA;AACEqE;AACA;AACF;;AAIA;AACErE;AACA;AACF;;AAGF;AAEA;;;;AAQE;AACEsE;AACF;;AAEE;AACE;;AAEE;AACA;AACEC;AACF;AACEA;AACF;AACF;AACF;AACA;AACE;AACA;;AAEE;AACEC;AACF;AACEA;AACF;AACF;AACF;AACF;AACE;AACE;;AAEE;AACA;AACED;;AAEAA;AACF;AACF;AACF;AACA;AACE;AACED;AACF;AACF;AACF;;AAGW;AAAK;AAAK;;AAErB;AAAa;AAAQ;;AACnBG;AACF;;AAGE;AACAC;;AAEJ;AACA;;AAEA;AAEA;AAOE;AACEC;AAAS7D;AAAc8C;AAAcgB;;AACrCC;AACAC;AACAZ;AACAa;AACAC;AACEC;;AAEFlB;AACF;AAEAD;AAEA;AACEoB;AACAC;;AAGFrE;AACF;;AClUA;AACEwC;AACAvH;AACAqH;AACAG;AACE;AACA;AACA6B;AACE7J;AACAoH;AACAD;AACA3G;;AAGF4H;AACEpI;AACAoH;AACAD;AACA3G;;AAEFsJ;AACE9J;AACAoH;AACAD;AACA3G;;AAEFyC;AACEjD;AACAoH;AACAD;AACA3G;AACF;;;AAEgBwH;AAAM;AAC1B;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AAEO;;;AAGLG;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;;;;AAEqBQ;;;AAGrB;AACA;AAEA;AACE;AACA;AACA;;AAEA3D;AACJ;AACA;AACA;AACI;AACF;AAEA;AACE;AACF;AAEA;;AAEE;AAGF;;;;;AAMEqF;;;AAGF;AACF;;AClGO;;;;;;;AAOL9J;AASF;AACE;;AAEA;AAEA;;;;;;;AAQI+J;AACF;AAIF;AACEjB;AACA;AACF;;;;;;AAQU5J;AAAW;AACnB;AACE;AAAmE8K;AAAiBC;AAAkBC;AAAe;;AAC5FhJ;AAAK;;AAEhC;AACF;AAEAuD;;AAMM0F;AACAC;;AAIR;;ACvEA;AACErC;AACAvH;AACAqH;AACAG;AACEhI;AACEA;AACAoH;AACAD;AACA3G;;AAEF6J;AACErK;AACAoH;AACAD;AACA3G;;AAEF8J;AACEtK;AACAoH;AACAD;AACA3G;;AAEF;;;AAGF0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;;;AAIE;AACA;AACA;;AAEAnD;AACJ;AACI;AACF;AAEA;AACE;AACF;AAEA;;AAEE;AAGF;AAEA;;;;;;;AAOEzE;AACF;AACF;;ACzFA;;AACuB;;AACE;AACvBuK;AACF;AAEA;;;;AAAkCC;AAAY;AAE9C;AAWO;;AAEL;AAKE;;AAEA;AACE;AACA;;AAEE;;AAKAC;;AAEJ;AACF;AAEA;AACEC;AACEC;;;AAGAJ;;AAEFK;AACF;AACA;;AAEI;;AAEJ;AACA;AACA;AACEnG;AACF;AACF;AAEA;;;AAKE;AAAa;AAAQ;AAAS;AAC5B;;AAEE;AACA;AACAY;AACF;AACEA;AACF;;;AAGEA;AACF;AACF;AACA;;AAEA;AACA;AACF;;AChGA;AAaA;AACA;AACA;AACA;AACEwF;AACE;AACA;AACA;AACA;AACA;;AAEFC;AACEvJ;AACAwJ;AACAC;AACAC;AACAC;AACAlL;;AAEFmH;AACE;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACAgE;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACAnL;AACA;;AAEFoL;;;;;;;;;AASAC;AACIlL;AAAeH;AAAe;AAC9BG;AAAgBH;AAAe;AAC/BG;AAAeH;AAAe;AAC9BG;AAAaH;AAAe;AAC5BG;AAAiBH;AAAe;AAEpCsL;;AAgCF;AAEA;AACEvD;AACAvH;AACAqH;AACAG;AACE;;AAEFd;AACF;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;AAGnCE;AACAyD;AAAsD;;;AAGtD3D;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACE;AACF;;AAEA;;AACQ4D;AAAsB;AAC9B;AACE;AACA;AACA;;;AAKA;AACF;AAEA;;AAEA;AAEA;AACE;AACF;;AAGF;;ACjLA;AAUO;;;AAGLC;AAKF;AACE;;AAEE;AAGF;AACA;AAA8BpD;AAAkC;AAChE;;;AAGwCqD;;AAIxC;AACE5C;AACA;AACF;AAEAnC;AAEA;AACElC;AACA;AACF;AAEA;AACEkH;AACIC;AAAoB1K;AAA+B;AACnD0K;AAAe1K;AAA0B;AACzC0K;AAAkB1K;AAA6B;AAC/C0K;AAAqB1K;AAAgC;AACrD0K;AAAiB1K;AAA4B;AAC7C0K;AAAe1K;AAA0B;AACzC0K;AAAiB1K;;;AAIvBuD;AACF;;ACnDA;AACEsD;AACAvH;AAEAqH;AACAG;AACE;AACA6D;AACE7L;AACAoH;AACAD;AACA3G;;AAEFkL;AACE1L;AACAoH;AACAD;AACA3G;;;;AAIJ0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;AACE;AACF;;AAEA;AACA;AACEiE;AACAH;;AAEF;AACF;;AC3DO;;;;;AAMHD;AASF;;AAIA;AAA8BpD;AAAkB;AAEhD;AAIA;AAEA;;;AAGE;AACF;;AAIA;AACEyD;AACEC;AAGF;AACA;AACF;AAEA;AACEtH;;AAEuBuH;AAAmBC;AAAaC;AAAa;AAEpEzH;AAGA;AACF;AAEAA;AACAA;AACAA;AAGAA;AAGF;;AC7DA;AACEsD;AACAvH;AACAqH;AACAG;AACE;AACAmE;AACEnM;AACAoH;AACAD;AACA3G;;AAEF4L;AACEpM;AACAoH;AACAD;AACA3G;;AAEF6L;AACErM;AACAoH;AACAD;AACA3G;;AAEFyC;AACEjD;AACAoH;AACAD;AACA3G;;;;AAIJ0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;AACA;;AAGA;AACE;AACA;AACA;;AAEAnD;AACJ;AACA;AACA;AACI;AACF;AAEA;AACE;AACF;AAEA;;AAEE;AAGF;AAEA;;;;;;;;;AAYF;;AC3GA;AAEO;;AAEL;AAA8BmD;AAAW;AACvC;AAEI0E;AACF;;;;;AAMA;AAEJ;AACF;;ACFA;;AAIA;AAAQC;AAAI;AAEZ;;AAEA;AAEO;;AAEL;AACA;AAAqDC;AAAe;AACpE;;AAEA;AACEC;;AAEF;AACA;AACA;AACEC;AACAC;AACAC;AACF;AACA;AACA;AACA;AACE;AAAa;AAAS;;AACpB;;AAEA;AACA;AACA;;AAEA;;AAEEnI;;AAEA;AACF;AACA;;AAGM;AACA;AAEN;AACE;AACe+G;;AAIb;AACA;AACeA;;;;AAI0BqB;AAAuB;;AAEtD1L;AAAoB;;;AAUxB;AACA;AAA8ByJ;AAAc;AAC5CjE;;AAEA;;;AASI;AACE;AACEmG;AAEJ;AACF;AACF;AACA;AACA;AACF;;;;AAIA;AACF;;;;AAIA;AACF;AACF;AACF;AACF;AACF;AACA;AAA4BL;AAAU;AACtCM;AACA;;AAEF;;AC9HA;AACEhF;AACAvH;AACAqH;AACAG;;;AAGAd;AACF;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;AACE;AACF;;AAGF;;AC9CO;AACL;AACE;AACE;AACF;AACF;AACA;AACF;AAEO;;AAKL;AACEvC;AACF;AACA;AACF;;AClBO;AAIL;;AACQmG;AAAO;;AAEb;AACF;;;AAGA;AACA;;AAEF;;ACAA;AACA;AAOA;;AAIE;AACEnG;;AAEE;AACF;AACF;AACA;AACF;AAEO;;AAIL;AACE;;AAEA;AACF;;AAEF;AAEO;;AAKDhD;AAAQD;AAAWD;AAASD;AAAY;AAI5C;;AACU8K;AAAM;;AAEZ;AACF;;AAEEC;AACF;AACF;AACA;AACF;;AC3DO;;AAOL;AAIA;AAKA;AACE;AAKF;AAEA;AACE;AAKF;AAEA;;;;;;AAUF;;AC/BA;AAAQV;AAAI;AAEL;;;AACUU;AAA2B;;;;;;AAOxCxF;AAQiB;AAGnB;AACEhD;AACF;AACEA;AACA;AACE;AACAyI;AACAC;AACAC;;;AAGFC;AAGA5I;AACA;AACEkC;AAGA2G;AACF;AACE3G;AACF;;;AAKAlC;;AAEEA;AACwE8I;;AAE1E;AACE9I;AACuF8I;;AAEzF;;;AAOA;AACF;AAEA;AACE3G;AACF;AACF;AAEA;;;;AAac5G;AAAK;AACb;AACE;;AAEIwI;AACAgF;;AAEJ;AACEC;AACF;AACF;AACA;;;;AAOF;AAGIF;AAAoB;;AAGtB9I;AACF;AACEA;AACF;AACF;AACF;AAEA;;AAEI;;AAEA;AACF;AACA;AACF;;AC/HO;;;;;;;AAOLgD;AASF;AACE;AAIA;AAA8BY;AAAkB;AAChD;AAMA;;AAIMnH;;;;;AAMAuG;;AAIN;AACF;;AChDA;AACEM;AACAvH;AACAqH;AACAG;AACE;AACA;;;AAGFd;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;;;AAKE;AACA;AACA;;AAEAnD;AACJ;AACA;AACI;AACF;AAEA;AACA;AAEA;AAGA;AACE;AACF;AAEA;AACEsD;;;;;;;AAOF;AACF;;AC/EO;AAML2F;AACAA;AACAA;AACAA;AACF;;ACMA;;AAUA;AAAQC;AAAwB;AAEzB;AAIL;AAEIC;;AAMJC;AACAC;AAEA;AAA8BzF;AAA6B;AAE3D;;;AAGE;AACA;;AAEA;;AAEA1B;AACF;AACEA;AACA;AACF;;;;AAOE;;AAIF;AACE;AACEiH;AAEAzD;AACEjJ;AACA8L;AACAxM;;AAEJ;AACA;;AAEA;AACF;AACE;;AAEE2G;AACF;AACA;AACE;AACA;AACE4G;AACF;AACF;AACF;AAEA;;;;AAIA;AACEpH;AACF;AACF;;AC7FA;AACEoB;AACAvH;AACAqH;AACAG;AACE;AACA6F;AACE7N;AACAQ;;AAEFsN;AACE9N;AACAQ;AACF;;AAEF0G;AACF;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;AACA;AAEA;AACE;AACF;AAEA;AACE;AAGF;AAEA;AACF;;ACtEO;AACL8F;AACAA;AACAA;AACAA;AACF;;ACHO;;AAEHM;AACA;AACF;AACE;AACF;AACF;;ACLA;AACEjG;AACAvH;AACAqH;AACAG;;;AAGAd;AACF;AACA;;AAEA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;AACE;AACF;AAEAqG;AACF;;ACpCO;AAOL;AACA;AACA;;AAEA;AACExJ;AACAA;AACAA;AACA;;AAEF;AACEA;AACAA;AACAA;AACA;;AAEF;AAEA;;;AAOE;AACA;AACA;;AAEA;;;AAIA;;AAEA;;;AAIA;;AAEA;AACEA;AACAA;;AAEF;;AAGEkC;AACA;;AAEElC;AACAA;;AAEF;AACAmC;AACF;AAEAnC;;AAIIA;AACA;AACF;;AAGF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAMA;AACEA;AACAA;;AAEF;AACAmC;AACF;AACF;;AC9GA;AACEmB;AACAvH;AAEAqH;AACAG;AACE;AACAkG;AACElO;AACAQ;;AAEF2N;AACEnO;AACAQ;;AAEF4N;AACEpO;AACAmH;AACA3G;;AAGF6N;AACErO;AACAmH;AACA3G;;AAGF8N;AACEtO;AACAQ;;AAEF+N;AACEvO;AACAmH;AACA3G;;AAEFgO;AACExO;AACAQ;AACF;;AAEF0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;;AAIA;AACEnD;;;;;AAKF;AAEA;;AAEA;;AAEA;AACE;AACA;AACA;;AAEAA;AAEJ;AACA;AAEI;AACF;AAEA;AACA;AACEyJ;AACF;;AAEA;;AAGA;AACEG;AACF;AACA;AACEA;AACF;AAEA;;AAEE5J;AACAA;AACAA;;AAEF;;AAGA;;AAKA;AAEA;AACE;AACF;;AAGF;;AC/JO;AAOL;AACA;AACA;;AAEA;AACEA;AACAA;AACAA;AACA;;AAEF;AACEA;AACAA;AACAA;AACA;;AAEF;AAEA;;;AAKE;AACA;AACA;;AAEA;;AAEA;;AAEA;AACEA;AACAA;;AAEF;;AAGEkC;AACA;;AAEElC;AACAA;;AAEF;AACAmC;AACF;;;AAIE6H;AACA;AACF;AAEA;AACE9H;AAGAC;AACF;;AAEA;AACA;AACA;;;AAGEnC;AACAA;;AAEF;;AAMEgK;AACAhK;AACAmC;AACF;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACAD;AACA8H;;AAEF;;;AAMA;AACEhK;AACAA;;AAEF;AACAmC;AACF;AACF;;AC9GA;AACEmB;AACAvH;AAEAqH;AACAG;AACE;AACAkG;AACElO;AACAmH;AACA3G;;AAEF2N;AACEnO;AACAQ;;AAEF6N;AACErO;AACAmH;AACA3G;;AAGF8N;AACEtO;AACAQ;;AAEFkO;AACE1O;AACAmH;AACA3G;;AAEFgO;AACExO;AACAQ;AACF;;AAEF0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;AAErC;;;;;AAKEA;AACF;;AAIA;AACEnD;;;;;AAKF;AAEA;;AAEA;;AAEA;AACE;AACA;AACA;;AAEAA;AAEJ;AACA;AAEI;AACF;;AAGA;AACEyJ;AACF;;AAGA;AACEG;AACF;AACA;AACEA;AACF;AAEA;;AAEE5J;AACAA;AACAA;;AAEF;;AAGA;;AAKA;AAEA;AACE;AACF;;AAGF;;ACpJA;AACEsD;AACAvH;AACAqH;AACAG;AACE;AACAmG;AACEnO;AACAQ;;AAEFgO;AACExO;AACAmH;AACA3G;AACF;AACA;;AAEF0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;;AAGA;AACA;AACEnD;;;;AAIAA;;AAEF;;AAEA;AACEkK;AACF;;;AAKElK;AAGA;AACEkK;AACF;AACAA;AAEA;AACE;AACF;AAEA;AAAkD/G;AAAW;AAC7D;AACF;;AAGEnD;AACA;AACE;AACAkK;AACF;AAEA;AACE;AACF;AAEA;AAAmD/G;AAAW;AAC9D;AACF;;AAEA;AACAgH;AAEF;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AAEMrD;;AAEAsD;AACF;AAEJ;;ACxHA;AACA;AACA;AACA;AACA;AACA;AACE9G;AACAvH;AAEAqH;AACAG;AACE;AACAkG;AACElO;AACAQ;;AAEF2N;AACEnO;AACAQ;;AAEF4N;AACEpO;AACAmH;AACA3G;;AAGF6N;AACErO;AACAmH;AACA3G;;AAGF8N;AACEtO;AACAQ;;AAEF+N;AACEvO;AACAmH;AACA3G;;AAEFgO;AACExO;AACAQ;AACF;;AAEF0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;;AAIA;AACEnD;;;;;AAKF;AAEA;;AAEA;;AAEA;AACE;AACA;AACA;;AAEAA;AAEJ;AACA;AAEI;AACF;AAEA;AACA;AACEyJ;AACF;;AAEA;;AAGA;AACEG;AACF;AACA;AACEA;AACF;AAEA;;AAEE5J;AACAA;AACAA;;AAEF;;AAGA;;AAKA;AAEA;AACE;AACF;;AAGF;;AClKA;AACEsD;AACAvH;AACAqH;AACAG;;;AA+BK;;;AAGLG;AACF;AAEA;AAGIP;AAAmC;AAErC;AAEIkH;AACAC;AACAC;AACAC;AACF;;AAGEC;AACEC;;AAEEtH;;AAEF;;;;;AAKF3G;AACF;AAEJ;;AC5EA;;AAAakO;AAAW;AAEjB;AACL;;AAEA;AACF;;ACFA;AAAQ7C;AAAI;AAEZ;AACExE;;AAEAF;;AAEAX;AACF;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;AAGnCE;;;;AAIAF;AACF;AAEA;AACE;AACF;;AAGF;;ACzCA;;AAAawH;AAAW;AAEjB;AACL;;AAEA;AACF;;ACFA;AAAQC;AAAI;AAEZ;AACEtH;;AAEAF;;AAEAX;AACF;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;AAGnCE;;;;AAIAF;AACF;AAEA;AACE;AACF;;AAGF;;ACtCA;AACEG;AACAvH;AACAqH;AACAG;;;AAGAd;AACF;AACA;;AAEA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;AACE;AACF;AAEA;AACF;;ACrCA;;;;;;AAAyC0H;AAAa;AAEtD;AACE;AACF;AAEA;AACE;AACF;AAEO;;ACKP;;;;;;;;;AASEA;AACF;AAEO;AAIP;AACE3H;;;;;;AAMA;AACF;AAEA;AACE;AACA;AAA+B4H;;AACjC;AAEA;AAIE;;;AAIM;;AAC6CpB;AAAI;;AAGvD;AACF;;AAEA;AACA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF;AAMA;;;;AAMQ;;AAEF;;AAEJ;AAEA;AAEA;;;AAMI;;AAEE;AACF;;AAEE;AACA;;;;AAIA;AACA;AACA;AACA;AACA;AACF;AACA;AACF;;;;;AAKA;;AAEJ;AA2CO;AACLA;AACAqB;AAC4B;;AAGsBrB;AAAI;;AAEtD;;AAGmCA;AAAI;AACvC;;AAKqC3B;;AAErC;AACA;AACA;AACA;AAIA;AACA;AACA;AACE;AACA;;;;AAIIiD;;AAEF;AACF;AACF;AACA;AAMEA;AACF;;AAEEA;;AAEF;AACA;AAEA;;AAGEC;AACF;AACA;AACED;AACF;AACA;AACEE;AACAC;;AAEF;AACA;AACA;AACA;AACE;;;AAGA;AACA;AACA;AACE;;;AAGA;AACF;AACA;AACA;;AAIE;;;AAMA;;;;;AAKE;AACF;AACF;AACA;;AAIAC;AAIF;AACEC;AACAC;AACF;;;;;;;;;;AAUEC;;AAEAC;AACAC;;AAEJ;;AC1SA;;;AAAkBC;AAAW;AAE7B;AAMO;;;AAIWC;AAAK;AACnBzI;;;AAGF;;;AAGI0I;AAGF;AACF;AACA;AACEA;AAGA;AACF;AACA;;AAIE;AACF;AACA;;;AAGE;AACF;;;AAGE;AACF;AACA;AACEA;AACA;AACF;AACA;;AAIE;AACF;AACA;AAIEA;AAGF;AACA;AACF;;ACnEO;;;;;AAKHC;AACF;AACA;AAGqB3I;;;AAIGA;;;AAICA;;;AAKfA;;AAAyC;AAGvC;;AACd;;ACfA;;;;;;;;AAQE2H;AACF;AAEA;;;AAEWtP;AAAkBuQ;;AAC7B;;AAEA;AACA;AACA;;;AAEWvQ;AAAWuQ;;AACtB;;AAEA;AACA;AACA;;;AAEWvQ;AAAYuQ;;AACvB;AAEA;;;AAEWvQ;AAAWuQ;;AACtB;;AAEA;AACA;AACA;;;AAEWvQ;AAAkBuQ;;AAC7B;;AAEA;AACA;AACA;;;AAEWvQ;AAAoBuQ;;AAC/B;AAEO;;ACnDP;AAAQC;AAAK;AAEb;AAEO;AAKL;;;AAMI;;AAEA;;AAEIC;;AAEF;AACE;AACF;AACF;AACF;AACF;AACEA;AACF;AACA;AAKF;AAEA;;AACUjF;AAAO;;AAEb;AACF;AACA;;;AAGA;AACA;AACA;;AAMA;AACA;;AAEF;;ACzDA;;;;;;;AAAmD8D;AAAa;AAEhE;AACE;AACA;AACA;AACF;AAEA;AACE;AACA;AACA;AACA;;AAIA;AACF;AAEA;AACE;AACA;AACE;AACA;AACA;AACA;AACA;;AAIJ;AAEA;AACE;AACA;AACA;AACF;AAEA;AACE;AACA;AACE;AACA;AACA;AACA;AACA;;AAIJ;AAEO;;ACjDP;;;;;;AAAyCA;AAAa;AAEtD;;AAEI;AACF;AACA;;AAEEoB;;AAEF;AACE;AACF;AACA;AACA;;;AAAwBC;;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEEC;AACF;AACF;AACA;AACF;AAEA;;AAEI;AACF;AACA;AACA;AACA;;AAEA;AACF;AAEA;;;AAGItC;AAA8DH;;;;AAGlE;AAEA;;AAEI;AACA;AACA;AAA6DA;;;AAE/D;AACF;AAEA;AACE;AACF;AAEA;AAKE;AACA;;AAEE;AACE;AACF;AACF;;;AAGEG;AAIMH;;;;AAKV;AAEA;;;AAGIG;AAEIH;;;;AAKR;AAEA;;AAKI;AACE;AACA;AACA;AAEIA;AACF;AACa;;AAGnB;AACF;AAEA;;AAKI;AACA;AACA;AACA;;AAEmDA;AAAI;;AAGzD;AACF;AAEO;AACL;AACAxG;;;;;;AAOA;AACF;;AC1IA;;;;;;;;AAQE2H;AACF;AAEA;AAEA;AASA;AAIE;AAIF;AAEA;;AAKA;AAEA;AAIE;AACF;AAEA;AAKE;AACA;AACA;AACE;;AAEE;;AAEI;;AAEEiB;AACF;AACF;AACF;AACE;;AAGQ;;AAEEA;AACF;AACF;AACE;AAAmB;AAC7B;;AAEA;;;AAGA;AACF;;AAC2B;AAAe;AAC1C;AACA;AACF;AACA;AAME;AACF;AACA;AACA;AACA;AACA;;;;;AAKE;AACEM;;AAEF;AACF;AACEA;AACAC;AACF;;AAEE;AACED;AACAC;AACF;AACF;AACA;;AAEA;AACA;AACED;AACAC;AACF;AACA;;;AAGEA;AACF;AACAC;;AAIF;AAEA;AAIEC;AACF;AAEA;AAIEA;AACF;AAEA;AAIEA;AACF;AAEO;;ACjKP;;AAAaC;AAAY;AAUlB;AAKL;;;AAGA;;AAEEC;;;AAGF;AAA2BvJ;;;AAC3B;AACA;;;AAGA;AACA;AACEwJ;AACAvG;AACA;AACAF;;AAEE;AACF;AACF;AACA;;AAEE0G;;AAEA;AACAA;AACEA;AACJ;AACA;AACF;;AClDA;AAAQ7E;AAAI;AAEZ;AACA;AAMO;;;AAIW5F;AAAQ;AACtBgB;;;;;;AAMEhB;AACF;;AAEA;AACE0J;AAGF;;AAEA1J;AAGA0J;AACF;AACF;;ACaA;;;AAAmBf;AAAa;AAEhC;AAEA;AAEO;;AAML;;AAEEc;AACF;;AAEE;AACF;AACA;AAA8B/H;AAA6B;;;;;;AAOzD1B;AACF;;AAIA;AACA;;AAEA;;;AAKE;;AAEE0J;AAGF;AACF;AACEA;AACF;AAEA;AACE;AACA;;;AACqD1J;AAAQ;AAC/D;AACF;AAEA;;AAMA;AAEA;;;;;;;AAWI0K;AACF;;;;;;AAMEC;AACEC;AACAC;AACAC;AACAC;AACAC;AACF;AACF;AAA2BhK;;;;AACrBqI;AAAyB;;AAE7BlD;AAAmDN;AAAe;AACpE;;AACQzG;AAAiB;AACzB;AACA;;;AAGA;AACA;;AAOEsK;AAGF;AACA;AAEsDuB;AAAY;AAClE;AACA;AACA;AACA;AACA;AAKA;;AAGA;AACEC;AACF;;AAKA;AACA;;AAEA;AACA;AAEA;AACA;AAAuD;AAAQ;AAG/D;AACA;AAAyC;AAAQ;;AACvC3Q;AAAsBsD;AAAsBrD;AAAQ;AAC5D;AACA;AACA;AACA;AAAa;;AACX;AAGA;AACE2Q;AACF;AACA;AAGA;;AAEE;AACA;;AAOEC;AACAC;AACAV;AACA;AACEA;AACF;AACF;AACAQ;AACF;AACF;AACA;AACE;AACA;;AAAyD9R;AAAK;AAC5D;;;AAME;AACA;AACA;;AAEA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACAiS;AACF;AACE;AAGA;;;AASI;AACEA;AACF;AACF;AACF;AACEA;AACF;AACF;;AAEE1B;AACA;AACAe;AACF;AACF;AACF;AACF;AACF;AACA;AACE;AACEY;AACA/D;AACA7N;AACF;AACA;;AAEE;;;;AAOIqG;AACF;AAEF;AAeE;AACE2K;AACF;AACF;AACF;AACF;AACA;;AAEE;;AAAwBtR;;AACtBmS;AAIF;AACA;AACF;AACA;AACF;;ACtUA;AACEpK;AACAvH;AACAqH;AACAG;AACE;AACAoK;AACEpS;AACAmH;AACA3G;;AAEF4P;AACEpQ;AACAmH;AACA3G;AACF;;AAEF0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;AAEA;AACE;AACF;;AAOF;;ACxDO;AAGL;;AAEE;AAGF;AACA;AACF;AAEA;AAIE;AAA8BS;AAAkC;AAChE;AACA;AAKA;AACES;AACA;AACF;;;AAKA;AAEA;AACE;AAAa;AACXrE;;;;AAMI;AAKJ;AACF;AACA;AAAiB;AACf;AACA;AACA;AACA;;;;AAIA;AACE4N;AACAC;AACAC;AACF;AACA9N;;AAIAA;;AAMA;;AAIA;;AAIA;AACF;AACA;AAAS;;AAIP;AACA;AACEA;AAGF;AACF;AACF;AACF;;AChGA;AACEsD;AACAvH;AACAqH;AACAG;AACE;;;AAGFd;AACF;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;;;;AAKE;AACA;AACA;;;AAGJ;AACA;AACA;AACI;AACF;AAEA;AACE;AACF;;AAGF;;ACxDA;AAAQqJ;AAAY;AAEb;AACL;AACEE;AACAvG;AACF;AACA;;;AAGI;AACF;AACA;;AAEA;AACEhE;AACF;AACF;AACA;AACF;;ACnBA;AAAQ2F;AAAI;AAEZ;AACExE;;AAEAF;;AAEAX;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;AAGnCE;;;;AAIAF;AACF;AAEA;AACE;AACF;;AAGF;;AC3CA;AAAQqJ;AAAY;AAEb;;AAEHE;AACAvG;AACF;AACA;;;AAGI;AACF;AACA;;AAEA;AACEhE;AACF;AACF;AACA;AACF;;ACnBA;AAAQyI;AAAI;AAEZ;AACEtH;;AAEAF;;AAEAX;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;AAGnCE;;;;AAIAF;AACF;AAEA;AACE;AACF;;AAGF;;ACpCO;;AAKHP;AAIF;AAEA;AACA;AAGI;;AAOF;AAEE;AACER;AACF;AACF;AAEF;AAOA2L;AAKA;;AAEE;AACF;AACE;AACA;AACEnK;AACF;AAEA;;AAOA;AACES;AACA;AACF;;AAEA;AACF;AACF;;ACxEO;;;AAQC;AACA;;AAEE2J;;;;AAMF;AACA;AASF;AACE;AAAsD5L;AAAM;AAC9D;AACF;AAGF;AACF;;ACxBA;AACA;AAEO;AAKL;AACA;;AAEA;AAEA;;;AAGI;AACAxB;;;AAUE;AACF;AACF;AACF;AAEA;AACE;AACF;;AAEA;;AAEA;AACE;AACEsB;AACF;AACEA;AACF;;AAEA;AAIA;AACAA;AACF;AACEA;AACF;;AAGF;;AChEO;AAQL;AACElC;AACF;AACE;AACAA;AAE2C8I;AAAoB;;;AAQ/D;AACF;AAEA;AACE3G;AACF;AACF;;ACjCO;;;;;AAOHa;AAOF;;AAGA;AACEiL;AAQF;AACF;;ACjBA;AACE3K;AACAvH;AACAqH;AACAG;AACE;AACA;AACA;AACAX;AACErH;AACAmH;AACA3G;;AAEFmS;AACE3S;AACAoH;AACAD;AACA3G;AACF;;AAEF0G;AACF;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;;AAEA;AACA;;;;;;;;;AAUA;AACA;AACE;AACF;AAEA;;;AAEkEP;AAAO;;;AAKvE;AACE;;AAEEG;;;;AAIAC;AACF;;AAEAhD;AACA;AACF;AACE;AACAA;AACqE8I;;AAEvE;AACF;AACF;;AC5GA;AACExF;AACAvH;AACAqH;AACAG;AACE;AACA;;;AAGFd;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;;;AAIA;AACA;AACE;AACA;AACA;;AAEAnD;AACJ;AACA;AACI;AACF;AAEA;AACE;AACF;;;AAIEsD;;;;AAIF;AACF;;ACnEA;AAEO;;AAEL;AAA8BH;AAAW;AACvC;AAEIgL;AACAD;AACF;;;;;AAMA;AAEJ;AACF;;ACnBO;;;;;;;;;AASLE;AAWF;;AAEE;AAA8BxK;AAAkB;AAEhD;;;;;AAMInH;;;;AAIA2R;;;AAMFlM;AACF;AACEmC;AACF;AACF;;ACtCA;AACEf;AACAvH;AACAqH;AACAG;AACE;AACA;AACA8K;AACE9S;AACAoH;AACAD;AACA3G;;AAEFuS;AACE/S;AACAoH;AACAD;AACA3G;;AAEFwS;AACEhT;AACAoH;AACAD;AACA3G;;AAEFyS;AACEjT;AACAoH;AACAD;AACA3G;;AAEFqS;AACE7S;AACAoH;AACAD;AACA3G;AACF;;AAEF0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;;;AAIE;AACA;AACA;;AAEAnD;AACJ;AACA;AACI;AACF;AAEA;AACE;AACF;AAEA;;AAEE;AAGF;AAEA;;;;;;;;;AASEyO;AACF;AACF;;AC9GO;;AAML;AAA8B7K;AAAkB;AAEhD;AACA;;AAME1B;AACF;AACEmC;AACF;AACF;;ACbA;AACEf;AACAvH;AACAqH;AACAG;;;AAGAd;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;AAEA;AACE;AACA;AACA;;AAEAnD;AACJ;AACA;AACA;AACI;AACF;AAEA;AACE;AACF;AAEA;;AAEE;AAGF;AAEA;AACF;;AC1EA;AASO;;;;;;;;AAQL0O;AAUF;;AAEE;AAA8B9K;AAAkB;AAEhD;;;;;;;;AASIiC;;AAKJ;AACExB;AACA;AACF;AAEA;AACE6C;AACIC;AAAa1K;AAA2B;AACxC0K;AAAe1K;AAA6B;AAC5C0K;AAAqB1K;AAAmC;AACxD0K;AAAyB1K;AAAuC;AAChE0K;AAAmB1K;;;AAIzByF;AACF;;AClDA;AACEoB;AACAvH;AACAqH;AACAG;AACE;AACAmL;AACEnT;AACAoH;AACAD;AACA3G;;AAEF4S;AACEpT;AACAmH;AACA3G;;AAEF6J;AACErK;AACAoH;AACAD;AACA3G;;AAEF8J;AACEtK;AACAoH;AACAD;AACA3G;;;;AAIJ0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;;;AAKE;AACA;AACA;;AAEAnD;AACJ;AACA;AACI;AACF;AAEA;AACE;AACF;AAEA;;AAEE;AAGF;AAEA;;;;;;AAME2O;;;AAGF;AACF;;ACrGO;;;;;;;;;AASLP;AAWF;;AAEE;AAA8BxK;AAAkB;AAEhD;AACA;;;;AAKInH;;;;AAIA2R;;;AAMFlM;AACF;AACEmC;AACF;AACF;;ACtCA;AACEf;AACAvH;AACAqH;AACAG;AACE;AACA;AACA8K;AACE9S;AACAoH;AACAD;AACA3G;;AAEFuS;AACE/S;AACAoH;AACAD;AACA3G;;AAEFwS;AACEhT;AACAoH;AACAD;AACA3G;;AAEFyS;AACEjT;AACAoH;AACAD;AACA3G;;AAEFqS;AACE7S;AACAoH;AACAD;AACA3G;AACF;;AAEF0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;;;AAIE;AACA;AACA;;AAEAnD;AACJ;AACA;AACA;AACI;AACF;AAEA;AACE;AACF;AAEA;;AAEE;AAGF;AAEA;;;;;;;;;;AAUA;AACF;;ACpHA;AASO;;AAML;AAA8B4D;AAAkB;AAEhD;AACA;AAKA;AACES;AACA;AACF;AAEA;AACE6C;AACIC;AAAa1K;AAA2B;AACxC0K;AAAe1K;AAA6B;AAC5C0K;AAAqB1K;AAAmC;AACxD0K;AAAyB1K;AAAuC;AAChE0K;AAAmB1K;AAAiC;AACpD0K;AAAmB1K;AAAiC;AACpD0K;AAAqB1K;;;AAI3ByF;AACF;;AC9BA;AACEoB;AACAvH;AACAqH;AACAG;AACE;;;AAGFd;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;;;AAIE;AACA;AACA;;AAEAnD;AACJ;AACA;AACI;AACF;AAEA;AACE;AACF;AAEA;;AAEE;AAGF;AAEA;AACF;;AClEA;AAEO;;AAEL;AAA8BmD;AAAW;AACvC;AAEIgL;AACAD;AACAU;AACAC;AACAC;AACF;;;;;AAMA;AAEJ;AACF;;ACnBO;;;AAGLC;;AAEAC;;;;;;AAMAC;;AAEAC;AAeF;;AAEE;AAA8BtL;AAAkB;AAEhD;;AAKMyB;AACAxK;AACAC;AACAqU;AACAC;AACAF;AACF;AAOJ;AACE7K;AACA;AACF;AAEAnC;AAEA;AACAlC;AAEA;;;AAGA;;AAMA;;AAEA;;AAEF;;ACpEA;AACEsD;AACAvH;AACAqH;AACAG;AACE8B;AACE9J;AACAoH;AACAD;AACA3G;;AAEFlB;AACEU;AACAoH;AACAD;AACA3G;;AAEFsT;AACE9T;AACAoH;AACAD;AACA3G;;AAEFgT;AACExT;AACAoH;AACAD;AACA3G;;AAEF2N;AACEnO;AACAQ;;AAEF6G;AACErH;AACAQ;;AAGFkT;AACE1T;AACAoH;AACA5G;;AAEFiT;AACEzT;AACAoH;AACAD;AACA3G;;AAEFyS;AACEjT;AACAoH;AACAD;AACA3G;;AAEFuT;AACE/T;AACAoH;AACAD;AACA3G;;AAEFmT;AACE3T;AACAoH;AACAD;AACA3G;AAEF;;AAEF0G;AACF;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;;AAIA;;AAKA;AACA;AACE;AACF;AAEA;AACA;AAGI;AAMA;;AAEF;AAEE;AAA+Df;AAAM;AACvE;;;AAQMvH;AAAoBwK;;AAE5B;AACE;AACA;AACA;;AAEArF;AACJ;AACA;AACA;AACA;AAWI;AACF;AAEA;;AAEE;AAGF;AAEA;;;AAGEqO;AACAkB;;;;;;;;;AASAN;AACF;AACF;;ACrMO;;AAML;AAA8BrL;AAAkB;AAEhD;AACA;;AAME1B;AACF;AACEmC;AACF;AACF;;ACbA;AACEf;AACAvH;AACAqH;AACAG;AACE;;;AAGFd;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;AAEA;AACE;AACA;AACA;;AAEAnD;AAEJ;AACA;AAEI;AACF;AAEA;AACE;AACF;AAEA;;AAEE;AAGF;AAEA;AACF;;AC5EA;AASO;;AAiBL;AAA8B4D;AAAkB;AAEhD;AACA;AAKA;AACES;AACA;AACF;AAEA;AACE6C;AACIC;AAAa1K;AAA2B;AACxC0K;AAAqB1K;AAAiC;AACtD0K;AAAiB1K;AAA+B;AAChD0K;AAAqB1K;;;;;;;AAQvBhC;AAEM8K;AACAC;AACAC;;;;AAKV;AAEAvD;;AAEF;;ACnDA;AACEoB;AACAvH;AACAqH;AACAG;AACE;AACA;AACAmL;AACEnT;AACAoH;AACAD;AACA3G;;AAGF4S;AACEpT;AACAoH;AACAD;AACA3G;;AAEF6J;AACErK;AACAoH;AACAD;AACA3G;;AAEF8J;AACEtK;AACAoH;AACAD;AACA3G;;AAEFyT;AACEjU;AACAoH;AACAD;AACA3G;;AAEF0T;AACElU;AACAoH;AACAD;AACA3G;AACF;;AAEF0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;;AAGE;AACA;AACA;;AAEAnD;AACJ;AACI;AACF;AAEA;AACE;AACF;AAEA;;AAEE;AAGF;;AAIE;AACA;AACEgH;AACA0I;;AAEAhB;AACAC;AACArJ;AACAO;AACA8J;AACAC;;AAcN;;ACrIO;;AAML;AAA8BhM;AAAkB;AAEhD;AACA;AAKA;AACES;AACA;AACF;AAEAnC;AACAlC;AACF;;ACZA;AACEsD;AACAvH;AACAqH;AACAG;AACE;;;AAGFd;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;AAEA;AACE;AACA;AACA;;AAEAnD;AAEJ;AACA;AAEI;AACF;AAEA;AACE;AACF;AAEA;;AAEE;AAGF;AAEA;AACF;;ACxEO;AAML;AAA8B4D;AAA0B;AAExD;;;;AAYA;AACES;AACF;AAEA;AACF;;AClBA;AACEf;AACAvH;AACAqH;AACAG;AACE;;;AAGFd;AACF;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;AAEA;AACE;AACA;AACA;;AAEAnD;AAEJ;AACA;AAEI;AACF;AAEA;AACE;AACF;AAEA;;AAEE;AAGF;;AAGF;;ACxEA;AAEO;;AAEL;AAA8BmD;AAAW;AACvC;AAEIgL;AACA0B;AACAjB;AACAC;AACAiB;AACF;;;;;AAMA;AAEJ;AACF;;ACRO;;;;;;AAMLlK;AAQF;AACE;AACEhC;AACF;;AAGE0B;;;AAGAgB;AACF;;AAKA;;AAMA;AACEtG;AACA;AACF;AAEA;AAEA;AACE+P;AACAC;AACAC;AACAC;AACAC;AACApM;AACAkB;AACAmL;AACAC;AACE9U;AACAyU;;AAEFM;AAAkB;AAClBC;AACF;;AAEA;;AAGAzM;AAEA;;AAGExB;AAQAnE;AACF;;AAIA2F;AACF;AAEA;AACE;;;AAGE;AAEA;AACA;AAEA;AACA;AAKA;AAQF;AACF;AAEA;;AAEA;AAEA;;AAEA;AAEA;;AAEA;;ACpIA;AACER;AACAvH;AACAqH;AACAG;AACE;AACA;AACAqC;AACErK;AACAoH;AACAD;AACA3G;;AAEF8J;AACEtK;AACAoH;AACAD;AACA3G;;AAEF4S;AACEpT;AACAoH;AACAD;AACA3G;;AAEFuK;AACE/K;AACAoH;AACAD;AACA3G;AACF;;AAEF0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;;;;;AAMnCA;AACF;AAEA;AACE;AACF;AAEA;;AAEE;AAGF;AAEA;;;;;;;AAOA;AACF;;ACzFO;;AAKD;AACE;AACF;AACA;AACA;;AAEN;AACA;AACA;AACI;AAEJ;;AChBO;;;;AASHnD;AAGA;AACF;AACA;AACF;;ACTO;AACL;;;AACoBwQ;AAAU;;;AAM5BC;;AAEJ;;AAEA;AACE;AACF;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AAEE;;;AAGA;AACA;AACF;AAEA;AACEC;AACE;AACE;;;AACoBF;AAAU;;AAE5B;;AAEA;AACA;;AAEA;;AAEA;AACF;;;AAGAG;AAIF;;AAEA;AACF;AACF;;AC/DO;AACL;AACE;AACE3Q;AACA;AACF;;AAOA;;AAGE;AACEA;AACA;AACF;AACE;AACA;AACAA;AAGF;AACF;AACF;AACF;;ACdA;AACEsD;AACAvH;AACAqH;AACAG;AACE;AACAqN;AACErV;AACAmH;AACA3G;;AAEF8U;AACEtV;AACAmH;AACA3G;AACF;;AAEF0G;AACF;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AAEO;;;AAGLiB;AACF;AAEA;AAGIP;AAAmC;AAErC;AACA;AACE2N;AACA;AACF;;;;;AAME3N;AACF;;AAEQyN;;;AAEN;AACA;AACA;;AAEA5Q;AACJ;AACI;AACF;AAEA;AACE;AACF;;AAEA;;;AACoBwQ;AAAU;AAC9B;;;AAGE;;;AAGA;AACF;AACE;;AAEA;AACA;;AAEA;AACF;;AAEExQ;AAGF;AACF;;ACrEA;;AAAgB+Q;AAAgB;;AAEhC;AACA;AACE;AACEtU;AACAC;;AAEF;;AAGE;AAEIsU;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACA;AACA;AACAC;AACAC;AACAC;AACA;AACAC;AACAC;AACAC;AACA;AACA;AACAC;AACF;AAEExH;AACEyH;AACEnW;;AAEF;;;AAGFU;AACA2N;AAAc9N;AAAoC;AACpD;;;AAIF;AACA;;;AAGE6V;;AAEF;AACEA;;;AAGF;AACEA;AACAC;AACAC;AACF;AACEF;AACF;;AAIA;AACEnS;AACF;;AAEF;AACF","debugId":"9211012b-2bab-40e6-b115-6389952c7273"}
|