@modern-js/app-tools 2.39.1 → 2.39.2-alpha.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.
Files changed (72) hide show
  1. package/dist/cjs/analyze/getBundleEntry.js +9 -1
  2. package/dist/cjs/config/initialize/inits.js +39 -43
  3. package/dist/esm/analyze/getBundleEntry.js +9 -1
  4. package/dist/esm/config/initialize/inits.js +44 -49
  5. package/dist/esm-node/analyze/getBundleEntry.js +9 -1
  6. package/dist/esm-node/config/initialize/inits.js +38 -43
  7. package/dist/js/modern/analyze/constants.js +15 -0
  8. package/dist/js/modern/analyze/generateCode.js +179 -0
  9. package/dist/js/modern/analyze/getBundleEntry.js +75 -0
  10. package/dist/js/modern/analyze/getClientRoutes.js +219 -0
  11. package/dist/js/modern/analyze/getFileSystemEntry.js +74 -0
  12. package/dist/js/modern/analyze/getHtmlTemplate.js +82 -0
  13. package/dist/js/modern/analyze/getServerRoutes.js +192 -0
  14. package/dist/js/modern/analyze/index.js +148 -0
  15. package/dist/js/modern/analyze/isDefaultExportFunction.js +32 -0
  16. package/dist/js/modern/analyze/makeLegalIdentifier.js +16 -0
  17. package/dist/js/modern/analyze/templates.js +88 -0
  18. package/dist/js/modern/analyze/utils.js +92 -0
  19. package/dist/js/modern/commands/build.js +154 -0
  20. package/dist/js/modern/commands/deploy.js +5 -0
  21. package/dist/js/modern/commands/dev.js +95 -0
  22. package/dist/js/modern/commands/index.js +3 -0
  23. package/dist/js/modern/commands/inspect.js +69 -0
  24. package/dist/js/modern/commands/start.js +31 -0
  25. package/dist/js/modern/exports/server.js +1 -0
  26. package/dist/js/modern/hooks.js +21 -0
  27. package/dist/js/modern/index.js +109 -0
  28. package/dist/js/modern/locale/en.js +35 -0
  29. package/dist/js/modern/locale/index.js +9 -0
  30. package/dist/js/modern/locale/zh.js +35 -0
  31. package/dist/js/modern/utils/config.js +78 -0
  32. package/dist/js/modern/utils/createCompiler.js +61 -0
  33. package/dist/js/modern/utils/createServer.js +18 -0
  34. package/dist/js/modern/utils/getSpecifiedEntries.js +36 -0
  35. package/dist/js/modern/utils/language.js +5 -0
  36. package/dist/js/modern/utils/printInstructions.js +11 -0
  37. package/dist/js/modern/utils/routes.js +15 -0
  38. package/dist/js/modern/utils/types.js +0 -0
  39. package/dist/js/node/analyze/constants.js +36 -0
  40. package/dist/js/node/analyze/generateCode.js +208 -0
  41. package/dist/js/node/analyze/getBundleEntry.js +89 -0
  42. package/dist/js/node/analyze/getClientRoutes.js +241 -0
  43. package/dist/js/node/analyze/getFileSystemEntry.js +90 -0
  44. package/dist/js/node/analyze/getHtmlTemplate.js +106 -0
  45. package/dist/js/node/analyze/getServerRoutes.js +208 -0
  46. package/dist/js/node/analyze/index.js +178 -0
  47. package/dist/js/node/analyze/isDefaultExportFunction.js +50 -0
  48. package/dist/js/node/analyze/makeLegalIdentifier.js +24 -0
  49. package/dist/js/node/analyze/templates.js +106 -0
  50. package/dist/js/node/analyze/utils.js +113 -0
  51. package/dist/js/node/commands/build.js +174 -0
  52. package/dist/js/node/commands/deploy.js +14 -0
  53. package/dist/js/node/commands/dev.js +120 -0
  54. package/dist/js/node/commands/index.js +44 -0
  55. package/dist/js/node/commands/inspect.js +98 -0
  56. package/dist/js/node/commands/start.js +47 -0
  57. package/dist/js/node/exports/server.js +13 -0
  58. package/dist/js/node/hooks.js +39 -0
  59. package/dist/js/node/index.js +141 -0
  60. package/dist/js/node/locale/en.js +42 -0
  61. package/dist/js/node/locale/index.js +20 -0
  62. package/dist/js/node/locale/zh.js +42 -0
  63. package/dist/js/node/utils/config.js +103 -0
  64. package/dist/js/node/utils/createCompiler.js +81 -0
  65. package/dist/js/node/utils/createServer.js +35 -0
  66. package/dist/js/node/utils/getSpecifiedEntries.js +46 -0
  67. package/dist/js/node/utils/language.js +13 -0
  68. package/dist/js/node/utils/printInstructions.js +22 -0
  69. package/dist/js/node/utils/routes.js +25 -0
  70. package/dist/js/node/utils/types.js +0 -0
  71. package/dist/types/config/initialize/inits.d.ts +2 -1
  72. package/package.json +6 -6
@@ -0,0 +1,219 @@
1
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
2
+
3
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
4
+
5
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
+
7
+ import path from 'path';
8
+ import { fs, createDebugger, findExists, normalizeToPosixPath } from '@modern-js/utils';
9
+ import { makeLegalIdentifier } from "./makeLegalIdentifier";
10
+ import { FILE_SYSTEM_ROUTES_COMPONENTS_DIR, FILE_SYSTEM_ROUTES_DYNAMIC_REGEXP, FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT, FILE_SYSTEM_ROUTES_IGNORED_REGEX, FILE_SYSTEM_ROUTES_INDEX, FILE_SYSTEM_ROUTES_LAYOUT, JS_EXTENSIONS } from "./constants";
11
+ const debug = createDebugger('get-client-routes');
12
+
13
+ const findLayout = dir => findExists(JS_EXTENSIONS.map(ext => path.resolve(dir, `${FILE_SYSTEM_ROUTES_LAYOUT}${ext}`)));
14
+
15
+ const shouldSkip = file => {
16
+ // should not skip directory.
17
+ if (fs.statSync(file).isDirectory()) {
18
+ return false;
19
+ }
20
+
21
+ const ext = path.extname(file);
22
+
23
+ if (FILE_SYSTEM_ROUTES_IGNORED_REGEX.test(file) || !JS_EXTENSIONS.includes(ext) || FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT === path.basename(file, ext)) {
24
+ return true;
25
+ }
26
+
27
+ return false;
28
+ };
29
+
30
+ const replaceWithAlias = (base, filePath, alias) => normalizeToPosixPath(path.join(alias, path.relative(base, filePath)));
31
+
32
+ const compName = (srcDirectory, filePath) => {
33
+ const legalCompName = makeLegalIdentifier(path.relative(srcDirectory, filePath));
34
+ return `Comp_${legalCompName}`;
35
+ };
36
+
37
+ const layoutNameAbbr = filePath => {
38
+ const prefix = 'L_';
39
+ const dirName = path.dirname(filePath).split('/').pop() || '';
40
+ return `${prefix}${makeLegalIdentifier(dirName)}`;
41
+ };
42
+
43
+ const parents = [];
44
+ /* eslint-disable no-param-reassign */
45
+
46
+ const recursiveReadDir = ({
47
+ dir,
48
+ routes,
49
+ basePath: _basePath = '/',
50
+ srcDirectory,
51
+ srcAlias
52
+ }) => {
53
+ let hasDynamicRoute = false;
54
+ let resetParent = false;
55
+ let parent = parents[parents.length - 1];
56
+ const layout = findLayout(dir);
57
+
58
+ if (layout) {
59
+ if (_basePath === '/') {
60
+ throw new Error(`should use _app instead of _layout in ${dir}`);
61
+ } else {
62
+ const alias = replaceWithAlias(srcDirectory, layout, srcAlias);
63
+ const componentName = compName(srcDirectory, layout);
64
+ const route = {
65
+ path: `${_basePath.substring(0, _basePath.length - 1)}`,
66
+ exact: false,
67
+ routes: [],
68
+ _component: alias,
69
+ component: componentName,
70
+ parent
71
+ };
72
+ parent = route;
73
+ resetParent = true;
74
+ routes.push(route);
75
+ parents.push(route);
76
+ routes = route.routes;
77
+ }
78
+ }
79
+
80
+ for (const relative of fs.readdirSync(dir)) {
81
+ const filePath = path.join(dir, relative);
82
+
83
+ if (!shouldSkip(filePath)) {
84
+ const filename = path.basename(filePath, path.extname(filePath));
85
+ const alias = replaceWithAlias(srcDirectory, filePath, srcAlias);
86
+ const componentName = compName(srcDirectory, filePath);
87
+ const dynamicRouteMatched = FILE_SYSTEM_ROUTES_DYNAMIC_REGEXP.exec(filename);
88
+
89
+ if (dynamicRouteMatched) {
90
+ if (hasDynamicRoute) {
91
+ throw new Error(`Can't set two dynamic route in one directory: ${dir}`);
92
+ } else {
93
+ hasDynamicRoute = true;
94
+ }
95
+ }
96
+
97
+ const route = {
98
+ path: `${_basePath}${dynamicRouteMatched ? `:${dynamicRouteMatched[1]}${dynamicRouteMatched[2]}` : filename}`,
99
+ _component: alias,
100
+ component: componentName,
101
+ exact: true,
102
+ parent
103
+ };
104
+
105
+ if (fs.statSync(filePath).isDirectory()) {
106
+ recursiveReadDir({
107
+ dir: filePath,
108
+ routes,
109
+ basePath: `${route.path}/`,
110
+ srcDirectory,
111
+ srcAlias
112
+ });
113
+ continue;
114
+ }
115
+
116
+ if (filename === FILE_SYSTEM_ROUTES_LAYOUT) {
117
+ continue;
118
+ }
119
+
120
+ if (filename === FILE_SYSTEM_ROUTES_INDEX) {
121
+ route.path = _basePath === '/' ? _basePath : `${_basePath.substring(0, _basePath.length - 1)}`;
122
+ }
123
+
124
+ if (filename === '404' && _basePath === '/') {
125
+ route.path = '*';
126
+ route.exact = false;
127
+ }
128
+
129
+ routes.push(route);
130
+ }
131
+ }
132
+
133
+ if (resetParent) {
134
+ parents.pop();
135
+ }
136
+ };
137
+ /* eslint-enable no-param-reassign */
138
+
139
+
140
+ const normalizeNestedRoutes = (nested, internalComponentsDir, internalDirectory, internalDirAlias) => {
141
+ const flat = routes => routes.reduce((memo, route) => memo.concat(Array.isArray(route.routes) ? flat(route.routes) : [route]), []);
142
+
143
+ const generate = route => {
144
+ const codes = [];
145
+ let lastComponent = route.component;
146
+ const imports = [`import React from 'react';`, `import ${lastComponent} from '${route._component}'`]; // eslint-disable-next-line no-param-reassign, no-cond-assign
147
+
148
+ while (route = route.parent) {
149
+ const layoutComponent = route.component;
150
+ const layoutComponentAbbr = layoutNameAbbr(route._component);
151
+ imports.push(`import ${layoutComponent} from '${route._component}';`);
152
+ const currentComponent = `${layoutComponentAbbr}_${lastComponent}`;
153
+ codes.push(`const ${currentComponent} = props => <${layoutComponent} Component={${lastComponent}} {...props} />;`);
154
+ lastComponent = currentComponent;
155
+ }
156
+
157
+ const file = path.resolve(internalComponentsDir, `${lastComponent}.jsx`);
158
+ fs.outputFileSync(file, `${imports.join('\n')}\n${codes.join('\n')}\nexport default ${lastComponent}`);
159
+ return {
160
+ component: lastComponent,
161
+ _component: replaceWithAlias(internalDirectory, file, internalDirAlias)
162
+ };
163
+ };
164
+
165
+ const normalized = flat(nested).map(route => route.parent ? _objectSpread(_objectSpread(_objectSpread({}, route), generate(route)), {}, {
166
+ parent: undefined
167
+ }) : _objectSpread(_objectSpread({}, route), {}, {
168
+ parent: undefined
169
+ }));
170
+ return normalized;
171
+ };
172
+
173
+ const getRouteWeight = route => route === '*' ? 999 : route.split(':').length - 1;
174
+
175
+ export const getClientRoutes = ({
176
+ entrypoint,
177
+ srcDirectory,
178
+ srcAlias,
179
+ internalDirectory,
180
+ internalDirAlias
181
+ }) => {
182
+ const {
183
+ entry,
184
+ entryName
185
+ } = entrypoint;
186
+
187
+ if (!fs.existsSync(entry)) {
188
+ throw new Error(`generate file system routes error, ${entry} directory not found.`);
189
+ }
190
+
191
+ if (!(fs.existsSync(entry) && fs.statSync(entry).isDirectory())) {
192
+ throw new Error(`generate file system routes error, ${entry} should be directory.`);
193
+ }
194
+
195
+ let routes = [];
196
+ recursiveReadDir({
197
+ dir: entry,
198
+ routes,
199
+ basePath: '/',
200
+ srcDirectory,
201
+ srcAlias
202
+ });
203
+ const internalComponentsDir = path.resolve(internalDirectory, `${entryName}/${FILE_SYSTEM_ROUTES_COMPONENTS_DIR}`);
204
+ fs.emptyDirSync(internalComponentsDir);
205
+ routes = normalizeNestedRoutes(routes, internalComponentsDir, internalDirectory, internalDirAlias);
206
+ parents.length = 0; // FIXME: support more situations
207
+
208
+ routes.sort((a, b) => {
209
+ const delta = getRouteWeight(a.path) - getRouteWeight(b.path);
210
+
211
+ if (delta === 0) {
212
+ return a.path.length - b.path.length;
213
+ }
214
+
215
+ return delta;
216
+ });
217
+ debug(`fileSystem routes: %o`, routes);
218
+ return routes;
219
+ };
@@ -0,0 +1,74 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { findExists, ensureAbsolutePath } from '@modern-js/utils';
4
+ import { isDefaultExportFunction } from "./isDefaultExportFunction";
5
+ import { JS_EXTENSIONS, INDEX_FILE_NAME, APP_FILE_NAME, PAGES_DIR_NAME, FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT } from "./constants";
6
+
7
+ const hasIndex = dir => findExists(JS_EXTENSIONS.map(ext => path.resolve(dir, `${INDEX_FILE_NAME}${ext}`)));
8
+
9
+ const hasApp = dir => findExists(JS_EXTENSIONS.map(ext => path.resolve(dir, `${APP_FILE_NAME}${ext}`)));
10
+
11
+ const hasPages = dir => fs.existsSync(path.join(dir, PAGES_DIR_NAME));
12
+
13
+ const isBundleEntry = dir => hasApp(dir) || hasPages(dir) || hasIndex(dir);
14
+
15
+ const scanDir = dirs => dirs.map(dir => {
16
+ const indexFile = hasIndex(dir);
17
+ const customBootstrap = isDefaultExportFunction(indexFile) ? indexFile : false;
18
+ const entryName = path.basename(dir);
19
+
20
+ if (indexFile && !customBootstrap) {
21
+ return {
22
+ entryName,
23
+ entry: indexFile,
24
+ isAutoMount: false
25
+ };
26
+ }
27
+
28
+ if (hasApp(dir)) {
29
+ return {
30
+ entryName,
31
+ entry: path.join(dir, APP_FILE_NAME),
32
+ isAutoMount: true,
33
+ customBootstrap
34
+ };
35
+ } else if (hasPages(dir)) {
36
+ return {
37
+ entryName,
38
+ entry: path.join(dir, PAGES_DIR_NAME),
39
+ fileSystemRoutes: {
40
+ globalApp: findExists(JS_EXTENSIONS.map(ext => path.resolve(dir, `./${PAGES_DIR_NAME}/${FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT}${ext}`)))
41
+ },
42
+ isAutoMount: true,
43
+ customBootstrap
44
+ };
45
+ } else {
46
+ return {
47
+ entryName,
48
+ entry: indexFile,
49
+ isAutoMount: false
50
+ };
51
+ }
52
+ });
53
+
54
+ export const getFileSystemEntry = (appContext, config) => {
55
+ const {
56
+ appDirectory
57
+ } = appContext;
58
+ const {
59
+ source: {
60
+ entriesDir
61
+ }
62
+ } = config;
63
+ const src = ensureAbsolutePath(appDirectory, entriesDir);
64
+
65
+ if (fs.existsSync(src)) {
66
+ if (fs.statSync(src).isDirectory()) {
67
+ return scanDir(isBundleEntry(src) ? [src] : fs.readdirSync(src).map(file => path.join(src, file)).filter(file => fs.statSync(file).isDirectory() && isBundleEntry(file)));
68
+ } else {
69
+ throw Error(`source.entriesDir accept a directory.`);
70
+ }
71
+ } else {
72
+ throw Error(`src dir ${entriesDir} not found.`);
73
+ }
74
+ };
@@ -0,0 +1,82 @@
1
+ import path from 'path';
2
+ import { fs, findExists, MAIN_ENTRY_NAME } from '@modern-js/utils';
3
+ import { HTML_PARTIALS_EXTENSIONS, HTML_PARTIALS_FOLDER } from "./constants";
4
+ import * as templates from "./templates";
5
+ var PartialPosition;
6
+
7
+ (function (PartialPosition) {
8
+ PartialPosition["TOP"] = "top";
9
+ PartialPosition["HEAD"] = "head";
10
+ PartialPosition["BODY"] = "body";
11
+ PartialPosition["BOTTOM"] = "bottom";
12
+ PartialPosition["INDEX"] = "index";
13
+ })(PartialPosition || (PartialPosition = {}));
14
+
15
+ const findPartials = (dir, entryName, position) => {
16
+ if (fs.existsSync(dir)) {
17
+ const base = findExists(HTML_PARTIALS_EXTENSIONS.map(ext => path.resolve(dir, `${position}${ext}`)));
18
+ const file = entryName ? findExists(HTML_PARTIALS_EXTENSIONS.map(ext => path.resolve(dir, entryName, `${position}${ext}`))) || base : base;
19
+ return file ? {
20
+ file,
21
+ content: fs.readFileSync(file, 'utf8')
22
+ } : null;
23
+ }
24
+
25
+ return null;
26
+ }; // generate html template for
27
+
28
+
29
+ export const getHtmlTemplate = async (entrypoints, api, {
30
+ appContext,
31
+ config
32
+ }) => {
33
+ const {
34
+ appDirectory,
35
+ internalDirectory
36
+ } = appContext;
37
+ const {
38
+ source: {
39
+ configDir
40
+ }
41
+ } = config;
42
+ const htmlDir = path.resolve(appDirectory, configDir, HTML_PARTIALS_FOLDER);
43
+ const htmlTemplates = {};
44
+
45
+ for (const entrypoint of entrypoints) {
46
+ const {
47
+ entryName
48
+ } = entrypoint;
49
+ const name = entrypoints.length === 1 && entryName === MAIN_ENTRY_NAME ? '' : entryName;
50
+ const customIndexTemplate = findPartials(htmlDir, name, PartialPosition.INDEX);
51
+
52
+ if (customIndexTemplate) {
53
+ htmlTemplates[entryName] = customIndexTemplate.file;
54
+ } else {
55
+ const hookRunners = api.useHookRunners();
56
+ const {
57
+ partials
58
+ } = await hookRunners.htmlPartials({
59
+ entrypoint,
60
+ partials: [PartialPosition.TOP, PartialPosition.HEAD, PartialPosition.BODY].reduce((previous, position) => {
61
+ const found = findPartials(htmlDir, name, position);
62
+ previous[position] = found ? [found.content] : [];
63
+ return previous;
64
+ }, {
65
+ top: [],
66
+ head: [],
67
+ body: []
68
+ })
69
+ });
70
+ const templatePath = path.resolve(internalDirectory, entryName, 'index.html');
71
+ fs.outputFileSync(templatePath, templates.html(partials), 'utf8');
72
+ htmlTemplates[entryName] = templatePath;
73
+ const bottomTemplate = findPartials(htmlDir, name, PartialPosition.BOTTOM);
74
+
75
+ if (bottomTemplate) {
76
+ htmlTemplates[`__${entryName}-bottom__`] = bottomTemplate.content;
77
+ }
78
+ }
79
+ }
80
+
81
+ return htmlTemplates;
82
+ };
@@ -0,0 +1,192 @@
1
+ const _excluded = ["path"],
2
+ _excluded2 = ["path"];
3
+
4
+ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
5
+
6
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
7
+
8
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
9
+
10
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
11
+
12
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
13
+
14
+ import path from 'path';
15
+ import fs from 'fs';
16
+ import { urlJoin, isPlainObject, removeLeadingSlash, getEntryOptions, SERVER_BUNDLE_DIRECTORY, MAIN_ENTRY_NAME, removeTailSlash } from '@modern-js/utils';
17
+ import { walkDirectory } from "./utils";
18
+ /**
19
+ * Add base url for each server route.
20
+ * @param baseUrl - Base url from server.baseUrl
21
+ * @param routes - Server routes.
22
+ * @returns Server routes with baseUrl prefixed.
23
+ */
24
+
25
+ const applyBaseUrl = (baseUrl, routes) => {
26
+ if (baseUrl) {
27
+ if (Array.isArray(baseUrl)) {
28
+ return baseUrl.reduce((previous, current) => [...previous, ...applyBaseUrl(current, routes)], []);
29
+ } else {
30
+ return routes.map(route => {
31
+ const urlPath = urlJoin(baseUrl, route.urlPath);
32
+ return _objectSpread(_objectSpread({}, route), {}, {
33
+ urlPath: urlPath === '/' ? urlPath : removeTailSlash(urlPath)
34
+ });
35
+ });
36
+ }
37
+ }
38
+
39
+ return routes;
40
+ };
41
+ /**
42
+ *
43
+ * @param original - Original entrypoint route info.
44
+ * @param routeOptions - Custom entrypoint route config from server.routes.
45
+ * @returns
46
+ */
47
+
48
+
49
+ const applyRouteOptions = (original, routeOptions) => {
50
+ const {
51
+ route,
52
+ disableSpa
53
+ } = routeOptions;
54
+ original.isSPA = !disableSpa; // set entryPath as dir
55
+
56
+ !original.isSPA && (original.entryPath = path.dirname(original.entryPath));
57
+ let routes;
58
+
59
+ if (route) {
60
+ if (Array.isArray(route)) {
61
+ routes = route.map(url => {
62
+ if (isPlainObject(url)) {
63
+ const _ref = url,
64
+ {
65
+ path: urlPath
66
+ } = _ref,
67
+ other = _objectWithoutProperties(_ref, _excluded);
68
+
69
+ return _objectSpread(_objectSpread(_objectSpread({}, original), other), {}, {
70
+ urlPath
71
+ });
72
+ } else {
73
+ return _objectSpread(_objectSpread({}, original), {}, {
74
+ urlPath: url
75
+ });
76
+ }
77
+ });
78
+ } else if (isPlainObject(route)) {
79
+ const _ref2 = route,
80
+ {
81
+ path: urlPath
82
+ } = _ref2,
83
+ other = _objectWithoutProperties(_ref2, _excluded2);
84
+
85
+ routes = [_objectSpread(_objectSpread(_objectSpread({}, original), other), {}, {
86
+ urlPath
87
+ })];
88
+ } else {
89
+ routes = [_objectSpread(_objectSpread({}, original), {}, {
90
+ urlPath: route
91
+ })];
92
+ }
93
+ } else {
94
+ routes = [original];
95
+ }
96
+
97
+ return routes;
98
+ };
99
+ /**
100
+ * Collect routes from entrypoints.
101
+ * @param entrypoints - Bundle entrypoints.
102
+ * @param config - Normalized user config.
103
+ * @returns entrypoint Routes
104
+ */
105
+
106
+
107
+ const collectHtmlRoutes = (entrypoints, appContext, config) => {
108
+ const {
109
+ output: {
110
+ htmlPath,
111
+ disableHtmlFolder,
112
+ enableModernMode
113
+ },
114
+ server: {
115
+ baseUrl,
116
+ routes,
117
+ ssr,
118
+ ssrByEntries
119
+ }
120
+ } = config;
121
+ const {
122
+ packageName
123
+ } = appContext;
124
+ let htmlRoutes = entrypoints.reduce((previous, {
125
+ entryName
126
+ }) => {
127
+ const entryOptions = getEntryOptions(entryName, ssr, ssrByEntries, packageName);
128
+ const isSSR = Boolean(entryOptions);
129
+ const {
130
+ resHeaders
131
+ } = (routes === null || routes === void 0 ? void 0 : routes[entryName]) || {};
132
+ let route = {
133
+ urlPath: `/${entryName === MAIN_ENTRY_NAME ? '' : entryName}`,
134
+ entryName,
135
+ entryPath: removeLeadingSlash(path.posix.normalize(`${htmlPath}/${entryName}${disableHtmlFolder ? '.html' : '/index.html'}`)),
136
+ isSPA: true,
137
+ isSSR,
138
+ responseHeaders: resHeaders,
139
+ enableModernMode: Boolean(enableModernMode),
140
+ bundle: isSSR ? `${SERVER_BUNDLE_DIRECTORY}/${entryName}.js` : undefined
141
+ };
142
+
143
+ if (routes !== null && routes !== void 0 && routes.hasOwnProperty(entryName)) {
144
+ const routeOptions = isPlainObject(routes[entryName]) ? routes[entryName] : {
145
+ route: routes[entryName]
146
+ };
147
+ route = applyRouteOptions(route, routeOptions);
148
+ }
149
+
150
+ return Array.isArray(route) ? [...previous, ...route] : [...previous, route];
151
+ }, []);
152
+ htmlRoutes = applyBaseUrl(baseUrl, htmlRoutes);
153
+ return htmlRoutes;
154
+ };
155
+ /**
156
+ * Collect static public file routes from config/public folder.
157
+ * @param appContext - App context info.
158
+ * @param config - normalized user config.
159
+ * @returns Static public file routes.
160
+ */
161
+
162
+
163
+ const collectStaticRoutes = (appContext, config) => {
164
+ const {
165
+ appDirectory
166
+ } = appContext;
167
+ const {
168
+ source: {
169
+ configDir
170
+ },
171
+ server: {
172
+ publicRoutes = {}
173
+ }
174
+ } = config;
175
+ const publicFolder = path.resolve(appDirectory, configDir, 'public');
176
+ return fs.existsSync(publicFolder) ? walkDirectory(publicFolder).map(filePath => {
177
+ const urlPath = `${urlJoin(toPosix(filePath).slice(toPosix(publicFolder).length))}`;
178
+ return {
179
+ urlPath: publicRoutes[removeLeadingSlash(urlPath)] || urlPath,
180
+ isSPA: true,
181
+ isSSR: false,
182
+ entryPath: toPosix(path.relative(path.resolve(appDirectory, configDir), filePath))
183
+ };
184
+ }) : [];
185
+ };
186
+
187
+ export const getServerRoutes = (entrypoints, {
188
+ appContext,
189
+ config
190
+ }) => [...collectHtmlRoutes(entrypoints, appContext, config), ...collectStaticRoutes(appContext, config)];
191
+
192
+ const toPosix = pathStr => pathStr.split(path.sep).join(path.posix.sep);