wormajs 0.3.1 → 1.0.0-beta.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/dist/bin/actions.js +162 -5
- package/dist/bin/cli.js +7 -1
- package/dist/bin/renderer.js +2 -8
- package/dist/checkUpdates.js +98 -0
- package/dist/config.js +7 -0
- package/dist/constant.js +1 -2
- package/dist/core/WorkerPool.js +14 -0
- package/dist/core/loader/callingCodeLoader/helper.js +2 -3
- package/dist/core/loader/callingCodeLoader/index.js +1 -1
- package/dist/core/parser/openApiParser/helper.js +32 -19
- package/dist/core/parser/templateParser/index.js +25 -12
- package/dist/core/workerPool/index.js +2 -1
- package/dist/functions/changeReport.js +230 -0
- package/dist/functions/diffApis.js +82 -0
- package/dist/functions/diffDocument.js +542 -0
- package/dist/functions/sourceSnapshot.js +107 -0
- package/dist/functions/wormaJson.js +306 -66
- package/dist/generate.js +24 -2
- package/dist/helper/config/ConfigHelper.js +1 -2
- package/dist/helper/config/ConfigManager.js +7 -0
- package/dist/helper/config/GeneratorHelper.js +74 -21
- package/dist/helper/config/zType.js +24 -1
- package/dist/helper/template/index.js +60 -4
- package/dist/index.js +17 -1
- package/dist/plugins/index.js +2 -2
- package/dist/plugins/presets/aiDoc.js +4 -0
- package/dist/plugins/presets/payloadModifier/dsl.js +147 -0
- package/dist/plugins/presets/payloadModifier/index.js +122 -135
- package/dist/plugins/presets/payloadModifier/patch.js +171 -0
- package/dist/plugins/presets/payloadModifier/scope.js +109 -0
- package/dist/plugins/presets/platform/index.js +1 -3
- package/dist/plugins/presets/postman.js +105 -0
- package/dist/template/presets/ai-doc/SKILL.md.handlebars +1 -1
- package/dist/template/presets/alova/common/services/{tag}.d.cts.handlebars +1 -1
- package/dist/template/presets/alova/module/services/{tag}.d.ts.handlebars +1 -1
- package/dist/template/presets/alova/partials/dts-fn-declare.handlebars +1 -1
- package/dist/template/presets/alova/partials/dts-types.handlebars +12 -0
- package/dist/template/presets/alova/typescript/services/{tag}.ts.handlebars +11 -6
- package/dist/template/presets/axios/partials/dts-types.handlebars +9 -5
- package/dist/template/presets/axios/typescript/services/{tag}.ts.handlebars +9 -5
- package/dist/template/presets/fetch/partials/dts-types.handlebars +8 -5
- package/dist/template/presets/fetch/typescript/services/{tag}.ts.handlebars +9 -5
- package/dist/template/presets/ky/partials/dts-types.handlebars +8 -5
- package/dist/template/presets/ky/typescript/services/{tag}.ts.handlebars +9 -5
- package/dist/utils/format.js +62 -15
- package/dist/utils/template.js +1 -1
- package/package.json +3 -2
- package/typings/index.d.ts +266 -13
- package/typings/plugins.d.ts +171 -80
- package/dist/plugins/presets/payloadModifier/hepler.js +0 -289
- package/dist/plugins/presets/platform/fastapi.js +0 -22
- package/dist/template/presets/alova/partials/dts-extra-config.handlebars +0 -8
|
@@ -2,154 +2,140 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.payloadModifier = payloadModifier;
|
|
4
4
|
const constant_1 = require("../../../constant");
|
|
5
|
+
const logger_1 = require("../../../helper/logger");
|
|
5
6
|
const utils_1 = require("../utils");
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
const dsl_1 = require("./dsl");
|
|
8
|
+
const patch_1 = require("./patch");
|
|
9
|
+
const scope_1 = require("./scope");
|
|
10
|
+
const LOG_TAG = '[payloadModifier]';
|
|
11
|
+
/** Tests a value against one or more rules. No rule given = everything matches. */
|
|
12
|
+
function matchRule(value, rule) {
|
|
13
|
+
if (rule === undefined) {
|
|
14
|
+
return true;
|
|
11
15
|
}
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
if (param.in === type) {
|
|
15
|
-
;
|
|
16
|
-
schema.properties[param.name] = param.schema;
|
|
17
|
-
if (param.required) {
|
|
18
|
-
;
|
|
19
|
-
schema.required.push(param.name);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return schema;
|
|
16
|
+
const rules = Array.isArray(rule) ? rule : [rule];
|
|
17
|
+
return rules.some(item => (0, utils_1.isMatch)(value, item));
|
|
24
18
|
}
|
|
25
|
-
|
|
26
|
-
function
|
|
27
|
-
if (
|
|
28
|
-
return
|
|
19
|
+
/** Tag dimension: any tag hitting any rule makes the config apply. */
|
|
20
|
+
function matchTags(tags, rule) {
|
|
21
|
+
if (rule === undefined) {
|
|
22
|
+
return true;
|
|
29
23
|
}
|
|
30
|
-
if (!
|
|
31
|
-
return
|
|
24
|
+
if (!Array.isArray(tags) || tags.length === 0) {
|
|
25
|
+
return false;
|
|
32
26
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
27
|
+
return tags.some(tag => matchRule(tag, rule));
|
|
28
|
+
}
|
|
29
|
+
/** Interface filters are ANDed together. */
|
|
30
|
+
function matchApi(apiDescriptor, config) {
|
|
31
|
+
return matchRule(apiDescriptor.url ?? '', config.path)
|
|
32
|
+
&& matchTags(apiDescriptor.tags, config.tag);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Navigates an unwrap path. Only `properties` is followed, so array items are out of
|
|
36
|
+
* reach by design — use `handler` for those. Returns `undefined` when a segment is missing.
|
|
37
|
+
*/
|
|
38
|
+
function unwrapSchema(root, path) {
|
|
39
|
+
let node = root;
|
|
40
|
+
for (const segment of path.split('.')) {
|
|
41
|
+
if (!node || !node.properties) {
|
|
42
|
+
return undefined;
|
|
43
43
|
}
|
|
44
|
-
|
|
45
|
-
...param,
|
|
46
|
-
schema: propSchema,
|
|
47
|
-
required: requiredSet.has(param.name),
|
|
48
|
-
});
|
|
44
|
+
node = node.properties[segment];
|
|
49
45
|
}
|
|
50
|
-
return
|
|
46
|
+
return node;
|
|
51
47
|
}
|
|
52
|
-
|
|
53
|
-
function
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
/** Runs patch then handler on a single located node. */
|
|
49
|
+
function applyStages(node, key, config, warn) {
|
|
50
|
+
let result = { schema: node };
|
|
51
|
+
if ('patch' in config) {
|
|
52
|
+
result = (0, patch_1.applyFieldValue)(node, config.patch, { warn });
|
|
53
|
+
if (!result.schema) {
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
56
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
targetSchema.oneOf = targetSchema.oneOf.map(item => modifySchemaProperties(item, config));
|
|
57
|
+
if (config.handler) {
|
|
58
|
+
const handled = config.handler(result.schema, key);
|
|
59
|
+
return { schema: handled ? (0, dsl_1.stripRef)(handled) : null, required: result.required };
|
|
61
60
|
}
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
function applyConfig(apiDescriptor, config) {
|
|
64
|
+
if (!apiDescriptor || !matchApi(apiDescriptor, config)) {
|
|
65
|
+
return apiDescriptor;
|
|
64
66
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
const warn = (message) => logger_1.logger.warn(`${LOG_TAG} ${message}`);
|
|
68
|
+
const root = (0, scope_1.getScopeSchema)(apiDescriptor, config.scope);
|
|
69
|
+
if (!root) {
|
|
70
|
+
return apiDescriptor;
|
|
67
71
|
}
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
const { required: requiredOverride, schema: schemaValue } = (0, hepler_1.applyModifierSchema)(props[key], config, { required: required.includes(key), key });
|
|
77
|
-
required = required.filter(r => r !== key);
|
|
78
|
-
if (!schemaValue) {
|
|
79
|
-
delete props[key];
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
props[key] = schemaValue;
|
|
83
|
-
if (requiredOverride) {
|
|
84
|
-
required.push(key);
|
|
85
|
-
}
|
|
72
|
+
// 1. redirect: the scope root itself is replaced before anything else runs
|
|
73
|
+
let located = root;
|
|
74
|
+
if (config.unwrap !== undefined) {
|
|
75
|
+
const unwrapped = unwrapSchema(root, config.unwrap);
|
|
76
|
+
if (!unwrapped) {
|
|
77
|
+
warn(`unwrap "${config.unwrap}" does not exist in scope "${config.scope}" of ${apiDescriptor.url}, config skipped`);
|
|
78
|
+
return apiDescriptor;
|
|
86
79
|
}
|
|
87
|
-
|
|
88
|
-
targetSchema.required = Array.from(new Set(required));
|
|
80
|
+
located = (0, dsl_1.stripRef)(unwrapped);
|
|
89
81
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return
|
|
82
|
+
// 2. locate: either the root itself or every matching top-level field
|
|
83
|
+
if (config.match === undefined) {
|
|
84
|
+
const { schema } = applyStages(located, undefined, config, warn);
|
|
85
|
+
const next = { ...apiDescriptor };
|
|
86
|
+
(0, scope_1.setScopeSchema)(next, config.scope, schema);
|
|
87
|
+
return next;
|
|
96
88
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
89
|
+
const keys = Object.keys(located.properties ?? {}).filter(key => (0, utils_1.isMatch)(key, config.match));
|
|
90
|
+
if (!keys.length) {
|
|
91
|
+
return apiDescriptor;
|
|
92
|
+
}
|
|
93
|
+
const properties = { ...(located.properties ?? {}) };
|
|
94
|
+
const required = new Set(Array.isArray(located.required) ? located.required : []);
|
|
95
|
+
for (const key of keys) {
|
|
96
|
+
const result = applyStages(properties[key], key, config, warn);
|
|
97
|
+
if (!result.schema) {
|
|
98
|
+
delete properties[key];
|
|
99
|
+
required.delete(key);
|
|
100
|
+
continue;
|
|
100
101
|
}
|
|
101
|
-
|
|
102
|
-
if (
|
|
103
|
-
|
|
102
|
+
properties[key] = result.schema;
|
|
103
|
+
if (result.required ?? required.has(key)) {
|
|
104
|
+
required.add(key);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
required.delete(key);
|
|
104
108
|
}
|
|
105
|
-
return { ...param, schema, required };
|
|
106
|
-
}).filter(item => item !== null);
|
|
107
|
-
}
|
|
108
|
-
// Apply config to a parameter scope (params or pathParams)
|
|
109
|
-
function applyToParameters(parameters, type, config) {
|
|
110
|
-
if (!parameters)
|
|
111
|
-
return undefined;
|
|
112
|
-
if (config.match) {
|
|
113
|
-
return modifyParameters(parameters, type, config);
|
|
114
|
-
}
|
|
115
|
-
const schema = parametersToSchema(parameters, type);
|
|
116
|
-
const result = (0, hepler_1.applyModifierSchema)(schema, config, { required: false });
|
|
117
|
-
return schemaToParameters(parameters, result.schema, type);
|
|
118
|
-
}
|
|
119
|
-
// Apply config to a schema scope (data or response)
|
|
120
|
-
function applyToSchemaField(schema, config) {
|
|
121
|
-
if (!schema)
|
|
122
|
-
return undefined;
|
|
123
|
-
if (config.match) {
|
|
124
|
-
return modifySchemaProperties(schema, config);
|
|
125
|
-
}
|
|
126
|
-
return (0, hepler_1.applyModifierSchema)(schema, config, { required: false }).schema ?? undefined;
|
|
127
|
-
}
|
|
128
|
-
function payloadModifierApiDescriptor(apiDescriptor, config) {
|
|
129
|
-
if (!apiDescriptor)
|
|
130
|
-
return null;
|
|
131
|
-
// API path filter: if path does not match, return as-is and this config does not apply
|
|
132
|
-
if (!(0, utils_1.isMatch)(apiDescriptor.url, config.path))
|
|
133
|
-
return apiDescriptor;
|
|
134
|
-
const newDescriptor = { ...apiDescriptor };
|
|
135
|
-
const { scope } = config;
|
|
136
|
-
switch (scope) {
|
|
137
|
-
case 'params':
|
|
138
|
-
newDescriptor.parameters = applyToParameters(newDescriptor.parameters, constant_1.ParameterIn.QUERY, config);
|
|
139
|
-
break;
|
|
140
|
-
case 'pathParams':
|
|
141
|
-
newDescriptor.parameters = applyToParameters(newDescriptor.parameters, constant_1.ParameterIn.PATH, config);
|
|
142
|
-
break;
|
|
143
|
-
case 'data':
|
|
144
|
-
newDescriptor.requestBody = applyToSchemaField(newDescriptor.requestBody, config);
|
|
145
|
-
break;
|
|
146
|
-
case 'response':
|
|
147
|
-
newDescriptor.responses = applyToSchemaField(newDescriptor.responses, config);
|
|
148
|
-
break;
|
|
149
109
|
}
|
|
150
|
-
|
|
110
|
+
const next = { ...apiDescriptor };
|
|
111
|
+
(0, scope_1.setScopeSchema)(next, config.scope, {
|
|
112
|
+
...located,
|
|
113
|
+
properties,
|
|
114
|
+
required: Array.from(required),
|
|
115
|
+
});
|
|
116
|
+
return next;
|
|
151
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Flexibly adds, deletes and modifies the payload of your APIs.
|
|
120
|
+
*
|
|
121
|
+
* Every config runs the same fixed pipeline: interface filter (`path` / `tag`) → redirect
|
|
122
|
+
* (`unwrap`) → locate (`match`) → patch (`patch`) → custom (`handler`). Configs are applied
|
|
123
|
+
* in array order, so a later config sees the result of the previous ones.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* payloadModifier([
|
|
128
|
+
* { scope: 'response', unwrap: 'data' },
|
|
129
|
+
* { scope: 'response', match: /[Ii]d$/, patch: 'string' },
|
|
130
|
+
* { scope: 'data', path: '/planPoint', patch: { operatorId: { type: 'string', required: true } } },
|
|
131
|
+
* ])
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
152
134
|
function payloadModifier(configs) {
|
|
135
|
+
// Guards against the config hook being run twice for the same descriptor,
|
|
136
|
+
// which happens when the CLI loads the same plugin instance more than once.
|
|
137
|
+
const processed = Symbol('worma:payloadModifier:processed');
|
|
138
|
+
const list = Array.isArray(configs) ? configs : [configs];
|
|
153
139
|
return {
|
|
154
140
|
name: constant_1.PluginName.PAYLOAD_MODIFIER,
|
|
155
141
|
config({ config }) {
|
|
@@ -158,13 +144,14 @@ function payloadModifier(configs) {
|
|
|
158
144
|
if (!apiDescriptor) {
|
|
159
145
|
return null;
|
|
160
146
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
147
|
+
if (apiDescriptor[processed]) {
|
|
148
|
+
return apiDescriptor;
|
|
149
|
+
}
|
|
150
|
+
const next = list.reduce((descriptor, conf) => (descriptor ? applyConfig(descriptor, conf) : null), apiDescriptor);
|
|
151
|
+
if (next) {
|
|
152
|
+
next[processed] = true;
|
|
153
|
+
}
|
|
154
|
+
return next;
|
|
168
155
|
},
|
|
169
156
|
});
|
|
170
157
|
},
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RESERVED_KEYS = void 0;
|
|
4
|
+
exports.isPatchObject = isPatchObject;
|
|
5
|
+
exports.applyFieldValue = applyFieldValue;
|
|
6
|
+
exports.applyPropertiesPatch = applyPropertiesPatch;
|
|
7
|
+
const dsl_1 = require("./dsl");
|
|
8
|
+
/**
|
|
9
|
+
* OpenAPI keywords plus `required`. An object holding one of them is a partial patch of
|
|
10
|
+
* the target itself; an object holding none of them is a shorthand for `properties`.
|
|
11
|
+
*/
|
|
12
|
+
exports.RESERVED_KEYS = new Set([
|
|
13
|
+
'type',
|
|
14
|
+
'required',
|
|
15
|
+
'description',
|
|
16
|
+
'properties',
|
|
17
|
+
'items',
|
|
18
|
+
'enum',
|
|
19
|
+
'oneOf',
|
|
20
|
+
'anyOf',
|
|
21
|
+
'allOf',
|
|
22
|
+
'format',
|
|
23
|
+
'example',
|
|
24
|
+
'default',
|
|
25
|
+
'deprecated',
|
|
26
|
+
'nullable',
|
|
27
|
+
'title',
|
|
28
|
+
]);
|
|
29
|
+
/** Keys written through verbatim when present in a patch object. */
|
|
30
|
+
const DOC_KEYS = [
|
|
31
|
+
'description',
|
|
32
|
+
'title',
|
|
33
|
+
'format',
|
|
34
|
+
'example',
|
|
35
|
+
'default',
|
|
36
|
+
'deprecated',
|
|
37
|
+
'nullable',
|
|
38
|
+
];
|
|
39
|
+
function isPatchObject(value) {
|
|
40
|
+
return Object.keys(value).some(key => exports.RESERVED_KEYS.has(key));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Applies a single patch value to a target schema. This is the one and only entry point
|
|
44
|
+
* of the patch syntax: the same rules apply to the top level patch and to every value
|
|
45
|
+
* inside a field table, therefore they apply recursively.
|
|
46
|
+
*
|
|
47
|
+
* @param current the target schema, `undefined` when the patch creates a new field
|
|
48
|
+
*/
|
|
49
|
+
function applyFieldValue(current, value, ctx) {
|
|
50
|
+
if (value === null) {
|
|
51
|
+
return { schema: null };
|
|
52
|
+
}
|
|
53
|
+
if (typeof value === 'string' || Array.isArray(value)) {
|
|
54
|
+
return { schema: replaceType(current, value) };
|
|
55
|
+
}
|
|
56
|
+
const patch = value;
|
|
57
|
+
if (!isPatchObject(patch)) {
|
|
58
|
+
return applyTablePatch(current, patch, ctx);
|
|
59
|
+
}
|
|
60
|
+
return applyPatchObject(current, patch, ctx);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Applies a field table to a target: a value of `null` deletes the field, every other
|
|
64
|
+
* value is applied recursively. Fields added this way are required unless they say otherwise.
|
|
65
|
+
*/
|
|
66
|
+
function applyPropertiesPatch(target, table, ctx) {
|
|
67
|
+
const properties = { ...(target.properties ?? {}) };
|
|
68
|
+
const required = new Set(Array.isArray(target.required) ? target.required : []);
|
|
69
|
+
for (const key of Object.keys(table)) {
|
|
70
|
+
const isNew = !(key in properties);
|
|
71
|
+
const result = applyFieldValue(isNew ? undefined : properties[key], table[key], ctx);
|
|
72
|
+
if (!result.schema) {
|
|
73
|
+
delete properties[key];
|
|
74
|
+
required.delete(key);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
properties[key] = result.schema;
|
|
78
|
+
const nextRequired = result.required ?? (isNew ? true : required.has(key));
|
|
79
|
+
if (nextRequired) {
|
|
80
|
+
required.add(key);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
required.delete(key);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
...target,
|
|
88
|
+
type: 'object',
|
|
89
|
+
properties,
|
|
90
|
+
required: Array.from(required),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** `null` as the whole table means dropping every field. */
|
|
94
|
+
function applyTablePatch(current, table, ctx) {
|
|
95
|
+
const base = current ?? { type: 'object' };
|
|
96
|
+
if (!isObjectTarget(base)) {
|
|
97
|
+
ctx.warn('field table patch skipped: the target is not an object schema');
|
|
98
|
+
return { schema: current ?? null };
|
|
99
|
+
}
|
|
100
|
+
return { schema: applyPropertiesPatch(base, table, ctx) };
|
|
101
|
+
}
|
|
102
|
+
function applyPatchObject(current, patch, ctx) {
|
|
103
|
+
let out = current ? { ...current } : {};
|
|
104
|
+
let required;
|
|
105
|
+
if (patch.type !== undefined) {
|
|
106
|
+
out = {
|
|
107
|
+
...(0, dsl_1.stripRef)((0, dsl_1.clearTypeFamily)(out)),
|
|
108
|
+
...(0, dsl_1.dslToSchemaObject)(patch.type),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
// `required` never becomes a schema key, the caller translates it.
|
|
112
|
+
if (patch.required !== undefined) {
|
|
113
|
+
required = !!patch.required;
|
|
114
|
+
}
|
|
115
|
+
if (patch.properties !== undefined) {
|
|
116
|
+
if (isObjectTarget(out)) {
|
|
117
|
+
out = applyPropertiesPatch(out, patch.properties, ctx);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
ctx.warn('`properties` patch skipped: the target is not an object schema');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (patch.items !== undefined) {
|
|
124
|
+
out.items = (0, dsl_1.dslToSchemaObject)(patch.items);
|
|
125
|
+
if (out.type !== 'array') {
|
|
126
|
+
out.type = 'array';
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (patch.enum !== undefined) {
|
|
130
|
+
out.enum = patch.enum;
|
|
131
|
+
if (out.type === undefined) {
|
|
132
|
+
const inferred = (0, dsl_1.inferEnumType)(patch.enum);
|
|
133
|
+
if (inferred) {
|
|
134
|
+
out.type = inferred;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// A union fully determines the type, so it replaces the type family just like `type` does.
|
|
139
|
+
for (const key of ['oneOf', 'anyOf', 'allOf']) {
|
|
140
|
+
const members = patch[key];
|
|
141
|
+
if (members === undefined) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
out = {
|
|
145
|
+
...(0, dsl_1.stripRef)((0, dsl_1.clearTypeFamily)(out)),
|
|
146
|
+
[key]: members.map(item => (0, dsl_1.dslToSchemaObject)(item)),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
for (const key of DOC_KEYS) {
|
|
150
|
+
const next = patch[key];
|
|
151
|
+
if (next !== undefined) {
|
|
152
|
+
out[key] = next;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return { schema: out, required };
|
|
156
|
+
}
|
|
157
|
+
/** Replaces the type of a target: type-family keys are cleared, everything else is kept. */
|
|
158
|
+
function replaceType(current, dsl) {
|
|
159
|
+
const rest = (0, dsl_1.stripRef)((0, dsl_1.clearTypeFamily)(current ?? {}));
|
|
160
|
+
return { ...rest, ...(0, dsl_1.dslToSchemaObject)(dsl) };
|
|
161
|
+
}
|
|
162
|
+
/** A patch may only touch the field table when the target really is an object. */
|
|
163
|
+
function isObjectTarget(target) {
|
|
164
|
+
if (!target) {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
if (target.oneOf || target.anyOf || target.allOf) {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
return target.type === undefined || target.type === 'object';
|
|
171
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scopeParameterIn = scopeParameterIn;
|
|
4
|
+
exports.parametersToSchema = parametersToSchema;
|
|
5
|
+
exports.removeParameters = removeParameters;
|
|
6
|
+
exports.schemaToParameters = schemaToParameters;
|
|
7
|
+
exports.getScopeSchema = getScopeSchema;
|
|
8
|
+
exports.setScopeSchema = setScopeSchema;
|
|
9
|
+
const constant_1 = require("../../../constant");
|
|
10
|
+
/** Maps a scope onto the parameter location it owns. Schema scopes have no location. */
|
|
11
|
+
function scopeParameterIn(scope) {
|
|
12
|
+
if (scope === 'params') {
|
|
13
|
+
return constant_1.ParameterIn.QUERY;
|
|
14
|
+
}
|
|
15
|
+
if (scope === 'pathParams') {
|
|
16
|
+
return constant_1.ParameterIn.PATH;
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
/** Builds an object-schema view of the parameters of one location. */
|
|
21
|
+
function parametersToSchema(parameters, location) {
|
|
22
|
+
const schema = { type: 'object', properties: {}, required: [] };
|
|
23
|
+
if (!Array.isArray(parameters)) {
|
|
24
|
+
return schema;
|
|
25
|
+
}
|
|
26
|
+
const properties = schema.properties;
|
|
27
|
+
const required = schema.required;
|
|
28
|
+
for (const param of parameters) {
|
|
29
|
+
if (param.in !== location) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
properties[param.name] = param.schema;
|
|
33
|
+
if (param.required) {
|
|
34
|
+
required.push(param.name);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return schema;
|
|
38
|
+
}
|
|
39
|
+
/** Drops every parameter of one location. */
|
|
40
|
+
function removeParameters(parameters, location) {
|
|
41
|
+
if (!Array.isArray(parameters)) {
|
|
42
|
+
return parameters;
|
|
43
|
+
}
|
|
44
|
+
return parameters.filter(param => param.in !== location);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Writes an object-schema view back into parameters. Parameters of other locations are
|
|
48
|
+
* kept untouched and fields absent from the original list are appended as new parameters.
|
|
49
|
+
*/
|
|
50
|
+
function schemaToParameters(parameters, schema, location) {
|
|
51
|
+
if (!Array.isArray(parameters)) {
|
|
52
|
+
return parameters;
|
|
53
|
+
}
|
|
54
|
+
if (!schema || typeof schema !== 'object' || !schema.properties) {
|
|
55
|
+
return removeParameters(parameters, location);
|
|
56
|
+
}
|
|
57
|
+
const properties = schema.properties;
|
|
58
|
+
const requiredSet = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
59
|
+
const next = [];
|
|
60
|
+
for (const param of parameters) {
|
|
61
|
+
if (param.in !== location) {
|
|
62
|
+
next.push(param);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const propSchema = properties[param.name];
|
|
66
|
+
if (!propSchema) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
next.push({ ...param, schema: propSchema, required: requiredSet.has(param.name) });
|
|
70
|
+
}
|
|
71
|
+
// fields added by a patch become brand new parameters
|
|
72
|
+
for (const name of Object.keys(properties)) {
|
|
73
|
+
if (next.some(param => param.in === location && param.name === name)) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
next.push({
|
|
77
|
+
name,
|
|
78
|
+
in: location,
|
|
79
|
+
required: requiredSet.has(name),
|
|
80
|
+
schema: properties[name],
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return next;
|
|
84
|
+
}
|
|
85
|
+
/** Reads the root schema of a scope. Parameter scopes are read as an object-schema view. */
|
|
86
|
+
function getScopeSchema(apiDescriptor, scope) {
|
|
87
|
+
const location = scopeParameterIn(scope);
|
|
88
|
+
if (location) {
|
|
89
|
+
return parametersToSchema(apiDescriptor.parameters, location);
|
|
90
|
+
}
|
|
91
|
+
return scope === 'data' ? apiDescriptor.requestBody : apiDescriptor.responses;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Writes the root schema of a scope back into the descriptor. `null` empties the scope.
|
|
95
|
+
*/
|
|
96
|
+
function setScopeSchema(apiDescriptor, scope, schema) {
|
|
97
|
+
const location = scopeParameterIn(scope);
|
|
98
|
+
if (location) {
|
|
99
|
+
apiDescriptor.parameters = schema === null
|
|
100
|
+
? removeParameters(apiDescriptor.parameters, location)
|
|
101
|
+
: schemaToParameters(apiDescriptor.parameters, schema, location);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (scope === 'data') {
|
|
105
|
+
apiDescriptor.requestBody = schema ?? undefined;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
apiDescriptor.responses = schema ?? undefined;
|
|
109
|
+
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.yapi = exports.swagger = exports.withCookie = exports.normalizeBase = exports.defineUrlPlatformPlugin = exports.knife4j =
|
|
4
|
-
var fastapi_1 = require("./fastapi");
|
|
5
|
-
Object.defineProperty(exports, "fastapi", { enumerable: true, get: function () { return fastapi_1.fastapi; } });
|
|
3
|
+
exports.yapi = exports.swagger = exports.withCookie = exports.normalizeBase = exports.defineUrlPlatformPlugin = exports.knife4j = void 0;
|
|
6
4
|
var knife4j_1 = require("./knife4j");
|
|
7
5
|
Object.defineProperty(exports, "knife4j", { enumerable: true, get: function () { return knife4j_1.knife4j; } });
|
|
8
6
|
var shared_1 = require("./shared");
|