text: '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'),
            },
            ...connection.options,
            debug: _.get(connection.options, 'debug', false),
            pool: {
              min: _.get(connection.options.pool, 'min', 0),
            },
          },
          strapi.config.hook.settings.knex,
          defaultConfig
        );
  
        // 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', value =>
              value && value.length > 13 ? value : parseFloat(value)
            ); // numeric filter
  
            if (_.isString(_.get(options.connection, 'schema'))) {
              options.pool = {
                ...options.pool,
                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();
        }
      }
    );
  };
  