@leadcms/sdk 3.1.1 → 3.3.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.
Files changed (72) hide show
  1. package/README.md +104 -50
  2. package/dist/cli/bin/generate-env.d.ts +1 -1
  3. package/dist/cli/bin/generate-env.d.ts.map +1 -1
  4. package/dist/cli/bin/generate-env.js +2 -2
  5. package/dist/cli/bin/generate-env.js.map +1 -1
  6. package/dist/cli/bin/pull-all.js +5 -1
  7. package/dist/cli/bin/pull-all.js.map +1 -1
  8. package/dist/cli/bin/pull-comments.js +3 -1
  9. package/dist/cli/bin/pull-comments.js.map +1 -1
  10. package/dist/cli/bin/pull-content.js +2 -1
  11. package/dist/cli/bin/pull-content.js.map +1 -1
  12. package/dist/cli/bin/pull-media.js +3 -1
  13. package/dist/cli/bin/pull-media.js.map +1 -1
  14. package/dist/cli/index.js +8 -4
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/index.d.ts +2 -0
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +2 -0
  19. package/dist/index.js.map +1 -1
  20. package/dist/lib/cms.d.ts.map +1 -1
  21. package/dist/lib/cms.js +0 -38
  22. package/dist/lib/cms.js.map +1 -1
  23. package/dist/lib/content-merge.d.ts +80 -0
  24. package/dist/lib/content-merge.d.ts.map +1 -0
  25. package/dist/lib/content-merge.js +350 -0
  26. package/dist/lib/content-merge.js.map +1 -0
  27. package/dist/lib/content-transformation.d.ts +0 -10
  28. package/dist/lib/content-transformation.d.ts.map +1 -1
  29. package/dist/lib/content-transformation.js +18 -32
  30. package/dist/lib/content-transformation.js.map +1 -1
  31. package/dist/scripts/fetch-leadcms-comments.d.ts +6 -1
  32. package/dist/scripts/fetch-leadcms-comments.d.ts.map +1 -1
  33. package/dist/scripts/fetch-leadcms-comments.js +36 -8
  34. package/dist/scripts/fetch-leadcms-comments.js.map +1 -1
  35. package/dist/scripts/fetch-leadcms-content.d.ts +38 -1
  36. package/dist/scripts/fetch-leadcms-content.d.ts.map +1 -1
  37. package/dist/scripts/fetch-leadcms-content.js +337 -63
  38. package/dist/scripts/fetch-leadcms-content.js.map +1 -1
  39. package/dist/scripts/generate-env-js.d.ts +13 -1
  40. package/dist/scripts/generate-env-js.d.ts.map +1 -1
  41. package/dist/scripts/generate-env-js.js +33 -15
  42. package/dist/scripts/generate-env-js.js.map +1 -1
  43. package/dist/scripts/init-leadcms.d.ts +5 -1
  44. package/dist/scripts/init-leadcms.d.ts.map +1 -1
  45. package/dist/scripts/init-leadcms.js +11 -6
  46. package/dist/scripts/init-leadcms.js.map +1 -1
  47. package/dist/scripts/leadcms-helpers.d.ts +1 -6
  48. package/dist/scripts/leadcms-helpers.d.ts.map +1 -1
  49. package/dist/scripts/leadcms-helpers.js.map +1 -1
  50. package/dist/scripts/pull-all.d.ts +23 -0
  51. package/dist/scripts/pull-all.d.ts.map +1 -1
  52. package/dist/scripts/pull-all.js +83 -2
  53. package/dist/scripts/pull-all.js.map +1 -1
  54. package/dist/scripts/pull-comments.d.ts +5 -1
  55. package/dist/scripts/pull-comments.d.ts.map +1 -1
  56. package/dist/scripts/pull-comments.js +8 -1
  57. package/dist/scripts/pull-comments.js.map +1 -1
  58. package/dist/scripts/pull-content.d.ts +2 -0
  59. package/dist/scripts/pull-content.d.ts.map +1 -1
  60. package/dist/scripts/pull-content.js +7 -1
  61. package/dist/scripts/pull-content.js.map +1 -1
  62. package/dist/scripts/pull-media.d.ts +5 -1
  63. package/dist/scripts/pull-media.d.ts.map +1 -1
  64. package/dist/scripts/pull-media.js +8 -1
  65. package/dist/scripts/pull-media.js.map +1 -1
  66. package/dist/scripts/push-leadcms-content.d.ts +38 -0
  67. package/dist/scripts/push-leadcms-content.d.ts.map +1 -1
  68. package/dist/scripts/push-leadcms-content.js +17 -4
  69. package/dist/scripts/push-leadcms-content.js.map +1 -1
  70. package/dist/scripts/sse-watcher.d.ts.map +1 -1
  71. package/dist/scripts/sse-watcher.js.map +1 -1
  72. package/package.json +3 -2
package/README.md CHANGED
@@ -5,6 +5,7 @@ A comprehensive, framework-agnostic SDK and CLI tools for integrating with LeadC
5
5
  ## Installation
6
6
 
7
7
  ### For Build-Time Usage (Most Common)
8
+
8
9
  If you only use LeadCMS SDK during the build process (static site generation):
9
10
 
10
11
  ```bash
@@ -12,6 +13,7 @@ npm install --save-dev @leadcms/sdk
12
13
  ```
13
14
 
14
15
  ### For Runtime Usage
16
+
15
17
  If you need LeadCMS SDK in your production application (SSR, API routes, live preview):
16
18
 
17
19
  ```bash
@@ -19,6 +21,7 @@ npm install @leadcms/sdk
19
21
  ```
20
22
 
21
23
  ### Global CLI Installation
24
+
22
25
  For CLI tools and project setup:
23
26
 
24
27
  ```bash
@@ -28,18 +31,21 @@ npm install -g @leadcms/sdk
28
31
  ### When to Use Each Installation Method
29
32
 
30
33
  **Development Dependency (`--save-dev`)** - Recommended for:
34
+
31
35
  - ✅ Static Site Generators (Next.js, Astro, Gatsby, Nuxt)
32
36
  - ✅ Build-time content fetching and processing
33
37
  - ✅ Static route generation
34
38
  - ✅ Content pre-processing during build
35
39
 
36
40
  **Production Dependency (`--save`)** - Use when you need:
41
+
37
42
  - 🔄 Server-Side Rendering (SSR) with dynamic content
38
43
  - 🔄 API routes that fetch LeadCMS content at runtime
39
44
  - 🔄 Live preview functionality in production
40
45
  - 🔄 Runtime content loading and processing
41
46
 
42
47
  **Global Installation (`-g`)** - Best for:
48
+
43
49
  - 🛠️ CLI commands across multiple projects
44
50
  - 🛠️ Project initialization and setup
45
51
  - 🛠️ Content fetching and Docker template generation
@@ -49,18 +55,23 @@ npm install -g @leadcms/sdk
49
55
  Get started with LeadCMS in 3 simple steps:
50
56
 
51
57
  ### 1. Initialize Your Project
58
+
52
59
  ```bash
53
60
  npx leadcms init
54
61
  ```
62
+
55
63
  This will:
64
+
56
65
  - Connect to your LeadCMS instance
57
66
  - Detect available entity types (content, media, comments)
58
67
  - Create configuration files (`.env` and optionally `leadcms.config.json`)
59
68
 
60
69
  ### 2. Authenticate (for write access)
70
+
61
71
  ```bash
62
72
  npx leadcms login
63
73
  ```
74
+
64
75
  - **LeadCMS v1.2.88+**: Automatic device authentication via browser
65
76
  - **Older versions**: Guided manual token extraction
66
77
  - Saves your API token securely to `.env`
@@ -68,9 +79,11 @@ npx leadcms login
68
79
  **Skip this step** if you only need read-only access to public content.
69
80
 
70
81
  ### 3. Download Your Content
82
+
71
83
  ```bash
72
84
  npx leadcms pull
73
85
  ```
86
+
74
87
  Downloads all content, media, and comments to your local project.
75
88
 
76
89
  **That's it!** You're ready to use LeadCMS content in your application. See [Usage Examples](#usage-examples) below.
@@ -82,18 +95,21 @@ Downloads all content, media, and comments to your local project.
82
95
  The LeadCMS SDK includes comprehensive CI/CD workflows for GitHub Actions that provide:
83
96
 
84
97
  ### 🧪 Automated Testing
98
+
85
99
  - **Multi-Node Support**: Tests run on Node.js 18, 20, and 22
86
100
  - **Coverage Reports**: Automatic coverage reporting with visual coverage diffs on PRs
87
101
  - **Test Results**: Interactive test results displayed directly in GitHub Actions
88
102
  - **JUnit XML**: Structured test output for integration with external tools
89
103
 
90
104
  ### 📊 Coverage Reporting
105
+
91
106
  - **LCOV Reports**: Line and branch coverage tracking
92
107
  - **PR Comments**: Automatic coverage comments on pull requests showing coverage changes
93
108
  - **Coverage Artifacts**: HTML coverage reports archived for 30 days
94
109
  - **Multiple Formats**: Coverage available in LCOV, HTML, and Clover formats
95
110
 
96
111
  ### 🔧 Quality Checks
112
+
97
113
  - **TypeScript Compilation**: Ensures type safety across all Node.js versions
98
114
  - **Package Validation**: Verifies package structure and CLI functionality
99
115
  - **Docker Template Testing**: Validates generated Docker configurations
@@ -115,8 +131,8 @@ jobs:
115
131
  - uses: actions/checkout@v4
116
132
  - uses: actions/setup-node@v4
117
133
  with:
118
- node-version: '20'
119
- cache: 'npm'
134
+ node-version: "20"
135
+ cache: "npm"
120
136
  - run: npm ci
121
137
  - run: npm test
122
138
  ```
@@ -136,13 +152,17 @@ npm run test:watch
136
152
 
137
153
  ### Test Coverage
138
154
 
139
- The SDK maintains high test coverage with comprehensive unit tests covering:
140
- - 📄 Content retrieval and parsing
155
+ The SDK maintains high test coverage with **481 tests across 30 test suites**, covering:
156
+
157
+ - 📄 Content retrieval, parsing, and transformation
141
158
  - 🌍 Multi-language support and translations
142
159
  - 📝 Draft content handling and user-specific overrides
143
160
  - 🏗️ Build-time optimizations and caching
144
161
  - 🔧 Configuration management and validation
145
162
  - 🔄 Push/Pull synchronization with conflict detection
163
+ - 🗂️ Content rename, type change, and deletion handling
164
+ - 🗑️ Media deletion sync and file cleanup
165
+ - 🔁 Sync token migration and edge cases
146
166
  - 🖥️ CLI command functionality with mocked API responses
147
167
 
148
168
  ### Testing with Mock Data
@@ -159,6 +179,7 @@ LEADCMS_USE_MOCK=true LEADCMS_MOCK_SCENARIO=mixedOperations npx leadcms push --d
159
179
  ```
160
180
 
161
181
  **Available Mock Scenarios:**
182
+
162
183
  - `allNew` - Local content that doesn't exist remotely (default)
163
184
  - `noChanges` - All content is in sync
164
185
  - `hasConflicts` - Remote content is newer than local
@@ -167,6 +188,7 @@ LEADCMS_USE_MOCK=true LEADCMS_MOCK_SCENARIO=mixedOperations npx leadcms push --d
167
188
  - `missingContentTypes` - Content with unknown types
168
189
 
169
190
  **Mock Mode Activation:**
191
+
170
192
  - `NODE_ENV=test` - Automatically uses mock mode
171
193
  - `LEADCMS_USE_MOCK=true` - Force mock mode
172
194
 
@@ -228,15 +250,15 @@ npx leadcms init
228
250
  For advanced use cases, you can configure the SDK programmatically:
229
251
 
230
252
  ```typescript
231
- import { configure } from '@leadcms/sdk';
253
+ import { configure } from "@leadcms/sdk";
232
254
 
233
255
  configure({
234
- url: 'https://your-leadcms-instance.com',
235
- apiKey: 'your-api-key',
236
- defaultLanguage: 'en',
237
- contentDir: '.leadcms/content',
238
- mediaDir: 'public/media',
239
- enableDrafts: false
256
+ url: "https://your-leadcms-instance.com",
257
+ apiKey: "your-api-key",
258
+ defaultLanguage: "en",
259
+ contentDir: ".leadcms/content",
260
+ mediaDir: "public/media",
261
+ enableDrafts: false,
240
262
  });
241
263
  ```
242
264
 
@@ -254,6 +276,7 @@ configure({
254
276
  ## CLI Usage
255
277
 
256
278
  ### Check SDK version
279
+
257
280
  ```bash
258
281
  npx leadcms version
259
282
  # or
@@ -263,11 +286,13 @@ npx leadcms --version
263
286
  ```
264
287
 
265
288
  ### Initialize configuration
289
+
266
290
  ```bash
267
291
  npx leadcms init
268
292
  ```
269
293
 
270
294
  Interactive setup wizard that:
295
+
271
296
  1. **Connects to your LeadCMS instance** - Validates URL and checks for existing authentication
272
297
  2. **Fetches configuration** - Retrieves default language and available languages from public `/api/config` endpoint
273
298
  3. **Configures directories** - Sets content and media directories (defaults: `.leadcms/content`, `public/media`)
@@ -277,16 +302,19 @@ Interactive setup wizard that:
277
302
  **Note:** The `/api/config` endpoint is public and works without authentication. For write operations and private content, run `leadcms login` after initialization.
278
303
 
279
304
  ### Login to LeadCMS
305
+
280
306
  ```bash
281
307
  npx leadcms login
282
308
  ```
283
309
 
284
310
  Authenticates with your LeadCMS instance:
311
+
285
312
  - **Device Authentication** (LeadCMS v1.2.88+) - Opens a browser link for secure authentication
286
313
  - **Manual Token** (older versions) - Guides you through extracting an API token
287
314
  - **Saves token** - Automatically stores the token in your `.env` file
288
315
 
289
316
  **When to use:**
317
+
290
318
  - After running `leadcms init` if you need write access
291
319
  - To update an expired or invalid token
292
320
  - When switching between LeadCMS instances
@@ -315,7 +343,7 @@ Would you like to authenticate now? (Y/n): n
315
343
  1. English (United States) [en-US] (default)
316
344
  2. Russian (Russia) [ru-RU]
317
345
 
318
- Default language code [en-US]:
346
+ Default language code [en-US]:
319
347
  ✓ Using default language: en-US
320
348
 
321
349
  📦 Supported entity types:
@@ -341,12 +369,14 @@ Next steps:
341
369
  ```
342
370
 
343
371
  The wizard creates:
372
+
344
373
  - **`.env`** (or `.env` if exists) with `LEADCMS_URL`, `LEADCMS_DEFAULT_LANGUAGE`, and optionally `LEADCMS_API_KEY`
345
374
  - **`leadcms.config.json`** only if custom directories are specified
346
375
 
347
376
  **Anonymous Mode:** Perfect for static sites that only need public content. Omit the API key to skip authentication entirely.
348
377
 
349
378
  ### Generate Docker deployment templates
379
+
350
380
  ```bash
351
381
  npx leadcms docker
352
382
  # Creates Docker files for production and preview deployments
@@ -368,24 +398,36 @@ npx leadcms pull-media
368
398
 
369
399
  # Pull only comments
370
400
  npx leadcms pull-comments
401
+
402
+ # Reset and pull everything from scratch
403
+ npx leadcms pull --reset
371
404
  ```
372
405
 
373
406
  > **Note:** `npx leadcms fetch` is still supported as an alias for backward compatibility.
374
407
 
375
408
  What each command does:
409
+
376
410
  - `npx leadcms pull` - Syncs content, media and comments into your project using the configured directories. Updates incremental sync tokens so subsequent runs are faster.
411
+ - `npx leadcms pull --reset` - Deletes all local content, media, comments, and sync tokens, then performs a full pull from scratch. Useful when local state has become inconsistent or after configuration changes.
377
412
  - `npx leadcms pull-content` - Downloads only content entities (MDX/JSON files) and updates local metadata.
378
413
  - `npx leadcms pull-media` - Downloads media files to your `mediaDir` (e.g., `public/media`). Use this when you changed media or want to refresh assets separately from content.
379
414
  - `npx leadcms pull-comments` - Downloads comments to the comments directory (e.g., `.leadcms/comments/`). Useful when you only need comment updates.
380
415
 
381
- > **Note:** The CLI uses incremental sync tokens to avoid re-downloading unchanged items where supported by the LeadCMS API.
416
+ **Intelligent sync handling:**
417
+
418
+ - **Incremental sync** — Sync tokens avoid re-downloading unchanged items on subsequent pulls.
419
+ - **Rename & type-change cleanup** — When content is renamed (slug change), moved to a different type, or switched format (MDX ↔ JSON), the old file is automatically removed before the new version is written.
420
+ - **Deleted content removal** — Content and media deleted on the server are removed locally during the next pull.
421
+ - **Sync token migration** — When upgrading from SDK ≤ 3.1, legacy sync tokens are automatically migrated to their new location inside each data directory.
382
422
 
383
423
  ### Push local content to LeadCMS
424
+
384
425
  ```bash
385
426
  npx leadcms push [options]
386
427
  ```
387
428
 
388
429
  Push your local content changes to LeadCMS. This command will:
430
+
389
431
  - Analyze local MDX/JSON files and compare with remote content
390
432
  - Detect new content, updates, and conflicts using `updatedAt` timestamps
391
433
  - Prompt for confirmation before making changes
@@ -393,26 +435,29 @@ Push your local content changes to LeadCMS. This command will:
393
435
  - Update local files with remote metadata (id, createdAt, updatedAt) after sync
394
436
 
395
437
  **Options:**
396
- - `--force` - Override remote changes (skip conflict check)
397
438
 
439
+ - `--force` - Override remote changes (skip conflict check)
398
440
 
399
441
  **Content frontmatter / metadata (required and optional fields):**
442
+
400
443
  ```yaml
401
444
  ---
402
- type: "article" # required: Content type (must exist in LeadCMS)
403
- title: "Article Title" # required: Content title
404
- slug: "article-slug" # required: URL slug (unique per locale)
405
- language: "en" # required: Content language
445
+ type: "article" # required: Content type (must exist in LeadCMS)
446
+ title: "Article Title" # required: Content title
447
+ slug: "article-slug" # required: URL slug (unique per locale)
448
+ language: "en" # required: Content language
406
449
  publishedAt: "2024-10-29T10:00:00Z" # optional: Publication date (omit to create a draft or schedule a future publish)
407
450
  # updatedAt: "2024-10-29T10:00:00Z" # optional: maintained by the server; do not set for new content
408
451
  ---
409
452
  ```
410
453
 
411
454
  Notes:
455
+
412
456
  - `publishedAt` is optional. Omitting it is a valid way to create draft or scheduled content depending on your LeadCMS workflow.
413
457
  - `updatedAt` is typically set and maintained by the LeadCMS server after content is created or updated. The SDK will use `updatedAt` when present for conflict detection, but you should not rely on it being set for brand-new local files.
414
458
 
415
459
  ### Check sync status
460
+
416
461
  ```bash
417
462
  npx leadcms status
418
463
  ```
@@ -422,6 +467,7 @@ Shows the current sync status between local and remote **content** without makin
422
467
  **Note:** The `status` command currently only supports content. Media and comments do not have sync status checking yet.
423
468
 
424
469
  ### Watch for real-time updates
470
+
425
471
  ```bash
426
472
  npx leadcms watch
427
473
  ```
@@ -435,9 +481,9 @@ The SDK provides framework-agnostic data access. Most frameworks use it as a **d
435
481
  export function generateStaticParams() {
436
482
  // This runs at BUILD TIME, not runtime
437
483
  const routes = getAllContentRoutes();
438
- return routes.map(route => ({
484
+ return routes.map((route) => ({
439
485
  slug: route.slugParts,
440
- ...(route.isDefaultLocale ? {} : { locale: route.locale })
486
+ ...(route.isDefaultLocale ? {} : { locale: route.locale }),
441
487
  }));
442
488
  }
443
489
 
@@ -445,9 +491,9 @@ export function generateStaticParams() {
445
491
  export function getStaticPaths() {
446
492
  // This runs at BUILD TIME, not runtime
447
493
  const routes = getAllContentRoutes();
448
- return routes.map(route => ({
494
+ return routes.map((route) => ({
449
495
  params: { slug: route.slug },
450
- props: { locale: route.locale, path: route.path }
496
+ props: { locale: route.locale, path: route.path },
451
497
  }));
452
498
  }
453
499
 
@@ -456,11 +502,11 @@ exports.createPages = async ({ actions }) => {
456
502
  const { createPage } = actions;
457
503
  const routes = getAllContentRoutes();
458
504
 
459
- routes.forEach(route => {
505
+ routes.forEach((route) => {
460
506
  createPage({
461
507
  path: route.path,
462
- component: path.resolve('./src/templates/content.js'),
463
- context: { slug: route.slug, locale: route.locale }
508
+ component: path.resolve("./src/templates/content.js"),
509
+ context: { slug: route.slug, locale: route.locale },
464
510
  });
465
511
  });
466
512
  };
@@ -468,18 +514,18 @@ exports.createPages = async ({ actions }) => {
468
514
  // Runtime Usage Examples (Production dependency required)
469
515
 
470
516
  // Next.js API Route (Runtime)
471
- import { getCMSContentBySlugForLocale } from '@leadcms/sdk';
517
+ import { getCMSContentBySlugForLocale } from "@leadcms/sdk";
472
518
 
473
519
  export async function GET(request) {
474
520
  // This runs at REQUEST TIME, needs production dependency
475
- const content = getCMSContentBySlugForLocale('about', 'en');
521
+ const content = getCMSContentBySlugForLocale("about", "en");
476
522
  return Response.json(content);
477
523
  }
478
524
 
479
525
  // Express.js Server (Runtime)
480
- app.get('/api/content/:slug', (req, res) => {
526
+ app.get("/api/content/:slug", (req, res) => {
481
527
  // This runs at REQUEST TIME, needs production dependency
482
- const content = getCMSContentBySlugForLocale(req.params.slug, 'en');
528
+ const content = getCMSContentBySlugForLocale(req.params.slug, "en");
483
529
  res.json(content);
484
530
  });
485
531
  ```
@@ -491,17 +537,17 @@ app.get('/api/content/:slug', (req, res) => {
491
537
  Get content from your LeadCMS instance:
492
538
 
493
539
  ```typescript
494
- import {
540
+ import {
495
541
  getCMSContentBySlugForLocale,
496
542
  getAllContentSlugsForLocale,
497
- getAllContentRoutes
498
- } from '@leadcms/sdk';
543
+ getAllContentRoutes,
544
+ } from "@leadcms/sdk";
499
545
 
500
546
  // Get single content item
501
- const content = getCMSContentBySlugForLocale('about-us', 'en');
547
+ const content = getCMSContentBySlugForLocale("about-us", "en");
502
548
 
503
549
  // Get all content slugs
504
- const slugs = getAllContentSlugsForLocale('en');
550
+ const slugs = getAllContentSlugsForLocale("en");
505
551
 
506
552
  // Get all routes for static generation
507
553
  const routes = getAllContentRoutes();
@@ -514,21 +560,22 @@ const routes = getAllContentRoutes();
514
560
  The SDK automatically detects preview slugs and enables draft content access without requiring explicit configuration:
515
561
 
516
562
  ```typescript
517
- import { getCMSContentBySlugForLocale } from '@leadcms/sdk';
563
+ import { getCMSContentBySlugForLocale } from "@leadcms/sdk";
518
564
 
519
565
  // Normal slug - only returns published content
520
- const published = getCMSContentBySlugForLocale('home', 'en');
566
+ const published = getCMSContentBySlugForLocale("home", "en");
521
567
  // Returns: null if content has no publishedAt
522
568
 
523
569
  // Preview slug with GUID - automatically enables draft access
524
570
  const preview = getCMSContentBySlugForLocale(
525
- 'home-550e8400-e29b-41d4-a716-446655440000',
526
- 'en'
571
+ "home-550e8400-e29b-41d4-a716-446655440000",
572
+ "en",
527
573
  );
528
574
  // Returns: draft content even without publishedAt
529
575
  ```
530
576
 
531
577
  **How it works:**
578
+
532
579
  - When a slug contains a GUID pattern (e.g., `home-{userUid}`), the SDK automatically:
533
580
  1. Detects the GUID suffix
534
581
  2. Extracts the base slug and userUid
@@ -536,6 +583,7 @@ const preview = getCMSContentBySlugForLocale(
536
583
  4. Returns user's draft version or falls back to base content
537
584
 
538
585
  **Benefits:**
586
+
539
587
  - ✅ Zero configuration - works automatically with LeadCMS preview URLs
540
588
  - 🔒 Secure - only preview slugs (with valid GUID) can access drafts
541
589
  - 🔄 Backward compatible - normal slugs continue to require `publishedAt`
@@ -570,18 +618,15 @@ npx leadcms pull-comments
570
618
  ```
571
619
 
572
620
  ```typescript
573
- import {
574
- getCommentsForContent,
575
- getCommentsTreeForContent
576
- } from '@leadcms/sdk';
621
+ import { getCommentsForContent, getCommentsTreeForContent } from "@leadcms/sdk";
577
622
 
578
623
  // Get flat list of comments
579
624
  const comments = getCommentsForContent(contentId);
580
625
 
581
626
  // Get comments as tree for threading
582
627
  const tree = getCommentsTreeForContent(contentId, undefined, {
583
- sortOrder: 'newest',
584
- replySortOrder: 'oldest'
628
+ sortOrder: "newest",
629
+ replySortOrder: "oldest",
585
630
  });
586
631
  ```
587
632
 
@@ -598,6 +643,7 @@ npx leadcms docker
598
643
  ```
599
644
 
600
645
  This creates:
646
+
601
647
  - `Dockerfile` - Production static site deployment
602
648
  - `nginx.conf` - Optimized nginx configuration
603
649
  - `scripts/inject-runtime-env.sh` - Runtime environment injection
@@ -650,6 +696,7 @@ docker run -p 80:80 \
650
696
  ## Debugging
651
697
 
652
698
  ### Debug Logging
699
+
653
700
  Control SDK logging verbosity with environment variables:
654
701
 
655
702
  ```bash
@@ -663,32 +710,35 @@ NODE_ENV=production npm run build
663
710
  Debug mode is automatically enabled when `NODE_ENV=development` or `LEADCMS_DEBUG=true`.
664
711
 
665
712
  ### Error Handling
713
+
666
714
  The SDK provides detailed error information for missing configuration files:
667
715
 
668
716
  ```typescript
669
- import { loadContentConfig, loadContentConfigStrict } from '@leadcms/sdk';
717
+ import { loadContentConfig, loadContentConfigStrict } from "@leadcms/sdk";
670
718
 
671
719
  // Graceful handling - returns null for missing files
672
- const config = loadContentConfig('layout'); // Returns null if missing
720
+ const config = loadContentConfig("layout"); // Returns null if missing
673
721
 
674
722
  // Strict handling - throws detailed errors for debugging
675
723
  try {
676
- const config = loadContentConfigStrict('layout');
724
+ const config = loadContentConfigStrict("layout");
677
725
  } catch (error) {
678
- console.log('Missing configuration:', error.configName);
679
- console.log('Expected locale:', error.locale);
680
- console.log('Full error:', error.message);
726
+ console.log("Missing configuration:", error.configName);
727
+ console.log("Expected locale:", error.locale);
728
+ console.log("Full error:", error.message);
681
729
  // Error message includes: configName, locale, and expected file path
682
730
  }
683
731
  ```
684
732
 
685
733
  **Error Details Include:**
734
+
686
735
  - `configName` - The specific configuration name that was requested
687
736
  - `locale` - The locale that was being loaded
688
737
  - `message` - Full descriptive error including expected file path
689
738
  - Clear console logging of missing files with exact paths
690
739
 
691
740
  ### Performance Tips
741
+
692
742
  - ✅ Use configuration files instead of programmatic configuration for better caching
693
743
  - ✅ The SDK caches file reads automatically - no manual optimization needed
694
744
  - ✅ In production builds, logging is minimal to reduce noise
@@ -702,18 +752,22 @@ try {
702
752
  - **[Documentation Index](./docs/README)** - Central hub for all documentation
703
753
 
704
754
  #### Content & Media
755
+
705
756
  - **[Content Management](./docs/CONTENT_MANAGEMENT.md)** - Retrieving, organizing, and working with content
706
757
  - **[Media Management](./docs/MEDIA_MANAGEMENT.md)** - Handling media files and optimization
707
758
  - **[Draft Handling](./docs/DRAFT_HANDLING.md)** - Working with draft content and user-specific drafts
708
759
 
709
760
  #### Comments
761
+
710
762
  - **[Comment Tree Guide](./docs/COMMENT_TREE.md)** - Building threaded comment interfaces with sorting and filtering
711
763
 
712
764
  #### Setup & Configuration
765
+
713
766
  - **[Interactive Init](./docs/INTERACTIVE_INIT.md)** - Setup wizard and authentication
714
767
  - **[Public API Mode](./docs/PUBLIC_API_MODE.md)** - Security-first approach and operation modes
715
768
 
716
769
  #### Development
770
+
717
771
  - **[Development Guide](./docs/DEVELOPMENT.md)** - Local development, testing, and debugging
718
772
  - **[GitHub Actions](./docs/GITHUB_ACTIONS.md)** - CI/CD setup and automated publishing
719
773
 
@@ -2,5 +2,5 @@
2
2
  /**
3
3
  * LeadCMS Generate Env CLI Entry Point
4
4
  */
5
- import '../../scripts/generate-env-js.js';
5
+ export {};
6
6
  //# sourceMappingURL=generate-env.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate-env.d.ts","sourceRoot":"","sources":["../../../src/cli/bin/generate-env.ts"],"names":[],"mappings":";AACA;;GAEG;AAGH,OAAO,kCAAkC,CAAC"}
1
+ {"version":3,"file":"generate-env.d.ts","sourceRoot":"","sources":["../../../src/cli/bin/generate-env.ts"],"names":[],"mappings":";AACA;;GAEG"}
@@ -2,6 +2,6 @@
2
2
  /**
3
3
  * LeadCMS Generate Env CLI Entry Point
4
4
  */
5
- // Import and run the generate-env script directly
6
- import '../../scripts/generate-env-js.js';
5
+ import { generateEnv } from '../../scripts/generate-env-js.js';
6
+ generateEnv();
7
7
  //# sourceMappingURL=generate-env.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate-env.js","sourceRoot":"","sources":["../../../src/cli/bin/generate-env.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,kDAAkD;AAClD,OAAO,kCAAkC,CAAC"}
1
+ {"version":3,"file":"generate-env.js","sourceRoot":"","sources":["../../../src/cli/bin/generate-env.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAE/D,WAAW,EAAE,CAAC"}
@@ -7,6 +7,7 @@ const args = process.argv.slice(2);
7
7
  // Parse target ID or slug
8
8
  let targetId;
9
9
  let targetSlug;
10
+ let reset = false;
10
11
  const idIndex = args.findIndex(arg => arg === '--id');
11
12
  if (idIndex !== -1 && args[idIndex + 1]) {
12
13
  targetId = args[idIndex + 1];
@@ -15,7 +16,10 @@ const slugIndex = args.findIndex(arg => arg === '--slug');
15
16
  if (slugIndex !== -1 && args[slugIndex + 1]) {
16
17
  targetSlug = args[slugIndex + 1];
17
18
  }
18
- pullAll({ targetId, targetSlug }).catch((error) => {
19
+ if (args.includes('--reset')) {
20
+ reset = true;
21
+ }
22
+ pullAll({ targetId, targetSlug, reset }).catch((error) => {
19
23
  console.error('Error running LeadCMS pull:', error.message);
20
24
  process.exit(1);
21
25
  });
@@ -1 +1 @@
1
- {"version":3,"file":"pull-all.js","sourceRoot":"","sources":["../../../src/cli/bin/pull-all.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEpD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,0BAA0B;AAC1B,IAAI,QAA4B,CAAC;AACjC,IAAI,UAA8B,CAAC;AAEnC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC;AACtD,IAAI,OAAO,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC;IACxC,QAAQ,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC;AAC1D,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC;IAC5C,UAAU,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,OAAO,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAU,EAAE,EAAE;IACrD,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"pull-all.js","sourceRoot":"","sources":["../../../src/cli/bin/pull-all.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEpD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,0BAA0B;AAC1B,IAAI,QAA4B,CAAC;AACjC,IAAI,UAA8B,CAAC;AACnC,IAAI,KAAK,GAAG,KAAK,CAAC;AAElB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC;AACtD,IAAI,OAAO,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC;IACxC,QAAQ,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC;AAC1D,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC;IAC5C,UAAU,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;IAC7B,KAAK,GAAG,IAAI,CAAC;AACf,CAAC;AAED,OAAO,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAU,EAAE,EAAE;IAC5D,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -3,7 +3,9 @@
3
3
  * LeadCMS Pull Comments CLI Entry Point
4
4
  */
5
5
  import { pullComments } from '../../scripts/pull-comments.js';
6
- pullComments().catch((error) => {
6
+ const args = process.argv.slice(2);
7
+ const reset = args.includes('--reset');
8
+ pullComments({ reset }).catch((error) => {
7
9
  console.error('Error running LeadCMS pull comments:', error.message);
8
10
  process.exit(1);
9
11
  });
@@ -1 +1 @@
1
- {"version":3,"file":"pull-comments.js","sourceRoot":"","sources":["../../../src/cli/bin/pull-comments.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAE9D,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC,KAAU,EAAE,EAAE;IAClC,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"pull-comments.js","sourceRoot":"","sources":["../../../src/cli/bin/pull-comments.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAE9D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAEvC,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAU,EAAE,EAAE;IAC3C,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -15,7 +15,8 @@ const slugIndex = args.findIndex(arg => arg === '--slug');
15
15
  if (slugIndex !== -1 && args[slugIndex + 1]) {
16
16
  targetSlug = args[slugIndex + 1];
17
17
  }
18
- pullContent({ targetId, targetSlug }).catch((error) => {
18
+ const reset = args.includes('--reset');
19
+ pullContent({ targetId, targetSlug, reset }).catch((error) => {
19
20
  console.error('Error running LeadCMS pull content:', error.message);
20
21
  process.exit(1);
21
22
  });
@@ -1 +1 @@
1
- {"version":3,"file":"pull-content.js","sourceRoot":"","sources":["../../../src/cli/bin/pull-content.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAE5D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,0BAA0B;AAC1B,IAAI,QAA4B,CAAC;AACjC,IAAI,UAA8B,CAAC;AAEnC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC;AACtD,IAAI,OAAO,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC;IACxC,QAAQ,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC;AAC1D,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC;IAC5C,UAAU,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,WAAW,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAU,EAAE,EAAE;IACzD,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"pull-content.js","sourceRoot":"","sources":["../../../src/cli/bin/pull-content.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAE5D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,0BAA0B;AAC1B,IAAI,QAA4B,CAAC;AACjC,IAAI,UAA8B,CAAC;AAEnC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC;AACtD,IAAI,OAAO,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC;IACxC,QAAQ,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC;AAC1D,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC;IAC5C,UAAU,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAEvC,WAAW,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAU,EAAE,EAAE;IAChE,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -3,7 +3,9 @@
3
3
  * LeadCMS Pull Media CLI Entry Point
4
4
  */
5
5
  import { pullMedia } from '../../scripts/pull-media.js';
6
- pullMedia().catch((error) => {
6
+ const args = process.argv.slice(2);
7
+ const reset = args.includes('--reset');
8
+ pullMedia({ reset }).catch((error) => {
7
9
  console.error('Error running LeadCMS pull media:', error.message);
8
10
  process.exit(1);
9
11
  });
@@ -1 +1 @@
1
- {"version":3,"file":"pull-media.js","sourceRoot":"","sources":["../../../src/cli/bin/pull-media.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAExD,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,KAAU,EAAE,EAAE;IAC/B,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"pull-media.js","sourceRoot":"","sources":["../../../src/cli/bin/pull-media.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAExD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAEvC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAU,EAAE,EAAE;IACxC,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}