crelte 0.5.1 → 0.5.3
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/cookies/ServerCookies.js +2 -2
- package/dist/init/client.js +2 -2
- package/dist/init/server.js +1 -1
- package/dist/queries/Queries.js +2 -2
- package/dist/queries/index.d.ts +2 -2
- package/dist/queries/index.d.ts.map +1 -1
- package/dist/queries/index.js +2 -2
- package/dist/queries/vars.d.ts +34 -0
- package/dist/queries/vars.d.ts.map +1 -1
- package/dist/queries/vars.js +47 -2
- package/dist/routing/router/BaseRouter.d.ts.map +1 -1
- package/dist/routing/router/BaseRouter.js +5 -7
- package/dist/routing/router/ClientRouter.d.ts +2 -1
- package/dist/routing/router/ClientRouter.d.ts.map +1 -1
- package/dist/routing/router/ClientRouter.js +4 -1
- package/dist/routing/router/Router.d.ts.map +1 -1
- package/dist/routing/router/Router.js +2 -2
- package/dist/routing/router/ServerRouter.d.ts +1 -0
- package/dist/routing/router/ServerRouter.d.ts.map +1 -1
- package/dist/routing/router/ServerRouter.js +3 -0
- package/dist/server/ServerRouter.js +1 -1
- package/dist/server/queries/routes.d.ts.map +1 -1
- package/dist/server/queries/routes.js +8 -2
- package/dist/server/shared.js +1 -1
- package/package.json +1 -1
- package/src/cookies/ServerCookies.ts +2 -2
- package/src/init/client.ts +2 -2
- package/src/init/server.ts +1 -1
- package/src/queries/Queries.ts +2 -2
- package/src/queries/index.ts +2 -1
- package/src/queries/vars.ts +51 -2
- package/src/routing/router/BaseRouter.ts +5 -7
- package/src/routing/router/ClientRouter.ts +6 -2
- package/src/routing/router/Router.ts +2 -2
- package/src/routing/router/ServerRouter.ts +4 -0
- package/src/server/ServerRouter.ts +1 -1
- package/src/server/queries/routes.ts +11 -2
- package/src/server/shared.ts +1 -1
|
@@ -7,7 +7,7 @@ export default class ServerCookies {
|
|
|
7
7
|
requestCookies;
|
|
8
8
|
setCookies;
|
|
9
9
|
constructor(headers) {
|
|
10
|
-
this.requestCookies = parseCookies(headers.get('
|
|
10
|
+
this.requestCookies = parseCookies(headers.get('Cookie') ?? '');
|
|
11
11
|
this.setCookies = new Map();
|
|
12
12
|
}
|
|
13
13
|
/// Rethrns the value of the cookie with the given name, or null if it doesn't exist.
|
|
@@ -27,7 +27,7 @@ export default class ServerCookies {
|
|
|
27
27
|
}
|
|
28
28
|
_populateHeaders(headers) {
|
|
29
29
|
for (const setCookie of this.setCookies.values()) {
|
|
30
|
-
headers.append('
|
|
30
|
+
headers.append('Set-Cookie', setCookieToString(setCookie));
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
}
|
package/dist/init/client.js
CHANGED
|
@@ -89,11 +89,11 @@ export async function main(data) {
|
|
|
89
89
|
intro: config.playIntro,
|
|
90
90
|
});
|
|
91
91
|
};
|
|
92
|
-
router.onError = e => {
|
|
92
|
+
router.onError = (e, req) => {
|
|
93
93
|
console.error('routing failed:', e, 'reloading trying to fix it');
|
|
94
94
|
// since onError is called only on subsequent requests we should never
|
|
95
95
|
// have an infinite loop here
|
|
96
|
-
window.location.
|
|
96
|
+
window.location.href = req.url.href;
|
|
97
97
|
};
|
|
98
98
|
router.onRender = async (cr, readyForRoute, domUpdated) => {
|
|
99
99
|
if (appInstance && cr.req.disableLoadData) {
|
package/dist/init/server.js
CHANGED
|
@@ -44,7 +44,7 @@ export async function main(data) {
|
|
|
44
44
|
ssrCache.set('FRONTEND_URL', data.serverData.frontend);
|
|
45
45
|
const cookies = new ServerCookies(data.serverData.headers);
|
|
46
46
|
ssrCache.set('crelteSites', data.serverData.sites);
|
|
47
|
-
const router = new ServerRouter(data.serverData.sites, data.serverData.headers.get('
|
|
47
|
+
const router = new ServerRouter(data.serverData.sites, data.serverData.headers.get('Accept-Language') ?? '', { debugTiming: config.debugTiming ?? false });
|
|
48
48
|
const queries = newQueries(ssrCache, router.route.readonly(), config);
|
|
49
49
|
const crelte = newCrelte({
|
|
50
50
|
config,
|
package/dist/queries/Queries.js
CHANGED
|
@@ -171,8 +171,8 @@ class Inner {
|
|
|
171
171
|
if (!resp.ok) {
|
|
172
172
|
throw new QueryError({ status: resp.status, body: await resp.text() }, 'resp not ok');
|
|
173
173
|
}
|
|
174
|
-
if (resp.headers.get('
|
|
175
|
-
console.log('Debug link', resp.headers.get('
|
|
174
|
+
if (resp.headers.get('X-Debug-Link'))
|
|
175
|
+
console.log('Debug link', resp.headers.get('X-Debug-Link'));
|
|
176
176
|
if (timing) {
|
|
177
177
|
console.log(logName + ' completed took: ' + (Date.now() - timing) + 'ms', vars);
|
|
178
178
|
}
|
package/dist/queries/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import Queries, { isQuery, QueriesOptions, Query, QueryOptions } from '../queries/Queries.js';
|
|
2
2
|
import { gql } from './gql.js';
|
|
3
3
|
import QueryError from './QueryError.js';
|
|
4
|
-
import { QueryVar, ValidIf, vars } from './vars.js';
|
|
5
|
-
export { Queries, type QueriesOptions, type QueryOptions, type Query, isQuery, QueryError, gql, vars, type ValidIf, QueryVar, };
|
|
4
|
+
import { QueryVar, ValidIf, vars, varsIdsEqual } from './vars.js';
|
|
5
|
+
export { Queries, type QueriesOptions, type QueryOptions, type Query, isQuery, QueryError, gql, vars, type ValidIf, QueryVar, varsIdsEqual, };
|
|
6
6
|
type InferQueryVarType<T> = T extends QueryVar<infer U> ? U : never;
|
|
7
7
|
type InferVariableTypes<T> = {
|
|
8
8
|
[K in keyof T]: InferQueryVarType<T[K]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/queries/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,EACf,OAAO,EACP,cAAc,EACd,KAAK,EACL,YAAY,EACZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/queries/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,EACf,OAAO,EACP,cAAc,EACd,KAAK,EACL,YAAY,EACZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAElE,OAAO,EACN,OAAO,EACP,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,OAAO,EACP,UAAU,EACV,GAAG,EACH,IAAI,EACJ,KAAK,OAAO,EACZ,QAAQ,EACR,YAAY,GACZ,CAAC;AAEF,KAAK,iBAAiB,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEpE,KAAK,kBAAkB,CAAC,CAAC,IAAI;KAC3B,CAAC,IAAI,MAAM,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACvC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,OAAO,CAClB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,IACpE,OAAO,GAAG,CAAC,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC"}
|
package/dist/queries/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Queries, { isQuery, } from '../queries/Queries.js';
|
|
2
2
|
import { gql } from './gql.js';
|
|
3
3
|
import QueryError from './QueryError.js';
|
|
4
|
-
import { QueryVar, vars } from './vars.js';
|
|
5
|
-
export { Queries, isQuery, QueryError, gql, vars, QueryVar, };
|
|
4
|
+
import { QueryVar, vars, varsIdsEqual } from './vars.js';
|
|
5
|
+
export { Queries, isQuery, QueryError, gql, vars, QueryVar, varsIdsEqual, };
|
package/dist/queries/vars.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export declare const vars: {
|
|
|
19
19
|
* the returned array will **never be empty**, but might be null if
|
|
20
20
|
* allowed. Id's are always non negative integers
|
|
21
21
|
*
|
|
22
|
+
* The numbers are always unique and sorted in ascending order
|
|
23
|
+
*
|
|
22
24
|
* ## Warning
|
|
23
25
|
* Ids are not automatically safe to be cached, it is also not
|
|
24
26
|
* enough to just check if the filter returned some results.
|
|
@@ -61,4 +63,36 @@ export declare class QueryVar<T = any> {
|
|
|
61
63
|
__QueryVar__(): void;
|
|
62
64
|
}
|
|
63
65
|
export declare function isQueryVar(v: any): v is QueryVar;
|
|
66
|
+
/**
|
|
67
|
+
* Checks if two id arrays are equal
|
|
68
|
+
*
|
|
69
|
+
* The first argument needs to come from a `vars.ids()` variable.
|
|
70
|
+
* The second argument should come from a query, where the output is trusted.
|
|
71
|
+
*
|
|
72
|
+
* ## Example
|
|
73
|
+
* ```
|
|
74
|
+
* export const variables = {
|
|
75
|
+
* categories: vars.ids()
|
|
76
|
+
* };
|
|
77
|
+
*
|
|
78
|
+
* export const caching: Caching<typeof variables> = (res, vars) => {
|
|
79
|
+
* // res is the graphql response
|
|
80
|
+
* return varsIdsEqual(vars.categories, res.categories);
|
|
81
|
+
* };
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* ## Note
|
|
85
|
+
* The following cases are considered equal:
|
|
86
|
+
* ```
|
|
87
|
+
* varsIdsEqual(null, null);
|
|
88
|
+
* varsIdsEqual([], null);
|
|
89
|
+
* varsIdsEqual([1,2], ['2',1]);
|
|
90
|
+
* ```
|
|
91
|
+
* These are not equal:
|
|
92
|
+
* ```
|
|
93
|
+
* varsIdsEqual([1], null);
|
|
94
|
+
* varsIdsEqual([2,1], [2,1]); // because the second arg gets ordered
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export declare function varsIdsEqual(a: number[] | null | undefined, b: (string | number)[] | null | undefined): boolean;
|
|
64
98
|
//# sourceMappingURL=vars.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vars.d.ts","sourceRoot":"","sources":["../../src/queries/vars.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,2BAA2B,CAAC;AAErD,eAAO,MAAM,IAAI;eACP,QAAQ,CAAC,GAAG,CAAC;kBACV,QAAQ,CAAC,MAAM,CAAC;kBAChB,QAAQ,CAAC,MAAM,CAAC;IAE5B;;;;;;;;OAQG;cACK,QAAQ,CAAC,MAAM,CAAC;IAExB
|
|
1
|
+
{"version":3,"file":"vars.d.ts","sourceRoot":"","sources":["../../src/queries/vars.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,2BAA2B,CAAC;AAErD,eAAO,MAAM,IAAI;eACP,QAAQ,CAAC,GAAG,CAAC;kBACV,QAAQ,CAAC,MAAM,CAAC;kBAChB,QAAQ,CAAC,MAAM,CAAC;IAE5B;;;;;;;;OAQG;cACK,QAAQ,CAAC,MAAM,CAAC;IAExB;;;;;;;;;;;;;;;;;;OAkBG;eACM,QAAQ,CAAC,MAAM,EAAE,CAAC;kBAEf,QAAQ,CAAC,MAAM,CAAC;CAM5B,CAAC;AAIF,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,YAAY,KAAK,OAAO,CAAC;AAE7D,qBAAa,QAAQ,CAAC,CAAC,GAAG,GAAG;IAC5B,OAAO,CAAC,IAAI,CAAgB;IAC5B,OAAO,CAAC,IAAI,CAA6C;IACzD,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,SAAS,CAAa;;IAS9B,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC;IAK1B,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC;IAK1B,EAAE,IAAI,QAAQ,CAAC,MAAM,CAAC;IAKtB,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;IAKzB,QAAQ,IAAI,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC;IAK9B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;IAKpC,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,GAAG,CAAC,GAAG,IAAI;IAqE9C;;;OAGG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAKpC,YAAY;CACZ;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,IAAI,QAAQ,CAEhD;AAOD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,YAAY,CAC3B,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,EAC9B,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,IAAI,GAAG,SAAS,GACvC,OAAO,CAWT"}
|
package/dist/queries/vars.js
CHANGED
|
@@ -18,6 +18,8 @@ export const vars = {
|
|
|
18
18
|
* the returned array will **never be empty**, but might be null if
|
|
19
19
|
* allowed. Id's are always non negative integers
|
|
20
20
|
*
|
|
21
|
+
* The numbers are always unique and sorted in ascending order
|
|
22
|
+
*
|
|
21
23
|
* ## Warning
|
|
22
24
|
* Ids are not automatically safe to be cached, it is also not
|
|
23
25
|
* enough to just check if the filter returned some results.
|
|
@@ -97,7 +99,7 @@ export class QueryVar {
|
|
|
97
99
|
break;
|
|
98
100
|
case 'id':
|
|
99
101
|
if (typeof v === 'string')
|
|
100
|
-
v =
|
|
102
|
+
v = Number(v);
|
|
101
103
|
if (!isValidId(v))
|
|
102
104
|
throw new Error(`variable ${this.name} is not a valid id`);
|
|
103
105
|
break;
|
|
@@ -112,7 +114,7 @@ export class QueryVar {
|
|
|
112
114
|
throw new Error(`variable ${this.name} is not allowed to be empty`);
|
|
113
115
|
}
|
|
114
116
|
// convert strings to numbers
|
|
115
|
-
v = v.map(
|
|
117
|
+
v = v.map(Number);
|
|
116
118
|
if (!v.every(isValidId))
|
|
117
119
|
throw new Error(`variable ${this.name} is not a list of valid ids`);
|
|
118
120
|
// make unique and sort by number
|
|
@@ -142,3 +144,46 @@ export function isQueryVar(v) {
|
|
|
142
144
|
function isValidId(id) {
|
|
143
145
|
return typeof id === 'number' && Number.isInteger(id) && id >= 0;
|
|
144
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Checks if two id arrays are equal
|
|
149
|
+
*
|
|
150
|
+
* The first argument needs to come from a `vars.ids()` variable.
|
|
151
|
+
* The second argument should come from a query, where the output is trusted.
|
|
152
|
+
*
|
|
153
|
+
* ## Example
|
|
154
|
+
* ```
|
|
155
|
+
* export const variables = {
|
|
156
|
+
* categories: vars.ids()
|
|
157
|
+
* };
|
|
158
|
+
*
|
|
159
|
+
* export const caching: Caching<typeof variables> = (res, vars) => {
|
|
160
|
+
* // res is the graphql response
|
|
161
|
+
* return varsIdsEqual(vars.categories, res.categories);
|
|
162
|
+
* };
|
|
163
|
+
* ```
|
|
164
|
+
*
|
|
165
|
+
* ## Note
|
|
166
|
+
* The following cases are considered equal:
|
|
167
|
+
* ```
|
|
168
|
+
* varsIdsEqual(null, null);
|
|
169
|
+
* varsIdsEqual([], null);
|
|
170
|
+
* varsIdsEqual([1,2], ['2',1]);
|
|
171
|
+
* ```
|
|
172
|
+
* These are not equal:
|
|
173
|
+
* ```
|
|
174
|
+
* varsIdsEqual([1], null);
|
|
175
|
+
* varsIdsEqual([2,1], [2,1]); // because the second arg gets ordered
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
export function varsIdsEqual(a, b) {
|
|
179
|
+
const aEmpty = !a?.length;
|
|
180
|
+
const bEmpty = !b?.length;
|
|
181
|
+
if (aEmpty && bEmpty)
|
|
182
|
+
return true;
|
|
183
|
+
if (aEmpty || bEmpty)
|
|
184
|
+
return false;
|
|
185
|
+
if (a.length !== b.length)
|
|
186
|
+
return false;
|
|
187
|
+
const nb = b.map(Number).sort((a, b) => a - b);
|
|
188
|
+
return a.every((v, i) => v === nb[i]);
|
|
189
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseRouter.d.ts","sourceRoot":"","sources":["../../../src/routing/router/BaseRouter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,OAAO,EAAE,EAAa,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,KAAK,MAAM,mBAAmB,CAAC;AACtC,OAAO,IAAI,EAAE,EAAE,eAAe,EAAe,MAAM,YAAY,CAAC;AAChE,OAAO,UAAU,EAAE,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAGhD,MAAM,MAAM,iBAAiB,GAAG,EAAE,GAAG,iBAAiB,CAAC;AAIvD,MAAM,CAAC,OAAO,OAAO,UAAU;IAC9B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IAEpB;;;;;OAKG;IACH,KAAK,EAAE,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAG9B;;;;;OAKG;IACH,IAAI,EAAE,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAG5B;;;;;OAKG;IACH,KAAK,EAAE,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAG9B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAExB;;;OAGG;IACH,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAE3B;;OAEG;IACH,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAElC,kBAAkB,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,aAAa,CAAC;IAEpD;;OAEG;IACH,eAAe,EAAE,CAAC,EAAE,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAE7D,kBAAkB,EAAE,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;IAE/C,UAAU,EAAE,UAAU,CAAC;IAEvB,gBAAgB,EAAE,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAGrC,QAAQ,EAAE,CACT,EAAE,EAAE,aAAa;IACjB;;;OAGG;IACH,aAAa,EAAE,MAAM,KAAK,EAC1B,UAAU,EAAE,CAAC,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,KACjD,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;gBAG3B,KAAK,EAAE,eAAe,EAAE,EACxB,SAAS,EAAE,MAAM,EAAE,EACnB,IAAI,EAAE,iBAAiB;IA0BxB;;OAEG;IACH,WAAW,IAAI,IAAI;IAInB;;OAEG;IACH,WAAW,IAAI,IAAI;IAInB,aAAa,IAAI,IAAI,GAAG,IAAI;IAI5B;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAKjC;;;;;;OAMG;IACH,eAAe,CACd,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,KAAK,GAAG,OAAO,EACtC,IAAI,GAAE,cAAmB,GACvB,OAAO;IA0BV;;;;;OAKG;IACH,cAAc,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAarC,4DAA4D;IACtD,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAIvD,WAAW,CACV,IAAI,EAAE,OAAO,EACb,KAAK,GAAE,cAAmB,GACxB,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAIlB,cAAc,CACnB,IAAI,EAAE,OAAO,EACb,KAAK,GAAE,cAAmB,GACxB,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAIxB;;OAEG;IACH,SAAS,IAAI,OAAO;
|
|
1
|
+
{"version":3,"file":"BaseRouter.d.ts","sourceRoot":"","sources":["../../../src/routing/router/BaseRouter.ts"],"names":[],"mappings":"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"}
|
|
@@ -150,27 +150,25 @@ export default class BaseRouter {
|
|
|
150
150
|
}
|
|
151
151
|
/** You are not allowed to pass in the same request twice */
|
|
152
152
|
async openRequest(_req) {
|
|
153
|
-
throw new Error('
|
|
153
|
+
throw new Error('env specific');
|
|
154
154
|
}
|
|
155
155
|
pushRequest(_req, _opts = {}) {
|
|
156
|
-
throw new Error('
|
|
156
|
+
throw new Error('env specific');
|
|
157
157
|
}
|
|
158
158
|
async replaceRequest(_req, _opts = {}) {
|
|
159
|
-
throw new Error('
|
|
159
|
+
throw new Error('env specific');
|
|
160
160
|
}
|
|
161
161
|
/**
|
|
162
162
|
* Checks if there are previous routes which would allow it to go back
|
|
163
163
|
*/
|
|
164
164
|
canGoBack() {
|
|
165
|
-
|
|
166
|
-
// return this.route.get()?.canGoBack() ?? false;
|
|
165
|
+
return this.route.get()?.canGoBack() ?? false;
|
|
167
166
|
}
|
|
168
167
|
/**
|
|
169
168
|
* Go back in the history
|
|
170
169
|
*/
|
|
171
170
|
back() {
|
|
172
|
-
throw new Error('
|
|
173
|
-
// this.inner.history.back();
|
|
171
|
+
throw new Error('env specific');
|
|
174
172
|
}
|
|
175
173
|
async preload(target) {
|
|
176
174
|
const req = this.targetToRequest(target, { origin: 'preload' });
|
|
@@ -9,7 +9,7 @@ export type ClientRouterOptions = {
|
|
|
9
9
|
export default class ClientRouter extends BaseRouter {
|
|
10
10
|
private scrollDebounceTimeout;
|
|
11
11
|
private preloadOnMouseOver;
|
|
12
|
-
onError: (e: any) => void;
|
|
12
|
+
onError: (e: any, req: Request) => void;
|
|
13
13
|
constructor(sites: SiteFromGraphQl[], opts: ClientRouterOptions);
|
|
14
14
|
/**
|
|
15
15
|
* ## Throws
|
|
@@ -21,6 +21,7 @@ export default class ClientRouter extends BaseRouter {
|
|
|
21
21
|
openRequest(req: Request): Promise<Route | void>;
|
|
22
22
|
pushRequest(req: Request, _opts?: RequestOptions): Promise<void | Route>;
|
|
23
23
|
replaceRequest(req: Request, _opts?: RequestOptions): Promise<void | Route>;
|
|
24
|
+
back(): void;
|
|
24
25
|
/**
|
|
25
26
|
* This returns a route if it was handled else if an error occured
|
|
26
27
|
* or the request was cancelled returns void
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientRouter.d.ts","sourceRoot":"","sources":["../../../src/routing/router/ClientRouter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,UAAU,EAAE,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,MAAM,mBAAmB,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG7C,MAAM,MAAM,mBAAmB,GAAG;IACjC,kBAAkB,EAAE,OAAO,CAAC;CAC5B,GAAG,iBAAiB,CAAC;AAEtB,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,UAAU;IACnD,OAAO,CAAC,qBAAqB,CAAa;IAC1C,OAAO,CAAC,kBAAkB,CAAU;IAEpC,OAAO,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"ClientRouter.d.ts","sourceRoot":"","sources":["../../../src/routing/router/ClientRouter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,UAAU,EAAE,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,MAAM,mBAAmB,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG7C,MAAM,MAAM,mBAAmB,GAAG;IACjC,kBAAkB,EAAE,OAAO,CAAC;CAC5B,GAAG,iBAAiB,CAAC;AAEtB,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,UAAU;IACnD,OAAO,CAAC,qBAAqB,CAAa;IAC1C,OAAO,CAAC,kBAAkB,CAAU;IAEpC,OAAO,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;gBAE5B,KAAK,EAAE,eAAe,EAAE,EAAE,IAAI,EAAE,mBAAmB;IAQ/D;;OAEG;IACG,IAAI;IAuBV;;OAEG;IACG,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IA6ChD,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,cAAmB;IAYpD,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,cAAmB;IAiB7D,IAAI,IAAI,IAAI;IAIZ;;;OAGG;IACG,qBAAqB,CAC1B,GAAG,EAAE,OAAO,EACZ,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GACnC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IASxB,MAAM;IAgEN,QAAQ;IAgCR,YAAY,CAAC,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,GAAG,IAAI;CAwEpD"}
|
|
@@ -87,6 +87,9 @@ export default class ClientRouter extends BaseRouter {
|
|
|
87
87
|
throw e;
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
+
back() {
|
|
91
|
+
window.history.back();
|
|
92
|
+
}
|
|
90
93
|
/**
|
|
91
94
|
* This returns a route if it was handled else if an error occured
|
|
92
95
|
* or the request was cancelled returns void
|
|
@@ -97,7 +100,7 @@ export default class ClientRouter extends BaseRouter {
|
|
|
97
100
|
}
|
|
98
101
|
catch (e) {
|
|
99
102
|
console.error('request failed', e);
|
|
100
|
-
this.onError(e);
|
|
103
|
+
this.onError(e, req);
|
|
101
104
|
}
|
|
102
105
|
}
|
|
103
106
|
listen() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../../src/routing/router/Router.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAEhD;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../../src/routing/router/Router.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// Todo this router should be stateful like globals
|
|
2
|
-
// allow to reference the correct route or request
|
|
3
1
|
export default class Router {
|
|
4
2
|
inner;
|
|
5
3
|
_request;
|
|
@@ -264,6 +262,7 @@ export default class Router {
|
|
|
264
262
|
* On the server this will always return false
|
|
265
263
|
*/
|
|
266
264
|
canGoBack() {
|
|
265
|
+
// todo should this be dependent on the current request?
|
|
267
266
|
return this.inner.canGoBack();
|
|
268
267
|
}
|
|
269
268
|
/**
|
|
@@ -272,6 +271,7 @@ export default class Router {
|
|
|
272
271
|
* On the server this throw an error
|
|
273
272
|
*/
|
|
274
273
|
back() {
|
|
274
|
+
// todo should this be dependent on the current request?
|
|
275
275
|
this.inner.back();
|
|
276
276
|
}
|
|
277
277
|
/**
|
|
@@ -15,6 +15,7 @@ export default class ServerRouter extends BaseRouter {
|
|
|
15
15
|
openRequest(req: Request): Promise<void>;
|
|
16
16
|
pushRequest(req: Request, _opts?: RequestOptions): Promise<void>;
|
|
17
17
|
replaceRequest(req: Request, _opts?: RequestOptions): Promise<void>;
|
|
18
|
+
back(): void;
|
|
18
19
|
/**
|
|
19
20
|
* This function always returns the request or a redirect one
|
|
20
21
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerRouter.d.ts","sourceRoot":"","sources":["../../../src/routing/router/ServerRouter.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,EAAE,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,MAAM,mBAAmB,CAAC;AACtC,OAAO,IAAI,EAAE,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAInD,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,UAAU;IACnD,OAAO,CAAC,QAAQ,CAAc;IAC9B,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;gBAGxB,KAAK,EAAE,eAAe,EAAE,EACxB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,iBAAiB;IAUxB;;;;OAIG;IACH,aAAa,IAAI,IAAI,GAAG,IAAI;IAItB,WAAW,CAAC,GAAG,EAAE,OAAO;IAiBxB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,cAAmB;IAKpD,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,cAAmB;IAK7D;;;;;;;OAOG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC;CAiBzD"}
|
|
1
|
+
{"version":3,"file":"ServerRouter.d.ts","sourceRoot":"","sources":["../../../src/routing/router/ServerRouter.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,EAAE,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,MAAM,mBAAmB,CAAC;AACtC,OAAO,IAAI,EAAE,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAInD,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,UAAU;IACnD,OAAO,CAAC,QAAQ,CAAc;IAC9B,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;gBAGxB,KAAK,EAAE,eAAe,EAAE,EACxB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,iBAAiB;IAUxB;;;;OAIG;IACH,aAAa,IAAI,IAAI,GAAG,IAAI;IAItB,WAAW,CAAC,GAAG,EAAE,OAAO;IAiBxB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,cAAmB;IAKpD,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,cAAmB;IAK7D,IAAI,IAAI,IAAI;IAIZ;;;;;;;OAOG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC;CAiBzD"}
|
|
@@ -41,6 +41,9 @@ export default class ServerRouter extends BaseRouter {
|
|
|
41
41
|
// todo not sure if that is what we want?
|
|
42
42
|
return await this.openRequest(req);
|
|
43
43
|
}
|
|
44
|
+
back() {
|
|
45
|
+
throw new Error('not supported on server');
|
|
46
|
+
}
|
|
44
47
|
/**
|
|
45
48
|
* This function always returns the request or a redirect one
|
|
46
49
|
*
|
|
@@ -82,7 +82,7 @@ export default class ServerRouter {
|
|
|
82
82
|
const { params, handlers } = this.inner.find(req.method, new URL(req.url).pathname);
|
|
83
83
|
if (!handlers.length)
|
|
84
84
|
return null;
|
|
85
|
-
const languages = parseAcceptLanguage(req.headers.get('
|
|
85
|
+
const languages = parseAcceptLanguage(req.headers.get('Accept-Language') ?? '').map(([l]) => l);
|
|
86
86
|
const prefSite = preferredSite(this._sites, languages);
|
|
87
87
|
const site = siteFromUrl(this._sites, new URL(req.url)) ??
|
|
88
88
|
prefSite ??
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/server/queries/routes.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,MAAM,oBAAoB,CAAC;AACrD,OAAO,cAAc,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAQ,MAAM,uBAAuB,CAAC;AAEvD,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAG9C,MAAM,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC;AAG9E,qBAAa,UAAU;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC;IACtC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;gBAG3B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,EACrC,SAAS,EAAE,SAAS,GAAG,IAAI;IAoB5B,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,kBAAkB;IAO1B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAgBzB;;;OAGG;IACH,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAexD,MAAM,CACX,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,mBAAmB,GACtB,OAAO,CAAC,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/server/queries/routes.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,MAAM,oBAAoB,CAAC;AACrD,OAAO,cAAc,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAQ,MAAM,uBAAuB,CAAC;AAEvD,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAG9C,MAAM,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC;AAG9E,qBAAa,UAAU;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC;IACtC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;gBAG3B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,EACrC,SAAS,EAAE,SAAS,GAAG,IAAI;IAoB5B,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,kBAAkB;IAO1B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAgBzB;;;OAGG;IACH,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAexD,MAAM,CACX,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,mBAAmB,GACtB,OAAO,CAAC,QAAQ,CAAC;CAiHpB;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAEzD"}
|
|
@@ -79,6 +79,8 @@ export class QueryRoute {
|
|
|
79
79
|
try {
|
|
80
80
|
const reqVars = await csr.req.json();
|
|
81
81
|
vars = this.validateVars(reqVars, caching.router);
|
|
82
|
+
if ('qName' in vars || 'xCraftSite' in vars)
|
|
83
|
+
throw new Error('qName and xCraftSite are reserved variable names');
|
|
82
84
|
}
|
|
83
85
|
catch (e) {
|
|
84
86
|
return newError(e, 400);
|
|
@@ -96,10 +98,12 @@ export class QueryRoute {
|
|
|
96
98
|
else if (reqSearch.has('siteToken')) {
|
|
97
99
|
siteToken = reqSearch.get('siteToken');
|
|
98
100
|
}
|
|
101
|
+
// check for x-craft-site header and pass it on
|
|
102
|
+
const xCraftSite = csr.req.headers.get('X-Craft-Site');
|
|
99
103
|
let cacheKey = null;
|
|
100
104
|
const useCache = !previewToken && caching.isEnabled();
|
|
101
105
|
if (useCache) {
|
|
102
|
-
cacheKey = await calcKey({
|
|
106
|
+
cacheKey = await calcKey({ ...vars, qName: this.name, xCraftSite });
|
|
103
107
|
const cached = await caching.getCache(cacheKey);
|
|
104
108
|
if (logInfo)
|
|
105
109
|
console.log(`${logInfo} ${cached ? 'hit' : 'miss'}`);
|
|
@@ -121,6 +125,8 @@ export class QueryRoute {
|
|
|
121
125
|
const xDebug = csr.req.headers.get('X-Debug');
|
|
122
126
|
if (xDebug)
|
|
123
127
|
headers['X-Debug'] = xDebug;
|
|
128
|
+
if (xCraftSite)
|
|
129
|
+
headers['X-Craft-Site'] = xCraftSite;
|
|
124
130
|
// now execute the gql request
|
|
125
131
|
let resp;
|
|
126
132
|
try {
|
|
@@ -141,7 +147,7 @@ export class QueryRoute {
|
|
|
141
147
|
return newError(e, 500);
|
|
142
148
|
}
|
|
143
149
|
const respHeaders = {};
|
|
144
|
-
const xDebugLink = resp.headers.get('
|
|
150
|
+
const xDebugLink = resp.headers.get('X-Debug-Link');
|
|
145
151
|
if (xDebugLink)
|
|
146
152
|
respHeaders['X-Debug'] = xDebugLink;
|
|
147
153
|
let jsonResp;
|
package/dist/server/shared.js
CHANGED
|
@@ -96,7 +96,7 @@ export async function modRender(env, mod, template, req, opts = {}) {
|
|
|
96
96
|
return new Response(html, { status, headers: nHeaders });
|
|
97
97
|
}
|
|
98
98
|
export async function modRenderError(env, mod, thrownError, template, req, opts = {}) {
|
|
99
|
-
const acceptLang = req.headers.get('
|
|
99
|
+
const acceptLang = req.headers.get('Accept-Language') ?? null;
|
|
100
100
|
// in the case of an error let's try to render a nice Error Page
|
|
101
101
|
const error = {
|
|
102
102
|
status: 500,
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@ export default class ServerCookies implements Cookies {
|
|
|
10
10
|
setCookies: Map<string, SetCookie>;
|
|
11
11
|
|
|
12
12
|
constructor(headers: Headers) {
|
|
13
|
-
this.requestCookies = parseCookies(headers.get('
|
|
13
|
+
this.requestCookies = parseCookies(headers.get('Cookie') ?? '');
|
|
14
14
|
this.setCookies = new Map();
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -35,7 +35,7 @@ export default class ServerCookies implements Cookies {
|
|
|
35
35
|
|
|
36
36
|
_populateHeaders(headers: Headers) {
|
|
37
37
|
for (const setCookie of this.setCookies.values()) {
|
|
38
|
-
headers.append('
|
|
38
|
+
headers.append('Set-Cookie', setCookieToString(setCookie));
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
package/src/init/client.ts
CHANGED
|
@@ -124,11 +124,11 @@ export async function main(data: MainData) {
|
|
|
124
124
|
});
|
|
125
125
|
};
|
|
126
126
|
|
|
127
|
-
router.onError = e => {
|
|
127
|
+
router.onError = (e, req) => {
|
|
128
128
|
console.error('routing failed:', e, 'reloading trying to fix it');
|
|
129
129
|
// since onError is called only on subsequent requests we should never
|
|
130
130
|
// have an infinite loop here
|
|
131
|
-
window.location.
|
|
131
|
+
window.location.href = req.url.href;
|
|
132
132
|
};
|
|
133
133
|
|
|
134
134
|
router.onRender = async (cr, readyForRoute, domUpdated) => {
|
package/src/init/server.ts
CHANGED
|
@@ -73,7 +73,7 @@ export async function main(data: MainData): Promise<RenderResponse> {
|
|
|
73
73
|
ssrCache.set('crelteSites', data.serverData.sites);
|
|
74
74
|
const router = new ServerRouter(
|
|
75
75
|
data.serverData.sites,
|
|
76
|
-
data.serverData.headers.get('
|
|
76
|
+
data.serverData.headers.get('Accept-Language') ?? '',
|
|
77
77
|
{ debugTiming: config.debugTiming ?? false },
|
|
78
78
|
);
|
|
79
79
|
|
package/src/queries/Queries.ts
CHANGED
|
@@ -304,8 +304,8 @@ class Inner {
|
|
|
304
304
|
);
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
-
if (resp.headers.get('
|
|
308
|
-
console.log('Debug link', resp.headers.get('
|
|
307
|
+
if (resp.headers.get('X-Debug-Link'))
|
|
308
|
+
console.log('Debug link', resp.headers.get('X-Debug-Link'));
|
|
309
309
|
|
|
310
310
|
if (timing) {
|
|
311
311
|
console.log(
|
package/src/queries/index.ts
CHANGED
|
@@ -6,7 +6,7 @@ import Queries, {
|
|
|
6
6
|
} from '../queries/Queries.js';
|
|
7
7
|
import { gql } from './gql.js';
|
|
8
8
|
import QueryError from './QueryError.js';
|
|
9
|
-
import { QueryVar, ValidIf, vars } from './vars.js';
|
|
9
|
+
import { QueryVar, ValidIf, vars, varsIdsEqual } from './vars.js';
|
|
10
10
|
|
|
11
11
|
export {
|
|
12
12
|
Queries,
|
|
@@ -19,6 +19,7 @@ export {
|
|
|
19
19
|
vars,
|
|
20
20
|
type ValidIf,
|
|
21
21
|
QueryVar,
|
|
22
|
+
varsIdsEqual,
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
type InferQueryVarType<T> = T extends QueryVar<infer U> ? U : never;
|
package/src/queries/vars.ts
CHANGED
|
@@ -22,6 +22,8 @@ export const vars = {
|
|
|
22
22
|
* the returned array will **never be empty**, but might be null if
|
|
23
23
|
* allowed. Id's are always non negative integers
|
|
24
24
|
*
|
|
25
|
+
* The numbers are always unique and sorted in ascending order
|
|
26
|
+
*
|
|
25
27
|
* ## Warning
|
|
26
28
|
* Ids are not automatically safe to be cached, it is also not
|
|
27
29
|
* enough to just check if the filter returned some results.
|
|
@@ -122,7 +124,7 @@ export class QueryVar<T = any> {
|
|
|
122
124
|
break;
|
|
123
125
|
|
|
124
126
|
case 'id':
|
|
125
|
-
if (typeof v === 'string') v =
|
|
127
|
+
if (typeof v === 'string') v = Number(v);
|
|
126
128
|
|
|
127
129
|
if (!isValidId(v))
|
|
128
130
|
throw new Error(`variable ${this.name} is not a valid id`);
|
|
@@ -144,7 +146,7 @@ export class QueryVar<T = any> {
|
|
|
144
146
|
}
|
|
145
147
|
|
|
146
148
|
// convert strings to numbers
|
|
147
|
-
v = v.map(
|
|
149
|
+
v = v.map(Number);
|
|
148
150
|
|
|
149
151
|
if (!v.every(isValidId))
|
|
150
152
|
throw new Error(
|
|
@@ -185,3 +187,50 @@ export function isQueryVar(v: any): v is QueryVar {
|
|
|
185
187
|
function isValidId(id: any): id is number {
|
|
186
188
|
return typeof id === 'number' && Number.isInteger(id) && id >= 0;
|
|
187
189
|
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Checks if two id arrays are equal
|
|
193
|
+
*
|
|
194
|
+
* The first argument needs to come from a `vars.ids()` variable.
|
|
195
|
+
* The second argument should come from a query, where the output is trusted.
|
|
196
|
+
*
|
|
197
|
+
* ## Example
|
|
198
|
+
* ```
|
|
199
|
+
* export const variables = {
|
|
200
|
+
* categories: vars.ids()
|
|
201
|
+
* };
|
|
202
|
+
*
|
|
203
|
+
* export const caching: Caching<typeof variables> = (res, vars) => {
|
|
204
|
+
* // res is the graphql response
|
|
205
|
+
* return varsIdsEqual(vars.categories, res.categories);
|
|
206
|
+
* };
|
|
207
|
+
* ```
|
|
208
|
+
*
|
|
209
|
+
* ## Note
|
|
210
|
+
* The following cases are considered equal:
|
|
211
|
+
* ```
|
|
212
|
+
* varsIdsEqual(null, null);
|
|
213
|
+
* varsIdsEqual([], null);
|
|
214
|
+
* varsIdsEqual([1,2], ['2',1]);
|
|
215
|
+
* ```
|
|
216
|
+
* These are not equal:
|
|
217
|
+
* ```
|
|
218
|
+
* varsIdsEqual([1], null);
|
|
219
|
+
* varsIdsEqual([2,1], [2,1]); // because the second arg gets ordered
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
222
|
+
export function varsIdsEqual(
|
|
223
|
+
a: number[] | null | undefined,
|
|
224
|
+
b: (string | number)[] | null | undefined,
|
|
225
|
+
): boolean {
|
|
226
|
+
const aEmpty = !a?.length;
|
|
227
|
+
const bEmpty = !b?.length;
|
|
228
|
+
if (aEmpty && bEmpty) return true;
|
|
229
|
+
if (aEmpty || bEmpty) return false;
|
|
230
|
+
|
|
231
|
+
if (a.length !== b.length) return false;
|
|
232
|
+
|
|
233
|
+
const nb = b.map(Number).sort((a, b) => a - b);
|
|
234
|
+
|
|
235
|
+
return a.every((v, i) => v === nb[i]);
|
|
236
|
+
}
|
|
@@ -198,37 +198,35 @@ export default class BaseRouter {
|
|
|
198
198
|
|
|
199
199
|
/** You are not allowed to pass in the same request twice */
|
|
200
200
|
async openRequest(_req: Request): Promise<Route | void> {
|
|
201
|
-
throw new Error('
|
|
201
|
+
throw new Error('env specific');
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
pushRequest(
|
|
205
205
|
_req: Request,
|
|
206
206
|
_opts: RequestOptions = {},
|
|
207
207
|
): Promise<Route | void> {
|
|
208
|
-
throw new Error('
|
|
208
|
+
throw new Error('env specific');
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
async replaceRequest(
|
|
212
212
|
_req: Request,
|
|
213
213
|
_opts: RequestOptions = {},
|
|
214
214
|
): Promise<Route | void> {
|
|
215
|
-
throw new Error('
|
|
215
|
+
throw new Error('env specific');
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
/**
|
|
219
219
|
* Checks if there are previous routes which would allow it to go back
|
|
220
220
|
*/
|
|
221
221
|
canGoBack(): boolean {
|
|
222
|
-
|
|
223
|
-
// return this.route.get()?.canGoBack() ?? false;
|
|
222
|
+
return this.route.get()?.canGoBack() ?? false;
|
|
224
223
|
}
|
|
225
224
|
|
|
226
225
|
/**
|
|
227
226
|
* Go back in the history
|
|
228
227
|
*/
|
|
229
228
|
back() {
|
|
230
|
-
throw new Error('
|
|
231
|
-
// this.inner.history.back();
|
|
229
|
+
throw new Error('env specific');
|
|
232
230
|
}
|
|
233
231
|
|
|
234
232
|
async preload(target: string | URL | Route | Request) {
|
|
@@ -13,7 +13,7 @@ export default class ClientRouter extends BaseRouter {
|
|
|
13
13
|
private scrollDebounceTimeout: any | null;
|
|
14
14
|
private preloadOnMouseOver: boolean;
|
|
15
15
|
|
|
16
|
-
onError: (e: any) => void;
|
|
16
|
+
onError: (e: any, req: Request) => void;
|
|
17
17
|
|
|
18
18
|
constructor(sites: SiteFromGraphQl[], opts: ClientRouterOptions) {
|
|
19
19
|
super(sites, navigator.languages.slice(), opts);
|
|
@@ -126,6 +126,10 @@ export default class ClientRouter extends BaseRouter {
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
back(): void {
|
|
130
|
+
window.history.back();
|
|
131
|
+
}
|
|
132
|
+
|
|
129
133
|
/**
|
|
130
134
|
* This returns a route if it was handled else if an error occured
|
|
131
135
|
* or the request was cancelled returns void
|
|
@@ -138,7 +142,7 @@ export default class ClientRouter extends BaseRouter {
|
|
|
138
142
|
return await this.handleRequest(req, updateHistory);
|
|
139
143
|
} catch (e) {
|
|
140
144
|
console.error('request failed', e);
|
|
141
|
-
this.onError(e);
|
|
145
|
+
this.onError(e, req);
|
|
142
146
|
}
|
|
143
147
|
}
|
|
144
148
|
|
|
@@ -16,8 +16,6 @@ import { Entry } from '../../loadData/index.js';
|
|
|
16
16
|
*/
|
|
17
17
|
export type UpdateRequest = (req: Request) => boolean | null | undefined | void;
|
|
18
18
|
|
|
19
|
-
// Todo this router should be stateful like globals
|
|
20
|
-
// allow to reference the correct route or request
|
|
21
19
|
export default class Router {
|
|
22
20
|
private inner: BaseRouter;
|
|
23
21
|
private _request: Request | null;
|
|
@@ -308,6 +306,7 @@ export default class Router {
|
|
|
308
306
|
* On the server this will always return false
|
|
309
307
|
*/
|
|
310
308
|
canGoBack(): boolean {
|
|
309
|
+
// todo should this be dependent on the current request?
|
|
311
310
|
return this.inner.canGoBack();
|
|
312
311
|
}
|
|
313
312
|
|
|
@@ -317,6 +316,7 @@ export default class Router {
|
|
|
317
316
|
* On the server this throw an error
|
|
318
317
|
*/
|
|
319
318
|
back() {
|
|
319
|
+
// todo should this be dependent on the current request?
|
|
320
320
|
this.inner.back();
|
|
321
321
|
}
|
|
322
322
|
|
|
@@ -121,7 +121,7 @@ export default class ServerRouter {
|
|
|
121
121
|
if (!handlers.length) return null;
|
|
122
122
|
|
|
123
123
|
const languages = parseAcceptLanguage(
|
|
124
|
-
req.headers.get('
|
|
124
|
+
req.headers.get('Accept-Language') ?? '',
|
|
125
125
|
).map(([l]) => l);
|
|
126
126
|
const prefSite = preferredSite(this._sites, languages);
|
|
127
127
|
const site =
|
|
@@ -104,6 +104,10 @@ export class QueryRoute {
|
|
|
104
104
|
try {
|
|
105
105
|
const reqVars = await csr.req.json();
|
|
106
106
|
vars = this.validateVars(reqVars, caching.router);
|
|
107
|
+
if ('qName' in vars || 'xCraftSite' in vars)
|
|
108
|
+
throw new Error(
|
|
109
|
+
'qName and xCraftSite are reserved variable names',
|
|
110
|
+
);
|
|
107
111
|
} catch (e) {
|
|
108
112
|
return newError(e, 400);
|
|
109
113
|
}
|
|
@@ -124,10 +128,13 @@ export class QueryRoute {
|
|
|
124
128
|
siteToken = reqSearch.get('siteToken');
|
|
125
129
|
}
|
|
126
130
|
|
|
131
|
+
// check for x-craft-site header and pass it on
|
|
132
|
+
const xCraftSite = csr.req.headers.get('X-Craft-Site');
|
|
133
|
+
|
|
127
134
|
let cacheKey: string | null = null;
|
|
128
135
|
const useCache = !previewToken && caching.isEnabled();
|
|
129
136
|
if (useCache) {
|
|
130
|
-
cacheKey = await calcKey({
|
|
137
|
+
cacheKey = await calcKey({ ...vars, qName: this.name, xCraftSite });
|
|
131
138
|
const cached = await caching.getCache(cacheKey);
|
|
132
139
|
|
|
133
140
|
if (logInfo) console.log(`${logInfo} ${cached ? 'hit' : 'miss'}`);
|
|
@@ -150,6 +157,8 @@ export class QueryRoute {
|
|
|
150
157
|
const xDebug = csr.req.headers.get('X-Debug');
|
|
151
158
|
if (xDebug) headers['X-Debug'] = xDebug;
|
|
152
159
|
|
|
160
|
+
if (xCraftSite) headers['X-Craft-Site'] = xCraftSite;
|
|
161
|
+
|
|
153
162
|
// now execute the gql request
|
|
154
163
|
let resp: Response;
|
|
155
164
|
try {
|
|
@@ -170,7 +179,7 @@ export class QueryRoute {
|
|
|
170
179
|
}
|
|
171
180
|
|
|
172
181
|
const respHeaders: Record<string, string> = {};
|
|
173
|
-
const xDebugLink = resp.headers.get('
|
|
182
|
+
const xDebugLink = resp.headers.get('X-Debug-Link');
|
|
174
183
|
if (xDebugLink) respHeaders['X-Debug'] = xDebugLink;
|
|
175
184
|
|
|
176
185
|
let jsonResp: Record<string, any>;
|
package/src/server/shared.ts
CHANGED
|
@@ -219,7 +219,7 @@ export async function modRenderError(
|
|
|
219
219
|
req: Request,
|
|
220
220
|
opts: ModRenderOptions = {},
|
|
221
221
|
): Promise<Response> {
|
|
222
|
-
const acceptLang = req.headers.get('
|
|
222
|
+
const acceptLang = req.headers.get('Accept-Language') ?? null;
|
|
223
223
|
|
|
224
224
|
// in the case of an error let's try to render a nice Error Page
|
|
225
225
|
const error = {
|