class Object is not a constructor - javascript

I've created my own Vue.js npm library to help me with my personal projects. Everything works fine except when trying to import a Class
I've defined the class as so:
import Vue from 'vue'
export default class Foo {
constructor () {
...
}
}
my npm packages.json:
"main": "./dist/my-custom-lib.common.js",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"build-bundle": "vue-cli-service build --target lib --name my-custom-lib ./index.js",
"test:unit": "vue-cli-service test:unit"
},
"files": [
"dist/my-custom-lib.common.js",
"src/components/*",
"src/controllers/*",
"src/mixins/*",
"src/utilities/*"
],
To publish I do a yarn build-bundle followed by npm publish.
When I try to import it from my other project:
import { Foo } from '#username/my-custom-lib'
I get the following error:
global-plugin.js?3d38:9 Uncaught TypeError: _username_my_custom_lib__WEBPACK_IMPORTED_MODULE_2__.Foo is not a constructor
I'm able to use all other functions/mixins/vue components but not this class.
EDIT: Here is the partial contents of the common.js file:
var foo_Foo =
/*#__PURE__*/
function () {
function Foo(router) {
_classCallCheck(this, Foo);
}
_createClass(Foo, [{
...source contents...
}]);
return Foo;
}();
/* concated harmony reexport foo */__webpack_require__.d(__webpack_exports__, "foo", function() { return foo_Foo; });
index.js which is called as part of yarn build-bundle contains the following:
import * as components from '#/components'
const VueComponents = {
install (Vue) {
for (const plugin in components) {
Vue.component(plugin, components[plugin])
}
}
}
export * from '#/mixins'
export * from '#/utilities'
export * from '#/controllers'
export default VueComponents
inside #/controllers/index.js:
import foo from './foo'
export {
foo
}

Related

Babel generating broken code when exporting react components from .jsx files

Consider below code:
src/bar.jsx:
import React from "react";
export default function Bar() {
return (
<>
<span>Bar</span>
</>
);
}
src/baz.jsx:
import React from "react";
export default function Baz() {
return (
<>
<span>Baz</span>
</>
);
}
src/foo.jsx:
import React from "react";
export default function Foo() {
return (
<>
<span>Foo</span>
</>
);
}
src/index.js:
export { default as Foo } from "./foo.jsx";
export { default as Bar } from "./bar.jsx";
export { default as Baz } from "./baz.jsx";
.babelrc:
{
"presets": ["#babel/preset-env", "#babel/preset-react"],
"plugins": [
["#babel/transform-runtime"]
],
"ignore": [
"**/*.stories.js"
]
}
package.json:
{
"devDependencies": {
"#babel/cli": "7.19.3",
"#babel/core": "7.19.3",
"#babel/eslint-parser": "7.19.1",
"#babel/plugin-transform-runtime": "7.19.1",
"#babel/polyfill": "7.12.1",
"#babel/preset-env": "7.19.4",
"#babel/preset-react": "7.18.6",
"#babel/register": "7.18.9",
"eslint": "^8.25.0",
"eslint-plugin-react": "^7.31.10",
"prettier": "^2.7.1"
},
"engines": {
"node": "17.8.0 || 18.11.0",
"npm": "8.5.5 || 8.19.2"
},
"main": "./index.js",
"name": "mcve_babel",
"peerDependencies": {
"react": "17.0.2",
"react-dom": "17.0.2",
"react-router-dom": "6.2.2"
},
"scripts": {
"build": "babel src -d out --delete-dir-on-start --source-maps inline --copy-files --no-copy-ignored"
},
"version": "0.0.1"
}
And when i try to run npm run build I'll get
dist/index.js:
"use strict";
var _interopRequireDefault = require("#babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "Bar", {
enumerable: true,
get: function get() {
return _bar["default"];
}
});
Object.defineProperty(exports, "Baz", {
enumerable: true,
get: function get() {
return _baz["default"];
}
});
Object.defineProperty(exports, "Foo", {
enumerable: true,
get: function get() {
return _foo["default"];
}
});
var _foo = _interopRequireDefault(require("./foo.jsx"));
var _bar = _interopRequireDefault(require("./bar.jsx"));
var _baz = _interopRequireDefault(require("./baz.jsx"));
The problem here is the dist tree will look like this:
dist/
├── bar.js
├── baz.js
├── foo.js
└── index.js
So If I tried to use this library in a webapp I'd get import errors because the babel generated code is broken (you can see the generated requires are pointing out to unexistent jsx files).
One possible workaround obviously would be by having exports without using extensions in the first place or by not using .jsx files but .js files instace. That said, I'd like to figure whether it's possible to have jsx files in place and still being able to transpile the code using babel without the final dist being broken code.
Am I missing any babel plugin/config?

Vue3 - imported module is undefined

Update: After downgrading vue-cli to 4.5.19 code is working fine.. So I think it's issue related with vue-cli or its dependency.
I've created simple vue.js project using vue-cli. After adding to the project package timecode by npm install timecode --save and try to use it in Vue component, imported module is undefined. I've a feeling this is problem related with webpack. Timecode package is written in commonJS and when I use it outside this project, it works fine. Any ideas?
#vue/cli v5.0.8,
npm v8.11.0,
node v16.16.0
package.json
{
"name": "hello-world",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"core-js": "^3.8.3",
"timecode": "^0.0.4",
"vue": "^3.2.13"
},
"devDependencies": {
"#vue/cli-plugin-babel": "~5.0.0",
"#vue/cli-service": "~5.0.0"
}
}
vue.config.js
const { defineConfig } = require('#vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true
})
babel.config.js
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset'
]
}
main.js
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
App.vue
<template>
<HelloWorld />
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "App",
components: {
HelloWorld,
},
};
</script>
<style>
</style>
HelloWorld.vue
<template></template>
<script setup>
import timecode from "timecode";
console.log(timecode); // { }
const timeCode = timecode.Timecode; // undefinied
const tc = timeCode.init({ framerate: "29.97", timecode: "01:00:00:00" }); // Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'init')
tc.add(4);
tc.add("00:02:03:00");
console.log(tc.toString());
</script>
<style>
</style>
Output in console
app.js:167 Uncaught TypeError: Cannot read properties of undefined (reading 'init')
at setup (HelloWorld.vue?e90b:7:1)
at callWithErrorHandling (runtime-core.esm-bundler.js?d2dd:155:1)
at setupStatefulComponent (runtime-core.esm-bundler.js?d2dd:7186:1)
at setupComponent (runtime-core.esm-bundler.js?d2dd:7140:1)
at mountComponent (runtime-core.esm-bundler.js?d2dd:5493:1)
at processComponent (runtime-core.esm-bundler.js?d2dd:5468:1)
at patch (runtime-core.esm-bundler.js?d2dd:5058:1)
at ReactiveEffect.componentUpdateFn [as fn] (runtime-core.esm-bundler.js?d2dd:5607:1)
at ReactiveEffect.run (reactivity.esm-bundler.js?89dc:185:1)
at instance.update (runtime-core.esm-bundler.js?d2dd:5714:1)
When I use this package, without vue, by simple npm init, npm install timecode --save and call it form node node index.js I don't have this problems.
index.js
const timecode = require("timecode").Timecode; // all fine
const tc = timecode.init({ framerate: "29.97", timecode: "01:00:00:00" });
tc.add(4)
tc.add("00:02:03:00");
tc.toString();
package.json
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"timecode": "^0.0.4"
}
}
If you are using Vue 3 Composite API you can register the package locally and use it
<template>
</template>
<script setup>
import timecode from 'timecode'
//create the constant value and assign it with the imported timecode
const timeCode = timecode.Timecode;
const tc = timeCode.init({ framerate: "29.97", timecode: "01:00:00:00" });
tc.add(4);
tc.add("00:02:03:00");
console.log(tc.toString());
</script>
<style>
</style>
If you are using Vue 3 Optional API you can try like this.
<template>
</template>
<script>
import timecode from 'timecode'
export default {
data: () => ({
timeCode: timecode.Timecode
}),
methods: {
//create a function to use your time code
useMyTimeCode() {
let tc = this.timeCode.init({ framerate: "29.97", timecode: "01:00:00:00" });
tc.add(4);
tc.add("00:02:03:00");
console.log(tc.toString());
}
},
created() {
//you can use you function anywhere and you can even modify the function to pass parameters
this.useMyTimeCode();
}
}
</script>
<style>
</style>
Remember to install the package as
npm i timecode

SyntaxError: Cannot use import statement outside a module: when running Jest-expo tests

The configuration for the project. Currently using jest-expo for testing in this project. The version of jest-expo in the project is 39.0.0. Version of Jest installed globally is 26.6.3
package.json :
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject",
"test": "jest",
"type": "module"
},
...
"devDependencies": {
"#babel/core": "^7.12.3",
"babel-preset-expo": "^8.3.0",
"jest-expo": "^39.0.0",
"react-test-renderer": "^17.0.1"
},
"jest": {
"preset": "jest-expo"
}
jest.config.js:
module.exports = {
setupFilesAfterEnv: [
'./setup-tests.js',
],
"transformIgnorePatterns": [
"/node_modules/#codler/react-native-keyboard-aware-scroll-view/lib/index.js",
"/node_modules/#react-native-community/async-storage/(?!(lib))",
"/node_modules/native-base-shoutem-theme/.*",
"node_modules/native-base/.*",
"node_modules/(?!(jest-)?react-native|react-clone-referenced-element|#react-native-community|expo(nent)?|#expo(nent)?/.*|react-navigation|#react-navigation/.*|#unimodules/.*|unimodules|sentry-expo|native-base|#sentry/.*|native-base-*|native-base-shoutem-*)"
],
verbose : true
};
babel.config.js
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: ['inline-dotenv'],
};
};
I am trying to render a snapshot for a login page that is react-native:
The error is caused by the below import module inside LoginScreen.js
import {
Content,
Container,
H2,
Form,
Item,
Input,
Button,
Text,
View,
} from "native-base";
Test case inside LoginScreen.test.js
import LoginScreen from './LoginScreen';
import React from 'react';
import renderer from 'react-test-renderer';
it('renders LoginScreen correctly', () => {
const tree = renderer.create(<LoginScreen />).toJSON();
expect(tree).toMatchSnapshot();
});
Test case is throwing the error
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import connectStyle, { clearThemeCache } from "./src/connectStyle";
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1258:14)
at Object.<anonymous> (node_modules/native-base/src/index.js:1:1)
I have tried other similar answers available on Stack Overflow. But none of them applied to the current project on which I am working with.
I have added connectStyle to the Jest transformIgnorePatterns but still it is throwing that error.
Current Project :
React native mobile application developed using expo.
Using jest-expo for testing.
Configuration of the project.
Tried uninstalling and re-installing all the npm and expo modules, that didn't help either.
This is an open issue on the Native base end. Further details can be found on this ticket :
https://github.com/GeekyAnts/NativeBase/issues/3105

Jest encountered an unexpected token

Not sure why it's complaining on this line:
const wrapper = shallow(<BitcoinWidget {...props} />);
/Users/leongaban/projects/match/bitcoin/src/components/bitcoinWidget.test.js: Unexpected token (17:26)
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
- To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
- If you need a custom transformation specify a "transform" option in your config.
- If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
15 |
16 | describe('when rendering', () => {
>17 | const wrapper = shallow(<BitcoinWidget {...props} />);
18 | ^
19 | it('should render a component matching the snapshot', () => {
20 | const tree = toJson(wrapper);
Entire test:
import React from 'react';
import { shallow } from 'enzyme';
import toJson from 'enzyme-to-json';
// Local components
import BitcoinWidget from './bitcoinWidget';
const props = {
logo: 'foobar',
coin: {
price: 0
},
refresh: jest.fn()
}
describe('when rendering', () => {
const wrapper = shallow(<BitcoinWidget {...props} />);
it('should render a component matching the snapshot', () => {
const tree = toJson(wrapper);
expect(tree).toMatchSnapshot();
expect(wrapper).toHaveLength(1);
});
});
The component
import React from 'react';
const BitcoinWidget = ({ logo, coin : { price }, refresh }) => {
return (
<div className="bitcoin-wrapper shadow">
<header>
<img src={logo} alt="Bitcoin Logo"/>
</header>
<div className="price">
Coinbase
${price}
</div>
<button className="btn striped-shadow white" onClick={refresh}>
<span>Refresh</span>
</button>
</div>
);
}
export default BitcoinWidget;
And my package.json
{
"name": "bitcoin",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.18.0",
"react": "^16.4.2",
"react-dom": "^16.4.2",
"react-redux": "^5.0.7",
"react-scripts": "1.1.5",
"redux": "^4.0.0",
"redux-thunk": "^2.3.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"eject": "react-scripts eject",
"test": "yarn run test-jest:update --verbose --maxWorkers=2",
"test-jest:update": "jest src --updateSnapshot",
"test-jest": "jest src"
},
"now": {
"name": "bitcoin",
"engines": {
"node": "8.11.3"
},
"alias": "leongaban.com"
},
"jest": {
"verbose": true,
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/client/assetsTransformer.js"
},
"moduleFileExtensions": [
"js",
"jsx"
],
"moduleDirectories": [
"node_modules"
]
},
"devDependencies": {
"enzyme": "^3.4.4",
"enzyme-to-json": "^3.3.4",
"jest": "^23.5.0"
}
}
Add this in your package.json jest config.
"transform": {
"\\.js$": "<rootDir>/node_modules/babel-jest"
},
Let me know if the issue still persists.
For anyone using create-react-app, only certain jest configurations can be changed in package.json when using create-react-app.
I have issues with Jest picking up an internal library, Jest would display 'unexpected token' errors wherever I had my imports from this library.
To solve this, you can change your test script to the below:
"test": "react-scripts test --transformIgnorePatterns 'node_modules/(?!(<your-package-goes-here>)/)'",
For anyone who struggled with this issue and none of the above answers worked for them.
After a long time of searching, I reached for this solution:
edit your jest.config.js to add transformIgnorePatterns
//jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
testMatch: ["**/__tests__/**/*.ts?(x)", "**/?(*.)+(test).ts?(x)"],
transform: {
"^.+\\.(js|ts)$": "ts-jest",
},
transformIgnorePatterns: [
"/node_modules/(?![#autofiy/autofiyable|#autofiy/property]).+\\.js$",
"/node_modules/(?![#autofiy/autofiyable|#autofiy/property]).+\\.ts$",
"/node_modules/(?![#autofiy/autofiyable|#autofiy/property]).+\\.tsx$",
],
}
put the packages that you want to ignore inside [] and separate them by |
in my case [#autofiy/autofiyable|#autofiy/property]
I also encountered the same error while setting up Jest in my React app created using Webpack. I had to add #babel/preset-env and it was fixed. I have also written a blog article about the same.
npm i -D #babel/preset-env
And then add this in "presets" in .babelrc file. E.g.
{
"presets": ["#babel/react", "#babel/env"]
}
https://medium.com/#shubhgupta147/how-i-solved-issues-while-setting-up-jest-and-enzyme-in-a-react-app-created-using-webpack-7e321647f080?sk=f3af93732228d60ccb24b47ef48d7062
I added the jest update to my package.json
"jest": {
"transformIgnorePatterns": [
"node_modules/(?!(<package-name>|<second-package-name>)/)"
]
},
Feel free to remove the |<second-package-name> if not required.
You can also do it as part of your script as mentioned #paulosullivan22
"test": "react-scripts test --transformIgnorePatterns 'node_modules/(?!(<package-name>)/)'"
In my case, the issue was that I was importing the original module in the mocked module:
import urlExist from "url-exist";
async function stubbedUrlExist(): Promise<boolean> {
// do something
}
export default stubbedUrlExist;
The solution was to not import url-exist in the url-exist mock. This might have lead to a circular import. Jest was perhaps catching this error in a generic try<>catch block dealing with the loading of modules.
Below works for me.
Create babel.config.js file.
module.exports = {
presets: [
[ '#babel/preset-env', { targets: { esmodules: true } } ],
[ '#babel/preset-react', { runtime: 'automatic' } ],
],
};
I updated some dependencies (react, jest and others), and I also got the error:
Jest encountered an unexpected token - SyntaxError: Cannot use import statement outside a module
I had dev dependencies with needed to be transpiled.
What I did first was start all over:
$ jest --init
A jest.config.js is now generated (before I just had Jest configuration in my package.json).
In the error message under details you can see the reporting module, for me it looked like this:
Details: /<project_root>/node_modules/axios/index.js:1
Adding the following transform ignore in jest.config.js solved my problem:
transformIgnorePatterns: [
"node_modules/(?!axios.*)"
],
The axios module was now nicely transpiled and gave no more problems, hope this helps!
https://jestjs.io/docs/27.x/getting-started
Below works for me
module.exports = {
presets: [
["#babel/preset-env", { targets: { node: "current" } }],
"#babel/preset-typescript", "#babel/react"
]
};
could not get it working with transforms, I ended up mocking the dependency:
Create a file: <path>/react-markdown.js
import React from 'react';
function ReactMarkdown({ children }){
return <>{children}</>;
}
export default ReactMarkdown;
On jest.config.js file add:
module.exports = {
moduleNameMapper: {
'react-markdown': '<path>/mocks/react-markdown.js',
},
};
credits to juanmartinez on https://github.com/remarkjs/react-markdown/issues/635

React Relay (react-relay) with Typescript throwing TypeError: Object prototype may only be an Object or null: undefined

I'm running into an really bizarre TypeError with react-relay when trying to instantiate a class that extends Relay.Mutation. I've created a simple Typescript project with create-react-app my-app --scripts-version=react-scripts-ts to demonstrate the issue.
Whenever I run yarn start, this is what I'm seeing:
This error doesn't really make sense to me:
TypeError: Object prototype may only be an Object or null: undefined
I'm just trying to instantiate a new instance of my own extended Relay.Mutation class. I'm really new to the React Relay world and ES6/Typescript in general so it's likely something silly I'm just missing.
In this simple project I'm using the example class directly as defined in the DefinitelyTyped repository.
Shouldn't I be able to use the class like so:
const atm = new AddTweetMutation({ text: 'asdf', userId: '1123' });
Here is what the AddTweetMutation.tsx class looks like:
import * as Relay from 'react-relay';
interface Props {
text: string;
userId: string;
}
interface State {
}
export default class AddTweetMutation extends Relay.Mutation<Props, State> {
public getMutation() {
return Relay.QL`mutation{addTweet}`;
}
public getFatQuery() {
return Relay.QL`
fragment on AddTweetPayload {
tweetEdge
user
}
`;
}
public getConfigs() {
return [{
type: 'RANGE_ADD',
parentName: 'user',
parentID: this.props.userId,
connectionName: 'tweets',
edgeName: 'tweetEdge',
rangeBehaviors: {
'': 'append',
},
}];
}
public getVariables() {
return this.props;
}
}
Here is the the entire Hello.tsx React component:
import * as React from 'react';
import AddTweetMutation from '../mutations/AddTweetMutation';
export interface Props {
name: string;
enthusiasmLevel?: number;
}
class Hello extends React.Component<Props, {}> {
render() {
const atm = new AddTweetMutation({ text: 'asdf', userId: '1123' });
console.log(atm);
const { name, enthusiasmLevel = 1 } = this.props;
if (enthusiasmLevel <= 0) {
throw new Error('You could be a little more enthusiastic. :D');
}
return (
<div className="hello">
<div className="greeting">
Hello {name + getExclamationMarks(enthusiasmLevel)}
</div>
</div>
);
}
}
export default Hello;
// helpers
function getExclamationMarks(numChars: number) {
return Array(numChars + 1).join('!');
}
This is what my package.json looks like:
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"#types/jest": "^20.0.6",
"#types/node": "^8.0.19",
"#types/react": "^16.0.0",
"#types/react-dom": "^15.5.2",
"#types/react-relay": "^0.9.13",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-relay": "^1.1.0",
"react-scripts-ts": "2.5.0"
},
"devDependencies": {},
"scripts": {
"start": "react-scripts-ts start",
"build": "react-scripts-ts build",
"test": "react-scripts-ts test --env=jsdom",
"eject": "react-scripts-ts eject"
}
}
Here's the project to github
Update: The typings are not currently valid for react-relay > 1.x. Please see the thread on github for this issue. I have also updated my repo with the workaround.
The problem is that react-relay#1.1.0 has changed its API and #types/react-relay#0.9.13 is outdated.
TypeScript statically analyze your code based on the typings (type definitions) available. So even thou #types/react-relay#0.9.13 is outdated, TypeScript doesn't know and just act based on it.
To solve this problem, you can either:
Contribute to #types/react-relay at https://github.com/DefinitelyTyped/DefinitelyTyped to update its typings
File issue on it at https://github.com/DefinitelyTyped/DefinitelyTyped to see if someone can help updating the typings.
Update the typings yourself locally using "module augmentation" (https://www.typescriptlang.org/docs/handbook/declaration-merging.html)
Not using #types/react-relay and do a declare module "react-relay" to mark it as any type (you will lose type safety and IDE support, but if the typings is not correct, it doesn't matter anyway).
For the last option, do this:
// custom-typings/react-relay.d.ts
declare module 'react-relay'
// tsconfig.json
{
"include": [
"custom-typings"
]
}

Categories

Resources