I'm new to Angular and Nodejs. I'm currently developing a Web Application using Angular 5. I want to create a node module and publish it to npm and use it in my app. This module should read from an xml file to create some objects. It always gives me the same error ( fs_1.readFile is not a function). I don't know if it 's possible to read from xml inside the node module.
I'm trying to create an npm package, within this package there will be an xml file. inside one of the classes of this package I want to read the xml file.
Here is screenshot from #types/node module. The function exists
Here is my index.js :
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const xml_js_1= require("xml-js");
class PasswordsConfiguration{
constructor(){
this.passwords=new Array();
this.companies=new Array();
this._json = undefined;
this.readXML()
}
readXML(){
var name,isFunction, maskAND, maskOR, key, defaultValue,companyName,displayedName;
try{
fs_1.readFile('./passwords-config.xml', 'utf8', (err, data) => {
// just neglect the rest of the code, it doesn#t enter this function.
if (err) {
}
else {
this._json = xml_js_1.xml2js(data, {
compact: true,
nativeType: true,
ignoreDeclaration: true,
ignoreComment: true
});
this._json.Configuration.Passwords.every((password) => {
name =password._attributes.name;
isFunction=Boolean(password._attributes.isFunction);
maskAND = parseInt(password._attributes.maskAND,16);
maskOR = parseInt(password._attributes.maskOR,16);
key = password._attributes.key;
defaultValue = parseInt(password._attributes.defaultValue,16);
this.passwords.push(new Password(name,isFunction, maskAND, maskOR, key, defaultValue));
});
this._json.Configuration.Companies.every((company) => {
companyName =company._attributes.name;
displayedName =company._attributes.displayedName;
this.companies.push(new Company(companyName,displayedName));
});
}
});
}catch(e){
}
}
}
exports.PasswordsConfiguration = PasswordsConfiguration;
Here is the index.d.ts
export declare class PasswordsConfiguration {
private _json:any;
passwords:Array<Password>;
companies:Array<Company>;
constructor();
readXML():void;
}
So is this functionality applicable? What's wrong in the code?
Related
I'm quite new to Javascript. I had to switch my project to type "Module" because an import required it. However it totally broke my code.
I am using an AutoLoader to load in all my created classes:
const modules = new Autoloader(path.resolve('./modules'), {
ignore: [
'command.js',
'service.js',
'event.js'
]
});
Normally when I printed out modules it would look like:
{ commands: { invite: class Invite extends Command } }
Now it doesnt recognize the class any more:
{ commands: { invite: undefined } }
The autoloader loads all the classes out (for example) my commands directory.
const api = require('../../api');
const Command = require('./command');
class Invite extends Command {
prefix = '/invite';
handle(message) {
let args = this.stripWithoutLower(message);
if (message.isGroupMsg !== this.groupOnly) {
return;
}
if (typeof args[1] !== 'undefined') {
let inviteCode = args[1].split('/');
if (typeof inviteCode[3] !== 'undefined') {
this.client.joinGroup(inviteCode[3]);
}
}
}
}
module.exports = Invite;
Normally I would use module.exports to export the class. Inside my main.js file I would them loop through the classes I've autoloaded to initiate them. For example:
const commandList = [];
Object.keys(modules['commands']).forEach(key => {
commandList.push(new modules['commands'][key](client));
});
The above coded was working until I had to switch everything to type "Module". Im very new to javascript forgive me about any mis typings.
I've read online that I had to switch module.exports to exports.default = Invite; or to export Class. Unfortunately both didn't worked.
What error am I getting:
TypeError: modules.commands[key] is not a constructor
Im having some issues when using module.exports inside NodeJS, and I've followed multiple guides, and im almost certain Im doing it right.
I have to scripts, main.js and event.js. Im trying to share a function from main.js to event.js, but its not working. Here is the code:
Main.js
function Scan(){
if(fs.readdirSync('./events/').length === 0){
console.log(colors.yellow('Events Folder Empty, Skipping Scan'))
} else {
var events = fs.readdirSync('./events/').filter(file => file.endsWith('.json'))
for(const file of events){
let rawdata = fs.readFileSync('./events/' + file);
let cJSON = JSON.parse(rawdata);
}
events.sort()
tevent = events[0]
StartAlerter()
}
}
module.exports = { Scan };
Event.js
const main = require('../main')
main.Scan;
This returns the error:
(node:19292) Warning: Accessing non-existent property 'Scan' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
What am I doing wrong?
I discovered that the arrangement had no effect in the error.
I simply changed the way I exported the function from the Main.js
from:
module.exports = { Scan };
to:
exports.Scan = Scan
And in Event.js, I was able to access the file like this
const main = require("./Main.js");
let result = main.Scan();
This solved my problem, I hope it helps another developer 😎
Problem solved, heres what I did differently:
module.exports = { Scan };
Is declared before the Scan function is defined, like so:
module.exports = { Scan };
function Scan(){
//Code
}
Then in event.js, I wrote
const main = require('../main')
As it is now a module, and can be used with the require() function.
Then to execute the funciton in event.js, I write
main.Scan()
To execute it.
better try :
module.exports = Scan;
I am gonna answer it using a simple example, like in this case below:
File A has 3 functions to process database activity: function
addDB, updateDB, and delData;
File B has 2 functions to process User activity on smartphone:
function addHistory, and editHistory;
Function updateDB in file A is calling function editHis in file B, and function editHistory is calling function updateDB in file A. This is what we called circular-dependency. And we need to prevent it by only giving output of state from editHistory and the rest will be processed inside file A.
//ORIGINAL FUNCTIONS which caused CIRCULAR DEPENDENCY
function updateDB() {
//process update function here
//call function in fileB
const history = require("fileB.js");
await history.editHistory(data).then((output) => {
if(output["message"] === "success"){
response = {
state: 1,
message: "success",
};
}
});
return response;
}
//THIS is the WRONG ONE
function editHistory() {
//process function to edit History here
//call function in fileA
const file = require("fileA.js");
await file.updateDB(data).then((output) => { //You should not call it here
if(output["message"] === "success") {
output = {
state: 1,
message: "success",
};
}
});
return output;
}
//==================================================//
//THE FIX
function updateDB() {
//process function here
const history = require("fileB.js");
await history.editHistory(data).then((output) => {
if(output["message"] === "success"){
await updateDB(data).then((output) => {
response = {
state: 1,
message: "success",
};
});
} else {
log("Error");
}
});
return response;
}
function editHistory() {
//process function to edit History here
// No more calling to function inside the file A
output = {
state: 1,
message: "success",
};
return output;
}
I'm developing test automation scripts in Cucumber + Puppeteer + Typescript. I'm facing the problem of importing variables being declared in the main module, something like index.js. First, a few words about what I want to achieve:
I'd like to run my tests by executing test-runner.ts, not by npm run cucumber because the requirements need to have more control on the flow. Draft of the test-runner.ts module looks like this:
const exec = require('child_process').exec;
const commandLineArgs = require('command-line-args');
export let launchUrl: string;
const optionDefinitions: Array<object> = [
{ name: 'country', alias: 'c' },
{ name: 'environment', alias: 'e' },
{ name: 'headless', alias: 'h' },
];
function initGlobals() {
const options = commandLineArgs(optionDefinitions);
if (options.environment === 'integration') {
launchUrl = 'https://example.url.com';
}
}
function main() {
let cucumber: any;
let cucumberHtmlReporter: any;
cucumber = exec('./node_modules/.bin/cucumber-js', (stdout: any, err: any) => {
console.log(err);
console.log(`stdout: ${stdout}`);
});
cucumber.on('exit', () => {
cucumberHtmlReporter = exec('node cucumber-html-reporter.js', (stdout: any, err: any) => {
console.log(err);
console.log(`stdout: ${stdout}`);
});
});
}
initGlobals();
main();
So, as you see it mainly parse arguments, run Cucumber and exports a variable. The variable is imported in step definition file. Theoretically, it should work fine but unfortunately, it doesn't. While importing the whole function is executed once again. That means every time when import { launchUrl } from ../test-runner is executed, a new Cucumber application is run and some kind of loop happens.
The question is: how should I export the variables to achieve my goal and avoid the situation like that?
Its best practice anyway to store your constants in a seperate config file that you can export your launchUrl from. Your test-runner.ts would than import it and mutate it as needed.
export const URL_CONFIG = { launchUrl: '' };
then in your test-runner:
import { URL_CONFIG } from './config';
URL_CONFIG.launchUrl = 'foo'; //Everywhere in the ap launchUrl is 'foo'
So I've been following some tutorials about unit testing with Cloud Code. Here is how I organize my code base :
cloud/
ChatMessage/
model.js
update.js
ChatRoom/
model.js
update.js
test/
test.js
In my model.js files, I have Parse.Object subclass with helper functions. It looks like this
class ChatMessage extends Parse.Object {
constructor() {
super('ChatMessage')
}
// Some functions
}
Parse.Object.registerSubclass('ChatMessage', ChatMessage)
module.exports = ChatMessage
In my update.js files, I have the before/after save and cloud code functions :
function beforeSave(request, response) {
// Do stuff
}
Parse.Cloud.beforeSave('ChatMessage', function (request, response) {
beforeSave(request, response)
})
module.exports = {
beforeSave: beforeSave,
}
I've extracted the content of the beforeSave function for test purposes. It enables me to expose the before save function to mocha. For the record, all this works fine in production.
Now in my test I do this :
const ChatMessage = require('../cloud/ChatMessage/model.js')
const ChatMessageUpdate = require('../cloud/ChatMessage/update.js')
const expect = require('expect')
describe('ChatMessage', function () {
const request = {
user: new Parse.User(),
object: new ChatMessage()
}
const response = {
success: function () {},
error: function () {}
}
describe('creation', function () {
it('should fail when the author is undefined', function () {
ChatMessageUpdate.beforeSave(request, response)
expect(response.error).toHaveBeenCalled()
})
})
})
I mock the request and response object. And then I try to launch a test using my beforeSave function. And I get the following error :
class ChatRoom extends Parse.Object {
^
ReferenceError: Parse is not defined
A quick fix is to add this at the beginning of my model file like this :
const Parse = require('parse/node')
But Parse is already expose in /cloud so it seems stupid to me to copy paste this line in every file. What should I do ? More precisely : how do I have my object oriented structure conform to tests ?
Also, what would be the best code structure to test all my code with zero asynchronous test (for test performance) ?
You should define Parse in your test suite as a global
Create a file in your test folder called helper.js that looks like this:
// helper.js
global.Parse = require('parse/node');
This should automatically get included in any of your tests. If you only have one test just add that line to the top of your test file.
Stuck with this one.
I am using laravel elxir with tsify to generate my js. I run the typescript through factor-bundle to split common js modules into a seperate files. I don't think though that will be a problem in this case because everything is in a spec.js
spec.ts
/// <reference path="../../../typings/index.d.ts" />
import "jasmine-jquery";
// #start widgets
import "./widgets/common/widget-factory/test";
factory-widget/index.ts
export class WidgetFactory {
.... this contains a require call to browser.service which i need to mock
}
factory-widget/test.ts
...
import {WidgetFactory} from "./index";
const proxyRequire = require("proxyquire");
it("should output the factory items", ()=> {
proxyRequire('./widgets/browser.service/index',{
"#global": true,
});
}
browser-service.ts
...
export class BrowserService implements IBrowserService{
//details
}
Getting an error Uncaught TypeError: require.resolve is not a function on line 262.
Here is the code ( yeah it's over 20,000 lines ) how else are you supposed to debug this stuff . ¯_(ツ)_/¯
I've looked at Stubbing with proxyquire. I am not holding my breath getting an answer on this one.
Edit: 06-09-2016
Proxquire is needed to overide the require call in the boot method of the WidgetFactory class
In factory-widget/index.ts:
boot(output = true):any {
let required = {};
if (this._sorted.length) {
this._sorted.forEach((key)=> {
if (output) {
console.log(`${this._path}${key}/index`);
// this is where is need to overide the call to require.
required[key] = require(`${this._path}${key}/index`);
}
});
this._sorted.forEach((key)=> {
let dependencies = {},
module = this._factory[key];
if (module.hasOwnProperty(this.dependencyKey)) {
module[this.dependencyKey].map((key)=> {
dependencies[_.camelCase(key)] = this.isService(module) ? new required[key] : key;
});
}
if (this.isTag(module)) {
if (output) {
document.addEventListener("DOMContentLoaded", ()=> {
riot.mount(key, dependencies);
});
}
//console.log(key,dependencies);
}
else {
}
})
}
}
I've added a proxyquireify example to the tsify GitHub repo. It's based on the simple example in the proxyquireify README.md.
The significant parts are the re-definition of require to call proxyquire in foo-spec.ts:
const proxyquire = require('proxyquireify')(require);
require = function (name) {
const stubs = {
'./bar': {
kinder: function () { return 'schokolade'; },
wunder: function () { return 'wirklich wunderbar'; }
}
};
return proxyquire(name, stubs);
} as NodeRequire;
and the configuration of the proxyquire plugin in build.js:
browserify()
.plugin(tsify)
.plugin(proxyquire.plugin)
.require(require.resolve('./src/foo-spec.ts'), { entry: true })
.bundle()
.pipe(process.stdout);
If you build the bundle.js and run it under Node.js, you should see that the message written to the console includes strings returned by the functions in the stubbed ./bar module.