@leadcms/sdk 1.3.0-pre → 2.1.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 (56) hide show
  1. package/README.md +82 -3
  2. package/dist/cli/index.js +55 -62
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +2 -18
  7. package/dist/index.js.map +1 -1
  8. package/dist/lib/cms.d.ts +1 -1
  9. package/dist/lib/cms.d.ts.map +1 -1
  10. package/dist/lib/cms.js +49 -72
  11. package/dist/lib/cms.js.map +1 -1
  12. package/dist/lib/config.d.ts +0 -8
  13. package/dist/lib/config.d.ts.map +1 -1
  14. package/dist/lib/config.js +13 -40
  15. package/dist/lib/config.js.map +1 -1
  16. package/dist/lib/console-colors.d.ts +49 -0
  17. package/dist/lib/console-colors.d.ts.map +1 -0
  18. package/dist/lib/console-colors.js +121 -0
  19. package/dist/lib/console-colors.js.map +1 -0
  20. package/dist/lib/content-transformation.d.ts +90 -0
  21. package/dist/lib/content-transformation.d.ts.map +1 -0
  22. package/dist/lib/content-transformation.js +335 -0
  23. package/dist/lib/content-transformation.js.map +1 -0
  24. package/dist/lib/data-service.d.ts +97 -0
  25. package/dist/lib/data-service.d.ts.map +1 -0
  26. package/dist/lib/data-service.js +389 -0
  27. package/dist/lib/data-service.js.map +1 -0
  28. package/dist/scripts/fetch-leadcms-content.d.ts +19 -0
  29. package/dist/scripts/fetch-leadcms-content.d.ts.map +1 -0
  30. package/dist/scripts/fetch-leadcms-content.js +301 -0
  31. package/dist/scripts/fetch-leadcms-content.js.map +1 -0
  32. package/dist/scripts/generate-env-js.d.ts +2 -0
  33. package/dist/scripts/generate-env-js.d.ts.map +1 -0
  34. package/dist/scripts/generate-env-js.js +22 -0
  35. package/dist/scripts/generate-env-js.js.map +1 -0
  36. package/dist/scripts/leadcms-helpers.d.ts +25 -0
  37. package/dist/scripts/leadcms-helpers.d.ts.map +1 -0
  38. package/dist/scripts/leadcms-helpers.js +78 -0
  39. package/dist/scripts/leadcms-helpers.js.map +1 -0
  40. package/dist/scripts/push-leadcms-content.d.ts +50 -0
  41. package/dist/scripts/push-leadcms-content.d.ts.map +1 -0
  42. package/dist/scripts/push-leadcms-content.js +1022 -0
  43. package/dist/scripts/push-leadcms-content.js.map +1 -0
  44. package/dist/scripts/sse-watcher.d.ts +20 -0
  45. package/dist/scripts/sse-watcher.d.ts.map +1 -0
  46. package/dist/scripts/sse-watcher.js +268 -0
  47. package/dist/scripts/sse-watcher.js.map +1 -0
  48. package/dist/scripts/status-leadcms-content.d.ts +4 -0
  49. package/dist/scripts/status-leadcms-content.d.ts.map +1 -0
  50. package/dist/scripts/status-leadcms-content.js +36 -0
  51. package/dist/scripts/status-leadcms-content.js.map +1 -0
  52. package/package.json +14 -12
  53. package/dist/scripts/fetch-leadcms-content.mjs +0 -367
  54. package/dist/scripts/generate-env-js.mjs +0 -24
  55. package/dist/scripts/leadcms-helpers.mjs +0 -208
  56. package/dist/scripts/sse-watcher.mjs +0 -300
@@ -1,300 +0,0 @@
1
- import "dotenv/config"
2
- import { EventSource } from "eventsource"
3
- import {
4
- saveContentFile,
5
- leadCMSUrl,
6
- leadCMSApiKey,
7
- defaultLanguage,
8
- CONTENT_DIR,
9
- } from "./leadcms-helpers.mjs"
10
- import { fetchContentTypes } from "./leadcms-helpers.mjs"
11
- import { fetchLeadCMSContent } from "./fetch-leadcms-content.mjs"
12
-
13
- // Log environment configuration for debugging
14
- console.log(`[SSE ENV] LeadCMS URL: ${leadCMSUrl}`)
15
- console.log(
16
- `[SSE ENV] LeadCMS API Key: ${leadCMSApiKey ? `${leadCMSApiKey.substring(0, 8)}...` : "NOT_SET"}`
17
- )
18
- console.log(`[SSE ENV] Default Language: ${defaultLanguage}`)
19
- console.log(`[SSE ENV] Content Dir: ${CONTENT_DIR}`)
20
-
21
- // Helper function to trigger content fetch
22
- async function triggerContentFetch() {
23
- try {
24
- console.log("[SSE] Starting content fetch...")
25
- await fetchLeadCMSContent()
26
- console.log("[SSE] Content fetch completed successfully")
27
- } catch (error) {
28
- console.error("[SSE] Content fetch failed:", error.message)
29
- }
30
- }
31
-
32
- function buildSSEUrl() {
33
- console.log(`[SSE URL] Building SSE URL with base: ${leadCMSUrl}`)
34
- const url = new URL("/api/sse/stream", leadCMSUrl)
35
- url.searchParams.set("entities", "Content")
36
- url.searchParams.set("includeContent", "true")
37
- url.searchParams.set("includeLiveDrafts", "true")
38
- const finalUrl = url.toString()
39
- console.log(`[SSE URL] Final SSE URL: ${finalUrl}`)
40
- return finalUrl
41
- }
42
-
43
- async function startSSEWatcher() {
44
- console.log(`[SSE] Starting SSE watcher...`)
45
- const typeMap = await fetchContentTypes()
46
- const sseUrl = buildSSEUrl()
47
- const eventSourceOptions = {}
48
-
49
- if (leadCMSApiKey) {
50
- console.log(`[SSE] Using API key for authentication`)
51
- eventSourceOptions.fetch = (input, init) => {
52
- console.log(`[SSE FETCH] Making authenticated request to: ${input}`)
53
- console.log(
54
- `[SSE FETCH] Headers:`,
55
- JSON.stringify(
56
- {
57
- ...init?.headers,
58
- Authorization: `Bearer ${leadCMSApiKey.substring(0, 8)}...`,
59
- },
60
- null,
61
- 2
62
- )
63
- )
64
-
65
- return fetch(input, {
66
- ...init,
67
- headers: {
68
- ...init?.headers,
69
- Authorization: `Bearer ${leadCMSApiKey}`,
70
- },
71
- })
72
- .then((response) => {
73
- console.log(`[SSE FETCH] Response status: ${response.status} ${response.statusText}`)
74
- console.log(
75
- `[SSE FETCH] Response headers:`,
76
- JSON.stringify(Object.fromEntries(response.headers.entries()), null, 2)
77
- )
78
- if (!response.ok) {
79
- console.error(`[SSE FETCH] Failed response: ${response.status} ${response.statusText}`)
80
- }
81
- return response
82
- })
83
- .catch((error) => {
84
- console.error(`[SSE FETCH] Fetch error:`, error.message)
85
- throw error
86
- })
87
- }
88
- } else {
89
- console.warn(`[SSE] No API key provided - attempting unauthenticated connection`)
90
- }
91
-
92
- console.log(`[SSE] Connecting to: ${sseUrl}`)
93
- console.log(`[SSE] Event source options:`, JSON.stringify(eventSourceOptions, null, 2))
94
- const es = new EventSource(sseUrl, eventSourceOptions)
95
-
96
- es.onopen = () => {
97
- console.log("[SSE] Connection opened successfully")
98
- }
99
-
100
- es.onmessage = (event) => {
101
- console.log(`[SSE] Received message:`, event.data)
102
- try {
103
- const data = JSON.parse(event.data)
104
- console.log(`[SSE] Parsed message data:`, JSON.stringify(data, null, 2))
105
-
106
- if (data.entityType === "Content") {
107
- console.log(`[SSE] Content message - Operation: ${data.operation}`)
108
- console.log(`[SSE] Content change detected - triggering full fetch`)
109
- triggerContentFetch()
110
- } else {
111
- console.log(`[SSE] Non-content message - Entity type: ${data.entityType}`)
112
- }
113
- } catch (e) {
114
- console.warn("[SSE] Failed to parse SSE message:", e.message)
115
- console.warn("[SSE] Raw event data:", event.data)
116
- }
117
- }
118
-
119
- es.addEventListener("connected", (event) => {
120
- console.log(`[SSE] Received 'connected' event:`, event.data)
121
- try {
122
- const data = JSON.parse(event.data)
123
- console.log(
124
- `[SSE] Connected successfully - Client ID: ${data.clientId}, Starting change log ID: ${data.startingChangeLogId}`
125
- )
126
- } catch (e) {
127
- console.warn("[SSE] Failed to parse connected event:", e.message)
128
- console.warn("[SSE] Raw connected event data:", event.data)
129
- }
130
- })
131
-
132
- es.addEventListener("heartbeat", (event) => {
133
- console.log(`[SSE] Received heartbeat:`, event.data)
134
- try {
135
- const data = JSON.parse(event.data)
136
- console.log(`[SSE] Heartbeat at ${data.timestamp}`)
137
- } catch (e) {
138
- console.warn("[SSE] Failed to parse heartbeat event:", e.message)
139
- console.warn("[SSE] Raw heartbeat event data:", event.data)
140
- }
141
- })
142
-
143
- es.addEventListener("draft-updated", (event) => {
144
- console.log(`[SSE] Received 'draft-updated' event:`, event.data)
145
- try {
146
- const data = JSON.parse(event.data)
147
- console.log(`[SSE] Draft updated data:`, JSON.stringify(data, null, 2))
148
-
149
- if (data.createdById && data.data) {
150
- console.log(`[SSE] Processing draft update for user: ${data.createdById}`)
151
- let contentData
152
- try {
153
- contentData = typeof data.data === "string" ? JSON.parse(data.data) : data.data
154
- console.log(`[SSE] Draft content data:`, JSON.stringify(contentData, null, 2))
155
- } catch (e) {
156
- console.warn("[SSE] Failed to parse draft content data:", e.message)
157
- console.warn("[SSE] Raw data:", data.data)
158
- return
159
- }
160
-
161
- // Determine content type for draft handling
162
- let contentType = undefined
163
- if (contentData && contentData.type && typeMap && typeMap[contentData.type]) {
164
- contentType = typeMap[contentData.type]
165
- }
166
-
167
- console.log(`[SSE] Draft updated - triggering full fetch`)
168
- triggerContentFetch()
169
-
170
- if (contentType === "MDX" || contentType === "JSON") {
171
- if (contentData && typeof contentData === "object") {
172
- const previewSlug = `${contentData.slug}-${data.createdById}`
173
- console.log(`[SSE] Saving draft content file for preview: ${previewSlug}`)
174
- ;(async () => {
175
- try {
176
- await saveContentFile({
177
- content: contentData,
178
- typeMap,
179
- contentDir: CONTENT_DIR,
180
- previewSlug: previewSlug,
181
- })
182
- console.log(`[SSE] Saved draft preview for ${previewSlug}`)
183
- } catch (error) {
184
- console.error(`[SSE] Error processing draft update:`, error.message)
185
- }
186
- })()
187
- }
188
- } else {
189
- console.log(`[SSE] Draft is not MDX or JSON (type: ${contentType}), skipping file save.`)
190
- }
191
- }
192
- } catch (e) {
193
- console.warn("[SSE] Failed to parse draft-updated event:", e.message)
194
- console.warn("[SSE] Raw draft-updated event data:", event.data)
195
- }
196
- })
197
-
198
- // Handle legacy DraftModified messages for backward compatibility
199
- es.addEventListener("message", (event) => {
200
- try {
201
- const data = JSON.parse(event.data)
202
-
203
- // Only handle DraftModified operations here for backward compatibility
204
- if (data.entityType === "Content" && data.operation === "DraftModified" && data.createdById && data.data) {
205
- console.log(`[SSE] Received legacy 'DraftModified' message for user: ${data.createdById}`)
206
- let contentData
207
- try {
208
- contentData = typeof data.data === "string" ? JSON.parse(data.data) : data.data
209
- console.log(`[SSE] Legacy draft content data:`, JSON.stringify(contentData, null, 2))
210
- } catch (e) {
211
- console.warn("[SSE] Failed to parse legacy draft content data:", e.message)
212
- console.warn("[SSE] Raw data:", data.data)
213
- return
214
- }
215
-
216
- // Determine content type for legacy draft handling
217
- let contentType = undefined
218
- if (contentData && contentData.type && typeMap && typeMap[contentData.type]) {
219
- contentType = typeMap[contentData.type]
220
- }
221
-
222
- console.log(`[SSE] Legacy draft modified - triggering full fetch`)
223
- triggerContentFetch()
224
-
225
- if (contentType === "MDX" || contentType === "JSON") {
226
- if (contentData && typeof contentData === "object") {
227
- const previewSlug = `${contentData.slug}-${data.createdById}`
228
- console.log(`[SSE] Saving legacy draft content file for preview: ${previewSlug}`)
229
- ;(async () => {
230
- try {
231
- await saveContentFile({
232
- content: contentData,
233
- typeMap,
234
- contentDir: CONTENT_DIR,
235
- previewSlug: previewSlug,
236
- })
237
- console.log(`[SSE] Saved legacy draft preview for ${previewSlug}`)
238
- } catch (error) {
239
- console.error(`[SSE] Error processing legacy draft modification:`, error.message)
240
- }
241
- })()
242
- }
243
- } else {
244
- console.log(`[SSE] Legacy draft is not MDX or JSON (type: ${contentType}), skipping file save.`)
245
- }
246
- }
247
- } catch {
248
- // Silently ignore parse errors for non-JSON messages
249
- }
250
- })
251
-
252
- es.addEventListener("content-updated", (event) => {
253
- console.log(`[SSE] Received 'content-updated' event:`, event.data)
254
- try {
255
- const data = JSON.parse(event.data)
256
- console.log(`[SSE] Content updated data:`, JSON.stringify(data, null, 2))
257
-
258
- console.log(`[SSE] Content updated - triggering full fetch`)
259
- triggerContentFetch()
260
- } catch (e) {
261
- console.warn("[SSE] Failed to parse content-updated event:", e.message)
262
- console.warn("[SSE] Raw content-updated event data:", event.data)
263
- }
264
- })
265
-
266
- es.onerror = (err) => {
267
- console.error("[SSE] Connection error occurred:", {
268
- type: err.type,
269
- message: err.message,
270
- code: err.code,
271
- timestamp: new Date().toISOString(),
272
- readyState: es.readyState,
273
- url: es.url,
274
- })
275
-
276
- // Log specific error types
277
- if (err.code === 401) {
278
- console.error("[SSE] Authentication failed (401) - check your LEADCMS_API_KEY")
279
- console.error(
280
- "[SSE] Current API Key (first 8 chars):",
281
- leadCMSApiKey ? leadCMSApiKey.substring(0, 8) : "NOT_SET"
282
- )
283
- } else if (err.code === 403) {
284
- console.error("[SSE] Forbidden (403) - insufficient permissions")
285
- } else if (err.code === 404) {
286
- console.error("[SSE] Not Found (404) - check your LEADCMS_URL and endpoint path")
287
- } else if (err.code >= 500) {
288
- console.error("[SSE] Server error (5xx) - LeadCMS server issue")
289
- }
290
-
291
- console.log("[SSE] Closing connection and will reconnect in 5s")
292
- es.close()
293
- setTimeout(() => {
294
- console.log("[SSE] Attempting to reconnect...")
295
- startSSEWatcher()
296
- }, 5000)
297
- }
298
- }
299
-
300
- startSSEWatcher()