JS commonjs exporting a function shows up as undefined - javascript

I define a function in app.js like so:
const sendNotif = (userIds, type, content) => {...}
exports.sendNotif = sendNotif;
And I import it in service.controller.js like so:
const { sendNotif } = require("../app");
sendNotif(...)
When I hover over it in vscode I can see the function definition, however, when I run the code I get that sendNotif is not a function, when I log its type using typeof, I get undefined.
EDIT: I'm using nodejs without any bundlers or compilers, I'm also exporting an HTTP server in app.js by doing exports.http = htpp, and then I import that in index.js and use it, then it works fine. I'm able to import things from app.js everywhere else except in this file, I can't import anything.
UPDATE:
I tried do so:
const app = require("../app");
console.log(app);
and I get an empty object
UPDATE: I'm able to import the function from apps within the same level, same directory, but not form files that are a level deeper, (ex ./ vs ../)
ANOTHER UPDATE: I updated my node version to 15.6 from 12.4 and now I get this output in the console:
(node:17052) Warning: Accessing non-existent property 'Symbol(nodejs.util.inspect.custom)' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
(node:17052) Warning: Accessing non-existent property 'constructor' of module exports inside circular dependency
(node:17052) Warning: Accessing non-existent property 'Symbol(Symbol.toStringTag)' of module exports inside circular dependency
(node:17052) Warning: Accessing non-existent property 'Symbol(Symbol.iterator)' of module exports inside circular dependency

Related

Import javascript from node_modules in angular

I installed a npm package which contains a javascript file, what I want to use. The js file name is all.js and contains this code:
import { initExtended } from './extended'
import Header from './components/header/header'
function initAll(options) {
// Set the options to an empty object by default if no options are passed.
options = typeof options !== 'undefined' ? options : {}
// Allow the user to initialise GOV.UK Frontend in only certain sections of the page
// Defaults to the entire document if nothing is set.
var scope = typeof options.scope !== 'undefined' ? options.scope : document
// Find first header module to enhance.
var $toggleButton = scope.querySelector('[data-module="govuk-header"]')
new Header($toggleButton).init()
initExtended(options)
}
export {
initAll,
Header
}
File all.js is located in node_modules.
When I tried to import it directly from index.html like:
<script type="module" src="node_modules/#id-sk/frontend/govuk/all.js"></script>
It is not working. Console error, file not found.
I also tried import it via angular.json:
"scripts": [
"./node_modules/#id-sk/frontend/govuk/all.js"
]
Also not working with error "Uncaught SyntaxError: Cannot use import statement outside a module (at scripts.js:15241:1)". The error refers to line:
import { initExtended } from './extended'
I also tried to import it in polyfills but I don't know how to call it.
As you are speaking about angular.json, I assume that you are working in an Angular application bootstrapped using the Angular CLI with default settings.
To be able to use this package #id-sk/frontend in your typescript files, you have to import it directly into your typescript file.
1. Import #id-sk/frontend in your TS files
// Import everything into a local variable
import * as govuk from '#id-sk/frontend';
// Import specific object
import { HeaderExtended } from '#id-sk/frontend';
2. Run ng serve
⚠ Spoil: It will lead to typings errors
3. Let's add or create typings
As #id-sk/frontend is not written in typescript, the compile doesn't know about the typings of this library.
Following this statement, you have two choices:
Find or contribute to DefinitelyTyped in order to create the typings of your package #id-sk/frontend
Create a local file typings.d.ts in your ./src folder to declare an empty module
declare module "#id-sk/frontend"
4. Kill & run ng serve again
Enjoy it!
Go further
You can add typings to your module in order to give you autocompletion on the provided objects of #id-sk/frontend.
``ts
declare module "#id-sk/frontend" {
export interface Options {
scope?: Document
}
export function initAll(options: Options): void;
}

Cypress not recognizing my imported module from outside /cypress directory

I am trying to import a module from a file outside my /cypress directory into the /cypress/integration directory's test.spec.js file like so:
import { LAB_MODEL } from '../../models/search/lab-model';
But inside this imported module "LAB_MODEL" there are other files being imported using the "##" at the start of the file imports like
import ExperimentDetails from "##/components/experiment/ExperimentDetails";
and I think this is why Cypress isn't working and giving me this error:
Error: Webpack Compilation Error
./models/search/lab-model.js
Module not found: Error: Can't resolve '##/components/experiment/ExperimentDetails' in '/Users/hidden/models/search'
resolve '##/components/experiment/ExperimentDetails' in '/Users/hidden/models/search'
Parsed request is a module
using description file: /Users/hidden/package.json (relative path: ./models/search)
Field 'browser' doesn't contain a valid alias configuration
resolve as module
So I think this is the reason why my test won't run, but I have no idea how to make Cypress recognize "##" imports and can't find any documentation/stackoverflow answers, any help is appreciated, thanks!
##/ looks like something that gets translated into a full path during the Nuxt build.
(ref The alias Property).
Cypress has a separate build that doesn't know about this Nuxt feature. You could try to replicate it with some webpack config via a preprocessor, but another way is to have your Nuxt app put a reference to lab_model on the window object
// somewhere in the Nuxt app
if (window.Cypress) {
window.lab_model = LAB_MODEL;
}
then at the top of the test
const lab_model = cy.state('window').lab_model;
This has the benefit of giving you the exact same instance of lab_model, in case you wanted to stub something.
In a starter Nuxt app, I added the code window.lab_model = LAB_MODEL in /pages/index.vue, but you can add it in any component that imports it, right after the import statement.
In the spec add a .should() to test the property exists, to allow the app time to settle.
it('gets labModel from the Nuxt app', () => {
cy.visit('http://localhost:3000/')
cy.window()
.should('have.property', 'lab_model') // retries until property appears
.then(labModel => {
console.log(labModel)
// test with labModel here
})
})

inject a require into a js vendor module

About the framework (while I think the problem itself does not heavily rely on that): Angular 2 with Webpack
There is the library Leaflet.heat which relies on simpleheat. I got the missing type definitions under control.
I'm importing the libraries in my vendor.ts
[...]
import 'simpleheat';
import 'leaflet.heat/src/HeatLayer';
[...]
Inside of the HeatLayer class, the function simpleheat:
[simpleheat.js]
if (typeof module !== 'undefined') module.exports = simpleheat;
function simpleheat(canvas) {
...
is called. However, the HeatLayer module file does not require simpleheat inside it's file.
Thus, creating an instance of L.HeatLayer works, but the execution of the respective code in it's function fails with
ReferenceError: simpleheat is not defined
Now, adding (for testing purposes) simpleheat = require('simpleheat'); into the HeatLayer file (a vendor), it works.
Understandably, I don't want to modify a vendor file.
Question:
What options do I have, to make the function simpleheat accessible from inside the HeatLayer module?
One Solution I just found:
Change the vendor.ts to the following:
(<any>window).simpleheat = require('simpleheat');
import 'leaflet.heat/src/HeatLayer';
Are there others/better?

Wiriting 'JSON.stringify' generates an error when Vue component loads

I am writing a Vue plugin, but anytime I try to add JSON.stringify to it I get a runtime error in the browser and the page goes blank. Anywhere in the Plugin file I write JSON.stringify I get the error:
Uncaught TypeError: Cannot assign to read only property 'exports' of object '#'
If I write JSON.stringify to a component directly (in the 'created' lifecycle hook, for example), nothing happens.
This is not an error during the webpack compilation, it happens only in the browser inside an eval. The line where the error occurs looks like this:
eval("/* WEBPACK VAR INJECTION */(function(module) {Object.defineProperty(__webpack_exports__ ....")
This is what is written in the plugin file
var MyPlugin = function () {
}
JSON.stringify({})
MyPlugin.secret = 'vue-plugin-secret'
MyPlugin.install = function (Vue, options) {
}
module.exports = MyPlugin
// export default MyPlugin
And this is how I get it in the component:
var MyPlugin = require('./MyPlugin')
If I comment the JSON.stringify line the error stops.
#edit
did what #Saurabh suggested, used 'import' so I had to change the export form of the plugin
//MyPlugin.js
export default MyPlugin
And in the .vue component I did
import MyPlugin from './MyPlugin';
this fixed the error, but what is the reason for this? some webpack configuration? (I'm using the default webpack configuration of vue-cli)

Typescript module loading error

I have a file module.d.ts with declaration
declare module "ArrayItem" {import out = require("models/ArrayItem"); export = out;}
Now I have a file Array.ts and the first line is
/// <reference path="../module.d.ts" />
import array = require("ArrayItem").
But this is not working. I got script error.
If I use,
/// <reference path="../module.d.ts" />
import array = require("models/ArrayItem")
Then I did not get any error.
What is the issue in module loading here?
If I have a module.d.ts, then the arrayitem module should be loaded from require("arrayitem").
Correct? Or should I always the correct path for ArrayItem?
I am confused here. Can someone throw help here?
If you are the owner of ArrayItem.ts then you don't need module.d.ts. Just reference the module directly.
You are getting a runtime error but not a compiler error because your runtime is trying to load ArrayItem.js for the current path and not from models/ArrayItem. There is no point in your module.d.ts file since it is only a wrapping of the definitions (but not code) in the typescript module, which your already going to pick up with a direct reference to the module.
So, don't use the /// and import using require("models/ArrayItem").

Categories