cmx-sdk 0.1.10 → 0.1.13

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.
Files changed (43) hide show
  1. package/README.md +351 -53
  2. package/dist/cli.js +968 -83
  3. package/dist/index.d.ts +1968 -74
  4. package/dist/index.js +1040 -69
  5. package/dist/index.js.map +1 -0
  6. package/package.json +47 -17
  7. package/dist/cli.d.ts +0 -2
  8. package/dist/commands/create-collection.d.ts +0 -9
  9. package/dist/commands/create-collection.js +0 -32
  10. package/dist/commands/create-data-type.d.ts +0 -8
  11. package/dist/commands/create-data-type.js +0 -32
  12. package/dist/commands/create-form.d.ts +0 -8
  13. package/dist/commands/create-form.js +0 -32
  14. package/dist/commands/generate.d.ts +0 -3
  15. package/dist/commands/generate.js +0 -164
  16. package/dist/commands/import-schema.d.ts +0 -5
  17. package/dist/commands/import-schema.js +0 -96
  18. package/dist/commands/list-collections.d.ts +0 -1
  19. package/dist/commands/list-collections.js +0 -27
  20. package/dist/commands/list-components.d.ts +0 -1
  21. package/dist/commands/list-components.js +0 -26
  22. package/dist/commands/list-data-types.d.ts +0 -1
  23. package/dist/commands/list-data-types.js +0 -27
  24. package/dist/commands/list-forms.d.ts +0 -1
  25. package/dist/commands/list-forms.js +0 -27
  26. package/dist/commands/sync-components.d.ts +0 -6
  27. package/dist/commands/sync-components.js +0 -42
  28. package/dist/lib/api-client.d.ts +0 -63
  29. package/dist/lib/api-client.js +0 -74
  30. package/src/cli.ts +0 -103
  31. package/src/commands/create-collection.ts +0 -47
  32. package/src/commands/create-data-type.ts +0 -53
  33. package/src/commands/create-form.ts +0 -53
  34. package/src/commands/generate.ts +0 -219
  35. package/src/commands/import-schema.ts +0 -151
  36. package/src/commands/list-collections.ts +0 -30
  37. package/src/commands/list-components.ts +0 -29
  38. package/src/commands/list-data-types.ts +0 -30
  39. package/src/commands/list-forms.ts +0 -30
  40. package/src/commands/sync-components.ts +0 -57
  41. package/src/index.ts +0 -219
  42. package/src/lib/api-client.ts +0 -138
  43. package/tsconfig.json +0 -17
package/README.md CHANGED
@@ -1,95 +1,393 @@
1
- # CMX SDK
1
+ # cmx-sdk
2
2
 
3
- CLI tool for managing CMX schemas and content.
3
+ Official SDK for building content-driven websites with CMX (Content Management Experience).
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
8
  npm install cmx-sdk
9
+ # or
10
+ pnpm add cmx-sdk
11
+ # or
12
+ yarn add cmx-sdk
9
13
  ```
10
14
 
11
- ## Environment Variables
15
+ ## Features
12
16
 
13
- ```bash
14
- CMX_API_URL=https://your-api-url.com
17
+ - Type-Safe API Client - Fetch content from CMX Admin with full TypeScript support
18
+ - MDX Rendering - Server-side MDX compilation with reference resolution
19
+ - MDX Components - Pre-built React components (Callout, Embed, BlogCard, Image, etc.)
20
+ - Next.js Optimized - Built-in support for ISR, caching, and revalidation
21
+ - Customizable - Inject your own custom components into MDX rendering
22
+
23
+ ## Quick Start
24
+
25
+ ### 1. Set up environment variables
26
+
27
+ Create a `.env.local` file:
28
+
29
+ ```env
30
+ CMX_API_URL=https://your-cmx-admin.example.com
15
31
  CMX_API_KEY=your_api_key_here
16
32
  ```
17
33
 
18
- ## Commands
34
+ ### 2. Fetch content
19
35
 
20
- ### create-collection
36
+ ```tsx
37
+ import { getCollectionContents, getCollectionContentDetail } from 'cmx-sdk';
21
38
 
22
- Create a new collection.
39
+ // List contents in a collection
40
+ const { collection, contents } = await getCollectionContents('blog');
23
41
 
24
- ```bash
25
- # Using JSON
26
- cmx-sdk create-collection --json '{"type":"post","slug":"blog","name":"ブログ"}'
42
+ // Get a specific content with references
43
+ const { collection, content, references } = await getCollectionContentDetail('blog', 'my-post');
44
+ ```
45
+
46
+ ### 3. Render MDX content
27
47
 
28
- # Using individual options
29
- cmx-sdk create-collection --type post --slug blog --name ブログ --description "ブログ記事"
48
+ ```tsx
49
+ import { renderMdx } from 'cmx-sdk';
50
+
51
+ // Render MDX with reference resolution (BlogCard, Image, etc.)
52
+ const { rendered } = await renderMdx(content.mdx, references);
53
+ return <article>{rendered}</article>;
54
+
55
+ // With custom components
56
+ import { FeatureCard } from './components/custom';
57
+ const { rendered } = await renderMdx(content.mdx, references, {
58
+ additionalComponents: { FeatureCard },
59
+ });
30
60
  ```
31
61
 
32
- ### create-data-type
62
+ ## API Reference
33
63
 
34
- Create a new data type.
64
+ ### Content Fetching
35
65
 
36
- ```bash
37
- cmx-sdk create-data-type --json '{"slug":"staff","name":"スタッフ","fields":[...]}'
66
+ ```tsx
67
+ import {
68
+ getCollectionContents,
69
+ getCollectionContentDetail,
70
+ getDataEntries,
71
+ getDataEntry,
72
+ getPreviewByToken,
73
+ } from 'cmx-sdk';
74
+
75
+ // Get contents from a collection
76
+ const { contents } = await getCollectionContents('blog');
77
+
78
+ // Get a specific content with resolved references
79
+ const { content, references } = await getCollectionContentDetail('blog', 'my-post');
80
+
81
+ // Get data entries (custom data types)
82
+ const { items } = await getDataEntries('team-members');
83
+
84
+ // Get data entries with options
85
+ const { items } = await getDataEntries('team-members', {
86
+ sortBy: 'createdAt',
87
+ sortOrder: 'desc',
88
+ limit: 10,
89
+ });
90
+
91
+ // Get a specific data entry
92
+ const entry = await getDataEntry('team-members', 'entry-id');
93
+
94
+ // Get preview content by token (no auth required)
95
+ const preview = await getPreviewByToken(token);
96
+ if (preview) {
97
+ const { content } = await renderMdx(preview.content.mdx, preview.references);
98
+ }
99
+ ```
100
+
101
+ ### MDX Rendering
102
+
103
+ ```tsx
104
+ import { renderMdx, renderMdxPreview } from 'cmx-sdk';
105
+
106
+ // Full rendering with reference resolution
107
+ const { content, references } = await renderMdx(item.mdx, item.references);
108
+
109
+ // With custom components injected
110
+ const { content } = await renderMdx(item.mdx, item.references, {
111
+ additionalComponents: { FeatureCard, PricingTable },
112
+ });
113
+
114
+ // Preview rendering (no reference resolution)
115
+ const element = await renderMdxPreview(mdxString);
116
+ ```
117
+
118
+ ### Cache Tags
119
+
120
+ Use Next.js cache tags for on-demand revalidation:
121
+
122
+ ```tsx
123
+ import { CACHE_TAGS, sdkFetchWithTags } from 'cmx-sdk';
124
+
125
+ // Built-in cache tags used by convenience functions:
126
+ // CACHE_TAGS.collections - all collections
127
+ // CACHE_TAGS.collection(slug) - specific collection
128
+ // CACHE_TAGS.content(col, content) - specific content
129
+ // CACHE_TAGS.data - all data types
130
+ // CACHE_TAGS.dataType(slug) - specific data type
131
+
132
+ // Revalidate by tag
133
+ import { revalidateTag } from 'next/cache';
134
+ revalidateTag(CACHE_TAGS.collection('blog'));
135
+
136
+ // Low-level: fetch with custom cache tags
137
+ const data = await sdkFetchWithTags<T>(
138
+ '/collections/blog/contents',
139
+ [CACHE_TAGS.collections, CACHE_TAGS.collection('blog')]
140
+ );
141
+ ```
142
+
143
+ ### Preview Mode
144
+
145
+ ```tsx
146
+ import { getPreviewByToken, renderMdx } from 'cmx-sdk';
147
+
148
+ const preview = await getPreviewByToken(token);
149
+ if (preview) {
150
+ const { content } = await renderMdx(preview.content.mdx, preview.references);
151
+ return <article>{content}</article>;
152
+ }
153
+ ```
154
+
155
+ ## Components
156
+
157
+ The SDK includes MDX components that are automatically available in `renderMdx`:
158
+
159
+ ### Standard Components
160
+
161
+ - `Callout` - Highlighted information boxes (info, warning, error, success)
162
+ - `Embed` - External content embedding (YouTube, Twitter, etc.)
163
+ - `Button` - Interactive buttons
164
+
165
+ ### Reference-Resolving Components
166
+
167
+ These components automatically resolve references from the API response:
168
+
169
+ - `BlogCard` - Linked content cards (resolves content title, slug, description)
170
+ - `Image` - Asset images with variants (resolves URL, alt text, dimensions)
171
+
172
+ ### Component Catalog
173
+
174
+ Access component metadata and validation:
175
+
176
+ ```tsx
177
+ import {
178
+ componentCatalog,
179
+ isValidComponent,
180
+ validateComponentProps,
181
+ validateMdx,
182
+ } from 'cmx-sdk';
183
+
184
+ // Check if a component is valid
185
+ isValidComponent('Callout'); // true
186
+
187
+ // Validate component props
188
+ const result = validateComponentProps('Callout', {
189
+ type: 'info',
190
+ title: 'Note',
191
+ });
192
+
193
+ // Validate entire MDX content
194
+ const validation = validateMdx(mdxString);
38
195
  ```
39
196
 
40
- ### create-form
197
+ ## Code Generation (CLI)
198
+
199
+ Generate typed functions and interfaces from your CMX data types and collections.
41
200
 
42
- Create a new form definition.
201
+ ### Usage
43
202
 
44
203
  ```bash
45
- cmx-sdk create-form --json '{"slug":"contact","name":"お問い合わせ","fields":[...]}'
204
+ npx cmx-sdk generate
46
205
  ```
47
206
 
48
- ### sync-components
207
+ This fetches your workspace's schema from the CMX API and generates TypeScript files in `cmx/generated/`.
49
208
 
50
- Sync custom components.
209
+ ### Options
51
210
 
52
211
  ```bash
53
- # From file
54
- cmx-sdk sync-components --file components.json
212
+ npx cmx-sdk generate --output src/cmx/generated # Custom output directory
213
+ ```
55
214
 
56
- # From JSON string
57
- cmx-sdk sync-components --json '{"components":[...]}'
215
+ ### Requirements
216
+
217
+ Set `CMX_API_URL` and `CMX_API_KEY` in your `.env` or `.env.local`:
218
+
219
+ ```env
220
+ CMX_API_URL=https://your-cmx-admin.example.com
221
+ CMX_API_KEY=your_api_key_here
58
222
  ```
59
223
 
60
- ### import-schema
224
+ ### Generated Output
61
225
 
62
- Import collections, data types, and forms from a schema file.
226
+ ```
227
+ cmx/generated/
228
+ ├── index.ts
229
+ ├── collections/
230
+ │ ├── index.ts
231
+ │ ├── blog.ts # getBlogContents(), getBlogContentDetail()
232
+ │ └── docs.ts # getDocsContents(), getDocsContentDetail()
233
+ └── data-types/
234
+ ├── index.ts
235
+ ├── team-members.ts # TeamMember type, getTeamMembers(), getTeamMember()
236
+ └── faq.ts # Faq type, getFaqs(), getFaq()
237
+ ```
63
238
 
64
- ```bash
65
- cmx-sdk import-schema --file schema.json
66
- ```
67
-
68
- **schema.json format:**
69
-
70
- ```json
71
- {
72
- "collections": [
73
- { "type": "post", "slug": "blog", "name": "ブログ" }
74
- ],
75
- "dataTypes": [
76
- { "slug": "staff", "name": "スタッフ", "fields": [...] }
77
- ],
78
- "forms": [
79
- { "slug": "contact", "name": "お問い合わせ", "fields": [...] }
80
- ]
239
+ ### Using Generated Code
240
+
241
+ ```tsx
242
+ // Before (generic, no type safety)
243
+ import { getDataEntries } from "cmx-sdk"
244
+ const { items } = await getDataEntries("team-members")
245
+ const name = items[0].name // ❌ type is unknown
246
+
247
+ // After (typed, auto-generated)
248
+ import { getTeamMembers } from "./cmx/generated"
249
+ const { items } = await getTeamMembers()
250
+ const name = items[0].name // ✅ type is string
251
+ ```
252
+
253
+ Data type fields are mapped to TypeScript types:
254
+
255
+ | Field Type | TypeScript Type |
256
+ |---|---|
257
+ | text, textarea, richtext, url, email | `string` |
258
+ | number | `number` |
259
+ | boolean | `boolean` |
260
+ | date, datetime | `string` |
261
+ | select (with choices) | `"value1" \| "value2"` |
262
+ | multiselect | `string[]` or union array |
263
+ | image, file | `string` |
264
+ | relation | `string` (or `string[]` if multiple) |
265
+ | json | `unknown` |
266
+
267
+ Non-required fields are typed as `T | null`.
268
+
269
+ ## TypeScript
270
+
271
+ The SDK is fully typed. Import types as needed:
272
+
273
+ ```tsx
274
+ import type {
275
+ // API response types
276
+ CollectionContentsResponse,
277
+ CollectionContentDetailResponse,
278
+ DataListResponse,
279
+ DataEntryItem,
280
+ PreviewResponse,
281
+ References,
282
+ ContentReference,
283
+ AssetReference,
284
+ // Rendering types
285
+ RenderResult,
286
+ RenderOptions,
287
+ ResolvedReferences,
288
+ // Component types
289
+ ComponentDefinition,
290
+ ValidationResult,
291
+ } from 'cmx-sdk';
292
+ ```
293
+
294
+ ## Advanced Usage
295
+
296
+ ### Low-Level Generated Functions
297
+
298
+ For advanced use cases, the SDK also exports the raw Orval-generated endpoint functions:
299
+
300
+ ```tsx
301
+ import {
302
+ getCollectionsSlugContents,
303
+ getCollectionsSlugContentsContentSlug,
304
+ getDataTypeSlug,
305
+ getPreviewToken,
306
+ } from 'cmx-sdk';
307
+
308
+ // These return { data, status, headers } instead of just the data
309
+ const response = await getCollectionsSlugContents('blog');
310
+ if (response.status === 200) {
311
+ const contents = response.data;
81
312
  }
82
313
  ```
83
314
 
84
- ## Development
315
+ ### Direct Fetcher Access
85
316
 
86
- ```bash
87
- # Build
88
- npm run build
317
+ ```tsx
318
+ import {
319
+ sdkFetcher,
320
+ sdkFetchWithTags,
321
+ getSdkApiBaseUrl,
322
+ getSdkApiToken,
323
+ } from 'cmx-sdk';
324
+
325
+ // Use the fetcher directly for custom endpoints
326
+ const data = await sdkFetchWithTags<MyType>('/custom/endpoint', ['my-tag']);
327
+ ```
328
+
329
+ ## Environment Variables
330
+
331
+ | Variable | Description | Required |
332
+ |----------|-------------|----------|
333
+ | `CMX_API_URL` | CMX Admin API base URL | Yes |
334
+ | `CMX_API_KEY` | API key for authentication | Yes |
335
+
336
+ ## Next.js Integration
337
+
338
+ The SDK is optimized for Next.js App Router (Server Components):
339
+
340
+ ```tsx
341
+ // app/blog/[slug]/page.tsx
342
+ import { getCollectionContents, getCollectionContentDetail, renderMdx } from 'cmx-sdk';
89
343
 
90
- # Watch mode
91
- npm run dev
344
+ export default async function BlogContent({
345
+ params,
346
+ }: {
347
+ params: Promise<{ slug: string }>;
348
+ }) {
349
+ const { slug } = await params;
350
+ const { content, references } = await getCollectionContentDetail('blog', slug);
351
+ const { content: rendered } = await renderMdx(content.mdx, references);
92
352
 
93
- # Clean
94
- npm run clean
353
+ return (
354
+ <article>
355
+ <h1>{content.title}</h1>
356
+ <p>{content.description}</p>
357
+ <div className="prose">{rendered}</div>
358
+ </article>
359
+ );
360
+ }
361
+
362
+ export async function generateStaticParams() {
363
+ const { contents } = await getCollectionContents('blog');
364
+ return contents.map((item) => ({ slug: item.slug }));
365
+ }
366
+
367
+ export async function generateMetadata({
368
+ params,
369
+ }: {
370
+ params: Promise<{ slug: string }>;
371
+ }) {
372
+ const { slug } = await params;
373
+ const { content } = await getCollectionContentDetail('blog', slug);
374
+ return {
375
+ title: content.title,
376
+ description: content.description,
377
+ };
378
+ }
95
379
  ```
380
+
381
+ ## Examples
382
+
383
+ Check out the [CMX Starter Kit](https://github.com/kzkm-lab/cmx-starter-kit) for a complete example of using the SDK.
384
+
385
+ ## License
386
+
387
+ MIT
388
+
389
+ ## Links
390
+
391
+ - [Documentation](https://github.com/kzkm-lab/cmx)
392
+ - [CMX Starter Kit](https://github.com/kzkm-lab/cmx-starter-kit)
393
+ - [Issues](https://github.com/kzkm-lab/cmx/issues)