Copy .js and compile .coffee during Makefile task - javascript

I have a node project with:
.coffeescript source in src
compiled coffeescript output to lib
shell scripts in bin
How can I adjust my Makefile, shown below, to also copy .js files in src to the lib directory?
BIN = ./node_modules/.bin
SRC = $(wildcard src/*.coffee)
LIB = $(SRC:src/%.coffee=lib/%.js)
init:
npm install
clean:
#rm -r -f $(LIB)
build: $(LIB)
dist: clean init build
lib/%.js: src/%.coffee
$(call coffeetime)
define coffeetime
#mkdir -p $(#D)
$(BIN)/coffee -bcp $< > $#
endef
Also, if you have any other suggestions to improve the Makefile, please share.

Something like this might work.
Add SRCJS = $(wildcard src/*.js)
Change LIB = $(SRC:src/%.coffee=lib/%.js) to LIB = $(SRC:src/%.coffee=lib/%.js) $(SRCJS:src/%=lib/%).
Add:
lib/%.js: src/%.js
#cp $< $#
If it doesn't work (for some reason) then you may need to use a static pattern rule but I think something like the above should work.

I would suggest you to use Grunt instead.
There is a few neat task that handle Coffeescript compiling very well. Like: https://github.com/gruntjs/grunt-contrib-coffee
Also, depending on your needs, Node.js can cope with Coffeescript directly if needed.

Related

Typescript: Make tsconfig emit one folder but not the other folder

I'm converting an existing project from js to typescript. I want to be able to set noEmit = true on one folder but have the other folder have noEmit = false.
The reason is that I have my client(angular) code set up through webpack and do not need typescript to generate the javascript for me. While the server (Node/express) still needs to be generated into javascript.
I've tried a few different combinations but haven't seem to find the right way to do it.
My only solution that I've been able to get to work is having two tsconfig.json and running a command like tsc -p src\server\tsconfig && tsc -p src\client\tsconfig
I realize that this is not a good solution, but I have not gotten a single tsconfig to work nor having a base tsconfig.
Here is the folder structure..
|-Src
|--/client
|--/server
Is there a way to achieve this using a single tsc command? Or is there a better way I should be formatting the project? Thanks!!
I don't think there's another solution besides having multiple tsconfig.json files like you're already doing, as per this answer and this comment.
You can make this a little more streamlined by having a tsconfig.json for compilation and a separate tsconfig-build.json that you use in your package.json for building, i.e.:
// package.json
{
"scripts": {
"build": "tsc -p tsconfig-build.json"
},
// ...
}
With this setup (assuming the default tsconfig.json is in your root), running tsc from the command line will use the default tsconfig.json, but running npm run build will use tsconfig-build.json. You can also have one tsconfig extend from another, so if you have a lot of options in common, you could add a tsconfig-base.json that both configs extend from.
You can probably achieve what you want with the exclude property in your tsconfig.json file.
Check the documentation
for the exclude property

How to pass browserify --require file to angular module?

I have engineered a build for an Angular SPA using NPM to call the browserify script to bundle it, i.e. you can run from the terminal npm run build:js which calls the following script in package.json:
"build:js": "browserify -r ./params-dev.js -e src/app/index.js -o build/index.js"
What I'm trying to do now is to create two different config objects for prod and QA. Each one will require a different file: params-dev.js or params-prod.js (like in the command above).
I am wondering how to access these variables in the resulting bundle? They are environment specific and some of it points to analytics codes, etc. Furthermore, I'm trying to move them out of the global scope, where they currently live.
Here is a sample of the params files I'd like to include with the bundles. There will be one for prod and one for QA:
var merge = require('merge'),
params = require('./params')
exports.config = merge(params, {
env: 'prod',
analyticsCode: 'blah08yweblah2e823lnblah',
otherProps: '...etc...'
})
So how do I access these variables now in my AngularJS module? I feel like I'm missing something obvious here.
Anyone have any ideas? Please let me know if you need more info.
In case it helps, my index.js looks like
(function () {
// common app require statements
require('blah')
require('blah-2')
angular.module('app', [require('angular-route')])
// etc etc
})()
I figured it out. :) If I add the target to the end of the required file path in the command like so:
"build:js": "browserify -r ./params-dev.js:params -e src/app/index.js -o build/index.js"
I can access the object by adding var params = require('params') to my angular file.

Babelify the files in place, in multiple directories

How can I use babel to transpile the JavaScript files containing ES6 stuff, in different directories? I want the result to be in the same directories (e.g. having foo/bar/index.js, I want to get the ES5 code in the same file, by overriding it).
To override one directory I use:
babel lib/ -d lib
This works for one folder (overrides all the content in the lib directory).
How can I do the same for two or more directories? For example, how can I do that for lib/ and bin/?
AFAIK the babel CLI isn't complex enough to support this use-case in a single command. However you could concatenate two commands to achieve the same result:
babel lib/ -d lib && babel bin/ -d bin
Or you could write a script that does this for you, using gulp or another build tool of your choice. For example (untested):
gulp.task('default', () =>
gulp.src(['bin/**/*.js', 'lib/**/*.js'], { base: './' })
.pipe(babel())
.pipe(gulp.dest('.'))
)
The codemod CLI is perfect for this.
It will just modify your files in place:
codemod --plugin babel-transformer.js src/**/*.js

gulpjs - merge multiple files to make one gulpfile

I am loving gulpjs, but am having an issue where my gulpfile.js is just getting really, really big.
I have searched pretty extensively and am having difficulty finding resources related to this, but is it possible to split a gulpfile.js up into multiple smaller js files just for organization?
Yes, you can do it to manage your tasks. For example if you have this file organization:
gulpfile.js
-- tasks
---- test.js
---- dev.js
You have to install de require-div module:
npm install require-dir --save-dev
And, finally, you add this code to your gulpfile
var requireDir = require('require-dir');
var dir = requireDir('./tasks');
Hope it helps.
Regards.
I do it this way (I use coffeescript, but the theory is sound), similar to the above:
tasks = fs.readdirSync './gulp/tasks'
tasks.forEach (task)->
require "./tasks/#{task}" if task.indexOf('coffee') >= 0
All it does is read the task folder and require all the files in it as long as they're .coffee files (which isn't 100% kosher, but it does avoid hidden dotfiles).

How do I include a .gitignore file as part of my npm module?

I am building an npm module that will generate a specific project template for certain software projects. As such, when a developer installs my npm module and runs it, I would like the program to create files and folders in a certain way.
One such file I would like to include in the project template is a .gitignore file because the software project is going to assume it will be tracked via git. However, when I call "npm install" on my module, npm renames all my .gitignore files to .npmignore files. How can I ensure that my .gitignore files are not tampered with by npm when I distribute my module?
Currently npm doesn't allow .gitignore files to be included as part of an npm package and will instead rename it to .npmignore.
A common workaround is to rename the .gitignore to gitignore before publishing. Then as part of an init script, rename the gitignore file to .gitignore. This approach is used in Create React App
Here's how to do it in Node, code from Create React App init script
const gitignoreExists = fs.existsSync(path.join(appPath, '.gitignore'));
if (gitignoreExists) {
// Append if there's already a `.gitignore` file there
const data = fs.readFileSync(path.join(appPath, 'gitignore'));
fs.appendFileSync(path.join(appPath, '.gitignore'), data);
fs.unlinkSync(path.join(appPath, 'gitignore'));
} else {
// Rename gitignore after the fact to prevent npm from renaming it to .npmignore
// See: https://github.com/npm/npm/issues/1862
fs.moveSync(
path.join(appPath, 'gitignore'),
path.join(appPath, '.gitignore'),
[]
);
}
https://github.com/npm/npm/issues/1862
Looks like this is a known issue. The answer at the bottom seems like the recommended approach. In case the issue or link ever gets destroyed:
For us, I think a better solution is going to be clear documentation that if authors wish to use .gitignore in their generators, they will need to name their files .##gitignore##, which will be a value gitignore set to the same string gitignore.
In this way, the file that gets published as a template file to npm is called .##gitignore## and won't get caught by npm, but then later it gets replaced with the string to be .gitignore.
You can see multiple commits dealing with npm issue 1862:
this project adds a rename.json:
lib/init-template/rename.json
{
".npmignore": ".gitignore",
}
this one renames the .gitignore:
templates/default/.gitignore → templates/default/{%=gitignore%}
index.js
## -114,6 +114,10 ## generator._pkgData = function (pkg) {
+ // npm will rename .gitignore to .npmignore:
+ // [ref](https://github.com/npm/npm/issues/1862)
+ pkg.gitignore = '.gitignore';
Edit: even though this answer causes .gitignore to be included in the published package (proven by unpkg), upon running npm install the .gitignore file is simply removed! So even getting NPM to include the file is not enough.
Another solution (simpler imo):
Include both .gitignore and .npmignore in the repo. Add the following to your .npmignore file:
!.gitignore
!.npmignore
Now that .npmignore will already exist in the published package, NPM won't rename .gitignore.

Categories