Skip to content
This repository has been archived by the owner on May 17, 2024. It is now read-only.

PE-184 Require samples for non hidden ops #33

Merged
merged 4 commits into from
Mar 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions lib/functional-constraints/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
const checks = [
require('./searchOrCreateKeys'),
require('./deepNestedFields'),
require('./mutuallyExclusiveFields')
require('./mutuallyExclusiveFields'),
require('./requiredSamples')
];

const runFunctionalConstraints = definition => {
const runFunctionalConstraints = (definition, mainSchema) => {
return checks.reduce((errors, checkFunc) => {
const errorsForCheck = checkFunc(definition);
const errorsForCheck = checkFunc(definition, mainSchema);
if (errorsForCheck) {
errors = errors.concat(errorsForCheck);
}
Expand Down
56 changes: 56 additions & 0 deletions lib/functional-constraints/requiredSamples.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
'use strict';

const _ = require('lodash');
const jsonschema = require('jsonschema');

// todo: deal with circular dep.
const RESOURCE_ID = '/ResourceSchema';
const RESOURCE_METHODS = ['get', 'hook', 'list', 'search', 'create'];

const check = definition => {
if (!definition.operation || _.get(definition, 'display.hidden')) {
return null;
}

const samples = _.get(definition, 'operation.sample', {});
return !_.isEmpty(samples)
? null
: new jsonschema.ValidationError(
'requires "sample", because it\'s not hidden',
definition,
definition.id
);
};

module.exports = (definition, mainSchema) => {
let definitions = [];

if (mainSchema.id === RESOURCE_ID) {
definitions = RESOURCE_METHODS.map(method => definition[method]).filter(
Boolean
);

// allow method definitions to inherit the sample
if (definition.sample) {
definitions.forEach(methodDefinition => {
if (methodDefinition.operation && !methodDefinition.operation.sample) {
methodDefinition.operation.sample = definition.sample;
}
});
}

if (!definitions.length) {
return [
new jsonschema.ValidationError(
'expected at least one resource operation',
definition,
definition.id
)
];
}
} else {
definitions = [definition];
}

return definitions.map(check).filter(Boolean);
};
4 changes: 2 additions & 2 deletions lib/schemas/BasicOperationSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module.exports = makeSchema(
description:
'Represents the fundamental mechanics of triggers, searches, or creates.',
type: 'object',
required: ['perform', 'sample'],
required: ['perform'],
properties: {
resource: {
description:
Expand All @@ -38,7 +38,7 @@ module.exports = makeSchema(
},
sample: {
description:
'What does a sample of data look like? Will use resource sample if missing.',
'What does a sample of data look like? Will use resource sample if missing. Required, if the display is not hidden.',
type: 'object',
// TODO: require id, ID, Id property?
minProperties: 1
Expand Down
24 changes: 24 additions & 0 deletions lib/schemas/CreateSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ module.exports = makeSchema(
sample: { id: 1 },
shouldLock: true
}
},
{
key: 'recipe',
noun: 'Recipe',
display: {
label: 'Create Recipe',
description: 'Creates a new recipe.',
hidden: true
},
operation: {
perform: '$func$2$f$'
}
}
],
antiExamples: [
Expand All @@ -46,6 +58,18 @@ module.exports = makeSchema(
description: 'Creates a new recipe.'
},
operation: { perform: '$func$2$f$', shouldLock: 'yes' }
},
{
key: 'recipe',
noun: 'Recipe',
display: {
label: 'Create Recipe',
description: 'Creates a new recipe.'
},
operation: {
perform: '$func$2$f$'
// sample is missing!
}
}
],
properties: {
Expand Down
35 changes: 35 additions & 0 deletions lib/schemas/ResourceMethodCreateSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,41 @@ module.exports = makeSchema(
'How will we find create a specific object given inputs? Will be turned into a create automatically.',
type: 'object',
required: ['display', 'operation'],
examples: [
{
display: {
label: 'Create Tag',
description: 'Create a new Tag in your account.'
},
operation: {
perform: '$func$2$f$',
sample: {
id: 1
}
}
},
{
display: {
label: 'Create Tag',
description: 'Create a new Tag in your account.',
hidden: true
},
operation: {
perform: '$func$2$f$'
}
}
],
antiExamples: [
{
display: {
label: 'Create Tag',
description: 'Create a new Tag in your account.'
},
operation: {
perform: '$func$2$f$'
}
}
],
properties: {
display: {
description: 'Define how this create method will be exposed in the UI.',
Expand Down
42 changes: 42 additions & 0 deletions lib/schemas/ResourceMethodGetSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,48 @@ module.exports = makeSchema(
'How will we get a single object given a unique identifier/id?',
type: 'object',
required: ['display', 'operation'],
examples: [
{
display: {
label: 'Get Tag by ID',
description: 'Grab a specific Tag by ID.'
},
operation: {
perform: {
url: '$func$0$f$'
},
sample: {
id: 385,
name: 'proactive enable ROI'
}
}
},
{
display: {
label: 'Get Tag by ID',
description: 'Grab a specific Tag by ID.',
hidden: true
},
operation: {
perform: {
url: '$func$0$f$'
}
}
}
],
antiExamples: [
{
display: {
label: 'Get Tag by ID',
description: 'Grab a specific Tag by ID.'
},
operation: {
perform: {
url: '$func$0$f$'
}
}
}
],
properties: {
display: {
description: 'Define how this get method will be exposed in the UI.',
Expand Down
39 changes: 39 additions & 0 deletions lib/schemas/ResourceMethodHookSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,45 @@ module.exports = makeSchema(
'How will we get notified of new objects? Will be turned into a trigger automatically.',
type: 'object',
required: ['display', 'operation'],
examples: [
{
display: {
label: 'Get Tag by ID',
description: 'Grab a specific Tag by ID.'
},
operation: {
type: 'hook',
perform: '$func$0$f$',
sample: {
id: 385,
name: 'proactive enable ROI'
}
}
},
{
display: {
label: 'Get Tag by ID',
description: 'Grab a specific Tag by ID.',
hidden: true
},
operation: {
type: 'hook',
perform: '$func$0$f$'
}
}
],
antiExamples: [
{
display: {
label: 'Get Tag by ID',
description: 'Grab a specific Tag by ID.'
},
operation: {
type: 'hook',
perform: '$func$0$f$'
}
}
],
properties: {
display: {
description:
Expand Down
44 changes: 44 additions & 0 deletions lib/schemas/ResourceMethodListSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,50 @@ module.exports = makeSchema(
'How will we get a list of new objects? Will be turned into a trigger automatically.',
type: 'object',
required: ['display', 'operation'],
examples: [
{
display: {
label: 'New User',
description: 'Trigger when a new User is created in your account.'
},
operation: {
perform: {
url: 'http://fake-crm.getsandbox.com/users'
},
sample: {
id: 49,
name: 'Veronica Kuhn',
email: 'veronica.kuhn@company.com'
}
}
},
{
display: {
label: 'New User',
description: 'Trigger when a new User is created in your account.',
hidden: true
},
operation: {
perform: {
url: 'http://fake-crm.getsandbox.com/users'
}
}
}
],
antiExamples: [
{
display: {
label: 'New User',
description: 'Trigger when a new User is created in your account.'
},
operation: {
perform: {
url: 'http://fake-crm.getsandbox.com/users'
}
// missing sample
}
}
],
properties: {
display: {
description:
Expand Down
35 changes: 35 additions & 0 deletions lib/schemas/ResourceMethodSearchSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,41 @@ module.exports = makeSchema(
'How will we find a specific object given filters or search terms? Will be turned into a search automatically.',
type: 'object',
required: ['display', 'operation'],
examples: [
{
display: {
label: 'Find a Recipe',
description: 'Search for recipe by cuisine style.'
},
operation: {
perform: '$func$2$f$',
sample: { id: 1 }
}
},
{
display: {
label: 'Find a Recipe',
description: 'Search for recipe by cuisine style.',
hidden: true
},
operation: {
perform: '$func$2$f$'
}
}
],
antiExamples: [
{
key: 'recipe',
noun: 'Recipe',
display: {
label: 'Find a Recipe',
description: 'Search for recipe by cuisine style.'
},
operation: {
perform: '$func$2$f$'
}
}
],
properties: {
display: {
description: 'Define how this search method will be exposed in the UI.',
Expand Down
Loading