node module include data file as a global variable - javascript

I set out to make my first node module. It's very simple, it just takes the input from a user and validates if it is valid or not by comparing it to a large data file. The data file is just a json object. Here is the code for index.js
// borrowed heavily from http://quickleft.com/blog/creating-and-publishing-a-node-js-module
/**
* Valiate a NAICS codes using 2012 NAICS codes
*
* #param {String} 2 to 6 digit numeric
* #return {Boolean}
*/
var fs = require('fs');
var obj = JSON.parse(fs.readFileSync('codes.json', 'utf8'));
module.exports = {
validateNAICS: function(inNAICS) {
inNAICS = inNAICS || "";
if (inNAICS.length > 6) { return false };
if (inNAICS.length < 2) { return false };
if (obj.hasOwnProperty(inNAICS)) { return true };
return false;
},
/**
* Given a NAICS code return the industry name
*
* #param {String} 2 to 6 digit numeric
* #return {String}
*/
translateNAICS: function(inNAICS) {
inNAICS = inNAICS || "000";
if (obj.hasOwnProperty(inNAICS)) { return obj[inNAICS] };
return "Unknown";
}
};
However, when I try to use this in a project, the code seems to look for codes.js in the project's root rather than in the modules root. I was able to prove this by making a copy of codes.js and putting it in the project's root and everything worked as expected.
So what is the proper way to include the data from codes.js so that it is available to my two functions?

The easiest way is to simply require it via a relative path name:
var obj = require('./codes.json');
Requires are always relative to the module itself, not the current working directory. Node.js understand that this is a JSON file and parses it accordingly.
In general, you can get a reference to the directory the module is in via the __dirname variable. So the following works as well:
var path = require('path');
var obj = JSON.parse(fs.readFileSync(path.join(__dirname, 'codes.json'), 'utf8'));

Related

How to get the value of a variable when you cant debug or use console.log()

I am trying to find where this extension I installed is storing the templates that are made. I want to know this and HOW they are stored so that I can change the code so that there is a specific template made within the extension itself. A default extension.
I think ive located where the directory for the templates is made but I cant seem to debug or console.log to get the value of this path. I believe the path will be the variable templateDir thats within the TemplatesManager.prototype.getTemplates function...
here is the templatesManager.js file so you can see how that variable is made.
It would be helpful if someone could help me understand how to obtain the value of that variable. I tried console.log(templateDir) but nothing pops up on the VS Code terminal, output, or any other console window.
'use strict';
var fs = require('fs');
var path = require('path');
var os = require('os');
/**
* Main class to handle the logic of the File Templates
* #export
* #class TemplatesManager
*/
var TemplatesManager = (function () {
function TemplatesManager(config) {
this.config = config;
}
/**
* Returns a list of available file templates by reading the Templates Directory.
* #returns string[]
*/
TemplatesManager.prototype.getTemplates = function () {
// #TODO make this async (use promises ???)
var templateDir = this.getTemplatesDir();
var templateFiles = fs.readdirSync(templateDir).map(function (item) {
if (!/^\./.exec(item)) {
return fs.statSync(path.join(templateDir, item)).isFile() ? item : null;
}
return null;
}).filter(function (filename) {
return filename !== null;
});
return templateFiles;
};
/**
* Read the contents of a templates
* #param filename The name of the template file.
* #return Buffer
*/
TemplatesManager.prototype.getTemplate = function (filename) {
return fs.readFileSync(path.join(this.getTemplatesDir(), filename), 'utf8');
};
/**
* Returns the templates directory location.
* If no user configuration is found, the extension will look for
* templates in USER_DATA_DIR/Code/FileTemplates.
* Otherwise it will look for the path defined in the extension configuration.
* #return {string}
*/
TemplatesManager.prototype.getTemplatesDir = function () {
return this.config.get('templates_dir', this.getDefaultTemplatesDir());
};
/**
* Returns the default templates location based on the user OS.
* #returns {string}
*/
TemplatesManager.prototype.getDefaultTemplatesDir = function () {
var userDataDir = null;
switch (process.platform) {
case 'linux':
userDataDir = path.join(os.homedir(), '.config');
break;
case 'darwin':
userDataDir = path.join(os.homedir(), 'Library', 'Application Support');
break;
case 'win32':
userDataDir = process.env.APPDATA;
break;
default:
throw Error("Unrecognizable operative system");
}
return path.join(userDataDir, 'Code', 'User', 'FileTemplates');
};
/**
* Creates the templates dir if not exists
* #throw Error
*/
TemplatesManager.prototype.createTemplatesDirIfNotExists = function () {
var templatesDir = this.getTemplatesDir();
fs.mkdir(templatesDir, '0755', function (err) {
if (err && err.code != 'EEXIST') {
throw Error("Failed to created templates directory " + templatesDir);
}
});
};
return TemplatesManager;
}());
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = TemplatesManager;
//# sourceMappingURL=templatesManager.js.map

How to configure jest snapshot locations

I'd like for my jest snapshots to be created as a sibling to my test file
I current have my snapshots being put in the default __snapshots__ folder.
Current:
What I would like to achieve:
I found this post on github: https://github.com/facebook/jest/issues/1650
In the thread someone says the following should work but I haven't had any luck (even with changing the regex and other changes):
module.exports = {
testPathForConsistencyCheck: 'some/example.test.js',
resolveSnapshotPath: (testPath, snapshotExtension) =>
testPath.replace(/\.test\.([tj]sx?)/, `${snapshotExtension}.$1`),
resolveTestPath: (snapshotFilePath, snapshotExtension) =>
snapshotFilePath.replace(snapshotExtension, '.test'),
}
In package.json (or if you use jest.config.js) you need to add the path for the snapshotResolver file:
"jest": {
"snapshotResolver": "./snapshotResolver.js"
}
snapshotResolver.js is a file with code that you found in a Github issue.
In my case this file was located at the root of the project (near node_modules folder)
These solutions are more complicated that is needed for what you are trying to do.
As per pointed out in https://github.com/facebook/jest/issues/1650
Solution
Create a file: I used - 'jest/snapshotResolver.js'
module.exports = {
resolveSnapshotPath: (testPath, snapshotExtension) =>
testPath + snapshotExtension,
resolveTestPath: (snapshotFilePath, snapshotExtension) =>
snapshotFilePath.replace(snapshotExtension, ''),
testPathForConsistencyCheck: 'some.test.js',
};
in your jest config set that file to the resolver
snapshotResolver: './jest/snapshotResolve.js',
or if your jest config in package.json:
"snapshotResolver": "./jest/snapshotResolve.js",
Explanation
In short these two functions mirror each other, one takes the test file path and returns the snapshot path, the other takes the snapshot path and returns the test file path. The third is a file path example for validation.
Clearer code To help clarify what is going on
One thing to keep in mind is that the path is the full path not the relative path.
/**
*
* #param testPath Path of the test file being test3ed
* #param snapshotExtension The extension for snapshots (.snap usually)
*/
const resolveSnapshotPath = (testPath, snapshotExtension) => {
const snapshotFilePath = testPath + snapshotExtension; //(i.e. some.test.js + '.snap')
return snapshotFilePath;
}
/**
*
* #param snapshotFilePath The filename of the snapshot (i.e. some.test.js.snap)
* #param snapshotExtension The extension for snapshots (.snap)
*/
const resolveTestPath = (snapshotFilePath, snapshotExtension) => {
const testPath = snapshotFilePath.replace(snapshotExtension, '').replace('__snapshots__/', ''); //Remove the .snap
return testPath;
}
/* Used to validate resolveTestPath(resolveSnapshotPath( {this} )) */
const testPathForConsistencyCheck = 'some.test.js';
module.exports = {
resolveSnapshotPath, resolveTestPath, testPathForConsistencyCheck
};
Also, in addition to the path to the snapshotResolver as suggested in the Vasyl Nahuliak's answer, to achieve having the snapshot and the test files looking like this:
file.test.js
file.test.js.snap
your snapshotResolver should look like this:
module.exports = {
testPathForConsistencyCheck: 'some/example.test.js',
resolveSnapshotPath: (testPath, snapshotExtension) =>
testPath.replace(/\.test\.([tj]sx?)/, `.test.$1${snapshotExtension}`),
resolveTestPath: (snapshotFilePath, snapshotExtension) =>
snapshotFilePath.replace(snapshotExtension, ''),
};

Faker.js Generating random paths doesn't work

I am using faker.js
https://www.npmjs.com/package/faker
to generate random data. It works fine although when I try to create a path like this
faker.system.directoryPath() + '/' + faker.system.filePath()
I have always got undefined in both, so it seems that it exists but doesn't return anything.
Did anyone use one of these methods before?
Thanks in advance, any help would be really appreciated.
Bye
Those functionalities are not implemented - take a look into https://github.com/Marak/faker.js/blob/master/lib/system.js#L132 and https://github.com/Marak/faker.js/blob/master/lib/system.js#L141
/**
* not yet implemented
*
* #method faker.system.filePath
*/
this.filePath = function () {
// TODO
};
Some proof of concept how it can be implemented:
var faker = require('faker');
var path = require('path');
faker.directoryPath = function() {
return path.format({base: faker.fake("{{random.words}}").replace(/ /g, path.sep).toLowerCase()})
}
console.log(faker.directoryPath() + path.sep + faker.system.fileName()) // e.g. avon\re-engineered\strategist_gorgeous_wooden_fish_cambridgeshire.sm

How to resolve a path that includes an environment variable, in nodejs?

I would like to run an executable and its path contains an enviroment variable, for example if I would like to run chrome.exe I would like to write something like this
var spawn = require('child_process').spawn;
spawn('chrome',[], {cwd: '%LOCALAPPDATA%\\Google\\Chrome\\Application', env: process.env})
instead of
var spawn = require('child_process').spawn;
spawn('chrome',[], {cwd: 'C:\\Users\myuser\\AppData\\Local\\Google\\Chrome\\Application', env: process.env}).
Is there a package I can use in order to achieve this?
You can use a regex to replace your variable with the relevant property of process.env :
let str = '%LOCALAPPDATA%\\Google\\Chrome\\Application'
let replaced = str.replace(/%([^%]+)%/g, (_,n) => process.env[n])
I don't think a package is needed when it's a one-liner.
I realize that the question is asking for Windows environment variables, but I modified #Denys Séguret's answer to handle bash's ${MY_VAR} and $MY_VAR style formats as I thought it might be useful for others who came here.
Note: the two arguments are because there are two groupings based on the variations of the format.
str.replace(/\$([A-Z_]+[A-Z0-9_]*)|\${([A-Z0-9_]*)}/ig, (_, a, b) => process.env[a || b])
Adding a TypeScript friendly addition to the excellent answer by Denys Séguret:
let replaced = str.replace(/%([^%]+)%/g, (original, matched) => {
const r = Process.env[matched]
return r ? r : ''
})
Here is a generic helper function for this:
/**
* Replaces all environment variables with their actual value.
* Keeps intact non-environment variables using '%'
* #param {string} filePath The input file path with percents
* #return {string} The resolved file path
*/
function resolveWindowsEnvironmentVariables (filePath) {
if (!filePath || typeof(filePath) !== 'string') {
return '';
}
/**
* #param {string} withPercents '%USERNAME%'
* #param {string} withoutPercents 'USERNAME'
* #return {string}
*/
function replaceEnvironmentVariable (withPercents, withoutPercents) {
let found = process.env[withoutPercents];
// 'C:\Users\%USERNAME%\Desktop\%asdf%' => 'C:\Users\bob\Desktop\%asdf%'
return found || withPercents;
}
// 'C:\Users\%USERNAME%\Desktop\%PROCESSOR_ARCHITECTURE%' => 'C:\Users\bob\Desktop\AMD64'
filePath = filePath.replace(/%([^%]+)%/g, replaceEnvironmentVariable);
return filePath;
}
Can be called from anywhere
Does basic type checking first, you may want to change what is returned by default in the first if block
Functions are named in ways that explain what they do
Variables are named in ways that explain what they are
Comments added make it clear what outcomes can occur
Handles non-environment variables wrapped in percents, since the Windows file system allows for folders to be named %asdf%
JSDoc blocks for automated documentation, type checking, and auto-complete in certain editors
You may also want to use if (process.platform !== 'win32') {} depending on your need
These answers are crazy. Just can use path:
const folder = require('path').join(
process.env.LOCALAPPDATA,
'Google/Chrome/Application',
);
console.log(folder); // C:\Users\MyName\AppData\Local\Google\Chrome\Application
On Linux/MacOS, I spawn a process to resolve paths with env variables, is safe - let bash to do the work for you. Obviously less performant, but a lot more robust. Looks like this:
import * as cp from 'child_process';
// mapPaths takes an array of paths/strings with env vars, and expands each one
export const mapPaths = (searchRoots: Array<string>, cb: Function) => {
const mappedRoots = searchRoots.map(function (v) {
return `echo "${v}"`;
});
const k = cp.spawn('bash');
k.stdin.end(mappedRoots.join(';'));
const results: Array<string> = [];
k.stderr.pipe(process.stderr);
k.stdout.on('data', (d: string) => {
results.push(d);
});
k.once('error', (e) => {
log.error(e.stack || e);
cb(e);
});
k.once('exit', code => {
const pths = results.map((d) => {
return String(d || '').trim();
})
.filter(Boolean);
cb(code, pths);
});
};

Extract ZIp File Using Library JSZip

I am working in windows 8 using HTML/JS. I am trying to Extract a Zip file which is picked file using FilePicker.
To extract Zip file I am using this page.
In this Link there is a function to Extract Zip file unzipAsync
function unzipAsync(filePath, replaceIfExists) {
var fileCollisionOption = replaceIfExists ?
storage.CreationCollisionOption.replaceExisting :
storage.CreationCollisionOption.failIfExists;
return storage.StorageFile
.getFileFromPathAsync(filePath)
.then(getFileAsUint8Array)
.then(function (zipFileContents) {
//Create the zip data in memory
var zip = new JSZip(zipFileContents);
//Extract files
var promises = [];
var lf = storage.ApplicationData.current.localFolder;
_.each(zip.files, function (zippedFile) {
//Create new file
promises.push(lf
.createFileAsync(zippedFile.name, fileCollisionOption)
.then(function (localStorageFile) {
//Copy the zipped file's contents into the local storage file
var fileContents = zip.file(zippedFile.name).asUint8Array();
return storage.FileIO
.writeBytesAsync(localStorageFile, fileContents);
})
);
});
return WinJS.Promise.join(promises);
});
}
Before this I added JSZIP Library to Project folder.
Help me, How Can I integrate the Library to my project. Here is my project Link
Edit:
function getFileAsUint8Array(file) {
return storage.FileIO.readBufferAsync(file)
.then(function (buffer) {
//Read the file into a byte array
var fileContents = new Uint8Array(buffer.length);
var dataReader = storage.Streams.DataReader.fromBuffer(buffer);
dataReader.readBytes(fileContents);
dataReader.close();
return fileContents;
});
}
Now it is working with out error. But it is not doing any thing like extracting my file.
NOTE:
- If anyone knows any another way which better than this or other Library which I can use to extract file for WinJS; please suggest me.
Well, I'm guessing you haven't created a getFileAsUint8Array function (or at least, you aren't showing it above). I am doing something similar (although getting the zip file from an XHR call instead). Once I have the zip file and the folder I want to put the zip files in I do something like the code below.
Note, however, that I had to modify this code as I do a few other things, so I haven't tested it exactly as is (and obviously it wouldn't work within your code above).
Here's the (mostly) full code:
WinJS.xhr({ "url": zipUrl, "responseType": "arraybuffer" })
.done(
function (e) {
if (!e.getResponseHeader("content-type") === "application/zip") {
console.error("Remote file was not sent with correct Content-Type: expected 'application/zip', but received '" + e.getResponseHeader("content-type") + "'");
}
unzipAndStore(new JSZip(e.response), someLocalFolder);
},
function() { /* handle ajax errors */ }
);
/**
* #param {JSZip} jszipobj The JSZip object
* #param {StorageFolder} localFolder The folder to unzip into
* #return {Promise}
*/
var unzipAndStore = function (jszipobj, localFolder) {
var promises = [];
Object.keys(jszipobj.files).forEach(function (key) {
var fileName;
// ignore folder entries, they're handled as needed below
if (/\/$/.test(key)) { return; }
fileName = jszipobj.files[key].name.match(/[^\/]+\.[^\.\/]+$/);
if (!fileName) {
console.error("Unable to process zip entry without proper filename: ", jszipobj.files[key].name);
return;
}
fileName = fileName[0];
promises.push(
getFolderFromPathRecursive(jszipobj.files[key].name, localFolder)
.then(
function (subFolder) {
console.log("creating file in folder: ", fileName, subFolder.name);
return subFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.replaceExisting)
}
)
.then(
function (localStorageFile) {
return Windows.Storage.FileIO
.writeBytesAsync(localStorageFile, jszipobj.file(jszipobj.files[key].name).asUint8Array());
}
)
);
});
return WinJS.Promise.join(promises);
};
/**
* Promise completes with the lowest level folder in the given path,
* creating subfolders along the way
* #param {String} path The path to the lowest subfolder you want a reference to
* #param {StorageFolder} rootFolder The folder to begin at for this iteration
* #return {Promise}
*/
var getFolderFromPathRecursive = function (path, rootFolder) {
var normalizedPath = path.replace(/\/?[^\/]+\.[^\.\/]+$/, ""), // remove a possible filename from the end of the path
folders = normalizedPath.split(/\//), // get an array of the folders in the path
subFolderName = folders.shift(); // remove the first folder in the path as the new one to create
return new WinJS.Promise(function (complete, error) {
if (!subFolderName || !subFolderName.length) {
complete(rootFolder);
return;
}
rootFolder
.createFolderAsync(subFolderName, Windows.Storage.CreationCollisionOption.openIfExists)
.then(
function (folder) {
return getFolderFromPathRecursive(folders.join("/"), folder);
},
error
)
.then(
function(folder) {
complete(folder);
return;
},
error
)
});
};
I did using Decompressing Sample by adding C# windows runtime to my JavaScript project
Here is my post

Categories