@astroway/sdk 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0-alpha.1 — 2026-05-09
4
+
5
+ Initial alpha release. Public API may shift before `0.1.0` proper based on integrator feedback.
6
+
7
+ ### What's in the box
8
+
9
+ - **Type-safe coverage of all 700+ AstroWay API endpoints** — paths, request bodies, and responses are auto-generated from the live OpenAPI 3.1 spec at build time.
10
+ - **`Astroway` client** wrapping [`openapi-fetch`](https://openapi-ts.dev/openapi-fetch/) — `aw.client.POST('/chart', { body })` with full IDE autocomplete.
11
+ - **Two auth schemes:** `X-Api-Key` (default, matches curl/Postman) or `Authorization: Bearer` (matches Stripe/OpenAI convention) via `authScheme: 'bearer'`.
12
+ - **Stainless-template error hierarchy:** `ApiError` → `BadRequestError` / `AuthenticationError` / `PermissionDeniedError` / `NotFoundError` / `UnprocessableEntityError` / `RateLimitError` / `InternalServerError` / `APIConnectionError` (→ `APITimeoutError`).
13
+ - **Built-in retry** with exponential backoff + full jitter on 408 / 409 / 429 / 5xx and connection errors. Default 2 retries; configurable per-request via `retry: { maxRetries: 0 }` to disable. Honors `Retry-After` headers on 429.
14
+ - **Per-request timeout** via `AbortController`, default 30s.
15
+ - **Identification headers** on every request — `User-Agent: astroway-sdk-typescript/<version> (Node/<node-version>)` and `X-Astroway-Channel: sdk-ts`. No telemetry, no phone-home.
16
+ - **37 unit tests** covering error classification, retry semantics, header propagation, and auth scheme switching.
17
+ - **OIDC + npm provenance + SLSA L3 attestation** in publish workflow.
18
+
19
+ ### Internal
20
+
21
+ - ESM-only package. `type: "module"` in `package.json`. Targets Node 20+ (works in browsers too via global `fetch`).
22
+ - TypeScript 5.7, `strict: true`, `exactOptionalPropertyTypes: true`, `noUncheckedIndexedAccess: true`.
23
+ - Zero runtime dependencies apart from `openapi-fetch` (~6 KB minified).
24
+ - Build pipeline: `npm run sync-spec` (fetch live spec) → `npm run generate` (openapi-typescript → `src/types.generated.ts`) → `tsc` (compile to `dist/`).
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AstroWay
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,222 @@
1
+ # @astroway/sdk
2
+
3
+ > Official TypeScript SDK for the [AstroWay API](https://api.astroway.info) — natal charts, synastry, transits, Vedic dashas, Tarot, Numerology, Human Design, AI horoscopes. Type-safe end to end, generated from the OpenAPI 3.1 spec.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@astroway/sdk.svg?style=flat&color=blue)](https://www.npmjs.com/package/@astroway/sdk)
6
+ [![npm downloads](https://img.shields.io/npm/dm/@astroway/sdk.svg?style=flat)](https://www.npmjs.com/package/@astroway/sdk)
7
+ [![license: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
8
+
9
+ 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`](https://openapi-ts.dev/openapi-fetch/) (~6 KB).
10
+
11
+ ---
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ npm install @astroway/sdk
17
+ # or pnpm add @astroway/sdk
18
+ # or yarn add @astroway/sdk
19
+ ```
20
+
21
+ Get an API key at <https://api.astroway.info/dashboard/sign-up> — **10,000 credits/month free**, no card required. Each endpoint costs 5–500 credits depending on what it computes ([pricing](https://api.astroway.info/pricing/)).
22
+
23
+ ---
24
+
25
+ ## Quick start
26
+
27
+ ```ts
28
+ import { Astroway } from '@astroway/sdk';
29
+
30
+ const aw = new Astroway({ apiKey: process.env.ASTROWAY_API_KEY! });
31
+
32
+ const { data, error } = await aw.client.POST('/chart', {
33
+ body: {
34
+ date: '1990-07-14',
35
+ time: '14:30:00',
36
+ timezoneOffset: 3,
37
+ latitude: 50.45,
38
+ longitude: 30.52,
39
+ houseSystem: 'P',
40
+ },
41
+ });
42
+
43
+ if (error) throw error;
44
+ console.log(`ASC: ${data.data.angles.asc.sign} ${data.data.angles.asc.degree.toFixed(2)}°`);
45
+ ```
46
+
47
+ `aw.client` is the typed [`openapi-fetch`](https://openapi-ts.dev/openapi-fetch/) instance — every endpoint, body, and response is autocompleted from the live OpenAPI spec. New endpoints appear on `npm install @astroway/sdk@latest` automatically.
48
+
49
+ ---
50
+
51
+ ## Common workflows
52
+
53
+ ### Natal chart
54
+
55
+ ```ts
56
+ const { data } = await aw.client.POST('/chart', {
57
+ body: { date: '1990-07-14', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52 },
58
+ });
59
+ ```
60
+
61
+ ### Synastry
62
+
63
+ ```ts
64
+ const { data } = await aw.client.POST('/synastry', {
65
+ body: {
66
+ chart1: { date: '1990-07-14', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52 },
67
+ chart2: { date: '1992-03-22', time: '09:15:00', timezoneOffset: 2, latitude: 48.85, longitude: 2.35 },
68
+ },
69
+ });
70
+ console.log(`Score: ${data.data.compatibility.score}/100 (${data.data.compatibility.label})`);
71
+ ```
72
+
73
+ ### Transits to natal
74
+
75
+ ```ts
76
+ const { data } = await aw.client.POST('/transits', {
77
+ body: {
78
+ date: '1990-07-14', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52,
79
+ targetDate: '2027-01-01',
80
+ },
81
+ });
82
+ ```
83
+
84
+ ### Vedic Vimshottari Mahadasha
85
+
86
+ ```ts
87
+ const { data } = await aw.client.POST('/vedic/dashas/vimshottari/maha', {
88
+ body: { date: '1985-07-22', time: '06:45:00', timezoneOffset: 5.5, latitude: 19.07, longitude: 72.87 },
89
+ });
90
+ ```
91
+
92
+ ### Tarot reading
93
+
94
+ ```ts
95
+ const { data } = await aw.client.POST('/tarot/rider-waite/spread', {
96
+ body: { spreadType: 'three-card', seed: 42 },
97
+ });
98
+ ```
99
+
100
+ ### Human Design
101
+
102
+ ```ts
103
+ const { data } = await aw.client.POST('/human-design', {
104
+ body: { date: '1990-07-14', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52 },
105
+ });
106
+ console.log(`${data.data.type} — ${data.data.strategy} — ${data.data.authority}`);
107
+ ```
108
+
109
+ ---
110
+
111
+ ## Error handling
112
+
113
+ The SDK throws typed subclasses of `ApiError`. Catch order matters — most specific first:
114
+
115
+ ```ts
116
+ import { Astroway, ApiError, AuthenticationError, RateLimitError, BadRequestError } from '@astroway/sdk';
117
+
118
+ try {
119
+ await aw.client.POST('/chart', { body });
120
+ } catch (e) {
121
+ if (e instanceof RateLimitError) {
122
+ await new Promise(r => setTimeout(r, (e.retryAfterSeconds ?? 60) * 1000));
123
+ // retry once...
124
+ } else if (e instanceof AuthenticationError) {
125
+ throw new Error('Rotate your AstroWay API key');
126
+ } else if (e instanceof BadRequestError) {
127
+ console.error('Validation failed:', e.body);
128
+ } else if (e instanceof ApiError) {
129
+ console.error(`API error ${e.status} (${e.code}): ${e.message} [request_id=${e.requestId}]`);
130
+ }
131
+ throw e;
132
+ }
133
+ ```
134
+
135
+ Full hierarchy: `ApiError` → `APIConnectionError` (→ `APITimeoutError`), `BadRequestError` (400), `AuthenticationError` (401), `PermissionDeniedError` (403), `NotFoundError` (404), `UnprocessableEntityError` (422), `RateLimitError` (429), `InternalServerError` (5xx).
136
+
137
+ ---
138
+
139
+ ## Configuration
140
+
141
+ ```ts
142
+ const aw = new Astroway({
143
+ apiKey: 'aw_live_...', // required
144
+ baseUrl: 'https://api.astroway.info/v1', // override for staging / self-hosted
145
+ authScheme: 'header', // 'header' (X-Api-Key, default) or 'bearer' (Authorization: Bearer)
146
+ timeoutMs: 30_000, // per-request timeout
147
+ retry: {
148
+ maxRetries: 2, // total attempts = 1 + maxRetries
149
+ baseDelayMs: 250,
150
+ maxDelayMs: 30_000,
151
+ retryableStatuses: new Set([408, 409, 429, 500, 502, 503, 504]),
152
+ },
153
+ fetch: globalThis.fetch, // custom fetch implementation
154
+ defaultHeaders: { 'X-Trace-Id': '...' }, // sent on every request
155
+ });
156
+ ```
157
+
158
+ The default retry honors `Retry-After` (seconds or HTTP-date) on 429 responses.
159
+
160
+ ---
161
+
162
+ ## Authentication
163
+
164
+ The SDK supports two equivalent auth schemes — pick whichever your stack prefers:
165
+
166
+ - **Header (default):** `X-Api-Key: aw_live_...` — same convention as `curl`/Postman examples.
167
+ - **Bearer:** `Authorization: Bearer aw_live_...` — same convention as Stripe/OpenAI/Anthropic SDKs.
168
+
169
+ Set via `authScheme: 'bearer'` in the constructor.
170
+
171
+ ---
172
+
173
+ ## TypeScript types
174
+
175
+ All paths and bodies are derived from the live OpenAPI 3.1 spec at <https://api.astroway.info/v1/openapi.json>:
176
+
177
+ ```ts
178
+ import type { paths, components } from '@astroway/sdk';
179
+
180
+ type ChartBody = paths['/chart']['post']['requestBody']['content']['application/json'];
181
+ type ChartResponse = paths['/chart']['post']['responses'][200]['content']['application/json'];
182
+ ```
183
+
184
+ Path autocomplete and body validation work out of the box — no separate `@types` package needed.
185
+
186
+ ---
187
+
188
+ ## Privacy
189
+
190
+ 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.
191
+
192
+ Outgoing requests carry two identifying headers so the AstroWay backend can distinguish SDK traffic from raw HTTP traffic in its own logs:
193
+
194
+ - `User-Agent: astroway-sdk-typescript/<version> (Node/<node-version>)`
195
+ - `X-Astroway-Channel: sdk-ts`
196
+
197
+ Neither carries a session ID, machine fingerprint, or anything personal.
198
+
199
+ ---
200
+
201
+ ## Stability
202
+
203
+ - **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.
204
+ - **Input shape stable inside a minor version.** Tightening (regex, range, enum) ships in patches; adding a required field requires a minor bump.
205
+ - **API version vs SDK version are independent.** SDK `0.x` follows its own semver; the API itself sits at `/v1/`. Across `v1` → `v2` API any breaking change is announced.
206
+
207
+ ---
208
+
209
+ ## Links
210
+
211
+ - 📦 npm: <https://www.npmjs.com/package/@astroway/sdk>
212
+ - 📘 API docs: <https://api.astroway.info/docs/api/>
213
+ - 🔑 Sign up & dashboard: <https://api.astroway.info/dashboard/>
214
+ - 💰 Pricing: <https://api.astroway.info/pricing/>
215
+ - 🤖 MCP server: [`@astroway/mcp`](https://www.npmjs.com/package/@astroway/mcp)
216
+ - 🌐 Website: <https://astroway.info>
217
+
218
+ ---
219
+
220
+ ## License
221
+
222
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Error hierarchy mirroring the Stainless template (OpenAI / Anthropic / Cloudflare SDKs).
3
+ *
4
+ * Catch order recommendation in user code:
5
+ * try { ... } catch (e) {
6
+ * if (e instanceof RateLimitError) { ... await sleep ... }
7
+ * else if (e instanceof AuthenticationError) { ... rotate key ... }
8
+ * else if (e instanceof ApiError) { ... generic 4xx/5xx ... }
9
+ * else throw e;
10
+ * }
11
+ */
12
+ interface ApiErrorInit {
13
+ status?: number;
14
+ code?: string;
15
+ body?: unknown;
16
+ requestId?: string;
17
+ cause?: unknown;
18
+ }
19
+ export declare class ApiError extends Error {
20
+ readonly name: string;
21
+ /** HTTP status code, when known. `undefined` for connection/timeout. */
22
+ readonly status?: number;
23
+ /** Server-provided error code (e.g. 'INVALID_KEY', 'OUT_OF_CREDITS'). */
24
+ readonly code?: string;
25
+ /** Raw response body (parsed if JSON). */
26
+ readonly body?: unknown;
27
+ /** AstroWay request ID, when present in `X-Request-Id` response header. */
28
+ readonly requestId?: string;
29
+ constructor(message: string, init?: ApiErrorInit);
30
+ }
31
+ export declare class APIConnectionError extends ApiError {
32
+ readonly name: string;
33
+ }
34
+ export declare class APITimeoutError extends APIConnectionError {
35
+ readonly name: string;
36
+ }
37
+ export declare class BadRequestError extends ApiError {
38
+ readonly name: string;
39
+ }
40
+ export declare class AuthenticationError extends ApiError {
41
+ readonly name: string;
42
+ }
43
+ export declare class PermissionDeniedError extends ApiError {
44
+ readonly name: string;
45
+ }
46
+ export declare class NotFoundError extends ApiError {
47
+ readonly name: string;
48
+ }
49
+ export declare class UnprocessableEntityError extends ApiError {
50
+ readonly name: string;
51
+ }
52
+ interface RateLimitErrorInit extends ApiErrorInit {
53
+ retryAfterSeconds?: number;
54
+ }
55
+ export declare class RateLimitError extends ApiError {
56
+ readonly name: string;
57
+ /** Suggested seconds to wait before retrying, from `Retry-After` or server hint. */
58
+ readonly retryAfterSeconds?: number;
59
+ constructor(message: string, init?: RateLimitErrorInit);
60
+ }
61
+ export declare class InternalServerError extends ApiError {
62
+ readonly name: string;
63
+ }
64
+ interface ClassifyArgs {
65
+ status: number;
66
+ code?: string;
67
+ message: string;
68
+ body?: unknown;
69
+ requestId?: string;
70
+ retryAfterSeconds?: number;
71
+ }
72
+ /**
73
+ * Maps an HTTP status + optional server error code to the most specific
74
+ * subclass. Used by the openapi-fetch error path.
75
+ */
76
+ export declare function classifyHttpError(args: ClassifyArgs): ApiError;
77
+ export {};
78
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,UAAU,YAAY;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAkB,IAAI,EAAE,MAAM,CAAc;IAC5C,wEAAwE;IACxE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,yEAAyE;IACzE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;gBAEhB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAOjD;AAED,qBAAa,kBAAmB,SAAQ,QAAQ;IAC9C,SAAkB,IAAI,EAAE,MAAM,CAAwB;CACvD;AAED,qBAAa,eAAgB,SAAQ,kBAAkB;IACrD,SAAkB,IAAI,EAAE,MAAM,CAAqB;CACpD;AAED,qBAAa,eAAgB,SAAQ,QAAQ;IAC3C,SAAkB,IAAI,EAAE,MAAM,CAAqB;CACpD;AAED,qBAAa,mBAAoB,SAAQ,QAAQ;IAC/C,SAAkB,IAAI,EAAE,MAAM,CAAyB;CACxD;AAED,qBAAa,qBAAsB,SAAQ,QAAQ;IACjD,SAAkB,IAAI,EAAE,MAAM,CAA2B;CAC1D;AAED,qBAAa,aAAc,SAAQ,QAAQ;IACzC,SAAkB,IAAI,EAAE,MAAM,CAAmB;CAClD;AAED,qBAAa,wBAAyB,SAAQ,QAAQ;IACpD,SAAkB,IAAI,EAAE,MAAM,CAA8B;CAC7D;AAED,UAAU,kBAAmB,SAAQ,YAAY;IAC/C,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,SAAkB,IAAI,EAAE,MAAM,CAAoB;IAClD,oFAAoF;IACpF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;gBAExB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,kBAAkB;CAIvD;AAED,qBAAa,mBAAoB,SAAQ,QAAQ;IAC/C,SAAkB,IAAI,EAAE,MAAM,CAAyB;CACxD;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAoB9D"}
package/dist/errors.js ADDED
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Error hierarchy mirroring the Stainless template (OpenAI / Anthropic / Cloudflare SDKs).
3
+ *
4
+ * Catch order recommendation in user code:
5
+ * try { ... } catch (e) {
6
+ * if (e instanceof RateLimitError) { ... await sleep ... }
7
+ * else if (e instanceof AuthenticationError) { ... rotate key ... }
8
+ * else if (e instanceof ApiError) { ... generic 4xx/5xx ... }
9
+ * else throw e;
10
+ * }
11
+ */
12
+ export class ApiError extends Error {
13
+ name = 'ApiError';
14
+ /** HTTP status code, when known. `undefined` for connection/timeout. */
15
+ status;
16
+ /** Server-provided error code (e.g. 'INVALID_KEY', 'OUT_OF_CREDITS'). */
17
+ code;
18
+ /** Raw response body (parsed if JSON). */
19
+ body;
20
+ /** AstroWay request ID, when present in `X-Request-Id` response header. */
21
+ requestId;
22
+ constructor(message, init) {
23
+ super(message, init?.cause !== undefined ? { cause: init.cause } : undefined);
24
+ if (init?.status !== undefined)
25
+ this.status = init.status;
26
+ if (init?.code !== undefined)
27
+ this.code = init.code;
28
+ if (init?.body !== undefined)
29
+ this.body = init.body;
30
+ if (init?.requestId !== undefined)
31
+ this.requestId = init.requestId;
32
+ }
33
+ }
34
+ export class APIConnectionError extends ApiError {
35
+ name = 'APIConnectionError';
36
+ }
37
+ export class APITimeoutError extends APIConnectionError {
38
+ name = 'APITimeoutError';
39
+ }
40
+ export class BadRequestError extends ApiError {
41
+ name = 'BadRequestError';
42
+ }
43
+ export class AuthenticationError extends ApiError {
44
+ name = 'AuthenticationError';
45
+ }
46
+ export class PermissionDeniedError extends ApiError {
47
+ name = 'PermissionDeniedError';
48
+ }
49
+ export class NotFoundError extends ApiError {
50
+ name = 'NotFoundError';
51
+ }
52
+ export class UnprocessableEntityError extends ApiError {
53
+ name = 'UnprocessableEntityError';
54
+ }
55
+ export class RateLimitError extends ApiError {
56
+ name = 'RateLimitError';
57
+ /** Suggested seconds to wait before retrying, from `Retry-After` or server hint. */
58
+ retryAfterSeconds;
59
+ constructor(message, init) {
60
+ super(message, init);
61
+ if (init?.retryAfterSeconds !== undefined)
62
+ this.retryAfterSeconds = init.retryAfterSeconds;
63
+ }
64
+ }
65
+ export class InternalServerError extends ApiError {
66
+ name = 'InternalServerError';
67
+ }
68
+ /**
69
+ * Maps an HTTP status + optional server error code to the most specific
70
+ * subclass. Used by the openapi-fetch error path.
71
+ */
72
+ export function classifyHttpError(args) {
73
+ const { status, code, message, body, requestId, retryAfterSeconds } = args;
74
+ const init = { status };
75
+ if (code !== undefined)
76
+ init.code = code;
77
+ if (body !== undefined)
78
+ init.body = body;
79
+ if (requestId !== undefined)
80
+ init.requestId = requestId;
81
+ switch (status) {
82
+ case 400: return new BadRequestError(message, init);
83
+ case 401: return new AuthenticationError(message, init);
84
+ case 403: return new PermissionDeniedError(message, init);
85
+ case 404: return new NotFoundError(message, init);
86
+ case 422: return new UnprocessableEntityError(message, init);
87
+ case 429: {
88
+ const rlInit = { ...init };
89
+ if (retryAfterSeconds !== undefined)
90
+ rlInit.retryAfterSeconds = retryAfterSeconds;
91
+ return new RateLimitError(message, rlInit);
92
+ }
93
+ }
94
+ if (status >= 500)
95
+ return new InternalServerError(message, init);
96
+ return new ApiError(message, init);
97
+ }
98
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @astroway/sdk — Official TypeScript SDK for the AstroWay API.
3
+ *
4
+ * Usage:
5
+ * import { Astroway } from '@astroway/sdk';
6
+ * const aw = new Astroway({ apiKey: process.env.ASTROWAY_API_KEY! });
7
+ * const { data, error } = await aw.POST('/chart', {
8
+ * body: { date: '1990-07-14', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52 },
9
+ * });
10
+ *
11
+ * Types come from the live OpenAPI 3.1 spec at build time. Error semantics
12
+ * mirror Stainless / OpenAI / Cloudflare SDKs — see ./errors.
13
+ */
14
+ import createClient from 'openapi-fetch';
15
+ import type { paths } from './types.generated.js';
16
+ import { type RetryOptions } from './retry.js';
17
+ export * from './errors.js';
18
+ export type { paths, components, operations } from './types.generated.js';
19
+ export interface AstrowayOptions {
20
+ /** API key — `aw_live_...` for production, `aw_test_...` for sandbox. Required. */
21
+ apiKey: string;
22
+ /** Override base URL — useful for staging or self-hosted. Default `https://api.astroway.info/v1`. */
23
+ baseUrl?: string;
24
+ /** Auth scheme. `header` (default) sends `X-Api-Key: <key>`. `bearer` sends `Authorization: Bearer <key>`. */
25
+ authScheme?: 'header' | 'bearer';
26
+ /** Per-request timeout in ms. Default 30_000. */
27
+ timeoutMs?: number;
28
+ /** Retry configuration. Default 2 retries, exp backoff, on 408/409/429/5xx/connection. Set `{ maxRetries: 0 }` to disable. */
29
+ retry?: RetryOptions;
30
+ /** Optional custom `fetch` implementation. Default — global `fetch`. */
31
+ fetch?: typeof globalThis.fetch;
32
+ /** Extra headers added to every request. */
33
+ defaultHeaders?: Record<string, string>;
34
+ }
35
+ /**
36
+ * Type-safe AstroWay client. Methods (`GET`, `POST`, `PUT`, `DELETE`) and
37
+ * paths come straight from `openapi-fetch` — see https://openapi-ts.dev/openapi-fetch/
38
+ * for the full API. Path autocomplete and request/response typing work out
39
+ * of the box.
40
+ */
41
+ export type AstrowayClient = ReturnType<typeof createClient<paths>>;
42
+ /**
43
+ * Creates a new AstroWay client. Equivalent to `new Astroway(...)` for
44
+ * users who prefer the factory style.
45
+ */
46
+ export declare function createAstroway(options: AstrowayOptions): AstrowayClient;
47
+ export declare class Astroway {
48
+ /** The underlying typed openapi-fetch client. */
49
+ readonly client: AstrowayClient;
50
+ readonly options: Required<Omit<AstrowayOptions, 'fetch' | 'defaultHeaders' | 'retry'>> & {
51
+ fetch: typeof globalThis.fetch;
52
+ defaultHeaders: Record<string, string>;
53
+ retry: RetryOptions;
54
+ };
55
+ constructor(options: AstrowayOptions);
56
+ }
57
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,YAAoC,MAAM,eAAe,CAAC;AACjE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAOlD,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/D,cAAc,aAAa,CAAC;AAC5B,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAI1E,MAAM,WAAW,eAAe;IAC9B,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,qGAAqG;IACrG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8GAA8G;IAC9G,UAAU,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACjC,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8HAA8H;IAC9H,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,wEAAwE;IACxE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AAEpE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,CAEvE;AAED,qBAAa,QAAQ;IACnB,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,gBAAgB,GAAG,OAAO,CAAC,CAAC,GAAG;QACxF,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;QAC/B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACvC,KAAK,EAAE,YAAY,CAAC;KACrB,CAAC;gBAEU,OAAO,EAAE,eAAe;CAkErC"}
package/dist/index.js ADDED
@@ -0,0 +1,122 @@
1
+ /**
2
+ * @astroway/sdk — Official TypeScript SDK for the AstroWay API.
3
+ *
4
+ * Usage:
5
+ * import { Astroway } from '@astroway/sdk';
6
+ * const aw = new Astroway({ apiKey: process.env.ASTROWAY_API_KEY! });
7
+ * const { data, error } = await aw.POST('/chart', {
8
+ * body: { date: '1990-07-14', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52 },
9
+ * });
10
+ *
11
+ * Types come from the live OpenAPI 3.1 spec at build time. Error semantics
12
+ * mirror Stainless / OpenAI / Cloudflare SDKs — see ./errors.
13
+ */
14
+ import createClient from 'openapi-fetch';
15
+ import { ApiError, APIConnectionError, APITimeoutError, classifyHttpError, } from './errors.js';
16
+ import { fetchWithRetry } from './retry.js';
17
+ import { SDK_VERSION } from './version.js';
18
+ export * from './errors.js';
19
+ const DEFAULT_BASE_URL = 'https://api.astroway.info/v1';
20
+ /**
21
+ * Creates a new AstroWay client. Equivalent to `new Astroway(...)` for
22
+ * users who prefer the factory style.
23
+ */
24
+ export function createAstroway(options) {
25
+ return new Astroway(options).client;
26
+ }
27
+ export class Astroway {
28
+ /** The underlying typed openapi-fetch client. */
29
+ client;
30
+ options;
31
+ constructor(options) {
32
+ if (!options.apiKey) {
33
+ throw new ApiError('AstroWay SDK: apiKey is required. Get one at https://api.astroway.info/dashboard/sign-up — 10,000 credits/month free.');
34
+ }
35
+ const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
36
+ const authScheme = options.authScheme ?? 'header';
37
+ const timeoutMs = options.timeoutMs ?? 30_000;
38
+ const retry = options.retry ?? {};
39
+ const fetchImpl = options.fetch ?? globalThis.fetch;
40
+ const defaultHeaders = options.defaultHeaders ?? {};
41
+ this.options = {
42
+ apiKey: options.apiKey,
43
+ baseUrl,
44
+ authScheme,
45
+ timeoutMs,
46
+ retry,
47
+ fetch: fetchImpl,
48
+ defaultHeaders,
49
+ };
50
+ const authHeaders = authScheme === 'bearer'
51
+ ? { Authorization: `Bearer ${options.apiKey}` }
52
+ : { 'X-Api-Key': options.apiKey };
53
+ const userAgent = `astroway-sdk-typescript/${SDK_VERSION} (Node/${typeof process !== 'undefined' ? process.versions.node : 'unknown'})`;
54
+ const clientOpts = {
55
+ baseUrl,
56
+ headers: {
57
+ ...authHeaders,
58
+ 'User-Agent': userAgent,
59
+ 'X-Astroway-Channel': 'sdk-ts',
60
+ ...defaultHeaders,
61
+ },
62
+ fetch: async (input) => {
63
+ const controller = new AbortController();
64
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
65
+ const reqInit = { signal: controller.signal };
66
+ try {
67
+ const res = await fetchWithRetry(() => fetchImpl(input, reqInit), retry);
68
+ await throwOnApiError(res);
69
+ return res;
70
+ }
71
+ catch (e) {
72
+ if (e instanceof ApiError)
73
+ throw e;
74
+ if (e?.name === 'AbortError') {
75
+ throw new APITimeoutError(`Request to ${input.url} timed out after ${timeoutMs}ms`, { cause: e });
76
+ }
77
+ throw new APIConnectionError(`Network error calling ${input.url}: ${e?.message ?? 'unknown'}. Check your connection or baseUrl.`, { cause: e });
78
+ }
79
+ finally {
80
+ clearTimeout(timer);
81
+ }
82
+ },
83
+ };
84
+ this.client = createClient(clientOpts);
85
+ }
86
+ }
87
+ /**
88
+ * Re-throws non-2xx responses as the appropriate error subclass.
89
+ * Body is consumed once and re-attached as a Response clone so the caller
90
+ * still sees `.json()`/`.text()` semantics if it inspects the original.
91
+ */
92
+ async function throwOnApiError(res) {
93
+ if (res.ok)
94
+ return;
95
+ const requestId = res.headers.get('x-request-id') ?? undefined;
96
+ const retryAfter = res.headers.get('retry-after');
97
+ const retryAfterSeconds = retryAfter && !Number.isNaN(Number(retryAfter)) ? Number(retryAfter) : undefined;
98
+ let body;
99
+ let code;
100
+ let message = `${res.status} ${res.statusText}`;
101
+ try {
102
+ const cloned = res.clone();
103
+ body = await cloned.json();
104
+ const err = body.error;
105
+ if (err?.code)
106
+ code = err.code;
107
+ if (err?.message)
108
+ message = err.message;
109
+ }
110
+ catch {
111
+ // Body wasn't JSON — keep the status-line message.
112
+ }
113
+ throw classifyHttpError({
114
+ status: res.status,
115
+ ...(code !== undefined ? { code } : {}),
116
+ message,
117
+ body,
118
+ ...(requestId !== undefined ? { requestId } : {}),
119
+ ...(retryAfterSeconds !== undefined ? { retryAfterSeconds } : {}),
120
+ });
121
+ }
122
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}