wormajs 0.3.0 → 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) {
|
|
@@ -85,13 +85,20 @@ function toSchemaObject(base, s) {
|
|
|
85
85
|
const arr = s;
|
|
86
86
|
cleanType(result);
|
|
87
87
|
result.type = 'array';
|
|
88
|
-
|
|
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));
|
|
89
93
|
result.items = (items.length === 1 ? items[0] : items);
|
|
90
94
|
return result;
|
|
91
95
|
}
|
|
92
96
|
// Primitive types — validate against SchemaPrimitive set during conversion
|
|
93
97
|
if (typeof s === 'string') {
|
|
94
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);
|
|
95
102
|
result.type = s;
|
|
96
103
|
return result;
|
|
97
104
|
}
|
|
@@ -117,15 +124,28 @@ function toSchemaObject(base, s) {
|
|
|
117
124
|
result.allOf = spec.allOf.map((item, idx) => toSchemaObject(baseAllOf[idx] || {}, item));
|
|
118
125
|
return result;
|
|
119
126
|
}
|
|
120
|
-
// 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`, ...).
|
|
121
129
|
if (s.enum) {
|
|
122
130
|
const spec = s;
|
|
131
|
+
// Drop the structural fields inherited from the base; documentation fields are kept.
|
|
132
|
+
cleanType(result);
|
|
123
133
|
result.enum = spec.enum;
|
|
124
134
|
if (spec.type) {
|
|
125
135
|
if (typeof spec.type === 'string') {
|
|
126
136
|
validatePrimitive(spec.type);
|
|
127
137
|
}
|
|
128
|
-
|
|
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)
|
|
129
149
|
}
|
|
130
150
|
return result;
|
|
131
151
|
}
|
|
@@ -134,9 +154,14 @@ function toSchemaObject(base, s) {
|
|
|
134
154
|
// scalar fields like description from base)
|
|
135
155
|
const ref = s;
|
|
136
156
|
if (ref && typeof ref === 'object') {
|
|
157
|
+
// Drop the structural fields inherited from the base; documentation fields are kept.
|
|
158
|
+
cleanType(result);
|
|
137
159
|
result.type = 'object';
|
|
138
160
|
const properties = {};
|
|
139
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 || {});
|
|
140
165
|
for (const key in ref) {
|
|
141
166
|
const val = ref[key];
|
|
142
167
|
if (!val) {
|
|
@@ -156,7 +181,7 @@ function toSchemaObject(base, s) {
|
|
|
156
181
|
isOptional = false;
|
|
157
182
|
effectiveVal = val;
|
|
158
183
|
}
|
|
159
|
-
const baseProp =
|
|
184
|
+
const baseProp = baseProperties[key];
|
|
160
185
|
properties[key] = toSchemaObject(baseProp || {}, effectiveVal);
|
|
161
186
|
if (isOptional) {
|
|
162
187
|
requiredSet.delete(key);
|
|
@@ -186,6 +211,37 @@ function schemaTypeToPrimitiveType(t) {
|
|
|
186
211
|
}
|
|
187
212
|
return t;
|
|
188
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
|
+
}
|
|
189
245
|
// Convert existing OpenAPI SchemaObject -> Schema (best-effort, for handler input)
|
|
190
246
|
function toSchemaSpec(obj) {
|
|
191
247
|
if (!obj || typeof obj !== 'object') {
|
|
@@ -204,9 +260,12 @@ function toSchemaSpec(obj) {
|
|
|
204
260
|
const arr = obj.allOf;
|
|
205
261
|
return { allOf: arr.map(item => toSchemaSpec(item)) };
|
|
206
262
|
}
|
|
207
|
-
// 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.
|
|
208
265
|
if (Array.isArray(obj.enum) && obj.enum.length > 0) {
|
|
209
|
-
const type = typeof obj.type === 'string'
|
|
266
|
+
const type = typeof obj.type === 'string'
|
|
267
|
+
? schemaTypeToPrimitiveType(obj.type)
|
|
268
|
+
: undefined;
|
|
210
269
|
return { enum: obj.enum, type };
|
|
211
270
|
}
|
|
212
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.
|