crelte 0.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.
- package/LICENSE.md +41 -0
- package/dist/Crelte.d.ts +55 -0
- package/dist/Crelte.d.ts.map +1 -0
- package/dist/Crelte.js +106 -0
- package/dist/CrelteBase.d.ts +16 -0
- package/dist/CrelteBase.d.ts.map +1 -0
- package/dist/CrelteBase.js +1 -0
- package/dist/CrelteRouted.d.ts +50 -0
- package/dist/CrelteRouted.d.ts.map +1 -0
- package/dist/CrelteRouted.js +88 -0
- package/dist/blocks/Blocks.d.ts +35 -0
- package/dist/blocks/Blocks.d.ts.map +1 -0
- package/dist/blocks/Blocks.js +100 -0
- package/dist/blocks/Blocks.svelte +21 -0
- package/dist/blocks/Blocks.svelte.d.ts +24 -0
- package/dist/blocks/Blocks.svelte.d.ts.map +1 -0
- package/dist/blocks/index.d.ts +5 -0
- package/dist/blocks/index.d.ts.map +1 -0
- package/dist/blocks/index.js +3 -0
- package/dist/cookies/ClientCookies.d.ts +9 -0
- package/dist/cookies/ClientCookies.d.ts.map +1 -0
- package/dist/cookies/ClientCookies.js +22 -0
- package/dist/cookies/ServerCookies.d.ts +13 -0
- package/dist/cookies/ServerCookies.d.ts.map +1 -0
- package/dist/cookies/ServerCookies.js +31 -0
- package/dist/cookies/index.d.ts +20 -0
- package/dist/cookies/index.d.ts.map +1 -0
- package/dist/cookies/index.js +1 -0
- package/dist/cookies/utils.d.ts +12 -0
- package/dist/cookies/utils.d.ts.map +1 -0
- package/dist/cookies/utils.js +32 -0
- package/dist/graphql/GraphQl.d.ts +60 -0
- package/dist/graphql/GraphQl.d.ts.map +1 -0
- package/dist/graphql/GraphQl.js +197 -0
- package/dist/graphql/gql.test.d.ts +2 -0
- package/dist/graphql/gql.test.d.ts.map +1 -0
- package/dist/graphql/gql.test.js +80 -0
- package/dist/graphql/index.d.ts +3 -0
- package/dist/graphql/index.d.ts.map +1 -0
- package/dist/graphql/index.js +2 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +83 -0
- package/dist/init/client.d.ts +13 -0
- package/dist/init/client.d.ts.map +1 -0
- package/dist/init/client.js +129 -0
- package/dist/init/server.d.ts +38 -0
- package/dist/init/server.d.ts.map +1 -0
- package/dist/init/server.js +95 -0
- package/dist/init/shared.d.ts +29 -0
- package/dist/init/shared.d.ts.map +1 -0
- package/dist/init/shared.js +154 -0
- package/dist/loadData/Globals.d.ts +33 -0
- package/dist/loadData/Globals.d.ts.map +1 -0
- package/dist/loadData/Globals.js +119 -0
- package/dist/loadData/index.d.ts +25 -0
- package/dist/loadData/index.d.ts.map +1 -0
- package/dist/loadData/index.js +39 -0
- package/dist/plugins/Events.d.ts +11 -0
- package/dist/plugins/Events.d.ts.map +1 -0
- package/dist/plugins/Events.js +29 -0
- package/dist/plugins/Plugins.d.ts +12 -0
- package/dist/plugins/Plugins.d.ts.map +1 -0
- package/dist/plugins/Plugins.js +12 -0
- package/dist/plugins/index.d.ts +5 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +2 -0
- package/dist/routing/History.d.ts +22 -0
- package/dist/routing/History.d.ts.map +1 -0
- package/dist/routing/History.js +36 -0
- package/dist/routing/InnerRouter.d.ts +111 -0
- package/dist/routing/InnerRouter.d.ts.map +1 -0
- package/dist/routing/InnerRouter.js +397 -0
- package/dist/routing/PageLoader.d.ts +37 -0
- package/dist/routing/PageLoader.d.ts.map +1 -0
- package/dist/routing/PageLoader.js +72 -0
- package/dist/routing/Route.d.ts +82 -0
- package/dist/routing/Route.d.ts.map +1 -0
- package/dist/routing/Route.js +134 -0
- package/dist/routing/Router.d.ts +162 -0
- package/dist/routing/Router.d.ts.map +1 -0
- package/dist/routing/Router.js +333 -0
- package/dist/routing/Site.d.ts +47 -0
- package/dist/routing/Site.d.ts.map +1 -0
- package/dist/routing/Site.js +48 -0
- package/dist/routing/index.d.ts +5 -0
- package/dist/routing/index.d.ts.map +1 -0
- package/dist/routing/index.js +4 -0
- package/dist/ssr/SsrCache.d.ts +12 -0
- package/dist/ssr/SsrCache.d.ts.map +1 -0
- package/dist/ssr/SsrCache.js +50 -0
- package/dist/ssr/SsrComponents.d.ts +7 -0
- package/dist/ssr/SsrComponents.d.ts.map +1 -0
- package/dist/ssr/SsrComponents.js +30 -0
- package/dist/ssr/index.d.ts +4 -0
- package/dist/ssr/index.d.ts.map +1 -0
- package/dist/ssr/index.js +3 -0
- package/package.json +79 -0
- package/src/Crelte.ts +135 -0
- package/src/CrelteBase.ts +24 -0
- package/src/CrelteRouted.ts +128 -0
- package/src/blocks/Blocks.svelte +68 -0
- package/src/blocks/Blocks.ts +155 -0
- package/src/blocks/index.ts +14 -0
- package/src/cookies/ClientCookies.ts +30 -0
- package/src/cookies/ServerCookies.ts +42 -0
- package/src/cookies/index.ts +24 -0
- package/src/cookies/utils.ts +53 -0
- package/src/graphql/GraphQl.ts +281 -0
- package/src/graphql/gql.test.ts +123 -0
- package/src/graphql/index.ts +8 -0
- package/src/index.ts +109 -0
- package/src/init/client.ts +190 -0
- package/src/init/server.ts +177 -0
- package/src/init/shared.ts +221 -0
- package/src/loadData/Globals.ts +150 -0
- package/src/loadData/index.ts +67 -0
- package/src/plugins/Events.ts +50 -0
- package/src/plugins/Plugins.ts +23 -0
- package/src/plugins/index.ts +5 -0
- package/src/routing/History.ts +52 -0
- package/src/routing/InnerRouter.ts +469 -0
- package/src/routing/PageLoader.ts +112 -0
- package/src/routing/Route.ts +184 -0
- package/src/routing/Router.ts +476 -0
- package/src/routing/Site.ts +65 -0
- package/src/routing/index.ts +5 -0
- package/src/ssr/SsrCache.ts +61 -0
- package/src/ssr/SsrComponents.ts +34 -0
- package/src/ssr/index.ts +4 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { CrelteBuilder } from '../Crelte.js';
|
|
2
|
+
import { loadFn, pluginsBeforeRender, setupPlugins } from './shared.js';
|
|
3
|
+
import { tick } from 'svelte';
|
|
4
|
+
const mainDataDefault = {
|
|
5
|
+
preloadOnMouseOver: false,
|
|
6
|
+
viewTransition: false,
|
|
7
|
+
playIntro: false,
|
|
8
|
+
// will be passed down to ClientRenderer
|
|
9
|
+
graphQlDebug: false,
|
|
10
|
+
debugTiming: false,
|
|
11
|
+
};
|
|
12
|
+
export function main(data) {
|
|
13
|
+
data = { ...mainDataDefault, ...data };
|
|
14
|
+
// rendering steps
|
|
15
|
+
// loadSites (first time)
|
|
16
|
+
// determine route (if site is empty on server redirect to correct language)
|
|
17
|
+
// loadData, entry (make globally available), pluginsData
|
|
18
|
+
// loadTemplate
|
|
19
|
+
// render
|
|
20
|
+
// on route change
|
|
21
|
+
// determine route
|
|
22
|
+
// entry, pluginsData
|
|
23
|
+
// loadTemplate
|
|
24
|
+
// update
|
|
25
|
+
// construct Crelte
|
|
26
|
+
const builder = new CrelteBuilder();
|
|
27
|
+
const endpoint = builder.ssrCache.get('ENDPOINT_URL');
|
|
28
|
+
builder.setupGraphQl(endpoint, {
|
|
29
|
+
debug: data.graphQlDebug,
|
|
30
|
+
debugTiming: data.debugTiming,
|
|
31
|
+
});
|
|
32
|
+
// on the client the cookies are always comming from document.cookie
|
|
33
|
+
builder.setupCookies('');
|
|
34
|
+
const csites = builder.ssrCache.get('crelteSites');
|
|
35
|
+
builder.setupRouter(csites, {
|
|
36
|
+
preloadOnMouseOver: data.preloadOnMouseOver,
|
|
37
|
+
});
|
|
38
|
+
const crelte = builder.build();
|
|
39
|
+
const serverError = crelte.ssrCache.get('ERROR');
|
|
40
|
+
if (serverError) {
|
|
41
|
+
// should this be called??
|
|
42
|
+
crelte.router._internal.initClient();
|
|
43
|
+
new data.errorPage.default({
|
|
44
|
+
target: document.body,
|
|
45
|
+
props: { ...serverError },
|
|
46
|
+
hydrate: true,
|
|
47
|
+
context: crelte._getContext(),
|
|
48
|
+
});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// setup plugins
|
|
52
|
+
setupPlugins(crelte, data.app.plugins ?? []);
|
|
53
|
+
// setup load Data
|
|
54
|
+
crelte.router._internal.onLoad = (route, site, opts) => {
|
|
55
|
+
const cr = crelte.toRouted(route, site);
|
|
56
|
+
return loadFn(cr, data.app, data.entryQuery, data.globalQuery, opts);
|
|
57
|
+
};
|
|
58
|
+
// render Space
|
|
59
|
+
let appInstance;
|
|
60
|
+
const updateAppProps = (props) => {
|
|
61
|
+
if (!appInstance) {
|
|
62
|
+
appInstance = new data.app.default({
|
|
63
|
+
target: document.body,
|
|
64
|
+
props,
|
|
65
|
+
hydrate: true,
|
|
66
|
+
context: crelte._getContext(),
|
|
67
|
+
intro: data.playIntro,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
appInstance.$set(props);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
let firstLoad = true;
|
|
75
|
+
crelte.router._internal.onLoaded = async (success, route, site, readyForProps) => {
|
|
76
|
+
const isFirstLoad = firstLoad;
|
|
77
|
+
firstLoad = false;
|
|
78
|
+
if (!success) {
|
|
79
|
+
// if this is not the first load we should reload the page
|
|
80
|
+
// we don't reload everytime because this might cause a reload loop
|
|
81
|
+
// and since the first load will probably just contain ssrCache data in almost all cases the first load will never faill
|
|
82
|
+
if (!isFirstLoad) {
|
|
83
|
+
// the load might contain a js error and we prefer the error
|
|
84
|
+
// page
|
|
85
|
+
window.location.reload();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
return handleLoadError(readyForProps());
|
|
89
|
+
}
|
|
90
|
+
const cr = crelte.toRouted(route, site);
|
|
91
|
+
const startTime = data.debugTiming ? Date.now() : null;
|
|
92
|
+
let render = async () => {
|
|
93
|
+
// we should trigger the route update here
|
|
94
|
+
pluginsBeforeRender(cr);
|
|
95
|
+
crelte.globals._updateSiteId(site.id);
|
|
96
|
+
updateAppProps(readyForProps());
|
|
97
|
+
await tick();
|
|
98
|
+
if (startTime) {
|
|
99
|
+
console.log('dom update took ' + (Date.now() - startTime) + 'ms');
|
|
100
|
+
}
|
|
101
|
+
crelte.router._internal.domReady(route);
|
|
102
|
+
};
|
|
103
|
+
// render with view Transition if enabled and not in hydration
|
|
104
|
+
if (data.viewTransition &&
|
|
105
|
+
appInstance &&
|
|
106
|
+
document.startViewTransition) {
|
|
107
|
+
render = () => document.startViewTransition(render);
|
|
108
|
+
}
|
|
109
|
+
await render();
|
|
110
|
+
};
|
|
111
|
+
crelte.router._internal.initClient();
|
|
112
|
+
}
|
|
113
|
+
function handleLoadError(e) {
|
|
114
|
+
console.log('loading or rendering the page failed with the error:');
|
|
115
|
+
console.error(e);
|
|
116
|
+
// Detect the browser language
|
|
117
|
+
// @ts-ignore
|
|
118
|
+
const userLang = navigator.language || navigator.userLanguage;
|
|
119
|
+
// Messages in different languages
|
|
120
|
+
const messages = {
|
|
121
|
+
en: 'An error has occurred. Please reload the page or try again later.',
|
|
122
|
+
de: 'Leider ist ein Fehler aufgetreten. Laden Sie die Seite neu, oder versuchen Sie es später noch mal.',
|
|
123
|
+
fr: 'Une erreur s’est produite. Veuillez recharger la page ou réessayer plus tard.',
|
|
124
|
+
it: 'Si è verificato un errore. Ricarica la pagina o riprova più tardi.',
|
|
125
|
+
nl: 'Er is een fout opgetreden. Herlaad de pagina of probeer het later opnieuw.',
|
|
126
|
+
};
|
|
127
|
+
const message = messages[userLang.split('-')[0]] ?? messages.en;
|
|
128
|
+
alert(message);
|
|
129
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type ServerData = {
|
|
2
|
+
url: string;
|
|
3
|
+
htmlTemplate: string;
|
|
4
|
+
ssrManifest: Record<string, string[]>;
|
|
5
|
+
acceptLang?: string;
|
|
6
|
+
endpoint: string;
|
|
7
|
+
craftWeb: string;
|
|
8
|
+
viteEnv: Map<string, string>;
|
|
9
|
+
cookies?: string;
|
|
10
|
+
};
|
|
11
|
+
export type MainData = {
|
|
12
|
+
app: any;
|
|
13
|
+
entryQuery: any;
|
|
14
|
+
globalQuery?: any;
|
|
15
|
+
serverData: ServerData;
|
|
16
|
+
graphQlDebug?: boolean;
|
|
17
|
+
debugTiming?: boolean;
|
|
18
|
+
};
|
|
19
|
+
export declare function main(data: MainData): Promise<{
|
|
20
|
+
status: number;
|
|
21
|
+
location?: string;
|
|
22
|
+
html?: string;
|
|
23
|
+
setCookies?: string[];
|
|
24
|
+
}>;
|
|
25
|
+
export type Error = {
|
|
26
|
+
status: number;
|
|
27
|
+
message: any;
|
|
28
|
+
};
|
|
29
|
+
export type MainErrorData = {
|
|
30
|
+
error: Error;
|
|
31
|
+
errorPage: any;
|
|
32
|
+
serverData: ServerData;
|
|
33
|
+
};
|
|
34
|
+
export declare function mainError(data: MainErrorData): Promise<{
|
|
35
|
+
status: number;
|
|
36
|
+
html?: string;
|
|
37
|
+
}>;
|
|
38
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../src/init/server.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,UAAU,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IAEtB,GAAG,EAAE,GAAG,CAAC;IACT,UAAU,EAAE,GAAG,CAAC;IAChB,WAAW,CAAC,EAAE,GAAG,CAAC;IAElB,UAAU,EAAE,UAAU,CAAC;IAGvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,wBAAsB,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC,CA4ED;AAED,MAAM,MAAM,KAAK,GAAG;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,GAAG,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAE3B,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,GAAG,CAAC;IAEf,UAAU,EAAE,UAAU,CAAC;CACvB,CAAC;AAEF,wBAAsB,SAAS,CAC9B,IAAI,EAAE,aAAa,GACjB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA0B5C"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { CrelteBuilder } from '../Crelte.js';
|
|
2
|
+
import { loadFn, pluginsBeforeRender, setupPlugins } from './shared.js';
|
|
3
|
+
import SsrComponents from '../ssr/SsrComponents.js';
|
|
4
|
+
import SsrCache from '../ssr/SsrCache.js';
|
|
5
|
+
export async function main(data) {
|
|
6
|
+
const builder = new CrelteBuilder();
|
|
7
|
+
// setup viteEnv
|
|
8
|
+
data.serverData.viteEnv.forEach((v, k) => {
|
|
9
|
+
builder.ssrCache.set(k, v);
|
|
10
|
+
});
|
|
11
|
+
const endpoint = data.serverData.endpoint;
|
|
12
|
+
builder.ssrCache.set('ENDPOINT_URL', endpoint);
|
|
13
|
+
builder.ssrCache.set('CRAFT_WEB_URL', data.serverData.craftWeb);
|
|
14
|
+
builder.setupGraphQl(endpoint, {
|
|
15
|
+
debug: data.graphQlDebug,
|
|
16
|
+
debugTiming: data.debugTiming,
|
|
17
|
+
});
|
|
18
|
+
const cookies = data.serverData.cookies ?? '';
|
|
19
|
+
builder.setupCookies(cookies);
|
|
20
|
+
const csites = await loadSites(builder);
|
|
21
|
+
builder.ssrCache.set('crelteSites', csites);
|
|
22
|
+
builder.setupRouter(csites);
|
|
23
|
+
const crelte = builder.build();
|
|
24
|
+
// setup plugins
|
|
25
|
+
setupPlugins(crelte, data.app.plugins ?? []);
|
|
26
|
+
// setup load Data
|
|
27
|
+
crelte.router._internal.onLoad = (route, site) => {
|
|
28
|
+
const cr = crelte.toRouted(route, site);
|
|
29
|
+
return loadFn(cr, data.app, data.entryQuery, data.globalQuery);
|
|
30
|
+
};
|
|
31
|
+
const { success, redirect, route, site, props } = await crelte.router._internal.initServer(data.serverData.url, data.serverData.acceptLang);
|
|
32
|
+
if (!success)
|
|
33
|
+
throw props;
|
|
34
|
+
if (redirect) {
|
|
35
|
+
return {
|
|
36
|
+
status: 302,
|
|
37
|
+
location: route.url.toString(),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const context = crelte._getContext();
|
|
41
|
+
const ssrComponents = new SsrComponents();
|
|
42
|
+
ssrComponents.addToContext(context);
|
|
43
|
+
pluginsBeforeRender(crelte.toRouted(route, site));
|
|
44
|
+
crelte.globals._updateSiteId(site.id);
|
|
45
|
+
// eslint-disable-next-line prefer-const
|
|
46
|
+
let { html, head } = data.app.default.render(props, { context });
|
|
47
|
+
head += ssrComponents.toHead(data.serverData.ssrManifest);
|
|
48
|
+
head += crelte.ssrCache._exportToHead();
|
|
49
|
+
let htmlTemplate = data.serverData.htmlTemplate;
|
|
50
|
+
htmlTemplate = htmlTemplate.replace('<!--page-lang-->', site.language);
|
|
51
|
+
const finalHtml = htmlTemplate
|
|
52
|
+
.replace('</head>', head + '\n\t</head>')
|
|
53
|
+
.replace('<!--ssr-body-->', html);
|
|
54
|
+
const entry = props.entry;
|
|
55
|
+
return {
|
|
56
|
+
status: entry.sectionHandle === 'error' ? parseInt(entry.typeHandle) : 200,
|
|
57
|
+
html: finalHtml,
|
|
58
|
+
setCookies: crelte.cookies._getSetCookiesHeaders(),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export async function mainError(data) {
|
|
62
|
+
const ssrCache = new SsrCache();
|
|
63
|
+
const context = new Map();
|
|
64
|
+
const ssrComponents = new SsrComponents();
|
|
65
|
+
ssrComponents.addToContext(context);
|
|
66
|
+
ssrCache.set('ERROR', data.error);
|
|
67
|
+
// eslint-disable-next-line prefer-const
|
|
68
|
+
let { html, head } = data.errorPage.default.render(data.error, { context });
|
|
69
|
+
head += ssrComponents.toHead(data.serverData.ssrManifest);
|
|
70
|
+
head += ssrCache._exportToHead();
|
|
71
|
+
let htmlTemplate = data.serverData.htmlTemplate;
|
|
72
|
+
htmlTemplate = htmlTemplate.replace('<!--page-lang-->', 'de');
|
|
73
|
+
const finalHtml = htmlTemplate
|
|
74
|
+
.replace('<!--ssr-head-->', head)
|
|
75
|
+
.replace('<!--ssr-body-->', html);
|
|
76
|
+
return {
|
|
77
|
+
status: data.error.status,
|
|
78
|
+
html: finalHtml,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// requires, GraphQl, SsrCache
|
|
82
|
+
async function loadSites(builder) {
|
|
83
|
+
if (!builder.graphQl)
|
|
84
|
+
throw new Error();
|
|
85
|
+
if ('CRAFT_SITES_CACHED' in globalThis) {
|
|
86
|
+
// @ts-ignore
|
|
87
|
+
return globalThis['CRAFT_SITES_CACHED'];
|
|
88
|
+
}
|
|
89
|
+
const resp = (await builder.graphQl.request('query { crelteSites { id baseUrl language name handle primary } }', {},
|
|
90
|
+
// don't cache since we cache ourself
|
|
91
|
+
{ caching: false }));
|
|
92
|
+
// @ts-ignore
|
|
93
|
+
globalThis['CRAFT_SITES_CACHED'] = resp.crelteSites;
|
|
94
|
+
return resp.crelteSites;
|
|
95
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import CrelteRouted, { GraphQlQuery } from '../CrelteRouted.js';
|
|
2
|
+
import Crelte from '../Crelte.js';
|
|
3
|
+
import { LoadData } from '../loadData/index.js';
|
|
4
|
+
import { PluginCreator } from '../plugins/Plugins.js';
|
|
5
|
+
import { LoadOptions } from '../routing/PageLoader.js';
|
|
6
|
+
interface App<D, E, T> {
|
|
7
|
+
loadGlobalData?: LoadData<D>;
|
|
8
|
+
loadEntryData?: LoadData<any>;
|
|
9
|
+
templates?: Record<string, LazyTemplateModule<E, T>>;
|
|
10
|
+
}
|
|
11
|
+
interface TemplateModule<E, T> {
|
|
12
|
+
default: any;
|
|
13
|
+
loadData?(cr: CrelteRouted, entry: E): Promise<T>;
|
|
14
|
+
}
|
|
15
|
+
type LazyTemplateModule<E, T> = (() => Promise<TemplateModule<E, T>>) | TemplateModule<E, T>;
|
|
16
|
+
export declare function setupPlugins(crelte: Crelte, plugins: PluginCreator[]): void;
|
|
17
|
+
export declare function pluginsBeforeRender(cr: CrelteRouted): void;
|
|
18
|
+
/**
|
|
19
|
+
* Get the entry from the page
|
|
20
|
+
*
|
|
21
|
+
* entries should export sectionHandle and typeHandle
|
|
22
|
+
*
|
|
23
|
+
* products should alias productTypeHandle with typeHandle,
|
|
24
|
+
* sectionHandle will be automatically set to product
|
|
25
|
+
*/
|
|
26
|
+
export declare function getEntry(page: any): any;
|
|
27
|
+
export declare function loadFn<D, E, T>(cr: CrelteRouted, app: App<D, E, T>, entryQuery: GraphQlQuery, globalQuery?: GraphQlQuery, loadOpts?: LoadOptions): Promise<any>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../../src/init/shared.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,EAAE,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAgB,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,UAAU,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACpB,cAAc,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAG7B,aAAa,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;IAE9B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;CACrD;AAED,UAAU,cAAc,CAAC,CAAC,EAAE,CAAC;IAE5B,OAAO,EAAE,GAAG,CAAC;IAEb,QAAQ,CAAC,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAClD;AAED,KAAK,kBAAkB,CAAC,CAAC,EAAE,CAAC,IACzB,CAAC,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GACrC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAExB,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,QAKpE;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAE1D;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,CAYvC;AAED,wBAAsB,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACnC,EAAE,EAAE,YAAY,EAChB,GAAG,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACjB,UAAU,EAAE,YAAY,EACxB,WAAW,CAAC,EAAE,YAAY,EAC1B,QAAQ,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,GAAG,CAAC,CAsGd"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { callLoadData } from '../loadData/index.js';
|
|
2
|
+
export function setupPlugins(crelte, plugins) {
|
|
3
|
+
for (const plugin of plugins) {
|
|
4
|
+
const p = plugin(crelte);
|
|
5
|
+
crelte.plugins.add(p);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export function pluginsBeforeRender(cr) {
|
|
9
|
+
cr.events.trigger('beforeRender', cr);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Get the entry from the page
|
|
13
|
+
*
|
|
14
|
+
* entries should export sectionHandle and typeHandle
|
|
15
|
+
*
|
|
16
|
+
* products should alias productTypeHandle with typeHandle,
|
|
17
|
+
* sectionHandle will be automatically set to product
|
|
18
|
+
*/
|
|
19
|
+
export function getEntry(page) {
|
|
20
|
+
if (page?.entry)
|
|
21
|
+
return { ...page.entry };
|
|
22
|
+
if (page?.product)
|
|
23
|
+
return {
|
|
24
|
+
sectionHandle: 'product',
|
|
25
|
+
...page.product,
|
|
26
|
+
};
|
|
27
|
+
return {
|
|
28
|
+
sectionHandle: 'error',
|
|
29
|
+
typeHandle: '404',
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export async function loadFn(cr, app, entryQuery, globalQuery, loadOpts) {
|
|
33
|
+
let dataProm = null;
|
|
34
|
+
// @ts-ignore
|
|
35
|
+
if (app.loadData) {
|
|
36
|
+
throw new Error('loadData is ambigous, choose loadGlobalData or ' +
|
|
37
|
+
'loadEntryData depending on if you need access to entry or not?');
|
|
38
|
+
}
|
|
39
|
+
if (app.loadGlobalData) {
|
|
40
|
+
dataProm = callLoadData(app.loadGlobalData, cr);
|
|
41
|
+
}
|
|
42
|
+
let globalProm = null;
|
|
43
|
+
if (globalQuery && !cr.globals._wasLoaded()) {
|
|
44
|
+
globalProm = (async () => {
|
|
45
|
+
const res = await cr.query(globalQuery);
|
|
46
|
+
// we need to do this sorcery here and can't wait until all
|
|
47
|
+
// globals functions are done, because some global function
|
|
48
|
+
// might want to use globals, and for that the function
|
|
49
|
+
// getOrWait exists on Globals
|
|
50
|
+
cr.globals._setData(cr.site.id, res);
|
|
51
|
+
return res;
|
|
52
|
+
})();
|
|
53
|
+
}
|
|
54
|
+
let pageProm = null;
|
|
55
|
+
if (cr.route.site) {
|
|
56
|
+
let uri = decodeURI(cr.route.uri);
|
|
57
|
+
if (uri.startsWith('/'))
|
|
58
|
+
uri = uri.substring(1);
|
|
59
|
+
if (uri === '' || uri === '/')
|
|
60
|
+
uri = '__home__';
|
|
61
|
+
pageProm = cr.query(entryQuery, {
|
|
62
|
+
uri,
|
|
63
|
+
siteId: cr.route.site.id,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const pluginsLoadGlobalData = cr.events.trigger('loadGlobalData', cr);
|
|
67
|
+
// loading progress is at 20%
|
|
68
|
+
loadOpts?.setProgress(0.2);
|
|
69
|
+
const [data, global, page] = await Promise.all([
|
|
70
|
+
dataProm,
|
|
71
|
+
globalProm,
|
|
72
|
+
pageProm,
|
|
73
|
+
...pluginsLoadGlobalData,
|
|
74
|
+
]);
|
|
75
|
+
if (global) {
|
|
76
|
+
cr.globals._setData(cr.site.id, global);
|
|
77
|
+
}
|
|
78
|
+
else if (!cr.globals._wasLoaded()) {
|
|
79
|
+
// we need to set the global data to an empty object
|
|
80
|
+
// so any waiters get's triggered
|
|
81
|
+
cr.globals._setData(cr.site.id, {});
|
|
82
|
+
}
|
|
83
|
+
// allow cr to get the global data
|
|
84
|
+
cr._globalDataLoaded();
|
|
85
|
+
const entry = getEntry(page);
|
|
86
|
+
let template;
|
|
87
|
+
if (app.templates) {
|
|
88
|
+
template = await loadTemplate(app.templates, entry);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
throw new Error('App must have templates or loadTemplate method');
|
|
92
|
+
}
|
|
93
|
+
// loading progress is at 60%
|
|
94
|
+
loadOpts?.setProgress(0.6);
|
|
95
|
+
const pluginsLoadData = cr.events.trigger('loadData', cr, entry);
|
|
96
|
+
let loadDataProm = null;
|
|
97
|
+
if (template.loadData) {
|
|
98
|
+
loadDataProm = callLoadData(template.loadData, cr, entry);
|
|
99
|
+
}
|
|
100
|
+
let entryDataProm = null;
|
|
101
|
+
if (app.loadEntryData) {
|
|
102
|
+
entryDataProm = callLoadData(app.loadEntryData, cr, entry);
|
|
103
|
+
}
|
|
104
|
+
const [templateData, entryData] = await Promise.all([
|
|
105
|
+
loadDataProm,
|
|
106
|
+
entryDataProm,
|
|
107
|
+
...pluginsLoadData,
|
|
108
|
+
]);
|
|
109
|
+
// loading progress is at 100%
|
|
110
|
+
loadOpts?.setProgress(1);
|
|
111
|
+
return {
|
|
112
|
+
...data,
|
|
113
|
+
...entryData,
|
|
114
|
+
entry,
|
|
115
|
+
template: template.default,
|
|
116
|
+
templateData: templateData,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function parseFilename(path) {
|
|
120
|
+
// get filename with extension
|
|
121
|
+
const slash = path.lastIndexOf('/');
|
|
122
|
+
const filename = path.substring(slash + 1);
|
|
123
|
+
const extPos = filename.lastIndexOf('.');
|
|
124
|
+
const name = filename.substring(0, extPos);
|
|
125
|
+
const ext = filename.substring(extPos + 1);
|
|
126
|
+
return [name, ext];
|
|
127
|
+
}
|
|
128
|
+
async function loadTemplate(rawModules, entry) {
|
|
129
|
+
// parse modules
|
|
130
|
+
const modules = new Map(Object.entries(rawModules)
|
|
131
|
+
.map(([path, mod]) => {
|
|
132
|
+
const [name, _ext] = parseFilename(path);
|
|
133
|
+
return [name, mod];
|
|
134
|
+
})
|
|
135
|
+
.filter(([name, _mod]) => !!name));
|
|
136
|
+
const entr = entry;
|
|
137
|
+
const handle = `${entr.sectionHandle}-${entr.typeHandle}`;
|
|
138
|
+
if (
|
|
139
|
+
// @ts-ignore
|
|
140
|
+
import.meta.env.DEV &&
|
|
141
|
+
!modules.has(handle) &&
|
|
142
|
+
!modules.has(entr.sectionHandle)) {
|
|
143
|
+
console.error(`Template not found: <${handle}>, expecting file: ${handle}.svelte or ${entr.sectionHandle}.svelte`);
|
|
144
|
+
}
|
|
145
|
+
const loadMod = modules.get(handle) ??
|
|
146
|
+
modules.get(entr.sectionHandle) ??
|
|
147
|
+
modules.get('error-404');
|
|
148
|
+
if (!loadMod)
|
|
149
|
+
throw new Error('could not find error-404 template');
|
|
150
|
+
if (typeof loadMod === 'function') {
|
|
151
|
+
return await loadMod();
|
|
152
|
+
}
|
|
153
|
+
return loadMod;
|
|
154
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type GlobalWaiters = [(g: Global<any> | null) => void];
|
|
2
|
+
export default class Globals {
|
|
3
|
+
private waiters;
|
|
4
|
+
private entries;
|
|
5
|
+
private loaded;
|
|
6
|
+
private prevSiteId;
|
|
7
|
+
constructor();
|
|
8
|
+
get(name: string): Global<any> | null;
|
|
9
|
+
getAsync(name: string): Promise<Global<any> | null> | Global<any> | null;
|
|
10
|
+
_wasLoaded(): boolean;
|
|
11
|
+
_setData(siteId: number, data: any): void;
|
|
12
|
+
_globalsBySite(siteId: number): Map<string, any>;
|
|
13
|
+
_updateSiteId(siteId: number): void;
|
|
14
|
+
}
|
|
15
|
+
export interface GlobalData {
|
|
16
|
+
siteId?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare class Global<T extends GlobalData> {
|
|
19
|
+
private inner;
|
|
20
|
+
private languages;
|
|
21
|
+
constructor(name: string, data: T[] | T, siteId: number);
|
|
22
|
+
/**
|
|
23
|
+
* The function get's called once with the current value and then when the
|
|
24
|
+
* values changes
|
|
25
|
+
*
|
|
26
|
+
* @return a function which should be called to unsubscribe
|
|
27
|
+
*/
|
|
28
|
+
subscribe(fn: (val: T) => void): () => void;
|
|
29
|
+
get(): T;
|
|
30
|
+
bySiteId(siteId: number): T | null;
|
|
31
|
+
_updateSiteId(siteId: number): void;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=Globals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Globals.d.ts","sourceRoot":"","sources":["../../../../src/loadData/Globals.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC;AAE9D,MAAM,CAAC,OAAO,OAAO,OAAO;IAG3B,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,UAAU,CAAgB;;IASlC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI;IAMrC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI;IAexE,UAAU,IAAI,OAAO;IAQrB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG;IAgBlC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC;IAUhD,aAAa,CAAC,MAAM,EAAE,MAAM;CAM5B;AAED,MAAM,WAAW,UAAU;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,MAAM,CAAC,CAAC,SAAS,UAAU;IACvC,OAAO,CAAC,KAAK,CAAc;IAE3B,OAAO,CAAC,SAAS,CAAa;gBAElB,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM;IAsBvD;;;;;OAKG;IACH,SAAS,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAI3C,GAAG,IAAI,CAAC;IAKR,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAOlC,aAAa,CAAC,MAAM,EAAE,MAAM;CAM5B"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/*
|
|
2
|
+
// returns a store which get's updated as soon as the site changes
|
|
3
|
+
const emergency = getGlobal('emergency');
|
|
4
|
+
|
|
5
|
+
// returns the data based on the current site (no store)
|
|
6
|
+
cr.getGlobal('emergency')
|
|
7
|
+
*/
|
|
8
|
+
import { Writable } from 'crelte-std/stores';
|
|
9
|
+
export default class Globals {
|
|
10
|
+
// while the globals are not loaded if somebody calls
|
|
11
|
+
// getOrWait then we need to store the waiters
|
|
12
|
+
waiters;
|
|
13
|
+
entries;
|
|
14
|
+
loaded;
|
|
15
|
+
prevSiteId;
|
|
16
|
+
constructor() {
|
|
17
|
+
this.waiters = new Map();
|
|
18
|
+
this.entries = new Map();
|
|
19
|
+
this.loaded = false;
|
|
20
|
+
this.prevSiteId = null;
|
|
21
|
+
}
|
|
22
|
+
get(name) {
|
|
23
|
+
return this.entries.get(name) ?? null;
|
|
24
|
+
}
|
|
25
|
+
// call this only in loadGlobalData when by default the global
|
|
26
|
+
// is not available
|
|
27
|
+
getAsync(name) {
|
|
28
|
+
if (this.loaded)
|
|
29
|
+
return this.get(name);
|
|
30
|
+
let waiter = this.waiters.get(name);
|
|
31
|
+
if (!waiter) {
|
|
32
|
+
waiter = [];
|
|
33
|
+
this.waiters.set(name, waiter);
|
|
34
|
+
}
|
|
35
|
+
return new Promise(resolve => {
|
|
36
|
+
waiter.push(resolve);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
// hidden
|
|
40
|
+
_wasLoaded() {
|
|
41
|
+
return this.loaded;
|
|
42
|
+
}
|
|
43
|
+
// hidden
|
|
44
|
+
// data is the data from the global graphql
|
|
45
|
+
// so it contains some keys and data which should be parsed
|
|
46
|
+
// and created a store for each key
|
|
47
|
+
_setData(siteId, data) {
|
|
48
|
+
const wasLoaded = this.loaded;
|
|
49
|
+
this.loaded = true;
|
|
50
|
+
for (const [key, value] of Object.entries(data)) {
|
|
51
|
+
this.entries.set(key, new Global(key, value, siteId));
|
|
52
|
+
}
|
|
53
|
+
if (!wasLoaded) {
|
|
54
|
+
this.waiters.forEach((waiters, key) => {
|
|
55
|
+
waiters.forEach(waiter => waiter(this.get(key)));
|
|
56
|
+
});
|
|
57
|
+
this.waiters.clear();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
_globalsBySite(siteId) {
|
|
61
|
+
const map = new Map();
|
|
62
|
+
for (const [key, global] of this.entries) {
|
|
63
|
+
map.set(key, global.bySiteId(siteId));
|
|
64
|
+
}
|
|
65
|
+
return map;
|
|
66
|
+
}
|
|
67
|
+
_updateSiteId(siteId) {
|
|
68
|
+
// todo we should only trigger
|
|
69
|
+
if (this.prevSiteId === siteId)
|
|
70
|
+
return;
|
|
71
|
+
this.entries.forEach(global => global._updateSiteId(siteId));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export class Global {
|
|
75
|
+
inner;
|
|
76
|
+
/// if languages is null this means we always have the same data
|
|
77
|
+
languages;
|
|
78
|
+
constructor(name, data, siteId) {
|
|
79
|
+
this.languages = null;
|
|
80
|
+
let inner;
|
|
81
|
+
if (Array.isArray(data)) {
|
|
82
|
+
// make sure the data contains an object with the property
|
|
83
|
+
// siteId
|
|
84
|
+
this.languages = data;
|
|
85
|
+
inner = data.find(d => d.siteId === siteId);
|
|
86
|
+
if (!inner?.siteId) {
|
|
87
|
+
throw new Error(`The global query ${name} does not contain the required siteId property`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
inner = data;
|
|
92
|
+
}
|
|
93
|
+
this.inner = new Writable(inner);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The function get's called once with the current value and then when the
|
|
97
|
+
* values changes
|
|
98
|
+
*
|
|
99
|
+
* @return a function which should be called to unsubscribe
|
|
100
|
+
*/
|
|
101
|
+
subscribe(fn) {
|
|
102
|
+
return this.inner.subscribe(fn);
|
|
103
|
+
}
|
|
104
|
+
get() {
|
|
105
|
+
return this.inner.get();
|
|
106
|
+
}
|
|
107
|
+
/// if you pass a siteId which comes from craft then you will never receive null
|
|
108
|
+
bySiteId(siteId) {
|
|
109
|
+
if (this.languages)
|
|
110
|
+
return this.languages.find(d => d.siteId === siteId) ?? null;
|
|
111
|
+
return this.inner.get();
|
|
112
|
+
}
|
|
113
|
+
_updateSiteId(siteId) {
|
|
114
|
+
if (!this.languages)
|
|
115
|
+
return;
|
|
116
|
+
const inner = this.languages.find(d => d.siteId === siteId);
|
|
117
|
+
this.inner.set(inner);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
*/
|
|
4
|
+
import type CrelteRouted from '../CrelteRouted.js';
|
|
5
|
+
import { type GraphQlQuery } from '../graphql/GraphQl.js';
|
|
6
|
+
import type Globals from './Globals.js';
|
|
7
|
+
import type { Global } from './Globals.js';
|
|
8
|
+
export type { Globals, Global };
|
|
9
|
+
export type LoadData<T> = ((cr: CrelteRouted, ...args: any[]) => Promise<T>) | GraphQlQuery | T;
|
|
10
|
+
export declare function callLoadData(ld: LoadData<unknown>, cr: CrelteRouted, ...args: any[]): Promise<unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* Spread the data of two loadData functions.
|
|
13
|
+
*
|
|
14
|
+
* ## Example
|
|
15
|
+
* ```
|
|
16
|
+
* export const loadData = mergeLoadData(
|
|
17
|
+
* {
|
|
18
|
+
* filter: (cr) => cr.route.search.get('filter'),
|
|
19
|
+
* },
|
|
20
|
+
* (cr) => cr.query(myQuery, { siteId: cr.site.id })
|
|
21
|
+
* )
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function mergeLoadData(...lds: LoadData<object>[]): LoadData<object>;
|
|
25
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/loadData/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAEhC,MAAM,MAAM,QAAQ,CAAC,CAAC,IACnB,CAAC,CAAC,EAAE,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,GAClD,YAAY,GACZ,CAAC,CAAC;AAEL,wBAAsB,YAAY,CACjC,EAAE,EAAE,QAAQ,CAAC,OAAO,CAAC,EACrB,EAAE,EAAE,YAAY,EAChB,GAAG,IAAI,EAAE,GAAG,EAAE,GACZ,OAAO,CAAC,OAAO,CAAC,CAuBlB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,GAAG,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAQ1E"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
*/
|
|
4
|
+
import { isGraphQlQuery } from '../graphql/GraphQl.js';
|
|
5
|
+
export async function callLoadData(ld, cr, ...args) {
|
|
6
|
+
// either we have a function
|
|
7
|
+
if (typeof ld === 'function') {
|
|
8
|
+
return await ld(cr, ...args);
|
|
9
|
+
}
|
|
10
|
+
// or a graphql query
|
|
11
|
+
if (isGraphQlQuery(ld)) {
|
|
12
|
+
return await cr.query(ld);
|
|
13
|
+
}
|
|
14
|
+
// or an object
|
|
15
|
+
if (typeof ld === 'object' && ld !== null) {
|
|
16
|
+
const data = await Promise.all(Object.values(ld).map(nld => callLoadData(nld, cr, ...args)));
|
|
17
|
+
return Object.fromEntries(Object.keys(ld).map((key, i) => [key, data[i]]));
|
|
18
|
+
}
|
|
19
|
+
return ld;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Spread the data of two loadData functions.
|
|
23
|
+
*
|
|
24
|
+
* ## Example
|
|
25
|
+
* ```
|
|
26
|
+
* export const loadData = mergeLoadData(
|
|
27
|
+
* {
|
|
28
|
+
* filter: (cr) => cr.route.search.get('filter'),
|
|
29
|
+
* },
|
|
30
|
+
* (cr) => cr.query(myQuery, { siteId: cr.site.id })
|
|
31
|
+
* )
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export function mergeLoadData(...lds) {
|
|
35
|
+
return async (cr, ...args) => {
|
|
36
|
+
const datas = await Promise.all(lds.map(ld => callLoadData(ld, cr, ...args)));
|
|
37
|
+
return datas.reduce((acc, data) => ({ ...acc, ...data }), {});
|
|
38
|
+
};
|
|
39
|
+
}
|