crelte 0.4.7 → 0.5.0-alpha.1
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/Crelte.d.ts +7 -6
- package/dist/Crelte.d.ts.map +1 -1
- package/dist/Crelte.js +5 -13
- package/dist/CrelteRequest.d.ts +9 -0
- package/dist/CrelteRequest.d.ts.map +1 -1
- package/dist/CrelteRequest.js +16 -2
- package/dist/blocks/Blocks.svelte +2 -2
- package/dist/blocks/Blocks.svelte.d.ts +3 -19
- package/dist/blocks/Blocks.svelte.d.ts.map +1 -1
- package/dist/cookies/ClientCookies.d.ts +0 -1
- package/dist/cookies/ClientCookies.d.ts.map +1 -1
- package/dist/cookies/ClientCookies.js +0 -1
- package/dist/cookies/ServerCookies.d.ts +1 -2
- package/dist/cookies/ServerCookies.d.ts.map +1 -1
- package/dist/cookies/ServerCookies.js +2 -6
- package/dist/cookies/index.d.ts +0 -2
- package/dist/cookies/index.d.ts.map +1 -1
- package/dist/graphql/GraphQl.d.ts +2 -2
- package/dist/graphql/GraphQl.d.ts.map +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -6
- package/dist/init/InternalApp.d.ts +30 -0
- package/dist/init/InternalApp.d.ts.map +1 -0
- package/dist/init/InternalApp.js +71 -0
- package/dist/init/client.d.ts +0 -5
- package/dist/init/client.d.ts.map +1 -1
- package/dist/init/client.js +88 -75
- package/dist/init/crelte-vite-plugin.d.ts +5 -0
- package/dist/init/server.d.ts +0 -5
- package/dist/init/server.d.ts.map +1 -1
- package/dist/init/server.js +50 -20
- package/dist/init/shared.d.ts +7 -18
- package/dist/init/shared.d.ts.map +1 -1
- package/dist/init/shared.js +97 -154
- package/dist/init/svelteComponents.d.ts +3 -0
- package/dist/init/svelteComponents.d.ts.map +1 -0
- package/dist/init/svelteComponents.js +7 -0
- package/dist/loadData/Globals.d.ts +40 -33
- package/dist/loadData/Globals.d.ts.map +1 -1
- package/dist/loadData/Globals.js +99 -88
- package/dist/loadData/index.d.ts +3 -2
- package/dist/loadData/index.d.ts.map +1 -1
- package/dist/loadData/index.js +2 -0
- package/dist/plugins/Events.d.ts +11 -13
- package/dist/plugins/Events.d.ts.map +1 -1
- package/dist/plugins/Events.js +10 -3
- package/dist/routing/BaseRoute.d.ts +255 -0
- package/dist/routing/BaseRoute.d.ts.map +1 -0
- package/dist/routing/BaseRoute.js +349 -0
- package/dist/routing/BaseRouter.d.ts +210 -0
- package/dist/routing/BaseRouter.d.ts.map +1 -0
- package/dist/routing/BaseRouter.js +444 -0
- package/dist/routing/ClientRouter.d.ts +32 -0
- package/dist/routing/ClientRouter.d.ts.map +1 -0
- package/dist/routing/ClientRouter.js +259 -0
- package/dist/routing/LoadRunner.d.ts +39 -0
- package/dist/routing/LoadRunner.d.ts.map +1 -0
- package/dist/routing/{PageLoader.js → LoadRunner.js} +32 -20
- package/dist/routing/Request.d.ts +35 -3
- package/dist/routing/Request.d.ts.map +1 -1
- package/dist/routing/Request.js +64 -5
- package/dist/routing/Route.d.ts +24 -223
- package/dist/routing/Route.d.ts.map +1 -1
- package/dist/routing/Route.js +26 -315
- package/dist/routing/Router.d.ts +49 -73
- package/dist/routing/Router.d.ts.map +1 -1
- package/dist/routing/Router.js +85 -251
- package/dist/routing/ServerRouter.d.ts +23 -0
- package/dist/routing/ServerRouter.d.ts.map +1 -0
- package/dist/routing/ServerRouter.js +57 -0
- package/dist/routing/utils.d.ts +5 -0
- package/dist/routing/utils.d.ts.map +1 -1
- package/dist/routing/utils.js +39 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +3 -0
- package/package.json +6 -5
- package/src/Crelte.ts +12 -18
- package/src/CrelteRequest.ts +21 -2
- package/src/cookies/ClientCookies.ts +0 -2
- package/src/cookies/ServerCookies.ts +2 -7
- package/src/cookies/index.ts +0 -3
- package/src/graphql/GraphQl.ts +2 -1
- package/src/index.ts +17 -9
- package/src/init/InternalApp.ts +134 -0
- package/src/init/client.ts +104 -93
- package/src/init/crelte-vite-plugin.d.ts +5 -0
- package/src/init/server.ts +70 -35
- package/src/init/shared.ts +107 -227
- package/src/init/svelteComponents.ts +12 -0
- package/src/loadData/Globals.ts +121 -102
- package/src/loadData/index.ts +3 -2
- package/src/plugins/Events.ts +40 -42
- package/src/routing/BaseRoute.ts +422 -0
- package/src/routing/BaseRouter.ts +528 -0
- package/src/routing/ClientRouter.ts +329 -0
- package/src/routing/{PageLoader.ts → LoadRunner.ts} +43 -30
- package/src/routing/Request.ts +97 -12
- package/src/routing/Route.ts +56 -376
- package/src/routing/Router.ts +100 -359
- package/src/routing/ServerRouter.ts +78 -0
- package/src/routing/utils.ts +53 -0
- package/src/utils.ts +4 -0
- package/dist/routing/InnerRouter.d.ts +0 -113
- package/dist/routing/InnerRouter.d.ts.map +0 -1
- package/dist/routing/InnerRouter.js +0 -417
- package/dist/routing/PageLoader.d.ts +0 -36
- package/dist/routing/PageLoader.d.ts.map +0 -1
- package/src/routing/InnerRouter.ts +0 -498
package/dist/init/shared.js
CHANGED
|
@@ -1,94 +1,82 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { isGraphQlQuery } from '../graphql/GraphQl.js';
|
|
2
2
|
import { callLoadData } from '../loadData/index.js';
|
|
3
|
+
import { isPromise } from '../utils.js';
|
|
3
4
|
export function setupPlugins(crelte, plugins) {
|
|
4
5
|
for (const plugin of plugins) {
|
|
5
6
|
const p = plugin(crelte);
|
|
6
7
|
crelte.plugins.add(p);
|
|
7
8
|
}
|
|
8
9
|
}
|
|
9
|
-
export function
|
|
10
|
-
cr.events.trigger('
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
typeHandle: '404',
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Get the entry from the page
|
|
18
|
-
*
|
|
19
|
-
* entries should export sectionHandle and typeHandle
|
|
20
|
-
*
|
|
21
|
-
* products should alias productTypeHandle with typeHandle,
|
|
22
|
-
* sectionHandle will be automatically set to product
|
|
23
|
-
*/
|
|
24
|
-
function getEntry(page) {
|
|
25
|
-
if (page?.entry)
|
|
26
|
-
return { ...page.entry };
|
|
27
|
-
if (page?.product)
|
|
28
|
-
return {
|
|
29
|
-
sectionHandle: 'product',
|
|
30
|
-
...page.product,
|
|
31
|
-
};
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
// todo it would be nice to call this only once per server start
|
|
35
|
-
export async function prepareLoadFn(crelte, app, entryQuery, globalQuery) {
|
|
36
|
-
const templateModules = prepareTemplates(app.templates ?? {});
|
|
37
|
-
let entryRouter = null;
|
|
38
|
-
if (app.entryRoutes) {
|
|
39
|
-
entryRouter = new EntryRouter(crelte);
|
|
40
|
-
await app.entryRoutes(entryRouter);
|
|
10
|
+
export function pluginsBeforeRequest(cr) {
|
|
11
|
+
const res = cr.events.trigger('beforeRequest', cr);
|
|
12
|
+
// if one of them is a promise we need to wait for it
|
|
13
|
+
if (res.some(isPromise)) {
|
|
14
|
+
return Promise.all(res).then();
|
|
41
15
|
}
|
|
42
|
-
return async (cr, loadOpts) => {
|
|
43
|
-
return await loadFn(cr, app, templateModules, entryRouter, entryQuery, globalQuery, loadOpts);
|
|
44
|
-
};
|
|
45
16
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
17
|
+
export function pluginsBeforeRender(cr, route) {
|
|
18
|
+
cr.events.trigger('beforeRender', cr, route);
|
|
19
|
+
}
|
|
20
|
+
// This should be onRequest or handleRequest
|
|
21
|
+
//
|
|
22
|
+
// it should also handle the site redirect and stuff like that
|
|
23
|
+
// we should have a onRequest
|
|
24
|
+
export async function loadFn(cr, app, loadOpts) {
|
|
25
|
+
const isCanceled = () => !!loadOpts?.isCanceled();
|
|
26
|
+
// loadGlobalData phase
|
|
56
27
|
let globalProm = null;
|
|
57
|
-
if (
|
|
28
|
+
if (app.loadGlobalData) {
|
|
29
|
+
// we need to set the globals as soon as loadGlobalData completes
|
|
30
|
+
// because other loadGlobalData functions might wait on the result
|
|
58
31
|
globalProm = (async () => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
//
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
32
|
+
// todo theoretically we could if the loadData is a an LoadObject
|
|
33
|
+
// assign each to the global as soon as we have it. Which might
|
|
34
|
+
// prevent some deadlocks but i don't think this will happen
|
|
35
|
+
// often
|
|
36
|
+
const globals = await callLoadData(app.loadGlobalData, cr, null);
|
|
37
|
+
if (!globals)
|
|
38
|
+
return globals;
|
|
39
|
+
if (typeof globals !== 'object') {
|
|
40
|
+
throw new Error('loadGlobalData needs to return an object or nothing');
|
|
41
|
+
}
|
|
42
|
+
for (const [k, v] of Object.entries(globals)) {
|
|
43
|
+
cr.globals.set(k, v);
|
|
44
|
+
}
|
|
68
45
|
})();
|
|
69
46
|
}
|
|
70
|
-
|
|
47
|
+
// todo maybe each setting of the property on the request should be
|
|
48
|
+
// checked to be empty before doing it
|
|
49
|
+
const entryProm = (async () => {
|
|
50
|
+
let loadEntry = app.loadEntry;
|
|
51
|
+
if (isGraphQlQuery(loadEntry)) {
|
|
52
|
+
const entryQuery = loadEntry;
|
|
53
|
+
loadEntry = cr => queryEntry(cr, entryQuery);
|
|
54
|
+
}
|
|
55
|
+
let entry = await callLoadData(loadEntry, cr, null);
|
|
56
|
+
if (isCanceled())
|
|
57
|
+
return [];
|
|
58
|
+
cr.req.entry = entry;
|
|
59
|
+
await Promise.all(cr.events.trigger('afterLoadEntry', cr));
|
|
60
|
+
if (isCanceled())
|
|
61
|
+
return [];
|
|
62
|
+
entry = cr.req.entry;
|
|
63
|
+
const template = await app.loadTemplate(entry);
|
|
64
|
+
if (isCanceled())
|
|
65
|
+
return [];
|
|
66
|
+
cr.req.template = template;
|
|
67
|
+
return [entry, template];
|
|
68
|
+
})();
|
|
71
69
|
const pluginsLoadGlobalData = cr.events.trigger('loadGlobalData', cr);
|
|
72
70
|
// loading progress is at 20%
|
|
73
71
|
loadOpts?.setProgress(0.2);
|
|
74
|
-
const [
|
|
75
|
-
dataProm,
|
|
72
|
+
const [_global, [entry, template]] = await Promise.all([
|
|
76
73
|
globalProm,
|
|
77
74
|
entryProm,
|
|
78
75
|
...pluginsLoadGlobalData,
|
|
79
76
|
]);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
cr.globals._setData(cr.site.id, global ?? {});
|
|
84
|
-
}
|
|
85
|
-
let template;
|
|
86
|
-
if (app.templates) {
|
|
87
|
-
template = await loadTemplate(templateModules, entry);
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
throw new Error('App must export some templates');
|
|
91
|
-
}
|
|
77
|
+
if (isCanceled())
|
|
78
|
+
return;
|
|
79
|
+
cr.globals._globalsLoaded();
|
|
92
80
|
// loading progress is at 60%
|
|
93
81
|
loadOpts?.setProgress(0.6);
|
|
94
82
|
const pluginsLoadData = cr.events.trigger('loadData', cr, entry);
|
|
@@ -105,92 +93,47 @@ async function loadFn(cr, app, templateModules, entryRouter, entryQuery, globalQ
|
|
|
105
93
|
entryDataProm,
|
|
106
94
|
...pluginsLoadData,
|
|
107
95
|
]);
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
...data,
|
|
96
|
+
cr.req.loadedData = {
|
|
97
|
+
...templateData,
|
|
112
98
|
...entryData,
|
|
113
|
-
entry,
|
|
114
|
-
template: template.default,
|
|
115
|
-
templateData: templateData,
|
|
116
99
|
};
|
|
100
|
+
// loading progress is at 100%
|
|
101
|
+
loadOpts?.setProgress(1);
|
|
117
102
|
}
|
|
118
|
-
function
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (cr.req.siteMatches()) {
|
|
130
|
-
let uri = decodeURI(cr.req.uri);
|
|
131
|
-
if (uri.startsWith('/'))
|
|
132
|
-
uri = uri.substring(1);
|
|
133
|
-
if (uri === '' || uri === '/')
|
|
134
|
-
uri = '__home__';
|
|
135
|
-
vars = {
|
|
136
|
-
uri,
|
|
137
|
-
siteId: cr.site.id,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
if (vars) {
|
|
141
|
-
await Promise.all(cr.events.trigger('beforeQueryEntry', cr, vars));
|
|
142
|
-
}
|
|
143
|
-
// basic query function
|
|
144
|
-
let loadFn = async (vars) => {
|
|
145
|
-
if (entryRouter) {
|
|
146
|
-
const entry = await entryRouter._handle(cr);
|
|
147
|
-
if (entry)
|
|
148
|
-
return entry;
|
|
149
|
-
}
|
|
150
|
-
if (vars) {
|
|
151
|
-
const page = await cr.query(entryQuery, vars);
|
|
152
|
-
return getEntry(page);
|
|
153
|
-
}
|
|
154
|
-
return null;
|
|
103
|
+
export async function queryEntry(cr, entryQuery) {
|
|
104
|
+
if (!cr.req.siteMatches())
|
|
105
|
+
throw new Error('to run the entryQuery the request needs to have a matching site');
|
|
106
|
+
let uri = decodeURI(cr.req.uri);
|
|
107
|
+
if (uri.startsWith('/'))
|
|
108
|
+
uri = uri.substring(1);
|
|
109
|
+
if (uri === '' || uri === '/')
|
|
110
|
+
uri = '__home__';
|
|
111
|
+
const vars = {
|
|
112
|
+
uri,
|
|
113
|
+
siteId: cr.site.id,
|
|
155
114
|
};
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
for (const fn of fns) {
|
|
159
|
-
const prevLoadFn = loadFn;
|
|
160
|
-
loadFn = async (vars) => {
|
|
161
|
-
return await fn(cr, vars, prevLoadFn);
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
const entry = (await loadFn(vars)) ?? ERROR_404_ENTRY;
|
|
165
|
-
await Promise.all(cr.events.trigger('afterQueryEntry', cr, entry));
|
|
166
|
-
return entry;
|
|
167
|
-
}
|
|
168
|
-
function prepareTemplates(rawModules) {
|
|
169
|
-
// parse modules
|
|
170
|
-
return new Map(Object.entries(rawModules)
|
|
171
|
-
.map(([path, mod]) => {
|
|
172
|
-
const [name, _ext] = parseFilename(path);
|
|
173
|
-
return [name, mod];
|
|
174
|
-
})
|
|
175
|
-
.filter(([name, _mod]) => !!name));
|
|
115
|
+
const page = await cr.query(entryQuery, vars);
|
|
116
|
+
return getEntry(page) ?? ERROR_404_ENTRY;
|
|
176
117
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if (
|
|
191
|
-
|
|
192
|
-
if (
|
|
193
|
-
return
|
|
194
|
-
|
|
195
|
-
|
|
118
|
+
const ERROR_404_ENTRY = {
|
|
119
|
+
sectionHandle: 'error',
|
|
120
|
+
typeHandle: '404',
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Get the entry from the page
|
|
124
|
+
*
|
|
125
|
+
* entries should export sectionHandle and typeHandle
|
|
126
|
+
*
|
|
127
|
+
* products should alias productTypeHandle with typeHandle,
|
|
128
|
+
* sectionHandle will be automatically set to product
|
|
129
|
+
*/
|
|
130
|
+
function getEntry(page) {
|
|
131
|
+
if (page?.entry)
|
|
132
|
+
return { ...page.entry };
|
|
133
|
+
if (page?.product)
|
|
134
|
+
return {
|
|
135
|
+
sectionHandle: 'product',
|
|
136
|
+
...page.product,
|
|
137
|
+
};
|
|
138
|
+
return null;
|
|
196
139
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svelteComponents.d.ts","sourceRoot":"","sources":["../../src/init/svelteComponents.ts"],"names":[],"mappings":"AAKA,wBAAgB,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,GAAG,GAAG,CAExD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,GAAG,GAAG,CAEzD"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { internalSvelteMount, internalSvelteRender, } from 'crelte-vite-plugin/svelteComponents.js';
|
|
2
|
+
export function svelteMount(comp, options) {
|
|
3
|
+
return internalSvelteMount(comp, options);
|
|
4
|
+
}
|
|
5
|
+
export function svelteRender(comp, options) {
|
|
6
|
+
return internalSvelteRender(comp, options);
|
|
7
|
+
}
|
|
@@ -1,11 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
import { Readable, Writable } from 'crelte-std/stores';
|
|
2
|
+
export type GlobalWaiters<T> = ((g: T | null) => void)[];
|
|
3
|
+
/**
|
|
4
|
+
* Globals is sort of a queue
|
|
5
|
+
*
|
|
6
|
+
* each time a new request get's started
|
|
7
|
+
* a copy of globals is created which references some properties of the original one
|
|
8
|
+
*
|
|
9
|
+
* then if everything is loaded th original globals is "overriden" with the new one
|
|
10
|
+
* and we get a new state
|
|
11
|
+
*/
|
|
2
12
|
export default class Globals {
|
|
3
13
|
private waiters;
|
|
4
|
-
private
|
|
14
|
+
private newData;
|
|
5
15
|
private stores;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
16
|
+
constructor(stores?: Map<string, Writable<any>>);
|
|
17
|
+
/**
|
|
18
|
+
* returns a globalValue
|
|
19
|
+
*
|
|
20
|
+
* ## Note
|
|
21
|
+
* This only works in loadData, in loadGlobalData this will
|
|
22
|
+
* throw an error. In that context you should use `.getAsync`
|
|
23
|
+
*/
|
|
24
|
+
get<T = any>(name: string): T | null;
|
|
9
25
|
/**
|
|
10
26
|
* returns a store which contains a globalSet
|
|
11
27
|
*
|
|
@@ -14,43 +30,34 @@ export default class Globals {
|
|
|
14
30
|
* always return null. In that context you should use
|
|
15
31
|
* `.getAsync`
|
|
16
32
|
*/
|
|
17
|
-
getStore<T = any>(name: string):
|
|
33
|
+
getStore<T = any>(name: string): Readable<T> | null;
|
|
18
34
|
/**
|
|
19
35
|
* Get a store which contains a globalSet and wait until it is loaded
|
|
20
36
|
*
|
|
21
37
|
* ## Note
|
|
22
38
|
* This is only useful in loadGlobalData in all other cases
|
|
23
|
-
* you can use `.
|
|
39
|
+
* you can use `.get` which does not return a Promise
|
|
24
40
|
*/
|
|
25
|
-
getAsync<T = any>(name: string
|
|
26
|
-
/** @hidden */
|
|
27
|
-
_wasLoaded(siteId: number): boolean;
|
|
28
|
-
/** @hidden */
|
|
29
|
-
_setData(siteId: number, data: any): void;
|
|
30
|
-
/** @hidden */
|
|
31
|
-
_updateSiteId(siteId: number): void;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* A globalSet store
|
|
35
|
-
*/
|
|
36
|
-
export declare class Global<T = any> {
|
|
37
|
-
/** @hidden */
|
|
38
|
-
private inner;
|
|
39
|
-
constructor(name: string, data: T);
|
|
41
|
+
getAsync<T = any>(name: string): Promise<T | null> | T | null;
|
|
40
42
|
/**
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
* can only be called in loadGlobalData contexts
|
|
44
|
+
*/
|
|
45
|
+
set<T>(name: string, data: T): void;
|
|
46
|
+
/**
|
|
47
|
+
* @hidden
|
|
48
|
+
* call this before starting the loadGlobalData phase
|
|
49
|
+
*/
|
|
50
|
+
_toRequest(): Globals;
|
|
51
|
+
/**
|
|
52
|
+
* @hidden
|
|
53
|
+
* call this after the loadGlobalData phase
|
|
45
54
|
*/
|
|
46
|
-
|
|
55
|
+
_globalsLoaded(): void;
|
|
47
56
|
/**
|
|
48
|
-
*
|
|
57
|
+
* @hidden
|
|
58
|
+
* call this after the loadData phase once the CrelteRequest
|
|
59
|
+
* gets completed
|
|
49
60
|
*/
|
|
50
|
-
|
|
51
|
-
/** @hidden */
|
|
52
|
-
_setSilent(value: T): void;
|
|
53
|
-
/** @hidden */
|
|
54
|
-
_notify(): void;
|
|
61
|
+
_syncToStores(): void;
|
|
55
62
|
}
|
|
56
63
|
//# sourceMappingURL=Globals.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Globals.d.ts","sourceRoot":"","sources":["../../src/loadData/Globals.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Globals.d.ts","sourceRoot":"","sources":["../../src/loadData/Globals.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;AAEzD;;;;;;;;GAQG;AACH,MAAM,CAAC,OAAO,OAAO,OAAO;IAK3B,OAAO,CAAC,OAAO,CAAyC;IAIxD,OAAO,CAAC,OAAO,CAA0B;IAGzC,OAAO,CAAC,MAAM,CAA6B;gBAE/B,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;IAM/C;;;;;;OAMG;IACH,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAmBpC;;;;;;;OAOG;IACH,QAAQ,CAAC,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI;IAInD;;;;;;OAMG;IACH,QAAQ,CAAC,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI;IAiB7D;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IA4B5B;;;OAGG;IACH,UAAU;IAQV;;;OAGG;IACH,cAAc;IAMd;;;;OAIG;IACH,aAAa;CAyBb"}
|
package/dist/loadData/Globals.js
CHANGED
|
@@ -7,21 +7,48 @@ cr.getGlobal('emergency')
|
|
|
7
7
|
|
|
8
8
|
*/
|
|
9
9
|
import { Writable } from 'crelte-std/stores';
|
|
10
|
+
/**
|
|
11
|
+
* Globals is sort of a queue
|
|
12
|
+
*
|
|
13
|
+
* each time a new request get's started
|
|
14
|
+
* a copy of globals is created which references some properties of the original one
|
|
15
|
+
*
|
|
16
|
+
* then if everything is loaded th original globals is "overriden" with the new one
|
|
17
|
+
* and we get a new state
|
|
18
|
+
*/
|
|
10
19
|
export default class Globals {
|
|
11
20
|
// while the globals are not loaded if somebody calls
|
|
12
21
|
// getAsync then we need to store the waiters
|
|
22
|
+
// this get's created as soon as a request was started
|
|
23
|
+
// and get's deleted as soon as all globals are loaded
|
|
13
24
|
waiters;
|
|
14
|
-
|
|
25
|
+
// this get's created as soon as a request was started
|
|
26
|
+
// and deleted once they are synced to the stores
|
|
27
|
+
newData;
|
|
28
|
+
// contains the current active globals
|
|
15
29
|
stores;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
this.
|
|
19
|
-
this.
|
|
20
|
-
this.stores = new Map();
|
|
21
|
-
this.currentSiteId = null;
|
|
30
|
+
constructor(stores) {
|
|
31
|
+
this.waiters = null;
|
|
32
|
+
this.newData = null;
|
|
33
|
+
this.stores = stores ?? new Map();
|
|
22
34
|
}
|
|
23
|
-
|
|
24
|
-
|
|
35
|
+
/**
|
|
36
|
+
* returns a globalValue
|
|
37
|
+
*
|
|
38
|
+
* ## Note
|
|
39
|
+
* This only works in loadData, in loadGlobalData this will
|
|
40
|
+
* throw an error. In that context you should use `.getAsync`
|
|
41
|
+
*/
|
|
42
|
+
get(name) {
|
|
43
|
+
if (this.waiters)
|
|
44
|
+
throw new Error('calling get in loadGlobalData will not work. call getAsync');
|
|
45
|
+
if (!this.newData) {
|
|
46
|
+
throw new Error('calling get outside of a loadData is forbidden. use getStore');
|
|
47
|
+
// todo do we wan't to allow this?
|
|
48
|
+
// isn't it just a footgun?
|
|
49
|
+
// return this.getStore(name)?.get() ?? null;
|
|
50
|
+
}
|
|
51
|
+
return this.newData.get(name) ?? null;
|
|
25
52
|
}
|
|
26
53
|
/**
|
|
27
54
|
* returns a store which contains a globalSet
|
|
@@ -32,78 +59,35 @@ export default class Globals {
|
|
|
32
59
|
* `.getAsync`
|
|
33
60
|
*/
|
|
34
61
|
getStore(name) {
|
|
35
|
-
return this.stores.get(name) ?? null;
|
|
62
|
+
return this.stores.get(name)?.readonly() ?? null;
|
|
36
63
|
}
|
|
37
64
|
/**
|
|
38
65
|
* Get a store which contains a globalSet and wait until it is loaded
|
|
39
66
|
*
|
|
40
67
|
* ## Note
|
|
41
68
|
* This is only useful in loadGlobalData in all other cases
|
|
42
|
-
* you can use `.
|
|
69
|
+
* you can use `.get` which does not return a Promise
|
|
43
70
|
*/
|
|
44
|
-
getAsync(name
|
|
45
|
-
if (this.
|
|
46
|
-
return
|
|
47
|
-
|
|
71
|
+
getAsync(name) {
|
|
72
|
+
if (this.newData)
|
|
73
|
+
return this.newData.get(name) ?? null;
|
|
74
|
+
if (!this.waiters)
|
|
75
|
+
throw new Error('calling getAsync in non loadGlobalData contexts is pointless. Use getStore instead');
|
|
76
|
+
let listeners = this.waiters.get(name);
|
|
48
77
|
if (!listeners) {
|
|
49
|
-
listeners =
|
|
50
|
-
this.waiters.set(
|
|
78
|
+
listeners = [];
|
|
79
|
+
this.waiters.set(name, listeners);
|
|
51
80
|
}
|
|
52
|
-
|
|
53
|
-
if (!waiter) {
|
|
54
|
-
waiter = [];
|
|
55
|
-
listeners.set(name, waiter);
|
|
56
|
-
}
|
|
57
|
-
return new Promise(resolve => {
|
|
58
|
-
waiter.push(resolve);
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
/** @hidden */
|
|
62
|
-
_wasLoaded(siteId) {
|
|
63
|
-
return this.data.has(siteId);
|
|
64
|
-
}
|
|
65
|
-
// data is the data from the global graphql
|
|
66
|
-
// so it contains some keys and data which should be parsed
|
|
67
|
-
// and created a store for each key
|
|
68
|
-
// do not call this if _wasLoaded returns true with the same siteId
|
|
69
|
-
/** @hidden */
|
|
70
|
-
_setData(siteId, data) {
|
|
71
|
-
const map = new Map(Object.entries(data));
|
|
72
|
-
this.data.set(siteId, map);
|
|
73
|
-
this.waiters.get(siteId)?.forEach((waiters, key) => {
|
|
74
|
-
waiters.forEach(waiter => waiter(map.get(key)));
|
|
75
|
-
});
|
|
76
|
-
this.waiters.delete(siteId);
|
|
77
|
-
}
|
|
78
|
-
/** @hidden */
|
|
79
|
-
_updateSiteId(siteId) {
|
|
80
|
-
if (this.currentSiteId === siteId)
|
|
81
|
-
return;
|
|
82
|
-
const data = this.data.get(siteId) ?? new Map();
|
|
83
|
-
// we set all global data to null via setSilent
|
|
84
|
-
// then set them all with the new data
|
|
85
|
-
// and update all of them
|
|
86
|
-
this.stores.forEach(global => global._setSilent(null));
|
|
87
|
-
data.forEach((value, key) => {
|
|
88
|
-
let global = this.stores.get(key);
|
|
89
|
-
if (global) {
|
|
90
|
-
global._setSilent(value);
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
global = new Global(key, value);
|
|
94
|
-
this.stores.set(key, global);
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
this.stores.forEach(global => global._notify());
|
|
81
|
+
return new Promise(resolve => listeners.push(resolve));
|
|
98
82
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
83
|
+
/**
|
|
84
|
+
* can only be called in loadGlobalData contexts
|
|
85
|
+
*/
|
|
86
|
+
set(name, data) {
|
|
87
|
+
if (!this.newData) {
|
|
88
|
+
// this is not strictly necessary but
|
|
89
|
+
throw new Error('can only be called in loadGlobalData contexts');
|
|
90
|
+
}
|
|
107
91
|
// todo remove in v1.0
|
|
108
92
|
// In v0.2, we queried the global data for all sites.
|
|
109
93
|
// We now check if the siteId is present and notify the user to remove it.
|
|
@@ -112,29 +96,56 @@ export class Global {
|
|
|
112
96
|
throw new Error(`The global query ${name} should not include the siteId` +
|
|
113
97
|
` property. Instead, use the siteId as a parameter.`);
|
|
114
98
|
}
|
|
115
|
-
this.
|
|
99
|
+
this.newData?.set(name, data);
|
|
100
|
+
const listeners = this.waiters?.get(name);
|
|
101
|
+
if (listeners) {
|
|
102
|
+
this.waiters.delete(name);
|
|
103
|
+
listeners.forEach(fn => fn(data));
|
|
104
|
+
}
|
|
116
105
|
}
|
|
117
106
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* @return a function which should be called to unsubscribe
|
|
107
|
+
* @hidden
|
|
108
|
+
* call this before starting the loadGlobalData phase
|
|
122
109
|
*/
|
|
123
|
-
|
|
124
|
-
|
|
110
|
+
_toRequest() {
|
|
111
|
+
const nGlobals = new Globals(this.stores);
|
|
112
|
+
nGlobals.waiters = new Map();
|
|
113
|
+
nGlobals.newData = new Map();
|
|
114
|
+
return nGlobals;
|
|
125
115
|
}
|
|
126
116
|
/**
|
|
127
|
-
*
|
|
117
|
+
* @hidden
|
|
118
|
+
* call this after the loadGlobalData phase
|
|
128
119
|
*/
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
_setSilent(value) {
|
|
134
|
-
this.inner.setSilent(value);
|
|
120
|
+
_globalsLoaded() {
|
|
121
|
+
// todo should we check if there are still waiters?
|
|
122
|
+
// theoretically this should never happen
|
|
123
|
+
this.waiters = null;
|
|
135
124
|
}
|
|
136
|
-
/**
|
|
137
|
-
|
|
138
|
-
|
|
125
|
+
/**
|
|
126
|
+
* @hidden
|
|
127
|
+
* call this after the loadData phase once the CrelteRequest
|
|
128
|
+
* gets completed
|
|
129
|
+
*/
|
|
130
|
+
_syncToStores() {
|
|
131
|
+
const setToNull = new Set(this.stores.keys());
|
|
132
|
+
for (const [name, data] of this.newData.entries()) {
|
|
133
|
+
setToNull.delete(name);
|
|
134
|
+
const store = this.stores.get(name);
|
|
135
|
+
if (store) {
|
|
136
|
+
// todo should we do this check always?
|
|
137
|
+
if (store.get() !== data)
|
|
138
|
+
store.set(data);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
this.stores.set(name, new Writable(data));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
for (const name of setToNull) {
|
|
145
|
+
console.warn(`global ${name} was not modified setting to null and removing it`);
|
|
146
|
+
this.stores.get(name).set(null);
|
|
147
|
+
this.stores.delete(name);
|
|
148
|
+
}
|
|
149
|
+
this.newData = null;
|
|
139
150
|
}
|
|
140
151
|
}
|
package/dist/loadData/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import CrelteRequest from '../CrelteRequest.js';
|
|
2
2
|
import { type GraphQlQuery } from '../graphql/GraphQl.js';
|
|
3
3
|
import type Globals from './Globals.js';
|
|
4
|
-
|
|
5
|
-
export type { Globals, Global };
|
|
4
|
+
export type { Globals };
|
|
6
5
|
export interface LoadDataFn<A1 = any> {
|
|
7
6
|
(cr: CrelteRequest, entryOrBlock: A1, ...args: any[]): Promise<any> | any;
|
|
8
7
|
}
|
|
@@ -80,6 +79,8 @@ export declare function callLoadData<A1 = any>(ld: LoadData<A1>, cr: CrelteReque
|
|
|
80
79
|
/**
|
|
81
80
|
* Spread the data of two loadData functions.
|
|
82
81
|
*
|
|
82
|
+
* Prefer to use the array syntax.
|
|
83
|
+
*
|
|
83
84
|
* ## Example
|
|
84
85
|
* ```
|
|
85
86
|
* export const loadData = mergeLoadData(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/loadData/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/loadData/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAExC,YAAY,EAAE,OAAO,EAAE,CAAC;AAExB,MAAM,WAAW,UAAU,CAAC,EAAE,GAAG,GAAG;IACnC,CAAC,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;CAC1E;AAED,MAAM,WAAW,WAAW,CAAC,EAAE,GAAG,GAAG;IACpC,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;CAC5B;AAGD,MAAM,WAAW,aAAa,CAAC,EAAE,GAAG,GAAG,CAAE,SAAQ,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;CAAG;AAKvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,MAAM,MAAM,QAAQ,CAAC,EAAE,GAAG,GAAG,IAC1B,UAAU,CAAC,EAAE,CAAC,GACd,YAAY,GACZ,WAAW,CAAC,EAAE,CAAC,GACf,aAAa,CAAC,EAAE,CAAC,GACjB,MAAM,GACN,MAAM,GACN,IAAI,GACJ,SAAS,CAAC;AAOb,wBAAsB,YAAY,CAAC,EAAE,GAAG,GAAG,EAC1C,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC,EAChB,EAAE,EAAE,aAAa,EACjB,IAAI,EAAE,EAAE,EACR,GAAG,IAAI,EAAE,GAAG,EAAE,GACZ,OAAO,CAAC,GAAG,CAAC,CA6Bd;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,EAAE,GAAG,GAAG,EACrC,GAAG,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,GACpB,UAAU,CAAC,EAAE,CAAC,CAUhB"}
|