104 lines
3.0 KiB
TypeScript
104 lines
3.0 KiB
TypeScript
|
#!/usr/bin/env ts-node
|
||
|
|
||
|
/*---------------------------------------------------------------------------------------------
|
||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||
|
*--------------------------------------------------------------------------------------------*/
|
||
|
|
||
|
// Inlines "allOf"s to allow for "additionalProperties": false. (https://github.com/microsoft/vscode-remote-release/issues/2967)
|
||
|
// Run this manually after updating devContainer.schema.src.json.
|
||
|
|
||
|
import * as fs from 'fs';
|
||
|
|
||
|
function transform(schema: any) {
|
||
|
|
||
|
const definitions = Object.keys(schema.definitions)
|
||
|
.reduce((d, k) => {
|
||
|
d[`#/definitions/${k}`] = (schema.definitions as any)[k];
|
||
|
return d;
|
||
|
}, {} as any);
|
||
|
|
||
|
function copy(from: any) {
|
||
|
const type = Array.isArray(from) ? 'array' : typeof from;
|
||
|
switch (type) {
|
||
|
case 'object': {
|
||
|
const to: any = {};
|
||
|
for (const key in from) {
|
||
|
switch (key) {
|
||
|
case 'definitions':
|
||
|
break;
|
||
|
case 'oneOf':
|
||
|
const list = copy(from[key])
|
||
|
.reduce((a: any[], o: any) => {
|
||
|
if (o.oneOf) {
|
||
|
a.push(...o.oneOf);
|
||
|
} else {
|
||
|
a.push(o);
|
||
|
}
|
||
|
return a;
|
||
|
}, [] as any[]);
|
||
|
if (list.length === 1) {
|
||
|
Object.assign(to, list[0]);
|
||
|
} else {
|
||
|
to.oneOf = list;
|
||
|
}
|
||
|
break;
|
||
|
case 'allOf':
|
||
|
const all = copy(from[key]);
|
||
|
const leaves = all.map((one: any) => (one.oneOf ? one.oneOf : [one]));
|
||
|
function cross(res: any, leaves: any[][]): any[] {
|
||
|
if (leaves.length) {
|
||
|
const rest = leaves.slice(1);
|
||
|
return ([] as any[]).concat(...leaves[0].map(leaf => {
|
||
|
const intermediate = { ...res, ...leaf };
|
||
|
if ('properties' in res && 'properties' in leaf) {
|
||
|
intermediate.properties = {
|
||
|
...res.properties,
|
||
|
...leaf.properties,
|
||
|
};
|
||
|
}
|
||
|
return cross(intermediate, rest);
|
||
|
}));
|
||
|
}
|
||
|
return [res];
|
||
|
}
|
||
|
const list2 = cross({}, leaves);
|
||
|
if (list2.length === 1) {
|
||
|
Object.assign(to, list2[0]);
|
||
|
} else {
|
||
|
to.oneOf = list2;
|
||
|
}
|
||
|
break;
|
||
|
case '$ref':
|
||
|
const ref = from[key];
|
||
|
const definition = definitions[ref];
|
||
|
if (definition) {
|
||
|
Object.assign(to, copy(definition));
|
||
|
} else {
|
||
|
to[key] = ref;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
to[key] = copy(from[key]);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (to.type === 'object' && !('additionalProperties' in to)) {
|
||
|
to.additionalProperties = false;
|
||
|
}
|
||
|
return to;
|
||
|
}
|
||
|
case 'array': {
|
||
|
return from.map(copy);
|
||
|
}
|
||
|
default:
|
||
|
return from;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return copy(schema);
|
||
|
}
|
||
|
|
||
|
const devContainer = JSON.parse(fs.readFileSync('../schemas/devContainer.schema.src.json', 'utf8'));
|
||
|
fs.writeFileSync('../schemas/devContainer.schema.generated.json', JSON.stringify(transform(devContainer), undefined, ' '));
|