@distinctagency/cms-client 1.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/dist/index.d.mts +419 -0
- package/dist/index.d.ts +419 -0
- package/dist/index.js +7074 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +7054 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +45 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import { SupabaseClient } from '@supabase/supabase-js';
|
|
2
|
+
|
|
3
|
+
/** Field types supported by the CMS schema */
|
|
4
|
+
type FieldType = "text" | "textarea" | "richtext" | "date" | "datetime" | "select" | "number" | "boolean" | "image" | "gallery" | "url" | "reference" | "computed" | "color" | "tags" | "json";
|
|
5
|
+
interface ImageConfig {
|
|
6
|
+
max_width?: number;
|
|
7
|
+
max_height?: number;
|
|
8
|
+
aspect_ratio?: string;
|
|
9
|
+
aspect_tolerance?: number;
|
|
10
|
+
long_edge?: number;
|
|
11
|
+
}
|
|
12
|
+
/** A single field definition within a content type schema */
|
|
13
|
+
interface FieldDefinition {
|
|
14
|
+
name: string;
|
|
15
|
+
type: FieldType;
|
|
16
|
+
label: string;
|
|
17
|
+
required?: boolean;
|
|
18
|
+
options?: string[];
|
|
19
|
+
default?: string | number | boolean;
|
|
20
|
+
/** For reference fields: the slug of the collection to reference */
|
|
21
|
+
reference_to?: string;
|
|
22
|
+
/** For computed fields: the computation config */
|
|
23
|
+
compute?: {
|
|
24
|
+
function: "read_time" | "word_count" | "char_count" | "excerpt_auto" | "seo_score";
|
|
25
|
+
source_field: string;
|
|
26
|
+
};
|
|
27
|
+
/** For image/gallery fields: processing constraints */
|
|
28
|
+
image_config?: ImageConfig;
|
|
29
|
+
}
|
|
30
|
+
interface Tenant {
|
|
31
|
+
id: string;
|
|
32
|
+
name: string;
|
|
33
|
+
slug: string;
|
|
34
|
+
domain: string | null;
|
|
35
|
+
staging_domain: string | null;
|
|
36
|
+
api_key: string;
|
|
37
|
+
created_at: string;
|
|
38
|
+
}
|
|
39
|
+
interface CmsClientOptions {
|
|
40
|
+
/** Tenant API key (UUID) — required for authentication */
|
|
41
|
+
apiKey: string;
|
|
42
|
+
/** CMS app URL for API calls (e.g. orders) */
|
|
43
|
+
appUrl?: string;
|
|
44
|
+
}
|
|
45
|
+
interface Profile {
|
|
46
|
+
id: string;
|
|
47
|
+
tenant_id: string;
|
|
48
|
+
full_name: string | null;
|
|
49
|
+
role: "super_admin" | "admin" | "editor";
|
|
50
|
+
created_at: string;
|
|
51
|
+
}
|
|
52
|
+
interface ContentTypeSeoConfig {
|
|
53
|
+
enabled: boolean;
|
|
54
|
+
/** Field mappings — which schema fields serve which SEO purpose */
|
|
55
|
+
field_map: {
|
|
56
|
+
/** Primary body content field (for word count, headings, links, images) */
|
|
57
|
+
content?: string;
|
|
58
|
+
/** Featured/hero image field */
|
|
59
|
+
featured_image?: string;
|
|
60
|
+
/** SEO title override field (falls back to standard title) */
|
|
61
|
+
seo_title?: string;
|
|
62
|
+
/** Meta description field (falls back to standard excerpt) */
|
|
63
|
+
seo_description?: string;
|
|
64
|
+
/** Author/byline field */
|
|
65
|
+
author?: string;
|
|
66
|
+
/** Published date field */
|
|
67
|
+
publish_date?: string;
|
|
68
|
+
/** Category or tag field */
|
|
69
|
+
category?: string;
|
|
70
|
+
/** Canonical URL field */
|
|
71
|
+
canonical_url?: string;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
interface ContentType {
|
|
75
|
+
id: string;
|
|
76
|
+
tenant_id: string;
|
|
77
|
+
name: string;
|
|
78
|
+
slug: string;
|
|
79
|
+
schema: FieldDefinition[];
|
|
80
|
+
seo_config?: ContentTypeSeoConfig | null;
|
|
81
|
+
created_at: string;
|
|
82
|
+
}
|
|
83
|
+
interface ContentItem {
|
|
84
|
+
id: string;
|
|
85
|
+
tenant_id: string;
|
|
86
|
+
content_type_id: string;
|
|
87
|
+
title: string;
|
|
88
|
+
slug: string;
|
|
89
|
+
status: "draft" | "published" | "archived" | "pending_review";
|
|
90
|
+
published_at: string | null;
|
|
91
|
+
seo_title: string | null;
|
|
92
|
+
seo_description: string | null;
|
|
93
|
+
og_image: string | null;
|
|
94
|
+
featured_image: string | null;
|
|
95
|
+
excerpt: string | null;
|
|
96
|
+
sort_order: number;
|
|
97
|
+
data: Record<string, unknown>;
|
|
98
|
+
created_by: string | null;
|
|
99
|
+
created_at: string;
|
|
100
|
+
updated_at: string;
|
|
101
|
+
/** Joined content type (included when queried with select) */
|
|
102
|
+
content_type?: ContentType;
|
|
103
|
+
}
|
|
104
|
+
interface MediaItem {
|
|
105
|
+
id: string;
|
|
106
|
+
tenant_id: string;
|
|
107
|
+
url: string;
|
|
108
|
+
filename: string;
|
|
109
|
+
alt_text: string | null;
|
|
110
|
+
mime_type: string | null;
|
|
111
|
+
size: number | null;
|
|
112
|
+
created_by: string | null;
|
|
113
|
+
created_at: string;
|
|
114
|
+
}
|
|
115
|
+
interface TenantMembership {
|
|
116
|
+
id: string;
|
|
117
|
+
user_id: string;
|
|
118
|
+
tenant_id: string;
|
|
119
|
+
role: "admin" | "editor";
|
|
120
|
+
created_at: string;
|
|
121
|
+
tenant?: Tenant;
|
|
122
|
+
}
|
|
123
|
+
interface ContentQueryOptions {
|
|
124
|
+
status?: "draft" | "published" | "archived" | "pending_review";
|
|
125
|
+
orderBy?: string;
|
|
126
|
+
orderDirection?: "asc" | "desc";
|
|
127
|
+
limit?: number;
|
|
128
|
+
offset?: number;
|
|
129
|
+
}
|
|
130
|
+
interface Product {
|
|
131
|
+
id: string;
|
|
132
|
+
tenant_id: string;
|
|
133
|
+
name: string;
|
|
134
|
+
slug: string;
|
|
135
|
+
description: string | null;
|
|
136
|
+
short_description: string | null;
|
|
137
|
+
status: "draft" | "published" | "archived";
|
|
138
|
+
price_cents: number;
|
|
139
|
+
compare_at_price_cents: number | null;
|
|
140
|
+
sku: string | null;
|
|
141
|
+
barcode: string | null;
|
|
142
|
+
featured_image: string | null;
|
|
143
|
+
gallery: string[];
|
|
144
|
+
category: string | null;
|
|
145
|
+
tags: string[];
|
|
146
|
+
weight_grams: number | null;
|
|
147
|
+
is_digital: boolean;
|
|
148
|
+
track_inventory: boolean;
|
|
149
|
+
allow_overselling: boolean;
|
|
150
|
+
seo_title: string | null;
|
|
151
|
+
seo_description: string | null;
|
|
152
|
+
metadata: Record<string, unknown>;
|
|
153
|
+
sort_order: number;
|
|
154
|
+
published_at: string | null;
|
|
155
|
+
created_at: string;
|
|
156
|
+
updated_at: string;
|
|
157
|
+
variants?: ProductVariant[];
|
|
158
|
+
options?: ProductOption[];
|
|
159
|
+
}
|
|
160
|
+
interface ProductVariant {
|
|
161
|
+
id: string;
|
|
162
|
+
product_id: string;
|
|
163
|
+
name: string;
|
|
164
|
+
sku: string | null;
|
|
165
|
+
price_cents: number | null;
|
|
166
|
+
option_values: Record<string, string>;
|
|
167
|
+
stock_quantity: number;
|
|
168
|
+
low_stock_threshold: number;
|
|
169
|
+
weight_grams: number | null;
|
|
170
|
+
image_url: string | null;
|
|
171
|
+
is_active: boolean;
|
|
172
|
+
sort_order: number;
|
|
173
|
+
}
|
|
174
|
+
interface ProductOption {
|
|
175
|
+
id: string;
|
|
176
|
+
product_id: string;
|
|
177
|
+
name: string;
|
|
178
|
+
values: string[];
|
|
179
|
+
sort_order: number;
|
|
180
|
+
}
|
|
181
|
+
interface OrderAddress {
|
|
182
|
+
line1: string;
|
|
183
|
+
line2?: string;
|
|
184
|
+
city: string;
|
|
185
|
+
region: string;
|
|
186
|
+
postcode: string;
|
|
187
|
+
country: string;
|
|
188
|
+
}
|
|
189
|
+
interface CreateOrderParams {
|
|
190
|
+
customer_email: string;
|
|
191
|
+
customer_name?: string;
|
|
192
|
+
customer_phone?: string;
|
|
193
|
+
line_items: {
|
|
194
|
+
product_id: string;
|
|
195
|
+
variant_id?: string;
|
|
196
|
+
quantity: number;
|
|
197
|
+
}[];
|
|
198
|
+
shipping_address?: OrderAddress;
|
|
199
|
+
billing_address?: OrderAddress;
|
|
200
|
+
shipping_method?: string;
|
|
201
|
+
discount_code?: string;
|
|
202
|
+
}
|
|
203
|
+
interface CreateOrderResult {
|
|
204
|
+
order_id: string;
|
|
205
|
+
order_number: string;
|
|
206
|
+
client_secret: string;
|
|
207
|
+
total_cents: number;
|
|
208
|
+
currency: string;
|
|
209
|
+
}
|
|
210
|
+
interface ProductQueryOptions {
|
|
211
|
+
category?: string;
|
|
212
|
+
tags?: string[];
|
|
213
|
+
limit?: number;
|
|
214
|
+
offset?: number;
|
|
215
|
+
sort?: "name" | "price_cents" | "created_at" | "sort_order";
|
|
216
|
+
order?: "asc" | "desc";
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Creates a CMS query client authenticated with a tenant API key.
|
|
221
|
+
*
|
|
222
|
+
* Usage:
|
|
223
|
+
* ```ts
|
|
224
|
+
* const cms = createCmsClient(supabase, { apiKey: process.env.CMS_API_KEY! })
|
|
225
|
+
* const events = await cms.getContentItems('events', { status: 'published' })
|
|
226
|
+
* ```
|
|
227
|
+
*
|
|
228
|
+
* The API key is sent as an `x-cms-api-key` header on every request.
|
|
229
|
+
* Supabase RLS policies validate it against the tenant's stored key.
|
|
230
|
+
*/
|
|
231
|
+
declare function createCmsClient(supabase: SupabaseClient, options: CmsClientOptions): {
|
|
232
|
+
/**
|
|
233
|
+
* List content items for a content type.
|
|
234
|
+
* Defaults to published items ordered by most recent.
|
|
235
|
+
*/
|
|
236
|
+
getContentItems(contentTypeSlug: string, options?: ContentQueryOptions): Promise<ContentItem[]>;
|
|
237
|
+
/**
|
|
238
|
+
* Get a single content item by its slug.
|
|
239
|
+
* Returns null if not found.
|
|
240
|
+
*/
|
|
241
|
+
getContentItemBySlug(contentTypeSlug: string, itemSlug: string): Promise<ContentItem | null>;
|
|
242
|
+
/**
|
|
243
|
+
* Get a content type definition (including its field schema).
|
|
244
|
+
*/
|
|
245
|
+
getContentType(contentTypeSlug: string): Promise<ContentType>;
|
|
246
|
+
/**
|
|
247
|
+
* Get all slugs for a content type (for generateStaticParams).
|
|
248
|
+
*/
|
|
249
|
+
getAllSlugs(contentTypeSlug: string): Promise<{
|
|
250
|
+
slug: string;
|
|
251
|
+
}[]>;
|
|
252
|
+
/**
|
|
253
|
+
* List all content types for this tenant.
|
|
254
|
+
*/
|
|
255
|
+
getContentTypes(): Promise<ContentType[]>;
|
|
256
|
+
/**
|
|
257
|
+
* Get all slug redirects for a content type.
|
|
258
|
+
* Use in next.config.js redirects() or middleware for 301s.
|
|
259
|
+
* Returns: [{ old_slug, new_slug }, ...]
|
|
260
|
+
*/
|
|
261
|
+
getRedirects(contentTypeSlug: string): Promise<{
|
|
262
|
+
old_slug: string;
|
|
263
|
+
new_slug: string;
|
|
264
|
+
}[]>;
|
|
265
|
+
/**
|
|
266
|
+
* Get all custom path redirects for this tenant.
|
|
267
|
+
* Use alongside getRedirects() in next.config.ts for full redirect coverage.
|
|
268
|
+
*/
|
|
269
|
+
getCustomRedirects(): Promise<{
|
|
270
|
+
source_path: string;
|
|
271
|
+
destination_path: string;
|
|
272
|
+
permanent: boolean;
|
|
273
|
+
}[]>;
|
|
274
|
+
/**
|
|
275
|
+
* Get form submissions for a specific form.
|
|
276
|
+
* Useful for displaying testimonials, reviews, etc.
|
|
277
|
+
*/
|
|
278
|
+
getFormSubmissions(formSlug: string, options?: {
|
|
279
|
+
status?: string;
|
|
280
|
+
limit?: number;
|
|
281
|
+
offset?: number;
|
|
282
|
+
}): Promise<Record<string, unknown>[]>;
|
|
283
|
+
/**
|
|
284
|
+
* Get a form configuration by slug.
|
|
285
|
+
*/
|
|
286
|
+
getForm(formSlug: string): Promise<Record<string, unknown> | null>;
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
declare function createShopClient(supabase: SupabaseClient, options: {
|
|
290
|
+
apiKey: string;
|
|
291
|
+
appUrl?: string;
|
|
292
|
+
}): {
|
|
293
|
+
getProducts(queryOptions?: ProductQueryOptions): Promise<Product[]>;
|
|
294
|
+
getProductBySlug(slug: string): Promise<Product | null>;
|
|
295
|
+
getProductCategories(): Promise<string[]>;
|
|
296
|
+
createOrder(params: CreateOrderParams): Promise<CreateOrderResult>;
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
interface CmsAnalyticsProps {
|
|
300
|
+
/** The CMS tracking endpoint URL */
|
|
301
|
+
trackingUrl?: string;
|
|
302
|
+
/** Tenant API key */
|
|
303
|
+
apiKey: string;
|
|
304
|
+
/** Content item ID (from CMS) */
|
|
305
|
+
contentItemId?: string;
|
|
306
|
+
/** Content type slug (e.g. "blog_posts") */
|
|
307
|
+
contentTypeSlug: string;
|
|
308
|
+
/** Item slug (e.g. "my-post") */
|
|
309
|
+
itemSlug: string;
|
|
310
|
+
/** Enable scroll depth tracking (default: true) */
|
|
311
|
+
trackScroll?: boolean;
|
|
312
|
+
/** Enable time-on-page tracking (default: true) */
|
|
313
|
+
trackTime?: boolean;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Drop-in analytics component for CMS content pages.
|
|
317
|
+
* Tracks page views, scroll depth, and time on page.
|
|
318
|
+
*
|
|
319
|
+
* Usage:
|
|
320
|
+
* ```tsx
|
|
321
|
+
* <CmsAnalytics
|
|
322
|
+
* apiKey={process.env.NEXT_PUBLIC_CMS_API_KEY!}
|
|
323
|
+
* contentTypeSlug="blog_posts"
|
|
324
|
+
* itemSlug={params.slug}
|
|
325
|
+
* />
|
|
326
|
+
* ```
|
|
327
|
+
*/
|
|
328
|
+
declare function CmsAnalytics({ trackingUrl, apiKey, contentItemId, contentTypeSlug, itemSlug, trackScroll, trackTime, }: CmsAnalyticsProps): null;
|
|
329
|
+
|
|
330
|
+
interface PageTrackerProps {
|
|
331
|
+
/** The CMS tracking endpoint URL */
|
|
332
|
+
trackingUrl?: string;
|
|
333
|
+
/** Tenant API key */
|
|
334
|
+
apiKey: string;
|
|
335
|
+
/** Enable scroll depth tracking (default: true) */
|
|
336
|
+
trackScroll?: boolean;
|
|
337
|
+
/** Enable time-on-page tracking (default: true) */
|
|
338
|
+
trackTime?: boolean;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Site-wide page tracker. Add once in root layout to track all pages.
|
|
342
|
+
* Automatically detects CMS content pages from URL structure.
|
|
343
|
+
*
|
|
344
|
+
* Usage in src/app/layout.tsx:
|
|
345
|
+
* ```tsx
|
|
346
|
+
* import { PageTracker } from "@distinct-cms/client"
|
|
347
|
+
*
|
|
348
|
+
* <body>
|
|
349
|
+
* {children}
|
|
350
|
+
* <PageTracker apiKey={process.env.NEXT_PUBLIC_CMS_API_KEY!} />
|
|
351
|
+
* </body>
|
|
352
|
+
* ```
|
|
353
|
+
*/
|
|
354
|
+
declare function PageTracker({ trackingUrl, apiKey, trackScroll, trackTime, }: PageTrackerProps): null;
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* CDN image transform helpers using Supabase Storage's built-in image transformation.
|
|
358
|
+
*
|
|
359
|
+
* Converts /object/public/ URLs to /render/image/public/ with transform params.
|
|
360
|
+
* Works both server-side and client-side (no Node.js-only APIs).
|
|
361
|
+
*/
|
|
362
|
+
interface ImageTransformOptions {
|
|
363
|
+
width?: number;
|
|
364
|
+
height?: number;
|
|
365
|
+
quality?: number;
|
|
366
|
+
resize?: "contain" | "cover" | "fill";
|
|
367
|
+
format?: "origin";
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Transform a Supabase Storage URL to use Supabase's image transformation.
|
|
371
|
+
* Converts /object/public/ URLs to /render/image/public/ with transform params.
|
|
372
|
+
*/
|
|
373
|
+
declare function getTransformUrl(originalUrl: string, options?: ImageTransformOptions): string;
|
|
374
|
+
/**
|
|
375
|
+
* Generate a srcSet string for responsive images.
|
|
376
|
+
*/
|
|
377
|
+
declare function getSrcSet(originalUrl: string, widths?: number[], quality?: number): string;
|
|
378
|
+
/**
|
|
379
|
+
* Generate common image sizes for different use cases.
|
|
380
|
+
*/
|
|
381
|
+
declare const IMAGE_PRESETS: {
|
|
382
|
+
readonly thumbnail: {
|
|
383
|
+
readonly width: 150;
|
|
384
|
+
readonly height: 150;
|
|
385
|
+
readonly resize: "cover";
|
|
386
|
+
readonly quality: 70;
|
|
387
|
+
};
|
|
388
|
+
readonly card: {
|
|
389
|
+
readonly width: 400;
|
|
390
|
+
readonly height: 300;
|
|
391
|
+
readonly resize: "cover";
|
|
392
|
+
readonly quality: 80;
|
|
393
|
+
};
|
|
394
|
+
readonly hero: {
|
|
395
|
+
readonly width: 1200;
|
|
396
|
+
readonly height: 630;
|
|
397
|
+
readonly resize: "cover";
|
|
398
|
+
readonly quality: 85;
|
|
399
|
+
};
|
|
400
|
+
readonly og: {
|
|
401
|
+
readonly width: 1200;
|
|
402
|
+
readonly height: 630;
|
|
403
|
+
readonly resize: "cover";
|
|
404
|
+
readonly quality: 90;
|
|
405
|
+
};
|
|
406
|
+
readonly avatar: {
|
|
407
|
+
readonly width: 80;
|
|
408
|
+
readonly height: 80;
|
|
409
|
+
readonly resize: "cover";
|
|
410
|
+
readonly quality: 75;
|
|
411
|
+
};
|
|
412
|
+
readonly full: {
|
|
413
|
+
readonly width: 1920;
|
|
414
|
+
readonly resize: "contain";
|
|
415
|
+
readonly quality: 85;
|
|
416
|
+
};
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
export { CmsAnalytics, type CmsClientOptions, type ContentItem, type ContentQueryOptions, type ContentType, type ContentTypeSeoConfig, type CreateOrderParams, type CreateOrderResult, type FieldDefinition, type FieldType, IMAGE_PRESETS, type ImageConfig, type ImageTransformOptions, type MediaItem, type OrderAddress, PageTracker, type Product, type ProductOption, type ProductQueryOptions, type ProductVariant, type Profile, type Tenant, type TenantMembership, createCmsClient, createShopClient, getSrcSet, getTransformUrl };
|