@unchainedshop/cockpit-api 2.2.0 → 2.2.2
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 +173 -10
- package/dist/client.d.ts +6 -6
- package/dist/fetch/client.d.ts +5 -5
- package/dist/fetch/client.js +18 -2
- package/dist/index.d.ts +1 -1
- package/dist/methods/assets.d.ts +17 -7
- package/dist/methods/content.d.ts +34 -2
- package/dist/methods/content.js +9 -1
- package/dist/methods/pages.d.ts +14 -2
- package/dist/methods/pages.js +12 -1
- package/dist/methods/routes.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -103,13 +103,17 @@ const localizedPost = await cockpit.getContentItem({
|
|
|
103
103
|
queryParams: { fields: { title: 1, content: 1 } }
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
// Get multiple content items
|
|
107
|
-
const
|
|
106
|
+
// Get multiple content items - always returns { data, meta? }
|
|
107
|
+
const response = await cockpit.getContentItems('posts', {
|
|
108
108
|
limit: 10,
|
|
109
|
-
skip: 0,
|
|
110
109
|
sort: { _created: -1 },
|
|
111
110
|
filter: { published: true }
|
|
112
111
|
});
|
|
112
|
+
// response: { data: Post[], meta?: { total: number } } | null
|
|
113
|
+
|
|
114
|
+
// Access items and metadata
|
|
115
|
+
const items = response?.data || [];
|
|
116
|
+
const total = response?.meta?.total;
|
|
113
117
|
|
|
114
118
|
// Get tree structure
|
|
115
119
|
const tree = await cockpit.getContentTree('categories', {
|
|
@@ -133,8 +137,10 @@ await cockpit.deleteContentItem('posts', '123');
|
|
|
133
137
|
### Pages
|
|
134
138
|
|
|
135
139
|
```typescript
|
|
136
|
-
// List pages
|
|
137
|
-
const
|
|
140
|
+
// List pages - always returns { data, meta? }
|
|
141
|
+
const response = await cockpit.pages({ locale: 'en', limit: 50 });
|
|
142
|
+
const allPages = response?.data || [];
|
|
143
|
+
const total = response?.meta?.total;
|
|
138
144
|
|
|
139
145
|
// Get page by ID
|
|
140
146
|
const page = await cockpit.pageById({ page: 'blog', id: '123', locale: 'en' });
|
|
@@ -206,9 +212,9 @@ const image = await cockpit.imageAssetById('asset-id', {
|
|
|
206
212
|
// Health check
|
|
207
213
|
const health = await cockpit.healthCheck();
|
|
208
214
|
|
|
209
|
-
// Clear cache
|
|
210
|
-
cockpit.clearCache(); // Clear all
|
|
211
|
-
cockpit.clearCache('pages'); // Clear by pattern
|
|
215
|
+
// Clear cache (async in v2.2.0+)
|
|
216
|
+
await cockpit.clearCache(); // Clear all
|
|
217
|
+
await cockpit.clearCache('pages'); // Clear by pattern
|
|
212
218
|
```
|
|
213
219
|
|
|
214
220
|
## Lightweight Fetch Client API
|
|
@@ -228,9 +234,16 @@ const cockpit = createFetchClient({
|
|
|
228
234
|
|
|
229
235
|
// Available methods
|
|
230
236
|
const page = await cockpit.pageByRoute('/about', { locale: 'en' });
|
|
231
|
-
|
|
237
|
+
|
|
238
|
+
// List methods return { data, meta? }
|
|
239
|
+
const pagesResponse = await cockpit.pages({ locale: 'en' });
|
|
240
|
+
const pages = pagesResponse?.data || [];
|
|
241
|
+
|
|
232
242
|
const pageById = await cockpit.pageById('blog', '123', { locale: 'en' });
|
|
233
|
-
|
|
243
|
+
|
|
244
|
+
const itemsResponse = await cockpit.getContentItems('news', { locale: 'en', limit: 10 });
|
|
245
|
+
const items = itemsResponse?.data || [];
|
|
246
|
+
|
|
234
247
|
const item = await cockpit.getContentItem('news', '123', { locale: 'en' });
|
|
235
248
|
const custom = await cockpit.fetchRaw('/custom/endpoint', { param: 'value' });
|
|
236
249
|
```
|
|
@@ -275,7 +288,10 @@ const cockpit = await CockpitAPI({
|
|
|
275
288
|
cache: {
|
|
276
289
|
max: 100, // Falls back to COCKPIT_CACHE_MAX (default: 100)
|
|
277
290
|
ttl: 100000, // Falls back to COCKPIT_CACHE_TTL (default: 100000)
|
|
291
|
+
store: customStore, // Optional: custom async cache store (Redis, Keyv, etc.)
|
|
278
292
|
},
|
|
293
|
+
// Or disable caching entirely
|
|
294
|
+
// cache: false,
|
|
279
295
|
});
|
|
280
296
|
```
|
|
281
297
|
|
|
@@ -305,6 +321,79 @@ const { tenant, slug } = resolveTenantFromUrl('https://mytenant.example.com/page
|
|
|
305
321
|
const allTenants = getTenantIds(); // From COCKPIT_SECRET_* env vars
|
|
306
322
|
```
|
|
307
323
|
|
|
324
|
+
## Custom Cache Stores
|
|
325
|
+
|
|
326
|
+
v2.2.0+ supports pluggable async cache stores for Redis, Keyv, or custom implementations:
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
import { createClient } from 'redis';
|
|
330
|
+
import type { AsyncCacheStore } from '@unchainedshop/cockpit-api';
|
|
331
|
+
|
|
332
|
+
// Redis example
|
|
333
|
+
const redisClient = createClient({ url: process.env.REDIS_URL });
|
|
334
|
+
await redisClient.connect();
|
|
335
|
+
|
|
336
|
+
const redisStore: AsyncCacheStore = {
|
|
337
|
+
async get(key: string) {
|
|
338
|
+
const value = await redisClient.get(key);
|
|
339
|
+
return value ? JSON.parse(value) : undefined;
|
|
340
|
+
},
|
|
341
|
+
async set(key: string, value: unknown) {
|
|
342
|
+
await redisClient.set(key, JSON.stringify(value), { EX: 100 });
|
|
343
|
+
},
|
|
344
|
+
async clear(pattern?: string) {
|
|
345
|
+
if (pattern) {
|
|
346
|
+
const keys = await redisClient.keys(`${pattern}*`);
|
|
347
|
+
if (keys.length > 0) await redisClient.del(keys);
|
|
348
|
+
} else {
|
|
349
|
+
await redisClient.flushDb();
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
const cockpit = await CockpitAPI({
|
|
355
|
+
endpoint: 'https://cms.example.com/api/graphql',
|
|
356
|
+
cache: { store: redisStore }
|
|
357
|
+
});
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Response Format (v3.0.0+)
|
|
361
|
+
|
|
362
|
+
All list methods return a **consistent response format** regardless of parameters:
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
interface CockpitListResponse<T> {
|
|
366
|
+
data: T[];
|
|
367
|
+
meta?: CockpitListMeta; // Present when using pagination (skip parameter)
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Methods with Consistent Response Format
|
|
372
|
+
|
|
373
|
+
- `getContentItems()` - Always returns `CockpitListResponse<T> | null`
|
|
374
|
+
- `pages()` - Always returns `CockpitListResponse<T> | null`
|
|
375
|
+
- Fetch client methods - Always return `CockpitListResponse<T> | null`
|
|
376
|
+
|
|
377
|
+
### Usage Example
|
|
378
|
+
|
|
379
|
+
```typescript
|
|
380
|
+
import type { CockpitListResponse } from '@unchainedshop/cockpit-api';
|
|
381
|
+
|
|
382
|
+
// Always get { data, meta? } format
|
|
383
|
+
const response = await cockpit.getContentItems('posts', { limit: 10, skip: 0 });
|
|
384
|
+
|
|
385
|
+
// Access items
|
|
386
|
+
const items = response?.data || [];
|
|
387
|
+
|
|
388
|
+
// Access metadata (available when using skip parameter)
|
|
389
|
+
const total = response?.meta?.total;
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
**Benefits:**
|
|
393
|
+
- No need to check if response is array or object
|
|
394
|
+
- Predictable type signatures
|
|
395
|
+
- Easier to work with pagination
|
|
396
|
+
|
|
308
397
|
## TypeScript Support
|
|
309
398
|
|
|
310
399
|
```typescript
|
|
@@ -314,6 +403,7 @@ import type {
|
|
|
314
403
|
CockpitAPIOptions,
|
|
315
404
|
CacheManager,
|
|
316
405
|
CacheOptions,
|
|
406
|
+
AsyncCacheStore,
|
|
317
407
|
|
|
318
408
|
// Query Options
|
|
319
409
|
ContentItemQueryOptions,
|
|
@@ -330,6 +420,8 @@ import type {
|
|
|
330
420
|
CockpitRoute,
|
|
331
421
|
CockpitSearchResult,
|
|
332
422
|
CockpitContentItem,
|
|
423
|
+
CockpitListResponse, // New: for paginated content responses
|
|
424
|
+
CockpitListMeta, // New: metadata in paginated responses
|
|
333
425
|
|
|
334
426
|
// Schema Types
|
|
335
427
|
MakeCockpitSchemaOptions,
|
|
@@ -360,6 +452,77 @@ import { ImageSizeMode, MimeType } from '@unchainedshop/cockpit-api';
|
|
|
360
452
|
- `defaultLanguage` option to configure which language maps to Cockpit's "default" locale
|
|
361
453
|
- Expanded tenant utilities: `resolveTenantFromUrl()`, `resolveTenantFromSubdomain()`
|
|
362
454
|
|
|
455
|
+
### v2.2.0 (Breaking Changes)
|
|
456
|
+
|
|
457
|
+
**Async Cache Operations:**
|
|
458
|
+
- All cache operations are now async and return Promises
|
|
459
|
+
- `await cockpit.clearCache()` is now required (was synchronous in v2.1.x)
|
|
460
|
+
- Custom cache stores can be provided via `cache.store` option
|
|
461
|
+
- Cache can be explicitly disabled with `cache: false`
|
|
462
|
+
|
|
463
|
+
**Migration:**
|
|
464
|
+
```typescript
|
|
465
|
+
// Before (v2.1.x)
|
|
466
|
+
cockpit.clearCache();
|
|
467
|
+
cockpit.clearCache('ROUTE');
|
|
468
|
+
|
|
469
|
+
// After (v2.2.0)
|
|
470
|
+
await cockpit.clearCache();
|
|
471
|
+
await cockpit.clearCache('ROUTE');
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
### v3.0.0 (Breaking Changes)
|
|
475
|
+
|
|
476
|
+
**Consistent List Response Format:**
|
|
477
|
+
|
|
478
|
+
All list methods now return `CockpitListResponse<T> | null` instead of varying between arrays and wrapped responses:
|
|
479
|
+
|
|
480
|
+
**Changed Methods:**
|
|
481
|
+
- `getContentItems()` - Now always returns `{ data: T[], meta?: {...} } | null`
|
|
482
|
+
- `pages()` - Now always returns `{ data: T[], meta?: {...} } | null`
|
|
483
|
+
- Fetch client `getContentItems()` and `pages()` - Now always return `{ data: T[], meta?: {...} } | null`
|
|
484
|
+
|
|
485
|
+
**Migration:**
|
|
486
|
+
```typescript
|
|
487
|
+
// Before (v2.x)
|
|
488
|
+
const items = await cockpit.getContentItems('posts', { limit: 10 });
|
|
489
|
+
// items could be Post[] or null
|
|
490
|
+
|
|
491
|
+
const pages = await cockpit.pages({ limit: 10 });
|
|
492
|
+
// pages could be Page[] or null
|
|
493
|
+
|
|
494
|
+
// After (v3.0.0)
|
|
495
|
+
const itemsResponse = await cockpit.getContentItems('posts', { limit: 10 });
|
|
496
|
+
const items = itemsResponse?.data || [];
|
|
497
|
+
const total = itemsResponse?.meta?.total;
|
|
498
|
+
|
|
499
|
+
const pagesResponse = await cockpit.pages({ limit: 10 });
|
|
500
|
+
const pages = pagesResponse?.data || [];
|
|
501
|
+
const total = pagesResponse?.meta?.total;
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
**Benefits:**
|
|
505
|
+
- Single, predictable return type for all list methods
|
|
506
|
+
- No need to check `Array.isArray()` or normalize responses
|
|
507
|
+
- Cleaner TypeScript types
|
|
508
|
+
- Metadata always accessible via `.meta` property
|
|
509
|
+
|
|
510
|
+
**TreeQueryOptions Type Correction:**
|
|
511
|
+
|
|
512
|
+
`TreeQueryOptions` no longer incorrectly includes `limit` and `skip` parameters (which were always ignored). Tree structures use `parent`, `populate`, `filter`, and `fields` instead.
|
|
513
|
+
|
|
514
|
+
```typescript
|
|
515
|
+
// Before (v2.x) - allowed but ignored
|
|
516
|
+
await cockpit.getContentTree('categories', { limit: 10 }); // ❌ TypeScript allowed this
|
|
517
|
+
|
|
518
|
+
// After (v3.0.0) - TypeScript prevents invalid usage
|
|
519
|
+
await cockpit.getContentTree('categories', {
|
|
520
|
+
parent: 'root-id', // ✅ Correct
|
|
521
|
+
populate: 2, // ✅ Correct
|
|
522
|
+
filter: { active: true } // ✅ Correct
|
|
523
|
+
});
|
|
524
|
+
```
|
|
525
|
+
|
|
363
526
|
## Peer Dependencies
|
|
364
527
|
|
|
365
528
|
- `graphql` (optional) - Required for the `graphQL()` method
|
package/dist/client.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { DocumentNode } from "graphql";
|
|
5
5
|
import { type CockpitAPIOptions } from "./core/config.ts";
|
|
6
|
-
import { type ContentItemQueryOptions, type ContentListQueryOptions, type TreeQueryOptions, type AggregateQueryOptions, type CockpitContentItem, type CockpitTreeNode } from "./methods/content.ts";
|
|
6
|
+
import { type ContentItemQueryOptions, type ContentListQueryOptions, type TreeQueryOptions, type AggregateQueryOptions, type CockpitContentItem, type CockpitTreeNode, type CockpitListResponse } from "./methods/content.ts";
|
|
7
7
|
import { type PageByIdOptions, type CockpitPage } from "./methods/pages.ts";
|
|
8
8
|
import { type MenuQueryOptions, type CockpitMenu } from "./methods/menus.ts";
|
|
9
9
|
import { type CockpitRoutesResponse, type CockpitSitemapEntry, type CockpitSettings } from "./methods/routes.ts";
|
|
@@ -16,12 +16,12 @@ import { type LocalizeOptions } from "./methods/localize.ts";
|
|
|
16
16
|
export interface CockpitAPIClient {
|
|
17
17
|
graphQL<T = unknown>(document: DocumentNode, variables?: Record<string, unknown>): Promise<T | null>;
|
|
18
18
|
getContentItem<T = unknown>(options: ContentItemQueryOptions): Promise<T | null>;
|
|
19
|
-
getContentItems<T = CockpitContentItem>(model: string, options?: ContentListQueryOptions): Promise<T
|
|
19
|
+
getContentItems<T = CockpitContentItem>(model: string, options?: ContentListQueryOptions): Promise<CockpitListResponse<T> | null>;
|
|
20
20
|
getContentTree<T = CockpitContentItem>(model: string, options?: TreeQueryOptions): Promise<CockpitTreeNode<T>[] | null>;
|
|
21
21
|
getAggregateModel<T = unknown>(options: AggregateQueryOptions): Promise<T[] | null>;
|
|
22
22
|
postContentItem<T = unknown>(model: string, item: Record<string, unknown>): Promise<T | null>;
|
|
23
23
|
deleteContentItem<T = unknown>(model: string, id: string): Promise<T | null>;
|
|
24
|
-
pages<T = CockpitPage>(options?: ContentListQueryOptions): Promise<T
|
|
24
|
+
pages<T = CockpitPage>(options?: ContentListQueryOptions): Promise<CockpitListResponse<T> | null>;
|
|
25
25
|
pageById<T = CockpitPage>(id: string, options?: PageByIdOptions): Promise<T | null>;
|
|
26
26
|
pageByRoute<T = CockpitPage>(route: string, options?: {
|
|
27
27
|
locale?: string;
|
|
@@ -39,14 +39,14 @@ export interface CockpitAPIClient {
|
|
|
39
39
|
/**
|
|
40
40
|
* Get a transformed image asset URL.
|
|
41
41
|
*
|
|
42
|
-
* **Important:**
|
|
43
|
-
*
|
|
42
|
+
* **Important:** At least one of `w` (width) or `h` (height) must be provided.
|
|
43
|
+
* The Cockpit CMS API requires this and returns a 400 error without it.
|
|
44
44
|
*
|
|
45
45
|
* @param assetId - The asset ID
|
|
46
46
|
* @param queryParams - Image transformation parameters (w or h required)
|
|
47
47
|
* @returns URL string to the generated image, or null if not found
|
|
48
48
|
*/
|
|
49
|
-
imageAssetById(assetId: string, queryParams
|
|
49
|
+
imageAssetById(assetId: string, queryParams: ImageAssetQueryParams): Promise<string | null>;
|
|
50
50
|
getFullRouteForSlug(slug: string): Promise<string | undefined>;
|
|
51
51
|
/**
|
|
52
52
|
* Clear cache entries matching pattern
|
package/dist/fetch/client.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - Minimal memory footprint
|
|
10
10
|
*/
|
|
11
11
|
import type { CockpitPage } from "../methods/pages.ts";
|
|
12
|
-
import type { CockpitContentItem } from "../methods/content.ts";
|
|
12
|
+
import type { CockpitContentItem, CockpitListResponse } from "../methods/content.ts";
|
|
13
13
|
/**
|
|
14
14
|
* Request cache mode for fetch requests
|
|
15
15
|
*/
|
|
@@ -52,12 +52,12 @@ export interface PageFetchParams {
|
|
|
52
52
|
export interface FetchClient {
|
|
53
53
|
/** Fetch a page by route */
|
|
54
54
|
pageByRoute<T = CockpitPage>(route: string, params?: PageFetchParams): Promise<T | null>;
|
|
55
|
-
/** Fetch pages list */
|
|
56
|
-
pages<T = CockpitPage>(params?: PageFetchParams): Promise<T
|
|
55
|
+
/** Fetch pages list. Always returns { data, meta? } or null. */
|
|
56
|
+
pages<T = CockpitPage>(params?: PageFetchParams): Promise<CockpitListResponse<T> | null>;
|
|
57
57
|
/** Fetch a page by ID */
|
|
58
58
|
pageById<T = CockpitPage>(id: string, params?: PageFetchParams): Promise<T | null>;
|
|
59
|
-
/** Fetch content items */
|
|
60
|
-
getContentItems<T = CockpitContentItem>(model: string, params?: PageFetchParams): Promise<T
|
|
59
|
+
/** Fetch content items. Always returns { data, meta? } or null. */
|
|
60
|
+
getContentItems<T = CockpitContentItem>(model: string, params?: PageFetchParams): Promise<CockpitListResponse<T> | null>;
|
|
61
61
|
/** Fetch a single content item */
|
|
62
62
|
getContentItem<T = unknown>(model: string, id?: string, params?: PageFetchParams): Promise<T | null>;
|
|
63
63
|
/** Raw fetch for custom paths */
|
package/dist/fetch/client.js
CHANGED
|
@@ -96,10 +96,18 @@ export function createFetchClient(options = {}) {
|
|
|
96
96
|
*/
|
|
97
97
|
async pages(params = {}) {
|
|
98
98
|
const { locale, ...rest } = params;
|
|
99
|
-
|
|
99
|
+
const result = await fetchRaw("/pages/pages", {
|
|
100
100
|
locale: normalizeLocale(locale),
|
|
101
101
|
...rest,
|
|
102
102
|
});
|
|
103
|
+
// Normalize response to always return { data, meta? }
|
|
104
|
+
if (result === null) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
if (Array.isArray(result)) {
|
|
108
|
+
return { data: result };
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
103
111
|
},
|
|
104
112
|
/**
|
|
105
113
|
* Fetch a page by ID
|
|
@@ -117,10 +125,18 @@ export function createFetchClient(options = {}) {
|
|
|
117
125
|
*/
|
|
118
126
|
async getContentItems(model, params = {}) {
|
|
119
127
|
const { locale, ...rest } = params;
|
|
120
|
-
|
|
128
|
+
const result = await fetchRaw(`/content/items/${model}`, {
|
|
121
129
|
locale: normalizeLocale(locale),
|
|
122
130
|
...rest,
|
|
123
131
|
});
|
|
132
|
+
// Normalize response to always return { data, meta? }
|
|
133
|
+
if (result === null) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
if (Array.isArray(result)) {
|
|
137
|
+
return { data: result };
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
124
140
|
},
|
|
125
141
|
/**
|
|
126
142
|
* Fetch a single content item
|
package/dist/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export type { PageByIdOptions, PageByRouteOptions } from "./methods/pages.ts";
|
|
|
18
18
|
export type { MenuQueryOptions } from "./methods/menus.ts";
|
|
19
19
|
export type { SearchQueryOptions } from "./methods/search.ts";
|
|
20
20
|
export type { LocalizeOptions } from "./methods/localize.ts";
|
|
21
|
-
export type { CockpitContentItem, CockpitNewsItem, CockpitTreeNode, } from "./methods/content.ts";
|
|
21
|
+
export type { CockpitContentItem, CockpitNewsItem, CockpitTreeNode, CockpitListResponse, CockpitListMeta, } from "./methods/content.ts";
|
|
22
22
|
export { ImageSizeMode, MimeType } from "./methods/assets.ts";
|
|
23
23
|
export type { CockpitAsset, ImageAssetQueryParams } from "./methods/assets.ts";
|
|
24
24
|
export type { CockpitPageType, CockpitPageMeta, CockpitPageSeo, CockpitLayoutBlock, CockpitPage, } from "./methods/pages.ts";
|
package/dist/methods/assets.d.ts
CHANGED
|
@@ -38,28 +38,38 @@ export declare enum MimeType {
|
|
|
38
38
|
WEBP = "webp",
|
|
39
39
|
BMP = "bmp"
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Image transformation parameters for imageAssetById.
|
|
43
|
+
*
|
|
44
|
+
* At least one of `w` (width) or `h` (height) must be provided.
|
|
45
|
+
* The Cockpit CMS API requires this and returns a 400 error without it.
|
|
46
|
+
*/
|
|
47
|
+
export type ImageAssetQueryParams = {
|
|
42
48
|
m?: ImageSizeMode;
|
|
43
|
-
w?: number;
|
|
44
|
-
h?: number;
|
|
45
49
|
q?: number;
|
|
46
50
|
mime?: MimeType;
|
|
47
51
|
re?: number;
|
|
48
52
|
t?: string;
|
|
49
53
|
o?: number;
|
|
50
|
-
}
|
|
54
|
+
} & ({
|
|
55
|
+
w: number;
|
|
56
|
+
h?: number;
|
|
57
|
+
} | {
|
|
58
|
+
w?: number;
|
|
59
|
+
h: number;
|
|
60
|
+
});
|
|
51
61
|
export interface AssetMethods {
|
|
52
62
|
assetById<T = CockpitAsset>(assetId: string): Promise<T | null>;
|
|
53
63
|
/**
|
|
54
64
|
* Get a transformed image asset URL.
|
|
55
65
|
*
|
|
56
|
-
* **Important:**
|
|
57
|
-
*
|
|
66
|
+
* **Important:** At least one of `w` (width) or `h` (height) must be provided.
|
|
67
|
+
* The Cockpit CMS API requires this and returns a 400 error without it.
|
|
58
68
|
*
|
|
59
69
|
* @param assetId - The asset ID
|
|
60
70
|
* @param queryParams - Image transformation parameters (w or h required)
|
|
61
71
|
* @returns URL string to the generated image, or null if not found
|
|
62
72
|
*/
|
|
63
|
-
imageAssetById(assetId: string, queryParams
|
|
73
|
+
imageAssetById(assetId: string, queryParams: ImageAssetQueryParams): Promise<string | null>;
|
|
64
74
|
}
|
|
65
75
|
export declare function createAssetMethods(ctx: MethodContext): AssetMethods;
|
|
@@ -30,9 +30,15 @@ export interface ContentItemQueryOptions extends ListQueryOptions {
|
|
|
30
30
|
export interface ContentListQueryOptions extends ListQueryOptions {
|
|
31
31
|
queryParams?: Record<string, unknown>;
|
|
32
32
|
}
|
|
33
|
-
export interface TreeQueryOptions
|
|
33
|
+
export interface TreeQueryOptions {
|
|
34
34
|
parent?: string;
|
|
35
|
+
filter?: Record<string, unknown>;
|
|
36
|
+
fields?: Record<string, 0 | 1>;
|
|
37
|
+
populate?: number;
|
|
38
|
+
locale?: string;
|
|
35
39
|
queryParams?: Record<string, unknown>;
|
|
40
|
+
/** Override the client-level useAdminAccess setting for this request */
|
|
41
|
+
useAdminAccess?: boolean;
|
|
36
42
|
}
|
|
37
43
|
export interface AggregateQueryOptions {
|
|
38
44
|
model: string;
|
|
@@ -66,9 +72,35 @@ export interface CockpitTreeNode<T = CockpitContentItem> {
|
|
|
66
72
|
children?: CockpitTreeNode<T>[];
|
|
67
73
|
data?: T;
|
|
68
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Metadata returned with paginated content responses
|
|
77
|
+
*/
|
|
78
|
+
export interface CockpitListMeta {
|
|
79
|
+
total?: number;
|
|
80
|
+
[key: string]: unknown;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Wrapper response format returned by Cockpit when using pagination (skip parameter)
|
|
84
|
+
*/
|
|
85
|
+
export interface CockpitListResponse<T> {
|
|
86
|
+
data: T[];
|
|
87
|
+
meta?: CockpitListMeta;
|
|
88
|
+
}
|
|
69
89
|
export interface ContentMethods {
|
|
70
90
|
getContentItem<T = unknown>(options: ContentItemQueryOptions): Promise<T | null>;
|
|
71
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Get multiple content items from a collection.
|
|
93
|
+
*
|
|
94
|
+
* @returns Always returns `CockpitListResponse<T>` with data and optional meta.
|
|
95
|
+
* Returns `null` if collection doesn't exist.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* const response = await cockpit.getContentItems('posts', { limit: 10 });
|
|
99
|
+
* // response: { data: Post[], meta?: { total: number } } | null
|
|
100
|
+
* const items = response?.data || [];
|
|
101
|
+
* const total = response?.meta?.total;
|
|
102
|
+
*/
|
|
103
|
+
getContentItems<T = CockpitContentItem>(model: string, options?: ContentListQueryOptions): Promise<CockpitListResponse<T> | null>;
|
|
72
104
|
getContentTree<T = CockpitContentItem>(model: string, options?: TreeQueryOptions): Promise<CockpitTreeNode<T>[] | null>;
|
|
73
105
|
getAggregateModel<T = unknown>(options: AggregateQueryOptions): Promise<T[] | null>;
|
|
74
106
|
postContentItem<T = unknown>(model: string, item: Record<string, unknown>): Promise<T | null>;
|
package/dist/methods/content.js
CHANGED
|
@@ -33,7 +33,15 @@ export function createContentMethods(ctx) {
|
|
|
33
33
|
populate,
|
|
34
34
|
},
|
|
35
35
|
});
|
|
36
|
-
|
|
36
|
+
const result = await ctx.http.fetch(url, buildFetchOptions(useAdminAccess));
|
|
37
|
+
// Normalize response to always return { data, meta? }
|
|
38
|
+
if (result === null) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (Array.isArray(result)) {
|
|
42
|
+
return { data: result };
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
37
45
|
},
|
|
38
46
|
async getContentTree(model, options = {}) {
|
|
39
47
|
requireParam(model, "a model");
|
package/dist/methods/pages.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pages API methods
|
|
3
3
|
*/
|
|
4
|
-
import type { MethodContext, ContentListQueryOptions } from "./content.ts";
|
|
4
|
+
import type { MethodContext, ContentListQueryOptions, CockpitListResponse } from "./content.ts";
|
|
5
5
|
import type { CockpitAsset } from "./assets.ts";
|
|
6
6
|
export interface PageByIdOptions {
|
|
7
7
|
locale?: string;
|
|
@@ -42,7 +42,19 @@ export interface CockpitPage extends CockpitPageMeta {
|
|
|
42
42
|
_p?: string;
|
|
43
43
|
}
|
|
44
44
|
export interface PagesMethods {
|
|
45
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Get pages list.
|
|
47
|
+
*
|
|
48
|
+
* @returns Always returns `CockpitListResponse<T>` with data and optional meta.
|
|
49
|
+
* Returns `null` if pages cannot be fetched.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* const response = await cockpit.pages({ limit: 10, skip: 0 });
|
|
53
|
+
* // response: { data: CockpitPage[], meta?: { total: number } } | null
|
|
54
|
+
* const pages = response?.data || [];
|
|
55
|
+
* const total = response?.meta?.total;
|
|
56
|
+
*/
|
|
57
|
+
pages<T = CockpitPage>(options?: ContentListQueryOptions): Promise<CockpitListResponse<T> | null>;
|
|
46
58
|
pageById<T = CockpitPage>(id: string, options?: PageByIdOptions): Promise<T | null>;
|
|
47
59
|
pageByRoute<T = CockpitPage>(route: string, options?: PageByRouteOptions | string): Promise<T | null>;
|
|
48
60
|
}
|
package/dist/methods/pages.js
CHANGED
|
@@ -10,7 +10,18 @@ export function createPagesMethods(ctx) {
|
|
|
10
10
|
locale,
|
|
11
11
|
queryParams: { ...queryParams, limit, skip, sort, filter, fields },
|
|
12
12
|
});
|
|
13
|
-
|
|
13
|
+
const result = await ctx.http.fetch(url);
|
|
14
|
+
// Normalize response to always return { data, meta? }
|
|
15
|
+
// Note: The Cockpit /api/pages/pages endpoint returns a raw array even when skip
|
|
16
|
+
// is provided, unlike /api/content/items/{model} which returns { data, meta }.
|
|
17
|
+
// This means meta.total will not be available for pages() method.
|
|
18
|
+
if (result === null) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
if (Array.isArray(result)) {
|
|
22
|
+
return { data: result };
|
|
23
|
+
}
|
|
24
|
+
return result;
|
|
14
25
|
},
|
|
15
26
|
async pageById(id, options = {}) {
|
|
16
27
|
requireParam(id, "a page id");
|
package/dist/methods/routes.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export interface CockpitSettings {
|
|
|
28
28
|
logo?: CockpitAsset | null;
|
|
29
29
|
small?: CockpitAsset | null;
|
|
30
30
|
favicon?: CockpitAsset | null;
|
|
31
|
-
[key: string]: CockpitAsset | null
|
|
31
|
+
[key: string]: CockpitAsset | null;
|
|
32
32
|
};
|
|
33
33
|
scripts?: {
|
|
34
34
|
header?: string | null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unchainedshop/cockpit-api",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "A package to interact with the Cockpit CMS API, including functionalities to handle GraphQL requests and various CMS content manipulations.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"homepage": "https://unchained.shop",
|