@modern-js/app-tools 2.50.0 → 2.50.1-alpha.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. package/dist/cjs/analyze/getServerRoutes.js +4 -3
  2. package/dist/cjs/commands/deploy.js +1 -0
  3. package/dist/cjs/hooks.js +1 -0
  4. package/dist/cjs/index.js +3 -1
  5. package/dist/cjs/plugins/deploy/dependencies/index.js +217 -0
  6. package/dist/cjs/plugins/deploy/dependencies/utils.js +165 -0
  7. package/dist/cjs/plugins/deploy/index.js +64 -0
  8. package/dist/cjs/plugins/deploy/platforms/netlify.js +136 -0
  9. package/dist/cjs/plugins/deploy/platforms/netlifyEntry.js +60 -0
  10. package/dist/cjs/plugins/deploy/platforms/node.js +90 -0
  11. package/dist/cjs/plugins/deploy/platforms/nodeEntry.js +44 -0
  12. package/dist/cjs/plugins/deploy/platforms/platform.js +16 -0
  13. package/dist/cjs/plugins/deploy/platforms/vercel.js +148 -0
  14. package/dist/cjs/plugins/deploy/platforms/vercelEntry.js +60 -0
  15. package/dist/cjs/plugins/deploy/utils.js +81 -0
  16. package/dist/cjs/utils/routes.js +7 -2
  17. package/dist/esm/analyze/getServerRoutes.js +5 -4
  18. package/dist/esm/commands/deploy.js +7 -1
  19. package/dist/esm/hooks.js +1 -0
  20. package/dist/esm/index.js +3 -1
  21. package/dist/esm/plugins/deploy/dependencies/index.js +580 -0
  22. package/dist/esm/plugins/deploy/dependencies/utils.js +407 -0
  23. package/dist/esm/plugins/deploy/index.js +135 -0
  24. package/dist/esm/plugins/deploy/platforms/netlify.js +291 -0
  25. package/dist/esm/plugins/deploy/platforms/netlifyEntry.js +202 -0
  26. package/dist/esm/plugins/deploy/platforms/node.js +124 -0
  27. package/dist/esm/plugins/deploy/platforms/nodeEntry.js +107 -0
  28. package/dist/esm/plugins/deploy/platforms/platform.js +0 -0
  29. package/dist/esm/plugins/deploy/platforms/vercel.js +225 -0
  30. package/dist/esm/plugins/deploy/platforms/vercelEntry.js +202 -0
  31. package/dist/esm/plugins/deploy/utils.js +47 -0
  32. package/dist/esm/utils/routes.js +6 -2
  33. package/dist/esm-node/analyze/getServerRoutes.js +5 -4
  34. package/dist/esm-node/commands/deploy.js +1 -0
  35. package/dist/esm-node/hooks.js +1 -0
  36. package/dist/esm-node/index.js +3 -1
  37. package/dist/esm-node/plugins/deploy/dependencies/index.js +183 -0
  38. package/dist/esm-node/plugins/deploy/dependencies/utils.js +124 -0
  39. package/dist/esm-node/plugins/deploy/index.js +44 -0
  40. package/dist/esm-node/plugins/deploy/platforms/netlify.js +102 -0
  41. package/dist/esm-node/plugins/deploy/platforms/netlifyEntry.js +68 -0
  42. package/dist/esm-node/plugins/deploy/platforms/node.js +56 -0
  43. package/dist/esm-node/plugins/deploy/platforms/nodeEntry.js +43 -0
  44. package/dist/esm-node/plugins/deploy/platforms/platform.js +0 -0
  45. package/dist/esm-node/plugins/deploy/platforms/vercel.js +114 -0
  46. package/dist/esm-node/plugins/deploy/platforms/vercelEntry.js +68 -0
  47. package/dist/esm-node/plugins/deploy/utils.js +44 -0
  48. package/dist/esm-node/utils/routes.js +6 -2
  49. package/dist/types/plugins/deploy/dependencies/index.d.ts +1 -0
  50. package/dist/types/plugins/deploy/dependencies/utils.d.ts +31 -0
  51. package/dist/types/plugins/deploy/index.d.ts +4 -0
  52. package/dist/types/plugins/deploy/platforms/netlify.d.ts +2 -0
  53. package/dist/types/plugins/deploy/platforms/netlifyEntry.d.ts +2 -0
  54. package/dist/types/plugins/deploy/platforms/node.d.ts +2 -0
  55. package/dist/types/plugins/deploy/platforms/nodeEntry.d.ts +1 -0
  56. package/dist/types/plugins/deploy/platforms/platform.d.ts +10 -0
  57. package/dist/types/plugins/deploy/platforms/vercel.d.ts +2 -0
  58. package/dist/types/plugins/deploy/platforms/vercelEntry.d.ts +2 -0
  59. package/dist/types/plugins/deploy/utils.d.ts +20 -0
  60. package/dist/types/types/hooks.d.ts +1 -0
  61. package/dist/types/utils/routes.d.ts +3 -3
  62. package/package.json +10 -6
@@ -0,0 +1,183 @@
1
+ import path, { isAbsolute } from "node:path";
2
+ import { fs as fse, pkgUp, semver } from "@modern-js/utils";
3
+ import { readPackageJSON } from "pkg-types";
4
+ import { parseNodeModulePath } from "mlly";
5
+ import { linkPackage, writePackage, isFile, findEntryFiles, traceFiles, findPackageParents, resolveTracedPath } from "./utils";
6
+ const handleDependencies = async (appDir, serverRootDir, include, entryFilter) => {
7
+ const base = "/";
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
+ const fileTrace = await traceFiles(entryFiles.concat(includeEntries), serverRootDir, base);
20
+ const currentProjectModules = path.join(appDir, "node_modules");
21
+ const tracedFiles = Object.fromEntries(await Promise.all([
22
+ ...fileTrace.reasons.entries()
23
+ ].map(async ([_path, reasons]) => {
24
+ if (reasons.ignored) {
25
+ return;
26
+ }
27
+ const filePath = await resolveTracedPath(base, _path);
28
+ if (filePath.startsWith(serverRootDir) || filePath.startsWith(appDir) && !filePath.startsWith(currentProjectModules)) {
29
+ return;
30
+ }
31
+ if (!await isFile(filePath)) {
32
+ return;
33
+ }
34
+ let baseDir;
35
+ let pkgName;
36
+ let subpath;
37
+ let pkgPath;
38
+ if (filePath.includes("node_modules")) {
39
+ const parsed = parseNodeModulePath(filePath);
40
+ baseDir = parsed.dir;
41
+ pkgName = parsed.name;
42
+ subpath = parsed.subpath;
43
+ pkgPath = path.join(baseDir, pkgName);
44
+ } else {
45
+ const MODERN_UTILS_PATH = "packages/toolkit/utils";
46
+ const MODERN_UTILS_PATH_REGEX = new RegExp(`(.*${MODERN_UTILS_PATH})`);
47
+ const match = filePath.match(MODERN_UTILS_PATH_REGEX);
48
+ const packageJsonPath = match ? path.join(match[0], "package.json") : await pkgUp({
49
+ cwd: path.dirname(filePath)
50
+ });
51
+ if (packageJsonPath) {
52
+ const packageJson = await fse.readJSON(packageJsonPath);
53
+ pkgPath = baseDir = path.dirname(packageJsonPath);
54
+ subpath = path.relative(baseDir, filePath);
55
+ pkgName = packageJson.name;
56
+ }
57
+ }
58
+ if (!baseDir) {
59
+ return;
60
+ }
61
+ const parents = await Promise.all([
62
+ ...reasons.parents
63
+ ].map((p) => resolveTracedPath(base, p)));
64
+ const tracedFile = {
65
+ path: filePath,
66
+ parents,
67
+ isDirectDep: parents.some((parent) => {
68
+ return parent.startsWith(appDir) && !parent.startsWith(currentProjectModules);
69
+ }),
70
+ subpath,
71
+ pkgName,
72
+ pkgPath
73
+ };
74
+ return [
75
+ filePath,
76
+ tracedFile
77
+ ];
78
+ })).then((r) => r.filter(Boolean)));
79
+ const tracedPackages = {};
80
+ for (const tracedFile of Object.values(tracedFiles)) {
81
+ const { pkgName } = tracedFile;
82
+ let tracedPackage = tracedPackages[pkgName];
83
+ let pkgJSON = await readPackageJSON(tracedFile.pkgPath, {
84
+ cache: true
85
+ }).catch(() => {
86
+ });
87
+ if (!pkgJSON) {
88
+ pkgJSON = {
89
+ name: pkgName,
90
+ version: "0.0.0"
91
+ };
92
+ }
93
+ if (!tracedPackage) {
94
+ tracedPackage = {
95
+ name: pkgName,
96
+ versions: {}
97
+ };
98
+ tracedPackages[pkgName] = tracedPackage;
99
+ }
100
+ let tracedPackageVersion = tracedPackage.versions[pkgJSON.version];
101
+ if (!tracedPackageVersion) {
102
+ tracedPackageVersion = {
103
+ path: tracedFile.pkgPath,
104
+ files: [],
105
+ isDirectDep: false,
106
+ pkgJSON
107
+ };
108
+ if (tracedFile.isDirectDep) {
109
+ tracedPackageVersion.isDirectDep = tracedFile.isDirectDep;
110
+ }
111
+ tracedPackage.versions[pkgJSON.version] = tracedPackageVersion;
112
+ }
113
+ tracedFile.path.startsWith(tracedFile.pkgPath) && tracedPackageVersion.path === tracedFile.pkgPath && tracedPackageVersion.files.push(tracedFile.path);
114
+ tracedFile.pkgName = pkgName;
115
+ tracedFile.pkgVersion = pkgJSON.version;
116
+ }
117
+ const multiVersionPkgs = {};
118
+ const singleVersionPackages = [];
119
+ for (const tracedPackage of Object.values(tracedPackages)) {
120
+ const versions = Object.keys(tracedPackage.versions);
121
+ if (versions.length === 1) {
122
+ singleVersionPackages.push(tracedPackage.name);
123
+ continue;
124
+ }
125
+ multiVersionPkgs[tracedPackage.name] = {};
126
+ for (const version of versions) {
127
+ multiVersionPkgs[tracedPackage.name][version] = findPackageParents(tracedPackage, version, tracedFiles);
128
+ }
129
+ }
130
+ await Promise.all(singleVersionPackages.map((pkgName) => {
131
+ const pkg = tracedPackages[pkgName];
132
+ const version = Object.keys(pkg.versions)[0];
133
+ return writePackage(pkg, version, serverRootDir);
134
+ }));
135
+ const projectPkgJson = await readPackageJSON(serverRootDir).catch(() => ({}));
136
+ for (const [pkgName, pkgVersions] of Object.entries(multiVersionPkgs)) {
137
+ const versionEntires = Object.entries(pkgVersions).sort(([v1, p1], [v2, p2]) => {
138
+ var _tracedPackages_pkgName_versions_v1, _tracedPackages_pkgName_versions, _tracedPackages_pkgName, _tracedPackages_pkgName_versions_v2, _tracedPackages_pkgName_versions1, _tracedPackages_pkgName1;
139
+ const shouldHoist1 = (_tracedPackages_pkgName = tracedPackages[pkgName]) === null || _tracedPackages_pkgName === void 0 ? void 0 : (_tracedPackages_pkgName_versions = _tracedPackages_pkgName.versions) === null || _tracedPackages_pkgName_versions === void 0 ? void 0 : (_tracedPackages_pkgName_versions_v1 = _tracedPackages_pkgName_versions[v1]) === null || _tracedPackages_pkgName_versions_v1 === void 0 ? void 0 : _tracedPackages_pkgName_versions_v1.isDirectDep;
140
+ const shouldHoist2 = (_tracedPackages_pkgName1 = tracedPackages[pkgName]) === null || _tracedPackages_pkgName1 === void 0 ? void 0 : (_tracedPackages_pkgName_versions1 = _tracedPackages_pkgName1.versions) === null || _tracedPackages_pkgName_versions1 === void 0 ? void 0 : (_tracedPackages_pkgName_versions_v2 = _tracedPackages_pkgName_versions1[v2]) === null || _tracedPackages_pkgName_versions_v2 === void 0 ? void 0 : _tracedPackages_pkgName_versions_v2.isDirectDep;
141
+ if (shouldHoist1 && !shouldHoist2) {
142
+ return -1;
143
+ }
144
+ if (!shouldHoist1 && shouldHoist2) {
145
+ return 1;
146
+ }
147
+ if (p1.length === 0) {
148
+ return -1;
149
+ }
150
+ if (p2.length === 0) {
151
+ return 1;
152
+ }
153
+ return semver.lt(v1, v2, {
154
+ loose: true
155
+ }) ? 1 : -1;
156
+ });
157
+ for (const [version, parentPkgs] of versionEntires) {
158
+ const pkg = tracedPackages[pkgName];
159
+ const pkgDestPath = `.modernjs/${pkgName}@${version}/node_modules/${pkgName}`;
160
+ await writePackage(pkg, version, serverRootDir, pkgDestPath);
161
+ await linkPackage(pkgDestPath, `${pkgName}`, serverRootDir);
162
+ for (const parentPkg of parentPkgs) {
163
+ const parentPkgName = parentPkg.replace(/@[^@]+$/, "");
164
+ await (multiVersionPkgs[parentPkgName] ? linkPackage(pkgDestPath, `.modernjs/${parentPkg}/node_modules/${pkgName}`, serverRootDir) : linkPackage(pkgDestPath, `${parentPkgName}/node_modules/${pkgName}`, serverRootDir));
165
+ }
166
+ }
167
+ }
168
+ const outputPkgPath = path.join(serverRootDir, "package.json");
169
+ await fse.writeJSON(outputPkgPath, {
170
+ name: `${projectPkgJson.name || "modernjs-project"}-prod`,
171
+ version: projectPkgJson.version || "0.0.0",
172
+ private: true,
173
+ dependencies: Object.fromEntries([
174
+ ...Object.values(tracedPackages).map((pkg) => [
175
+ pkg.name,
176
+ Object.keys(pkg.versions)[0]
177
+ ])
178
+ ].sort(([a], [b]) => a.localeCompare(b)))
179
+ });
180
+ };
181
+ export {
182
+ handleDependencies
183
+ };
@@ -0,0 +1,124 @@
1
+ import path from "path";
2
+ import os from "node:os";
3
+ import { fs as fse } from "@modern-js/utils";
4
+ import { parseNodeModulePath } from "mlly";
5
+ import { nodeFileTrace, resolve } from "@vercel/nft";
6
+ function applyPublicCondition(pkg) {
7
+ var _pkg_publishConfig;
8
+ if (pkg === null || pkg === void 0 ? void 0 : (_pkg_publishConfig = pkg.publishConfig) === null || _pkg_publishConfig === void 0 ? void 0 : _pkg_publishConfig.exports) {
9
+ var _pkg_publishConfig1;
10
+ pkg.exports = pkg === null || pkg === void 0 ? void 0 : (_pkg_publishConfig1 = pkg.publishConfig) === null || _pkg_publishConfig1 === void 0 ? void 0 : _pkg_publishConfig1.exports;
11
+ }
12
+ }
13
+ const writePackage = async (pkg, version, projectDir, _pkgPath) => {
14
+ const pkgPath = _pkgPath || pkg.name;
15
+ for (const src of pkg.versions[version].files) {
16
+ if (src.includes("node_modules")) {
17
+ const { subpath } = parseNodeModulePath(src);
18
+ const dest = path.join(projectDir, "node_modules", pkgPath, subpath);
19
+ const dirname = path.dirname(dest);
20
+ await fse.ensureDir(dirname);
21
+ await fse.copyFile(src, dest);
22
+ } else {
23
+ const subpath = path.relative(pkg.versions[version].path, src);
24
+ const dest = path.join(projectDir, "node_modules", pkgPath, subpath);
25
+ const dirname = path.dirname(dest);
26
+ await fse.ensureDir(dirname);
27
+ await fse.copyFile(src, dest);
28
+ }
29
+ }
30
+ const { pkgJSON } = pkg.versions[version];
31
+ applyPublicCondition(pkgJSON);
32
+ const packageJsonPath = path.join(projectDir, "node_modules", pkgPath, "package.json");
33
+ await fse.ensureDir(path.dirname(packageJsonPath));
34
+ await fse.writeFile(packageJsonPath, JSON.stringify(pkgJSON, null, 2));
35
+ };
36
+ const isWindows = os.platform() === "win32";
37
+ const linkPackage = async (from, to, projectRootDir) => {
38
+ const src = path.join(projectRootDir, "node_modules", from);
39
+ const dest = path.join(projectRootDir, "node_modules", to);
40
+ const dstStat = await fse.lstat(dest).catch(() => null);
41
+ const exists = dstStat === null || dstStat === void 0 ? void 0 : dstStat.isSymbolicLink();
42
+ if (exists) {
43
+ return;
44
+ }
45
+ await fse.mkdir(path.dirname(dest), {
46
+ recursive: true
47
+ });
48
+ await fse.symlink(path.relative(path.dirname(dest), src), dest, isWindows ? "junction" : "dir").catch((error) => {
49
+ console.error("Cannot link", from, "to", to, error);
50
+ });
51
+ };
52
+ const readDirRecursive = async (dir, options = {}) => {
53
+ const { filter } = options;
54
+ const files = await fse.readdir(dir, {
55
+ withFileTypes: true
56
+ });
57
+ const filesAndDirs = await Promise.all(files.map(async (file) => {
58
+ const resolvedPath = path.resolve(dir, file.name);
59
+ if (file.isDirectory()) {
60
+ return readDirRecursive(resolvedPath, options);
61
+ } else {
62
+ return filter && !filter(resolvedPath) ? [] : resolvedPath;
63
+ }
64
+ }));
65
+ return filesAndDirs.flat();
66
+ };
67
+ const isFile = async (file) => {
68
+ try {
69
+ const stat = await fse.stat(file);
70
+ return stat.isFile();
71
+ } catch (error) {
72
+ if (error.code === "ENOENT") {
73
+ return false;
74
+ }
75
+ throw error;
76
+ }
77
+ };
78
+ const findEntryFiles = async (rootDir, entryFilter) => {
79
+ const files = await readDirRecursive(rootDir, {
80
+ filter: entryFilter
81
+ });
82
+ return files.filter((file) => file.endsWith(".mjs") || file.endsWith(".cjs") || file.endsWith(".js"));
83
+ };
84
+ const findPackageParents = (pkg, version, tracedFiles) => {
85
+ const versionFiles = pkg.versions[version].files.map((path2) => tracedFiles[path2]);
86
+ const parentPkgs = [
87
+ ...new Set(versionFiles.flatMap((file) => file.parents.map((parentPath) => {
88
+ const parentFile = tracedFiles[parentPath];
89
+ if (!parentFile || parentFile.pkgName === pkg.name) {
90
+ return null;
91
+ }
92
+ return `${parentFile.pkgName}@${parentFile.pkgVersion}`;
93
+ }).filter(Boolean)))
94
+ ];
95
+ return parentPkgs;
96
+ };
97
+ const traceFiles = async (entryFiles, serverRootDir, base = "/") => {
98
+ return await nodeFileTrace(entryFiles, {
99
+ base,
100
+ processCwd: serverRootDir,
101
+ resolve: async (id, parent, job, isCjs) => {
102
+ if (id.startsWith("@modern-js/prod-server")) {
103
+ return require.resolve(id, {
104
+ paths: [
105
+ require.resolve("@modern-js/app-tools")
106
+ ]
107
+ });
108
+ } else {
109
+ return resolve(id, parent, job, isCjs);
110
+ }
111
+ }
112
+ });
113
+ };
114
+ const resolveTracedPath = async (base, p) => fse.realpath(path.resolve(base, p));
115
+ export {
116
+ findEntryFiles,
117
+ findPackageParents,
118
+ isFile,
119
+ linkPackage,
120
+ readDirRecursive,
121
+ resolveTracedPath,
122
+ traceFiles,
123
+ writePackage
124
+ };
@@ -0,0 +1,44 @@
1
+ import { provider } from "std-env";
2
+ import { getProjectUsage } from "./utils";
3
+ import { createNodePreset } from "./platforms/node";
4
+ import { createVercelPreset } from "./platforms/vercel";
5
+ import { createNetlifyPreset } from "./platforms/netlify";
6
+ const deployPresets = {
7
+ node: createNodePreset,
8
+ vercel: createVercelPreset,
9
+ netlify: createNetlifyPreset
10
+ };
11
+ async function getDeployPreset(appContext, modernConfig, deployTarget) {
12
+ const { appDirectory, distDirectory } = appContext;
13
+ const { useSSR, useAPI, useWebServer } = getProjectUsage(appDirectory, distDirectory);
14
+ const needModernServer = useSSR || useAPI || useWebServer;
15
+ const createPreset = deployPresets[deployTarget];
16
+ if (!createPreset) {
17
+ throw new Error(`Unknown deploy target: '${deployTarget}'. MODERNJS_DEPLOY should be 'node', 'vercel', or 'netlify'.`);
18
+ }
19
+ return createPreset(appContext, modernConfig, needModernServer);
20
+ }
21
+ var deploy_default = () => ({
22
+ name: "@modern-js/plugin-deploy",
23
+ setup: (api) => {
24
+ const deployTarget = process.env.MODERNJS_DEPLOY || provider || "node";
25
+ return {
26
+ async deploy() {
27
+ const appContext = api.useAppContext();
28
+ const { metaName } = appContext;
29
+ if (metaName !== "modern-js" && !process.env.MODERNJS_DEPLOY) {
30
+ return;
31
+ }
32
+ const modernConfig = api.useResolvedConfigContext();
33
+ const deployPreset = await getDeployPreset(appContext, modernConfig, deployTarget);
34
+ (deployPreset === null || deployPreset === void 0 ? void 0 : deployPreset.prepare) && await (deployPreset === null || deployPreset === void 0 ? void 0 : deployPreset.prepare());
35
+ (deployPreset === null || deployPreset === void 0 ? void 0 : deployPreset.writeOutput) && await (deployPreset === null || deployPreset === void 0 ? void 0 : deployPreset.writeOutput());
36
+ (deployPreset === null || deployPreset === void 0 ? void 0 : deployPreset.genEntry) && await (deployPreset === null || deployPreset === void 0 ? void 0 : deployPreset.genEntry());
37
+ (deployPreset === null || deployPreset === void 0 ? void 0 : deployPreset.end) && await (deployPreset === null || deployPreset === void 0 ? void 0 : deployPreset.end());
38
+ }
39
+ };
40
+ }
41
+ });
42
+ export {
43
+ deploy_default as default
44
+ };
@@ -0,0 +1,102 @@
1
+ import path from "node:path";
2
+ import { ROUTE_SPEC_FILE, DEFAULT_SERVER_CONFIG, fs as fse, getInternalPlugins } from "@modern-js/utils";
3
+ import { isMainEntry } from "../../../utils/routes";
4
+ import { genPluginImportsCode, serverAppContenxtTemplate } from "../utils";
5
+ import { handleDependencies } from "../dependencies";
6
+ async function cleanDistDirectory(dir) {
7
+ try {
8
+ const items = await fse.readdir(dir);
9
+ for (const item of items) {
10
+ const fullPath = path.join(dir, item);
11
+ if (item !== "static" && item !== "_redirects") {
12
+ await fse.remove(fullPath);
13
+ }
14
+ }
15
+ } catch (error) {
16
+ console.error("Error cleaning directory:", error);
17
+ }
18
+ }
19
+ const createNetlifyPreset = (appContext, modernConfig, needModernServer) => {
20
+ const { appDirectory, distDirectory, serverInternalPlugins, entrypoints } = appContext;
21
+ const plugins = getInternalPlugins(appDirectory, serverInternalPlugins);
22
+ const netlifyOutput = path.join(appDirectory, ".netlify");
23
+ const funcsDirectory = path.join(netlifyOutput, "functions");
24
+ const entryFilePath = path.join(funcsDirectory, "index.js");
25
+ return {
26
+ async prepare() {
27
+ await fse.remove(netlifyOutput);
28
+ },
29
+ async writeOutput() {
30
+ const routes = [];
31
+ const { source: { mainEntryName } } = modernConfig;
32
+ if (!needModernServer) {
33
+ entrypoints.forEach((entry) => {
34
+ const isMain = isMainEntry(entry.entryName, mainEntryName);
35
+ routes.push({
36
+ src: `/${isMain ? "" : `${entry.entryName}/`}*`,
37
+ dest: `/html/${entry.entryName}/index.html`,
38
+ status: 200
39
+ });
40
+ });
41
+ } else {
42
+ routes.push({
43
+ src: "/*",
44
+ dest: `/.netlify/functions/index`,
45
+ status: 200
46
+ });
47
+ }
48
+ const redirectContent = routes.map((route) => {
49
+ return `${route.src} ${route.dest} ${route.status}`;
50
+ }).join("\n");
51
+ if (needModernServer) {
52
+ await fse.ensureDir(funcsDirectory);
53
+ await fse.copy(distDirectory, funcsDirectory, {
54
+ filter: (src) => {
55
+ const distStaticDirectory = path.join(distDirectory, `static`);
56
+ return !src.includes(distStaticDirectory);
57
+ }
58
+ });
59
+ }
60
+ const redirectFilePath = path.join(distDirectory, "_redirects");
61
+ await fse.writeFile(redirectFilePath, redirectContent);
62
+ },
63
+ async genEntry() {
64
+ var _modernConfig_bff;
65
+ if (!needModernServer) {
66
+ return;
67
+ }
68
+ const serverConfig = {
69
+ bff: {
70
+ prefix: modernConfig === null || modernConfig === void 0 ? void 0 : (_modernConfig_bff = modernConfig.bff) === null || _modernConfig_bff === void 0 ? void 0 : _modernConfig_bff.prefix
71
+ },
72
+ output: {
73
+ path: "."
74
+ }
75
+ };
76
+ const pluginImportCode = genPluginImportsCode(plugins || []);
77
+ const dynamicProdOptions = {
78
+ config: serverConfig,
79
+ serverConfigFile: DEFAULT_SERVER_CONFIG,
80
+ plugins
81
+ };
82
+ let entryCode = (await fse.readFile(path.join(__dirname, "./netlifyEntry.js"))).toString();
83
+ const serverAppContext = serverAppContenxtTemplate(appContext);
84
+ entryCode = entryCode.replace("p_genPluginImportsCode", pluginImportCode).replace("p_ROUTE_SPEC_FILE", `"${ROUTE_SPEC_FILE}"`).replace("p_dynamicProdOptions", JSON.stringify(dynamicProdOptions)).replace("p_sharedDirectory", serverAppContext.sharedDirectory).replace("p_apiDirectory", serverAppContext.apiDirectory).replace("p_lambdaDirectory", serverAppContext.lambdaDirectory);
85
+ await fse.writeFile(entryFilePath, entryCode);
86
+ },
87
+ async end() {
88
+ if (process.env.NODE_ENV !== "test" && process.env.NODE_ENV !== "development") {
89
+ await cleanDistDirectory(distDirectory);
90
+ }
91
+ if (!needModernServer) {
92
+ return;
93
+ }
94
+ await handleDependencies(appDirectory, funcsDirectory, [
95
+ "@modern-js/prod-server"
96
+ ]);
97
+ }
98
+ };
99
+ };
100
+ export {
101
+ createNetlifyPreset
102
+ };
@@ -0,0 +1,68 @@
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __commonJS = (cb, mod) => function __require() {
3
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
4
+ };
5
+ var require_netlifyEntry = __commonJS({
6
+ "src/plugins/deploy/platforms/netlifyEntry.js"(exports, module) {
7
+ const fs = require("node:fs/promises");
8
+ const path = require("node:path");
9
+ const { createNetlifyFunction } = require("@modern-js/prod-server/netlify");
10
+ p_genPluginImportsCode;
11
+ if (!process.env.NODE_ENV) {
12
+ process.env.NODE_ENV = "production";
13
+ }
14
+ let requestHandler = null;
15
+ let handlerCreationPromise = null;
16
+ async function loadRoutes(routeFilepath) {
17
+ try {
18
+ await fs.access(routeFilepath);
19
+ const content = await fs.readFile(routeFilepath, "utf-8");
20
+ const routeSpec = JSON.parse(content);
21
+ return routeSpec.routes || [];
22
+ } catch (error) {
23
+ console.warn("route.json not found or invalid, continuing with empty routes.");
24
+ return [];
25
+ }
26
+ }
27
+ async function initServer() {
28
+ const routeFilepath = path.join(__dirname, p_ROUTE_SPEC_FILE);
29
+ const routes = await loadRoutes(routeFilepath);
30
+ const dynamicProdOptions = p_dynamicProdOptions;
31
+ const prodServerOptions = {
32
+ pwd: __dirname,
33
+ routes,
34
+ disableCustomHook: true,
35
+ appContext: {
36
+ sharedDirectory: p_sharedDirectory,
37
+ apiDirectory: p_apiDirectory,
38
+ lambdaDirectory: p_lambdaDirectory
39
+ },
40
+ ...dynamicProdOptions
41
+ };
42
+ const requestHandler2 = await createNetlifyFunction(prodServerOptions);
43
+ return requestHandler2;
44
+ }
45
+ async function createHandler() {
46
+ if (!handlerCreationPromise) {
47
+ handlerCreationPromise = (async () => {
48
+ try {
49
+ requestHandler = await initServer();
50
+ } catch (error) {
51
+ console.error("Error creating server:", error);
52
+ process.exit(1);
53
+ }
54
+ })();
55
+ }
56
+ await handlerCreationPromise;
57
+ return requestHandler;
58
+ }
59
+ createHandler();
60
+ module.exports.default = async (request, context) => {
61
+ if (!requestHandler) {
62
+ await createHandler();
63
+ }
64
+ return requestHandler(request, context);
65
+ };
66
+ }
67
+ });
68
+ export default require_netlifyEntry();
@@ -0,0 +1,56 @@
1
+ import path from "node:path";
2
+ import { ROUTE_SPEC_FILE, DEFAULT_SERVER_CONFIG, fs as fse, getInternalPlugins, chalk } from "@modern-js/utils";
3
+ import { genPluginImportsCode, serverAppContenxtTemplate } from "../utils";
4
+ import { handleDependencies } from "../dependencies";
5
+ const createNodePreset = (appContext, config) => {
6
+ const { appDirectory, distDirectory, serverInternalPlugins } = appContext;
7
+ const plugins = getInternalPlugins(appDirectory, serverInternalPlugins);
8
+ const outputDirectory = path.join(appDirectory, ".output");
9
+ const staticDirectory = path.join(outputDirectory, "static");
10
+ const entryFilePath = path.join(outputDirectory, "index.js");
11
+ return {
12
+ async prepare() {
13
+ await fse.remove(outputDirectory);
14
+ },
15
+ async writeOutput() {
16
+ await fse.copy(distDirectory, outputDirectory);
17
+ },
18
+ async genEntry() {
19
+ var _config_bff;
20
+ const serverConfig = {
21
+ server: {
22
+ port: 8080
23
+ },
24
+ bff: {
25
+ prefix: config === null || config === void 0 ? void 0 : (_config_bff = config.bff) === null || _config_bff === void 0 ? void 0 : _config_bff.prefix
26
+ },
27
+ output: {
28
+ path: "."
29
+ }
30
+ };
31
+ const pluginImportCode = genPluginImportsCode(plugins || []);
32
+ const dynamicProdOptions = {
33
+ config: serverConfig,
34
+ serverConfigFile: DEFAULT_SERVER_CONFIG,
35
+ plugins
36
+ };
37
+ let entryCode = (await fse.readFile(path.join(__dirname, "./nodeEntry.js"))).toString();
38
+ const serverAppContext = serverAppContenxtTemplate(appContext);
39
+ entryCode = entryCode.replace("p_genPluginImportsCode", pluginImportCode).replace("p_ROUTE_SPEC_FILE", `"${ROUTE_SPEC_FILE}"`).replace("p_dynamicProdOptions", JSON.stringify(dynamicProdOptions)).replace("p_sharedDirectory", serverAppContext.sharedDirectory).replace("p_apiDirectory", serverAppContext.apiDirectory).replace("p_lambdaDirectory", serverAppContext.lambdaDirectory);
40
+ await fse.writeFile(entryFilePath, entryCode);
41
+ },
42
+ async end() {
43
+ console.log("Static directory:", chalk.blue(path.relative(appDirectory, staticDirectory)));
44
+ console.log(`You can preview this build by`, chalk.blue(`node .output/index`));
45
+ const filter = (filePath) => {
46
+ return !filePath.startsWith(staticDirectory);
47
+ };
48
+ await handleDependencies(appDirectory, outputDirectory, [
49
+ "@modern-js/prod-server"
50
+ ], filter);
51
+ }
52
+ };
53
+ };
54
+ export {
55
+ createNodePreset
56
+ };
@@ -0,0 +1,43 @@
1
+ const fs = require("node:fs/promises");
2
+ const path = require("node:path");
3
+ const { createProdServer } = require("@modern-js/prod-server");
4
+ p_genPluginImportsCode;
5
+ if (!process.env.NODE_ENV) {
6
+ process.env.NODE_ENV = "production";
7
+ }
8
+ async function loadRoutes(routeFilepath) {
9
+ try {
10
+ await fs.access(routeFilepath);
11
+ const content = await fs.readFile(routeFilepath, "utf-8");
12
+ const routeSpec = JSON.parse(content);
13
+ return routeSpec.routes || [];
14
+ } catch (error) {
15
+ console.warn("route.json not found or invalid, continuing with empty routes.");
16
+ return [];
17
+ }
18
+ }
19
+ async function main() {
20
+ const routeFilepath = path.join(__dirname, p_ROUTE_SPEC_FILE);
21
+ const routes = await loadRoutes(routeFilepath);
22
+ const dynamicProdOptions = p_dynamicProdOptions;
23
+ const prodServerOptions = {
24
+ pwd: __dirname,
25
+ routes,
26
+ disableCustomHook: true,
27
+ appContext: {
28
+ sharedDirectory: p_sharedDirectory,
29
+ apiDirectory: p_apiDirectory,
30
+ lambdaDirectory: p_lambdaDirectory
31
+ },
32
+ ...dynamicProdOptions
33
+ };
34
+ const app = await createProdServer(prodServerOptions);
35
+ const port = process.env.PORT || 8080;
36
+ app.listen({
37
+ host: "::",
38
+ port
39
+ }, () => {
40
+ console.log(`\x1B[32mServer is listening on http://[::]:${port}`, "\x1B[0m");
41
+ });
42
+ }
43
+ main();