@ahoo-wang/fetcher-generator 2.1.1 → 2.2.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 +190 -58
- package/README.zh-CN.md +406 -0
- package/dist/cli.cjs +1 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.ts +10 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +59 -33
- package/dist/cli.js.map +1 -1
- package/dist/client/clientGenerator.d.ts.map +1 -1
- package/dist/client/commandClientGenerator.d.ts.map +1 -1
- package/dist/client/queryClientGenerator.d.ts.map +1 -1
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +736 -499
- package/dist/index.js.map +1 -1
- package/dist/model/modelGenerator.d.ts.map +1 -1
- package/dist/types.d.ts +3 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +4 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/sourceFiles.d.ts.map +1 -1
- package/package.json +9 -8
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
# @ahoo-wang/fetcher-generator
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@ahoo-wang/fetcher-generator)
|
|
4
|
+
[](https://github.com/Ahoo-Wang/fetcher/actions)
|
|
5
|
+
[](https://codecov.io/gh/Ahoo-Wang/fetcher)
|
|
6
|
+
[](https://github.com/Ahoo-Wang/fetcher/blob/main/LICENSE)
|
|
7
|
+
[](https://www.npmjs.com/package/@ahoo-wang/fetcher-generator)
|
|
8
|
+
[](https://www.npmjs.com/package/@ahoo-wang/fetcher-generator)
|
|
9
|
+
|
|
10
|
+
从 OpenAPI 规范生成 TypeScript 代码,专为 [Wow](https://github.com/Ahoo-Wang/Wow) 领域驱动设计框架打造。生成类型安全的模型、查询客户端和命令客户端。
|
|
11
|
+
|
|
12
|
+
**[Wow](https://github.com/Ahoo-Wang/Wow) 框架**:一个领域驱动设计框架,提供事件溯源、CQRS(命令查询责任分离)和聚合模式,用于构建可扩展的分布式系统。
|
|
13
|
+
|
|
14
|
+
## 🌟 特性
|
|
15
|
+
|
|
16
|
+
- **🎯 OpenAPI 3.0+ 支持**:完整支持 OpenAPI 3.0+ 规范(JSON/YAML)
|
|
17
|
+
- **📦 TypeScript 代码生成**:生成类型安全的 TypeScript 接口、枚举和类
|
|
18
|
+
- **🏗️ 领域驱动设计**:专为 WOW 框架打造,支持聚合、命令、查询和领域事件
|
|
19
|
+
- **🔧 CLI 工具**:易用的命令行界面,用于代码生成
|
|
20
|
+
- **🎨 装饰器式 API**:生成装饰器式的客户端类,实现清晰的 API 交互
|
|
21
|
+
- **📋 全面的模型**:处理复杂的模式,包括联合、交集、枚举和引用
|
|
22
|
+
- **🚀 Fetcher 生态集成**:无缝集成 Fetcher 生态系统包
|
|
23
|
+
- **📊 进度日志**:生成过程中的友好日志记录和进度指示器
|
|
24
|
+
- **📁 自动索引生成**:自动生成 index.ts 文件,实现清晰的模块组织
|
|
25
|
+
- **🌐 远程规范支持**:直接从 HTTP/HTTPS URL 加载 OpenAPI 规范
|
|
26
|
+
- **🎭 事件流**:生成常规和事件流命令客户端
|
|
27
|
+
|
|
28
|
+
## 🚀 快速开始
|
|
29
|
+
|
|
30
|
+
### 安装
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# 使用 npm
|
|
34
|
+
npm install -g @ahoo-wang/fetcher-generator
|
|
35
|
+
|
|
36
|
+
# 使用 pnpm
|
|
37
|
+
pnpm add -g @ahoo-wang/fetcher-generator
|
|
38
|
+
|
|
39
|
+
# 使用 yarn
|
|
40
|
+
yarn global add @ahoo-wang/fetcher-generator
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 基本用法
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# 从 OpenAPI 规范生成 TypeScript 代码
|
|
47
|
+
fetcher-generator generate -i ./openapi-spec.json -o ./generated
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 📖 使用方法
|
|
51
|
+
|
|
52
|
+
### 命令行界面
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
fetcher-generator generate [options]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
#### 选项
|
|
59
|
+
|
|
60
|
+
- `-i, --input <path>`:输入 OpenAPI 规范文件路径或 URL(必需)
|
|
61
|
+
- 支持本地文件路径(例如:`./api-spec.json`、`./api-spec.yaml`)
|
|
62
|
+
- 支持 HTTP/HTTPS URL(例如:`https://api.example.com/openapi.json`)
|
|
63
|
+
- `-o, --output <path>`:输出目录路径(默认为 `src/generated`)
|
|
64
|
+
- `-c, --config <file>`:配置文件路径(可选)
|
|
65
|
+
- `-v, --verbose`:启用详细日志记录
|
|
66
|
+
- `--dry-run`:显示将要生成的内容而不写入文件(保留供将来使用)
|
|
67
|
+
- `-h, --help`:显示帮助信息
|
|
68
|
+
- `-V, --version`:显示版本号
|
|
69
|
+
|
|
70
|
+
#### 示例
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# 从本地 OpenAPI JSON 文件生成代码
|
|
74
|
+
fetcher-generator generate -i ./api-spec.json -o ./src/generated
|
|
75
|
+
|
|
76
|
+
# 从 YAML 规范生成代码
|
|
77
|
+
fetcher-generator generate -i ./api-spec.yaml -o ./src/generated
|
|
78
|
+
|
|
79
|
+
# 从远程 OpenAPI 规范通过 HTTPS 生成代码
|
|
80
|
+
fetcher-generator generate -i https://api.example.com/openapi.json -o ./src/generated
|
|
81
|
+
|
|
82
|
+
# 从远程 YAML 规范通过 HTTP 生成代码
|
|
83
|
+
fetcher-generator generate -i http://localhost:8080/api-spec.yaml -o ./src/generated
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 生成的代码结构
|
|
87
|
+
|
|
88
|
+
生成器在输出目录中创建以下结构:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
output/
|
|
92
|
+
├── {bounded-context}/
|
|
93
|
+
│ ├── index.ts # 自动生成的索引文件,导出所有聚合
|
|
94
|
+
│ ├── boundedContext.ts # 有界上下文别名常量
|
|
95
|
+
│ ├── types.ts # 有界上下文的共享类型
|
|
96
|
+
│ └── {aggregate}/ # 聚合特定文件
|
|
97
|
+
│ ├── index.ts # 聚合的自动生成索引文件
|
|
98
|
+
│ ├── types.ts # 聚合特定类型、模型和枚举
|
|
99
|
+
│ ├── queryClient.ts # 查询客户端工厂,用于状态和事件查询
|
|
100
|
+
│ └── commandClient.ts # 命令客户端类(常规和流式)
|
|
101
|
+
├── index.ts # 根索引文件,导出所有有界上下文
|
|
102
|
+
└── tsconfig.json # 生成代码的 TypeScript 配置
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### 索引文件生成
|
|
106
|
+
|
|
107
|
+
生成器自动创建 `index.ts` 文件,为便捷的模块导出提供支持:
|
|
108
|
+
|
|
109
|
+
- **根 index.ts**:导出所有有界上下文
|
|
110
|
+
- **有界上下文 index.ts**:导出上下文中的所有聚合
|
|
111
|
+
- **聚合 index.ts**:导出聚合中的所有文件
|
|
112
|
+
|
|
113
|
+
这允许干净的导入,例如:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// 导入有界上下文的所有内容
|
|
117
|
+
import * as compensation from './generated/compensation';
|
|
118
|
+
|
|
119
|
+
// 导入特定聚合
|
|
120
|
+
import { executionFailed } from './generated/compensation';
|
|
121
|
+
|
|
122
|
+
// 导入特定文件
|
|
123
|
+
import { ExecutionFailedState } from './generated/compensation/execution_failed';
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 🎯 生成的代码示例
|
|
127
|
+
|
|
128
|
+
### 模型
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
/** apply_execution_failed */
|
|
132
|
+
export interface ApplyExecutionFailed {
|
|
133
|
+
error: ErrorDetails;
|
|
134
|
+
executeAt: number;
|
|
135
|
+
recoverable: RecoverableType | undefined;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** apply_execution_success */
|
|
139
|
+
export interface ApplyExecutionSuccess {
|
|
140
|
+
executeAt: number;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** execution_failed_status */
|
|
144
|
+
export enum ExecutionFailedStatus {
|
|
145
|
+
PREPARED = 'PREPARED',
|
|
146
|
+
SUCCEEDED = 'SUCCEEDED',
|
|
147
|
+
FAILED = 'FAILED',
|
|
148
|
+
COMPENSATED = 'COMPENSATED',
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 查询客户端
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// 生成的查询客户端工厂,用于领域驱动设计
|
|
156
|
+
import {
|
|
157
|
+
QueryClientFactory,
|
|
158
|
+
QueryClientOptions,
|
|
159
|
+
ResourceAttributionPathSpec,
|
|
160
|
+
} from '@ahoo-wang/fetcher-wow';
|
|
161
|
+
import {
|
|
162
|
+
CartAggregatedFields,
|
|
163
|
+
CartItemAdded,
|
|
164
|
+
CartItemRemoved,
|
|
165
|
+
CartQuantityChanged,
|
|
166
|
+
CartState,
|
|
167
|
+
} from './types';
|
|
168
|
+
|
|
169
|
+
const DEFAULT_QUERY_CLIENT_OPTIONS: QueryClientOptions = {
|
|
170
|
+
contextAlias: 'example',
|
|
171
|
+
aggregateName: 'cart',
|
|
172
|
+
resourceAttribution: ResourceAttributionPathSpec.OWNER,
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
type DOMAIN_EVENT_TYPES = CartItemAdded | CartItemRemoved | CartQuantityChanged;
|
|
176
|
+
|
|
177
|
+
export const cartQueryClientFactory = new QueryClientFactory<
|
|
178
|
+
CartState,
|
|
179
|
+
CartAggregatedFields | string,
|
|
180
|
+
DOMAIN_EVENT_TYPES
|
|
181
|
+
>(DEFAULT_QUERY_CLIENT_OPTIONS);
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 命令客户端
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
// 生成的命令客户端,具有装饰器式 API
|
|
188
|
+
import { ContentTypeValues } from '@ahoo-wang/fetcher';
|
|
189
|
+
import {
|
|
190
|
+
type ApiMetadata,
|
|
191
|
+
type ApiMetadataCapable,
|
|
192
|
+
api,
|
|
193
|
+
attribute,
|
|
194
|
+
autoGeneratedError,
|
|
195
|
+
del,
|
|
196
|
+
path,
|
|
197
|
+
post,
|
|
198
|
+
put,
|
|
199
|
+
request,
|
|
200
|
+
} from '@ahoo-wang/fetcher-decorator';
|
|
201
|
+
import { JsonEventStreamResultExtractor } from '@ahoo-wang/fetcher-eventstream';
|
|
202
|
+
import type {
|
|
203
|
+
CommandRequest,
|
|
204
|
+
CommandResult,
|
|
205
|
+
CommandResultEventStream,
|
|
206
|
+
DeleteAggregate,
|
|
207
|
+
RecoverAggregate,
|
|
208
|
+
} from '@ahoo-wang/fetcher-wow';
|
|
209
|
+
import {
|
|
210
|
+
AddCartItem,
|
|
211
|
+
ChangeQuantity,
|
|
212
|
+
MockVariableCommand,
|
|
213
|
+
MountedCommand,
|
|
214
|
+
RemoveCartItem,
|
|
215
|
+
ViewCart,
|
|
216
|
+
} from './types';
|
|
217
|
+
|
|
218
|
+
enum COMMAND_ENDPOINT_PATHS {
|
|
219
|
+
VIEW_CART = '/owner/{ownerId}/cart/view_cart',
|
|
220
|
+
ADD_CART_ITEM = '/owner/{ownerId}/cart/add_cart_item',
|
|
221
|
+
CHANGE_QUANTITY = '/owner/{ownerId}/cart/change_quantity',
|
|
222
|
+
REMOVE_CART_ITEM = '/owner/{ownerId}/cart/remove_cart_item',
|
|
223
|
+
MOUNTED_COMMAND = '/owner/{ownerId}/cart/mounted_command',
|
|
224
|
+
MOCK_VARIABLE_COMMAND = '/tenant/{tenantId}/owner/{ownerId}/cart/{id}/{customerId}/{mockEnum}',
|
|
225
|
+
DEFAULT_DELETE_AGGREGATE = '/owner/{ownerId}/cart',
|
|
226
|
+
DEFAULT_RECOVER_AGGREGATE = '/owner/{ownerId}/cart/recover',
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const DEFAULT_COMMAND_CLIENT_OPTIONS: ApiMetadata = {
|
|
230
|
+
basePath: 'example',
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
@api()
|
|
234
|
+
export class CartCommandClient implements ApiMetadataCapable {
|
|
235
|
+
constructor(
|
|
236
|
+
public readonly apiMetadata: ApiMetadata = DEFAULT_COMMAND_CLIENT_OPTIONS,
|
|
237
|
+
) {}
|
|
238
|
+
|
|
239
|
+
/** view_cart */
|
|
240
|
+
@put(COMMAND_ENDPOINT_PATHS.VIEW_CART)
|
|
241
|
+
viewCart(
|
|
242
|
+
@request() commandRequest: CommandRequest<ViewCart>,
|
|
243
|
+
@attribute() attributes: Record<string, any>,
|
|
244
|
+
): Promise<CommandResult> {
|
|
245
|
+
throw autoGeneratedError(commandRequest, attributes);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* 加入购物车
|
|
250
|
+
* 加入购物车
|
|
251
|
+
*/
|
|
252
|
+
@post(COMMAND_ENDPOINT_PATHS.ADD_CART_ITEM)
|
|
253
|
+
addCartItem(
|
|
254
|
+
@request() commandRequest: CommandRequest<AddCartItem>,
|
|
255
|
+
@attribute() attributes: Record<string, any>,
|
|
256
|
+
): Promise<CommandResult> {
|
|
257
|
+
throw autoGeneratedError(commandRequest, attributes);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** 变更购买数量 */
|
|
261
|
+
@put(COMMAND_ENDPOINT_PATHS.CHANGE_QUANTITY)
|
|
262
|
+
changeQuantity(
|
|
263
|
+
@request() commandRequest: CommandRequest<ChangeQuantity>,
|
|
264
|
+
@attribute() attributes: Record<string, any>,
|
|
265
|
+
): Promise<CommandResult> {
|
|
266
|
+
throw autoGeneratedError(commandRequest, attributes);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** 删除商品 */
|
|
270
|
+
@put(COMMAND_ENDPOINT_PATHS.REMOVE_CART_ITEM)
|
|
271
|
+
removeCartItem(
|
|
272
|
+
@request() commandRequest: CommandRequest<RemoveCartItem>,
|
|
273
|
+
@attribute() attributes: Record<string, any>,
|
|
274
|
+
): Promise<CommandResult> {
|
|
275
|
+
throw autoGeneratedError(commandRequest, attributes);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
生成器还创建流式命令客户端,用于事件驱动的交互:
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
@api('', {
|
|
284
|
+
headers: { Accept: ContentTypeValues.TEXT_EVENT_STREAM },
|
|
285
|
+
resultExtractor: JsonEventStreamResultExtractor,
|
|
286
|
+
})
|
|
287
|
+
export class CartStreamCommandClient implements ApiMetadataCapable {
|
|
288
|
+
constructor(
|
|
289
|
+
public readonly apiMetadata: ApiMetadata = DEFAULT_COMMAND_CLIENT_OPTIONS,
|
|
290
|
+
) {}
|
|
291
|
+
|
|
292
|
+
/** view_cart */
|
|
293
|
+
@put(COMMAND_ENDPOINT_PATHS.VIEW_CART)
|
|
294
|
+
viewCart(
|
|
295
|
+
@request() commandRequest: CommandRequest<ViewCart>,
|
|
296
|
+
@attribute() attributes: Record<string, any>,
|
|
297
|
+
): Promise<CommandResultEventStream> {
|
|
298
|
+
throw autoGeneratedError(commandRequest, attributes);
|
|
299
|
+
}
|
|
300
|
+
// ... 其他流式方法
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## 🔧 与 Fetcher 集成
|
|
305
|
+
|
|
306
|
+
生成的代码设计为与 Fetcher 生态系统无缝集成:
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
import { Fetcher } from '@ahoo-wang/fetcher';
|
|
310
|
+
import { cartQueryClientFactory } from './generated/example/cart/queryClient';
|
|
311
|
+
import { CartCommandClient } from './generated/example/cart/commandClient';
|
|
312
|
+
|
|
313
|
+
// 创建 fetcher 实例
|
|
314
|
+
const fetcher = new Fetcher({
|
|
315
|
+
baseURL: 'https://api.example.com',
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// 注册 fetcher(如果使用命名 fetcher)
|
|
319
|
+
Fetcher.register('api', fetcher);
|
|
320
|
+
|
|
321
|
+
// 使用生成的查询客户端工厂
|
|
322
|
+
const queryClient = cartQueryClientFactory.createQueryClient();
|
|
323
|
+
const cartState = await queryClient.loadAggregate('cart-id');
|
|
324
|
+
|
|
325
|
+
// 使用生成的命令客户端
|
|
326
|
+
const commandClient = new CartCommandClient();
|
|
327
|
+
const result = await commandClient.addCartItem(
|
|
328
|
+
{
|
|
329
|
+
command: {
|
|
330
|
+
productId: 'product-123',
|
|
331
|
+
quantity: 2,
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
ownerId: 'user-456',
|
|
336
|
+
},
|
|
337
|
+
);
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## 📋 OpenAPI 规范要求
|
|
341
|
+
|
|
342
|
+
生成器期望 OpenAPI 3.0+ 规范具有 WOW 领域驱动设计框架的特定模式:
|
|
343
|
+
|
|
344
|
+
### 聚合定义
|
|
345
|
+
|
|
346
|
+
聚合通过遵循 `{context}.{aggregate}` 模式的标签进行识别。
|
|
347
|
+
|
|
348
|
+
### 操作模式
|
|
349
|
+
|
|
350
|
+
生成器通过 `operationId` 后缀识别操作:
|
|
351
|
+
|
|
352
|
+
- **状态快照**:以 `.snapshot_state.single` 结尾的操作
|
|
353
|
+
- **事件查询**:以 `.event.list_query` 结尾的操作
|
|
354
|
+
- **字段查询**:以 `.snapshot.count` 结尾的操作
|
|
355
|
+
- **命令**:任何具有有效命令请求/响应结构的 HTTP 操作
|
|
356
|
+
|
|
357
|
+
### 命令和查询
|
|
358
|
+
|
|
359
|
+
- **命令**:具有 `POST`、`PUT`、`DELETE` 方法的操作,返回 `wow.CommandOk` 响应
|
|
360
|
+
- **查询**:具有 `GET` 方法的操作,用于检索聚合状态或事件
|
|
361
|
+
- **事件**:返回事件流数组的操作,具有领域事件结构
|
|
362
|
+
|
|
363
|
+
### 模式约定
|
|
364
|
+
|
|
365
|
+
- 为模式使用描述性名称
|
|
366
|
+
- 避免以 `wow.` 为前缀的模式(保留供内部框架使用)
|
|
367
|
+
- 命令请求正文应引用 `components/schemas` 中的模式
|
|
368
|
+
- 状态和事件模式应遵循域建模的预期结构
|
|
369
|
+
|
|
370
|
+
## 🛠️ 开发
|
|
371
|
+
|
|
372
|
+
### 构建
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
# 构建包
|
|
376
|
+
pnpm build
|
|
377
|
+
|
|
378
|
+
# 运行测试
|
|
379
|
+
pnpm test
|
|
380
|
+
|
|
381
|
+
# 运行 linting
|
|
382
|
+
pnpm lint
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### 测试生成器
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
# 生成测试输出
|
|
389
|
+
pnpm generate
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## 🤝 贡献
|
|
393
|
+
|
|
394
|
+
欢迎贡献!请随时提交拉取请求。对于重大更改,请先打开 issue 进行讨论。
|
|
395
|
+
|
|
396
|
+
## 📄 许可证
|
|
397
|
+
|
|
398
|
+
本项目采用 Apache License 2.0 许可证 - 查看 [LICENSE](../../LICENSE) 文件获取详情。
|
|
399
|
+
|
|
400
|
+
## 🔗 链接
|
|
401
|
+
|
|
402
|
+
- [Fetcher 核心](https://github.com/Ahoo-Wang/fetcher/tree/main/packages/fetcher)
|
|
403
|
+
- [Fetcher 装饰器](https://github.com/Ahoo-Wang/fetcher/tree/main/packages/decorator)
|
|
404
|
+
- [Fetcher 事件流](https://github.com/Ahoo-Wang/fetcher/tree/main/packages/eventstream)
|
|
405
|
+
- [GitHub 仓库](https://github.com/Ahoo-Wang/fetcher)
|
|
406
|
+
- [NPM 包](https://www.npmjs.com/package/@ahoo-wang/fetcher-generator)
|
package/dist/cli.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";const
|
|
2
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("commander"),g=require("./index.cjs"),d=require("ts-morph");require("yaml");require("fs");require("@ahoo-wang/fetcher");require("path");class h{getTimestamp(){return new Date().toISOString().slice(11,19)}info(e,...t){const o=this.getTimestamp();t.length>0?console.log(`[${o}] ℹ️ ${e}`,...t):console.log(`[${o}] ℹ️ ${e}`)}success(e,...t){const o=this.getTimestamp();t.length>0?console.log(`[${o}] ✅ ${e}`,...t):console.log(`[${o}] ✅ ${e}`)}error(e,...t){const o=this.getTimestamp();t.length>0?console.error(`[${o}] ❌ ${e}`,...t):console.error(`[${o}] ❌ ${e}`)}progress(e,t=0,...o){const n=this.getTimestamp(),i=" ".repeat(t);o.length>0?console.log(`[${n}] 🔄 ${i}${e}`,...o):console.log(`[${n}] 🔄 ${i}${e}`)}progressWithCount(e,t,o,n=0,...i){const s=this.getTimestamp(),p=" ".repeat(n),l=`[${e}/${t}]`;i.length>0?console.log(`[${s}] 🔄 ${p}${l} ${o}`,...i):console.log(`[${s}] 🔄 ${p}${l} ${o}`)}}function $(r){if(!r)return!1;try{const e=new URL(r);return e.protocol==="http:"||e.protocol==="https:"}catch{return r.length>0}}async function f(r){const e=new h;process.on("SIGINT",()=>{e.error("Generation interrupted by user"),process.exit(130)}),$(r.input)||(e.error("Invalid input: must be a valid file path or HTTP/HTTPS URL"),process.exit(2));try{e.info("Starting code generation...");const t=new d.Project,o={inputPath:r.input,outputDir:r.output,project:t,logger:e};await new g.CodeGenerator(o).generate(),e.success(`Code generation completed successfully! Files generated in: ${r.output}`)}catch(t){e.error(`Error during code generation: ${t}`),process.exit(1)}}const m="2.2.0",T={version:m};function u(){return c.program.name("fetcher-generator").description("OpenAPI Specification TypeScript code generator for Wow").version(T.version),c.program.command("generate").description("Generate TypeScript code from OpenAPI specification").requiredOption("-i, --input <path>","Input OpenAPI specification file path or URL (http/https)").option("-o, --output <path>","Output directory path","src/generated").option("-c, --config <file>","Configuration file path").option("-v, --verbose","Enable verbose logging").option("--dry-run","Show what would be generated without writing files").action(f),c.program}function a(){u().parse()}a();exports.runCLI=a;exports.setupCLI=u;
|
|
3
3
|
//# sourceMappingURL=cli.cjs.map
|
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.cjs","sources":["../src/utils/logger.ts","../src/utils/clis.ts","../src/cli.ts"],"sourcesContent":["/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from '../types';\n\n/**\n * Default console-based logger implementation.\n * Provides friendly colored output for different log levels.\n */\nexport class ConsoleLogger implements Logger {\n info(message: string, ...params: any[]): void {\n console.log(
|
|
1
|
+
{"version":3,"file":"cli.cjs","sources":["../src/utils/logger.ts","../src/utils/clis.ts","../src/cli.ts"],"sourcesContent":["/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from '../types';\n\n/**\n * Default console-based logger implementation.\n * Provides friendly colored output for different log levels.\n */\nexport class ConsoleLogger implements Logger {\n private getTimestamp(): string {\n return new Date().toISOString().slice(11, 19); // HH:MM:SS format\n }\n\n info(message: string, ...params: any[]): void {\n const timestamp = this.getTimestamp();\n if (params.length > 0) {\n console.log(`[${timestamp}] ℹ️ ${message}`, ...params);\n } else {\n console.log(`[${timestamp}] ℹ️ ${message}`);\n }\n }\n\n success(message: string, ...params: any[]): void {\n const timestamp = this.getTimestamp();\n if (params.length > 0) {\n console.log(`[${timestamp}] ✅ ${message}`, ...params);\n } else {\n console.log(`[${timestamp}] ✅ ${message}`);\n }\n }\n\n error(message: string, ...params: any[]): void {\n const timestamp = this.getTimestamp();\n if (params.length > 0) {\n console.error(`[${timestamp}] ❌ ${message}`, ...params);\n } else {\n console.error(`[${timestamp}] ❌ ${message}`);\n }\n }\n\n progress(message: string, level = 0, ...params: any[]): void {\n const timestamp = this.getTimestamp();\n const indent = ' '.repeat(level);\n if (params.length > 0) {\n console.log(`[${timestamp}] 🔄 ${indent}${message}`, ...params);\n } else {\n console.log(`[${timestamp}] 🔄 ${indent}${message}`);\n }\n }\n\n progressWithCount(\n current: number,\n total: number,\n message: string,\n level = 0,\n ...params: any[]\n ): void {\n const timestamp = this.getTimestamp();\n const indent = ' '.repeat(level);\n const countStr = `[${current}/${total}]`;\n if (params.length > 0) {\n console.log(\n `[${timestamp}] 🔄 ${indent}${countStr} ${message}`,\n ...params,\n );\n } else {\n console.log(`[${timestamp}] 🔄 ${indent}${countStr} ${message}`);\n }\n }\n}\n\n/**\n * Silent logger that suppresses all output.\n */\nexport class SilentLogger implements Logger {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n info(_message: string, ...params: any[]): void {\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n success(_message: string, ...params: any[]): void {\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n error(_message: string, ...params: any[]): void {\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n progress(_message: string, ...params: any[]): void {\n }\n\n /* eslint-disable @typescript-eslint/no-unused-vars */\n progressWithCount(\n _current: number,\n _total: number,\n _message: string,\n _level = 0,\n ..._params: any[]\n ): void {\n }\n\n /* eslint-enable @typescript-eslint/no-unused-vars */\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ConsoleLogger } from './logger';\nimport { GeneratorOptions } from '../types';\nimport { CodeGenerator } from '../index';\nimport { Project } from 'ts-morph';\n\n/**\n * Validates the input path or URL.\n * @param input - Input path or URL\n * @returns true if valid\n */\nexport function validateInput(input: string): boolean {\n if (!input) return false;\n\n // Check if it's a URL\n try {\n const url = new URL(input);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n // Not a URL, check if it's a file path\n // For file paths, we'll let parseOpenAPI handle it\n return input.length > 0;\n }\n}\n\n/**\n * Action handler for the generate command.\n * @param options - Command options\n */\nexport async function generateAction(options: {\n input: string;\n output: string;\n config?: string;\n verbose?: boolean;\n dryRun?: boolean;\n}) {\n const logger = new ConsoleLogger();\n\n // Handle signals\n process.on('SIGINT', () => {\n logger.error('Generation interrupted by user');\n process.exit(130);\n });\n\n // Validate input\n if (!validateInput(options.input)) {\n logger.error('Invalid input: must be a valid file path or HTTP/HTTPS URL');\n process.exit(2);\n }\n\n try {\n logger.info('Starting code generation...');\n const project = new Project();\n const generatorOptions: GeneratorOptions = {\n inputPath: options.input,\n outputDir: options.output,\n project,\n logger,\n };\n const codeGenerator = new CodeGenerator(generatorOptions);\n await codeGenerator.generate();\n logger.success(\n `Code generation completed successfully! Files generated in: ${options.output}`,\n );\n } catch (error) {\n logger.error(`Error during code generation: ${error}`);\n process.exit(1);\n }\n}","#!/usr/bin/env node\n\n/**\n * CLI entry point for the Fetcher OpenAPI code generator.\n * Sets up the commander program with generate command and handles execution.\n */\n\nimport { program } from 'commander';\nimport { generateAction } from './utils';\nimport packageJson from '../package.json';\n\n/**\n * Sets up the CLI program with all commands and options.\n * @returns The configured commander program instance\n */\nexport function setupCLI() {\n program\n .name('fetcher-generator')\n .description('OpenAPI Specification TypeScript code generator for Wow')\n .version(packageJson.version);\n\n program\n .command('generate')\n .description('Generate TypeScript code from OpenAPI specification')\n .requiredOption(\n '-i, --input <path>',\n 'Input OpenAPI specification file path or URL (http/https)',\n )\n .option('-o, --output <path>', 'Output directory path', 'src/generated')\n .option('-c, --config <file>', 'Configuration file path')\n .option('-v, --verbose', 'Enable verbose logging')\n .option('--dry-run', 'Show what would be generated without writing files')\n .action(generateAction);\n\n return program;\n}\n\n/**\n * Runs the CLI program by parsing command line arguments.\n * Only executes when this file is run directly (not imported).\n */\nexport function runCLI() {\n setupCLI().parse();\n}\n\nrunCLI();\n"],"names":["ConsoleLogger","message","params","timestamp","level","indent","current","total","countStr","validateInput","input","url","generateAction","options","logger","project","Project","generatorOptions","CodeGenerator","error","setupCLI","program","packageJson","runCLI"],"mappings":"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"}
|
package/dist/cli.d.ts
CHANGED
|
@@ -3,5 +3,14 @@
|
|
|
3
3
|
* CLI entry point for the Fetcher OpenAPI code generator.
|
|
4
4
|
* Sets up the commander program with generate command and handles execution.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Sets up the CLI program with all commands and options.
|
|
8
|
+
* @returns The configured commander program instance
|
|
9
|
+
*/
|
|
10
|
+
export declare function setupCLI(): import('commander').Command;
|
|
11
|
+
/**
|
|
12
|
+
* Runs the CLI program by parsing command line arguments.
|
|
13
|
+
* Only executes when this file is run directly (not imported).
|
|
14
|
+
*/
|
|
15
|
+
export declare function runCLI(): void;
|
|
7
16
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;GAGG"}
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;GAGG;AAMH;;;GAGG;AACH,wBAAgB,QAAQ,gCAoBvB;AAED;;;GAGG;AACH,wBAAgB,MAAM,SAErB"}
|
package/dist/cli.js
CHANGED
|
@@ -1,57 +1,83 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { program as
|
|
3
|
-
import { CodeGenerator as
|
|
4
|
-
import { Project as
|
|
2
|
+
import { program as c } from "commander";
|
|
3
|
+
import { CodeGenerator as a } from "./index.js";
|
|
4
|
+
import { Project as g } from "ts-morph";
|
|
5
5
|
import "yaml";
|
|
6
6
|
import "fs";
|
|
7
7
|
import "@ahoo-wang/fetcher";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
import "path";
|
|
9
|
+
class u {
|
|
10
|
+
getTimestamp() {
|
|
11
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(11, 19);
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
info(e, ...t) {
|
|
14
|
+
const o = this.getTimestamp();
|
|
15
|
+
t.length > 0 ? console.log(`[${o}] ℹ️ ${e}`, ...t) : console.log(`[${o}] ℹ️ ${e}`);
|
|
14
16
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
success(e, ...t) {
|
|
18
|
+
const o = this.getTimestamp();
|
|
19
|
+
t.length > 0 ? console.log(`[${o}] ✅ ${e}`, ...t) : console.log(`[${o}] ✅ ${e}`);
|
|
17
20
|
}
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
error(e, ...t) {
|
|
22
|
+
const o = this.getTimestamp();
|
|
23
|
+
t.length > 0 ? console.error(`[${o}] ❌ ${e}`, ...t) : console.error(`[${o}] ❌ ${e}`);
|
|
24
|
+
}
|
|
25
|
+
progress(e, t = 0, ...o) {
|
|
26
|
+
const r = this.getTimestamp(), i = " ".repeat(t);
|
|
27
|
+
o.length > 0 ? console.log(`[${r}] 🔄 ${i}${e}`, ...o) : console.log(`[${r}] 🔄 ${i}${e}`);
|
|
28
|
+
}
|
|
29
|
+
progressWithCount(e, t, o, r = 0, ...i) {
|
|
30
|
+
const s = this.getTimestamp(), p = " ".repeat(r), l = `[${e}/${t}]`;
|
|
31
|
+
i.length > 0 ? console.log(
|
|
32
|
+
`[${s}] 🔄 ${p}${l} ${o}`,
|
|
33
|
+
...i
|
|
34
|
+
) : console.log(`[${s}] 🔄 ${p}${l} ${o}`);
|
|
20
35
|
}
|
|
21
36
|
}
|
|
22
|
-
function
|
|
23
|
-
if (!
|
|
37
|
+
function f(n) {
|
|
38
|
+
if (!n) return !1;
|
|
24
39
|
try {
|
|
25
|
-
const e = new URL(
|
|
40
|
+
const e = new URL(n);
|
|
26
41
|
return e.protocol === "http:" || e.protocol === "https:";
|
|
27
42
|
} catch {
|
|
28
|
-
return
|
|
43
|
+
return n.length > 0;
|
|
29
44
|
}
|
|
30
45
|
}
|
|
31
|
-
async function
|
|
32
|
-
const e = new
|
|
46
|
+
async function $(n) {
|
|
47
|
+
const e = new u();
|
|
33
48
|
process.on("SIGINT", () => {
|
|
34
49
|
e.error("Generation interrupted by user"), process.exit(130);
|
|
35
|
-
}),
|
|
50
|
+
}), f(n.input) || (e.error("Invalid input: must be a valid file path or HTTP/HTTPS URL"), process.exit(2));
|
|
36
51
|
try {
|
|
37
52
|
e.info("Starting code generation...");
|
|
38
|
-
const
|
|
39
|
-
inputPath:
|
|
40
|
-
outputDir:
|
|
41
|
-
project:
|
|
53
|
+
const t = new g(), o = {
|
|
54
|
+
inputPath: n.input,
|
|
55
|
+
outputDir: n.output,
|
|
56
|
+
project: t,
|
|
42
57
|
logger: e
|
|
43
58
|
};
|
|
44
|
-
await new
|
|
45
|
-
`Code generation completed successfully! Files generated in: ${
|
|
59
|
+
await new a(o).generate(), e.success(
|
|
60
|
+
`Code generation completed successfully! Files generated in: ${n.output}`
|
|
46
61
|
);
|
|
47
|
-
} catch (
|
|
48
|
-
e.error(`Error during code generation: ${
|
|
62
|
+
} catch (t) {
|
|
63
|
+
e.error(`Error during code generation: ${t}`), process.exit(1);
|
|
49
64
|
}
|
|
50
65
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
66
|
+
const h = "2.2.0", m = {
|
|
67
|
+
version: h
|
|
68
|
+
};
|
|
69
|
+
function d() {
|
|
70
|
+
return c.name("fetcher-generator").description("OpenAPI Specification TypeScript code generator for Wow").version(m.version), c.command("generate").description("Generate TypeScript code from OpenAPI specification").requiredOption(
|
|
71
|
+
"-i, --input <path>",
|
|
72
|
+
"Input OpenAPI specification file path or URL (http/https)"
|
|
73
|
+
).option("-o, --output <path>", "Output directory path", "src/generated").option("-c, --config <file>", "Configuration file path").option("-v, --verbose", "Enable verbose logging").option("--dry-run", "Show what would be generated without writing files").action($), c;
|
|
74
|
+
}
|
|
75
|
+
function T() {
|
|
76
|
+
d().parse();
|
|
77
|
+
}
|
|
78
|
+
T();
|
|
79
|
+
export {
|
|
80
|
+
T as runCLI,
|
|
81
|
+
d as setupCLI
|
|
82
|
+
};
|
|
57
83
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../src/utils/logger.ts","../src/utils/clis.ts","../src/cli.ts"],"sourcesContent":["/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from '../types';\n\n/**\n * Default console-based logger implementation.\n * Provides friendly colored output for different log levels.\n */\nexport class ConsoleLogger implements Logger {\n info(message: string, ...params: any[]): void {\n console.log(`ℹ️ ${message}`, params);\n }\n\n success(message: string, ...params: any[]): void {\n console.log(`✅ ${message}`, params);\n }\n\n error(message: string, ...params: any[]): void {\n console.error(`❌ ${message}`, params);\n }\n\n progress(message: string, ...params: any[]): void {\n console.log(`🔄 ${message}`, params);\n }\n}\n\n/**\n * Silent logger that suppresses all output.\n */\nexport class SilentLogger implements Logger {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n info(_message: string, ...params: any[]): void {\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n success(_message: string, ...params: any[]): void {\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n error(_message: string, ...params: any[]): void {\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n progress(_message: string, ...params: any[]): void {\n }\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ConsoleLogger } from './logger';\nimport { GeneratorOptions } from '../types';\nimport { CodeGenerator } from '../index';\nimport { Project } from 'ts-morph';\n\n/**\n * Validates the input path or URL.\n * @param input - Input path or URL\n * @returns true if valid\n */\nexport function validateInput(input: string): boolean {\n if (!input) return false;\n\n // Check if it's a URL\n try {\n const url = new URL(input);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n // Not a URL, check if it's a file path\n // For file paths, we'll let parseOpenAPI handle it\n return input.length > 0;\n }\n}\n\n/**\n * Action handler for the generate command.\n * @param options - Command options\n */\nexport async function generateAction(options: {\n input: string;\n output: string;\n config?: string;\n verbose?: boolean;\n dryRun?: boolean;\n}) {\n const logger = new ConsoleLogger();\n\n // Handle signals\n process.on('SIGINT', () => {\n logger.error('Generation interrupted by user');\n process.exit(130);\n });\n\n // Validate input\n if (!validateInput(options.input)) {\n logger.error('Invalid input: must be a valid file path or HTTP/HTTPS URL');\n process.exit(2);\n }\n\n try {\n logger.info('Starting code generation...');\n const project = new Project();\n const generatorOptions: GeneratorOptions = {\n inputPath: options.input,\n outputDir: options.output,\n project,\n logger,\n };\n const codeGenerator = new CodeGenerator(generatorOptions);\n await codeGenerator.generate();\n logger.success(\n `Code generation completed successfully! Files generated in: ${options.output}`,\n );\n } catch (error) {\n logger.error(`Error during code generation: ${error}`);\n process.exit(1);\n }\n}","#!/usr/bin/env node\n\n/**\n * CLI entry point for the Fetcher OpenAPI code generator.\n * Sets up the commander program with generate command and handles execution.\n */\n\nimport { program } from 'commander';\nimport { generateAction } from './utils';\n\nprogram\n .name('fetcher-generator')\n .description('OpenAPI Specification TypeScript code generator for Wow')\n .version('2.1.1');\n\nprogram\n .command('generate')\n .description('Generate TypeScript code from OpenAPI specification')\n .requiredOption(\n '-i, --input <path>',\n 'Input OpenAPI specification file path or URL (http/https)',\n )\n .option('-o, --output <path>', 'Output directory path', 'src/generated')\n .option('-c, --config <file>', 'Configuration file path')\n .option('-v, --verbose', 'Enable verbose logging')\n .option('--dry-run', 'Show what would be generated without writing files')\n .action(generateAction);\n\nprogram.parse();\n"],"names":["ConsoleLogger","message","params","validateInput","input","url","generateAction","options","logger","project","Project","generatorOptions","CodeGenerator","error","program"],"mappings":";;;;;;;AAmBO,MAAMA,EAAgC;AAAA,EAC3C,KAAKC,MAAoBC,GAAqB;AAC5C,YAAQ,IAAI,OAAOD,CAAO,IAAIC,CAAM;AAAA,EACtC;AAAA,EAEA,QAAQD,MAAoBC,GAAqB;AAC/C,YAAQ,IAAI,KAAKD,CAAO,IAAIC,CAAM;AAAA,EACpC;AAAA,EAEA,MAAMD,MAAoBC,GAAqB;AAC7C,YAAQ,MAAM,KAAKD,CAAO,IAAIC,CAAM;AAAA,EACtC;AAAA,EAEA,SAASD,MAAoBC,GAAqB;AAChD,YAAQ,IAAI,MAAMD,CAAO,IAAIC,CAAM;AAAA,EACrC;AACF;ACZO,SAASC,EAAcC,GAAwB;AACpD,MAAI,CAACA,EAAO,QAAO;AAGnB,MAAI;AACF,UAAMC,IAAM,IAAI,IAAID,CAAK;AACzB,WAAOC,EAAI,aAAa,WAAWA,EAAI,aAAa;AAAA,EACtD,QAAQ;AAGN,WAAOD,EAAM,SAAS;AAAA,EACxB;AACF;AAMA,eAAsBE,EAAeC,GAMlC;AACD,QAAMC,IAAS,IAAIR,EAAA;AAGnB,UAAQ,GAAG,UAAU,MAAM;AACzB,IAAAQ,EAAO,MAAM,gCAAgC,GAC7C,QAAQ,KAAK,GAAG;AAAA,EAClB,CAAC,GAGIL,EAAcI,EAAQ,KAAK,MAC9BC,EAAO,MAAM,4DAA4D,GACzE,QAAQ,KAAK,CAAC;AAGhB,MAAI;AACF,IAAAA,EAAO,KAAK,6BAA6B;AACzC,UAAMC,IAAU,IAAIC,EAAA,GACdC,IAAqC;AAAA,MACzC,WAAWJ,EAAQ;AAAA,MACnB,WAAWA,EAAQ;AAAA,MACnB,SAAAE;AAAA,MACA,QAAAD;AAAA,IAAA;AAGF,UADsB,IAAII,EAAcD,CAAgB,EACpC,SAAA,GACpBH,EAAO;AAAA,MACL,+DAA+DD,EAAQ,MAAM;AAAA,IAAA;AAAA,EAEjF,SAASM,GAAO;AACd,IAAAL,EAAO,MAAM,iCAAiCK,CAAK,EAAE,GACrD,QAAQ,KAAK,CAAC;AAAA,EAChB;AACF;ACtEAC,EACG,KAAK,mBAAmB,EACxB,YAAY,yDAAyD,EACrE,QAAQ,OAAO;AAElBA,EACG,QAAQ,UAAU,EAClB,YAAY,qDAAqD,EACjE;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,uBAAuB,yBAAyB,eAAe,EACtE,OAAO,uBAAuB,yBAAyB,EACvD,OAAO,iBAAiB,wBAAwB,EAChD,OAAO,aAAa,oDAAoD,EACxE,OAAOR,CAAc;AAExBQ,EAAQ,MAAA;"}
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../src/utils/logger.ts","../src/utils/clis.ts","../src/cli.ts"],"sourcesContent":["/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from '../types';\n\n/**\n * Default console-based logger implementation.\n * Provides friendly colored output for different log levels.\n */\nexport class ConsoleLogger implements Logger {\n private getTimestamp(): string {\n return new Date().toISOString().slice(11, 19); // HH:MM:SS format\n }\n\n info(message: string, ...params: any[]): void {\n const timestamp = this.getTimestamp();\n if (params.length > 0) {\n console.log(`[${timestamp}] ℹ️ ${message}`, ...params);\n } else {\n console.log(`[${timestamp}] ℹ️ ${message}`);\n }\n }\n\n success(message: string, ...params: any[]): void {\n const timestamp = this.getTimestamp();\n if (params.length > 0) {\n console.log(`[${timestamp}] ✅ ${message}`, ...params);\n } else {\n console.log(`[${timestamp}] ✅ ${message}`);\n }\n }\n\n error(message: string, ...params: any[]): void {\n const timestamp = this.getTimestamp();\n if (params.length > 0) {\n console.error(`[${timestamp}] ❌ ${message}`, ...params);\n } else {\n console.error(`[${timestamp}] ❌ ${message}`);\n }\n }\n\n progress(message: string, level = 0, ...params: any[]): void {\n const timestamp = this.getTimestamp();\n const indent = ' '.repeat(level);\n if (params.length > 0) {\n console.log(`[${timestamp}] 🔄 ${indent}${message}`, ...params);\n } else {\n console.log(`[${timestamp}] 🔄 ${indent}${message}`);\n }\n }\n\n progressWithCount(\n current: number,\n total: number,\n message: string,\n level = 0,\n ...params: any[]\n ): void {\n const timestamp = this.getTimestamp();\n const indent = ' '.repeat(level);\n const countStr = `[${current}/${total}]`;\n if (params.length > 0) {\n console.log(\n `[${timestamp}] 🔄 ${indent}${countStr} ${message}`,\n ...params,\n );\n } else {\n console.log(`[${timestamp}] 🔄 ${indent}${countStr} ${message}`);\n }\n }\n}\n\n/**\n * Silent logger that suppresses all output.\n */\nexport class SilentLogger implements Logger {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n info(_message: string, ...params: any[]): void {\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n success(_message: string, ...params: any[]): void {\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n error(_message: string, ...params: any[]): void {\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n progress(_message: string, ...params: any[]): void {\n }\n\n /* eslint-disable @typescript-eslint/no-unused-vars */\n progressWithCount(\n _current: number,\n _total: number,\n _message: string,\n _level = 0,\n ..._params: any[]\n ): void {\n }\n\n /* eslint-enable @typescript-eslint/no-unused-vars */\n}\n","/*\n * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ConsoleLogger } from './logger';\nimport { GeneratorOptions } from '../types';\nimport { CodeGenerator } from '../index';\nimport { Project } from 'ts-morph';\n\n/**\n * Validates the input path or URL.\n * @param input - Input path or URL\n * @returns true if valid\n */\nexport function validateInput(input: string): boolean {\n if (!input) return false;\n\n // Check if it's a URL\n try {\n const url = new URL(input);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n // Not a URL, check if it's a file path\n // For file paths, we'll let parseOpenAPI handle it\n return input.length > 0;\n }\n}\n\n/**\n * Action handler for the generate command.\n * @param options - Command options\n */\nexport async function generateAction(options: {\n input: string;\n output: string;\n config?: string;\n verbose?: boolean;\n dryRun?: boolean;\n}) {\n const logger = new ConsoleLogger();\n\n // Handle signals\n process.on('SIGINT', () => {\n logger.error('Generation interrupted by user');\n process.exit(130);\n });\n\n // Validate input\n if (!validateInput(options.input)) {\n logger.error('Invalid input: must be a valid file path or HTTP/HTTPS URL');\n process.exit(2);\n }\n\n try {\n logger.info('Starting code generation...');\n const project = new Project();\n const generatorOptions: GeneratorOptions = {\n inputPath: options.input,\n outputDir: options.output,\n project,\n logger,\n };\n const codeGenerator = new CodeGenerator(generatorOptions);\n await codeGenerator.generate();\n logger.success(\n `Code generation completed successfully! Files generated in: ${options.output}`,\n );\n } catch (error) {\n logger.error(`Error during code generation: ${error}`);\n process.exit(1);\n }\n}","#!/usr/bin/env node\n\n/**\n * CLI entry point for the Fetcher OpenAPI code generator.\n * Sets up the commander program with generate command and handles execution.\n */\n\nimport { program } from 'commander';\nimport { generateAction } from './utils';\nimport packageJson from '../package.json';\n\n/**\n * Sets up the CLI program with all commands and options.\n * @returns The configured commander program instance\n */\nexport function setupCLI() {\n program\n .name('fetcher-generator')\n .description('OpenAPI Specification TypeScript code generator for Wow')\n .version(packageJson.version);\n\n program\n .command('generate')\n .description('Generate TypeScript code from OpenAPI specification')\n .requiredOption(\n '-i, --input <path>',\n 'Input OpenAPI specification file path or URL (http/https)',\n )\n .option('-o, --output <path>', 'Output directory path', 'src/generated')\n .option('-c, --config <file>', 'Configuration file path')\n .option('-v, --verbose', 'Enable verbose logging')\n .option('--dry-run', 'Show what would be generated without writing files')\n .action(generateAction);\n\n return program;\n}\n\n/**\n * Runs the CLI program by parsing command line arguments.\n * Only executes when this file is run directly (not imported).\n */\nexport function runCLI() {\n setupCLI().parse();\n}\n\nrunCLI();\n"],"names":["ConsoleLogger","message","params","timestamp","level","indent","current","total","countStr","validateInput","input","url","generateAction","options","logger","project","Project","generatorOptions","CodeGenerator","error","setupCLI","program","packageJson","runCLI"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientGenerator.d.ts","sourceRoot":"","sources":["../../src/client/clientGenerator.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGzD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,iBAAiB;IACpD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAuB;IAC5D,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAyB;IAEhE;;;OAGG;gBACS,OAAO,EAAE,eAAe;IAMpC;;OAEG;IACH,QAAQ,IAAI,IAAI;
|
|
1
|
+
{"version":3,"file":"clientGenerator.d.ts","sourceRoot":"","sources":["../../src/client/clientGenerator.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGzD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,iBAAiB;IACpD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAuB;IAC5D,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAyB;IAEhE;;;OAGG;gBACS,OAAO,EAAE,eAAe;IAMpC;;OAEG;IACH,QAAQ,IAAI,IAAI;IAqBhB;;;OAGG;IACH,qBAAqB,CAAC,YAAY,EAAE,MAAM;CAc3C"}
|