77 resetReloadForError ,
88 __secret_internals ,
99 isNetworkError ,
10+ getHistory ,
1011} from "@next-core/runtime" ;
1112import { HttpRequestConfig , http } from "@next-core/http" ;
1213import { i18n , initializeI18n } from "@next-core/i18n" ;
@@ -20,6 +21,7 @@ import {
2021 analytics ,
2122} from "@next-core/easyops-runtime" ;
2223import "@next-core/theme" ;
24+ import type { BootstrapData , Storyboard } from "@next-core/types" ;
2325import "./XMLHttpRequest.js" ;
2426import { loadCheckLogin } from "./loadCheckLogin.js" ;
2527import { fulfilStoryboard , loadBootstrapData } from "./loadBootstrapData.js" ;
@@ -30,6 +32,10 @@ import { getMock } from "./mocks.js";
3032import { NS , K , locales } from "./i18n.js" ;
3133import { DefaultError } from "./DefaultError.js" ;
3234
35+ const isAppPreview = ! ! new URLSearchParams ( window . location . search ) . get (
36+ "_experimental_app_preview_"
37+ ) ;
38+
3339customElements . define ( "easyops-default-error" , DefaultError ) ;
3440
3541analytics . initialize (
@@ -115,61 +121,126 @@ const requestEnd = (): void => {
115121window . addEventListener ( "request.start" , requestStart ) ;
116122window . addEventListener ( "request.end" , requestEnd ) ;
117123
118- const runtime = createRuntime ( {
119- hooks : {
120- auth,
121- fulfilStoryboard,
122- checkPermissions,
123- flowApi,
124- checkInstalledApps,
125- menu,
126- images : { imagesFactory, widgetImagesFactory } ,
127- messageDispatcher,
128- pageView : analytics . pageView ,
129- } ,
130- } ) ;
124+ function doCreateRuntime ( ) {
125+ return createRuntime ( {
126+ hooks : {
127+ auth,
128+ checkPermissions,
129+ flowApi,
130+ checkInstalledApps,
131+ menu,
132+ images : { imagesFactory, widgetImagesFactory } ,
133+ messageDispatcher,
134+ ...( isAppPreview
135+ ? null
136+ : {
137+ fulfilStoryboard,
138+ pageView : analytics . pageView ,
139+ } ) ,
140+ } ,
141+ } ) ;
142+ }
131143
132144initializeI18n ( NS , locales ) ;
133145
146+ interface PreviewWindow extends Window {
147+ _preview_only_appPreviewer ?: AppPreviewer ;
148+ }
149+
150+ class AppPreviewer {
151+ #setupCalled = false ;
152+
153+ async setup ( data : BootstrapData , url : string ) {
154+ try {
155+ if ( this . #setupCalled) {
156+ throw new Error (
157+ "_preview_only_setupAppPreview can only be called once"
158+ ) ;
159+ }
160+ this . #setupCalled = true ;
161+ history . replaceState ( null , "" , url ) ;
162+ const runtime = doCreateRuntime ( ) ;
163+ await loadCheckLogin ( ) ;
164+ await runtime . bootstrap ( data as any ) ;
165+ } catch ( error ) {
166+ handleError ( error ) ;
167+ }
168+ requestEnd ( ) ;
169+ }
170+
171+ async update ( appId : string , storyboard : Partial < Storyboard > ) {
172+ __secret_internals . updateStoryboard ( appId , storyboard ) ;
173+ }
174+
175+ reload ( ) {
176+ getHistory ( ) . reload ( ) ;
177+ }
178+
179+ push ( url : string ) {
180+ getHistory ( ) . push ( url ) ;
181+ }
182+
183+ replace ( url : string ) {
184+ getHistory ( ) . replace ( url ) ;
185+ }
186+
187+ goBack ( ) {
188+ getHistory ( ) . goBack ( ) ;
189+ }
190+
191+ goForward ( ) {
192+ getHistory ( ) . goForward ( ) ;
193+ }
194+ }
195+
134196async function main ( ) {
135197 try {
136- const [ , bootstrapData ] = await Promise . all ( [
137- loadCheckLogin ( ) ,
138- loadBootstrapData ( ) ,
139- ] ) ;
140- await runtime . bootstrap ( bootstrapData ) ;
141- resetReloadForError ( ) ;
198+ if ( isAppPreview ) {
199+ requestStart ( ) ;
200+ ( window as PreviewWindow ) . _preview_only_appPreviewer = new AppPreviewer ( ) ;
201+ return "ok" ;
202+ } else {
203+ const runtime = doCreateRuntime ( ) ;
204+ const [ , bootstrapData ] = await Promise . all ( [
205+ loadCheckLogin ( ) ,
206+ loadBootstrapData ( ) ,
207+ ] ) ;
208+ await runtime . bootstrap ( bootstrapData ) ;
209+ resetReloadForError ( ) ;
210+ }
142211 return "ok" ;
143212 } catch ( error ) {
144- // eslint-disable-next-line no-console
145- console . error ( "bootstrap failed:" , error ) ;
146-
147- if ( shouldReloadForError ( error ) ) {
148- location . reload ( ) ;
149- return "failed" ;
150- }
213+ handleError ( error ) ;
214+ return "failed" ;
215+ }
216+ }
151217
152- // `.bootstrap-error` makes loading-bar invisible.
153- document . body . classList . add ( "bootstrap-error" ) ;
154-
155- const errorElement = document . createElement (
156- "easyops-default-error"
157- ) as DefaultError ;
158- errorElement . errorTitle = isNetworkError ( error )
159- ? i18n . t ( `${ NS } :${ K . NETWORK_ERROR } ` )
160- : i18n . t ( `${ NS } :${ K . BOOTSTRAP_ERROR } ` ) ;
161- errorElement . textContent = httpErrorToString ( error ) ;
162- const linkElement = document . createElement ( "a" ) ;
163- linkElement . slot = "link" ;
164- linkElement . href = location . href ;
165- linkElement . textContent = i18n . t ( `${ NS } :${ K . RELOAD } ` ) ;
166- errorElement . appendChild ( linkElement ) ;
167-
168- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
169- document . querySelector ( "#main-mount-point" ) ! . replaceChildren ( errorElement ) ;
218+ function handleError ( error : unknown ) {
219+ // eslint-disable-next-line no-console
220+ console . error ( "bootstrap failed:" , error ) ;
170221
222+ if ( shouldReloadForError ( error ) ) {
223+ location . reload ( ) ;
171224 return "failed" ;
172225 }
226+
227+ // `.bootstrap-error` makes loading-bar invisible.
228+ document . body . classList . add ( "bootstrap-error" ) ;
229+
230+ const errorElement = document . createElement (
231+ "easyops-default-error"
232+ ) as DefaultError ;
233+ errorElement . errorTitle = isNetworkError ( error )
234+ ? i18n . t ( `${ NS } :${ K . NETWORK_ERROR } ` )
235+ : i18n . t ( `${ NS } :${ K . BOOTSTRAP_ERROR } ` ) ;
236+ errorElement . textContent = httpErrorToString ( error ) ;
237+ const linkElement = document . createElement ( "a" ) ;
238+ linkElement . slot = "link" ;
239+ linkElement . href = location . href ;
240+ linkElement . textContent = i18n . t ( `${ NS } :${ K . RELOAD } ` ) ;
241+ errorElement . appendChild ( linkElement ) ;
242+
243+ document . querySelector ( "#main-mount-point" ) ! . replaceChildren ( errorElement ) ;
173244}
174245
175246const bootstrapStatus = main ( ) ;
0 commit comments