nuxt-gin-tools 0.2.18 → 0.2.20

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 CHANGED
@@ -1,102 +1,426 @@
1
- # nuxt-gin-tools
1
+ # nuxt-gin-tools 🧰
2
2
 
3
- `nuxt-gin-tools` 是 `nuxt-gin-starter` 的配套开发工具包,提供 Nuxt + Gin 项目的统一命令入口。
3
+ [![npm version](https://img.shields.io/npm/v/nuxt-gin-tools?style=flat-square)](https://www.npmjs.com/package/nuxt-gin-tools)
4
+ [![npm downloads](https://img.shields.io/npm/dm/nuxt-gin-tools?style=flat-square)](https://www.npmjs.com/package/nuxt-gin-tools)
5
+ [![Node](https://img.shields.io/badge/Node-18%2B-339933?logo=node.js&logoColor=white&style=flat-square)](https://nodejs.org)
6
+ [![Nuxt](https://img.shields.io/badge/Nuxt-4.x-00DC82?logo=nuxt&logoColor=white&style=flat-square)](https://nuxt.com)
7
+ [![Go](https://img.shields.io/badge/Go-supported-00ADD8?logo=go&logoColor=white&style=flat-square)](https://go.dev)
8
+ [![License](https://img.shields.io/badge/license-MIT-0b5fff?style=flat-square)](./LICENSE)
4
9
 
5
- 核心目标:
6
- - 一条命令启动前后端开发环境
7
- - 自动处理 Go 侧依赖和文件监听重启
8
- - 提供 OpenAPI 代码生成与构建打包辅助
10
+ `nuxt-gin-tools` is the companion CLI for [`nuxt-gin-starter`](https://github.com/RapboyGao/nuxt-gin-starter.git), built to make **Nuxt + Gin** development feel like one coherent workflow instead of two separate toolchains.
9
11
 
10
- ## 功能概览
12
+ Quick Jump:
11
13
 
12
- - `nuxt-gin dev`
13
- - 启动 Nuxt 开发服务
14
- - 启动 Go 文件监听(基于 `chokidar`)
15
- - Go 文件变化后自动重启 `go run main.go`
16
- - `nuxt-gin install`
17
- - 执行 Nuxt prepare
18
- - 如果检测到 Go,则执行 `go mod download && go mod tidy`
19
- - `nuxt-gin gen`
20
- - 基于 `openapi.yaml` 生成 Go / TS API 代码
21
- - `nuxt-gin build`
22
- - 执行项目构建与打包流程
23
- - `nuxt-gin cleanup`
24
- - 清理开发产物
25
- - `nuxt-gin update`
26
- - 执行依赖更新流程
14
+ - [English](#english)
15
+ - [中文](#中文)
27
16
 
28
- ## 安装
17
+ ## English
29
18
 
30
- `nuxt-gin-starter` 项目中作为依赖安装:
19
+ ### Highlights
20
+
21
+ - 🚀 One command to run Nuxt dev + Go watcher together
22
+ - 🔁 Automatic Go restart on file changes with `chokidar`
23
+ - 📦 Build-and-pack workflow for deployment artifacts
24
+ - 🧩 `pack.config.ts` support with typed config helper
25
+ - 🛡️ Config validation with `warn` and `error` feedback
26
+ - 🔧 Useful CLI switches for partial workflows like `--skip-go`
27
+
28
+ ### 📦 Install
31
29
 
32
30
  ```bash
33
- pnpm add nuxt-gin-tools
31
+ pnpm add -D nuxt-gin-tools
34
32
  ```
35
33
 
36
- ## 快速开始
34
+ ### ⚡ Quick Start
37
35
 
38
36
  ```bash
39
- # 初始化依赖(可选)
37
+ # optional bootstrap
40
38
  nuxt-gin install
41
39
 
42
- # 启动开发
40
+ # start Nuxt + Go together
43
41
  nuxt-gin dev
44
42
  ```
45
43
 
46
- ## 命令说明
44
+ Common variants:
45
+
46
+ ```bash
47
+ # frontend only
48
+ nuxt-gin dev --skip-go
49
+
50
+ # go watcher only
51
+ nuxt-gin dev --skip-nuxt
52
+
53
+ # skip cleanup / bootstrap checks
54
+ nuxt-gin dev --no-cleanup
55
+ ```
56
+
57
+ ### 🗂️ Commands
58
+
59
+ #### `nuxt-gin dev`
60
+
61
+ Runs the local development stack:
62
+
63
+ - Nuxt: `npx nuxt dev --port=<nuxtPort> --host`
64
+ - Go: watches files and restarts `go run main.go`
65
+
66
+ Flags:
67
+
68
+ - `--skip-go`: start Nuxt only
69
+ - `--skip-nuxt`: start Go only
70
+ - `--no-cleanup`: skip pre-cleanup and bootstrap checks
71
+
72
+ #### `nuxt-gin install`
73
+
74
+ Bootstraps the project:
75
+
76
+ - always runs `npx nuxt prepare`
77
+ - if Go is available, also runs `go mod download && go mod tidy`
78
+
79
+ #### `nuxt-gin gen`
80
+
81
+ Generates API code from `openapi.yaml`:
82
+
83
+ - Go Gin server code
84
+ - TypeScript axios client code
85
+
86
+ #### `nuxt-gin build`
87
+
88
+ Runs the build-and-pack flow.
89
+
90
+ Flags:
91
+
92
+ - `--skip-go`: skip Go build
93
+ - `--skip-nuxt`: skip Nuxt static build
94
+ - `--binary-name <name>`: override the Go binary name under `.build/.server`
95
+
96
+ #### `nuxt-gin cleanup`
97
+
98
+ Removes generated temp files and build output.
99
+
100
+ #### `nuxt-gin update`
101
+
102
+ Updates project dependencies with a conservative default strategy:
103
+
104
+ - Node: `pnpm update`
105
+ - Go: `go get -u=patch ./... && go mod tidy`
106
+
107
+ Flags:
108
+
109
+ - `--latest`: switch to a more aggressive upgrade strategy
110
+ - `--skip-go`: skip Go dependency updates
111
+ - `--skip-node`: skip Node dependency updates
112
+
113
+ ### 🧩 `pack.config.ts` / `pack.config.json`
114
+
115
+ `nuxt-gin build` can auto-load pack config from the project root with this priority:
116
+
117
+ 1. `pack.config.ts`
118
+ 2. `pack.config.js`
119
+ 3. `pack.config.cjs`
120
+ 4. `pack.config.mjs`
121
+ 5. `pack.config.json`
122
+
123
+ If multiple config files exist, the CLI prints a `warn` and uses the first one by priority.
124
+
125
+ Recommended TypeScript form:
126
+
127
+ ```ts
128
+ import createPackConfig from 'nuxt-gin-tools/src/pack';
129
+
130
+ export default createPackConfig({
131
+ zipName: 'server.7z',
132
+ extraFilesGlobs: ['prisma/**'],
133
+ packageJson: {
134
+ private: true,
135
+ },
136
+ });
137
+ ```
138
+
139
+ Legacy JSON is still supported:
140
+
141
+ ```json
142
+ {
143
+ "zipName": "server.7z",
144
+ "extraFilesGlobs": ["prisma/**"]
145
+ }
146
+ ```
147
+
148
+ Validation behavior:
149
+
150
+ - ❌ obvious type problems produce an `error` and stop packing
151
+ - ⚠️ ambiguous but survivable cases produce a `warn`
152
+ - 📝 example: if both `zipPath` and `zipName` are present, `zipPath` wins and a warning is shown
153
+
154
+ ### 🧱 `pack.config.ts` Helper
155
+
156
+ Use the helper from [`src/pack.ts`](./src/pack.ts):
157
+
158
+ ```ts
159
+ import createPackConfig from 'nuxt-gin-tools/src/pack';
160
+
161
+ export default createPackConfig({
162
+ serverPath: '.build/production/server',
163
+ zipName: 'release.7z',
164
+ });
165
+ ```
166
+
167
+ It provides:
168
+
169
+ - `PackConfig` type
170
+ - `createPackConfig(config)` helper
171
+ - default export as `createPackConfig`
172
+
173
+ ### ⚙️ Runtime Config
174
+
175
+ #### `server.config.json`
176
+
177
+ `dev` reads this file for the main runtime wiring:
178
+
179
+ - `ginPort`: Gin server port
180
+ - `nuxtPort`: Nuxt dev port
181
+ - `baseUrl`: Nuxt base URL
182
+ - `killPortBeforeDevelop`: whether to free ports before dev, default `true`
183
+ - `cleanupBeforeDevelop`: whether to cleanup before dev, default `false`
184
+
185
+ #### Frontend Runtime Exposure
186
+
187
+ `createDefaultConfig` injects values into Nuxt `runtimeConfig.public`:
188
+
189
+ - `public.ginPort`: available in development, `null` in production
190
+ - `public.isDevelopment`: direct development flag
191
+
192
+ Example:
193
+
194
+ ```ts
195
+ const config = useRuntimeConfig();
196
+ const ginPort = config.public.ginPort;
197
+ const isDevelopment = config.public.isDevelopment;
198
+ ```
199
+
200
+ #### `.go-watch.json`
47
201
 
48
- ### `nuxt-gin dev`
202
+ Go watcher rules come from `.go-watch.json`:
203
+
204
+ ```json
205
+ {
206
+ "tmpDir": ".build/.server",
207
+ "testDataDir": "testdata",
208
+ "includeExt": ["go", "tpl", "html"],
209
+ "includeDir": [],
210
+ "includeFile": [],
211
+ "excludeDir": [
212
+ "assets",
213
+ ".build/.server",
214
+ "vendor",
215
+ "testdata",
216
+ "node_modules",
217
+ "vue",
218
+ "api",
219
+ ".vscode",
220
+ ".git"
221
+ ],
222
+ "excludeFile": [],
223
+ "excludeRegex": ["_test.go"]
224
+ }
225
+ ```
226
+
227
+ You can also point to a custom watcher config:
228
+
229
+ ```bash
230
+ NUXT_GIN_WATCH_CONFIG=/path/to/.go-watch.json
231
+ ```
232
+
233
+ ### 🖥️ Environment
234
+
235
+ - Node.js
236
+ - pnpm
237
+ - Go, if you need the Gin side to run
238
+ - `openapi-generator-cli`, only for `nuxt-gin gen`
239
+
240
+ ### 📝 Notes
241
+
242
+ - 💨 Go hot reload no longer depends on Air
243
+ - 👀 The current watcher model is `chokidar` + restart `go run main.go`
244
+ - 🪟 Packaging uses platform-aware executable naming: Windows defaults to `.exe`, Linux/macOS defaults to no extension
245
+
246
+ ---
247
+
248
+ ## 中文
249
+
250
+ ### ✨ 功能亮点
251
+
252
+ - 🚀 一条命令同时启动 Nuxt 与 Go 开发环境
253
+ - 🔁 基于 `chokidar` 的 Go 文件监听与自动重启
254
+ - 📦 内置构建与打包流程,适合产物发布
255
+ - 🧩 支持 `pack.config.ts`,并提供类型化 helper
256
+ - 🛡️ 对打包配置做校验,区分 `warn` 和 `error`
257
+ - 🔧 支持 `--skip-go` 等局部开发参数
258
+
259
+ ### 📦 安装
260
+
261
+ ```bash
262
+ pnpm add -D nuxt-gin-tools
263
+ ```
264
+
265
+ ### ⚡ 快速开始
266
+
267
+ ```bash
268
+ # 可选:初始化依赖
269
+ nuxt-gin install
270
+
271
+ # 同时启动前后端开发环境
272
+ nuxt-gin dev
273
+ ```
274
+
275
+ 常见变体:
276
+
277
+ ```bash
278
+ # 仅启动前端
279
+ nuxt-gin dev --skip-go
280
+
281
+ # 仅启动 Go 监听
282
+ nuxt-gin dev --skip-nuxt
283
+
284
+ # 跳过预清理 / 预安装检查
285
+ nuxt-gin dev --no-cleanup
286
+ ```
287
+
288
+ ### 🗂️ 命令说明
289
+
290
+ #### `nuxt-gin dev`
291
+
292
+ 启动本地开发环境:
49
293
 
50
- 开发模式下会并行运行:
51
294
  - Nuxt:`npx nuxt dev --port=<nuxtPort> --host`
52
- - Go:监听变更并运行 `go run main.go`
295
+ - Go:监听文件变化并重启 `go run main.go`
296
+
297
+ 参数:
298
+
299
+ - `--skip-go`:只启动 Nuxt
300
+ - `--skip-nuxt`:只启动 Go
301
+ - `--no-cleanup`:跳过 develop 前的 cleanup / bootstrap 检查
302
+
303
+ #### `nuxt-gin install`
304
+
305
+ 用于初始化项目:
306
+
307
+ - 总是执行 `npx nuxt prepare`
308
+ - 检测到 Go 后,额外执行 `go mod download && go mod tidy`
309
+
310
+ #### `nuxt-gin gen`
311
+
312
+ 基于 `openapi.yaml` 生成 API 代码:
313
+
314
+ - Go Gin server 代码
315
+ - TypeScript axios 客户端代码
316
+
317
+ #### `nuxt-gin build`
318
+
319
+ 执行构建与打包流程。
320
+
321
+ 参数:
322
+
323
+ - `--skip-go`:跳过 Go 构建
324
+ - `--skip-nuxt`:跳过 Nuxt 静态构建
325
+ - `--binary-name <name>`:覆盖 `.build/.server` 下的 Go 二进制名称
326
+
327
+ #### `nuxt-gin cleanup`
53
328
 
54
- Go 监听规则来自 `.go-watch.json`(见下文)。
329
+ 清理临时文件与构建产物。
55
330
 
56
- ### `nuxt-gin install`
331
+ #### `nuxt-gin update`
57
332
 
58
- - 总是执行:`npx nuxt prepare`
59
- - 检测到 Go 时额外执行:`go mod download && go mod tidy`
333
+ 按偏保守的默认策略更新依赖:
60
334
 
61
- ### `nuxt-gin gen`
335
+ - Node:`pnpm update`
336
+ - Go:`go get -u=patch ./... && go mod tidy`
62
337
 
63
- 依赖 `openapi-generator-cli`,默认会:
64
- - 生成 Go Gin server 相关代码
65
- - 生成 TypeScript axios 客户端代码
338
+ 参数:
66
339
 
67
- ### `nuxt-gin build`
340
+ - `--latest`:切换成更激进的升级策略
341
+ - `--skip-go`:跳过 Go 依赖更新
342
+ - `--skip-node`:跳过 Node 依赖更新
68
343
 
69
- 执行工具链内置的构建与打包逻辑。
344
+ ### 🧩 `pack.config.ts` / `pack.config.json`
70
345
 
71
- ### `nuxt-gin cleanup`
346
+ `nuxt-gin build` 会自动读取项目根目录中的打包配置,优先级如下:
72
347
 
73
- 清理由工具链生成的临时目录和产物。
348
+ 1. `pack.config.ts`
349
+ 2. `pack.config.js`
350
+ 3. `pack.config.cjs`
351
+ 4. `pack.config.mjs`
352
+ 5. `pack.config.json`
353
+
354
+ 如果同时存在多个配置文件,CLI 会输出 `warn`,并按优先级选择第一个。
355
+
356
+ 推荐使用 TypeScript 写法:
357
+
358
+ ```ts
359
+ import createPackConfig from 'nuxt-gin-tools/src/pack';
360
+
361
+ export default createPackConfig({
362
+ zipName: 'server.7z',
363
+ extraFilesGlobs: ['prisma/**'],
364
+ packageJson: {
365
+ private: true,
366
+ },
367
+ });
368
+ ```
369
+
370
+ 旧的 JSON 配置仍然兼容:
371
+
372
+ ```json
373
+ {
374
+ "zipName": "server.7z",
375
+ "extraFilesGlobs": ["prisma/**"]
376
+ }
377
+ ```
378
+
379
+ 校验规则:
380
+
381
+ - ❌ 明显类型错误会直接 `error` 并终止打包
382
+ - ⚠️ 可继续执行但存在歧义的情况会输出 `warn`
383
+ - 📝 例如同时设置 `zipPath` 和 `zipName` 时,会提示 `zipPath` 优先生效
384
+
385
+ ### 🧱 `pack.config.ts` Helper
386
+
387
+ 可通过 [`src/pack.ts`](./src/pack.ts) 使用 helper:
388
+
389
+ ```ts
390
+ import createPackConfig from 'nuxt-gin-tools/src/pack';
391
+
392
+ export default createPackConfig({
393
+ serverPath: '.build/production/server',
394
+ zipName: 'release.7z',
395
+ });
396
+ ```
74
397
 
75
- ### `nuxt-gin update`
398
+ 它提供:
76
399
 
77
- 执行项目约定的更新逻辑。
400
+ - `PackConfig` 类型
401
+ - `createPackConfig(config)` 函数
402
+ - 默认导出即 `createPackConfig`
78
403
 
79
- ## 配置
404
+ ### ⚙️ 运行时配置
80
405
 
81
- ### 1) `server.config.json`
406
+ #### `server.config.json`
82
407
 
83
- `dev` 命令会读取该文件,常用字段:
408
+ `dev` 命令会读取这个文件来确定运行方式:
84
409
 
85
- - `ginPort`: Gin 服务端口
86
- - `nuxtPort`: Nuxt 开发端口
87
- - `baseUrl`: Nuxt baseUrl
88
- - `killPortBeforeDevelop`: 开发前是否释放端口(默认 `true`)
89
- - `cleanupBeforeDevelop`: 开发前是否执行 cleanup(默认 `false`)
410
+ - `ginPort`:Gin 服务端口
411
+ - `nuxtPort`:Nuxt 开发端口
412
+ - `baseUrl`:Nuxt 的 base URL
413
+ - `killPortBeforeDevelop`:开发前是否释放端口,默认 `true`
414
+ - `cleanupBeforeDevelop`:开发前是否执行 cleanup,默认 `false`
90
415
 
91
- ### 3) 开发环境向前端暴露 `ginPort`
416
+ #### 前端运行时暴露
92
417
 
93
- `createDefaultConfig` 会在 Nuxt `runtimeConfig.public` 中注入 `ginPort`:
418
+ `createDefaultConfig` 会把以下值注入 Nuxt `runtimeConfig.public`:
94
419
 
95
- - 开发环境:`useRuntimeConfig().public.ginPort` `server.config.json` 的 `ginPort`
96
- - 生产环境:`useRuntimeConfig().public.ginPort` 为 `null`
97
- - 所有环境:`useRuntimeConfig().public.isDevelopment` 直接暴露当前是否开发环境
420
+ - `public.ginPort`:开发环境可读,生产环境为 `null`
421
+ - `public.isDevelopment`:当前是否为开发环境
98
422
 
99
- 前端示例:
423
+ 示例:
100
424
 
101
425
  ```ts
102
426
  const config = useRuntimeConfig();
@@ -104,9 +428,9 @@ const ginPort = config.public.ginPort;
104
428
  const isDevelopment = config.public.isDevelopment;
105
429
  ```
106
430
 
107
- ### 2) `.go-watch.json`
431
+ #### `.go-watch.json`
108
432
 
109
- Go 监听配置文件,示例:
433
+ Go 监听规则来自 `.go-watch.json`:
110
434
 
111
435
  ```json
112
436
  {
@@ -131,20 +455,21 @@ Go 监听配置文件,示例:
131
455
  }
132
456
  ```
133
457
 
134
- 也支持环境变量指定路径:
458
+ 也支持通过环境变量指定:
135
459
 
136
460
  ```bash
137
461
  NUXT_GIN_WATCH_CONFIG=/path/to/.go-watch.json
138
462
  ```
139
463
 
140
- ## 环境依赖
464
+ ### 🖥️ 环境依赖
141
465
 
142
466
  - Node.js
143
467
  - pnpm
144
- - Go(需要运行 Gin 侧开发与依赖下载时)
145
- - `openapi-generator-cli`(仅 `nuxt-gin gen` 需要)
468
+ - Go,若需要运行 Gin 侧开发流程
469
+ - `openapi-generator-cli`,仅 `nuxt-gin gen` 需要
146
470
 
147
- ## 说明
471
+ ### 📝 说明
148
472
 
149
- - Go 侧热更新已不再依赖 Air
150
- - 当前方案为:`chokidar` 监听文件变化 + 重启 `go run main.go`。
473
+ - 💨 Go 热更新不再依赖 Air
474
+ - 👀 当前 Go 开发监听方案为 `chokidar` + 重启 `go run main.go`
475
+ - 🪟 打包时会按平台生成可执行文件名:Windows 默认 `.exe`,Linux/macOS 默认无扩展名
@@ -1,56 +1,4 @@
1
- import type { BuildOptions } from "./builder";
2
- export interface PackConfig extends BuildOptions {
3
- /**
4
- * 额外需要打包的文件映射
5
- * key: 源文件路径(相对于项目根目录或绝对路径)
6
- * value: 打包后对应位置(相对于服务器构建目录或绝对路径)
7
- */
8
- extraFiles?: Record<string, string>;
9
- /**
10
- * 额外需要打包的文件 Glob(相对于项目根目录)
11
- */
12
- extraFilesGlobs?: string[];
13
- /**
14
- * 排除文件/目录 Glob(相对于项目根目录)
15
- */
16
- exclude?: string[];
17
- /**
18
- * 打包输出 zip 名称(相对于默认 zip 目录)
19
- */
20
- zipName?: string;
21
- /**
22
- * 打包输出 zip 路径(相对于项目根目录或绝对路径)
23
- */
24
- zipPath?: string;
25
- /**
26
- * 服务器构建输出目录(相对于项目根目录或绝对路径)
27
- */
28
- serverPath?: string;
29
- /**
30
- * 打包前钩子
31
- */
32
- beforePack?: () => Promise<void> | void;
33
- /**
34
- * 打包后钩子
35
- */
36
- afterPack?: (zipPath: string) => Promise<void> | void;
37
- /**
38
- * 是否清理 dist
39
- */
40
- cleanDist?: boolean;
41
- /**
42
- * 是否写入启动脚本和 package.json
43
- */
44
- writeScripts?: boolean;
45
- /**
46
- * 写入/覆盖 package.json 内容
47
- */
48
- packageJson?: Record<string, unknown>;
49
- /**
50
- * 复制时是否覆盖同名文件
51
- */
52
- overwrite?: boolean;
53
- }
1
+ import type { PackConfig } from "../src/pack";
54
2
  /**
55
3
  * 生成相对于服务器构建目录的绝对路径
56
4
  * @param relativePath - 相对路径
@@ -61,6 +9,10 @@ export declare const ZIP_PATH: string;
61
9
  export declare const SERVER_PATH: string;
62
10
  export declare const ORIGINAL_DIST_PATH: string;
63
11
  export declare const PACK_CONFIG_PATH: string;
12
+ export declare const PACK_CONFIG_TS_PATH: string;
13
+ export declare const PACK_CONFIG_JS_PATH: string;
14
+ export declare const PACK_CONFIG_CJS_PATH: string;
15
+ export declare const PACK_CONFIG_MJS_PATH: string;
64
16
  export declare const BUILD_EXECUTABLE: string;
65
17
  export declare const SERVER_EXECUTABLE: string;
66
18
  export declare const PACKAGE_JSON_CONTENT: {
package/commands/pack.js CHANGED
@@ -45,7 +45,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
45
45
  return (mod && mod.__esModule) ? mod : { "default": mod };
46
46
  };
47
47
  Object.defineProperty(exports, "__esModule", { value: true });
48
- exports.FILES_TO_COPY = exports.PACKAGE_JSON_CONTENT = exports.SERVER_EXECUTABLE = exports.BUILD_EXECUTABLE = exports.PACK_CONFIG_PATH = exports.ORIGINAL_DIST_PATH = exports.SERVER_PATH = exports.ZIP_PATH = void 0;
48
+ exports.FILES_TO_COPY = exports.PACKAGE_JSON_CONTENT = exports.SERVER_EXECUTABLE = exports.BUILD_EXECUTABLE = exports.PACK_CONFIG_MJS_PATH = exports.PACK_CONFIG_CJS_PATH = exports.PACK_CONFIG_JS_PATH = exports.PACK_CONFIG_TS_PATH = exports.PACK_CONFIG_PATH = exports.ORIGINAL_DIST_PATH = exports.SERVER_PATH = exports.ZIP_PATH = void 0;
49
49
  exports.builtPath = builtPath;
50
50
  exports.buildAndPack = buildAndPack;
51
51
  // 导入项目构建工具,用于执行 Nuxt 项目的构建流程
@@ -58,6 +58,7 @@ const FS = __importStar(require("fs-extra"));
58
58
  const Path = __importStar(require("path"));
59
59
  const os = __importStar(require("os"));
60
60
  const fast_glob_1 = __importDefault(require("fast-glob"));
61
+ const { createJiti } = require("jiti");
61
62
  /**
62
63
  * 生成相对于服务器构建目录的绝对路径
63
64
  * @param relativePath - 相对路径
@@ -73,6 +74,10 @@ exports.SERVER_PATH = Path.resolve(process.cwd(), ".build/production/server");
73
74
  // 定义原始 dist 目录路径,用于清理操作
74
75
  exports.ORIGINAL_DIST_PATH = Path.resolve(process.cwd(), "dist");
75
76
  exports.PACK_CONFIG_PATH = Path.resolve(process.cwd(), "pack.config.json");
77
+ exports.PACK_CONFIG_TS_PATH = Path.resolve(process.cwd(), "pack.config.ts");
78
+ exports.PACK_CONFIG_JS_PATH = Path.resolve(process.cwd(), "pack.config.js");
79
+ exports.PACK_CONFIG_CJS_PATH = Path.resolve(process.cwd(), "pack.config.cjs");
80
+ exports.PACK_CONFIG_MJS_PATH = Path.resolve(process.cwd(), "pack.config.mjs");
76
81
  exports.BUILD_EXECUTABLE = os.platform() === "win32" ? "production.exe" : "production";
77
82
  exports.SERVER_EXECUTABLE = os.platform() === "win32" ? "server-production.exe" : "server-production"; // 根据操作系统选择可执行文件名
78
83
  // 定义打包后项目的 package.json 内容
@@ -90,6 +95,94 @@ const DEFAULT_FILES_TO_COPY = {
90
95
  };
91
96
  // 兼容旧导出:默认构建目录下的绝对目标路径
92
97
  exports.FILES_TO_COPY = Object.fromEntries(Object.entries(DEFAULT_FILES_TO_COPY).map(([src, dest]) => [src, builtPath(dest)]));
98
+ function warnPackConfig(message) {
99
+ console.warn(`[nuxt-gin-tools][pack] WARN: ${message}`);
100
+ }
101
+ function errorPackConfig(message) {
102
+ throw new Error(`[nuxt-gin-tools][pack] ${message}`);
103
+ }
104
+ function isPlainObject(value) {
105
+ return typeof value === "object" && value !== null && !Array.isArray(value);
106
+ }
107
+ function validateStringArray(fieldName, value, issues) {
108
+ if (value === undefined) {
109
+ return;
110
+ }
111
+ if (!Array.isArray(value)) {
112
+ issues.push({ level: "error", message: `${fieldName} must be an array of strings` });
113
+ return;
114
+ }
115
+ for (const item of value) {
116
+ if (typeof item !== "string") {
117
+ issues.push({ level: "error", message: `${fieldName} must contain only strings` });
118
+ return;
119
+ }
120
+ }
121
+ }
122
+ function validateStringRecord(fieldName, value, issues) {
123
+ if (value === undefined) {
124
+ return;
125
+ }
126
+ if (!isPlainObject(value)) {
127
+ issues.push({ level: "error", message: `${fieldName} must be an object of string to string` });
128
+ return;
129
+ }
130
+ for (const [key, item] of Object.entries(value)) {
131
+ if (typeof key !== "string" || typeof item !== "string") {
132
+ issues.push({ level: "error", message: `${fieldName} must be an object of string to string` });
133
+ return;
134
+ }
135
+ }
136
+ }
137
+ function validatePackConfig(config, sourcePath) {
138
+ if (!isPlainObject(config)) {
139
+ errorPackConfig(`${Path.basename(sourcePath)} must export an object`);
140
+ }
141
+ const issues = [];
142
+ const typedConfig = config;
143
+ const stringFields = ["binaryName", "zipName", "zipPath", "serverPath"];
144
+ for (const field of stringFields) {
145
+ const value = typedConfig[field];
146
+ if (value !== undefined && typeof value !== "string") {
147
+ issues.push({ level: "error", message: `${field} must be a string` });
148
+ }
149
+ }
150
+ const booleanFields = ["skipGo", "skipNuxt", "cleanDist", "writeScripts", "overwrite"];
151
+ for (const field of booleanFields) {
152
+ const value = typedConfig[field];
153
+ if (value !== undefined && typeof value !== "boolean") {
154
+ issues.push({ level: "error", message: `${field} must be a boolean` });
155
+ }
156
+ }
157
+ validateStringArray("extraFilesGlobs", typedConfig.extraFilesGlobs, issues);
158
+ validateStringArray("exclude", typedConfig.exclude, issues);
159
+ validateStringRecord("extraFiles", typedConfig.extraFiles, issues);
160
+ if (typedConfig.packageJson !== undefined && !isPlainObject(typedConfig.packageJson)) {
161
+ issues.push({ level: "error", message: `packageJson must be an object` });
162
+ }
163
+ if (typedConfig.beforePack !== undefined && typeof typedConfig.beforePack !== "function") {
164
+ issues.push({ level: "error", message: `beforePack must be a function` });
165
+ }
166
+ if (typedConfig.afterPack !== undefined && typeof typedConfig.afterPack !== "function") {
167
+ issues.push({ level: "error", message: `afterPack must be a function` });
168
+ }
169
+ if (typedConfig.zipName !== undefined && typedConfig.zipPath !== undefined) {
170
+ issues.push({ level: "warn", message: `zipPath and zipName are both set; zipPath takes precedence` });
171
+ }
172
+ if (typedConfig.skipGo === true && typedConfig.skipNuxt === true) {
173
+ issues.push({ level: "warn", message: `skipGo and skipNuxt are both true; build step will be skipped` });
174
+ }
175
+ for (const issue of issues) {
176
+ if (issue.level === "warn") {
177
+ warnPackConfig(`${Path.basename(sourcePath)}: ${issue.message}`);
178
+ }
179
+ }
180
+ const errors = issues.filter((issue) => issue.level === "error");
181
+ if (errors.length > 0) {
182
+ errorPackConfig(`${Path.basename(sourcePath)} is invalid:\n- ${errors.map((item) => item.message).join("\n- ")}`);
183
+ }
184
+ return config;
185
+ }
93
186
  /**
94
187
  * 写入启动脚本和 package.json 文件到构建目录
95
188
  */
@@ -148,10 +241,32 @@ function mergePackageJson(base, override) {
148
241
  return Object.assign(Object.assign(Object.assign({}, base), override), { scripts: Object.assign(Object.assign({}, baseScripts), overrideScripts) });
149
242
  }
150
243
  function readPackConfigFromCwd() {
151
- if (!FS.existsSync(exports.PACK_CONFIG_PATH)) {
244
+ const candidates = [
245
+ exports.PACK_CONFIG_TS_PATH,
246
+ exports.PACK_CONFIG_JS_PATH,
247
+ exports.PACK_CONFIG_CJS_PATH,
248
+ exports.PACK_CONFIG_MJS_PATH,
249
+ exports.PACK_CONFIG_PATH,
250
+ ].filter((configPath) => FS.existsSync(configPath));
251
+ if (candidates.length === 0) {
152
252
  return undefined;
153
253
  }
154
- return FS.readJSONSync(exports.PACK_CONFIG_PATH);
254
+ if (candidates.length > 1) {
255
+ warnPackConfig(`multiple pack config files found (${candidates.map((item) => Path.basename(item)).join(", ")}); using ${Path.basename(candidates[0])}`);
256
+ }
257
+ const selectedPath = candidates[0];
258
+ let loadedConfig;
259
+ if (selectedPath.endsWith(".json")) {
260
+ loadedConfig = FS.readJSONSync(selectedPath);
261
+ }
262
+ else {
263
+ const jiti = createJiti(__filename, { moduleCache: false, interopDefault: true });
264
+ loadedConfig = jiti(selectedPath);
265
+ }
266
+ const normalizedConfig = isPlainObject(loadedConfig) && "default" in loadedConfig
267
+ ? loadedConfig.default
268
+ : loadedConfig;
269
+ return validatePackConfig(normalizedConfig, selectedPath);
155
270
  }
156
271
  function resolveServerPath(config) {
157
272
  if (!(config === null || config === void 0 ? void 0 : config.serverPath)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-gin-tools",
3
- "version": "0.2.18",
3
+ "version": "0.2.20",
4
4
  "description": "This project is used as a dependency for [nuxt-gin-starter](https://github.com/RapboyGao/nuxt-gin-starter.git)",
5
5
  "bin": {
6
6
  "nuxt-gin": "index.js"
@@ -18,7 +18,8 @@
18
18
  "chokidar": "^3.6.0",
19
19
  "concurrently": "^9.2.0",
20
20
  "fast-glob": "^3.3.3",
21
- "fs-extra": "^11.3.0"
21
+ "fs-extra": "^11.3.0",
22
+ "jiti": "^2.6.1"
22
23
  },
23
24
  "devDependencies": {
24
25
  "@types/fs-extra": "^11.0.4",
package/src/pack.d.ts ADDED
@@ -0,0 +1,55 @@
1
+ import type { BuildOptions } from "../commands/builder";
2
+ export interface PackConfig extends BuildOptions {
3
+ /**
4
+ * 额外需要打包的文件映射
5
+ * key: 源文件路径(相对于项目根目录或绝对路径)
6
+ * value: 打包后对应位置(相对于服务器构建目录或绝对路径)
7
+ */
8
+ extraFiles?: Record<string, string>;
9
+ /**
10
+ * 额外需要打包的文件 Glob(相对于项目根目录)
11
+ */
12
+ extraFilesGlobs?: string[];
13
+ /**
14
+ * 排除文件/目录 Glob(相对于项目根目录)
15
+ */
16
+ exclude?: string[];
17
+ /**
18
+ * 打包输出 zip 名称(相对于默认 zip 目录)
19
+ */
20
+ zipName?: string;
21
+ /**
22
+ * 打包输出 zip 路径(相对于项目根目录或绝对路径)
23
+ */
24
+ zipPath?: string;
25
+ /**
26
+ * 服务器构建输出目录(相对于项目根目录或绝对路径)
27
+ */
28
+ serverPath?: string;
29
+ /**
30
+ * 打包前钩子
31
+ */
32
+ beforePack?: () => Promise<void> | void;
33
+ /**
34
+ * 打包后钩子
35
+ */
36
+ afterPack?: (zipPath: string) => Promise<void> | void;
37
+ /**
38
+ * 是否清理 dist
39
+ */
40
+ cleanDist?: boolean;
41
+ /**
42
+ * 是否写入启动脚本和 package.json
43
+ */
44
+ writeScripts?: boolean;
45
+ /**
46
+ * 写入/覆盖 package.json 内容
47
+ */
48
+ packageJson?: Record<string, unknown>;
49
+ /**
50
+ * 复制时是否覆盖同名文件
51
+ */
52
+ overwrite?: boolean;
53
+ }
54
+ export declare function createPackConfig(config: PackConfig): PackConfig;
55
+ export default createPackConfig;
package/src/pack.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createPackConfig = createPackConfig;
4
+ function createPackConfig(config) {
5
+ return config;
6
+ }
7
+ exports.default = createPackConfig;