Skip to content

phasetdev/phaset-from-backstage

Repository files navigation

phaset-from-backstage

Convert Backstage catalog entities to Phaset records with intelligent field mapping and batch processing.

Installation

npm install phaset-from-backstage

Usage

Programmatic (Node.js)

⚠️ Important: When using the library programmatically, you must read files yourself. File paths are NOT supported - pass YAML content as strings instead. This is intentional to support tree-shaking for browser builds.

Using parsed objects

import { convertBackstageEntity } from 'phaset-from-backstage';

const manifest = convertBackstageEntity({
  apiVersion: 'backstage.io/v1alpha1',
  kind: 'Component',
  metadata: {
    name: 'my-service',
    annotations: { 'github.com/project-slug': 'myorg/my-service' }
  },
  spec: { type: 'service', lifecycle: 'production' }
}, 'your-org-id');

Reading from files

import { readFileSync } from 'node:fs';
import { convertBackstageEntity } from 'phaset-from-backstage';

// Read the file yourself and pass the YAML content
const yamlContent = readFileSync('./catalog-info.yaml', 'utf-8');
const manifest = convertBackstageEntity(yamlContent, 'your-org-id');

With diagnostics (warnings, unmapped fields)

import { readFileSync } from 'node:fs';
import { convertBackstageEntityWithDetails } from 'phaset-from-backstage';

const yamlContent = readFileSync('./catalog-info.yaml', 'utf-8');
const { manifest, warnings, unmappedFields } = convertBackstageEntityWithDetails(yamlContent, 'your-org-id');

console.log('Warnings:', warnings);
console.log('Unmapped fields:', unmappedFields);

Batch conversion

import { readFileSync } from 'node:fs';
import { PhasetFromBackstage } from 'phaset-from-backstage';

const converter = new PhasetFromBackstage({
  organizationId: 'myorg',
  defaultRepo: 'myorg/unknown'
});

const files = ['./catalog-info.yaml', './other-catalog.yaml'];
const yamlContents = files.map(f => readFileSync(f, 'utf-8'));
const results = converter.convertBatchWithDetails(yamlContents);

Browser Usage

The library is fully browser-compatible! The browser build automatically excludes Node.js filesystem APIs.

<script type="module">
  import { convertBackstageEntity } from 'phaset-from-backstage';

  // Pass YAML strings or parsed objects (NOT file paths)
  const yamlString = `apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: my-service
spec:
  type: service
  lifecycle: production`;

  const manifest = convertBackstageEntity(yamlString, 'your-org-id');
  console.log(manifest);
</script>

CLI

For file-based conversions, use the CLI instead:

# Single file
phaset-from-backstage convert --org myorg --input catalog-info.yaml

# Batch convert
phaset-from-backstage batch --org myorg --input-dir ./catalogs --output-dir ./output

# Analyze catalog structure
phaset-from-backstage analyze --org myorg --input-dir ./catalogs --output report.json

Key Mappings

Backstage Phaset Notes
metadata.name spec.name -
metadata.description spec.description Defaults to "Component: {name}"
spec.lifecycle spec.lifecycleStage experimental→development, etc.
spec.owner contacts[].email If email format
metadata.tags tags[] Cleaned, max 5
metadata.links links[] Max 10
spec.dependsOn dependencies[] Default criticality: medium
github.com/project-slug spec.repo org/repo format
security-level annotation spec.dataSensitivity public/internal/secret
business-criticality annotation spec.businessCriticality critical/high/medium/low

Inferred from tags

  • aws, gcp, azuredeploymentModel: public_cloud
  • open-sourcesourcingModel: open_source
  • critical, tier-1businessCriticality: critical (if production)

Configuration

import { PhasetFromBackstage } from 'phaset-from-backstage';
import { readFileSync, writeFileSync } from 'node:fs';

const converter = new PhasetFromBackstage({
  organizationId: 'myorg',
  defaultRepo: 'myorg/unknown',
  includeAnnotationsAsMetadata: true,
  includeLabelsAsMetadata: true,
  mapCustomFields: true,
  strictMode: false
});

const yamlContent = readFileSync('./catalog-info.yaml', 'utf-8');
const results = converter.convertWithDetails(yamlContent);

console.log('Manifest:', results.manifest);
console.log('Warnings:', results.warnings);
console.log('Unmapped fields:', results.unmappedFields);

// Write if you want to persist the data
writeFileSync('phaset.manifest.json', JSON.stringify(results.manifest, null, 2));

Migration workflow

  1. Analyze catalog: phaset-from-backstage analyze --org myorg --input-dir ./catalogs
  2. Review report for common annotations and fields
  3. Create ID mappings for teams/systems/domains (8-char IDs required)
  4. Batch convert: phaset-from-backstage batch --org myorg --input-dir ./catalogs --output-dir ./output
  5. Review warnings and unmapped fields
  6. Import to Phaset

License

MIT