crelte 0.4.8 → 0.5.0-alpha.2

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 (110) hide show
  1. package/dist/Crelte.d.ts +7 -6
  2. package/dist/Crelte.d.ts.map +1 -1
  3. package/dist/Crelte.js +5 -13
  4. package/dist/CrelteRequest.d.ts +9 -0
  5. package/dist/CrelteRequest.d.ts.map +1 -1
  6. package/dist/CrelteRequest.js +16 -2
  7. package/dist/blocks/Blocks.svelte +2 -2
  8. package/dist/blocks/Blocks.svelte.d.ts +3 -19
  9. package/dist/blocks/Blocks.svelte.d.ts.map +1 -1
  10. package/dist/cookies/ClientCookies.d.ts +0 -1
  11. package/dist/cookies/ClientCookies.d.ts.map +1 -1
  12. package/dist/cookies/ClientCookies.js +0 -1
  13. package/dist/cookies/ServerCookies.d.ts +1 -2
  14. package/dist/cookies/ServerCookies.d.ts.map +1 -1
  15. package/dist/cookies/ServerCookies.js +2 -6
  16. package/dist/cookies/index.d.ts +0 -2
  17. package/dist/cookies/index.d.ts.map +1 -1
  18. package/dist/graphql/GraphQl.d.ts +2 -2
  19. package/dist/graphql/GraphQl.d.ts.map +1 -1
  20. package/dist/index.d.ts +9 -3
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +14 -6
  23. package/dist/init/InternalApp.d.ts +30 -0
  24. package/dist/init/InternalApp.d.ts.map +1 -0
  25. package/dist/init/InternalApp.js +71 -0
  26. package/dist/init/client.d.ts +0 -5
  27. package/dist/init/client.d.ts.map +1 -1
  28. package/dist/init/client.js +88 -75
  29. package/dist/init/crelte-vite-plugin.d.ts +5 -0
  30. package/dist/init/server.d.ts +0 -5
  31. package/dist/init/server.d.ts.map +1 -1
  32. package/dist/init/server.js +49 -20
  33. package/dist/init/shared.d.ts +7 -18
  34. package/dist/init/shared.d.ts.map +1 -1
  35. package/dist/init/shared.js +97 -154
  36. package/dist/init/svelteComponents.d.ts +3 -0
  37. package/dist/init/svelteComponents.d.ts.map +1 -0
  38. package/dist/init/svelteComponents.js +7 -0
  39. package/dist/loadData/Globals.d.ts +40 -33
  40. package/dist/loadData/Globals.d.ts.map +1 -1
  41. package/dist/loadData/Globals.js +99 -88
  42. package/dist/loadData/index.d.ts +3 -2
  43. package/dist/loadData/index.d.ts.map +1 -1
  44. package/dist/loadData/index.js +2 -0
  45. package/dist/plugins/Events.d.ts +11 -13
  46. package/dist/plugins/Events.d.ts.map +1 -1
  47. package/dist/plugins/Events.js +10 -3
  48. package/dist/routing/BaseRoute.d.ts +255 -0
  49. package/dist/routing/BaseRoute.d.ts.map +1 -0
  50. package/dist/routing/BaseRoute.js +349 -0
  51. package/dist/routing/BaseRouter.d.ts +210 -0
  52. package/dist/routing/BaseRouter.d.ts.map +1 -0
  53. package/dist/routing/BaseRouter.js +444 -0
  54. package/dist/routing/ClientRouter.d.ts +32 -0
  55. package/dist/routing/ClientRouter.d.ts.map +1 -0
  56. package/dist/routing/ClientRouter.js +259 -0
  57. package/dist/routing/LoadRunner.d.ts +39 -0
  58. package/dist/routing/LoadRunner.d.ts.map +1 -0
  59. package/dist/routing/{PageLoader.js → LoadRunner.js} +32 -20
  60. package/dist/routing/Request.d.ts +35 -3
  61. package/dist/routing/Request.d.ts.map +1 -1
  62. package/dist/routing/Request.js +64 -5
  63. package/dist/routing/Route.d.ts +24 -223
  64. package/dist/routing/Route.d.ts.map +1 -1
  65. package/dist/routing/Route.js +26 -315
  66. package/dist/routing/Router.d.ts +49 -73
  67. package/dist/routing/Router.d.ts.map +1 -1
  68. package/dist/routing/Router.js +85 -251
  69. package/dist/routing/ServerRouter.d.ts +23 -0
  70. package/dist/routing/ServerRouter.d.ts.map +1 -0
  71. package/dist/routing/ServerRouter.js +57 -0
  72. package/dist/routing/utils.d.ts +5 -0
  73. package/dist/routing/utils.d.ts.map +1 -1
  74. package/dist/routing/utils.js +39 -0
  75. package/dist/utils.d.ts +1 -0
  76. package/dist/utils.d.ts.map +1 -1
  77. package/dist/utils.js +3 -0
  78. package/package.json +7 -6
  79. package/src/Crelte.ts +12 -18
  80. package/src/CrelteRequest.ts +21 -2
  81. package/src/cookies/ClientCookies.ts +0 -2
  82. package/src/cookies/ServerCookies.ts +2 -7
  83. package/src/cookies/index.ts +0 -3
  84. package/src/graphql/GraphQl.ts +2 -1
  85. package/src/index.ts +17 -9
  86. package/src/init/InternalApp.ts +134 -0
  87. package/src/init/client.ts +104 -93
  88. package/src/init/crelte-vite-plugin.d.ts +5 -0
  89. package/src/init/server.ts +67 -35
  90. package/src/init/shared.ts +107 -227
  91. package/src/init/svelteComponents.ts +12 -0
  92. package/src/loadData/Globals.ts +121 -102
  93. package/src/loadData/index.ts +3 -2
  94. package/src/plugins/Events.ts +40 -42
  95. package/src/routing/BaseRoute.ts +422 -0
  96. package/src/routing/BaseRouter.ts +528 -0
  97. package/src/routing/ClientRouter.ts +329 -0
  98. package/src/routing/{PageLoader.ts → LoadRunner.ts} +43 -30
  99. package/src/routing/Request.ts +97 -12
  100. package/src/routing/Route.ts +56 -376
  101. package/src/routing/Router.ts +100 -359
  102. package/src/routing/ServerRouter.ts +78 -0
  103. package/src/routing/utils.ts +53 -0
  104. package/src/utils.ts +4 -0
  105. package/dist/routing/InnerRouter.d.ts +0 -113
  106. package/dist/routing/InnerRouter.d.ts.map +0 -1
  107. package/dist/routing/InnerRouter.js +0 -417
  108. package/dist/routing/PageLoader.d.ts +0 -36
  109. package/dist/routing/PageLoader.d.ts.map +0 -1
  110. package/src/routing/InnerRouter.ts +0 -498
@@ -1,9 +1,19 @@
1
1
  import { CrelteBuilder } from '../Crelte.js';
2
2
  import CrelteRequest from '../CrelteRequest.js';
3
- import { GraphQlQuery } from '../graphql/GraphQl.js';
4
3
  import { SiteFromGraphQl } from '../routing/Site.js';
5
- import { pluginsBeforeRender, prepareLoadFn, setupPlugins } from './shared.js';
4
+ import {
5
+ loadFn,
6
+ pluginsBeforeRender,
7
+ pluginsBeforeRequest,
8
+ setupPlugins,
9
+ } from './shared.js';
6
10
  import { tick } from 'svelte';
11
+ import { svelteMount } from './svelteComponents.js';
12
+ import ClientCookies from '../cookies/ClientCookies.js';
13
+ import ClientRouter from '../routing/ClientRouter.js';
14
+ import InternalApp from './InternalApp.js';
15
+ import { Route } from '../routing/index.js';
16
+ import { Writable } from 'crelte-std/stores';
7
17
 
8
18
  /**
9
19
  * The main function to start the client side rendering
@@ -13,10 +23,6 @@ export type MainData = {
13
23
  app: any;
14
24
  /** The Error.svelte module */
15
25
  errorPage: any;
16
- /** The entry query from queries/entry.graphql */
17
- entryQuery: GraphQlQuery;
18
- /** The global query from queries/global.graphql */
19
- globalQuery?: GraphQlQuery;
20
26
  };
21
27
 
22
28
  const mainDataDefault = {
@@ -52,111 +58,110 @@ const mainDataDefault = {
52
58
  export async function main(data: MainData) {
53
59
  data = { ...mainDataDefault, ...data };
54
60
 
55
- // rendering steps
61
+ // todo if entryQuery or globalQuery is present show a hint
62
+ // they should be added to App.svelte and removed from here
56
63
 
57
- // loadSites (first time)
58
- // determine route (if site is empty on server redirect to correct language)
59
- // loadData, entry (make globally available), pluginsData
60
- // loadTemplate
61
- // render
64
+ const builder = new CrelteBuilder(data.app.config ?? {});
62
65
 
63
- // on route change
64
- // determine route
65
- // entry, pluginsData
66
- // loadTemplate
67
- // update
66
+ const serverError = builder.ssrCache.get('ERROR');
67
+ if (serverError) {
68
+ // todo should this init the client, but maybe we just
69
+ // want it as minimal as possible
68
70
 
69
- // construct Crelte
71
+ svelteMount(data.errorPage.default, {
72
+ target: document.body,
73
+ props: serverError,
74
+ });
75
+ return;
76
+ }
70
77
 
71
- const builder = new CrelteBuilder(data.app.config ?? {});
72
78
  const endpoint = builder.ssrCache.get('ENDPOINT_URL') as string;
73
79
  builder.setupGraphQl(endpoint);
74
80
 
75
81
  // on the client the cookies are always coming from document.cookie
76
- builder.setupCookies('');
82
+ builder.setupCookies(new ClientCookies());
77
83
 
78
84
  const csites = builder.ssrCache.get('crelteSites') as SiteFromGraphQl[];
79
- builder.setupRouter(csites);
85
+ const router = new ClientRouter(csites, {
86
+ debugTiming: builder.config.debugTiming ?? false,
87
+ preloadOnMouseOver: builder.config.preloadOnMouseOver ?? false,
88
+ });
89
+ builder.setupRouter(router);
80
90
 
81
91
  const crelte = builder.build();
82
92
 
83
- const serverError = crelte.ssrCache.get('ERROR');
84
- if (serverError) {
85
- // should this be called??
86
- crelte.router._internal.initClient();
87
-
88
- new data.errorPage.default({
89
- target: document.body,
90
- props: { ...serverError },
91
- hydrate: true,
92
- context: crelte._getContext(),
93
- });
94
- return;
95
- }
93
+ const app = new InternalApp(data.app);
96
94
 
97
95
  // setup plugins
98
- setupPlugins(crelte, data.app.plugins ?? []);
99
- data.app.init?.(crelte);
100
-
101
- const loadFn = await prepareLoadFn(
102
- crelte,
103
- data.app,
104
- data.entryQuery,
105
- data.globalQuery,
106
- );
96
+ setupPlugins(crelte, app.plugins);
97
+ app.init(crelte);
107
98
 
108
- // setup load Data
109
-
110
- crelte.router._internal.onLoad = (req, opts) => {
99
+ router.onNewCrelteRequest = req => {
111
100
  const cr = new CrelteRequest(crelte, req);
112
- return loadFn(cr, opts);
101
+ cr._setRouter(cr.router._toRequest(req));
102
+ cr._setGlobals(cr.globals._toRequest());
103
+ return cr;
113
104
  };
114
105
 
106
+ router.onBeforeRequest = pluginsBeforeRequest;
107
+
108
+ router.loadRunner.loadFn = (cr, opts) => loadFn(cr, app, opts);
109
+
115
110
  // render Space
116
111
 
117
112
  let appInstance: any;
118
- const updateAppProps = (props: any) => {
119
- if (!appInstance) {
120
- appInstance = new data.app.default({
121
- target: document.body,
122
- props,
123
- hydrate: true,
124
- context: crelte._getContext(),
125
- intro: builder.config.playIntro,
126
- });
127
- } else {
128
- appInstance.$set(props);
113
+ let routeProp: Writable<Route>;
114
+ const renderApp = (route: Route) => {
115
+ if (appInstance) {
116
+ routeProp!.set(route);
117
+ return;
129
118
  }
119
+
120
+ routeProp = new Writable(route);
121
+ appInstance = svelteMount(data.app.default, {
122
+ target: document.body,
123
+ props: { route: routeProp },
124
+ context: crelte._getContext(),
125
+ intro: builder.config.playIntro,
126
+ });
130
127
  };
131
128
 
132
- let firstLoad = true;
133
- crelte.router._internal.onLoaded = async (success, req, readyForProps) => {
134
- const isFirstLoad = firstLoad;
135
- firstLoad = false;
136
-
137
- if (!success) {
138
- // if this is not the first load we should reload the page
139
- // we don't reload everytime because this might cause a reload loop
140
- // and since the first load will probably just contain ssrCache data
141
- // in almost all cases the first load will never faill
142
- if (!isFirstLoad) {
143
- // the load might contain a js error and we prefer the error
144
- // page
145
- window.location.reload();
146
- return;
147
- }
129
+ router.onError = e => {
130
+ console.error('routing failed:', e, 'reloading trying to fix it');
131
+ // since onError is called only on subsequent requests we should never
132
+ // have an infinite loop here
133
+ window.location.reload();
134
+ };
148
135
 
149
- return handleLoadError(readyForProps());
150
- }
136
+ // let firstLoad = true;
137
+ router.onRender = async (cr, readyForRoute, domUpdated) => {
138
+ if (appInstance && cr.req.disableLoadData) {
139
+ // if the app is already rendered and entry did not change
140
+ // we just wan't to run domUpdated because we don't wan't to update anything
151
141
 
152
- const cr = new CrelteRequest(crelte, req);
142
+ const route = readyForRoute();
143
+ cr.router._requestCompleted();
144
+ // globals should not be run because they will be empty
145
+ // since nobody called loadGlobalData (todo maybe globals should also,
146
+ // know if it accepts updates)
147
+
148
+ // todo should we wait a tick here?
149
+ await tick();
150
+
151
+ domUpdated(cr, route);
152
+
153
+ return route;
154
+ }
153
155
 
154
156
  const startTime = builder.config.debugTiming ? Date.now() : null;
157
+
155
158
  let render = async () => {
159
+ const route = readyForRoute();
160
+ cr.router._requestCompleted();
161
+ cr.globals._syncToStores();
156
162
  // we should trigger the route update here
157
- pluginsBeforeRender(cr);
158
- crelte.globals._updateSiteId(cr.site.id);
159
- updateAppProps(readyForProps());
163
+ pluginsBeforeRender(cr, route);
164
+ renderApp(route);
160
165
 
161
166
  await tick();
162
167
 
@@ -166,7 +171,9 @@ export async function main(data: MainData) {
166
171
  );
167
172
  }
168
173
 
169
- crelte.router._internal.domReady(cr.req);
174
+ domUpdated(cr, route);
175
+
176
+ return route;
170
177
  };
171
178
 
172
179
  // render with view Transition if enabled and not in hydration
@@ -175,22 +182,26 @@ export async function main(data: MainData) {
175
182
  appInstance &&
176
183
  (document as any).startViewTransition
177
184
  ) {
178
- render = () => (document as any).startViewTransition(render);
185
+ const prevRender = render;
186
+ render = async () =>
187
+ new Promise(resolve => {
188
+ (document as any).startViewTransition(async () => {
189
+ resolve(await prevRender());
190
+ });
191
+ });
179
192
  }
180
193
 
181
- await render();
194
+ return await render();
182
195
  };
183
196
 
184
- crelte.router._internal.onNothingLoaded = async (req, ready) => {
185
- crelte.globals._updateSiteId(req.site.id);
186
- ready();
187
-
188
- await tick();
189
-
190
- crelte.router._internal.domReady(req);
191
- };
192
-
193
- crelte.router._internal.initClient();
197
+ try {
198
+ await router.init();
199
+ } catch (e) {
200
+ // the first load we can't handle with a redirect since this might
201
+ // cause an infinite loop
202
+ // but since almost everything should be ssrCached nothing should fail
203
+ handleLoadError(e);
204
+ }
194
205
  }
195
206
 
196
207
  function handleLoadError(e: any) {
@@ -0,0 +1,5 @@
1
+ declare module 'crelte-vite-plugin/svelteComponents.js' {
2
+ // Declarations for the internal functions imported from the plugin
3
+ export function internalSvelteMount(comp: any, options: any): any;
4
+ export function internalSvelteRender(comp: any, options: any): any;
5
+ }
@@ -1,11 +1,19 @@
1
1
  import { CrelteBuilder } from '../Crelte.js';
2
2
  import { SiteFromGraphQl } from '../routing/Site.js';
3
- import { pluginsBeforeRender, prepareLoadFn, setupPlugins } from './shared.js';
3
+ import {
4
+ loadFn,
5
+ pluginsBeforeRender,
6
+ pluginsBeforeRequest,
7
+ setupPlugins,
8
+ } from './shared.js';
4
9
  import SsrComponents from '../ssr/SsrComponents.js';
5
10
  import SsrCache from '../ssr/SsrCache.js';
6
11
  import ServerCookies from '../cookies/ServerCookies.js';
7
12
  import CrelteRequest from '../CrelteRequest.js';
8
- import { GraphQlQuery } from '../graphql/GraphQl.js';
13
+ import { svelteRender } from './svelteComponents.js';
14
+ import { Writable } from 'crelte-std/stores';
15
+ import ServerRouter from '../routing/ServerRouter.js';
16
+ import InternalApp from './InternalApp.js';
9
17
 
10
18
  export type ServerData = {
11
19
  url: string;
@@ -25,10 +33,6 @@ export type ServerData = {
25
33
  export type MainData = {
26
34
  /** The App.svelte module */
27
35
  app: any;
28
- /** The entry query from queries/entry.graphql */
29
- entryQuery: GraphQlQuery;
30
- /** The global query from queries/global.graphql */
31
- globalQuery?: GraphQlQuery;
32
36
 
33
37
  /** Server data provided by crelte-node */
34
38
  serverData: ServerData;
@@ -60,6 +64,9 @@ export async function main(data: MainData): Promise<{
60
64
  html?: string;
61
65
  setCookies?: string[];
62
66
  }> {
67
+ // todo if entryQuery or globalQuery is present show a hint
68
+ // they should be added to App.svelte and removed from here
69
+
63
70
  const builder = new CrelteBuilder(data.app.config ?? {});
64
71
 
65
72
  // setup viteEnv
@@ -73,39 +80,50 @@ export async function main(data: MainData): Promise<{
73
80
  builder.setupGraphQl(endpoint);
74
81
 
75
82
  const cookies = data.serverData.cookies ?? '';
76
- builder.setupCookies(cookies);
83
+ builder.setupCookies(new ServerCookies(cookies));
77
84
 
78
85
  builder.ssrCache.set('crelteSites', data.serverData.sites);
79
- builder.setupRouter(data.serverData.sites);
86
+ const router = new ServerRouter(data.serverData.sites, {
87
+ debugTiming: builder.config.debugTiming ?? false,
88
+ });
89
+ builder.setupRouter(router);
80
90
 
81
91
  const crelte = builder.build();
82
92
 
83
- // setup plugins
84
- setupPlugins(crelte, data.app.plugins ?? []);
85
- data.app.init?.(crelte);
86
-
87
- const loadFn = await prepareLoadFn(
88
- crelte,
89
- data.app,
90
- data.entryQuery,
91
- data.globalQuery,
92
- );
93
+ const app = new InternalApp(data.app);
93
94
 
94
- // setup load Data
95
+ // setup plugins
96
+ setupPlugins(crelte, app.plugins);
97
+ app.init(crelte);
95
98
 
96
- crelte.router._internal.onLoad = req => {
99
+ router.onNewCrelteRequest = req => {
97
100
  const cr = new CrelteRequest(crelte, req);
98
- return loadFn(cr);
101
+ cr._setRouter(cr.router._toRequest(req));
102
+ cr._setGlobals(cr.globals._toRequest());
103
+ return cr;
104
+ };
105
+
106
+ router.onBeforeRequest = pluginsBeforeRequest;
107
+
108
+ router.loadRunner.loadFn = (cr, opts) => loadFn(cr, app, opts);
109
+
110
+ router.onRender = (cr, readyForRoute, _domUpdated) => {
111
+ const route = readyForRoute();
112
+ cr.router._requestCompleted();
113
+ cr.globals._syncToStores();
114
+ pluginsBeforeRender(cr, route);
115
+
116
+ return route;
99
117
  };
100
118
 
101
- const { success, redirect, req, props } =
102
- await crelte.router._internal.initServer(
103
- data.serverData.url,
104
- data.serverData.acceptLang,
105
- );
106
- if (!success) throw props;
119
+ // throws if there was an error
120
+ const [req, route] = await router.init(
121
+ data.serverData.url,
122
+ data.serverData.acceptLang,
123
+ );
107
124
 
108
- if (redirect) {
125
+ // if redirect
126
+ if (!route) {
109
127
  return {
110
128
  status: req.statusCode ?? 302,
111
129
  location: req.url.toString(),
@@ -119,23 +137,31 @@ export async function main(data: MainData): Promise<{
119
137
  const ssrComponents = new SsrComponents();
120
138
  ssrComponents.addToContext(context);
121
139
 
122
- const cr = new CrelteRequest(crelte, req);
123
- pluginsBeforeRender(cr);
124
- crelte.globals._updateSiteId(cr.site.id);
140
+ // app should not use getRoute but use the route store
141
+ // received from the props, since it will only update when
142
+ // the entryChanges
143
+ const routeProp = new Writable(route);
144
+
125
145
  // eslint-disable-next-line prefer-const
126
- let { html, head } = data.app.default.render(props, { context });
146
+ let { html, head } = svelteRender(data.app.default, {
147
+ props: { route: routeProp },
148
+ context,
149
+ });
127
150
 
128
151
  head += ssrComponents.toHead(data.serverData.ssrManifest);
129
152
  head += crelte.ssrCache._exportToHead();
130
153
 
131
154
  let htmlTemplate = data.serverData.htmlTemplate;
132
- htmlTemplate = htmlTemplate.replace('<!--page-lang-->', cr.site.language);
155
+ htmlTemplate = htmlTemplate.replace(
156
+ '<!--page-lang-->',
157
+ route.site.language,
158
+ );
133
159
 
134
160
  const finalHtml = htmlTemplate
135
161
  .replace('</head>', head + '\n\t</head>')
136
162
  .replace('<!--ssr-body-->', html);
137
163
 
138
- const entry = props.entry;
164
+ const entry = route.entry;
139
165
 
140
166
  return {
141
167
  status:
@@ -189,8 +215,14 @@ export async function mainError(
189
215
 
190
216
  ssrCache.set('ERROR', data.error);
191
217
 
218
+ // todo on the client crelte is in the context
219
+ // but it should match this impl
220
+
192
221
  // eslint-disable-next-line prefer-const
193
- let { html, head } = data.errorPage.default.render(data.error, { context });
222
+ let { html, head } = svelteRender(data.errorPage.default, {
223
+ props: data.error,
224
+ context,
225
+ });
194
226
 
195
227
  head += ssrComponents.toHead(data.serverData.ssrManifest);
196
228
  head += ssrCache._exportToHead();