@@ -18,6 +18,8 @@ import type {
18
18
import { initStoryblokBridge } from "./utils/initStoryblokBridge" ;
19
19
import { storyblokLogo } from "./dev-toolbar/toolbarApp" ;
20
20
export { handleStoryblokMessage } from "./live-preview/handleStoryblokMessage" ;
21
+ export { syncContentUpdate } from "./content-layer/syncContentUpdate" ;
22
+ export { storyblokLoader } from "./content-layer/storyblokLoader" ;
21
23
22
24
export {
23
25
storyblokEditable ,
@@ -103,6 +105,10 @@ export type IntegrationOptions = {
103
105
* A boolean to enable/disable the Experimental Live Preview feature. Disabled by default.
104
106
*/
105
107
livePreview ?: boolean ;
108
+ /**
109
+ * A boolean to enable/disable storyblok content layer.
110
+ */
111
+ contentLayer ?: boolean ;
106
112
} ;
107
113
108
114
export default function storyblokIntegration ( {
@@ -111,6 +117,7 @@ export default function storyblokIntegration({
111
117
componentsDir = "src" ,
112
118
enableFallbackComponent = false ,
113
119
livePreview = false ,
120
+ contentLayer = false ,
114
121
...restOptions
115
122
} : IntegrationOptions ) : AstroIntegration {
116
123
const resolvedOptions = {
@@ -119,6 +126,7 @@ export default function storyblokIntegration({
119
126
componentsDir,
120
127
enableFallbackComponent,
121
128
livePreview,
129
+ contentLayer,
122
130
...restOptions ,
123
131
} ;
124
132
@@ -205,13 +213,66 @@ export default function storyblokIntegration({
205
213
order : "pre" ,
206
214
} ) ;
207
215
}
216
+ // This is only enabled if experimentalLivePreview feature is on
217
+ if ( contentLayer ) {
218
+ injectScript (
219
+ "page" ,
220
+ `
221
+ import { loadStoryblokBridge, syncContentUpdate } from "@storyblok/astro";
222
+ loadStoryblokBridge().then(() => {
223
+ const { StoryblokBridge } = window;
224
+ const storyblokInstance = new StoryblokBridge()
225
+ storyblokInstance.on(["published", "change", "input"], syncContentUpdate);
226
+ });
227
+ `
228
+ ) ;
229
+ }
230
+
208
231
addDevToolbarApp ( {
209
232
id : "storyblok" ,
210
233
name : "Storyblok" ,
211
234
icon : storyblokLogo ,
212
235
entrypoint : "@storyblok/astro/toolbarApp.ts" ,
213
236
} ) ;
214
237
} ,
238
+ ...( contentLayer
239
+ ? {
240
+ "astro:server:setup" : async ( { server, refreshContent } ) => {
241
+ // `server` is the Vite dev server instance
242
+ server . middlewares . use ( "/_refresh" , async ( req , res ) => {
243
+ if ( req . method !== "POST" ) {
244
+ res . writeHead ( 405 , { "Content-Type" : "application/json" } ) ;
245
+ res . end ( JSON . stringify ( { error : "Method Not Allowed" } ) ) ;
246
+ return ;
247
+ }
248
+ let body = [ ] ;
249
+ req . on ( "data" , ( chunk ) => body . push ( chunk ) ) ;
250
+ req . on ( "end" , async ( ) => {
251
+ try {
252
+ const story = JSON . parse ( Buffer . concat ( body ) . toString ( ) ) ;
253
+ await refreshContent ?.( {
254
+ context : { story } ,
255
+ loaders : [ "story-loader" ] ,
256
+ } ) ;
257
+ res . writeHead ( 200 , { "Content-Type" : "application/json" } ) ;
258
+ res . end (
259
+ JSON . stringify ( {
260
+ message : "Content refreshed successfully" ,
261
+ } )
262
+ ) ;
263
+ } catch ( error ) {
264
+ res . writeHead ( 500 , { "Content-Type" : "application/json" } ) ;
265
+ res . end (
266
+ JSON . stringify ( {
267
+ error : `Failed to refresh content: ${ error . message } ` ,
268
+ } )
269
+ ) ;
270
+ }
271
+ } ) ;
272
+ } ) ;
273
+ } ,
274
+ }
275
+ : { } ) ,
215
276
} ,
216
277
} ;
217
278
}
0 commit comments