crelte 0.5.11 → 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.map +1 -1
- package/dist/init/client.js +23 -14
- package/dist/init/server.d.ts.map +1 -1
- package/dist/init/server.js +11 -3
- 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 +6 -1
- 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/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/ClientRouter.d.ts.map +1 -1
- package/dist/routing/router/ClientRouter.js +18 -11
- package/dist/routing/router/Router.d.ts.map +1 -1
- package/dist/routing/router/Router.js +8 -12
- 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/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 +26 -14
- package/src/init/server.ts +11 -3
- 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 +12 -1
- package/src/plugins/Plugins.ts +66 -1
- package/src/routing/route/Request.ts +11 -4
- package/src/routing/router/ClientRouter.ts +23 -14
- package/src/routing/router/Router.ts +8 -10
- package/src/server/CrelteServer.ts +4 -2
- 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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Cookies } from '../cookies/index.js';
|
|
1
2
|
import ServerCookies from '../cookies/ServerCookies.js';
|
|
2
3
|
import { Request } from '../routing/index.js';
|
|
3
4
|
import { urlWithPath } from '../utils.js';
|
|
@@ -11,6 +12,7 @@ export default class CrelteServerRequest {
|
|
|
11
12
|
_sites;
|
|
12
13
|
_langs;
|
|
13
14
|
_queries;
|
|
15
|
+
_scookies;
|
|
14
16
|
_cookies;
|
|
15
17
|
constructor(req, opts) {
|
|
16
18
|
this.req = req;
|
|
@@ -19,7 +21,8 @@ export default class CrelteServerRequest {
|
|
|
19
21
|
this._langs = opts.languages;
|
|
20
22
|
this.prefSite = opts.preferredSite;
|
|
21
23
|
this._queries = opts.queries.z_toRequest(new Request(new URL(req.url), req.site));
|
|
22
|
-
this.
|
|
24
|
+
this._scookies = new ServerCookies(req.headers);
|
|
25
|
+
this._cookies = new Cookies(this._scookies);
|
|
23
26
|
}
|
|
24
27
|
/**
|
|
25
28
|
* Easy access to this.req.site
|
|
@@ -104,6 +107,6 @@ export default class CrelteServerRequest {
|
|
|
104
107
|
}
|
|
105
108
|
/** @hidden */
|
|
106
109
|
z_finishResponse(resp) {
|
|
107
|
-
this.
|
|
110
|
+
this._scookies._populateHeaders(resp.headers);
|
|
108
111
|
}
|
|
109
112
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { CloneableOrPrimitive } from '../index.js';
|
|
2
|
+
import { Readable } from './index.js';
|
|
3
|
+
export default class StagedWritable<T> {
|
|
4
|
+
private inner;
|
|
5
|
+
private mode;
|
|
6
|
+
private staged;
|
|
7
|
+
/**
|
|
8
|
+
* Creates a new StagedWritable
|
|
9
|
+
*
|
|
10
|
+
* @param def A default value
|
|
11
|
+
*/
|
|
12
|
+
constructor(def: T);
|
|
13
|
+
/**
|
|
14
|
+
* Returns true if the store is currently staged
|
|
15
|
+
*/
|
|
16
|
+
isStaged(): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Returns a new StagedWritable which is staged and has the same value as the current one
|
|
19
|
+
* To commit the staged value, call `commit` on the returned StagedWritable
|
|
20
|
+
*/
|
|
21
|
+
stage(): StagedWritable<T>;
|
|
22
|
+
/**
|
|
23
|
+
* The function get's called once with the current value and then when the
|
|
24
|
+
* values changes
|
|
25
|
+
*
|
|
26
|
+
* #### Note
|
|
27
|
+
* This does not check for equality like svelte.
|
|
28
|
+
*
|
|
29
|
+
* @return a function which should be called to unsubscribe
|
|
30
|
+
*/
|
|
31
|
+
subscribe(fn: (val: T) => void, invalidate?: () => void): () => void;
|
|
32
|
+
/**
|
|
33
|
+
* Either updates the store and calls all subscribers with the value or
|
|
34
|
+
* updates the stateful value if previously toStateful was called
|
|
35
|
+
*/
|
|
36
|
+
set(inner: T): void;
|
|
37
|
+
/**
|
|
38
|
+
* If the value was staged, then update the store and call all subscribers with the value
|
|
39
|
+
*/
|
|
40
|
+
commit(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Get the current value either staged or not
|
|
43
|
+
*/
|
|
44
|
+
get(): T;
|
|
45
|
+
readonly(): Readable<T>;
|
|
46
|
+
readclone<U extends T & CloneableOrPrimitive>(this: StagedWritable<U>): Readable<U>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=StagedWritable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StagedWritable.d.ts","sourceRoot":"","sources":["../../../src/std/stores/StagedWritable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,MAAM,CAAC,OAAO,OAAO,cAAc,CAAC,CAAC;IACpC,OAAO,CAAC,KAAK,CAAc;IAE3B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,MAAM,CAAgB;IAE9B;;;;OAIG;gBACS,GAAG,EAAE,CAAC;IAMlB;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;;OAGG;IACH,KAAK,IAAI,cAAc,CAAC,CAAC,CAAC;IAQ1B;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,UAAU,CAAC,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAIpE;;;OAGG;IACH,GAAG,CAAC,KAAK,EAAE,CAAC;IASZ;;OAEG;IACH,MAAM;IASN;;OAEG;IACH,GAAG,IAAI,CAAC;IAKR,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC;IAIvB,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,oBAAoB,EAC3C,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,GACrB,QAAQ,CAAC,CAAC,CAAC;CAGd"}
|
|
@@ -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';
|