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

@astroway/sdk

v1.1.0

Published

Official TypeScript SDK for the AstroWay API — natal, synastry, transits, Vedic, Human Design, Tarot, Numerology, AI horoscopes. Type-safe, retry-aware, OpenAPI 3.1 generated.

Downloads

486

Readme

@astroway/sdk

Official TypeScript SDK for the AstroWay API — natal charts, synastry, transits, Vedic dashas, Tarot, Numerology, Human Design, AI horoscopes. Type-safe end to end, generated from the OpenAPI 3.1 spec.

npm version npm downloads license: MIT

700+ endpoints. Path autocomplete + request/response types from your IDE. Built-in retry on 429/5xx with exponential backoff. Stainless-style error hierarchy (AuthenticationError / RateLimitError / BadRequestError / …). Zero-dep at runtime apart from openapi-fetch (~6 KB).


Install

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

Get an API key at https://api.astroway.info/dashboard/sign-up10,000 credits/month free, no card required. Each endpoint costs 5–500 credits depending on what it computes (pricing).


Quick start

import { Astroway } from '@astroway/sdk';

const aw = new Astroway({ apiKey: process.env.ASTROWAY_API_KEY! });

const chart = await aw.chart.compute({
  date: '1990-07-14',
  time: '14:30:00',
  timezoneOffset: 3,
  latitude: 50.45,
  longitude: 30.52,
  houseSystem: 'P',
});

console.log(`ASC: ${chart.angles.asc.sign} ${chart.angles.asc.degree.toFixed(2)}°`);

The SDK exposes 94 typed namespaces / 623 methods auto-generated from the OpenAPI spec — aw.synastry.aspectGrid({...}), aw.bazi.dayMaster({...}), aw.vedic.dashasVimshottariMaha({...}), etc. Path autocomplete and body/response types come straight from your IDE; the { ok, data, error } envelope is unwrapped for you.

Need a raw response or an endpoint not yet covered by namespaces? aw.client is the underlying openapi-fetch instance — aw.client.POST('/chart', { body }) returns the full envelope with the same typing.


Common workflows

Natal chart

const { data } = await aw.client.POST('/chart', {
  body: { date: '1990-07-14', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52 },
});

Synastry

const result = await aw.synastry.compute({
  chart1: { date: '1990-07-14', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52 },
  chart2: { date: '1992-03-22', time: '09:15:00', timezoneOffset: 2, latitude: 48.85, longitude: 2.35 },
});
console.log(`Score: ${result.compatibility.score}/100 (${result.compatibility.label})`);

Transits to natal

const transits = await aw.transits.compute({
  date: '1990-07-14', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52,
  targetDate: '2027-01-01',
});

Vedic Vimshottari Mahadasha

const dasha = await aw.vedic.dashasVimshottariMaha({
  date: '1985-07-22', time: '06:45:00', timezoneOffset: 5.5, latitude: 19.07, longitude: 72.87,
});

Tarot reading

const spread = await aw.tarot.riderWaiteSpread({ spreadType: 'three-card', seed: 42 });

Human Design

const hd = await aw.humanDesign.compute({
  date: '1990-07-14', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52,
});
console.log(`${hd.type} — ${hd.strategy} — ${hd.authority}`);

Error handling

The SDK throws typed subclasses of ApiError. Catch order matters — most specific first:

import { Astroway, ApiError, AuthenticationError, RateLimitError, BadRequestError } from '@astroway/sdk';

try {
  await aw.client.POST('/chart', { body });
} catch (e) {
  if (e instanceof RateLimitError) {
    await new Promise(r => setTimeout(r, (e.retryAfterSeconds ?? 60) * 1000));
    // retry once...
  } else if (e instanceof AuthenticationError) {
    throw new Error('Rotate your AstroWay API key');
  } else if (e instanceof BadRequestError) {
    console.error('Validation failed:', e.body);
  } else if (e instanceof ApiError) {
    console.error(`API error ${e.status} (${e.code}): ${e.message} [request_id=${e.requestId}]`);
  }
  throw e;
}

Full hierarchy: ApiErrorAPIConnectionError (→ APITimeoutError), BadRequestError (400), AuthenticationError (401), PermissionDeniedError (403), NotFoundError (404), UnprocessableEntityError (422), RateLimitError (429), InternalServerError (5xx).


Configuration

const aw = new Astroway({
  apiKey: 'aw_live_...',                  // required
  baseUrl: 'https://api.astroway.info/v1', // override for staging / self-hosted
  authScheme: 'header',                    // 'header' (X-Api-Key, default) or 'bearer' (Authorization: Bearer)
  timeoutMs: 30_000,                       // per-request timeout
  retry: {
    maxRetries: 2,                         // total attempts = 1 + maxRetries
    baseDelayMs: 250,
    maxDelayMs: 30_000,
    retryableStatuses: new Set([408, 409, 429, 500, 502, 503, 504]),
  },
  idempotency: 'auto',                     // 'auto' | 'off' | { generator: () => string }
  fetch: globalThis.fetch,                 // custom fetch implementation
  defaultHeaders: { 'X-Trace-Id': '...' },  // sent on every request
});

The default retry honors Retry-After (seconds or HTTP-date) on 429 responses.

Idempotency

Every POST request gets a fresh UUIDv4 Idempotency-Key header so a network-blip retry never double-bills:

// Auto: every POST gets a new key (default — recommended for credit-metered POSTs).
const aw = new Astroway({ apiKey });

// Override per call when retrying manually:
await aw.synastry.aspectGrid(body, { idempotencyKey: 'replay-abc' });

// Off: caller controls the header (or skips it).
const aw = new Astroway({ apiKey, idempotency: 'off' });

// Custom generator (deterministic test keys, ULIDs, etc):
const aw = new Astroway({ apiKey, idempotency: { generator: () => myUlid() } });

The header fails open — older backend versions ignore it without breaking anything.


Authentication

The SDK supports two equivalent auth schemes — pick whichever your stack prefers:

  • Header (default): X-Api-Key: aw_live_... — same convention as curl/Postman examples.
  • Bearer: Authorization: Bearer aw_live_... — same convention as Stripe/OpenAI/Anthropic SDKs.

Set via authScheme: 'bearer' in the constructor.


TypeScript types

All paths and bodies are derived from the live OpenAPI 3.1 spec at https://api.astroway.info/v1/openapi.json:

import type { paths, components } from '@astroway/sdk';

type ChartBody = paths['/chart']['post']['requestBody']['content']['application/json'];
type ChartResponse = paths['/chart']['post']['responses'][200]['content']['application/json'];

Path autocomplete and body validation work out of the box — no separate @types package needed.


Privacy

The SDK does not phone home. There is no telemetry, no analytics, no usage reporting. The only network traffic the SDK originates is the AstroWay API calls you ask it to make.

Outgoing requests carry two identifying headers so the AstroWay backend can distinguish SDK traffic from raw HTTP traffic in its own logs:

  • User-Agent: astroway-sdk-typescript/<version> (Node/<node-version>)
  • X-Astroway-Channel: sdk-ts

Neither carries a session ID, machine fingerprint, or anything personal.


Stability

Since 1.0.0 (2026-05-11) this package follows strict SemVer:

  • Public exports won't be removed or narrowed in 1.x. Doing so requires a 2.0.0 major bump with a deprecation period covering at least one minor.
  • Tool identifiers stable inside a major version. Any path that ships under 1.x won't be renamed or removed without a deprecation note in CHANGELOG.md and a one-minor parallel-availability window.
  • Input shape stable inside a minor version. Tightening (regex, range, enum) ships in patches; adding a required field requires a minor bump.
  • API version vs SDK version are independent. SDK 1.x follows its own semver; the API itself sits at /v1/. Across v1v2 API any breaking change is announced.
  • Node 22+ required since 1.0.0. Need Node 20? Stay on 0.1.x (will receive critical security patches).

Migration from 0.1.0-alpha.x / 0.1.0-beta.x / 0.1.0-rc.x to 0.1.0

0.1.0 freezes the public surface. No breaking changes vs 0.1.0-rc.2 — every export, namespace, error class, and option added across alphas/betas/RCs ships unchanged. The freeze means future 0.1.x patches will not narrow types or remove exports; that level of change requires a 0.2.0 minor bump.

| Coming from | Action | |---|---| | 0.1.0-alpha.1 / 0.1.0-alpha.2 (manual aw.client.POST(path, body) + retry) | Switch to typed namespaces — aw.chart.compute(body), aw.synastry.aspectGrid(body), etc. The escape hatch (aw.client.POST) still works. | | 0.1.0-alpha.3alpha.6 (no idempotency / errors / helpers) | Pick up automatic Idempotency-Key on POSTs, error.requestId / error.creditsRemaining getters, BirthDateTime.fromCity() helpers in the /helpers subpath. | | 0.1.0-beta.1beta.3 (no streaming / cache) | Use aw.streamSSE('/horoscope/daily', body) for AI streams. Opt into caching via new Astroway({ cache: 'memory' }). | | 0.1.0-rc.1 (no test client) | import { MockAstroway } from '@astroway/sdk/testing' for unit tests. | | 0.1.0-rc.2 (no transport tuning) | Optional: pass dispatcher (undici Agent) and per-call timeoutMs for heavy workloads. |

A type-stability test suite (tests/types.test.ts) using vitest's expectTypeOf locks the surface — any future PR that breaks the public types fails CI before reaching npm.


Links


License

MIT — see LICENSE.