@unchainedshop/cockpit-api 1.0.34 → 2.1.1

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 (72) hide show
  1. package/README.md +330 -65
  2. package/dist/client.d.ts +72 -0
  3. package/dist/client.js +101 -0
  4. package/dist/cockpit-logger.d.ts +8 -5
  5. package/dist/cockpit-logger.js +7 -20
  6. package/dist/core/cache.d.ts +19 -0
  7. package/dist/core/cache.js +32 -0
  8. package/dist/core/config.d.ts +44 -0
  9. package/dist/core/config.js +32 -0
  10. package/dist/core/http.d.ts +34 -0
  11. package/dist/core/http.js +98 -0
  12. package/dist/core/index.d.ts +14 -0
  13. package/dist/core/index.js +10 -0
  14. package/dist/core/locale.d.ts +11 -0
  15. package/dist/core/locale.js +19 -0
  16. package/dist/core/query-string.d.ts +18 -0
  17. package/dist/core/query-string.js +20 -0
  18. package/dist/core/url-builder.d.ts +22 -0
  19. package/dist/core/url-builder.js +35 -0
  20. package/dist/core/validation.d.ts +13 -0
  21. package/dist/core/validation.js +22 -0
  22. package/dist/fetch/client.d.ts +85 -0
  23. package/dist/fetch/client.js +143 -0
  24. package/dist/fetch/index.d.ts +19 -0
  25. package/dist/fetch/index.js +18 -0
  26. package/dist/index.d.ts +28 -2
  27. package/dist/index.js +13 -2
  28. package/dist/methods/assets.d.ts +65 -0
  29. package/dist/methods/assets.js +37 -0
  30. package/dist/methods/content.d.ts +77 -0
  31. package/dist/methods/content.js +79 -0
  32. package/dist/methods/graphql.d.ts +9 -0
  33. package/dist/methods/graphql.js +13 -0
  34. package/dist/methods/index.d.ts +22 -0
  35. package/dist/methods/index.js +12 -0
  36. package/dist/methods/localize.d.ts +12 -0
  37. package/dist/methods/localize.js +17 -0
  38. package/dist/methods/menus.d.ts +42 -0
  39. package/dist/methods/menus.js +25 -0
  40. package/dist/methods/pages.d.ts +49 -0
  41. package/dist/methods/pages.js +34 -0
  42. package/dist/methods/routes.d.ts +46 -0
  43. package/dist/methods/routes.js +24 -0
  44. package/dist/methods/search.d.ts +27 -0
  45. package/dist/methods/search.js +16 -0
  46. package/dist/methods/system.d.ts +15 -0
  47. package/dist/methods/system.js +14 -0
  48. package/dist/schema/executor.d.ts +67 -0
  49. package/dist/schema/executor.js +81 -0
  50. package/dist/schema/index.d.ts +26 -0
  51. package/dist/schema/index.js +26 -0
  52. package/dist/schema/schema-builder.d.ts +42 -0
  53. package/dist/schema/schema-builder.js +77 -0
  54. package/dist/transformers/asset-path.d.ts +20 -0
  55. package/dist/transformers/asset-path.js +40 -0
  56. package/dist/transformers/compose.d.ts +9 -0
  57. package/dist/transformers/compose.js +14 -0
  58. package/dist/transformers/image-path.d.ts +28 -0
  59. package/dist/transformers/image-path.js +60 -0
  60. package/dist/transformers/index.d.ts +8 -0
  61. package/dist/transformers/index.js +9 -0
  62. package/dist/transformers/page-link.d.ts +18 -0
  63. package/dist/transformers/page-link.js +45 -0
  64. package/dist/utils/index.d.ts +5 -0
  65. package/dist/utils/index.js +5 -0
  66. package/dist/utils/route-map.d.ts +12 -0
  67. package/dist/utils/route-map.js +86 -0
  68. package/dist/utils/tenant.d.ts +71 -0
  69. package/dist/utils/tenant.js +88 -0
  70. package/package.json +49 -7
  71. package/dist/api.d.ts +0 -69
  72. package/dist/api.js +0 -303
package/README.md CHANGED
@@ -1,36 +1,80 @@
1
1
  # Cockpit API
2
2
 
3
- A package to interact with the Cockpit CMS API, including functionalities to handle GraphQL requests and various CMS content manipulations.
4
- ## Installation
3
+ [![npm version](https://img.shields.io/npm/v/@unchainedshop/cockpit-api.svg)](https://www.npmjs.com/package/@unchainedshop/cockpit-api)
4
+ [![CI](https://github.com/unchainedshop/cockpit-api/actions/workflows/ci.yml/badge.svg)](https://github.com/unchainedshop/cockpit-api/actions/workflows/ci.yml)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](https://nodejs.org/)
7
+
8
+ A TypeScript client for interacting with [Cockpit CMS](https://github.com/Cockpit-HQ/Cockpit), including GraphQL requests, content management, and schema stitching support.
5
9
 
6
- Install the package via npm:
10
+ ## Installation
7
11
 
8
12
  ```sh
9
13
  npm install --save @unchainedshop/cockpit-api
10
14
  ```
11
15
 
12
- ## Usage
16
+ ## Package Exports
13
17
 
14
- ### Initialization
18
+ This package provides three entry points:
15
19
 
16
- First, set your cockpit graphql endpoint to env
20
+ | Export | Description |
21
+ |--------|-------------|
22
+ | `@unchainedshop/cockpit-api` | Full-featured async API client with caching and response transformation |
23
+ | `@unchainedshop/cockpit-api/schema` | GraphQL schema stitching utilities |
24
+ | `@unchainedshop/cockpit-api/fetch` | Lightweight client for edge/RSC environments |
17
25
 
18
- ```bash
19
- COCKPIT_GRAPHQL_ENDPOINT
20
- ```
21
- then import and initialize the API:
26
+ ## Quick Start
27
+
28
+ ### Main Client
22
29
 
23
- ```javascript
30
+ ```typescript
24
31
  import { CockpitAPI } from '@unchainedshop/cockpit-api';
25
32
 
26
- const cockpit = await CockpitAPI();
33
+ // With explicit endpoint
34
+ const cockpit = await CockpitAPI({
35
+ endpoint: 'https://your-cockpit-instance.com/api/graphql',
36
+ });
37
+
38
+ // Or using environment variables
39
+ const cockpit = await CockpitAPI(); // Uses COCKPIT_GRAPHQL_ENDPOINT
27
40
  ```
28
41
 
29
- ### GraphQL Requests
42
+ ### Lightweight Fetch Client (Edge/RSC)
43
+
44
+ ```typescript
45
+ import { createFetchClient } from '@unchainedshop/cockpit-api/fetch';
46
+
47
+ // Synchronous initialization - no await needed
48
+ const cockpit = createFetchClient({
49
+ endpoint: process.env.NEXT_PUBLIC_COCKPIT_ENDPOINT,
50
+ tenant: 'mytenant',
51
+ cache: 'force-cache', // Uses platform caching
52
+ });
53
+
54
+ const page = await cockpit.pageByRoute('/about', { locale: 'en' });
55
+ ```
30
56
 
31
- You can make GraphQL requests using the `graphQL` method:
57
+ ### GraphQL Schema Stitching
32
58
 
33
- ```javascript
59
+ ```typescript
60
+ import { makeCockpitGraphQLSchema } from '@unchainedshop/cockpit-api/schema';
61
+ import { stitchSchemas } from '@graphql-tools/stitch';
62
+
63
+ const cockpitSchema = await makeCockpitGraphQLSchema({
64
+ tenantHeader: 'x-cockpit-space',
65
+ filterMutations: true,
66
+ });
67
+
68
+ const gatewaySchema = stitchSchemas({
69
+ subschemas: [{ schema: cockpitSchema }],
70
+ });
71
+ ```
72
+
73
+ ## Main Client API
74
+
75
+ ### GraphQL Requests
76
+
77
+ ```typescript
34
78
  import { gql } from 'graphql-tag';
35
79
 
36
80
  const query = gql`
@@ -43,67 +87,288 @@ const query = gql`
43
87
  `;
44
88
 
45
89
  const result = await cockpit.graphQL(query, {});
46
- console.log(result);
47
90
  ```
48
91
 
49
92
  ### Content Operations
50
93
 
51
- You can perform various content operations such as fetching items, aggregating models, and manipulating pages.
52
-
53
- Example to get a content item:
54
-
55
- ```javascript
56
- const contentItem = await cockpit.getContentItem({ model: 'posts', id: '123' });
57
- console.log(contentItem);
58
- ```
59
-
60
- ### CockpitAPI
61
-
62
- Provides various methods to interact with the Cockpit CMS.
63
-
64
- **Methods:**
65
- - `graphQL(document, variables)`
66
- - `getContentItem({ model, id }, locale, queryParams)`
67
- - `getAggregateModel({ model, pipeline }, locale)`
68
- - `getContentItems(model, locale, queryParams)`
69
- - `getContentTree(model, locale, queryParams)`
70
- - `postContentItem(model, item)`
71
- - `deleteContentItem(model, id)`
72
- - `pages(locale, queryParams)`
73
- - `pageById({ page, id }, locale, queryParams)`
74
- - `pageByRoute(route, locale)`
75
- - `pagesMenus(locale)`
76
- - `pagesMenu(name, locale)`
77
- - `pagesRoutes(locale)`
78
- - `pagesSitemap()`
79
- - `pagesSetting(locale)`
80
- - `healthCheck()`
81
- - `lokalize(projectName,locale, nested)`
82
- - `assetById(assetId)`
83
- - `imageAssetById(assetId, queryParams)`
84
- - `getFullRouteForSlug(slug)`
85
-
86
- ### Optional configuration
87
- you can change the caching behavior by setting the envs below
88
-
94
+ ```typescript
95
+ // Get a single content item
96
+ const post = await cockpit.getContentItem({ model: 'posts', id: '123' });
97
+
98
+ // With locale and field selection
99
+ const localizedPost = await cockpit.getContentItem({
100
+ model: 'posts',
101
+ id: '123',
102
+ locale: 'en',
103
+ queryParams: { fields: { title: 1, content: 1 } }
104
+ });
105
+
106
+ // Get multiple content items with pagination
107
+ const posts = await cockpit.getContentItems('posts', {
108
+ limit: 10,
109
+ skip: 0,
110
+ sort: { _created: -1 },
111
+ filter: { published: true }
112
+ });
113
+
114
+ // Get tree structure
115
+ const tree = await cockpit.getContentTree('categories', {
116
+ parent: 'root-id',
117
+ populate: 2
118
+ });
119
+
120
+ // Aggregation pipeline
121
+ const stats = await cockpit.getAggregateModel({
122
+ model: 'orders',
123
+ pipeline: [{ $group: { _id: '$status', count: { $sum: 1 } } }]
124
+ });
125
+
126
+ // Create content item
127
+ const newPost = await cockpit.postContentItem('posts', { title: 'New Post' });
128
+
129
+ // Delete content item
130
+ await cockpit.deleteContentItem('posts', '123');
131
+ ```
132
+
133
+ ### Pages
134
+
135
+ ```typescript
136
+ // List pages
137
+ const allPages = await cockpit.pages({ locale: 'en', limit: 50 });
138
+
139
+ // Get page by ID
140
+ const page = await cockpit.pageById({ page: 'blog', id: '123', locale: 'en' });
141
+
142
+ // Get page by route
143
+ const aboutPage = await cockpit.pageByRoute('/about', { locale: 'en', populate: 2 });
144
+ ```
145
+
146
+ ### Menus
147
+
148
+ ```typescript
149
+ // Get all menus
150
+ const menus = await cockpit.pagesMenus({ locale: 'en' });
151
+
152
+ // Get specific menu
153
+ const mainMenu = await cockpit.pagesMenu('main-navigation', { locale: 'en' });
154
+ ```
155
+
156
+ ### Routes & Sitemap
157
+
158
+ ```typescript
159
+ const routes = await cockpit.pagesRoutes('en');
160
+ const sitemap = await cockpit.pagesSitemap();
161
+ const settings = await cockpit.pagesSetting('en');
162
+ const fullRoute = await cockpit.getFullRouteForSlug('my-slug');
163
+ ```
164
+
165
+ ### Search (Detektivo addon)
166
+
167
+ ```typescript
168
+ const results = await cockpit.search({
169
+ index: 'products',
170
+ q: 'search term',
171
+ limit: 10,
172
+ offset: 0
173
+ });
174
+ ```
175
+
176
+ ### Localization (Lokalize addon)
177
+
178
+ ```typescript
179
+ const translations = await cockpit.localize('my-project', {
180
+ locale: 'en',
181
+ nested: true
182
+ });
183
+ ```
184
+
185
+ ### Assets
186
+
187
+ ```typescript
188
+ import { ImageSizeMode, MimeType } from '@unchainedshop/cockpit-api';
189
+
190
+ // Get asset metadata
191
+ const asset = await cockpit.assetById('asset-id');
192
+
193
+ // Get transformed image
194
+ const image = await cockpit.imageAssetById('asset-id', {
195
+ m: ImageSizeMode.BestFit,
196
+ w: 800,
197
+ h: 600,
198
+ q: 80,
199
+ mime: MimeType.WEBP
200
+ });
201
+ ```
202
+
203
+ ### System
204
+
205
+ ```typescript
206
+ // Health check
207
+ const health = await cockpit.healthCheck();
208
+
209
+ // Clear cache
210
+ cockpit.clearCache(); // Clear all
211
+ cockpit.clearCache('pages'); // Clear by pattern
212
+ ```
213
+
214
+ ## Lightweight Fetch Client API
215
+
216
+ The fetch client is designed for edge/RSC environments with minimal overhead:
217
+
218
+ ```typescript
219
+ import { createFetchClient } from '@unchainedshop/cockpit-api/fetch';
220
+
221
+ const cockpit = createFetchClient({
222
+ endpoint: process.env.NEXT_PUBLIC_COCKPIT_ENDPOINT,
223
+ tenant: 'mytenant',
224
+ cache: 'force-cache',
225
+ apiKey: 'your-api-key',
226
+ headers: { 'X-Custom-Header': 'value' }
227
+ });
228
+
229
+ // Available methods
230
+ const page = await cockpit.pageByRoute('/about', { locale: 'en' });
231
+ const pages = await cockpit.pages({ locale: 'en' });
232
+ const pageById = await cockpit.pageById('blog', '123', { locale: 'en' });
233
+ const items = await cockpit.getContentItems('news', { locale: 'en', limit: 10 });
234
+ const item = await cockpit.getContentItem('news', '123', { locale: 'en' });
235
+ const custom = await cockpit.fetchRaw('/custom/endpoint', { param: 'value' });
236
+ ```
237
+
238
+ ## Schema Stitching API
239
+
240
+ For building GraphQL gateways with Cockpit:
241
+
242
+ ```typescript
243
+ import { makeCockpitGraphQLSchema, createRemoteExecutor } from '@unchainedshop/cockpit-api/schema';
244
+
245
+ // Create schema for stitching
246
+ const schema = await makeCockpitGraphQLSchema({
247
+ tenantHeader: 'x-cockpit-space',
248
+ filterMutations: true,
249
+ transforms: [], // Additional GraphQL transforms
250
+ extractTenant: (ctx) => ctx.req?.headers['x-tenant'],
251
+ cockpitOptions: {
252
+ endpoint: 'https://cms.example.com/api/graphql',
253
+ apiKey: 'your-api-key',
254
+ useAdminAccess: true
255
+ }
256
+ });
257
+
258
+ // Or use the executor directly for custom implementations
259
+ const executor = createRemoteExecutor({
260
+ tenantHeader: 'x-cockpit-space',
261
+ cockpitOptions: { endpoint: '...' }
262
+ });
263
+ ```
264
+
265
+ ## Configuration Options
266
+
267
+ ```typescript
268
+ const cockpit = await CockpitAPI({
269
+ endpoint: 'https://...', // Falls back to COCKPIT_GRAPHQL_ENDPOINT
270
+ tenant: 'mytenant', // Optional: for multi-tenant setups
271
+ apiKey: 'your-api-key', // Falls back to COCKPIT_SECRET env var
272
+ useAdminAccess: true, // Optional: inject api-Key header
273
+ defaultLanguage: 'de', // Language that maps to Cockpit's "default" locale (default: "de")
274
+ preloadRoutes: true, // Optional: preload route replacements
275
+ cache: {
276
+ max: 100, // Falls back to COCKPIT_CACHE_MAX (default: 100)
277
+ ttl: 100000, // Falls back to COCKPIT_CACHE_TTL (default: 100000)
278
+ },
279
+ });
280
+ ```
281
+
282
+ ## Environment Variables
283
+
89
284
  ```bash
90
- COCKPIT_CACHE__MAX_LIMIT # number of records to store in before overwriting it
91
- COCKPIT_CACHE_TTL # caching period in milliseconds
285
+ COCKPIT_GRAPHQL_ENDPOINT=https://your-cockpit-instance.com/api/graphql
286
+ COCKPIT_SECRET=your-api-key # Default API key
287
+ COCKPIT_SECRET_MYTENANT=tenant-api-key # Tenant-specific API key
288
+ COCKPIT_CACHE_MAX=100 # Max cache entries (default: 100)
289
+ COCKPIT_CACHE_TTL=100000 # Cache TTL in ms (default: 100000)
92
290
  ```
93
291
 
292
+ ## Multi-Tenant Support
293
+
294
+ ```typescript
295
+ // Tenant-specific client
296
+ const cockpit = await CockpitAPI({
297
+ endpoint: 'https://cms.example.com/api/graphql',
298
+ tenant: 'mytenant', // Requests use /:mytenant/api/... path
299
+ });
300
+
301
+ // Resolve tenant from URL
302
+ import { resolveTenantFromUrl, getTenantIds } from '@unchainedshop/cockpit-api';
303
+
304
+ const { tenant, slug } = resolveTenantFromUrl('https://mytenant.example.com/page');
305
+ const allTenants = getTenantIds(); // From COCKPIT_SECRET_* env vars
306
+ ```
307
+
308
+ ## TypeScript Support
309
+
310
+ ```typescript
311
+ import type {
312
+ // Client
313
+ CockpitAPIClient,
314
+ CockpitAPIOptions,
315
+ CacheManager,
316
+ CacheOptions,
317
+
318
+ // Query Options
319
+ ContentItemQueryOptions,
320
+ ContentListQueryOptions,
321
+ TreeQueryOptions,
322
+ PageQueryOptions,
323
+ SearchQueryOptions,
324
+ ImageAssetQueryParams,
325
+
326
+ // Response Types
327
+ CockpitPage,
328
+ CockpitAsset,
329
+ CockpitMenu,
330
+ CockpitRoute,
331
+ CockpitSearchResult,
332
+ CockpitContentItem,
333
+
334
+ // Schema Types
335
+ MakeCockpitSchemaOptions,
336
+ CockpitExecutorContext,
337
+
338
+ // Fetch Types
339
+ FetchClientOptions,
340
+ FetchCacheMode,
341
+ } from '@unchainedshop/cockpit-api';
342
+
343
+ import { ImageSizeMode, MimeType } from '@unchainedshop/cockpit-api';
344
+ ```
345
+
346
+ ## Breaking Changes
347
+
348
+ ### v2.0.0
349
+
350
+ - `lokalize()` renamed to `localize()`
351
+ - Methods use options objects instead of positional parameters
352
+ - HTTP errors now throw instead of returning `null` (404 still returns `null`)
353
+ - Each client instance has its own cache (no shared state)
354
+
355
+ ### v2.1.0 (New Features)
356
+
357
+ - `/schema` subpackage for GraphQL schema stitching
358
+ - `/fetch` subpackage for lightweight edge/RSC environments
359
+ - `preloadRoutes` option for preloading route replacements
360
+ - `defaultLanguage` option to configure which language maps to Cockpit's "default" locale
361
+ - Expanded tenant utilities: `resolveTenantFromUrl()`, `resolveTenantFromSubdomain()`
362
+
363
+ ## Peer Dependencies
364
+
365
+ - `graphql` (optional) - Required for the `graphQL()` method
366
+ - `@graphql-tools/wrap` (optional) - Required for the `/schema` subpackage
367
+
94
368
  ## Contributing
95
369
 
96
370
  Contributions are welcome! Please open an issue or submit a pull request.
97
371
 
98
- 1. Fork the repository.
99
- 2. Create a new branch: `git checkout -b feature-branch-name`.
100
- 3. Make your changes and commit them: `git commit -m 'Add new feature'`.
101
- 4. Push to the branch: `git push origin feature-branch-name`.
102
- 5. Open a pull request.
103
-
104
372
  ## License
105
373
 
106
374
  This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
107
- ```
108
-
109
- This `README.md` covers installation, basic usage, detailed API reference, contribution guidelines, and licensing information. Adjust the details as needed for your specific implementation.
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Cockpit API Client Factory
3
+ */
4
+ import type { DocumentNode } from "graphql";
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";
7
+ import { type PageByIdOptions, type CockpitPage } from "./methods/pages.ts";
8
+ import { type MenuQueryOptions, type CockpitMenu } from "./methods/menus.ts";
9
+ import { type CockpitRoutesResponse, type CockpitSitemapEntry, type CockpitSettings } from "./methods/routes.ts";
10
+ import { type ImageAssetQueryParams, type CockpitAsset } from "./methods/assets.ts";
11
+ import { type SearchQueryOptions, type CockpitSearchResult } from "./methods/search.ts";
12
+ import { type LocalizeOptions } from "./methods/localize.ts";
13
+ /**
14
+ * Cockpit API Client interface
15
+ */
16
+ export interface CockpitAPIClient {
17
+ graphQL<T = unknown>(document: DocumentNode, variables?: Record<string, unknown>): Promise<T | null>;
18
+ getContentItem<T = unknown>(options: ContentItemQueryOptions): Promise<T | null>;
19
+ getContentItems<T = CockpitContentItem>(model: string, options?: ContentListQueryOptions): Promise<T[] | null>;
20
+ getContentTree<T = CockpitContentItem>(model: string, options?: TreeQueryOptions): Promise<CockpitTreeNode<T>[] | null>;
21
+ getAggregateModel<T = unknown>(options: AggregateQueryOptions): Promise<T[] | null>;
22
+ postContentItem<T = unknown>(model: string, item: Record<string, unknown>): Promise<T | null>;
23
+ deleteContentItem<T = unknown>(model: string, id: string): Promise<T | null>;
24
+ pages<T = CockpitPage>(options?: ContentListQueryOptions): Promise<T[] | null>;
25
+ pageById<T = CockpitPage>(id: string, options?: PageByIdOptions): Promise<T | null>;
26
+ pageByRoute<T = CockpitPage>(route: string, options?: {
27
+ locale?: string;
28
+ populate?: number;
29
+ } | string): Promise<T | null>;
30
+ pagesMenus<T = CockpitMenu>(options?: MenuQueryOptions | string): Promise<T[] | null>;
31
+ pagesMenu<T = CockpitMenu>(name: string, options?: MenuQueryOptions | string): Promise<T | null>;
32
+ pagesRoutes<T = CockpitRoutesResponse>(locale?: string): Promise<T | null>;
33
+ pagesSitemap<T = CockpitSitemapEntry>(): Promise<T[] | null>;
34
+ pagesSetting<T = CockpitSettings>(locale?: string): Promise<T | null>;
35
+ search<T = CockpitSearchResult>(options: SearchQueryOptions): Promise<T | null>;
36
+ healthCheck<T = unknown>(): Promise<T | null>;
37
+ localize<T = unknown>(projectName: string, options?: LocalizeOptions): Promise<T | null>;
38
+ assetById<T = CockpitAsset>(assetId: string): Promise<T | null>;
39
+ /**
40
+ * Get a transformed image asset URL.
41
+ *
42
+ * **Important:** The `w` (width) or `h` (height) parameter is required by the API.
43
+ * Without it, the API returns a 400 error.
44
+ *
45
+ * @param assetId - The asset ID
46
+ * @param queryParams - Image transformation parameters (w or h required)
47
+ * @returns URL string to the generated image, or null if not found
48
+ */
49
+ imageAssetById(assetId: string, queryParams?: ImageAssetQueryParams): Promise<string | null>;
50
+ getFullRouteForSlug(slug: string): Promise<string | undefined>;
51
+ clearCache(pattern?: string): void;
52
+ }
53
+ /**
54
+ * Creates a Cockpit API client
55
+ *
56
+ * @param options - Configuration options (falls back to env vars if not provided)
57
+ * @returns Promise resolving to the API client
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * // With explicit options
62
+ * const client = await CockpitAPI({
63
+ * endpoint: 'https://cms.example.com/api/graphql',
64
+ * tenant: 'mytenant',
65
+ * useAdminAccess: true,
66
+ * });
67
+ *
68
+ * // Or using environment variables (COCKPIT_GRAPHQL_ENDPOINT, etc.)
69
+ * const client = await CockpitAPI();
70
+ * ```
71
+ */
72
+ export declare function CockpitAPI(options?: CockpitAPIOptions): Promise<CockpitAPIClient>;
package/dist/client.js ADDED
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Cockpit API Client Factory
3
+ */
4
+ import { createConfig } from "./core/config.js";
5
+ import { createCacheManager } from "./core/cache.js";
6
+ import { createUrlBuilder } from "./core/url-builder.js";
7
+ import { createHttpClient } from "./core/http.js";
8
+ import { createImagePathTransformer } from "./transformers/image-path.js";
9
+ import { generateCmsRouteReplacements } from "./utils/route-map.js";
10
+ import { createContentMethods, } from "./methods/content.js";
11
+ import { createPagesMethods, } from "./methods/pages.js";
12
+ import { createMenuMethods, } from "./methods/menus.js";
13
+ import { createRouteMethods, } from "./methods/routes.js";
14
+ import { createAssetMethods, } from "./methods/assets.js";
15
+ import { createGraphQLMethods } from "./methods/graphql.js";
16
+ import { createSearchMethods, } from "./methods/search.js";
17
+ import { createLocalizeMethods, } from "./methods/localize.js";
18
+ import { createSystemMethods } from "./methods/system.js";
19
+ /**
20
+ * Creates a Cockpit API client
21
+ *
22
+ * @param options - Configuration options (falls back to env vars if not provided)
23
+ * @returns Promise resolving to the API client
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * // With explicit options
28
+ * const client = await CockpitAPI({
29
+ * endpoint: 'https://cms.example.com/api/graphql',
30
+ * tenant: 'mytenant',
31
+ * useAdminAccess: true,
32
+ * });
33
+ *
34
+ * // Or using environment variables (COCKPIT_GRAPHQL_ENDPOINT, etc.)
35
+ * const client = await CockpitAPI();
36
+ * ```
37
+ */
38
+ export async function CockpitAPI(options = {}) {
39
+ // Create configuration
40
+ const config = createConfig(options);
41
+ const endpointString = config.endpoint.toString();
42
+ // Create cache manager - env vars take precedence, then options, then cache.ts defaults
43
+ const envCacheMax = process.env["COCKPIT_CACHE_MAX"];
44
+ const envCacheTtl = process.env["COCKPIT_CACHE_TTL"];
45
+ const cacheOptions = {};
46
+ const maxValue = options.cache?.max ??
47
+ (envCacheMax !== undefined ? parseInt(envCacheMax, 10) : undefined);
48
+ const ttlValue = options.cache?.ttl ??
49
+ (envCacheTtl !== undefined ? parseInt(envCacheTtl, 10) : undefined);
50
+ if (maxValue !== undefined)
51
+ cacheOptions.max = maxValue;
52
+ if (ttlValue !== undefined)
53
+ cacheOptions.ttl = ttlValue;
54
+ const cache = createCacheManager(config.cachePrefix, cacheOptions);
55
+ // Generate route replacements for image path transformer (optional)
56
+ const routeReplacements = options.preloadRoutes === true
57
+ ? await generateCmsRouteReplacements(endpointString, options.tenant, cache)
58
+ : {};
59
+ // Create response transformer
60
+ const transformerConfig = {
61
+ baseUrl: config.endpoint.origin,
62
+ replacements: routeReplacements,
63
+ };
64
+ if (options.tenant !== undefined)
65
+ transformerConfig.tenant = options.tenant;
66
+ const transformer = createImagePathTransformer(transformerConfig);
67
+ // Create URL builder
68
+ const urlBuilder = createUrlBuilder(config);
69
+ // Create HTTP client
70
+ const http = createHttpClient(config, transformer);
71
+ // Create method context
72
+ const ctx = {
73
+ http,
74
+ url: urlBuilder,
75
+ cache,
76
+ endpoint: endpointString,
77
+ ...(options.tenant !== undefined && { tenant: options.tenant }),
78
+ };
79
+ // Create method groups
80
+ const contentMethods = createContentMethods(ctx);
81
+ const pagesMethods = createPagesMethods(ctx);
82
+ const menuMethods = createMenuMethods(ctx);
83
+ const routeMethods = createRouteMethods(ctx);
84
+ const assetMethods = createAssetMethods(ctx);
85
+ const graphqlMethods = createGraphQLMethods(ctx);
86
+ const searchMethods = createSearchMethods(ctx);
87
+ const localizeMethods = createLocalizeMethods(ctx);
88
+ const systemMethods = createSystemMethods(ctx);
89
+ // Compose the client
90
+ return {
91
+ ...contentMethods,
92
+ ...pagesMethods,
93
+ ...menuMethods,
94
+ ...routeMethods,
95
+ ...assetMethods,
96
+ ...graphqlMethods,
97
+ ...searchMethods,
98
+ ...localizeMethods,
99
+ ...systemMethods,
100
+ };
101
+ }
@@ -1,5 +1,8 @@
1
- import type { Logger } from "@unchainedshop/logger";
2
- declare let logger: Logger;
3
- declare const log: (message: any, ...args: any[]) => void;
4
- export { logger };
5
- export default log;
1
+ /**
2
+ * Logger for Cockpit API
3
+ */
4
+ import { createLogger } from "@unchainedshop/logger";
5
+ type Logger = ReturnType<typeof createLogger>;
6
+ export declare const logger: Logger;
7
+ declare const logInfo: Logger["info"];
8
+ export default logInfo;
@@ -1,20 +1,7 @@
1
- let logger = {
2
- info: console.log,
3
- error: console.error,
4
- warn: console.warn,
5
- debug: console.debug,
6
- trace: console.trace,
7
- };
8
- async function loadLogger() {
9
- try {
10
- const { createLogger } = await import("@unchainedshop/logger");
11
- logger = createLogger("cockpit") || logger;
12
- }
13
- catch (e) {
14
- // console.warn(e);
15
- }
16
- }
17
- loadLogger();
18
- const log = logger.info;
19
- export { logger };
20
- export default log;
1
+ /**
2
+ * Logger for Cockpit API
3
+ */
4
+ import { createLogger } from "@unchainedshop/logger";
5
+ export const logger = createLogger("cockpit");
6
+ const logInfo = logger.info;
7
+ export default logInfo;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Cache management with LRU cache and tenant isolation
3
+ */
4
+ export interface CacheOptions {
5
+ /** Maximum number of entries (default: 100) */
6
+ max?: number;
7
+ /** Time-to-live in milliseconds (default: 100000) */
8
+ ttl?: number;
9
+ }
10
+ export interface CacheManager {
11
+ get(key: string): unknown;
12
+ set(key: string, value: NonNullable<unknown>): void;
13
+ clear(pattern?: string): void;
14
+ }
15
+ /**
16
+ * Creates a cache manager with prefixed keys
17
+ * Each call creates a new LRU cache instance - no shared state
18
+ */
19
+ export declare function createCacheManager(cachePrefix: string, options?: CacheOptions): CacheManager;