@modern-js/app-tools 2.52.0 → 2.53.1-alpha.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/dist/cjs/plugins/deploy/dependencies/index.js +1 -11
- package/dist/cjs/plugins/deploy/platforms/netlify.js +1 -1
- package/dist/cjs/plugins/deploy/platforms/node.js +1 -1
- package/dist/cjs/plugins/deploy/platforms/vercel.js +1 -1
- package/dist/esm/plugins/deploy/dependencies/index.js +4 -14
- package/dist/esm/plugins/deploy/platforms/netlify.js +1 -1
- package/dist/esm/plugins/deploy/platforms/node.js +1 -1
- package/dist/esm/plugins/deploy/platforms/vercel.js +1 -1
- package/dist/esm-node/plugins/deploy/dependencies/index.js +2 -12
- package/dist/esm-node/plugins/deploy/platforms/netlify.js +1 -1
- package/dist/esm-node/plugins/deploy/platforms/node.js +1 -1
- package/dist/esm-node/plugins/deploy/platforms/vercel.js +1 -1
- package/dist/js/modern/analyze/constants.js +15 -0
- package/dist/js/modern/analyze/generateCode.js +179 -0
- package/dist/js/modern/analyze/getBundleEntry.js +75 -0
- package/dist/js/modern/analyze/getClientRoutes.js +219 -0
- package/dist/js/modern/analyze/getFileSystemEntry.js +74 -0
- package/dist/js/modern/analyze/getHtmlTemplate.js +82 -0
- package/dist/js/modern/analyze/getServerRoutes.js +192 -0
- package/dist/js/modern/analyze/index.js +148 -0
- package/dist/js/modern/analyze/isDefaultExportFunction.js +32 -0
- package/dist/js/modern/analyze/makeLegalIdentifier.js +16 -0
- package/dist/js/modern/analyze/templates.js +88 -0
- package/dist/js/modern/analyze/utils.js +92 -0
- package/dist/js/modern/commands/build.js +154 -0
- package/dist/js/modern/commands/deploy.js +5 -0
- package/dist/js/modern/commands/dev.js +95 -0
- package/dist/js/modern/commands/index.js +3 -0
- package/dist/js/modern/commands/inspect.js +69 -0
- package/dist/js/modern/commands/start.js +31 -0
- package/dist/js/modern/exports/server.js +1 -0
- package/dist/js/modern/hooks.js +21 -0
- package/dist/js/modern/index.js +109 -0
- package/dist/js/modern/locale/en.js +35 -0
- package/dist/js/modern/locale/index.js +9 -0
- package/dist/js/modern/locale/zh.js +35 -0
- package/dist/js/modern/utils/config.js +78 -0
- package/dist/js/modern/utils/createCompiler.js +61 -0
- package/dist/js/modern/utils/createServer.js +18 -0
- package/dist/js/modern/utils/getSpecifiedEntries.js +36 -0
- package/dist/js/modern/utils/language.js +5 -0
- package/dist/js/modern/utils/printInstructions.js +11 -0
- package/dist/js/modern/utils/routes.js +15 -0
- package/dist/js/modern/utils/types.js +0 -0
- package/dist/js/node/analyze/constants.js +36 -0
- package/dist/js/node/analyze/generateCode.js +208 -0
- package/dist/js/node/analyze/getBundleEntry.js +89 -0
- package/dist/js/node/analyze/getClientRoutes.js +241 -0
- package/dist/js/node/analyze/getFileSystemEntry.js +90 -0
- package/dist/js/node/analyze/getHtmlTemplate.js +106 -0
- package/dist/js/node/analyze/getServerRoutes.js +208 -0
- package/dist/js/node/analyze/index.js +178 -0
- package/dist/js/node/analyze/isDefaultExportFunction.js +50 -0
- package/dist/js/node/analyze/makeLegalIdentifier.js +24 -0
- package/dist/js/node/analyze/templates.js +106 -0
- package/dist/js/node/analyze/utils.js +113 -0
- package/dist/js/node/commands/build.js +174 -0
- package/dist/js/node/commands/deploy.js +14 -0
- package/dist/js/node/commands/dev.js +120 -0
- package/dist/js/node/commands/index.js +44 -0
- package/dist/js/node/commands/inspect.js +98 -0
- package/dist/js/node/commands/start.js +47 -0
- package/dist/js/node/exports/server.js +13 -0
- package/dist/js/node/hooks.js +39 -0
- package/dist/js/node/index.js +141 -0
- package/dist/js/node/locale/en.js +42 -0
- package/dist/js/node/locale/index.js +20 -0
- package/dist/js/node/locale/zh.js +42 -0
- package/dist/js/node/utils/config.js +103 -0
- package/dist/js/node/utils/createCompiler.js +81 -0
- package/dist/js/node/utils/createServer.js +35 -0
- package/dist/js/node/utils/getSpecifiedEntries.js +46 -0
- package/dist/js/node/utils/language.js +13 -0
- package/dist/js/node/utils/printInstructions.js +22 -0
- package/dist/js/node/utils/routes.js +25 -0
- package/dist/js/node/utils/types.js +0 -0
- package/dist/types/config/initialize/inits.d.ts +1 -1
- package/dist/types/plugins/deploy/dependencies/index.d.ts +1 -1
- package/package.json +17 -17
@@ -36,19 +36,9 @@ var import_utils = require("@modern-js/utils");
|
|
36
36
|
var import_pkg_types = require("pkg-types");
|
37
37
|
var import_mlly = require("mlly");
|
38
38
|
var import_utils2 = require("./utils");
|
39
|
-
const handleDependencies = async (appDir, serverRootDir,
|
39
|
+
const handleDependencies = async (appDir, serverRootDir, includeEntries, entryFilter) => {
|
40
40
|
const base = "/";
|
41
41
|
const entryFiles = await (0, import_utils2.findEntryFiles)(serverRootDir, entryFilter);
|
42
|
-
const includeEntries = include.map((item) => {
|
43
|
-
if ((0, import_node_path.isAbsolute)(item)) {
|
44
|
-
return item;
|
45
|
-
}
|
46
|
-
try {
|
47
|
-
return require.resolve(item);
|
48
|
-
} catch (error) {
|
49
|
-
}
|
50
|
-
return item;
|
51
|
-
});
|
52
42
|
const fileTrace = await (0, import_utils2.traceFiles)(entryFiles.concat(includeEntries), serverRootDir, base);
|
53
43
|
const currentProjectModules = import_node_path.default.join(appDir, "node_modules");
|
54
44
|
const tracedFiles = Object.fromEntries(await Promise.all([
|
@@ -125,7 +125,7 @@ const createNetlifyPreset = (appContext, modernConfig, needModernServer) => {
|
|
125
125
|
return;
|
126
126
|
}
|
127
127
|
await (0, import_dependencies.handleDependencies)(appDirectory, funcsDirectory, [
|
128
|
-
"@modern-js/prod-server"
|
128
|
+
require.resolve("@modern-js/prod-server")
|
129
129
|
]);
|
130
130
|
}
|
131
131
|
};
|
@@ -79,7 +79,7 @@ const createNodePreset = (appContext, config) => {
|
|
79
79
|
return !filePath.startsWith(staticDirectory);
|
80
80
|
};
|
81
81
|
await (0, import_dependencies.handleDependencies)(appDirectory, outputDirectory, [
|
82
|
-
"@modern-js/prod-server"
|
82
|
+
require.resolve("@modern-js/prod-server")
|
83
83
|
], filter);
|
84
84
|
}
|
85
85
|
};
|
@@ -137,7 +137,7 @@ const createVercelPreset = (appContext, modernConfig, needModernServer) => {
|
|
137
137
|
return;
|
138
138
|
}
|
139
139
|
await (0, import_dependencies.handleDependencies)(appDirectory, funcsDirectory, [
|
140
|
-
"@modern-js/prod-server"
|
140
|
+
require.resolve("@modern-js/prod-server")
|
141
141
|
]);
|
142
142
|
}
|
143
143
|
};
|
@@ -3,14 +3,14 @@ import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
|
|
3
3
|
import { _ as _to_consumable_array } from "@swc/helpers/_/_to_consumable_array";
|
4
4
|
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
|
5
5
|
import { _ as _ts_values } from "@swc/helpers/_/_ts_values";
|
6
|
-
import path
|
6
|
+
import path from "node:path";
|
7
7
|
import { fs as fse, pkgUp, semver } from "@modern-js/utils";
|
8
8
|
import { readPackageJSON } from "pkg-types";
|
9
9
|
import { parseNodeModulePath } from "mlly";
|
10
10
|
import { linkPackage, writePackage, isFile, findEntryFiles, traceFiles, findPackageParents, resolveTracedPath } from "./utils";
|
11
11
|
var handleDependencies = function() {
|
12
|
-
var _ref = _async_to_generator(function(appDir, serverRootDir,
|
13
|
-
var base, entryFiles,
|
12
|
+
var _ref = _async_to_generator(function(appDir, serverRootDir, includeEntries, entryFilter) {
|
13
|
+
var base, entryFiles, fileTrace, currentProjectModules, tracedFiles, _, tracedPackages, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, tracedFile, pkgName, tracedPackage, pkgJSON, tracedPackageVersion, err, multiVersionPkgs, singleVersionPackages, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, tracedPackage1, versions, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, version, projectPkgJson, _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _loop, _iterator3, _step3, err, outputPkgPath;
|
14
14
|
return _ts_generator(this, function(_state) {
|
15
15
|
switch (_state.label) {
|
16
16
|
case 0:
|
@@ -21,16 +21,6 @@ var handleDependencies = function() {
|
|
21
21
|
];
|
22
22
|
case 1:
|
23
23
|
entryFiles = _state.sent();
|
24
|
-
includeEntries = include.map(function(item) {
|
25
|
-
if (isAbsolute(item)) {
|
26
|
-
return item;
|
27
|
-
}
|
28
|
-
try {
|
29
|
-
return require.resolve(item);
|
30
|
-
} catch (error) {
|
31
|
-
}
|
32
|
-
return item;
|
33
|
-
});
|
34
24
|
return [
|
35
25
|
4,
|
36
26
|
traceFiles(entryFiles.concat(includeEntries), serverRootDir, base)
|
@@ -571,7 +561,7 @@ var handleDependencies = function() {
|
|
571
561
|
}
|
572
562
|
});
|
573
563
|
});
|
574
|
-
return function handleDependencies2(appDir, serverRootDir,
|
564
|
+
return function handleDependencies2(appDir, serverRootDir, includeEntries, entryFilter) {
|
575
565
|
return _ref.apply(this, arguments);
|
576
566
|
};
|
577
567
|
}();
|
@@ -272,7 +272,7 @@ var createNetlifyPreset = function(appContext, modernConfig, needModernServer) {
|
|
272
272
|
return [
|
273
273
|
4,
|
274
274
|
handleDependencies(appDirectory, funcsDirectory, [
|
275
|
-
"@modern-js/prod-server"
|
275
|
+
require.resolve("@modern-js/prod-server")
|
276
276
|
])
|
277
277
|
];
|
278
278
|
case 3:
|
@@ -206,7 +206,7 @@ var createVercelPreset = function(appContext, modernConfig, needModernServer) {
|
|
206
206
|
return [
|
207
207
|
4,
|
208
208
|
handleDependencies(appDirectory, funcsDirectory, [
|
209
|
-
"@modern-js/prod-server"
|
209
|
+
require.resolve("@modern-js/prod-server")
|
210
210
|
])
|
211
211
|
];
|
212
212
|
case 1:
|
@@ -1,21 +1,11 @@
|
|
1
|
-
import path
|
1
|
+
import path from "node:path";
|
2
2
|
import { fs as fse, pkgUp, semver } from "@modern-js/utils";
|
3
3
|
import { readPackageJSON } from "pkg-types";
|
4
4
|
import { parseNodeModulePath } from "mlly";
|
5
5
|
import { linkPackage, writePackage, isFile, findEntryFiles, traceFiles, findPackageParents, resolveTracedPath } from "./utils";
|
6
|
-
const handleDependencies = async (appDir, serverRootDir,
|
6
|
+
const handleDependencies = async (appDir, serverRootDir, includeEntries, entryFilter) => {
|
7
7
|
const base = "/";
|
8
8
|
const entryFiles = await findEntryFiles(serverRootDir, entryFilter);
|
9
|
-
const includeEntries = include.map((item) => {
|
10
|
-
if (isAbsolute(item)) {
|
11
|
-
return item;
|
12
|
-
}
|
13
|
-
try {
|
14
|
-
return require.resolve(item);
|
15
|
-
} catch (error) {
|
16
|
-
}
|
17
|
-
return item;
|
18
|
-
});
|
19
9
|
const fileTrace = await traceFiles(entryFiles.concat(includeEntries), serverRootDir, base);
|
20
10
|
const currentProjectModules = path.join(appDir, "node_modules");
|
21
11
|
const tracedFiles = Object.fromEntries(await Promise.all([
|
@@ -46,7 +46,7 @@ const createNodePreset = (appContext, config) => {
|
|
46
46
|
return !filePath.startsWith(staticDirectory);
|
47
47
|
};
|
48
48
|
await handleDependencies(appDirectory, outputDirectory, [
|
49
|
-
"@modern-js/prod-server"
|
49
|
+
require.resolve("@modern-js/prod-server")
|
50
50
|
], filter);
|
51
51
|
}
|
52
52
|
};
|
@@ -0,0 +1,15 @@
|
|
1
|
+
export const JS_EXTENSIONS = ['.js', '.ts', '.jsx', '.tsx'];
|
2
|
+
export const INDEX_FILE_NAME = 'index';
|
3
|
+
export const APP_FILE_NAME = 'App';
|
4
|
+
export const PAGES_DIR_NAME = 'pages';
|
5
|
+
export const FILE_SYSTEM_ROUTES_FILE_NAME = 'routes.js';
|
6
|
+
export const ENTRY_POINT_FILE_NAME = 'index.js';
|
7
|
+
export const ENTRY_BOOTSTRAP_FILE_NAME = 'bootstrap.js';
|
8
|
+
export const FILE_SYSTEM_ROUTES_DYNAMIC_REGEXP = /^\[(\S+)\]([*+?]?)$/;
|
9
|
+
export const FILE_SYSTEM_ROUTES_LAYOUT = '_layout';
|
10
|
+
export const FILE_SYSTEM_ROUTES_GLOBAL_LAYOUT = '_app';
|
11
|
+
export const FILE_SYSTEM_ROUTES_INDEX = 'index';
|
12
|
+
export const FILE_SYSTEM_ROUTES_IGNORED_REGEX = /\.(d|test|spec|e2e)\.(js|jsx|ts|tsx)$/;
|
13
|
+
export const HTML_PARTIALS_FOLDER = 'html';
|
14
|
+
export const HTML_PARTIALS_EXTENSIONS = ['.htm', '.html', '.ejs'];
|
15
|
+
export const FILE_SYSTEM_ROUTES_COMPONENTS_DIR = 'internal_components';
|
@@ -0,0 +1,179 @@
|
|
1
|
+
import path from 'path';
|
2
|
+
import { fs } from '@modern-js/utils';
|
3
|
+
import * as templates from "./templates";
|
4
|
+
import { getClientRoutes } from "./getClientRoutes";
|
5
|
+
import { FILE_SYSTEM_ROUTES_FILE_NAME, ENTRY_POINT_FILE_NAME, ENTRY_BOOTSTRAP_FILE_NAME } from "./constants";
|
6
|
+
import { getDefaultImports } from "./utils";
|
7
|
+
|
8
|
+
const createImportSpecifier = specifiers => {
|
9
|
+
let defaults = '';
|
10
|
+
const named = [];
|
11
|
+
|
12
|
+
for (const {
|
13
|
+
local,
|
14
|
+
imported
|
15
|
+
} of specifiers) {
|
16
|
+
if (local && imported) {
|
17
|
+
named.push(`${imported} as ${local}`);
|
18
|
+
} else if (local) {
|
19
|
+
defaults = local;
|
20
|
+
} else {
|
21
|
+
named.push(imported);
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
if (defaults && named.length) {
|
26
|
+
return `${defaults}, { ${named.join(', ')} }`;
|
27
|
+
} else if (defaults) {
|
28
|
+
return defaults;
|
29
|
+
} else {
|
30
|
+
return `{ ${named.join(', ')} }`;
|
31
|
+
}
|
32
|
+
};
|
33
|
+
|
34
|
+
export const createImportStatements = statements => {
|
35
|
+
// merge import statements with the same value.
|
36
|
+
const deDuplicated = [];
|
37
|
+
const seen = new Map();
|
38
|
+
|
39
|
+
for (const {
|
40
|
+
value,
|
41
|
+
specifiers,
|
42
|
+
initialize
|
43
|
+
} of statements) {
|
44
|
+
if (!seen.has(value)) {
|
45
|
+
deDuplicated.push({
|
46
|
+
value,
|
47
|
+
specifiers,
|
48
|
+
initialize
|
49
|
+
});
|
50
|
+
seen.set(value, specifiers);
|
51
|
+
} else {
|
52
|
+
var _deDuplicated$modifyI, _deDuplicated$modifyI2;
|
53
|
+
|
54
|
+
seen.get(value).push(...specifiers); // make "initialize" param can be connected when multiple plugins were imported from same package
|
55
|
+
|
56
|
+
const modifyIndex = deDuplicated.findIndex(v => v.value === value);
|
57
|
+
const originInitialize = (_deDuplicated$modifyI = (_deDuplicated$modifyI2 = deDuplicated[modifyIndex]) === null || _deDuplicated$modifyI2 === void 0 ? void 0 : _deDuplicated$modifyI2.initialize) !== null && _deDuplicated$modifyI !== void 0 ? _deDuplicated$modifyI : '';
|
58
|
+
deDuplicated[modifyIndex].initialize = originInitialize.concat(`\n${initialize || ''}`);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
return deDuplicated.map(({
|
63
|
+
value,
|
64
|
+
specifiers,
|
65
|
+
initialize
|
66
|
+
}) => `import ${createImportSpecifier(specifiers)} from '${value}';\n${initialize || ''}`).join('\n');
|
67
|
+
};
|
68
|
+
export const generateCode = async (appContext, config, entrypoints, api) => {
|
69
|
+
const {
|
70
|
+
internalDirectory,
|
71
|
+
srcDirectory,
|
72
|
+
internalDirAlias,
|
73
|
+
internalSrcAlias
|
74
|
+
} = appContext;
|
75
|
+
const hookRunners = api.useHookRunners();
|
76
|
+
const {
|
77
|
+
output: {
|
78
|
+
mountId
|
79
|
+
}
|
80
|
+
} = config;
|
81
|
+
|
82
|
+
for (const entrypoint of entrypoints) {
|
83
|
+
const {
|
84
|
+
entryName,
|
85
|
+
isAutoMount,
|
86
|
+
customBootstrap,
|
87
|
+
fileSystemRoutes
|
88
|
+
} = entrypoint;
|
89
|
+
|
90
|
+
if (isAutoMount) {
|
91
|
+
// generate routes file for file system routes entrypoint.
|
92
|
+
if (fileSystemRoutes) {
|
93
|
+
const initialRoutes = getClientRoutes({
|
94
|
+
entrypoint,
|
95
|
+
srcDirectory,
|
96
|
+
srcAlias: internalSrcAlias,
|
97
|
+
internalDirectory,
|
98
|
+
internalDirAlias
|
99
|
+
});
|
100
|
+
const {
|
101
|
+
routes
|
102
|
+
} = await hookRunners.modifyFileSystemRoutes({
|
103
|
+
entrypoint,
|
104
|
+
routes: initialRoutes
|
105
|
+
});
|
106
|
+
const {
|
107
|
+
code
|
108
|
+
} = await hookRunners.beforeGenerateRoutes({
|
109
|
+
entrypoint,
|
110
|
+
code: templates.fileSystemRoutes({
|
111
|
+
routes
|
112
|
+
})
|
113
|
+
});
|
114
|
+
fs.outputFileSync(path.resolve(internalDirectory, `./${entryName}/${FILE_SYSTEM_ROUTES_FILE_NAME}`), code, 'utf8');
|
115
|
+
} // call modifyEntryImports hook
|
116
|
+
|
117
|
+
|
118
|
+
const {
|
119
|
+
imports: importStatements
|
120
|
+
} = await hookRunners.modifyEntryImports({
|
121
|
+
entrypoint,
|
122
|
+
imports: getDefaultImports({
|
123
|
+
entrypoint,
|
124
|
+
srcDirectory,
|
125
|
+
internalSrcAlias,
|
126
|
+
internalDirAlias,
|
127
|
+
internalDirectory
|
128
|
+
})
|
129
|
+
}); // call modifyEntryRuntimePlugins hook
|
130
|
+
|
131
|
+
const {
|
132
|
+
plugins
|
133
|
+
} = await hookRunners.modifyEntryRuntimePlugins({
|
134
|
+
entrypoint,
|
135
|
+
plugins: []
|
136
|
+
}); // call modifyEntryRenderFunction hook
|
137
|
+
|
138
|
+
const {
|
139
|
+
code: renderFunction
|
140
|
+
} = await hookRunners.modifyEntryRenderFunction({
|
141
|
+
entrypoint,
|
142
|
+
code: templates.renderFunction({
|
143
|
+
plugins,
|
144
|
+
customBootstrap,
|
145
|
+
fileSystemRoutes
|
146
|
+
})
|
147
|
+
}); // call modifyEntryExport hook
|
148
|
+
|
149
|
+
const {
|
150
|
+
exportStatement
|
151
|
+
} = await hookRunners.modifyEntryExport({
|
152
|
+
entrypoint,
|
153
|
+
exportStatement: 'export default AppWrapper;'
|
154
|
+
});
|
155
|
+
const code = templates.index({
|
156
|
+
mountId: mountId,
|
157
|
+
imports: createImportStatements(importStatements),
|
158
|
+
renderFunction,
|
159
|
+
exportStatement
|
160
|
+
});
|
161
|
+
const entryFile = path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_FILE_NAME}`);
|
162
|
+
entrypoint.entry = entryFile; // generate entry file.
|
163
|
+
|
164
|
+
if (config.source.enableAsyncEntry) {
|
165
|
+
const {
|
166
|
+
code: asyncEntryCode
|
167
|
+
} = await hookRunners.modifyAsyncEntry({
|
168
|
+
entrypoint,
|
169
|
+
code: `import('./${ENTRY_BOOTSTRAP_FILE_NAME}');`
|
170
|
+
});
|
171
|
+
fs.outputFileSync(entryFile, asyncEntryCode, 'utf8');
|
172
|
+
const bootstrapFile = path.resolve(internalDirectory, `./${entryName}/${ENTRY_BOOTSTRAP_FILE_NAME}`);
|
173
|
+
fs.outputFileSync(bootstrapFile, code, 'utf8');
|
174
|
+
} else {
|
175
|
+
fs.outputFileSync(entryFile, code, 'utf8');
|
176
|
+
}
|
177
|
+
}
|
178
|
+
}
|
179
|
+
};
|
@@ -0,0 +1,75 @@
|
|
1
|
+
import path from 'path';
|
2
|
+
import { ensureAbsolutePath, fs, findExists, MAIN_ENTRY_NAME } from '@modern-js/utils';
|
3
|
+
import { getFileSystemEntry } from "./getFileSystemEntry";
|
4
|
+
import { JS_EXTENSIONS } from "./constants";
|
5
|
+
|
6
|
+
const ensureExtensions = file => {
|
7
|
+
if (!path.extname(file)) {
|
8
|
+
return findExists(JS_EXTENSIONS.map(ext => `${file}${ext}`)) || file;
|
9
|
+
}
|
10
|
+
|
11
|
+
return file;
|
12
|
+
};
|
13
|
+
|
14
|
+
const ifAlreadyExists = (entrypoints, checked) => entrypoints.some(entrypoint => {
|
15
|
+
if (ensureExtensions(entrypoint.entry) === ensureExtensions(checked.entry)) {
|
16
|
+
// reset entryName
|
17
|
+
checked.entryName = entrypoint.entryName;
|
18
|
+
return true;
|
19
|
+
} // filesystem routes entrypoint conflict with normal entrypoint.
|
20
|
+
|
21
|
+
|
22
|
+
if (entrypoint.entry.startsWith(checked.entry) || checked.entry.startsWith(entrypoint.entry)) {
|
23
|
+
throw new Error(`Entry configuration conflicts\n Your configuration: ${checked.entry}.\n Default entrypoint: ${entrypoint.entry}\n Please reset source.entries or set source.disableDefaultEntries to disable the default entry rules.`);
|
24
|
+
}
|
25
|
+
|
26
|
+
return false;
|
27
|
+
});
|
28
|
+
|
29
|
+
export const getBundleEntry = (appContext, config) => {
|
30
|
+
const {
|
31
|
+
appDirectory,
|
32
|
+
packageName
|
33
|
+
} = appContext;
|
34
|
+
const {
|
35
|
+
source: {
|
36
|
+
disableDefaultEntries,
|
37
|
+
entries,
|
38
|
+
entriesDir
|
39
|
+
}
|
40
|
+
} = config;
|
41
|
+
const defaults = disableDefaultEntries ? [] : getFileSystemEntry(appContext, config); // merge entrypoints from user config with directory convention.
|
42
|
+
|
43
|
+
if (entries) {
|
44
|
+
Object.keys(entries).forEach(name => {
|
45
|
+
const value = entries[name];
|
46
|
+
const entrypoint = typeof value === 'string' ? {
|
47
|
+
entryName: name,
|
48
|
+
entry: ensureAbsolutePath(appDirectory, value),
|
49
|
+
isAutoMount: true,
|
50
|
+
fileSystemRoutes: fs.statSync(ensureAbsolutePath(appDirectory, value)).isDirectory() ? {} : undefined
|
51
|
+
} : {
|
52
|
+
entryName: name,
|
53
|
+
entry: ensureAbsolutePath(appDirectory, value.entry),
|
54
|
+
isAutoMount: !value.disableMount,
|
55
|
+
fileSystemRoutes: value.enableFileSystemRoutes ? {} : undefined
|
56
|
+
};
|
57
|
+
|
58
|
+
if (!ifAlreadyExists(defaults, entrypoint)) {
|
59
|
+
defaults.push(entrypoint);
|
60
|
+
}
|
61
|
+
});
|
62
|
+
}
|
63
|
+
|
64
|
+
if (!disableDefaultEntries) {
|
65
|
+
// find main entry point which server route is '/'.
|
66
|
+
const entriesDirAbs = ensureAbsolutePath(appDirectory, entriesDir);
|
67
|
+
const found = defaults.find(({
|
68
|
+
entryName,
|
69
|
+
entry
|
70
|
+
}) => entryName === packageName || path.dirname(entry) === entriesDirAbs);
|
71
|
+
found && (found.entryName = MAIN_ENTRY_NAME);
|
72
|
+
}
|
73
|
+
|
74
|
+
return defaults;
|
75
|
+
};
|
@@ -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
|
+
};
|