Say I have this code
import someOtherFunction from 'whatever'
function testFunction(hello) {
return someOtherFunction(hello.world.name)
}
I want to transform this to something like:
import someOtherFunction from 'whatever'
function testFunction(hello) {
return world.name
}
Basically, I want to remove the hello property and the function wrapping them.
What I have achieved so far:
transformSync(code, {
plugins: [
function customPlugin() {
return {
visitor: {
Identifier(path) {
if (path.isIdentifier({ name: 'world' })) {
if (
path.parentPath.isMemberExpression()
&& path.parentPath.get('object').isIdentifier({ name: 'hello' })
) {
path.parentPath.name = '' // remove hello property?
}
}
}
}
}
},
]
})
Related
So the goal is to have included only those endpoints (and its methods e.g. get, post...) which are defined in the configuration file.
Example structure object that holds all the endpoints.
et swaggerApis = {
header: {
propertyHeader: "valueHeader"
},
blocks: [
{
tags: ["Tenant & User"],
paths: {
"/tenants": {
post: {
property: "value"
},
get: {
property: "value"
}
},
"/tenants/{id}": {
post: {
property: "value"
},
get: {
property: "value"
},
delete: {
property: "value"
}
}
}
}
]
};
Example of the configuration file that holds only those endpoints and its methods we want to have included in the final object.
const CONFIG = {
api: {
include: {
"/tenants/{id}": ["get"]
}
}
};
So far here is my second version of the JavaScript code that works but introduces a high cyclometric complexity and is hard to read. I'm pretty new to JavaScript and looking a way not just to improve this code.
function includeEnpointsByConfig(data) {
for (let blockItem of data.blocks) {
for (let path in blockItem.paths) { //console.log(blockItem.paths[path])
let result = setMethodsOfEndpoint(path, blockItem.paths[path]);
if (result === 'undefined') {
delete blockItem.paths[path] // if the config does not contain, remove
} else {
blockItem.paths[path] = result;
}
}
}
return data;
}
function setMethodsOfEndpoint(path, value) {
let newMethods = {};
for (let confPath in CONFIG.api.include) {
if (path === confPath) { // match endpoint in config and swaggerApis object
if (CONFIG.api.include[confPath].length > 0) { // if array in config is not empty , filter
for (let c of CONFIG.api.include[confPath]) { //console.log(c); // get
for (let v in value) {// properties of object tenants/{id} => {get{}, post{}}
if (v === c) {
newMethods = { ...newMethods, [v]: value[v] };
}
}
}
} else {// if array in config is empty , return param "value" from setMethodsOfEndpoint so we will include all methods of endpoint
return value;
}
} else {
return 'undefined'
}
}
if (Object.keys(newMethods).length !==0) { // if in the config is in the array (nothing that match with swaggerEndpoints e.g. typo get --> gte)
return newMethods
} else {
return value;
}
}
console.log(includeEnpointsByConfig(swaggerApis));
Code can be found also here
https://codesandbox.io/s/blazing-worker-1emzl?file=/src/index2.js
I believe there is a way to do it much easier, cleaner and more effective.
Thank you
With some creative usage of Array.prototype.forEach(), Object.keys() and Object.entries():
swaggerApis.blocks.forEach(block => {
Object.entries(block.paths).forEach(([path, methods]) => {
if (!CONFIG.api.include[path]) {
delete block.paths[path];
} else {
Object.keys(methods).forEach(method => {
if (!CONFIG.api.include[path].includes(method)) {
delete methods[method];
}
});
}
});
});
Complete snippet:
const swaggerApis = {
header: {
propertyHeader: "valueHeader"
},
blocks: [
{
tags: ["Tenant & User"],
paths: {
"/tenants": {
post: {
property: "value"
},
get: {
property: "value"
}
},
"/tenants/{id}": {
post: {
property: "value"
},
get: {
property: "value"
},
delete: {
property: "value"
}
}
}
}
]
};
const CONFIG = {
api: {
include: {
"/tenants/{id}": ["get"]
}
}
};
swaggerApis.blocks.forEach(block => {
Object.entries(block.paths).forEach(([path, methods]) => {
if (!CONFIG.api.include[path]) {
delete block.paths[path];
} else {
Object.keys(methods).forEach(method => {
if (!CONFIG.api.include[path].includes(method)) {
delete methods[method];
}
});
}
});
});
console.log(swaggerApis);
Why is this variable unresolved if there is an instance that we transwer into the function?
Could anyone help me with it?
Vue.component('university-row', {
props: ['university', 'editMethod'],
template: 'Templates'
methods: {
edit: function () {
>>>>>>>>>>>>>>this.editMethod(this.university);<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}
}
});
Vue.component('university-list', {
props: ['universities'],
data: function() {
return {
university: null
}
},
template: 'Templates',
methods: {
editMethod: function() {
>>>>>>>>>>>>>>>>>this.university = university;<<<<<<<<<<<<<<<<<<<<<<This one is unresolved
}
}
});
the second component has
universityApi.get().then(result =>
result.json().then(data =>
data.forEach(university => this.universities.push(university))
)
)
},```
I'm trying to access my data property in my Vue.js component. Looks like I'm missing something obvious.
Here is a short version of my code. StoreFilter.vue is a wrapper for matfish2/vue-tables-2.
<template>
<store-filter :selected.sync="storeIds"></store-filter>
</template>
<script>
import StoreFilter from './Filters/StoreFilter';
export default {
components: {
StoreFilter
},
data() {
return {
options : {
requestFunction(data) {
console.log(this.storeIds); //undefined
return axios.get('/api/orders', {
params: data
}).catch(function (e) {
this.dispatch('error', e);
}.bind(this));
},
},
storeIds: [],
}
},
watch : {
storeIds(storeIds) {
this.refreshTable();
}
},
methods : {
refreshTable() {
this.$refs.table.refresh();
}
}
}
</script>
How to get storeIds from requestFunction?
Use a closure, see rewrite below.
data() {
let dataHolder = {};
dataHolder.storeIds = [];
dataHolder.options = {
requestFunction(data) {
// closure
console.log(dataHolder.storeIds); // not undefined
return axios.get('/api/orders', {
params: data
}).catch(function (e) {
this.dispatch('error', e);
}.bind(this));
}
}
return dataHolder;
}
I recommend using the created() way to handle this.
export default {
// whatever you got here
data () {
return {
options: {}
}
},
created () {
axios.get('/api/orders', { some: params }).then(response => this.options = response.data)
}
}
Let's say I have a component which repeats with a v-for loop like so:
<hotel v-for="(hotel, index) in hotels"></hotel>
And my hotels array would look like so:
[
{
name: false
},
{
name: false
},
{
name: true
},
{
name: true
}
]
How could I perform an action when my v-for loop encounters the property name set to true only on the very first time it encounters this truthy property?
I know I could probably cache a property somewhere and only run something once and not run again if it has been set but this does not feel efficient.
Use a computed to make a copy of hotels where the first one has an isFirst property.
computed: {
hotelsWithFirstMarked() {
var result = this.hotels.slice();
var first = result.find(x => x.name);
if (first) {
first.isFirst = true;
}
return result;
}
}
Just use computed source
HTML
<div v-for="(hotel, index) in renderHotels"></div>
JS
export default {
name: 'message',
data () {
return{
hotels:[
{
name: false
},
{
name: false
},
{
name: true
},
{
name: true
}
] ,
wasFirst : false
}
},
methods:{
},
computed:{
renderHotels(){
return this.hotels.map((hotel)=>{
if(hotel.name && !this.wasFirst){
this.wasFirst = true;
alert('First True');
console.log(hotel);
}
})
}
}
}
Best way is to use filter function.
data() {
return {
firstTime: false,
};
},
filters: {
myFunc: function (hotel) {
if (hotel.name && !this.firstTime) {
//perform some action
this.firstTime = true;
}
}
}
<hotel v-for="(hotel, index) in hotels | myFunc"></hotel>
im currently having a problem when i try to use a function in a createMapping component, this is the code
itemConcurso.js
import {h, createMapping} from 'maquette';
function enterAnim(domNode, properties) {
domNode.className += ' animated fadeInUp';
}
const item = createMapping(
function getSourceKey(source) {
console.log(source);
return source;
},
function createTarget(item, i) {
return (func) => {
const helper = () => { func(item.Id) };
return {
renderMaquette: function() {
return h(`ul#${item.Id}.item-concurso.list-group.mt-3`, { key: item.Id, enterAnimation: enterAnim, onclick: helper}, [
h('li.list-group-item.list-group-item.list-heading-primary', [
h('div.pull-right', [
h('h4', item.Ministerio__c)
]),
h('h3', item.Name.toUpperCase())
]),
h("li.list-group-item", [
h('h4', item.activity),
h('ul', [
h('li', ['Perfil buscado: ', item.Nombre_de_perfil__c]),
h('li', ['Conocimientos requeridos: ', item.Conocimientos_tecnicos_requeridos__c]),
h('li', ['DescripciĆ³n: ', item.Descripcion__c]),
])
])
]);
}
}
};
},
function updateTarget(updatedSource, target) {
console.log(updatedSource);
});
export default item;
App.js
function probando(id) {
console.log(id);
}
const app = function() {
return {
renderMaquette: function() {
return h('div#concurso', [
searchB.renderMaquette(),
itemConcurso.results.map(function(component) {
return component(test).renderMaquette();
})]);
}
}
}
It actually works, but in the first time i click the component it throws the following error:
vendor.bundle.js:15132 Uncaught Error: Functions may not be updated on subsequent renders (property: onclick). Hint: declare event handler functions outside the render() function.
at updateProperties (vendor.bundle.js:15132)
at updateDom (vendor.bundle.js:15370)
at updateChildren (vendor.bundle.js:15241)
at updateDom (vendor.bundle.js:15369)
at Object.update (vendor.bundle.js:15393)
at doRender (vendor.bundle.js:15636)
I tried many things but it seems like there is a thing that im not understanding
The problem with the code is that createTarget returns a function which produces new {renderMaquette: ...} instances during the app.renderMaquette.
Because these instances are new, a new helper is created, hence the error.
If you want to pass a func to item, you could export a function createItem(func) instead of export default item