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

268 lines (255 loc) • 7.48 kB
Promise = require 'bluebird' permissions = require '../sbvr-api/permissions' uiModel = ''' Vocabulary: ui Term: text Concept type: Text (Type) Term: name Concept type: Short Text (Type) Term: textarea --Database id Field: name Reference Scheme: text Fact type: textarea is disabled Fact type: textarea has name Necessity: Each textarea has exactly 1 name Necessity: Each name is of exactly 1 textarea Fact type: textarea has text Necessity: Each textarea has exactly 1 text''' # Middleware isServerOnAir = do -> resolve = null promise = new Promise (_resolve) -> resolve = _resolve (value) -> if value? if promise.isPending() resolve(value) resolve = null else promise = Promise.fulfilled(value) return promise serverIsOnAir = (req, res, next) -> isServerOnAir().then (onAir) -> if onAir next() else next('route') # Setup function exports.config = models: [ modelName: 'ui', modelText: uiModel apiRoot: 'ui' customServerCode: exports ] exports.setup = (app, sbvrUtils, db) -> uiApi = sbvrUtils.api.ui devApi = sbvrUtils.api.dev setupModels = (tx) -> uiApiTx = uiApi.clone passthrough: tx: tx req: permissions.root uiApiTx.get resource: 'textarea' options: $select: 'id' $filter: name: 'model_area' .then (result) -> if result.length is 0 # Add a model_area entry if it doesn't already exist. uiApiTx.post resource: 'textarea' body: name: 'model_area' text: ' ' .then -> devApi.get resource: 'model' passthrough: tx: tx req: permissions.rootRead options: $select: ['is_of__vocabulary', 'model_value'] $filter: model_type: 'se' is_of__vocabulary: 'data' .then (result) -> if result.length is 0 throw new Error('No SE data model found') instance = result[0] sbvrUtils.executeModel(tx, apiRoot: instance.is_of__vocabulary modelText: instance.model_value ) .then -> isServerOnAir(true) .catch (err) -> isServerOnAir(false) app.get '/onAir', (req, res, next) -> isServerOnAir() .then (onAir) -> res.json(onAir) app.post '/update', permissions.checkPermissionsMiddleware('all'), serverIsOnAir, (req, res, next) -> res.sendStatus(404) app.post '/execute', permissions.checkPermissionsMiddleware('all'), (req, res, next) -> uiApi.get resource: 'textarea' passthrough: req: permissions.rootRead options: $select: 'text' $filter: name: 'model_area' .then (result) -> if result.length is 0 throw new Error('Could not find the model to execute') modelText = result[0].text db.transaction (tx) -> sbvrUtils.executeModel(tx, apiRoot: 'data' modelText: modelText ) .then -> uiApi.patch resource: 'textarea' passthrough: tx: tx req: permissions.root options: $filter: name: 'model_area' body: is_disabled: true .then -> isServerOnAir(true) res.sendStatus(200) .catch (err) -> isServerOnAir(false) res.status(404).json(err) app.post '/validate', permissions.checkPermissionsMiddleware('get'), (req, res, next) -> sbvrUtils.runRule('data', req.body.rule) .then (results) -> res.json(results) .catch (err) -> console.log('Error validating', err) res.sendStatus(404) app.delete '/cleardb', permissions.checkPermissionsMiddleware('delete'), (req, res, next) -> db.transaction (tx) -> tx.tableList() .then (result) -> Promise.all result.rows.map (table) -> tx.dropTable(table.name) .then -> sbvrUtils.executeStandardModels(tx) .then -> # TODO: HACK: This is usually done by config-loader and should be done there # In general cleardb is very destructive and should really go through a full "reboot" procedure to set everything up again. console.warn('DEL /cleardb is very destructive and should really be followed by a full restart/reload.') sbvrUtils.executeModels(tx, exports.config.models) .then -> setupModels(tx) .then -> res.sendStatus(200) .catch (err) -> console.error('Error clearing db', err, err.stack) res.sendStatus(503) app.put '/importdb', permissions.checkPermissionsMiddleware('set'), (req, res, next) -> queries = req.body.split(';') db.transaction (tx) -> Promise.reduce( queries (result, query) -> query = query.trim() if query.length > 0 tx.executeSql(query).catch((err) -> throw [query, err] ) null ) .then -> res.sendStatus(200) .catch (err) -> console.error('Error importing db', err, err.stack) res.sendStatus(404) app.get '/exportdb', permissions.checkPermissionsMiddleware('get'), (req, res, next) -> db.transaction (tx) -> tx.tableList("name NOT LIKE '%_buk'") .then (result) -> exported = '' Promise.all result.rows.map (table) -> tableName = table.name exported += 'DROP TABLE IF EXISTS "' + tableName + '";\n' exported += table.sql + ';\n' tx.executeSql('SELECT * FROM "' + tableName + '";') .then (result) -> insQuery = '' result.rows.forEach (currRow) -> notFirst = false insQuery += 'INSERT INTO "' + tableName + '" (' valQuery = '' for own propName of currRow if notFirst insQuery += ',' valQuery += ',' else notFirst = true insQuery += '"' + propName + '"' valQuery += "'" + currRow[propName] + "'" insQuery += ') values (' + valQuery + ');\n' exported += insQuery .return(exported) .then (exported) -> res.json(exported) .catch (err) -> console.error('Error exporting db', err, err.stack) res.sendStatus(503) app.post '/backupdb', permissions.checkPermissionsMiddleware('all'), serverIsOnAir, (req, res, next) -> db.transaction (tx) -> tx.tableList("name NOT LIKE '%_buk'") .then (result) -> Promise.all result.rows.map (currRow) -> tableName = currRow.name tx.dropTable(tableName + '_buk', true) .then -> tx.executeSql('ALTER TABLE "' + tableName + '" RENAME TO "' + tableName + '_buk";') .then -> res.sendStatus(200) .catch (err) -> console.error('Error backing up db', err, err.stack) res.sendStatus(404) app.post '/restoredb', permissions.checkPermissionsMiddleware('all'), serverIsOnAir, (req, res, next) -> db.transaction (tx) -> tx.tableList("name LIKE '%_buk'") .then (result) -> Promise.all result.rows.map (currRow) -> tableName = currRow.name tx.dropTable(tableName[0...-4], true) .then -> tx.executeSql('ALTER TABLE "' + tableName + '" RENAME TO "' + tableName[0...-4] + '";') .then -> res.sendStatus(200) .catch (err) -> console.error('Error restoring db', err, err.stack) res.sendStatus(404) app.all('/data/*', serverIsOnAir, sbvrUtils.handleODataRequest) app.get('/Auth/*', serverIsOnAir, sbvrUtils.handleODataRequest) app.merge('/ui/*', sbvrUtils.handleODataRequest) app.patch('/ui/*', sbvrUtils.handleODataRequest) app.delete '/', serverIsOnAir, (req, res, next) -> Promise.all([ uiApi.patch resource: 'textarea' passthrough: req: permissions.root options: $filter: name: 'model_area' body: text: '' name: 'model_area' is_disabled: false sbvrUtils.deleteModel('data') ]).then -> isServerOnAir(false) res.sendStatus(200) db.transaction(setupModels)