crelte 0.1.0

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 (130) hide show
  1. package/LICENSE.md +41 -0
  2. package/dist/Crelte.d.ts +55 -0
  3. package/dist/Crelte.d.ts.map +1 -0
  4. package/dist/Crelte.js +106 -0
  5. package/dist/CrelteBase.d.ts +16 -0
  6. package/dist/CrelteBase.d.ts.map +1 -0
  7. package/dist/CrelteBase.js +1 -0
  8. package/dist/CrelteRouted.d.ts +50 -0
  9. package/dist/CrelteRouted.d.ts.map +1 -0
  10. package/dist/CrelteRouted.js +88 -0
  11. package/dist/blocks/Blocks.d.ts +35 -0
  12. package/dist/blocks/Blocks.d.ts.map +1 -0
  13. package/dist/blocks/Blocks.js +100 -0
  14. package/dist/blocks/Blocks.svelte +21 -0
  15. package/dist/blocks/Blocks.svelte.d.ts +24 -0
  16. package/dist/blocks/Blocks.svelte.d.ts.map +1 -0
  17. package/dist/blocks/index.d.ts +5 -0
  18. package/dist/blocks/index.d.ts.map +1 -0
  19. package/dist/blocks/index.js +3 -0
  20. package/dist/cookies/ClientCookies.d.ts +9 -0
  21. package/dist/cookies/ClientCookies.d.ts.map +1 -0
  22. package/dist/cookies/ClientCookies.js +22 -0
  23. package/dist/cookies/ServerCookies.d.ts +13 -0
  24. package/dist/cookies/ServerCookies.d.ts.map +1 -0
  25. package/dist/cookies/ServerCookies.js +31 -0
  26. package/dist/cookies/index.d.ts +20 -0
  27. package/dist/cookies/index.d.ts.map +1 -0
  28. package/dist/cookies/index.js +1 -0
  29. package/dist/cookies/utils.d.ts +12 -0
  30. package/dist/cookies/utils.d.ts.map +1 -0
  31. package/dist/cookies/utils.js +32 -0
  32. package/dist/graphql/GraphQl.d.ts +60 -0
  33. package/dist/graphql/GraphQl.d.ts.map +1 -0
  34. package/dist/graphql/GraphQl.js +197 -0
  35. package/dist/graphql/gql.test.d.ts +2 -0
  36. package/dist/graphql/gql.test.d.ts.map +1 -0
  37. package/dist/graphql/gql.test.js +80 -0
  38. package/dist/graphql/index.d.ts +3 -0
  39. package/dist/graphql/index.d.ts.map +1 -0
  40. package/dist/graphql/index.js +2 -0
  41. package/dist/index.d.ts +67 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +83 -0
  44. package/dist/init/client.d.ts +13 -0
  45. package/dist/init/client.d.ts.map +1 -0
  46. package/dist/init/client.js +129 -0
  47. package/dist/init/server.d.ts +38 -0
  48. package/dist/init/server.d.ts.map +1 -0
  49. package/dist/init/server.js +95 -0
  50. package/dist/init/shared.d.ts +29 -0
  51. package/dist/init/shared.d.ts.map +1 -0
  52. package/dist/init/shared.js +154 -0
  53. package/dist/loadData/Globals.d.ts +33 -0
  54. package/dist/loadData/Globals.d.ts.map +1 -0
  55. package/dist/loadData/Globals.js +119 -0
  56. package/dist/loadData/index.d.ts +25 -0
  57. package/dist/loadData/index.d.ts.map +1 -0
  58. package/dist/loadData/index.js +39 -0
  59. package/dist/plugins/Events.d.ts +11 -0
  60. package/dist/plugins/Events.d.ts.map +1 -0
  61. package/dist/plugins/Events.js +29 -0
  62. package/dist/plugins/Plugins.d.ts +12 -0
  63. package/dist/plugins/Plugins.d.ts.map +1 -0
  64. package/dist/plugins/Plugins.js +12 -0
  65. package/dist/plugins/index.d.ts +5 -0
  66. package/dist/plugins/index.d.ts.map +1 -0
  67. package/dist/plugins/index.js +2 -0
  68. package/dist/routing/History.d.ts +22 -0
  69. package/dist/routing/History.d.ts.map +1 -0
  70. package/dist/routing/History.js +36 -0
  71. package/dist/routing/InnerRouter.d.ts +111 -0
  72. package/dist/routing/InnerRouter.d.ts.map +1 -0
  73. package/dist/routing/InnerRouter.js +397 -0
  74. package/dist/routing/PageLoader.d.ts +37 -0
  75. package/dist/routing/PageLoader.d.ts.map +1 -0
  76. package/dist/routing/PageLoader.js +72 -0
  77. package/dist/routing/Route.d.ts +82 -0
  78. package/dist/routing/Route.d.ts.map +1 -0
  79. package/dist/routing/Route.js +134 -0
  80. package/dist/routing/Router.d.ts +162 -0
  81. package/dist/routing/Router.d.ts.map +1 -0
  82. package/dist/routing/Router.js +333 -0
  83. package/dist/routing/Site.d.ts +47 -0
  84. package/dist/routing/Site.d.ts.map +1 -0
  85. package/dist/routing/Site.js +48 -0
  86. package/dist/routing/index.d.ts +5 -0
  87. package/dist/routing/index.d.ts.map +1 -0
  88. package/dist/routing/index.js +4 -0
  89. package/dist/ssr/SsrCache.d.ts +12 -0
  90. package/dist/ssr/SsrCache.d.ts.map +1 -0
  91. package/dist/ssr/SsrCache.js +50 -0
  92. package/dist/ssr/SsrComponents.d.ts +7 -0
  93. package/dist/ssr/SsrComponents.d.ts.map +1 -0
  94. package/dist/ssr/SsrComponents.js +30 -0
  95. package/dist/ssr/index.d.ts +4 -0
  96. package/dist/ssr/index.d.ts.map +1 -0
  97. package/dist/ssr/index.js +3 -0
  98. package/package.json +79 -0
  99. package/src/Crelte.ts +135 -0
  100. package/src/CrelteBase.ts +24 -0
  101. package/src/CrelteRouted.ts +128 -0
  102. package/src/blocks/Blocks.svelte +68 -0
  103. package/src/blocks/Blocks.ts +155 -0
  104. package/src/blocks/index.ts +14 -0
  105. package/src/cookies/ClientCookies.ts +30 -0
  106. package/src/cookies/ServerCookies.ts +42 -0
  107. package/src/cookies/index.ts +24 -0
  108. package/src/cookies/utils.ts +53 -0
  109. package/src/graphql/GraphQl.ts +281 -0
  110. package/src/graphql/gql.test.ts +123 -0
  111. package/src/graphql/index.ts +8 -0
  112. package/src/index.ts +109 -0
  113. package/src/init/client.ts +190 -0
  114. package/src/init/server.ts +177 -0
  115. package/src/init/shared.ts +221 -0
  116. package/src/loadData/Globals.ts +150 -0
  117. package/src/loadData/index.ts +67 -0
  118. package/src/plugins/Events.ts +50 -0
  119. package/src/plugins/Plugins.ts +23 -0
  120. package/src/plugins/index.ts +5 -0
  121. package/src/routing/History.ts +52 -0
  122. package/src/routing/InnerRouter.ts +469 -0
  123. package/src/routing/PageLoader.ts +112 -0
  124. package/src/routing/Route.ts +184 -0
  125. package/src/routing/Router.ts +476 -0
  126. package/src/routing/Site.ts +65 -0
  127. package/src/routing/index.ts +5 -0
  128. package/src/ssr/SsrCache.ts +61 -0
  129. package/src/ssr/SsrComponents.ts +34 -0
  130. package/src/ssr/index.ts +4 -0
package/src/Crelte.ts ADDED
@@ -0,0 +1,135 @@
1
+ import ClientCookies from './cookies/ClientCookies.js';
2
+ import { Cookies } from './cookies/index.js';
3
+ import ServerCookies from './cookies/ServerCookies.js';
4
+ import CrelteBase from './CrelteBase.js';
5
+ import CrelteRouted, { GraphQlQuery } from './CrelteRouted.js';
6
+ import GraphQl, {
7
+ GraphQlOptions,
8
+ GraphQlRequestOptions,
9
+ } from './graphql/GraphQl.js';
10
+ import Globals from './loadData/Globals.js';
11
+ import Events from './plugins/Events.js';
12
+ import Plugins, { Plugin } from './plugins/Plugins.js';
13
+ import Route from './routing/Route.js';
14
+ import Router, { RouterOpts } from './routing/Router.js';
15
+ import Site, { SiteFromGraphQl } from './routing/Site.js';
16
+ import SsrCache from './ssr/SsrCache.js';
17
+
18
+ export class CrelteBuilder {
19
+ ssrCache: SsrCache;
20
+ plugins: Plugins;
21
+ events: Events;
22
+ graphQl?: GraphQl;
23
+ router?: Router;
24
+ globals: Globals;
25
+ cookies: Cookies;
26
+
27
+ constructor() {
28
+ this.ssrCache = new SsrCache();
29
+ this.plugins = new Plugins();
30
+ this.events = new Events();
31
+ this.globals = new Globals();
32
+ // @ts-ignore
33
+ this.cookies = import.meta.env.SSR
34
+ ? new ServerCookies()
35
+ : new ClientCookies();
36
+ }
37
+
38
+ setupGraphQl(endpoint: string, opts: GraphQlOptions = {}) {
39
+ this.graphQl = new GraphQl(endpoint, this.ssrCache, opts);
40
+ }
41
+
42
+ setupRouter(sites: SiteFromGraphQl[], opts: RouterOpts = {}) {
43
+ this.router = new Router(sites, opts);
44
+ }
45
+
46
+ setupCookies(cookies: string) {
47
+ this.cookies._init(cookies);
48
+ }
49
+
50
+ build(): Crelte {
51
+ return new Crelte(this);
52
+ }
53
+ }
54
+
55
+ export default class Crelte implements CrelteBase {
56
+ ssrCache: SsrCache;
57
+ graphQl: GraphQl;
58
+ router: Router;
59
+ plugins: Plugins;
60
+ events: Events;
61
+ globals: Globals;
62
+ cookies: Cookies;
63
+
64
+ constructor(builder: CrelteBuilder) {
65
+ if (!builder.graphQl || !builder.router)
66
+ throw new Error('builder not ready');
67
+
68
+ this.ssrCache = builder.ssrCache;
69
+ this.graphQl = builder.graphQl;
70
+ this.router = builder.router;
71
+ this.plugins = builder.plugins;
72
+ this.events = builder.events;
73
+ this.globals = builder.globals;
74
+ this.cookies = builder.cookies;
75
+ }
76
+
77
+ getPlugin(name: string): Plugin | null {
78
+ return this.plugins.get(name);
79
+ }
80
+
81
+ /**
82
+ * returns an env Variables, always needs to be prefixed VITE_
83
+ * Except ENDPOINT_URL and CRAFT_WEB_URL
84
+ */
85
+ getEnv(name: string): string | null {
86
+ return this.ssrCache.get(name);
87
+ }
88
+
89
+ /// calling this from loadGlobalData will always return null
90
+ /// this does return the resolved store
91
+ getGlobal(name: string): any | null {
92
+ return this.globals.get(name) ?? null;
93
+ }
94
+
95
+ /// requires a site if the route does not contain a site
96
+ toRouted(route?: Route, site?: Site): CrelteRouted {
97
+ if (!route) {
98
+ route = this.router.route.get();
99
+ }
100
+
101
+ if (!site) {
102
+ if (!route.site) throw new Error('site is required');
103
+ site = route.site;
104
+ }
105
+
106
+ return new CrelteRouted(this, route, site);
107
+ }
108
+
109
+ /**
110
+ * Run a GraphQl Query
111
+ *
112
+ * @param query the default export from a graphql file
113
+ * @param variables variables that should be passed to the
114
+ * graphql query
115
+ * @param options opts `{ caching: true, previewToken: string,
116
+ * siteToken: string, ignoreStatusCode: false, headers: {} }`
117
+ */
118
+ async query(
119
+ query: GraphQlQuery,
120
+ variables: Record<string, unknown> = {},
121
+ opts: GraphQlRequestOptions = {},
122
+ ): Promise<unknown> {
123
+ // this function is added as convenience
124
+ return this.toRouted().query(query, variables, opts);
125
+ }
126
+
127
+ // don't use
128
+ _getContext(): Map<string, any> {
129
+ const map = new Map();
130
+
131
+ map.set('crelte', this);
132
+
133
+ return map;
134
+ }
135
+ }
@@ -0,0 +1,24 @@
1
+ import { GraphQlQuery } from './CrelteRouted.js';
2
+ import { GraphQlRequestOptions } from './graphql/GraphQl.js';
3
+
4
+ // todo or name it CrelteCommon, CrelteShared?
5
+ export default interface CrelteBase {
6
+ /// calling this from loadGlobalData will always return null
7
+ /// this does return the resolved store
8
+ getGlobal(name: string): any | null;
9
+
10
+ /**
11
+ * Run a GraphQl Query
12
+ *
13
+ * @param query the default export from a graphql file
14
+ * @param variables variables that should be passed to the
15
+ * graphql query
16
+ * @param options opts `{ caching: true, previewToken: string,
17
+ * siteToken: string, ignoreStatusCode: false, headers: {} }`
18
+ */
19
+ query(
20
+ query: GraphQlQuery,
21
+ variables?: Record<string, unknown>,
22
+ opts?: GraphQlRequestOptions,
23
+ ): Promise<unknown>;
24
+ }
@@ -0,0 +1,128 @@
1
+ import { Cookies } from './cookies/index.js';
2
+ import Crelte from './Crelte.js';
3
+ import CrelteBase from './CrelteBase.js';
4
+ import GraphQl, { GraphQlRequestOptions } from './graphql/GraphQl.js';
5
+ import type Globals from './loadData/Globals.js';
6
+ import type Events from './plugins/Events.js';
7
+ import Plugins, { Plugin } from './plugins/Plugins.js';
8
+ import Route from './routing/Route.js';
9
+ import Router from './routing/Router.js';
10
+ import Site from './routing/Site.js';
11
+ import SsrCache from './ssr/SsrCache.js';
12
+
13
+ export type GraphQlQuery = {
14
+ path?: string;
15
+ query: string;
16
+ };
17
+
18
+ export default class CrelteRouted implements CrelteBase {
19
+ route: Route;
20
+ site: Site;
21
+
22
+ private inner: Crelte;
23
+ private innerGlobals: Map<string, any>;
24
+
25
+ constructor(inner: Crelte, route: Route, site: Site) {
26
+ this.route = route;
27
+ this.site = site;
28
+
29
+ this.inner = inner;
30
+ this.innerGlobals = new Map();
31
+ }
32
+
33
+ get crelte(): Crelte {
34
+ return this.inner;
35
+ }
36
+
37
+ get ssrCache(): SsrCache {
38
+ return this.inner.ssrCache;
39
+ }
40
+
41
+ get plugins(): Plugins {
42
+ return this.inner.plugins;
43
+ }
44
+
45
+ get events(): Events {
46
+ return this.inner.events;
47
+ }
48
+
49
+ get graphQl(): GraphQl {
50
+ return this.inner.graphQl;
51
+ }
52
+
53
+ get router(): Router {
54
+ return this.inner.router;
55
+ }
56
+
57
+ get globals(): Globals {
58
+ return this.inner.globals;
59
+ }
60
+
61
+ get cookies(): Cookies {
62
+ return this.inner.cookies;
63
+ }
64
+
65
+ // overload this function to add your plugin type
66
+ getPlugin(name: string): Plugin | null {
67
+ return this.inner.plugins.get(name);
68
+ }
69
+
70
+ /**
71
+ * returns an env Variables, always needs to be prefixed VITE_
72
+ * Except ENDPOINT_URL and CRAFT_WEB_URL
73
+ */
74
+ getEnv(name: string): string | null {
75
+ return this.inner.getEnv(name);
76
+ }
77
+
78
+ /// calling this from loadGlobalData will always return null
79
+ /// this does return the resolved store
80
+ getGlobal(name: string): any | null {
81
+ return this.innerGlobals.get(name) ?? null;
82
+ }
83
+
84
+ /// get a global and wait for it if it is still loaded
85
+ /// this is useful when you need to load a global in the
86
+ /// loadGlobalData function
87
+ async getGlobalAsync(name: string): Promise<any | null> {
88
+ const global = this.innerGlobals.get(name);
89
+ if (global) return global;
90
+
91
+ const r = await this.inner.globals.getAsync(name);
92
+ if (!r) return null;
93
+
94
+ return r.bySiteId(this.site.id);
95
+ }
96
+
97
+ /**
98
+ * Run a GraphQl Query
99
+ *
100
+ * @param query the default export from a graphql file
101
+ * @param variables variables that should be passed to the
102
+ * graphql query
103
+ * @param options opts `{ caching: true, previewToken: string,
104
+ * siteToken: string, ignoreStatusCode: false, headers: {} }`
105
+ */
106
+ async query(
107
+ query: GraphQlQuery,
108
+ variables: Record<string, unknown> = {},
109
+ opts: GraphQlRequestOptions = {},
110
+ ): Promise<unknown> {
111
+ const search = this.route.search;
112
+
113
+ if (search.has('token') && search.get('x-craft-live-preview')) {
114
+ opts.previewToken = search.get('token')!;
115
+ } else if (search.has('siteToken')) {
116
+ opts.siteToken = search.get('siteToken')!;
117
+ }
118
+
119
+ opts.path = query.path;
120
+
121
+ return await this.graphQl.request(query.query, variables, opts);
122
+ }
123
+
124
+ // hidden
125
+ _globalDataLoaded() {
126
+ this.innerGlobals = this.inner.globals._globalsBySite(this.site.id);
127
+ }
128
+ }
@@ -0,0 +1,68 @@
1
+ <script context="module" lang="ts">
2
+ import { CrelteRouted } from '../index.js';
3
+
4
+ /*
5
+ usage:
6
+
7
+ const mods = import.meta.glob('./contentDetail/*.svelte', {
8
+ // can either be eager loaded or not
9
+ eager: true,
10
+ });
11
+
12
+ const mods = blockModules(
13
+ import.meta.glob('./contentDetail/*.svelte', { eager: true }),
14
+ {
15
+ alias: {
16
+ 'contentDetail': 'contentDetail',
17
+ }
18
+ }
19
+ );
20
+
21
+ export const loadData = {
22
+ blocks: (cr, entry) => loadBlocksData(cr, entry.blocks, mods)
23
+ };
24
+
25
+ export let blocks;
26
+
27
+ // provide entry if wanted, all $$restProps will be passed to the children
28
+ <Blocks {blocks} {entry} />
29
+
30
+ */
31
+
32
+ import Blocks, {
33
+ type AsyncModule,
34
+ type Module,
35
+ type BlockModulesOptions,
36
+ BlockModules,
37
+ newBlocks,
38
+ } from './Blocks.js';
39
+
40
+ export type { BlockModules, BlockModulesOptions, AsyncModule, Module };
41
+
42
+ export function blockModules(
43
+ modules: Record<string, AsyncModule>,
44
+ opts: BlockModulesOptions = {},
45
+ ): BlockModules {
46
+ return new BlockModules(modules, opts);
47
+ }
48
+
49
+ export async function loadBlocksData(
50
+ cr: CrelteRouted,
51
+ blocks: any[],
52
+ modules: BlockModules,
53
+ ): Promise<Blocks> {
54
+ const nBlocks = await newBlocks(blocks, modules);
55
+
56
+ await nBlocks.loadData(cr);
57
+
58
+ return nBlocks;
59
+ }
60
+ </script>
61
+
62
+ <script lang="ts">
63
+ export let blocks: Blocks;
64
+ </script>
65
+
66
+ {#each blocks.each() as { mod, props }}
67
+ <svelte:component this={mod} {...props} {...$$restProps} />
68
+ {/each}
@@ -0,0 +1,155 @@
1
+ import { CrelteRouted } from '../index.js';
2
+ import { callLoadData } from '../loadData/index.js';
3
+
4
+ export interface Module {
5
+ // svelte component
6
+ default: any;
7
+ handle?: string | string[];
8
+ keepTypeHandle?: boolean;
9
+
10
+ loadData?: (block: any) => Promise<any>;
11
+ }
12
+
13
+ export type AsyncModule = (() => Promise<Module>) | Module;
14
+
15
+ export type BlockModulesOptions = {
16
+ // if a block should handle multiple blocks
17
+ alias?: Record<string, string>;
18
+ };
19
+
20
+ export class BlockModules {
21
+ modules: Map<string, AsyncModule>;
22
+ alias: Map<string, string>;
23
+
24
+ constructor(
25
+ modules: Record<string, AsyncModule>,
26
+ opts: BlockModulesOptions = {},
27
+ ) {
28
+ this.modules = new Map(
29
+ Object.entries(modules)
30
+ .map(([path, mod]) => {
31
+ const [name, ext] = parseFilename(path);
32
+
33
+ return [ext === 'svelte' ? name : '', mod] as [
34
+ string,
35
+ AsyncModule,
36
+ ];
37
+ })
38
+ .filter(([name, _mod]) => !!name),
39
+ );
40
+
41
+ this.alias = new Map(Object.entries(opts.alias ?? {}));
42
+
43
+ // backwards compatibility allow to use the export const handle
44
+ this.modules.forEach((mod, name) => {
45
+ if (typeof mod === 'function') return;
46
+
47
+ if (mod.handle) {
48
+ const handles = Array.isArray(mod.handle)
49
+ ? mod.handle
50
+ : [mod.handle];
51
+ handles.forEach(handle => {
52
+ this.alias.set(handle, name);
53
+ });
54
+ }
55
+ });
56
+ }
57
+
58
+ /**
59
+ * Loads the required modules
60
+ *
61
+ * @throws an error if a module is not found
62
+ */
63
+ async load(requiredModules: Set<string>): Promise<Map<string, Module>> {
64
+ const loaded = await Promise.all(
65
+ [...requiredModules.keys()].map(mod => {
66
+ let module = this.modules.get(mod);
67
+ if (!module)
68
+ module = this.modules.get(this.alias.get(mod) ?? '');
69
+
70
+ if (!module) throw new Error(`Module ${mod} not found`);
71
+
72
+ return typeof module === 'function' ? module() : module;
73
+ }),
74
+ );
75
+
76
+ // todo once loaded override it in module again
77
+
78
+ return new Map<string, Module>(
79
+ [...requiredModules.keys()].map((mod, i) => [mod, loaded[i]]),
80
+ );
81
+ }
82
+ }
83
+
84
+ export async function newBlocks(blocks: any[], modules: BlockModules) {
85
+ // define all required modules
86
+ const requiredModules: Set<string> = new Set();
87
+
88
+ for (const block of blocks) {
89
+ if (!block.typeHandle) throw new Error('Block must have a typeHandle');
90
+
91
+ requiredModules.add(block.typeHandle);
92
+ }
93
+
94
+ const loadedModules = await modules.load(requiredModules);
95
+
96
+ return new Blocks(blocks, loadedModules);
97
+ }
98
+
99
+ export default class Blocks {
100
+ blocks: any[];
101
+ data: any[];
102
+ modules: Map<string, Module>;
103
+
104
+ constructor(blocks: any[], modules: Map<string, Module>) {
105
+ this.blocks = blocks;
106
+ this.modules = modules;
107
+ this.data = blocks.map(() => null);
108
+ }
109
+
110
+ async loadData(cr: CrelteRouted) {
111
+ this.data = await Promise.all(
112
+ this.blocks.map((block, i) => {
113
+ const mod = this.modules.get(block.typeHandle)!;
114
+
115
+ if ('loadData' in mod) {
116
+ return callLoadData(mod.loadData, cr, block, {
117
+ getSibling: (offset: number) => {
118
+ return this.blocks[i + offset] ?? null;
119
+ },
120
+ });
121
+ }
122
+
123
+ return {};
124
+ }),
125
+ );
126
+ }
127
+
128
+ each(): { mod: any; props: any }[] {
129
+ return this.blocks.map((block, i) => {
130
+ const mod = this.modules.get(block.typeHandle)!;
131
+
132
+ const props = { ...block };
133
+ if (!mod.keepTypeHandle) delete props.typeHandle;
134
+ Object.assign(props, this.data[i]);
135
+
136
+ return {
137
+ mod: mod.default,
138
+ props,
139
+ };
140
+ });
141
+ }
142
+ }
143
+
144
+ function parseFilename(path: string): [string, string] {
145
+ // get filename with extension
146
+ const slash = path.lastIndexOf('/');
147
+ const filename = path.substring(slash + 1);
148
+
149
+ const extPos = filename.lastIndexOf('.');
150
+
151
+ const name = filename.substring(0, extPos);
152
+ const ext = filename.substring(extPos + 1);
153
+
154
+ return [name, ext];
155
+ }
@@ -0,0 +1,14 @@
1
+ import Blocks, {
2
+ type BlockModules,
3
+ type BlockModulesOptions,
4
+ type AsyncModule,
5
+ type Module,
6
+ blockModules,
7
+ loadBlocksData,
8
+ } from './Blocks.svelte';
9
+
10
+ export type { BlockModules, BlockModulesOptions, AsyncModule, Module };
11
+
12
+ export { Blocks, blockModules, loadBlocksData };
13
+
14
+ export default Blocks;
@@ -0,0 +1,30 @@
1
+ import { Cookies, SetOptions } from './index.js';
2
+ import { parseCookies, setCookieToString } from './utils.js';
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() {}
9
+
10
+ _init(_cookies: string): void {}
11
+
12
+ get(name: string): string | null {
13
+ const cookies = getCookies();
14
+ return cookies.get(name) ?? null;
15
+ }
16
+
17
+ set(name: string, value: string, opts?: SetOptions): void {
18
+ const setCookie = { name, value, ...opts };
19
+
20
+ document.cookie = setCookieToString(setCookie);
21
+ }
22
+
23
+ remove(name: string): void {
24
+ this.set(name, '', { maxAge: 0 });
25
+ }
26
+ }
27
+
28
+ function getCookies(): Map<string, string> {
29
+ return parseCookies(document.cookie);
30
+ }
@@ -0,0 +1,42 @@
1
+ import { Cookies, SetOptions } from './index.js';
2
+ import { parseCookies, SetCookie, setCookieToString } from './utils.js';
3
+
4
+ export default class ServerCookies implements Cookies {
5
+ requestCookies: Map<string, string>;
6
+ setCookies: Map<string, SetCookie>;
7
+
8
+ constructor() {
9
+ this.requestCookies = new Map();
10
+ this.setCookies = new Map();
11
+ }
12
+
13
+ _init(cookies: string): void {
14
+ // parse the cookies
15
+ this.requestCookies = parseCookies(cookies);
16
+ }
17
+
18
+ /// Rethrns the value of the cookie with the given name, or null if it doesn't exist.
19
+ get(name: string): string | null {
20
+ const setCookie = this.setCookies.get(name);
21
+ // js allows undefined > 0
22
+ if (setCookie && setCookie.maxAge! > 0) {
23
+ return setCookie.value;
24
+ }
25
+
26
+ return this.requestCookies.get(name) ?? null;
27
+ }
28
+
29
+ set(name: string, value: string, opts?: SetOptions): void {
30
+ this.setCookies.set(name, { name, value, ...opts });
31
+ }
32
+
33
+ remove(name: string): void {
34
+ this.set(name, '', { maxAge: 0 });
35
+ }
36
+
37
+ _getSetCookiesHeaders(): string[] {
38
+ return Array.from(this.setCookies.values()).map(setCookie =>
39
+ setCookieToString(setCookie),
40
+ );
41
+ }
42
+ }
@@ -0,0 +1,24 @@
1
+ export type SetOptions = {
2
+ maxAge?: number;
3
+ path?: string;
4
+ domain?: string;
5
+ secure?: boolean;
6
+ httpOnly?: boolean;
7
+ };
8
+
9
+ export interface Cookies {
10
+ /**
11
+ * returns the value of the cookie
12
+ */
13
+ get(name: string): string | null;
14
+
15
+ /**
16
+ * sets the value of the cookie
17
+ */
18
+ set(name: string, value: string, opts?: SetOptions): void;
19
+
20
+ remove(name: string): void;
21
+
22
+ // doc hidden
23
+ _init(cookies: string): void;
24
+ }
@@ -0,0 +1,53 @@
1
+ export function parseCookies(cookies: string): Map<string, string> {
2
+ return new Map(
3
+ cookies.split(';').map(cookie => {
4
+ let [name, value] = cookie.split('=');
5
+ /// this is the behaviour of chrome
6
+ if (typeof value === 'undefined') {
7
+ value = name;
8
+ name = '';
9
+ }
10
+
11
+ name = name.trim();
12
+ value = decodeURIComponent(value.trim());
13
+
14
+ return [name, value];
15
+ }),
16
+ );
17
+ }
18
+
19
+ export type SetCookie = {
20
+ name: string;
21
+ value: string;
22
+ maxAge?: number;
23
+ path?: string;
24
+ domain?: string;
25
+ secure?: boolean;
26
+ httpOnly?: boolean;
27
+ };
28
+
29
+ export function setCookieToString(cookie: SetCookie): string {
30
+ let s = `${cookie.name}=${encodeURIComponent(cookie.value)}`;
31
+
32
+ if (typeof cookie.maxAge === 'number') {
33
+ s += `; Max-Age=${cookie.maxAge}`;
34
+ }
35
+
36
+ if (cookie.path) {
37
+ s += `; Path=${cookie.path}`;
38
+ }
39
+
40
+ if (cookie.domain) {
41
+ s += `; Domain=${cookie.domain}`;
42
+ }
43
+
44
+ if (cookie.secure) {
45
+ s += `; Secure`;
46
+ }
47
+
48
+ if (cookie.httpOnly) {
49
+ s += `; HttpOnly`;
50
+ }
51
+
52
+ return s;
53
+ }