Joi validation of array - hapi.js

trying to validate that an array has zero or more strings in one case and that it has zero or more objects in another , struggling with Joi docs :(
validate: {
headers: Joi.object({
'content-type': "application/vnd.api+json",
accept: "application/vnd.api+json"
}).options({ allowUnknown: true }),
payload : Joi.object().keys({
data : Joi.object().keys({
type: Joi.any().allow('BY_TEMPLATE').required(),
attributes: Joi.object({
to : Joi.string().email().required(),
templateId : Joi.string().required(),
categories : Joi.array().items( //trying to validate here that each element is a string),
variables : Joi.array({
//also trying to validate here that each element is an Object with one key and value
})
})
}).required()
})
}

Joi.array().items() accepts another Joi schema to use against the array elements. So an array of strings is this easy:
Joi.array().items(Joi.string())
Same for an array of objects; just pass an object schema to items():
Joi.array().items(Joi.object({
// Object schema
}))

If you want to validate an array of strings in Joi:
Joi.array().items(Joi.string().valid("item1", "item2", "item3", "item4"))

you can try this:
function(data) {
const Schema = {
categories: Joi.array().items(Joi.string()),
variables: Joi.array().items(Joi.object().keys().min(1))
}
return Joi.validate(data, Schema)
}
for more details checkout this repo: https://github.com/raysk4ever/nodejs_withMongoRefArray

You can also try this way, I have been using it for long time and working fine for me.
If your array is array of objects than use below:
const Joi = require('joi');
let schema = Joi.object().keys({
items: Joi.array().items(
Joi.object({
item_id: Joi.number().required(),
item_qty: Joi.number().required(),
item_type_id: Joi.number().required(),
item_qty: Joi.number().required(),
base_price: Joi.number().required(),
actual_price: Joi.number().required(),
})
).required(),
});
let errors = Joi.validate(req.body, schema);
if you array is simple array than:
let schema = Joi.object().keys({
items: Joi.array().items(
Joi.number().required()
).min(10).required()});

Joi.array().items(Joi.string().required(), Joi.number().required()); found it here

Validation when we have an array of objects using Joi:
const schema = Joi.array().items(
Joi.object().keys({
id: Joi.number().required(),
name: Joi.string().required(),
}));
We could add validations for objects inside an array itself.

validate: {
headers: Joi.object({
'content-type': "application/vnd.api+json",
accept: "application/vnd.api+json"
}).options({ allowUnknown: true }),
payload : Joi.object().keys({
data : Joi.object().keys({
type: Joi.any().allow('BY_TEMPLATE').required(),
attributes: Joi.object({
to : Joi.string().email().required(),
templateId : Joi.string().required(),
categories : Joi.array().items(Joi.string()),
variables : Joi.array().items(Joi.object().keys().max(1))
})
}).required()
})
}

Related

How to change the columns collection set of a kendo TreeList dynamically?

Try to change the columns list dynamically via a query ...
When I construct the TreeList, I call for columns :
$("#treelist").kendoTreeList({
columns: AnalyseCenterSKUService.getKPIColumnList($scope)
If I return a simple array with the fields, it's working ..
If I call a $http.get (inside my getKPIColumnList(..) function) which add some columns to the existing array of columns, the TreeList is not constructed correctly.
Any suggestion will be really appreciated ! :)
EDIT 22-10-2019 09:00
Treelist init
$("#treelist").kendoTreeList({
columns: AnalyseCenterSKUService.getKPIColumnList($scope),
scrollable: true,
columnMenu : {
columns : true
},
height: "100%",
dataBound: function (e) {
ExpandAll();
},
dataSource: {
schema: {
model: {
id: "id",
parentId: "parentId",
fields: {
id: { type: "number" },
parentId: { type: "number", nullable: true },
fields: {
id: { type: "number" },
parentId: { type: "number", nullable: false }
}
}
}
},
transport: {
read: {
url: "/api/AnalyseCenter/GetWorkOrderTree/0",
dataType: "json"
}
}
}
The getKPIColumnList return an static array + some push with dynamic columns (from DB)
angular.module('AnalyseCenterDirectives')
.service ('AnalyseCenterSKUService', function ($http) {
var toReturn = [ {field: "Name", title: "HiƩrachie SKU", width: "30%" }, ..., ..., .... ];
I try in this function to push DB result
return $http.get("/api/AnalyseCenter/GetWorkOrderHistorianAdditonalColumns?equipmentName=" + equipmentName)
.then(function (result) {
var data = result.data;
if (data && data !== 'undefined') {
var fromDB = data;
angular.forEach(fromDB, function (tag) {
var tagName = tag.replace(".","_");
toReturn.push({
field: tagName, title: tag, width: '10%',
attributes: { style: "text-align:right;"} })
})
The stored procedure GetWorkOrderHistorianAdditonalColumns returns a list of string (future column)
That is because ajax is async, that means your tree list is being initialized before the request finishes. A classic question for JavaScript newcomers. I suggest you take a while to read about ajax, like How does AJAX works for instance.
Back to your problem. You need to create your tree list inside the success callback(I can't give you a more complete solution since I don't know what you're doing inside your function or which framework you're using to open that ajax request) with the result data, which is probably your columns. Then it would work as if you're initializing it with arrays.

Strapi graphql mutation Syntax Error: Unterminated string

I always get Syntax Error: Unterminated string when I try to update my database using javascript strapi sdk. this.chapter.content is a html string generated by ckeditor. How can I escape this string to update my database using graphql?
async updateChapter() {
const q = `
mutation {
updateChapter(input: {
where: {
id: "${this.$route.params.chapterId}"
},
data: {
content: "${this.chapter.content.replace(/[.*+?^${}()|[\]\\]/g, '\\$&').replace(/(?:\r\n|\r|\n)/g, '\n')}"
title: "${this.chapter.title}"
}
}) {
chapter{
title
id
content
}
}
}
`;
const res = await strapi.request("post", "/graphql", {
data: {
query: q
}
});
this.chapter = res.data.chapter;
}
Technically you could use block string notation to get around this issue. However, you really should supply dynamic input values using variables instead of string interpolation. This way you can easily provide any of sort of values (strings, numbers, objects, etc.) and GraphQL will parse them accordingly -- including strings with line breaks.
const query = `
mutation MyMutation ($chapterId: ID!, $content: String!, $title: String!) {
updateChapter(input: {
where: {
id: $chapterId
},
data: {
content: $content
title: $title
}
}) {
chapter{
title
id
content
}
}
}
`
const variables = {
chapterId: '...',
content: '...',
title: '...',
}
const res = await strapi.request("post", "/graphql", {
data: {
query,
variables,
},
})
Note that $chapterId may need to be of the type String! instead if that's what's called for in the schema. Since variables can also be input object types, instead of providing 3 different variables, you could also provide a single variable to be passed to the input argument instead:
const query = `
mutation MyMutation ($input: SomeInputObjectTypeHere!) {
updateChapter(input: $input) {
chapter{
title
id
content
}
}
}
`
const variables = {
input: {
where: {
id: '...',
},
data: {
content: '...',
title: '...',
},
},
}
Again, just replace SomeInputObjectTypeHere with the appropriate type in your schema.
Another solution maybe help
Code with issue: For example mainReason and actionTaken fields are text inputs and data contains some white spaces. This action give error: Unterminated string
mutation { updateApplicationForm(input:{ where:{id:"${ticketData.id}"}
data:{
mainReason: "${ticketData.mainReason}"
actionTaken: "${ticketData.actionTaken}"
appStatus: ${ticketData.appStatus}
action: "${ticketData.action}"
}
Fix this problem with JSON.stringify method
mutation { updateApplicationForm(input:{ where:{id:"${ticketData.id}"}
data:{
mainReason:${JSON.stringify(ticketData.mainReason)}
actionTaken:${JSON.stringify(ticketData.actionTaken)}
appStatus: ${ticketData.appStatus}
action: "${ticketData.action}"
}

JQuery DataTable data not available even data is received from server

I want to draw a table to show users data from my server.
First I am using Ajex to get the users data:
var usersList = {};
usersList.users = ["Afthieleanmah", "Hadulmahsanran","tabletest1"];
var dataSet1=[];
var i;
$.ajax({
url: '../users',
type: 'POST',
contentType: 'application/json',
cache: false,
data: JSON.stringify(usersList),
success:function(response, text){
if(response.users !== undefined){
dataSet1 = response.users;
}
}
});
I can successfully get the users data and save the data in dataSet1 as a JSON array contains Objects. Its format is like this:
[
{
username: "Tiger Nixon",
job_title: "System Architect",
city: "Edinburgh",
extn: "5421"
},
{
username: "Tiger Nixon2",
job_title: "System Architect",
city: "Edinburgh",
extn: "5421"
}
]
Then I create a table and pass in configuration:
// table confirgurations
var tableConfig={
pageLength: 5,
bLengthChange: false,
columns:[
{data: "username", title: "Name"},
{data: "job_title", title: "Position"},
{data: "city", title: "City"}
],
data:dataSet1
};
// create table
var userTable=$('#table-id').DataTable(tableConfig);
I am sure that I can get users data from API "/users" and save it into dataSet1. But everytime I load the page containing the table, the table always shows "No data available in table". I set a breakpoint on this line :
var tableConfig={
and let it continue to run. The weird things happen. The Table shows the data.............. No idea why
You should initialize your table after you receive response from the server in the success function. Also use destroy in case you're performin your Ajax request multiple times.
For example:
$.ajax({
// ... skipped ...
success:function(response, text){
if(response.users !== undefined){
dataSet1 = response.users;
}
// table confirgurations
var tableConfig={
// ... skippped ...
destroy: true
};
// ... skippped ...
var userTable=$('#table-id').DataTable(tableConfig);
}
});
However ideally you should let jQuery DataTables do the Ajax request using ajax option.

Transform objects pointfree style with Ramda

Given the function below, how do I convert it to point-free style? Would be nice to use Ramda's prop and path and skip the data argument, but I just can't figure out the proper syntax.
const mapToOtherFormat = (data) => (
{
'Name': data.Name
'Email': data.User.Email,
'Foo': data.Foo[0].Bar
});
One option would be to make use of R.applySpec, which creates a new function that builds objects by applying the functions at each key of the supplied "spec" against the given arguments of the resulting function.
const mapToOtherFormat = R.applySpec({
Name: R.prop('Name'),
Email: R.path(['User', 'Email']),
Foo: R.path(['Foo', 0, 'Bar'])
})
const result = mapToOtherFormat({
Name: 'Bob',
User: { Email: 'bob#example.com' },
Foo: [{ Bar: 'moo' }, { Bar: 'baa' }]
})
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.22.1/ramda.min.js"></script>
Here's my attempt:
const mapToOtherFormat = R.converge(
(...list) => R.pipe(...list)({}),
[
R.pipe(R.view(R.lensProp('Name')), R.set(R.lensProp('Name'))),
R.pipe(R.view(R.compose(R.lensProp('User'), R.lensProp('Email'))), R.set(R.lensProp('Email'))),
R.pipe(R.view(R.compose(R.lensProp('Foo'), R.lensIndex(0), R.lensProp('Bar'))), R.set(R.lensProp('Foo')))
]
)
const obj = {Name: 'name', User: {Email: 'email'}, Foo: [{Bar: 2}]}
mapToOtherFormat(obj)
Ramda console
[Edit]
We can make it completely point-free:
const mapToOtherFormat = R.converge(
R.pipe(R.pipe, R.flip(R.call)({})),
[
R.pipe(R.view(R.lensProp('Name')), R.set(R.lensProp('Name'))),
R.pipe(R.view(R.compose(R.lensProp('User'), R.lensProp('Email'))), R.set(R.lensProp('Email'))),
R.pipe(R.view(R.compose(R.lensProp('Foo'), R.lensIndex(0), R.lensProp('Bar'))), R.set(R.lensProp('Foo')))
]
)
Ramda console

how to use react-native realm

I started to use realm in my project and I have a question about retrieving the data. When I make a call to query all of the objects in my Subdivision model the return result includes the get/set methods. I must parse and stringify this before I am able to use it. I have read the docs and I do not see anything about this. Is this something that has to be done or am I missing something?
Model
class Subdivision extends Realm.Object { }
Subdivision.schema = {
name: 'Subdivision',
primaryKey: 'id',
properties: {
id: 'int',
subdivisionName: 'string',
latitude: 'float',
longitude: 'float',
status: 'string',
statusFlag: 'string',
marketId: 'int',
color: { type: 'int', optional: true },
colorStr: { type: 'string', optional: true }
}
};
Setting Subdivisions
_.each(response, (item) => {
Realm.write(() => {
Realm.create('Subdivision', item);
});
});
Getting Subdivisions
let result = Realm.objects('Subdivision');
let strRes = JSON.parse(JSON.stringify(result))
You shouldn't have to call JSON.stringify on result. Realm.objects returns a Results object which functions very similiarly to a JS Array: https://realm.io/docs/react-native/0.13.0/api/Realm.Results.html
You should be able to access each result using subscript indexing or other JS enumerations methods, ie result[0], or results.forEach((subidv) => {...}) etc.