@schalkneethling/miyagi-core 4.0.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.
Files changed (138) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +43 -0
  3. package/api/app.js +39 -0
  4. package/api/index.js +236 -0
  5. package/bin/miyagi.js +2 -0
  6. package/dist/css/iframe.css +31 -0
  7. package/dist/css/main.css +1 -0
  8. package/dist/js/_iframe-links-DdifIr4P.js +1 -0
  9. package/dist/js/_mock-data-Dypo4Bl_.js +1 -0
  10. package/dist/js/_prism-By3NMwUd.js +1 -0
  11. package/dist/js/iframe.build.js +1 -0
  12. package/dist/js/iframe.js +1 -0
  13. package/dist/js/index-BKDKaBC6.js +1 -0
  14. package/dist/js/jsontree.js +1 -0
  15. package/dist/js/main.build.js +1 -0
  16. package/dist/js/main.js +1 -0
  17. package/frontend/assets/css/iframe/accordion-tabs.css +77 -0
  18. package/frontend/assets/css/iframe/jsontree.js.css +325 -0
  19. package/frontend/assets/css/iframe/prism.css +132 -0
  20. package/frontend/assets/css/iframe/styleguide/colors.css +61 -0
  21. package/frontend/assets/css/iframe/styleguide/fonts.css +37 -0
  22. package/frontend/assets/css/iframe/styleguide/index.css +109 -0
  23. package/frontend/assets/css/iframe/styleguide/spacings.css +21 -0
  24. package/frontend/assets/css/iframe.css +410 -0
  25. package/frontend/assets/css/main/menu/config-switcher.css +49 -0
  26. package/frontend/assets/css/main/menu/config-switchers.css +67 -0
  27. package/frontend/assets/css/main/menu/goto.css +24 -0
  28. package/frontend/assets/css/main/menu/nav.css +113 -0
  29. package/frontend/assets/css/main/menu/search.css +64 -0
  30. package/frontend/assets/css/main/menu/title.css +40 -0
  31. package/frontend/assets/css/main/menu.css +114 -0
  32. package/frontend/assets/css/main/reset.css +217 -0
  33. package/frontend/assets/css/main.css +71 -0
  34. package/frontend/assets/css/shared.css +34 -0
  35. package/frontend/assets/css/tokens.css +112 -0
  36. package/frontend/assets/favicon.ico +0 -0
  37. package/frontend/assets/js/_accordion-tabs.js +403 -0
  38. package/frontend/assets/js/_goto.js +63 -0
  39. package/frontend/assets/js/_iframe-links.js +19 -0
  40. package/frontend/assets/js/_is-triggered.js +15 -0
  41. package/frontend/assets/js/_main.js +379 -0
  42. package/frontend/assets/js/_mock-data.js +13 -0
  43. package/frontend/assets/js/_prism.js +1098 -0
  44. package/frontend/assets/js/_search.js +190 -0
  45. package/frontend/assets/js/_socket.js +9 -0
  46. package/frontend/assets/js/config-switcher/development-mode.js +49 -0
  47. package/frontend/assets/js/config-switcher/index.js +63 -0
  48. package/frontend/assets/js/config-switcher/text-direction.js +30 -0
  49. package/frontend/assets/js/config-switcher/theme.js +87 -0
  50. package/frontend/assets/js/iframe.build.js +43 -0
  51. package/frontend/assets/js/iframe.js +52 -0
  52. package/frontend/assets/js/jsontree.js +979 -0
  53. package/frontend/assets/js/main.build.js +40 -0
  54. package/frontend/assets/js/main.js +42 -0
  55. package/frontend/assets/js/styleguide/color-converter.js +741 -0
  56. package/frontend/assets/js/styleguide/index.js +119 -0
  57. package/frontend/views/component_variation.twig.miyagi +57 -0
  58. package/frontend/views/design-tokens/colors.twig.miyagi +43 -0
  59. package/frontend/views/design-tokens/sizes.twig.miyagi +35 -0
  60. package/frontend/views/design-tokens/typography.twig.miyagi +38 -0
  61. package/frontend/views/iframe_component.twig.miyagi +141 -0
  62. package/frontend/views/iframe_component_variation.twig.miyagi +55 -0
  63. package/frontend/views/iframe_index.twig.miyagi +14 -0
  64. package/frontend/views/layouts/iframe_default.twig.miyagi +22 -0
  65. package/frontend/views/main.twig.miyagi +24 -0
  66. package/frontend/views/menu/config-switchers.twig.miyagi +83 -0
  67. package/frontend/views/menu/goto.twig.miyagi +9 -0
  68. package/frontend/views/menu/menu.twig.miyagi +21 -0
  69. package/frontend/views/menu/nav.twig.miyagi +95 -0
  70. package/frontend/views/menu/search.twig.miyagi +13 -0
  71. package/frontend/views/menu/title.twig.miyagi +24 -0
  72. package/index.js +3 -0
  73. package/lib/build/index.js +1020 -0
  74. package/lib/cli/app.js +38 -0
  75. package/lib/cli/component.js +56 -0
  76. package/lib/cli/index.js +5 -0
  77. package/lib/cli/lint.js +180 -0
  78. package/lib/config.js +74 -0
  79. package/lib/default-config.js +105 -0
  80. package/lib/generator/component.js +199 -0
  81. package/lib/generator/mocks.js +201 -0
  82. package/lib/helpers.js +184 -0
  83. package/lib/i18n/en.js +91 -0
  84. package/lib/i18n/index.js +17 -0
  85. package/lib/index.js +166 -0
  86. package/lib/init/args.js +55 -0
  87. package/lib/init/config.js +330 -0
  88. package/lib/init/engines.js +65 -0
  89. package/lib/init/index.js +102 -0
  90. package/lib/init/rendering.js +12 -0
  91. package/lib/init/router.js +249 -0
  92. package/lib/init/static.js +133 -0
  93. package/lib/init/twing/cache.js +34 -0
  94. package/lib/init/twing/functions.js +51 -0
  95. package/lib/init/views.js +19 -0
  96. package/lib/init/watcher.js +402 -0
  97. package/lib/logger.js +94 -0
  98. package/lib/mocks/get.js +111 -0
  99. package/lib/mocks/index.js +9 -0
  100. package/lib/mocks/resolve/ref.js +484 -0
  101. package/lib/mocks/resolve/tpl.js +246 -0
  102. package/lib/mocks/resolve.js +205 -0
  103. package/lib/render/helpers.js +51 -0
  104. package/lib/render/index.js +38 -0
  105. package/lib/render/views/iframe/component.docs.js +77 -0
  106. package/lib/render/views/iframe/component.js +338 -0
  107. package/lib/render/views/iframe/design-tokens/colors.js +52 -0
  108. package/lib/render/views/iframe/design-tokens/index.js +9 -0
  109. package/lib/render/views/iframe/design-tokens/sizes.js +49 -0
  110. package/lib/render/views/iframe/design-tokens/typography.js +52 -0
  111. package/lib/render/views/iframe/docs.js +68 -0
  112. package/lib/render/views/iframe/index.js +44 -0
  113. package/lib/render/views/iframe/variation.js +116 -0
  114. package/lib/render/views/iframe/variation.standalone.js +89 -0
  115. package/lib/render/views/main/component.docs.js +53 -0
  116. package/lib/render/views/main/component.js +74 -0
  117. package/lib/render/views/main/design-tokens.js +53 -0
  118. package/lib/render/views/main/docs.js +47 -0
  119. package/lib/render/views/main/index.js +46 -0
  120. package/lib/state/components.js +132 -0
  121. package/lib/state/css.js +50 -0
  122. package/lib/state/docs.js +111 -0
  123. package/lib/state/file-contents.js +207 -0
  124. package/lib/state/helpers.js +86 -0
  125. package/lib/state/index.js +56 -0
  126. package/lib/state/menu/index.js +275 -0
  127. package/lib/state/menu/structure.js +146 -0
  128. package/lib/state/partials.js +23 -0
  129. package/lib/state/source-tree.js +75 -0
  130. package/lib/styleguide/color-names.js +150 -0
  131. package/lib/styleguide/colors.js +135 -0
  132. package/lib/styleguide/helpers.js +37 -0
  133. package/lib/styleguide/index.js +17 -0
  134. package/lib/styleguide/media-queries.js +26 -0
  135. package/lib/styleguide/spacings.js +35 -0
  136. package/lib/styleguide/typography.js +61 -0
  137. package/lib/validator/mocks.js +105 -0
  138. package/package.json +117 -0
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Module for printing and parsing CLI arguments
3
+ * @module initArgs
4
+ */
5
+
6
+ import yargs from "yargs";
7
+ import { hideBin } from "yargs/helpers";
8
+ import pkgJson from "../../package.json" with { type: "json" };
9
+
10
+ export default yargs(hideBin(process.argv))
11
+ .command("start", "Starts the miyagi server", {
12
+ verbose: {
13
+ description:
14
+ "Logging additional information — helpful mainly in case of errors.",
15
+ type: "boolean",
16
+ },
17
+ })
18
+ .command("build", "Creates a static build of all your components", {
19
+ folder: {
20
+ description: "The folder where your static build files will be saved",
21
+ type: "string",
22
+ },
23
+ })
24
+ .command(
25
+ "new",
26
+ "Creates a new component folder (including template, CSS, JS, documentation, mocks, and schema files)",
27
+ {
28
+ skip: {
29
+ description:
30
+ "files that will not be created\n(space separated list of tpl, css, js, docs, mocks, schema)",
31
+ type: "array",
32
+ },
33
+ only: {
34
+ description:
35
+ "tells miyagi to only created the passes file types\n(space separated list of tpl, css, js, docs, mocks, schema)",
36
+ type: "array",
37
+ },
38
+ },
39
+ )
40
+ .command(
41
+ "mocks",
42
+ "Creates a mock data file with dummy content based on the schema file",
43
+ )
44
+ .command(
45
+ "lint",
46
+ "Validates if the component's mock data matches its JSON schema",
47
+ )
48
+ .help()
49
+ .version(pkgJson.version)
50
+ .alias("help", "h")
51
+ .alias("verbose", "v")
52
+ .demandCommand()
53
+ .epilogue(
54
+ "Please check https://docs.miyagi.dev/configuration/options/ for all options",
55
+ );
@@ -0,0 +1,330 @@
1
+ /**
2
+ * Module for sanitizing the user configuration and merging it with the default configuration
3
+ * @module initConfig
4
+ */
5
+
6
+ import deepMerge from "deepmerge";
7
+ import log from "../logger.js";
8
+ import appConfig from "../default-config.js";
9
+ import { t, available as langAvailable } from "../i18n/index.js";
10
+ import fs from "fs";
11
+ import path from "path";
12
+
13
+ const { defaultUserConfig } = appConfig;
14
+
15
+ /**
16
+ * @param {string} path - unsanitized directory or file path
17
+ * @returns {string} the given path sanitized
18
+ */
19
+ function sanitizePath(path) {
20
+ if (path === null) return path;
21
+
22
+ let sanitizedPath = path;
23
+
24
+ if (sanitizedPath.startsWith("./")) {
25
+ sanitizedPath = sanitizedPath.slice(2);
26
+ } else if (sanitizedPath.startsWith("/")) {
27
+ sanitizedPath = sanitizedPath.slice(1);
28
+ }
29
+
30
+ if (sanitizedPath === "." || sanitizedPath === "/") {
31
+ sanitizedPath = "";
32
+ }
33
+
34
+ if (sanitizedPath.endsWith("/")) {
35
+ sanitizedPath = sanitizedPath.slice(0, -1);
36
+ }
37
+
38
+ return sanitizedPath;
39
+ }
40
+
41
+ /**
42
+ * @param {string|Array} strOrArr - file path or array of file paths
43
+ * @returns {Array} the given file path in an array or simply the given array
44
+ */
45
+ function arrayfy(strOrArr) {
46
+ return Array.isArray(strOrArr) ? strOrArr : [strOrArr];
47
+ }
48
+
49
+ /**
50
+ *
51
+ * @param {object} root0
52
+ * @param {string} root0.src
53
+ * @param {boolean} [root0.defer]
54
+ * @param {boolean} [root0.async]
55
+ * @param {string} [root0.type]
56
+ * @param {string} [root0.position]
57
+ * @returns {object}
58
+ */
59
+ function getJsFileObject({ src, defer, async, type, position = "head" }) {
60
+ return {
61
+ src,
62
+ defer,
63
+ async,
64
+ type,
65
+ position,
66
+ };
67
+ }
68
+
69
+ /**
70
+ * @param {string|Array|object} strOrArrOrObj - user assets files, either one file as string, an array of files or an object with strings or array for each NODE_ENV
71
+ * @param {object} manifest - manifest object
72
+ * @param {string} [manifest.file] - manifest file path
73
+ * @param {object} [manifest.content] - parsed json content of manifest file
74
+ * @param {string} root
75
+ * @returns {string[]} converts the given object to an array of asset file path strings
76
+ */
77
+ function getJsFilesArray(strOrArrOrObj, manifest, root) {
78
+ if (!Array.isArray(strOrArrOrObj)) {
79
+ log("warn", "config.assets.js is not an array.");
80
+ return [];
81
+ }
82
+
83
+ let files = strOrArrOrObj.map((entry) =>
84
+ typeof entry === "string" ? getJsFileObject({ src: entry }) : entry,
85
+ );
86
+
87
+ if (files.length > 0 && manifest.file && manifest.content) {
88
+ files = files.map((file) => {
89
+ const manifestEntry = getPathFromManifest(file.src, manifest, root);
90
+
91
+ if (manifestEntry) {
92
+ return {
93
+ ...file,
94
+ src: path.join(path.dirname(manifest.file), manifestEntry),
95
+ };
96
+ } else {
97
+ return file;
98
+ }
99
+ });
100
+ }
101
+
102
+ return files
103
+ .filter((file) => typeof file.src === "string")
104
+ .map((file) => ({
105
+ ...file,
106
+ src: sanitizePath(file.src),
107
+ }));
108
+ }
109
+
110
+ /**
111
+ * @param {string|Array|object} strOrArrOrObj - user assets files, either one file as string, an array of files or an object with strings or array for each NODE_ENV
112
+ * @param {object} manifest - manifest object
113
+ * @param {string|null} [manifest.file] - manifest file path
114
+ * @param {object} [manifest.content] - parsed json content of manifest file
115
+ * @param {string} root
116
+ * @returns {string[]} converts the given object to an array of asset file path strings
117
+ */
118
+ function getCssFilesArray(strOrArrOrObj, manifest, root) {
119
+ if (!Array.isArray(strOrArrOrObj)) {
120
+ log("warn", "config.assets.css is not an array.");
121
+ return [];
122
+ }
123
+
124
+ let files = strOrArrOrObj.filter((entry) => typeof entry === "string");
125
+
126
+ if (files.length > 0 && manifest.content && manifest.file) {
127
+ files = files.map((file) => {
128
+ const manifestEntry = getPathFromManifest(file, manifest, root);
129
+
130
+ if (manifestEntry) {
131
+ return path.join(path.dirname(manifest.file), manifestEntry);
132
+ } else {
133
+ return file;
134
+ }
135
+ });
136
+ }
137
+
138
+ return files.map(sanitizePath);
139
+ }
140
+
141
+ /**
142
+ * @param {string|Array|object} strOrArrOrObj
143
+ * @returns {string[]} the given param converted to an array of asset file path strings
144
+ */
145
+ function getAssetFoldersArray(strOrArrOrObj) {
146
+ if (!Array.isArray(strOrArrOrObj)) {
147
+ log("warn", "config.assets.folder is not an array.");
148
+ return [];
149
+ }
150
+
151
+ return strOrArrOrObj
152
+ .filter((entry) => typeof entry === "string")
153
+ .map(sanitizePath);
154
+ }
155
+
156
+ /**
157
+ * @param {object} [userConfig] the unmerged user configuration
158
+ * @returns {object} the user configuration merged with the default configuration
159
+ */
160
+ export default (userConfig = {}) => {
161
+ const config = { ...userConfig };
162
+
163
+ if (config.build) {
164
+ if (config.build.basePath) {
165
+ if (!config.build.basePath.startsWith("/")) {
166
+ config.build.basePath = `/${config.build.basePath}`;
167
+ }
168
+
169
+ if (!config.build.basePath.endsWith("/")) {
170
+ config.build.basePath = `${config.build.basePath}/`;
171
+ }
172
+ }
173
+ }
174
+
175
+ if (config.assets) {
176
+ let manifest = {};
177
+
178
+ if (config.assets.manifest) {
179
+ try {
180
+ const manifestContent = fs.readFileSync(
181
+ path.resolve(
182
+ path.join(config.assets.root || "", config.assets.manifest),
183
+ ),
184
+ { encoding: "utf8" },
185
+ );
186
+
187
+ manifest.file = config.assets.manifest;
188
+ manifest.content = JSON.parse(manifestContent);
189
+
190
+ // eslint-disable-next-line no-unused-vars
191
+ } catch (e) {
192
+ log(
193
+ "warn",
194
+ t("manifestNotFound").replace("{{manifest}}", config.assets.manifest),
195
+ );
196
+ }
197
+ }
198
+
199
+ if (config.assets.folder) {
200
+ config.assets.folder = getAssetFoldersArray(config.assets.folder);
201
+ }
202
+
203
+ if (config.assets.css) {
204
+ config.assets.css = getCssFilesArray(
205
+ config.assets.css,
206
+ manifest,
207
+ config.assets.root,
208
+ );
209
+ }
210
+
211
+ if (config.assets.js) {
212
+ config.assets.js = getJsFilesArray(
213
+ config.assets.js,
214
+ manifest,
215
+ config.assets.root,
216
+ );
217
+ }
218
+
219
+ if (!config.assets.customProperties) {
220
+ config.assets.customProperties = {};
221
+ }
222
+
223
+ if (Array.isArray(config.assets.customProperties.files)) {
224
+ config.assets.customProperties.files =
225
+ config.assets.customProperties.files.filter(
226
+ (entry) => typeof entry === "string",
227
+ );
228
+
229
+ if (manifest?.content) {
230
+ config.assets.customProperties.files =
231
+ config.assets.customProperties.files.map((file) => {
232
+ const manifestEntry = getPathFromManifest(
233
+ file,
234
+ manifest,
235
+ config.assets.root,
236
+ );
237
+
238
+ if (manifestEntry) {
239
+ return path.join(path.dirname(manifest.file), manifestEntry);
240
+ } else {
241
+ return file;
242
+ }
243
+ });
244
+ }
245
+ } else {
246
+ log("warn", "config.assets.customProperties.files is not an array.");
247
+
248
+ config.assets.customProperties.files = [];
249
+ }
250
+ }
251
+
252
+ if (config.components) {
253
+ if (config.components.ignores) {
254
+ config.components.ignores = arrayfy(config.components.ignores).map(
255
+ sanitizePath,
256
+ );
257
+ }
258
+ }
259
+
260
+ if (!config.ui) config.ui = {};
261
+ if (!config.ui.theme) config.ui.theme = {};
262
+ if (!config.ui.theme.light) config.ui.theme.light = {};
263
+ if (!config.ui.theme.dark) config.ui.theme.dark = {};
264
+
265
+ if (config.ui.theme.logo) {
266
+ if (typeof config.ui.theme.logo === "string") {
267
+ const { logo } = config.ui.theme;
268
+
269
+ config.ui.theme.logo = {
270
+ light: logo,
271
+ dark: logo,
272
+ };
273
+ } else {
274
+ if (config.ui.theme.logo.light && !config.ui.theme.logo.dark) {
275
+ config.ui.theme.logo.dark = config.ui.theme.logo.light;
276
+ } else if (config.ui.theme.logo.dark && !config.ui.theme.logo.light) {
277
+ config.ui.theme.logo.light = config.ui.theme.logo.dark;
278
+ }
279
+ }
280
+
281
+ if (config.ui.theme.logo.light) {
282
+ config.ui.theme.logo.light = sanitizePath(config.ui.theme.logo.light);
283
+ }
284
+ if (config.ui.theme.logo.dark) {
285
+ config.ui.theme.logo.dark = sanitizePath(config.ui.theme.logo.dark);
286
+ }
287
+ }
288
+
289
+ const merged = deepMerge(defaultUserConfig, config);
290
+
291
+ merged.components.folder = sanitizePath(merged.components.folder);
292
+
293
+ // do this later as otherwise the deepMerge would do concatenation which we do not want
294
+ if (config.files) {
295
+ if (config.files.mocks) {
296
+ if (config.files.mocks.extension) {
297
+ merged.files.mocks.extension = arrayfy(config.files.mocks.extension);
298
+
299
+ if (merged.files.mocks.extension.length === 1) {
300
+ merged.files.mocks.extension.push(
301
+ defaultUserConfig.files.mocks.extension[1],
302
+ );
303
+ }
304
+ }
305
+ }
306
+ }
307
+
308
+ if (!langAvailable.includes(merged.ui.lang)) {
309
+ merged.ui.lang = "en";
310
+ }
311
+
312
+ return merged;
313
+ };
314
+
315
+ /**
316
+ * @param {string} file
317
+ * @param {object} manifest
318
+ * @param {string} root
319
+ * @returns {string|null}
320
+ */
321
+ function getPathFromManifest(file, manifest, root = "") {
322
+ const entry = Object.entries(manifest.content).find(([key]) => {
323
+ return (
324
+ path.resolve(root, path.dirname(manifest.file), sanitizePath(key)) ===
325
+ path.resolve(root, sanitizePath(file))
326
+ );
327
+ });
328
+
329
+ return entry ? entry[1] : null;
330
+ }
@@ -0,0 +1,65 @@
1
+ import path from "path";
2
+ import {
3
+ createSynchronousEnvironment,
4
+ createSynchronousFilesystemLoader,
5
+ } from "twing";
6
+ import fs from "fs";
7
+ import { t } from "../i18n/index.js";
8
+ import log from "../logger.js";
9
+ import * as helpers from "../helpers.js";
10
+ import TwingCache from "./twing/cache.js";
11
+ import * as twingFunctions from "./twing/functions.js";
12
+
13
+ /**
14
+ * @returns {void}
15
+ */
16
+ function setMiyagiEngine() {
17
+ const loader = createSynchronousFilesystemLoader(fs);
18
+ const twing = createSynchronousEnvironment(loader, {
19
+ cache: new TwingCache(),
20
+ });
21
+
22
+ loader.addPath(
23
+ path.join(import.meta.dirname, "../../frontend/views"),
24
+ "@miyagi",
25
+ );
26
+
27
+ Object.values(twingFunctions).forEach((twingFunction) => {
28
+ twing.addFunction(twingFunction);
29
+ });
30
+
31
+ global.app.engine("miyagi", async (str, options, cb) =>
32
+ cb(await twing.render(str, options)),
33
+ );
34
+ }
35
+
36
+ /**
37
+ * @returns {Promise<void>}
38
+ */
39
+ async function setUserEngine() {
40
+ const { extension } = global.config.files.templates;
41
+ const { engine } = global.config;
42
+
43
+ if (!engine.render) {
44
+ log("error", "No render function has beend defined.");
45
+ process.exit(1);
46
+ }
47
+
48
+ try {
49
+ global.app.engine(
50
+ helpers.getSingleFileExtension(extension),
51
+ async (name, context, cb) => await engine.render({ name, context, cb }),
52
+ );
53
+ } catch (e) {
54
+ log("error", t("settingEngineFailed"), e);
55
+ process.exit(1);
56
+ }
57
+ }
58
+
59
+ /**
60
+ * @returns {Promise<void>}
61
+ */
62
+ export default async function initEngines() {
63
+ await setUserEngine();
64
+ setMiyagiEngine();
65
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Module for initializing miyagi
3
+ * @module init
4
+ */
5
+
6
+ import express from "express";
7
+ // deepcode ignore HttpToHttps: local server only
8
+ import http from "http";
9
+ import cookieParser from "cookie-parser";
10
+
11
+ import appConfig from "../default-config.js";
12
+ import { t } from "../i18n/index.js";
13
+ import build from "../build/index.js";
14
+ import log from "../logger.js";
15
+ import setEngines from "./engines.js";
16
+ import setRouter from "./router.js";
17
+ import setState from "../state/index.js";
18
+ import setStatic from "./static.js";
19
+ import setViews from "./views.js";
20
+ import setWatcher from "./watcher.js";
21
+
22
+ /**
23
+ * @param {object} mergedConfig
24
+ * @returns {Promise<object>}
25
+ */
26
+ export default async function init(mergedConfig) {
27
+ // deepcode ignore UseCsurfForExpress: local server only, deepcode ignore DisablePoweredBy: local server only
28
+ global.app = express();
29
+ global.app.use(cookieParser());
30
+ global.config = mergedConfig;
31
+ global.app.set("view cache", global.config.isBuild);
32
+ global.app.set("cache", global.config.isBuild);
33
+
34
+ await setEngines();
35
+
36
+ const port = process.env.PORT || appConfig.defaultPort;
37
+
38
+ global.app.set("port", port);
39
+
40
+ await setState({
41
+ sourceTree: true,
42
+ menu: true,
43
+ partials: true,
44
+ fileContents: true,
45
+ css: true,
46
+ });
47
+
48
+ setStatic();
49
+ setRouter();
50
+ setViews();
51
+
52
+ if (global.config.isBuild) {
53
+ return build()
54
+ .then((message) => {
55
+ log("success", message);
56
+ process.exit(0);
57
+ })
58
+ .catch((error) => {
59
+ log("error", error);
60
+ process.exit(1);
61
+ });
62
+ }
63
+
64
+ const { server, port: actualPort } = await startServer(
65
+ global.app.get("port"),
66
+ );
67
+
68
+ setWatcher(server);
69
+
70
+ log("success", `${t("serverStarted").replace("{{port}}", actualPort)}\n`);
71
+
72
+ return server;
73
+ }
74
+
75
+ /**
76
+ * @param {number} port - the port that should be used
77
+ * @returns {Promise} gets resolved with the server instance and the actual port
78
+ */
79
+ function startServer(port) {
80
+ const server = http.createServer(global.app);
81
+
82
+ return new Promise((resolve) => {
83
+ server
84
+ .listen(port, function () {
85
+ resolve({ server, port });
86
+ })
87
+ .on("error", (error) => {
88
+ if (error["code"] === "EADDRINUSE") {
89
+ log(
90
+ "error",
91
+ t("portInUse").replace("{{port}}", port),
92
+ error.toString(),
93
+ );
94
+ server.close(async function () {
95
+ const response = await startServer(port + 1);
96
+
97
+ resolve(response);
98
+ });
99
+ }
100
+ });
101
+ });
102
+ }
@@ -0,0 +1,12 @@
1
+ import init from "./index.js";
2
+
3
+ /**
4
+ * Runs the renderer to either start the server or create a build
5
+ * @param {object} config - the user configuration object
6
+ * @returns {Promise<object>}
7
+ */
8
+ export default async function initRendering(config) {
9
+ if (config) {
10
+ return await init(config);
11
+ }
12
+ }