Skip to content

Custom Package Transformations ​

ts-pkgx allows you to implement custom transformations for package data to suit your specific needs.

Basic Transformation ​

You can implement custom transformation logic when processing packages:

typescript
import type { PkgxPackage } from 'ts-pkgx'
import { fetchPantryPackage } from 'ts-pkgx'

async function fetchAndTransform(packageName: string): Promise<PkgxPackage> {
  const { packageInfo } = await fetchPantryPackage(packageName)

  // Add custom metadata
  const enhancedPackage: PkgxPackage = {
    ...packageInfo,
    description: `${packageInfo.description} [Enhanced]`,
    // Add custom fields or modify existing ones
    customCategory: determineCategory(packageInfo),
  }

  return enhancedPackage
}

function determineCategory(pkg: PkgxPackage): string {
  if (pkg.domain.includes('lang'))
    return 'programming-language'
  if (pkg.programs.some(p => p.includes('server')))
    return 'server'
  return 'utility'
}

This approach allows you to extend the basic package information with your own custom fields or modify existing ones.

Transform Packages in Batches ​

You can apply transformations to multiple packages at once:

typescript
import { fetchPantryPackage } from 'ts-pkgx'
import { fetchPackageListFromGitHub } from 'ts-pkgx/utils'

async function transformPackageBatch(category: string): Promise<PkgxPackage[]> {
  // Get all packages from GitHub
  const allPackages = await fetchPackageListFromGitHub()

  // Filter packages by category (example: languages)
  const filteredPackages = allPackages.filter(pkg =>
    pkg.includes('lang') || ['python', 'node', 'ruby', 'go'].some(lang => pkg.includes(lang))
  )

  // Fetch and transform each package
  const results = await Promise.all(
    filteredPackages.map(async (pkg) => {
      try {
        const { packageInfo } = await fetchPantryPackage(pkg)
        return {
          ...packageInfo,
          category,
          importance: calculateImportance(packageInfo),
        }
      }
      catch (error) {
        console.error(`Error processing ${pkg}:`, error)
        return null
      }
    })
  )

  // Filter out nulls from errors
  return results.filter(Boolean) as PkgxPackage[]
}

function calculateImportance(pkg: PkgxPackage): number {
  let score = 0
  // More programs = higher score
  score += pkg.programs.length * 2
  // More dependencies = higher complexity = higher score
  score += pkg.dependencies.length
  // Has GitHub URL = higher score
  score += pkg.githubUrl ? 5 : 0
  return score
}

// Usage
const languagePackages = await transformPackageBatch('programming-languages')

Custom Package Analysis ​

You can create functions to analyze package data:

typescript
function analyzePackageDependencies(pkg: PkgxPackage): {
  directDeps: string[]
  hasCyclicDeps: boolean
  depthLevel: number
} {
  // Implementation of dependency analysis
  const directDeps = pkg.dependencies

  // Check for circular dependencies (simplified example)
  const hasCyclicDeps = pkg.dependencies.some((dep) => {
    const depPkg = getPackage(dep)
    return depPkg && depPkg.dependencies.includes(pkg.domain)
  })

  // Calculate dependency depth (simplified)
  const depthLevel = Math.min(3, pkg.dependencies.length > 0 ? 1 : 0)

  return { directDeps, hasCyclicDeps, depthLevel }
}

Extending Package Properties ​

You can extend the basic PkgxPackage interface with additional properties:

typescript
// Extended package type with custom properties
interface ExtendedPkgxPackage extends PkgxPackage {
  category: string
  popularity: number
  latestVersion: string
  installOptions: {
    global: string
    local: string
  }
}

function extendPackage(pkg: PkgxPackage): ExtendedPkgxPackage {
  return {
    ...pkg,
    category: determineCategory(pkg),
    popularity: calculatePopularity(pkg),
    latestVersion: pkg.versions[0] || 'unknown',
    installOptions: {
      global: `pkgx ${pkg.domain} --global`,
      local: `pkgx ${pkg.domain}`
    }
  }
}

Save Transformed Packages ​

You can save your transformed packages in custom formats:

typescript
import fs from 'node:fs'
import path from 'node:path'

function saveTransformedPackage(
  pkg: ExtendedPkgxPackage,
  outputDir: string
): void {
  const fileName = `${pkg.domain.replace(/\./g, '_')}.json`
  const filePath = path.join(outputDir, fileName)

  fs.writeFileSync(
    filePath,
    JSON.stringify(pkg, null, 2)
  )

  console.log(`Saved transformed package to ${filePath}`)
}

Transform During Fetch ​

You can integrate transformations directly into the fetch process:

typescript
// Modify the fetchAndSavePackage function to include transformations
async function fetchTransformAndSavePackage(
  packageName: string,
  outputDir: string,
  transformer: (pkg: PkgxPackage) => PkgxPackage
): Promise<{ success: boolean, filePath?: string }> {
  try {
    // Fetch the package
    const { packageInfo } = await fetchPantryPackage(packageName)

    // Apply the transformation
    const transformedPackage = transformer(packageInfo)

    // Save the transformed package
    const fileName = `${packageName.replace(/\./g, '')}.json`
    const filePath = path.join(outputDir, fileName)

    fs.writeFileSync(filePath, JSON.stringify(transformedPackage, null, 2))

    return { success: true, filePath }
  }
  catch (error) {
    console.error(`Error processing ${packageName}:`, error)
    return { success: false }
  }
}

This customization capability allows you to tailor the package data to your specific requirements.

Released under the MIT License.