# @x12i/graphenix-format

> Graphenix graph description format: JSON schema, validation, and CRUD helpers.

Latest version **2.0.0** (published 2026-04-26) · MIT license · 0 weekly downloads

## Install

```sh
npm install @x12i/graphenix-format
pnpm add @x12i/graphenix-format
yarn add @x12i/graphenix-format
bun add @x12i/graphenix-format
```

## Health

**Score 60/100 (C)** — status: active.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 2.0.0 |
| Published | 2026-04-26 |
| First published | 2026-04-26 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 1 |
| Unpacked size | 82.5 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Maintainers | x12i |
| Keywords | graph, workflow, json-schema, validation, graphenix |

## Links

- npm: https://www.npmjs.com/package/@x12i/graphenix-format
- Repository: https://github.com/x12i/graphenix-format
- Homepage: https://github.com/x12i/graphenix-format#readme
- Issues: https://github.com/x12i/graphenix-format/issues
- npm.io page: https://npm.io/package/@x12i/graphenix-format

## Dependencies (1)

- [ajv](https://npm.io/package/ajv.md) ^8.17.1

## Alternatives

- [@regle/core](https://npm.io/package/@regle/core.md) — 47.0K weekly downloads
- [typeof-arguments](https://npm.io/package/typeof-arguments.md) — 12.5K weekly downloads
- [@lokalise/projects-engine-contracts](https://npm.io/package/@lokalise/projects-engine-contracts.md) — 978 weekly downloads
- [@osjwnpm/nam-laboriosam-quibusdam](https://npm.io/package/@osjwnpm/nam-laboriosam-quibusdam.md) — 70 weekly downloads
- [@oridune/validator](https://npm.io/package/@oridune/validator.md) — 16 weekly downloads

## Recent versions

- 2.0.0 (latest) — 2026-04-26

## README

## `@x12i/graphenix-format`

TypeScript/JavaScript utilities for working with the **Graphenix Format 1.0.0**:

- **JSON Schema** for validation (`schema/graphenix-format-1.0.0.schema.json`)
- **Runtime validator** built on [`ajv`](https://ajv.js.org)
- Lightweight **CRUD helpers** for nodes, edges, types and subgraphs
- First-class **TypeScript types** for graph documents

---

### Install

```bash
npm install @x12i/graphenix-format
# or
yarn add @x12i/graphenix-format
```

---

### Usage

#### Validate a graph document

```ts
import { validateGraph, type GraphDocument } from "@x12i/graphenix-format";

const doc: GraphDocument = {
  formatVersion: "1.0.0",
  id: "graph:auth/user-signup",
  graph: {
    nodes: [],
    edges: [],
    inputs: [],
    outputs: []
  }
};

const result = validateGraph(doc);

if (!result.valid) {
  console.error(result.errors);
}
```

Each error has:

- **`message`**: human readable message
- **`path`**: JSON Pointer to the failing instance
- **`keyword`** and **`params`** from `ajv` for tooling.

---

#### Quick start: minimal Graphenix document

This is a minimal but complete **Graphenix Format 1.0.0** document that you can load, validate, and then modify:

```ts
import {
  validateGraph,
  type GraphDocument,
  addNode,
  addEdge
} from "@x12i/graphenix-format";

const doc: GraphDocument = {
  formatVersion: "1.0.0",
  id: "graph:auth/user-signup",
  name: "User Signup",
  graph: {
    nodes: [
      {
        id: "node:validate-input",
        kind: "builtin:validate",
        inputs: [
          {
            id: "in:payload",
            direction: "input",
            type: "builtin:object",
            required: true
          }
        ],
        outputs: [
          {
            id: "out:validated",
            direction: "output",
            type: "builtin:object"
          }
        ],
        parameters: {
          schemaType: "type:User"
        }
      }
    ],
    edges: [],
    inputs: [
      {
        id: "graph-input:request",
        name: "Request Body",
        type: "builtin:object",
        target: {
          nodeId: "node:validate-input",
          portId: "in:payload"
        }
      }
    ],
    outputs: [],
    metadata: {}
  },
  types: [
    {
      id: "type:User",
      kind: "object",
      fields: [
        { name: "id", type: "builtin:string", required: true },
        { name: "email", type: "builtin:string", required: true }
      ]
    }
  ]
};

// Validate against the Graphenix JSON Schema
const res = validateGraph(doc);
if (!res.valid) {
  throw new Error(JSON.stringify(res.errors, null, 2));
}

// Programmatically add a new node + edge
const withCreateNode = addNode(doc, {
  id: "node:create-user",
  kind: "task:http-request",
  inputs: [
    {
      id: "in:validated",
      direction: "input",
      type: "type:User",
      required: true
    }
  ],
  outputs: [
    {
      id: "out:user",
      direction: "output",
      type: "type:User"
    }
  ],
  parameters: {
    method: "POST",
    url: "https://example.com/users"
  }
});

const finalDoc = addEdge(withCreateNode, {
  id: "edge:validate-to-create",
  from: { nodeId: "node:validate-input", portId: "out:validated" },
  to: { nodeId: "node:create-user", portId: "in:validated" }
});
```

This matches the structure described in `GRAPHENIX-FORMAT.md` and can be fed directly to your executor.

---

#### CRUD helpers

CRUD helpers operate on an in-memory `GraphDocument` and return a new document by default (immutable), or mutate in-place when `mutate: true` is passed.

```ts
import {
  addNode,
  updateNode,
  removeNode,
  addEdge,
  removeEdge,
  addType
} from "@x12i/graphenix-format";

import type { GraphDocument } from "@x12i/graphenix-format";

let doc: GraphDocument = /* ... */;

// Add a node (immutable)
doc = addNode(doc, {
  id: "node:validate-input",
  kind: "builtin:validate",
  inputs: [],
  outputs: []
});

// Update a node
doc = updateNode(doc, "node:validate-input", {
  name: "Validate Input"
});

// Remove a node (also removes attached edges and graph IO)
doc = removeNode(doc, "node:validate-input");
```

All CRUD helpers accept an optional `{ mutate?: boolean }`:

```ts
addNode(doc, newNode, { mutate: true }); // modifies `doc` in place
```

Available helpers:

- **Nodes**: `getNode`, `addNode`, `updateNode`, `removeNode`
- **Edges**: `getEdge`, `addEdge`, `updateEdge`, `removeEdge`
- **Types**: `getType`, `addType`, `updateType`, `removeType`
- **Subgraphs**: `getSubgraph`, `addSubgraph`, `updateSubgraph`, `removeSubgraph`

---

### Working with subgraphs and types

Subgraphs are just nested `graph` structures that can be referenced via node `kind`:

```ts
import {
  type GraphDocument,
  addSubgraph,
  addNode
} from "@x12i/graphenix-format";

let doc: GraphDocument = /* existing document */;

// Add a reusable subgraph
doc = addSubgraph(doc, {
  id: "graph:user-validation",
  name: "User Validation",
  graph: {
    nodes: [],
    edges: [],
    inputs: [],
    outputs: []
  }
});

// Use it as a node in the main graph
doc = addNode(doc, {
  id: "node:user-validation",
  kind: "subgraph:graph:user-validation",
  inputs: [],
  outputs: []
});
```

For a full description of all fields and constraints, see `GRAPHENIX-FORMAT.md` in this repo.

---

### Build & test locally

```bash
# install dev dependencies
npm install

# build ESM + CJS
npm run build

# run a tiny smoke test that validates the minimal example graph
npm test
```

The minimal example graph lives in `src/examples/minimal-graph.ts` and mirrors the example from `GRAPHENIX-FORMAT.md`.

---

### Design-level graph input contracts (`graph.inputs[].contract`)

`graph.inputs` describes external input **ports** (`id`, `type`, `target`). The optional `contract` block on each input adds the **design-level semantic role** of the input value and optional resolver hints — without changing execution semantics.

The contract is execution-neutral: validators accept it, but engines are not required to perform any lookup based on it.

**Suggested `semanticKind` values:**

- `record` — a structured record fed in as raw input.
- `query` — a search/query specification.
- `user-input` — direct end-user input.
- `content` — opaque content payload (text, blob, document).
- `metadata` — descriptive metadata about another value.
- `execution` — a prior graph execution as input.

For the `execution` semantic, the `resolver` block can declare how to look up the prior execution (source `graphId` and an optional `metadataFilter`).

**Example: a normal `record` input**

```json
{
  "id": "rawRecord",
  "type": "object",
  "target": {
    "nodeId": "q1",
    "portId": "record"
  },
  "contract": {
    "semanticKind": "record",
    "required": true,
    "schema": {
      "type": "object"
    }
  }
}
```

**Example: a prior graph execution as input**

```json
{
  "id": "upstreamGroupTriage",
  "name": "Upstream group triage execution",
  "type": "execution",
  "target": {
    "nodeId": "q1",
    "portId": "upstreamExecution"
  },
  "contract": {
    "semanticKind": "execution",
    "required": true,
    "resolver": {
      "kind": "graph-execution",
      "graphId": "network-vuln-group-triage.v1",
      "metadataFilter": {
        "status": "completed"
      }
    }
  }
}
```

**TypeScript:**

```ts
import type { GraphInput, GraphInputContract } from "@x12i/graphenix-format";

const input: GraphInput = {
  id: "rawRecord",
  type: "object",
  target: { nodeId: "q1", portId: "record" },
  contract: {
    semanticKind: "record",
    required: true,
    schema: { type: "object" }
  }
};
```

**Non-goals:**

- Engines are not required to perform runtime lookup for `resolver`.
- Worox-specific execution behavior is **not** defined in Graphenix core.
- The format is **not** split into design and runtime sections.
- `metadata` and `extensions` are unchanged.

---

### Worox-graph alignment (`metadata.graphEntry` / `metadata.graphResponse`)

Worox-graph attaches **entry** and **response** contracts to graph JSON; graphenix-format exposes the same shapes as **optional fields on the graph document**:

| Field | Type | Role |
|-------|------|------|
| `metadata.graphEntry` | `GraphEntryContract` | Entry / execution expectations |
| `metadata.graphResponse` | `GraphResponseContract` | Final output shape |

**`GraphEntryContract`** may include:

- `summary` — short description of what the graph expects at entry.
- `requiredExecutionPaths` / `notableExecutionPaths` — path descriptors (engine-specific item shapes).
- `executionSchema` — JSON Schema for the merged **execution** object after entry (optional tooling validation only).

**`GraphResponseContract`** may include:

- `summary` — description of the response.
- `finalOutputSchema` — JSON Schema for the **final output** value (optional tooling validation only).

**I/O visibility layers (single narrative for authors):**

- **Layer 01** — **Entry**: what must be satisfied when the graph is invoked; described by `graphEntry` (`summary`, paths, `executionSchema`).
- **Layer 08** — **Response**: what leaves the graph as the final result; described by `graphResponse` (`summary`, `finalOutputSchema`).

Optional **AJV** checks (not required for graphenix planning):

```ts
import {
  validateGraph,
  validateExecutionAgainstContract,
  validateFinalOutputAgainstContract,
  type GraphDocument
} from "@x12i/graphenix-format";

const doc: GraphDocument = /* ... with metadata.graphEntry / metadata.graphResponse ... */;

validateGraph(doc);
validateExecutionAgainstContract(doc, mergedExecution);
validateFinalOutputAgainstContract(doc, finalOutput);
```

For how worox-graph’s task/DAG JSON differs from port-based `Graph`, see [`docs/interop-worox-graph.md`](docs/interop-worox-graph.md).

**Planning-only catalog fields (worox-graph):** optional `metadata.catalogRequests` on the document, and optional `metadata.catalogRequest` / `metadata.catalogBinding` on nodes, align with `@woroces/worox-graph` (`refs.ts`). JSON Schema `$defs` `WoroxCatalogRequest`, `WoroxCatalogBinding`, `WoroxCatalogRequests` describe the same keys for optional cross-validation; execution is unchanged.

---

### Notes

- The package is **execution-agnostic**: it only knows about the static Graphenix format.
- Runtime concerns (scheduling, retries, parallelism, logging, etc.) are intentionally left to your executor/runtime.

---
_Source: https://npm.io/package/@x12i/graphenix-format · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
