UNPKG

65.1 kBJavaScriptView Raw
1require('source-map-support').install({
2 environment: 'node'
3});
4
5'use strict';
6
7Object.defineProperty(exports, '__esModule', { value: true });
8
9function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
10
11var Ora = _interopDefault(require('ora'));
12var os = require('os');
13var os__default = _interopDefault(os);
14var cluster = require('cluster');
15var cluster__default = _interopDefault(cluster);
16var path = require('path');
17var path__default = _interopDefault(path);
18var lux = _interopDefault(require('rollup-plugin-lux'));
19var json = _interopDefault(require('rollup-plugin-json'));
20var alias = _interopDefault(require('rollup-plugin-alias'));
21var babel = _interopDefault(require('rollup-plugin-babel'));
22var eslint = _interopDefault(require('rollup-plugin-eslint'));
23var resolve$1 = _interopDefault(require('rollup-plugin-node-resolve'));
24var rollup = require('rollup');
25var fs = require('fs');
26var fs__default = _interopDefault(fs);
27var EventEmitter = _interopDefault(require('events'));
28var fbWatchman = require('fb-watchman');
29var child_process = require('child_process');
30var inflection = require('inflection');
31var chalk = require('chalk');
32var chalk__default = _interopDefault(chalk);
33var readline = require('readline');
34var tty = require('tty');
35var ansiRegex = _interopDefault(require('ansi-regex'));
36require('http');
37require('url');
38var repl = require('repl');
39
40const {env:ENV}=process;function getPID(){let{pid}=process;if(cluster.isWorker&&typeof cluster.worker.pid==='number'){pid=cluster.worker.pid;}return pid}const CWD=process.cwd();const PID=getPID();const PORT=parseInt(ENV.PORT,10)||4000;const NODE_ENV=ENV.NODE_ENV||'development';const DATABASE_URL=ENV.DATABASE_URL;const LUX_CONSOLE=ENV.LUX_CONSOLE||false;const PLATFORM=os.platform();
41
42function exec$1(cmd,opts){return new Promise((resolve$$1,reject)=>{child_process.exec(cmd,opts,(err,stdout,stderr)=>{if(err){reject(err);return}resolve$$1([stdout,stderr]);});})}
43
44function K(){return this}
45
46var asyncToGenerator = function (fn) {
47 return function () {
48 var gen = fn.apply(this, arguments);
49 return new Promise(function (resolve$$1, reject) {
50 function step(key, arg) {
51 try {
52 var info = gen[key](arg);
53 var value = info.value;
54 } catch (error) {
55 reject(error);
56 return;
57 }
58
59 if (info.done) {
60 resolve$$1(value);
61 } else {
62 return Promise.resolve(value).then(function (value) {
63 step("next", value);
64 }, function (err) {
65 step("throw", err);
66 });
67 }
68 }
69
70 return step("next");
71 });
72 };
73};
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97var objectWithoutProperties = function (obj, keys) {
98 var target = {};
99
100 for (var i in obj) {
101 if (keys.indexOf(i) >= 0) continue;
102 if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
103 target[i] = obj[i];
104 }
105
106 return target;
107};
108
109var tryCatch = (()=>{var _ref=asyncToGenerator(function*(fn,rescue=K){let result;try{result=yield fn();}catch(err){result=yield rescue(err);}return result});function tryCatch(_x){return _ref.apply(this,arguments)}return tryCatch})();
110
111function isJSFile(target){return path.extname(target)==='.js'}
112
113const FREEZER=new WeakSet;
114
115function isObject(value){return Boolean(value)&&typeof value==='object'&&!Array.isArray(value)}
116
117function freeze(value){FREEZER.add(value);return value}function freezeProps(target,makePublic,...props){Object.defineProperties(target,props.reduce((obj,key)=>Object.assign({},obj,{[key]:{value:Reflect.get(target,key),writable:false,enumerable:makePublic,configurable:false}}),{}));return target}
118
119function isFrozen(value){return FREEZER.has(value)}
120
121class FreezeableMap extends Map{set(key,value){if(!this.isFrozen()){super.set(key,value);}return this}clear(){if(!this.isFrozen()){super.clear();}}delete(key){return this.isFrozen()?false:super.delete(key)}freeze(deep){if(deep){this.forEach(Object.freeze);}return freeze(this)}isFrozen(){return isFrozen(this)}}
122
123class FreezeableSet extends Set{add(value){if(!this.isFrozen()){super.add(value);}return this}clear(){if(!this.isFrozen()){super.clear();}}delete(value){return this.isFrozen()?false:super.delete(value)}freeze(deep){if(deep){this.forEach(Object.freeze);}return freeze(this)}isFrozen(){return isFrozen(this)}}
124
125const SUBSCRIPTION_NAME='lux-watcher';function fallback(instance,path$$1){return fs.watch(path$$1,{recursive:true},(type,name)=>{if(isJSFile(name)){instance.emit('change',[{name,type}]);}})}function setupWatchmen(instance,path$$1){return new Promise((resolve$$1,reject)=>{const client=new fbWatchman.Client;client.capabilityCheck({},capabilityErr=>{if(capabilityErr){reject(capabilityErr);return}client.command(['watch-project',path$$1],(watchErr,{watch: watch$$1,relative_path:relativePath}={})=>{if(watchErr){reject(watchErr);return}client.command(['clock',watch$$1],(clockErr,{clock:since})=>{if(clockErr){reject(clockErr);return}client.command(['subscribe',watch$$1,SUBSCRIPTION_NAME,{since,relative_root:relativePath,fields:['name','size','exists','type'],expression:['allof',['match','*.js']]}],subscribeErr=>{if(subscribeErr){reject(subscribeErr);return}client.on('subscription',({files,subscription})=>{if(subscription===SUBSCRIPTION_NAME){instance.emit('change',files);}});resolve$$1(client);});});});});})}var initialize = (()=>{var _ref=asyncToGenerator(function*(instance,path$$1,useWatchman){const appPath=path.join(path$$1,'app');let client;if(useWatchman){yield tryCatch(asyncToGenerator(function*(){yield exec$1('which watchman');client=yield setupWatchmen(instance,appPath);}));}Object.assign(instance,{path:appPath,client:client||fallback(instance,appPath)});freezeProps(instance,true,'path','client');return instance});function initialize(_x,_x2,_x3){return _ref.apply(this,arguments)}return initialize})();
126
127class Watcher extends EventEmitter{constructor(path$$1,useWatchman=true){super();return initialize(this,path$$1,useWatchman)}destroy(){const{client}=this;if(client instanceof fbWatchman.Client){client.end();}else{client.close();}}}
128
129function createResolver(resolve$$1,reject){return function fsResolver(err,...args){const[data]=args;if(err){reject(err);return}resolve$$1(args.length>1?args:data);}}
130
131let rmrf$$1=(()=>{var _ref=asyncToGenerator(function*(target){const stats=yield tryCatch(function(){return stat(target)});if(stats&&stats.isDirectory()){let files=yield tryCatch(function(){return readdir(target)});if(files){files=files.map(function(file){return rmrf$$1(path__default.join(target,file))});yield Promise.all(files);yield rmdir(target);}}else if(stats&&stats.isFile()){yield tryCatch(function(){return unlink(target)});}return true});return function rmrf$$1(_x){return _ref.apply(this,arguments)}})();
132
133var exists$$1 = (()=>{var _ref=asyncToGenerator(function*(path$$1,dir){if(path$$1 instanceof RegExp){const pattern=path$$1;let files=[];if(dir){files=yield readdir(dir);}return files.some(function(file){return pattern.test(file)})}const str=path$$1;return Boolean((yield tryCatch(function(){return stat(str)})))});function exists$$1(_x,_x2){return _ref.apply(this,arguments)}return exists$$1})();
134
135function chain(source){return{pipe(handler){return chain(handler(source))},value(){return source},construct(constructor){return chain(Reflect.construct(constructor,[source]))}}}
136
137function resolvePath(cwd=CWD,dir='',name=''){return chain(name.split('/')).pipe(parts=>path__default.join(cwd,dir,...parts)).pipe(path__default.parse).pipe((_ref)=>{let{base}=_ref;let etc=objectWithoutProperties(_ref,['base']);return Object.assign({base},etc,{relative:path__default.join(etc.dir.substr(etc.dir.indexOf(dir)),base),absolute:path__default.join(etc.dir,base)})}).value()}
138
139function watch$1(path$$1){return new Watcher(path$$1)}function stat(path$$1){return new Promise((resolve$$1,reject)=>{fs__default.stat(path$$1,createResolver(resolve$$1,reject));})}function mkdir(path$$1,mode=511){return new Promise((resolve$$1,reject)=>{fs__default.mkdir(path$$1,mode,createResolver(resolve$$1,reject));})}function mkdirRec(path$$1,mode=511){const parent=path.resolve(path$$1,'..');return stat(parent).catch(err=>{if(err.code==='ENOENT'){return mkdirRec(parent,mode)}return Promise.reject(err)}).then(()=>mkdir(path$$1,mode)).catch(err=>{if(err.code!=='EEXIST'){return Promise.reject(err)}return Promise.resolve()})}function rmdir(path$$1){return new Promise((resolve$$1,reject)=>{fs__default.rmdir(path$$1,createResolver(resolve$$1,reject));})}function readdir(path$$1){return new Promise((resolve$$1,reject)=>{fs__default.readdir(path$$1,createResolver(resolve$$1,reject));})}function readdirRec(path$$1,opts){return readdir(path$$1,opts).then(files=>Promise.all(files.map(file=>{const filePath=path.join(path$$1,file);return Promise.all([filePath,stat(filePath)])}))).then(files=>Promise.all(files.map(([file,stats])=>Promise.all([file,stats.isDirectory()?readdirRec(file):[]])))).then(files=>files.reduce((arr,[file,children])=>{const name=path.basename(file);arr[arr.length]=name;return arr.concat(children.map(child=>path.join(name,path.basename(child))))},[]))}function readFile(path$$1,opts){return new Promise((resolve$$1,reject)=>{fs__default.readFile(path$$1,typeof opts==='object'?opts:{},createResolver(resolve$$1,reject));})}function writeFile(path$$1,data,opts){return new Promise((resolve$$1,reject)=>{fs__default.writeFile(path$$1,data,opts,createResolver(resolve$$1,reject));})}function appendFile(path$$1,data,opts){return new Promise((resolve$$1,reject)=>{fs__default.appendFile(path$$1,data,typeof opts==='object'?opts:{},createResolver(resolve$$1,reject));})}function unlink(path$$1){return new Promise((resolve$$1,reject)=>{fs__default.unlink(path$$1,createResolver(resolve$$1,reject));})}
140
141function insertValues(strings,...values){if(values.length){return strings.reduce((result,part,idx)=>{let value=values[idx];if(value&&typeof value.toString==='function'){value=value.toString();}else{value='';}return result+part+value},'')}return strings.join('')}
142
143const bodyPattern=/^\n([\s\S]+)\s{2}$/gm;const trailingWhitespace=/\s+$/;function template(strings,...values){const compiled=insertValues(strings,...values);let[body]=compiled.match(bodyPattern)||[];let indentLevel=/^\s{0,4}(.+)$/g;if(!body){body=compiled;indentLevel=/^\s{0,2}(.+)$/g;}return body.split('\n').slice(1).map(line=>{let str=line.replace(indentLevel,'$1');if(trailingWhitespace.test(str)){str=str.replace(trailingWhitespace,'');}return str}).join('\n')}
144
145function handleWarning(warning){if(warning.code==='UNUSED_EXTERNAL_IMPORT'){return}console.warn(warning.message);}
146
147function isExternal(dir){return id=>!(id.startsWith('.')||id.endsWith('lux-framework')||id.startsWith('/')||/^[A-Z]:[\\/]/.test(id)||id.startsWith('app')||id.startsWith(path__default.join(dir,'app'))||id.startsWith(path__default.join(dir,'dist'))||id==='LUX_LOCAL'||id==='babelHelpers'||id==='\0babelHelpers')}
148
149function underscore$1(source='',upper=false){return inflection.underscore(source,upper).replace(/-/g,'_')}
150
151function compose(main,...etc){return input=>main(etc.reduceRight((value,fn)=>fn(value),input))}function composeAsync(main,...etc){return input=>etc.reduceRight((value,fn)=>Promise.resolve(value).then(fn),Promise.resolve(input)).then(main)}
152
153const DOUBLE_COLON=/::/g;const formatName=compose(name=>name.replace(DOUBLE_COLON,'$'),inflection.camelize,underscore$1,name=>path.posix.join(path.dirname(name),path.basename(name,'.js')));
154
155function createExportStatement(name,path$$1,isDefault=true){const normalized=path.posix.join(...path$$1.split(path.sep));if(isDefault){return`export {\n default as ${name}\n} from '../${normalized}';\n\n`}return`export {\n ${name}\n} from '../${normalized}';\n\n`}function createWriter(file){const writerFor=(type,handleWrite)=>value=>{const formatSymbol=compose(str=>str+inflection.capitalize(type),formatName);return Promise.all(value.map(item=>{if(handleWrite){return handleWrite(item)}const path$$1=path.join('app',inflection.pluralize(type),item);const symbol=formatSymbol(item);return appendFile(file,createExportStatement(symbol,path$$1))}))};return{controllers:writerFor('controller'),serializers:writerFor('serializer'),models:writerFor('model',(()=>{var _ref=asyncToGenerator(function*(item){const path$$1=path.join('app','models',item);const name=formatName(item);return appendFile(file,createExportStatement(name,path$$1))});return function(_x){return _ref.apply(this,arguments)}})()),migrations:writerFor('migration',(()=>{var _ref2=asyncToGenerator(function*(item){const path$$1=path.join('db','migrate',item);const name=chain(item).pipe(function(str){return path.basename(str,'.js')}).pipe(underscore$1).pipe(function(str){return str.substr(17)}).pipe(function(str){return inflection.camelize(str,true)}).value();yield appendFile(file,createExportStatement(`up as ${name}Up`,path$$1,false));yield appendFile(file,createExportStatement(`down as ${name}Down`,path$$1,false));});return function(_x2){return _ref2.apply(this,arguments)}})())}}var createManifest = (()=>{var _ref3=asyncToGenerator(function*(dir,assets,{useStrict}){const dist=path.join(dir,'dist');const file=path.join(dist,'index.js');const writer=createWriter(file);yield tryCatch(function(){return mkdir(dist)});yield writeFile(file,useStrict?'\'use strict\';\n\n':'');yield Promise.all(Array.from(assets).map(function([key,value]){const write=Reflect.get(writer,key);if(write){return write(value)}else if(!write&&typeof value==='string'){return appendFile(file,createExportStatement(key,value))}return Promise.resolve()}));});function createManifest(_x3,_x4,_x5){return _ref3.apply(this,arguments)}return createManifest})();
156
157var createBootScript = (()=>{var _ref=asyncToGenerator(function*(dir,{useStrict}){let data=template`
158 const CWD = process.cwd();
159 const { env: { PORT } } = process;
160 const { Application, config, database } = require('./bundle');
161
162 module.exports = new Application(
163 Object.assign(config, {
164 database,
165 path: CWD,
166 port: PORT
167 })
168 ).catch(err => {
169 process.send({
170 error: err ? err.stack : void 0,
171 message: 'error'
172 });
173 });
174 `;if(useStrict){data=`'use strict';\n\n${data}`;}yield writeFile(path__default.join(dir,'dist','boot.js'),data);});function createBootScript(_x,_x2){return _ref.apply(this,arguments)}return createBootScript})();
175
176let compile=(()=>{var _ref=asyncToGenerator(function*(dir,env,opts={}){const{useStrict=false}=opts;const local=path__default.join(__dirname,'..','src','index.js');const entry=path__default.join(dir,'dist','index.js');const external=isExternal(dir);let banner;const assets=yield Promise.all([readdir(path__default.join(dir,'app','models')),readdir(path__default.join(dir,'db','migrate')),readdirRec(path__default.join(dir,'app','controllers')),readdirRec(path__default.join(dir,'app','serializers'))]).then(function(types){let[models,migrations,controllers,serializers]=types;models=models.filter(isJSFile);migrations=migrations.filter(isJSFile);controllers=controllers.filter(isJSFile);serializers=serializers.filter(isJSFile);return new Map([['Application',path__default.join('app','index.js')],['config',path__default.join('config','environments',`${env}.js`)],['controllers',controllers],['database',path__default.join('config','database.js')],['migrations',migrations],['models',models],['routes',path__default.join('app','routes.js')],['seed',path__default.join('db','seed.js')],['serializers',serializers]])});yield Promise.all([createManifest(dir,assets,{useStrict}),createBootScript(dir,{useStrict})]);const aliases={app:path.posix.join('/',...dir.split(path__default.sep),'app'),LUX_LOCAL:path.posix.join('/',...local.split(path__default.sep))};if(os__default.platform()==='win32'){const[volume]=dir;const prefix=`${volume}:/`;Object.assign(aliases,{app:aliases.app.replace(prefix,''),LUX_LOCAL:aliases.LUX_LOCAL.replace(prefix,'')});}const bundle=yield rollup.rollup({entry,onwarn: handleWarning,external,plugins:[alias(Object.assign({resolve:['.js']},aliases)),json(),resolve$1(),eslint({cwd:dir,parser:'babel-eslint',useEslintrc:false,include:[path__default.join(dir,'app','**')],exclude:[path__default.join(dir,'package.json'),path__default.join(__dirname,'..','src','**')]}),babel({exclude:'node_modules/**'}),lux(path__default.resolve(path__default.sep,dir,'app'))]});yield rmrf$$1(entry);banner=template`
177 const srcmap = require('source-map-support').install({
178 environment: 'node'
179 });
180 `;if(useStrict){banner=`'use strict';\n\n${banner}`;}return bundle.write({banner,dest:path__default.join(dir,'dist','bundle.js'),format:'cjs',sourceMap:true,useStrict:false})});return function compile(_x,_x2){return _ref.apply(this,arguments)}})();
181
182let build=(()=>{var _ref=asyncToGenerator(function*(useStrict=false){const spinner=new Ora({text:'Building your application...',spinner:'dots'});spinner.start();yield compile(CWD,NODE_ENV,{useStrict});spinner.stop();});return function build(){return _ref.apply(this,arguments)}})();
183
184const drivers=new Map([['postgres','pg'],['sqlite','sqlite3'],['mysql','mysql2'],['mariadb','mariasql'],['oracle','oracle']]);function driverFor(database='sqlite'){return drivers.get(database)||'sqlite3'}
185
186var appTemplate = (name=>{const normalized=chain(name).pipe(underscore$1).pipe(inflection.classify).value();return template`
187 import { Application } from 'lux-framework';
188
189 class ${normalized} extends Application {
190
191 }
192
193 export default ${normalized};
194 `});
195
196var configTemplate = ((name,env)=>{const isTestENV=env==='test';const isProdENV=env==='production';return template`
197 export default {
198 logging: {
199 level: ${isProdENV?'\'INFO\'':'\'DEBUG\''},
200 format: ${isProdENV?'\'json\'':'\'text\''},
201 enabled: ${(!isTestENV).toString()},
202
203 filter: {
204 params: []
205 }
206 }
207 };
208 `});
209
210var routesTemplate = (()=>template`
211 export default function routes() {
212
213 }
214`);
215
216function indent(amount=1){return' '.repeat(amount)}
217
218var dbTemplate = ((name,driver)=>{const schemaName=underscore$1(name);let driverName=driver;let template='export default {\n';let username;if(!driverName){driverName='sqlite3';}if(driverName==='pg'){username='postgres';}else if(driverName!=='pg'&&driverName!=='sqlite3'){username='root';}['development','test','production'].forEach(environment=>{template+=`${indent(2)}${environment}: {\n`;if(driverName!=='sqlite3'){template+=`${indent(4)}pool: 5,\n`;}template+=`${indent(4)}driver: '${driverName}',\n`;if(username){template+=`${indent(4)}username: '${username}',\n`;}switch(environment){case'development':template+=`${indent(4)}database: '${schemaName}_dev'\n`;break;case'test':template+=`${indent(4)}database: '${schemaName}_test'\n`;break;case'production':template+=`${indent(4)}database: '${schemaName}_prod'\n`;break;default:template+=`${indent(4)}database: '${schemaName}_${environment}'\n`;break;}template+=`${indent(2)}}`;if(environment!=='production'){template+=',\n\n';}});template+='\n};\n';return template});
219
220var seedTemplate = (()=>template`
221 export default async function seed() {
222
223 }
224`);
225
226var version="1.1.3";var devDependencies={"babel-core":"6.21.0","babel-plugin-istanbul":"3.1.2","babel-plugin-transform-es2015-modules-commonjs":"6.18.0","babel-preset-lux":"2.0.1","chai":"3.5.0","eslint-config-airbnb-base":"11.0.1","eslint-plugin-flowtype":"2.30.0","eslint-plugin-import":"2.2.0","faker":"3.1.0","flow-bin":"0.37.4","flow-typed":"2.0.0","mocha":"3.2.0","mocha-junit-reporter":"1.13.0","node-fetch":"1.6.3","nyc":"10.0.0","remark-cli":"2.1.0","remark-lint":"5.4.0","remark-preset-lint-recommended":"1.0.0","rollup-plugin-multi-entry":"2.0.1","shx":"0.2.2","sinon":"1.17.7"};
227
228const LUX_VERSION=version;const BABEL_PRESET_VERSION=devDependencies['babel-preset-lux'];var pkgJSONTemplate = (name$$1=>template`
229 {
230 "name": "${name$$1}",
231 "version": "0.0.1",
232 "description": "",
233 "scripts": {
234 "start": "lux serve",
235 "test": "lux test"
236 },
237 "author": "",
238 "license": "MIT",
239 "dependencies": {
240 "babel-core": "6.17.0",
241 "babel-preset-lux": "${BABEL_PRESET_VERSION}",
242 "knex": "0.12.6",
243 "lux-framework": "${LUX_VERSION}"
244 },
245 "engines": {
246 "node": ">= 6.0"
247 }
248 }
249`);
250
251var babelrcTemplate = (()=>template`
252 {
253 "presets": ["lux"]
254 }
255`);
256
257var eslintrcTemplate = (()=>template`
258 {
259 "parser": "babel-eslint",
260 "extends": "eslint:recommended",
261 "env": {
262 "node": true
263 },
264 "globals": {
265 "Map": true,
266 "Set": true,
267 "Proxy": true,
268 "Promise": true,
269 "Reflect": true,
270 "WeakMap": true,
271 "WeakSet": true,
272 "Iterable": true
273 }
274 }
275`);
276
277var readmeTemplate = (name=>template`
278 # ${name}
279
280 ## Installation
281
282 * \`git clone https://github.com/<this-repository>\`
283 * \`cd ${name}\`
284 * \`npm install\`
285
286 ## Running / Development
287
288 * \`lux serve\`
289
290 ## Testing
291
292 * \`lux test\`
293
294 ## Further Reading / Useful Links
295 * [Lux](https://github.com/postlight/lux/)
296 * [Chai](http://chaijs.com/) / [Mocha](http://mochajs.org/)
297`);
298
299var licenseTemplate = (()=>template`
300 The MIT License (MIT)
301
302 Copyright (c) 2016
303
304 Permission is hereby granted, free of charge, to any person obtaining a copy
305 of this software and associated documentation files (the "Software"), to deal
306 in the Software without restriction, including without limitation the rights
307 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
308 copies of the Software, and to permit persons to whom the Software is
309 furnished to do so, subject to the following conditions:
310
311 The above copyright notice and this permission notice shall be included in all
312 copies or substantial portions of the Software.
313
314 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
315 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
316 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
317 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
318 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
319 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
320 SOFTWARE.
321`);
322
323var gitignoreTemplate = (()=>template`
324 # See http://help.github.com/ignore-files/ for more about ignoring files.
325
326 # dependencies
327 /node_modules
328
329 # build
330 /dist
331
332 # logs
333 /log
334 npm-debug.log
335
336 # misc
337 *.DS_Store
338`);
339
340const YES=/^y(es)?$/i;function createPrompt(){const prompt=readline.createInterface({input:process.stdin,output:process.stdout});prompt.setPrompt('');return{question(text){return new Promise(resolve$$1=>{prompt.question(text,answer=>{resolve$$1(YES.test(answer));});})},close(){prompt.close();}}}
341
342const NAMESPACED_RESOURCE_MESSAGE=template`
343
344 🎉 It looks like the resource you generated is within a namespace!
345
346 Lux will only update your 'routes.js' file if you generate a resource at the\
347 root namespace (i.e 'lux generate resource users').
348
349 In order to access the resource you have created, remember to manually update\
350 your 'routes.js' file.
351
352 Example:
353
354 export default function routes() {
355 ${chalk.dim('// this resource will be accessible at /users')}
356 this.resource('users');
357
358 this.namespace('admin', function () {
359 ${chalk.dim('// this resource will be accessible at /admin/users')}
360 this.resource('users');
361 });
362 }
363
364`;
365
366const VALID_DRIVERS=['pg','sqlite3','mssql','mysql','mysql2','mariasql','strong-oracle','oracle'];
367
368const DEBUG='DEBUG';const INFO='INFO';const WARN='WARN';const ERROR='ERROR';const FORMATS=new FreezeableSet(['text','json']);FORMATS.freeze();const LEVELS=new FreezeableMap([[DEBUG,0],[INFO,1],[WARN,2],[ERROR,3]]);LEVELS.freeze();
369
370const HAS_OBJECT_ENTRIES=typeof Object.entries==='function';function entries(source){if(HAS_OBJECT_ENTRIES){return Object.entries(source)}return Object.keys(source).reduce((result,key)=>{const value=Reflect.get(source,key);result.push([key,value]);return result},[])}
371
372function setType(fn){return fn()}
373
374function omit(src,...omitted){return setType(()=>entries(src).filter(([key])=>omitted.indexOf(key)<0).reduce((result,[key,value])=>Object.assign({},result,{[key]:value}),{}))}
375
376const ANSI=ansiRegex();const STDOUT=/^(DEBUG|INFO)$/;const STDERR=/^(WARN|ERROR)$/;
377
378function stringify(value,spaces){if(isObject(value)||Array.isArray(value)){return JSON.stringify(value,null,spaces)}return String(value)}
379
380function formatMessage(data,format){if(data instanceof Error){return data.stack}else if(format==='json'){return stringify(data).replace(ANSI,'')}return stringify(data,2)}
381
382function createWriter$1(format){return function write(data){const{level}=data;const etc=objectWithoutProperties(data,['level']);let{message,timestamp}=etc;let output;if(format==='json'){output={};if(message&&typeof message==='object'&&message.message){output=Object.assign({timestamp,level,message:message.message},omit(message,'message'));}else{output=Object.assign({timestamp,level,message},etc);}output=formatMessage(output,'json');}else{let columns=0;if(process.stdout instanceof tty.WriteStream){columns=process.stdout.columns;}message=formatMessage(message,'text');switch(level){case WARN:timestamp=chalk.yellow(`[${timestamp}]`);break;case ERROR:timestamp=chalk.red(`[${timestamp}]`);break;default:timestamp=chalk.dim(`[${timestamp}]`);break;}output=`${timestamp} ${message}\n\n${chalk.dim('-').repeat(columns)}\n`;}if(STDOUT.test(level)){process.stdout.write(`${output}\n`);}else if(STDERR.test(level)){process.stderr.write(`${output}\n`);}}}
383
384function line(strings,...values){return insertValues(strings,...values).replace(/(\r\n|\n|\r|)/gm,'').replace(/\s+/g,' ').trim()}
385
386function countDigits(num){const digits=Math.floor(Math.log10(num)+1);return digits>0&&Number.isFinite(digits)?digits:1}function pad(startTime,endTime,duration){const maxLength=countDigits(endTime-startTime);return' '.repeat(maxLength-countDigits(duration))+duration}const debugTemplate=({path: path$$1,stats,route,method,params,colorStr,startTime,endTime,statusCode,statusMessage,remoteAddress})=>`\
387${line`
388 Processed ${chalk.cyan(`${method}`)} "${path$$1}" from ${remoteAddress}
389 with ${Reflect.apply(colorStr,null,[`${statusCode}`])}
390 ${Reflect.apply(colorStr,null,[`${statusMessage}`])} by ${route?`${chalk.yellow(route.controller.constructor.name)}#${chalk.blue(route.action)}`:null}
391`}
392
393${chalk.magenta('Params')}
394
395${JSON.stringify(params,null,2)}
396
397${chalk.magenta('Stats')}
398
399${stats.map(stat=>{const{type,duration,controller}=stat;let{name}=stat;name=chalk.blue(name);if(type==='action'){name=`${chalk.yellow(controller)}#${name}`;}return`${pad(startTime,endTime,duration)} ms ${name}`}).join('\n')}
400${pad(startTime,endTime,stats.reduce((total,{duration})=>total+duration,0))} ms Total
401${(endTime-startTime).toString()} ms Actual\
402`;const infoTemplate=({path: path$$1,route,method,params,colorStr,startTime,endTime,statusCode,statusMessage,remoteAddress})=>line`
403Processed ${chalk.cyan(`${method}`)} "${path$$1}" ${chalk.magenta('Params')} ${JSON.stringify(params)} from ${remoteAddress} in ${(endTime-startTime).toString()} ms with ${Reflect.apply(colorStr,null,[`${statusCode}`])} ${Reflect.apply(colorStr,null,[`${statusMessage}`])} by ${route?`${chalk.yellow(route.controller.constructor.name)}#${chalk.blue(route.action)}`:null}
404`;
405
406function filterParams(params,...filtered){return entries(params).map(([key,value])=>[key,filtered.indexOf(key)>=0?'[FILTERED]':value]).reduce((result,[key,value])=>Object.assign({},result,{[key]:value&&typeof value==='object'&&!Array.isArray(value)?filterParams(value,...filtered):value}),{})}
407
408function logText(logger,{startTime,request:req,response:res}){res.once('finish',()=>{const endTime=Date.now();const{route,method,url:{path: path$$1},connection:{remoteAddress}}=req;const{stats,statusMessage}=res;let{params}=req;let{statusCode}=res;let statusColor;params=filterParams(params,...logger.filter.params);if(statusCode>=200&&statusCode<400){statusColor='green';}else{statusColor='red';}let colorStr=Reflect.get(chalk__default,statusColor);if(typeof colorStr==='undefined'){colorStr=str=>str;}statusCode=statusCode.toString();const templateData={path: path$$1,stats,route,method,params,colorStr,startTime,endTime,statusCode,statusMessage,remoteAddress};if(logger.level===DEBUG){logger.debug(debugTemplate(templateData));}else{logger.info(infoTemplate(templateData));}});}
409
410const MESSAGE='Processed Request';function logJSON(logger,{request:req,response:res}){res.once('finish',()=>{const{method,headers,httpVersion,url:{path: path$$1},connection:{remoteAddress}}=req;const{statusCode:status}=res;const userAgent=headers.get('user-agent');const protocol=`HTTP/${httpVersion}`;let{params}=req;params=filterParams(params,...logger.filter.params);logger.info({message:MESSAGE,method,path: path$$1,params,status,protocol,userAgent,remoteAddress});});}
411
412function createRequestLogger(logger){return function request(req,res,{startTime}){if(logger.format==='json'){logJSON(logger,{startTime,request:req,response:res});}else{logText(logger,{startTime,request:req,response:res});}}}
413
414const PATTERN=/(?:,?`|'|").+(?:`|'|"),?/;function sql(strings,...values){return insertValues(strings,...values).split(' ').map(part=>{if(PATTERN.test(part)){return part}return part.toUpperCase()}).join(' ')}
415
416class Logger{constructor({level,format,filter,enabled}){let write=K;let request=K;if(!LUX_CONSOLE&&enabled){write=createWriter$1(format);request=createRequestLogger(this);}Object.defineProperties(this,{level:{value:level,writable:false,enumerable:true,configurable:false},format:{value:format,writable:false,enumerable:true,configurable:false},filter:{value:filter,writable:false,enumerable:true,configurable:false},enabled:{value:Boolean(enabled),writable:false,enumerable:true,configurable:false},request:{value:request,writable:false,enumerable:false,configurable:false}});const levelNum=LEVELS.get(level)||0;LEVELS.forEach((val,key)=>{Reflect.defineProperty(this,key.toLowerCase(),{writable:false,enumerable:false,configurable:false,value:val>=levelNum?message=>{write({message,level:key,timestamp:this.getTimestamp()});}:K});});}getTimestamp(){return new Date().toISOString()}}
417
418class InvalidDriverError extends Error{constructor(driver){super(line`
419 Invalid database driver ${chalk.yellow(driver)} in ./config/database.js.
420 Please use one of the following database drivers:
421 ${VALID_DRIVERS.map(str=>chalk.green(str)).join(', ')}.
422 `);}}
423
424class ModelMissingError extends Error{constructor(name){super(`Could not resolve model by name '${name}'`);}}
425
426class MigrationsPendingError extends Error{constructor(migrations=[]){const pending=migrations.map(str=>chalk.yellow(str.substr(0,str.length-3))).join(', ');super(line`
427 The following migrations are pending ${pending}.
428 Please run ${chalk.green('lux db:migrate')} before starting your application.
429 `);}}
430
431function createServerError(Target,statusCode){return setType(()=>{const ServerError=class ServerError extends Target{constructor(...args){super(...args);this.statusCode=statusCode;}};Reflect.defineProperty(ServerError,'name',{value:Target.name});return ServerError})}
432
433class MalformedRequestError extends SyntaxError{constructor(){super(line`
434 There was an error parsing the request body. Please make sure that the
435 request body is a valid JSON API document.
436 `);}}createServerError(MalformedRequestError,400);
437
438const MIME_TYPE='application/vnd.api+json';
439
440class NotAcceptableError extends TypeError{constructor(contentType){super(line`
441 Media type parameters is not supported. Try your request again
442 without specifying '${contentType.replace(MIME_TYPE,'')}'.
443 `);}}createServerError(NotAcceptableError,406);
444
445class UnsupportedMediaTypeError extends TypeError{constructor(contentType){super(line`
446 Media type parameters is not supported. Try your request again
447 without specifying '${contentType.replace(MIME_TYPE,'')}'.
448 `);}}createServerError(UnsupportedMediaTypeError,415);
449
450class InvalidContentTypeError extends TypeError{constructor(contentType='undefined'){super(line`
451 Content-Type: '${contentType}' is not supported. Try your request again
452 with Content-Type: '${MIME_TYPE}'.
453 `);}}createServerError(InvalidContentTypeError,400);
454
455class UniqueConstraintError extends Error{}createServerError(UniqueConstraintError,409);
456
457class ConfigMissingError extends Error{constructor(environment){super(`Database config not found for environment ${environment}.`);}}
458
459class RecordNotFoundError extends Error{constructor({name,primaryKey},primaryKeyValue){super(`Could not find ${name} with ${primaryKey} ${stringify(primaryKeyValue)}.`);}}createServerError(RecordNotFoundError,404);
460
461function connect(path$$1,config={}){let{pool}=config;const{host,socket,driver,database,username,password,port,ssl,url: url$$1}=config;if(VALID_DRIVERS.indexOf(driver)<0){throw new InvalidDriverError(driver)}if(pool&&typeof pool==='number'){pool={min:pool>1?2:1,max:pool};}const knex=require(path.join(path$$1,'node_modules','knex'));const usingSQLite=driver==='sqlite3';const connection=DATABASE_URL||url$$1||{host,database,password,port,ssl,user:username,socketPath:socket,filename:usingSQLite?path.join(path$$1,'db',`${database||'default'}_${NODE_ENV}.sqlite`):undefined};return knex({pool,connection,debug:false,client:driver,useNullAsDefault:usingSQLite})}
462
463var createMigrations = (()=>{var _ref=asyncToGenerator(function*(schema){const hasTable=yield schema().hasTable('migrations');if(!hasTable){yield schema().createTable('migrations',function(table){table.string('version',16).primary();});}return true});function createMigrations(_x){return _ref.apply(this,arguments)}return createMigrations})();
464
465var pendingMigrations = (()=>{var _ref=asyncToGenerator(function*(appPath,table){const migrations=yield readdir(`${appPath}/db/migrate`);const versions=yield table().select().then(function(data){return data.map(function({version}){return version})});return migrations.filter(function(migration){return versions.indexOf(migration.replace(/^(\d{16})-.+$/g,'$1'))<0})});function pendingMigrations(_x,_x2){return _ref.apply(this,arguments)}return pendingMigrations})();
466
467var initialize$1 = (()=>{var _ref=asyncToGenerator(function*(instance,opts){const{path: path$$1,models,logger,checkMigrations}=opts;let{config}=opts;config=Reflect.get(config,NODE_ENV);if(!config){throw new ConfigMissingError(NODE_ENV)}const{debug=NODE_ENV==='development'}=config;Object.defineProperties(instance,{path:{value:path$$1,writable:false,enumerable:false,configurable:false},debug:{value:debug,writable:false,enumerable:false,configurable:false},models:{value:models,writable:false,enumerable:false,configurable:false},logger:{value:logger,writable:false,enumerable:false,configurable:false},config:{value:config,writable:false,enumerable:true,configurable:false},schema:{value:function(){return instance.connection.schema},writable:false,enumerable:false,configurable:false},connection:{value:connect(path$$1,config),writable:false,enumerable:false,configurable:false}});if(cluster.isMaster||cluster.worker&&cluster.worker.id===1){yield createMigrations(instance.schema);if(checkMigrations){const pending=yield pendingMigrations(path$$1,function(){return instance.connection('migrations')});if(pending.length){throw new MigrationsPendingError(pending)}}}yield Promise.all(Array.from(models.values()).map(function(model){return model.initialize(instance,function(){return instance.connection(model.tableName)})}));return instance});function initialize(_x,_x2){return _ref.apply(this,arguments)}return initialize})();
468
469var normalizeModelName = compose(inflection.singularize,inflection.dasherize,underscore$1);
470
471function formatInt(int){return(int/10).toString().replace('.','').substr(0,2)}function*padding(char,amount){for(let i=0;i<amount;i+=1){yield char;}}function generateTimestamp(){const now=new Date;const timestamp=now.toISOString().substr(0,10).split('-').join('')+formatInt(now.getHours())+formatInt(now.getMinutes())+formatInt(now.getSeconds())+formatInt(now.getMilliseconds());return timestamp+Array.from(padding('0',16-timestamp.length)).join('')}
472
473class Migration{constructor(fn){this.fn=fn;}run(schema){return this.fn(schema)}}
474
475class Database{constructor({path: path$$1,models,config,logger,checkMigrations}){return initialize$1(this,{path: path$$1,models,config,logger,checkMigrations})}modelFor(type){const model=this.models.get(normalizeModelName(type));if(!model){throw new ModelMissingError(type)}return model}}
476
477const VALID_ATTR=/^(\w|-)+:(\w|-)+$/;const RELATIONSHIP=/^belongs-to|has-(one|many)$/;var modelTemplate = ((name,attrs)=>{const normalized=chain(name).pipe(underscore$1).pipe(inflection.classify).value();return template`
478 import { Model } from 'lux-framework';
479
480 class ${normalized} extends Model {
481 ${entries((attrs||[]).filter(attr=>VALID_ATTR.test(attr)).map(attr=>attr.split(':')).filter(([,type])=>RELATIONSHIP.test(type)).reduce((types,[related,type])=>{const key=chain(type).pipe(underscore$1).pipe(str=>inflection.camelize(str,true)).value();const value=Reflect.get(types,key);if(value){const inverse=inflection.camelize(normalized,true);const relatedKey=chain(related).pipe(underscore$1).pipe(str=>inflection.camelize(str,true)).value();return Object.assign({},types,{[key]:[...value,`${indent(8)}${relatedKey}: {${os.EOL}`+`${indent(10)}inverse: '${inverse}'${os.EOL}`+`${indent(8)}}`]})}return types},{hasOne:[],hasMany:[],belongsTo:[]})).filter(([,value])=>value.length).reduce((result,[key,value],index)=>chain(result).pipe(str=>{if(index&&str.length){return`${str}${os.EOL.repeat(2)}`}return str}).pipe(str=>str+`${indent(index===0?2:6)}static ${key} = {${os.EOL}`+`${value.join(`,${os.EOL.repeat(2)}`)}${os.EOL}`+`${indent(6)}};`).value(),'')}
482 }
483
484 export default ${normalized};
485 `});
486
487var serializerTemplate = ((name,attrs)=>{let normalized=chain(name).pipe(underscore$1).pipe(inflection.classify).value();if(!normalized.endsWith('Application')){normalized=inflection.pluralize(normalized);}const body=entries(attrs.filter(attr=>/^(\w|-)+:(\w|-)+$/g.test(attr)).map(attr=>attr.split(':')).reduce((obj,parts)=>{const[,type]=parts;let[attr]=parts;let{hasOne,hasMany,attributes}=obj;attr=`${indent(8)}'${inflection.camelize(underscore$1(attr),true)}'`;switch(type){case'belongs-to':case'has-one':hasOne=[...hasOne,attr];break;case'has-many':hasMany=[...hasMany,attr];break;default:attributes=[...attributes,attr];}return{attributes,hasOne,hasMany}},{attributes:[],belongsTo:[],hasOne:[],hasMany:[]})).reduce((result,group,index)=>{const[key]=group;let[,value]=group;let str=result;if(value.length){value=value.join(',\n');if(index&&str.length){str+='\n\n';}str+=`${indent(index===0?2:6)}${key} = `+`[\n${value}\n${indent(6)}];`;}return str},'');return template`
488 import { Serializer } from 'lux-framework';
489
490 class ${normalized}Serializer extends Serializer {
491 ${body}
492 }
493
494 export default ${normalized}Serializer;
495 `});
496
497var controllerTemplate = ((name,attrs)=>{let normalized=chain(name).pipe(underscore$1).pipe(inflection.classify).value();if(!normalized.endsWith('Application')){normalized=inflection.pluralize(normalized);}const body=entries(attrs.filter(attr=>/^(\w|-)+:(\w|-)+$/g.test(attr)).map(attr=>attr.split(':')[0]).reduce((obj,attr)=>Object.assign({},obj,{params:[...obj.params,`${indent(8)}'${inflection.camelize(underscore$1(attr),true)}'`]}),{params:[]})).reduce((result,group,index)=>{const[key]=group;let[,value]=group;let str=result;if(value.length){value=value.join(',\n');if(index&&str.length){str+='\n\n';}str+=`${indent(index===0?2:6)}${key} = `+`[\n${value}\n${indent(6)}];`;}return str},'');return template`
498 import { Controller } from 'lux-framework';
499
500 class ${normalized}Controller extends Controller {
501 ${body}
502 }
503
504 export default ${normalized}Controller;
505 `});
506
507var emptyMigrationTemplate = (()=>template`
508 export function up(schema) {
509
510 }
511
512 export function down(schema) {
513
514 }
515`);
516
517var modelMigrationTemplate = ((name,attrs)=>{const indices=['id'];const table=chain(name).pipe(str=>str.substr(24)).pipe(underscore$1).pipe(inflection.pluralize).value();let body='';if(Array.isArray(attrs)){body=attrs.filter(attr=>/^(\w|-)+:(\w|-)+$/g.test(attr)).map(attr=>attr.split(':')).filter(([,type])=>!/^has-(one|many)$/g.test(type)).map(attr=>{let[column,type]=attr;column=underscore$1(column);if(type==='belongs-to'){type='integer';column=`${column}_id`;if(Array.isArray(indices)){indices.push(column);}}return[column,type]}).map((attr,index)=>{let[column]=attr;const[,type]=attr;const shouldIndex=indices.indexOf(column)>=0;column=`${indent(index>0?8:0)}table.${type}('${column}')`;return shouldIndex?`${column}.index();`:`${column};`}).join('\n');}return template`
518 export function up(schema) {
519 return schema.createTable('${table}', table => {
520 table.increments('id');
521 ${body}
522 table.timestamps();
523
524 table.index('created_at');
525 table.index('updated_at');
526 });
527 }
528
529 export function down(schema) {
530 return schema.dropTable('${table}');
531 }
532 `});
533
534var middlewareTemplate = (name=>{const normalized=chain(name).pipe(underscore$1).pipe(str=>inflection.camelize(str,true)).value();return template`
535 export default function ${normalized}(/*request, response*/) {
536
537 }
538 `});
539
540var utilTemplate = (name=>{const normalized=chain(name).pipe(underscore$1).pipe(str=>inflection.camelize(str,true)).value();return template`
541 export default function ${normalized}() {
542
543 }
544 `});
545
546function log(data){if(data instanceof Error){process.stdout.write(`${data.stack||data.message}\n`);}else{process.stderr.write(`${data}\n`);}}
547
548const FORWARD_SLASH=/\//g;function createGenerator({dir,template,hasConflict=exists$$1}){return(()=>{var _ref2=asyncToGenerator(function*(_ref){let{cwd,attrs,onConflict}=_ref;let opts=objectWithoutProperties(_ref,['cwd','attrs','onConflict']);const path$$1=resolvePath(cwd,dir,`${opts.name}.js`);const name=opts.name.replace(FORWARD_SLASH,'-');let action=chalk.green('create');yield mkdirRec(path$$1.dir);if(yield hasConflict(path$$1.absolute)){const shouldContinue=yield onConflict(path$$1.relative);if(shouldContinue&&typeof shouldContinue==='string'){yield rmrf$$1(path.join(path$$1.dir,shouldContinue));log(`${chalk.red('remove')} ${path.join(dir,shouldContinue)}`);}else if(shouldContinue&&typeof shouldContinue==='boolean'){action=chalk.yellow('overwrite');yield rmrf$$1(path$$1.absolute);}else{log(`${chalk.yellow('skip')} ${path$$1.relative}`);return}}yield writeFile(path$$1.absolute,template(name,attrs));log(`${action} ${path$$1.relative}`);});return function(_x){return _ref2.apply(this,arguments)}})()}
549
550function detectConflict(path$$1){const{dir,base}=resolvePath(path$$1);const pattern=new RegExp(`^\\d+-${base.substr(17)}$`);return exists$$1(pattern,dir)}function createConflictResolver({cwd,onConflict}){return(()=>{var _ref=asyncToGenerator(function*(path$$1){if(yield onConflict(path$$1)){const parsed=resolvePath(cwd,path$$1);const migrations=yield readdir(parsed.dir);return migrations.find(function(file){return file.substr(17)===parsed.base.substr(17)})||false}return false});return function(_x){return _ref.apply(this,arguments)}})()}
551
552let controller=(()=>{var _ref=asyncToGenerator(function*(opts){const{cwd}=opts;let{name}=opts;const dir=path.join('app','controllers');const generate=createGenerator({dir,template:controllerTemplate});if(!name.endsWith('application')){name=inflection.pluralize(name);}yield generate(Object.assign({},opts,{cwd,name}));const namespace=path.posix.dirname(name);if(namespace==='.'){return}const hasParent=yield exists$$1(path.join(cwd,dir,namespace.split('/'),'application.js'));if(!hasParent){yield controller(Object.assign({},opts,{cwd,name:`${namespace}/application`,attrs:[]}));}});return function controller(_x){return _ref.apply(this,arguments)}})();let serializer=(()=>{var _ref2=asyncToGenerator(function*(opts){const{cwd}=opts;let{name}=opts;const dir=path.join('app','serializers');const generate=createGenerator({dir,template:serializerTemplate});if(!name.endsWith('application')){name=inflection.pluralize(name);}yield generate(Object.assign({},opts,{cwd,name}));const namespace=path.posix.dirname(name);if(namespace==='.'){return}const hasParent=yield exists$$1(path.join(cwd,dir,...[...namespace.split('/'),'application.js']));if(!hasParent){yield serializer(Object.assign({},opts,{cwd,name:`${namespace}/application`,attrs:[]}));}});return function serializer(_x2){return _ref2.apply(this,arguments)}})();function migration(opts){const{cwd,onConflict}=opts;let{name}=opts;const dir=path.join('db','migrate');const generate=createGenerator({dir,template:emptyMigrationTemplate,hasConflict:detectConflict});name=chain(name).pipe(path.posix.basename).pipe(str=>`${generateTimestamp()}-${str}`).value();return generate(Object.assign({},opts,{cwd,name,onConflict:createConflictResolver({cwd,onConflict})}))}function modelMigration(opts){const{cwd,onConflict}=opts;let{name}=opts;const dir=path.join('db','migrate');const generate=createGenerator({dir,template:modelMigrationTemplate,hasConflict:detectConflict});name=chain(name).pipe(path.posix.basename).pipe(inflection.pluralize).pipe(str=>`${generateTimestamp()}-create-${str}`).value();return generate(Object.assign({},opts,{cwd,name,onConflict:createConflictResolver({cwd,onConflict})}))}let model=(()=>{var _ref3=asyncToGenerator(function*(opts){let{name}=opts;const generate=createGenerator({dir:path.join('app','models'),template:modelTemplate});yield modelMigration(Object.assign({name},opts));name=chain(name).pipe(path.posix.basename).pipe(inflection.singularize).value();return generate(Object.assign({},opts,{name}))});return function model(_x3){return _ref3.apply(this,arguments)}})();function middleware(opts){let{name}=opts;const parts=name.split('/');name=parts.pop()||name;const generate=createGenerator({dir:path.join('app','middleware',...parts),template:middlewareTemplate});return generate(Object.assign({},opts,{name}))}function util(opts){let{name}=opts;const parts=name.split('/');name=parts.pop()||name;const generate=createGenerator({dir:path.join('app','utils',...parts),template:utilTemplate});return generate(Object.assign({},opts,{name}))}let resource=(()=>{var _ref4=asyncToGenerator(function*(opts){yield model(opts);yield controller(opts);yield serializer(opts);if(path.posix.dirname(opts.name)==='.'){log(NAMESPACED_RESOURCE_MESSAGE);return}const path$$1=path.join(opts.cwd,'app','routes.js');const routes=chain((yield readFile(path$$1))).pipe(function(buf){return buf.toString('utf8')}).pipe(function(str){return str.split('\n')}).pipe(function(lines){return lines.reduce(function(result,line,index,arr){const closeIndex=arr.lastIndexOf('}');let str=result;if(line&&index<=closeIndex){str+=`${line}\n`;}if(index+1===closeIndex){str+=` this.resource('${inflection.pluralize(opts.name)}');\n`;}return str},'')}).value();yield writeFile(path$$1,routes);log(`${chalk.green('update')} app/routes.js`);});return function resource(_x4){return _ref4.apply(this,arguments)}})();
553
554
555
556var generators = Object.freeze({
557 controller: controller,
558 serializer: serializer,
559 migration: migration,
560 modelMigration: modelMigration,
561 model: model,
562 middleware: middleware,
563 util: util,
564 resource: resource
565});
566
567function generatorFor(type){const normalized=type.toLowerCase();const generator=Reflect.get(generators,normalized);if(!generator){throw new Error(`Could not find a generator for '${type}'.`)}return generator}
568
569let runGenerator=(()=>{var _ref=asyncToGenerator(function*({cwd,type,name,attrs}){const generator=generatorFor(type);const prompt=createPrompt();yield generator({cwd,type,name,attrs,onConflict:function(path$$1){return prompt.question(`${chalk.green('?')} ${chalk.red('Overwrite')} ${path$$1}? (Y/n)\r`)}});prompt.close();});return function runGenerator(_x){return _ref.apply(this,arguments)}})();
570
571function generate({cwd=CWD,name,type,attrs=[]}){return runGenerator({cwd,name,type,attrs})}
572
573let create=(()=>{var _ref=asyncToGenerator(function*(name,database){const driver=driverFor(database);const project=`${CWD}/${name}`;yield mkdir(project);yield Promise.all([mkdir(`${project}/app`),mkdir(`${project}/config`),mkdir(`${project}/db`)]);yield Promise.all([mkdir(`${project}/app/models`),mkdir(`${project}/app/serializers`),mkdir(`${project}/app/controllers`),mkdir(`${project}/app/middleware`),mkdir(`${project}/app/utils`),mkdir(`${project}/config/environments`),mkdir(`${project}/db/migrate`)]);yield Promise.all([writeFile(`${project}/app/index.js`,appTemplate(name)),writeFile(`${project}/app/routes.js`,routesTemplate()),writeFile(`${project}/config/environments/development.js`,configTemplate(name,'development')),writeFile(`${project}/config/environments/test.js`,configTemplate(name,'test')),writeFile(`${project}/config/environments/production.js`,configTemplate(name,'production')),writeFile(`${project}/config/database.js`,dbTemplate(name,driver)),writeFile(`${project}/db/seed.js`,seedTemplate()),writeFile(`${project}/README.md`,readmeTemplate(name)),writeFile(`${project}/LICENSE`,licenseTemplate()),writeFile(`${project}/package.json`,pkgJSONTemplate(name,database)),writeFile(`${project}/.babelrc`,babelrcTemplate()),writeFile(`${project}/.eslintrc.json`,eslintrcTemplate()),writeFile(`${project}/.gitignore`,gitignoreTemplate())]);const logOutput=template`
574 ${chalk.green('create')} app/index.js
575 ${chalk.green('create')} app/routes.js
576 ${chalk.green('create')} bin/app.js
577 ${chalk.green('create')} config/environments/development.js
578 ${chalk.green('create')} config/environments/test.js
579 ${chalk.green('create')} config/environments/production.js
580 ${chalk.green('create')} config/database.js
581 ${chalk.green('create')} db/migrate
582 ${chalk.green('create')} db/seed.js
583 ${chalk.green('create')} README.md
584 ${chalk.green('create')} LICENSE
585 ${chalk.green('create')} package.json
586 ${chalk.green('create')} .babelrc
587 ${chalk.green('create')} .eslintrc.json
588 ${chalk.green('create')} .gitignore
589 `;process.stdout.write(logOutput.substr(0,logOutput.length-1));process.stdout.write(os.EOL);yield Promise.all([generate({cwd:project,type:'serializer',name:'application'}),generate({cwd:project,type:'controller',name:'application'})]);yield exec$1('git init && git add .',{cwd:project});process.stdout.write(`${chalk.green('initialize')} git`);process.stdout.write(os.EOL);const spinner=new Ora({text:'Installing dependencies from npm...',spinner:'dots'});spinner.start();yield exec$1('npm install',{cwd:project});yield exec$1(`npm install --save --save-exact ${driver}`,{cwd:project});spinner.stop();});return function create(_x,_x2){return _ref.apply(this,arguments)}})();
590
591const GITHUB_URL='https://github.com/postlight/lux';function fileLink(path$$1,{line,branch='master'}={}){let link=`${GITHUB_URL}/blob/${branch}/${path$$1}`;if(typeof line==='number'&&line>=0){link+=`#${line}`;}return link}
592
593const DB_INTERFACE_URL=fileLink('src/packages/database/interfaces.js',{line:17});const CONNECTION_STRING_MESSAGE=template`
594
595 You're using a URL in your database config (config/database.js).
596
597 In that case, Lux assumes you don't need to create or drop your database.
598 If you'd like to create or drop a database, set up your database config
599 without the url.
600
601 For guidance, see:
602 ${DB_INTERFACE_URL}
603`;
604
605function createDefaultConfig(){const isTestENV=NODE_ENV==='test';const isProdENV=NODE_ENV==='production';return{server:{cors:{enabled:false}},logging:{level:isProdENV?'INFO':'DEBUG',format:isProdENV?'json':'text',enabled:!isTestENV,filter:{params:[]}}}}
606
607function hasOwnProperty$1(target,key){return Reflect.apply(Object.prototype.hasOwnProperty,target,[key])}function merge(dest,source){return setType(()=>entries(source).reduce((result,[key,value])=>{if(hasOwnProperty$1(result,key)&&isObject(value)){const currentValue=Reflect.get(result,key);if(isObject(currentValue)){return Object.assign({},result,{[key]:merge(currentValue,value)})}}return Object.assign({},result,{[key]:value})},Object.assign({},dest)))}
608
609const NAMESPACE_DELIMITER=/\$-/g;function formatKey(key,formatter){return chain(key).pipe(str=>{if(formatter){return formatter(str)}return str}).pipe(underscore$1).pipe(inflection.dasherize).pipe(str=>str.replace(NAMESPACE_DELIMITER,'/')).value()}
610
611const SUFFIX_PATTERN=/^.+(Controller|Down|Serializer|Up)/;function normalize$1(manifest){return entries(manifest).reduce((obj,[key,value])=>{if(SUFFIX_PATTERN.test(key)){const suffix=key.replace(SUFFIX_PATTERN,'$1');const stripSuffix=source=>source.replace(suffix,'');switch(suffix){case'Controller':obj.controllers.set(formatKey(key,stripSuffix),value);break;case'Serializer':obj.serializers.set(formatKey(key,stripSuffix),value);break;case'Up':case'Down':obj.migrations.set(formatKey(key),Reflect.construct(Migration,[value]));break;default:break;}}else{switch(key){case'Application':case'routes':case'seed':Reflect.set(obj,formatKey(key),value);break;case'config':Reflect.set(obj,'config',Object.assign({},merge(createDefaultConfig(),Object.assign({},obj.config,value))));break;case'database':Reflect.set(obj,'config',Object.assign({},obj.config,{database:value}));break;default:obj.models.set(formatKey(key),value);break;}}return obj},{config:{},controllers:new FreezeableMap,migrations:new FreezeableMap,models:new FreezeableMap,serializers:new FreezeableMap})}function bundleFor(path$$1){const manifest=Reflect.apply(require,null,[path.join(path$$1,'dist','bundle')]);return chain(manifest).pipe(normalize$1).pipe(entries).construct(FreezeableMap).value().freeze()}
612
613function createLoader(path$$1){let bundle;return function load(type){if(!bundle){bundle=bundleFor(path$$1);}return bundle.get(type)}}
614
615let dbcreate=(()=>{var _ref=asyncToGenerator(function*(){const load=createLoader(CWD);let cfg=load('config');cfg=Reflect.get(cfg.database,NODE_ENV);const{url: url$$1,driver,database}=cfg;const config=objectWithoutProperties(cfg,['url','driver','database']);if(driver==='sqlite3'){yield writeFile(`${CWD}/db/${database}_${NODE_ENV}.sqlite`,'');}else{if(DATABASE_URL||url$$1){process.stderr.write(CONNECTION_STRING_MESSAGE);process.stderr.write(os.EOL);return}const{schema}=connect(CWD,Object.assign({},config,{driver}));const query=schema.raw(`CREATE DATABASE ${database}`);query.on('query',function(){process.stdout.write(query.toString());process.stdout.write(os.EOL);});yield query;}});return function dbcreate(){return _ref.apply(this,arguments)}})();
616
617let dbdrop=(()=>{var _ref=asyncToGenerator(function*(){const load=createLoader(CWD);let cfg=load('config');cfg=Reflect.get(cfg.database,NODE_ENV);const{url: url$$1,driver,database}=cfg;const config=objectWithoutProperties(cfg,['url','driver','database']);if(driver==='sqlite3'){yield rmrf$$1(`${CWD}/db/${database}_${NODE_ENV}.sqlite`);}else{if(DATABASE_URL||url$$1){process.stderr.write(CONNECTION_STRING_MESSAGE);process.stderr.write(os.EOL);return}const{schema}=connect(CWD,Object.assign({},config,{driver}));const query=schema.raw(`DROP DATABASE IF EXISTS ${database}`);query.on('query',function(){process.stdout.write(query.toString());process.stdout.write(os.EOL);});yield query;}});return function dbdrop(){return _ref.apply(this,arguments)}})();
618
619let dbmigrate=(()=>{var _ref=asyncToGenerator(function*(){const load=createLoader(CWD);const{database:config}=load('config');const models=load('models');const migrations=load('migrations');const{connection,schema}=yield new Database({config,models,path:CWD,checkMigrations:false,logger:new Logger({enabled:false})});const pending=yield pendingMigrations(CWD,function(){return connection('migrations')});if(pending.length){const runners=pending.map(function(name){const version=name.replace(/^(\d{16})-.+$/g,'$1');const key=name.replace(new RegExp(`${version}-(.+)\\.js`),'$1');return[version,migrations.get(`${key}-up`)]}).filter(function([,migration]){return Boolean(migration)}).reverse().map(function([version,migration]){return function(){const query=migration.run(schema());return query.on('query',function(){process.stdout.write(sql`${query.toString()}`);process.stdout.write(os.EOL);}).then(function(){return connection('migrations').insert({version})})}});yield composeAsync(...runners)();}return true});return function dbmigrate(){return _ref.apply(this,arguments)}})();
620
621let dbrollback=(()=>{var _ref=asyncToGenerator(function*(){const load=createLoader(CWD);const{database:config}=load('config');const models=load('models');const migrations=load('migrations');const{connection,schema}=yield new Database({config,models,path:CWD,checkMigrations:false,logger:new Logger({enabled:false})});const migrationFiles=yield readdir(`${CWD}/db/migrate`);if(migrationFiles.length){let migration;let version=yield connection('migrations').orderBy('version','desc').first();if(version&&version.version){version=version.version;}const target=migrationFiles.find(function(m){return m.indexOf(version)===0});if(target){migration=target.replace(new RegExp(`${version}-(.+)\\.js`),'$1');migration=migrations.get(`${migration}-down`);if(migration){const query=migration.run(schema());yield query.on('query',function(){process.stdout.write(sql`${query.toString()}`);process.stdout.write(os.EOL);});yield connection('migrations').where({version}).del();}}}});return function dbrollback(){return _ref.apply(this,arguments)}})();
622
623function dbseed(){const load=createLoader(CWD);const{database:config}=load('config');const seed=load('seed');const models=load('models');return new Database({config,models,path:CWD,logger:new Logger({enabled:false})}).then(store=>store.connection.transaction(seed))}
624
625let destroyType=(()=>{var _ref=asyncToGenerator(function*(type,name){const normalizedType=type.toLowerCase();let normalizedName=name;let path$$1;let migrations;switch(normalizedType){case'model':normalizedName=inflection.singularize(normalizedName);path$$1=`app/${inflection.pluralize(normalizedType)}/${normalizedName}.js`;break;case'migration':migrations=yield readdir(`${CWD}/db/migrate`);normalizedName=migrations.find(function(file){return`${normalizedName}.js`===file.substr(17)});path$$1=`db/migrate/${normalizedName}`;break;case'controller':case'serializer':normalizedName=inflection.pluralize(normalizedName);path$$1=`app/${inflection.pluralize(normalizedType)}/${normalizedName}.js`;break;case'middleware':path$$1=`app/${normalizedType}/${normalizedName}.js`;break;case'util':path$$1=`app/${inflection.pluralize(normalizedType)}/${normalizedName}.js`;break;default:return;}if(yield exists$$1(`${CWD}/${path$$1}`)){yield rmrf$$1(`${CWD}/${path$$1}`);process.stdout.write(`${chalk.red('remove')} ${path$$1}`);process.stdout.write(os.EOL);}});return function destroyType(_x,_x2){return _ref.apply(this,arguments)}})();let destroy$1=(()=>{var _ref2=asyncToGenerator(function*({type,name}){if(type==='resource'){const routes=(yield readFile(`${CWD}/app/routes.js`)).toString('utf8').split('\n').reduce(function(lines,line){const pattern=new RegExp(`\\s*this.resource\\(('|"|\`)${inflection.pluralize(name)}('|"|\`)\\);?`);return pattern.test(line)?lines:[...lines,line]},'').join('\n');yield Promise.all([destroyType('model',name),destroyType('migration',`create-${inflection.pluralize(name)}`),destroyType('serializer',name),destroyType('controller',name)]);yield writeFile(`${CWD}/app/routes.js`,routes);process.stdout.write(`${chalk.green('update')} app/routes.js`);process.stdout.write(os.EOL);}else if(type==='model'){yield Promise.all([destroyType(type,name),destroyType('migration',`create-${inflection.pluralize(name)}`)]);}else{yield destroyType(type,name);}});return function destroy(_x3){return _ref2.apply(this,arguments)}})();
626
627function repl$1(){return new Promise((()=>{var _ref=asyncToGenerator(function*(resolve$$1){const app=yield Reflect.apply(require,null,[path__default.join(CWD,'dist','boot')]);const instance=repl.start({prompt:'> '});instance.once('exit',resolve$$1);Object.assign(instance.context,Object.assign({app,logger:app.logger,routes:app.router,[app.constructor.name]:app},Array.from(app.models).reduce(function(context,[,model]){return Object.assign({},context,{[model.name]:model})},{}),Array.from(app.controllers).reduce(function(context,[,controller]){return Object.assign({},context,{[controller.constructor.name]:controller})},{}),Array.from(app.serializers).reduce(function(context,[,serializer]){return Object.assign({},context,{[serializer.constructor.name]:serializer})},{})));});return function(_x){return _ref.apply(this,arguments)}})())}
628
629function*range(start$$1,end){for(let i=start$$1;i<=end;i+=1){yield i;}}
630
631class Cluster extends EventEmitter{constructor({path: path$$1,port,logger,maxWorkers}){super();Object.defineProperties(this,{path:{value:path$$1,writable:false,enumerable:true,configurable:false},port:{value:port,writable:false,enumerable:true,configurable:false},logger:{value:logger,writable:false,enumerable:true,configurable:false},workers:{value:new Set,writable:false,enumerable:true,configurable:false},maxWorkers:{value:maxWorkers||os__default.cpus().length,writable:false,enumerable:true,configurable:false}});cluster__default.setupMaster({exec:path.join(path$$1,'dist','boot.js')});process.on('update',changed=>{changed.forEach(({name:filename})=>{logger.info(`${chalk.green('update')} ${filename}`);});this.reload();});this.forkAll().then(()=>this.emit('ready'));}fork(retry=true){return new Promise(resolve$$1=>{if(this.workers.size<this.maxWorkers){const worker$$1=cluster__default.fork({NODE_ENV,PORT:this.port});const timeout=setTimeout(()=>{this.logger.info(line`
632 Removing worker process: ${chalk.red(`${worker$$1.process.pid}`)}
633 `);clearTimeout(timeout);worker$$1.removeAllListeners();worker$$1.kill();this.workers.delete(worker$$1);resolve$$1(worker$$1);if(retry){this.fork(false);}},30000);const handleError=err=>{if(err){this.logger.error(err);}this.logger.info(line`
634 Removing worker process: ${chalk.red(`${worker$$1.process.pid}`)}
635 `);clearTimeout(timeout);worker$$1.removeAllListeners();worker$$1.kill();this.workers.delete(worker$$1);resolve$$1(worker$$1);};worker$$1.on('message',msg=>{let data={};let message=msg;if(typeof message==='object'){data=omit(message,'message');message=message.message;}switch(message){case'ready':this.logger.info(line`
636 Adding worker process: ${chalk.green(`${worker$$1.process.pid}`)}
637 `);this.workers.add(worker$$1);clearTimeout(timeout);worker$$1.removeListener('error',handleError);resolve$$1(worker$$1);break;case'error':handleError(data.error);break;default:break;}});worker$$1.once('error',handleError);worker$$1.once('exit',code=>{const{process:{pid}}=worker$$1;if(typeof code==='number'){this.logger.info(line`
638 Worker process: ${chalk.red(`${pid}`)} exited with code ${code}
639 `);}this.logger.info(`Removing worker process: ${chalk.red(`${pid}`)}`);clearTimeout(timeout);worker$$1.removeAllListeners();this.workers.delete(worker$$1);this.fork();});}})}shutdown(worker$$1){return new Promise(resolve$$1=>{this.workers.delete(worker$$1);worker$$1.send('shutdown');worker$$1.disconnect();const timeout=setTimeout(()=>worker$$1.kill(),5000);worker$$1.once('exit',()=>{resolve$$1(worker$$1);clearTimeout(timeout);});})}reload(){if(this.workers.size){const groups=Array.from(this.workers).reduce((arr,item,idx,src)=>{if((idx+1)%2){const group=src.slice(idx,idx+2);return[...arr,()=>Promise.all(group.map(worker$$1=>this.shutdown(worker$$1)))]}return arr},[]);return composeAsync(...groups)()}return this.fork()}forkAll(){return Promise.race(Array.from(range(1,this.maxWorkers)).map(()=>this.fork()))}}
640
641function createCluster({path: path$$1,port,logger,maxWorkers}){return new Cluster({path: path$$1,port,logger,maxWorkers})}
642
643let serve=(()=>{var _ref=asyncToGenerator(function*({hot=NODE_ENV==='development',cluster: cluster$$1=false,useStrict=false}){const load=createLoader(CWD);const{logging}=load('config');const logger=new Logger(logging);if(hot){const watcher=yield watch$1(CWD);watcher.on('change',(()=>{var _ref2=asyncToGenerator(function*(changed){yield build(useStrict);process.emit('update',changed);});return function(_x2){return _ref2.apply(this,arguments)}})());}createCluster({logger,path:CWD,port:PORT,maxWorkers:cluster$$1?undefined:1}).once('ready',function(){logger.info(`Lux Server listening on port: ${chalk.cyan(`${PORT}`)}`);});});return function serve(_x){return _ref.apply(this,arguments)}})();
644
645function test(){process.stdout.write('Coming Soon!');process.stdout.write(os.EOL);return Promise.resolve()}
646
647exports.build = build;
648exports.create = create;
649exports.dbcreate = dbcreate;
650exports.dbdrop = dbdrop;
651exports.dbmigrate = dbmigrate;
652exports.dbrollback = dbrollback;
653exports.dbseed = dbseed;
654exports.destroy = destroy$1;
655exports.generate = generate;
656exports.repl = repl$1;
657exports.serve = serve;
658exports.test = test;
659//# sourceMappingURL=index.js.map