Vue Unresolved Variable PhpStorm - javascript

I have a Vue script. When I debug it with PhpStorm, I got Unresolved variable syntax error even though I set the variable redirect_to. Please check image. How can I solve it?
<script>
const timeToRefetch = 2000;
let intervalRef;
const homePageUrl = "/";
let messageCount = 0;
var app = new Vue({
el: "#app",
data: {
status: "",
message: "",
redirect_to: ""
},
created() {
const refThis = this;
intervalRef = setInterval(() => {
fetch(ApiUrl)
.then(response => response.json())
.then(repos => {
refThis.status = repos.status;
this.message = repos.message;
clearInterval(intervalRef);
setTimeout(() => {
window.location.href = repos.redirect_to;
}, 3000);
},
);
}, timeToRefetch);
}
});
</script>

If you use some object with keys only known in runtime (generated, received through the ajax call, etc.) in your code, there is no way for the IDE to resolve them using static code analysis. But you can let the IDE know what your runtime data looks like. Possible solution using JSDoc annotations:
/**
* #typedef {Object} repos
* #property {string} status
* #property {string} message
* #property {string} redirect_to
*
*/
...
var app = new Vue({
el: "#app",
data: {
status: "",
message: "",
redirect_to: ""
},
created() {
const refThis = this;
intervalRef = setInterval(() => {
fetch(ApiUrl)
.then(response => response.json())
.then(
/**
* #param {repos} repos
*/
(repos) => {
refThis.status = repos.status;
this.message = repos.message;
clearInterval(intervalRef);
setTimeout(() => {
window.location.href = repos.redirect_to;
}, 3000);
},
);
}, timeToRefetch);
}
});
See also https://youtrack.jetbrains.com/issue/WEB-17419#comment=27-1058451, https://intellij-support.jetbrains.com/hc/en-us/community/posts/206349469-disable-unresolved-variable-on-json-object-received-by-ajax-call for other possible workarounds

Related

How to update RTK Query cache when Firebase RTDB change event fired (update, write, create, delete)

I am using redux-tookit, rtk-query (for querying other api's and not just Firebase) and Firebase (for authentication and db).
The code below works just fine for retrieving and caching the data but I wish to take advantage of both rtk-query caching as well as Firebase event subscribing, so that when ever a change is made in the DB (from any source even directly in firebase console) the cache is updated.
I have tried both updateQueryCache and invalidateTags but so far I am not able to find an ideal approach that works.
Any assistance in pointing me in the right direction would be greatly appreciated.
// firebase.ts
export const onRead = (
collection: string,
callback: (snapshort: DataSnapshot) => void,
options: ListenOptions = { onlyOnce: false }
) => onValue(ref(db, collection), callback, options);
export async function getCollection<T>(
collection: string,
onlyOnce: boolean = false
): Promise<T> {
let timeout: NodeJS.Timeout;
return new Promise<T>((resolve, reject) => {
timeout = setTimeout(() => reject('Request timed out!'), ASYNC_TIMEOUT);
onRead(collection, (snapshot) => resolve(snapshot.val()), { onlyOnce });
}).finally(() => clearTimeout(timeout));
}
// awards.ts
const awards = dbApi
.enhanceEndpoints({ addTagTypes: ['Themes'] })
.injectEndpoints({
endpoints: (builder) => ({
getThemes: builder.query<ThemeData[], void>({
async queryFn(arg, api) {
try {
const { auth } = api.getState() as RootState;
const programme = auth.user?.unit.guidingProgramme!;
const path = `/themes/${programme}`;
const themes = await getCollection<ThemeData[]>(path, true);
return { data: themes };
} catch (error) {
return { error: error as FirebaseError };
}
},
providesTags: ['Themes'],
keepUnusedDataFor: 1000 * 60
}),
getTheme: builder.query<ThemeData, string | undefined>({
async queryFn(slug, api) {
try {
const initiate = awards.endpoints.getThemes.initiate;
const getThemes = api.dispatch(initiate());
const { data } = (await getThemes) as ApiResponse<ThemeData[]>;
const name = slug
?.split('-')
.map(
(value) =>
value.substring(0, 1).toUpperCase() +
value.substring(1).toLowerCase()
)
.join(' ');
return { data: data?.find((theme) => theme.name === name) };
} catch (error) {
return { error: error as FirebaseError };
}
},
keepUnusedDataFor: 0
})
})
});

Property 'getNetworkId' does not exist on type 'never' Typescript

I'm currently working with the cardano serialization library to code crypto transactions in typescript. I'm referencing a wallet connector template that has example code for transactions but is all written in Javascript. So in translating it over I've received a number of syntax errors that have generally been easy to resolve until now. I have a number of ts(2532) errors (Object is possibly 'undefined' that are solved through '?' chaining, I know that's not my best solution but for now I'm trying to get it error free first. When I utilize a ? operator chain though I then get the property does not exist on type 'never' error in the following code
getNetworkId = async () => {
try {
const networkId = await this?.API?.getNetworkId()
this.setState({ networkId })
} catch (err) {
console.log(err)
} }
Below I've included the majority of the code down until that error
export default class App extends React.Component<any, any> {
API: undefined
protocolParams: {
linearFee: { minFeeA: string; minFeeB: string }
minUtxo: string
poolDeposit: string
keyDeposit: string
maxValSize: number
maxTxSize: number
priceMem: number
priceStep: number
coinsPerUtxoWord: string
}
constructor(props: any) {
super(props)
this.state = {
selectedTabId: '1',
whichWalletSelected: undefined,
walletFound: false,
walletIsEnabled: false,
walletName: undefined,
walletIcon: undefined,
walletAPIVersion: undefined,
wallets: [],
networkId: undefined,
Utxos: undefined,
CollatUtxos: undefined,
balance: undefined,
changeAddress: undefined,
rewardAddress: undefined,
usedAddress: undefined,
txBody: undefined,
txBodyCborHex_unsigned: '',
txBodyCborHex_signed: '',
submittedTxHash: '',
addressBech32SendADA:
'addr_test1qrt7j04dtk4hfjq036r2nfewt59q8zpa69ax88utyr6es2ar72l7vd6evxct69wcje5cs25ze4qeshejy828h30zkydsu4yrmm',
lovelaceToSend: 3000000,
assetNameHex: '4c494645',
assetPolicyIdHex:
'ae02017105527c6c0c9840397a39cc5ca39fabe5b9998ba70fda5f2f',
assetAmountToSend: 5,
addressScriptBech32:
'addr_test1wpnlxv2xv9a9ucvnvzqakwepzl9ltx7jzgm53av2e9ncv4sysemm8',
datumStr: '12345678',
plutusScriptCborHex: '4e4d01000033222220051200120011',
transactionIdLocked: '',
transactionIndxLocked: 0,
lovelaceLocked: 3000000,
manualFee: 900000,
}
/**
* When the wallet is connect it returns the connector which is
* written to this API variable and all the other operations
* run using this API object
*/
this.API = undefined
/**
* Protocol parameters
* #type {{
* keyDeposit: string,
* coinsPerUtxoWord: string,
* minUtxo: string,
* poolDeposit: string,
* maxTxSize: number,
* priceMem: number,
* maxValSize: number,
* linearFee: {minFeeB: string, minFeeA: string}, priceStep: number
* }}
*/
this.protocolParams = {
linearFee: {
minFeeA: '44',
minFeeB: '155381',
},
minUtxo: '34482',
poolDeposit: '500000000',
keyDeposit: '2000000',
maxValSize: 5000,
maxTxSize: 16384,
priceMem: 0.0577,
priceStep: 0.0000721,
coinsPerUtxoWord: '34482',
}
this.pollWallets = this.pollWallets.bind(this)
}
/**
* Poll the wallets it can read from the browser.
* Sometimes the html document loads before the browser initialized browser plugins (like Nami or Flint).
* So we try to poll the wallets 3 times (with 1 second in between each try).
*
* Note: CCVault and Eternl are the same wallet, Eternl is a rebrand of CCVault
* So both of these wallets as the Eternl injects itself twice to maintain
* backward compatibility
*
* #param count The current try count.
*/
pollWallets = (count = 0) => {
const wallets = []
for (const key in window.cardano) {
if (window.cardano[key].enable && wallets.indexOf(key) === -1) {
wallets.push(key)
}
}
if (wallets.length === 0 && count < 3) {
setTimeout(() => {
this.pollWallets(count + 1)
}, 1000)
return
}
this.setState(
{
wallets,
whichWalletSelected: wallets[0],
},
() => {
this.refreshData()
}
)
}
/**
* Handles the tab selection on the user form
* #param tabId
*/
handleTabId = (tabId: any) => this.setState({ selectedTabId: tabId })
/**
* Handles the radio buttons on the form that
* let the user choose which wallet to work with
* #param obj
*/
handleWalletSelect = (obj: { target: { value: any } }) => {
const whichWalletSelected = obj.target.value
this.setState({ whichWalletSelected }, () => {
this.refreshData()
})
}
/**
* Generate address from the plutus contract cborhex
*/
generateScriptAddress = () => {
// cborhex of the alwayssucceeds.plutus
// const cborhex = "4e4d01000033222220051200120011";
// const cbor = Buffer.from(cborhex, "hex");
// const blake2bhash = blake.blake2b(cbor, 0, 28);
const script = PlutusScript.from_bytes(
Buffer.from(this.state.plutusScriptCborHex, 'hex')
)
// const blake2bhash = blake.blake2b(script.to_bytes(), 0, 28);
const blake2bhash =
'67f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656'
const scripthash = ScriptHash.from_bytes(Buffer.from(blake2bhash, 'hex'))
const cred = StakeCredential.from_scripthash(scripthash)
const networkId = NetworkInfo.testnet().network_id()
const baseAddr = EnterpriseAddress.new(networkId, cred)
const addr = baseAddr.to_address()
const addrBech32 = addr.to_bech32()
// hash of the address generated from script
console.log(Buffer.from(addr.to_bytes(), 'utf8').toString('hex'))
// hash of the address generated using cardano-cli
const ScriptAddress = Address.from_bech32(
'addr_test1wpnlxv2xv9a9ucvnvzqakwepzl9ltx7jzgm53av2e9ncv4sysemm8'
)
console.log(Buffer.from(ScriptAddress.to_bytes(), 'utf8').toString('hex'))
console.log(ScriptAddress.to_bech32())
console.log(addrBech32)
}
/**
* Checks if the wallet is running in the browser
* Does this for Nami, Eternl and Flint wallets
* #returns {boolean}
*/
checkIfWalletFound = () => {
const walletKey = this.state.whichWalletSelected
const walletFound = !!window?.cardano?.[walletKey]
this.setState({ walletFound })
return walletFound
}
/**
* Checks if a connection has been established with
* the wallet
* #returns {Promise<boolean>}
*/
checkIfWalletEnabled = async () => {
let walletIsEnabled = false
try {
const walletName = this.state.whichWalletSelected
walletIsEnabled = await window.cardano[walletName].isEnabled()
} catch (err) {
console.log(err)
}
this.setState({ walletIsEnabled })
return walletIsEnabled
}
/**
* Enables the wallet that was chosen by the user
* When this executes the user should get a window pop-up
* from the wallet asking to approve the connection
* of this app to the wallet
* #returns {Promise<boolean>}
*/
enableWallet = async () => {
const walletKey = this.state.whichWalletSelected
try {
this.API = await window.cardano[walletKey].enable()
} catch (err) {
console.log(err)
}
return this.checkIfWalletEnabled()
}
/**
* Get the API version used by the wallets
* writes the value to state
* #returns {*}
*/
getAPIVersion = () => {
const walletKey = this.state.whichWalletSelected
const walletAPIVersion = window?.cardano?.[walletKey].apiVersion
this.setState({ walletAPIVersion })
return walletAPIVersion
}
/**
* Get the name of the wallet (nami, eternl, flint)
* and store the name in the state
* #returns {*}
*/
getWalletName = () => {
const walletKey = this.state.whichWalletSelected
const walletName = window?.cardano?.[walletKey].name
this.setState({ walletName })
return walletName
}
/**
* Gets the Network ID to which the wallet is connected
* 0 = testnet
* 1 = mainnet
* Then writes either 0 or 1 to state
* #returns {Promise<void>}
*/
getNetworkId = async () => {
try {
const networkId = await this?.API?.getNetworkId()
this.setState({ networkId })
} catch (err) {
console.log(err)
}
}
/**
* Gets the UTXOs from the user's wallet and then
* stores in an object in the state
* #returns {Promise<void>}
*/
getUtxos = async () => {
let Utxos = []
try {
const rawUtxos = await this?.API?.getUtxos()
for (const rawUtxo of rawUtxos) {
const utxo = TransactionUnspentOutput.from_bytes(
Buffer.from(rawUtxo, 'hex')
)
const input = utxo.input()
const txid = Buffer.from(
input.transaction_id().to_bytes(),
'utf8'
).toString('hex')
const txindx = input.index()
const output = utxo.output()
const amount = output.amount().coin().to_str() // ADA amount in lovelace
const multiasset = output.amount().multiasset()
let multiAssetStr = ''
if (multiasset) {
const keys = multiasset.keys() // policy Ids of thee multiasset
const N = keys.len()
// console.log(`${N} Multiassets in the UTXO`)
for (let i = 0; i < N; i++) {
const policyId = keys.get(i)
const policyIdHex = Buffer.from(
policyId.to_bytes(),
'utf8'
).toString('hex')
// console.log(`policyId: ${policyIdHex}`)
const assets = multiasset.get(policyId)
const assetNames = assets.keys()
const K = assetNames.len()
// console.log(`${K} Assets in the Multiasset`)
for (let j = 0; j < K; j++) {
const assetName = assetNames.get(j)
const assetNameString = Buffer.from(
assetName.name(),
'utf8'
).toString()
const assetNameHex = Buffer.from(
assetName.name(),
'utf8'
).toString('hex')
const multiassetAmt = multiasset.get_asset(policyId, assetName)
multiAssetStr += `+ ${multiassetAmt.to_str()} + ${policyIdHex}.${assetNameHex} (${assetNameString})`
// console.log(assetNameString)
// console.log(`Asset Name: ${assetNameHex}`)
}
}
}

axios.spread() cache my API whereas axios.get() does not

I'm facing a weird situation where I need to call a bunch of my CMS API routes from my server in order to use their response.data into an object that will then be passed to my client side.
This is the code that caches my data: meaning that when I change a field on my CMS, that data that is being pulled is not updated.
The code is:
let baseUrl = "https://sismographie-cms.herokuapp.com/api/"
let locales = ["?locale=en", "?locale=fr"]
let links = [
"contact-page",
"keywords",
"podcasts",
"random-question-arrays",
"featured-entries-headlines-anims",
"main-text",
"headline",
"cookie-setting",
"header-info-array",
"random-question-prompt",
"contact-page",
"map-entry-right-text",
"map-entry-left-text",
"sponsor-logos",
"credit",
"projects-about-texts"
].map((ele, index) => {
return {
en: `${baseUrl + ele + locales[0]}`,
fr: `${baseUrl + ele + locales[1]}`,
}
});
let objectKeys = [
"info",
"keywords",
"podcasts",
"randomQuestions",
"featuredEntries",
"balladosSubtitle",
"balladosTitles",
"cookiesSetting",
"headerInfoArray",
"randomQuestionPrompt",
"conctactPage",
"mapEntryRightText",
"mapEntryLeftText",
"sponsorLogos",
"credit",
"ProjectsAboutText"
];
let getAxiosRequests = (locale) => {
return links
.map((ele, index) => {
return axios.get(ele[locale])
})
};
axios.all(getAxiosRequests("fr"))
.then(axios.spread((...responses) => {
let cmsObjFr = mapToObject(objectKeys, responses);
axios.all(getAxiosRequests("en"))
.then(axios.spread(
(...responses) => {
let cmsObjEn = mapToObject(objectKeys, responses);
console.log(cmsObjEn);
app.get('/cms-routes', (req, res) => {
res.json({fr: cmsObjFr, en: cmsObjEn})
})
})).catch(errors => {
console.error(errors);
});
})).catch(errors => {
console.error(errors);
});
const mapToObject = (objectKeys, responses) => {
return objectKeys.reduce(
(sum, key, index) => Object.assign(
sum, { [key]: responses[index].data.data}),{}
);
};
When I access the json object, I see that the field I just changed did not update.
When I individually call that same field's CMS route, however, the response contains the updated version of the data:
app.get("/credits", (req, res ) => {
console.log("/credits' call");
axios.get("https://sismographie-cms.herokuapp.com/api/credit?locale=en")
.then(data => res.json(data.data))
})
For, let's say, the credit field, this method will give me the updated version I don't have access when I'm using the axios.spread method.
The problem is that because you create your route handler (app.get("/cms-routes")) after retrieving data, the data it responds with is fixed and will never change.
You need to move the data retrieval logic into the route handler.
Also, as mentioned above axios.all() and axios.spread() are deprecated and should not be used.
const links = {
info: "contact-page",
keywords: "keywords",
podcasts: "podcasts",
randomQuestions: "random-question-arrays",
featuredEntries: "featured-entries-headlines-anims",
balladosSubtitle: "main-text",
balladosTitles: "headline",
cookiesSetting: "cookie-setting",
headerInfoArray: "header-info-array",
randomQuestionPrompt: "random-question-prompt",
conctactPage: "contact-page",
mapEntryRightText: "map-entry-right-text",
mapEntryLeftText: "map-entry-left-text",
sponsorLogos: "sponsor-logos",
credit: "credit",
ProjectsAboutText: "projects-about-texts",
};
const baseURL = "https://sismographie-cms.herokuapp.com/api/";
/**
* Resolves with an array of single property objects, eg
* [
* {
* info: {...}
* },
* {
* keywords: {...}
* },
* ...
* ]
*/
const getAll = (locale) =>
Promise.all(
Object.entries(links).map(async ([key, link]) => ({
[key]: (await axios.get(link, { baseURL, params: { locale } })).data.data,
}))
);
app.get("/cms-routes", async (req, res) => {
const [fr, en] = await Promise.all([getAll("fr"), getAll("en")]);
res.json({ fr: Object.assign(...fr), en: Object.assign(...en) });
});
I've taken the liberty of simplifying your data structures so your links and object keys are tightly coupled.

Sequelize model association update not reflected as expected

I'm trying to associate tags to an organization via sequelize's set<Model>(...) method and it seems to be setting the tags correctly in the db but the updated org with these new tags does not reflect this.
organization model
'use strict';
module.exports = (sequelize, DataTypes) => {
var organization = sequelize.define('organization', {
...
}, {});
organization.associate = function (models) {
// associations can be defined here
organization.hasMany(models.tag)
};
return organization;
};
tag model
'use strict';
module.exports = (sequelize, DataTypes) => {
...
tags.associate = function(models) {
// associations can be defined here
tags.belongsTo(models.organization)
};
return tags;
};
method
/**
* Update organization
* #param {object} db - The db handle
* #param {object} stats - The datadog client
*/
function updateOrganization(db, stats) {
return function (req, res) {
let tagsToAdd = []
let tagsToDelete = []
let myOrg
db.organization.findOne({
where: {
id: req.params.id
},
include: ['tags', 'users', 'retrievals']
})
.then(org => {
myOrg = org
return org.getTags()
})
.then(tags => {
let promises = []
...a bunch of irrelevant logic
// Add all the new tags
tagsToAdd.forEach(tag => {
promises.push(myOrg.createTag({ name: 'newTag' }))
})
return Promise.all(promises)
})
.then(updatedOrg => {
console.log('updatedOrg = ', updatedOrg) <-- Does NOT have tags in updated org output even though they actually exist in db. Why not???
return res.status(HttpStatus.OK).send(updatedOrg)
})
}
}
After countless hours of smashing my skull against anything near me i finally figured out that i needed to call reload()
.then(updatedOrg => {
console.log('updatedOrg = ', updatedOrg)
return res.status(HttpStatus.OK).send(updatedOrg)
})
should be
.then(updatedOrg => {
return myOrg.reload()
})
.then(updatedOrg => {
return res.status(HttpStatus.OK).send(updatedOrg)
})

Mocha pass different parameters to each test file

I have a test file with a single describe that I want to run it twice but each time I want to pass different parameters into it.
My code looks like that:
MochaRunner.js
'use strict';
const fs = require('fs');
const path = require('path');
const Mocha = require('mocha');
const uuidv1 = require('uuid/v1');
class MochaRunner {
/**
* #param {Object} options
*/
constructor(options = {}) {
this._tmps = [];
this._mocha = new Mocha(options);
}
/**
* Run tests
* #param {Array} tests
* #returns {Promise}
*/
run(tests) {
return new Promise((resolve, reject) => {
const Config = require('../config').create();
let counter = 0;
tests.forEach(test => {
const testDir = path.dirname(test.testPath);
const tmpTest = path.join(testDir,`${uuidv1()}.spec.js`);
fs.writeFileSync(tmpTest, fs.readFileSync(test.testPath));
this._tmps.push(tmpTest);
this._mocha.addFile(tmpTest);
Config.setOptions('var ' + counter++);
});
this._mocha.run((err) => {
return err ? reject(err) : resolve();
});
}).catch(() => {
return this.cleanup();
});
}
/**
* Get mocha instance
* #returns {Mocha}
*/
getMocha() {
return this._mocha;
}
/**
* Remove tmp test files
* #returns {Promise}
*/
cleanup() {
this._tmps.forEach(tmpTest => {
fs.unlinkSync(tmpTest);
});
return Promise.resolve();
}
}
module.exports = MochaRunner;
Config.js
class Config {
constructor() {
this.options = {};
}
setOptions(options){
this.options = options;
}
}
module.exports = {
_instance: null,
create: function(){
if (this._instance){
return this._instance;
}
this._instance= new Config();
return this._instance;
}
};
test.e2e.test.js
const chai = require('chai');
const Config = require('./config').create();
const assertionStyles = {
assert: chai.assert,
expect: chai.expect,
should: chai.should,
};
setImmediate(async () => {
describe('describe blah blha', function () {
console.log(Config.options);
it('test case', function () {
assertionStyles.expect(true).to.be.true;
});
});
run();
});
I do this when I want to run the above code:
let tests = ['test.e2e.test.js', 'test.e2e.test.js'];
let mocha = new MochaRunner({});
await mochaRunner.run(tests).then(() => {
mochaRunner.cleanup();
});
In the above example, I want to pass different data when the test will run for second time.
For example, I want the first file read the param from Config with the value:
'var 0'
and the second file read the param with the value:
'var 1'
Any ideas please?
Any help would be greatly appreciated!

Categories