@primate/solid 0.0.2 → 0.2.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.
- package/README.md +1 -2
- package/package.json +4 -3
- package/src/client/client.js +3 -3
- package/src/client/exports.js +0 -1
- package/src/client/hydrate.js +4 -1
- package/src/client/liveview.js +5 -6
- package/src/module.js +47 -132
- package/src/client/create-root2.js +0 -22
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primate/solid",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Primate Solid module",
|
|
5
5
|
"homepage": "https://primatejs.com/modules/solid",
|
|
6
6
|
"bugs": "https://github.com/primatejs/primate/issues",
|
|
@@ -16,12 +16,13 @@
|
|
|
16
16
|
"directory": "packages/solid"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
+
"@primate/frontend": "^0.2.0",
|
|
19
20
|
"babel-preset-solid": "^1.7.7",
|
|
20
|
-
"runtime-compat": "^0.25.
|
|
21
|
+
"runtime-compat": "^0.25.7",
|
|
21
22
|
"solid-js": "^1.7.11"
|
|
22
23
|
},
|
|
23
24
|
"peerDependencies": {
|
|
24
|
-
"primate": "0.
|
|
25
|
+
"primate": "0.22"
|
|
25
26
|
},
|
|
26
27
|
"type": "module",
|
|
27
28
|
"exports": "./src/exports.js"
|
package/src/client/client.js
CHANGED
|
@@ -7,13 +7,13 @@ const {groups: {code: hydration_script}} = generateHydrationScript()
|
|
|
7
7
|
|
|
8
8
|
export default ({names, data}, options) => `
|
|
9
9
|
import * as components from "app";
|
|
10
|
-
import {hydrate_solid} from "app";
|
|
10
|
+
import {hydrate_solid, render_solid} from "app";
|
|
11
11
|
|
|
12
|
-
window._$HY = {
|
|
12
|
+
window._$HY = {events: [], completed: new WeakSet(), r: {}};
|
|
13
13
|
|
|
14
14
|
${hydration_script}
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
let dispose = hydrate_solid(() => components.${rootname}({
|
|
17
17
|
components: [${names.map(name => `components.${name}`).join(", ")}],
|
|
18
18
|
data: JSON.parse(${JSON.stringify(JSON.stringify(data))}),
|
|
19
19
|
}), globalThis.window.document.body);
|
package/src/client/exports.js
CHANGED
package/src/client/hydrate.js
CHANGED
package/src/client/liveview.js
CHANGED
|
@@ -3,10 +3,9 @@ import rootname from "./rootname.js";
|
|
|
3
3
|
export default `
|
|
4
4
|
const {liveview} = components;
|
|
5
5
|
window.addEventListener("DOMContentLoaded", _ => liveview((props, update) => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
);
|
|
6
|
+
dispose();
|
|
7
|
+
dispose = render_solid(() => components.${rootname}({
|
|
8
|
+
components: props.names.map(name => components[name]),
|
|
9
|
+
data: props.data,
|
|
10
|
+
}), globalThis.window.document.body);
|
|
12
11
|
}));`;
|
package/src/module.js
CHANGED
|
@@ -1,63 +1,38 @@
|
|
|
1
|
-
import crypto from "runtime-compat/crypto";
|
|
2
1
|
import {Path} from "runtime-compat/fs";
|
|
3
2
|
import {Response, Status, MediaType} from "runtime-compat/http";
|
|
3
|
+
import * as base from "@primate/frontend";
|
|
4
|
+
import {renderToString as render} from "solid-js/web";
|
|
4
5
|
import {transformAsync} from "@babel/core";
|
|
5
6
|
import solid from "babel-preset-solid";
|
|
6
|
-
import {
|
|
7
|
-
import {tryreturn} from "runtime-compat/async";
|
|
8
|
-
import errors from "./errors.js";
|
|
9
|
-
import {client, create_root, create_root2, rootname, hydrate} from "./client/exports.js";
|
|
7
|
+
import {client, create_root, rootname, hydrate} from "./client/exports.js";
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
const packager = import.meta.runtime?.packager ?? "package.json";
|
|
13
|
-
const library = import.meta.runtime?.library ?? "node_modules";
|
|
14
|
-
|
|
15
|
-
const encoder = new TextEncoder();
|
|
16
|
-
const hash = async (string, algorithm = "sha-256") => {
|
|
17
|
-
const base = 16;
|
|
18
|
-
const target_pad_length = 2;
|
|
19
|
-
const target_slice = 12;
|
|
20
|
-
const bytes = await crypto.subtle.digest(algorithm, encoder.encode(string));
|
|
21
|
-
return Array.from(new Uint8Array(bytes))
|
|
22
|
-
.map(byte => byte.toString(base).padStart(target_pad_length, "0"))
|
|
23
|
-
.join("")
|
|
24
|
-
.slice(0, target_slice);
|
|
25
|
-
};
|
|
26
|
-
const normalize = async path => `solid_${await hash(path)}`;
|
|
9
|
+
const normalize = base.normalize("solid");
|
|
27
10
|
|
|
28
11
|
const import$ = async (module, app, copy_dependency) => {
|
|
29
|
-
const {
|
|
12
|
+
const {library, packager} = app;
|
|
13
|
+
const {http: {static: {root}}} = app.config;
|
|
30
14
|
const parts = module.split("/");
|
|
31
15
|
const path = [library, ...parts];
|
|
32
16
|
const pkg = await Path.resolve().join(...path, packager).json();
|
|
33
17
|
if (copy_dependency) {
|
|
34
18
|
const dependency = Path.resolve().join(...path);
|
|
35
|
-
const to = app.
|
|
19
|
+
const to = app.runpath(app.config.location.client, library, ...parts);
|
|
36
20
|
await dependency.file.copy(`${to}`);
|
|
37
21
|
}
|
|
38
22
|
|
|
39
23
|
const entry = pkg.exports["."].browser.import;
|
|
40
|
-
app.importmaps[module] = new Path(root,
|
|
24
|
+
app.importmaps[module] = new Path(root, library, module, entry).path;
|
|
41
25
|
};
|
|
42
26
|
|
|
43
|
-
const filename = `${rootname}.js`;
|
|
44
27
|
const type = "module";
|
|
45
28
|
|
|
46
|
-
const
|
|
47
|
-
tryreturn(async () => (await import(`${path}.js`)).default)
|
|
48
|
-
.orelse(_ => errors.MissingComponent.throw(path.name, path));
|
|
49
|
-
|
|
50
|
-
const make_component = base => async (name, props) =>
|
|
51
|
-
({name, component: await load(base.join(name)), props});
|
|
52
|
-
|
|
53
|
-
const handler = (name, props = {}, {status = Status.OK} = {}) =>
|
|
29
|
+
const handler = config => (name, props = {}, {status = Status.OK, page} = {}) =>
|
|
54
30
|
async (app, {layouts = [], as_layout} = {}, request) => {
|
|
31
|
+
const {make, root} = config;
|
|
32
|
+
const {headers} = request;
|
|
55
33
|
const options = {
|
|
56
34
|
liveview: app.liveview !== undefined,
|
|
57
35
|
};
|
|
58
|
-
const {headers} = request;
|
|
59
|
-
const {paths} = app.build;
|
|
60
|
-
const make = make_component(paths.server.join(app.config.build.app));
|
|
61
36
|
if (as_layout) {
|
|
62
37
|
return make(name, props);
|
|
63
38
|
}
|
|
@@ -78,9 +53,8 @@ const handler = (name, props = {}, {status = Status.OK} = {}) =>
|
|
|
78
53
|
});
|
|
79
54
|
}
|
|
80
55
|
|
|
81
|
-
const root = paths.server.join(filename);
|
|
82
56
|
const imported = (await import(root)).default;
|
|
83
|
-
const body =
|
|
57
|
+
const body = render(() => imported({
|
|
84
58
|
components: components.map(({component}) => component),
|
|
85
59
|
data,
|
|
86
60
|
}));
|
|
@@ -91,119 +65,60 @@ const handler = (name, props = {}, {status = Status.OK} = {}) =>
|
|
|
91
65
|
// needs to be called before app.render
|
|
92
66
|
const headers$ = await app.headers();
|
|
93
67
|
|
|
94
|
-
return new Response(await app.render({body}), {
|
|
68
|
+
return new Response(await app.render({body, page}), {
|
|
95
69
|
status,
|
|
96
70
|
headers: {...headers$, "Content-Type": MediaType.TEXT_HTML},
|
|
97
71
|
});
|
|
98
72
|
};
|
|
99
73
|
|
|
100
|
-
const options = {
|
|
101
|
-
server: [solid, {
|
|
102
|
-
generate: "ssr",
|
|
103
|
-
hydratable: true,
|
|
104
|
-
}],
|
|
105
|
-
client: [solid, {
|
|
106
|
-
generate: "dom",
|
|
107
|
-
hydratable: true,
|
|
108
|
-
}],
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const endings = {
|
|
112
|
-
solid: ".solid",
|
|
113
|
-
js: ".solid.js",
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const transform = {
|
|
117
|
-
async server(file) {
|
|
118
|
-
return (await transformAsync(file, {presets: [options.server]})).code;
|
|
119
|
-
},
|
|
120
|
-
async client(file) {
|
|
121
|
-
return (await transformAsync(file, {presets: [options.client]})).code;
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
|
|
125
74
|
export default ({
|
|
126
|
-
|
|
75
|
+
directory,
|
|
76
|
+
dynamicProps,
|
|
127
77
|
extension = "jsx",
|
|
128
78
|
} = {}) => {
|
|
129
|
-
const env = {};
|
|
130
|
-
|
|
131
79
|
return {
|
|
132
|
-
name: "
|
|
133
|
-
init(app, next) {
|
|
134
|
-
env.source = app.build.paths.components;
|
|
135
|
-
|
|
136
|
-
return next(app);
|
|
137
|
-
},
|
|
80
|
+
name: "primate:solid",
|
|
138
81
|
register(app, next) {
|
|
139
|
-
app.register(
|
|
82
|
+
app.register(extension, handler(base.register({app, rootname})));
|
|
83
|
+
|
|
140
84
|
return next(app);
|
|
141
85
|
},
|
|
142
86
|
async compile(app, next) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}));
|
|
156
|
-
|
|
157
|
-
const root = await transform.server(create_root2(app.layoutDepth,
|
|
158
|
-
dynamicProps));
|
|
159
|
-
const to = app.build.paths.server.join(filename);
|
|
160
|
-
await to.file.write(root);
|
|
87
|
+
await base.compile({
|
|
88
|
+
app,
|
|
89
|
+
directory: directory ?? app.config.location.components,
|
|
90
|
+
extension,
|
|
91
|
+
rootname,
|
|
92
|
+
create_root,
|
|
93
|
+
dynamicProps,
|
|
94
|
+
async compile(file) {
|
|
95
|
+
const presets = [[solid, {generate: "ssr", hydratable: true}]];
|
|
96
|
+
return (await transformAsync(file, {presets})).code;
|
|
97
|
+
},
|
|
98
|
+
});
|
|
161
99
|
|
|
162
100
|
return next(app);
|
|
163
101
|
},
|
|
164
102
|
async publish(app, next) {
|
|
165
|
-
|
|
166
|
-
await target.file.create();
|
|
167
|
-
|
|
168
|
-
// create client components
|
|
169
|
-
const components = await env.source.collect(/^.*.solid/u);
|
|
170
|
-
await Promise.all(components.map(async component => {
|
|
171
|
-
const name = component.path.replace(`${env.source}/`, "");
|
|
172
|
-
const file = await component.file.read();
|
|
173
|
-
const code = await transform.client(file);
|
|
174
|
-
const build = app.config.build.app;
|
|
175
|
-
const {path} = component;
|
|
176
|
-
|
|
177
|
-
{
|
|
178
|
-
{
|
|
179
|
-
const src = `${path}.js`.replace(`${env.source}`, _ => build);
|
|
180
|
-
await app.publish({src,
|
|
181
|
-
code: code.replaceAll(endings.solid, endings.js),
|
|
182
|
-
type});
|
|
183
|
-
}
|
|
184
|
-
const imported = await normalize(name);
|
|
185
|
-
app.bootstrap({
|
|
186
|
-
type: "script",
|
|
187
|
-
code: `export {default as ${imported}} from "./${name}.js";\n`,
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
}));
|
|
191
|
-
|
|
103
|
+
// import libs
|
|
192
104
|
await import$("solid-js", app, true);
|
|
193
105
|
await import$("solid-js/web", app);
|
|
194
|
-
|
|
195
|
-
app.
|
|
196
|
-
|
|
197
|
-
{
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
106
|
+
// export hydration code
|
|
107
|
+
app.export({type: "script", code: hydrate});
|
|
108
|
+
|
|
109
|
+
await base.publish({
|
|
110
|
+
app,
|
|
111
|
+
directory: directory ?? app.config.location.components,
|
|
112
|
+
extension,
|
|
113
|
+
rootname,
|
|
114
|
+
create_root,
|
|
115
|
+
dynamicProps,
|
|
116
|
+
normalize,
|
|
117
|
+
async compile(file) {
|
|
118
|
+
const presets = [[solid, {generate: "dom", hydratable: true}]];
|
|
119
|
+
return {js: (await transformAsync(file, {presets})).code};
|
|
120
|
+
},
|
|
121
|
+
});
|
|
207
122
|
|
|
208
123
|
return next(app);
|
|
209
124
|
},
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export default (length, data) => {
|
|
2
|
-
const n = length - 1;
|
|
3
|
-
const body = Array.from({length: n}, (_, i) => i - 1)
|
|
4
|
-
.reduceRight((child, _, i) => `<Show
|
|
5
|
-
when={components[${i + 1}] !== undefined}
|
|
6
|
-
fallback={
|
|
7
|
-
<>
|
|
8
|
-
<Dynamic component={components[${i}]} ${data}={data[${i}]} />
|
|
9
|
-
</>
|
|
10
|
-
}
|
|
11
|
-
>
|
|
12
|
-
<Dynamic component={components[${i}]} ${data}={data[${i}]}>${child}</Dynamic>
|
|
13
|
-
</Show>
|
|
14
|
-
`, `<Dynamic component={components[${n}]} ${data}={data[${n}]} />`);
|
|
15
|
-
|
|
16
|
-
return `
|
|
17
|
-
import {Dynamic, Show} from "solid-js/web";
|
|
18
|
-
export default function Root({components, data} = {}) {
|
|
19
|
-
return ${body};
|
|
20
|
-
};
|
|
21
|
-
`;
|
|
22
|
-
};
|