wormajs 0.3.1 → 0.4.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.
|
@@ -39,6 +39,9 @@ function aiDoc(config) {
|
|
|
39
39
|
? (node_path_1.default.isAbsolute(customTemplatePath) ? customTemplatePath : node_path_1.default.resolve(projectPath, customTemplatePath))
|
|
40
40
|
: (0, template_1.getPresetTemplatePath)(constant_1.PresetTemplateName.AI_DOC);
|
|
41
41
|
const serverName = capturedServerName || templateData.title || 'API';
|
|
42
|
+
// Skill name written into SKILL.md frontmatter. Defaults to `apis-<title>`
|
|
43
|
+
// which is the historical name the generated skill used before this option existed.
|
|
44
|
+
const skillName = config?.skillName ?? `apis-${templateData.title ?? ''}`;
|
|
42
45
|
// Compute file location for each API (relative path from project root to generated file)
|
|
43
46
|
// Skip fileLocation for alova-globals since APIs are called globally, not from a specific file
|
|
44
47
|
const isGlobals = templateData.config?.templateName === 'alova-globals';
|
|
@@ -65,6 +68,7 @@ function aiDoc(config) {
|
|
|
65
68
|
data: {
|
|
66
69
|
...enrichedData,
|
|
67
70
|
serverName,
|
|
71
|
+
skillName,
|
|
68
72
|
},
|
|
69
73
|
});
|
|
70
74
|
if (agentValue) {
|
|
@@ -55,7 +55,6 @@ const VALID_PRIMITIVES = new Set([
|
|
|
55
55
|
'unknown',
|
|
56
56
|
'any',
|
|
57
57
|
'never',
|
|
58
|
-
'integer',
|
|
59
58
|
]);
|
|
60
59
|
function validatePrimitive(val) {
|
|
61
60
|
if (!VALID_PRIMITIVES.has(val)) {
|
|
@@ -86,13 +85,20 @@ function toSchemaObject(base, s) {
|
|
|
86
85
|
const arr = s;
|
|
87
86
|
cleanType(result);
|
|
88
87
|
result.type = 'array';
|
|
89
|
-
|
|
88
|
+
// Pass the original `items` down as the base of each element so documentation
|
|
89
|
+
// fields (e.g. `description`) survive the round-trip.
|
|
90
|
+
const baseItems = base.items;
|
|
91
|
+
const baseItemsList = Array.isArray(baseItems) ? baseItems : (baseItems ? [baseItems] : []);
|
|
92
|
+
const items = arr.map((item, idx) => toSchemaObject((baseItemsList[idx] || {}), item));
|
|
90
93
|
result.items = (items.length === 1 ? items[0] : items);
|
|
91
94
|
return result;
|
|
92
95
|
}
|
|
93
96
|
// Primitive types — validate against SchemaPrimitive set during conversion
|
|
94
97
|
if (typeof s === 'string') {
|
|
95
98
|
validatePrimitive(s);
|
|
99
|
+
// Drop the structural fields inherited from the base so they don't leak into the
|
|
100
|
+
// new type; documentation fields such as `description` are kept.
|
|
101
|
+
cleanType(result);
|
|
96
102
|
result.type = s;
|
|
97
103
|
return result;
|
|
98
104
|
}
|
|
@@ -118,15 +124,28 @@ function toSchemaObject(base, s) {
|
|
|
118
124
|
result.allOf = spec.allOf.map((item, idx) => toSchemaObject(baseAllOf[idx] || {}, item));
|
|
119
125
|
return result;
|
|
120
126
|
}
|
|
121
|
-
// Enum:
|
|
127
|
+
// Enum: write the enum values back, converting the TS primitive type from the
|
|
128
|
+
// handler into its OpenAPI counterpart (`number` -> `integer`/`number`, `string`, ...).
|
|
122
129
|
if (s.enum) {
|
|
123
130
|
const spec = s;
|
|
131
|
+
// Drop the structural fields inherited from the base; documentation fields are kept.
|
|
132
|
+
cleanType(result);
|
|
124
133
|
result.enum = spec.enum;
|
|
125
134
|
if (spec.type) {
|
|
126
135
|
if (typeof spec.type === 'string') {
|
|
127
136
|
validatePrimitive(spec.type);
|
|
128
137
|
}
|
|
129
|
-
|
|
138
|
+
// `number` only becomes `integer` when every enum value is an integer.
|
|
139
|
+
result.type = enumTypeToSchemaType(spec.type, spec.enum);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
// No type from the handler: keep an OpenAPI 3.1 type array (e.g. `['string', 'null']`)
|
|
143
|
+
// as-is, otherwise infer the type from the enum values.
|
|
144
|
+
const fallback = Array.isArray(base.type) ? base.type : inferEnumType(spec.enum);
|
|
145
|
+
if (fallback) {
|
|
146
|
+
result.type = fallback;
|
|
147
|
+
}
|
|
148
|
+
// otherwise the enum stays untyped (mixed or empty values)
|
|
130
149
|
}
|
|
131
150
|
return result;
|
|
132
151
|
}
|
|
@@ -135,9 +154,14 @@ function toSchemaObject(base, s) {
|
|
|
135
154
|
// scalar fields like description from base)
|
|
136
155
|
const ref = s;
|
|
137
156
|
if (ref && typeof ref === 'object') {
|
|
157
|
+
// Drop the structural fields inherited from the base; documentation fields are kept.
|
|
158
|
+
cleanType(result);
|
|
138
159
|
result.type = 'object';
|
|
139
160
|
const properties = {};
|
|
140
161
|
const requiredSet = new Set();
|
|
162
|
+
// The base of each property is taken from the ORIGINAL `base.properties` (not from the
|
|
163
|
+
// object being built) so documentation fields like `description` survive the round-trip.
|
|
164
|
+
const baseProperties = (base.properties || {});
|
|
141
165
|
for (const key in ref) {
|
|
142
166
|
const val = ref[key];
|
|
143
167
|
if (!val) {
|
|
@@ -157,7 +181,7 @@ function toSchemaObject(base, s) {
|
|
|
157
181
|
isOptional = false;
|
|
158
182
|
effectiveVal = val;
|
|
159
183
|
}
|
|
160
|
-
const baseProp =
|
|
184
|
+
const baseProp = baseProperties[key];
|
|
161
185
|
properties[key] = toSchemaObject(baseProp || {}, effectiveVal);
|
|
162
186
|
if (isOptional) {
|
|
163
187
|
requiredSet.delete(key);
|
|
@@ -187,6 +211,37 @@ function schemaTypeToPrimitiveType(t) {
|
|
|
187
211
|
}
|
|
188
212
|
return t;
|
|
189
213
|
}
|
|
214
|
+
// Convert a SchemaPrimitive (the TS type used by the handler) back into the OpenAPI type
|
|
215
|
+
// of an enum. A numeric enum is written as `integer` (the OpenAPI counterpart of the TS
|
|
216
|
+
// `number`) only when every value is an integer, otherwise it stays `number` so the type
|
|
217
|
+
// matches the values. `string`/`boolean` map 1:1, TS-only types are written through as-is.
|
|
218
|
+
function enumTypeToSchemaType(t, enumValues) {
|
|
219
|
+
if (t === 'number') {
|
|
220
|
+
return enumValues.every(v => typeof v === 'number' && Number.isInteger(v))
|
|
221
|
+
? 'integer'
|
|
222
|
+
: 'number';
|
|
223
|
+
}
|
|
224
|
+
return t;
|
|
225
|
+
}
|
|
226
|
+
// Infer the OpenAPI type of an enum from its values, used when no type is declared so the
|
|
227
|
+
// enum does not stay untyped. Returns `undefined` for mixed or empty values so that no
|
|
228
|
+
// (possibly wrong) type is written.
|
|
229
|
+
function inferEnumType(enumValues) {
|
|
230
|
+
if (!enumValues.length) {
|
|
231
|
+
return undefined;
|
|
232
|
+
}
|
|
233
|
+
if (enumValues.every(v => typeof v === 'string')) {
|
|
234
|
+
return 'string';
|
|
235
|
+
}
|
|
236
|
+
if (enumValues.every(v => typeof v === 'boolean')) {
|
|
237
|
+
return 'boolean';
|
|
238
|
+
}
|
|
239
|
+
if (enumValues.every(v => typeof v === 'number')) {
|
|
240
|
+
return enumValues.every(v => Number.isInteger(v)) ? 'integer' : 'number';
|
|
241
|
+
}
|
|
242
|
+
// mixed value types -> leave the enum untyped
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
190
245
|
// Convert existing OpenAPI SchemaObject -> Schema (best-effort, for handler input)
|
|
191
246
|
function toSchemaSpec(obj) {
|
|
192
247
|
if (!obj || typeof obj !== 'object') {
|
|
@@ -205,9 +260,12 @@ function toSchemaSpec(obj) {
|
|
|
205
260
|
const arr = obj.allOf;
|
|
206
261
|
return { allOf: arr.map(item => toSchemaSpec(item)) };
|
|
207
262
|
}
|
|
208
|
-
// Enum
|
|
263
|
+
// Enum: the OpenAPI type is normalized to its TS primitive counterpart
|
|
264
|
+
// (e.g. `integer` -> `number`), consistent with how plain primitives are converted.
|
|
209
265
|
if (Array.isArray(obj.enum) && obj.enum.length > 0) {
|
|
210
|
-
const type = typeof obj.type === 'string'
|
|
266
|
+
const type = typeof obj.type === 'string'
|
|
267
|
+
? schemaTypeToPrimitiveType(obj.type)
|
|
268
|
+
: undefined;
|
|
211
269
|
return { enum: obj.enum, type };
|
|
212
270
|
}
|
|
213
271
|
// Array -> native array
|
package/package.json
CHANGED
package/typings/plugins.d.ts
CHANGED
|
@@ -438,6 +438,12 @@ export type SkillAgent = "aider-desk" | "amp" | "antigravity" | "antigravity-cli
|
|
|
438
438
|
export interface AiDocConfig {
|
|
439
439
|
template?: string;
|
|
440
440
|
outputDir?: string;
|
|
441
|
+
/**
|
|
442
|
+
* Name written into the generated skill's `SKILL.md` frontmatter. This is the
|
|
443
|
+
* name the skill is installed/referenced under. When omitted, the skill keeps
|
|
444
|
+
* its default name derived from the API title: `apis-<title>`.
|
|
445
|
+
*/
|
|
446
|
+
skillName?: string;
|
|
441
447
|
/**
|
|
442
448
|
* Which coding agent(s) to install the generated skill into.
|
|
443
449
|
* - omitted: do NOT install the skill.
|
|
@@ -575,7 +581,7 @@ export declare function importType(imports: Record<string, string[]>, options?:
|
|
|
575
581
|
files?: string[];
|
|
576
582
|
}): ApiPlugin;
|
|
577
583
|
export type ModifierScope = "params" | "pathParams" | "data" | "response";
|
|
578
|
-
export type SchemaPrimitive = "number" | "string" | "boolean" | "undefined" | "null" | "unknown" | "any" | "never"
|
|
584
|
+
export type SchemaPrimitive = "number" | "string" | "boolean" | "undefined" | "null" | "unknown" | "any" | "never";
|
|
579
585
|
/**
|
|
580
586
|
* Array type: a native JS array whose elements are Schemas.
|
|
581
587
|
* e.g. ['string'] means string[]; ['string', 'number'] means the tuple [string, number]
|