Skip to content

Commit 5f1ca3f

Browse files
fix(json-schema): handle duplicate field names (#13)
Some app configs may have duplicate field names. Forman handles that with bidirectional value binding. In JSON Schema, we can't have duplicate property names, so if the property has already been defined, we skip the redefinition, and keep the first defined one only.
1 parent fe98e1e commit 5f1ca3f

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# system related
22
.DS_Store
33
.vscode
4+
.idea
45

56
#test related
67
coverage/*

src/forman.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,15 @@ function handleCollectionType(field: FormanSchemaField, result: JSONSchema7, con
221221

222222
if (!subField.name) return;
223223

224+
/*
225+
Some app configs may have duplicate field names.
226+
Forman handles that with bidirectional value binding.
227+
In JSON Schema, we can't have duplicate property names,
228+
so if the property has already been defined, we skip the redefinition,
229+
and keep the first defined one only.
230+
*/
231+
if (result.properties && Object.hasOwn(result.properties, subField.name)) return;
232+
224233
if (subField.required) {
225234
result.required!.push(subField.name);
226235
}

test/redefine.spec.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { describe, expect, it } from '@jest/globals';
2+
import { toJSONSchema } from '../src';
3+
4+
describe('Redefine', () => {
5+
// This is nasty, but apparently some app configs have it like that...
6+
it('should survive redefinition of properties', () => {
7+
const field = {
8+
type: 'collection',
9+
spec: [
10+
{
11+
name: 'name',
12+
type: 'text',
13+
label: 'Name',
14+
},
15+
{
16+
name: 'age',
17+
type: 'uinteger',
18+
label: 'Age',
19+
},
20+
{
21+
name: 'name',
22+
type: 'text',
23+
label: 'Full Name',
24+
},
25+
],
26+
};
27+
const schema = toJSONSchema(field);
28+
expect(schema).toStrictEqual({
29+
description: undefined,
30+
properties: {
31+
age: {
32+
description: undefined,
33+
title: 'Age',
34+
type: 'number',
35+
},
36+
name: {
37+
description: undefined,
38+
title: 'Name',
39+
type: 'string',
40+
},
41+
},
42+
required: [],
43+
title: undefined,
44+
type: 'object',
45+
});
46+
});
47+
});

0 commit comments

Comments
 (0)