Skip to content

Quick Start

This guide walks through building a plan, running it, and inspecting the results.

  1. Install the package

    Terminal window
    npm install @origints/core
  2. Create a plan

    A plan defines what data to extract and how to structure the output. Plans are immutable — once compiled, they can be run multiple times.

    import { Planner, load } from '@origints/core'
    const plan = new Planner()
    .in(load({ name: 'Alice', age: 30, role: 'admin' }))
    .emit((out, $) => out
    .add('name', $.get('name').string())
    .add('age', $.get('age').number())
    .add('role', $.get('role').string())
    )
    .compile()
  3. Run the plan

    import { run } from '@origints/core'
    const result = await run(plan)
  4. Handle the result

    The result is a discriminated union — never a thrown exception:

    if (result.ok) {
    console.log(result.value)
    // { name: 'Alice', age: 30, role: 'admin' }
    } else {
    for (const failure of result.failures) {
    console.error(`[${failure.kind}] ${failure.message}`)
    }
    }
  5. Inspect lineage

    Every run records provenance, regardless of success or failure:

    import { formatLineageAsString } from '@origints/core'
    console.log(formatLineageAsString(result.lineage, plan.ast))

File inputs produce byte streams. Decoding must be explicit via transforms.

import { Planner, loadFile, run, parseJson } from '@origints/core'
const plan = new Planner()
.in(loadFile('data.json'))
.mapIn(parseJson())
.emit((out, $) => out
.add('id', $.get('id').number())
.add('name', $.get('name').string())
)
.compile()
const result = await run(plan, {
readFile: (path) => fs.promises.readFile(path),
})
// Nested access
const plan = new Planner()
.in(load({ user: { profile: { email: 'alice@example.com' } } }))
.emit((out, $) => out
.add('email', $.get('user').get('profile').get('email').string())
)
.compile()
// Array mapping
const plan2 = new Planner()
.in(load({
users: [
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 },
],
}))
.emit((out, $) => out
.add('names', $.get('users').array(u => u.get('name').string()))
)
.compile()
const result = await run(plan2)
// result.value: { names: ['Alice', 'Bob'] }

A single plan can pull data from multiple sources:

const plan = new Planner()
.in(loadFile('config.json'))
.mapIn(parseJson())
.emit((out, $) => out.add('host', $.get('host').string()))
.in(loadFile('users.json'))
.mapIn(parseJson())
.emit((out, $) => out
.add('users', $.get('data').array(u => u.get('name').string()))
)
.compile()

Validate inputs against a Standard Schema (Zod, Valibot, etc.):

import { z } from 'zod'
const UserSchema = z.object({
name: z.string(),
age: z.number().min(0),
})
const plan = new Planner()
.in(load({ name: 'Bob', age: 25 }).validate(UserSchema))
.emit((out, $) => out
.add('name', $.get('name').string())
.add('age', $.get('age').number())
)
.compile()