Skip to content

Extending the Aliases System

ts-pkgx includes a built-in aliases system that maps common package names to their full domain names. You can extend this system to customize it for your specific needs.

Understanding the Aliases System

The aliases system is a simple mapping from shorthand names to full domain names:

typescript
import { PACKAGE_ALIASES } from 'ts-pkgx/fetch'

// Examine the built-in aliases
console.log(PACKAGE_ALIASES)

The default aliases include mappings like:

typescript
const PACKAGE_ALIASES: Record<string, string> = {
  node: 'nodejs.org',
  python: 'python.org',
  go: 'go.dev',
  rust: 'rust-lang.org',
  ruby: 'ruby-lang.org',
  php: 'php.net',
  perl: 'perl.org',
  deno: 'deno.land',
  bun: 'bun.sh',
  // ... and many more
}

Adding Custom Aliases

You can add your own aliases to the system:

typescript
import { PACKAGE_ALIASES } from 'ts-pkgx/fetch'

// Add custom aliases
function extendAliases(customAliases: Record<string, string>): void {
  Object.entries(customAliases).forEach(([alias, domain]) => {
    if (!PACKAGE_ALIASES[alias]) {
      PACKAGE_ALIASES[alias] = domain
      console.log(`Added alias: ${alias} -> ${domain}`)
    }
  })
}

// Usage
extendAliases({
  js: 'nodejs.org',
  py: 'python.org',
  rs: 'rust-lang.org',
  bunjs: 'bun.sh',
})

This allows you to use your preferred shorthand names when fetching packages.

Organization-Specific Aliases

For teams or organizations, you might want to create a set of standardized aliases:

typescript
// Organization-specific aliases for a team
const ORGANIZATION_ALIASES: Record<string, string> = {
  'web-server': 'nginx.org',
  'db': 'postgresql.org',
  'cache': 'redis.io',
  'mq': 'rabbitmq.com',
  'search': 'elastic.co',
  'frontend': 'reactjs.org',
}

// Extend the standard aliases with organization-specific ones
extendAliases(ORGANIZATION_ALIASES)

Creating Category Aliases

You can create aliases that represent categories of packages:

typescript
// Map categories to their representative package
const CATEGORY_ALIASES: Record<string, string> = {
  'js-runtime': 'nodejs.org',
  'py-runtime': 'python.org',
  'database': 'postgresql.org',
  'container': 'docker.com',
  'orchestration': 'kubernetes.io',
}

extendAliases(CATEGORY_ALIASES)

Aliases for Nested Paths

For packages with nested paths, you can create aliases for easier access:

typescript
// Aliases for nested paths
const NESTED_PATH_ALIASES: Record<string, string> = {
  'git-crypt': 'agwa.name/git-crypt',
  'bun-create': 'github.com/oven-sh/create-bun',
  'cargo-generate': 'github.com/cargo-generate/cargo-generate',
}

extendAliases(NESTED_PATH_ALIASES)

Version-Specific Aliases

You can create aliases for specific versions of packages:

typescript
// Aliases for specific versions
const VERSION_ALIASES: Record<string, string> = {
  'node16': 'nodejs.org@16',
  'node18': 'nodejs.org@18',
  'node20': 'nodejs.org@20',
  'python3.9': 'python.org@3.9',
  'python3.10': 'python.org@3.10',
}

// You would need to modify the resolver to handle the version part
function resolveVersionedAlias(alias: string): { domain: string, version?: string } {
  if (VERSION_ALIASES[alias]) {
    const [domain, version] = VERSION_ALIASES[alias].split('@')
    return { domain, version }
  }

  if (PACKAGE_ALIASES[alias]) {
    return { domain: PACKAGE_ALIASES[alias] }
  }

  return { domain: alias }
}

Persisting Custom Aliases

For persistent customization, you can save and load your aliases:

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

const ALIASES_FILE = path.join(process.cwd(), 'pkgx-aliases.json')

// Save aliases to a file
function saveAliases(): void {
  fs.writeFileSync(ALIASES_FILE, JSON.stringify(PACKAGE_ALIASES, null, 2))
  console.log(`Saved aliases to ${ALIASES_FILE}`)
}

// Load aliases from a file
function loadAliases(): void {
  if (fs.existsSync(ALIASES_FILE)) {
    try {
      const aliases = JSON.parse(fs.readFileSync(ALIASES_FILE, 'utf8'))
      extendAliases(aliases)
      console.log(`Loaded aliases from ${ALIASES_FILE}`)
    }
    catch (error) {
      console.error('Error loading aliases:', error)
    }
  }
}

// Initialize aliases when your application starts
loadAliases()

// Save aliases when your application exits
process.on('exit', saveAliases)

Generating Aliases Automatically

You can generate aliases automatically based on domain patterns:

typescript
import { pantry } from 'ts-pkgx'

// Generate aliases for all packages
function generateAliases(): Record<string, string> {
  const generatedAliases: Record<string, string> = {}

  for (const [domain, pkg] of Object.entries(pantry)) {
    // Basic name alias (remove spaces and lowercase)
    const nameAlias = pkg.name.toLowerCase().replace(/\s+/g, '')
    if (!PACKAGE_ALIASES[nameAlias] && nameAlias !== domain) {
      generatedAliases[nameAlias] = domain
    }

    // First word of the domain (before the dot)
    const domainFirstPart = domain.split('.')[0]
    if (!PACKAGE_ALIASES[domainFirstPart] && domainFirstPart !== domain) {
      generatedAliases[domainFirstPart] = domain
    }

    // For packages with programs, use the main program name as an alias
    if (pkg.programs.length > 0) {
      const mainProgram = pkg.programs[0]
      if (!PACKAGE_ALIASES[mainProgram] && mainProgram !== domain) {
        generatedAliases[mainProgram] = domain
      }
    }
  }

  return generatedAliases
}

// Generate and extend aliases
const autoAliases = generateAliases()
extendAliases(autoAliases)

CLI for Alias Management

You can add CLI commands to manage aliases:

typescript
cli
  .command('alias <name> <domain>', 'Add a package alias')
  .action((name, domain) => {
    PACKAGE_ALIASES[name] = domain
    console.log(`Added alias: ${name} -> ${domain}`)
    saveAliases()
  })

cli
  .command('aliases', 'List all package aliases')
  .action(() => {
    console.log('Package aliases:')
    Object.entries(PACKAGE_ALIASES)
      .sort(([a], [b]) => a.localeCompare(b))
      .forEach(([alias, domain]) => {
        console.log(`  ${alias.padEnd(15)} -> ${domain}`)
      })
  })

cli
  .command('remove-alias <name>', 'Remove a package alias')
  .action((name) => {
    if (PACKAGE_ALIASES[name]) {
      const domain = PACKAGE_ALIASES[name]
      delete PACKAGE_ALIASES[name]
      console.log(`Removed alias: ${name} -> ${domain}`)
      saveAliases()
    }
    else {
      console.error(`Alias not found: ${name}`)
    }
  })

These extensions to the aliases system allow you to customize ts-pkgx to fit your specific workflow and preferences.

Released under the MIT License.