crelte 0.5.10 → 0.5.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bodyClass/BodyClass.d.ts +39 -0
- package/dist/bodyClass/BodyClass.d.ts.map +1 -0
- package/dist/bodyClass/BodyClass.js +51 -0
- package/dist/bodyClass/ClientBodyClass.d.ts +12 -0
- package/dist/bodyClass/ClientBodyClass.d.ts.map +1 -0
- package/dist/bodyClass/ClientBodyClass.js +57 -0
- package/dist/bodyClass/ServerBodyClass.d.ts +12 -0
- package/dist/bodyClass/ServerBodyClass.d.ts.map +1 -0
- package/dist/bodyClass/ServerBodyClass.js +47 -0
- package/dist/bodyClass/index.d.ts +2 -0
- package/dist/bodyClass/index.d.ts.map +1 -0
- package/dist/bodyClass/index.js +1 -0
- package/dist/cookies/ClientCookies.d.ts +8 -3
- package/dist/cookies/ClientCookies.d.ts.map +1 -1
- package/dist/cookies/ClientCookies.js +31 -7
- package/dist/cookies/Cookies.d.ts +42 -0
- package/dist/cookies/Cookies.d.ts.map +1 -0
- package/dist/cookies/Cookies.js +44 -0
- package/dist/cookies/ServerCookies.d.ts +3 -2
- package/dist/cookies/ServerCookies.d.ts.map +1 -1
- package/dist/cookies/ServerCookies.js +6 -4
- package/dist/cookies/index.d.ts +1 -25
- package/dist/cookies/index.d.ts.map +1 -1
- package/dist/cookies/index.js +1 -1
- package/dist/crelte.d.ts +7 -1
- package/dist/crelte.d.ts.map +1 -1
- package/dist/crelte.js +2 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/init/client.d.ts +1 -8
- package/dist/init/client.d.ts.map +1 -1
- package/dist/init/client.js +26 -24
- package/dist/init/server.d.ts.map +1 -1
- package/dist/init/server.js +12 -4
- package/dist/init/shared.d.ts +1 -0
- package/dist/init/shared.d.ts.map +1 -1
- package/dist/init/shared.js +16 -5
- package/dist/loadData/Globals.d.ts.map +1 -1
- package/dist/node/index.js +1 -1
- package/dist/plugins/Events.d.ts +12 -7
- package/dist/plugins/Events.d.ts.map +1 -1
- package/dist/plugins/Plugins.d.ts +36 -1
- package/dist/plugins/Plugins.d.ts.map +1 -1
- package/dist/plugins/Plugins.js +32 -0
- package/dist/queries/Queries.d.ts +30 -5
- package/dist/queries/Queries.d.ts.map +1 -1
- package/dist/queries/Queries.js +19 -2
- package/dist/queries/gql.d.ts +2 -2
- package/dist/queries/gql.d.ts.map +1 -1
- package/dist/queries/index.d.ts +47 -2
- package/dist/queries/index.d.ts.map +1 -1
- package/dist/queries/index.js +2 -2
- package/dist/queries/vars.d.ts +2 -0
- package/dist/queries/vars.d.ts.map +1 -1
- package/dist/queries/vars.js +10 -0
- package/dist/routing/route/Request.d.ts +1 -1
- package/dist/routing/route/Request.d.ts.map +1 -1
- package/dist/routing/route/Request.js +7 -3
- package/dist/routing/router/BaseRouter.d.ts +2 -1
- package/dist/routing/router/BaseRouter.d.ts.map +1 -1
- package/dist/routing/router/BaseRouter.js +4 -2
- package/dist/routing/router/ClientRouter.d.ts.map +1 -1
- package/dist/routing/router/ClientRouter.js +21 -15
- package/dist/routing/router/Router.d.ts +2 -1
- package/dist/routing/router/Router.d.ts.map +1 -1
- package/dist/routing/router/Router.js +10 -13
- package/dist/routing/utils.d.ts +1 -0
- package/dist/routing/utils.d.ts.map +1 -1
- package/dist/routing/utils.js +1 -1
- package/dist/server/CrelteServer.d.ts +1 -0
- package/dist/server/CrelteServer.d.ts.map +1 -1
- package/dist/server/CrelteServer.js +5 -2
- package/dist/server/ServerRouter.d.ts.map +1 -1
- package/dist/server/ServerRouter.js +17 -7
- package/dist/server/queries/QueryGqlRoute.d.ts +28 -0
- package/dist/server/queries/QueryGqlRoute.d.ts.map +1 -0
- package/dist/server/queries/QueryGqlRoute.js +194 -0
- package/dist/server/queries/QueryHandleRoute.d.ts +12 -0
- package/dist/server/queries/QueryHandleRoute.d.ts.map +1 -0
- package/dist/server/queries/QueryHandleRoute.js +24 -0
- package/dist/server/queries/queries.d.ts.map +1 -1
- package/dist/server/queries/queries.js +42 -19
- package/dist/server/queries/routes.d.ts +7 -30
- package/dist/server/queries/routes.d.ts.map +1 -1
- package/dist/server/queries/routes.js +13 -199
- package/dist/std/stores/StagedWritable.d.ts +48 -0
- package/dist/std/stores/StagedWritable.d.ts.map +1 -0
- package/dist/std/stores/StagedWritable.js +84 -0
- package/dist/std/stores/index.d.ts +2 -1
- package/dist/std/stores/index.d.ts.map +1 -1
- package/dist/std/stores/index.js +2 -1
- package/dist/std/sync/Barrier.js +1 -1
- package/dist/utils.d.ts +9 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +11 -0
- package/package.json +5 -1
- package/src/bodyClass/BodyClass.ts +72 -0
- package/src/bodyClass/ClientBodyClass.ts +62 -0
- package/src/bodyClass/ServerBodyClass.ts +65 -0
- package/src/bodyClass/index.ts +1 -0
- package/src/cookies/ClientCookies.ts +41 -10
- package/src/cookies/Cookies.ts +70 -0
- package/src/cookies/ServerCookies.ts +9 -6
- package/src/cookies/index.ts +5 -29
- package/src/crelte.ts +9 -0
- package/src/index.ts +15 -1
- package/src/init/client.ts +29 -24
- package/src/init/server.ts +12 -4
- package/src/init/shared.ts +18 -6
- package/src/loadData/Globals.ts +1 -1
- package/src/node/index.ts +1 -1
- package/src/plugins/Events.ts +22 -7
- package/src/plugins/Plugins.ts +66 -1
- package/src/queries/Queries.ts +47 -14
- package/src/queries/gql.ts +2 -2
- package/src/queries/index.ts +71 -0
- package/src/queries/vars.ts +13 -0
- package/src/routing/route/Request.ts +11 -4
- package/src/routing/router/BaseRouter.ts +4 -2
- package/src/routing/router/ClientRouter.ts +26 -18
- package/src/routing/router/Router.ts +10 -11
- package/src/routing/utils.ts +1 -1
- package/src/server/CrelteServer.ts +4 -2
- package/src/server/ServerRouter.ts +18 -7
- package/src/server/queries/QueryGqlRoute.ts +224 -0
- package/src/server/queries/QueryHandleRoute.ts +37 -0
- package/src/server/queries/queries.ts +57 -21
- package/src/server/queries/routes.ts +25 -229
- package/src/std/stores/StagedWritable.ts +96 -0
- package/src/std/stores/index.ts +2 -1
- package/src/std/sync/Barrier.ts +1 -1
- package/src/utils.ts +15 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import Writable from './Writable.js';
|
|
2
|
+
export default class StagedWritable {
|
|
3
|
+
inner;
|
|
4
|
+
// -1 = not staged, 0 = staged but no new value, 1 = staged
|
|
5
|
+
mode;
|
|
6
|
+
staged;
|
|
7
|
+
/**
|
|
8
|
+
* Creates a new StagedWritable
|
|
9
|
+
*
|
|
10
|
+
* @param def A default value
|
|
11
|
+
*/
|
|
12
|
+
constructor(def) {
|
|
13
|
+
this.inner = new Writable(def);
|
|
14
|
+
this.mode = -1;
|
|
15
|
+
this.staged = undefined;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Returns true if the store is currently staged
|
|
19
|
+
*/
|
|
20
|
+
isStaged() {
|
|
21
|
+
return this.mode >= 0;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Returns a new StagedWritable which is staged and has the same value as the current one
|
|
25
|
+
* To commit the staged value, call `commit` on the returned StagedWritable
|
|
26
|
+
*/
|
|
27
|
+
stage() {
|
|
28
|
+
const n = Object.create(this);
|
|
29
|
+
n.inner = this.inner;
|
|
30
|
+
n.mode = 0;
|
|
31
|
+
n.staged = undefined;
|
|
32
|
+
return n;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The function get's called once with the current value and then when the
|
|
36
|
+
* values changes
|
|
37
|
+
*
|
|
38
|
+
* #### Note
|
|
39
|
+
* This does not check for equality like svelte.
|
|
40
|
+
*
|
|
41
|
+
* @return a function which should be called to unsubscribe
|
|
42
|
+
*/
|
|
43
|
+
subscribe(fn, invalidate) {
|
|
44
|
+
return this.inner.subscribe(fn, invalidate);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Either updates the store and calls all subscribers with the value or
|
|
48
|
+
* updates the stateful value if previously toStateful was called
|
|
49
|
+
*/
|
|
50
|
+
set(inner) {
|
|
51
|
+
if (this.mode >= 0) {
|
|
52
|
+
this.mode = 1;
|
|
53
|
+
this.staged = inner;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this.inner.set(inner);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* If the value was staged, then update the store and call all subscribers with the value
|
|
61
|
+
*/
|
|
62
|
+
commit() {
|
|
63
|
+
if (this.mode < 0)
|
|
64
|
+
throw new Error('not staged, call stage first');
|
|
65
|
+
if (this.mode === 1)
|
|
66
|
+
this.inner.set(this.staged);
|
|
67
|
+
this.staged = undefined;
|
|
68
|
+
this.mode = -1;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get the current value either staged or not
|
|
72
|
+
*/
|
|
73
|
+
get() {
|
|
74
|
+
if (this.mode === 1)
|
|
75
|
+
return this.staged;
|
|
76
|
+
return this.inner.get();
|
|
77
|
+
}
|
|
78
|
+
readonly() {
|
|
79
|
+
return this.inner.readonly();
|
|
80
|
+
}
|
|
81
|
+
readclone() {
|
|
82
|
+
return this.inner.readclone();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Readable from './Readable.js';
|
|
2
2
|
import Writable from './Writable.js';
|
|
3
3
|
import Readclone from './Readclone.js';
|
|
4
|
-
|
|
4
|
+
import StagedWritable from './StagedWritable.js';
|
|
5
|
+
export { Writable, Readable, Readclone, StagedWritable };
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/std/stores/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,SAAS,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/std/stores/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,cAAc,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC"}
|
package/dist/std/stores/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Readable from './Readable.js';
|
|
2
2
|
import Writable from './Writable.js';
|
|
3
3
|
import Readclone from './Readclone.js';
|
|
4
|
-
|
|
4
|
+
import StagedWritable from './StagedWritable.js';
|
|
5
|
+
export { Writable, Readable, Readclone, StagedWritable };
|
package/dist/std/sync/Barrier.js
CHANGED
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
export declare function objClone(obj: any): any;
|
|
2
2
|
export declare function isPromise<T>(p: Promise<T> | T): p is Promise<T>;
|
|
3
|
+
/**
|
|
4
|
+
* A helper to chain promises without needing a microtask if its not a promise
|
|
5
|
+
* Equivalent to:
|
|
6
|
+
* ```
|
|
7
|
+
* const val = await p;
|
|
8
|
+
* then(val);
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export declare function promiseThen<T, R = void>(p: Promise<T> | T, then: (val: T) => R): Promise<R> | R;
|
|
3
12
|
export declare function urlWithPath(url: string, path?: string): URL;
|
|
4
13
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAMtC;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAE/D;AAGD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,GAAG,CAI3D"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAMtC;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAE/D;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,EACtC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GACjB,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAEhB;AAGD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,GAAG,CAI3D"}
|
package/dist/utils.js
CHANGED
|
@@ -9,6 +9,17 @@ export function objClone(obj) {
|
|
|
9
9
|
export function isPromise(p) {
|
|
10
10
|
return typeof p?.then === 'function';
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* A helper to chain promises without needing a microtask if its not a promise
|
|
14
|
+
* Equivalent to:
|
|
15
|
+
* ```
|
|
16
|
+
* const val = await p;
|
|
17
|
+
* then(val);
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function promiseThen(p, then) {
|
|
21
|
+
return isPromise(p) ? p.then(then) : then(p);
|
|
22
|
+
}
|
|
12
23
|
// the pathname is always replaced
|
|
13
24
|
export function urlWithPath(url, path) {
|
|
14
25
|
const u = new URL(url);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crelte",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.12",
|
|
4
4
|
"author": "Crelte <support@crelte.com>",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -72,6 +72,10 @@
|
|
|
72
72
|
"types": "./dist/cookies/index.d.ts",
|
|
73
73
|
"default": "./dist/cookies/index.js"
|
|
74
74
|
},
|
|
75
|
+
"./bodyClass": {
|
|
76
|
+
"types": "./dist/bodyClass/index.d.ts",
|
|
77
|
+
"default": "./dist/bodyClass/index.js"
|
|
78
|
+
},
|
|
75
79
|
"./blocks": {
|
|
76
80
|
"types": "./dist/blocks/index.d.ts",
|
|
77
81
|
"default": "./dist/blocks/index.js"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import StagedWritable from '../std/stores/StagedWritable.js';
|
|
2
|
+
|
|
3
|
+
export default class BodyClass {
|
|
4
|
+
private inner: PlatformBodyClass;
|
|
5
|
+
private store: StagedWritable<void>;
|
|
6
|
+
|
|
7
|
+
constructor(inner: PlatformBodyClass, store?: StagedWritable<void>) {
|
|
8
|
+
this.inner = inner;
|
|
9
|
+
this.store = store ?? new StagedWritable(void 0);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
subscribe(
|
|
13
|
+
fn: (val: BodyClass) => void,
|
|
14
|
+
invalidate?: () => void,
|
|
15
|
+
): () => void {
|
|
16
|
+
return this.store.subscribe(() => fn(this), invalidate);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Checks if the body contains the given class
|
|
21
|
+
*/
|
|
22
|
+
contains(cls: string): boolean {
|
|
23
|
+
return this.inner.contains(cls);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Adds the given classes to the body
|
|
28
|
+
*/
|
|
29
|
+
add(...classes: string[]): void {
|
|
30
|
+
this.inner.add(...classes);
|
|
31
|
+
this.store.set();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Toggles the given class on the body
|
|
36
|
+
*
|
|
37
|
+
* ## Warning
|
|
38
|
+
* toggle without `force` should almost never be used
|
|
39
|
+
* on the server. If you call this for example in loadData
|
|
40
|
+
* the server will add the class and the client will the remove
|
|
41
|
+
* it.
|
|
42
|
+
*/
|
|
43
|
+
toggle(cls: string, force?: boolean): void {
|
|
44
|
+
this.inner.toggle(cls, force);
|
|
45
|
+
this.store.set();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
remove(...classes: string[]): void {
|
|
49
|
+
this.inner.remove(...classes);
|
|
50
|
+
this.store.set();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** @hidden */
|
|
54
|
+
z_toRequest(): BodyClass {
|
|
55
|
+
return new BodyClass(this.inner.toRequest(), this.store.stage());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** @hidden */
|
|
59
|
+
z_render(): void {
|
|
60
|
+
this.inner.render?.();
|
|
61
|
+
this.store.commit();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface PlatformBodyClass {
|
|
66
|
+
contains(cls: string): boolean;
|
|
67
|
+
add(...classes: string[]): void;
|
|
68
|
+
toggle(cls: string, force?: boolean): void;
|
|
69
|
+
remove(...classes: string[]): void;
|
|
70
|
+
toRequest(): PlatformBodyClass;
|
|
71
|
+
render?: () => void;
|
|
72
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { PlatformBodyClass } from './BodyClass.js';
|
|
2
|
+
|
|
3
|
+
export default class ClientBodyClass implements PlatformBodyClass {
|
|
4
|
+
private inner: Set<string> | null;
|
|
5
|
+
|
|
6
|
+
constructor(inner?: Set<string>) {
|
|
7
|
+
this.inner = inner ?? null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
contains(cls: string): boolean {
|
|
11
|
+
if (this.inner) return this.inner.has(cls);
|
|
12
|
+
return cl().contains(cls);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
add(...classes: string[]): void {
|
|
16
|
+
if (this.inner) classes.forEach(cls => this.inner!.add(cls));
|
|
17
|
+
else cl().add(...classes);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
toggle(cls: string, force?: boolean): void {
|
|
21
|
+
if (this.inner) {
|
|
22
|
+
const add =
|
|
23
|
+
typeof force === 'boolean' ? force : !this.inner.has(cls);
|
|
24
|
+
|
|
25
|
+
if (add) this.inner.add(cls);
|
|
26
|
+
else this.inner.delete(cls);
|
|
27
|
+
} else {
|
|
28
|
+
cl().toggle(cls, force);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
remove(...classes: string[]): void {
|
|
33
|
+
if (this.inner) classes.forEach(cls => this.inner!.delete(cls));
|
|
34
|
+
else cl().remove(...classes);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
toRequest(): ClientBodyClass {
|
|
38
|
+
const inner = new Set(cl());
|
|
39
|
+
return new ClientBodyClass(inner);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
render(): void {
|
|
43
|
+
if (!this.inner) throw new Error('call toRequest first');
|
|
44
|
+
const current = new Set(cl());
|
|
45
|
+
|
|
46
|
+
for (const cls of this.inner) {
|
|
47
|
+
const existed = current.delete(cls);
|
|
48
|
+
if (!existed) cl().add(cls);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// now lets remove all classes that still exist in current
|
|
52
|
+
for (const cls of current) {
|
|
53
|
+
cl().remove(cls);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
this.inner = null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function cl(): DOMTokenList {
|
|
61
|
+
return document.body.classList;
|
|
62
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { PlatformBodyClass } from './BodyClass.js';
|
|
2
|
+
|
|
3
|
+
export default class ServerBodyClass implements PlatformBodyClass {
|
|
4
|
+
private inner: Set<string>;
|
|
5
|
+
|
|
6
|
+
constructor() {
|
|
7
|
+
this.inner = new Set();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
contains(cls: string): boolean {
|
|
11
|
+
return this.inner.has(cls);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
add(...classes: string[]): void {
|
|
15
|
+
validate(classes);
|
|
16
|
+
classes.forEach(cls => this.inner.add(cls));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
toggle(cls: string, force?: boolean): void {
|
|
20
|
+
validate([cls]);
|
|
21
|
+
|
|
22
|
+
if (import.meta.env.DEV && typeof force !== 'boolean') {
|
|
23
|
+
console.warn(
|
|
24
|
+
'Using toggle without force on the server can lead ' +
|
|
25
|
+
'to unexpected results. Because in a loadData the server will add it ' +
|
|
26
|
+
'and the client will afterwards remove it.',
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const add = typeof force === 'boolean' ? force : !this.inner.has(cls);
|
|
31
|
+
|
|
32
|
+
if (add) this.inner.add(cls);
|
|
33
|
+
else this.inner.delete(cls);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
remove(...classes: string[]): void {
|
|
37
|
+
validate(classes);
|
|
38
|
+
classes.forEach(cls => this.inner.delete(cls));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
toRequest(): ServerBodyClass {
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
z_processHtmlTemplate(html: string): string {
|
|
46
|
+
const SEARCH_STR = '<!--body-class-->';
|
|
47
|
+
if (this.inner.size && !html.includes(SEARCH_STR)) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
'index.html needs to contain `class="<!--body-class-->"`',
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return html.replace(SEARCH_STR, Array.from(this.inner).join(' '));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function validate(classes: string[]) {
|
|
58
|
+
for (const cls of classes) {
|
|
59
|
+
if (cls.includes(' ')) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
`Invalid class name "${cls}". Class names must not contain spaces.`,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as BodyClass } from './BodyClass.js';
|
|
@@ -1,26 +1,57 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { parseCookies, setCookieToString } from './utils.js';
|
|
1
|
+
import { PlatformCookies, RemoveOptions, SetOptions } from './Cookies.js';
|
|
2
|
+
import { parseCookies, SetCookie, setCookieToString } from './utils.js';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
constructor(
|
|
4
|
+
export default class ClientCookies implements PlatformCookies {
|
|
5
|
+
private inner: Map<string, string> | null;
|
|
6
|
+
private setCookies: Map<string, SetCookie> | null;
|
|
7
|
+
|
|
8
|
+
constructor(
|
|
9
|
+
inner?: Map<string, string>,
|
|
10
|
+
setCookies?: Map<string, SetCookie>,
|
|
11
|
+
) {
|
|
12
|
+
this.inner = inner ?? null;
|
|
13
|
+
this.setCookies = setCookies ?? null;
|
|
14
|
+
}
|
|
9
15
|
|
|
10
16
|
get(name: string): string | null {
|
|
11
|
-
|
|
12
|
-
|
|
17
|
+
if (!this.inner || !this.setCookies) {
|
|
18
|
+
const cookies = getCookies();
|
|
19
|
+
return cookies.get(name) ?? null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const setCookie = this.setCookies.get(name);
|
|
23
|
+
if (setCookie) {
|
|
24
|
+
return (setCookie.maxAge ?? 1) > 0 ? setCookie.value : null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return this.inner.get(name) ?? null;
|
|
13
28
|
}
|
|
14
29
|
|
|
15
30
|
set(name: string, value: string, opts?: SetOptions): void {
|
|
16
31
|
const setCookie = { name, value, path: '/', ...opts };
|
|
17
32
|
|
|
18
|
-
|
|
33
|
+
if (this.setCookies) this.setCookies.set(name, setCookie);
|
|
34
|
+
else document.cookie = setCookieToString(setCookie);
|
|
19
35
|
}
|
|
20
36
|
|
|
21
37
|
remove(name: string, opts?: RemoveOptions): void {
|
|
22
38
|
this.set(name, '', { ...opts, maxAge: 0 });
|
|
23
39
|
}
|
|
40
|
+
|
|
41
|
+
toRequest(): ClientCookies {
|
|
42
|
+
return new ClientCookies(getCookies(), new Map());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
render(): void {
|
|
46
|
+
if (!this.setCookies) throw new Error('call toRequest first');
|
|
47
|
+
|
|
48
|
+
for (const setCookie of this.setCookies.values()) {
|
|
49
|
+
document.cookie = setCookieToString(setCookie);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.inner = null;
|
|
53
|
+
this.setCookies = null;
|
|
54
|
+
}
|
|
24
55
|
}
|
|
25
56
|
|
|
26
57
|
function getCookies(): Map<string, string> {
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import StagedWritable from '../std/stores/StagedWritable.js';
|
|
2
|
+
|
|
3
|
+
export type SetOptions = {
|
|
4
|
+
maxAge?: number;
|
|
5
|
+
path?: string;
|
|
6
|
+
domain?: string;
|
|
7
|
+
secure?: boolean;
|
|
8
|
+
httpOnly?: boolean;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type RemoveOptions = Omit<SetOptions, 'maxAge'>;
|
|
12
|
+
|
|
13
|
+
export default class Cookies {
|
|
14
|
+
private inner: PlatformCookies;
|
|
15
|
+
private store: StagedWritable<void>;
|
|
16
|
+
|
|
17
|
+
constructor(inner: PlatformCookies, store?: StagedWritable<void>) {
|
|
18
|
+
this.inner = inner;
|
|
19
|
+
this.store = store ?? new StagedWritable(void 0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
subscribe(fn: (val: Cookies) => void, invalidate?: () => void): () => void {
|
|
23
|
+
return this.store.subscribe(() => fn(this), invalidate);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* returns the value of the cookie
|
|
28
|
+
*/
|
|
29
|
+
get(name: string): string | null {
|
|
30
|
+
return this.inner.get(name);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* sets the value of the cookie
|
|
35
|
+
*
|
|
36
|
+
* #### Note
|
|
37
|
+
* path defaults to '/'
|
|
38
|
+
*/
|
|
39
|
+
set(name: string, value: string, opts?: SetOptions): void {
|
|
40
|
+
this.inner.set(name, value, opts);
|
|
41
|
+
this.store.set();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* removes the cookie
|
|
46
|
+
*/
|
|
47
|
+
remove(name: string, opts?: RemoveOptions): void {
|
|
48
|
+
this.inner.remove(name, opts);
|
|
49
|
+
this.store.set();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** @hidden */
|
|
53
|
+
z_toRequest(): Cookies {
|
|
54
|
+
return new Cookies(this.inner.toRequest(), this.store.stage());
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** @hidden */
|
|
58
|
+
z_render(): void {
|
|
59
|
+
this.inner.render?.();
|
|
60
|
+
this.store.commit();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface PlatformCookies {
|
|
65
|
+
get(name: string): string | null;
|
|
66
|
+
set(name: string, value: string, opts?: SetOptions): void;
|
|
67
|
+
remove(name: string, opts?: RemoveOptions): void;
|
|
68
|
+
toRequest(): PlatformCookies;
|
|
69
|
+
render?: () => void;
|
|
70
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PlatformCookies, RemoveOptions, SetOptions } from './Cookies.js';
|
|
2
2
|
import { parseCookies, type SetCookie, setCookieToString } from './utils.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* #### Warning
|
|
6
6
|
* This is not stable and should only be used internally by crelte
|
|
7
7
|
*/
|
|
8
|
-
export default class ServerCookies implements
|
|
8
|
+
export default class ServerCookies implements PlatformCookies {
|
|
9
9
|
requestCookies: Map<string, string>;
|
|
10
10
|
setCookies: Map<string, SetCookie>;
|
|
11
11
|
|
|
@@ -14,12 +14,11 @@ export default class ServerCookies implements Cookies {
|
|
|
14
14
|
this.setCookies = new Map();
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
///
|
|
17
|
+
/// Returns the value of the cookie with the given name, or null if it doesn't exist.
|
|
18
18
|
get(name: string): string | null {
|
|
19
19
|
const setCookie = this.setCookies.get(name);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return setCookie.value;
|
|
20
|
+
if (setCookie) {
|
|
21
|
+
return (setCookie.maxAge ?? 1) > 0 ? setCookie.value : null;
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
return this.requestCookies.get(name) ?? null;
|
|
@@ -33,6 +32,10 @@ export default class ServerCookies implements Cookies {
|
|
|
33
32
|
this.set(name, '', { ...opts, maxAge: 0 });
|
|
34
33
|
}
|
|
35
34
|
|
|
35
|
+
toRequest(): ServerCookies {
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
|
|
36
39
|
_populateHeaders(headers: Headers) {
|
|
37
40
|
for (const setCookie of this.setCookies.values()) {
|
|
38
41
|
headers.append('Set-Cookie', setCookieToString(setCookie));
|
package/src/cookies/index.ts
CHANGED
|
@@ -1,29 +1,5 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
httpOnly?: boolean;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export type RemoveOptions = Omit<SetOptions, 'maxAge'>;
|
|
10
|
-
|
|
11
|
-
export interface Cookies {
|
|
12
|
-
/**
|
|
13
|
-
* returns the value of the cookie
|
|
14
|
-
*/
|
|
15
|
-
get(name: string): string | null;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* sets the value of the cookie
|
|
19
|
-
*
|
|
20
|
-
* #### Note
|
|
21
|
-
* path defaults to '/'
|
|
22
|
-
*/
|
|
23
|
-
set(name: string, value: string, opts?: SetOptions): void;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* removes the cookie
|
|
27
|
-
*/
|
|
28
|
-
remove(name: string, opts?: RemoveOptions): void;
|
|
29
|
-
}
|
|
1
|
+
export {
|
|
2
|
+
default as Cookies,
|
|
3
|
+
type SetOptions,
|
|
4
|
+
type RemoveOptions,
|
|
5
|
+
} from './Cookies.js';
|
package/src/crelte.ts
CHANGED
|
@@ -9,6 +9,7 @@ import Queries, { Query, QueryOptions } from './queries/Queries.js';
|
|
|
9
9
|
import { Readable } from './std/stores/index.js';
|
|
10
10
|
import { Entry } from './loadData/index.js';
|
|
11
11
|
import { urlWithPath } from './utils.js';
|
|
12
|
+
import { BodyClass } from './bodyClass/index.js';
|
|
12
13
|
|
|
13
14
|
/** The type for the app.config object */
|
|
14
15
|
export type Config = {
|
|
@@ -113,6 +114,11 @@ export type Crelte = {
|
|
|
113
114
|
*/
|
|
114
115
|
cookies: Cookies;
|
|
115
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Get the BodyClass instance
|
|
119
|
+
*/
|
|
120
|
+
bodyClass: BodyClass;
|
|
121
|
+
|
|
116
122
|
/**
|
|
117
123
|
* Get a Plugin by name
|
|
118
124
|
*/
|
|
@@ -263,6 +269,7 @@ export function newCrelte({
|
|
|
263
269
|
router,
|
|
264
270
|
queries,
|
|
265
271
|
cookies,
|
|
272
|
+
bodyClass,
|
|
266
273
|
}: {
|
|
267
274
|
config: Required<Config>;
|
|
268
275
|
ssrCache: SsrCache;
|
|
@@ -272,6 +279,7 @@ export function newCrelte({
|
|
|
272
279
|
router: Router;
|
|
273
280
|
queries: Queries;
|
|
274
281
|
cookies: Cookies;
|
|
282
|
+
bodyClass: BodyClass;
|
|
275
283
|
}): Crelte {
|
|
276
284
|
return {
|
|
277
285
|
config,
|
|
@@ -282,6 +290,7 @@ export function newCrelte({
|
|
|
282
290
|
router,
|
|
283
291
|
queries,
|
|
284
292
|
cookies,
|
|
293
|
+
bodyClass,
|
|
285
294
|
|
|
286
295
|
getPlugin: name => plugins.get(name),
|
|
287
296
|
getEnv: key => ssrCache.get(key as any) as any,
|
package/src/index.ts
CHANGED
|
@@ -17,7 +17,8 @@ import {
|
|
|
17
17
|
LoadDataObj,
|
|
18
18
|
} from './loadData/index.js';
|
|
19
19
|
import Queries from './queries/Queries.js';
|
|
20
|
-
import { Readable } from './std/stores/index.js';
|
|
20
|
+
import { Readable, Writable } from './std/stores/index.js';
|
|
21
|
+
import { BodyClass } from './bodyClass/index.js';
|
|
21
22
|
|
|
22
23
|
export {
|
|
23
24
|
type Crelte,
|
|
@@ -33,6 +34,9 @@ export {
|
|
|
33
34
|
/** The type for the app.init function */
|
|
34
35
|
export type Init = (crelte: Crelte) => void;
|
|
35
36
|
|
|
37
|
+
/** The Props that are passed to the app */
|
|
38
|
+
export type AppProps = { route: Writable<Route> };
|
|
39
|
+
|
|
36
40
|
function innerGetCrelte(): Crelte {
|
|
37
41
|
return getContext('crelte');
|
|
38
42
|
}
|
|
@@ -174,6 +178,16 @@ export function getCookies(): Cookies {
|
|
|
174
178
|
return innerGetCrelte().cookies;
|
|
175
179
|
}
|
|
176
180
|
|
|
181
|
+
/**
|
|
182
|
+
* returns the body class instance
|
|
183
|
+
*
|
|
184
|
+
* #### Note
|
|
185
|
+
* This only works during component initialisation.
|
|
186
|
+
*/
|
|
187
|
+
export function getBodyClass(): BodyClass {
|
|
188
|
+
return innerGetCrelte().bodyClass;
|
|
189
|
+
}
|
|
190
|
+
|
|
177
191
|
/**
|
|
178
192
|
* Listen for route changes
|
|
179
193
|
*
|