@better-i18n/sdk 0.1.1 → 0.2.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/package.json +6 -8
- package/src/client.ts +10 -21
- package/src/index.ts +1 -4
- package/src/types.ts +5 -48
- package/src/content.ts +0 -9
- package/src/translations-cdn.ts +0 -51
- package/src/translations.ts +0 -6
package/package.json
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-i18n/sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "SDK for fetching content and
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Content SDK for Better i18n - headless CMS client for fetching content models and entries",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"types": "src/index.ts",
|
|
8
8
|
"exports": {
|
|
9
|
-
".": "./src/index.ts"
|
|
10
|
-
"./content": "./src/content.ts",
|
|
11
|
-
"./translations": "./src/translations.ts"
|
|
9
|
+
".": "./src/index.ts"
|
|
12
10
|
},
|
|
13
11
|
"files": [
|
|
14
12
|
"src",
|
|
@@ -18,11 +16,11 @@
|
|
|
18
16
|
"typecheck": "tsc --noEmit"
|
|
19
17
|
},
|
|
20
18
|
"keywords": [
|
|
21
|
-
"i18n",
|
|
22
|
-
"translations",
|
|
23
19
|
"content",
|
|
24
20
|
"sdk",
|
|
25
|
-
"headless-cms"
|
|
21
|
+
"headless-cms",
|
|
22
|
+
"better-i18n",
|
|
23
|
+
"cms"
|
|
26
24
|
],
|
|
27
25
|
"devDependencies": {
|
|
28
26
|
"typescript": "~5.9.3"
|
package/src/client.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import type { ClientConfig,
|
|
1
|
+
import type { ClientConfig, ContentClient } from "./types";
|
|
2
2
|
import { createContentAPIClient } from "./content-api";
|
|
3
|
-
import { createTranslationsCDNClient } from "./translations-cdn";
|
|
4
3
|
|
|
5
|
-
const DEFAULT_CDN_BASE = "https://cdn.better-i18n.com";
|
|
6
4
|
const DEFAULT_API_BASE = "https://api.better-i18n.com";
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
|
-
* Creates a Better i18n
|
|
7
|
+
* Creates a Better i18n content client.
|
|
10
8
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* Fetches content models and entries from the REST API.
|
|
10
|
+
* Requires an API key for authentication.
|
|
13
11
|
*
|
|
14
12
|
* @example
|
|
15
13
|
* ```typescript
|
|
@@ -19,31 +17,22 @@ const DEFAULT_API_BASE = "https://api.better-i18n.com";
|
|
|
19
17
|
* apiKey: "bi18n_...",
|
|
20
18
|
* });
|
|
21
19
|
*
|
|
22
|
-
*
|
|
23
|
-
* const posts = await client.
|
|
24
|
-
* const post = await client.
|
|
25
|
-
* const models = await client.content.getModels();
|
|
26
|
-
*
|
|
27
|
-
* // Translations (CDN mode, no API key needed)
|
|
28
|
-
* const strings = await client.translations.get("common", { language: "fr" });
|
|
20
|
+
* const models = await client.getModels();
|
|
21
|
+
* const posts = await client.getEntries("blog-posts", { language: "fr" });
|
|
22
|
+
* const post = await client.getEntry("blog-posts", "hello-world");
|
|
29
23
|
* ```
|
|
30
24
|
*/
|
|
31
|
-
export function createClient(config: ClientConfig):
|
|
25
|
+
export function createClient(config: ClientConfig): ContentClient {
|
|
32
26
|
const { org, project } = config;
|
|
33
|
-
const cdnBase = (config.cdnBase || DEFAULT_CDN_BASE).replace(/\/$/, "");
|
|
34
27
|
const apiBase = (config.apiBase || DEFAULT_API_BASE).replace(/\/$/, "");
|
|
35
28
|
|
|
36
29
|
if (!config.apiKey) {
|
|
37
30
|
throw new Error(
|
|
38
|
-
"API key is required
|
|
31
|
+
"API key is required for content API access.\n" +
|
|
39
32
|
"Set apiKey in your client config:\n\n" +
|
|
40
33
|
' createClient({ org: "...", project: "...", apiKey: "bi18n_..." })',
|
|
41
34
|
);
|
|
42
35
|
}
|
|
43
36
|
|
|
44
|
-
return
|
|
45
|
-
content: createContentAPIClient(apiBase, org, project, config.apiKey),
|
|
46
|
-
// Translations always served from CDN for performance
|
|
47
|
-
translations: createTranslationsCDNClient(cdnBase, org, project),
|
|
48
|
-
};
|
|
37
|
+
return createContentAPIClient(apiBase, org, project, config.apiKey);
|
|
49
38
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
export { createClient } from "./client";
|
|
2
|
+
export { createContentAPIClient } from "./content-api";
|
|
2
3
|
export type {
|
|
3
4
|
ClientConfig,
|
|
4
|
-
BetterI18nClient,
|
|
5
5
|
ContentClient,
|
|
6
|
-
TranslationsClient,
|
|
7
6
|
ContentEntry,
|
|
8
7
|
ContentEntryListItem,
|
|
9
8
|
ContentModel,
|
|
10
|
-
TranslationManifest,
|
|
11
9
|
ListEntriesOptions,
|
|
12
10
|
GetEntryOptions,
|
|
13
|
-
GetTranslationsOptions,
|
|
14
11
|
} from "./types";
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// ─── Client Configuration ────────────────────────────────────────────
|
|
2
2
|
|
|
3
|
-
/** Configuration for creating a Better i18n client. */
|
|
3
|
+
/** Configuration for creating a Better i18n content client. */
|
|
4
4
|
export interface ClientConfig {
|
|
5
5
|
/** Organization slug (e.g., "acme-corp"). */
|
|
6
6
|
org: string;
|
|
@@ -8,9 +8,7 @@ export interface ClientConfig {
|
|
|
8
8
|
project: string;
|
|
9
9
|
/** API key for authenticating content requests. Required. */
|
|
10
10
|
apiKey: string;
|
|
11
|
-
/**
|
|
12
|
-
cdnBase?: string;
|
|
13
|
-
/** REST API base URL for content. Defaults to `https://api.better-i18n.com`. */
|
|
11
|
+
/** REST API base URL. Defaults to `https://api.better-i18n.com`. */
|
|
14
12
|
apiBase?: string;
|
|
15
13
|
}
|
|
16
14
|
|
|
@@ -58,27 +56,11 @@ export interface ContentModel {
|
|
|
58
56
|
entryCount: number;
|
|
59
57
|
}
|
|
60
58
|
|
|
61
|
-
// ───
|
|
62
|
-
|
|
63
|
-
/** Manifest describing project languages and translation coverage. */
|
|
64
|
-
export interface TranslationManifest {
|
|
65
|
-
projectSlug: string;
|
|
66
|
-
sourceLanguage: string;
|
|
67
|
-
languages: Array<{
|
|
68
|
-
code: string;
|
|
69
|
-
name: string;
|
|
70
|
-
nativeName: string;
|
|
71
|
-
isSource: boolean;
|
|
72
|
-
keyCount: number;
|
|
73
|
-
}>;
|
|
74
|
-
updatedAt: string;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// ─── Client Interfaces ──────────────────────────────────────────────
|
|
59
|
+
// ─── Client Interface ───────────────────────────────────────────────
|
|
78
60
|
|
|
79
61
|
/** Options for listing content entries. */
|
|
80
62
|
export interface ListEntriesOptions {
|
|
81
|
-
/** Language code for localized content. Defaults to
|
|
63
|
+
/** Language code for localized content. Defaults to source language. */
|
|
82
64
|
language?: string;
|
|
83
65
|
/** Page number (1-based). */
|
|
84
66
|
page?: number;
|
|
@@ -88,13 +70,7 @@ export interface ListEntriesOptions {
|
|
|
88
70
|
|
|
89
71
|
/** Options for fetching a single content entry. */
|
|
90
72
|
export interface GetEntryOptions {
|
|
91
|
-
/** Language code for localized content. Defaults to
|
|
92
|
-
language?: string;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** Options for fetching translations. */
|
|
96
|
-
export interface GetTranslationsOptions {
|
|
97
|
-
/** Language code. Defaults to `"en"`. */
|
|
73
|
+
/** Language code for localized content. Defaults to source language. */
|
|
98
74
|
language?: string;
|
|
99
75
|
}
|
|
100
76
|
|
|
@@ -114,22 +90,3 @@ export interface ContentClient {
|
|
|
114
90
|
options?: GetEntryOptions,
|
|
115
91
|
): Promise<ContentEntry>;
|
|
116
92
|
}
|
|
117
|
-
|
|
118
|
-
/** Client for fetching translation strings. */
|
|
119
|
-
export interface TranslationsClient {
|
|
120
|
-
/** Fetch translations for a namespace. */
|
|
121
|
-
get(
|
|
122
|
-
namespace: string,
|
|
123
|
-
options?: GetTranslationsOptions,
|
|
124
|
-
): Promise<Record<string, string>>;
|
|
125
|
-
/** Fetch the project translation manifest. */
|
|
126
|
-
getManifest(): Promise<TranslationManifest>;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/** The unified Better i18n client. */
|
|
130
|
-
export interface BetterI18nClient {
|
|
131
|
-
/** Content sub-client for headless CMS operations. */
|
|
132
|
-
content: ContentClient;
|
|
133
|
-
/** Translations sub-client for i18n string fetching. */
|
|
134
|
-
translations: TranslationsClient;
|
|
135
|
-
}
|
package/src/content.ts
DELETED
package/src/translations-cdn.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
TranslationsClient,
|
|
3
|
-
TranslationManifest,
|
|
4
|
-
GetTranslationsOptions,
|
|
5
|
-
} from "./types";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Creates a translations client that fetches from the CDN.
|
|
9
|
-
*
|
|
10
|
-
* Translation files are pre-built JSON served from Cloudflare R2.
|
|
11
|
-
* No authentication required.
|
|
12
|
-
*
|
|
13
|
-
* URL patterns:
|
|
14
|
-
* - Namespace: `{cdnBase}/{org}/{project}/{lang}/{namespace}.json`
|
|
15
|
-
* - Manifest: `{cdnBase}/{org}/{project}/manifest.json`
|
|
16
|
-
*/
|
|
17
|
-
export function createTranslationsCDNClient(
|
|
18
|
-
cdnBase: string,
|
|
19
|
-
org: string,
|
|
20
|
-
project: string,
|
|
21
|
-
): TranslationsClient {
|
|
22
|
-
const base = `${cdnBase}/${org}/${project}`;
|
|
23
|
-
|
|
24
|
-
return {
|
|
25
|
-
async get(
|
|
26
|
-
namespace: string,
|
|
27
|
-
options?: GetTranslationsOptions,
|
|
28
|
-
): Promise<Record<string, string>> {
|
|
29
|
-
const lang = options?.language || "en";
|
|
30
|
-
const ns = namespace || "default";
|
|
31
|
-
const res = await fetch(`${base}/${lang}/${ns}.json`);
|
|
32
|
-
if (!res.ok) {
|
|
33
|
-
if (res.status === 404) return {};
|
|
34
|
-
throw new Error(
|
|
35
|
-
`Failed to fetch translations for ${ns} (${lang}): ${res.status}`,
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
return res.json();
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
async getManifest(): Promise<TranslationManifest> {
|
|
42
|
-
const res = await fetch(`${base}/manifest.json`);
|
|
43
|
-
if (!res.ok) {
|
|
44
|
-
throw new Error(
|
|
45
|
-
`Failed to fetch translation manifest: ${res.status}`,
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
return res.json();
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
}
|