oak-docker-tools/dist/cli.js

717 lines
24 KiB
JavaScript

#!/usr/bin/env node
// src/cli.ts
import { execSync } from "child_process";
import fs3 from "fs";
import path3 from "path";
import { parseArgs } from "util";
// src/template/runtime.ts
import fs from "fs";
import path from "path";
function generateDockerfile(pwd2, projectName, options, allProjects, projectPackageMap) {
const { extra, env, registry, port, nodeVersion } = options;
console.log("\n-> \u68C0\u67E5\u9879\u76EE\u4F9D\u8D56\u5173\u7CFB...");
const dependencyGraph = {};
for (const project of allProjects) {
dependencyGraph[project] = /* @__PURE__ */ new Set();
}
for (const project of allProjects) {
console.log(`\u68C0\u67E5\u9879\u76EE: ${project}`);
const packageJsonPath = path.join(pwd2, project, "package.json");
if (!fs.existsSync(packageJsonPath)) {
console.error(`\u627E\u4E0D\u5230\u9879\u76EE\u7684 package.json: ${packageJsonPath}`);
continue;
}
const packageJson = projectPackageMap[project];
const dependencies = packageJson.dependencies || {};
for (const dep in dependencies) {
if (dependencies[dep].startsWith("file:")) {
const depProjectPath = dependencies[dep].replace("file:", "");
const targetPath = path.join(pwd2, project, depProjectPath);
const depProject = path.basename(targetPath);
console.log(` \u53D1\u73B0\u672C\u5730\u4F9D\u8D56: ${depProject} (\u6765\u81EA ${project})`);
if (!allProjects.includes(depProject)) {
console.error(`\u672A\u5305\u542B\u7684\u4F9D\u8D56\u9879\u76EE: ${depProject}\uFF0C\u8BF7\u901A\u8FC7 --extra \u53C2\u6570\u6DFB\u52A0`);
process.exit(1);
}
dependencyGraph[project].add(depProject);
}
}
}
function topoSort(graph) {
const inDegree = {};
const result = [];
for (const p in graph)
inDegree[p] = 0;
for (const p in graph) {
for (const dep of graph[p]) {
inDegree[dep] = (inDegree[dep] || 0) + 1;
}
}
const queue = Object.keys(inDegree).filter((p) => inDegree[p] === 0);
while (queue.length > 0) {
const current = queue.shift();
result.push(current);
for (const dep of graph[current]) {
inDegree[dep]--;
if (inDegree[dep] === 0)
queue.push(dep);
}
}
if (result.length !== Object.keys(graph).length) {
console.error("\u68C0\u6D4B\u5230\u5FAA\u73AF\u4F9D\u8D56\uFF0C\u8BF7\u68C0\u67E5\u9879\u76EE\u95F4\u7684 file: \u5F15\u7528");
process.exit(1);
}
return result;
}
const sortedProjects = topoSort(dependencyGraph).reverse();
console.log("\n\u6784\u5EFA\u987A\u5E8F\u5982\u4E0B\uFF1A");
sortedProjects.forEach((p, i) => console.log(` ${i + 1}. ${p}`));
const mainIndex = sortedProjects.indexOf(projectName);
if (mainIndex !== -1 && mainIndex !== sortedProjects.length - 1) {
sortedProjects.splice(mainIndex, 1);
sortedProjects.push(projectName);
}
let dockerfile = `# ===========================
# Stage 1: Build
# ===========================
FROM node:${nodeVersion}-alpine AS builder
WORKDIR /app
# \u8BBE\u7F6E\u955C\u50CF\u7AD9
RUN npm config set registry ${registry}
`;
for (const project of sortedProjects) {
dockerfile += `# \u590D\u5236 ${project}
`;
dockerfile += `COPY ./${project} ./${project}
`;
}
dockerfile += `
# ===========================
# \u6784\u5EFA\u6240\u6709\u9879\u76EE
# ===========================
`;
for (const project of sortedProjects) {
dockerfile += `
# \u6784\u5EFA ${project}
WORKDIR /app/${project}
RUN npm install
`;
const pkjson = projectPackageMap[project];
if (project === projectName) {
if (pkjson.scripts?.["make:domain"])
dockerfile += `RUN npm run make:domain
`;
if (pkjson.scripts?.["build"])
dockerfile += `RUN npm run build
`;
if (pkjson.scripts?.["confuse"])
dockerfile += `RUN npm run confuse
`;
} else {
dockerfile += `RUN npm run build || true
`;
}
}
dockerfile += `
# ===========================
# \u6E05\u7406\u6784\u5EFA\u4EA7\u7269
# ===========================
`;
for (const project of sortedProjects) {
dockerfile += `
# \u6E05\u7406 ${project}
WORKDIR /app/${project}
RUN rm -rf src && rm -rf web && rm -rf wechatMp && rm -rf native && rm -rf */**/*.d.ts \\
&& rm -rf */**.ts && rm -rf .git && rm -rf .gitignore && rm -rf .husky && rm -rf configurations && rm -rf upgrade \\
&& find node_modules -type d -name "test" -o -name "__tests__" -exec rm -rf {} + \\
&& find node_modules -type f \\( -name "*.ts" -o -name "*.d.ts" \\) -delete \\
&& find node_modules -type f \\( -name "*.map" \\) -delete \\
&& find node_modules -type f -name "LICENSE" -o -name "LICENSE.txt" -delete \\
&& find node_modules -type f -name "*.md" -o -name "*.markdown" -o -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" -o -name "*.gif" -delete
`;
}
dockerfile += `
# ===========================
# Stage 2: Runtime
# ===========================
FROM node:${nodeVersion}-alpine
WORKDIR /app
COPY --from=builder /app ./
WORKDIR /app/${projectName}
RUN npm install -g @socket.io/pm2
`;
for (const project of sortedProjects) {
dockerfile += `
# \u6E05\u7406 ${project} \u8FD0\u884C\u65F6\u4E0D\u9700\u8981\u7684\u6587\u4EF6
WORKDIR /app/${project}
RUN rm -rf src \\
&& find node_modules -type d -name "test" -o -name "__tests__" -exec rm -rf {} + \\
&& find node_modules -type f \\( -name "*.ts" -o -name "*.d.ts" -o -name "*.map" \\) -delete \\
&& find . -type f -name "*.test.js" -delete
`;
}
dockerfile += `
WORKDIR /app/${projectName}
EXPOSE ${port.join(" ")}
CMD ["pm2-runtime", "start", "pm2.${env}.json"]
`;
return dockerfile;
}
function generateDockerignore() {
return `# Node modules
node_modules
npm-debug.log
# \u6D4B\u8BD5\u548C\u6587\u6863
test
tests
__tests__
*.test.js
*.spec.js
docs
coverage
# \u5F00\u53D1\u6587\u4EF6
.git
.gitignore
.env
.env.*
*.md
.vscode
.idea
# \u6784\u5EFA\u4EA7\u7269\uFF08\u5728\u5BB9\u5668\u5185\u6784\u5EFA\uFF09
dist
build
# \u4E34\u65F6\u6587\u4EF6
*.log
*.tmp
.DS_Store
`;
}
// src/template/init.ts
import fs2 from "fs";
import path2 from "path";
function generateInitDockerfile(pwd2, projectName, options) {
const { extra, env, registry, port, nodeVersion } = options;
const allProjects = [projectName];
allProjects.push(...extra);
console.log("\n\u{1F50D} \u68C0\u67E5\u9879\u76EE\u4F9D\u8D56\u5173\u7CFB...");
const projectPackageMap = {};
for (const project of allProjects) {
console.log(`\u68C0\u67E5\u9879\u76EE: ${project}`);
const packageJsonPath = path2.join(pwd2, project, "package.json");
if (fs2.existsSync(packageJsonPath)) {
const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf-8"));
projectPackageMap[project] = packageJson;
const dependencies = packageJson.dependencies || {};
for (const dep in dependencies) {
if (dependencies[dep].startsWith("file:")) {
const depProjectPath = dependencies[dep].replace("file:", "");
const targetPath = path2.join(pwd2, project, depProjectPath);
const depProject = path2.basename(targetPath);
console.log(` \u53D1\u73B0\u672C\u5730\u4F9D\u8D56: ${depProject} (\u6765\u81EA ${project})`);
if (!allProjects.includes(depProject)) {
console.error(`\u274C \u53D1\u73B0\u672A\u5305\u542B\u7684\u4F9D\u8D56\u9879\u76EE: ${depProject}\uFF0C\u8BF7\u5728\u547D\u4EE4\u884C\u4E2D\u901A\u8FC7 --extra \u53C2\u6570\u6DFB\u52A0`);
process.exit(1);
}
}
}
} else {
console.error(`\u274C \u627E\u4E0D\u5230\u9879\u76EE\u7684 package.json: ${packageJsonPath}`);
}
}
let dockerfile = `# ===========================
# Stage 1: Build
# ===========================
FROM node:${nodeVersion}-alpine AS builder
WORKDIR /app
# \u8BBE\u7F6E\u955C\u50CF\u7AD9
RUN npm config set registry ${registry}
`;
for (const project of allProjects) {
dockerfile += `# \u590D\u5236 ${project}
`;
dockerfile += `COPY ./${project} ./${project}
`;
}
dockerfile += `
# ===========================
# \u6784\u5EFA\u6240\u6709\u9879\u76EE
# ===========================
`;
for (const project of allProjects) {
dockerfile += `
# \u6784\u5EFA ${project}
WORKDIR /app/${project}
RUN npm install
`;
if (project === projectName) {
const pkjson = projectPackageMap[project];
if (pkjson.scripts && pkjson.scripts["make:domain"]) {
dockerfile += `RUN npm run make:domain
`;
}
if (pkjson.scripts && pkjson.scripts["build"]) {
dockerfile += `RUN npm run build
`;
}
if (pkjson.scripts && pkjson.scripts["confuse"]) {
dockerfile += `RUN npm run confuse
`;
}
} else {
dockerfile += `RUN npm run build || true
`;
}
}
dockerfile += `
# ===========================
# \u6E05\u7406\u6784\u5EFA\u4EA7\u7269
# ===========================
`;
for (const project of allProjects) {
dockerfile += `
# \u6E05\u7406 ${project}
WORKDIR /app/${project}
RUN rm -rf src && rm -rf web && rm -rf wechatMp && rm -rf native && rm -rf */**/*.d.ts \\
&& rm -rf */**.ts && rm -rf .git && rm -rf .gitignore && rm -rf .husky && rm -rf configurations && rm -rf upgrade \\
&& find node_modules -type d -name "test" -o -name "__tests__" -exec rm -rf {} + \\
&& find node_modules -type f \\( -name "*.ts" -o -name "*.d.ts" \\) -delete \\
&& find node_modules -type f \\( -name "*.map" \\) -delete \\
&& find node_modules -type f -name "LICENSE" -o -name "LICENSE.txt" -delete \\
&& find node_modules -type f -name "*.md" -o -name "*.markdown" -o -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" -o -name "*.gif" -delete
`;
}
dockerfile += `
# ===========================
# Stage 2: Runtime
# ===========================
FROM node:${nodeVersion}-alpine
WORKDIR /app
# \u4ECE\u6784\u5EFA\u9636\u6BB5\u590D\u5236\u6240\u6709\u5185\u5BB9
COPY --from=builder /app ./
WORKDIR /app/${projectName}
# \u518D\u6B21\u6E05\u7406\uFF08\u786E\u4FDD\u8FD0\u884C\u65F6\u955C\u50CF\u6700\u5C0F\u5316\uFF09
`;
for (const project of allProjects) {
dockerfile += `
# \u6E05\u7406 ${project} \u8FD0\u884C\u65F6\u4E0D\u9700\u8981\u7684\u6587\u4EF6
WORKDIR /app/${project}
RUN rm -rf src \\
&& find node_modules -type d -name "test" -o -name "__tests__" -exec rm -rf {} + \\
&& find node_modules -type f \\( -name "*.ts" -o -name "*.d.ts" -o -name "*.map" \\) -delete \\
&& find . -type f -name "*.test.js" -delete
`;
}
for (const project of allProjects) {
dockerfile += `
# \u6E05\u7406 ${project} \u8FD0\u884C\u65F6\u4E0D\u9700\u8981\u7684\u6587\u4EF6\u5939\u548C\u6587\u4EF6
WORKDIR /app/${project}
RUN set -eux; \\
echo "Cleaning ${project} ..."; \\
# \u5220\u9664\u4E00\u7EA7\u76EE\u5F55\uFF08\u4FDD\u7559 lib\u3001data\u3001node_modules\u3001scripts\u3001configuration\uFF09
find . -mindepth 1 -maxdepth 1 -type d ! -name "lib" ! -name "data" ! -name "node_modules" ! -name "scripts" ! -name "configuration" -exec rm -rf {} +; \\
# \u5220\u9664\u4E00\u7EA7\u6587\u4EF6\uFF08\u4FDD\u7559 package.json\uFF09
find . -mindepth 1 -maxdepth 1 -type f ! -name "package.json" -exec rm -f {} +; \\
# \u6E05\u7406 lib \u4E0B\u591A\u4F59\u76EE\u5F55\uFF08\u4FDD\u7559 oak-app-domain\u3001routines\u3001data\u3001context\u3001config\u3001configuration\u3001 utils\u3001types\uFF09
if [ -d "lib" ]; then \\
echo "pass"; \\
fi
`;
}
dockerfile += `
# \u5207\u6362\u56DE\u4E3B\u9879\u76EE\u76EE\u5F55
WORKDIR /app/${projectName}
`;
return dockerfile;
}
function generateInitDockerignore() {
return `# Node modules
node_modules
npm-debug.log
# \u6D4B\u8BD5\u548C\u6587\u6863
test
tests
__tests__
*.test.js
*.spec.js
docs
coverage
# \u5F00\u53D1\u6587\u4EF6
.git
.gitignore
.env
.env.*
*.md
.vscode
.idea
# \u6784\u5EFA\u4EA7\u7269\uFF08\u5728\u5BB9\u5668\u5185\u6784\u5EFA\uFF09
dist
build
# \u4E34\u65F6\u6587\u4EF6
*.log
*.tmp
.DS_Store
`;
}
// src/cli.ts
var pwd = process.cwd();
try {
execSync("docker --version", { stdio: "ignore" });
} catch (error) {
console.error("\u274C Docker \u547D\u4EE4\u4E0D\u53EF\u7528\uFF0C\u8BF7\u786E\u4FDD\u5DF2\u5B89\u88C5\u5E76\u6B63\u786E\u914D\u7F6E Docker");
process.exit(1);
}
if (process.platform !== "linux" && process.platform !== "darwin") {
console.error("\u274C \u76EE\u524D\u4EC5\u652F\u6301 Linux \u548C macOS \u7CFB\u7EDF");
process.exit(1);
}
function parseCliArgs() {
const { values, positionals } = parseArgs({
options: {
env: {
type: "string",
default: "dev"
},
help: {
type: "boolean",
short: "h",
default: false
},
extra: {
type: "string",
multiple: true,
default: []
},
registry: {
type: "string",
default: "https://registry.npmmirror.com"
},
port: {
type: "string",
default: ["3001", "8080"],
multiple: true
},
"node-version": {
type: "string",
default: "20"
},
// 打包web还是后端
"build-type": {
type: "string",
default: "backend"
},
"web-source": {
type: "string",
default: "web"
}
},
allowPositionals: true
});
if (values.help) {
console.log(`
\u4F7F\u7528\u65B9\u6CD5: docker-builder <\u9879\u76EE\u76EE\u5F55> [\u9009\u9879]
\u53C2\u6570:
<\u9879\u76EE\u76EE\u5F55> \u8981\u6253\u5305\u7684\u9879\u76EE\u76EE\u5F55\uFF08\u5FC5\u9700\uFF09
\u9009\u9879:
--env=<environment> \u73AF\u5883\u7C7B\u578B (dev|prod|staging)\uFF0C\u9ED8\u8BA4: dev
--extra=<model> \u989D\u5916\u7684\u4F9D\u8D56\u76EE\u5F55\uFF08\u53EF\u591A\u6B21\u4F7F\u7528\uFF09
--registry=<url> npm \u955C\u50CF\u7AD9\u5730\u5740\uFF0C\u9ED8\u8BA4: https://registry.npmmirror.com
--port=<port> \u66B4\u9732\u7684\u7AEF\u53E3\u53F7\uFF0C\u9ED8\u8BA4: 3001
--node-version=<ver> Node.js \u7248\u672C\uFF0C\u9ED8\u8BA4: 20
--build-type=<type> \u6784\u5EFA\u7C7B\u578B (native|wechatMp|web|backend)\uFF0C\u9ED8\u8BA4: backend
-h, --help \u663E\u793A\u6B64\u5E2E\u52A9\u4FE1\u606F
\u793A\u4F8B:
docker-builder project
docker-builder project --extra=model1 --extra=model2
docker-builder project --env=prod --port=8080 --node-version=18
`);
return null;
}
if (positionals.length === 0) {
console.error("\u274C \u8BF7\u6307\u5B9A\u8981\u6253\u5305\u7684\u9879\u76EE\u76EE\u5F55");
console.error(" \u4F7F\u7528 --help \u67E5\u770B\u8BE6\u7EC6\u7528\u6CD5");
process.exit(1);
}
const projectDir = path3.resolve(positionals[0]);
const env = values.env;
if (!["dev", "prod", "staging"].includes(env)) {
console.error(`\u274C \u65E0\u6548\u7684\u73AF\u5883\u7C7B\u578B: ${env}`);
console.error(" \u652F\u6301\u7684\u73AF\u5883: dev, prod, staging");
process.exit(1);
}
if (!["native", "wechatMp", "web", "backend", "init"].includes(values["build-type"])) {
console.error(`\u274C \u65E0\u6548\u7684\u6784\u5EFA\u7C7B\u578B: ${values["build-type"]}`);
console.error(" \u652F\u6301\u7684\u7C7B\u578B: native, wechatMp, web, backend");
process.exit(1);
}
return {
projectDir,
options: {
env,
extra: values.extra,
registry: values.registry,
port: values.port,
nodeVersion: values["node-version"],
buildType: values["build-type"],
webSource: values["web-source"]
}
};
}
function buildDockerImage(imageBase, name, pwd2) {
console.log(`
\u{1F527} Building image for ${name}...`);
execSync(`docker build -t ${imageBase}:${name} ${pwd2}`, {
stdio: "inherit"
});
}
function saveDockerImage(imageBase, name, pwd2) {
const distDir = path3.join(pwd2, "dist");
if (!fs3.existsSync(distDir)) {
fs3.mkdirSync(distDir);
}
const outputImagePath = path3.join(distDir, "server", imageBase, `${imageBase}-${name}.tar`);
if (!fs3.existsSync(path3.dirname(outputImagePath))) {
fs3.mkdirSync(path3.dirname(outputImagePath), { recursive: true });
}
console.log(`\u{1F4E6} Saving image to ${outputImagePath}...`);
execSync(`docker save -o ${outputImagePath} ${imageBase}:${name}`, {
stdio: "inherit"
});
}
function copyConfiguration(projectDir, imageBase, name, pwd2) {
const configDir = path3.join(projectDir, "configuration");
if (!fs3.existsSync(configDir)) {
console.info(
`\u9879\u76EE\u76EE\u5F55\u4E2D\u6CA1\u6709 configurations \u6587\u4EF6\u5939\uFF1A${configDir}, \u8DF3\u8FC7\u914D\u7F6E\u6587\u4EF6\u590D\u5236\u6B65\u9AA4`
);
return;
}
const distConfigDir = path3.join(pwd2, "dist", "server", imageBase, "configuration");
if (!fs3.existsSync(distConfigDir)) {
fs3.mkdirSync(distConfigDir, { recursive: true });
}
const configFiles = fs3.readdirSync(configDir).filter((file) => file.endsWith(".json"));
for (const file of configFiles) {
const srcPath = path3.join(configDir, file);
const destPath = path3.join(distConfigDir, file);
console.log(`\u590D\u5236\u914D\u7F6E\u6587\u4EF6 ${srcPath} \u5230 ${destPath}...`);
fs3.copyFileSync(srcPath, destPath);
}
}
function writeInitCommandScript(projectDir, imageBase, name, pwd2) {
const distDir = path3.join(pwd2, "dist", "server", imageBase);
if (!fs3.existsSync(distDir)) {
fs3.mkdirSync(distDir, { recursive: true });
}
const scriptPath = path3.join(distDir, "init.sh");
const scriptContent = `#!/bin/sh
docker load -i ${imageBase}-${name}.tar
docker rm ${imageBase}-${name}-init || true
docker run -it \\
--name ${imageBase}-${name}-init \\
-v $(pwd)/configuration:/app/${imageBase}/configuration \\
${imageBase}:${name} \\
npm run server:init
`;
fs3.writeFileSync(scriptPath, scriptContent, { mode: 493 });
console.log(` \u5DF2\u751F\u6210init\u811A\u672C: ${scriptPath}`);
}
function writeStartCommandScript(projectDir, imageBase, name, pwd2) {
const distDir = path3.join(pwd2, "dist", "server", imageBase);
if (!fs3.existsSync(distDir)) {
fs3.mkdirSync(distDir, { recursive: true });
}
const scriptPath = path3.join(distDir, "start.sh");
const scriptContent = `#!/bin/sh
docker load -i ${imageBase}-${name}.tar
docker run -d \\
--name ${imageBase}-${name} \\
-v $(pwd)/configuration:/app/${imageBase}/configuration \\
-p 3001:3001 \\
-p 8080:8080 \\
--restart=always \\
${imageBase}:${name} \\
pm2-runtime start pm2.dev.json
`;
fs3.writeFileSync(scriptPath, scriptContent, { mode: 493 });
console.log(` \u5DF2\u751F\u6210\u542F\u52A8\u811A\u672C: ${scriptPath}`);
}
function main() {
const args = parseCliArgs();
if (!args) {
process.exit(0);
}
const { projectDir, options } = args;
const pwd2 = process.cwd();
console.log(`-> \u914D\u7F6E\u4FE1\u606F:`);
console.log(` \u9879\u76EE\u76EE\u5F55: ${projectDir}`);
console.log(` \u73AF\u5883: ${options.env}`);
console.log(` \u6784\u5EFA\u7C7B\u578B: ${options.buildType}`);
console.log(
` \u989D\u5916\u4F9D\u8D56: ${options.extra.length > 0 ? options.extra.join(", ") : "\u65E0"}`
);
console.log(` npm \u955C\u50CF\u7AD9: ${options.registry}`);
console.log(` \u7AEF\u53E3: ${options.port}`);
console.log(` Node.js \u7248\u672C: ${options.nodeVersion}`);
if (!fs3.existsSync(projectDir)) {
console.error(`\u274C \u9879\u76EE\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${projectDir}`);
process.exit(1);
}
switch (options.buildType) {
case "backend":
packageBackend(projectDir, options);
break;
case "web":
packageWeb(projectDir, options);
break;
case "init":
packageInit(projectDir, options);
break;
default:
console.error(`\u274C \u4E0D\u652F\u6301\u7684\u6784\u5EFA\u7C7B\u578B: ${options.buildType}`);
process.exit(1);
}
copyTemplateFiles(path3.join(pwd2, "dist"));
}
function packageBackend(projectDir, options) {
const imageBase = path3.basename(projectDir);
const projectName = path3.basename(projectDir);
const projectPackageMap = {};
const allProjects = [projectName];
const { extra } = options;
allProjects.push(...extra);
for (const project of allProjects) {
const packageJsonPath = path3.join(pwd, project, "package.json");
const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf-8"));
projectPackageMap[project] = packageJson;
}
const dockerfileContent = generateDockerfile(pwd, projectName, options, allProjects, projectPackageMap);
const dockerignoreContent = generateDockerignore();
fs3.writeFileSync(path3.join(pwd, "Dockerfile"), dockerfileContent);
fs3.writeFileSync(path3.join(pwd, ".dockerignore"), dockerignoreContent);
console.log("\n \u5DF2\u751F\u6210 Dockerfile \u548C .dockerignore");
try {
const name = projectPackageMap[projectName].version || "latest";
console.log(`
\u6784\u5EFA\u955C\u50CF: ${projectName}:${name}`);
buildDockerImage(imageBase, name, pwd);
saveDockerImage(imageBase, name, pwd);
copyConfiguration(projectDir, imageBase, name, pwd);
writeStartCommandScript(projectDir, imageBase, name, pwd);
writeInitCommandScript(projectDir, imageBase, name, pwd);
console.log("\n\u955C\u50CF\u6784\u5EFA\u6210\u529F\uFF01");
} finally {
fs3.rmSync(path3.join(pwd, "Dockerfile"), { force: true });
fs3.rmSync(path3.join(pwd, ".dockerignore"), { force: true });
}
}
function packageWeb(projectDir, options) {
console.log(`
\u{1F527} \u6253\u5305 Web \u9879\u76EE...`);
const distDir = path3.join(pwd, "dist");
if (!fs3.existsSync(distDir)) {
fs3.mkdirSync(distDir);
}
execSync(`npm install`, {
stdio: "inherit",
cwd: projectDir
});
execSync(`npm run build:${options.webSource}${options.env === "staging" ? ":staging" : ""}`, {
stdio: "inherit",
cwd: projectDir
});
const webDistDir = path3.join(projectDir, options.webSource, "build");
if (!fs3.existsSync(webDistDir)) {
console.error(`\u274C \u6784\u5EFA\u5931\u8D25\uFF0C\u627E\u4E0D\u5230 Web \u6784\u5EFA\u4EA7\u7269\u76EE\u5F55: ${webDistDir}`);
process.exit(1);
}
const projectName = path3.basename(projectDir);
const outputWebDir = path3.join(distDir, "html", projectName, options.webSource);
if (!fs3.existsSync(path3.join(distDir, "html", projectName))) {
fs3.mkdirSync(path3.join(distDir, "html", projectName));
}
fs3.rmSync(outputWebDir, { recursive: true, force: true });
fs3.mkdirSync(outputWebDir);
execSync(`cp -r ${webDistDir}/* ${outputWebDir}/`, {
stdio: "inherit"
});
console.log(`\u2705 Web \u9879\u76EE\u6253\u5305\u6210\u529F\uFF0C\u4EA7\u7269\u4F4D\u4E8E: ${outputWebDir}`);
}
function packageInit(projectDir, options) {
const imageBase = path3.basename(projectDir);
const projectName = path3.basename(projectDir);
const dockerfileContent = generateInitDockerfile(pwd, projectName, options);
const dockerignoreContent = generateInitDockerignore();
fs3.writeFileSync(path3.join(pwd, "Dockerfile"), dockerfileContent);
fs3.writeFileSync(path3.join(pwd, ".dockerignore"), dockerignoreContent);
console.log("\n \u5DF2\u751F\u6210 Dockerfile \u548C .dockerignore");
try {
const name = `init-${options.env}`;
console.log(`
\u{1F527} \u6784\u5EFA\u521D\u59CB\u5316\u955C\u50CF ${name}...`);
buildDockerImage(imageBase, name, pwd);
saveDockerImage(imageBase, name, pwd);
console.log("\n \u521D\u59CB\u5316\u955C\u50CF\u6784\u5EFA\u6210\u529F\uFF01");
} finally {
fs3.rmSync(path3.join(pwd, "Dockerfile"), { force: true });
fs3.rmSync(path3.join(pwd, ".dockerignore"), { force: true });
}
}
function copyTemplateFiles(dist) {
const __dirname = path3.dirname(new URL(import.meta.url).pathname);
const templateDir = path3.join(__dirname, "../template");
function copyDir(srcDir, destDir) {
if (!fs3.existsSync(destDir)) {
fs3.mkdirSync(destDir, { recursive: true });
}
const entries = fs3.readdirSync(srcDir, { withFileTypes: true });
for (const entry of entries) {
const srcPath = path3.join(srcDir, entry.name);
const destPath = path3.join(destDir, entry.name);
if (entry.isDirectory()) {
copyDir(srcPath, destPath);
} else {
if (fs3.existsSync(destPath)) {
continue;
}
fs3.copyFileSync(srcPath, destPath);
}
}
}
copyDir(templateDir, dist);
}
main();