I am using node v6.8.0, TypeScript v2.0.3, gulp v3.9.1, and gulp-typescript v3.0.2. When I build with gulp I get an error.
Here is my code
/// <reference path="../_all.d.ts" />
'use strict';
import * as Pool from '~mysql/lib/Pool';
import * as mysql from 'mysql';
import * as conf from '../config/config';
class DbConnection {
public pool: Pool;
public static bootstrap(): DbConnection {
return new DbConnection();
}
constructor() {
const setting: conf.Setting = (new conf.Config()).config();
this.pool = mysql.createPool({
connectionLimit: 10,
host: setting.infiniDbHost,
user: setting.infiniDbUser,
password: setting.infiniDbPassword,
debug: false
});
}
}
const dbConnection: DbConnection = DbConnection.bootstrap();
export default dbConnection.pool;
Here is the error that I get:
[11:21:07] Using gulpfile ~/Repos/git/WdAnalytics/gulpfile.js
[11:21:07] Starting 'clean'...
[11:21:07] Finished 'clean' after 21 ms
[11:21:07] Starting 'default'...
src/data/infiniDbConnection.ts(28,16): error TS2503: Cannot find namespace 'dbConnection'.
[11:21:08] TypeScript: 1 semantic error
[11:21:08] TypeScript: 2 emit errors
[11:21:08] TypeScript: emit failed
[11:21:08] Finished 'default' after 1.38 s
Here is my gulpfile.js
var gulp = require('gulp');
var ts = require('gulp-typescript');
var clean = require('gulp-clean');
var src = ['src/**/*.ts', '!src/_all.d.ts'];
gulp.task('default', ['clean'], function() {
return gulp.src(src)
.pipe(ts({
noImplicitAny: true,
noEmitOnError: true
}))
.pipe(gulp.dest('dist/.'))
;
});
gulp.task('clean', function() {
return gulp.src('dist/.', {read: false})
.pipe(clean())
;
});
I can't figure out why it thinks dbConnection is a namespace when it is clearly an object.
I changed noEmitOnError: true to noEmitOnError: false and it still tells me there is a semantic error but it builds and runs just fine.
Related
after converting a simple react module to es6 class; i got some gulp parsing errors.
var React = require('react');
// import React from 'react';
class UdpComp extends React.Component {
constructor (props){
super(props);
this.state = { udpinput: props.udpinput };
},
render: function() {
return(
<div className="udpText">
<h2>UDP-INPUT: {this.state.udpinput}</h2>
</div>
) // return
} // render
})// UdpComp
export default UdpComp;
ok, my gulpfile.babel.js looks like this:
var gulp = require('gulp'),
browserify = require('gulp-browserify'),
concatCss = require('gulp-concat-css'),
sass = require('gulp-sass'),
run = require('gulp-run');
var src = './process',
app = './app';
var sassOptions = {
errLogToConsole: true,
outputStyle: 'expanded'
}; // https://www.sitepoint.com/simple-gulpy-workflow-sass/
gulp.task('js', function() {
return gulp.src( src + '/js/apprender.js' )
.pipe(browserify({
transform: 'reactify',
extensions: 'browserify-css',
debug: true
}))
.on('error', function (err) {
console.error('Error!', err.message);
})
.pipe(gulp.dest(app + '/js'));
});
gulp.task('html', function() {
gulp.src( src + '/**/*.html');
});
gulp.task('css', function() {
gulp.src( src + '/css/*.css')
.pipe(sass(sassOptions).on('error', sass.logError))
.pipe(concatCss('app.css'))
.pipe(gulp.dest(app + '/css'));
});
gulp.task('fonts', function() {
gulp.src('node_modules/bootstrap/dist/fonts/**/*')
.pipe(gulp.dest(app + '/fonts'));
});
gulp.task('watch', ['serve'], function() {
gulp.watch( src + '/js/**/*', ['js']);
gulp.watch( src + '/css/**/*.css', ['css']);
gulp.watch([ app + '/**/*.html'], ['html']);
});
gulp.task('serve', ['html', 'js', 'css'], function() {
run('electron app/main.js').exec();
});
gulp.task('default', ['watch', 'fonts', 'serve']);
when calling gulp I get
\process\js\UdpCompReact.js: Parse Error: Line 14: Unexpected
identifier error
why, how can I parse es6 code?
Can't see what's on line 14 but I'd guess it's the comma right after your constructor. As opposed to ES5 "classes", ES6 classes don't require (and don't allow) commas between methods. Just remove it and it should work (or at least get past line 14)
You need a transpiler that converts it to ES5, afterwards pipe it in the gulp task. I use babel and there is a gulp-babel npm package
I changed my code to this, when using the older version the transpiling works.
import React from 'react' throws an error.
// var React = require('react');
import React from 'react';
class UdpComp extends React.Component {
constructor (props){
super(props);
this.state = { udpinput: this.props.udpinput };
}
render () {
return(
<div className="udpText">
<h2>UDP-INPUT: {this.state.udpinput}</h2>
</div>
) // return
} // render
}; // UdpComp
module.exports = UdpComp;
// export default UdpComp;
I am facing a problem when uploading and updating files on an FTP server using vinyl-ftp in gulp.
My gulpfile.js code is:
var gutil = require('gulp-util');
var ftp = require('vinyl-ftp');
gulp.task( 'deploy-dev', function () {
var conn = ftp.create( {
host: 'my_server_host_name',
user: 'my_server_username',
password: 'my_server_password',
parallel: 5,
log: gutil.log
} );
var globs = [
'assets/**',
'!node_modules/**',
'!assets/img/**',
'!assets/bower_componets/**',
'!assets/dist/**'
];
// using base = '.' will transfer everything to /public_html correctly
// turn off buffering in gulp.src for best performance
return gulp.src( globs, { base: 'assets/', buffer: false } )
.pipe( conn.newer( '/public_html/demos/P-09-Sakha/html' ) ) // only upload newer files
.pipe( conn.dest( '/public_html/demos/P-09-Sakha/html' ) );
} );
// Default Task
gulp.task('default', [ 'scripts','css','watch', 'deploy-dev']);
And in my terminal I see the following error:
[16:58:12] Using gulpfile E:\xamp\htdocs\projects\P-09-sakha\html\gulpfile.js
[16:58:12] Starting 'scripts'...
[16:58:12] Starting 'css'...
[16:58:12] Starting 'watch'...
[16:58:12] Finished 'watch' after 74 ms
[16:58:12] Starting 'deploy-dev'...
[16:58:12] CONN
[16:58:12] CONN
[16:58:14] ERROR Error: Sorry, cleartext sessions are not accepted on this serve
r.
at makeError (E:\xamp\htdocs\projects\P-09-sakha\html\node_modules\vinyl-ftp
\node_modules\ftp\lib\connection.js:1067:13)
at Parser.<anonymous> (E:\xamp\htdocs\projects\P-09-sakha\html\node_modules\
vinyl-ftp\node_modules\ftp\lib\connection.js:113:25)
I would be highly obliged if anyone can help me in this regard.
Try setting the options secure and secureOptions:
var conn = ftp.create( {
host: 'my_server_host_name',
user: 'my_server_username',
password: 'my_server_password',
parallel: 5,
log: gutil.log,
secure: true,
secureOptions: {
rejectUnauthorized: false
}
} );
I want to build a quick nodejs script to package a Typescript app as SystemJS modules, a lot like what Angular2 bundles look like.
I tried different configurations but I can't seem to put my finger on it, and haven't found clear enough documentation as of yet.
Note that for this "test", I am not using Gulp or Jspm at all, just systemjs-builder for the time being (and don't plan on using jspm at all either)
Here's what my "project" looks like:
---- Project's Root
-------- index.ts // export * from './modules/index' and eventually more
-------- modules
------------ index.ts // export * from './menu/index'
------------ menu
---------------- menu.component.ts // export class
---------------- menu.service.ts // export class
I want to package this under a single file, where I will have multiple SystemRegister modules that can be consumed in an app thereafter
I tried the following without success:
var Builder = require('systemjs-builder');
// optional constructor options
// sets the baseURL and loads the configuration file
var builder = new Builder('./modules');
builder.bundle('./modules/index.ts', {
/* SystemJS Configuration Here */
baseURL: './modules',
transpiler: 'typescript',
typescriptOptions: {
"module": "system",
"emitDecoratorMetadata": true,
"experimentalDecorators": true
},
defaultExtension: 'ts',
packages: {
'modules': {
defaultExtension: 'ts'
}
}
}, 'infrastructure.js')
.then(function() {
console.log('Build complete');
})
.catch(function(err) {
console.error(err);
})
First of all, the defaultExtension options doesn't seem to work at all
So when I do import {something} from 'filePath'; (without extension), it tries to load filePath, instead of filePath.ts;
Second, if I try adding the .ts extension in my imports (which I don't want to do), it complains that the code is invalid (unexpected token #, unexpected token menuItem and so forth)
Anyone have a good example or some explanations on how this is supposed to work?
Thank you
here you have an example: angular typescript skeleton
build task looks like this:
const path = require('path');
const Builder = require('jspm').Builder;
const builder = new Builder();
const packageJson = require(path.join(config.projectDir, 'package.json'));
return beginBuild()
.then(buildSFX)
.catch((err) => console.log('Build Failed', err));
function beginBuild() {
builder.reset();
return builder.loadConfig(path.join(config.projectDir, packageJson.jspm.configFile))
}
function buildSFX() {
const appName = packageJson.name;
const distFileName = `${appName}.min.js`;
const outFile = path.join(config.distDir, distFileName);
const moduleName = 'app';
const buildConfig = {
format: 'global',
minify: true,
sourceMaps: true
};
return builder.buildStatic(moduleName, outFile, buildConfig);
}
and jspm conf looks like this:
System.config({
defaultJSExtensions: true,
transpiler: "typescript",
typescriptOptions: {
"tsconfig": "src/tsconfig.json"
},
paths: {
"github:*": "vendor/jspm_packages/github/*",
"npm:*": "vendor/jspm_packages/npm/*",
"app": "src/index"
}
/// ...
}
Why do you want to bundle typescript? Bundling is a method used for optimizing the delivery of source code to the browser. The browser doesn't know typescript, it only knows javascript (unless you do on the fly transpiling).
I am using the npm modules grunt env and load-grunt-config in my project. grunt env handles environment variables for you, while load-grunt-config handles, well, loads the grunt configuration for you. You can put your tasks into other files, then load-grunt-config will bundle them up and have grunt load & consume them for you. You can also make an aliases.js file, with tasks you want to combine together into one task, running one after another. It's similar to the grunt.registerTask task in the original Gruntfile.js. I put all my grunt tasks inside a separate grunt/ folder under the root folder with the main Gruntfile, with no extra subfolders, as suggested by the load-grunt-config README.md on Github. Here is my slimmed-down Gruntfile:
module.exports = function(grunt) {
'use strict';
require('time-grunt')(grunt);
// function & property declarations
grunt.initConfig({
pkg: grunt.file.readJSON('package.json')
});
require('load-grunt-config')(grunt, {
init: true,
loadGruntConfig: {
scope: 'devDependencies',
pattern: ['grunt-*', 'time-grunt']
}
});
};
In theory, setting all these files up the correct way for load-grunt-config to load should be exactly the same as just having a Gruntfile.js. However, I seem to have run into a little snag. It seems the environment variables set under the env task do not get set for the subsequent grunt tasks, but are set by the time node processes its tasks, in this case an express server.
grunt env task:
module.exports = {
// environment variable values for developers
// creating/maintaining site
dev: {
options: {
add: {
NODE_ENV: 'dev',
MONGO_PORT: 27017,
SERVER_PORT: 3000
}
}
}
};
grunt-shell-spawn task:
// shell command tasks
module.exports = {
// starts up MongoDB server/daemon
mongod: {
command: 'mongod --bind_ip konneka.org --port ' + (process.env.MONGO_PORT || 27017) + ' --dbpath C:/MongoDB/data/db --ipv6',
options: {
async: true, // makes this command asynchronous
stdout: false, // does not print to the console
stderr: true, // prints errors to the console
failOnError: true, // fails this task when it encounters errors
execOptions: {
cwd: '.'
}
}
}
};
grunt express task:
module.exports = {
// default options
options: {
hostname: '127.0.0.1', // allow connections from localhost
port: (process.env.SERVER_PORT || 3000), // default port
},
prod: {
options: {
livereload: true, // automatically reload server when express pages change
// serverreload: true, // run forever-running server (do not close when finished)
server: path.resolve(__dirname, '../backend/page.js'), // express server file
bases: 'dist/' // watch files in app folder for changes
}
}
};
aliases.js file (grunt-load-config's way of combining tasks so they run one after the other):
module.exports = {
// starts forever-running server with "production" environment
server: ['env:prod', 'shell:mongod', 'express:prod', 'express-keepalive']
};
part of backend/env/prod.js (environment-specific Express configuration, loaded if NODE_ENV is set to "prod", modeled after MEAN.JS):
'use strict';
module.exports = {
port: process.env.SERVER_PORT || 3001,
dbUrl: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || 'mongodb://konneka.org:' + (process.env.MONGO_PORT || 27018) + '/mean'
};
part of backend/env/dev.js (environment-specific Express configuration for dev environment, loaded if the `NODE_ENV variable is not set or is set to "dev"):
module.exports = {
port: process.env.SERVER_PORT || 3000,
dbUrl: 'mongodb://konneka.org:' + (process.env.MONGO_PORT || 27017) + '/mean-dev'
};
part of backend/page.js (my Express configuration page, also modeled after MEAN.JS):
'use strict';
var session = require('express-session');
var mongoStore = require('connect-mongo')(session);
var express = require('express');
var server = express();
...
// create the database object
var monServer = mongoose.connect(environ.dbUrl);
// create a client-server session, using a MongoDB collection/table to store its info
server.use(session({
resave: true,
saveUninitialized: true,
secret: environ.sessionSecret,
store: new mongoStore({
db: monServer.connections[0].db, // specify the database these sessions will be saved into
auto_reconnect: true
})
}));
...
// listen on port related to environment variable
server.listen(process.env.SERVER_PORT || 3000);
module.exports = server;
When I run grunt server, I get:
$ cd /c/repos/konneka/ && grunt server
Running "env:prod" (env) task
Running "shell:mongod" (shell) task
Running "express:prod" (express) task
Running "express-server:prod" (express-server) task
Web server started on port:3000, hostname: 127.0.0.1 [pid: 3996]
Running "express-keepalive" task
Fatal error: failed to connect to [konneka.org:27018]
Execution Time (2014-08-15 18:05:31 UTC)
loading tasks 38.3s █████████████████████████████████ 79%
express-server:prod 8.7s ████████ 18%
express-keepalive 1.2s ██ 2%
Total 48.3s
Now, I can't seem to get the database connected in the first place, but ignore that for now. Notice that the server is started on port 3000, meaning that during execution of the grunt express:prod task, SERVER_PORT is not set so the port gets set to 3000. There are numerous other examples like this, where an environment variable is not set so my app uses the default. However, notice that session tries to connect to the database on port 27018 (and fails), so MONGO_PORT does get set eventually.
If I had just tried the grunt server task, I could chalk it up to load-grunt-config running the tasks in parallel instead of one after the other or some other error, but even when I try the tasks one-by-one, such as running grunt env:prod shell:mongod express-server:prod express-keepalive, I get similar (incorrect) results, so either grunt or grunt env run the tasks in parallel, as well, or something else is going on.
What's going on here? Why are the environment variables not set correctly for later grunt tasks? When are they eventually set, and why then rather than some other time? How can I make them get set for grunt tasks themselves rather than after, assuming there even is a way?
The solution is rather obvious once you figure it out, so let's start at the beginning:
The problem
You're using load-grunt-config to load a set of modules (objects that define tasks) and combine them into one module (object) and pass it along to Grunt. To better understand what load-grunt-config is doing, take a moment to read through the source (it's just three files). So, instead of writing:
// filename: Gruntfile.js
grunt.initConfig({
foo: {
a: {
options: {},
}
},
bar: {
b: {
options: {},
}
}
});
You can write this:
// filename: grunt/foo.js
module.exports = {
a: {
options: {},
}
}
// filename: grunt/bar.js
module.exports = {
b: {
options: {},
}
}
// filename: Gruntfile.js
require('load-grunt-config')(grunt);
Basically, this way you can split up a Grunt configuration into multiple files and have it be more "maintainable". But what you'll need to realize is that these two approaches are semantically equivalent. That is, you can expect them to behave the same way.
Thus, when you write the following*:
(* I've reduced the problem in an attempt to make this answer a bit more general and to reduce noise. I've excluded things like loading the tasks and extraneous option passing, but the error should still be the same. Also note that I've changed the values of the environment variables because the default was the same as what was being set.)
// filename: grunt/env.js
module.exports = {
dev: {
options: {
add: {
// These values are different for demo purposes
NODE_ENV: 'dev',
MONGO_PORT: 'dev_mongo_port',
SERVER_PORT: 'dev_server_port'
}
}
}
};
// filename: grunt/shell.js
module.exports = {
mongod: {
command: 'mongod --port ' + (process.env.MONGO_PORT || 27017)
}
};
// filename: grunt/aliases.js
module.exports = {
server: ['env:prod', 'shell:mongod']
};
// filename: Gruntfile.js
module.exports = function (grunt) {
require('load-grunt-config')(grunt);
};
You can consider the above the same as below:
module.exports = function (grunt) {
grunt.initConfig({
env: {
dev: {
options: {
add: {
NODE_ENV: 'dev',
MONGO_PORT: 'dev_mongo_port',
SERVER_PORT: 'dev_server_port'
}
}
}
},
shell: {
mongod: {
command: 'mongod --port ' + (process.env.MONGO_PORT || 27017)
}
}
});
grunt.registerTask('server', ['env:dev', 'shell:mongod']);
};
Now do you see the problem? What command do you expect shell:mongod to run? The correct answer is:
mongod --port 27017
Where what you want to be executed is:
mongo --port dev_mongo_port
The problem is that when (process.env.MONGO_PORT || 27017) is evaluated the environment variables have not yet been set (i.e. before the env:dev task has been run).
A solution
Well let's look at a working Grunt configuration before splitting it across multiple files:
module.exports = function (grunt) {
grunt.initConfig({
env: {
dev: {
options: {
add: {
NODE_ENV: 'dev',
MONGO_PORT: 'dev_mongo_port',
SERVER_PORT: 'dev_server_port'
}
}
}
},
shell: {
mongod: {
command: 'mongod --port ${MONGO_PORT:-27017}'
}
}
});
grunt.registerTask('server', ['env:dev', 'shell:mongod']);
};
Now when you run shell:mongod, the command will contain ${MONGO_PORT:-27017} and Bash (or just sh) will look for the environment variable you would have set in the task before it (i.e. env:dev).
Okay, that's all well and good for the shell:mongod task, but what about the other tasks, Express for example?
You'll need to move away from environment variables (unless you want to set them up before invoking Grunt. Why? Take this Grunt configuration for example:
module.exports = function (grunt) {
grunt.initConfig({
env: {
dev: {
options: {
add: {
NODE_ENV: 'dev',
MONGO_PORT: 'dev_mongo_port',
SERVER_PORT: 'dev_server_port'
}
}
}
},
express: {
options: {
hostname: '127.0.0.1'
port: (process.env.SERVER_PORT || 3000)
},
prod: {
options: {
livereload: true
server: path.resolve(__dirname, '../backend/page.js'),
bases: 'dist/'
}
}
}
});
grunt.registerTask('server', ['env:dev', 'express:prod']);
};
What port will the express:prod task configuration contain? 3000. What you need is for it to reference the value you've defined in the above task. How you do this is up to you. You could:
Separate the env configuration and reference its values
module.exports = function (grunt) {
grunt.config('env', {
dev: {
options: {
add: {
NODE_ENV: 'dev',
MONGO_PORT: 'dev_mongo_port',
SERVER_PORT: 'dev_server_port'
}
}
}
});
grunt.config('express', {
options: {
hostname: '127.0.0.1'
port: '<%= env.dev.options.add.SERVER_PORT %>'
}
});
grunt.registerTask('server', ['env:dev', 'express:prod']);
};
But you'll notice that the semantics of the env task don't hold up here due to it no longer representing a task's configuration. You could use an object of your own design:
module.exports = function (grunt) {
grunt.config('env', {
dev: {
NODE_ENV: 'dev',
MONGO_PORT: 'dev_mongo_port',
SERVER_PORT: 'dev_server_port'
}
});
grunt.config('express', {
options: {
hostname: '127.0.0.1'
port: '<%= env.dev.SERVER_PORT %>'
}
});
grunt.registerTask('server', ['env:dev', 'express:prod']);
};
Pass grunt an argument to specify what config it should use
Have multiple configuration files (e.g. Gruntfile.js.dev and Gruntfile.js.prod) and rename them as needed
Read a development configuration file (e.g. grunt.file.readJSON('config.development.json')) if it exists and fall back to a production configuration file if it doesn't exist
Some better way not listed here
But all of the above should achieve the same end result.
This seems to be the essence of what you are trying to do, and it works for me. The important part was what I mentioned in my comment -- chaining the environment task before running the other tasks.
Gruntfile.js
module.exports = function(grunt) {
// Do grunt-related things in here
grunt.loadNpmTasks('grunt-env');
grunt.initConfig({
env: {
dev: {
PROD : 'http://production.server'
}
}
});
grunt.registerTask('printEnv', 'prints a message with an env var', function() { console.log('Env var in subsequent grunt task: ' + process.env.PROD) } );
grunt.registerTask('prod', ['env:dev', 'printEnv']);
};
Output of grunt prod
Running "env:dev" (env) task
Running "printEnv" task
Env var in subsequent grunt task: http://production.server
Done, without errors.
I have two different paths where I want to compile the mobile vs desktop code. I would like to alternate by passing a grunt parameter in the command line.
/**
* #module Build
* #class Build.Config
* #static
*/
module.exports = function(grunt) {
var config = {};
var NewPath;
var env = grunt.option('target') || "Mobile";
if (env == "Desktop") { // MAKE THIS DYNAMIC WITH COMMAND LINE ARGUMENT
newPath = "source/desktop/";
}
else {
newPath = "source/mobile/";
}
config.root = newPath;
config.stylesheets = config.root + '/stylesheets';
config.javascripts = config.root + '/javascripts';
config.images = config.root + '/images';
config.jsbin = config.javascripts + '/generated';
config.cssbin = config.stylesheets + '/generated';
config.docsbin = 'docs';
// Project configuration.
grunt.initConfig({
'beautifier': {
'options': {
'indentSize': 1,
'indentChar': '\t',
'spaceAfterAnonFunction': true
}
},
'beautify': {
'files': [ config.javascripts + '/app/**/*.js' ]
},
'requirejs': require('./build/config/requirejs.js')(config),
'watch': require('./build/config/watch.js')(config),
'stylus':require('./build/config/stylus.js')(config)
});
// Default task.
grunt.registerTask('default', ['stylus:compile','requirejs']);
grunt.registerTask('dev', ['stylus:dev']);
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.loadNpmTasks('grunt-contrib-stylus');
};
Turns out I was doing it right I just needed to pass in the variable for env correctly:
$ grunt --target="Desktop"
An alternate to --option is to pass it through the colon. for example passing it to jshint
grunt jshint:desktop
Then configure grunt to pick up that command line argument using process.argv and you can use it to configure your paths or whatever else might be needed:
module.exports = function(grunt) {
"use strict";
//dynamic config after the ':'. 'desktop' here
var env = process.argv[2].split(':')[1];
var config = {
pkg: grunt.file.readJSON('package.json'),
jshint: {
options: {
jshintrc: '.jshintrc',
"force": true
}
},
};
//...
config.jshint[env] = { // ex: $ grunt jshint:desktop
src: ['public/'+env+'/js/main.js']
};
//...
// Project configuration.
grunt.initConfig(config);
//...
};
One caveat on using process is that it won't work when you use a grunt task that respawns your process like the useful grunt-concurrent. In that case it's bettter to go with grunt.option as shown by #im_benton. passing grunt mytask --myvar=myval and picking it up in you Gruntfile.js as grunt.option('myvar') `