WebStorm JSON files unresolved variable properties (syntax) - json

Practical example is this best here, so here goes. I have a JSON file named file.json as such:
{
"key": "hello"
}
And a JS file in the same directory as such (NodeJS):
'use strict';
// Dependencies
const jsonFile = require('./file.json');
// Globals
const anotherFile = {
key: 'world'
}
const fn = () => {
console.log(jsonFile.key); // this 'key' is not recognized
console.log(anotherFile.key); // this 'key' is recognized
};
Now, that fn function should, and does, print hello and world to the console. My problem is that while WebStorm recognizes the second file (anotherFile) as a JavaScript object, it doesn't do so with the one imported from the JSON.
That means that anotherFile.key has "key" in purple (in my template) color, while the other one is plain white with the underline that you get when it's "Unresolved variable key".
Also means that I can write anotherFile and it will show me all available options (functions, properties, etc) and key will be there, while in the first file, jsonFile, it wont.
Is there any way to force WebStorm to recognize JSON's as JavaScript objects?
Thanks!
Edit: Using WebStorm 11.0.1

Please try upgrading - your code works fine for me in 2016.2:

In Preference>Editor>File Types you should have this :
But I thought it was like this by default ...

Related

Jest Unable to Parse Image Files

I'm trying to set up the configuration and mock files for jest to parse/ignore image files in order for the tests to pass. Just about every online resource leads me to the jest docs located: https://jestjs.io/docs/webpack#handling-static-assets
which tell you exactly how to handle the situation. However, not in my case. I've tried both options of creating mock files and using a transformer.
My current jest.config.js:
module.exports = {
projects: [
{
displayName: 'Unit',
testMatch: ["**/?(*.)+(spec|test).[tj]s?(x)"],
setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
testPathIgnorePatterns: ["<rootDir>/.next/", "<rootDir>/node_modules/", "<rootDir>/cypress/"],
moduleFileExtensions: ["js", "jsx", "ts", "tsx"],
moduleDirectories: ["node_modules", "bower_components", "shared"],
moduleNameMapper: {
"^.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
'^.+\\.(css|sass|scss)$': '<rootDir>/__mocks__/styleMock.js'
},
// transform: {
// "\\.js$": "jest",
// "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/fileTransformer.js"
// //'^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['next/babel'] }],
// }
},
{
displayName: 'Pacts',
testMatch: ["**/?(*.)+(pacttest).[tj]s?(x)"],
testPathIgnorePatterns: ["<rootDir>/.next/", "<rootDir>/node_modules/", "<rootDir>/cypress/"],
watchPathIgnorePatterns: ["pact/logs/*", "pact/pacts/*"],
}
],
};
my fileMock.js:
module.exports = 'test-file-stub';
My styleMock.js:
module.exports = {};
My fileTransformer.js:
const path = require('path');
module.exports = {
process(src, filename, config, options) {
return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
},
};
//export default module.exports;
my directory:
I've been bouncing back and forth trying different options in the configurations but they pretty much all lead me to the same two errors, one when I try to use the transformer, and another without. With the transformer commented out, I get 2 errors thrown at the fileMock.js file:
TypeError: Invalid URL: test-file-stub
Failed to parse src "test-file-stub" on next/image
Both of these are referring to the suggested string for the mock. I initially thought that maybe the string was a placeholder for code to actually handle something. But after some reading, my understanding is that it's actually just supposed to be a string there. Perhaps it's a specific string dependent on my environment? And next/image is where I'm importing the image component from.
I'm prioritizing the mocking (please correct me if I'm wrong) because my understand is the mock tells jest to ignore the image file and proceed with the rest of the test while the transformer actually attempts to change the file type from js to jpg or png or whatever filetype the image is. However, I'm trying everything I can. When I try to the run the tests with the transformer portion uncommented I receive an error before any tests are even run stating:
TypeError: Jest: a transformm must export something.
(which is why there is a commented out export default statement.)
This is my first time ever attempting anything like this and I think I've reached a point where I cannot think of anything else to try. If anybody has experienced anything like this please lay some knowledge on me. I'm not sure if I have the mockfiles set up incorrectly or if it's something in the configurations.
Thanks.
I was able to work around this by creating an image URL here:
https://www.base64-image.de/
and replacing the "test-file-stub" string with the generated URL string.
module.exports = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV/TSotUHeyg4pChOogFURFHrUIRKoRaoVUHk0s/hCYNSYuLo+BacPBjserg4qyrg6sgCH6AuLk5KbpIif9LCi1iPDjux7t7j7t3gFAvMc0KjAGaXjFTibiYya6IwVeE0I9ujCAgM8uYlaQkPMfXPXx8vYvxLO9zf44uNWcxwCcSzzDDrBCvE09tVgzO+8QRVpRV4nPiUZMuSPzIdcXlN84FhwWeGTHTqTniCLFYaGOljVnR1IgniaOqplO+kHFZ5bzFWStVWfOe/IXhnL68xHWag0hgAYuQIEJBFRsooYIYrTopFlK0H/fwDzh+iVwKuTbAyDGPMjTIjh/8D353a+Unxt2kcBzoeLHtjyEguAs0arb9fWzbjRPA/wxc6S1/uQ5Mf5Jea2nRI6BnG7i4bmnKHnC5A/Q9GbIpO5KfppDPA+9n9E1ZoPcW6Fx1e2vu4/QBSFNXyRvg4BAYLlD2mse7Q+29/Xum2d8PVXFym6OczU4AAAAJcEhZcwAALiMAAC4jAXilP3YAAAAHdElNRQflCBkOKh9/wZ+SAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAAAxJREFUCNdj+P//PwAF/gL+3MxZ5wAAAABJRU5ErkJggg==';

Index.js file continuously gives "JSON text did not start with array" despite being formatted as an array

I have a parse-server hosted by heroku, which has an index.js file utilized for its configuration. I want to use Mailgun to up functionality for the user to request a password reset, and I have set up the config file, following this answer, as follows:
var api = new ParseServer({
appName: 'App Name',
publicServerURL: 'https://<name>.herokuapp.com/parse',
databaseURI: databaseUri || 'mongodb://localhost:27017/dev',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID || 'myAppId',
masterKey: process.env.MASTER_KEY || '', //Add your master key here. Keep it $
serverURL: process.env.SERVER_URL || 'http://localhost:1337/parse', // Don't$
liveQuery: {
classNames: ["Posts", "Comments"] // List of classes to support for query s$
},
push: JSON.parse(process.env.SERVER_PUSH || "{}"),
verifyUserEmails: true, //causing errors
emailAdapter: { //causing errors
module: 'parse-server-simple-mailgun-adapter',
options: {
fromAddress: 'parse#example.com',
domain: '<domain>',
apiKey: '<key>',
}
}
});
This code does not work, though, because of the verifyUserEmails and emailAdapter. Removing both of them removes the "JSON text did not start with array" error. Adding either one of them back in results in the error being thrown. I have no idea why, though, since I do not see any obvious reason as to how they aren't being set up in an array correctly?
Do I need to set up the cooresponding config vars in heroku in addition to having them in the config file? I considered this, but appName and publicServerURL are not set up in this way and don't give this error.
emailAdapter.options.apiKey doesn't need a comma at the end since its the last element of it's JSON.
I wouldn't be surprised that you're also leaving in the comma at the end of verifyUserEmails when you include it improperly as well.
options: {
fromAddress: 'parse#example.com',
domain: '<domain>',
apiKey: '<key>',
}
This is not valid JSON, because there is a comma at the end of the apiKey line. The last item in a JSON object does not have a comma.
For anyone that is repeatedly running into this issue, I have figured out exactly what was going wrong. Despite the error informing me that my JSON was incorrectly formatted, it turns out it was actually that the module was misnamed. According to this post, the updated module has been renamed to '#parse/simple-mailgun-adapter'. Inserting this into the index.js, after ensuring I had ran the npm install --save #parse/simple-mailgun-adapter in my local repo, fixed the issue.

Nodejs - trying to edit images' metadata with Exiftool

I am currently working on a NodeJS (Express) project to edit images' metadata with Exiftool.
To edit images' metadata with Exiftool, I've to create a JSON file containing all metadata to modify then execute the command :
exiftool -j=metadata.json pathToTheImage/image.jpg
The json file must look like that :
[{"SourceFile":"pathToTheImage/image.jpg","XMP-dc:Title":"Image's title"}]
Here's my code to do that :
const {exec} = require('child_process');
let fs = require('fs');
let uploadPath = "uploads";
let uploadName = "image.jpg";
...
app.post('/metadata/editor', (req, res) => {
let jsonToImport = [...];
fs.writeFileSync("metadata.json", JSON.stringify(jsonToImport));
exec('exiftool -j=metadata.json ' + uploadPath + '/' + uploadName, (error, stdout, stderr) => {
if (error) {
console.error(error);
return;
}
res.redirect('/metadata/checker/' + uploadName);
});
});
The problem is at the level of "writeFileSync/exec".
Independently these two lines work well, that's to say that if I've just the first line, the JSON file is well created. And if I've just the second ligne, image's metadata are well updated.
But when I execute this two lines together, the JSON file is well created but the exec line do "nothing" (or something that I can't determine).
This code uses synchronous functions, I've test it with asynchronous functions, this is the same behavior.
Currently, to do what I need, I must execute the code above to create the JSON file, then I must comment the writeFileSync line and I must reexecute the code to update image's metadata correctly.
It's really strange, I've try to read the JSON file content before the exec line but everything is ok. I've use asynchronous functions, with and without promise... there is nothing to do it doesn't work.
Thank you for your help.
I'll answer my own question:
The problem was that I use nodemon, however by default nodemon watches JSON files. But in my code I created a JSON file to use it right after. So, I created the JSON file correctly, nodemon sees it, and restarts the node server; the rest of the code does not run.
To fix this, I added an option to ignore the created files in my package.json:
"nodemonConfig": {
"ignore": [
"path/to/files/to/ingore/*"
]
}

Angular 4 html for loop displaying loosely typed object (string) normally but not when element is extracted directly?

I'm using Angular 4 to develop an app which is mainly about displaying data from DB and CRUD.
Long story short I found that in Angular 4 the component html doesn't like displaying loosely typed object (leaving the space blank while displaying other things like normal with no warning or error given in console) even if it can be easily displayed in console.log output, as shown in a string.
So I made a function in the service file to cast the values into a set structure indicating they're strings.
So now something like this works:
HTML
...
<div>{{something.value}}</div>
...
Component.ts
...
ngOnInit() {
this.route.params.subscribe(params => {
this.pkey = params['pkey'];
this.service.getSomethingById(this.pkey)
.then(
something => {
this.something = this.service.convertToStructure(something);
},
error => this.errorMessage = <any>error);
});
}
...
Code of the function convertToStructure(something)
convertToStructure(someArr: myStructure): myStructure {
let something: myStructure = new myStructure();
something.value = someArr[0].value;
return something;
}
But as I dig into other files for copy and paste and learn skills from what my partner worked (we're both new to Angular) I found that he did NOT cast the said values into a fixed structure.
He thought my problem on not being able to display the values (before I solved the problem) was because of me not realizing it was not a plain JSON object {...} but an array with a single element containing the object [{...}] .
He only solved half of my problem, cause adding [0] in html/component.ts was not able to make it work.
Component.ts when it did NOT work
...
ngOnInit() {
this.route.params.subscribe(params => {
this.pkey = params['pkey'];
this.service.getSomethingById(this.pkey)
.then(
something => {
console.log(something[0].value); //"the value"
this.something = something[0]; //html can't find its value
},
error => this.errorMessage = <any>error);
});
}
...
HTML when it did NOT work
...
<div>{{something[0].value}}</div> <!--Gives error on the debug console saying can't find 'value' of undefined-->
...
And of course when I'm using the failed HTML I only used this.something = something instead of putting in the [0], and vice versa.
So I looked into his code in some other page that display similar data, and I found that he used *ngFor in html to extract the data and what surprised me is that his html WORKED even if both of our original data from the promise is identical (using the same service to get the same object from sever).
Here's what he did in html:
...
<div *ngFor="let obj of objArr" ... >
{{obj.value}}
</div>
...
His html worked.
I'm not sure what happened, both of us are using a raw response from the same service promise but using for loop in html makes it automatically treat the value as strings while me trying to simply inject the value fails even if console.log shows a double quoted string.
What's the difference between having the for loop and not having any for loop but injecting the variable into html directly?
Why didn't he have to tell Angular to use the set structure indicating the values are strings while me having to do all the trouble to let html knows it's but a string?
The difference here is as you said that your JSON is not simple object , its JSON Array and to display data from JSON array you need loop. So, that is why your friends code worked and yours did not. And please also add JSON as well.

Unable to print complete JSON using console.log

I am trying to import JSON file into Sample variable but only first few characters are displayed from Sample variable.
The sample.json is 20,00,000 characters, When i print Sample variable on Console only first 3,756 characters are printed.Is there any limitations on the characters that can be printed through console.log?
Complete data persists in Sample variable, I verified it by searching for strings that occur at the end of sample.json file
var Sample = require('./sample.json');
export default class proj extends Component {
constructor(props) {
super(props);
this.state = {
locations: [],
};
}
loadOnEvent() {
console.log(Sample);
//this.state={ locations : Sample };
}
}
Is there any other way to print data in Sample variable.
You have to convert json to string using JSON.stringify before logging.
/* ... */
loadOnEvent() {
console.log(JSON.stringify(Sample));
//this.state={ locations : Sample };
}
/* ... */
Try to use another way to load. Use fetch if file is remote or use fs if file is local.
If it is memory problem supposed by #Shota consider to use server side processing requests to json file. It is good solution to setup microservice which load json file at startup and handle requests to data struct parsed from json file.
Answer for webpack use case:
Configure webpack to use file-loader or copy-webpack-plugin for specifically this file because it enough big. Consider to load it in parallel with webpack bundle. If your application have big parts which need not each case they must be moved to separated bundles.