Skip to content

Commit 1514a98

Browse files
authored
feat: openapi 3.2.0 nodeType (#191)
* feat: openapi 3.2 nodeType * chore: remove ununsed case
1 parent cec74bc commit 1514a98

File tree

7 files changed

+3804
-3853
lines changed

7 files changed

+3804
-3853
lines changed

package-lock.json

Lines changed: 3108 additions & 3800 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/openapi-sampler.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ function convertJsonToXml(obj, schema) {
1717
obj = { [schema?.xml?.name || 'root']: obj }; // XML document must contain one root element
1818
}
1919
const builder = new XMLBuilder({
20-
ignoreAttributes : false,
20+
ignoreAttributes: false,
2121
format: true,
2222
attributeNamePrefix: '$',
2323
textNodeName: '#text',
24+
cdataPropName: '#cdata',
2425
});
2526
return builder.build(obj);
2627
}

src/samplers/array.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,27 @@ export function sampleArray(schema, options = {}, spec, context) {
2323

2424
for (let i = 0; i < arrayLength; i++) {
2525
let itemSchema = itemSchemaGetter(i);
26-
let { value: sample } = traverse(itemSchema, options, spec, {depth: depth + 1});
26+
let { value: sample } = traverse(itemSchema, options, spec, { depth: depth + 1 });
2727
if (options?.format === 'xml') {
28-
const { value, propertyName } = applyXMLAttributes({value: sample}, itemSchema, context);
28+
const { value, propertyName } = applyXMLAttributes({ value: sample }, itemSchema, context);
2929
if (propertyName) {
3030
if (!res?.[propertyName]) {
3131
res = { ...res, [propertyName]: [] };
3232
}
3333
res[propertyName].push(value);
3434
} else {
35-
res = {...res, ...value};
35+
res = { ...res, ...value };
3636
}
3737
} else {
3838
res.push(sample);
3939
}
4040
}
4141

4242
if (options?.format === 'xml' && depth === 1) {
43-
const { value, propertyName } = applyXMLAttributes({value: null}, schema, context);
43+
const { value, propertyName } = applyXMLAttributes({ value: null }, schema, context);
4444
if (propertyName) {
4545
if (value) {
46-
res = Array.isArray(res) ? { [propertyName]: {...value, ...res.map(item => ({['#text']: {...item}}))} } : { [propertyName]: {...res, ...value }};
46+
res = Array.isArray(res) ? { [propertyName]: { ...value, ...res.map(item => ({ ['#text']: { ...item } })) } } : { [propertyName]: { ...res, ...value } };
4747
} else {
4848
res = { [propertyName]: res };
4949
}

src/samplers/object.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export function sampleObject(schema, options = {}, spec, context) {
1313
const requiredPropertiesMap = {};
1414

1515
for (const requiredProperty of requiredProperties) {
16-
requiredPropertiesMap[requiredProperty] = true;
16+
requiredPropertiesMap[requiredProperty] = true;
1717
}
1818

1919
Object.keys(schema.properties).forEach(propertyName => {
@@ -41,7 +41,7 @@ export function sampleObject(schema, options = {}, spec, context) {
4141
const { propertyName: newPropertyName, value } = applyXMLAttributes(sample, schema.properties[propertyName], { propertyName });
4242
if (newPropertyName) {
4343
res[newPropertyName] = value;
44-
} else {
44+
} else if (value !== null && typeof value === 'object') {
4545
res = { ...res, ...value };
4646
}
4747
} else {
@@ -52,8 +52,8 @@ export function sampleObject(schema, options = {}, spec, context) {
5252

5353
if (schema && typeof schema.additionalProperties === 'object') {
5454
const propertyName = schema.additionalProperties['x-additionalPropertiesName'] || 'property';
55-
res[`${String(propertyName)}1`] = traverse(schema.additionalProperties, options, spec, {depth: depth + 1 }).value;
56-
res[`${String(propertyName)}2`] = traverse(schema.additionalProperties, options, spec, {depth: depth + 1 }).value;
55+
res[`${String(propertyName)}1`] = traverse(schema.additionalProperties, options, spec, { depth: depth + 1 }).value;
56+
res[`${String(propertyName)}2`] = traverse(schema.additionalProperties, options, spec, { depth: depth + 1 }).value;
5757
}
5858

5959
// Strictly enforce maxProperties constraint
@@ -64,18 +64,18 @@ export function sampleObject(schema, options = {}, spec, context) {
6464
// Always include required properties first, if present
6565
const requiredProperties = Array.isArray(schema.required) ? schema.required : [];
6666
requiredProperties.forEach(propName => {
67-
if (res[propName] !== undefined) {
68-
filteredResult[propName] = res[propName];
69-
propertiesAdded++;
70-
}
67+
if (res[propName] !== undefined) {
68+
filteredResult[propName] = res[propName];
69+
propertiesAdded++;
70+
}
7171
});
7272

7373
// Add other properties until maxProperties is reached
7474
Object.keys(res).forEach(propName => {
75-
if (propertiesAdded < schema.maxProperties && !filteredResult.hasOwnProperty(propName)) {
76-
filteredResult[propName] = res[propName];
77-
propertiesAdded++;
78-
}
75+
if (propertiesAdded < schema.maxProperties && !filteredResult.hasOwnProperty(propName)) {
76+
filteredResult[propName] = res[propName];
77+
propertiesAdded++;
78+
}
7979
});
8080

8181
res = filteredResult;

src/traverse.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ export function traverse(schema, options, spec, context) {
7272
$refCache[ref] = true;
7373
const traverseResult = traverse(referenced, options, spec, context);
7474
if (options.format === 'xml') {
75-
const {propertyName, value} = applyXMLAttributes(traverseResult, referenced, context);
76-
result = {...traverseResult, value: {[propertyName || 'root']: value}};
75+
const refName = ref.split('/').pop();
76+
const xmlContext = { ...context, propertyName: context?.propertyName || refName };
77+
const { propertyName, value } = applyXMLAttributes(traverseResult, referenced, xmlContext);
78+
result = { ...traverseResult, value: { [propertyName || 'root']: value } };
7779
} else {
7880
result = traverseResult;
7981
}
@@ -172,12 +174,12 @@ export function traverse(schema, options, spec, context) {
172174
return inferred;
173175
}
174176

175-
const localExample = traverse({...schema, oneOf: undefined, anyOf: undefined }, options, spec, context);
177+
const localExample = traverse({ ...schema, oneOf: undefined, anyOf: undefined }, options, spec, context);
176178
const subSchemaExample = traverse(selectedSubSchema, options, spec, context);
177179

178180
if (typeof localExample.value === 'object' && typeof subSchemaExample.value === 'object') {
179181
const mergedExample = mergeDeep(localExample.value, subSchemaExample.value);
180-
return {...subSchemaExample, value: mergedExample };
182+
return { ...subSchemaExample, value: mergedExample };
181183
}
182184

183185
return subSchemaExample;

src/utils.js

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export function uuid(str) {
6464
export function getResultForCircular(type) {
6565
return {
6666
value: type === 'object' ?
67-
{}
67+
{}
6868
: type === 'array' ? [] : undefined
6969
};
7070
}
@@ -83,47 +83,89 @@ export function getXMLAttributes(schema) {
8383
};
8484
}
8585

86+
function resolveNodeType(schema) {
87+
const xml = schema?.xml;
88+
89+
if (xml?.nodeType) {
90+
return xml.nodeType;
91+
}
92+
93+
if (xml?.attribute === true) {
94+
return 'attribute';
95+
}
96+
97+
if (xml?.wrapped === true && schema?.type === 'array') {
98+
return 'element';
99+
}
100+
101+
if (schema?.$ref || schema?.$dynamicRef || schema?.type === 'array') {
102+
return 'none';
103+
}
104+
105+
if (schema?.oneOf || schema?.anyOf || schema?.allOf) {
106+
return 'none';
107+
}
108+
109+
return 'element';
110+
}
111+
86112
export function applyXMLAttributes(result, schema = {}, context = {}) {
87113
const { value: oldValue } = result;
88114
const { propertyName: oldPropertyName } = context;
89-
const { name, prefix, namespace, attribute, wrapped } =
90-
getXMLAttributes(schema);
115+
const { name, prefix, namespace } = getXMLAttributes(schema);
116+
const effectiveNodeType = resolveNodeType(schema);
117+
91118
let propertyName = name || oldPropertyName ? `${prefix ? prefix + ':' : ''}${name || oldPropertyName}` : null;
92119

93120
let value = typeof oldValue === 'object'
94121
? Array.isArray(oldValue)
95-
? [...oldValue]
96-
: { ...oldValue }
122+
? [...oldValue]
123+
: { ...oldValue }
97124
: oldValue;
98125

99-
if (attribute && propertyName) {
100-
propertyName = `$${propertyName}`;
126+
switch (effectiveNodeType) {
127+
case 'attribute':
128+
if (propertyName) {
129+
propertyName = `$${propertyName}`;
130+
}
131+
break;
132+
133+
case 'text':
134+
propertyName = '#text';
135+
break;
136+
137+
case 'cdata':
138+
propertyName = '#cdata';
139+
break;
140+
141+
case 'none':
142+
if (schema.type === 'array') {
143+
propertyName = null;
144+
if (schema.example !== undefined) {
145+
propertyName = schema.items?.xml?.name || propertyName;
146+
}
147+
} else {
148+
propertyName = null;
149+
}
150+
break;
151+
152+
default:
153+
if (schema.type === 'array') {
154+
if (Array.isArray(value)) {
155+
value = { [propertyName]: [...value] };
156+
}
157+
}
158+
break;
101159
}
102160

103-
if (namespace) {
161+
if (namespace && effectiveNodeType !== 'text' && effectiveNodeType !== 'cdata' && effectiveNodeType !== 'none') {
104162
if (typeof value === 'object') {
105163
value[`$xmlns${prefix ? ':' + prefix : ''}`] = namespace;
106164
} else {
107165
value = { [`$xmlns${prefix ? ':' + prefix : ''}`]: namespace, ['#text']: value };
108166
}
109167
}
110168

111-
if (schema.type === 'array') {
112-
if (wrapped && Array.isArray(value)) {
113-
value = { [propertyName]: [...value] };
114-
}
115-
if (!wrapped) {
116-
propertyName = null;
117-
}
118-
119-
if (schema.example !== undefined && !wrapped) {
120-
propertyName = schema.items?.xml?.name || propertyName;
121-
}
122-
}
123-
if (schema.oneOf || schema.anyOf || schema.allOf || schema.$ref) {
124-
propertyName = null;
125-
}
126-
127169
return {
128170
propertyName,
129171
value,

0 commit comments

Comments
 (0)