npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@subspacecomputing/sdk

v0.1.4

Published

TypeScript SDK for ASTRIA — Subspace Computing Engine

Readme

ASTRIA — TypeScript SDK

TypeScript SDK for ASTRIA, the Subspace Computing Engine.

Installation

npm install @subspacecomputing/sdk
# or
yarn add @subspacecomputing/sdk
# or
pnpm add @subspacecomputing/sdk

Usage

Initialization

import { ASTRIA } from '@subspacecomputing/sdk';

// Initialize the client (defaults to production URL)
const client = new ASTRIA('your-api-key-here');

Teams (X-Team-Id)

Optional third constructor argument sets the team UUID (header X-Team-Id). Use setTeamId to change or clear it. If the API needs a team context, you may get 400 with error.reason === 'team_context_required' — handle ValidationError and read err.errorReason.

const client = new ASTRIA('key', 'https://api.subspacecomputing.com', 'team-uuid');
client.setTeamId(undefined);

Simple Projection (1 scenario)

// Create a simple SP Model
const spec = {
  scenarios: 1, // Must be 1 for project()
  steps: 12,
  variables: [
    {
      name: 'capital',
      init: 1000.0,
      formula: 'capital[t-1] * 1.05', // 5% growth per period
    },
  ],
};

// Run the projection
const result = await client.project(spec);

// Display results
console.log(`Final capital: ${result.final_values.capital}`);
console.log(`Trajectory: ${result.trajectory.capital}`);

Monte Carlo Simulation (Multiple scenarios)

// SP Model with random variables
const spec = {
  scenarios: 1000, // 1000 Monte Carlo scenarios
  steps: 12,
  variables: [
    {
      name: 'taux',
      dist: 'uniform',
      params: { min: 0.03, max: 0.07 },
      per: 'scenario',
    },
    {
      name: 'capital',
      init: 1000.0,
      formula: 'capital[t-1] * (1 + taux)',
    },
  ],
};

// Run the simulation
const result = await client.simulate(spec);

// Analyze results
console.log(`Mean final capital: ${result.last_mean.capital}`);
console.log(`Median: ${result.statistics.capital.median}`);
console.log(`P5: ${result.statistics.capital.percentiles['5']}`);
console.log(`P95: ${result.statistics.capital.percentiles['95']}`);

Per-step statistics (fan charts)

When the API supports it, set include_per_step_statistics: true to receive full MC statistics at each time step (t = 0 through steps). The last entry matches statistics[var].

const spec = {
  scenarios: 1000,
  steps: 12,
  include_per_step_statistics: true,
  variables: [/* ... */],
};

const result = await client.simulate(spec);

if (result.per_step_statistics?.capital) {
  const atHorizon = result.per_step_statistics.capital.at(-1);
  console.log(`P10 at horizon: ${atHorizon?.p10 ?? atHorizon?.percentiles['10']}`);
}

Batch Mode (Multiple Entities)

// SP Model template
const template = {
  scenarios: 1,
  steps: '65 - batch_params.age', // Dynamic steps
  variables: [
    {
      name: 'age_actuel',
      init: 'batch_params.age',
    },
    {
      name: 'salaire',
      init: 'batch_params.salary',
      formula: 'salaire[t-1] * 1.03', // 3% annual increase
    },
    {
      name: 'capital_retraite',
      init: 0.0,
      formula: 'capital_retraite[t-1] * 1.05 + salaire[t] * 0.10',
    },
  ],
};

// Entity data
const batchParams = [
  { entity_id: 'emp_001', age: 45, salary: 60000 },
  { entity_id: 'emp_002', age: 50, salary: 80000 },
  { entity_id: 'emp_003', age: 35, salary: 50000 },
];

// Global aggregations (optional)
const aggregations = [
  {
    name: 'capital_total',
    formula: 'sum(capital_retraite[t_final])',
  },
  {
    name: 'moyenne_capital',
    formula: 'mean(capital_retraite[t_final])',
  },
];

// Run batch
const result = await client.projectBatch(template, batchParams, aggregations);

// Analyze results
for (const entity of result.entities) {
  console.log(`${entity._entity_id}: Capital = ${entity.final_values.capital_retraite}`);
}

console.log(`Total capital: ${result.aggregations?.capital_total}`);
console.log(`Average: ${result.aggregations?.moyenne_capital}`);

Run a stored model (projectionId + inputs)

Execute a projection already saved in Subspace. Load run_inputs once (cache in your app), drive the UI from that descriptor, then runModel many times with overrides only. Astria runs the calculation; model structure (formula, dist type, per) is not overridable.

const proj = await client.loadModel(projectionId); // getProjection + in-memory cache
// Or: const proj = await client.getProjection(projectionId);

const result = await client.runModel(projectionId, { capital: 25000 });
console.log(result);

Input shapes by run_inputs.kind:

| kind | Example value in inputs | |--------|---------------------------| | init | { capital: 25000 } | | params | { taux: { min: 0.02, max: 0.05 } } | | values | { inflation: [0.01, 0.02, 0.03] } | | table_ref / table | { mortality: '<uuid>' } or { grid: { ... } } | | run | { scenarios: 100, steps: 12 } |

Unknown keys → API 400 unknown_run_input. rerunRun(runId) re-executes a past run snapshot, not the live model.

Pattern for a dynamic form / batch loop:

const proj = await client.loadModel(projectionId);
const inputs: Record<string, unknown> = {};
for (const desc of proj.run_inputs ?? []) {
  if (desc.kind === 'init') {
    inputs[desc.name] = desc.default; // or from UI
  } else if (desc.kind === 'params') {
    inputs[desc.name] = { ...(desc.default as object) };
  }
  // else if (desc.kind === 'values') ...
}
const result = await client.runModel(projectionId, inputs);

Runs: read, artifact, rerun, replay

Four distinct operations on persisted runs:

| Method | What it does | |--------|----------------| | getRun(runId) | Read metadata, stored SP Model snapshot, and result_summary | | getRunArtifact(artifactId) | Read heavy results already computed (final_values / URL) | | rerunRun(runId, specPatch?) | Re-execute the run's snapshot in Astria; creates a new run | | replayRun(runId, scenarioId) | Reproduce one Monte Carlo scenario when seeds were stored |

// Cross-language analysis: app computed → TypeScript/Python reads original results
const run = await client.getRun(runId);
console.log(run.result_summary);
if (run.artefact_id) {
  const artifact = await client.getRunArtifact(run.artefact_id);
  console.log(artifact.final_values);
}

// Re-execute the exact snapshot (validation) — new run, same projection
const baseline = await client.rerunRun(runId);
console.log(baseline.run_id, baseline.source_spec_hash, baseline.spec_changed);

// What-if: fork the snapshot with a JSON Merge Patch (source run unchanged)
const whatIf = await client.rerunRun(runId, {
  meta: { seed: 42 },
});
console.log(whatIf.executed_spec_hash);

// Exact one-scenario MC replay (requires meta.store_seeds_for_replay on the source run)
const replay = await client.replayRun(runId, 0);
console.log(replay.final_values);

Notes

  • rerunRun uses the run's stored spec, not the projection's current dsl_template.
  • Requires persist_mode=full.
  • replayRun needs seeds persisted on the source run; it does not accept a body (path params only).
  • Live table_refs may resolve to newer data than at original execution time.

Validation

// Validate an SP Model before execution
const validation = await client.validate(spec);

if (validation.is_valid) {
  console.log('✅ SP Model is valid');
  if (validation.warnings) {
    console.log(`⚠️  Warnings: ${validation.warnings}`);
  }
} else {
  console.log(`❌ Errors: ${validation.errors}`);
}

Utilities

// Get examples
const examples = await client.getExamples();
console.log(`Available examples: ${examples.examples.length}`);

// Check usage
const usage = await client.getUsage();
console.log(
  `Simulations used: ${usage.quota.used}/${usage.quota.limit}`
);

// Get plans
const plans = await client.getPlans();
for (const plan of plans.plans) {
  console.log(`${plan.name}: $${plan.price_monthly}/month`);
}

Error Handling

import {
  ASTRIA,
  SubspaceError,
  QuotaExceededError,
  RateLimitError,
  AuthenticationError,
  ValidationError,
} from '@subspacecomputing/sdk';

try {
  const result = await client.simulate(spec);
} catch (error) {
  if (error instanceof QuotaExceededError) {
    console.error(`Monthly quota exceeded: ${error.message}`);
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limit exceeded: ${error.message}`);
    const retryAfter = error.response?.headers.get('Retry-After');
    if (retryAfter) {
      console.log(`Retry after: ${retryAfter} seconds`);
    }
  } else if (error instanceof AuthenticationError) {
    console.error(`Invalid API key: ${error.message}`);
  } else if (error instanceof ValidationError) {
    console.error(`Validation error: ${error.detail}`);
  } else if (error instanceof SubspaceError) {
    console.error(`API error: ${error.message}`);
  }
}

Rate Limit and Quota Information

After making a request, you can check your rate limit and quota status:

// Make a request
const result = await client.project(spec);

// Check rate limit info
const rateLimit = client.getRateLimitInfo();
if (rateLimit) {
  console.log(
    `Rate limit: ${rateLimit.remaining}/${rateLimit.limit} remaining`
  );
}

// Check quota info
const quota = client.getQuotaInfo();
if (quota) {
  console.log(
    `Quota: ${quota.used}/${quota.limit} used, ${quota.remaining} remaining`
  );
}

Documentation

Full documentation: https://www.subspacecomputing.com/developer

API Reference: https://www.subspacecomputing.com/docs

Support: [email protected]

License

MIT License. See LICENSE for details.

Copyright

© 2026 Subspace Computing Inc. All Rights Reserved