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

@voxgig-sdk/voxgig-solardemo

v0.1.0

Published

Unofficial generated TypeScript SDK for the Solar System public API. Not affiliated with or endorsed by the upstream API provider.

Downloads

120

Readme

Solardemo TypeScript SDK

The TypeScript SDK for the Solardemo API — a type-safe, entity-oriented client with full async/await support.

The API is exposed as capitalised, semantic Entities — e.g. client.Moon() — each with a small set of operations (list, load, create, update, remove) instead of raw URL paths and query parameters. This keeps the surface predictable and low-friction for both humans and AI agents.

Other languages, the CLI, and MCP server live alongside this one — see the top-level README.

Install

npm install @voxgig-sdk/voxgig-solardemo

Tutorial: your first API call

This tutorial walks through creating a client, listing entities, and loading a specific record.

1. Create a client

import { SolardemoSDK } from '@voxgig-sdk/voxgig-solardemo'

const client = new SolardemoSDK()

2. List moon records

list() resolves to an array of Moon ENTITIES — every operation resolves to entities, not raw records. Iterate them directly, and call .data() on one for the record it holds:

const moons = await client.Moon().list({ planet_id: "example" })

for (const moon of moons) {
  console.log(moon)
}

3. Load a moon

Moon is nested under planet, so provide the planet_id. load() returns the entity directly and throws on failure:

try {
  const moon = await client.Moon().load({
    planet_id: 'example_planet_id',
    id: 'example_id',
  })
  console.log(moon)
} catch (err) {
  console.error('load failed:', err)
}

4. Create, update, and remove

// Create — returns the created Moon ENTITY (.data() for the record)
const created = await client.Moon().create({
  planet_id: 'example_planet_id',
  diameter: 1,
  id: 'example_id',
  kind: 'example_kind',
  name: 'example_name',
})

// Update — the id comes off the returned entity's data()
const updated = await client.Moon().update({
  id: created.data().id!,
  planet_id: 'example_planet_id',
  diameter: 1,
})

// Remove
await client.Moon().remove({
  id: created.data().id!,
  planet_id: 'example_planet_id',
})

Error handling

Entity operations reject on failure, so wrap them in try / catch:

try {
  const moons = await client.Moon().list()
  console.log(moons)
} catch (err) {
  console.error('list failed:', err)
}

The low-level direct() method does not throw — it returns the value or an Error, so check the result before using it:

const result = await client.direct({
  path: '/api/resource/{id}',
  method: 'GET',
  params: { id: 'example_id' },
})

if (result instanceof Error) {
  throw result
}

How-to guides

Make a direct HTTP request

For endpoints not covered by entity methods:

const result = await client.direct({
  path: '/api/resource/{id}',
  method: 'GET',
  params: { id: 'example' },
})

if (result instanceof Error) {
  throw result
}
if (result.ok) {
  console.log(result.status)  // 200
  console.log(result.data)    // response body
}

Prepare a request without sending it

const fetchdef = await client.prepare({
  path: '/api/resource/{id}',
  method: 'DELETE',
  params: { id: 'example' },
})

// Inspect before sending
console.log(fetchdef.url)
console.log(fetchdef.method)
console.log(fetchdef.headers)

Use test mode

Create a mock client for unit testing — no server required:

const client = SolardemoSDK.test()

const moon = await client.Moon().list()
// moon is the entity, populated with mock response data
// — call moon.data() for the record itself
console.log(moon)

You can also use the instance method:

const client = new SolardemoSDK()
const testClient = client.tester()

Retain entity state across calls

Entity instances remember their last match and data:

const entity = client.Moon()

// First call runs the operation and stores its result
await entity.list()

// Subsequent calls reuse the stored state
const data = entity.data()
console.log(data.id)

Add custom middleware

Pass features via the extend option:

const logger = {
  hooks: {
    PreRequest: (ctx: any) => {
      console.log('Requesting:', ctx.spec.method, ctx.spec.path)
    },
    PreResponse: (ctx: any) => {
      console.log('Status:', ctx.out.request?.status)
    },
  },
}

const client = new SolardemoSDK({
  extend: [logger],
})

Run live tests

Create a .env.local file at the project root:

SOLARDEMO_TEST_LIVE=TRUE

Then run:

cd ts && npm test

Reference

SolardemoSDK

Constructor

new SolardemoSDK(options?: {
  base?: string
  prefix?: string
  suffix?: string
  feature?: Record<string, { active: boolean }>
  extend?: Feature[]
})

| Option | Type | Description | | --- | --- | --- | | base | string | Base URL of the API server. | | prefix | string | URL path prefix prepended to all requests. | | suffix | string | URL path suffix appended to all requests. | | feature | object | Feature activation flags (e.g. { test: { active: true } }). | | extend | Feature[] | Additional feature instances to load. |

Methods

| Method | Returns | Description | | --- | --- | --- | | options() | object | Deep copy of current SDK options. | | utility() | Utility | Deep copy of the SDK utility object. | | prepare(fetchargs?) | Promise<FetchDef> | Build an HTTP request definition without sending it. | | direct(fetchargs?) | Promise<DirectResult> | Build and send an HTTP request. | | Moon(data?) | MoonEntity | Create a Moon entity instance. | | Planet(data?) | PlanetEntity | Create a Planet entity instance. | | tester(testopts?, sdkopts?) | SolardemoSDK | Create a test-mode client instance. |

Static methods

| Method | Returns | Description | | --- | --- | --- | | SolardemoSDK.test(testopts?, sdkopts?) | SolardemoSDK | Create a test-mode client. |

Entity interface

All entities share the same interface.

Methods

| Method | Signature | Description | | --- | --- | --- | | load | load(reqmatch?, ctrl?): Promise<Entity> | Load a single entity by match criteria. | | list | list(reqmatch?, ctrl?): Promise<Entity[]> | List entities matching the criteria. | | create | create(reqdata?, ctrl?): Promise<Entity> | Create a new entity. | | update | update(reqdata?, ctrl?): Promise<Entity> | Update an existing entity. | | remove | remove(reqmatch?, ctrl?): Promise<void> | Remove an entity. | | data | data(data?: Partial<Entity>): Entity | Get or set entity data. | | match | match(match?: Partial<Entity>): Partial<Entity> | Get or set entity match criteria. | | make | make(): Entity | Create a new instance with the same options. | | client | client(): SolardemoSDK | Return the parent SDK client. | | entopts | entopts(): object | Return a copy of the entity options. |

Return values

Entity operations resolve to the entity data directly — there is no result envelope:

  • load, create and update resolve to a single entity object.
  • list resolves to an array of entity objects (iterate it directly; there is no .data and no .ok).
  • remove resolves to void.

On a failed request these methods throw, so wrap calls in try/catch to handle errors. Only direct() returns the result envelope described below.

DirectResult shape

The direct() method returns:

{
  ok: boolean
  status: number
  headers: object
  data: any
}

On error, ok is false and an err property contains the error.

FetchDef shape

The prepare() method returns:

{
  url: string
  method: string
  headers: Record<string, string>
  body?: any
}

Entities

Moon

| Field | Description | | --- | --- | | diameter | | | id | | | kind | | | name | | | planet_id | |

Operations: create, list, load, remove, update.

API path: /api/planet/{planet_id}/moon

Planet

| Field | Description | | --- | --- | | diameter | | | forbid | | | id | | | kind | | | name | | | ok | | | start | | | state | | | stop | | | why | |

Operations: create, list, load, remove, update.

API path: /api/planet/{planet_id}/forbid

Entities

Moon

Create an instance: const moon = client.Moon()

Operations

| Method | Description | | --- | --- | | create(data) | Create a new entity with the given data. | | list(match) | List entities matching the criteria. | | load(match) | Load a single entity by match criteria. | | remove(match) | Remove the matching entity. | | update(data) | Update an existing entity. |

Fields

| Field | Type | Description | | --- | --- | --- | | diameter | number | | | id | string | | | kind | string | | | name | string | | | planet_id | string | |

Example: Load

const moon = await client.Moon().load({ id: 'moon_id', planet_id: 'planet_id' })

Example: List

const moons = await client.Moon().list({ planet_id: "example" })

Example: Create

const moon = await client.Moon().create({
  planet_id: 'example_planet_id',
  diameter: 1,
  id: 'example_id',
  kind: 'example_kind',
  name: 'example_name',
})

Planet

Create an instance: const planet = client.Planet()

Operations

| Method | Description | | --- | --- | | create(data) | Create a new entity with the given data. | | list(match) | List entities matching the criteria. | | load(match) | Load a single entity by match criteria. | | remove(match) | Remove the matching entity. | | update(data) | Update an existing entity. |

Fields

| Field | Type | Description | | --- | --- | --- | | diameter | number | | | forbid | boolean | | | id | string | | | kind | string | | | name | string | | | ok | boolean | | | start | boolean | | | state | string | | | stop | boolean | | | why | string | |

Example: Load

const planet = await client.Planet().load({ id: 'planet_id' })

Example: List

const planets = await client.Planet().list()

Example: Create

const planet = await client.Planet().create({
  diameter: 1,
  id: 'example_id',
  kind: 'example_kind',
  name: 'example_name',
})

Advanced

The sections above cover everyday use. The material below explains the SDK's internals — useful when extending it with custom features, but not needed for normal use.

The operation pipeline

Every entity operation follows a six-stage pipeline. Each stage fires a feature hook before executing:

PrePoint → PreSpec → PreRequest → PreResponse → PreResult → PreDone
  • PrePoint: Resolves which API endpoint to call based on the operation name and entity configuration.
  • PreSpec: Builds the HTTP spec — URL, method, headers, body — from the resolved point and the caller's parameters.
  • PreRequest: Sends the HTTP request. Features can intercept here to replace the transport (as TestFeature does with mocks).
  • PreResponse: Parses the raw HTTP response.
  • PreResult: Extracts the business data from the parsed response.
  • PreDone: Final stage before returning to the caller. Entity state (match, data) is updated here.

If any stage errors, the pipeline short-circuits and the error surfaces to the caller — see Error handling for how that looks in this language.

Features and hooks

Features are the extension mechanism. A feature is an object with a hooks map. Each hook key is a pipeline stage name, and the value is a function that receives the context.

The SDK ships with built-in features:

  • TestFeature: In-memory mock transport for testing without a live server

Features are initialized in order. Hooks fire in the order features were added, so later features can override earlier ones.

Module structure

solardemo/
├── src/
│   ├── SolardemoSDK.ts        # Main SDK class
│   ├── entity/             # Entity implementations
│   ├── feature/            # Built-in features (Base, Test, Log)
│   └── utility/            # Utility functions
├── test/                   # Test suites
└── dist/                   # Compiled output

Import the SDK from the package root:

import { SolardemoSDK } from '@voxgig-sdk/voxgig-solardemo'

Entity state

Entity instances are stateful. After a successful list, the entity stores the returned data and match criteria internally. Subsequent calls on the same instance can rely on this state.

const moon = client.Moon()
await moon.list()

// moon.data() now returns the moon data from the last `list`
// moon.match() returns the last match criteria

Call make() to create a fresh instance with the same configuration but no stored state.

Direct vs entity access

The entity interface handles URL construction, parameter placement, and response parsing automatically. Use it for standard CRUD operations.

The direct method gives full control over the HTTP request. Use it for non-standard endpoints, bulk operations, or any path not modelled as an entity. The prepare method is useful for debugging — it shows exactly what direct would send.

Full Reference

See REFERENCE.md for complete API reference documentation including all method signatures, entity field schemas, and detailed usage examples.