@primate/svelte 0.15.0 → 0.15.2
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/package.json +1 -1
- package/src/client/client.js +14 -0
- package/src/client/create-root.js +25 -0
- package/src/client/exports.js +3 -0
- package/src/client/liveview.js +16 -0
- package/src/client/rootname.js +1 -0
- package/src/module.js +15 -64
package/package.json
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import rootname from "./rootname.js";
|
|
2
|
+
import liveview from "./liveview.js";
|
|
3
|
+
|
|
4
|
+
export default ({names, data}, options) => `
|
|
5
|
+
import * as components from "app";
|
|
6
|
+
let root = new components.${rootname}({
|
|
7
|
+
target: document.body,
|
|
8
|
+
hydrate: true,
|
|
9
|
+
props: {
|
|
10
|
+
components: [${names.map(name => `components.${name}`).join(", ")}],
|
|
11
|
+
data: JSON.parse(${JSON.stringify(JSON.stringify(data))}),
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
${options.liveview ? liveview : ""}`;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export default (length, data) => {
|
|
2
|
+
const n = length - 1;
|
|
3
|
+
const body = Array.from({length: n}, (_, i) => i - 1)
|
|
4
|
+
.reduceRight((child, _, i) => `
|
|
5
|
+
{#if components[${i + 1}]}
|
|
6
|
+
<svelte:component this={components[${i}]} ${data}={data[${i}]}>
|
|
7
|
+
${child}
|
|
8
|
+
</svelte:component>
|
|
9
|
+
{:else}
|
|
10
|
+
<svelte:component this={components[${i}]} ${data}={data[${i}]} />
|
|
11
|
+
{/if}
|
|
12
|
+
`, `<svelte:component this={components[${n}]} ${data}={data[${n}]} />`);
|
|
13
|
+
|
|
14
|
+
return `
|
|
15
|
+
<script>
|
|
16
|
+
import {afterUpdate} from "svelte";
|
|
17
|
+
export let components;
|
|
18
|
+
export let data;
|
|
19
|
+
export let update = () => undefined;
|
|
20
|
+
|
|
21
|
+
afterUpdate(update);
|
|
22
|
+
</script>
|
|
23
|
+
${body}
|
|
24
|
+
`;
|
|
25
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import rootname from "./rootname.js";
|
|
2
|
+
|
|
3
|
+
export default `
|
|
4
|
+
const {liveview} = components;
|
|
5
|
+
window.addEventListener("DOMContentLoaded", _ => liveview((props, update) => {
|
|
6
|
+
root.$destroy();
|
|
7
|
+
root = new components.${rootname}({
|
|
8
|
+
target: document.body,
|
|
9
|
+
hydrate: true,
|
|
10
|
+
props: {
|
|
11
|
+
components: props.names.map(name => components[name]),
|
|
12
|
+
data: props.data,
|
|
13
|
+
update,
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
}));`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default "root";
|
package/src/module.js
CHANGED
|
@@ -4,13 +4,14 @@ import {Response, Status, MediaType} from "runtime-compat/http";
|
|
|
4
4
|
import * as compiler from "svelte/compiler";
|
|
5
5
|
import {tryreturn} from "runtime-compat/async";
|
|
6
6
|
import errors from "./errors.js";
|
|
7
|
+
import {client, create_root, rootname} from "./client/exports.js";
|
|
7
8
|
|
|
8
9
|
const endings = {
|
|
9
10
|
svelte: ".svelte",
|
|
10
11
|
js: ".svelte.js",
|
|
11
12
|
};
|
|
12
|
-
const rootname = "root";
|
|
13
13
|
|
|
14
|
+
const encoder = new TextEncoder();
|
|
14
15
|
const hash = async (string, algorithm = "sha-256") => {
|
|
15
16
|
const base = 16;
|
|
16
17
|
const target_pad_length = 2;
|
|
@@ -25,11 +26,6 @@ const normalize = async path => `_${await hash(path)}`;
|
|
|
25
26
|
|
|
26
27
|
const filename = `${rootname}.js`;
|
|
27
28
|
|
|
28
|
-
const options = {
|
|
29
|
-
server: {generate: "ssr", hydratable: true},
|
|
30
|
-
client: {generate: "dom", hydratable: true},
|
|
31
|
-
};
|
|
32
|
-
|
|
33
29
|
const type = "module";
|
|
34
30
|
|
|
35
31
|
const load = async path =>
|
|
@@ -39,10 +35,12 @@ const load = async path =>
|
|
|
39
35
|
const make_component = base => async (name, props) =>
|
|
40
36
|
({name, component: await load(base.join(name)), props});
|
|
41
37
|
|
|
42
|
-
const encoder = new TextEncoder();
|
|
43
|
-
|
|
44
38
|
const handler = (name, props = {}, {status = Status.OK, page} = {}) =>
|
|
45
39
|
async (app, {layouts = [], as_layout} = {}, request) => {
|
|
40
|
+
const options = {
|
|
41
|
+
liveview: app.liveview !== undefined,
|
|
42
|
+
};
|
|
43
|
+
const {headers} = request;
|
|
46
44
|
const {paths} = app.build;
|
|
47
45
|
const make = make_component(paths.server.join(app.config.build.app));
|
|
48
46
|
if (as_layout) {
|
|
@@ -57,15 +55,14 @@ const handler = (name, props = {}, {status = Status.OK, page} = {}) =>
|
|
|
57
55
|
const data = components.map(component => component.props);
|
|
58
56
|
const names = await Promise.all(components.map(component =>
|
|
59
57
|
normalize(component.name)));
|
|
60
|
-
|
|
61
|
-
const liveview = app.liveview !== undefined;
|
|
62
|
-
if (liveview && request.headers.get(app.liveview.header) !== undefined) {
|
|
58
|
+
if (options.liveview && headers.get(app.liveview.header) !== undefined) {
|
|
63
59
|
return new Response(JSON.stringify({names, data}), {
|
|
64
60
|
status,
|
|
65
61
|
headers: {...await app.headers(),
|
|
66
62
|
"Content-Type": MediaType.APPLICATION_JSON},
|
|
67
63
|
});
|
|
68
64
|
}
|
|
65
|
+
|
|
69
66
|
const root = paths.server.join(filename);
|
|
70
67
|
const imported = (await import(root)).default;
|
|
71
68
|
const {html} = imported.render({
|
|
@@ -73,67 +70,21 @@ const handler = (name, props = {}, {status = Status.OK, page} = {}) =>
|
|
|
73
70
|
data,
|
|
74
71
|
});
|
|
75
72
|
|
|
76
|
-
const code =
|
|
77
|
-
import * as components from "app";
|
|
78
|
-
const getComponents = names =>
|
|
79
|
-
Object.entries(components).filter(([name, component]) =>
|
|
80
|
-
names.includes(name))
|
|
81
|
-
.map(([, component]) => component);
|
|
82
|
-
let root = new components.${rootname}({
|
|
83
|
-
target: document.body,
|
|
84
|
-
hydrate: true,
|
|
85
|
-
props: {
|
|
86
|
-
components: getComponents([${names.map(name => `"${name}"`)}]),
|
|
87
|
-
data: JSON.parse(${JSON.stringify(JSON.stringify(data))}),
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
${liveview ? `
|
|
92
|
-
const {liveview} = components;
|
|
93
|
-
window.addEventListener("DOMContentLoaded", _ => liveview(props => {
|
|
94
|
-
root.$destroy();
|
|
95
|
-
root = new components.${rootname}({
|
|
96
|
-
target: document.body,
|
|
97
|
-
hydrate: true,
|
|
98
|
-
props: {
|
|
99
|
-
components: getComponents(props.names),
|
|
100
|
-
data: props.data,
|
|
101
|
-
},
|
|
102
|
-
});
|
|
103
|
-
}));
|
|
104
|
-
` : ""}
|
|
105
|
-
`;
|
|
73
|
+
const code = client({names, data}, options);
|
|
106
74
|
|
|
107
75
|
await app.publish({code, type, inline: true});
|
|
108
|
-
|
|
109
|
-
const headers = await app.headers();
|
|
76
|
+
// needs to be called before app.render
|
|
77
|
+
const headers$ = await app.headers();
|
|
110
78
|
|
|
111
79
|
return new Response(await app.render({body: html, page}), {
|
|
112
80
|
status,
|
|
113
|
-
headers: {...headers
|
|
81
|
+
headers: {...headers$, "Content-Type": MediaType.TEXT_HTML},
|
|
114
82
|
});
|
|
115
83
|
};
|
|
116
84
|
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
.reduceRight((child, _, i) => `
|
|
121
|
-
{#if components[${i + 1}]}
|
|
122
|
-
<svelte:component this={components[${i}]} ${data}={data[${i}]}>
|
|
123
|
-
${child}
|
|
124
|
-
</svelte:component>
|
|
125
|
-
{:else}
|
|
126
|
-
<svelte:component this={components[${i}]} ${data}={data[${i}]} />
|
|
127
|
-
{/if}
|
|
128
|
-
`, `<svelte:component this={components[${n}]} ${data}={data[${n}]} />`);
|
|
129
|
-
|
|
130
|
-
return `
|
|
131
|
-
<script>
|
|
132
|
-
export let components;
|
|
133
|
-
export let data;
|
|
134
|
-
</script>
|
|
135
|
-
${body}
|
|
136
|
-
`;
|
|
85
|
+
const options = {
|
|
86
|
+
server: {generate: "ssr", hydratable: true},
|
|
87
|
+
client: {generate: "dom", hydratable: true},
|
|
137
88
|
};
|
|
138
89
|
|
|
139
90
|
const {svelte, js} = endings;
|