support coffee-script models and client code
Load models for any filetypes registered in require.extensions. - Server side coffee-script requires a `require('coffee-script/register');` - Client side coffee-script requires Coffeeify.
This commit is contained in:
parent
3961f1c615
commit
e936deffe2
|
@ -0,0 +1,35 @@
|
|||
## Server Files in Coffee-Script
|
||||
|
||||
In order to create application files in coffee-script, you'll need to register the coffee-script extension:
|
||||
|
||||
```javascript
|
||||
require('coffee-script/register');
|
||||
```
|
||||
|
||||
You'll need to do this at any entry points for the app (e.g. the server.js file, mocha.opts, and gulp/grunt). It is recommended to leave the entry point of the app (server.js by default, specified as 'main' in package.json) as a javascript file, and then register coffee-script, and proceed with any coffee-requires.
|
||||
|
||||
## Client Files in Coffee-Script
|
||||
|
||||
You can use the Coffeeify module to include Coffee files in your browser package. Use a build script like this:
|
||||
|
||||
|
||||
```javascript
|
||||
// assuming you haven't done so already
|
||||
require('coffee-script/register');
|
||||
|
||||
var b = browserify({
|
||||
basedir: appDir,
|
||||
extensions: ['.coffee'], //causes browserify to look for this extension
|
||||
debug: true
|
||||
});
|
||||
|
||||
b.transform('coffeeify'); //adds coffee compiler to the build pipeline
|
||||
|
||||
b.require('./app.coffee', { expose: 'browser-app' }); //requiring your file will set the entry point
|
||||
boot.compileToBrowserify(appDir, b);
|
||||
|
||||
var bundlePath = sandbox.resolve('browser-app-bundle.js'); //remember, the final result is still '.js'
|
||||
var out = fs.createWriteStream(bundlePath);
|
||||
|
||||
b.bundle().pipe(out);
|
||||
```
|
|
@ -253,13 +253,14 @@ function findModelDefinitions(rootDir, sources) {
|
|||
}
|
||||
|
||||
var files = tryReadDir(srcDir);
|
||||
|
||||
files
|
||||
.filter(function(f) {
|
||||
return f[0] !== '_' && path.extname(f) === '.json';
|
||||
})
|
||||
.forEach(function(f) {
|
||||
var fullPath = path.resolve(srcDir, f);
|
||||
var entry = loadModelDefinition(rootDir, fullPath);
|
||||
var entry = loadModelDefinition(rootDir, fullPath, files);
|
||||
var modelName = entry.definition.name;
|
||||
if (!modelName) {
|
||||
debug('Skipping model definition without Model name: %s',
|
||||
|
@ -303,24 +304,29 @@ function resolveSourceDir(rootDir, sourceDir) {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
function loadModelDefinition(rootDir, jsonFile) {
|
||||
function loadModelDefinition(rootDir, jsonFile, allFiles) {
|
||||
var definition = require(jsonFile);
|
||||
var basename = path.basename(jsonFile, path.extname(jsonFile));
|
||||
|
||||
var sourceFile = path.join(
|
||||
path.dirname(jsonFile),
|
||||
path.basename(jsonFile, path.extname(jsonFile)));
|
||||
// find a matching file with `.js` or any other supported extension like `.coffee`
|
||||
var base, ext, validFileType;
|
||||
var sourceFile = allFiles
|
||||
.filter(function(f) {
|
||||
ext = path.extname(f);
|
||||
base = path.basename(f, ext);
|
||||
validFileType = (ext !== '.node') && (ext !== '.json') &&
|
||||
((typeof require.extensions[ext]) === 'function');
|
||||
return validFileType && (base === basename);
|
||||
})[0];
|
||||
|
||||
try {
|
||||
// resolve the file to `.js` or any other supported extension like `.coffee`
|
||||
sourceFile = path.join(path.dirname(jsonFile), sourceFile);
|
||||
sourceFile = require.resolve(sourceFile);
|
||||
} catch (err) {
|
||||
debug('Model source code not found: %s - %s', sourceFile, err.code || err);
|
||||
sourceFile = undefined;
|
||||
}
|
||||
|
||||
if (sourceFile === jsonFile)
|
||||
sourceFile = undefined;
|
||||
|
||||
debug('Found model "%s" - %s %s', definition.name,
|
||||
path.relative(rootDir, jsonFile),
|
||||
sourceFile ? path.relative(rootDir, sourceFile) : '(no source file)');
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
"devDependencies": {
|
||||
"browserify": "^6.1.0",
|
||||
"fs-extra": "^0.12.0",
|
||||
"browserify": "^4.1.8",
|
||||
"coffee-script": "^1.8.0",
|
||||
"coffeeify": "^0.7.0",
|
||||
"jshint": "^2.5.6",
|
||||
"loopback": "^2.5.0",
|
||||
"mocha": "^1.19.0",
|
||||
|
|
|
@ -6,6 +6,31 @@ var browserify = require('browserify');
|
|||
var sandbox = require('./helpers/sandbox');
|
||||
var vm = require('vm');
|
||||
|
||||
var compileStrategies = {
|
||||
'default': function(appDir) {
|
||||
var b = browserify({
|
||||
basedir: appDir,
|
||||
debug: true
|
||||
});
|
||||
|
||||
b.require('./app.js', { expose: 'browser-app' });
|
||||
return b;
|
||||
},
|
||||
|
||||
'coffee': function(appDir) {
|
||||
var b = browserify({
|
||||
basedir: appDir,
|
||||
extensions: ['.coffee'],
|
||||
debug: true
|
||||
});
|
||||
|
||||
b.transform('coffeeify');
|
||||
|
||||
b.require('./app.coffee', { expose: 'browser-app' });
|
||||
return b;
|
||||
},
|
||||
};
|
||||
|
||||
describe('browser support', function() {
|
||||
this.timeout(60000); // 60s to give browserify enough time to finish
|
||||
|
||||
|
@ -28,14 +53,38 @@ describe('browser support', function() {
|
|||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('supports coffee-script files', function(done) {
|
||||
// add coffee-script to require.extensions
|
||||
require('coffee-script/register');
|
||||
|
||||
var appDir = path.resolve(__dirname, './fixtures/coffee-app');
|
||||
|
||||
browserifyTestApp(appDir, 'coffee', function(err, bundlePath) {
|
||||
if (err) return done(err);
|
||||
|
||||
var app = executeBundledApp(bundlePath);
|
||||
|
||||
// configured in fixtures/browser-app/boot/configure.coffee
|
||||
expect(app.settings).to.have.property('custom-key', 'custom-value');
|
||||
expect(Object.keys(app.models)).to.include('Customer');
|
||||
expect(app.models.Customer.settings)
|
||||
.to.have.property('_customized', 'Customer');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function browserifyTestApp(appDir, next) {
|
||||
var b = browserify({
|
||||
basedir: appDir,
|
||||
debug: true
|
||||
});
|
||||
b.require('./app.js', { expose: 'browser-app' });
|
||||
function browserifyTestApp(appDir, strategy, next) {
|
||||
//set default args
|
||||
if (((typeof strategy) === 'function') && !next) {
|
||||
next = strategy;
|
||||
strategy = undefined;
|
||||
}
|
||||
if (!strategy)
|
||||
strategy = 'default';
|
||||
|
||||
var b = compileStrategies[strategy](appDir);
|
||||
|
||||
boot.compileToBrowserify(appDir, b);
|
||||
|
||||
|
|
|
@ -450,6 +450,31 @@ describe('compiler', function() {
|
|||
sourceFile: path.resolve(appdir.PATH, 'models', 'car.js')
|
||||
});
|
||||
});
|
||||
|
||||
it('loads coffeescript models from `./models`', function() {
|
||||
// add coffee-script to require.extensions
|
||||
require('coffee-script/register');
|
||||
|
||||
appdir.createConfigFilesSync({}, {}, {
|
||||
Car: { dataSource: 'db' }
|
||||
});
|
||||
appdir.writeConfigFileSync('models/car.json', { name: 'Car' });
|
||||
appdir.writeFileSync('models/car.coffee', '');
|
||||
|
||||
var instructions = boot.compile(appdir.PATH);
|
||||
|
||||
expect(instructions.models).to.have.length(1);
|
||||
expect(instructions.models[0]).to.eql({
|
||||
name: 'Car',
|
||||
config: {
|
||||
dataSource: 'db'
|
||||
},
|
||||
definition: {
|
||||
name: 'Car'
|
||||
},
|
||||
sourceFile: path.resolve(appdir.PATH, 'models', 'car.coffee')
|
||||
});
|
||||
});
|
||||
|
||||
it('supports `modelSources` option', function() {
|
||||
appdir.createConfigFilesSync({}, {}, {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
loopback = require 'loopback'
|
||||
boot = require '../../../'
|
||||
|
||||
module.exports = client = loopback()
|
||||
boot(client)
|
|
@ -0,0 +1,2 @@
|
|||
module.exports = (app) ->
|
||||
app.set 'custom-key', 'custom-value'
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"db": {
|
||||
"connector": "remote"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"Customer": {
|
||||
"dataSource": "db"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = (Customer) ->
|
||||
Customer.settings._customized = 'Customer'
|
||||
Customer.base.settings._customized = 'Base'
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "Customer",
|
||||
"base": "User"
|
||||
}
|
Loading…
Reference in New Issue