UNPKG

@resin/pinejs

Version:

Pine.js is a sophisticated rules-driven API engine that enables you to define rules in a structured subset of English. Those rules are used in order for Pine.js to generate a database schema and the associated [OData](http://www.odata.org/) API. This make

188 lines (171 loc) 5.57 kB
_ = require 'lodash' Promise = require 'bluebird' sbvrUtils = require '../sbvr-api/sbvr-utils' permissions = require '../sbvr-api/permissions' fs = Promise.promisifyAll(require('fs')) # Setup function exports.setup = (app) -> loadConfig = (data) -> sbvrUtils.db.transaction (tx) -> Promise.map data.models, (model) -> if model.modelText? sbvrUtils.executeModel(tx, model) .then -> console.info('Sucessfully executed ' + model.modelName + ' model.') .catch (err) -> throw new Error(['Failed to execute ' + model.modelName + ' model from ' + model.modelFile, err, err.stack]) .then -> authApiTx = sbvrUtils.api.Auth.clone passthrough: tx: tx req: permissions.root if data.users? permissions = {} for user in data.users when user.permissions? _.each user.permissions, (permissionName) -> permissions[permissionName] ?= authApiTx.get resource: 'permission' options: $select: 'id' $filter: name: permissionName .then (result) -> if result.length is 0 authApiTx.post resource: 'permission' body: name: permissionName options: { returnResource: false } .get('id') else return result[0].id .tapCatch (e) -> e.message = 'Could not create or find permission "' + permissionName + '": ' + e.message Promise.map data.users, (user) -> authApiTx.get resource: 'user' options: $select: 'id' $filter: username: user.username .then (result) -> if result.length is 0 authApiTx.post resource: 'user' body: username: user.username password: user.password options: { returnResource: false } .get('id') else return result[0].id .then (userID) -> if user.permissions? Promise.map user.permissions, (permissionName) -> permissions[permissionName] .then (permissionID) -> authApiTx.get resource: 'user__has__permission' options: $select: 'id' $filter: user: userID permission: permissionID .then (result) -> if result.length is 0 authApiTx.post resource: 'user__has__permission' body: user: userID permission: permissionID options: { returnResource: false } .tapCatch (e) -> e.message = 'Could not create or find user "' + user.username + '": ' + e.message .then -> Promise.map data.models, (model) -> if model.modelText? apiRoute = '/' + model.apiRoot + '/*' app.options(apiRoute, (req, res) -> res.sendStatus(200)) app.all(apiRoute, sbvrUtils.handleODataRequest) if model.customServerCode? if _.isObject(model.customServerCode) customCode = model.customServerCode else try customCode = nodeRequire(model.customServerCode) catch e e.message = 'Error loading custom server code: ' + e.message throw e if !_.isFunction(customCode.setup) return try new Promise (resolve, reject) -> promise = customCode.setup app, sbvrUtils, sbvrUtils.db, (err) -> if err reject(err) else resolve() if Promise.is(promise) resolve(promise) catch e e.message = 'Error running custom server code: ' + e.message throw e loadJSON = (path) -> console.info('Loading JSON:', path) json = fs.readFileSync(path, 'utf8') return JSON.parse(json) loadApplicationConfig = (config) -> if !require.extensions['.coffee']? try # Try to register the coffee-script loader if it doesn't exist # We ignore if it fails though, since that probably just means it is not available/needed. require('coffee-script/register') if !require.extensions['.ts']? try require('ts-node/register') path = require('path') console.info('Loading application config') switch typeof config when 'undefined' root = process.argv[2] or __dirname config = loadJSON(path.join(root, 'config.json')) when 'string' root = path.dirname(config) config = loadJSON(config) when 'object' root = process.cwd() Promise.map config.models, (model) -> fs.readFileAsync(path.join(root, model.modelFile), 'utf8') .then (modelText) -> model.modelText = modelText if model.customServerCode? model.customServerCode = root + '/' + model.customServerCode .then -> model.migrations ||= {} if model.migrationsPath migrationsPath = path.join(root, model.migrationsPath) delete model.migrationsPath fs.readdirAsync(migrationsPath) .map (filename) -> filePath = path.join(migrationsPath, filename) migrationKey = filename.split('-')[0] switch path.extname(filename) when '.coffee', '.js' fn = nodeRequire(filePath) model.migrations[migrationKey] = fn when '.sql' fs.readFileAsync(filePath) .then (sqlBuffer) -> model.migrations[migrationKey] = sqlBuffer.toString() else console.error("Unrecognised migration file extension, skipping: #{path.extname filename}") .then -> loadConfig(config) .catch (err) -> console.error('Error loading application config', err, err.stack) process.exit(1) return { loadConfig loadApplicationConfig }