electron "MAIN" : requiring you own js file and call function from it - javascript

I'm can't understand some things here related to electron. I've been searching for hours for the magic answer but couldn't find anything.
My goal is simple. I don't want my main electron.js file to be 5000 lines long without any kind of organization so I'm trying to split the code into multiple js file that make sense.
My idea was to use import { someFunction1, someFunction2 } from './scripts/someScript' in my electron.js and then just creating that file with the arrow function in it and export them.
Then I could call the function as I want in the main file. However, it doesn't seem to be possible. I've read electronjs doesn't support ES6 syntax. I've read about Babel (But from what I read, it implies a bunch of additional configuration and I don't want to spend days trying to add this to the bunch of configuration that are already messy with electron + React (No boiler plate here). And I didn't find anything specifics for this combo.
Question is. Is this doable in 2021? Am I missing anything? What would you guys recommend?
File would look something like this:
import { someNodeModuleFunction } from 'someNodeModule';
const someFunction1 = () => {
return 1;
};
const someFunction2 = () => {
return 2;
};
export { someFunction1, someFunction2 }
EDIT
Here's the actual code I have a problem with. I still get
if the file is .js: "Must use import to load ES Module"
If the file is .mjs: "Cannot use import statement outside a module"
This script is simply using fs to create a directory:
DataManagement.mjs:
import { existsSync, mkdir } from 'fs';
const electron = require('electron');
const app = electron.app;
const documentFolder = app.getPath('documents');
const CreateDataDirectory = () => {
const mainPath = documentFolder + 'AppName'
if (!existsSync(mainPath)) {
mkdir(mainPath);
}
};
module.exports = { CreateDataDirectory }
Calling it like that in electron.js:
const { CreateDataDirectory } = require('./scripts/DataManagement.mjs');
[...]
CreateDataDirectory()
Not sure how dividing the code can be that hard. :)

You may need to use Node.js module syntax (require and module.exports) or Babel (code transpiler).
For example:
import { someNodeModuleFunction } from 'someNodeModule';
const someFunction1 = () => {
return 1;
};
const someFunction2 = () => {
return 2;
};
module.exports = { someFunction1, someFunction2 }
Using your module:
const { someFunction1, someFunction2 } = require ('./FILE.js');
// ...

You could use module.exports:
otherModule.js
const someFunction1 = () => {
return 1;
};
const someFunction2 = () => {
return 2;
};
module.exports = {
someFunction1,
someFunction2
};
main.js
const { someFunction1, someFunction2 } = require('otherModule.js');

Related

NodeJS: My jest spyOn function is not being called

I don't understand why my spy is not being used. I have used this code elsewhere and it has worked fine.
Here is my test:
const {DocumentEngine} = require('../documentEngine')
const fileUtils = require('../utils/fileUtils')
const request = {...}
const fieldConfig = {...}
test('If the Carbone addons file is not found, context is built with the carboneAddons property as an empty object', async () => {
const expectedResult = {
carboneAddons: {},
}
const fileExistSpy = jest
.spyOn(fileUtils, 'checkFileExists')
.mockResolvedValue(false)
const result = await docEngine.buildContext(request, fieldConfig)
expect(fileExistSpy).toHaveBeenCalledTimes(1)
})
Here is the code that it is being tested:
async function buildContextForLocalResources(request, fieldConfig) {
/* other code */
const addonFormatters = await getCarboneAddonFormatters()
const context = {
sourceJson,
addonFormatters,
documentFormat,
documentTemplateId,
documentTemplateFile,
responseType,
jsonTransformContext
}
return context
}
async function getCarboneAddonFormatters() {
const addOnPath = path.resolve(
docConfig.DOC_GEN_RESOURCE_LOCATION,
'library/addon-formatters.js'
)
if (await checkFileExists(addOnPath)) {
logger.info('Formatters found and are being used')
const {formatters} = require(addOnPath)
return formatters
}
logger.info('No formatters were found')
return {}
}
This is the code from my fileUtils file:
const fs = require('fs/promises')
async function checkFileExists(filePath) {
try {
await fs.stat(filePath)
return true
} catch (e) {
return false
}
}
My DocumentEngine class calls the buildContext function which in turn calls the its method getCarboneAddonFormatters. The fileUtils is outside of DocumentEngine class in a utilities folder. The original code I had this working on was TypeScript as opposed to this which is just NodeJS Javascript. The config files for both are the same. When I try to step through the code (VSCode debugger), as soon as I hit the line with await fs.stat(filePath) in the checkFileExists function, it kicks me out of the test and moves on to the next test - no error messages or warnings.
I've spent most of the day trying to figure this out. I don't think I need to do an instance wrapper for the documentEngine, because checkFileExists is not a class member, and that looks like a React thing...
Any help in getting this to work would be appreciated.

Unable to implement singleton patten in javascript

I am trying to implement a singleton pattern for the fastify instance. My code is as follows :-
const { createFastifyServer: server } = require("../app");
const getFastifyInstance = (() => {
let fastify;
return {
fastifyInstance: async () => {
if (!fastify) {
console.log("Called")
fastify = server();
await fastify.ready();
}
return fastify
}
}
})();
const { fastifyInstance } = getFastifyInstance
module.exports = fastifyInstance
Now wherever I am importing the code in a different file, the console prints "Called" each time it's imported in a new file, but shouldn't that be only once if singleton pattern was correctly implemented. Any idea what am I doing wrong?

How to stub a libary function in JavaScript

For example, if I have main.js calling a defined in src/lib/a.js, and function a calls node-uuid.v1, how can I stub node-uuid.v1 when testing main.js?
main.js
const a = require("./src/lib/a").a
const main = () => {
return a()
}
module.exports = main
src/lib/a.js
const generateUUID = require("node-uuid").v1
const a = () => {
let temp = generateUUID()
return temp
}
module.exports = {
a
}
tests/main-test.js
const assert = require("assert")
const main = require("../main")
const sinon = require("sinon")
const uuid = require("node-uuid")
describe('main', () => {
it('should return a newly generated uuid', () => {
sinon.stub(uuid, "v1").returns("121321")
assert.equal(main(), "121321")
})
})
The sinon.stub(...) statement doesn't stub uuid.v1 for src/lib/a.js as the above test fails.
Is there a way to globally a library function so that it does the specified behavior whenever it gets called?
You should configure the stub before importing the main module. In this way the module will call the stub instead of the original function.
const assert = require("assert")
const sinon = require("sinon")
const uuid = require("node-uuid")
describe('main', () => {
it('should return a newly generated uuid', () => {
sinon.stub(uuid, "v1").returns("121321")
const main = require("../main")
assert.equal(main(), "121321")
})
})
Bear in mind that node-uuid is deprecated as you can see by this warning
[Deprecation warning: The use of require('uuid') is deprecated and
will not be supported after version 3.x of this module. Instead, use
require('uuid/[v1|v3|v4|v5]') as shown in the examples below.]
About how to stub that for testing would be a bit more harder than before as actually there is no an easy way to mock a standalone function using sinon
Creating a custom module
//custom uuid
module.exports.v1 = require('uuid/v1');
Requiring uuid from the custom module in your project
const uuid = require('<path_to_custom_module>');
Sinon.stub(uuid, 'v1').returns('12345');

Module Import error - cannot find module

I was trying to import the module dynamically in ES6 on Meteor application. But getting an error cannot find module. The same import works when I'm using the static import statement.
Please have a look at the below code -
const JOBS = ['update-report-cron'];
const jobs = {
start() {
JOBS.forEach((job) => {
console.log(`job ${job} has been started`);
let fileName = './' + job + '.js';
console.log(require(fileName));
})
}
};
module.exports = {jobs};
ERROR - Cannot find module './update-report-cron.js'
Try
export default const jobs = {
// your code
}
When you import, use
import { jobs } from './update-report-cron.js'
Ru's answer is not correct, not sure how it's your answer.
Try
export default const jobs = {
// your code
}
When you import, use
import jobs from './update-report-cron.js'

Require not behaving as expected

I'm using the proxyquire library, which mocks packages on import.
I'm creating my own proxyquire function, which stubs a variety of packages I use regularly and want to stub regularly (meteor packages, which have a special import syntax):
// myProxyquire.js
import proxyquire from 'proxyquire';
const importsToStub = {
'meteor/meteor': { Meteor: { defer: () => {} } },
};
const myProxyquire = filePath => proxyquire(filePath, importsToStub);
export default myProxyquire;
Now I want to write a test of a file which uses one of these packages:
// src/foo.js
import { Meteor } from 'meteor/meteor'; // This import should be stubbed
export const foo = () => {
Meteor.defer(() => console.log('hi')); // This call should be stubbed
return 'bar';
};
And finally I test it like this:
// src/foo.test.js
import myProxyquire from '../myProxyquire';
// This should be looking in the `src` folder
const { foo } = myProxyquire('./foo'); // error: ENOENT: no such file
describe('foo', () => {
it("should return 'bar'", () => {
expect(foo()).to.equal('bar');
});
});
Note that my last 2 files are nested inside a subfolder src. So when I try to run this test, I get an error saying that the module ./foo couldn't be found, as it is being looked for in the "root" directory, where the myProxyquire.js file is, not the src directory as expected.
You might be able to work around that (expected) behaviour by using a module like caller-path to determine from which file myProxyquire was called, and resolving the passed path relative to that file:
'use strict'; // this line is important and should not be removed
const callerPath = require('caller-path');
const { dirname, resolve } = require('path');
module.exports.default = path => require(resolve(dirname(callerPath()), path));
However, I have no idea of this works with import (and, presumably, transpilers).

Categories

Resources