I'm new to programming, and I'm creating a generator with yeoman-generator. How do I go through an array of objects and select the option I choose? I tried it but it didn't work. can you help me?
prompting() {
const prompts = [
{
type: 'checkbox',
name: 'database',
message: 'Select Database support:',
choices: [
{
name: 'H2',
value: 'h2',
}, {
name: 'HSQLDB',
value: 'hsqldb'
}, {
name: 'Apache Derby',
value: 'derby'
},
]
return this.prompt(prompts).then(answers => {
this.database = answers.database;
const hasDataBase = db => this.database.indexOf(db) !== -1;
this.h2 = hasDataBase('h2');
this.hsqldb = hasDataBase('hsql');
this.derby = hasDataBase('derby');
});
}
]}
This is the format it can take (from their example page https://yeoman.io/authoring/user-interactions.html). I tested this myself and it works.
var Generator = require('yeoman-generator');
module.exports = class extends Generator {
async prompting() {
const prompts = await this.prompt([
{
type: 'checkbox',
name: 'database',
message: 'Select Database support:',
choices: [
{
name: 'H2',
value: 'h2',
}, {
name: 'HSQLDB',
value: 'hsqldb'
}, {
name: 'Apache Derby',
value: 'derby'
}
]
}]);
this.log("database", prompts.database);
}
};
Related
Apologies if title is not clear.
I am using json2csv npm package to prepare csv from json object and this package allows us to add a hook to transform object before actual csv line is prepared.
I only need to manipulate two properties out of all. How can I do this effectively? My code feels too bloated.
const {
Parser: Json2csvParser,
transforms: { unwind },
} = require('json2csv');
const json2csvFields = [
{ value: 'root.filename', label: 'File Name' },
{ value: 'issue.root.priority', label: 'Priority' },
{ value: 'issue.root.url', label: 'URL' },
{ value: 'issue.root.startline', label: 'Start Line' },
{ value: 'issue.root.stopline', label: 'Stop Line' },
{ value: 'issue.root.startcolumn', label: 'Start Column' },
{ value: 'issue.root.stopcolumn', label: 'Stop Column' },
{ value: 'issue.root.issuename', label: 'Issue Name' },
{ value: 'issue.root.issuecategory', label: 'Issue Category' },
{ value: 'issue._', label: 'Issue Description' },
];
const sampleData = [
{
root: {
filename:
'/home/users/john-doe/workspace/foo-project/src/main/classes/foo.cls',
},
issue: {
root: {
priority: 1,
url: 'www.example.com',
startline: 100,
stopline: 105,
startcolumn: 20,
stopcolumn: 25,
issuename: 'blah',
issuecategory: 'Category A',
},
_: ' Fox ',
},
},
];
const json2csvOptions = {
fields: json2csvFields,
quote: '',
header: true,
transforms: [
(item) => ({
'root.filename': item.root.filename.replace(
'/home/users/john-doe/workspace/foo-project/src/main/classes/',
''
),
'issue._': `"${item.issue._.trim()}"`,
// Except for the above two, everything else doens't need any transformation.
'issue.root.priority': item.issue.root.priority,
'issue.root.url': item.issue.root.url,
'issue.root.startline': item.issue.root.startline,
'issue.root.stopline': item.issue.root.stopline,
'issue.root.startcolumn': item.issue.root.startcolumn,
'issue.root.stopcolumn': item.issue.root.stopcolumn,
'issue.root.issuename': item.issue.root.issuename,
'issue.root.issuecategory': item.issue.root.issuecategory,
}),
],
};
const json2csvParser = new Json2csvParser(json2csvOptions);
const csv = json2csvParser.parse(sampleData);
console.log(csv);
This prints below output:
File Name,Priority,URL,Start Line,Stop Line,Start Column,Stop Column,Issue Name,Issue Category,Issue Description
foo.cls,1,www.example.com,100,105,20,25,blah,Category A,"Fox"
EDIT: Updated code to a working example.
After listing the two properties with special treatment, use Object.fromEntries and Object.entries to transform all the issue.root properties to their flat structure with .s in the property names. Then that object can be spread into the returned object.
const transformsFn = ({ root, issue }) => ({
'root.filename': root.filename.replace(
'/home/users/john-doe/workspace/foo-project/src/main/classes/',
''
),
'issue._': `"${issue._.trim()}"`,
...Object.fromEntries(
Object.entries(issue.root).map(
([key, val]) => [`issue.root.${key}`, val]
)
),
});
const json2csvOptions = {
fields: json2csvFields,
quote: '',
header: true,
transforms: [transformsFn],
};
I have this array of JSON objects:
and I want to add a unique ID (string) to each entry, like this:
let myTree = [
{
text: 'Batteries',
id: '0',
children: [
{
text: 'BatteryCharge',
id: '0-0'
},
{
text: 'LiIonBattery',
id: '0-1'
}
]
},
{
text: 'Supplemental',
id: '1',
children: [
{
text: 'LidarSensor',
id: '1-0',
children: [
{
text: 'Side',
id: '1-0-0'
},
{
text: 'Tower',
id: '1-0-1'
}
]
}
]
}
]
I just can't think of the right logic to achieve this. I have written this recursive function, which obviously does not achieve what I want:
function addUniqueID(tree, id=0) {
if(typeof(tree) == "object"){
// if the object is not an array
if(tree.length == undefined){
tree['id'] = String(id);
}
for(let key in tree) {
addUniqueID(tree[key], id++);
}
}
}
addUniqueID(myTree);
How can I solve this problem?
Instead of using a number/id in the recursive function I build a string.
let myTree = [{
text: 'Batteries',
children: [{
text: 'BatteryCharge'
},
{
text: 'LiIonBattery'
}
]
},
{
text: 'Supplemental',
children: [{
text: 'LidarSensor',
children: [{
text: 'Side'
},
{
text: 'Tower'
}
]
}]
}
];
function addUniqueID(arr, idstr = '') {
arr.forEach((obj, i) => {
obj.id = `${idstr}${i}`;
if (obj.children) {
addUniqueID(obj.children, `${obj.id}-`);
}
});
}
addUniqueID(myTree);
console.log(myTree);
I hope you are well.
why don't you consider using uuid?
In node there is the uuid module which you can use to generate unique identifiers, I share a base example:
install:
npm install uuid
npm i --save-dev #types/uuid
code:
import {v4 as uuid} from 'uuid';
let _id = uuid();
How to transfer field names to groups in a React json schema ui: groups nested object scenario. For example: object1.field1
I want to group the modelMetada and legancyMetaData objects given in the schema by selecting them from the properties inside.
The reason I want this is to show it by grouping it as I want in the tab.
const newSchema = {
$schema: 'http://json-schema.org/draft-07/schema#',
title: 'Physical Model',
type: 'object',
properties: {
modelMetadata: {
type: 'object',
properties: {
name: {
type: 'string',
title: 'Model Name',
description: 'Name of the Model',
},
displayName: {
type: 'string',
title: 'Model Display Name',
description: 'Display Name of the Model',
},
},
},
legacyMetaData: {
type: 'object',
properties: {
id: {
type: 'string',
title: 'Legacy ID',
description: 'ID of the Model in the Legacy System',
},
name: {
type: 'string',
title: 'Legacy Name',
description: 'Legacy Name of the Model',
},
},
},
},
};
const groups = [
{
modelMetadata: ['modelMetadata'],
legacyMetaData: ['legacyMetaData'],
customize: ['modelMetadata.displayName','legacyMetaData.name'], // ????
},
];
The code block I grouped
const doGrouping = ({ properties, groups, formContext }):any => {
const mapped = groups.map((g) => {
if (typeof g === 'string') {
const found = properties.filter((p) => p.name === g);
if (found.length === 1) {
const el = found[0];
return el.content;
}
return EXTRANEOUS;
} else if (typeof g === 'object') {
const { templates } = formContext;
const GroupComponent = templates
? templates[g['ui:template']]
: DefaultTemplate;
// #ts-ignore
const tempProperties = Object.keys(g).reduce((acc, key) => {
const field = g[key];
if (key.startsWith('ui:')) return acc;
if (!Array.isArray(field)) return acc;
return [
...acc,
{
name: key,
children: doGrouping({
properties,
formContext,
groups: field,
}),
},
];
}, []);
return <GroupComponent properties={tempProperties} />;
}
throw new Error(`Invalid object type: ${typeof g} ${g}`);
});
const remainder = mapped.filter((m) => m === REST);
if (remainder.length > 0) {
throw new Error('Remainder fields not supported');
}
return mapped;
};
I'm using NPM 'inquirer' package in order to present the user various questions. One of them is a 'choices' selection.
Is there a way to present follow up questions based on the 'choices' selection?
Here's my code:
const { prompt } = require('inquirer');
require('colors');
const questions = [
{
type: 'input',
name: 'appName',
message: 'Enter application name:'
},
{
type: 'input',
name: 'appDescription',
message: 'Enter app description:'
},
{
type: 'input',
name: 'appAuthor',
message: 'Enter app author:'
},
{
type: 'checkbox',
name: 'plugins',
message: 'Select plugins to install:',
choices: [
{
name: 'Cassandra'
}
]
}
];
module.exports.performQuestions = async () => {
console.log('\nWelcome to Chef!\n'.underline.italic.cyan);
const answers = await prompt(questions);
if (!answers.appName) {
console.error('\nPlease provide app name!\n'.red);
process.exit(1);
}
answers.appType = 'service';
return answers;
};
Here I want to present a few more questions if the user selects 'Cassandra' is that possible?
Thanks.
You can use "when" and like in the example bellow, the second question will popup only if "Cassandra" is selected:
const QUESTIONS = [
{
name: 'your-name',
type: 'list',
message: 'Your name:',
choices: ['Batman', 'Superman', 'Ultron', 'Cassandra'],
},
{
name: 'hello-cassandra',
type: 'confirm',
message: 'Oh, hello Cassandra!',
when: (answers) => answers['your-name'] === 'Cassandra',
},
];
inquirer.prompt(QUESTIONS)
.then(answers =>
{
console.log(answers);
});
I'm having an issue with sequelize on create with associated model with an "unique" value. It works when I create a "book" with a new "category", but if the "category" already exists it throws an error because it tried to duplicate an "unique" value. Is there a way to make sequelize.create try to use findAndCreate on a associated model?
My setup
Book:
const Book = sequelize.define('book', {
title: Sequelize.STRING,
})
Category:
const Category = sequelize.define('category', {
id: Sequelize.BIGINT,
name: {
type: Sequelize.STRING,
unique: true,
},
})
and the relationship:
Book.belongsTo(Category, { foreignKey: 'category_id' })
So, when i create a book i can write:
Book.create(
{
title: 'Book',
category: {
name: 'Foo'
}
}, {
include: [
{
model: Category
}
]
}
)
if after that I create another book:
Book.create(
{
title: 'Another Book',
category: {
name: 'Foo'
}
}, {
include: [
{
model: Category
}
]
}
)
it throws the error saying category.name must be unique
For anyone with the same question, this was my final solution:
On my services.js I created the function create that receives a request(req) and all my models already initialized.
create: (req, models) => {
const { category, ...rest } = req.body
if (category && category.name && !rest.category_id) {
return models.Category
.findOrCreate({
where: {
name: category.name
}
})
.then(([returnedCategory]) => {
return models.Book.create(
{
...rest,
category_id: returnedCategory.id
},
{ ...defaultOptions(models) }
)
})
} else {
return models.Book.create(rest, { ...defaultOptions(models) })
}
},
defaultOptions looks like this:
const defaultOptions = models => {
return {
attributes: {
exclude: ['category_id', 'created_at', 'updated_at'],
},
include: [
{ model: models.Category, attributes: ['id', 'name'] },
],
}
}