@leadcms/sdk 3.0.2 → 3.2.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/README.md +89 -47
- package/dist/cli/bin/generate-env.js +0 -0
- package/dist/cli/bin/init.js +0 -0
- package/dist/cli/bin/login.js +0 -0
- package/dist/cli/bin/pull-all.js +17 -1
- package/dist/cli/bin/pull-all.js.map +1 -1
- package/dist/cli/bin/pull-comments.js +0 -0
- package/dist/cli/bin/pull-content.js +13 -1
- package/dist/cli/bin/pull-content.js.map +1 -1
- package/dist/cli/bin/pull-media.js +0 -0
- package/dist/cli/bin/push-all.d.ts +7 -0
- package/dist/cli/bin/push-all.d.ts.map +1 -0
- package/dist/cli/bin/push-all.js +59 -0
- package/dist/cli/bin/push-all.js.map +1 -0
- package/dist/cli/bin/push-content.d.ts +6 -0
- package/dist/cli/bin/push-content.d.ts.map +1 -0
- package/dist/cli/bin/push-content.js +27 -0
- package/dist/cli/bin/push-content.js.map +1 -0
- package/dist/cli/bin/push-media.d.ts +6 -0
- package/dist/cli/bin/push-media.d.ts.map +1 -0
- package/dist/cli/bin/push-media.js +21 -0
- package/dist/cli/bin/push-media.js.map +1 -0
- package/dist/cli/bin/push.js +0 -0
- package/dist/cli/bin/status-all.d.ts +7 -0
- package/dist/cli/bin/status-all.d.ts.map +1 -0
- package/dist/cli/bin/status-all.js +56 -0
- package/dist/cli/bin/status-all.js.map +1 -0
- package/dist/cli/bin/status-content.d.ts +6 -0
- package/dist/cli/bin/status-content.d.ts.map +1 -0
- package/dist/cli/bin/status-content.js +30 -0
- package/dist/cli/bin/status-content.js.map +1 -0
- package/dist/cli/bin/status-media.d.ts +6 -0
- package/dist/cli/bin/status-media.d.ts.map +1 -0
- package/dist/cli/bin/status-media.js +20 -0
- package/dist/cli/bin/status-media.js.map +1 -0
- package/dist/cli/bin/status.js +0 -0
- package/dist/cli/bin/watch.js +0 -0
- package/dist/cli/index.js +39 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/lib/cms.d.ts.map +1 -1
- package/dist/lib/cms.js +0 -38
- package/dist/lib/cms.js.map +1 -1
- package/dist/lib/content-transformation.d.ts +0 -10
- package/dist/lib/content-transformation.d.ts.map +1 -1
- package/dist/lib/content-transformation.js +18 -32
- package/dist/lib/content-transformation.js.map +1 -1
- package/dist/lib/data-service.d.ts +42 -0
- package/dist/lib/data-service.d.ts.map +1 -1
- package/dist/lib/data-service.js +316 -6
- package/dist/lib/data-service.js.map +1 -1
- package/dist/scripts/fetch-leadcms-comments.d.ts +6 -1
- package/dist/scripts/fetch-leadcms-comments.d.ts.map +1 -1
- package/dist/scripts/fetch-leadcms-comments.js +36 -8
- package/dist/scripts/fetch-leadcms-comments.js.map +1 -1
- package/dist/scripts/fetch-leadcms-content.d.ts +37 -1
- package/dist/scripts/fetch-leadcms-content.d.ts.map +1 -1
- package/dist/scripts/fetch-leadcms-content.js +239 -58
- package/dist/scripts/fetch-leadcms-content.js.map +1 -1
- package/dist/scripts/generate-env-js.d.ts +8 -1
- package/dist/scripts/generate-env-js.d.ts.map +1 -1
- package/dist/scripts/generate-env-js.js +26 -10
- package/dist/scripts/generate-env-js.js.map +1 -1
- package/dist/scripts/init-leadcms.d.ts +5 -1
- package/dist/scripts/init-leadcms.d.ts.map +1 -1
- package/dist/scripts/init-leadcms.js +11 -6
- package/dist/scripts/init-leadcms.js.map +1 -1
- package/dist/scripts/leadcms-helpers.d.ts +1 -6
- package/dist/scripts/leadcms-helpers.d.ts.map +1 -1
- package/dist/scripts/leadcms-helpers.js.map +1 -1
- package/dist/scripts/pull-all.d.ts +13 -1
- package/dist/scripts/pull-all.d.ts.map +1 -1
- package/dist/scripts/pull-all.js +66 -2
- package/dist/scripts/pull-all.js.map +1 -1
- package/dist/scripts/pull-content.d.ts +5 -1
- package/dist/scripts/pull-content.d.ts.map +1 -1
- package/dist/scripts/pull-content.js +48 -1
- package/dist/scripts/pull-content.js.map +1 -1
- package/dist/scripts/push-leadcms-content.d.ts +43 -0
- package/dist/scripts/push-leadcms-content.d.ts.map +1 -1
- package/dist/scripts/push-leadcms-content.js +115 -19
- package/dist/scripts/push-leadcms-content.js.map +1 -1
- package/dist/scripts/push-media.d.ts +136 -0
- package/dist/scripts/push-media.d.ts.map +1 -0
- package/dist/scripts/push-media.js +531 -0
- package/dist/scripts/push-media.js.map +1 -0
- package/dist/scripts/sse-watcher.d.ts.map +1 -1
- package/dist/scripts/sse-watcher.js.map +1 -1
- package/package.json +2 -2
|
@@ -56,17 +56,16 @@ export async function transformRemoteForComparison(remote, localContent, typeMap
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
* Transform remote content to MDX format
|
|
59
|
+
* Transform remote content to MDX format for comparison with local content.
|
|
60
|
+
* Includes ALL non-system remote fields so that field removals in local content
|
|
61
|
+
* are properly detected as changes.
|
|
60
62
|
*/
|
|
61
63
|
function transformToMDXFormatForComparison(remote, localContent) {
|
|
62
|
-
//
|
|
63
|
-
let localFields;
|
|
64
|
+
// Validate that local content is parseable MDX, fall back to full transform if not
|
|
64
65
|
try {
|
|
65
|
-
|
|
66
|
-
localFields = new Set(Object.keys(parsed.data));
|
|
66
|
+
matter(localContent);
|
|
67
67
|
}
|
|
68
68
|
catch (error) {
|
|
69
|
-
// If we can't parse local content, fall back to including all fields
|
|
70
69
|
return transformToMDXFormat(remote);
|
|
71
70
|
}
|
|
72
71
|
let body = remote.body || "";
|
|
@@ -90,16 +89,11 @@ function transformToMDXFormatForComparison(remote, localContent) {
|
|
|
90
89
|
// Exclude system/internal fields that should not appear in local files
|
|
91
90
|
const systemFields = ['body', 'isLocal'];
|
|
92
91
|
systemFields.forEach(field => delete mergedFrontmatter[field]);
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
for (const [key, value] of Object.entries(mergedFrontmatter)) {
|
|
97
|
-
if (localFields.has(key)) {
|
|
98
|
-
localFieldsOnlyFrontmatter[key] = value;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
92
|
+
// Include ALL non-system remote fields so that field removals are detected.
|
|
93
|
+
// The timestamp check in matchContent already prevents false positives from
|
|
94
|
+
// server-side field additions (remote newer → conflict, not comparison).
|
|
101
95
|
// Filter out null and undefined values to prevent them from appearing in frontmatter
|
|
102
|
-
const filteredFrontmatter = filterNullValues(
|
|
96
|
+
const filteredFrontmatter = filterNullValues(mergedFrontmatter);
|
|
103
97
|
// Apply media path replacements to both frontmatter and body content
|
|
104
98
|
const cleanedFrontmatter = replaceApiMediaPaths(filteredFrontmatter);
|
|
105
99
|
const cleanedContent = replaceApiMediaPaths(bodyContent);
|
|
@@ -107,17 +101,16 @@ function transformToMDXFormatForComparison(remote, localContent) {
|
|
|
107
101
|
return matter.stringify(`\n${cleanedContent.trim()}`, cleanedFrontmatter);
|
|
108
102
|
}
|
|
109
103
|
/**
|
|
110
|
-
* Transform remote content to JSON format
|
|
104
|
+
* Transform remote content to JSON format for comparison with local content.
|
|
105
|
+
* Includes ALL non-system remote fields so that field removals in local content
|
|
106
|
+
* are properly detected as changes.
|
|
111
107
|
*/
|
|
112
108
|
function transformToJSONFormatForComparison(remote, localContent) {
|
|
113
|
-
//
|
|
114
|
-
let localFields;
|
|
109
|
+
// Validate that local content is parseable JSON, fall back to full transform if not
|
|
115
110
|
try {
|
|
116
|
-
|
|
117
|
-
localFields = new Set(Object.keys(localData));
|
|
111
|
+
JSON.parse(localContent);
|
|
118
112
|
}
|
|
119
113
|
catch (error) {
|
|
120
|
-
// If we can't parse local content, fall back to including all fields
|
|
121
114
|
return transformToJSONFormat(remote);
|
|
122
115
|
}
|
|
123
116
|
let bodyObj = {};
|
|
@@ -132,8 +125,11 @@ function transformToJSONFormatForComparison(remote, localContent) {
|
|
|
132
125
|
const merged = { ...transformedBodyObj };
|
|
133
126
|
// Exclude system/internal fields that should not appear in local files
|
|
134
127
|
const systemFields = ['body', 'isLocal'];
|
|
128
|
+
// Include ALL non-system remote fields so that field removals are detected.
|
|
129
|
+
// The timestamp check in matchContent already prevents false positives from
|
|
130
|
+
// server-side field additions (remote newer → conflict, not comparison).
|
|
135
131
|
for (const [k, v] of Object.entries(remote)) {
|
|
136
|
-
if (!systemFields.includes(k)
|
|
132
|
+
if (!systemFields.includes(k)) {
|
|
137
133
|
merged[k] = replaceApiMediaPaths(v);
|
|
138
134
|
}
|
|
139
135
|
}
|
|
@@ -279,16 +275,6 @@ function filterNullValues(obj) {
|
|
|
279
275
|
}
|
|
280
276
|
return filtered;
|
|
281
277
|
}
|
|
282
|
-
/**
|
|
283
|
-
* System fields that should be excluded from local files
|
|
284
|
-
* These are truly internal fields, not user content fields
|
|
285
|
-
*/
|
|
286
|
-
export const SYSTEM_FIELDS = ['body', 'isLocal'];
|
|
287
|
-
/**
|
|
288
|
-
* User content fields that should be preserved in local files
|
|
289
|
-
* These are timestamp fields that represent user content metadata
|
|
290
|
-
*/
|
|
291
|
-
export const USER_CONTENT_FIELDS = ['createdAt', 'updatedAt', 'publishedAt'];
|
|
292
278
|
/**
|
|
293
279
|
* Save content file using shared transformation logic
|
|
294
280
|
* This function combines transformation and file writing operations
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-transformation.js","sourceRoot":"","sources":["../../src/lib/content-transformation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAoBxC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,MAAyB,EACzB,UAA0B,EAAE;IAE5B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;IAElD,IAAI,WAAW,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;SAAM,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;QAClC,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,6BAA6B,WAAW,EAAE,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,MAAyB,EACzB,YAAoB,EACpB,UAA0B,EAAE;IAE5B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;IAElD,IAAI,WAAW,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,iCAAiC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACjE,CAAC;SAAM,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;QAClC,OAAO,kCAAkC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAClE,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,6BAA6B,WAAW,EAAE,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"content-transformation.js","sourceRoot":"","sources":["../../src/lib/content-transformation.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,15 +19,29 @@ interface ContentType {
|
|
|
19
19
|
format: string;
|
|
20
20
|
name: string;
|
|
21
21
|
}
|
|
22
|
+
export interface MediaItem {
|
|
23
|
+
id: number;
|
|
24
|
+
location: string;
|
|
25
|
+
scopeUid: string;
|
|
26
|
+
name: string;
|
|
27
|
+
description?: string | null;
|
|
28
|
+
size: number;
|
|
29
|
+
extension: string;
|
|
30
|
+
mimeType: string;
|
|
31
|
+
createdAt: string;
|
|
32
|
+
updatedAt?: string | null;
|
|
33
|
+
}
|
|
22
34
|
interface MockScenario {
|
|
23
35
|
name: string;
|
|
24
36
|
description: string;
|
|
25
37
|
remoteContent: ContentItem[];
|
|
26
38
|
contentTypes: Record<string, string>;
|
|
39
|
+
remoteMedia: MediaItem[];
|
|
27
40
|
}
|
|
28
41
|
interface MockData {
|
|
29
42
|
remoteContent: ContentItem[];
|
|
30
43
|
contentTypes: Record<string, string>;
|
|
44
|
+
remoteMedia: MediaItem[];
|
|
31
45
|
scenario: string;
|
|
32
46
|
}
|
|
33
47
|
/**
|
|
@@ -58,6 +72,14 @@ declare class LeadCMSDataService {
|
|
|
58
72
|
* Get all content types from LeadCMS or mock data
|
|
59
73
|
*/
|
|
60
74
|
getContentTypes(): Promise<ContentType[]>;
|
|
75
|
+
/**
|
|
76
|
+
* Get a specific content item by ID
|
|
77
|
+
*/
|
|
78
|
+
getContentById(id: number): Promise<ContentItem | null>;
|
|
79
|
+
/**
|
|
80
|
+
* Get content by slug and language
|
|
81
|
+
*/
|
|
82
|
+
getContentBySlug(slug: string, language?: string): Promise<ContentItem | null>;
|
|
61
83
|
/**
|
|
62
84
|
* Create new content in LeadCMS or mock
|
|
63
85
|
*/
|
|
@@ -66,10 +88,30 @@ declare class LeadCMSDataService {
|
|
|
66
88
|
* Update existing content in LeadCMS or mock
|
|
67
89
|
*/
|
|
68
90
|
updateContent(id: number, content: Partial<ContentItem>): Promise<ContentItem>;
|
|
91
|
+
/**
|
|
92
|
+
* Delete content from LeadCMS
|
|
93
|
+
*/
|
|
94
|
+
deleteContent(id: number): Promise<void>;
|
|
69
95
|
/**
|
|
70
96
|
* Create content type in LeadCMS or mock
|
|
71
97
|
*/
|
|
72
98
|
createContentType(contentType: Partial<ContentType>): Promise<ContentType>;
|
|
99
|
+
/**
|
|
100
|
+
* Get all media from LeadCMS using sync API (without token for full fetch)
|
|
101
|
+
*/
|
|
102
|
+
getAllMedia(scopeUid?: string): Promise<MediaItem[]>;
|
|
103
|
+
/**
|
|
104
|
+
* Upload media file to LeadCMS
|
|
105
|
+
*/
|
|
106
|
+
uploadMedia(formData: any): Promise<MediaItem>;
|
|
107
|
+
/**
|
|
108
|
+
* Update existing media file in LeadCMS
|
|
109
|
+
*/
|
|
110
|
+
updateMedia(formData: any): Promise<MediaItem>;
|
|
111
|
+
/**
|
|
112
|
+
* Delete media file from LeadCMS
|
|
113
|
+
*/
|
|
114
|
+
deleteMedia(pathToFile: string): Promise<void>;
|
|
73
115
|
/**
|
|
74
116
|
* Check if we're using mock data
|
|
75
117
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-service.d.ts","sourceRoot":"","sources":["../../src/lib/data-service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA2CH,UAAU,WAAW;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,UAAU,WAAW;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,WAAW,EAAE,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"data-service.d.ts","sourceRoot":"","sources":["../../src/lib/data-service.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/data-service.js
CHANGED
|
@@ -42,7 +42,8 @@ const MOCK_SCENARIOS = {
|
|
|
42
42
|
name: 'All Content New',
|
|
43
43
|
description: 'Local content that doesn\'t exist remotely',
|
|
44
44
|
remoteContent: [],
|
|
45
|
-
contentTypes: { article: 'MDX', page: 'JSON', blog: 'MDX' }
|
|
45
|
+
contentTypes: { article: 'MDX', page: 'JSON', blog: 'MDX' },
|
|
46
|
+
remoteMedia: []
|
|
46
47
|
},
|
|
47
48
|
noChanges: {
|
|
48
49
|
name: 'No Changes',
|
|
@@ -58,7 +59,21 @@ const MOCK_SCENARIOS = {
|
|
|
58
59
|
body: 'This article exists both locally and remotely.'
|
|
59
60
|
}
|
|
60
61
|
],
|
|
61
|
-
contentTypes: { article: 'MDX', page: 'JSON', blog: 'MDX' }
|
|
62
|
+
contentTypes: { article: 'MDX', page: 'JSON', blog: 'MDX' },
|
|
63
|
+
remoteMedia: [
|
|
64
|
+
{
|
|
65
|
+
id: 1,
|
|
66
|
+
location: '/api/media/blog/hero.jpg',
|
|
67
|
+
scopeUid: 'blog',
|
|
68
|
+
name: 'hero.jpg',
|
|
69
|
+
description: null,
|
|
70
|
+
size: 245760,
|
|
71
|
+
extension: '.jpg',
|
|
72
|
+
mimeType: 'image/jpeg',
|
|
73
|
+
createdAt: '2024-10-29T10:00:00Z',
|
|
74
|
+
updatedAt: null
|
|
75
|
+
}
|
|
76
|
+
]
|
|
62
77
|
},
|
|
63
78
|
hasConflicts: {
|
|
64
79
|
name: 'Has Conflicts',
|
|
@@ -74,7 +89,8 @@ const MOCK_SCENARIOS = {
|
|
|
74
89
|
body: 'This is the remote version that was updated after the local version.'
|
|
75
90
|
}
|
|
76
91
|
],
|
|
77
|
-
contentTypes: { article: 'MDX', page: 'JSON', blog: 'MDX' }
|
|
92
|
+
contentTypes: { article: 'MDX', page: 'JSON', blog: 'MDX' },
|
|
93
|
+
remoteMedia: []
|
|
78
94
|
},
|
|
79
95
|
hasUpdates: {
|
|
80
96
|
name: 'Has Updates',
|
|
@@ -90,7 +106,8 @@ const MOCK_SCENARIOS = {
|
|
|
90
106
|
body: 'This is the original content.'
|
|
91
107
|
}
|
|
92
108
|
],
|
|
93
|
-
contentTypes: { article: 'MDX', page: 'JSON', blog: 'MDX' }
|
|
109
|
+
contentTypes: { article: 'MDX', page: 'JSON', blog: 'MDX' },
|
|
110
|
+
remoteMedia: []
|
|
94
111
|
},
|
|
95
112
|
mixedOperations: {
|
|
96
113
|
name: 'Mixed Operations',
|
|
@@ -106,13 +123,28 @@ const MOCK_SCENARIOS = {
|
|
|
106
123
|
body: 'Original post content.'
|
|
107
124
|
}
|
|
108
125
|
],
|
|
109
|
-
contentTypes: { article: 'MDX', page: 'JSON', blog: 'MDX' }
|
|
126
|
+
contentTypes: { article: 'MDX', page: 'JSON', blog: 'MDX' },
|
|
127
|
+
remoteMedia: [
|
|
128
|
+
{
|
|
129
|
+
id: 1,
|
|
130
|
+
location: '/api/media/privacy-policy/bg-image.avif',
|
|
131
|
+
scopeUid: 'privacy-policy',
|
|
132
|
+
name: 'bg-image.avif',
|
|
133
|
+
description: null,
|
|
134
|
+
size: 780720,
|
|
135
|
+
extension: '.avif',
|
|
136
|
+
mimeType: 'image/avif',
|
|
137
|
+
createdAt: '2025-06-16T06:57:41.017481Z',
|
|
138
|
+
updatedAt: '2025-06-16T06:59:09.014782Z'
|
|
139
|
+
}
|
|
140
|
+
]
|
|
110
141
|
},
|
|
111
142
|
missingContentTypes: {
|
|
112
143
|
name: 'Missing Content Types',
|
|
113
144
|
description: 'Content with unknown content types',
|
|
114
145
|
remoteContent: [],
|
|
115
|
-
contentTypes: { article: 'MDX', page: 'JSON', blog: 'MDX' }
|
|
146
|
+
contentTypes: { article: 'MDX', page: 'JSON', blog: 'MDX' },
|
|
147
|
+
remoteMedia: []
|
|
116
148
|
}
|
|
117
149
|
};
|
|
118
150
|
/**
|
|
@@ -169,6 +201,7 @@ class LeadCMSDataService {
|
|
|
169
201
|
this.mockData = {
|
|
170
202
|
remoteContent: JSON.parse(JSON.stringify(scenario.remoteContent)),
|
|
171
203
|
contentTypes: { ...scenario.contentTypes },
|
|
204
|
+
remoteMedia: JSON.parse(JSON.stringify(scenario.remoteMedia)),
|
|
172
205
|
scenario: scenario.name
|
|
173
206
|
};
|
|
174
207
|
}
|
|
@@ -263,6 +296,48 @@ class LeadCMSDataService {
|
|
|
263
296
|
throw error;
|
|
264
297
|
}
|
|
265
298
|
}
|
|
299
|
+
/**
|
|
300
|
+
* Get a specific content item by ID
|
|
301
|
+
*/
|
|
302
|
+
async getContentById(id) {
|
|
303
|
+
this._initialize();
|
|
304
|
+
if (this.useMock && this.mockData) {
|
|
305
|
+
console.log(`[MOCK] Getting content with ID: ${id}`);
|
|
306
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
307
|
+
const content = this.mockData.remoteContent.find(c => c.id === id);
|
|
308
|
+
return content || null;
|
|
309
|
+
}
|
|
310
|
+
try {
|
|
311
|
+
console.log(`[API] Fetching content with ID: ${id}`);
|
|
312
|
+
if (!this.baseURL) {
|
|
313
|
+
throw new Error('LeadCMS URL is not configured.');
|
|
314
|
+
}
|
|
315
|
+
const response = await axios.get(`${this.baseURL}/api/content/${id}`, {
|
|
316
|
+
headers: this.getApiHeaders()
|
|
317
|
+
});
|
|
318
|
+
return response.data;
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
if (error.response?.status === 404) {
|
|
322
|
+
console.log(`[API] Content with ID ${id} not found`);
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
if (error.response?.status === 401) {
|
|
326
|
+
throw formatAuthenticationError(error);
|
|
327
|
+
}
|
|
328
|
+
console.error(`[API] Failed to fetch content by ID ${id}:`, error.message);
|
|
329
|
+
throw error;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Get content by slug and language
|
|
334
|
+
*/
|
|
335
|
+
async getContentBySlug(slug, language) {
|
|
336
|
+
this._initialize();
|
|
337
|
+
const allContent = await this.getAllContent();
|
|
338
|
+
const content = allContent.find(c => c.slug === slug && (!language || c.language === language));
|
|
339
|
+
return content || null;
|
|
340
|
+
}
|
|
266
341
|
/**
|
|
267
342
|
* Create new content in LeadCMS or mock
|
|
268
343
|
*/
|
|
@@ -362,6 +437,45 @@ class LeadCMSDataService {
|
|
|
362
437
|
throw error;
|
|
363
438
|
}
|
|
364
439
|
}
|
|
440
|
+
/**
|
|
441
|
+
* Delete content from LeadCMS
|
|
442
|
+
*/
|
|
443
|
+
async deleteContent(id) {
|
|
444
|
+
this._initialize();
|
|
445
|
+
if (this.useMock && this.mockData) {
|
|
446
|
+
console.log(`[MOCK] Deleting content with ID: ${id}`);
|
|
447
|
+
await new Promise(resolve => setTimeout(resolve, 80));
|
|
448
|
+
// Remove from mock data
|
|
449
|
+
const index = this.mockData.remoteContent.findIndex(c => c.id === id);
|
|
450
|
+
if (index !== -1) {
|
|
451
|
+
this.mockData.remoteContent.splice(index, 1);
|
|
452
|
+
}
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
try {
|
|
456
|
+
console.log(`[API] Deleting content with ID: ${id}`);
|
|
457
|
+
if (!this.baseURL) {
|
|
458
|
+
throw new Error('LeadCMS URL is not configured.');
|
|
459
|
+
}
|
|
460
|
+
await axios.delete(`${this.baseURL}/api/content/${id}`, {
|
|
461
|
+
headers: this.getApiHeaders()
|
|
462
|
+
});
|
|
463
|
+
console.log('[API] Content deleted successfully');
|
|
464
|
+
}
|
|
465
|
+
catch (error) {
|
|
466
|
+
if (error.response?.status === 401) {
|
|
467
|
+
throw formatAuthenticationError(error);
|
|
468
|
+
}
|
|
469
|
+
if (error.response?.status === 422) {
|
|
470
|
+
const enhancedError = new Error(`Content validation failed: ${formatApiValidationErrors(error.response)}`);
|
|
471
|
+
enhancedError.status = 422;
|
|
472
|
+
enhancedError.validationErrors = error.response.data.errors;
|
|
473
|
+
throw enhancedError;
|
|
474
|
+
}
|
|
475
|
+
console.error('[API] Failed to delete content:', error.message);
|
|
476
|
+
throw error;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
365
479
|
/**
|
|
366
480
|
* Create content type in LeadCMS or mock
|
|
367
481
|
*/
|
|
@@ -389,6 +503,200 @@ class LeadCMSDataService {
|
|
|
389
503
|
throw error;
|
|
390
504
|
}
|
|
391
505
|
}
|
|
506
|
+
/**
|
|
507
|
+
* Get all media from LeadCMS using sync API (without token for full fetch)
|
|
508
|
+
*/
|
|
509
|
+
async getAllMedia(scopeUid) {
|
|
510
|
+
this._initialize();
|
|
511
|
+
if (this.useMock && this.mockData) {
|
|
512
|
+
console.log('[MOCK] Returning mock media data');
|
|
513
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
514
|
+
let media = [...this.mockData.remoteMedia];
|
|
515
|
+
if (scopeUid) {
|
|
516
|
+
media = media.filter(m => m.scopeUid === scopeUid);
|
|
517
|
+
}
|
|
518
|
+
return media;
|
|
519
|
+
}
|
|
520
|
+
try {
|
|
521
|
+
console.log('[API] Fetching media from LeadCMS using sync API...');
|
|
522
|
+
if (!this.baseURL) {
|
|
523
|
+
throw new Error('LeadCMS URL is not configured.');
|
|
524
|
+
}
|
|
525
|
+
const allMedia = [];
|
|
526
|
+
let syncToken = '';
|
|
527
|
+
let page = 0;
|
|
528
|
+
// Paginate through all media using sync API
|
|
529
|
+
while (true) {
|
|
530
|
+
const url = new URL('/api/media/sync', this.baseURL);
|
|
531
|
+
url.searchParams.set('filter[limit]', '100');
|
|
532
|
+
url.searchParams.set('syncToken', syncToken);
|
|
533
|
+
if (scopeUid) {
|
|
534
|
+
url.searchParams.set('query', `scopeUid=${scopeUid}`);
|
|
535
|
+
}
|
|
536
|
+
const response = await axios.get(url.toString());
|
|
537
|
+
if (response.status === 204) {
|
|
538
|
+
break; // No more data
|
|
539
|
+
}
|
|
540
|
+
const data = response.data;
|
|
541
|
+
if (data.items && Array.isArray(data.items)) {
|
|
542
|
+
allMedia.push(...data.items);
|
|
543
|
+
}
|
|
544
|
+
const nextToken = response.headers['x-next-sync-token'] || syncToken;
|
|
545
|
+
if (!nextToken || nextToken === syncToken) {
|
|
546
|
+
break; // No more pages
|
|
547
|
+
}
|
|
548
|
+
syncToken = nextToken;
|
|
549
|
+
page++;
|
|
550
|
+
}
|
|
551
|
+
console.log(`[API] Fetched ${allMedia.length} media items`);
|
|
552
|
+
return allMedia;
|
|
553
|
+
}
|
|
554
|
+
catch (error) {
|
|
555
|
+
console.error('[API] Failed to fetch media:', error.message);
|
|
556
|
+
throw error;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Upload media file to LeadCMS
|
|
561
|
+
*/
|
|
562
|
+
async uploadMedia(formData) {
|
|
563
|
+
this._initialize();
|
|
564
|
+
if (this.useMock && this.mockData) {
|
|
565
|
+
console.log('[MOCK] Uploading media file');
|
|
566
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
567
|
+
// Extract data from FormData for mock
|
|
568
|
+
const scopeUid = formData.get('ScopeUid');
|
|
569
|
+
const fileName = formData.get('File')?.name || 'mock-file.jpg';
|
|
570
|
+
const description = formData.get('Description');
|
|
571
|
+
const newMedia = {
|
|
572
|
+
id: this.mockData.remoteMedia.length + 1,
|
|
573
|
+
location: `/api/media/${scopeUid}/${fileName}`,
|
|
574
|
+
scopeUid,
|
|
575
|
+
name: fileName,
|
|
576
|
+
description,
|
|
577
|
+
size: 100000, // Mock size
|
|
578
|
+
extension: fileName.substring(fileName.lastIndexOf('.')),
|
|
579
|
+
mimeType: 'image/jpeg',
|
|
580
|
+
createdAt: new Date().toISOString(),
|
|
581
|
+
updatedAt: null
|
|
582
|
+
};
|
|
583
|
+
this.mockData.remoteMedia.push(newMedia);
|
|
584
|
+
return newMedia;
|
|
585
|
+
}
|
|
586
|
+
try {
|
|
587
|
+
console.log('[API] Uploading media file...');
|
|
588
|
+
if (!this.baseURL) {
|
|
589
|
+
throw new Error('LeadCMS URL is not configured.');
|
|
590
|
+
}
|
|
591
|
+
const response = await axios.post(`${this.baseURL}/api/media`, formData, {
|
|
592
|
+
headers: {
|
|
593
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
594
|
+
// Don't set Content-Type, let axios set it with boundary for multipart
|
|
595
|
+
}
|
|
596
|
+
});
|
|
597
|
+
console.log('[API] Media uploaded successfully');
|
|
598
|
+
return response.data;
|
|
599
|
+
}
|
|
600
|
+
catch (error) {
|
|
601
|
+
if (error.response?.status === 401) {
|
|
602
|
+
throw formatAuthenticationError(error);
|
|
603
|
+
}
|
|
604
|
+
if (error.response?.status === 422) {
|
|
605
|
+
const validationMessage = formatApiValidationErrors(error.response);
|
|
606
|
+
const enhancedError = new Error(`Media validation failed${validationMessage}`);
|
|
607
|
+
enhancedError.status = 422;
|
|
608
|
+
throw enhancedError;
|
|
609
|
+
}
|
|
610
|
+
console.error('[API] Failed to upload media:', error.message);
|
|
611
|
+
throw error;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Update existing media file in LeadCMS
|
|
616
|
+
*/
|
|
617
|
+
async updateMedia(formData) {
|
|
618
|
+
this._initialize();
|
|
619
|
+
if (this.useMock && this.mockData) {
|
|
620
|
+
console.log('[MOCK] Updating media file');
|
|
621
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
622
|
+
const scopeUid = formData.get('ScopeUid');
|
|
623
|
+
const fileName = formData.get('FileName');
|
|
624
|
+
const existingIndex = this.mockData.remoteMedia.findIndex(m => m.scopeUid === scopeUid && m.name === fileName);
|
|
625
|
+
if (existingIndex === -1) {
|
|
626
|
+
throw new Error(`Media file ${scopeUid}/${fileName} not found`);
|
|
627
|
+
}
|
|
628
|
+
const updatedMedia = {
|
|
629
|
+
...this.mockData.remoteMedia[existingIndex],
|
|
630
|
+
updatedAt: new Date().toISOString()
|
|
631
|
+
};
|
|
632
|
+
this.mockData.remoteMedia[existingIndex] = updatedMedia;
|
|
633
|
+
return updatedMedia;
|
|
634
|
+
}
|
|
635
|
+
try {
|
|
636
|
+
console.log('[API] Updating media file...');
|
|
637
|
+
if (!this.baseURL) {
|
|
638
|
+
throw new Error('LeadCMS URL is not configured.');
|
|
639
|
+
}
|
|
640
|
+
const response = await axios.patch(`${this.baseURL}/api/media`, formData, {
|
|
641
|
+
headers: {
|
|
642
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
console.log('[API] Media updated successfully');
|
|
646
|
+
return response.data;
|
|
647
|
+
}
|
|
648
|
+
catch (error) {
|
|
649
|
+
if (error.response?.status === 401) {
|
|
650
|
+
throw formatAuthenticationError(error);
|
|
651
|
+
}
|
|
652
|
+
if (error.response?.status === 422) {
|
|
653
|
+
const validationMessage = formatApiValidationErrors(error.response);
|
|
654
|
+
const enhancedError = new Error(`Media validation failed${validationMessage}`);
|
|
655
|
+
enhancedError.status = 422;
|
|
656
|
+
throw enhancedError;
|
|
657
|
+
}
|
|
658
|
+
console.error('[API] Failed to update media:', error.message);
|
|
659
|
+
throw error;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Delete media file from LeadCMS
|
|
664
|
+
*/
|
|
665
|
+
async deleteMedia(pathToFile) {
|
|
666
|
+
this._initialize();
|
|
667
|
+
if (this.useMock && this.mockData) {
|
|
668
|
+
console.log(`[MOCK] Deleting media file: ${pathToFile}`);
|
|
669
|
+
await new Promise(resolve => setTimeout(resolve, 80));
|
|
670
|
+
// Parse path to extract scopeUid and name
|
|
671
|
+
// Path format: /api/media/scopeUid/filename or scopeUid/filename
|
|
672
|
+
const cleanPath = pathToFile.replace('/api/media/', '');
|
|
673
|
+
const lastSlash = cleanPath.lastIndexOf('/');
|
|
674
|
+
const scopeUid = cleanPath.substring(0, lastSlash);
|
|
675
|
+
const name = cleanPath.substring(lastSlash + 1);
|
|
676
|
+
const index = this.mockData.remoteMedia.findIndex(m => m.scopeUid === scopeUid && m.name === name);
|
|
677
|
+
if (index !== -1) {
|
|
678
|
+
this.mockData.remoteMedia.splice(index, 1);
|
|
679
|
+
}
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
try {
|
|
683
|
+
console.log(`[API] Deleting media file: ${pathToFile}`);
|
|
684
|
+
if (!this.baseURL) {
|
|
685
|
+
throw new Error('LeadCMS URL is not configured.');
|
|
686
|
+
}
|
|
687
|
+
await axios.delete(`${this.baseURL}/api/media/${pathToFile}`, {
|
|
688
|
+
headers: this.getApiHeaders()
|
|
689
|
+
});
|
|
690
|
+
console.log('[API] Media deleted successfully');
|
|
691
|
+
}
|
|
692
|
+
catch (error) {
|
|
693
|
+
if (error.response?.status === 401) {
|
|
694
|
+
throw formatAuthenticationError(error);
|
|
695
|
+
}
|
|
696
|
+
console.error('[API] Failed to delete media:', error.message);
|
|
697
|
+
throw error;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
392
700
|
/**
|
|
393
701
|
* Check if we're using mock data
|
|
394
702
|
*/
|
|
@@ -419,6 +727,7 @@ class LeadCMSDataService {
|
|
|
419
727
|
this.mockData = {
|
|
420
728
|
remoteContent: JSON.parse(JSON.stringify(scenario.remoteContent)),
|
|
421
729
|
contentTypes: { ...scenario.contentTypes },
|
|
730
|
+
remoteMedia: JSON.parse(JSON.stringify(scenario.remoteMedia)),
|
|
422
731
|
scenario: scenario.name
|
|
423
732
|
};
|
|
424
733
|
console.log(`[MOCK] Switched to scenario: ${scenario.name}`);
|
|
@@ -435,6 +744,7 @@ class LeadCMSDataService {
|
|
|
435
744
|
return {
|
|
436
745
|
remoteContent: [...this.mockData.remoteContent],
|
|
437
746
|
contentTypes: { ...this.mockData.contentTypes },
|
|
747
|
+
remoteMedia: [...this.mockData.remoteMedia],
|
|
438
748
|
scenario: this.currentScenario?.name || ''
|
|
439
749
|
};
|
|
440
750
|
}
|