nuxt-gin-tools 0.2.22 → 0.3.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/README.md +287 -79
- package/commands/cleanup.d.ts +7 -4
- package/commands/cleanup.js +32 -21
- package/commands/dev-go.js +8 -8
- package/commands/develop.js +19 -0
- package/commands/pack.js +47 -6
- package/commands/postinstall.d.ts +5 -1
- package/commands/postinstall.js +25 -8
- package/commands/update.d.ts +4 -2
- package/commands/update.js +16 -3
- package/index.js +40 -24
- package/package.json +2 -2
- package/src/assets/go-gin-server.json +5 -0
- package/src/assets/pack-config.schema.json +62 -0
- package/src/assets/server-config.schema.json +35 -0
- package/src/cli/commands/build.d.ts +1 -0
- package/src/cli/commands/build.js +22 -0
- package/src/cli/commands/cleanup.d.ts +11 -0
- package/src/cli/commands/cleanup.js +115 -0
- package/src/cli/commands/develop.d.ts +26 -0
- package/src/cli/commands/develop.js +168 -0
- package/src/cli/commands/install.d.ts +6 -0
- package/src/cli/commands/install.js +59 -0
- package/src/cli/commands/update.d.ts +9 -0
- package/src/cli/commands/update.js +55 -0
- package/src/cli/options.d.ts +10 -0
- package/src/cli/options.js +66 -0
- package/src/cli/terminal-ui.d.ts +7 -0
- package/src/cli/terminal-ui.js +118 -0
- package/src/cli-options.d.ts +1 -0
- package/src/cli-options.js +15 -0
- package/src/config/package-manager.d.ts +7 -0
- package/src/config/package-manager.js +39 -0
- package/src/nuxt-gin.d.ts +103 -0
- package/src/nuxt-gin.js +178 -0
- package/src/pack.d.ts +9 -1
- package/src/package-manager.d.ts +7 -0
- package/src/package-manager.js +39 -0
- package/src/services/build-service.d.ts +7 -0
- package/src/services/build-service.js +35 -0
- package/src/services/go-dev-service.d.ts +8 -0
- package/src/services/go-dev-service.js +356 -0
- package/src/services/pack-service.d.ts +23 -0
- package/src/services/pack-service.js +372 -0
- package/src/system/ports.d.ts +7 -0
- package/src/system/ports.js +112 -0
- package/src/terminal-ui.d.ts +3 -0
- package/src/terminal-ui.js +99 -14
- package/src/utils.js +3 -3
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.FILES_TO_COPY = exports.PACKAGE_JSON_CONTENT = exports.SERVER_EXECUTABLE = exports.BUILD_EXECUTABLE = exports.LEGACY_PACK_CONFIG_MJS_PATH = exports.LEGACY_PACK_CONFIG_CJS_PATH = exports.LEGACY_PACK_CONFIG_JS_PATH = exports.LEGACY_PACK_CONFIG_TS_PATH = exports.LEGACY_PACK_CONFIG_PATH = exports.ORIGINAL_DIST_PATH = exports.SERVER_PATH = exports.ZIP_PATH = void 0;
|
|
49
|
+
exports.builtPath = builtPath;
|
|
50
|
+
exports.buildAndPack = buildAndPack;
|
|
51
|
+
const build_service_1 = __importDefault(require("./build-service"));
|
|
52
|
+
const Zip = __importStar(require("7zip-min"));
|
|
53
|
+
const FS = __importStar(require("fs-extra"));
|
|
54
|
+
const Path = __importStar(require("path"));
|
|
55
|
+
const os = __importStar(require("os"));
|
|
56
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
57
|
+
const nuxt_gin_1 = require("../nuxt-gin");
|
|
58
|
+
const terminal_ui_1 = require("../cli/terminal-ui");
|
|
59
|
+
const { createJiti } = require("jiti");
|
|
60
|
+
function builtPath(relativePath) {
|
|
61
|
+
return Path.resolve(exports.SERVER_PATH, relativePath);
|
|
62
|
+
}
|
|
63
|
+
exports.ZIP_PATH = Path.resolve(process.cwd(), ".build/production/server.7z");
|
|
64
|
+
exports.SERVER_PATH = Path.resolve(process.cwd(), ".build/production/server");
|
|
65
|
+
exports.ORIGINAL_DIST_PATH = Path.resolve(process.cwd(), "dist");
|
|
66
|
+
exports.LEGACY_PACK_CONFIG_PATH = Path.resolve(process.cwd(), "pack.config.json");
|
|
67
|
+
exports.LEGACY_PACK_CONFIG_TS_PATH = Path.resolve(process.cwd(), "pack.config.ts");
|
|
68
|
+
exports.LEGACY_PACK_CONFIG_JS_PATH = Path.resolve(process.cwd(), "pack.config.js");
|
|
69
|
+
exports.LEGACY_PACK_CONFIG_CJS_PATH = Path.resolve(process.cwd(), "pack.config.cjs");
|
|
70
|
+
exports.LEGACY_PACK_CONFIG_MJS_PATH = Path.resolve(process.cwd(), "pack.config.mjs");
|
|
71
|
+
exports.BUILD_EXECUTABLE = os.platform() === "win32" ? "production.exe" : "production";
|
|
72
|
+
exports.SERVER_EXECUTABLE = os.platform() === "win32" ? "server-production.exe" : "server-production";
|
|
73
|
+
exports.PACKAGE_JSON_CONTENT = {
|
|
74
|
+
private: true,
|
|
75
|
+
scripts: {
|
|
76
|
+
start: `./${exports.SERVER_EXECUTABLE}`,
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
const DEFAULT_FILES_TO_COPY = {
|
|
80
|
+
"vue/.output": "vue/.output",
|
|
81
|
+
[`.build/.server/${exports.BUILD_EXECUTABLE}`]: exports.SERVER_EXECUTABLE,
|
|
82
|
+
};
|
|
83
|
+
exports.FILES_TO_COPY = Object.fromEntries(Object.entries(DEFAULT_FILES_TO_COPY).map(([src, dest]) => [src, builtPath(dest)]));
|
|
84
|
+
function warnPackConfig(message) {
|
|
85
|
+
(0, terminal_ui_1.printCommandWarn)(`[pack] ${message}`);
|
|
86
|
+
}
|
|
87
|
+
function errorPackConfig(message) {
|
|
88
|
+
throw new Error(`[nuxt-gin-tools][pack] ${message}`);
|
|
89
|
+
}
|
|
90
|
+
function isPlainObject(value) {
|
|
91
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
92
|
+
}
|
|
93
|
+
function validateStringArray(fieldName, value, issues) {
|
|
94
|
+
if (value === undefined) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (!Array.isArray(value)) {
|
|
98
|
+
issues.push({ level: "error", message: `${fieldName} must be an array of strings` });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
for (const item of value) {
|
|
102
|
+
if (typeof item !== "string") {
|
|
103
|
+
issues.push({ level: "error", message: `${fieldName} must contain only strings` });
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function validateStringRecord(fieldName, value, issues) {
|
|
109
|
+
if (value === undefined) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (!isPlainObject(value)) {
|
|
113
|
+
issues.push({ level: "error", message: `${fieldName} must be an object of string to string` });
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
for (const [key, item] of Object.entries(value)) {
|
|
117
|
+
if (typeof key !== "string" || typeof item !== "string") {
|
|
118
|
+
issues.push({ level: "error", message: `${fieldName} must be an object of string to string` });
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function validatePackConfig(config, sourcePath) {
|
|
124
|
+
if (!isPlainObject(config)) {
|
|
125
|
+
errorPackConfig(`${Path.basename(sourcePath)} must export an object`);
|
|
126
|
+
}
|
|
127
|
+
const issues = [];
|
|
128
|
+
const typedConfig = config;
|
|
129
|
+
const stringFields = ["binaryName", "zipName", "zipPath", "serverPath"];
|
|
130
|
+
for (const field of stringFields) {
|
|
131
|
+
const value = typedConfig[field];
|
|
132
|
+
if (value !== undefined && typeof value !== "string") {
|
|
133
|
+
issues.push({ level: "error", message: `${field} must be a string` });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const booleanFields = [
|
|
137
|
+
"skipGo",
|
|
138
|
+
"skipNuxt",
|
|
139
|
+
"skipBuild",
|
|
140
|
+
"skipZip",
|
|
141
|
+
"cleanDist",
|
|
142
|
+
"writeScripts",
|
|
143
|
+
"overwrite",
|
|
144
|
+
];
|
|
145
|
+
for (const field of booleanFields) {
|
|
146
|
+
const value = typedConfig[field];
|
|
147
|
+
if (value !== undefined && typeof value !== "boolean") {
|
|
148
|
+
issues.push({ level: "error", message: `${field} must be a boolean` });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
validateStringArray("extraFilesGlobs", typedConfig.extraFilesGlobs, issues);
|
|
152
|
+
validateStringArray("exclude", typedConfig.exclude, issues);
|
|
153
|
+
validateStringRecord("extraFiles", typedConfig.extraFiles, issues);
|
|
154
|
+
if (typedConfig.packageJson !== undefined && !isPlainObject(typedConfig.packageJson)) {
|
|
155
|
+
issues.push({ level: "error", message: `packageJson must be an object` });
|
|
156
|
+
}
|
|
157
|
+
if (typedConfig.beforePack !== undefined && typeof typedConfig.beforePack !== "function") {
|
|
158
|
+
issues.push({ level: "error", message: `beforePack must be a function` });
|
|
159
|
+
}
|
|
160
|
+
if (typedConfig.afterPack !== undefined && typeof typedConfig.afterPack !== "function") {
|
|
161
|
+
issues.push({ level: "error", message: `afterPack must be a function` });
|
|
162
|
+
}
|
|
163
|
+
if (typedConfig.zipName !== undefined && typedConfig.zipPath !== undefined) {
|
|
164
|
+
issues.push({ level: "warn", message: `zipPath and zipName are both set; zipPath takes precedence` });
|
|
165
|
+
}
|
|
166
|
+
if (typedConfig.skipGo === true && typedConfig.skipNuxt === true) {
|
|
167
|
+
issues.push({ level: "warn", message: `skipGo and skipNuxt are both true; build step will be skipped` });
|
|
168
|
+
}
|
|
169
|
+
if (typedConfig.skipBuild === true && typedConfig.skipZip === true) {
|
|
170
|
+
issues.push({ level: "warn", message: `skipBuild and skipZip are both true; only bundle assembly will run` });
|
|
171
|
+
}
|
|
172
|
+
for (const issue of issues) {
|
|
173
|
+
if (issue.level === "warn") {
|
|
174
|
+
warnPackConfig(`${Path.basename(sourcePath)}: ${issue.message}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const errors = issues.filter((issue) => issue.level === "error");
|
|
178
|
+
if (errors.length > 0) {
|
|
179
|
+
errorPackConfig(`${Path.basename(sourcePath)} is invalid:\n- ${errors.map((item) => item.message).join("\n- ")}`);
|
|
180
|
+
}
|
|
181
|
+
return config;
|
|
182
|
+
}
|
|
183
|
+
function writeScriptFiles(serverPath, config) {
|
|
184
|
+
FS.outputFileSync(Path.resolve(serverPath, "start.bat"), `powershell -ExecutionPolicy ByPass -File ./start.ps1`);
|
|
185
|
+
FS.outputFileSync(Path.resolve(serverPath, "start.ps1"), `./${exports.SERVER_EXECUTABLE}`);
|
|
186
|
+
FS.outputFileSync(Path.resolve(serverPath, "start.sh"), `./${exports.SERVER_EXECUTABLE}`);
|
|
187
|
+
const mergedPackageJson = mergePackageJson(exports.PACKAGE_JSON_CONTENT, config === null || config === void 0 ? void 0 : config.packageJson);
|
|
188
|
+
FS.outputJSONSync(Path.resolve(serverPath, "package.json"), mergedPackageJson, { spaces: 2 });
|
|
189
|
+
}
|
|
190
|
+
function writeServerConfigFile(serverPath) {
|
|
191
|
+
const resolvedDest = Path.resolve(serverPath, "server.config.json");
|
|
192
|
+
const projectServerConfigPath = Path.resolve(process.cwd(), "server.config.json");
|
|
193
|
+
if (FS.existsSync(projectServerConfigPath)) {
|
|
194
|
+
FS.copySync(projectServerConfigPath, resolvedDest);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
throw new Error("server.config.json is required for packaging output");
|
|
198
|
+
}
|
|
199
|
+
function copyGeneratedFiles(serverPath, config) {
|
|
200
|
+
var _a;
|
|
201
|
+
const copyOptions = {
|
|
202
|
+
overwrite: (config === null || config === void 0 ? void 0 : config.overwrite) !== false,
|
|
203
|
+
errorOnExist: (config === null || config === void 0 ? void 0 : config.overwrite) === false,
|
|
204
|
+
};
|
|
205
|
+
for (const [src, dest] of Object.entries(DEFAULT_FILES_TO_COPY)) {
|
|
206
|
+
const resolvedDest = Path.resolve(serverPath, dest);
|
|
207
|
+
FS.copySync(Path.resolve(process.cwd(), src), resolvedDest, copyOptions);
|
|
208
|
+
}
|
|
209
|
+
if (config === null || config === void 0 ? void 0 : config.extraFiles) {
|
|
210
|
+
for (const [src, dest] of Object.entries(config.extraFiles)) {
|
|
211
|
+
const resolvedSrc = Path.resolve(process.cwd(), src);
|
|
212
|
+
const resolvedDest = Path.isAbsolute(dest) ? dest : Path.resolve(serverPath, dest);
|
|
213
|
+
FS.copySync(resolvedSrc, resolvedDest, copyOptions);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if ((_a = config === null || config === void 0 ? void 0 : config.extraFilesGlobs) === null || _a === void 0 ? void 0 : _a.length) {
|
|
217
|
+
const matchedFiles = fast_glob_1.default.sync(config.extraFilesGlobs, {
|
|
218
|
+
cwd: process.cwd(),
|
|
219
|
+
onlyFiles: true,
|
|
220
|
+
dot: true,
|
|
221
|
+
ignore: config.exclude,
|
|
222
|
+
});
|
|
223
|
+
for (const file of matchedFiles) {
|
|
224
|
+
const resolvedSrc = Path.resolve(process.cwd(), file);
|
|
225
|
+
const resolvedDest = Path.resolve(serverPath, file);
|
|
226
|
+
FS.copySync(resolvedSrc, resolvedDest, copyOptions);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
writeServerConfigFile(serverPath);
|
|
230
|
+
}
|
|
231
|
+
function mergePackageJson(base, override) {
|
|
232
|
+
if (!override) {
|
|
233
|
+
return base;
|
|
234
|
+
}
|
|
235
|
+
const baseScripts = typeof base.scripts === "object" && base.scripts ? base.scripts : {};
|
|
236
|
+
const overrideScripts = typeof override.scripts === "object" && override.scripts ? override.scripts : {};
|
|
237
|
+
return Object.assign(Object.assign(Object.assign({}, base), override), { scripts: Object.assign(Object.assign({}, baseScripts), overrideScripts) });
|
|
238
|
+
}
|
|
239
|
+
function readPackConfigFromCwd() {
|
|
240
|
+
const candidates = [
|
|
241
|
+
exports.LEGACY_PACK_CONFIG_TS_PATH,
|
|
242
|
+
exports.LEGACY_PACK_CONFIG_JS_PATH,
|
|
243
|
+
exports.LEGACY_PACK_CONFIG_CJS_PATH,
|
|
244
|
+
exports.LEGACY_PACK_CONFIG_MJS_PATH,
|
|
245
|
+
exports.LEGACY_PACK_CONFIG_PATH,
|
|
246
|
+
].filter((configPath) => FS.existsSync(configPath));
|
|
247
|
+
if (candidates.length === 0) {
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
if (candidates.length > 1) {
|
|
251
|
+
warnPackConfig(`multiple legacy pack config files found (${candidates.map((item) => Path.basename(item)).join(", ")}); using ${Path.basename(candidates[0])}`);
|
|
252
|
+
}
|
|
253
|
+
const selectedPath = candidates[0];
|
|
254
|
+
let loadedConfig;
|
|
255
|
+
if (selectedPath.endsWith(".json")) {
|
|
256
|
+
loadedConfig = FS.readJSONSync(selectedPath);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
const jiti = createJiti(__filename, { moduleCache: false, interopDefault: true });
|
|
260
|
+
loadedConfig = jiti(selectedPath);
|
|
261
|
+
}
|
|
262
|
+
const normalizedConfig = isPlainObject(loadedConfig) && "default" in loadedConfig
|
|
263
|
+
? loadedConfig.default
|
|
264
|
+
: loadedConfig;
|
|
265
|
+
return validatePackConfig(normalizedConfig, selectedPath);
|
|
266
|
+
}
|
|
267
|
+
function resolveServerPath(config) {
|
|
268
|
+
if (!(config === null || config === void 0 ? void 0 : config.serverPath)) {
|
|
269
|
+
return exports.SERVER_PATH;
|
|
270
|
+
}
|
|
271
|
+
return Path.isAbsolute(config.serverPath)
|
|
272
|
+
? config.serverPath
|
|
273
|
+
: Path.resolve(process.cwd(), config.serverPath);
|
|
274
|
+
}
|
|
275
|
+
function resolveZipPath(config) {
|
|
276
|
+
if (config === null || config === void 0 ? void 0 : config.zipPath) {
|
|
277
|
+
return Path.isAbsolute(config.zipPath)
|
|
278
|
+
? config.zipPath
|
|
279
|
+
: Path.resolve(process.cwd(), config.zipPath);
|
|
280
|
+
}
|
|
281
|
+
if (config === null || config === void 0 ? void 0 : config.zipName) {
|
|
282
|
+
return Path.resolve(Path.dirname(exports.ZIP_PATH), config.zipName);
|
|
283
|
+
}
|
|
284
|
+
return exports.ZIP_PATH;
|
|
285
|
+
}
|
|
286
|
+
function makeZip(serverPath, zipPath) {
|
|
287
|
+
return new Promise((resolve, reject) => {
|
|
288
|
+
Zip.pack(serverPath, zipPath, (error) => {
|
|
289
|
+
if (error) {
|
|
290
|
+
(0, terminal_ui_1.printCommandError)("打包失败", error);
|
|
291
|
+
reject(error);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
(0, terminal_ui_1.printCommandSuccess)("pack", `archive ready: ${zipPath}`);
|
|
295
|
+
resolve(zipPath);
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
function cleanUp(config) {
|
|
300
|
+
if ((config === null || config === void 0 ? void 0 : config.cleanDist) === false) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
if (FS.existsSync(exports.ORIGINAL_DIST_PATH)) {
|
|
304
|
+
FS.removeSync(exports.ORIGINAL_DIST_PATH);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function buildAndPack(config) {
|
|
308
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
309
|
+
var _a;
|
|
310
|
+
(0, terminal_ui_1.printCommandBanner)("build", "Build project artifacts and pack deployment bundle");
|
|
311
|
+
const projectConfig = (0, nuxt_gin_1.resolveNuxtGinProjectConfig)();
|
|
312
|
+
for (const warning of projectConfig.warnings) {
|
|
313
|
+
(0, terminal_ui_1.printCommandWarn)(`[config] ${warning}`);
|
|
314
|
+
}
|
|
315
|
+
const actions = [];
|
|
316
|
+
const legacyPackConfig = readPackConfigFromCwd();
|
|
317
|
+
if (!projectConfig.config.pack && legacyPackConfig) {
|
|
318
|
+
(0, terminal_ui_1.printCommandWarn)("[config] using legacy pack.config.* fallback; migrate to nuxt-gin.config.ts");
|
|
319
|
+
}
|
|
320
|
+
const resolvedConfig = (0, nuxt_gin_1.mergeDefined)((_a = projectConfig.config.pack) !== null && _a !== void 0 ? _a : legacyPackConfig, config);
|
|
321
|
+
if (!(0, nuxt_gin_1.readLegacyServerConfig)()) {
|
|
322
|
+
throw new Error("server.config.json is required in project root before running build");
|
|
323
|
+
}
|
|
324
|
+
const serverPath = resolveServerPath(resolvedConfig);
|
|
325
|
+
const zipPath = resolveZipPath(resolvedConfig);
|
|
326
|
+
if (!(resolvedConfig === null || resolvedConfig === void 0 ? void 0 : resolvedConfig.skipBuild)) {
|
|
327
|
+
yield (0, build_service_1.default)(resolvedConfig);
|
|
328
|
+
actions.push("built project artifacts");
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
(0, terminal_ui_1.printCommandInfo)("build", "skipping build step");
|
|
332
|
+
actions.push("skipped build step");
|
|
333
|
+
}
|
|
334
|
+
if (resolvedConfig === null || resolvedConfig === void 0 ? void 0 : resolvedConfig.beforePack) {
|
|
335
|
+
yield resolvedConfig.beforePack();
|
|
336
|
+
actions.push("ran beforePack hook");
|
|
337
|
+
}
|
|
338
|
+
copyGeneratedFiles(serverPath, resolvedConfig);
|
|
339
|
+
actions.push(`assembled bundle in ${serverPath}`);
|
|
340
|
+
if ((resolvedConfig === null || resolvedConfig === void 0 ? void 0 : resolvedConfig.writeScripts) !== false) {
|
|
341
|
+
writeScriptFiles(serverPath, resolvedConfig);
|
|
342
|
+
actions.push("wrote startup scripts and package.json");
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
actions.push("skipped startup script generation");
|
|
346
|
+
}
|
|
347
|
+
if (!(resolvedConfig === null || resolvedConfig === void 0 ? void 0 : resolvedConfig.skipZip)) {
|
|
348
|
+
yield makeZip(serverPath, zipPath);
|
|
349
|
+
(0, terminal_ui_1.printCommandInfo)("pack", `7z archive: ${zipPath}`);
|
|
350
|
+
actions.push(`created 7z archive at ${zipPath}`);
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
(0, terminal_ui_1.printCommandInfo)("pack", "skipping 7z archive step");
|
|
354
|
+
actions.push("skipped 7z archive step");
|
|
355
|
+
}
|
|
356
|
+
(0, terminal_ui_1.printCommandInfo)("pack", `bundle dir: ${serverPath}`);
|
|
357
|
+
if (resolvedConfig === null || resolvedConfig === void 0 ? void 0 : resolvedConfig.afterPack) {
|
|
358
|
+
yield resolvedConfig.afterPack(zipPath);
|
|
359
|
+
actions.push("ran afterPack hook");
|
|
360
|
+
}
|
|
361
|
+
cleanUp(resolvedConfig);
|
|
362
|
+
if ((resolvedConfig === null || resolvedConfig === void 0 ? void 0 : resolvedConfig.cleanDist) === false) {
|
|
363
|
+
actions.push("kept dist directory by configuration");
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
actions.push("cleaned dist directory");
|
|
367
|
+
}
|
|
368
|
+
(0, terminal_ui_1.printCommandSuccess)("build", "Build and pack completed");
|
|
369
|
+
(0, terminal_ui_1.printCommandSummary)("build", actions);
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
exports.default = buildAndPack;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type KillPortOptions = {
|
|
2
|
+
logPrefix?: string;
|
|
3
|
+
portLabel?: string;
|
|
4
|
+
};
|
|
5
|
+
export declare function killPort(port: number, options?: KillPortOptions): void;
|
|
6
|
+
export declare function killPorts(ports: Array<number | undefined>, options?: KillPortOptions): void;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.killPort = killPort;
|
|
7
|
+
exports.killPorts = killPorts;
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const os_1 = __importDefault(require("os"));
|
|
10
|
+
const terminal_ui_1 = require("../cli/terminal-ui");
|
|
11
|
+
function isValidPort(port) {
|
|
12
|
+
return Number.isInteger(port) && port > 0;
|
|
13
|
+
}
|
|
14
|
+
function buildMessage(pid, port, platform, options) {
|
|
15
|
+
var _a;
|
|
16
|
+
const prefix = (options === null || options === void 0 ? void 0 : options.logPrefix) ? `[${options.logPrefix}] ` : "";
|
|
17
|
+
const label = (_a = options === null || options === void 0 ? void 0 : options.portLabel) !== null && _a !== void 0 ? _a : "port";
|
|
18
|
+
return `${prefix}killed process ${pid} on ${label} ${port} (${platform})`;
|
|
19
|
+
}
|
|
20
|
+
function killPortUnix(port, options) {
|
|
21
|
+
try {
|
|
22
|
+
const output = (0, child_process_1.execSync)(`lsof -ti tcp:${port}`, {
|
|
23
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
24
|
+
})
|
|
25
|
+
.toString()
|
|
26
|
+
.trim();
|
|
27
|
+
if (!output) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const pids = output
|
|
31
|
+
.split("\n")
|
|
32
|
+
.map((pid) => Number(pid.trim()))
|
|
33
|
+
.filter((pid) => Number.isInteger(pid) && pid > 0);
|
|
34
|
+
for (const pid of pids) {
|
|
35
|
+
try {
|
|
36
|
+
process.kill(pid, "SIGKILL");
|
|
37
|
+
(0, terminal_ui_1.printCommandSuccess)("port", buildMessage(pid, port, "unix", options));
|
|
38
|
+
}
|
|
39
|
+
catch (_a) {
|
|
40
|
+
// Best-effort: if the process is already gone, ignore.
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (_b) {
|
|
45
|
+
// Best-effort: lsof might be missing or no process is listening on the port.
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function killPortWindows(port, options) {
|
|
49
|
+
try {
|
|
50
|
+
const output = (0, child_process_1.execSync)(`netstat -ano -p tcp`, {
|
|
51
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
52
|
+
})
|
|
53
|
+
.toString()
|
|
54
|
+
.trim();
|
|
55
|
+
if (!output) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const pids = new Set();
|
|
59
|
+
for (const line of output.split("\n")) {
|
|
60
|
+
const trimmed = line.trim();
|
|
61
|
+
if (!trimmed || !trimmed.startsWith("TCP")) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const parts = trimmed.split(/\s+/);
|
|
65
|
+
if (parts.length < 5) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const localAddress = parts[1];
|
|
69
|
+
const pid = Number(parts[parts.length - 1]);
|
|
70
|
+
const match = localAddress.match(/:(\d+)$/);
|
|
71
|
+
if (!match) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const localPort = Number(match[1]);
|
|
75
|
+
if (localPort === port && Number.isInteger(pid) && pid > 0) {
|
|
76
|
+
pids.add(pid);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
for (const pid of pids) {
|
|
80
|
+
try {
|
|
81
|
+
(0, child_process_1.execSync)(`taskkill /PID ${pid} /F`, {
|
|
82
|
+
stdio: ["ignore", "ignore", "ignore"],
|
|
83
|
+
});
|
|
84
|
+
(0, terminal_ui_1.printCommandSuccess)("port", buildMessage(pid, port, "win32", options));
|
|
85
|
+
}
|
|
86
|
+
catch (_a) {
|
|
87
|
+
// Best-effort: if the process is already gone, ignore.
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (_b) {
|
|
92
|
+
// Best-effort: netstat might be missing or no process is listening on the port.
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function killPort(port, options) {
|
|
96
|
+
if (!isValidPort(port)) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (os_1.default.platform() === "win32") {
|
|
100
|
+
killPortWindows(port, options);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
killPortUnix(port, options);
|
|
104
|
+
}
|
|
105
|
+
function killPorts(ports, options) {
|
|
106
|
+
const validPorts = ports
|
|
107
|
+
.filter((port) => typeof port === "number" && isValidPort(port))
|
|
108
|
+
.filter((port, index, list) => list.indexOf(port) === index);
|
|
109
|
+
for (const port of validPorts) {
|
|
110
|
+
killPort(port, options);
|
|
111
|
+
}
|
|
112
|
+
}
|
package/src/terminal-ui.d.ts
CHANGED
|
@@ -2,3 +2,6 @@ export declare function printCommandBanner(command: string, subtitle: string): v
|
|
|
2
2
|
export declare function printCommandSuccess(command: string, message: string): void;
|
|
3
3
|
export declare function printCommandInfo(label: string, message: string): void;
|
|
4
4
|
export declare function printCommandWarn(message: string): void;
|
|
5
|
+
export declare function printCommandError(message: string, error?: unknown): void;
|
|
6
|
+
export declare function printCommandLog(label: string, message: string): void;
|
|
7
|
+
export declare function printCommandSummary(command: string, items: string[]): void;
|
package/src/terminal-ui.js
CHANGED
|
@@ -7,27 +7,112 @@ exports.printCommandBanner = printCommandBanner;
|
|
|
7
7
|
exports.printCommandSuccess = printCommandSuccess;
|
|
8
8
|
exports.printCommandInfo = printCommandInfo;
|
|
9
9
|
exports.printCommandWarn = printCommandWarn;
|
|
10
|
+
exports.printCommandError = printCommandError;
|
|
11
|
+
exports.printCommandLog = printCommandLog;
|
|
12
|
+
exports.printCommandSummary = printCommandSummary;
|
|
10
13
|
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
const TERMINAL_WIDTH = 72;
|
|
15
|
+
function printLine(message, method = "log") {
|
|
16
|
+
if (method === "warn") {
|
|
17
|
+
console.warn(message);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (method === "error") {
|
|
21
|
+
console.error(message);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
console.log(message);
|
|
25
|
+
}
|
|
26
|
+
function repeat(char, width = TERMINAL_WIDTH) {
|
|
27
|
+
return char.repeat(width);
|
|
28
|
+
}
|
|
29
|
+
function formatClock() {
|
|
30
|
+
return new Date().toLocaleTimeString("en-GB", {
|
|
31
|
+
hour: "2-digit",
|
|
32
|
+
minute: "2-digit",
|
|
33
|
+
second: "2-digit",
|
|
34
|
+
hour12: false,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function padText(value, width) {
|
|
38
|
+
const text = value.length > width ? `${value.slice(0, Math.max(0, width - 1))}…` : value;
|
|
39
|
+
return text + " ".repeat(Math.max(0, width - text.length));
|
|
40
|
+
}
|
|
41
|
+
function sectionBorder(color) {
|
|
42
|
+
return color(`╭${repeat("─", TERMINAL_WIDTH - 2)}╮`);
|
|
43
|
+
}
|
|
44
|
+
function sectionFooter(color) {
|
|
45
|
+
return color(`╰${repeat("─", TERMINAL_WIDTH - 2)}╯`);
|
|
46
|
+
}
|
|
47
|
+
function sectionBody(text, color) {
|
|
48
|
+
return color(`│ ${padText(text, TERMINAL_WIDTH - 4)} │`);
|
|
49
|
+
}
|
|
50
|
+
function printSection(lines, options) {
|
|
51
|
+
var _a;
|
|
52
|
+
if (lines.length === 0) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const method = (_a = options.method) !== null && _a !== void 0 ? _a : "log";
|
|
56
|
+
printLine(options.color(``), method);
|
|
57
|
+
printLine(sectionBorder(options.color), method);
|
|
58
|
+
for (const line of lines) {
|
|
59
|
+
printLine(sectionBody(line, options.color), method);
|
|
60
|
+
}
|
|
61
|
+
printLine(sectionFooter(options.color), method);
|
|
62
|
+
}
|
|
63
|
+
function commandChip(command) {
|
|
64
|
+
return chalk_1.default.bgBlueBright.black(` ${command.toUpperCase()} `);
|
|
65
|
+
}
|
|
66
|
+
function subtleChip(text) {
|
|
67
|
+
return chalk_1.default.bgBlackBright.white(` ${text} `);
|
|
13
68
|
}
|
|
14
69
|
function printCommandBanner(command, subtitle) {
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
console.log(detail);
|
|
23
|
-
console.log(border);
|
|
70
|
+
const timestamp = subtleChip(formatClock());
|
|
71
|
+
const title = `nuxt-gin-tools ${commandChip(command)} ${timestamp}`;
|
|
72
|
+
const detail = chalk_1.default.cyanBright(subtitle);
|
|
73
|
+
printLine("");
|
|
74
|
+
printSection([title, detail], {
|
|
75
|
+
color: chalk_1.default.blueBright,
|
|
76
|
+
});
|
|
24
77
|
}
|
|
25
78
|
function printCommandSuccess(command, message) {
|
|
26
|
-
|
|
79
|
+
printLine(chalk_1.default.greenBright(`◆ ${chalk_1.default.bold(command)} completed`) + chalk_1.default.green(` ${message}`));
|
|
27
80
|
}
|
|
28
81
|
function printCommandInfo(label, message) {
|
|
29
|
-
|
|
82
|
+
const head = chalk_1.default.bgCyan.black(` ${label.toUpperCase()} `);
|
|
83
|
+
printLine(`${head} ${chalk_1.default.cyanBright(message)}`);
|
|
30
84
|
}
|
|
31
85
|
function printCommandWarn(message) {
|
|
32
|
-
|
|
86
|
+
printSection([`${chalk_1.default.bold("warning")} ${message}`], {
|
|
87
|
+
color: chalk_1.default.yellow,
|
|
88
|
+
method: "warn",
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function printCommandError(message, error) {
|
|
92
|
+
const detail = error instanceof Error ? error.message : error !== undefined ? String(error) : "";
|
|
93
|
+
const lines = [`${chalk_1.default.bold("error")} ${message}`];
|
|
94
|
+
if (detail) {
|
|
95
|
+
lines.push(chalk_1.default.redBright(detail));
|
|
96
|
+
}
|
|
97
|
+
printSection(lines, {
|
|
98
|
+
color: chalk_1.default.red,
|
|
99
|
+
method: "error",
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function printCommandLog(label, message) {
|
|
103
|
+
const chip = chalk_1.default.bgMagenta.white(` ${label} `);
|
|
104
|
+
printLine(`${chip} ${chalk_1.default.white(message)}`);
|
|
105
|
+
}
|
|
106
|
+
function printCommandSummary(command, items) {
|
|
107
|
+
const normalizedItems = items.map((item) => item.trim()).filter(Boolean);
|
|
108
|
+
if (normalizedItems.length === 0) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const lines = [
|
|
112
|
+
`${chalk_1.default.bold(`${command} summary`)} ${chalk_1.default.gray(`(${normalizedItems.length} items)`)}`,
|
|
113
|
+
...normalizedItems.map((item) => chalk_1.default.magenta(`• ${item}`)),
|
|
114
|
+
];
|
|
115
|
+
printSection(lines, {
|
|
116
|
+
color: chalk_1.default.magentaBright,
|
|
117
|
+
});
|
|
33
118
|
}
|
package/src/utils.js
CHANGED
|
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.killPort = killPort;
|
|
7
7
|
exports.killPorts = killPorts;
|
|
8
8
|
const child_process_1 = require("child_process");
|
|
9
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
10
9
|
const os_1 = __importDefault(require("os"));
|
|
10
|
+
const terminal_ui_1 = require("./terminal-ui");
|
|
11
11
|
function isValidPort(port) {
|
|
12
12
|
return Number.isInteger(port) && port > 0;
|
|
13
13
|
}
|
|
@@ -34,7 +34,7 @@ function killPortUnix(port, options) {
|
|
|
34
34
|
for (const pid of pids) {
|
|
35
35
|
try {
|
|
36
36
|
process.kill(pid, "SIGKILL");
|
|
37
|
-
|
|
37
|
+
(0, terminal_ui_1.printCommandSuccess)("port", buildMessage(pid, port, "unix", options));
|
|
38
38
|
}
|
|
39
39
|
catch (_a) {
|
|
40
40
|
// Best-effort: if the process is already gone, ignore.
|
|
@@ -81,7 +81,7 @@ function killPortWindows(port, options) {
|
|
|
81
81
|
(0, child_process_1.execSync)(`taskkill /PID ${pid} /F`, {
|
|
82
82
|
stdio: ["ignore", "ignore", "ignore"],
|
|
83
83
|
});
|
|
84
|
-
|
|
84
|
+
(0, terminal_ui_1.printCommandSuccess)("port", buildMessage(pid, port, "win32", options));
|
|
85
85
|
}
|
|
86
86
|
catch (_a) {
|
|
87
87
|
// Best-effort: if the process is already gone, ignore.
|