mirror of
				https://github.com/strapi/strapi.git
				synced 2025-10-31 09:56:44 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			241 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			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();
 | |
|       }
 | |
|     }
 | |
|   );
 | |
| };
 | 
