@onyx.dev/onyx-database 2.0.1 → 2.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/README.md CHANGED
@@ -81,16 +81,25 @@ brew install onyx-cli
81
81
 
82
82
  This SDK resolves credentials automatically using the chain **explicit config ➜ environment variables ➜ `ONYX_CONFIG_PATH` file ➜ project config file ➜ home profile** _(Node.js only for file-based sources)_. Call `onyx.init({ databaseId: 'database-id' })` to target a specific database, or omit the `databaseId` to use the default. You can also pass credentials directly via config.
83
83
 
84
+ **Reliability defaults (read this):**
85
+ - **Retries:** GET/query calls auto-retry up to 3 times with Fibonacci backoff starting at 300ms (honors `Retry-After`); writes never retry.
86
+ - **Config cache:** Resolved config is cached per `${databaseId}-${apiKey}` for 5 minutes; tune with `ttl`, clear via `onyx.clearCacheConfig()`.
87
+
84
88
  ### Option A) Environment variables (recommended for production)
85
89
 
86
- Set the following environment variables for your database:
90
+ Set these environment variables for your database:
87
91
 
88
- - `ONYX_DATABASE_ID`
89
- - `ONYX_DATABASE_BASE_URL`
90
- - `ONYX_DATABASE_API_KEY`
91
- - `ONYX_DATABASE_API_SECRET`
92
- - `ONYX_AI_BASE_URL` (optional; defaults to `https://ai.onyx.dev`)
93
- - `ONYX_DEFAULT_MODEL` (optional; used by `db.chat('...')`, defaults to `onyx`)
92
+ | Variable | Purpose | Default when unset |
93
+ | --- | --- | --- |
94
+ | `ONYX_DATABASE_ID` | Target database ID | required |
95
+ | `ONYX_DATABASE_BASE_URL` | Base URL for DB API | `https://api.onyx.dev` |
96
+ | `ONYX_DATABASE_API_KEY` | API key | required |
97
+ | `ONYX_DATABASE_API_SECRET` | API secret | required |
98
+ | `ONYX_AI_BASE_URL` | Base URL for AI endpoints | `https://ai.onyx.dev` |
99
+ | `ONYX_DEFAULT_MODEL` | Model used by `db.chat()` shorthand | `onyx` |
100
+ | `ONYX_CONFIG_PATH` | Path to JSON credentials file (Node only; ignored on edge) | unset (falls back to env ➜ project file ➜ home profile) |
101
+ | `ONYX_DEBUG` | Enable HTTP + config debug logging | off |
102
+ | `ONYX_STREAM_DEBUG` | Enable streaming debug logs | off |
94
103
 
95
104
  ```ts
96
105
  import { onyx } from '@onyx.dev/onyx-database';
@@ -168,15 +177,34 @@ export default {
168
177
  };
169
178
  ```
170
179
 
171
- ### Connection handling
180
+ ### Connection & config caching
172
181
 
173
182
  Calling `onyx.init()` returns a lightweight client. Configuration is resolved once
174
- and cached for 5 minutes to avoid repeated credential lookups (override with
175
- `ttl` or reset via `onyx.clearCacheConfig()`). Each database instance keeps a
176
- single internal `HttpClient`. Requests use the runtime's global `fetch`, which
177
- already reuses connections and pools them for keep‑alive. Reuse the returned
178
- `db` for multiple operations; extra SDK‑level connection pooling generally isn't
179
- necessary unless you create many short‑lived clients.
183
+ and cached **per `${databaseId}-${apiKey}` pair** for 5 minutes to avoid repeated
184
+ env/file lookups (override with `ttl` or reset via `onyx.clearCacheConfig()`).
185
+ Each database instance keeps a single internal `HttpClient`. Requests use the
186
+ runtime's global `fetch`, which already reuses connections and pools them for
187
+ keep‑alive. Reuse the returned `db` for multiple operations; extra SDK‑level
188
+ connection pooling generally isn't necessary unless you create many short‑lived
189
+ clients.
190
+
191
+ ### Typed vs untyped init
192
+
193
+ `onyx.init()` is generic. Omit the type for quick scripts; add your generated schema type for full safety.
194
+
195
+ ```ts
196
+ // Untyped: flexible, no compile-time field checks
197
+ const db = onyx.init();
198
+ const user = await db.from('User').findById('abc'); // inferred as any/unknown
199
+ ```
200
+
201
+ ```ts
202
+ // Typed: import generated schema to get autocomplete and validation
203
+ import type { OnyxSchema as Schema } from './onyx/types';
204
+ const db = onyx.init<Schema>();
205
+ const user = await db.from('User').findById('abc'); // inferred as Schema['User']
206
+ // user.emali -> TypeScript error
207
+ ```
180
208
 
181
209
  ---
182
210
 
@@ -1,5 +1,5 @@
1
1
  var name = "@onyx.dev/onyx-database";
2
- var version = "2.0.1";
2
+ var version = "2.1.0";
3
3
 
4
4
  /**
5
5
  * Supported operators for building query criteria.
@@ -1,5 +1,5 @@
1
1
  var name = "@onyx.dev/onyx-database";
2
- var version = "2.0.1";
2
+ var version = "2.1.0";
3
3
 
4
4
  /**
5
5
  * Supported operators for building query criteria.
package/dist/edge.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // package.json
4
4
  var name = "@onyx.dev/onyx-database";
5
- var version = "2.0.1";
5
+ var version = "2.1.0";
6
6
 
7
7
  // src/config/defaults.ts
8
8
  var DEFAULT_BASE_URL = "https://api.onyx.dev";
@@ -1977,20 +1977,38 @@ var AiChatClientImpl = class {
1977
1977
  }
1978
1978
  };
1979
1979
  function createOnyxFacade(resolveConfig2) {
1980
- let cachedCfg = null;
1980
+ const cachedCfgs = /* @__PURE__ */ new Map();
1981
+ const cacheKey = (databaseId, apiKey) => {
1982
+ const id = typeof databaseId === "string" && databaseId.trim() !== "" ? databaseId.trim() : null;
1983
+ const key = typeof apiKey === "string" && apiKey.trim() !== "" ? apiKey.trim() : null;
1984
+ return id && key ? `${id}-${key}` : null;
1985
+ };
1981
1986
  function resolveConfigWithCache(config) {
1982
1987
  const ttl = config?.ttl ?? DEFAULT_CACHE_TTL;
1983
1988
  const now = Date.now();
1984
- if (cachedCfg && cachedCfg.expires > now) {
1985
- return cachedCfg.promise;
1989
+ const hintKey = cacheKey(config?.databaseId, config?.apiKey) ?? "__default__";
1990
+ const existing = cachedCfgs.get(hintKey);
1991
+ if (existing && existing.expires > now) {
1992
+ return existing.promise;
1986
1993
  }
1994
+ if (existing) cachedCfgs.delete(hintKey);
1987
1995
  const { ttl: _ttl, requestLoggingEnabled: _reqLog, responseLoggingEnabled: _resLog, ...rest } = config ?? {};
1988
- const promise = resolveConfig2(rest);
1989
- cachedCfg = { promise, expires: now + ttl };
1996
+ const expires = now + ttl;
1997
+ const promise = resolveConfig2(rest).then((resolved) => {
1998
+ const resolvedKey = cacheKey(resolved.databaseId, resolved.apiKey) ?? hintKey;
1999
+ const nextExpires = Date.now() + ttl;
2000
+ cachedCfgs.set(resolvedKey, { promise, expires: nextExpires });
2001
+ if (resolvedKey !== hintKey) {
2002
+ const stale = cachedCfgs.get(hintKey);
2003
+ if (stale && stale.promise === promise) cachedCfgs.delete(hintKey);
2004
+ }
2005
+ return resolved;
2006
+ });
2007
+ cachedCfgs.set(hintKey, { promise, expires });
1990
2008
  return promise;
1991
2009
  }
1992
2010
  function clearCacheConfig() {
1993
- cachedCfg = null;
2011
+ cachedCfgs.clear();
1994
2012
  }
1995
2013
  return {
1996
2014
  init(config) {