Skip to content

Commit

Permalink
Add support for context
Browse files Browse the repository at this point in the history
  • Loading branch information
nechaido authored and o-rumiantsev committed Jun 12, 2019
1 parent 7cfae84 commit 34f6a54
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 31 deletions.
16 changes: 12 additions & 4 deletions lib/metaschema-config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const {
actionCreator,
} = require('./action');

const { addContext, postprocessContext } = require('./context');
const { preprocessResources, addResources } = require('./resource');
const { addApplication, processApplication } = require('./application');

Expand Down Expand Up @@ -139,6 +140,7 @@ module.exports = {
localDecorators,
pathToType: {
domains: 'domains',
context: 'context',
category: 'category',
action: 'action',
form: 'form',
Expand All @@ -151,6 +153,7 @@ module.exports = {
prepare: ms => {
ms.categories = new Map();
ms.domains = new Map();
ms.context = new Map();
ms.actions = new Map();
ms.resources = {
common: new Map(),
Expand Down Expand Up @@ -186,6 +189,10 @@ module.exports = {
...config.processors.domains,
validateSchema: [validateSchema],
},
context: {
add: [addContext],
postprocess: [postprocessContext],
},
category: {
add: [...config.processors.category.add, addCategory],
postprocess: [
Expand Down Expand Up @@ -222,10 +229,11 @@ module.exports = {
processOrder: {
domains: 0,
category: 1,
form: 2,
action: 3,
resource: 4,
application: 5,
context: 2,
form: 3,
action: 4,
resource: 5,
application: 6,
},
},
};
45 changes: 45 additions & 0 deletions lib/metaschema-config/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use strict';

const { SchemaValidationError } = require('metaschema').errors;

const addContext = (context, ms) => {
const errors = [];
const duplicateContext = ms.context.size > 0;
if (duplicateContext) {
errors.push(
new SchemaValidationError('duplicate', context.name, {
type: 'context',
value: context.name,
})
);
} else {
Object.entries(context.definition).forEach(([name, field]) =>
ms.context.set(name, field)
);
}
return errors;
};

const postprocessContext = (context, ms) => {
const errors = [];
for (const [fieldName, field] of Object.entries(context.definition)) {
const domain = ms.domains.get(field.domain);
if (domain) {
field.definition = domain;
} else {
errors.push(
new SchemaValidationError(
'unresolved',
`${context.name}.${fieldName}`,
{ type: 'domain', value: field.domain }
)
);
}
}
return errors;
};

module.exports = {
addContext,
postprocessContext,
};
57 changes: 30 additions & 27 deletions lib/metaschema-config/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,23 @@ const {
extractDecorator,
} = require('metaschema');

const propToTypes = {
domain: 'domains',
category: 'category',
context: 'context',
};

const dataTypes = Object.keys(propToTypes);
const getDefinition = {
domain: domain => domain,
category: category => category.definition,
context: context => context,
};

const processFields = (ms, category, fields, source) => {
const errors = [];
for (const [key, field] of Object.entries(fields)) {
if (field.domain) {
const def = ms.domains.get(field.domain);
if (!def) {
errors.push(
new SchemaValidationError('unresolved', `${source}.${key}`, {
type: 'domain',
value: field.domain,
})
);
} else {
Object.assign(field, { domain: field.domain, definition: def });
}
} else if (field.category) {
const cat = ms.categories.get(field.category);
if (!cat) {
errors.push(
new SchemaValidationError('unresolved', `${source}.${key}`, {
type: 'category',
value: field.category,
})
);
} else {
field.definition = cat.definition;
}
} else if (typeof field === 'string') {
if (typeof field === 'string') {
const src = `${source}.${key}`;
if (!category) {
errors.push(
Expand All @@ -44,11 +33,25 @@ const processFields = (ms, category, fields, source) => {
continue;
}
try {
const def = extractByPath(category, field.field, ms, src);
Object.assign(field, def);
Object.assign(field, extractByPath(category, field.field, ms, src));
} catch (error) {
errors.push(error);
}
} else {
for (const type of dataTypes) {
const value = field[type];
if (value) {
const def = ms[propToTypes[type]].get(value);
if (!def) {
const info = { type, value };
errors.push(
new SchemaValidationError('unresolved', `${source}.${key}`, info)
);
} else {
field.definition = getDefinition[type](def);
}
}
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/context/duplicate/context.context
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
({
Nomen: { domain: 'Nomen' },
});
3 changes: 3 additions & 0 deletions test/fixtures/context/duplicate/custom.domains
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
({
Nomen: { type: 'string' },
});
3 changes: 3 additions & 0 deletions test/fixtures/context/duplicate/duplicateDomain.context
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
({
DuplicateNomen: { domain: 'Nomen' },
});
3 changes: 3 additions & 0 deletions test/fixtures/context/unresolved/context.context
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
({
Nomen: { domain: 'Nomen' },
});
32 changes: 32 additions & 0 deletions test/ms.context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';

const metaschema = require('metaschema');
const metatests = require('metatests');

const { options, config } = require('../lib/metaschema-config/config');

const { MetaschemaError, SchemaValidationError } = metaschema.errors;

metatests.test('metaschema context error on duplicated domains', async test => {
await test.rejects(
metaschema.fs.load('test/fixtures/context/duplicate', options, config),
new MetaschemaError([
new SchemaValidationError('duplicate', 'duplicateDomain', {
type: 'context',
value: 'duplicateDomain',
}),
])
);
});

metatests.test('metaschema context error on unresolved domain', async test => {
await test.rejects(
metaschema.fs.load('test/fixtures/context/unresolved', options, config),
new MetaschemaError([
new SchemaValidationError('unresolved', 'context.Nomen', {
type: 'domain',
value: 'Nomen',
}),
])
);
});

0 comments on commit 34f6a54

Please sign in to comment.