Transpile Model View Controller in Javascript - javascript

I want to use Gulp, Rollup and Babel to transpile ES6 app to ES5 (that use the module reveal pattern with IIFE).
The gulp file:
var gulp = require('gulp');
var rollup = require('gulp-better-rollup');
var babel = require('rollup-plugin-babel');
gulp.task('roll', function () {
return gulp.src('_01_src/js/form/*.js')
.pipe(rollup(
{plugins: [babel({presets: ['es2015-rollup']})]},
{format: 'iife',}
)
)
.pipe(gulp.dest('_02_build/js/form/'));
});
The controller import model and view and is transpiled ok:
var controller = (function (model) {
'use strict';
model = 'default' in model ? model['default'] : model;
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var Cat = function Cat(name) {
classCallCheck(this, Cat);
this.name = name;
};
return Cat;
}(model));
The problem that I have is when I want to group together (to avoid collision) like this is not working:
( function() { var model = function () { ... }()
var view = function () { ... }()
var controller = function (model, view) {
......
}(model, view) )}()
I have multiple app that contains MVC and I want first to group and app together than group all app;
So I start:
js
app1
- model.js
- view.js
- controller.js
app2
- model.js
- view.js
- controller.js
app3
- model.js
- view.js
- controller.js
After task run I want to have, which don't collide:
js
app1.js
app2.js
app3.js

I have partial working example from the rollup-stream in github team/users, but only works for an app(and not exactly transpiled as MVC), not with multiple apps.
const gulp = require('gulp');
const scss = require('gulp-sass');
const babel = require('gulp-babel');
const watch = require('gulp-watch');
const autopre = require('gulp-autoprefixer');
const uglify = require('gulp-uglify');
const rollup = require('rollup-stream');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
gulp.task('rollup', function () {
return rollup({
entry: '_01_src/js/form/app.js',
format: 'iife',
})
// turn the raw text stream into a stream containing one streaming Vinyl file.
.pipe(source('form.js'))
// buffer that file's contents. most gulp plugins don't support streaming files.
.pipe(buffer())
// transform the files.
.pipe(babel({
presets: ['es2015']
}))
// and output to _02_build/js/form.js as normal.
.pipe(gulp.dest('_02_build/js'));
});

would this help? I think create tasks for each app, you mentioned before group together it transpile OK
const path = require('path')
const fs = require('fs-extra')
const gulp = require('gulp')
const rollup = require('gulp-better-rollup')
const babel = require('rollup-plugin-babel');
// suppose your project looks like
// --project
// | +-gulpfile.js
// | +-src
// | | +-app1
// | | | +-controller.js
// | | | +-model.js
// | | | +-view.js
// | | +-app2
// the target path where your apps locates,
var targetPath = path.join(__dirname, 'src')
// files will build into
var destTargetPath = path.join(__dirname, 'dest')
// find app1,app2.... and exclude node_modules
var dirs = fs.readdirSync(targetPath).filter((filename) => {
if (filename === 'node_modules') return false
var stat = fs.statSync(path.join(targetPath, filename))
return stat.isDirectory()
})
// I want a task name for each app
var dir2task = dir => 'x_' + dir
// add tasks for each app
dirs.forEach((dir) => {
// as it worked for single app
gulp.task(dir2task(dir), () => {
//this return means tells gulp when job is done
return gulp.src(path.join(targetPath, dir) + '/**/*.js')
.pipe(rollup({
plugins: [babel({
presets: ['es2015-rollup']
})]
}, {
format: 'iife',
}))
.pipe(gulp.dest(path.join(destTargetPath, dir)))
})
})
// run them all and after all apps built,and copy or rename your built controller to appx.js, there's no need for return, my mistake
gulp.task('default', dirs.map(dir2task), () => {
dirs.forEach((dir) => {
fs.copySync(path.join(destTargetPath, dir, 'controller.js'), path.join(destTargetPath, dir + '.js'))
})
})
// result will be
// --project
// | +-gulpfile.js
// | +-src
// | | +-app1
// | | +-....
// | +-dist
// | | +-app1.js
// | | +-app2.js

You can use static variable.
Here's how to make model, view, and controller as static variable.
function a_project () {
}
a_project.model = function(){};
a_project.view = function(){};
a_project.controller = function(){};
var myInstance = new MyClass();
This will help you to call model, view and controller variable.

Related

Mocking process methods in Jest

I have electron-util.js file I want to cover with tests:
const isElectron = "electron" in process.versions;
const isUsingAsar =
isElectron &&
process.mainModule &&
process.mainModule.filename.includes("app.asar");
export const fixPathForAsarUnpack = path =>
isUsingAsar ? path.replace("app.asar", "app.asar.unpacked") : path;
In order to test fixPathForAsarUnpack method I need to mock versions and mainModule from process. I tried to do it like this:
import { fixPathForAsarUnpack } from "../src/electron-util";
test("fixes path for Electron", () => {
process.versions = {
electron: "0.0.0",
mainModule: {
filename: "/app.asar/index.html"
}
};
const path =
"/Users/relix/My.app/Contents/Resources/app.asar/node_modules/foo/binary";
expect(fixPathForAsarUnpack(path)).toBe(
"/Users/relix/My.app/Contents/Resources/app.asar.unpack/node_modules/foo/binary"
);
});
But it throws an error:
● fixes path for Electron
TypeError: Cannot assign to read only property 'versions' of object '[object process]'
4 |
5 | test("fixes path for Electron", () => {
> 6 | process.versions = {
| ^
7 | electron: "0.0.0",
8 | mainModule: {
9 | filename:
at Object.<anonymous>.test (__test__/electron-util.test.js:6:3)
What am I doing wrong, how should I mock process object?
You should mock the process in this way:
const originalProcess = process
global.process = {...originalProcess, version: "your code here"}
// do the test
// ...
// restore the original process object for next tests
global.process = originalProcess

Nodejs - No webpack bundle

I want to "bundle" some files into a single js file, but I don't want the webpack wrapper.
Let's say I have 3 files :
// file1.js
export default { hello: "hello" };
// file2.js
export default { world: "world" };
// index.js
import file1 from "./file1";
import file2 from "./file2";
(() => ({ ...file1, ...file2 }))()
I want the following result :
// build/output.js (+ babel...)
(function(){
return Object.assign({}, { hello: "hello" }, { world: "world" });
})()
Not a single line of code apart from the above build output.
Is it possible with webpack? Thanks!
O.P. Solution
Ok, so I found a solution!
It's maybe not the best one, but it works.
I found this library here which concatenates files together.
Building
I can build using : npm run build.
And the code that concatenates the files is :
// ======================================================
// Tools / Bundle
// ======================================================
// Libs
var path = require("path");
var bundle = require("bundle-js");
module.exports.exec = function() {
// Disable logging (hack for 'bundle-js' library).
var _log = console.log;
console.log = function() {};
// Concatenate each file (required by the application).
var file = path.resolve(__dirname, "../src/index.js");
var bundledCode = bundle({
entry: file,
print: false,
disablebeautify: true
});
// Enable logging.
console.log = _log;
// Return bundled code.
return bundledCode;
};
For some reasons, bundle-js always outputs something even with the option { print: false }. So I added a small hack to fix this.

node.js unit testing mock dependency

I have a question on using proxyquire (or any other suggestions on how to test the following code)
If i have the following file to test:
var path = require('path');
module.exports = function (conf) {
var exported = {};
exported.getIssue = function (issueId, done) {
...
...
};
return exported;
};
How do i pass in the 'conf' variable while using proxyquire to mock 'path; var?
Is there any other way to do this if not using proxyquire?
You simply have to pass conf variable to the module/function required via proxyquire. Proxyquire has meaning to to do the same CommonJs require stuff, but with the possibility of mocking and stubing some modules. So you should act the same.
var pathMock = {
someMethod = function() {}
};
var confMock = {
someMethod = function() {}
};
spyOn(pathMock, 'someMethod').and.callThrough();
spyOn(confMock, 'someMethod').and.callThrough();
module = proxyquire('../path/to/module', {
path: pathMock
});
it('do some test', function(done) {
module(conf).getIssue();
expect(pathMock.someMethod).toHaveBeenCalled;
expect(confMock.someMethod).toHaveBeenCalled;
});

Why I lost my variable after browserify

I have "react actions" file. And something going wrong.
'use strict';
var AppDispatcher = require('../dispatcher/AppDispatcher');
var constants = require('../constants/constants');
var URIjs = require('URIjs');
function loadPageData(url) {
//ajax call
}
var InputsRowActions = {
//some methods, like this
changePage: function(page) {
//work with url params..
loadPageData(url);
}
console.log(URIjs) //-> undefined
};
module.exports = InputsRowActions;
I can't understand, why URIjs didn't defined ?
My Gulp browserify task:
var b = browserify('./app/assets/react/app.react.js', {
debug: true
});
b = watchify(b);
b.transform('reactify');
b.on('update', bundle);
function bundle(fileName) {
return b
.bundle()
.pipe(source('app.react.js'))
.pipe(buffer())
.pipe(gulp.dest('app/assets/javascripts/'));
}
gulp.task('browserify', bundle);
I have same problem, with requiring 'lodash'.

How to Call Method of ModelB.js from within ModelA.js?

I am working with loopback 2.0.
I generated my models with the yeoman generator and added a js file for each model to extend its behavior.
How can I call a method from ModelA within ModelB?
EXAMPLE
Folder structure:
/common
/models
Car.json
Car.js
Engine.json
Engine.js
...
Car.js:
module.exports = function(Car) {
Car.drive = function(destination, fn) { ... }
...
};
Engine.js:
module.exports = function(Engine) {
Engine.doSomething = function(something, fn) {
// *** Here is where I want to invoke a method from the Car.js
var loopback = require('loopback');
var Car = loopback.models.Car;
Car.drive('49.1234,12.1234', fn);
// ***
}
...
};
The model class such as Engine will have a property app to provide access to other models, for example:
module.exports = function(Engine) {
Engine.doSomething = function(something, fn) {
// *** Here is where I want to invoke a method from the Car.js
var Car = Engine.app.models.Car;
Car.drive('49.1234,12.1234', fn);
// ***
}
...
};

Categories

Resources