@better-i18n/sdk 2.0.1 → 3.0.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
@@ -8,8 +8,9 @@ Content SDK for [Better i18n](https://better-i18n.com). A lightweight, typed cli
8
8
  - 🔒 **Type-Safe** — Full TypeScript types with generic custom fields
9
9
  - 🌍 **Language-Aware** — Fetch localized content by language code
10
10
  - 📄 **Pagination Built-in** — Paginated listing with total count and `hasMore`
11
- - 🔍 **Filtering & Sorting** — Filter by status, sort by date or title
12
- - ⚡ **Lightweight** — Thin wrapper over REST API
11
+ - 🔍 **Filtering, Search & Sorting** — Filter by status, custom fields, full-text search
12
+ - ⚡ **Chainable Query Builder** — Supabase-style `from().eq().order().limit()` API
13
+ - 🛡️ **Error-Safe** — `{ data, error }` pattern — never throws on API errors
13
14
 
14
15
  ## Installation
15
16
 
@@ -27,78 +28,144 @@ const client = createClient({
27
28
  apiKey: process.env.BETTER_I18N_API_KEY!,
28
29
  });
29
30
 
30
- // List content models
31
- const models = await client.getModels();
32
-
33
- // List published blog posts
34
- const { items, total, hasMore } = await client.getEntries("blog-posts", {
35
- status: "published",
36
- sort: "publishedAt",
37
- order: "desc",
38
- language: "en",
39
- limit: 10,
40
- });
41
-
42
- // Get a single entry with localized content
43
- const post = await client.getEntry("blog-posts", "hello-world", {
44
- language: "fr",
45
- });
46
- console.log(post.title, post.body);
31
+ // List published blog posts (chainable API)
32
+ const { data: posts, error, total, hasMore } = await client
33
+ .from("blog-posts")
34
+ .eq("status", "published")
35
+ .order("publishedAt", { ascending: false })
36
+ .limit(10)
37
+ .language("en");
38
+
39
+ // Get a single entry
40
+ const { data: post, error: postError } = await client
41
+ .from("blog-posts")
42
+ .expand("author", "category")
43
+ .language("fr")
44
+ .single("hello-world");
45
+
46
+ if (post) {
47
+ console.log(post.title, post.body);
48
+ }
47
49
  ```
48
50
 
49
- ## API
51
+ ## Chainable Query Builder
50
52
 
51
- | Method | Description |
52
- | --- | --- |
53
- | `getModels()` | List all content models with entry counts |
54
- | `getEntries(modelSlug, options?)` | Paginated list of entries for a model |
55
- | `getEntry(modelSlug, entrySlug, options?)` | Full content entry with all fields |
53
+ The `from()` method returns an immutable, chainable query builder — inspired by Supabase JS.
56
54
 
57
- ### `getEntries` Options
55
+ Every chain method returns a **new** builder instance, so you can safely reuse base queries:
58
56
 
59
- | Option | Type | Default | Description |
60
- | --- | --- | --- | --- |
61
- | `language` | `string` | source language | Language code for localized content |
62
- | `status` | `"draft" \| "published" \| "archived"` | all | Filter by entry status |
63
- | `sort` | `"publishedAt" \| "createdAt" \| "updatedAt" \| "title"` | `"updatedAt"` | Sort field |
64
- | `order` | `"asc" \| "desc"` | `"desc"` | Sort direction |
65
- | `page` | `number` | `1` | Page number (1-based) |
66
- | `limit` | `number` | `50` | Entries per page (1-100) |
67
- | `fields` | `string[]` | all fields | Fields to include in response |
68
- | `expand` | `string[]` | none | Relation field names to expand |
57
+ ```typescript
58
+ const publishedPosts = client
59
+ .from("blog-posts")
60
+ .eq("status", "published");
61
+
62
+ // Reuse the base query
63
+ const recentPosts = await publishedPosts
64
+ .order("publishedAt", { ascending: false })
65
+ .limit(5);
66
+
67
+ const popularPosts = await publishedPosts
68
+ .order("title", { ascending: true })
69
+ .limit(10);
70
+ ```
69
71
 
70
- ### `getEntry` Options
72
+ ### Chain Methods
71
73
 
72
- | Option | Type | Default | Description |
73
- | --- | --- | --- | --- |
74
- | `language` | `string` | source language | Language code for localized content |
75
- | `fields` | `string[]` | all fields | Fields to include in response |
76
- | `expand` | `string[]` | none | Relation field names to expand |
74
+ | Method | Description | Example |
75
+ | --- | --- | --- |
76
+ | `.select(...fields)` | Choose which fields to include | `.select("title", "body")` |
77
+ | `.eq(field, value)` | Filter by built-in field (status, etc.) | `.eq("status", "published")` |
78
+ | `.filter(field, value)` | Filter by custom field value | `.filter("category", "engineering")` |
79
+ | `.search(term)` | Full-text search on entry titles | `.search("kubernetes")` |
80
+ | `.language(code)` | Set language for localized content | `.language("fr")` |
81
+ | `.order(field, opts?)` | Set sort field and direction | `.order("publishedAt", { ascending: false })` |
82
+ | `.limit(n)` | Max entries per page (1-100) | `.limit(10)` |
83
+ | `.page(n)` | Page number (1-based) | `.page(2)` |
84
+ | `.expand(...fields)` | Expand relation fields | `.expand("author", "category")` |
85
+
86
+ ### Terminal Methods
87
+
88
+ | Method | Description | Returns |
89
+ | --- | --- | --- |
90
+ | `.single(slug)` | Fetch a single entry by slug | `{ data, error }` |
91
+ | `await builder` | Execute list query (thenable) | `{ data, error, total, hasMore }` |
77
92
 
78
93
  ### Response Types
79
94
 
80
- **`getEntries` returns `PaginatedResponse<ContentEntryListItem>`:**
95
+ **List query returns `QueryResult<T[]>`:**
81
96
 
82
97
  ```typescript
83
98
  {
84
- items: ContentEntryListItem[]; // id, slug, title, publishedAt, customFields, relations?
85
- total: number; // total matching entries
86
- hasMore: boolean; // more pages available
99
+ data: ContentEntryListItem[] | null; // null on error
100
+ error: Error | null; // null on success
101
+ total: number; // total matching entries
102
+ hasMore: boolean; // more pages available
87
103
  }
88
104
  ```
89
105
 
90
- **`getEntry` returns `ContentEntry<CF>`:**
106
+ **Single query returns `SingleQueryResult<ContentEntry>`:**
91
107
 
92
108
  ```typescript
93
109
  {
94
- id, slug, status, publishedAt, sourceLanguage, availableLanguages,
95
- title, body, customFields, relations?
110
+ data: ContentEntry | null; // null on error
111
+ error: Error | null; // null on success
96
112
  }
97
113
  ```
98
114
 
115
+ ### Examples
116
+
117
+ ```typescript
118
+ // Full-text search
119
+ const { data: results } = await client
120
+ .from("blog-posts")
121
+ .search("kubernetes")
122
+ .limit(5);
123
+
124
+ // Custom field filtering
125
+ const { data: techPosts } = await client
126
+ .from("blog-posts")
127
+ .filter("category", "engineering")
128
+ .eq("status", "published")
129
+ .language("en");
130
+
131
+ // Select specific fields + expand relations
132
+ const { data: entries } = await client
133
+ .from("blog-posts")
134
+ .select("title", "body")
135
+ .expand("author")
136
+ .order("publishedAt", { ascending: false });
137
+
138
+ // Pagination
139
+ const { data: page2, hasMore } = await client
140
+ .from("blog-posts")
141
+ .eq("status", "published")
142
+ .limit(20)
143
+ .page(2);
144
+ ```
145
+
146
+ ## Error Handling
147
+
148
+ The chainable API uses the `{ data, error }` pattern — it never throws on API errors:
149
+
150
+ ```typescript
151
+ const { data, error } = await client
152
+ .from("blog-posts")
153
+ .eq("status", "published")
154
+ .limit(10);
155
+
156
+ if (error) {
157
+ console.error("Failed to fetch posts:", error.message);
158
+ return;
159
+ }
160
+
161
+ // data is guaranteed non-null here
162
+ console.log(`Found ${data.length} posts`);
163
+ ```
164
+
99
165
  ## Typed Custom Fields
100
166
 
101
- Use the generic type parameter for type-safe custom fields:
167
+ Custom fields are returned flat directly on the entry object (no `customFields` wrapper).
168
+ Use the generic type parameter for type-safe access:
102
169
 
103
170
  ```typescript
104
171
  interface BlogFields {
@@ -106,37 +173,65 @@ interface BlogFields {
106
173
  category: string | null;
107
174
  }
108
175
 
109
- const post = await client.getEntry<BlogFields>("blog-posts", "hello-world");
110
- post.customFields.readingTime; // string | null (typed!)
111
- post.customFields.category; // string | null (typed!)
176
+ const { data: post } = await client
177
+ .from("blog-posts")
178
+ .single<BlogFields>("hello-world");
179
+
180
+ if (post) {
181
+ post.readingTime; // string | null (typed!)
182
+ post.category; // string | null (typed!)
183
+ }
112
184
  ```
113
185
 
114
186
  ## Expanding Relations
115
187
 
116
- Use `expand` to resolve related entries in a single request. Expanded relations are available under the `relations` key.
188
+ Use `expand` to resolve related entries in a single request:
117
189
 
118
190
  ```typescript
119
- const { items } = await client.getEntries("blog-posts", {
120
- expand: ["author", "category"],
121
- });
122
-
123
- // Access expanded relation fields
124
- items[0].relations?.author?.title; // "Alice Johnson"
125
- items[0].relations?.author?.modelSlug; // "users"
126
- items[0].relations?.author?.customFields?.avatar; // "https://..."
127
- items[0].relations?.category?.title; // "Engineering"
191
+ const { data: posts } = await client
192
+ .from("blog-posts")
193
+ .expand("author", "category")
194
+ .eq("status", "published");
195
+
196
+ if (posts) {
197
+ posts[0].relations?.author?.title; // "Alice Johnson"
198
+ posts[0].relations?.author?.avatar; // "https://..."
199
+ posts[0].relations?.category?.title; // "Engineering"
200
+ }
128
201
  ```
129
202
 
130
- Each expanded relation is a `RelationValue` object:
203
+ Each expanded relation is a `RelationValue` object with custom fields spread directly:
131
204
 
132
205
  ```typescript
133
- interface RelationValue {
206
+ type RelationValue = {
134
207
  id: string;
135
208
  slug: string;
136
209
  title: string;
137
210
  modelSlug: string;
138
- customFields?: Record<string, string | null>;
139
- }
211
+ } & Record<string, string | null>;
212
+ ```
213
+
214
+ ## Legacy API
215
+
216
+ The method-based API is still available for backward compatibility:
217
+
218
+ ```typescript
219
+ // List content models
220
+ const models = await client.getModels();
221
+
222
+ // List entries (throws on error)
223
+ const { items, total, hasMore } = await client.getEntries("blog-posts", {
224
+ status: "published",
225
+ sort: "publishedAt",
226
+ order: "desc",
227
+ language: "en",
228
+ limit: 10,
229
+ });
230
+
231
+ // Get single entry (throws on error)
232
+ const post = await client.getEntry("blog-posts", "hello-world", {
233
+ language: "fr",
234
+ });
140
235
  ```
141
236
 
142
237
  ## Configuration
@@ -146,6 +241,7 @@ interface RelationValue {
146
241
  | `project` | Yes | Project identifier in `org/project` format (e.g., `"acme/web-app"`) |
147
242
  | `apiKey` | Yes | API key from [dashboard](https://dash.better-i18n.com) |
148
243
  | `apiBase` | No | API base URL (default: `https://content.better-i18n.com`) |
244
+ | `debug` | No | Enable debug logging for request/response inspection |
149
245
 
150
246
  ## Documentation
151
247
 
package/dist/client.d.ts CHANGED
@@ -2,8 +2,8 @@ import type { ClientConfig, ContentClient } from "./types.js";
2
2
  /**
3
3
  * Creates a Better i18n content client.
4
4
  *
5
- * Fetches content models and entries from the REST API.
6
- * Requires an API key for authentication.
5
+ * Supports both a **Supabase-style chainable API** (`from()`) and the
6
+ * legacy method-based API (`getEntries`, `getEntry`, `getModels`).
7
7
  *
8
8
  * @example
9
9
  * ```typescript
@@ -12,9 +12,22 @@ import type { ClientConfig, ContentClient } from "./types.js";
12
12
  * apiKey: "bi18n_...",
13
13
  * });
14
14
  *
15
+ * // Chainable API (recommended)
16
+ * const { data, error } = await client
17
+ * .from("blog-posts")
18
+ * .eq("status", "published")
19
+ * .order("publishedAt", { ascending: false })
20
+ * .limit(10);
21
+ *
22
+ * // Single entry
23
+ * const { data: post } = await client
24
+ * .from("blog-posts")
25
+ * .language("fr")
26
+ * .single("hello-world");
27
+ *
28
+ * // Legacy API (still works)
15
29
  * const models = await client.getModels();
16
30
  * const posts = await client.getEntries("blog-posts", { language: "fr" });
17
- * const post = await client.getEntry("blog-posts", "hello-world");
18
31
  * ```
19
32
  */
20
33
  export declare function createClient(config: ClientConfig): ContentClient;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAK9D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,aAAa,CAoBhE"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAM9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,aAAa,CA6BhE"}
package/dist/client.js CHANGED
@@ -1,10 +1,11 @@
1
- import { createContentAPIClient } from "./content-api.js";
1
+ import { createHttpClient } from "./http.js";
2
+ import { ContentQueryBuilder } from "./query-builder.js";
2
3
  const DEFAULT_API_BASE = "https://content.better-i18n.com";
3
4
  /**
4
5
  * Creates a Better i18n content client.
5
6
  *
6
- * Fetches content models and entries from the REST API.
7
- * Requires an API key for authentication.
7
+ * Supports both a **Supabase-style chainable API** (`from()`) and the
8
+ * legacy method-based API (`getEntries`, `getEntry`, `getModels`).
8
9
  *
9
10
  * @example
10
11
  * ```typescript
@@ -13,9 +14,22 @@ const DEFAULT_API_BASE = "https://content.better-i18n.com";
13
14
  * apiKey: "bi18n_...",
14
15
  * });
15
16
  *
17
+ * // Chainable API (recommended)
18
+ * const { data, error } = await client
19
+ * .from("blog-posts")
20
+ * .eq("status", "published")
21
+ * .order("publishedAt", { ascending: false })
22
+ * .limit(10);
23
+ *
24
+ * // Single entry
25
+ * const { data: post } = await client
26
+ * .from("blog-posts")
27
+ * .language("fr")
28
+ * .single("hello-world");
29
+ *
30
+ * // Legacy API (still works)
16
31
  * const models = await client.getModels();
17
32
  * const posts = await client.getEntries("blog-posts", { language: "fr" });
18
- * const post = await client.getEntry("blog-posts", "hello-world");
19
33
  * ```
20
34
  */
21
35
  export function createClient(config) {
@@ -30,6 +44,14 @@ export function createClient(config) {
30
44
  "Set apiKey in your client config:\n\n" +
31
45
  ' createClient({ project: "acme/web-app", apiKey: "bi18n_..." })');
32
46
  }
33
- return createContentAPIClient(apiBase, org, project, config.apiKey, config.debug);
47
+ const http = createHttpClient(apiBase, org, project, config.apiKey, config.debug);
48
+ return {
49
+ from(modelSlug) {
50
+ return ContentQueryBuilder.create(http, modelSlug);
51
+ },
52
+ getModels: () => http.getModels(),
53
+ getEntries: (model, opts) => http.getEntries(model, opts),
54
+ getEntry: (model, slug, opts) => http.getEntry(model, slug, opts),
55
+ };
34
56
  }
35
57
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,gBAAgB,GAAG,iCAAiC,CAAC;AAE3D;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,YAAY,CAAC,MAAoB;IAC/C,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,gBAAgB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAExE,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,2BAA2B,MAAM,CAAC,OAAO,mDAAmD,CAC7F,CAAC;IACJ,CAAC;IACD,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC;IAE7B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACb,+CAA+C;YAC7C,uCAAuC;YACvC,kEAAkE,CACrE,CAAC;IACJ,CAAC;IAED,OAAO,sBAAsB,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;AACpF,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,gBAAgB,GAAG,iCAAiC,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,YAAY,CAAC,MAAoB;IAC/C,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,gBAAgB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAExE,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,2BAA2B,MAAM,CAAC,OAAO,mDAAmD,CAC7F,CAAC;IACJ,CAAC;IACD,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC;IAE7B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACb,+CAA+C;YAC7C,uCAAuC;YACvC,kEAAkE,CACrE,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAElF,OAAO;QACL,IAAI,CAAC,SAAiB;YACpB,OAAO,mBAAmB,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACrD,CAAC;QACD,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE;QACjC,UAAU,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC;QACzD,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC;KAClE,CAAC;AACJ,CAAC"}
@@ -1,14 +1,5 @@
1
- import type { ContentClient } from "./types.js";
2
1
  /**
3
- * Creates a content client that fetches from the REST API.
4
- *
5
- * This mode supports filtering, pagination, and real-time data (no caching lag).
6
- * Requires an API key for authentication via the `x-api-key` header.
7
- *
8
- * URL patterns:
9
- * - Models: `{apiBase}/v1/content/{org}/{project}/models`
10
- * - Entries: `{apiBase}/v1/content/{org}/{project}/models/{model}/entries`
11
- * - Entry: `{apiBase}/v1/content/{org}/{project}/models/{model}/entries/{slug}`
2
+ * @deprecated Import from `./http.js` instead. This file is kept for backward compatibility.
12
3
  */
13
- export declare function createContentAPIClient(apiBase: string, org: string, project: string, apiKey: string, debug?: boolean): ContentClient;
4
+ export { createHttpClient as createContentAPIClient } from "./http.js";
14
5
  //# sourceMappingURL=content-api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"content-api.d.ts","sourceRoot":"","sources":["../src/content-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EAOd,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,KAAK,UAAQ,GACZ,aAAa,CA+Ef"}
1
+ {"version":3,"file":"content-api.d.ts","sourceRoot":"","sources":["../src/content-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,gBAAgB,IAAI,sBAAsB,EAAE,MAAM,WAAW,CAAC"}
@@ -1,82 +1,5 @@
1
1
  /**
2
- * Creates a content client that fetches from the REST API.
3
- *
4
- * This mode supports filtering, pagination, and real-time data (no caching lag).
5
- * Requires an API key for authentication via the `x-api-key` header.
6
- *
7
- * URL patterns:
8
- * - Models: `{apiBase}/v1/content/{org}/{project}/models`
9
- * - Entries: `{apiBase}/v1/content/{org}/{project}/models/{model}/entries`
10
- * - Entry: `{apiBase}/v1/content/{org}/{project}/models/{model}/entries/{slug}`
2
+ * @deprecated Import from `./http.js` instead. This file is kept for backward compatibility.
11
3
  */
12
- export function createContentAPIClient(apiBase, org, project, apiKey, debug = false) {
13
- const base = `${apiBase}/v1/content/${org}/${project}`;
14
- const headers = {
15
- "x-api-key": apiKey,
16
- "content-type": "application/json",
17
- };
18
- const log = debug
19
- ? (...args) => console.log("[better-i18n]", ...args)
20
- : () => { };
21
- if (debug) {
22
- log("Client initialized", { apiBase, org, project, base });
23
- }
24
- async function request(url, label) {
25
- log(`→ ${label}`, url);
26
- const res = await fetch(url, { headers });
27
- log(`← ${res.status} ${res.statusText}`);
28
- if (!res.ok) {
29
- const body = await res.text().catch(() => "");
30
- log(" Error body:", body);
31
- throw new Error(`API error ${label}: ${res.status} ${body}`);
32
- }
33
- const data = await res.json();
34
- log(" Response:", JSON.stringify(data).slice(0, 500));
35
- return { res, data };
36
- }
37
- return {
38
- async getModels() {
39
- const { data } = await request(`${base}/models`, "getModels");
40
- return data;
41
- },
42
- async getEntries(modelSlug, options) {
43
- const params = new URLSearchParams();
44
- if (options?.language)
45
- params.set("language", options.language);
46
- if (options?.status)
47
- params.set("status", options.status);
48
- if (options?.sort)
49
- params.set("sort", options.sort);
50
- if (options?.order)
51
- params.set("order", options.order);
52
- if (options?.page)
53
- params.set("page", String(options.page));
54
- if (options?.limit)
55
- params.set("limit", String(options.limit));
56
- if (options?.expand?.length)
57
- params.set("expand", options.expand.join(","));
58
- if (options?.fields?.length)
59
- params.set("fields", options.fields.join(","));
60
- const qs = params.toString() ? `?${params}` : "";
61
- const { data } = await request(`${base}/models/${modelSlug}/entries${qs}`, `getEntries(${modelSlug})`);
62
- return {
63
- items: data.items,
64
- total: data.total,
65
- hasMore: data.hasMore,
66
- };
67
- },
68
- async getEntry(modelSlug, entrySlug, options) {
69
- const params = new URLSearchParams();
70
- if (options?.language)
71
- params.set("language", options.language);
72
- if (options?.expand?.length)
73
- params.set("expand", options.expand.join(","));
74
- if (options?.fields?.length)
75
- params.set("fields", options.fields.join(","));
76
- const qs = params.toString() ? `?${params}` : "";
77
- const { data } = await request(`${base}/models/${modelSlug}/entries/${entrySlug}${qs}`, `getEntry(${modelSlug}/${entrySlug})`);
78
- return data;
79
- },
80
- };
81
- }
4
+ export { createHttpClient as createContentAPIClient } from "./http.js";
82
5
  //# sourceMappingURL=content-api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"content-api.js","sourceRoot":"","sources":["../src/content-api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"content-api.js","sourceRoot":"","sources":["../src/content-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,gBAAgB,IAAI,sBAAsB,EAAE,MAAM,WAAW,CAAC"}
package/dist/http.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import type { ContentEntry, ContentEntryListItem, ContentModel, GetEntryOptions, ListEntriesOptions, PaginatedResponse } from "./types.js";
2
+ /** Low-level HTTP client used by both the legacy API and the query builder. */
3
+ export interface HttpClient {
4
+ /** Make a raw GET request and return `{ data, error }` (never throws). */
5
+ request<T>(path: string, params?: URLSearchParams): Promise<HttpResult<T>>;
6
+ /** List content models. */
7
+ getModels(): Promise<ContentModel[]>;
8
+ /** List entries with legacy options. */
9
+ getEntries(model: string, opts?: ListEntriesOptions): Promise<PaginatedResponse<ContentEntryListItem>>;
10
+ /** Fetch a single entry by slug. */
11
+ getEntry<CF extends Record<string, string | null> = Record<string, string | null>>(model: string, slug: string, opts?: GetEntryOptions): Promise<ContentEntry<CF>>;
12
+ }
13
+ export type HttpResult<T> = {
14
+ data: T;
15
+ error: null;
16
+ } | {
17
+ data: null;
18
+ error: Error;
19
+ };
20
+ export declare function createHttpClient(apiBase: string, org: string, project: string, apiKey: string, debug?: boolean): HttpClient;
21
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAIpB,+EAA+E;AAC/E,MAAM,WAAW,UAAU;IACzB,0EAA0E;IAC1E,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,2BAA2B;IAC3B,SAAS,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACrC,wCAAwC;IACxC,UAAU,CACR,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,kBAAkB,GACxB,OAAO,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACpD,oCAAoC;IACpC,QAAQ,CAAC,EAAE,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAC/E,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,eAAe,GACrB,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;CAC9B;AAED,MAAM,MAAM,UAAU,CAAC,CAAC,IACpB;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAIjC,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,KAAK,UAAQ,GACZ,UAAU,CAuFZ"}
package/dist/http.js ADDED
@@ -0,0 +1,78 @@
1
+ // ─── Factory ────────────────────────────────────────────────────────
2
+ export function createHttpClient(apiBase, org, project, apiKey, debug = false) {
3
+ const base = `${apiBase}/v1/content/${org}/${project}`;
4
+ const headers = {
5
+ "x-api-key": apiKey,
6
+ "content-type": "application/json",
7
+ };
8
+ const log = debug
9
+ ? (...args) => console.log("[better-i18n]", ...args)
10
+ : () => { };
11
+ if (debug) {
12
+ log("Client initialized", { apiBase, org, project, base });
13
+ }
14
+ /** Internal fetch helper — throws on HTTP errors. */
15
+ async function rawRequest(url, label) {
16
+ log(`→ ${label}`, url);
17
+ const res = await fetch(url, { headers });
18
+ log(`← ${res.status} ${res.statusText}`);
19
+ if (!res.ok) {
20
+ const body = await res.text().catch(() => "");
21
+ log(" Error body:", body);
22
+ throw new Error(`API error ${label}: ${res.status} ${body}`);
23
+ }
24
+ const data = (await res.json());
25
+ log(" Response:", JSON.stringify(data).slice(0, 500));
26
+ return data;
27
+ }
28
+ return {
29
+ async request(path, params) {
30
+ const qs = params?.toString() ? `?${params}` : "";
31
+ const url = `${base}${path}${qs}`;
32
+ try {
33
+ const data = await rawRequest(url, `request(${path})`);
34
+ return { data, error: null };
35
+ }
36
+ catch (err) {
37
+ return { data: null, error: err instanceof Error ? err : new Error(String(err)) };
38
+ }
39
+ },
40
+ async getModels() {
41
+ return rawRequest(`${base}/models`, "getModels");
42
+ },
43
+ async getEntries(modelSlug, options) {
44
+ const params = new URLSearchParams();
45
+ if (options?.language)
46
+ params.set("language", options.language);
47
+ if (options?.status)
48
+ params.set("status", options.status);
49
+ if (options?.sort)
50
+ params.set("sort", options.sort);
51
+ if (options?.order)
52
+ params.set("order", options.order);
53
+ if (options?.page)
54
+ params.set("page", String(options.page));
55
+ if (options?.limit)
56
+ params.set("limit", String(options.limit));
57
+ if (options?.expand?.length)
58
+ params.set("expand", options.expand.join(","));
59
+ if (options?.fields?.length)
60
+ params.set("fields", options.fields.join(","));
61
+ const qs = params.toString() ? `?${params}` : "";
62
+ const data = await rawRequest(`${base}/models/${modelSlug}/entries${qs}`, `getEntries(${modelSlug})`);
63
+ return { items: data.items, total: data.total, hasMore: data.hasMore };
64
+ },
65
+ async getEntry(modelSlug, entrySlug, options) {
66
+ const params = new URLSearchParams();
67
+ if (options?.language)
68
+ params.set("language", options.language);
69
+ if (options?.expand?.length)
70
+ params.set("expand", options.expand.join(","));
71
+ if (options?.fields?.length)
72
+ params.set("fields", options.fields.join(","));
73
+ const qs = params.toString() ? `?${params}` : "";
74
+ return rawRequest(`${base}/models/${modelSlug}/entries/${entrySlug}${qs}`, `getEntry(${modelSlug}/${entrySlug})`);
75
+ },
76
+ };
77
+ }
78
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAkCA,uEAAuE;AAEvE,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,GAAW,EACX,OAAe,EACf,MAAc,EACd,KAAK,GAAG,KAAK;IAEb,MAAM,IAAI,GAAG,GAAG,OAAO,eAAe,GAAG,IAAI,OAAO,EAAE,CAAC;IACvD,MAAM,OAAO,GAA2B;QACtC,WAAW,EAAE,MAAM;QACnB,cAAc,EAAE,kBAAkB;KACnC,CAAC;IAEF,MAAM,GAAG,GAAG,KAAK;QACf,CAAC,CAAC,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC;QAC/D,CAAC,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;IAEb,IAAI,KAAK,EAAE,CAAC;QACV,GAAG,CAAC,oBAAoB,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,qDAAqD;IACrD,KAAK,UAAU,UAAU,CAAI,GAAW,EAAE,KAAa;QACrD,GAAG,CAAC,KAAK,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;QACvB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1C,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,aAAa,KAAK,KAAK,GAAG,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;QACrC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,KAAK,CAAC,OAAO,CAAI,IAAY,EAAE,MAAwB;YACrD,MAAM,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClD,MAAM,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,EAAE,EAAE,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,UAAU,CAAI,GAAG,EAAE,WAAW,IAAI,GAAG,CAAC,CAAC;gBAC1D,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;YAC/B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACpF,CAAC;QACH,CAAC;QAED,KAAK,CAAC,SAAS;YACb,OAAO,UAAU,CAAiB,GAAG,IAAI,SAAS,EAAE,WAAW,CAAC,CAAC;QACnE,CAAC;QAED,KAAK,CAAC,UAAU,CACd,SAAiB,EACjB,OAA4B;YAE5B,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YACrC,IAAI,OAAO,EAAE,QAAQ;gBAAE,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;YAChE,IAAI,OAAO,EAAE,MAAM;gBAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YAC1D,IAAI,OAAO,EAAE,IAAI;gBAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YACpD,IAAI,OAAO,EAAE,KAAK;gBAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;YACvD,IAAI,OAAO,EAAE,IAAI;gBAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5D,IAAI,OAAO,EAAE,KAAK;gBAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;YAC/D,IAAI,OAAO,EAAE,MAAM,EAAE,MAAM;gBAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5E,IAAI,OAAO,EAAE,MAAM,EAAE,MAAM;gBAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5E,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAEjD,MAAM,IAAI,GAAG,MAAM,UAAU,CAI1B,GAAG,IAAI,WAAW,SAAS,WAAW,EAAE,EAAE,EAAE,cAAc,SAAS,GAAG,CAAC,CAAC;YAE3E,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QACzE,CAAC;QAED,KAAK,CAAC,QAAQ,CACZ,SAAiB,EACjB,SAAiB,EACjB,OAAyB;YAEzB,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YACrC,IAAI,OAAO,EAAE,QAAQ;gBAAE,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;YAChE,IAAI,OAAO,EAAE,MAAM,EAAE,MAAM;gBAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5E,IAAI,OAAO,EAAE,MAAM,EAAE,MAAM;gBAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5E,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAEjD,OAAO,UAAU,CACf,GAAG,IAAI,WAAW,SAAS,YAAY,SAAS,GAAG,EAAE,EAAE,EACvD,YAAY,SAAS,IAAI,SAAS,GAAG,CACtC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,8 @@
1
1
  export { createClient } from "./client.js";
2
+ export { ContentQueryBuilder, SingleQueryBuilder } from "./query-builder.js";
3
+ export { createHttpClient } from "./http.js";
4
+ /** @deprecated Use `createHttpClient` from `./http.js` instead. */
2
5
  export { createContentAPIClient } from "./content-api.js";
3
- export type { ClientConfig, ContentClient, ContentEntry, ContentEntryListItem, ContentEntryStatus, ContentEntrySortField, ContentModel, ListEntriesOptions, GetEntryOptions, PaginatedResponse, RelationValue, } from "./types.js";
6
+ export type { ClientConfig, ContentClient, ContentEntry, ContentEntryListItem, ContentEntryStatus, ContentEntrySortField, ContentModel, ListEntriesOptions, GetEntryOptions, PaginatedResponse, QueryResult, SingleQueryResult, RelationValue, } from "./types.js";
7
+ export type { HttpClient, HttpResult } from "./http.js";
4
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,YAAY,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,aAAa,GACd,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,mEAAmE;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,YAAY,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
1
  export { createClient } from "./client.js";
2
+ export { ContentQueryBuilder, SingleQueryBuilder } from "./query-builder.js";
3
+ export { createHttpClient } from "./http.js";
4
+ /** @deprecated Use `createHttpClient` from `./http.js` instead. */
2
5
  export { createContentAPIClient } from "./content-api.js";
3
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,mEAAmE;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,134 @@
1
+ import type { HttpClient } from "./http.js";
2
+ import type { ContentEntry, ContentEntryListItem, ContentEntrySortField, QueryResult, SingleQueryResult } from "./types.js";
3
+ interface QueryParams {
4
+ fields: string[];
5
+ expand: string[];
6
+ filters: Record<string, string>;
7
+ search: string | undefined;
8
+ language: string | undefined;
9
+ status: string | undefined;
10
+ sort: ContentEntrySortField | undefined;
11
+ ascending: boolean | undefined;
12
+ limitVal: number | undefined;
13
+ pageVal: number | undefined;
14
+ }
15
+ /**
16
+ * Terminal builder for fetching a single entry by slug.
17
+ * Thenable — can be awaited directly.
18
+ */
19
+ export declare class SingleQueryBuilder<CF extends Record<string, string | null> = Record<string, string | null>> {
20
+ private readonly _http;
21
+ private readonly _model;
22
+ private readonly _slug;
23
+ private readonly _params;
24
+ /** @internal */
25
+ constructor(_http: HttpClient, _model: string, _slug: string, _params: QueryParams);
26
+ /** Execute the query. Prefer `await builder` over calling this directly. */
27
+ execute(): Promise<SingleQueryResult<ContentEntry<CF>>>;
28
+ /** Makes this object thenable so `await builder.single("slug")` works. */
29
+ then<TResult1 = SingleQueryResult<ContentEntry<CF>>, TResult2 = never>(onfulfilled?: ((value: SingleQueryResult<ContentEntry<CF>>) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
30
+ }
31
+ /**
32
+ * Supabase-style chainable query builder for content entries.
33
+ *
34
+ * Each chainable method returns a **new** builder instance (immutable).
35
+ * The builder is thenable — `await` it to execute the query.
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const { data, error, total, hasMore } = await client
40
+ * .from("blog-posts")
41
+ * .select("title", "body")
42
+ * .eq("status", "published")
43
+ * .order("publishedAt", { ascending: false })
44
+ * .limit(10)
45
+ * .language("en");
46
+ * ```
47
+ */
48
+ export declare class ContentQueryBuilder<T = ContentEntryListItem> {
49
+ private readonly _http;
50
+ private readonly _model;
51
+ private readonly _params;
52
+ /** @internal — use `ContentQueryBuilder.create()` */
53
+ private constructor();
54
+ /** @internal */
55
+ static create(http: HttpClient, model: string): ContentQueryBuilder;
56
+ private clone;
57
+ /**
58
+ * Choose which fields to include in the response.
59
+ *
60
+ * @example `.select("title", "body", "category")`
61
+ */
62
+ select(...fields: string[]): ContentQueryBuilder<T>;
63
+ /**
64
+ * Filter by a built-in field value (status, etc.).
65
+ *
66
+ * @example `.eq("status", "published")`
67
+ */
68
+ eq(field: string, value: string): ContentQueryBuilder<T>;
69
+ /**
70
+ * Filter by a custom field value. Maps to `?filter[field]=value` on the REST API.
71
+ *
72
+ * @example `.filter("category", "engineering")`
73
+ */
74
+ filter(field: string, value: string): ContentQueryBuilder<T>;
75
+ /**
76
+ * Full-text search on entry titles.
77
+ *
78
+ * @example `.search("kubernetes")`
79
+ */
80
+ search(term: string): ContentQueryBuilder<T>;
81
+ /**
82
+ * Set the language for localized content.
83
+ *
84
+ * @example `.language("fr")`
85
+ */
86
+ language(code: string): ContentQueryBuilder<T>;
87
+ /**
88
+ * Set the sort field and direction.
89
+ *
90
+ * @example `.order("publishedAt", { ascending: false })`
91
+ */
92
+ order(field: ContentEntrySortField, opts?: {
93
+ ascending?: boolean;
94
+ }): ContentQueryBuilder<T>;
95
+ /**
96
+ * Limit the number of results per page (1-100).
97
+ *
98
+ * @example `.limit(10)`
99
+ */
100
+ limit(n: number): ContentQueryBuilder<T>;
101
+ /**
102
+ * Set the page number (1-based).
103
+ *
104
+ * @example `.page(2)`
105
+ */
106
+ page(n: number): ContentQueryBuilder<T>;
107
+ /**
108
+ * Expand relation fields by name.
109
+ *
110
+ * @example `.expand("author", "category")`
111
+ */
112
+ expand(...fields: string[]): ContentQueryBuilder<T>;
113
+ /**
114
+ * Switch to single-entry mode. Returns a thenable that resolves a single entry.
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * const { data: post, error } = await client
119
+ * .from("blog-posts")
120
+ * .language("fr")
121
+ * .single("hello-world");
122
+ * ```
123
+ */
124
+ single<CF extends Record<string, string | null> = Record<string, string | null>>(slug: string): SingleQueryBuilder<CF>;
125
+ /**
126
+ * Execute the list query. Prefer `await builder` over calling this directly.
127
+ */
128
+ execute(): Promise<QueryResult<T[]>>;
129
+ /** Makes this object thenable so `await client.from("posts").limit(5)` works. */
130
+ then<TResult1 = QueryResult<T[]>, TResult2 = never>(onfulfilled?: ((value: QueryResult<T[]>) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
131
+ private buildSearchParams;
132
+ }
133
+ export {};
134
+ //# sourceMappingURL=query-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-builder.d.ts","sourceRoot":"","sources":["../src/query-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,237 @@
1
+ function emptyParams() {
2
+ return {
3
+ fields: [],
4
+ expand: [],
5
+ filters: {},
6
+ search: undefined,
7
+ language: undefined,
8
+ status: undefined,
9
+ sort: undefined,
10
+ ascending: undefined,
11
+ limitVal: undefined,
12
+ pageVal: undefined,
13
+ };
14
+ }
15
+ // ─── SingleQueryBuilder ─────────────────────────────────────────────
16
+ /**
17
+ * Terminal builder for fetching a single entry by slug.
18
+ * Thenable — can be awaited directly.
19
+ */
20
+ export class SingleQueryBuilder {
21
+ _http;
22
+ _model;
23
+ _slug;
24
+ _params;
25
+ /** @internal */
26
+ constructor(_http, _model, _slug, _params) {
27
+ this._http = _http;
28
+ this._model = _model;
29
+ this._slug = _slug;
30
+ this._params = _params;
31
+ }
32
+ /** Execute the query. Prefer `await builder` over calling this directly. */
33
+ async execute() {
34
+ const params = new URLSearchParams();
35
+ if (this._params.language)
36
+ params.set("language", this._params.language);
37
+ if (this._params.fields.length)
38
+ params.set("fields", this._params.fields.join(","));
39
+ if (this._params.expand.length)
40
+ params.set("expand", this._params.expand.join(","));
41
+ const result = await this._http.request(`/models/${this._model}/entries/${this._slug}`, params);
42
+ if (result.error) {
43
+ return { data: null, error: result.error };
44
+ }
45
+ return { data: result.data, error: null };
46
+ }
47
+ /** Makes this object thenable so `await builder.single("slug")` works. */
48
+ then(onfulfilled, onrejected) {
49
+ return this.execute().then(onfulfilled, onrejected);
50
+ }
51
+ }
52
+ // ─── ContentQueryBuilder ────────────────────────────────────────────
53
+ /**
54
+ * Supabase-style chainable query builder for content entries.
55
+ *
56
+ * Each chainable method returns a **new** builder instance (immutable).
57
+ * The builder is thenable — `await` it to execute the query.
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const { data, error, total, hasMore } = await client
62
+ * .from("blog-posts")
63
+ * .select("title", "body")
64
+ * .eq("status", "published")
65
+ * .order("publishedAt", { ascending: false })
66
+ * .limit(10)
67
+ * .language("en");
68
+ * ```
69
+ */
70
+ export class ContentQueryBuilder {
71
+ _http;
72
+ _model;
73
+ _params;
74
+ /** @internal — use `ContentQueryBuilder.create()` */
75
+ constructor(_http, _model, _params) {
76
+ this._http = _http;
77
+ this._model = _model;
78
+ this._params = _params;
79
+ }
80
+ /** @internal */
81
+ static create(http, model) {
82
+ return new ContentQueryBuilder(http, model, emptyParams());
83
+ }
84
+ // ─── Private helpers ────────────────────────────────────────────
85
+ clone(patch) {
86
+ return new ContentQueryBuilder(this._http, this._model, {
87
+ ...this._params,
88
+ ...patch,
89
+ });
90
+ }
91
+ // ─── Chainable methods ──────────────────────────────────────────
92
+ /**
93
+ * Choose which fields to include in the response.
94
+ *
95
+ * @example `.select("title", "body", "category")`
96
+ */
97
+ select(...fields) {
98
+ return this.clone({ fields: [...this._params.fields, ...fields] });
99
+ }
100
+ /**
101
+ * Filter by a built-in field value (status, etc.).
102
+ *
103
+ * @example `.eq("status", "published")`
104
+ */
105
+ eq(field, value) {
106
+ if (field === "status") {
107
+ return this.clone({ status: value });
108
+ }
109
+ return this.clone({
110
+ filters: { ...this._params.filters, [field]: value },
111
+ });
112
+ }
113
+ /**
114
+ * Filter by a custom field value. Maps to `?filter[field]=value` on the REST API.
115
+ *
116
+ * @example `.filter("category", "engineering")`
117
+ */
118
+ filter(field, value) {
119
+ return this.clone({
120
+ filters: { ...this._params.filters, [field]: value },
121
+ });
122
+ }
123
+ /**
124
+ * Full-text search on entry titles.
125
+ *
126
+ * @example `.search("kubernetes")`
127
+ */
128
+ search(term) {
129
+ return this.clone({ search: term });
130
+ }
131
+ /**
132
+ * Set the language for localized content.
133
+ *
134
+ * @example `.language("fr")`
135
+ */
136
+ language(code) {
137
+ return this.clone({ language: code });
138
+ }
139
+ /**
140
+ * Set the sort field and direction.
141
+ *
142
+ * @example `.order("publishedAt", { ascending: false })`
143
+ */
144
+ order(field, opts) {
145
+ return this.clone({
146
+ sort: field,
147
+ ascending: opts?.ascending,
148
+ });
149
+ }
150
+ /**
151
+ * Limit the number of results per page (1-100).
152
+ *
153
+ * @example `.limit(10)`
154
+ */
155
+ limit(n) {
156
+ return this.clone({ limitVal: n });
157
+ }
158
+ /**
159
+ * Set the page number (1-based).
160
+ *
161
+ * @example `.page(2)`
162
+ */
163
+ page(n) {
164
+ return this.clone({ pageVal: n });
165
+ }
166
+ /**
167
+ * Expand relation fields by name.
168
+ *
169
+ * @example `.expand("author", "category")`
170
+ */
171
+ expand(...fields) {
172
+ return this.clone({ expand: [...this._params.expand, ...fields] });
173
+ }
174
+ // ─── Terminal methods ───────────────────────────────────────────
175
+ /**
176
+ * Switch to single-entry mode. Returns a thenable that resolves a single entry.
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * const { data: post, error } = await client
181
+ * .from("blog-posts")
182
+ * .language("fr")
183
+ * .single("hello-world");
184
+ * ```
185
+ */
186
+ single(slug) {
187
+ return new SingleQueryBuilder(this._http, this._model, slug, this._params);
188
+ }
189
+ /**
190
+ * Execute the list query. Prefer `await builder` over calling this directly.
191
+ */
192
+ async execute() {
193
+ const params = this.buildSearchParams();
194
+ const result = await this._http.request(`/models/${this._model}/entries`, params);
195
+ if (result.error) {
196
+ return { data: null, error: result.error, total: 0, hasMore: false };
197
+ }
198
+ return {
199
+ data: result.data.items,
200
+ error: null,
201
+ total: result.data.total,
202
+ hasMore: result.data.hasMore,
203
+ };
204
+ }
205
+ /** Makes this object thenable so `await client.from("posts").limit(5)` works. */
206
+ then(onfulfilled, onrejected) {
207
+ return this.execute().then(onfulfilled, onrejected);
208
+ }
209
+ // ─── Internal ───────────────────────────────────────────────────
210
+ buildSearchParams() {
211
+ const params = new URLSearchParams();
212
+ if (this._params.language)
213
+ params.set("language", this._params.language);
214
+ if (this._params.status)
215
+ params.set("status", this._params.status);
216
+ if (this._params.sort)
217
+ params.set("sort", this._params.sort);
218
+ if (this._params.ascending !== undefined) {
219
+ params.set("order", this._params.ascending ? "asc" : "desc");
220
+ }
221
+ if (this._params.pageVal)
222
+ params.set("page", String(this._params.pageVal));
223
+ if (this._params.limitVal)
224
+ params.set("limit", String(this._params.limitVal));
225
+ if (this._params.fields.length)
226
+ params.set("fields", this._params.fields.join(","));
227
+ if (this._params.expand.length)
228
+ params.set("expand", this._params.expand.join(","));
229
+ if (this._params.search)
230
+ params.set("search", this._params.search);
231
+ for (const [key, value] of Object.entries(this._params.filters)) {
232
+ params.set(`filter[${key}]`, value);
233
+ }
234
+ return params;
235
+ }
236
+ }
237
+ //# sourceMappingURL=query-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-builder.js","sourceRoot":"","sources":["../src/query-builder.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -9,8 +9,8 @@ export interface ClientConfig {
9
9
  /** Enable debug logging to see request URLs, headers, and responses. */
10
10
  debug?: boolean;
11
11
  }
12
- /** Expanded relation value returned when a relation field is expanded. */
13
- export interface RelationValue {
12
+ /** Expanded relation value returned when a relation field is expanded. Custom fields are spread directly on the object. */
13
+ export type RelationValue = {
14
14
  /** Referenced entry UUID */
15
15
  id: string;
16
16
  /** Referenced entry slug */
@@ -19,11 +19,10 @@ export interface RelationValue {
19
19
  title: string;
20
20
  /** Target model slug */
21
21
  modelSlug: string;
22
- /** The related entry's own custom field values (or user profile fields for _users). */
23
- customFields?: Record<string, string | null>;
24
- }
22
+ } & Record<string, string | null>;
25
23
  /**
26
24
  * A full content entry with all localized fields.
25
+ * Custom fields are spread directly on the entry object (flat access).
27
26
  *
28
27
  * @typeParam CF - Custom fields shape. Defaults to `Record<string, string | null>`.
29
28
  *
@@ -31,38 +30,36 @@ export interface RelationValue {
31
30
  * ```typescript
32
31
  * // Typed custom fields
33
32
  * interface BlogFields { readingTime: string | null; category: string | null }
34
- * const post = await client.getEntry<BlogFields>("blog", "hello-world");
35
- * post.customFields.readingTime; // string | null (typed!)
33
+ * const { data: post } = await client.from("blog").single<BlogFields>("hello-world");
34
+ * post.readingTime; // string | null (typed!)
35
+ * post.category; // string | null (typed!)
36
36
  * ```
37
37
  */
38
- export interface ContentEntry<CF extends Record<string, string | null> = Record<string, string | null>> {
38
+ export type ContentEntry<CF extends Record<string, string | null> = Record<string, string | null>> = {
39
39
  id: string;
40
40
  slug: string;
41
41
  status: "draft" | "published" | "archived";
42
42
  publishedAt: string | null;
43
43
  sourceLanguage: string;
44
44
  availableLanguages: string[];
45
- customFields: CF;
46
45
  /** Expanded relation fields (only present when expand is used) */
47
46
  relations?: Record<string, RelationValue | null>;
48
47
  title: string;
49
48
  /** Rich text body as Markdown string. */
50
49
  body: string | null;
51
- }
50
+ } & CF;
52
51
  /** Entry status filter values. */
53
52
  export type ContentEntryStatus = "draft" | "published" | "archived";
54
- /** A summary item for content entry lists. */
55
- export interface ContentEntryListItem {
53
+ /** A summary item for content entry lists. Custom fields are spread directly on the object. */
54
+ export type ContentEntryListItem<CF extends Record<string, string | null> = Record<string, string | null>> = {
56
55
  slug: string;
57
56
  title: string;
58
57
  publishedAt: string | null;
59
58
  /** Markdown body — only present when `fields` includes `"body"`. */
60
59
  body?: string | null;
61
- /** Custom fields — only present when `fields` includes specific field names. */
62
- customFields?: Record<string, string | null>;
63
60
  /** Expanded relation fields (only present when expand is used) */
64
61
  relations?: Record<string, RelationValue | null>;
65
- }
62
+ } & CF;
66
63
  /** Paginated response wrapper. */
67
64
  export interface PaginatedResponse<T> {
68
65
  items: T[];
@@ -77,6 +74,18 @@ export interface ContentModel {
77
74
  kind: string;
78
75
  entryCount: number;
79
76
  }
77
+ /** Result of a list query — Supabase-style `{ data, error }` pattern. */
78
+ export interface QueryResult<T> {
79
+ data: T | null;
80
+ error: Error | null;
81
+ total: number;
82
+ hasMore: boolean;
83
+ }
84
+ /** Result of a single-entry query — Supabase-style `{ data, error }` pattern. */
85
+ export interface SingleQueryResult<T> {
86
+ data: T | null;
87
+ error: Error | null;
88
+ }
80
89
  /** Sortable fields for content entries. */
81
90
  export type ContentEntrySortField = "publishedAt" | "createdAt" | "updatedAt" | "title";
82
91
  /** Options for listing content entries. */
@@ -107,13 +116,33 @@ export interface GetEntryOptions {
107
116
  /** Relation field names to expand (e.g., ["category", "author"]) */
108
117
  expand?: string[];
109
118
  }
119
+ import type { ContentQueryBuilder } from "./query-builder.js";
110
120
  /** Client for fetching content entries and models. */
111
121
  export interface ContentClient {
122
+ /**
123
+ * Start a chainable query for a content model — Supabase-style API.
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * const { data, error } = await client
128
+ * .from("blog-posts")
129
+ * .eq("status", "published")
130
+ * .order("publishedAt", { ascending: false })
131
+ * .limit(10);
132
+ * ```
133
+ */
134
+ from(modelSlug: string): ContentQueryBuilder;
112
135
  /** List all content models in the project. */
113
136
  getModels(): Promise<ContentModel[]>;
114
- /** List entries for a content model with pagination. */
137
+ /**
138
+ * List entries for a content model with pagination.
139
+ * @deprecated Use `client.from(modelSlug)` for a chainable, composable API.
140
+ */
115
141
  getEntries(modelSlug: string, options?: ListEntriesOptions): Promise<PaginatedResponse<ContentEntryListItem>>;
116
- /** Fetch a single content entry by slug. */
142
+ /**
143
+ * Fetch a single content entry by slug.
144
+ * @deprecated Use `client.from(modelSlug).single(slug)` for error-safe API.
145
+ */
117
146
  getEntry<CF extends Record<string, string | null> = Record<string, string | null>>(modelSlug: string, entrySlug: string, options?: GetEntryOptions): Promise<ContentEntry<CF>>;
118
147
  }
119
148
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-i18n/sdk",
3
- "version": "2.0.1",
3
+ "version": "3.0.0",
4
4
  "description": "Content SDK for Better i18n - headless CMS client for fetching content models and entries",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,7 +17,7 @@
17
17
  "README.md"
18
18
  ],
19
19
  "scripts": {
20
- "build": "tsc",
20
+ "build": "tsc -b --force",
21
21
  "typecheck": "tsc --noEmit",
22
22
  "clean": "rm -rf dist",
23
23
  "prepublishOnly": "bun run build"