@genapi/pipeline 3.7.1 → 4.0.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 ADDED
@@ -0,0 +1,60 @@
1
+ # @genapi/pipeline
2
+
3
+ <!-- automd:badges -->
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@genapi/pipeline)](https://npmjs.com/package/@genapi/pipeline)
6
+ [![npm downloads](https://img.shields.io/npm/dm/@genapi/pipeline)](https://npm.chart.dev/@genapi/pipeline)
7
+
8
+ <!-- /automd -->
9
+
10
+ GenAPI pipeline core: config reading, data source fetching, parsing, compilation, generation, and output. Composable for custom generation flows.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pnpm add @genapi/pipeline
16
+ ```
17
+
18
+ ## API
19
+
20
+ <!-- automd:jsdocs src=src/index.ts -->
21
+
22
+ ## Pipeline
23
+
24
+ ### `compiler(configRead)`
25
+
26
+ Compiles graphs to AST: request code and typings for each output.
27
+
28
+ ### `config(userConfig)`
29
+
30
+ Normalizes pipeline config: output paths, responseType, baseURL (from meta), and builds ConfigRead with inputs/outputs.
31
+
32
+ ### `default(config, original, parser, compiler, generate, dest)`
33
+
34
+ Builds a GenAPI pipeline from five steps: config → original → parser → compiler → generate → dest.
35
+
36
+ ### `dest(configRead)`
37
+
38
+ Writes output files from configRead.outputs (code to path).
39
+
40
+ ### `generate(configRead)`
41
+
42
+ Generates code string from AST for each output and formats with Prettier.
43
+
44
+ ### `original(configRead)`
45
+
46
+ Fetches source: resolves uri/http/json from configRead.inputs and sets configRead.source.
47
+
48
+ <!-- /automd -->
49
+
50
+ ## License
51
+
52
+ [MIT](https://github.com/hairyf/genapi/blob/main/LICENSE)
53
+
54
+ <!-- automd:with-automd -->
55
+
56
+ ---
57
+
58
+ _🤖 auto updated with [automd](https://automd.unjs.io)_
59
+
60
+ <!-- /automd -->
package/dist/index.d.mts CHANGED
@@ -2,55 +2,98 @@ import { ApiPipeline } from "@genapi/shared";
2
2
 
3
3
  //#region src/pipeline/index.d.ts
4
4
  /**
5
- * Pipeline readinput)function
5
+ * Pipeline read (input) step: turns raw config into internal config + inputs.
6
6
  */
7
7
  type PipelineRead<Config, ConfigRead> = (config: Config) => ConfigRead | Promise<ConfigRead>;
8
8
  /**
9
- * Transfer data in pipeline
9
+ * Middle step that receives and returns config read; used for original, parser, compiler, generate.
10
10
  */
11
11
  type PipelineFlow<ConfigRead> = (configRead: ConfigRead) => ConfigRead | Promise<ConfigRead>;
12
12
  /**
13
- * Pipeline destoutput)function
13
+ * Pipeline dest (output) step: writes files from config read.
14
14
  */
15
- type PipelineDest<ConfigRead> = (configRead: ApiPipeline.ConfigRead) => void;
15
+ type PipelineDest<ConfigRead> = (configRead: ApiPipeline.ConfigRead) => void | Promise<void>;
16
16
  /**
17
- * create genapi pipeline process
18
- * @param config read config pa
19
- * @param original get the source according to config
20
- * @param parser resolve source as available data
21
- * @param compiler compile parse info conversion AST tree
22
- * @param generate generate code
23
- * @param dest dest file
17
+ * Builds a GenAPI pipeline from five steps: config → original → parser → compiler → generate → dest.
18
+ *
19
+ * @param config - Reads config and returns ConfigRead
20
+ * @param original - Fetches source (e.g. OpenAPI JSON)
21
+ * @param parser - Parses source into graphs
22
+ * @param compiler - Compiles graphs to AST
23
+ * @param generate - Generates code string
24
+ * @param dest - Writes output files
25
+ * @returns A function that runs the pipeline for a given config
26
+ * @group Pipeline
24
27
  */
25
28
  declare function pipeline<Config = ApiPipeline.Config, ConfigRead = ApiPipeline.ConfigRead>(config: PipelineRead<Config, ConfigRead>, original: PipelineFlow<ConfigRead>, parser: PipelineFlow<ConfigRead>, compiler: PipelineFlow<ConfigRead>, generate: PipelineFlow<ConfigRead>, dest: PipelineDest<ConfigRead>): ApiPipeline.Pipeline;
26
29
  declare namespace pipeline {
27
- var config: typeof config;
28
- var original: typeof original;
29
- var parser: typeof original;
30
- var compiler: typeof compiler;
31
- var generate: typeof generate;
32
- var dest: typeof dest;
30
+ var config: typeof config;
31
+ var original: typeof original;
32
+ var parser: typeof original;
33
+ var compiler: typeof compiler;
34
+ var generate: typeof generate;
35
+ var dest: typeof dest;
33
36
  }
34
-
37
+ //#endregion
38
+ //#region src/compiler/request.d.ts
39
+ declare function compilerTsRequestDeclaration(configRead: ApiPipeline.ConfigRead): string;
40
+ //#endregion
41
+ //#region src/compiler/typings.d.ts
42
+ /**
43
+ * Compiles configRead graphs to typings code string using knitwork-x.
44
+ */
45
+ declare function compilerTsTypingsDeclaration(configRead: ApiPipeline.ConfigRead, comment?: boolean): string;
35
46
  //#endregion
36
47
  //#region src/compiler/index.d.ts
48
+ /**
49
+ * Compiles graphs to code string: request and typings for each output.
50
+ *
51
+ * @param configRead - ConfigRead with graphs and outputs
52
+ * @returns Same configRead with output.code set
53
+ * @group Pipeline
54
+ */
37
55
  declare function compiler(configRead: ApiPipeline.ConfigRead): ApiPipeline.ConfigRead<ApiPipeline.Config>;
38
-
39
56
  //#endregion
40
57
  //#region src/config/index.d.ts
58
+ /**
59
+ * Normalizes pipeline config: output paths, responseType, baseURL, and builds ConfigRead with inputs/outputs.
60
+ *
61
+ * @param userConfig - Raw config from defineConfig
62
+ * @returns ConfigRead (config + inputs + outputs)
63
+ * @group Pipeline
64
+ */
41
65
  declare function config(userConfig: ApiPipeline.Config): ApiPipeline.ConfigRead<Required<ApiPipeline.Config>>;
42
-
43
66
  //#endregion
44
67
  //#region src/dest/index.d.ts
45
- declare function dest(configRead: ApiPipeline.ConfigRead): void;
46
-
68
+ /**
69
+ * Writes output files from configRead.outputs (code to path).
70
+ *
71
+ * @param configRead - ConfigRead with outputs[].path and outputs[].code
72
+ * @group Pipeline
73
+ */
74
+ declare function dest(configRead: ApiPipeline.ConfigRead): Promise<void>;
47
75
  //#endregion
48
76
  //#region src/generate/index.d.ts
49
- declare function generate(configRead: ApiPipeline.ConfigRead): ApiPipeline.ConfigRead<ApiPipeline.Config>;
50
-
77
+ /**
78
+ * Formats code for each output with Prettier.
79
+ *
80
+ * @param configRead - ConfigRead with outputs[].code
81
+ * @returns Same configRead with outputs[].code formatted
82
+ * @group Pipeline
83
+ */
84
+ declare function generate(configRead: ApiPipeline.ConfigRead, options?: any): Promise<ApiPipeline.ConfigRead<ApiPipeline.Config>>;
85
+ declare function formatTypescript(code: string, options?: any): Promise<string>;
51
86
  //#endregion
52
87
  //#region src/original/index.d.ts
88
+ /**
89
+ * Fetches source: resolves uri/http/json from configRead.inputs and sets configRead.source.
90
+ * Transforms the source based on parser configuration (wpapi -> swagger2, swagger -> unchanged).
91
+ * Supports YAML source URLs (e.g. .yaml / .yml); uses confbox for parsing (same as undocs).
92
+ *
93
+ * @param configRead - ConfigRead with inputs (uri, http, or json)
94
+ * @returns Same configRead with source set and transformed if needed
95
+ * @group Pipeline
96
+ */
53
97
  declare function original(configRead: ApiPipeline.ConfigRead): Promise<ApiPipeline.ConfigRead<ApiPipeline.Config>>;
54
-
55
98
  //#endregion
56
- export { PipelineDest, PipelineFlow, PipelineRead, compiler, config, pipeline as default, dest, generate, original };
99
+ export { type PipelineDest, type PipelineFlow, type PipelineRead, compiler, compilerTsRequestDeclaration, compilerTsTypingsDeclaration, config, pipeline as default, dest, formatTypescript, generate, original };
package/dist/index.mjs CHANGED
@@ -1,114 +1,177 @@
1
1
  import pPipe from "p-pipe";
2
- import { astNodeToCode, codeToAstNode, createComment, createFunction, createImport, createInterface, createTypeAlias, createVariable } from "ts-factory-extra";
3
- import { NodeFlags, factory } from "typescript";
2
+ import { inject, provide } from "@genapi/shared";
3
+ import { genComment, genFunction, genImport, genInterface, genTypeAlias, genVariable } from "knitwork-x";
4
4
  import path from "node:path";
5
5
  import process from "node:process";
6
- import { provide } from "@genapi/shared";
7
6
  import fs from "fs-extra";
8
7
  import { format } from "prettier";
9
- import got from "got";
8
+ import { wpapiToSwagger2 } from "@genapi/transform";
9
+ import { parseYAML } from "confbox";
10
+ import { ofetch } from "ofetch";
10
11
 
11
12
  //#region src/compiler/typings.ts
13
+ /**
14
+ * Compiles configRead graphs to typings code string using knitwork-x.
15
+ */
12
16
  function compilerTsTypingsDeclaration(configRead, comment = true) {
13
17
  configRead.graphs.comments = configRead.graphs.comments || [];
14
18
  configRead.graphs.typings = configRead.graphs.typings || [];
15
19
  configRead.graphs.interfaces = configRead.graphs.interfaces || [];
20
+ const sections = [];
21
+ if (comment && configRead.graphs.comments.length > 0) sections.push(genComment(configRead.graphs.comments.join("\n"), { block: true }));
16
22
  const typings = configRead.graphs.typings.map((item) => {
17
- return createTypeAlias(item.export, item.name, item.value);
23
+ return genTypeAlias(item.name, item.value, { export: !!item.export });
18
24
  });
25
+ if (typings.length > 0) sections.push(typings.join("\n"));
19
26
  const interfaces = configRead.graphs.interfaces.map((item) => {
20
- return createInterface({
21
- export: item.export,
22
- name: item.name,
23
- properties: item.properties || []
24
- });
27
+ const properties = (item.properties || []).map((p) => ({
28
+ name: p.name,
29
+ type: p.type ?? "any",
30
+ optional: !p.required,
31
+ jsdoc: p.description
32
+ }));
33
+ return genInterface(item.name, properties, { export: !!item.export });
25
34
  });
26
- const nodes = [
27
- factory.createIdentifier(""),
28
- ...typings,
29
- factory.createIdentifier(""),
30
- ...interfaces
31
- ];
32
- if (comment) nodes.unshift(createComment("multi", configRead.graphs.comments));
33
- return nodes;
35
+ if (interfaces.length > 0) sections.push(interfaces.join("\n"));
36
+ return sections.filter(Boolean).join("\n\n");
34
37
  }
35
38
 
36
39
  //#endregion
37
40
  //#region src/compiler/request.ts
38
- const varFlags = {
39
- let: NodeFlags.Let,
40
- const: NodeFlags.Const,
41
- var: NodeFlags.None
42
- };
43
41
  function compilerTsRequestDeclaration(configRead) {
44
- configRead.graphs.imports = configRead.graphs.imports || [];
45
- configRead.graphs.comments = configRead.graphs.comments || [];
46
- configRead.graphs.variables = configRead.graphs.variables || [];
47
- configRead.graphs.functions = configRead.graphs.functions || [];
48
- const isGenerateType = configRead.outputs.some((v) => v.type === "typings");
49
- const isTypescript = configRead.outputs.some((v) => v.type === "request" && v.path.endsWith(".ts"));
50
- const comments = [createComment("multi", configRead.graphs.comments)];
51
- const imports = configRead.graphs.imports?.map((item) => {
52
- return createImport(item.name, item.names, item.value, item.namespace);
42
+ const { graphs, config, outputs } = configRead;
43
+ const sections = [];
44
+ const interfaceMap = new Map((graphs.interfaces || []).map((i) => [i.name, i]));
45
+ if (graphs.comments?.length) sections.push(genComment(graphs.comments.join("\n"), { block: true }));
46
+ const importLines = (graphs.imports || []).map((item) => {
47
+ const isType = !!item.type;
48
+ if (item.namespace) return genImport(item.value, {
49
+ name: "*",
50
+ as: item.name
51
+ }, { type: isType });
52
+ if (item.name && !item.names) return genImport(item.value, item.name, { type: isType });
53
+ const names = item.names || [];
54
+ const imports = item.name ? [{
55
+ name: "default",
56
+ as: item.name
57
+ }, ...names.map((n) => ({ name: n }))] : names;
58
+ return genImport(item.value, imports, { type: isType });
53
59
  });
54
- const variables = configRead.graphs.variables.map((item) => {
55
- return createVariable(item.export, varFlags[item.flag], item.name, item.value);
60
+ if (config.meta?.mockjs) importLines.push(genImport("better-mock", { name: "Mock" }));
61
+ if (importLines.length) sections.push(importLines.join("\n"));
62
+ const variables = (graphs.variables || []).map((item) => genVariable(item.name, item.value ?? "", {
63
+ export: !!item.export,
64
+ kind: item.flag
65
+ }));
66
+ if (variables.length) sections.push(variables.join("\n"));
67
+ const functions = genFunctionsWithMock(graphs.functions || [], interfaceMap, config);
68
+ if (functions.length) sections.push(functions.join("\n\n"));
69
+ const isGenerateType = outputs.some((v) => v.type === "typings");
70
+ const isTsRequest = outputs.some((v) => v.type === "request" && v.path.endsWith(".ts"));
71
+ if (!isGenerateType && isTsRequest) sections.push(compilerTsTypingsDeclaration(configRead, false));
72
+ return sections.filter(Boolean).join("\n\n");
73
+ }
74
+ const RE_NAMESPACE = /^(Types\.|import\(['"][^'"]+['"]\)\.)/g;
75
+ const RE_ARRAY_TYPE = /^(.+)\[\]$/;
76
+ /**
77
+ * 优化后的 Mock 模板生成函数
78
+ */
79
+ function generateMockTemplate(typeName, interfaceMap, visited = /* @__PURE__ */ new Set()) {
80
+ const cleanTypeName = typeName.replace(RE_NAMESPACE, "").trim();
81
+ const arrayMatch = cleanTypeName.match(RE_ARRAY_TYPE);
82
+ if (arrayMatch) return `[${generateMockTemplate(arrayMatch[1], interfaceMap, visited)}]`;
83
+ const primitiveMap = {
84
+ string: "'@string'",
85
+ number: "'@integer'",
86
+ boolean: "'@boolean'",
87
+ Date: "'@datetime'",
88
+ void: "null",
89
+ any: "'@string'"
90
+ };
91
+ if (primitiveMap[cleanTypeName]) return primitiveMap[cleanTypeName];
92
+ if (cleanTypeName.includes("|")) return "{}";
93
+ const interfaceDef = interfaceMap.get(cleanTypeName);
94
+ if (!interfaceDef?.properties || visited.has(cleanTypeName)) return "{}";
95
+ visited.add(cleanTypeName);
96
+ const properties = interfaceDef.properties.filter((prop) => prop.type).map((prop) => {
97
+ const propType = prop.type.replace(RE_NAMESPACE, "").trim();
98
+ const nextVisited = new Set(visited);
99
+ if (propType.endsWith("[]")) {
100
+ const itemTemplate = generateMockTemplate(propType.slice(0, -2), interfaceMap, nextVisited);
101
+ return `'${prop.name}|1-5': ${itemTemplate}`;
102
+ }
103
+ const innerTemplate = generateMockTemplate(propType, interfaceMap, nextVisited);
104
+ return `'${prop.name}': ${innerTemplate}`;
56
105
  });
57
- const functions = configRead.graphs.functions.flatMap((item) => {
58
- return createFunction({
106
+ visited.delete(cleanTypeName);
107
+ return properties.length > 0 ? `{\n ${properties.join(",\n ")}\n }` : "{}";
108
+ }
109
+ function genFunctionsWithMock(functions, interfaceMap, config) {
110
+ const functionBlocks = [];
111
+ (functions || []).forEach((item) => {
112
+ const functionCode = genFunction({
59
113
  export: true,
60
- comment: item.description,
61
114
  name: item.name,
62
- parameters: item.parameters,
63
- body: item.body?.map(codeToAstNode),
115
+ parameters: (item.parameters || []).map((p) => ({
116
+ name: p.name,
117
+ type: p.type,
118
+ optional: !p.required
119
+ })),
120
+ body: item.body || [],
64
121
  async: item.async,
65
122
  returnType: item.returnType,
66
123
  generics: item.generics,
67
- generator: item.generator
124
+ jsdoc: item.description
68
125
  });
126
+ functionBlocks.push(functionCode);
127
+ const responseType = inject(item.name)?.responseType;
128
+ if (!config.meta?.mockjs || !responseType || responseType === "void" || responseType === "any") return;
129
+ const mockTemplate = generateMockTemplate(responseType, interfaceMap);
130
+ functionBlocks.push(`${item.name}.mock = () => Mock.mock(${mockTemplate});`);
69
131
  });
70
- const nodes = [
71
- ...comments,
72
- factory.createIdentifier(""),
73
- ...imports,
74
- factory.createIdentifier(""),
75
- ...variables,
76
- factory.createIdentifier(""),
77
- ...functions
78
- ];
79
- if (!isGenerateType && isTypescript) {
80
- nodes.push(factory.createIdentifier(""));
81
- nodes.push(factory.createIdentifier(""));
82
- nodes.push(...compilerTsTypingsDeclaration(configRead, false));
83
- }
84
- return nodes;
132
+ return functionBlocks;
85
133
  }
86
134
 
87
135
  //#endregion
88
136
  //#region src/compiler/index.ts
137
+ /**
138
+ * Compiles graphs to code string: request and typings for each output.
139
+ *
140
+ * @param configRead - ConfigRead with graphs and outputs
141
+ * @returns Same configRead with output.code set
142
+ * @group Pipeline
143
+ */
89
144
  function compiler(configRead) {
90
145
  for (const output of configRead.outputs) {
91
- if (output.type === "request" && !configRead.config.onlyDeclaration) output.ast = compilerTsRequestDeclaration(configRead);
92
- if (output.type === "typings") output.ast = compilerTsTypingsDeclaration(configRead);
146
+ if (output.type === "request" && !configRead.config.meta?.onlyDeclaration) output.code = compilerTsRequestDeclaration(configRead);
147
+ if (output.type === "typings") output.code = compilerTsTypingsDeclaration(configRead);
93
148
  }
94
149
  return configRead;
95
150
  }
96
151
 
97
152
  //#endregion
98
153
  //#region src/config/index.ts
154
+ /**
155
+ * Normalizes pipeline config: output paths, responseType, baseURL, and builds ConfigRead with inputs/outputs.
156
+ *
157
+ * @param userConfig - Raw config from defineConfig
158
+ * @returns ConfigRead (config + inputs + outputs)
159
+ * @group Pipeline
160
+ */
99
161
  function config(userConfig) {
100
- userConfig.import = userConfig.import || {};
101
- userConfig.responseType = userConfig.responseType || {};
162
+ userConfig.meta = userConfig.meta || {};
163
+ userConfig.meta.import = userConfig.meta.import || {};
164
+ userConfig.meta.responseType = userConfig.meta.responseType || {};
102
165
  if (typeof userConfig.output === "string") userConfig.output = { main: userConfig.output };
103
166
  userConfig.output = userConfig.output || {};
104
167
  userConfig.output.main = userConfig.output.main || "src/api/index.ts";
105
- if (typeof userConfig.baseURL === "string") userConfig.baseURL = userConfig.baseURL.endsWith("/\"") ? userConfig.baseURL = `${userConfig.baseURL.slice(0, userConfig.baseURL.length - 2)}"` : userConfig.baseURL;
168
+ if (typeof userConfig.meta.baseURL === "string") userConfig.meta.baseURL = userConfig.meta.baseURL.endsWith("/\"") ? userConfig.meta.baseURL = `${userConfig.meta.baseURL.slice(0, userConfig.meta.baseURL.length - 2)}"` : userConfig.meta.baseURL;
106
169
  if (userConfig.output?.type !== false) userConfig.output.type = userConfig.output.type || userConfig.output.main.replace(/\.ts|\.js/g, ".type.ts");
107
- if (typeof userConfig.responseType === "string") userConfig.responseType = { infer: userConfig.responseType };
170
+ if (typeof userConfig.meta.responseType === "string") userConfig.meta.responseType = { infer: userConfig.meta.responseType };
108
171
  const userRoot = process.cwd();
109
172
  const isTypescript = userConfig.output.main.endsWith(".ts");
110
173
  const isGenerateType = userConfig.output?.type !== false;
111
- const importTypePath = userConfig.import.type || getImportTypePath(userConfig.output.main, userConfig.output.type || "");
174
+ const importTypePath = userConfig.meta.import.type || getImportTypePath(userConfig.output.main, userConfig.output.type || "");
112
175
  const imports = [isTypescript && isGenerateType && {
113
176
  name: "Types",
114
177
  value: importTypePath,
@@ -120,10 +183,10 @@ function config(userConfig) {
120
183
  root: path.join(userRoot, path.dirname(userConfig.output.main)),
121
184
  path: path.join(userRoot, userConfig.output.main)
122
185
  }];
123
- const typings = [!!userConfig.responseType.infer && {
186
+ const typings = [!!userConfig.meta.responseType?.infer && {
124
187
  export: true,
125
188
  name: "Infer<T>",
126
- value: userConfig.responseType.infer
189
+ value: userConfig.meta.responseType.infer
127
190
  }];
128
191
  if (userConfig.output.type !== false) outputs.push({
129
192
  type: "typings",
@@ -145,7 +208,7 @@ function config(userConfig) {
145
208
  functions: [],
146
209
  interfaces: [],
147
210
  typings: typings.filter(Boolean),
148
- response: userConfig.responseType
211
+ response: userConfig.meta.responseType
149
212
  }
150
213
  };
151
214
  provide({
@@ -154,8 +217,8 @@ function config(userConfig) {
154
217
  });
155
218
  return configRead;
156
219
  }
157
- function prefix(path$1) {
158
- return path$1.startsWith(".") ? path$1 : `./${path$1}`;
220
+ function prefix(path) {
221
+ return path.startsWith(".") ? path : `./${path}`;
159
222
  }
160
223
  function getImportTypePath(main, type) {
161
224
  let importTypePath = path.dirname(main);
@@ -166,61 +229,109 @@ function getImportTypePath(main, type) {
166
229
 
167
230
  //#endregion
168
231
  //#region src/dest/index.ts
169
- function dest(configRead) {
170
- configRead.outputs.map(async (output) => {
232
+ /**
233
+ * Writes output files from configRead.outputs (code to path).
234
+ *
235
+ * @param configRead - ConfigRead with outputs[].path and outputs[].code
236
+ * @group Pipeline
237
+ */
238
+ async function dest(configRead) {
239
+ await Promise.all(configRead.outputs.map(async (output) => {
171
240
  await fs.ensureDir(output.root);
172
241
  await fs.writeFile(output.path, output.code || "", { flag: "w" });
173
- });
242
+ }));
174
243
  }
175
244
 
176
245
  //#endregion
177
246
  //#region src/generate/index.ts
178
- function generate(configRead) {
179
- for (const output of configRead.outputs || []) {
180
- if (output.ast) output.code = astNodeToCode(output.ast);
181
- if (output.code) output.code = formatTypescript(output.code);
182
- }
247
+ /**
248
+ * Formats code for each output with Prettier.
249
+ *
250
+ * @param configRead - ConfigRead with outputs[].code
251
+ * @returns Same configRead with outputs[].code formatted
252
+ * @group Pipeline
253
+ */
254
+ async function generate(configRead, options) {
255
+ for (const output of configRead.outputs || []) if (output.code) output.code = await formatTypescript(output.code, options);
183
256
  return configRead;
184
257
  }
185
- function formatTypescript(code) {
186
- return format(code, {
258
+ async function formatTypescript(code, options) {
259
+ return await format(code, {
187
260
  printWidth: 800,
261
+ ...options,
188
262
  parser: "typescript"
189
263
  });
190
264
  }
191
265
 
192
266
  //#endregion
193
267
  //#region src/original/index.ts
268
+ function isYamlUrl(url) {
269
+ try {
270
+ const pathname = new URL(url).pathname;
271
+ return pathname.endsWith(".yaml") || pathname.endsWith(".yml");
272
+ } catch {
273
+ return false;
274
+ }
275
+ }
276
+ async function fetchSource(url, options) {
277
+ if (isYamlUrl(url)) return parseYAML(await ofetch(url, {
278
+ ...options,
279
+ responseType: "text"
280
+ }));
281
+ if (options && Object.keys(options).length > 0) return await ofetch(url, options);
282
+ return await ofetch(url);
283
+ }
284
+ /**
285
+ * Fetches source: resolves uri/http/json from configRead.inputs and sets configRead.source.
286
+ * Transforms the source based on parser configuration (wpapi -> swagger2, swagger -> unchanged).
287
+ * Supports YAML source URLs (e.g. .yaml / .yml); uses confbox for parsing (same as undocs).
288
+ *
289
+ * @param configRead - ConfigRead with inputs (uri, http, or json)
290
+ * @returns Same configRead with source set and transformed if needed
291
+ * @group Pipeline
292
+ */
194
293
  async function original(configRead) {
195
- if (configRead.inputs.uri) configRead.source = await got({
196
- url: configRead.inputs.uri,
197
- responseType: "json"
198
- }).json();
199
- if (configRead.inputs.http) configRead.source = await got({
200
- ...configRead.inputs.http,
201
- responseType: "json"
202
- }).json();
294
+ if (configRead.inputs.uri) configRead.source = await fetchSource(configRead.inputs.uri);
295
+ if (configRead.inputs.http) {
296
+ const { url, ...options } = configRead.inputs.http;
297
+ configRead.source = await fetchSource(url || configRead.inputs.uri || "", options);
298
+ }
203
299
  if (configRead.inputs.json) configRead.source = await readJsonSource(configRead.inputs.json);
204
300
  if (!configRead.source) throw new Error("No source found, please check your input config.");
301
+ if ((configRead.config.parser || "swagger") === "wpapi") configRead.source = wpapiToSwagger2(configRead.source);
205
302
  if (!configRead.source.schemes?.length) {
303
+ const effectiveUrl = configRead.inputs.http?.url || configRead.inputs.uri || "";
206
304
  const schemes = [];
207
- if (configRead.inputs.uri?.startsWith("https://")) schemes.push("https", "http");
208
- if (configRead.inputs.uri?.startsWith("http://")) schemes.push("http");
209
- configRead.source.schemes = schemes;
305
+ if (effectiveUrl.startsWith("https://")) schemes.push("https", "http");
306
+ if (effectiveUrl.startsWith("http://")) schemes.push("http");
307
+ if (schemes.length > 0) configRead.source.schemes = schemes;
210
308
  }
211
309
  return configRead;
212
310
  }
213
311
  function readJsonSource(json) {
214
- if (!json) return;
215
- if (typeof json === "object") return json;
216
- else return import(json).then((mod) => mod.default);
312
+ if (!json) return Promise.resolve(void 0);
313
+ if (typeof json === "object") return Promise.resolve(json);
314
+ const trimmed = String(json).trim();
315
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) return Promise.resolve(JSON.parse(json));
316
+ return import(json).then((mod) => mod.default);
217
317
  }
218
318
 
219
319
  //#endregion
220
320
  //#region src/pipeline/index.ts
221
- function pipeline(config$1, original$1, parser, compiler$1, generate$1, dest$1) {
222
- const pipe = pPipe(config$1, original$1, parser, compiler$1, generate$1, dest$1);
223
- return pipe;
321
+ /**
322
+ * Builds a GenAPI pipeline from five steps: config original parser compiler generate dest.
323
+ *
324
+ * @param config - Reads config and returns ConfigRead
325
+ * @param original - Fetches source (e.g. OpenAPI JSON)
326
+ * @param parser - Parses source into graphs
327
+ * @param compiler - Compiles graphs to AST
328
+ * @param generate - Generates code string
329
+ * @param dest - Writes output files
330
+ * @returns A function that runs the pipeline for a given config
331
+ * @group Pipeline
332
+ */
333
+ function pipeline(config, original, parser, compiler, generate, dest) {
334
+ return pPipe(config, original, parser, compiler, generate, dest);
224
335
  }
225
336
  pipeline.config = config;
226
337
  pipeline.original = original;
@@ -234,4 +345,4 @@ pipeline.dest = dest;
234
345
  var src_default = pipeline;
235
346
 
236
347
  //#endregion
237
- export { compiler, config, src_default as default, dest, generate, original };
348
+ export { compiler, compilerTsRequestDeclaration, compilerTsTypingsDeclaration, config, src_default as default, dest, formatTypescript, generate, original };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genapi/pipeline",
3
3
  "type": "module",
4
- "version": "3.7.1",
4
+ "version": "4.0.0",
5
5
  "author": "Hairyf <wwu710632@gmail.com>",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/hairyf/genapi#readme",
@@ -15,29 +15,32 @@
15
15
  "shared"
16
16
  ],
17
17
  "sideEffects": false,
18
- "main": "./dist/index.mjs",
18
+ "exports": {
19
+ ".": "./dist/index.mjs",
20
+ "./package.json": "./package.json"
21
+ },
22
+ "types": "./dist/index.d.mts",
19
23
  "files": [
20
24
  "dist"
21
25
  ],
22
26
  "dependencies": {
23
- "fs-extra": "^11.1.0",
24
- "got": "11.8.6",
25
- "p-pipe": "^3",
26
- "prettier": "^2.8.4",
27
- "ts-factory-extra": "^0.0.5",
28
- "typescript": "^5.0.0",
29
- "@genapi/shared": "3.7.1"
27
+ "confbox": "^0.2.4",
28
+ "fs-extra": "^11.3.3",
29
+ "knitwork-x": "^0.2.0",
30
+ "ofetch": "^1.5.1",
31
+ "p-pipe": "^4.0.0",
32
+ "prettier": "^3.8.1",
33
+ "@genapi/shared": "4.0.0",
34
+ "@genapi/transform": "4.0.0"
30
35
  },
31
36
  "devDependencies": {
32
- "@types/fs-extra": "^11.0.1"
37
+ "@types/fs-extra": "^11.0.4",
38
+ "@types/prettier": "^2.7.3"
33
39
  },
34
40
  "scripts": {
35
41
  "build": "tsdown",
36
- "start": "tsx src/index.ts"
37
- },
38
- "exports": {
39
- ".": "./dist/index.mjs"
40
- },
41
- "module": "./dist/index.mjs",
42
- "types": "./dist/index.d.mts"
42
+ "dev": "tsdown --watch",
43
+ "typecheck": "tsc --noEmit",
44
+ "automd": "automd"
45
+ }
43
46
  }