crelte 0.5.13 → 0.5.15
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/queries/Queries.d.ts +3 -0
- package/dist/queries/Queries.d.ts.map +1 -1
- package/dist/queries/Queries.js +3 -0
- package/dist/queries/index.d.ts +21 -0
- package/dist/queries/index.d.ts.map +1 -1
- package/dist/queries/vars.d.ts +25 -2
- package/dist/queries/vars.d.ts.map +1 -1
- package/dist/queries/vars.js +42 -1
- package/dist/routing/route/BaseRoute.d.ts.map +1 -1
- package/dist/routing/route/BaseRoute.js +4 -17
- package/dist/server/Request.d.ts +2 -2
- package/dist/server/Request.js +2 -2
- package/dist/server/queries/QueryGqlRoute.d.ts +3 -1
- package/dist/server/queries/QueryGqlRoute.d.ts.map +1 -1
- package/dist/server/queries/QueryGqlRoute.js +4 -2
- package/dist/server/queries/QueryHandleRoute.d.ts +3 -2
- package/dist/server/queries/QueryHandleRoute.d.ts.map +1 -1
- package/dist/server/queries/QueryHandleRoute.js +4 -2
- package/dist/server/queries/queries.d.ts.map +1 -1
- package/dist/server/queries/queries.js +12 -2
- package/dist/server/queries/routes.d.ts +3 -2
- package/dist/server/queries/routes.d.ts.map +1 -1
- package/dist/server/queries/routes.js +9 -3
- package/dist/static/index.d.ts +1 -1
- package/dist/std/index.d.ts +1 -0
- package/dist/std/index.d.ts.map +1 -1
- package/dist/std/index.js +1 -0
- package/dist/std/url/index.d.ts +40 -0
- package/dist/std/url/index.d.ts.map +1 -0
- package/dist/std/url/index.js +65 -0
- package/dist/std/url/utils.d.ts +19 -0
- package/dist/std/url/utils.d.ts.map +1 -0
- package/dist/std/url/utils.js +40 -0
- package/dist/translations/index.d.ts +2 -2
- package/dist/translations/index.d.ts.map +1 -1
- package/dist/translations/translationsPlugin.d.ts +4 -1
- package/dist/translations/translationsPlugin.d.ts.map +1 -1
- package/dist/translations/translationsPlugin.js +32 -2
- package/dist/vite/index.js +3 -2
- package/package.json +5 -1
- package/src/queries/Queries.ts +3 -0
- package/src/queries/index.ts +25 -0
- package/src/queries/vars.ts +58 -3
- package/src/routing/route/BaseRoute.ts +8 -22
- package/src/server/Request.ts +2 -2
- package/src/server/queries/QueryGqlRoute.ts +17 -2
- package/src/server/queries/QueryHandleRoute.ts +5 -2
- package/src/server/queries/queries.ts +29 -3
- package/src/server/queries/routes.ts +17 -3
- package/src/static/index.ts +1 -1
- package/src/std/index.ts +1 -0
- package/src/std/url/index.ts +78 -0
- package/src/std/url/utils.ts +48 -0
- package/src/translations/index.ts +2 -0
- package/src/translations/translationsPlugin.ts +46 -3
- package/src/vite/index.ts +4 -2
|
@@ -4,6 +4,12 @@ import ServerRouter from '../ServerRouter.js';
|
|
|
4
4
|
|
|
5
5
|
export type CacheIfFn = (response: any, vars: Record<string, any>) => boolean;
|
|
6
6
|
|
|
7
|
+
/// Either throw or return a boolean
|
|
8
|
+
export type ValidIfFn = (
|
|
9
|
+
vars: Record<string, any>,
|
|
10
|
+
sr: ServerRouter,
|
|
11
|
+
) => void | boolean;
|
|
12
|
+
|
|
7
13
|
/// Anything other than returning undefined will replace the response
|
|
8
14
|
//
|
|
9
15
|
// Note that even if you return undefined since the response is by reference
|
|
@@ -20,13 +26,14 @@ export type HandleFn = (
|
|
|
20
26
|
) => Promise<any> | any;
|
|
21
27
|
|
|
22
28
|
/**
|
|
23
|
-
* Returns the validated variables if some vars
|
|
29
|
+
* Returns the validated variables if some vars were defined
|
|
24
30
|
* else just returns all vars
|
|
25
31
|
*/
|
|
26
32
|
export function validateVars(
|
|
27
33
|
qvars: Record<string, QueryVar> | null,
|
|
28
34
|
vars: any,
|
|
29
|
-
|
|
35
|
+
validIfFn: ValidIfFn | null,
|
|
36
|
+
sr: ServerRouter,
|
|
30
37
|
): Record<string, any> {
|
|
31
38
|
if (!vars || typeof vars !== 'object')
|
|
32
39
|
throw new Error('expected an object as vars');
|
|
@@ -36,7 +43,14 @@ export function validateVars(
|
|
|
36
43
|
const nVars: Record<string, any> = {};
|
|
37
44
|
|
|
38
45
|
for (const [k, v] of Object.entries(qvars)) {
|
|
39
|
-
nVars[k] = v.validValue(vars[k],
|
|
46
|
+
nVars[k] = v.validValue(vars[k], sr);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (validIfFn) {
|
|
50
|
+
// or throw
|
|
51
|
+
const valid = validIfFn(nVars, sr);
|
|
52
|
+
if (typeof valid === 'boolean' && !valid)
|
|
53
|
+
throw new Error('invalid variables for query');
|
|
40
54
|
}
|
|
41
55
|
|
|
42
56
|
return nVars;
|
package/src/static/index.ts
CHANGED
package/src/std/index.ts
CHANGED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { BaseRoute } from '../../routing/index.js';
|
|
2
|
+
import { deleteSearchParam, pathnameEq, searchEq, toUrl } from './utils.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Sets the search params of a URL based on the provided options.
|
|
6
|
+
*
|
|
7
|
+
* If a value is `null`, `undefined`, or an empty string, the corresponding
|
|
8
|
+
* search param will be deleted.
|
|
9
|
+
*
|
|
10
|
+
* #### Example
|
|
11
|
+
* ```js
|
|
12
|
+
* urlWithSearch(entry.url, { p: 1 });
|
|
13
|
+
* // or remove a value
|
|
14
|
+
* urlWithSearch(entry.url, { p: null });
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function urlWithSearch(
|
|
18
|
+
url: BaseRoute | URL | string | null | undefined,
|
|
19
|
+
opts: Record<string, string | number | null | undefined>,
|
|
20
|
+
): string | null {
|
|
21
|
+
if (!url) return null;
|
|
22
|
+
|
|
23
|
+
url = toUrl(url);
|
|
24
|
+
|
|
25
|
+
for (const [k, v] of Object.entries(opts)) {
|
|
26
|
+
if (!deleteSearchParam(v)) {
|
|
27
|
+
url.searchParams.set(k, v as string);
|
|
28
|
+
} else {
|
|
29
|
+
url.searchParams.delete(k);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return url.href;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Compares two URLs for equality.
|
|
38
|
+
* Normally search and hash are ignored.
|
|
39
|
+
*
|
|
40
|
+
* If either or both url is `null` or `undefined`, the function will return
|
|
41
|
+
* `false`.
|
|
42
|
+
*
|
|
43
|
+
* #### Example
|
|
44
|
+
* ```svelte
|
|
45
|
+
* <script>
|
|
46
|
+
* import { getRoute } from 'crelte';
|
|
47
|
+
*
|
|
48
|
+
* const route = getRoute();
|
|
49
|
+
* </script>
|
|
50
|
+
*
|
|
51
|
+
* <a href={item.url} class:active={urlEq($route, item.url)}>
|
|
52
|
+
* {item.title}
|
|
53
|
+
* </a>
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export function urlEq(
|
|
57
|
+
a: BaseRoute | URL | string | null | undefined,
|
|
58
|
+
b: BaseRoute | URL | string | null | undefined,
|
|
59
|
+
opts?: { search?: boolean; hash?: boolean },
|
|
60
|
+
): boolean {
|
|
61
|
+
if (!a || !b) return false;
|
|
62
|
+
|
|
63
|
+
a = toUrl(a);
|
|
64
|
+
b = toUrl(b);
|
|
65
|
+
|
|
66
|
+
// check origin and pathname
|
|
67
|
+
const baseMatches =
|
|
68
|
+
a.origin === b.origin && pathnameEq(a.pathname, b.pathname);
|
|
69
|
+
if (!baseMatches) return false;
|
|
70
|
+
|
|
71
|
+
// check search
|
|
72
|
+
if (opts?.search && !searchEq(a.searchParams, b.searchParams)) return false;
|
|
73
|
+
|
|
74
|
+
// check hash
|
|
75
|
+
if (opts?.hash && a.hash !== b.hash) return false;
|
|
76
|
+
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { BaseRoute } from '../../routing/index.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Checks if a search param should be removed.
|
|
5
|
+
* This is the case if the value is `null`, `undefined`, or an empty string.
|
|
6
|
+
*/
|
|
7
|
+
export function deleteSearchParam(value: string | number | null | undefined) {
|
|
8
|
+
return (
|
|
9
|
+
typeof value === 'undefined' ||
|
|
10
|
+
value === null ||
|
|
11
|
+
(typeof value === 'string' && value === '')
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Converts a `BaseRoute`, `URL`, or string to a `URL` object.
|
|
17
|
+
*/
|
|
18
|
+
export function toUrl(url: BaseRoute | URL | string): URL {
|
|
19
|
+
if (typeof url === 'string') return new URL(url);
|
|
20
|
+
|
|
21
|
+
if (url instanceof BaseRoute) return new URL(url.url);
|
|
22
|
+
|
|
23
|
+
return url;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Compares two `URLSearchParams` objects for equality.
|
|
28
|
+
*/
|
|
29
|
+
export function searchEq(a: URLSearchParams, b: URLSearchParams): boolean {
|
|
30
|
+
if (a.size !== b.size) return false;
|
|
31
|
+
|
|
32
|
+
// Clone to avoid mutating the original objects
|
|
33
|
+
const cloneA = new URLSearchParams(a);
|
|
34
|
+
const cloneB = new URLSearchParams(b);
|
|
35
|
+
|
|
36
|
+
cloneA.sort();
|
|
37
|
+
cloneB.sort();
|
|
38
|
+
|
|
39
|
+
return cloneA.toString() === cloneB.toString();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Compares two pathnames for equality, ignoring trailing slashes.
|
|
44
|
+
*/
|
|
45
|
+
export function pathnameEq(a: string, b: string): boolean {
|
|
46
|
+
// check for trailing slashes
|
|
47
|
+
return a === b || a === b + '/' || a + '/' === b;
|
|
48
|
+
}
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
createTranslations,
|
|
14
14
|
getTranslationsPlugin,
|
|
15
15
|
type TranslateFunction,
|
|
16
|
+
type TranslationVarValue,
|
|
16
17
|
type TranslateStore,
|
|
17
18
|
type Translations,
|
|
18
19
|
TranslationsPlugin,
|
|
@@ -50,6 +51,7 @@ export {
|
|
|
50
51
|
LoaderCreator,
|
|
51
52
|
TranslateStore,
|
|
52
53
|
TranslateFunction,
|
|
54
|
+
TranslationVarValue,
|
|
53
55
|
// loaders
|
|
54
56
|
createFileLoader,
|
|
55
57
|
createGlobalLoader,
|
|
@@ -7,8 +7,9 @@ import { getCrelte } from '../index.js';
|
|
|
7
7
|
|
|
8
8
|
export type TranslateFunction = (
|
|
9
9
|
key: string,
|
|
10
|
-
|
|
10
|
+
vars?: Record<string, TranslationVarValue>,
|
|
11
11
|
) => string;
|
|
12
|
+
export type TranslationVarValue = string | number;
|
|
12
13
|
export type TranslateStore = Readable<TranslateFunction>;
|
|
13
14
|
export type Translations = Record<string, string>;
|
|
14
15
|
export type TranslationsPluginOptions = {
|
|
@@ -89,18 +90,60 @@ export class TranslationsPlugin implements Plugin {
|
|
|
89
90
|
/** @hidden */
|
|
90
91
|
z_createTranslateStore(namespace: string): TranslateStore {
|
|
91
92
|
const store = derived(this.crelte.router.site, site => {
|
|
92
|
-
return (
|
|
93
|
+
return (
|
|
94
|
+
key: string,
|
|
95
|
+
vars?: Record<string, TranslationVarValue>,
|
|
96
|
+
) => {
|
|
93
97
|
const lang = site?.language ?? this.firstLang;
|
|
94
98
|
if (!lang) throw new Error('no lang');
|
|
95
99
|
|
|
96
100
|
const data = this.get(lang, namespace);
|
|
97
101
|
if (!data) console.error(`namespace '${namespace}' not loaded`);
|
|
98
|
-
|
|
102
|
+
|
|
103
|
+
const text = data?.[key] || key;
|
|
104
|
+
if (!vars) return text;
|
|
105
|
+
return this.z_resolveVariables(text, vars);
|
|
99
106
|
};
|
|
100
107
|
});
|
|
101
108
|
|
|
102
109
|
return new Readable(store);
|
|
103
110
|
}
|
|
111
|
+
|
|
112
|
+
/** @hidden */
|
|
113
|
+
z_resolveVariables(
|
|
114
|
+
text: string,
|
|
115
|
+
vars: Record<string, TranslationVarValue> = {},
|
|
116
|
+
): string {
|
|
117
|
+
let result = '';
|
|
118
|
+
let index = 0;
|
|
119
|
+
|
|
120
|
+
while (index < text.length) {
|
|
121
|
+
const openIndex = text.indexOf('{', index);
|
|
122
|
+
if (openIndex === -1) {
|
|
123
|
+
result += text.slice(index);
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const closeIndex = text.indexOf('}', openIndex + 1);
|
|
128
|
+
if (closeIndex === -1) {
|
|
129
|
+
result += text.slice(index);
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
result += text.slice(index, openIndex);
|
|
134
|
+
|
|
135
|
+
const key = text.slice(openIndex + 1, closeIndex);
|
|
136
|
+
if (key in vars) {
|
|
137
|
+
result += vars[key];
|
|
138
|
+
} else {
|
|
139
|
+
result += `{${key}}`;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
index = closeIndex + 1;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
104
147
|
}
|
|
105
148
|
|
|
106
149
|
/**
|
package/src/vite/index.ts
CHANGED
|
@@ -180,7 +180,7 @@ export default function crelte(opts?: CrelteOptions): Plugin {
|
|
|
180
180
|
publicDir: isSsrBuild ? false : 'public',
|
|
181
181
|
base: '/',
|
|
182
182
|
server: {
|
|
183
|
-
port: 8080,
|
|
183
|
+
port: config.server?.port ?? 8080,
|
|
184
184
|
},
|
|
185
185
|
optimizeDeps: {
|
|
186
186
|
exclude: ['crelte'],
|
|
@@ -338,7 +338,9 @@ async function serveVite(env: EnvData, vite: ViteDevServer) {
|
|
|
338
338
|
nReq: Connect.IncomingMessage,
|
|
339
339
|
res: ServerResponse,
|
|
340
340
|
) => {
|
|
341
|
-
const protocol =
|
|
341
|
+
const protocol =
|
|
342
|
+
(nReq.headers['x-forwarded-proto'] as string | undefined) ??
|
|
343
|
+
(vite.config.server.https ? 'https' : 'http');
|
|
342
344
|
const baseUrl = protocol + '://' + nReq.headers['host'];
|
|
343
345
|
|
|
344
346
|
const req = requestToWebRequest(baseUrl, nReq);
|