elm-pages 2.1.11 → 3.0.0-beta.1
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/codegen/elm-pages-codegen.js +38507 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
- package/generator/{template/public/style.css → dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock} +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +6795 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25651 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +110 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +187 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/package.json +1 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/src/Reporter.elm +26 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/src/Runner.elm +62 -0
- package/generator/dead-code-review/elm.json +35 -0
- package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +181 -0
- package/generator/dead-code-review/src/ReviewConfig.elm +9 -0
- package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +455 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +6795 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +27617 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +110 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +187 -0
- package/generator/review/elm-stuff/tests-0.19.1/js/package.json +1 -0
- package/generator/review/elm-stuff/tests-0.19.1/src/Reporter.elm +26 -0
- package/generator/review/elm-stuff/tests-0.19.1/src/Runner.elm +62 -0
- package/generator/review/elm.json +13 -4
- package/{src → generator/review/src}/Pages/Review/NoContractViolations.elm +148 -148
- package/generator/review/tests/Pages/Review/NoContractViolationsTest.elm +331 -0
- package/generator/src/RouteBuilder.elm +420 -0
- package/generator/src/SharedTemplate.elm +4 -5
- package/generator/src/SiteConfig.elm +3 -9
- package/generator/src/build.js +308 -95
- package/generator/src/cli.js +103 -8
- package/generator/src/codegen.js +192 -35
- package/generator/src/compile-elm.js +183 -31
- package/generator/src/dev-server.js +353 -96
- package/generator/src/elm-application.json +3 -1
- package/generator/src/elm-codegen.js +34 -0
- package/generator/src/elm-file-constants.js +2 -0
- package/generator/src/error-formatter.js +20 -1
- package/generator/src/generate-template-module-connector.js +125 -927
- package/generator/src/hello.ts +5 -0
- package/generator/src/pre-render-html.js +58 -104
- package/generator/src/render-worker.js +27 -13
- package/generator/src/render.js +252 -197
- package/generator/src/request-cache-fs.js +18 -0
- package/generator/src/request-cache.js +128 -56
- package/generator/src/rewrite-client-elm-json.js +49 -0
- package/generator/src/route-codegen-helpers.js +62 -1
- package/generator/static-code/dev-style.css +22 -0
- package/generator/static-code/elm-pages.js +43 -39
- package/generator/static-code/hmr.js +98 -88
- package/generator/template/app/Api.elm +25 -0
- package/generator/template/app/ErrorPage.elm +38 -0
- package/generator/template/app/Route/Index.elm +87 -0
- package/generator/template/{src → app}/Shared.elm +34 -13
- package/generator/template/app/Site.elm +19 -0
- package/generator/template/{src → app}/View.elm +0 -0
- package/generator/template/elm-pages.config.mjs +5 -0
- package/generator/template/elm.json +1 -0
- package/generator/template/{public/index.js → index.ts} +7 -3
- package/generator/template/package.json +4 -4
- package/generator/template/public/favicon.ico +0 -0
- package/generator/template/public/images/icon-png.png +0 -0
- package/generator/template/src/.gitkeep +0 -0
- package/generator/template/style.css +4 -0
- package/package.json +33 -23
- package/src/ApiRoute.elm +176 -43
- package/src/BuildError.elm +10 -1
- package/src/CookieParser.elm +84 -0
- package/src/DataSource/Env.elm +38 -0
- package/src/DataSource/File.elm +27 -16
- package/src/DataSource/Glob.elm +126 -80
- package/src/DataSource/Http.elm +283 -304
- package/src/DataSource/Internal/Glob.elm +5 -21
- package/src/DataSource/Internal/Request.elm +25 -0
- package/src/DataSource/Port.elm +17 -14
- package/src/DataSource.elm +55 -318
- package/src/Form/Field.elm +717 -0
- package/src/Form/FieldStatus.elm +36 -0
- package/src/Form/FieldView.elm +417 -0
- package/src/Form/FormData.elm +22 -0
- package/src/Form/Validation.elm +391 -0
- package/src/Form/Value.elm +118 -0
- package/src/Form.elm +1683 -0
- package/src/FormData.elm +58 -0
- package/src/FormDecoder.elm +102 -0
- package/src/Head/Seo.elm +12 -4
- package/src/Head.elm +12 -2
- package/src/HtmlPrinter.elm +1 -1
- package/src/Internal/ApiRoute.elm +17 -4
- package/src/Internal/Request.elm +7 -0
- package/src/PageServerResponse.elm +68 -0
- package/src/Pages/ContentCache.elm +1 -229
- package/src/Pages/Fetcher.elm +58 -0
- package/src/Pages/FormState.elm +256 -0
- package/src/Pages/Generate.elm +800 -0
- package/src/Pages/Internal/Form.elm +17 -0
- package/src/Pages/Internal/NotFoundReason.elm +3 -55
- package/src/Pages/Internal/Platform/Cli.elm +777 -579
- package/src/Pages/Internal/Platform/Effect.elm +5 -5
- package/src/Pages/Internal/Platform/StaticResponses.elm +178 -394
- package/src/Pages/Internal/Platform/ToJsPayload.elm +24 -23
- package/src/Pages/Internal/Platform.elm +1244 -504
- package/src/Pages/Internal/ResponseSketch.elm +19 -0
- package/src/Pages/Internal/RoutePattern.elm +596 -45
- package/src/Pages/Manifest.elm +26 -0
- package/src/Pages/Msg.elm +79 -0
- package/src/Pages/ProgramConfig.elm +67 -14
- package/src/Pages/SiteConfig.elm +3 -6
- package/src/Pages/StaticHttp/Request.elm +4 -2
- package/src/Pages/StaticHttpRequest.elm +50 -215
- package/src/Pages/Transition.elm +70 -0
- package/src/Path.elm +1 -0
- package/src/Pattern.elm +98 -0
- package/src/RenderRequest.elm +2 -2
- package/src/RequestsAndPending.elm +111 -9
- package/src/Server/Request.elm +1253 -0
- package/src/Server/Response.elm +292 -0
- package/src/Server/Session.elm +316 -0
- package/src/Server/SetCookie.elm +169 -0
- package/src/TerminalText.elm +1 -1
- package/src/Test/Html/Internal/ElmHtml/Markdown.elm +0 -1
- package/src/Test/Html/Internal/ElmHtml/ToString.elm +1 -1
- package/generator/src/Page.elm +0 -359
- package/generator/src/codegen-template-module.js +0 -183
- package/generator/src/elm-pages-js-minified.js +0 -1
- package/generator/template/src/Api.elm +0 -14
- package/generator/template/src/Page/Index.elm +0 -69
- package/generator/template/src/Site.elm +0 -41
- package/src/DataSource/ServerRequest.elm +0 -60
- package/src/Internal/OptimizedDecoder.elm +0 -18
- package/src/KeepOrDiscard.elm +0 -6
- package/src/OptimizedDecoder/Pipeline.elm +0 -335
- package/src/OptimizedDecoder.elm +0 -818
- package/src/Pages/Internal/ApplicationType.elm +0 -6
- package/src/Pages/Secrets.elm +0 -83
- package/src/Secrets.elm +0 -111
- package/src/SecretsDict.elm +0 -45
package/generator/src/cli.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const build = require("./build.js");
|
|
4
|
+
const dirHelpers = require("./dir-helpers.js");
|
|
4
5
|
const dev = require("./dev-server.js");
|
|
5
|
-
const generate = require("./codegen-template-module.js");
|
|
6
6
|
const init = require("./init.js");
|
|
7
7
|
const codegen = require("./codegen.js");
|
|
8
8
|
const fs = require("fs");
|
|
9
9
|
const path = require("path");
|
|
10
|
+
const { restoreColorSafe } = require("./error-formatter");
|
|
10
11
|
|
|
11
12
|
const commander = require("commander");
|
|
13
|
+
const { compileCliApp } = require("./compile-elm.js");
|
|
14
|
+
const { runElmCodegenInstall } = require("./elm-codegen.js");
|
|
15
|
+
const Argument = commander.Argument;
|
|
16
|
+
const Option = commander.Option;
|
|
12
17
|
|
|
13
18
|
const packageVersion = require("../../package.json").version;
|
|
14
19
|
|
|
@@ -38,10 +43,25 @@ async function main() {
|
|
|
38
43
|
await build.run(options);
|
|
39
44
|
});
|
|
40
45
|
|
|
46
|
+
program
|
|
47
|
+
.command("gen")
|
|
48
|
+
.option(
|
|
49
|
+
"--base <basePath>",
|
|
50
|
+
"build site to be served under a base path",
|
|
51
|
+
"/"
|
|
52
|
+
)
|
|
53
|
+
.description(
|
|
54
|
+
"generate code, useful for CI where you don't want to run a full build"
|
|
55
|
+
)
|
|
56
|
+
.action(async (options) => {
|
|
57
|
+
await codegen.generate(options.base);
|
|
58
|
+
});
|
|
59
|
+
|
|
41
60
|
program
|
|
42
61
|
.command("dev")
|
|
43
62
|
.description("start a dev server")
|
|
44
63
|
.option("--port <number>", "serve site at localhost:<port>", "1234")
|
|
64
|
+
.option("--debug", "Run elm make with --debug")
|
|
45
65
|
.option(
|
|
46
66
|
"--keep-cache",
|
|
47
67
|
"Preserve the HTTP and JS Port cache instead of deleting it on server start"
|
|
@@ -56,13 +76,6 @@ async function main() {
|
|
|
56
76
|
await dev.start(options);
|
|
57
77
|
});
|
|
58
78
|
|
|
59
|
-
program
|
|
60
|
-
.command("add <moduleName>")
|
|
61
|
-
.description("create a new Page module")
|
|
62
|
-
.action(async (moduleName) => {
|
|
63
|
-
await generate.run({ moduleName });
|
|
64
|
-
});
|
|
65
|
-
|
|
66
79
|
program
|
|
67
80
|
.command("init <projectName>")
|
|
68
81
|
.description("scaffold a new elm-pages project boilerplate")
|
|
@@ -70,6 +83,69 @@ async function main() {
|
|
|
70
83
|
await init.run(projectName);
|
|
71
84
|
});
|
|
72
85
|
|
|
86
|
+
program
|
|
87
|
+
.command("codegen <moduleName>")
|
|
88
|
+
.description("run a generator")
|
|
89
|
+
.allowUnknownOption()
|
|
90
|
+
.allowExcessArguments()
|
|
91
|
+
.action(async (moduleName, options, options2) => {
|
|
92
|
+
if (!/^[A-Z][a-zA-Z0-9_]*(\.[A-Z][a-zA-Z0-9_]*)*$/.test(moduleName)) {
|
|
93
|
+
throw `Invalid module name "${moduleName}", must be in the format of an Elm module`;
|
|
94
|
+
}
|
|
95
|
+
const splitModuleName = moduleName.split(".");
|
|
96
|
+
const expectedFilePath = path.join(
|
|
97
|
+
process.cwd(),
|
|
98
|
+
"codegen",
|
|
99
|
+
`${splitModuleName.join("/")}.elm`
|
|
100
|
+
);
|
|
101
|
+
if (!fs.existsSync(expectedFilePath)) {
|
|
102
|
+
throw `I couldn't find a module named ${expectedFilePath}`;
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
await codegen.generate("");
|
|
106
|
+
await runElmCodegenInstall();
|
|
107
|
+
await compileCliApp(
|
|
108
|
+
// { debug: true },
|
|
109
|
+
{},
|
|
110
|
+
`${splitModuleName.join("/")}.elm`,
|
|
111
|
+
path.join(process.cwd(), "codegen/elm-stuff/scaffold.js"),
|
|
112
|
+
"codegen",
|
|
113
|
+
|
|
114
|
+
path.join(process.cwd(), "codegen/elm-stuff/scaffold.js")
|
|
115
|
+
);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.log(restoreColorSafe(error));
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const elmScaffoldProgram = getAt(
|
|
122
|
+
splitModuleName,
|
|
123
|
+
require(path.join(process.cwd(), "./codegen/elm-stuff/scaffold.js")).Elm
|
|
124
|
+
);
|
|
125
|
+
const program = elmScaffoldProgram.init({
|
|
126
|
+
flags: { argv: ["", ...options2.args], versionMessage: "1.2.3" },
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
safeSubscribe(program, "print", (message) => {
|
|
130
|
+
console.log(message);
|
|
131
|
+
});
|
|
132
|
+
safeSubscribe(program, "printAndExitFailure", (message) => {
|
|
133
|
+
console.log(message);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
});
|
|
136
|
+
safeSubscribe(program, "printAndExitSuccess", (message) => {
|
|
137
|
+
console.log(message);
|
|
138
|
+
process.exit(0);
|
|
139
|
+
});
|
|
140
|
+
safeSubscribe(program, "writeFile", async (info) => {
|
|
141
|
+
const filePath = path.join(process.cwd(), "app", info.path);
|
|
142
|
+
await dirHelpers.tryMkdir(path.dirname(filePath));
|
|
143
|
+
fs.writeFileSync(filePath, info.body);
|
|
144
|
+
console.log("Success! Created file", filePath);
|
|
145
|
+
process.exit(0);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
73
149
|
program
|
|
74
150
|
.command("docs")
|
|
75
151
|
.description("open the docs for locally generated modules")
|
|
@@ -89,6 +165,25 @@ async function main() {
|
|
|
89
165
|
program.parse(process.argv);
|
|
90
166
|
}
|
|
91
167
|
|
|
168
|
+
/**
|
|
169
|
+
* @param {string[]} properties
|
|
170
|
+
* @param {Object} object
|
|
171
|
+
* @returns unknown
|
|
172
|
+
*/
|
|
173
|
+
function getAt(properties, object) {
|
|
174
|
+
if (properties.length === 0) {
|
|
175
|
+
return object;
|
|
176
|
+
} else {
|
|
177
|
+
const [next, ...rest] = properties;
|
|
178
|
+
return getAt(rest, object[next]);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function safeSubscribe(program, portName, subscribeFunction) {
|
|
183
|
+
program.ports[portName] &&
|
|
184
|
+
program.ports[portName].subscribe(subscribeFunction);
|
|
185
|
+
}
|
|
186
|
+
|
|
92
187
|
function clearHttpAndPortCache() {
|
|
93
188
|
const directory = ".elm-pages/http-response-cache";
|
|
94
189
|
if (fs.existsSync(directory)) {
|
package/generator/src/codegen.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
const fs = require("fs");
|
|
2
|
+
const fsExtra = require("fs-extra");
|
|
2
3
|
const copyModifiedElmJson = require("./rewrite-elm-json.js");
|
|
4
|
+
const copyModifiedElmJsonClient = require("./rewrite-client-elm-json.js");
|
|
3
5
|
const { elmPagesCliFile, elmPagesUiFile } = require("./elm-file-constants.js");
|
|
6
|
+
const spawnCallback = require("cross-spawn").spawn;
|
|
7
|
+
const which = require("which");
|
|
4
8
|
const {
|
|
5
9
|
generateTemplateModuleConnector,
|
|
6
10
|
} = require("./generate-template-module-connector.js");
|
|
@@ -12,65 +16,218 @@ global.builtAt = new Date();
|
|
|
12
16
|
* @param {string} basePath
|
|
13
17
|
*/
|
|
14
18
|
async function generate(basePath) {
|
|
15
|
-
const cliCode = generateTemplateModuleConnector(basePath, "cli");
|
|
16
|
-
const browserCode = generateTemplateModuleConnector(
|
|
19
|
+
const cliCode = await generateTemplateModuleConnector(basePath, "cli");
|
|
20
|
+
const browserCode = await generateTemplateModuleConnector(
|
|
21
|
+
basePath,
|
|
22
|
+
"browser"
|
|
23
|
+
);
|
|
17
24
|
ensureDirSync("./elm-stuff");
|
|
18
25
|
ensureDirSync("./.elm-pages");
|
|
26
|
+
ensureDirSync("./gen");
|
|
19
27
|
ensureDirSync("./elm-stuff/elm-pages/.elm-pages");
|
|
20
28
|
|
|
21
29
|
const uiFileContent = elmPagesUiFile();
|
|
30
|
+
|
|
22
31
|
await Promise.all([
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
32
|
+
copyToBoth("RouteBuilder.elm"),
|
|
33
|
+
copyToBoth("SharedTemplate.elm"),
|
|
34
|
+
copyToBoth("SiteConfig.elm"),
|
|
35
|
+
|
|
36
|
+
fs.promises.writeFile("./.elm-pages/Pages.elm", uiFileContent),
|
|
27
37
|
fs.promises.copyFile(
|
|
28
38
|
path.join(__dirname, `./elm-application.json`),
|
|
29
39
|
`./elm-stuff/elm-pages/elm-application.json`
|
|
30
40
|
),
|
|
31
|
-
fs.promises.copyFile(
|
|
32
|
-
path.join(__dirname, `./Page.elm`),
|
|
33
|
-
`./elm-stuff/elm-pages/.elm-pages/Page.elm`
|
|
34
|
-
),
|
|
35
|
-
fs.promises.copyFile(
|
|
36
|
-
path.join(__dirname, `./SharedTemplate.elm`),
|
|
37
|
-
`./.elm-pages/SharedTemplate.elm`
|
|
38
|
-
),
|
|
39
|
-
fs.promises.copyFile(
|
|
40
|
-
path.join(__dirname, `./SharedTemplate.elm`),
|
|
41
|
-
`./elm-stuff/elm-pages/.elm-pages/SharedTemplate.elm`
|
|
42
|
-
),
|
|
43
|
-
fs.promises.copyFile(
|
|
44
|
-
path.join(__dirname, `./SiteConfig.elm`),
|
|
45
|
-
`./.elm-pages/SiteConfig.elm`
|
|
46
|
-
),
|
|
47
|
-
fs.promises.copyFile(
|
|
48
|
-
path.join(__dirname, `./SiteConfig.elm`),
|
|
49
|
-
`./elm-stuff/elm-pages/.elm-pages/SiteConfig.elm`
|
|
50
|
-
),
|
|
51
|
-
fs.promises.writeFile("./.elm-pages/Pages.elm", uiFileContent),
|
|
52
41
|
// write `Pages.elm` with cli interface
|
|
53
42
|
fs.promises.writeFile(
|
|
54
43
|
"./elm-stuff/elm-pages/.elm-pages/Pages.elm",
|
|
55
44
|
elmPagesCliFile()
|
|
56
45
|
),
|
|
57
46
|
fs.promises.writeFile(
|
|
58
|
-
"./elm-stuff/elm-pages/.elm-pages/
|
|
47
|
+
"./elm-stuff/elm-pages/.elm-pages/Main.elm",
|
|
59
48
|
cliCode.mainModule
|
|
60
49
|
),
|
|
61
50
|
fs.promises.writeFile(
|
|
62
51
|
"./elm-stuff/elm-pages/.elm-pages/Route.elm",
|
|
63
52
|
cliCode.routesModule
|
|
64
53
|
),
|
|
65
|
-
fs.promises.writeFile(
|
|
66
|
-
"./.elm-pages/TemplateModulesBeta.elm",
|
|
67
|
-
browserCode.mainModule
|
|
68
|
-
),
|
|
54
|
+
fs.promises.writeFile("./.elm-pages/Main.elm", browserCode.mainModule),
|
|
69
55
|
fs.promises.writeFile("./.elm-pages/Route.elm", browserCode.routesModule),
|
|
56
|
+
writeFetcherModules("./.elm-pages", browserCode.fetcherModules),
|
|
57
|
+
writeFetcherModules(
|
|
58
|
+
"./elm-stuff/elm-pages/client/.elm-pages",
|
|
59
|
+
browserCode.fetcherModules
|
|
60
|
+
),
|
|
61
|
+
writeFetcherModules(
|
|
62
|
+
"./elm-stuff/elm-pages/.elm-pages",
|
|
63
|
+
browserCode.fetcherModules
|
|
64
|
+
),
|
|
65
|
+
// write modified elm.json to elm-stuff/elm-pages/
|
|
66
|
+
copyModifiedElmJson(),
|
|
67
|
+
// ...(await listFiles("./Pages/Internal")).map(copyToBoth),
|
|
70
68
|
]);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function writeFetcherModules(basePath, fetcherData) {
|
|
72
|
+
Promise.all(
|
|
73
|
+
fetcherData.map(([name, fileContent]) => {
|
|
74
|
+
let filePath = path.join(basePath, `/Fetcher/${name.join("/")}.elm`);
|
|
75
|
+
ensureDirSync(path.dirname(filePath));
|
|
76
|
+
return fs.promises.writeFile(filePath, fileContent);
|
|
77
|
+
})
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function newCopyBoth(modulePath) {
|
|
82
|
+
await fs.promises.copyFile(
|
|
83
|
+
path.join(__dirname, modulePath),
|
|
84
|
+
path.join(`./elm-stuff/elm-pages/client/.elm-pages/`, modulePath)
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function generateClientFolder(basePath) {
|
|
89
|
+
const browserCode = await generateTemplateModuleConnector(
|
|
90
|
+
basePath,
|
|
91
|
+
"browser"
|
|
92
|
+
);
|
|
93
|
+
const uiFileContent = elmPagesUiFile();
|
|
94
|
+
ensureDirSync("./elm-stuff/elm-pages/client/app");
|
|
95
|
+
ensureDirSync("./elm-stuff/elm-pages/client/.elm-pages");
|
|
96
|
+
await newCopyBoth("RouteBuilder.elm");
|
|
97
|
+
await newCopyBoth("SharedTemplate.elm");
|
|
98
|
+
await newCopyBoth("SiteConfig.elm");
|
|
71
99
|
|
|
72
|
-
|
|
73
|
-
|
|
100
|
+
await copyModifiedElmJsonClient();
|
|
101
|
+
await fsExtra.copy("./app", "./elm-stuff/elm-pages/client/app", {
|
|
102
|
+
recursive: true,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
await fs.promises.writeFile(
|
|
106
|
+
"./elm-stuff/elm-pages/client/.elm-pages/Main.elm",
|
|
107
|
+
browserCode.mainModule
|
|
108
|
+
);
|
|
109
|
+
await fs.promises.writeFile(
|
|
110
|
+
"./elm-stuff/elm-pages/client/.elm-pages/Route.elm",
|
|
111
|
+
browserCode.routesModule
|
|
112
|
+
);
|
|
113
|
+
await fs.promises.writeFile(
|
|
114
|
+
"./elm-stuff/elm-pages/client/.elm-pages/Pages.elm",
|
|
115
|
+
uiFileContent
|
|
116
|
+
);
|
|
117
|
+
await runElmReviewCodemod("./elm-stuff/elm-pages/client/");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @param {string} [ cwd ]
|
|
122
|
+
*/
|
|
123
|
+
async function runElmReviewCodemod(cwd) {
|
|
124
|
+
return new Promise(async (resolve, reject) => {
|
|
125
|
+
const child = spawnCallback(
|
|
126
|
+
`elm-review`,
|
|
127
|
+
[
|
|
128
|
+
"--fix-all-without-prompt",
|
|
129
|
+
"--report",
|
|
130
|
+
"json",
|
|
131
|
+
"--namespace",
|
|
132
|
+
"elm-pages",
|
|
133
|
+
"--config",
|
|
134
|
+
path.join(__dirname, "../../generator/dead-code-review"),
|
|
135
|
+
"--elmjson",
|
|
136
|
+
"elm.json",
|
|
137
|
+
"--compiler",
|
|
138
|
+
await which("lamdera"),
|
|
139
|
+
],
|
|
140
|
+
{ cwd: path.join(process.cwd(), cwd || ".") }
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
let scriptOutput = "";
|
|
144
|
+
|
|
145
|
+
child.stdout.setEncoding("utf8");
|
|
146
|
+
child.stdout.on("data", function (/** @type {string} */ data) {
|
|
147
|
+
scriptOutput += data.toString();
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
child.stderr.setEncoding("utf8");
|
|
151
|
+
child.stderr.on("data", function (/** @type {string} */ data) {
|
|
152
|
+
scriptOutput += data.toString();
|
|
153
|
+
});
|
|
154
|
+
child.on("error", function () {
|
|
155
|
+
reject(scriptOutput);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
child.on("close", function (code) {
|
|
159
|
+
if (code === 0) {
|
|
160
|
+
resolve(scriptOutput);
|
|
161
|
+
} else {
|
|
162
|
+
reject(scriptOutput);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @param {string} moduleToCopy
|
|
170
|
+
* @returns { Promise<void> }
|
|
171
|
+
*/
|
|
172
|
+
async function copyToBoth(moduleToCopy) {
|
|
173
|
+
await Promise.all([
|
|
174
|
+
copyFileEnsureDir(
|
|
175
|
+
path.join(__dirname, moduleToCopy),
|
|
176
|
+
path.join(`./.elm-pages/`, moduleToCopy)
|
|
177
|
+
),
|
|
178
|
+
copyFileEnsureDir(
|
|
179
|
+
path.join(__dirname, moduleToCopy),
|
|
180
|
+
path.join(`./elm-stuff/elm-pages/client/.elm-pages`, moduleToCopy)
|
|
181
|
+
),
|
|
182
|
+
copyFileEnsureDir(
|
|
183
|
+
path.join(__dirname, moduleToCopy),
|
|
184
|
+
path.join(`./elm-stuff/elm-pages/.elm-pages/`, moduleToCopy)
|
|
185
|
+
)]);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @param {string} from
|
|
190
|
+
* @param {string} to
|
|
191
|
+
*/
|
|
192
|
+
async function copyFileEnsureDir(from, to) {
|
|
193
|
+
await fs.promises.mkdir(path.dirname(to), {
|
|
194
|
+
recursive: true,
|
|
195
|
+
})
|
|
196
|
+
await fs.promises.copyFile(from, to)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @param {string} dir
|
|
201
|
+
* @returns {Promise<string[]>}
|
|
202
|
+
*/
|
|
203
|
+
async function listFiles(dir) {
|
|
204
|
+
try {
|
|
205
|
+
const fullDir = path.join(__dirname, dir);
|
|
206
|
+
const files = await fs.promises.readdir(fullDir);
|
|
207
|
+
return merge(
|
|
208
|
+
await Promise.all(
|
|
209
|
+
files.flatMap(async (file_) => {
|
|
210
|
+
const file = path.join(dir, path.basename(file_));
|
|
211
|
+
if (
|
|
212
|
+
(await fs.promises.stat(path.join(__dirname, file))).isDirectory()
|
|
213
|
+
) {
|
|
214
|
+
return await listFiles(file);
|
|
215
|
+
} else {
|
|
216
|
+
return [file];
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
)
|
|
220
|
+
);
|
|
221
|
+
} catch (e) {
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* @param {any[]} arrays
|
|
228
|
+
*/
|
|
229
|
+
function merge(arrays) {
|
|
230
|
+
return [].concat.apply([], arrays);
|
|
74
231
|
}
|
|
75
232
|
|
|
76
|
-
module.exports = { generate };
|
|
233
|
+
module.exports = { generate, generateClientFolder };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const spawnCallback = require("cross-spawn").spawn;
|
|
2
2
|
const fs = require("fs");
|
|
3
|
+
const fsHelpers = require("./dir-helpers.js");
|
|
4
|
+
const fsPromises = require("fs").promises;
|
|
3
5
|
const path = require("path");
|
|
4
6
|
const kleur = require("kleur");
|
|
5
|
-
const debug = true;
|
|
6
7
|
const { inject } = require("elm-hot");
|
|
7
8
|
const pathToClientElm = path.join(
|
|
8
9
|
process.cwd(),
|
|
@@ -10,55 +11,172 @@ const pathToClientElm = path.join(
|
|
|
10
11
|
"browser-elm.js"
|
|
11
12
|
);
|
|
12
13
|
|
|
13
|
-
async function
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
async function compileElmForBrowser(options) {
|
|
15
|
+
await runElm(options, "./.elm-pages/Main.elm", pathToClientElm);
|
|
16
|
+
return fs.promises.writeFile(
|
|
17
|
+
"./.elm-pages/cache/elm.js",
|
|
18
|
+
inject(await fs.promises.readFile(pathToClientElm, "utf-8")).replace(
|
|
19
|
+
/return \$elm\$json\$Json\$Encode\$string\(.REPLACE_ME_WITH_FORM_TO_STRING.\)/g,
|
|
20
|
+
"let appendSubmitter = (myFormData, event) => { event.submitter && event.submitter.name && event.submitter.name.length > 0 ? myFormData.append(event.submitter.name, event.submitter.value) : myFormData; return myFormData }; return " +
|
|
21
|
+
(true
|
|
22
|
+
? // TODO remove hardcoding
|
|
23
|
+
"_Json_wrap([...(appendSubmitter(new FormData(_Json_unwrap(event).target), _Json_unwrap(event)))])"
|
|
24
|
+
: "[...(new FormData(event.target))")
|
|
25
|
+
)
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function compileCliApp(
|
|
30
|
+
options,
|
|
31
|
+
elmEntrypointPath,
|
|
32
|
+
outputPath,
|
|
33
|
+
cwd,
|
|
34
|
+
readFrom
|
|
35
|
+
) {
|
|
36
|
+
await compileElm(options, elmEntrypointPath, outputPath, cwd);
|
|
37
|
+
|
|
38
|
+
const elmFileContent = await fsPromises.readFile(readFrom, "utf-8");
|
|
39
|
+
// Source: https://github.com/elm-explorations/test/blob/d5eb84809de0f8bbf50303efd26889092c800609/src/Elm/Kernel/HtmlAsJson.js
|
|
40
|
+
const forceThunksSource = ` _HtmlAsJson_toJson(x)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
var virtualDomKernelConstants =
|
|
44
|
+
{
|
|
45
|
+
nodeTypeTagger: 4,
|
|
46
|
+
nodeTypeThunk: 5,
|
|
47
|
+
kids: "e",
|
|
48
|
+
refs: "l",
|
|
49
|
+
thunk: "m",
|
|
50
|
+
node: "k",
|
|
51
|
+
value: "a"
|
|
52
|
+
}
|
|
16
53
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
(
|
|
54
|
+
function forceThunks(vNode) {
|
|
55
|
+
if (typeof vNode !== "undefined" && vNode.$ === "#2") {
|
|
56
|
+
// This is a tuple (the kids : List (String, Html) field of a Keyed node); recurse into the right side of the tuple
|
|
57
|
+
vNode.b = forceThunks(vNode.b);
|
|
58
|
+
}
|
|
59
|
+
if (typeof vNode !== 'undefined' && vNode.$ === virtualDomKernelConstants.nodeTypeThunk && !vNode[virtualDomKernelConstants.node]) {
|
|
60
|
+
// This is a lazy node; evaluate it
|
|
61
|
+
var args = vNode[virtualDomKernelConstants.thunk];
|
|
62
|
+
vNode[virtualDomKernelConstants.node] = vNode[virtualDomKernelConstants.thunk].apply(args);
|
|
63
|
+
// And then recurse into the evaluated node
|
|
64
|
+
vNode[virtualDomKernelConstants.node] = forceThunks(vNode[virtualDomKernelConstants.node]);
|
|
65
|
+
}
|
|
66
|
+
if (typeof vNode !== 'undefined' && vNode.$ === virtualDomKernelConstants.nodeTypeTagger) {
|
|
67
|
+
// This is an Html.map; recurse into the node it is wrapping
|
|
68
|
+
vNode[virtualDomKernelConstants.node] = forceThunks(vNode[virtualDomKernelConstants.node]);
|
|
69
|
+
}
|
|
70
|
+
if (typeof vNode !== 'undefined' && typeof vNode[virtualDomKernelConstants.kids] !== 'undefined') {
|
|
71
|
+
// This is something with children (either a node with kids : List Html, or keyed with kids : List (String, Html));
|
|
72
|
+
// recurse into the children
|
|
73
|
+
vNode[virtualDomKernelConstants.kids] = vNode[virtualDomKernelConstants.kids].map(forceThunks);
|
|
74
|
+
}
|
|
75
|
+
return vNode;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function _HtmlAsJson_toJson(html) {
|
|
79
|
+
`;
|
|
80
|
+
|
|
81
|
+
await fsPromises.writeFile(
|
|
82
|
+
readFrom,
|
|
83
|
+
elmFileContent
|
|
20
84
|
.replace(
|
|
21
85
|
/return \$elm\$json\$Json\$Encode\$string\(.REPLACE_ME_WITH_JSON_STRINGIFY.\)/g,
|
|
22
|
-
"return " +
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return ports ? { ports: ports, die: die } : { die: die };`
|
|
86
|
+
"return " +
|
|
87
|
+
// TODO should the logic for this be `if options.optimize`? Or does the first case not make sense at all?
|
|
88
|
+
(true
|
|
89
|
+
? `${forceThunksSource}
|
|
90
|
+
return _Json_wrap(forceThunks(html));
|
|
91
|
+
`
|
|
92
|
+
: `${forceThunksSource}
|
|
93
|
+
return forceThunks(html);
|
|
94
|
+
`)
|
|
34
95
|
)
|
|
96
|
+
.replace(/console\.log..App dying../, "")
|
|
35
97
|
);
|
|
36
98
|
}
|
|
37
99
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
100
|
+
/**
|
|
101
|
+
* @param {string} elmEntrypointPath
|
|
102
|
+
* @param {string} outputPath
|
|
103
|
+
* @param {string | undefined} cwd
|
|
104
|
+
*/
|
|
105
|
+
async function compileElm(options, elmEntrypointPath, outputPath, cwd) {
|
|
106
|
+
await spawnElmMake(options, elmEntrypointPath, outputPath, cwd);
|
|
107
|
+
if (!options.debug) {
|
|
108
|
+
// TODO maybe pass in a boolean argument for whether it's build or dev server, and only do eol2 for build
|
|
109
|
+
// await elmOptimizeLevel2(outputPath, cwd);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function spawnElmMake(options, elmEntrypointPath, outputPath, cwd) {
|
|
114
|
+
return new Promise(async (resolve, reject) => {
|
|
115
|
+
const subprocess = spawnCallback(
|
|
116
|
+
`lamdera`,
|
|
117
|
+
[
|
|
118
|
+
"make",
|
|
119
|
+
elmEntrypointPath,
|
|
120
|
+
"--output",
|
|
121
|
+
outputPath,
|
|
122
|
+
// TODO use --optimize for prod build
|
|
123
|
+
...(options.debug ? ["--debug"] : []),
|
|
124
|
+
"--report",
|
|
125
|
+
"json",
|
|
126
|
+
],
|
|
127
|
+
{
|
|
128
|
+
// ignore stdout
|
|
129
|
+
// stdio: ["inherit", "ignore", "inherit"],
|
|
130
|
+
|
|
131
|
+
cwd: cwd,
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
if (await fsHelpers.fileExists(outputPath)) {
|
|
135
|
+
await fsPromises.unlink(outputPath, {
|
|
136
|
+
force: true /* ignore errors if file doesn't exist */,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
let commandOutput = "";
|
|
140
|
+
|
|
141
|
+
subprocess.stderr.on("data", function (data) {
|
|
142
|
+
commandOutput += data;
|
|
143
|
+
});
|
|
144
|
+
subprocess.on("error", function () {
|
|
145
|
+
reject(commandOutput);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
subprocess.on("close", async (code) => {
|
|
149
|
+
if (
|
|
150
|
+
code == 0 &&
|
|
151
|
+
(await fsHelpers.fileExists(outputPath)) &&
|
|
152
|
+
commandOutput === ""
|
|
153
|
+
) {
|
|
154
|
+
resolve();
|
|
155
|
+
} else {
|
|
156
|
+
reject(commandOutput);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
});
|
|
44
160
|
}
|
|
45
161
|
|
|
46
162
|
/**
|
|
47
163
|
* @param {string} elmEntrypointPath
|
|
48
164
|
* @param {string} outputPath
|
|
49
|
-
* @param {string} [
|
|
165
|
+
* @param {string} [cwd]
|
|
166
|
+
* @param {{ debug: boolean; }} options
|
|
50
167
|
*/
|
|
51
|
-
async function runElm(elmEntrypointPath, outputPath, cwd) {
|
|
168
|
+
async function runElm(options, elmEntrypointPath, outputPath, cwd) {
|
|
52
169
|
const startTime = Date.now();
|
|
53
170
|
return new Promise((resolve, reject) => {
|
|
54
171
|
const child = spawnCallback(
|
|
55
|
-
`
|
|
172
|
+
`lamdera`,
|
|
56
173
|
[
|
|
57
174
|
"make",
|
|
58
175
|
elmEntrypointPath,
|
|
59
176
|
"--output",
|
|
60
177
|
outputPath,
|
|
61
|
-
"--debug",
|
|
178
|
+
...(options.debug ? ["--debug"] : []),
|
|
179
|
+
...(options.optimize ? ["--optimize"] : []),
|
|
62
180
|
"--report",
|
|
63
181
|
"json",
|
|
64
182
|
],
|
|
@@ -124,7 +242,7 @@ async function runElmReview(cwd) {
|
|
|
124
242
|
child.on("close", function (code) {
|
|
125
243
|
console.log(`Ran elm-review in ${timeFrom(startTime)}`);
|
|
126
244
|
if (code === 0) {
|
|
127
|
-
|
|
245
|
+
resolve(scriptOutput);
|
|
128
246
|
} else {
|
|
129
247
|
resolve(scriptOutput);
|
|
130
248
|
}
|
|
@@ -132,10 +250,44 @@ async function runElmReview(cwd) {
|
|
|
132
250
|
});
|
|
133
251
|
}
|
|
134
252
|
|
|
253
|
+
function elmOptimizeLevel2(outputPath, cwd) {
|
|
254
|
+
return new Promise((resolve, reject) => {
|
|
255
|
+
const optimizedOutputPath = outputPath + ".opt";
|
|
256
|
+
const subprocess = spawnCallback(
|
|
257
|
+
`elm-optimize-level-2`,
|
|
258
|
+
[outputPath, "--output", optimizedOutputPath],
|
|
259
|
+
{
|
|
260
|
+
// ignore stdout
|
|
261
|
+
// stdio: ["inherit", "ignore", "inherit"],
|
|
262
|
+
|
|
263
|
+
cwd: cwd,
|
|
264
|
+
}
|
|
265
|
+
);
|
|
266
|
+
let commandOutput = "";
|
|
267
|
+
|
|
268
|
+
subprocess.stderr.on("data", function (data) {
|
|
269
|
+
commandOutput += data;
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
subprocess.on("close", async (code) => {
|
|
273
|
+
if (
|
|
274
|
+
code === 0 &&
|
|
275
|
+
commandOutput === "" &&
|
|
276
|
+
(await fsHelpers.fileExists(optimizedOutputPath))
|
|
277
|
+
) {
|
|
278
|
+
await fs.promises.copyFile(optimizedOutputPath, outputPath);
|
|
279
|
+
resolve();
|
|
280
|
+
} else {
|
|
281
|
+
reject(commandOutput);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
135
287
|
module.exports = {
|
|
136
|
-
spawnElmMake,
|
|
137
288
|
compileElmForBrowser,
|
|
138
289
|
runElmReview,
|
|
290
|
+
compileCliApp,
|
|
139
291
|
};
|
|
140
292
|
|
|
141
293
|
/**
|