Skip to content

Migrate GraphIR 1 data to GraphIR 2 ​

Coral 0.2.5 uses @graph-ir/core@0.2.1 and accepts authored GraphIR 2.0 at its public GraphIR boundaries. Coral 0.2.4 used exact core 0.2.0 and GraphIR 1.0. Migrate stored GraphIR 1 data before passing it to Coral 0.2.5 APIs.

GraphIR 1 to GraphIR 2 ​

Use the core package's named migrateIR adapter at the load boundary. A successful lossless migration returns a GraphIR 2 value that can be passed to the language, render, or viz packages.

ts
import { migrateIR, type GraphIR as GraphIR2 } from '@graph-ir/core';
import { convertGraphToFlow } from '@coral-viz/viz';

const storedGraphIR1: unknown = {
  version: '1.0.0',
  id: 'stored',
  nodes: [{ id: 'service', type: 'service' }],
  edges: [],
};

const result = migrateIR(storedGraphIR1);
if (!result.success || !result.migrated) {
  throw new Error(result.errors.join('\n'));
}

const graph: GraphIR2 = result.migrated;
const flow = convertGraphToFlow(graph);
if (flow.nodes.length !== 1) throw new Error('Migrated graph was not projected');

const ambiguousGraphIR1: unknown = {
  version: '1.0.0',
  id: 'ambiguous',
  nodes: [
    { id: 'a', type: 'service' },
    { id: 'b', type: 'database' },
  ],
  edges: [{
    id: 'edge',
    source: 'a',
    target: 'b',
    routingPoints: [{ x: 1, y: 2 }],
  }],
};

const refused = migrateIR(ambiguousGraphIR1);
if (refused.success || !refused.losses.some(
  (loss) => loss.path === '/edges/0/routingPoints',
)) {
  throw new Error('Ambiguous geometry was not refused');
}

const dropped = migrateIR(ambiguousGraphIR1, { ambiguousGeometry: 'drop' });
if (!dropped.success || !dropped.migrated) {
  throw new Error(dropped.errors.join('\n'));
}
if (!dropped.losses.some((loss) =>
  loss.path === '/edges/0/routingPoints' && loss.field === 'routingPoints')) {
  throw new Error('Explicit migration loss was not attributed');
}
for (const loss of dropped.losses) console.warn(loss.path, loss.reason);

GraphIR 1 routingPoints are ambiguous: points do not say whether their coordinates are absolute, relative, or anchored. Migration therefore refuses them by default. If discarding that geometry is acceptable, opt in explicitly with ambiguousGeometry: 'drop' and inspect the returned losses before using the migrated graph.

GraphIR 2 replaces routingPoints with authored routeIntent, narrows GraphIR.version to 2.0.0, and removes LayoutOptions.algorithmOptions. Migration does not invent route intent or algorithm-specific meaning that was not present in the source. Keep the migration at an explicit trust boundary; do not cast a GraphIR 1 object to GraphIR 2.

Compatibility boundary ​

The 0.2.5 compatibility gate verifies published 0.2.4 artifacts against core 0.2.0 and candidate 0.2.5 artifacts against core 0.2.1. The GraphIR changes above are the only approved public transition. Existing Coral layout APIs retain their six legacy diagnostic codes; the five spatial-layout diagnostics are exposed through the additive spatial diagnostic types.