Alexandre Bodin 66b2d4f5c3 Init
2019-10-23 17:02:23 +02:00

241 lines
7.1 KiB
JavaScript

'use strict';
/**
* Module dependencies
*/
// Node.js core.
const fs = require('fs');
const path = require('path');
// Public node modules.
const _ = require('lodash');
/* eslint-disable prefer-template */
// Array of supported clients.
const CLIENTS = [
'pg',
'mysql',
'mysql2',
'sqlite3',
'mariasql',
'oracle',
'strong-oracle',
'mssql',
];
const defaultConfig = {
host: 'localhost',
charset: 'utf8',
};
/**
* Knex hook
*/
module.exports = strapi => {
// For each connection in the config register a new Knex connection.
_.forEach(
_.pickBy(strapi.config.connections, {
connector: 'bookshelf',
}),
(connection, name) => {
// Make sure we use the client even if the typo is not the exact one.
switch (connection.settings.client) {
case 'postgre':
case 'postgres':
case 'postgresql':
connection.settings.client = 'pg';
break;
case 'sqlite':
connection.settings.client = 'sqlite3';
break;
case 'maria':
case 'mariadb':
connection.settings.client = 'mariasql';
break;
case 'ms':
connection.settings.client = 'mssql';
break;
}
// Make sure the client is supported.
if (!_.includes(CLIENTS, connection.settings.client)) {
strapi.log.error(
'The client `' +
connection.settings.client +
'` for the `' +
name +
'` connection is not supported.'
);
strapi.stop();
}
// Make sure the client is installed in the application
// `node_modules` directory.
let client;
try {
client = require(connection.settings.client);
} catch (err) {
strapi.log.error(
'The client `' + connection.settings.client + '` is not installed.'
);
strapi.log.error(
'You can install it with `$ npm install ' +
connection.settings.client +
' --save`.'
);
strapi.stop();
}
const options = _.defaultsDeep(
{
client: connection.settings.client,
connection: {
host: _.get(connection.settings, 'host'),
user:
_.get(connection.settings, 'username') ||
_.get(connection.settings, 'user'),
password: _.get(connection.settings, 'password'),
database: _.get(connection.settings, 'database'),
charset: _.get(connection.settings, 'charset'),
schema: _.get(connection.settings, 'schema', 'public'),
port: _.get(connection.settings, 'port'),
socketPath: _.get(connection.settings, 'socketPath'),
ssl: _.get(connection.settings, 'ssl', false),
timezone: _.get(connection.settings, 'timezone', 'utc'),
filename: _.get(connection.settings, 'filename', '.tmp/data.db'),
},
debug: _.get(connection.options, 'debug', false),
acquireConnectionTimeout: _.get(
connection.options,
'acquireConnectionTimeout'
),
migrations: _.get(connection.options, 'migrations'),
useNullAsDefault: _.get(connection.options, 'useNullAsDefault'),
},
strapi.config.hook.settings.knex,
defaultConfig
);
if (connection.settings.client !== 'sqlite3') {
options.pool = {
min: _.get(connection.options, 'pool.min', 0),
max: _.get(connection.options, 'pool.max', 10),
acquireTimeoutMillis: _.get(
connection.options,
'pool.acquireTimeoutMillis',
2000
),
createTimeoutMillis: _.get(
connection.options,
'pool.createTimeoutMillis',
2000
),
idleTimeoutMillis: _.get(
connection.options,
'pool.idleTimeoutMillis',
30000
),
reapIntervalMillis: _.get(
connection.options,
'pool.reapIntervalMillis',
1000
),
createRetryIntervalMillis: _.get(
connection.options,
'pool.createRetryIntervalMillis',
200
),
};
}
// Resolve path to the directory containing the database file.
const fileDirectory = options.connection.filename
? path.dirname(
path.resolve(strapi.config.appPath, options.connection.filename)
)
: '';
switch (options.client) {
case 'mysql':
options.connection.supportBigNumbers = true;
options.connection.bigNumberStrings = true;
options.connection.typeCast = (field, next) => {
if (field.type == 'DECIMAL' || field.type === 'NEWDECIMAL') {
var value = field.string();
return value === null ? null : Number(value);
}
if (field.type == 'TINY' && field.length == 1) {
let value = field.string();
return value ? value == '1' : null;
}
return next();
};
break;
case 'pg':
client.types.setTypeParser(1700, 'text', parseFloat);
if (_.isString(_.get(options.connection, 'schema'))) {
options.pool = {
min: _.get(connection.options, 'pool.min') || 0,
max: _.get(connection.options, 'pool.max') || 10,
afterCreate: (conn, cb) => {
conn.query(
`SET SESSION SCHEMA '${options.connection.schema}';`,
err => {
cb(err, conn);
}
);
},
};
} else {
delete options.connection.schema;
}
break;
case 'sqlite3':
// Create the directory if it does not exist.
try {
fs.statSync(fileDirectory);
} catch (err) {
fs.mkdirSync(fileDirectory);
}
// Force base directory.
// Note: it removes the warning logs when starting the administration in development mode.
options.connection.filename = path.resolve(
strapi.config.appPath,
options.connection.filename
);
// Disable warn log
// .returning() is not supported by sqlite3 and will not have any effect.
options.log = {
warn: () => {},
};
break;
}
// Finally, use the client via `knex`.
// If anyone has a solution to use different paths for `knex` and clients
// please drop us an email at support@strapi.io-- it would avoid the Strapi
// applications to have `knex` as a dependency.
try {
// Try to require from local dependency.
const connection = require('knex')(options);
_.set(strapi, `connections.${name}`, connection);
} catch (err) {
strapi.log.error('Impossible to use the `' + name + '` connection...');
strapi.log.warn(
'Be sure that your client `' +
name +
'` are in the same node_modules directory'
);
strapi.log.error(err);
strapi.stop();
}
}
);
};