@astroway/sdk 0.1.0-alpha.1 → 0.1.0
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 +350 -0
- package/README.md +59 -31
- package/dist/cache.d.ts +101 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +198 -0
- package/dist/cache.js.map +1 -0
- package/dist/errors.d.ts +30 -6
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +45 -14
- package/dist/errors.js.map +1 -1
- package/dist/helpers/birth-date-time.d.ts +76 -0
- package/dist/helpers/birth-date-time.d.ts.map +1 -0
- package/dist/helpers/birth-date-time.js +112 -0
- package/dist/helpers/birth-date-time.js.map +1 -0
- package/dist/helpers/index.d.ts +3 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +3 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/idempotency.d.ts +10 -0
- package/dist/idempotency.d.ts.map +1 -0
- package/dist/idempotency.js +41 -0
- package/dist/idempotency.js.map +1 -0
- package/dist/index.d.ts +97 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +191 -3
- package/dist/index.js.map +1 -1
- package/dist/namespaces.generated.d.ts +1513 -0
- package/dist/namespaces.generated.d.ts.map +1 -0
- package/dist/namespaces.generated.js +865 -0
- package/dist/namespaces.generated.js.map +1 -0
- package/dist/runtime.d.ts +7 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +31 -0
- package/dist/runtime.js.map +1 -0
- package/dist/stream.d.ts +71 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +199 -0
- package/dist/stream.js.map +1 -0
- package/dist/testing.d.ts +133 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +132 -0
- package/dist/testing.js.map +1 -0
- package/dist/types.generated.d.ts +784 -176
- package/dist/types.generated.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/with-response.d.ts +36 -0
- package/dist/with-response.d.ts.map +1 -0
- package/dist/with-response.js +38 -0
- package/dist/with-response.js.map +1 -0
- package/package.json +19 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,355 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.0 — 2026-05-11
|
|
4
|
+
|
|
5
|
+
**Stable surface commitment.** Public API frozen — every export shipped across alphas / betas / RCs is now part of the `0.1.x` contract. No code changes vs `0.1.0-rc.2` — same `Astroway` constructor, same 103 namespaces / 623 methods, same error hierarchy, same helpers / cache / streaming / mock / dispatcher / timeout surface. Ready to be depended on.
|
|
6
|
+
|
|
7
|
+
### Locked
|
|
8
|
+
|
|
9
|
+
- **Public exports** — every named export from `@astroway/sdk` (root), `@astroway/sdk/errors`, `@astroway/sdk/helpers`, `@astroway/sdk/testing` is part of the surface contract. Removing or narrowing any of them requires a `1.0.0` major bump.
|
|
10
|
+
- **Type signatures** — type-stability test suite (`tests/types.test.ts`) using vitest's `expectTypeOf` asserts:
|
|
11
|
+
- `Astroway` constructor accepts `AstrowayOptions`, instance has all 103 namespaces.
|
|
12
|
+
- `AstrowayOptions` shape (apiKey/baseUrl/authScheme/timeoutMs/idempotency/dispatcher/...).
|
|
13
|
+
- `CallOptions` shape (headers/signal/idempotencyKey/timeoutMs).
|
|
14
|
+
- `IdempotencyMode` union (`'auto' | 'off' | { generator }`).
|
|
15
|
+
- Error subclass tree (every `*Error` extends `ApiError` correctly).
|
|
16
|
+
- `RuntimeInfo`, `CacheOption`, `SSEEvent`, `WithResponseResult` shapes.
|
|
17
|
+
Any future PR that breaks these fails CI before reaching npm.
|
|
18
|
+
- **`package.json` `exports` map** locked at the four documented subpaths (root, `/errors`, `/helpers`, `/testing`).
|
|
19
|
+
- **README "Stability" section** committing to inside-major-version stability for tool identifiers and inside-minor-version stability for input shapes.
|
|
20
|
+
|
|
21
|
+
### Migration
|
|
22
|
+
|
|
23
|
+
No code changes needed — `npm install @astroway/sdk@0.1.0` is a drop-in upgrade from any `0.1.0-rc.x`. Migration table in README covers the path from each pre-release stage.
|
|
24
|
+
|
|
25
|
+
### Verification
|
|
26
|
+
|
|
27
|
+
141 vitest tests pass (128 from rc.2 baseline + 13 new in `tests/types.test.ts`). `tsc --noEmit` clean.
|
|
28
|
+
|
|
29
|
+
## 0.1.0-rc.2 — 2026-05-10
|
|
30
|
+
|
|
31
|
+
Connection pooling + per-request timeout. Heavy users (1000-chart batch synastry, scheduled cron jobs) need control over the underlying transport; one-off slow endpoints need to extend the timeout without raising the global default. Both ship behind opt-in options that don't change the default surface.
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- **`AstrowayOptions.dispatcher`** — pass an undici `Agent`, `Pool`, `MockAgent`, or any object compatible with the Node native fetch `dispatcher` field. Node-only — silently ignored on browser, edge runtimes, Bun, Deno (where `dispatcher` isn't recognized by `fetch`). Typical use:
|
|
36
|
+
```ts
|
|
37
|
+
import { Astroway } from '@astroway/sdk';
|
|
38
|
+
import { Agent } from 'undici';
|
|
39
|
+
const dispatcher = new Agent({
|
|
40
|
+
keepAliveTimeout: 60_000,
|
|
41
|
+
keepAliveMaxTimeout: 600_000,
|
|
42
|
+
connections: 50,
|
|
43
|
+
});
|
|
44
|
+
const aw = new Astroway({ apiKey, dispatcher });
|
|
45
|
+
```
|
|
46
|
+
- **`CallOptions.timeoutMs`** — per-request timeout override on every namespace method. Travels via an internal `x-astroway-timeout-ms` header that the client wrapper strips before sending — the API never sees it. Useful for shortening defaults on fast calls or extending them for one-off heavy queries:
|
|
47
|
+
```ts
|
|
48
|
+
await aw.transits.calendar(body, { timeoutMs: 60_000 }); // longer than default
|
|
49
|
+
await aw.geo.search(body, { timeoutMs: 2_000 }); // bail out early
|
|
50
|
+
```
|
|
51
|
+
- **Long-running default timeout** — when no explicit `timeoutMs` is set, AI gateway and SSE paths (`/ai/*`, `/horoscope/*`, `/interpret/*`, `/mcp/streaming`, `/stream/*`) get 120 s instead of 30 s. Setting `timeoutMs` on the constructor still overrides this for the whole client.
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- `APITimeoutError` now reports the **effective** timeout (after per-call override or path-based default) instead of the constructor default.
|
|
56
|
+
|
|
57
|
+
### Migration from rc.1
|
|
58
|
+
|
|
59
|
+
No breaking changes. New options are purely additive and opt-in.
|
|
60
|
+
|
|
61
|
+
### Verification
|
|
62
|
+
|
|
63
|
+
128 vitest tests pass (122 baseline + 6 new). `tsc --noEmit` clean. Build artifacts unchanged in surface — `dist/index.{js,d.ts}` size delta < 0.5 KB.
|
|
64
|
+
|
|
65
|
+
## 0.1.0-rc.1 — 2026-05-10
|
|
66
|
+
|
|
67
|
+
First **release candidate**. Mock client for testing — drop-in replacement for `Astroway` that records all calls and returns scripted fixtures with zero HTTP traffic. Reference: gap noted in [Speakeasy SDK best practices](https://www.speakeasy.com/blog/sdk-best-practices); inspired by Anthropic's `MockAnthropic` pattern.
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
|
|
71
|
+
- **`@astroway/sdk/testing`** subpath export (tree-shakable):
|
|
72
|
+
```ts
|
|
73
|
+
import { MockAstroway, mockApiError } from '@astroway/sdk/testing';
|
|
74
|
+
|
|
75
|
+
const mock = new MockAstroway();
|
|
76
|
+
mock.respond('POST', '/chart', { angles: { asc: 'Aries' } });
|
|
77
|
+
const r = await mock.chart.compute(body); // returns the fixture
|
|
78
|
+
expect(mock.calls).toHaveLength(1);
|
|
79
|
+
```
|
|
80
|
+
- **`MockAstroway`** class — same namespace surface as `Astroway` (`mock.chart.compute`, `mock.synastry.aspectGrid`, all 103 namespaces), but no network. Calls dispatch through an in-memory fixture table that records every invocation.
|
|
81
|
+
- **`mock.respond(method, path, fixture)`** — register a fixture as a plain value or a factory `(ctx) => value` (where `ctx = { body, callIndex, method, path }`). Async factories supported.
|
|
82
|
+
- **`mock.calls`** — array of `{ method, path, body, headers, resolved }` recorded calls in order. Errors are recorded too (with the error object as `resolved`).
|
|
83
|
+
- **`mock.callsFor(path, method?)`** + **`mock.callCount`** — assertion helpers.
|
|
84
|
+
- **`mock.reset()`** — clear calls and fixtures (use in `beforeEach`).
|
|
85
|
+
- **`mockApiError({ status, code?, message?, retryAfterSeconds?, creditsRemaining? })`** — fixture factory that throws a classified `ApiError` subclass, so `mockApiError({ status: 401, code: 'INVALID_API_KEY' })` resolves into an `AuthenticationError` exactly like a real 401. Also covers `RateLimitError`, `QuotaExceededError`, `CalculationError`, etc.
|
|
86
|
+
- **Helpful error on unmocked routes** — calling an endpoint without a fixture throws `ApiError("MockAstroway: no fixture for POST /chart...")` with the exact `respond()` call to add.
|
|
87
|
+
|
|
88
|
+
### Why a separate subpath
|
|
89
|
+
|
|
90
|
+
`@astroway/sdk/testing` keeps the production bundle clean — bundlers that honour `exports` won't drag the mock harness into your shipped artifact. Vitest / Jest / `node:test` consumers just import from the subpath.
|
|
91
|
+
|
|
92
|
+
### What's NOT mocked
|
|
93
|
+
|
|
94
|
+
- Timeout, retry, idempotency-key generation, runtime detection — those are network-layer concerns and don't make sense without HTTP. To test those, run the real client against a recording server (`nock`, `msw`, or local `api-calc`).
|
|
95
|
+
- Streaming / SSE — `streamSSE()` doesn't go through the mock dispatch yet. Future work.
|
|
96
|
+
|
|
97
|
+
### Migration from beta.3
|
|
98
|
+
|
|
99
|
+
No breaking changes. `MockAstroway` is purely additive.
|
|
100
|
+
|
|
101
|
+
### Verification
|
|
102
|
+
|
|
103
|
+
- 122 vitest tests pass (10 new in `tests/testing.test.ts`).
|
|
104
|
+
- `tsc --noEmit` clean.
|
|
105
|
+
- Coverage: namespace surface dispatch, call recording (method/path/body/headers/resolved), `callsFor` filtering, `reset` clearing, fixture factories (sync + async, body + callIndex propagation, ctx shape), `mockApiError` (401 → `AuthenticationError`, 429 → `RateLimitError` with `retryAfterSeconds`), unmocked routes throw helpful error.
|
|
106
|
+
|
|
107
|
+
## 0.1.0-beta.3 — 2026-05-10
|
|
108
|
+
|
|
109
|
+
Deterministic response cache. Charts are pure functions of `(date, time, lat, lon, tz)` — caching them client-side saves credits and makes dev loops instant. **No competitor does this** — pure differentiator vs Prokerala / Astrologer.
|
|
110
|
+
|
|
111
|
+
### Added
|
|
112
|
+
|
|
113
|
+
- **`cache` constructor option** with four flavours:
|
|
114
|
+
```ts
|
|
115
|
+
new Astroway({ apiKey: '...', cache: 'memory' }); // in-process Map
|
|
116
|
+
new Astroway({ apiKey: '...', cache: 'localStorage' }); // browser/edge Storage
|
|
117
|
+
new Astroway({ apiKey: '...', cache: myStore }); // BYO CacheStore
|
|
118
|
+
new Astroway({ apiKey: '...', cache: { store, ttlMs } }); // store + custom TTL
|
|
119
|
+
```
|
|
120
|
+
- **`MemoryStore`** — `Map`-backed; `get`/`set`/`delete`/`clear`/`size`. Default for `cache: 'memory'`.
|
|
121
|
+
- **`LocalStorageStore`** — wraps `globalThis.localStorage` (or any `Storage`); silently drops on quota / private-mode errors.
|
|
122
|
+
- **`CacheStore` interface** for BYO adapters (Redis via `node-redis`, IndexedDB, etc.). Async `get`/`set` supported.
|
|
123
|
+
- **`buildCacheKey(method, path, body)`** + **`canonicalise(value)`** + **`isDeterministicPath(path)`** + **`CACHE_KEY_PREFIX`** + **`DETERMINISTIC_PATH_PREFIXES` / `NON_DETERMINISTIC_PATH_PREFIXES`** exposed as public exports for users who want to build their own caching layer.
|
|
124
|
+
- **Default policy** — cached: `/chart`, `/synastry`, `/composite`, `/midpoints`, `/aspects`, `/houses`, `/planets`, `/vedic/*`, `/numerology/*`, `/tarot/*`, `/hd/*`, `/human-design/*`, `/dasha/*`. Skipped: `/transits`, `/horoscope`, `/interpret`, `/ai/*`, `/mcp/*`, `/stream/*`, `/now`, `/today`. Unknown endpoints skipped by default.
|
|
125
|
+
|
|
126
|
+
### Cache key
|
|
127
|
+
|
|
128
|
+
`astroway_v1_<sha256(canonical-json(method, path, body))>` — order-insensitive on object keys (`{date, lat}` ≡ `{lat, date}`), order-preserving on lists. SHA-256 via Web Crypto so it works in every runtime (Node 20+, Deno, Bun, browsers, Cloudflare Workers, Vercel Edge). Bumping the `v1` prefix in a future release auto-invalidates stale entries; multi-SDK Redis backends never collide.
|
|
129
|
+
|
|
130
|
+
### Wire details
|
|
131
|
+
|
|
132
|
+
- Cache hit returns a synthetic `Response` with `x-astroway-cache: hit` header so users can distinguish from network responses if needed.
|
|
133
|
+
- Cache write happens **after** response classification, so 4xx/5xx never poison the cache.
|
|
134
|
+
- TTL default is 24h; expired entries are not served (re-fetched + cached fresh).
|
|
135
|
+
- Body parsing is wrapped in try/catch — non-JSON success bodies skip cache rather than crashing.
|
|
136
|
+
|
|
137
|
+
### Migration from beta.2
|
|
138
|
+
|
|
139
|
+
No breaking changes. Existing code keeps working. Adding `cache: 'memory'` to your constructor opts is the only thing you need to change.
|
|
140
|
+
|
|
141
|
+
### Verification
|
|
142
|
+
|
|
143
|
+
- 112 vitest tests pass (21 new in `tests/cache.test.ts`).
|
|
144
|
+
- `tsc --noEmit` clean.
|
|
145
|
+
- Coverage: canonicalise (key-order, list-order, scalars), buildCacheKey (order-insensitive on keys, method/path differentiation, namespace prefix, list-order preserved), isDeterministicPath (allowlist + denylist + unknown denied), MemoryStore round-trip + clear + size, LocalStorageStore quota/exception fault tolerance, end-to-end (deterministic → 1 HTTP call across 2 invocations, cache key order-insensitive end-to-end, non-deterministic skipped, no-cache config behaves like beta.2, expired entries not served, useful error when localStorage requested in non-browser).
|
|
146
|
+
|
|
147
|
+
## 0.1.0-beta.2 — 2026-05-10
|
|
148
|
+
|
|
149
|
+
Streaming for AI endpoints (`/horoscope/daily`, `/interpret/*`, `/mcp/streaming`). The shape mirrors Anthropic's `MessageStream` and OpenAI's `client.chat.completions.create({stream: true})` — `for await` over normalised chunks.
|
|
150
|
+
|
|
151
|
+
### Added
|
|
152
|
+
|
|
153
|
+
- **`aw.streamSSE(path, body?, options?)`** — async iterable of normalised stream chunks:
|
|
154
|
+
```ts
|
|
155
|
+
for await (const chunk of aw.streamSSE('/horoscope/daily', { date: '2026-05-10' })) {
|
|
156
|
+
if (chunk.type === 'text_delta') process.stdout.write(chunk.text);
|
|
157
|
+
if (chunk.type === 'done') break;
|
|
158
|
+
if (chunk.type === 'error') throw new Error(chunk.message);
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
Named `streamSSE` rather than `stream` because `/stream/*` is already a namespace for synchronous calc endpoints (`stream.positions`, `stream.ingress`, ...).
|
|
162
|
+
- **`StreamChunk`** discriminated union: `text_delta` (with `.text`), `done`, `error` (with `.message` + optional `.code`), `event` (passthrough for unknown event names so server-side additions don't break user code).
|
|
163
|
+
- **`SSEEvent` + `parseSSEStream(response)`** — lower-level wire parser for users who need direct access to the SSE event stream (raw `event` / `data` / `id` / `retry` fields). Exposed as a public export.
|
|
164
|
+
- **`normaliseStreamChunk(event)`** — turns a raw `SSEEvent` into a `StreamChunk` with discriminated `type`.
|
|
165
|
+
- **HTTP errors before the stream are classified normally** — a 401 hits `AuthenticationError`, 429 hits `RateLimitError`, etc. The stream throws synchronously on the first iteration if the server returned a non-2xx.
|
|
166
|
+
- **Idempotency-Key auto-attaches on POST streams** — a network blip + reconnect with the same key replays the same generation when the backend supports it; fails open otherwise. Override per-call via `options.idempotencyKey`.
|
|
167
|
+
- **`AbortSignal` honoured** — `aw.streamSSE(path, body, { signal: controller.signal })` cancels the stream mid-flight.
|
|
168
|
+
|
|
169
|
+
### Wire format
|
|
170
|
+
|
|
171
|
+
Standard [HTML5 SSE spec](https://html.spec.whatwg.org/multipage/server-sent-events.html). Multi-line `data:` is concatenated with `\n`. JSON-shaped data is auto-decoded. Comments (`:`-prefixed lines) and unknown fields are silently skipped. CRLF line endings supported.
|
|
172
|
+
|
|
173
|
+
Known event names normalised to `StreamChunk` types:
|
|
174
|
+
- `text_delta` (`{ text: "..." }` or string) → `{ type: 'text_delta', text }`
|
|
175
|
+
- `done` / `end` / `message_stop` → `{ type: 'done' }`
|
|
176
|
+
- `error` → `{ type: 'error', message, code? }`
|
|
177
|
+
- everything else → `{ type: 'event', event, data }`
|
|
178
|
+
|
|
179
|
+
### Migration from beta.1
|
|
180
|
+
|
|
181
|
+
No breaking changes. Existing code keeps working. `streamSSE` is additive.
|
|
182
|
+
|
|
183
|
+
### Verification
|
|
184
|
+
|
|
185
|
+
- 91 vitest tests pass (18 new in `tests/stream.test.ts`).
|
|
186
|
+
- `tsc --noEmit` clean.
|
|
187
|
+
- Coverage: SSE wire parser (single event, multi-line `data`, JSON auto-decode, CRLF, comments, `id`/`retry`, multi-event, trailing-newline-missing flush), chunk normalisation (text_delta string + object, done aliases, error code, unknown event passthrough), end-to-end (request shape + headers + auto-idempotency + per-call override + HTTP error classification).
|
|
188
|
+
|
|
189
|
+
## 0.1.0-beta.1 — 2026-05-10
|
|
190
|
+
|
|
191
|
+
First **beta** — official support for non-Node runtimes. Vercel Edge, Cloudflare Workers, Deno, Bun, browser bundlers all work out of the box now. The core code was already runtime-agnostic; this release makes that contract explicit and adds runtime detection for the User-Agent.
|
|
192
|
+
|
|
193
|
+
### Added
|
|
194
|
+
|
|
195
|
+
- **`detectRuntime()`** in `src/runtime.ts` — feature-detects Node / Deno / Bun / Cloudflare Workers (workerd) / Vercel Edge / Browser. Used internally for the User-Agent suffix; exported for users who want to switch behaviour by runtime.
|
|
196
|
+
- **`User-Agent` includes the actual runtime + version**: `astroway-sdk-typescript/0.1.0-beta.1 (node/22.13.0)` on Node, `(workerd/cloudflare)` in Workers, `(deno/2.x)` on Deno, etc. Replaces the previous Node-only string.
|
|
197
|
+
- **`package.json` `exports` map** adds explicit conditions for `browser`, `worker`, `deno`, `bun` — bundlers and edge runtimes pick the right entry without warnings.
|
|
198
|
+
- **`browser` field in `package.json`** (legacy) — webpack/rollup-style bundlers without conditional-export awareness still work.
|
|
199
|
+
|
|
200
|
+
### Verified runtimes
|
|
201
|
+
|
|
202
|
+
- Node 20+ (LTS line)
|
|
203
|
+
- Bun 1.x
|
|
204
|
+
- Deno 1.x / 2.x
|
|
205
|
+
- Cloudflare Workers (workerd) — typed via `navigator.userAgent === 'Cloudflare-Workers'`
|
|
206
|
+
- Vercel Edge Runtime — typed via `globalThis.EdgeRuntime`
|
|
207
|
+
- Browser (modern, ES2022+) — direct `<script type="module">` or via Vite/Webpack
|
|
208
|
+
|
|
209
|
+
The SDK only depends on `globalThis.fetch` + Web Crypto + standard ES2022 features. No `node:fs`, no `Buffer`, no `node-fetch` polyfill. The 700+ generated TypeScript types compile to a single ESM file.
|
|
210
|
+
|
|
211
|
+
### Migration from alpha.6
|
|
212
|
+
|
|
213
|
+
No breaking changes. Existing Node code keeps working. Browser/edge code that previously bundled `@astroway/sdk` should still work — this release just makes the support contract explicit.
|
|
214
|
+
|
|
215
|
+
### Internal
|
|
216
|
+
|
|
217
|
+
- Runtime probe uses safe `typeof` checks for `Bun`, `Deno`, `EdgeRuntime`, `navigator`, `process`, `window` — every branch is a no-op on hosts that don't expose the global.
|
|
218
|
+
- 73 vitest tests pass (2 new — runtime detection shape + User-Agent assembly).
|
|
219
|
+
|
|
220
|
+
## 0.1.0-alpha.6 — 2026-05-10
|
|
221
|
+
|
|
222
|
+
`BirthDateTime` builder for the (date, time, lat, lon, tz) tuple every chart-style endpoint takes. Reduces boilerplate, validates formats up-front, and ships in a tree-shakeable `@astroway/sdk/helpers` subpath so the helper doesn't bloat the core bundle when you don't use it.
|
|
223
|
+
|
|
224
|
+
### Added
|
|
225
|
+
|
|
226
|
+
- **`BirthDateTime`** in `@astroway/sdk/helpers`:
|
|
227
|
+
```ts
|
|
228
|
+
import { BirthDateTime } from '@astroway/sdk/helpers';
|
|
229
|
+
|
|
230
|
+
const birth = BirthDateTime.fromCoordinates({
|
|
231
|
+
date: '1990-07-14', time: '14:30:00',
|
|
232
|
+
latitude: 50.45, longitude: 30.52, timezoneOffset: 3,
|
|
233
|
+
});
|
|
234
|
+
const chart = await aw.chart.compute(birth.toBody());
|
|
235
|
+
```
|
|
236
|
+
- **Three factories:**
|
|
237
|
+
- `BirthDateTime.fromCoordinates({ date, time, latitude, longitude, timezoneOffset })` — explicit canonical wire shape with eager validation.
|
|
238
|
+
- `BirthDateTime.fromDate(date, geo)` — accepts a JS `Date` (split into `YYYY-MM-DD` + `HH:MM:SS` via UTC components).
|
|
239
|
+
- `BirthDateTime.parse(iso, geo)` — accepts a full ISO 8601 string like `1990-07-14T14:30:00`. Strips trailing `Z` / `+HH:MM`.
|
|
240
|
+
- **`.toBody()`** — wire shape suitable for any chart-style endpoint.
|
|
241
|
+
- **`.toDate()`** — convert back to a JS `Date` (constructed in UTC for determinism).
|
|
242
|
+
- **Tree-shakeable subpath** — `@astroway/sdk/helpers` import path doesn't pull in the helper unless you use it.
|
|
243
|
+
|
|
244
|
+
### Geocoding deferred
|
|
245
|
+
|
|
246
|
+
The roadmap originally bundled `BirthDateTime.fromCity('Kyiv, UA', ...)` here, but the upstream `/v1/geo/search` endpoint isn't shipped yet. `fromCity()` will land alongside that endpoint in api-calc — no SDK release is blocked on it.
|
|
247
|
+
|
|
248
|
+
### Migration from alpha.5
|
|
249
|
+
|
|
250
|
+
No breaking changes. `BirthDateTime` is a new optional helper. Existing code keeps working.
|
|
251
|
+
|
|
252
|
+
### Internal
|
|
253
|
+
|
|
254
|
+
- New `src/helpers/birth-date-time.ts` module.
|
|
255
|
+
- `package.json` `exports` map adds the `./helpers` subpath.
|
|
256
|
+
- 71 vitest tests pass (12 new — fromCoordinates / fromDate / parse / toBody / toDate, plus error paths).
|
|
257
|
+
|
|
258
|
+
## 0.1.0-alpha.5 — 2026-05-10
|
|
259
|
+
|
|
260
|
+
`.withResponse()` for support tickets, plus refined error types for quota exhaustion and calculation failures.
|
|
261
|
+
|
|
262
|
+
### Added
|
|
263
|
+
|
|
264
|
+
- **`ResultPromise<T>`** — Anthropic-style awaitable returned by every namespace method. Default `await aw.synastry.aspectGrid({...})` resolves to `data` (unchanged), and `aw.synastry.aspectGrid({...}).withResponse()` returns `{ data, requestId, creditsRemaining, headers, response }` for support-ticket request IDs and credit dashboards.
|
|
265
|
+
- **`QuotaExceededError`** — distinguishes "you ran out of credits" from "you got rate-limited" (the latter resolves with backoff; the former needs a top-up). Triggered by HTTP 402 or `code: OUT_OF_CREDITS` / `QUOTA_EXCEEDED` / `CREDIT_LIMIT_REACHED` regardless of HTTP status.
|
|
266
|
+
- **`CalculationError`** — for server-side calculation failures (Swiss Ephemeris boundaries, missing datasets, unsupported house systems for high latitudes). Triggered by `code: CALCULATION_ERROR` / `EPHEMERIS_ERROR`.
|
|
267
|
+
- **`creditsRemaining`** field uniform across all `ApiError` subclasses, surfaced from `X-Credits-Remaining` response header.
|
|
268
|
+
- **`retryAfterSeconds`** moved from `RateLimitError` to base `ApiError` — useful on quota-exceeded responses too, not just 429.
|
|
269
|
+
|
|
270
|
+
### Changed
|
|
271
|
+
|
|
272
|
+
- `RateLimitError` no longer has its own init type; uses uniform `ApiErrorInit`. Field `retryAfterSeconds` still works the same way.
|
|
273
|
+
|
|
274
|
+
### Migration from alpha.4
|
|
275
|
+
|
|
276
|
+
No breaking source changes — namespaces still default-resolve to `data`. `RateLimitError.retryAfterSeconds` still exists and behaves identically; the field just lives on the base `ApiError` now (also accessible as `(e as ApiError).retryAfterSeconds`).
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
// Existing code unchanged:
|
|
280
|
+
const result = await aw.synastry.aspectGrid({...});
|
|
281
|
+
|
|
282
|
+
// New: pull request ID + remaining credits for a support ticket
|
|
283
|
+
const { data, requestId, creditsRemaining } = await aw.synastry.aspectGrid({...}).withResponse();
|
|
284
|
+
|
|
285
|
+
// New: catch QuotaExceededError separately from RateLimitError
|
|
286
|
+
try {
|
|
287
|
+
await aw.client.POST('/chart', { body });
|
|
288
|
+
} catch (e) {
|
|
289
|
+
if (e instanceof RateLimitError) await sleep((e.retryAfterSeconds ?? 60) * 1000);
|
|
290
|
+
else if (e instanceof QuotaExceededError) topUpAndAlert(e.creditsRemaining);
|
|
291
|
+
else if (e instanceof CalculationError) skipDate(e.body);
|
|
292
|
+
else throw e;
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Internal
|
|
297
|
+
|
|
298
|
+
- New `src/with-response.ts` module exporting `ResultPromise<T>` and `WithResponseResult<T>`.
|
|
299
|
+
- Generator now wraps namespace return type as `ResultPromise<T>` instead of plain `Promise<T>`.
|
|
300
|
+
- Fetch wrapper reads `X-Credits-Remaining` header on every response.
|
|
301
|
+
- 59 vitest tests pass (8 new — withResponse shape, code-based classification, header surfacing).
|
|
302
|
+
|
|
303
|
+
## 0.1.0-alpha.4 — 2026-05-10
|
|
304
|
+
|
|
305
|
+
Auto-attached `Idempotency-Key` header on every POST. A network blip retry that double-bills is the worst possible UX for a credit-metered API — the SDK now hands the backend a UUIDv4 per request so server-side dedup can short-circuit the duplicate.
|
|
306
|
+
|
|
307
|
+
### Added
|
|
308
|
+
|
|
309
|
+
- **`Idempotency-Key` header on POST by default.** Auto-generated UUIDv4 (RFC 4122) per request. Skipped on GET/HEAD; respected when caller provides their own key.
|
|
310
|
+
- **`idempotency` constructor option:** `'auto'` (default), `'off'` (disable auto-generation), or `{ generator: () => string }` for custom key sources (deterministic test keys, ULIDs, etc).
|
|
311
|
+
- **`idempotencyKey` per-call option** on every namespace method: `aw.synastry.aspectGrid({...}, { idempotencyKey: 'replay-abc' })`. Useful when retrying manually and you want the server to deduplicate.
|
|
312
|
+
- **`generateIdempotencyKey()` exported** for users who want the same key generator without the SDK plumbing.
|
|
313
|
+
- **`IdempotencyMode` type exported** for typed config.
|
|
314
|
+
|
|
315
|
+
### Backend coordination
|
|
316
|
+
|
|
317
|
+
The header fails open — older backend versions or self-hosted deployments without idempotency support simply ignore it. As `api-calc` rolls out idempotency caching, existing SDK users get retry-safe POSTs automatically.
|
|
318
|
+
|
|
319
|
+
### Internal
|
|
320
|
+
|
|
321
|
+
- New `src/idempotency.ts` module: `generateIdempotencyKey`, `shouldAttachIdempotency`, `resolveKeyGenerator`. Web Crypto first, Math.random fallback for old runtimes.
|
|
322
|
+
- 51 vitest tests pass (8 new idempotency tests).
|
|
323
|
+
|
|
324
|
+
### Migration from alpha.3
|
|
325
|
+
|
|
326
|
+
No breaking changes. The header is additive on POSTs; servers that don't recognise it ignore it. To suppress globally: `new Astroway({ idempotency: 'off' })`.
|
|
327
|
+
|
|
328
|
+
## 0.1.0-alpha.3 — 2026-05-10
|
|
329
|
+
|
|
330
|
+
Typed resource namespaces over the openapi-fetch client. `aw.synastry.aspectGrid({...})` instead of `aw.client.POST('/synastry/aspect-grid', { body })` — same typing, friendlier surface, automatic envelope unwrap.
|
|
331
|
+
|
|
332
|
+
### Added
|
|
333
|
+
|
|
334
|
+
- **94 namespaces, 623 methods** auto-generated from the OpenAPI spec. Naming rule: operationId split on `_`/`-`, camelCased; first segment becomes the namespace, the rest the method. Single-segment opIds get `compute` (e.g. `aw.transits.compute({...})`). Multi-segment opIds get the camelCased remainder (e.g. `aw.bazi.dayMaster({...})`, `aw.vedic.dashasVimshottariMaha({...})`).
|
|
335
|
+
- **Auto-unwrap of `{ ok, data, error }` envelope.** Namespace methods return `data` directly; existing code on `aw.client.POST(...)` still gets the full envelope.
|
|
336
|
+
- **`CallOptions` per call:** `headers`, `signal` (`AbortSignal`) for cancellation.
|
|
337
|
+
- **`scripts/generate-namespaces.mjs`** in build pipeline (`npm run generate`).
|
|
338
|
+
|
|
339
|
+
### Unchanged
|
|
340
|
+
|
|
341
|
+
- `aw.client` (raw openapi-fetch) and `aw.request` escape hatches still work.
|
|
342
|
+
- Path-template endpoints (`/webhooks/{id}/test`) are not namespaced — use `aw.client.POST` with `params.path`.
|
|
343
|
+
- All other APIs from alpha.1 are untouched: error hierarchy, retry, identification headers, auth schemes.
|
|
344
|
+
|
|
345
|
+
### Migration from alpha.1
|
|
346
|
+
|
|
347
|
+
No breaking changes. New namespaces are additive properties on the `Astroway` instance. Switch any `aw.client.POST('/synastry/aspect-grid', { body })` call to `aw.synastry.aspectGrid(body)` for cleaner code — both return typed responses, but namespaces unwrap the envelope.
|
|
348
|
+
|
|
349
|
+
## 0.1.0-alpha.2 — 2026-05-09
|
|
350
|
+
|
|
351
|
+
OIDC re-publish for SLSA L3 provenance. No SDK code changes — same surface, same 37 tests. Picks up Sigstore-attested record (the local `0.1.0-alpha.1` lacked provenance because it was published from a developer machine outside CI). `repository.url` normalization (`git+https://…`).
|
|
352
|
+
|
|
3
353
|
## 0.1.0-alpha.1 — 2026-05-09
|
|
4
354
|
|
|
5
355
|
Initial alpha release. Public API may shift before `0.1.0` proper based on integrator feedback.
|
package/README.md
CHANGED
|
@@ -29,22 +29,21 @@ import { Astroway } from '@astroway/sdk';
|
|
|
29
29
|
|
|
30
30
|
const aw = new Astroway({ apiKey: process.env.ASTROWAY_API_KEY! });
|
|
31
31
|
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
houseSystem: 'P',
|
|
40
|
-
},
|
|
32
|
+
const chart = await aw.chart.compute({
|
|
33
|
+
date: '1990-07-14',
|
|
34
|
+
time: '14:30:00',
|
|
35
|
+
timezoneOffset: 3,
|
|
36
|
+
latitude: 50.45,
|
|
37
|
+
longitude: 30.52,
|
|
38
|
+
houseSystem: 'P',
|
|
41
39
|
});
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
console.log(`ASC: ${data.data.angles.asc.sign} ${data.data.angles.asc.degree.toFixed(2)}°`);
|
|
41
|
+
console.log(`ASC: ${chart.angles.asc.sign} ${chart.angles.asc.degree.toFixed(2)}°`);
|
|
45
42
|
```
|
|
46
43
|
|
|
47
|
-
|
|
44
|
+
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.
|
|
45
|
+
|
|
46
|
+
Need a raw response or an endpoint not yet covered by namespaces? `aw.client` is the underlying [`openapi-fetch`](https://openapi-ts.dev/openapi-fetch/) instance — `aw.client.POST('/chart', { body })` returns the full envelope with the same typing.
|
|
48
47
|
|
|
49
48
|
---
|
|
50
49
|
|
|
@@ -61,49 +60,43 @@ const { data } = await aw.client.POST('/chart', {
|
|
|
61
60
|
### Synastry
|
|
62
61
|
|
|
63
62
|
```ts
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
chart2: { date: '1992-03-22', time: '09:15:00', timezoneOffset: 2, latitude: 48.85, longitude: 2.35 },
|
|
68
|
-
},
|
|
63
|
+
const result = await aw.synastry.compute({
|
|
64
|
+
chart1: { date: '1990-07-14', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52 },
|
|
65
|
+
chart2: { date: '1992-03-22', time: '09:15:00', timezoneOffset: 2, latitude: 48.85, longitude: 2.35 },
|
|
69
66
|
});
|
|
70
|
-
console.log(`Score: ${
|
|
67
|
+
console.log(`Score: ${result.compatibility.score}/100 (${result.compatibility.label})`);
|
|
71
68
|
```
|
|
72
69
|
|
|
73
70
|
### Transits to natal
|
|
74
71
|
|
|
75
72
|
```ts
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
targetDate: '2027-01-01',
|
|
80
|
-
},
|
|
73
|
+
const transits = await aw.transits.compute({
|
|
74
|
+
date: '1990-07-14', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52,
|
|
75
|
+
targetDate: '2027-01-01',
|
|
81
76
|
});
|
|
82
77
|
```
|
|
83
78
|
|
|
84
79
|
### Vedic Vimshottari Mahadasha
|
|
85
80
|
|
|
86
81
|
```ts
|
|
87
|
-
const
|
|
88
|
-
|
|
82
|
+
const dasha = await aw.vedic.dashasVimshottariMaha({
|
|
83
|
+
date: '1985-07-22', time: '06:45:00', timezoneOffset: 5.5, latitude: 19.07, longitude: 72.87,
|
|
89
84
|
});
|
|
90
85
|
```
|
|
91
86
|
|
|
92
87
|
### Tarot reading
|
|
93
88
|
|
|
94
89
|
```ts
|
|
95
|
-
const
|
|
96
|
-
body: { spreadType: 'three-card', seed: 42 },
|
|
97
|
-
});
|
|
90
|
+
const spread = await aw.tarot.riderWaiteSpread({ spreadType: 'three-card', seed: 42 });
|
|
98
91
|
```
|
|
99
92
|
|
|
100
93
|
### Human Design
|
|
101
94
|
|
|
102
95
|
```ts
|
|
103
|
-
const
|
|
104
|
-
|
|
96
|
+
const hd = await aw.humanDesign.compute({
|
|
97
|
+
date: '1990-07-14', time: '14:30:00', timezoneOffset: 3, latitude: 50.45, longitude: 30.52,
|
|
105
98
|
});
|
|
106
|
-
console.log(`${
|
|
99
|
+
console.log(`${hd.type} — ${hd.strategy} — ${hd.authority}`);
|
|
107
100
|
```
|
|
108
101
|
|
|
109
102
|
---
|
|
@@ -150,6 +143,7 @@ const aw = new Astroway({
|
|
|
150
143
|
maxDelayMs: 30_000,
|
|
151
144
|
retryableStatuses: new Set([408, 409, 429, 500, 502, 503, 504]),
|
|
152
145
|
},
|
|
146
|
+
idempotency: 'auto', // 'auto' | 'off' | { generator: () => string }
|
|
153
147
|
fetch: globalThis.fetch, // custom fetch implementation
|
|
154
148
|
defaultHeaders: { 'X-Trace-Id': '...' }, // sent on every request
|
|
155
149
|
});
|
|
@@ -157,6 +151,26 @@ const aw = new Astroway({
|
|
|
157
151
|
|
|
158
152
|
The default retry honors `Retry-After` (seconds or HTTP-date) on 429 responses.
|
|
159
153
|
|
|
154
|
+
### Idempotency
|
|
155
|
+
|
|
156
|
+
Every POST request gets a fresh UUIDv4 `Idempotency-Key` header so a network-blip retry never double-bills:
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
// Auto: every POST gets a new key (default — recommended for credit-metered POSTs).
|
|
160
|
+
const aw = new Astroway({ apiKey });
|
|
161
|
+
|
|
162
|
+
// Override per call when retrying manually:
|
|
163
|
+
await aw.synastry.aspectGrid(body, { idempotencyKey: 'replay-abc' });
|
|
164
|
+
|
|
165
|
+
// Off: caller controls the header (or skips it).
|
|
166
|
+
const aw = new Astroway({ apiKey, idempotency: 'off' });
|
|
167
|
+
|
|
168
|
+
// Custom generator (deterministic test keys, ULIDs, etc):
|
|
169
|
+
const aw = new Astroway({ apiKey, idempotency: { generator: () => myUlid() } });
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The header fails open — older backend versions ignore it without breaking anything.
|
|
173
|
+
|
|
160
174
|
---
|
|
161
175
|
|
|
162
176
|
## Authentication
|
|
@@ -204,6 +218,20 @@ Neither carries a session ID, machine fingerprint, or anything personal.
|
|
|
204
218
|
- **Input shape stable inside a minor version.** Tightening (regex, range, enum) ships in patches; adding a required field requires a minor bump.
|
|
205
219
|
- **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
220
|
|
|
221
|
+
### Migration from `0.1.0-alpha.x` / `0.1.0-beta.x` / `0.1.0-rc.x` to `0.1.0`
|
|
222
|
+
|
|
223
|
+
`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.
|
|
224
|
+
|
|
225
|
+
| Coming from | Action |
|
|
226
|
+
|---|---|
|
|
227
|
+
| `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. |
|
|
228
|
+
| `0.1.0-alpha.3` … `alpha.6` (no idempotency / errors / helpers) | Pick up automatic `Idempotency-Key` on POSTs, `error.requestId` / `error.creditsRemaining` getters, `BirthDateTime.fromCity()` helpers in the `/helpers` subpath. |
|
|
229
|
+
| `0.1.0-beta.1` … `beta.3` (no streaming / cache) | Use `aw.streamSSE('/horoscope/daily', body)` for AI streams. Opt into caching via `new Astroway({ cache: 'memory' })`. |
|
|
230
|
+
| `0.1.0-rc.1` (no test client) | `import { MockAstroway } from '@astroway/sdk/testing'` for unit tests. |
|
|
231
|
+
| `0.1.0-rc.2` (no transport tuning) | Optional: pass `dispatcher` (undici Agent) and per-call `timeoutMs` for heavy workloads. |
|
|
232
|
+
|
|
233
|
+
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.
|
|
234
|
+
|
|
207
235
|
---
|
|
208
236
|
|
|
209
237
|
## Links
|
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic response cache.
|
|
3
|
+
*
|
|
4
|
+
* Charts are pure functions of `(date, time, lat, lon, tz)`. Caching them
|
|
5
|
+
* client-side saves credits and makes dev loops instant. None of the public
|
|
6
|
+
* astrology APIs do this — pure differentiator vs Prokerala / Astrologer.
|
|
7
|
+
*
|
|
8
|
+
* ## Storage
|
|
9
|
+
*
|
|
10
|
+
* Pluggable via the {@link CacheStore} interface:
|
|
11
|
+
* - {@link MemoryStore}: in-process Map (default when `cache: 'memory'`)
|
|
12
|
+
* - {@link LocalStorageStore}: browser/edge `Storage` adapter
|
|
13
|
+
* - bring-your-own: pass any object satisfying `CacheStore` (Redis, IndexedDB, etc.)
|
|
14
|
+
*
|
|
15
|
+
* ## Policy
|
|
16
|
+
*
|
|
17
|
+
* Two lists baked into the SDK (override per-call via `{cache: true|false}`):
|
|
18
|
+
*
|
|
19
|
+
* - {@link DETERMINISTIC_PATH_PREFIXES} — pure functions (cached by default)
|
|
20
|
+
* - {@link NON_DETERMINISTIC_PATH_PREFIXES} — time-sensitive (skipped by default)
|
|
21
|
+
*
|
|
22
|
+
* Unknown endpoints are skipped by default. Force per-call when known safe.
|
|
23
|
+
*
|
|
24
|
+
* ## Key
|
|
25
|
+
*
|
|
26
|
+
* `astroway_v1_<sha256(canonical-json(method, path, body))>` — order-insensitive
|
|
27
|
+
* on object keys, order-preserving on lists.
|
|
28
|
+
*/
|
|
29
|
+
export declare const CACHE_KEY_PREFIX = "astroway_v1_";
|
|
30
|
+
export declare const DETERMINISTIC_PATH_PREFIXES: readonly string[];
|
|
31
|
+
export declare const NON_DETERMINISTIC_PATH_PREFIXES: readonly string[];
|
|
32
|
+
/**
|
|
33
|
+
* Whether `path` is safe to cache by default. The denylist wins over the
|
|
34
|
+
* allowlist — `/horoscope/daily` is never cached even if `/horoscope` is on
|
|
35
|
+
* a custom allowlist.
|
|
36
|
+
*/
|
|
37
|
+
export declare function isDeterministicPath(path: string): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Recursively sort object keys; preserve list order. After canonicalisation,
|
|
40
|
+
* two requests with the same logical body but different field order produce
|
|
41
|
+
* identical JSON.
|
|
42
|
+
*/
|
|
43
|
+
export declare function canonicalise(value: unknown): unknown;
|
|
44
|
+
/**
|
|
45
|
+
* Build a cache key for a request. Two semantically-equivalent calls produce
|
|
46
|
+
* the same key — `{ date, lat }` and `{ lat, date }` collide, by design.
|
|
47
|
+
*/
|
|
48
|
+
export declare function buildCacheKey(method: string, path: string, body: unknown): Promise<string>;
|
|
49
|
+
export interface CacheEntry {
|
|
50
|
+
/** Unix milliseconds. */
|
|
51
|
+
expiresAt: number;
|
|
52
|
+
/** Anything that round-trips through JSON. */
|
|
53
|
+
value: unknown;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* BYO storage. Implementations must round-trip `value` losslessly through
|
|
57
|
+
* `JSON.stringify` / `JSON.parse` — no support for `Map`, `Set`, `Date`, etc.
|
|
58
|
+
*/
|
|
59
|
+
export interface CacheStore {
|
|
60
|
+
get(key: string): Promise<CacheEntry | null> | CacheEntry | null;
|
|
61
|
+
set(key: string, entry: CacheEntry): Promise<void> | void;
|
|
62
|
+
delete?(key: string): Promise<void> | void;
|
|
63
|
+
}
|
|
64
|
+
/** In-process `Map`-backed store. Use this for tests and short-lived processes. */
|
|
65
|
+
export declare class MemoryStore implements CacheStore {
|
|
66
|
+
private readonly map;
|
|
67
|
+
get(key: string): CacheEntry | null;
|
|
68
|
+
set(key: string, entry: CacheEntry): void;
|
|
69
|
+
delete(key: string): void;
|
|
70
|
+
/** Discard all entries — useful in test teardown. */
|
|
71
|
+
clear(): void;
|
|
72
|
+
/** Number of cached entries (regardless of expiry). */
|
|
73
|
+
get size(): number;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Browser / edge-runtime `Storage` adapter. Falls back to no-op on
|
|
77
|
+
* quota / private-mode errors.
|
|
78
|
+
*/
|
|
79
|
+
export declare class LocalStorageStore implements CacheStore {
|
|
80
|
+
private readonly storage;
|
|
81
|
+
constructor(storage?: Storage);
|
|
82
|
+
get(key: string): CacheEntry | null;
|
|
83
|
+
set(key: string, entry: CacheEntry): void;
|
|
84
|
+
delete(key: string): void;
|
|
85
|
+
}
|
|
86
|
+
export type CacheOption = false | 'memory' | 'localStorage' | CacheStore | {
|
|
87
|
+
store: CacheStore;
|
|
88
|
+
ttlMs?: number;
|
|
89
|
+
};
|
|
90
|
+
export interface ResolvedCache {
|
|
91
|
+
store: CacheStore;
|
|
92
|
+
defaultTtlMs: number;
|
|
93
|
+
}
|
|
94
|
+
/** Default 24h TTL — long enough that pure-function endpoints feel "permanent". */
|
|
95
|
+
export declare const DEFAULT_CACHE_TTL_MS: number;
|
|
96
|
+
/**
|
|
97
|
+
* Turn the user-facing `cache` option into a `{store, defaultTtlMs}` pair.
|
|
98
|
+
* `undefined` / `false` → no cache.
|
|
99
|
+
*/
|
|
100
|
+
export declare function resolveCacheOption(option: CacheOption | undefined): ResolvedCache | null;
|
|
101
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAE/C,eAAO,MAAM,2BAA2B,EAAE,SAAS,MAAM,EAcxD,CAAC;AAEF,eAAO,MAAM,+BAA+B,EAAE,SAAS,MAAM,EAS5D,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASzD;AAQD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASpD;AAiBD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED,MAAM,WAAW,UAAU;IACzB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,UAAU,GAAG,IAAI,CAAC;IACjE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC5C;AAED,mFAAmF;AACnF,qBAAa,WAAY,YAAW,UAAU;IAC5C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAiC;IACrD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAGnC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI;IAGzC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAGzB,qDAAqD;IACrD,KAAK,IAAI,IAAI;IAGb,uDAAuD;IACvD,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAED;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,UAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,GAAE,OAAiC;IAEvE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IASnC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI;IAOzC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAK1B;AAED,MAAM,MAAM,WAAW,GACnB,KAAK,GACL,QAAQ,GACR,cAAc,GACd,UAAU,GACV;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,mFAAmF;AACnF,eAAO,MAAM,oBAAoB,QAAsB,CAAC;AAExD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,aAAa,GAAG,IAAI,CAgBxF"}
|