Following simple code:
const { exec, spawn, fork, execFile } = require('child_process')
const startAllJobs = async () => {
const process = fork('app/util/nlp/sentenceHelper.js');
};
sentenceHelper:
import { split } from 'sentence-splitter';
/*....more but unimportant since it breaks at first line*/
Babel setup:
starter.js
// Transpile all code following this line with babel and use 'env' (aka ES6) preset.
require("#babel/register")({
extensions: ['.js', '.ts'],
"presets": [["#babel/preset-env"
], "#babel/preset-typescript"],
"plugins": ["#babel/plugin-transform-runtime"]
})
require("#babel/polyfill");
require('datejs');
// Import the rest of our application.
module.exports = require('./app/index.js');
Error:
import { split } from 'sentence-splitter';
^
SyntaxError: Unexpected token {
How can I use ES6 Syntax within child processes?
Node version: 12.0.0
Related
Given the code snippet, including a simple tsx string of a React component:
// test.ts
import j from "jscodeshift";
const code = `
const words: string[] = ["hello", "world"];
export default function(){
return <div>{words.map(word => <span>{word}</span>)}</div>;
}
`;
const ast = j(code);
console.log(ast.toSource());
When that file is executed with node ts-node test.ts it errors like this:
.../jscodeshift/node_modules/#babel/parser/src/parser/error.js:97
const err: SyntaxError & ErrorContext = new SyntaxError(message);
^
SyntaxError: Const declarations require an initialization value (1:11)
...
How can I use the j options to use a parser that successfully parses the .tsx code?
I expect something like
const ast = j(code, { parser: something, plugins: [somethingElse]});
But I couldn't make it work, so far
Apparently, one possibility is to use babel parser and some plugins
import { parseSync } from "#babel/core";
import j from "jscodeshift";
const ast = j(code, {
parser: {
parse: (source) =>
parseSync(source, {
plugins: [`#babel/plugin-syntax-jsx`, `#babel/plugin-proposal-class-properties`],
overrides: [
{
test: [`**/*.ts`, `**/*.tsx`],
plugins: [[`#babel/plugin-syntax-typescript`, { isTSX: true }]],
},
],
filename: "source-file.tsx", // this defines the loader depending on the extension
parserOpts: {
tokens: true, // recast uses this
},
}),
});
This code was mainly copied from egghead.io article https://egghead.io/blog/codemods-with-babel-plugins
I have a react app where I wanted to import a javascript file from a third-party library but file is mark with shebang #!/usr/bin/env node.
I found (e.g. here How to Configure Webpack with Shebang Loader to Ignore Hashbang Importing Cesium React Component into Typescript React Component) I can load file by overriding webpack configuration and adding a new loader shebang-loader (I also have tried shebang-loader2) but overriding webpack in react app is recommended only with #craco/craco so I added it to package.json and tried add loader to existing webpack-config.js.
I produced this lines of code. File craco.config.js:
const throwError = (message) =>
throwUnexpectedConfigError({
packageName: 'craco',
githubRepo: 'gsoft-inc/craco',
message,
githubIssueQuery: 'webpack',
});
module.exports = {
webpack: {
configure: (webpackConfig, {paths}) => {
const shebangLoader = { test: /node_modules\/npm-groovy-lint\/lib\/groovy-lint.js$/, loader: "shebang-loader" }
const {isAdded: shebangLoaderIsAdded1} = addAfterLoader(webpackConfig, loaderByName('url-loader'), shebangLoader);
if (!shebangLoaderIsAdded1) throwError('failed to add shebang-loader');
return webpackConfig;
},
},
};
It resolves problem with shebang and it ignores #!/usr/bin/env node but now I still get error
Module parse failed: Unexpected token (14:16)
File was processed with these loaders:
* ./node_modules/shebang2-loader/index.js
You may need an additional loader to handle the result of these loaders.
| const { getSourceLines, isErrorInLogLevelScope } = require("./utils");
| class NpmGroovyLint {
> "use strict";
| options = {}; // NpmGroovyLint options
| args = []; // Command line arguments
It looks like it does not recognise "use strict" line.
Can anyone put some suggestions what should be a problem ?
After few hours of investigation, I have finally come to a resolution. Firstly I have to say that there is no option to use NpmGroovyLint in react-like applications that run in browsers because after I resolved mentioned problem up here I figured that NpmGroovyLint uses node libraries as perf_hooks which are not available in a browser enviroment.
But I can post code that resolves the problem described in my question. It was needed to add a plugin to babel-loader named 'plugin-proposal-class-properties'. Here is my snipped of craco config. You can use it as a recipe occasionally.
const {addAfterLoader, getLoaders, loaderByName, removeLoaders, throwUnexpectedConfigError} = require('#craco/craco');
const throwError = (message) =>
throwUnexpectedConfigError({
packageName: 'craco',
githubRepo: 'gsoft-inc/craco',
message,
githubIssueQuery: 'webpack',
});
module.exports = {
webpack: {
configure: (webpackConfig, {paths}) => {
const {hasFoundAny, matches} = getLoaders(webpackConfig, loaderByName('babel-loader'));
if (!hasFoundAny) throwError('failed to find babel-loader');
const {hasRemovedAny, removedCount} = removeLoaders(webpackConfig, loaderByName('babel-loader'));
if (!hasRemovedAny) throwError('no babel-loader to remove');
if (removedCount !== 2) throwError('had expected to remove 2 babel loader instances');
//add plugin proposal class properties to existing babel loader
const propClassOptions = {...matches[1].loader.options, ...{plugins: ["#babel/plugin-proposal-class-properties"]}};
const propClassLoader = {...matches[1].loader, ...{options: propClassOptions}};
const babelLoaderWithPropClassPlugin = {...matches[1], ...{loader: propClassLoader}};
const shebangLoader = {
test: /node_modules\/npm-groovy-lint\/lib\/groovy-lint.js$/,
use: [{loader: 'shebang2-loader'}, {...{loader: require.resolve('babel-loader')}, ...{options: propClassOptions}}]
}
const {isAdded: babelLoaderWithPropClassIsAdded} = addAfterLoader(webpackConfig, loaderByName('url-loader'), matches[0].loader);
if (!babelLoaderWithPropClassIsAdded) throwError('failed to add ts-loader');
const {isAdded: babelLoaderIsAdded} = addAfterLoader(webpackConfig, loaderByName('babel-loader'), babelLoaderWithPropClassPlugin.loader);
if (!babelLoaderIsAdded) throwError('failed to add back babel-loader for non-application JS');
const {isAdded: shebangLoaderIsAdded1} = addAfterLoader(webpackConfig, loaderByName('url-loader'), shebangLoader);
if (!shebangLoaderIsAdded1) throwError('failed to add shebang-loader');
return webpackConfig;
},
},
};
I have a working rollup.config.js file but need to run a separate packaging script after Rollup is done. My plan was to use Rollup's watchers via their JS API. However, I cannot get the JS API to work at all.
I am referencing this code from the Rollup site...
const loadConfigFile = require('rollup/dist/loadConfigFile');
const path = require('path');
const rollup = require('rollup');
loadConfigFile(path.resolve(__dirname, 'rollup.config.js'))
.then(async ({options, warnings}) => {
warnings.flush();
const bundle = await rollup.rollup(options);
await Promise.all(options.output.map(bundle.write));
rollup.watch(options);
})
but I keep getting an error Unknown input options: 0.......Error: You must supply options.input to rollup
My rollup.config.js is as follow...
import svelte from 'rollup-plugin-svelte';
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from "rollup-plugin-terser";
import replace from '#rollup/plugin-replace';
import json from '#rollup/plugin-json';
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/bundle.js'
},
plugins: [
json(),
production && replace({
'eruda': ``,
exclude: 'node_modules/**',
delimiters: ['import * as eruda from \'', '\'']
}),
production && replace({
'eruda': ``,
exclude: 'node_modules/**',
delimiters: ['', '.init()']
}),
svelte({
dev: !production,
css: css => {
css.write('public/bundle.css');
}
}),
resolve({ browser: true }),
commonjs(),
!production && livereload('public'),
production && terser()
],
watch: {
clearScreen: false
}
};
Any thoughts are appreciated!
I think the example at rollupjs.org is wrong. Shouldn't it be like this instead?
const loadConfigFile = require('rollup/dist/loadConfigFile')
const path = require('path')
const rollup = require('rollup')
// load the config file next to the current script;
// the provided config object has the same effect as passing "--format es"
// on the command line and will override the format of all outputs
loadConfigFile(path.resolve(__dirname, 'rollup.config.js'), {format: 'es'})
.then(({options, warnings}) => {
// "warnings" wraps the default `onwarn` handler passed by the CLI.
// This prints all warnings up to this point:
console.log(`We currently have ${warnings.count} warnings`)
// This prints all deferred warnings
warnings.flush()
// options is an "inputOptions" object with an additional "output"
// property that contains an array of "outputOptions".
// The following will generate all outputs and write them to disk the same
// way the CLI does it:
options.map(async options => {
const bundle = await rollup.rollup(options)
await Promise.all(options.output.map(bundle.write))
// You can also pass this directly to "rollup.watch"
rollup.watch(options)
})
})
Figured it out, apparently the options returned from loadConfigFile is an array so I had to do options[0] inside the async function
I'm using webpack and babel to transpile my ES6 javascript and React project to a bundle.js.
I'm getting this error:
bundle.js:90058: ERROR - Parse error. Semi-colon expected:
return async function (dispatch) {
Why is the "async" keyword still in the final transpiled bundle.js?
Here is my babel.config.js:
module.exports = {
presets: [
[
"#babel/preset-env",
{
useBuiltIns: "entry",
corejs: 3,
}
],
"#babel/preset-react"
],
plugins: [
"#babel/plugin-transform-runtime",
"#babel/plugin-proposal-class-properties",
"#babel/plugin-transform-async-to-generator",
"react-hot-loader/babel",
]
};
In my root index.jsx file I have these two imports:
import 'core-js/stable';
import 'regenerator-runtime/runtime';
The actual code in question is the following:
export const getUser = () => async (dispatch) => { ... }
...which gets transpiled to this:
var getUser = function getUser() {
return async function (dispatch) {
...
}
}
Is there some other configuration needed to convert those async/await keywords?
How can I mock an ES6 module import using Jest?
For example we have the following structure:
// ../store.js
function getData(data) {
return data / 3;
}
export { getData };
// ../myModule.js
import { getData } from './store';
function myModule(param) {
return getData(param) * 4;
}
export { myModule };
// ./myModule.test.js
import { myModule ] from '../myModule';
test('2 x 4 equal 8', () => {
expect(getData(6)).toBe(8);
});
To mock ES2015 modules, your jest config needs to use babel to convert the modules first.
You'll want to yarn add --dev babel-jest babel-preset-env
and then your package.json should look something like this:
"jest": {
"moduleFileExtensions": [
"js",
"jsx"
],
"moduleDirectories": [
"node_modules"
],
"transform": {
"^.+\\.(js|jsx|mjs)$": "<rootDir>/node_modules/babel-jest"
},
"transformIgnorePatterns": [
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$",
"^.+\\.module\\.css$"
]
}
Secondly, in your .babelrc you need to specify your environment for test like so:
{
"presets": [
["env", "react"]
],
"env": {
"development": {
"presets": [["env"], "react"]
},
"production": {
"presets": [["env"], "react"]
},
"test": {
"presets": [["env"], "react"]
}
}
}
Once that's done, you can mock a module. For example, make a file called __mocks__/store.js (where the mocks folder is in the same level as your store.js file. Inside of your mocks file, you can do something like
const getData = () => return 42;
export { getData };
and in your myModule.test.js you need this line:
jest.mock('./store');
If you want, you can see a working example from one of my repositories here:
https://github.com/AnilRedshift/linkedINonymous/
If you want make automated test with jest, you have to include before the test/describe the next call
jest.mock('../myModule');
It returns void result from all functions.
Other alternative is mock mixed:
const mock: any = jest.genMockFromModule('../myModule');
mock.getData = jest.fn().mockImplementation(6);
The call to method getData returns 6.