babelify 6 with browserify and the es2015 preset is not working - browserify

I am attempting to use the new babel release, and while trying to use the es2015 preset babel doesn't seem to be able to understand arrow functions?
My setup on pre-babel6 was as follows:
transform: [['babelify', {sourceMap: false, stage: 0, optional: 'runtime', ignore: ["*.min.js"]}]]
and with babel6
transform: [['babelify', {"presets": ["es2015"]}]]
which does not work. Why is this?
edit
adding "stage-0" got rid of the syntax error messages, but has stoped me from being able to extend anything with the error: 'this' is not allowed before super() when I have infact got a super() call.
edit
Set up a simple test application with some es7 and tried to use the babel-core require hook, same problem.
edit
Ok so I have narrowed it down to stage-0 working differently in babeljs 6^.
Here is what I have noticed:
Run file
require("babel-core/register")(
{
presets: ["es2015", "stage-0"]
}
);
require("./app.js");
Works with:
class extendable {
constructor() {
console.log('extended')
}
}
class app extends extendable {
constructor() {
super();
this.method();
this.method2();
}
method() {
// arrow functions
setTimeout(() => {
console.log("works")
}, 1000)
}
/**
* arrow function method
*/
method2 = () => {
console.log('works')
}
}
new app();
Doesn't work with:
class extendable {
constructor() {
console.log('extended')
}
}
class app extends extendable {
constructor() {
super();
this.method();
this.method2();
}
method() {
// arrow functions
setTimeout(() => {
console.log("works")
}, 1000)
}
/**
* arrow function method
*/
method2 = () => {
// give an error: 'this' is not allowed before super()
this.state = "hello";
}
}
new app();
So I am a little confused. Is this really incorrect syntax? How have I been able to use this pre-babel6?

This is a Babeljs bug
See
Subclasses with class properties (without constructor) error #2942
[Regression BUG] Class scoped function showing SyntaxError: 'this' is not allowed before super() #2971
Hopefully this will see a fast fix.
edit #2942 is not referencing the same bug. Here is an issue following this bug: #3028

It depends a bit on how you are executing browserify, this is what the Github repository from babelify (https://github.com/babel/babelify) says about it :
From the CLI:
$ browserify script.js -o bundle.js \
-t [ babelify --presets [ es2015 react ] ]
With Node:
browserify("./script.js")
.transform("babelify", {presets: ["es2015", "react"]})
.bundle()
.pipe(fs.createWriteStream("bundle.js"));

Related

How to test dynamic modules in Nest.js?

My implementation is based on this article: https://dev.to/nestjs/advanced-nestjs-how-to-build-completely-dynamic-nestjs-modules-1370
I want to test my generic, Twilio-based SMS sender service that I share between multiple parts of my application. I want to configure it when I'm importing it from somewhere else, so I'm writing it as a dynamic module. On top of that, the options that I pass to the dynamic module are themselves constructed dynamically, they are read from my .env file. I'm using the factory pattern when I'm registering my provider:
// app.module.ts
#Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: [
'.env',
],
validationSchema,
}),
SharedSmsModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService<EnvironmentVariables>) => {
return {
accountSid: configService.get('TWILIO_ACCOUNT_SID'),
authToken: configService.get('TWILIO_AUTH_TOKEN'),
smsSenderPhoneNumber: configService.get(
'TWILIO_SMS_SENDER_PHONE_NUMBER'
),
};
},
}),
],
})
export class AppModule {}
My shared-sms module calls the function provided in the registerAsync method in app.module.ts:
// shared-sms.module.ts
export interface SharedSmsModuleOptions {
accountSid: string;
authToken: string;
smsSenderPhoneNumber: string;
}
export interface SharedSmsModuleAsyncOptions extends ModuleMetadata {
imports: any[];
inject: any[];
useFactory?: (
...args: any[]
) => Promise<SharedSmsModuleOptions> | SharedSmsModuleOptions;
}
#Module({})
export class SharedSmsModule {
static registerAsync(
sharedSmsModuleAsyncOptions: SharedSmsModuleAsyncOptions
): DynamicModule {
return {
global: true,
module: SharedSmsModule,
imports: sharedSmsModuleAsyncOptions.imports,
providers: [
{
provide: 'SHARED_SMS_OPTIONS',
useFactory: sharedSmsModuleAsyncOptions.useFactory,
inject: sharedSmsModuleAsyncOptions.inject || [],
},
SharedSmsService,
],
exports: [SharedSmsService],
};
}
}
Now I have access to the options variables in my shared-sms.service:
// shared-sms.service
#Injectable()
export class SharedSmsService {
private twilioClient: Twilio;
constructor(
#Inject('SHARED_SMS_OPTIONS') private options: SharedSmsModuleOptions
) {
this.twilioClient = new Twilio(
this.options.accountSid,
this.options.authToken
);
}
async sendSms(sendSmsDto: SendSmsDto): Promise<MessageInstance> {
await validateOrReject(plainToInstance(SendSmsDto, sendSmsDto));
const smsData = {
from: this.options.smsSenderPhoneNumber,
to: sendSmsDto.to,
body: sendSmsDto.body,
};
return await this.twilioClient.messages.create(smsData);
}
}
So long everything seems to be working. But I'm having issues when I'm trying to test the service's sendSms function. I can write tests that work when I'm providing hardcoded Twilio test account values in my test file. But I don't want to commit them to the repository, so I would want to get them from my .env file. I have tried providing everything to the Test.createTestingModule function when I'm creating my moduleRef, based on what I did in the code that I already wrote, but I couldn't specify the Twilio test account values dynamically. As I don't see documentation regarding this issue, I feel like that I'm either missing a conceptual point (providing so many things in the test seems like an overkill) or there is a trivial work-around. Please help me figure out how to pass those values to my tests from my .env file

Jest + Vue vm properties and methods unresolved in IntelliJ

My Vue Component:
data() {
return {
test: false,
}
},
methods: {
setTestToTrue() {
this.test = true
},
My JestJs test
Is there any way to get rid of the warnings?
This would require adding special support for wrapper.vm, as the methods are added dynamically in runtime and thus can't be resolved statically
Please vote for WEB-51228 to be notified on any progress with it

Mobx how to compute values in state

I'm new to Mobx and I can't work out how to compute a value in my store.
I'm following the docs description of using the 'computed' modifier.
Here's my (cut down) appState:
export default class AppState {
constructor() {
/* MOBX STATE */
extendObservable(this, {
// Links
'links': [],
'updateLinks': action((newlinks) => {
this.links = newlinks;
}),
'linksWithComments': computed(() => this.links),
});
}
}
'links' works fine in my React components, but when I add 'linksWithComments' I see this error:
Uncaught Error: [MobX] 'keys()' can only be used on observable objects, arrays, sets and maps
What am I doing wrong? 'links' is an array, and as far as I can tell it's observable, so what does the error mean? I've googled for the error message but haven't found anything that explains what's going on.
I've tried this form also:
get linksWithComments () { return 2*3; },
In this case 'linksWithComments' is undefined.
Versions:
"mobx": "^6.1.8",
"mobx-react": "^7.1.0",
"mobx-react-lite": "^3.2.0",
Thank you!
Preferred way to use MobX#6 with classes is to use makeAutoObservable or makeObservable:
class AppState {
links = [];
constructor() {
makeAutoObservable(this);
}
updateLinks = (newLinks) => {
this.links = newLinks;
};
get linksWithComments() {
return this.links.filter((link) => link > 0.5);
}
}
Have you tried it?
I've made Codesanbox example for you to explore!
More info in the official docs

Vetur error when using multiple queries in same .gql file

I am using Vue typeScript with GraphQL. Whenever I try to use a query using deconstructor I get an error from Vetur. I am able to use GetPostData query in the Vue Component and its working fine.
Trying to use this - https://github.com/apollographql/graphql-tag#support-for-multiple-operations
Vue File
import { GetPostData } from "../../util/queries/getPageData.gql";
getPageData.gql
query GetPostData {
continents {
code
}
}
query GetCountries($code: String!) {
country(code: $code) {
code
}
}
Vue.config.js
const antdTheme = require("./src/theme.js");
module.exports = {
publicPath: "/",
pwa: {
iconPaths: {
favicon32: "./favicon.png",
favicon16: "./favicon.png",
appleTouchIcon: "./favicon.png",
maskIcon: "./favicon.png",
msTileImage: "./favicon.png"
}
},
css: {
loaderOptions: {
less: {
modifyVars: antdTheme,
javascriptEnabled: true
}
}
},
chainWebpack: config => {
// GraphQL Loader
config.module
.rule("graphql")
.test(/\.(graphql|gql)$/)
.use("graphql-tag/loader")
.loader("graphql-tag/loader")
.end();
}
};
I think it states that's what you can do but I don't think you really can.
It's better to put all your queries in a javascript file and import 'graphql-tag' to store queries instead of using a .gql file.
Just tested and Vetur didn't complain, could have been a bug that is already fixed.
According to graphql-tag package this case is supported (docs), so if Vetur complains must be an issue with the extension itself.

Angular 2 - Use ComponentResolver to load component downloaded at runtime

I'm trying to load a component dynamically in my Angular2 app.
By dynamically I don't just mean to insert into the DOM a component that is missing from the parent component's template; I mean to download from the server another component, because the User might not ever need it, and then insert it into the DOM.
So I followed this to understand how to load the component with Systemjs and now I see that, in RC4, we need to use this and ComponentResolver to inject things into the DOM.
So here is my code for the module-wrapper component that should put things together:
export class ModuleWrapperComponent implements OnInit {
#ViewChild("module", { read: ViewContainerRef }) target: ViewContainerRef;
#Input() isOpen: boolean;
#Input() moduleId: number;
type: string = null;
moduleRef: ComponentRef<any> = null;
private isViewInitialized: boolean = false;
constructor(private resolver: ComponentResolver) { }
private _loadModule(moduleId: number): Promise<string> {
if (!!this.type)
return Promise.resolve(this.type);
var mod = {
component: "DashboardComponent",
path: "/app/modules/dashboard.component"
};
return System
.import(mod.path)
.then(() => this.type = mod.component);
}
updateComponent() {
if (!this.isViewInitialized)
return;
if (!!this.moduleRef)
this.moduleRef.destroy();
if (this.isOpen) {
this._loadModule(this.moduleId)
.then(type => {
this.resolver.resolveComponent(type)
.then(factory => {
this.moduleRef = this.target.createComponent(factory)
// to access the created instance use
// this.compRef.instance.someProperty = 'someValue';
// this.compRef.instance.someOutput.subscribe(val => doSomething());
});
})
}
}
ngOnChanges() {
this.updateComponent();
}
ngAfterViewInit() {
this.isViewInitialized = true;
this.updateComponent();
}
ngOnDestroy() {
if (!!this.moduleRef)
this.moduleRef.destroy();
}
}
Sadly, I get this error from ComponentResolver:
Error: Cannot resolve component using 'DashboardComponent'. at new BaseException$1 (http://localhost:63815/lib/#angular/compiler//bundles/compiler.umd.js:971:27)
I reckon that loading the module in Systemjs is not enough...so how do I tell ComponentResolver that I've downloaded a new component? The official documentation is still young and lacking...
On a side note, say that my Dashboard component loads additional stuff with imports...Systemjs will handle all that automatically, won't it?
Thanks in advance!
This does not exactly answer your question.
BUT,
We had a similar requirement and were loading components dynamically using SystemJs.
It was all working fine until we started thinking about build and deployment strategies and came across Webpack
Since the value of moduleId is only known at runtime, so webpack will not be able to resolve the actual module components at compile time and will not bundle those files.
You will need to have static imports for your dynamic module components somewhere in your code if you want them to be bundled as part of your single app.js