Skip to content

Commit 23a344b

Browse files
committed
refactor: 重构 Arg 模块,更简练
1 parent c353038 commit 23a344b

File tree

16 files changed

+779
-523
lines changed

16 files changed

+779
-523
lines changed

src/printer/Arg.ts

Lines changed: 102 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,78 @@
11
import type { OpenAPILatest } from '../types/openapi';
22
import type { Named } from './Named';
3+
import type { PrinterOptions } from './types';
34
import { isRefParameter, type OpenApiLatest_Parameter, requiredKeyStringify } from './helpers';
45
import { Schemata } from './Schemata';
56

6-
export type ArgKind = 'path' | 'headers' | 'cookies' | 'params' | 'data' | 'config' | 'response';
7-
export interface ArgParsed {
8-
arg: Arg;
9-
originName: string;
10-
uniqueName: string;
11-
required: boolean;
12-
type: string;
13-
comments: Record<string, unknown>;
14-
props: string[];
15-
}
16-
interface InternalArgItem {
7+
export type ArgKind = 'path' | 'header' | 'cookie' | 'param' | 'data' | 'config' | 'response';
8+
9+
const kindAxiosPropNames: Record<ArgKind, string> = {
10+
path: 'url',
11+
header: 'headers',
12+
cookie: 'cookies',
13+
param: 'params',
14+
data: 'data',
15+
config: 'config',
16+
response: 'response',
17+
};
18+
const kindAxiosDocNames: Record<ArgKind, string> = {
19+
path: 'path',
20+
header: 'headers',
21+
cookie: 'cookies',
22+
param: 'params',
23+
data: 'data',
24+
config: 'config',
25+
response: 'response',
26+
};
27+
28+
export interface ArgProp {
29+
name: string;
1730
parameter: OpenAPILatest.ParameterObject;
1831
schema: OpenAPILatest.SchemaObject;
1932
}
2033

2134
export class Arg {
2235
parameters: OpenApiLatest_Parameter[] = [];
36+
originName: string = '';
37+
38+
/**
39+
* 作为属性的名称
40+
*/
41+
propName = '';
42+
/**
43+
* 作为参数的注释名称
44+
*/
45+
docName = '';
46+
/**
47+
* 作为参数的变量名称
48+
*/
49+
varName = '';
50+
/**
51+
* 是否必填
52+
*/
53+
required: boolean = false;
54+
/**
55+
* 类型
56+
*/
57+
type: string = '';
58+
comments: Record<string, unknown> = {};
59+
props: ArgProp[] = [];
2360

2461
constructor(
2562
readonly named: Named,
2663
readonly kind: ArgKind,
2764
readonly schemata: Schemata,
65+
readonly printOptions: PrinterOptions,
2866
/**
2967
* 是否单参数(如 data、config、response)
3068
*/
3169
readonly isSingle: boolean = false,
32-
) {}
70+
) {
71+
this.originName = this.kind;
72+
this.propName = kindAxiosPropNames[this.kind];
73+
this.docName = kindAxiosDocNames[this.kind];
74+
this.varName = '';
75+
}
3376

3477
url: string = '';
3578
urlParams: string[] = [];
@@ -57,11 +100,9 @@ export class Arg {
57100
this.parameters.push(parameter);
58101
}
59102

60-
parse(): ArgParsed | null {
61-
const internalArgItems: InternalArgItem[] = [];
103+
parse(): Arg | null {
62104
const fixedParameters = this.parameters.filter(p => !isRefParameter(p) && 'schema' in p && p.schema) as OpenAPILatest.ParameterObject[];
63105
const propLength = fixedParameters.length;
64-
const props = fixedParameters.map(p => p.name);
65106
const requiredNames: string[] = [];
66107

67108
fixedParameters.forEach((parameter) => {
@@ -75,79 +116,64 @@ export class Arg {
75116
parameter.required = true;
76117
}
77118

78-
internalArgItems.push({
119+
this.props.push({
79120
parameter,
121+
name,
80122
schema: schema!,
81123
});
82124
});
83125

84126
switch (propLength) {
85127
case 0: {
86-
if (this.kind === 'path') {
87-
return {
88-
arg: this,
89-
originName: this.kind,
90-
uniqueName: this.named.nextVarName(this.kind),
91-
// 路径参数必填
92-
required: true,
93-
type: this.defaultType,
94-
comments: {},
95-
props,
96-
};
97-
}
98-
99-
if (this.kind === 'config') {
100-
const name = this.named.nextVarName(this.kind);
101-
return {
102-
arg: this,
103-
originName: this.kind,
104-
uniqueName: name,
105-
required: false,
106-
type: this.defaultType,
107-
comments: {
108-
[`param [${name}]`]: 'request config',
109-
},
110-
props,
111-
};
128+
switch (this.kind) {
129+
case 'path':
130+
this.required = true;
131+
this.type = this.defaultType;
132+
this.varName = this.named.nextVarName(this.docName);
133+
return this;
134+
135+
case 'config':
136+
this.type = this.defaultType;
137+
this.varName = this.named.nextVarName(this.docName);
138+
this.comments = {
139+
[`param [${this.varName}]`]: `request ${this.propName}`,
140+
};
141+
return this;
112142
}
113-
114143
return null;
115144
}
116145

117146
case 1: {
118147
// prop0: type0
119-
const [firstArg] = internalArgItems;
148+
const [firstArg] = this.props;
120149
const { parameter, schema } = firstArg;
121150
const result = this.schemata.print(schema);
122-
const name = this.kind === 'response' ? this.kind : this.named.nextVarName(parameter.name || this.kind);
151+
const isResponse = this.kind === 'response';
123152
const required = parameter.required || result.required || false;
124153

125-
return {
126-
arg: this,
127-
originName: parameter.name,
128-
uniqueName: name,
129-
required,
130-
type: Schemata.toString(result, true),
131-
props,
132-
comments:
133-
this.kind === 'response'
134-
? {
135-
returns: parameter.description || schema.description || false,
136-
}
137-
: {
138-
[`param ${requiredKeyStringify(name, required)}`]:
139-
parameter.description || schema.description || `request ${this.kind === 'data' ? 'data' : 'param'}`,
140-
},
141-
};
154+
this.originName = firstArg.name;
155+
this.varName = this.named.nextVarName(firstArg.name);
156+
this.required = required;
157+
this.type = Schemata.toString(result);
158+
this.comments = isResponse
159+
? {
160+
returns: parameter.description || schema.description || false,
161+
}
162+
: {
163+
[
164+
`param ${requiredKeyStringify(this.varName, required)}`]: parameter.description || schema.description
165+
|| (this.kind === 'data' ? 'request data' : `request ${this.docName} ${JSON.stringify(firstArg.name)}`),
166+
};
167+
return this;
142168
}
143169

144170
default: {
145171
// name: {prop0: type0, prop1: type1, ...}
146172
const rootSchema: OpenAPILatest.SchemaObject = {
147173
type: 'object',
148-
properties: internalArgItems.reduce(
149-
(acc, { parameter, schema }) => {
150-
acc[parameter.name] = {
174+
properties: this.props.reduce(
175+
(acc, { parameter, schema, name: originName }) => {
176+
acc[originName] = {
151177
...schema,
152178
description: parameter.description || schema.description,
153179
deprecated: parameter.deprecated || schema.deprecated,
@@ -159,25 +185,19 @@ export class Arg {
159185
required: requiredNames,
160186
};
161187
const result = this.schemata.print(rootSchema);
162-
const name = this.named.nextVarName(this.kind);
163188
const required = requiredNames.length > 0;
164189

165-
return {
166-
arg: this,
167-
originName: this.kind,
168-
uniqueName: name,
169-
required,
170-
type: Schemata.toString(result),
171-
props,
172-
comments:
173-
this.kind === 'response'
174-
? {
175-
returns: result.comments.description,
176-
}
177-
: {
178-
[`param ${requiredKeyStringify(name, required)}`]: 'request params',
179-
},
180-
};
190+
this.required = required;
191+
this.type = Schemata.toString(result);
192+
this.varName = this.named.nextVarName(this.docName);
193+
this.comments = this.kind === 'response'
194+
? {
195+
returns: result.comments.description,
196+
}
197+
: {
198+
[`param ${requiredKeyStringify(this.docName, required)}`]: `request ${this.docName}`,
199+
};
200+
return this;
181201
}
182202
}
183203
}

src/printer/Args.ts

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import type { ArgParsed as FixedArg } from './Arg';
1+
import type { Arg } from './Arg';
22
import { requiredTypeStringify } from './helpers';
33

44
export class Args {
5-
fixedArgs: FixedArg[];
6-
constructor(private args: (FixedArg | null)[]) {
5+
fixedArgs: Arg[];
6+
constructor(private args: (Arg | null)[]) {
77
this.fixedArgs = this._sort();
88
}
99

1010
private _sort() {
11-
const fixedArgs = this.args.filter(Boolean) as FixedArg[];
11+
const fixedArgs = this.args.filter(Boolean) as Arg[];
1212
return fixedArgs.sort((a, b) => Number(b.required) - Number(a.required));
1313
}
1414

@@ -28,7 +28,7 @@ export class Args {
2828
return this.fixedArgs
2929
.filter(fixArg => fixArg.type !== '')
3030
.map((fixArg) => {
31-
return `${fixArg.uniqueName}${requiredTypeStringify(fixArg.required)}${fixArg.type}`;
31+
return `${fixArg.varName}${requiredTypeStringify(fixArg.required)}${fixArg.type}`;
3232
})
3333
.join(',');
3434
}
@@ -40,28 +40,38 @@ export class Args {
4040
toValues() {
4141
return this.fixedArgs
4242
.map((fixedArg) => {
43-
const { originName, uniqueName, arg, props } = fixedArg;
43+
const { originName, varName, propName, kind, props, url, isSingle } = fixedArg;
4444

45-
if (arg.kind === 'config')
46-
return `...${uniqueName}`;
45+
switch (kind) {
46+
case 'config':
47+
return `...${varName}`;
4748

48-
if (arg.kind === 'path') {
49-
const resolvedURL = arg.url.replace(/\{(.*?)\}/g, (_, name) => {
50-
if (!props.includes(name)) {
51-
throw new Error(`路径参数 ${name} 不存在`);
52-
}
49+
case 'path': {
50+
const pathNameInProps = props.reduce((acc, cur) => {
51+
acc[cur.name] = true;
52+
return acc;
53+
}, {} as Record<string, boolean>);
54+
const resolvedURL = url.replace(/\{(.*?)\}/g, (_, originName) => {
55+
const propPrintName = pathNameInProps[originName];
5356

54-
// 只有一个路径参数时,路径值直接传入
55-
if (props.length === 1)
56-
return `\${${uniqueName}}`;
57+
if (!propPrintName) {
58+
throw new Error(`路径参数 ${originName} 未定义`);
59+
}
5760

58-
return `\${${uniqueName}['${name}']}`;
59-
});
60-
return `url: \`${resolvedURL}\``;
61-
}
61+
// 只有一个路径参数时,路径值直接传入
62+
if (props.length === 1)
63+
return `\${${varName}}`;
64+
65+
return `\${${varName}[${JSON.stringify(propPrintName)}]}`;
66+
});
67+
return `url: \`${resolvedURL}\``;
68+
}
6269

63-
const value = props.length === 1 && !arg.isSingle ? `{${JSON.stringify(originName)}: ${uniqueName}}` : uniqueName;
64-
return `${arg.kind}: ${value}`;
70+
default: {
71+
const value = props.length === 1 && !isSingle ? `{${JSON.stringify(originName)}: ${varName}}` : varName;
72+
return `${propName}: ${value}`;
73+
}
74+
}
6575
})
6676
.join(',\n');
6777
}

src/printer/Named.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,19 @@ export class Named {
66
typeNameCountMap = new Map<string /* type */, number /* count */>();
77
refIdTypeMap = new Map<string /* refId */, string /* refType */>();
88

9-
constructor() {
10-
KEYWORD_VARS.forEach(this.internalVarName.bind(this));
11-
INTERNAL_VARS.forEach(this.internalVarName.bind(this));
12-
INTERNAL_TYPES.forEach(this.internalTypeName.bind(this));
9+
constructor({ keywordVars, internalTypes, internalVars }: {
10+
keywordVars?: boolean;
11+
internalVars?: boolean;
12+
internalTypes?: boolean;
13+
} = {}) {
14+
if (keywordVars)
15+
KEYWORD_VARS.forEach(this.internalVarName.bind(this));
16+
17+
if (internalVars)
18+
INTERNAL_VARS.forEach(this.internalVarName.bind(this));
19+
20+
if (internalTypes)
21+
INTERNAL_TYPES.forEach(this.internalTypeName.bind(this));
1322
}
1423

1524
/**

0 commit comments

Comments
 (0)