crelte 0.5.11 → 0.5.13

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.
Files changed (110) hide show
  1. package/dist/blocks/Blocks.d.ts +1 -1
  2. package/dist/blocks/Blocks.d.ts.map +1 -1
  3. package/dist/bodyClass/BodyClass.d.ts +56 -0
  4. package/dist/bodyClass/BodyClass.d.ts.map +1 -0
  5. package/dist/bodyClass/BodyClass.js +70 -0
  6. package/dist/bodyClass/ClientBodyClass.d.ts +17 -0
  7. package/dist/bodyClass/ClientBodyClass.d.ts.map +1 -0
  8. package/dist/bodyClass/ClientBodyClass.js +71 -0
  9. package/dist/bodyClass/ServerBodyClass.d.ts +18 -0
  10. package/dist/bodyClass/ServerBodyClass.d.ts.map +1 -0
  11. package/dist/bodyClass/ServerBodyClass.js +61 -0
  12. package/dist/bodyClass/index.d.ts +2 -0
  13. package/dist/bodyClass/index.d.ts.map +1 -0
  14. package/dist/bodyClass/index.js +1 -0
  15. package/dist/bodyClass/utils.d.ts +39 -0
  16. package/dist/bodyClass/utils.d.ts.map +1 -0
  17. package/dist/bodyClass/utils.js +84 -0
  18. package/dist/cookies/ClientCookies.d.ts +8 -3
  19. package/dist/cookies/ClientCookies.d.ts.map +1 -1
  20. package/dist/cookies/ClientCookies.js +31 -7
  21. package/dist/cookies/Cookies.d.ts +42 -0
  22. package/dist/cookies/Cookies.d.ts.map +1 -0
  23. package/dist/cookies/Cookies.js +44 -0
  24. package/dist/cookies/ServerCookies.d.ts +3 -2
  25. package/dist/cookies/ServerCookies.d.ts.map +1 -1
  26. package/dist/cookies/ServerCookies.js +6 -4
  27. package/dist/cookies/index.d.ts +1 -25
  28. package/dist/cookies/index.d.ts.map +1 -1
  29. package/dist/cookies/index.js +1 -1
  30. package/dist/crelte.d.ts +7 -1
  31. package/dist/crelte.d.ts.map +1 -1
  32. package/dist/crelte.js +4 -1
  33. package/dist/index.d.ts +13 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +9 -0
  36. package/dist/init/client.d.ts.map +1 -1
  37. package/dist/init/client.js +23 -14
  38. package/dist/init/server.d.ts.map +1 -1
  39. package/dist/init/server.js +12 -3
  40. package/dist/init/shared.d.ts +1 -0
  41. package/dist/init/shared.d.ts.map +1 -1
  42. package/dist/init/shared.js +19 -5
  43. package/dist/loadData/Globals.d.ts.map +1 -1
  44. package/dist/loadData/entry.d.ts +11 -2
  45. package/dist/loadData/entry.d.ts.map +1 -1
  46. package/dist/loadData/entry.js +11 -2
  47. package/dist/node/index.js +1 -1
  48. package/dist/plugins/Events.d.ts +6 -1
  49. package/dist/plugins/Events.d.ts.map +1 -1
  50. package/dist/plugins/Plugins.d.ts +36 -1
  51. package/dist/plugins/Plugins.d.ts.map +1 -1
  52. package/dist/plugins/Plugins.js +32 -0
  53. package/dist/queries/index.d.ts +1 -1
  54. package/dist/queries/index.d.ts.map +1 -1
  55. package/dist/routing/route/Request.d.ts +1 -1
  56. package/dist/routing/route/Request.d.ts.map +1 -1
  57. package/dist/routing/route/Request.js +7 -3
  58. package/dist/routing/router/ClientRouter.d.ts.map +1 -1
  59. package/dist/routing/router/ClientRouter.js +18 -11
  60. package/dist/routing/router/Router.d.ts.map +1 -1
  61. package/dist/routing/router/Router.js +8 -12
  62. package/dist/server/CrelteServer.d.ts +1 -0
  63. package/dist/server/CrelteServer.d.ts.map +1 -1
  64. package/dist/server/CrelteServer.js +5 -2
  65. package/dist/server/queries/QueryGqlRoute.d.ts.map +1 -1
  66. package/dist/server/queries/QueryGqlRoute.js +3 -3
  67. package/dist/server/queries/routes.d.ts +1 -1
  68. package/dist/server/queries/routes.d.ts.map +1 -1
  69. package/dist/std/stores/StagedWritable.d.ts +48 -0
  70. package/dist/std/stores/StagedWritable.d.ts.map +1 -0
  71. package/dist/std/stores/StagedWritable.js +84 -0
  72. package/dist/std/stores/index.d.ts +2 -1
  73. package/dist/std/stores/index.d.ts.map +1 -1
  74. package/dist/std/stores/index.js +2 -1
  75. package/dist/std/sync/Barrier.js +1 -1
  76. package/dist/utils.d.ts +9 -0
  77. package/dist/utils.d.ts.map +1 -1
  78. package/dist/utils.js +11 -0
  79. package/package.json +5 -1
  80. package/src/blocks/Blocks.ts +1 -1
  81. package/src/bodyClass/BodyClass.ts +94 -0
  82. package/src/bodyClass/ClientBodyClass.ts +79 -0
  83. package/src/bodyClass/ServerBodyClass.ts +86 -0
  84. package/src/bodyClass/index.ts +1 -0
  85. package/src/bodyClass/utils.ts +118 -0
  86. package/src/cookies/ClientCookies.ts +41 -10
  87. package/src/cookies/Cookies.ts +70 -0
  88. package/src/cookies/ServerCookies.ts +9 -6
  89. package/src/cookies/index.ts +5 -29
  90. package/src/crelte.ts +12 -0
  91. package/src/index.ts +15 -1
  92. package/src/init/client.ts +26 -14
  93. package/src/init/server.ts +12 -3
  94. package/src/init/shared.ts +21 -6
  95. package/src/loadData/Globals.ts +1 -1
  96. package/src/loadData/entry.ts +12 -2
  97. package/src/node/index.ts +1 -1
  98. package/src/plugins/Events.ts +12 -1
  99. package/src/plugins/Plugins.ts +66 -1
  100. package/src/queries/index.ts +5 -1
  101. package/src/routing/route/Request.ts +11 -4
  102. package/src/routing/router/ClientRouter.ts +23 -14
  103. package/src/routing/router/Router.ts +8 -10
  104. package/src/server/CrelteServer.ts +4 -2
  105. package/src/server/queries/QueryGqlRoute.ts +3 -2
  106. package/src/server/queries/routes.ts +1 -0
  107. package/src/std/stores/StagedWritable.ts +96 -0
  108. package/src/std/stores/index.ts +2 -1
  109. package/src/std/sync/Barrier.ts +1 -1
  110. package/src/utils.ts +15 -0
@@ -0,0 +1,94 @@
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
+ if (this.inner.toggle(cls, force)) this.store.set();
45
+ }
46
+
47
+ /**
48
+ * Removes the given classes from the body
49
+ */
50
+ remove(...classes: string[]): void {
51
+ this.inner.remove(...classes);
52
+ this.store.set();
53
+ }
54
+
55
+ /**
56
+ * Sets the class for the given variant removing the old class for that
57
+ * variant, if cls is null it will remove the variant class
58
+ *
59
+ * If you just have like a dark or light mode and only for the dark mode a
60
+ * class, **prefer** `toggle('dark', isDarkMode)` over
61
+ * `setVariant('mode', isDarkMode ? 'dark' : null)`
62
+ *
63
+ * ## Note
64
+ * The variant name is only used for the internal state management
65
+ * and has no inpact on the actual class name
66
+ */
67
+ setVariant(variant: string, cls: string | null): void {
68
+ if (this.inner.setVariant(variant, cls)) this.store.set();
69
+ }
70
+
71
+ /** @hidden */
72
+ z_toRequest(): BodyClass {
73
+ return new BodyClass(this.inner.toRequest(), this.store.stage());
74
+ }
75
+
76
+ /** @hidden */
77
+ z_render(): void {
78
+ this.inner.render?.();
79
+ this.store.commit();
80
+ }
81
+ }
82
+
83
+ export interface PlatformBodyClass {
84
+ contains(cls: string): boolean;
85
+ add(...classes: string[]): void;
86
+ // returns true if the value was changed (this is different to the
87
+ // DOMTokenList.toggle which returns true if the class is now present)
88
+ toggle(cls: string, force?: boolean): boolean;
89
+ remove(...classes: string[]): void;
90
+ // returns true if the value was changed
91
+ setVariant(variant: string, cls: string | null): boolean;
92
+ toRequest(): PlatformBodyClass;
93
+ render?: () => void;
94
+ }
@@ -0,0 +1,79 @@
1
+ import SsrCache from '../ssr/SsrCache.js';
2
+ import { PlatformBodyClass } from './BodyClass.js';
3
+ import { ClassSet, ssrCacheToVariants, Variants } from './utils.js';
4
+
5
+ export default class ClientBodyClass implements PlatformBodyClass {
6
+ private variants: Variants;
7
+ // during the request store the classes here
8
+ private inner: ClassSet | null;
9
+
10
+ constructor(variants: Variants, inner?: ClassSet) {
11
+ this.variants = variants;
12
+ this.inner = inner ?? null;
13
+ }
14
+
15
+ static fromSsrCache(ssrCache: SsrCache): ClientBodyClass {
16
+ const variants = ssrCacheToVariants(ssrCache);
17
+ return new ClientBodyClass(variants);
18
+ }
19
+
20
+ contains(cls: string): boolean {
21
+ if (this.inner) return this.inner.has(cls);
22
+ return cl().contains(cls);
23
+ }
24
+
25
+ add(...classes: string[]): void {
26
+ if (this.inner) classes.forEach(cls => this.inner!.add(cls));
27
+ else cl().add(...classes);
28
+ }
29
+
30
+ // returns true if the value was changed
31
+ toggle(cls: string, force?: boolean): boolean {
32
+ const exists = this.contains(cls);
33
+ const shouldExist = typeof force === 'boolean' ? force : !exists;
34
+ const changed = shouldExist !== exists;
35
+
36
+ if (this.inner) {
37
+ if (shouldExist) this.inner.add(cls);
38
+ else this.inner.delete(cls);
39
+ } else {
40
+ cl().toggle(cls, force);
41
+ }
42
+
43
+ return changed;
44
+ }
45
+
46
+ remove(...classes: string[]): void {
47
+ if (this.inner) classes.forEach(cls => this.inner!.delete(cls));
48
+ else cl().remove(...classes);
49
+ }
50
+
51
+ setVariant(variant: string, cls: string | null): boolean {
52
+ if (this.inner) return this.inner.setVariant(variant, cls);
53
+
54
+ const { remove, add } = this.variants.set(variant, cls);
55
+
56
+ if (remove) cl().remove(remove);
57
+ if (add) cl().add(add);
58
+
59
+ return !!remove || !!add;
60
+ }
61
+
62
+ toRequest(): ClientBodyClass {
63
+ const inner = new ClassSet(cl(), this.variants.entries(), true);
64
+ return new ClientBodyClass(this.variants, inner);
65
+ }
66
+
67
+ render(): void {
68
+ if (!this.inner) throw new Error('call toRequest first');
69
+
70
+ const inner = this.inner;
71
+ this.inner = null;
72
+
73
+ inner.applyHistory(this);
74
+ }
75
+ }
76
+
77
+ function cl(): DOMTokenList {
78
+ return document.body.classList;
79
+ }
@@ -0,0 +1,86 @@
1
+ import SsrCache from '../ssr/SsrCache.js';
2
+ import { PlatformBodyClass } from './BodyClass.js';
3
+ import { ClassSet, variantsToSsrCache } from './utils.js';
4
+
5
+ export default class ServerBodyClass implements PlatformBodyClass {
6
+ private inner: ClassSet;
7
+
8
+ constructor() {
9
+ this.inner = new ClassSet();
10
+ }
11
+
12
+ contains(cls: string): boolean {
13
+ return this.inner.has(cls);
14
+ }
15
+
16
+ add(...classes: string[]): void {
17
+ validate(classes);
18
+ classes.forEach(cls => this.inner.add(cls));
19
+ }
20
+
21
+ toggle(cls: string, force?: boolean): boolean {
22
+ validate([cls]);
23
+
24
+ if (import.meta.env.DEV && typeof force !== 'boolean') {
25
+ console.warn(
26
+ 'Using toggle without force on the server can lead ' +
27
+ 'to unexpected results. Because in a loadData the server will add it ' +
28
+ 'and the client will afterwards remove it.',
29
+ );
30
+ }
31
+
32
+ const exists = this.inner.has(cls);
33
+ const shouldExist = typeof force === 'boolean' ? force : !exists;
34
+ const changed = shouldExist !== exists;
35
+
36
+ if (shouldExist) this.inner.add(cls);
37
+ else this.inner.delete(cls);
38
+
39
+ return changed;
40
+ }
41
+
42
+ remove(...classes: string[]): void {
43
+ validate(classes);
44
+ classes.forEach(cls => this.inner.delete(cls));
45
+ }
46
+
47
+ /**
48
+ * @returns Returns true if the value was changed
49
+ */
50
+ setVariant(variant: string, cls: string | null): boolean {
51
+ return this.inner.setVariant(variant, cls);
52
+ }
53
+
54
+ toRequest(): ServerBodyClass {
55
+ // no second request should ever start on the server
56
+ return this;
57
+ }
58
+
59
+ z_populateSsrCache(ssrCache: SsrCache): void {
60
+ variantsToSsrCache(this.inner.z_variants, ssrCache);
61
+ }
62
+
63
+ z_processHtmlTemplate(html: string): string {
64
+ const SEARCH_STR = '<!--body-class-->';
65
+ if (this.inner.length && !html.includes(SEARCH_STR)) {
66
+ throw new Error(
67
+ 'index.html needs to contain `class="<!--body-class-->"`',
68
+ );
69
+ }
70
+
71
+ return html.replace(
72
+ SEARCH_STR,
73
+ Array.from(this.inner.classes()).join(' '),
74
+ );
75
+ }
76
+ }
77
+
78
+ function validate(classes: string[]) {
79
+ for (const cls of classes) {
80
+ if (cls.includes(' ')) {
81
+ throw new Error(
82
+ `Invalid class name "${cls}". Class names must not contain spaces.`,
83
+ );
84
+ }
85
+ }
86
+ }
@@ -0,0 +1 @@
1
+ export { default as BodyClass } from './BodyClass.js';
@@ -0,0 +1,118 @@
1
+ import SsrCache from '../ssr/SsrCache.js';
2
+
3
+ export type HistoryClassSet = {
4
+ add(cls: string): void;
5
+ remove(cls: string): void;
6
+ setVariant(variant: string, cls: string | null): void;
7
+ };
8
+
9
+ export class ClassSet {
10
+ private _classes: Set<string>;
11
+ /** @hidden */
12
+ z_variants: Variants;
13
+ private history: ((cl: HistoryClassSet) => void)[] | null;
14
+
15
+ constructor(
16
+ classes?: Iterable<string>,
17
+ variants?: Iterable<[string, string]>,
18
+ history: boolean = false,
19
+ ) {
20
+ this._classes = new Set(classes);
21
+ this.z_variants = new Variants();
22
+ this.history = history ? [] : null;
23
+ }
24
+
25
+ classes(): Iterable<string> {
26
+ return this._classes;
27
+ }
28
+
29
+ get length(): number {
30
+ return this._classes.size;
31
+ }
32
+
33
+ has(cls: string): boolean {
34
+ return this._classes.has(cls);
35
+ }
36
+
37
+ add(cls: string): void {
38
+ this._classes.add(cls);
39
+ if (this.history) this.history.push(c => c.add(cls));
40
+ }
41
+
42
+ delete(cls: string): void {
43
+ this._classes.delete(cls);
44
+ if (this.history) this.history.push(c => c.remove(cls));
45
+ }
46
+
47
+ /**
48
+ * @returns Returns true if the value was changed
49
+ */
50
+ setVariant(variant: string, cls: string | null): boolean {
51
+ const { remove, add } = this.z_variants.set(variant, cls);
52
+
53
+ if (remove) this.delete(remove);
54
+ if (add) this.add(add);
55
+
56
+ const changed = !!remove || !!add;
57
+
58
+ if (this.history) this.history.push(c => c.setVariant(variant, cls));
59
+
60
+ return changed;
61
+ }
62
+
63
+ /**
64
+ * Fails if no history is active.
65
+ */
66
+ applyHistory(cl: HistoryClassSet): void {
67
+ this.history!.forEach(fn => fn(cl));
68
+ }
69
+ }
70
+
71
+ export type VariantSetReturn = {
72
+ remove?: string;
73
+ add?: string;
74
+ };
75
+
76
+ export class Variants {
77
+ // list of active variant classes
78
+ private inner: Map<string, string>;
79
+
80
+ constructor(entries?: Iterable<[string, string]>) {
81
+ this.inner = new Map(entries);
82
+ }
83
+
84
+ set(variant: string, cls: string | null): VariantSetReturn {
85
+ const current = this.inner.get(variant) ?? null;
86
+
87
+ if (current === cls) return {};
88
+
89
+ const obj: VariantSetReturn = {};
90
+
91
+ if (current) obj.remove = current;
92
+ if (cls) {
93
+ obj.add = cls;
94
+ this.inner.set(variant, cls);
95
+ } else {
96
+ this.inner.delete(variant);
97
+ }
98
+
99
+ return obj;
100
+ }
101
+
102
+ entries(): Iterable<[string, string]> {
103
+ return this.inner.entries();
104
+ }
105
+ }
106
+
107
+ // separate function for tree shaking
108
+ export function ssrCacheToVariants(ssrCache: SsrCache): Variants {
109
+ return new Variants(ssrCache.get('BODY_CLASS_VAR')!);
110
+ }
111
+
112
+ // separate function for tree shaking
113
+ export function variantsToSsrCache(
114
+ variants: Variants,
115
+ ssrCache: SsrCache,
116
+ ): void {
117
+ ssrCache.set('BODY_CLASS_VAR', Array.from(variants.entries()));
118
+ }
@@ -1,26 +1,57 @@
1
- import { Cookies, RemoveOptions, SetOptions } from './index.js';
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
- // the philosophy here is that document.cookie is the source of truth
5
- // so we don't cache cookies here
6
- // if this changes, modify init/client.ts
7
- export default class ClientCookies implements Cookies {
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
- const cookies = getCookies();
12
- return cookies.get(name) ?? null;
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
- document.cookie = setCookieToString(setCookie);
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 { Cookies, RemoveOptions, SetOptions } from './index.js';
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 Cookies {
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
- /// Rethrns the value of the cookie with the given name, or null if it doesn't exist.
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
- // js allows undefined > 0
21
- if (setCookie && setCookie.maxAge! > 0) {
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));
@@ -1,29 +1,5 @@
1
- export type SetOptions = {
2
- maxAge?: number;
3
- path?: string;
4
- domain?: string;
5
- secure?: boolean;
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,10 @@ export function newCrelte({
282
290
  router,
283
291
  queries,
284
292
  cookies,
293
+ bodyClass,
294
+
295
+ // when adding a new helper function make sure to add it to
296
+ // onNewCrelteRequest if needed
285
297
 
286
298
  getPlugin: name => plugins.get(name),
287
299
  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
  *