Skip to content

Commit

Permalink
fix(schemas): remove references going nowhere
Browse files Browse the repository at this point in the history
  • Loading branch information
trieloff committed Dec 6, 2019
1 parent 0fc5692 commit 2186142
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 130 deletions.
28 changes: 10 additions & 18 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const build = require('./lib/markdownBuilder');
const write = require('./lib/writeMarkdown');
const readme = require('./lib/readmeBuilder');
const formatInfo = require('./lib/formatInfo');
const { loader } = require('./lib/schemaProxy');

const { info, error, debug } = logger;

Expand Down Expand Up @@ -133,40 +134,30 @@ const schemaDir = argv.x;
const target = fs.statSync(schemaPath);
const schemaExtension = argv.e;

const schemaloader = loader();

// list all schema files in the specified directory
readdirp.promise(schemaPath, { root: schemaPath, fileFilter: `*.${schemaExtension}` })
// then collect data about the schemas and turn everything into a big object
.then(schemas => pipe(
schemas,
map(schema => schema.fullPath),
map(path => ({
path,
// eslint-disable-next-line global-require, import/no-dynamic-require
schema: require(path),
direct: true,
})),
validate(ajv, logger),
// read the ID
map(extract),
map(path => schemaloader(require(path), path)),
// validate
// validate(ajv, logger),
// find contained schemas
map(traverse),
flat,
traverse,

// remove pure ref schemas
filterRefs,
//filterRefs,

(x) => {
const y = list(x);
console.log(JSON.stringify(y, undefined, ' '));
return y;
},

// format titles and descriptions
formatInfo({ extension: schemaExtension }),

// make a nice object
generate,

/* skip for now
// generate Markdown ASTs
build({
header: argv.h,
Expand All @@ -187,6 +178,7 @@ readdirp.promise(schemaPath, { root: schemaPath, fileFilter: `*.${schemaExtensio
debug,
meta: argv.m,
}),
*/
))

.then((schemas) => {
Expand Down
7 changes: 6 additions & 1 deletion examples/schemas/complex.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
],
"$schema": "http://json-schema.org/draft-06/schema#",
"$id": "https://example.com/schemas/complex",
"title": "Complex References ",
"title": "Complex References",
"type": "object",
"description": "This is an example schema that uses types defined in other schemas.",
"properties": {
Expand All @@ -21,6 +21,11 @@
"version": "1.0.0",
"testProperty": "test"
},
"refrefed": {
"$ref": "#/properties/refnamed",
"version": "1.0.0",
"testProperty": "test"
},
"reflist": {
"type": "array",
"items": {
Expand Down
5 changes: 0 additions & 5 deletions examples/schemas/identifiable.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@
"title": "Identifiable",
"description": "This is a *very* simple example of a JSON schema. There is only one property.",
"type": "object",
"allOf": [
{
"$ref": "#/definitions/id"
}
],
"properties": {
"@id": {
"type": "string",
Expand Down
5 changes: 0 additions & 5 deletions examples/schemas/simple.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@
"title": "Simple",
"description": "This is a *very* simple example of a JSON schema. There is only one property.",
"type": "object",
"allOf": [
{
"$ref": "#/definitions/id"
}
],
"properties": {
"id": {
"type": "string",
Expand Down
5 changes: 0 additions & 5 deletions examples/schemas/stabilizing.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@
"description": "This is a schema which is currently in the `stabilizing` status.",
"meta:status": "stabilizing",
"type": "object",
"allOf": [
{
"$ref": "#/definitions/id"
}
],
"properties": {
"id": {
"type": "string",
Expand Down
5 changes: 0 additions & 5 deletions examples/schemas/typearrays.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@
"title": "Type Arrays",
"description": "This schema test type arrays and nullable types",
"type": "object",
"allOf": [
{
"$ref": "#/definitions/id"
}
],
"properties": {
"null": {
"type": "null",
Expand Down
10 changes: 9 additions & 1 deletion lib/schemaProxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,19 @@ const handler = ({
};

meta[symbols.resolve] = (target, prop, receiver) => (path) => {
console.log('trying to resolve', path, 'in', receiver[symbols.filename]);
if (path==undefined) {
return receiver;
}
const [head, ...tail] = typeof path === 'string' ? path.split('/') : path;
if ((head === '' || head === undefined) && tail.length === 0) {
return receiver;
} else if (head === '' || head === undefined) {
return receiver[symbols.resolve](tail);
} else {
} else if (receiver[head]) {
return receiver[head][symbols.resolve](tail);
} else {
throw new Error('bad');
}
};

Expand Down Expand Up @@ -82,6 +88,7 @@ const handler = ({
if (typeof retval === 'object') {
if (retval.$ref) {
const [uri, pointer] = retval.$ref.split('#');
console.log('resolving ref', uri, pointer, 'from', receiver[symbols.filename]);
const basedoc = uri || receiver[symbols.id];
if (schemas.known[basedoc]) {
const referenced = schemas.known[basedoc][symbols.resolve](pointer);
Expand Down Expand Up @@ -126,6 +133,7 @@ module.exports.loader = () => {
const slugger = ghslugger();

return (schema, filename) => {
console.log('loading', filename);
const proxied = new Proxy(schema, handler({ filename, schemas, slugger }));
schemas.loaded.push(proxied);
if (proxied.$id) {
Expand Down
98 changes: 9 additions & 89 deletions lib/traverseSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,95 +49,6 @@ const ignoreKeywords = [
'uniqueItems',
];

/**
* Traverses a Schema node (containing a JSON Schema) to find sub-schemas,
* which are then emitted as asequence.
* @param {Schema} node
*/
function traverse(node) {
const { schema, pointer = '', id } = node;
const rootpath = node.rootpath ? node.rootpath : node.path;
const items = pipe(
// turn the schema object into a sequence of key value pairs
iter(schema),
map(([key, subschema]) => {
subschema._definedin = `${id}#${pointer}/${key}`;

if (Array.isArray(subschema) && arrayKeywords.includes(key)) {
// descend into the array
return pipe(
iter(subschema),
enumerate,
map(([index, subsubschema]) => {
const retval = {
schema: subsubschema,
direct: false,
pointer: `${pointer}/${key}/${index}`,
id,
root: schema,
rootpath,
// TODO add additional properties for tracking
};

subsubschema._definedin = `${id}#${pointer}/${key}/${index}`;


return retval;
}),
);
}
if (subschema && typeof subschema === 'object' && propertyKeywords.includes(key)) {
// descend into the object
return pipe(
iter(subschema),
map(([subkey, subsubschema]) => {
const retval = {
schema: subsubschema,
direct: false,
pointer: `${pointer}/${key}/${subkey}`,
id,
root: schema,
rootpath,
// TODO add additional properties for tracking
};

subsubschema._definedin = `${id}#${pointer}/${key}/${subkey}`;

return retval;
}),
);
}
if (subschema && typeof subschema === 'object' && !ignoreKeywords.includes(key)) {
// this could be a schema, too
const retval = {
schema: subschema,
direct: false,
pointer: `${pointer}/${key}`,
id,
root: schema,
rootpath,
// TODO add additional properties for tracking
};

return [retval];
}
return [];
}),
flat,
);

schema._definedin = `${id}#${pointer}`;

const itemsarray = list(items, Array);

const subitems = map(items, traverse);
const subitemsarray = list(subitems, Array);

const allitems = [node, ...itemsarray, ...subitemsarray];

return allitems;
}

function sflat(arr) {
return arr.reduce((p, v) => {
if (Array.isArray(v)) {
Expand All @@ -161,5 +72,14 @@ function traverseSchema(schema) {
return [];
}

/**
* Traverses a Schema node (containing a JSON Schema) to find sub-schemas,
* which are then emitted as asequence.
* @param {Schema} node
*/
function traverse(schemas) {
return sflat(list(schemas).map(traverseSchema));
}

module.exports = traverse;
module.exports.traverseSchema = traverseSchema;
3 changes: 2 additions & 1 deletion lib/validateSchemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
* governing permissions and limitations under the License.
*/
const { map } = require('ferrum');
const { filename } = require('./symbols');

function validate(validator, logger) {
return schemas => map(schemas, (schema) => {
try {
validator.addSchema(schema.schema, schema.path);
validator.addSchema(schema, schema[filename]);
return schema;
} catch (e) {
logger.error('Ajv processing error for schema at path', schema.path);
Expand Down
19 changes: 19 additions & 0 deletions test/schemaProxy.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,23 @@ describe('Testing Schema Proxy', () => {

assert.equal(example[meta].shortdescription, 'This is an example of using a definitions object within a schema');
});

it.only('Schema proxy loads complex schemas with meta information', () => {
const myloader = loader();

const files = [
'abstract.schema.json',
'simple.schema.json',
'complex.schema.json',
];

const schemas = files.map(file => {
const fname = path.resolve(__dirname, '..', 'examples', 'schemas', file);
return myloader(require(fname), fname);
});

assert.deepEqual(schemas[2].title, 'Complex References');
assert.equal(schemas[2].properties.refnamed.title, 'Simple');
assert.equal(schemas[2].properties.refrefed.title, 'Simple');
});
});

0 comments on commit 2186142

Please sign in to comment.