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

217 lines • 8.71 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.setup = void 0; const Bluebird = require("bluebird"); const fs = require("fs"); const _ = require("lodash"); const path = require("path"); const sbvrUtils = require("../sbvr-api/sbvr-utils"); const permissions = require("../sbvr-api/permissions"); const getOrCreate = async (authApiTx, resource, uniqueFields, extraFields) => { const [result] = (await authApiTx.get({ resource, options: { $select: 'id', $filter: uniqueFields, }, })); if (result != null) { return result.id; } const { id } = (await authApiTx.post({ resource, body: { ...uniqueFields, ...extraFields }, options: { returnResource: false }, })); return id; }; const getOrCreatePermission = async (authApiTx, permissionName) => { try { return getOrCreate(authApiTx, 'permission', { name: permissionName }); } catch (e) { e.message = `Could not create or find permission "${permissionName}": ${e.message}`; throw e; } }; exports.setup = (app) => { const loadConfig = (data) => sbvrUtils.db.transaction(async (tx) => { const authApiTx = sbvrUtils.api.Auth.clone({ passthrough: { tx, req: permissions.root, }, }); const { users } = data; if (users != null) { const permissionsCache = {}; users.forEach((user) => { if (user.permissions == null) { return; } user.permissions.forEach((permissionName) => { if (permissionsCache[permissionName] != null) { return; } permissionsCache[permissionName] = getOrCreatePermission(authApiTx, permissionName); }); }); await Bluebird.map(users, async (user) => { try { const userID = await getOrCreate(authApiTx, 'user', { username: user.username, }, { password: user.password, }); if (user.permissions != null) { await Bluebird.map(user.permissions, async (permissionName) => { const permissionID = await permissionsCache[permissionName]; await getOrCreate(authApiTx, 'user__has__permission', { user: userID, permission: permissionID, }); }); } } catch (e) { e.message = `Could not create or find user "${user.username}": ${e.message}`; throw e; } }); } await Bluebird.map(data.models, async (model) => { if ((model.abstractSql != null || model.modelText != null) && model.apiRoot != null) { try { await sbvrUtils.executeModel(tx, model); const apiRoute = `/${model.apiRoot}/*`; app.options(apiRoute, (_req, res) => res.sendStatus(200)); app.all(apiRoute, sbvrUtils.handleODataRequest); console.info('Successfully executed ' + model.modelName + ' model.'); } catch (err) { const message = `Failed to execute ${model.modelName} model from ${model.modelFile}`; if (_.isError(err)) { err.message = message; throw err; } throw new Error(message); } } if (model.customServerCode != null) { let customCode; if (typeof model.customServerCode === 'string') { try { customCode = nodeRequire(model.customServerCode).setup; } catch (e) { e.message = `Error loading custom server code: '${e.message}'`; throw e; } } else if (_.isObject(model.customServerCode)) { customCode = model.customServerCode.setup; } else { throw new Error(`Invalid type for customServerCode '${typeof model.customServerCode}'`); } if (typeof customCode !== 'function') { return; } return customCode(app, sbvrUtils, sbvrUtils.db); } }); }); const loadConfigFile = (configPath) => { console.info('Loading config:', configPath); return Bluebird.resolve(Promise.resolve().then(() => require(configPath))); }; const loadApplicationConfig = Bluebird.method(async (config) => { try { if (require.extensions['.coffee'] == null) { try { require('coffeescript/register'); } catch (e) { } } if (require.extensions['.ts'] == null) { try { require('ts-node/register/transpile-only'); } catch (e) { } } console.info('Loading application config'); let root; let configObj; if (config == null) { root = path.resolve(process.argv[2]) || __dirname; configObj = await loadConfigFile(path.join(root, 'config.json')); } else if (typeof config === 'string') { root = path.dirname(config); configObj = await loadConfigFile(config); } else if (_.isObject(config)) { root = process.cwd(); configObj = config; } else { throw new Error(`Invalid type for config '${typeof config}'`); } const resolvePath = (s) => { if (path.isAbsolute(s)) { return s; } return path.join(root, s); }; await Bluebird.map(configObj.models, async (model) => { if (model.modelFile != null) { model.modelText = await fs.promises.readFile(resolvePath(model.modelFile), 'utf8'); } if (typeof model.customServerCode === 'string') { model.customServerCode = resolvePath(model.customServerCode); } if (model.migrations == null) { model.migrations = {}; } const migrations = model.migrations; if (model.migrationsPath) { const migrationsPath = resolvePath(model.migrationsPath); delete model.migrationsPath; await Bluebird.map(fs.promises.readdir(migrationsPath), async (filename) => { const filePath = path.join(migrationsPath, filename); const [migrationKey] = filename.split('-', 1); switch (path.extname(filename)) { case '.coffee': case '.ts': case '.js': migrations[migrationKey] = nodeRequire(filePath); break; case '.sql': migrations[migrationKey] = await fs.promises.readFile(filePath, 'utf8'); break; default: console.error(`Unrecognised migration file extension, skipping: ${path.extname(filename)}`); } }); } if (model.initSqlPath) { const initSqlPath = resolvePath(model.initSqlPath); model.initSql = await fs.promises.readFile(initSqlPath, 'utf8'); } }); await loadConfig(configObj); } catch (err) { console.error('Error loading application config', err, err.stack); process.exit(1); } }); return { loadConfig, loadApplicationConfig, }; }; //# sourceMappingURL=config-loader.js.map