crelte 0.5.11 → 0.5.12
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/dist/bodyClass/BodyClass.d.ts +39 -0
- package/dist/bodyClass/BodyClass.d.ts.map +1 -0
- package/dist/bodyClass/BodyClass.js +51 -0
- package/dist/bodyClass/ClientBodyClass.d.ts +12 -0
- package/dist/bodyClass/ClientBodyClass.d.ts.map +1 -0
- package/dist/bodyClass/ClientBodyClass.js +57 -0
- package/dist/bodyClass/ServerBodyClass.d.ts +12 -0
- package/dist/bodyClass/ServerBodyClass.d.ts.map +1 -0
- package/dist/bodyClass/ServerBodyClass.js +47 -0
- package/dist/bodyClass/index.d.ts +2 -0
- package/dist/bodyClass/index.d.ts.map +1 -0
- package/dist/bodyClass/index.js +1 -0
- package/dist/cookies/ClientCookies.d.ts +8 -3
- package/dist/cookies/ClientCookies.d.ts.map +1 -1
- package/dist/cookies/ClientCookies.js +31 -7
- package/dist/cookies/Cookies.d.ts +42 -0
- package/dist/cookies/Cookies.d.ts.map +1 -0
- package/dist/cookies/Cookies.js +44 -0
- package/dist/cookies/ServerCookies.d.ts +3 -2
- package/dist/cookies/ServerCookies.d.ts.map +1 -1
- package/dist/cookies/ServerCookies.js +6 -4
- package/dist/cookies/index.d.ts +1 -25
- package/dist/cookies/index.d.ts.map +1 -1
- package/dist/cookies/index.js +1 -1
- package/dist/crelte.d.ts +7 -1
- package/dist/crelte.d.ts.map +1 -1
- package/dist/crelte.js +2 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/init/client.d.ts.map +1 -1
- package/dist/init/client.js +23 -14
- package/dist/init/server.d.ts.map +1 -1
- package/dist/init/server.js +11 -3
- package/dist/init/shared.d.ts +1 -0
- package/dist/init/shared.d.ts.map +1 -1
- package/dist/init/shared.js +16 -5
- package/dist/loadData/Globals.d.ts.map +1 -1
- package/dist/node/index.js +1 -1
- package/dist/plugins/Events.d.ts +6 -1
- package/dist/plugins/Events.d.ts.map +1 -1
- package/dist/plugins/Plugins.d.ts +36 -1
- package/dist/plugins/Plugins.d.ts.map +1 -1
- package/dist/plugins/Plugins.js +32 -0
- package/dist/routing/route/Request.d.ts +1 -1
- package/dist/routing/route/Request.d.ts.map +1 -1
- package/dist/routing/route/Request.js +7 -3
- package/dist/routing/router/ClientRouter.d.ts.map +1 -1
- package/dist/routing/router/ClientRouter.js +18 -11
- package/dist/routing/router/Router.d.ts.map +1 -1
- package/dist/routing/router/Router.js +8 -12
- package/dist/server/CrelteServer.d.ts +1 -0
- package/dist/server/CrelteServer.d.ts.map +1 -1
- package/dist/server/CrelteServer.js +5 -2
- package/dist/std/stores/StagedWritable.d.ts +48 -0
- package/dist/std/stores/StagedWritable.d.ts.map +1 -0
- package/dist/std/stores/StagedWritable.js +84 -0
- package/dist/std/stores/index.d.ts +2 -1
- package/dist/std/stores/index.d.ts.map +1 -1
- package/dist/std/stores/index.js +2 -1
- package/dist/std/sync/Barrier.js +1 -1
- package/dist/utils.d.ts +9 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +11 -0
- package/package.json +5 -1
- package/src/bodyClass/BodyClass.ts +72 -0
- package/src/bodyClass/ClientBodyClass.ts +62 -0
- package/src/bodyClass/ServerBodyClass.ts +65 -0
- package/src/bodyClass/index.ts +1 -0
- package/src/cookies/ClientCookies.ts +41 -10
- package/src/cookies/Cookies.ts +70 -0
- package/src/cookies/ServerCookies.ts +9 -6
- package/src/cookies/index.ts +5 -29
- package/src/crelte.ts +9 -0
- package/src/index.ts +15 -1
- package/src/init/client.ts +26 -14
- package/src/init/server.ts +11 -3
- package/src/init/shared.ts +18 -6
- package/src/loadData/Globals.ts +1 -1
- package/src/node/index.ts +1 -1
- package/src/plugins/Events.ts +12 -1
- package/src/plugins/Plugins.ts +66 -1
- package/src/routing/route/Request.ts +11 -4
- package/src/routing/router/ClientRouter.ts +23 -14
- package/src/routing/router/Router.ts +8 -10
- package/src/server/CrelteServer.ts +4 -2
- package/src/std/stores/StagedWritable.ts +96 -0
- package/src/std/stores/index.ts +2 -1
- package/src/std/sync/Barrier.ts +1 -1
- package/src/utils.ts +15 -0
package/src/crelte.ts
CHANGED
|
@@ -9,6 +9,7 @@ import Queries, { Query, QueryOptions } from './queries/Queries.js';
|
|
|
9
9
|
import { Readable } from './std/stores/index.js';
|
|
10
10
|
import { Entry } from './loadData/index.js';
|
|
11
11
|
import { urlWithPath } from './utils.js';
|
|
12
|
+
import { BodyClass } from './bodyClass/index.js';
|
|
12
13
|
|
|
13
14
|
/** The type for the app.config object */
|
|
14
15
|
export type Config = {
|
|
@@ -113,6 +114,11 @@ export type Crelte = {
|
|
|
113
114
|
*/
|
|
114
115
|
cookies: Cookies;
|
|
115
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Get the BodyClass instance
|
|
119
|
+
*/
|
|
120
|
+
bodyClass: BodyClass;
|
|
121
|
+
|
|
116
122
|
/**
|
|
117
123
|
* Get a Plugin by name
|
|
118
124
|
*/
|
|
@@ -263,6 +269,7 @@ export function newCrelte({
|
|
|
263
269
|
router,
|
|
264
270
|
queries,
|
|
265
271
|
cookies,
|
|
272
|
+
bodyClass,
|
|
266
273
|
}: {
|
|
267
274
|
config: Required<Config>;
|
|
268
275
|
ssrCache: SsrCache;
|
|
@@ -272,6 +279,7 @@ export function newCrelte({
|
|
|
272
279
|
router: Router;
|
|
273
280
|
queries: Queries;
|
|
274
281
|
cookies: Cookies;
|
|
282
|
+
bodyClass: BodyClass;
|
|
275
283
|
}): Crelte {
|
|
276
284
|
return {
|
|
277
285
|
config,
|
|
@@ -282,6 +290,7 @@ export function newCrelte({
|
|
|
282
290
|
router,
|
|
283
291
|
queries,
|
|
284
292
|
cookies,
|
|
293
|
+
bodyClass,
|
|
285
294
|
|
|
286
295
|
getPlugin: name => plugins.get(name),
|
|
287
296
|
getEnv: key => ssrCache.get(key as any) as any,
|
package/src/index.ts
CHANGED
|
@@ -17,7 +17,8 @@ import {
|
|
|
17
17
|
LoadDataObj,
|
|
18
18
|
} from './loadData/index.js';
|
|
19
19
|
import Queries from './queries/Queries.js';
|
|
20
|
-
import { Readable } from './std/stores/index.js';
|
|
20
|
+
import { Readable, Writable } from './std/stores/index.js';
|
|
21
|
+
import { BodyClass } from './bodyClass/index.js';
|
|
21
22
|
|
|
22
23
|
export {
|
|
23
24
|
type Crelte,
|
|
@@ -33,6 +34,9 @@ export {
|
|
|
33
34
|
/** The type for the app.init function */
|
|
34
35
|
export type Init = (crelte: Crelte) => void;
|
|
35
36
|
|
|
37
|
+
/** The Props that are passed to the app */
|
|
38
|
+
export type AppProps = { route: Writable<Route> };
|
|
39
|
+
|
|
36
40
|
function innerGetCrelte(): Crelte {
|
|
37
41
|
return getContext('crelte');
|
|
38
42
|
}
|
|
@@ -174,6 +178,16 @@ export function getCookies(): Cookies {
|
|
|
174
178
|
return innerGetCrelte().cookies;
|
|
175
179
|
}
|
|
176
180
|
|
|
181
|
+
/**
|
|
182
|
+
* returns the body class instance
|
|
183
|
+
*
|
|
184
|
+
* #### Note
|
|
185
|
+
* This only works during component initialisation.
|
|
186
|
+
*/
|
|
187
|
+
export function getBodyClass(): BodyClass {
|
|
188
|
+
return innerGetCrelte().bodyClass;
|
|
189
|
+
}
|
|
190
|
+
|
|
177
191
|
/**
|
|
178
192
|
* Listen for route changes
|
|
179
193
|
*
|
package/src/init/client.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
loadFn,
|
|
4
4
|
newQueries,
|
|
5
5
|
onNewCrelteRequest,
|
|
6
|
+
pluginsAfterRender,
|
|
6
7
|
pluginsBeforeRender,
|
|
7
8
|
pluginsBeforeRequest,
|
|
8
9
|
setupPlugins,
|
|
@@ -19,6 +20,9 @@ import Plugins from '../plugins/Plugins.js';
|
|
|
19
20
|
import Events from '../plugins/Events.js';
|
|
20
21
|
import Globals from '../loadData/Globals.js';
|
|
21
22
|
import { Writable } from '../std/stores/index.js';
|
|
23
|
+
import ClientBodyClass from '../bodyClass/ClientBodyClass.js';
|
|
24
|
+
import { BodyClass } from '../bodyClass/index.js';
|
|
25
|
+
import { Cookies } from '../cookies/index.js';
|
|
22
26
|
|
|
23
27
|
/**
|
|
24
28
|
* The main function to start the client side rendering
|
|
@@ -74,7 +78,6 @@ export async function main(data: MainData) {
|
|
|
74
78
|
});
|
|
75
79
|
|
|
76
80
|
const queries = newQueries(ssrCache, router.route.readonly(), config);
|
|
77
|
-
const cookies = new ClientCookies();
|
|
78
81
|
|
|
79
82
|
const crelte = newCrelte({
|
|
80
83
|
config,
|
|
@@ -84,7 +87,8 @@ export async function main(data: MainData) {
|
|
|
84
87
|
globals: new Globals(),
|
|
85
88
|
router: new Router(router),
|
|
86
89
|
queries,
|
|
87
|
-
cookies,
|
|
90
|
+
cookies: new Cookies(new ClientCookies()),
|
|
91
|
+
bodyClass: new BodyClass(new ClientBodyClass()),
|
|
88
92
|
});
|
|
89
93
|
|
|
90
94
|
const app = new InternalApp(data.app);
|
|
@@ -101,22 +105,22 @@ export async function main(data: MainData) {
|
|
|
101
105
|
|
|
102
106
|
// render Space
|
|
103
107
|
|
|
104
|
-
let
|
|
105
|
-
let routeProp: Writable<Route>;
|
|
108
|
+
let routeProp: Writable<Route> | null = null;
|
|
106
109
|
const renderApp = (route: Route) => {
|
|
107
|
-
if (
|
|
108
|
-
routeProp
|
|
110
|
+
if (routeProp) {
|
|
111
|
+
routeProp.set(route);
|
|
109
112
|
return;
|
|
110
113
|
}
|
|
111
114
|
|
|
112
115
|
routeProp = new Writable(route);
|
|
113
|
-
|
|
116
|
+
svelteMount(data.app.default, {
|
|
114
117
|
target: document.body,
|
|
115
118
|
props: { route: routeProp },
|
|
116
119
|
context: new Map([['crelte', crelte]]),
|
|
117
120
|
intro: config.playIntro,
|
|
118
121
|
});
|
|
119
122
|
};
|
|
123
|
+
const appMounted = () => !!routeProp;
|
|
120
124
|
|
|
121
125
|
router.onError = (e, req) => {
|
|
122
126
|
console.error('routing failed:', e, 'reloading trying to fix it');
|
|
@@ -126,9 +130,9 @@ export async function main(data: MainData) {
|
|
|
126
130
|
};
|
|
127
131
|
|
|
128
132
|
router.onRender = async (cr, readyForRoute, domUpdated) => {
|
|
129
|
-
if (
|
|
133
|
+
if (appMounted() && cr.req.disableLoadData) {
|
|
130
134
|
// if the app is already rendered and entry did not change
|
|
131
|
-
// we just wan't to run domUpdated because we don't
|
|
135
|
+
// we just wan't to run domUpdated because we don't want to update anything
|
|
132
136
|
|
|
133
137
|
const route = readyForRoute();
|
|
134
138
|
cr.router.z_requestCompleted();
|
|
@@ -140,6 +144,7 @@ export async function main(data: MainData) {
|
|
|
140
144
|
await tick();
|
|
141
145
|
|
|
142
146
|
domUpdated(cr, route);
|
|
147
|
+
pluginsAfterRender(cr, route);
|
|
143
148
|
|
|
144
149
|
return route;
|
|
145
150
|
}
|
|
@@ -149,9 +154,15 @@ export async function main(data: MainData) {
|
|
|
149
154
|
let render = async () => {
|
|
150
155
|
const route = readyForRoute();
|
|
151
156
|
cr.router.z_requestCompleted();
|
|
152
|
-
|
|
153
|
-
// we
|
|
154
|
-
|
|
157
|
+
// this is only important on the first render
|
|
158
|
+
// else we will catch an earlier branch in onRender
|
|
159
|
+
if (route.entryChanged) {
|
|
160
|
+
cr.globals.z_syncToStores();
|
|
161
|
+
pluginsBeforeRender(cr, route);
|
|
162
|
+
cr.cookies.z_render();
|
|
163
|
+
cr.bodyClass.z_render();
|
|
164
|
+
}
|
|
165
|
+
|
|
155
166
|
renderApp(route);
|
|
156
167
|
|
|
157
168
|
await tick();
|
|
@@ -163,6 +174,7 @@ export async function main(data: MainData) {
|
|
|
163
174
|
}
|
|
164
175
|
|
|
165
176
|
domUpdated(cr, route);
|
|
177
|
+
pluginsAfterRender(cr, route);
|
|
166
178
|
|
|
167
179
|
return route;
|
|
168
180
|
};
|
|
@@ -170,7 +182,7 @@ export async function main(data: MainData) {
|
|
|
170
182
|
// render with view Transition if enabled and not in hydration
|
|
171
183
|
if (
|
|
172
184
|
config.viewTransition &&
|
|
173
|
-
|
|
185
|
+
appMounted() &&
|
|
174
186
|
(document as any).startViewTransition
|
|
175
187
|
) {
|
|
176
188
|
const prevRender = render;
|
|
@@ -211,8 +223,8 @@ function handleLoadError(e: any) {
|
|
|
211
223
|
|
|
212
224
|
// Messages in different languages
|
|
213
225
|
const messages: Record<string, string> = {
|
|
214
|
-
en: 'An error has occurred. Please reload the page or try again later.',
|
|
215
226
|
de: 'Leider ist ein Fehler aufgetreten. Laden Sie die Seite neu, oder versuchen Sie es später noch mal.',
|
|
227
|
+
en: 'An error has occurred. Please reload the page or try again later.',
|
|
216
228
|
fr: 'Une erreur s’est produite. Veuillez recharger la page ou réessayer plus tard.',
|
|
217
229
|
it: 'Si è verificato un errore. Ricarica la pagina o riprova più tardi.',
|
|
218
230
|
nl: 'Er is een fout opgetreden. Herlaad de pagina of probeer het later opnieuw.',
|
package/src/init/server.ts
CHANGED
|
@@ -23,6 +23,9 @@ import {
|
|
|
23
23
|
RenderRequest,
|
|
24
24
|
RenderResponse,
|
|
25
25
|
} from '../server/shared.js';
|
|
26
|
+
import ServerBodyClass from '../bodyClass/ServerBodyClass.js';
|
|
27
|
+
import BodyClass from '../bodyClass/BodyClass.js';
|
|
28
|
+
import { Cookies } from '../cookies/index.js';
|
|
26
29
|
|
|
27
30
|
export { type RenderRequest, type RenderResponse } from '../server/shared.js';
|
|
28
31
|
|
|
@@ -75,6 +78,7 @@ export async function main(data: MainData): Promise<RenderResponse> {
|
|
|
75
78
|
ssrCache.set('FRONTEND_URL', data.serverData.frontend);
|
|
76
79
|
|
|
77
80
|
const cookies = new ServerCookies(data.serverData.headers);
|
|
81
|
+
const bodyClass = new ServerBodyClass();
|
|
78
82
|
|
|
79
83
|
ssrCache.set('crelteSites', data.serverData.sites);
|
|
80
84
|
const router = new ServerRouter(
|
|
@@ -93,7 +97,8 @@ export async function main(data: MainData): Promise<RenderResponse> {
|
|
|
93
97
|
globals: new Globals(),
|
|
94
98
|
router: new Router(router),
|
|
95
99
|
queries,
|
|
96
|
-
cookies,
|
|
100
|
+
cookies: new Cookies(cookies),
|
|
101
|
+
bodyClass: new BodyClass(bodyClass),
|
|
97
102
|
});
|
|
98
103
|
|
|
99
104
|
const app = new InternalApp(data.app);
|
|
@@ -111,6 +116,8 @@ export async function main(data: MainData): Promise<RenderResponse> {
|
|
|
111
116
|
cr.router.z_requestCompleted();
|
|
112
117
|
cr.globals.z_syncToStores();
|
|
113
118
|
pluginsBeforeRender(cr, route);
|
|
119
|
+
cr.cookies.z_render();
|
|
120
|
+
cr.bodyClass.z_render();
|
|
114
121
|
|
|
115
122
|
return route;
|
|
116
123
|
};
|
|
@@ -121,7 +128,7 @@ export async function main(data: MainData): Promise<RenderResponse> {
|
|
|
121
128
|
// if redirect
|
|
122
129
|
if (!route) {
|
|
123
130
|
const headers = new Headers();
|
|
124
|
-
|
|
131
|
+
cookies._populateHeaders(headers);
|
|
125
132
|
|
|
126
133
|
return {
|
|
127
134
|
status: req.statusCode ?? 302,
|
|
@@ -153,6 +160,7 @@ export async function main(data: MainData): Promise<RenderResponse> {
|
|
|
153
160
|
'<!--page-lang-->',
|
|
154
161
|
route.site.language,
|
|
155
162
|
);
|
|
163
|
+
htmlTemplate = bodyClass.z_processHtmlTemplate(htmlTemplate);
|
|
156
164
|
|
|
157
165
|
const finalHtml = htmlTemplate
|
|
158
166
|
.replace('</head>', head + '\n\t</head>')
|
|
@@ -161,7 +169,7 @@ export async function main(data: MainData): Promise<RenderResponse> {
|
|
|
161
169
|
const entry = route.entry;
|
|
162
170
|
|
|
163
171
|
const headers = new Headers();
|
|
164
|
-
|
|
172
|
+
cookies._populateHeaders(headers);
|
|
165
173
|
|
|
166
174
|
return {
|
|
167
175
|
status:
|
package/src/init/shared.ts
CHANGED
|
@@ -32,6 +32,11 @@ export function pluginsBeforeRequest(cr: CrelteRequest): Promise<void> | void {
|
|
|
32
32
|
|
|
33
33
|
export function pluginsBeforeRender(cr: CrelteRequest, route: Route): void {
|
|
34
34
|
cr.events.trigger('beforeRender', cr, route);
|
|
35
|
+
cr.plugins.z_render(cr, route);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function pluginsAfterRender(cr: CrelteRequest, route: Route): void {
|
|
39
|
+
cr.events.trigger('afterRender', cr, route);
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
export function newQueries(
|
|
@@ -64,12 +69,15 @@ export function onNewCrelteRequest(
|
|
|
64
69
|
...crelte,
|
|
65
70
|
router: crelte.router.z_toRequest(req),
|
|
66
71
|
queries: crelte.queries.z_toRequest(req),
|
|
72
|
+
plugins: crelte.plugins.z_toRequest(req),
|
|
67
73
|
globals: crelte.globals.z_toRequest(),
|
|
74
|
+
cookies: crelte.cookies.z_toRequest(),
|
|
75
|
+
bodyClass: crelte.bodyClass.z_toRequest(),
|
|
68
76
|
};
|
|
69
77
|
return crelteToRequest(nCrelte, req);
|
|
70
78
|
}
|
|
71
79
|
|
|
72
|
-
async function
|
|
80
|
+
async function eventsLoadEntry(cr: CrelteRequest): Promise<Entry | null> {
|
|
73
81
|
const listeners = cr.events.getListeners('loadEntry');
|
|
74
82
|
|
|
75
83
|
for (const loadEntry of listeners) {
|
|
@@ -123,7 +131,7 @@ export async function loadFn(
|
|
|
123
131
|
// checked to be empty before doing it
|
|
124
132
|
const entryProm = (async () => {
|
|
125
133
|
// first let's try to call the plugin loadEntry
|
|
126
|
-
let entry = await
|
|
134
|
+
let entry = await eventsLoadEntry(cr);
|
|
127
135
|
if (isCanceled()) return [];
|
|
128
136
|
|
|
129
137
|
// if no plugin provides an entry we load it from the app
|
|
@@ -152,7 +160,8 @@ export async function loadFn(
|
|
|
152
160
|
return [entry, template] as [Entry, TemplateModule];
|
|
153
161
|
})();
|
|
154
162
|
|
|
155
|
-
const
|
|
163
|
+
const eventsLoadGlobalData = cr.events.trigger('loadGlobalData', cr);
|
|
164
|
+
const pluginsLoadGlobalData = cr.plugins.z_loadGlobalData(cr);
|
|
156
165
|
|
|
157
166
|
// loading progress is at 20%
|
|
158
167
|
loadOpts?.setProgress(0.2);
|
|
@@ -160,6 +169,7 @@ export async function loadFn(
|
|
|
160
169
|
const loadGlobalDataProm = Promise.all([
|
|
161
170
|
globalProm,
|
|
162
171
|
entryProm,
|
|
172
|
+
...eventsLoadGlobalData,
|
|
163
173
|
...pluginsLoadGlobalData,
|
|
164
174
|
]);
|
|
165
175
|
|
|
@@ -167,7 +177,7 @@ export async function loadFn(
|
|
|
167
177
|
// we force resolve them to prevent deadlocks
|
|
168
178
|
if (
|
|
169
179
|
import.meta.env.DEV &&
|
|
170
|
-
!(await Promise.
|
|
180
|
+
!(await Promise.race([loadGlobalDataProm, timeout(2000)]))
|
|
171
181
|
) {
|
|
172
182
|
console.error(
|
|
173
183
|
'DEV: globals took longer than 2 seconds to load. ' +
|
|
@@ -184,8 +194,6 @@ export async function loadFn(
|
|
|
184
194
|
// loading progress is at 60%
|
|
185
195
|
loadOpts?.setProgress(0.6);
|
|
186
196
|
|
|
187
|
-
const pluginsLoadData = cr.events.trigger('loadData', cr, entry);
|
|
188
|
-
|
|
189
197
|
let loadDataProm = null;
|
|
190
198
|
if (template.loadData) {
|
|
191
199
|
loadDataProm = callLoadData(template.loadData, cr, entry);
|
|
@@ -196,9 +204,13 @@ export async function loadFn(
|
|
|
196
204
|
entryDataProm = callLoadData(app.loadEntryData, cr, entry);
|
|
197
205
|
}
|
|
198
206
|
|
|
207
|
+
const eventsLoadData = cr.events.trigger('loadData', cr, entry);
|
|
208
|
+
const pluginsLoadData = cr.plugins.z_loadData(cr);
|
|
209
|
+
|
|
199
210
|
const [templateData, entryData] = await Promise.all([
|
|
200
211
|
loadDataProm,
|
|
201
212
|
entryDataProm,
|
|
213
|
+
...eventsLoadData,
|
|
202
214
|
...pluginsLoadData,
|
|
203
215
|
]);
|
|
204
216
|
|
package/src/loadData/Globals.ts
CHANGED
|
@@ -131,7 +131,7 @@ export default class Globals {
|
|
|
131
131
|
* @hidden
|
|
132
132
|
* call this before starting the loadGlobalData phase
|
|
133
133
|
*/
|
|
134
|
-
z_toRequest() {
|
|
134
|
+
z_toRequest(): Globals {
|
|
135
135
|
const nGlobals = new Globals(this.stores);
|
|
136
136
|
nGlobals.waiters = new Map();
|
|
137
137
|
nGlobals.newData = new Map();
|
package/src/node/index.ts
CHANGED
|
@@ -166,7 +166,7 @@ export default async function createServer(serverMod: any, buildTime: string) {
|
|
|
166
166
|
} catch (e) {
|
|
167
167
|
basicError(res, e);
|
|
168
168
|
}
|
|
169
|
-
}).listen(8080);
|
|
169
|
+
}).listen(process.env.PORT ?? 8080);
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
function basicError(res: ServerResponse, err: any) {
|
package/src/plugins/Events.ts
CHANGED
|
@@ -32,6 +32,9 @@ export default class Events {
|
|
|
32
32
|
* Will be executed in preload as well.
|
|
33
33
|
*
|
|
34
34
|
* @returns a function to remove the listener
|
|
35
|
+
*
|
|
36
|
+
* #### afterRender
|
|
37
|
+
* Note this will also be executed when disableLoadData is true
|
|
35
38
|
*/
|
|
36
39
|
// override this function to add your own function signatures
|
|
37
40
|
on(
|
|
@@ -58,7 +61,14 @@ export default class Events {
|
|
|
58
61
|
ev: 'loadData',
|
|
59
62
|
fn: (cr: CrelteRequest, entry: Entry) => Promise<any> | any,
|
|
60
63
|
): () => void;
|
|
61
|
-
on(
|
|
64
|
+
on(
|
|
65
|
+
ev: 'beforeRender',
|
|
66
|
+
fn: (cr: CrelteRequest, route: Route) => void,
|
|
67
|
+
): () => void;
|
|
68
|
+
on(
|
|
69
|
+
ev: 'afterRender',
|
|
70
|
+
fn: (cr: CrelteRequest, route: Route) => void,
|
|
71
|
+
): () => void;
|
|
62
72
|
on(ev: string, fn: (...args: any[]) => any): () => void {
|
|
63
73
|
let set = this.inner.get(ev);
|
|
64
74
|
if (!set) {
|
|
@@ -108,6 +118,7 @@ export default class Events {
|
|
|
108
118
|
entry: Entry,
|
|
109
119
|
): (Promise<any> | any)[];
|
|
110
120
|
trigger(ev: 'beforeRender', cr: CrelteRequest, route: Route): void[];
|
|
121
|
+
trigger(ev: 'afterRender', cr: CrelteRequest, route: Route): void[];
|
|
111
122
|
trigger(ev: string, ...args: any[]): any[] {
|
|
112
123
|
const set = this.inner.get(ev);
|
|
113
124
|
if (!set) return [];
|
package/src/plugins/Plugins.ts
CHANGED
|
@@ -1,10 +1,32 @@
|
|
|
1
|
-
import { Crelte } from '../crelte.js';
|
|
1
|
+
import { Crelte, CrelteRequest } from '../crelte.js';
|
|
2
|
+
import { Request, Route } from '../routing/index.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* A plugin
|
|
5
6
|
*/
|
|
6
7
|
export interface Plugin {
|
|
7
8
|
name: string;
|
|
9
|
+
/**
|
|
10
|
+
* The returned value will be used inside of CrelteRequest
|
|
11
|
+
*/
|
|
12
|
+
toRequest?: (req: Request) => Plugin;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* This will be called during the loadGlobalData phase.
|
|
16
|
+
*/
|
|
17
|
+
loadGlobalData?: (cr: CrelteRequest) => Promise<void> | void;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* This will be called during the loadData phase.
|
|
21
|
+
*/
|
|
22
|
+
loadData?: (cr: CrelteRequest) => Promise<void> | void;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* This will be called before the dom gets updated.
|
|
26
|
+
*
|
|
27
|
+
* At this point you can update variables or stores.
|
|
28
|
+
*/
|
|
29
|
+
render?: (cr: CrelteRequest, route: Route) => void;
|
|
8
30
|
}
|
|
9
31
|
|
|
10
32
|
/**
|
|
@@ -46,4 +68,47 @@ export default class Plugins {
|
|
|
46
68
|
get(name: string): Plugin | null {
|
|
47
69
|
return this.plugins.get(name) ?? null;
|
|
48
70
|
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @hidden
|
|
74
|
+
*/
|
|
75
|
+
z_toRequest(req: Request): Plugins {
|
|
76
|
+
const nPlugins = new Plugins();
|
|
77
|
+
|
|
78
|
+
for (let plugin of this.plugins.values()) {
|
|
79
|
+
if (typeof plugin.toRequest === 'function')
|
|
80
|
+
plugin = plugin.toRequest(req);
|
|
81
|
+
|
|
82
|
+
nPlugins.add(plugin);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return nPlugins;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @hidden
|
|
90
|
+
*/
|
|
91
|
+
z_loadGlobalData(cr: CrelteRequest): (Promise<void> | void | undefined)[] {
|
|
92
|
+
return Array.from(this.plugins.values()).map(plugin =>
|
|
93
|
+
plugin.loadGlobalData?.(cr),
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @hidden
|
|
99
|
+
*/
|
|
100
|
+
z_loadData(cr: CrelteRequest): (Promise<void> | void | undefined)[] {
|
|
101
|
+
return Array.from(this.plugins.values()).map(plugin =>
|
|
102
|
+
plugin.loadData?.(cr),
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @hidden
|
|
108
|
+
*/
|
|
109
|
+
z_render(cr: CrelteRequest, route: Route): void {
|
|
110
|
+
for (const plugin of this.plugins.values()) {
|
|
111
|
+
plugin.render?.(cr, route);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
49
114
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Site from '../Site.js';
|
|
2
|
-
import { objClone } from '../../utils.js';
|
|
2
|
+
import { objClone, promiseThen } from '../../utils.js';
|
|
3
3
|
import BaseRoute, { RouteOrigin } from './BaseRoute.js';
|
|
4
4
|
import Route, { TemplateModule } from './Route.js';
|
|
5
5
|
import { Entry } from '../../loadData/index.js';
|
|
@@ -254,8 +254,15 @@ class RenderBarrier {
|
|
|
254
254
|
const action = this.inner.add();
|
|
255
255
|
|
|
256
256
|
return {
|
|
257
|
-
ready:
|
|
258
|
-
if (!this.inner.isOpen())
|
|
257
|
+
ready: () => {
|
|
258
|
+
if (!this.inner.isOpen())
|
|
259
|
+
return promiseThen(
|
|
260
|
+
// wait for action.ready
|
|
261
|
+
action.ready(null),
|
|
262
|
+
// then return if it was cancelled
|
|
263
|
+
() => this.cancelled,
|
|
264
|
+
);
|
|
265
|
+
|
|
259
266
|
return this.cancelled;
|
|
260
267
|
},
|
|
261
268
|
remove: () => {
|
|
@@ -292,7 +299,7 @@ export type DelayRender = {
|
|
|
292
299
|
*
|
|
293
300
|
* @returns if the render was cancelled
|
|
294
301
|
*/
|
|
295
|
-
ready: () => Promise<boolean
|
|
302
|
+
ready: () => Promise<boolean> | boolean;
|
|
296
303
|
|
|
297
304
|
/**
|
|
298
305
|
* If youre not interested when the render happens anymore
|
|
@@ -107,7 +107,7 @@ export default class ClientRouter extends BaseRouter {
|
|
|
107
107
|
async pushRequest(req: Request, _opts: RequestOptions = {}) {
|
|
108
108
|
const url = req.url;
|
|
109
109
|
|
|
110
|
-
return
|
|
110
|
+
return this.handleRequest(req, route => {
|
|
111
111
|
window.history.pushState(
|
|
112
112
|
route.z_toState(),
|
|
113
113
|
'',
|
|
@@ -119,18 +119,13 @@ export default class ClientRouter extends BaseRouter {
|
|
|
119
119
|
async replaceRequest(req: Request, _opts: RequestOptions = {}) {
|
|
120
120
|
const url = req.url;
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
});
|
|
130
|
-
} catch (e) {
|
|
131
|
-
console.warn('replacing route failed', e);
|
|
132
|
-
throw e;
|
|
133
|
-
}
|
|
122
|
+
return this.handleRequest(req, () => {
|
|
123
|
+
window.history.replaceState(
|
|
124
|
+
req.z_toState(),
|
|
125
|
+
'',
|
|
126
|
+
url.pathname + url.search + url.hash,
|
|
127
|
+
);
|
|
128
|
+
});
|
|
134
129
|
}
|
|
135
130
|
|
|
136
131
|
back(): void {
|
|
@@ -164,6 +159,7 @@ export default class ClientRouter extends BaseRouter {
|
|
|
164
159
|
const req = this.targetToRequest(link.href, {
|
|
165
160
|
origin: 'click',
|
|
166
161
|
context: { ...link.dataset },
|
|
162
|
+
disableScroll: attributeToBool(link, 'data-disable-scroll'),
|
|
167
163
|
});
|
|
168
164
|
const currRoute = this.route.get();
|
|
169
165
|
const routeEq =
|
|
@@ -189,7 +185,9 @@ export default class ClientRouter extends BaseRouter {
|
|
|
189
185
|
|
|
190
186
|
if (
|
|
191
187
|
link &&
|
|
192
|
-
|
|
188
|
+
// todo remove data-no-preload
|
|
189
|
+
!attributeToBool(link, 'data-no-preload') &&
|
|
190
|
+
!attributeToBool(link, 'data-disable-preload') &&
|
|
193
191
|
link.href
|
|
194
192
|
) {
|
|
195
193
|
this.preload(link.href);
|
|
@@ -311,3 +309,14 @@ export default class ClientRouter extends BaseRouter {
|
|
|
311
309
|
}
|
|
312
310
|
}
|
|
313
311
|
}
|
|
312
|
+
|
|
313
|
+
function attributeToBool(el: HTMLElement, attr: string): boolean {
|
|
314
|
+
switch (el.getAttribute(attr)) {
|
|
315
|
+
case '':
|
|
316
|
+
case 'true':
|
|
317
|
+
return true;
|
|
318
|
+
case 'false':
|
|
319
|
+
default:
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
@@ -226,19 +226,18 @@ export default class Router {
|
|
|
226
226
|
});
|
|
227
227
|
if (!req) return;
|
|
228
228
|
|
|
229
|
-
|
|
230
|
-
return await this.inner.pushRequest(req, opts);
|
|
231
|
-
} catch (e) {
|
|
229
|
+
return this.inner.pushRequest(req, opts).catch(e => {
|
|
232
230
|
console.warn('pushing route failed', e);
|
|
233
231
|
throw e;
|
|
234
|
-
}
|
|
232
|
+
});
|
|
235
233
|
}
|
|
236
234
|
|
|
237
235
|
/**
|
|
238
236
|
* @deprecated use push instead
|
|
239
237
|
*/
|
|
240
238
|
pushState(route: Route | Request) {
|
|
241
|
-
|
|
239
|
+
if (import.meta.env.DEV)
|
|
240
|
+
console.warn('pushState is deprecated, use push instead');
|
|
242
241
|
this.push(route);
|
|
243
242
|
}
|
|
244
243
|
|
|
@@ -287,19 +286,18 @@ export default class Router {
|
|
|
287
286
|
});
|
|
288
287
|
if (!req) return;
|
|
289
288
|
|
|
290
|
-
|
|
291
|
-
return await this.inner.replaceRequest(req, opts);
|
|
292
|
-
} catch (e) {
|
|
289
|
+
return this.inner.replaceRequest(req, opts).catch(e => {
|
|
293
290
|
console.warn('replacing route failed', e);
|
|
294
291
|
throw e;
|
|
295
|
-
}
|
|
292
|
+
});
|
|
296
293
|
}
|
|
297
294
|
|
|
298
295
|
/**
|
|
299
296
|
* @deprecated use replace instead
|
|
300
297
|
*/
|
|
301
298
|
replaceState(route: Route | Request) {
|
|
302
|
-
|
|
299
|
+
if (import.meta.env.DEV)
|
|
300
|
+
console.warn('replaceState is deprecated, use replace instead');
|
|
303
301
|
this.replace(route);
|
|
304
302
|
}
|
|
305
303
|
|
|
@@ -24,6 +24,7 @@ export default class CrelteServerRequest {
|
|
|
24
24
|
private _sites: Site[];
|
|
25
25
|
private _langs: string[];
|
|
26
26
|
private _queries: Queries;
|
|
27
|
+
private _scookies: ServerCookies;
|
|
27
28
|
private _cookies: Cookies;
|
|
28
29
|
|
|
29
30
|
constructor(req: ServerRequest, opts: CrelteServerRequestOptions) {
|
|
@@ -37,7 +38,8 @@ export default class CrelteServerRequest {
|
|
|
37
38
|
this._queries = opts.queries.z_toRequest(
|
|
38
39
|
new Request(new URL(req.url), req.site),
|
|
39
40
|
);
|
|
40
|
-
this.
|
|
41
|
+
this._scookies = new ServerCookies(req.headers);
|
|
42
|
+
this._cookies = new Cookies(this._scookies);
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
/**
|
|
@@ -145,6 +147,6 @@ export default class CrelteServerRequest {
|
|
|
145
147
|
|
|
146
148
|
/** @hidden */
|
|
147
149
|
z_finishResponse(resp: Response) {
|
|
148
|
-
|
|
150
|
+
this._scookies._populateHeaders(resp.headers);
|
|
149
151
|
}
|
|
150
152
|
}
|