/************************************************************************ * This file is part of EspoCRM. * * EspoCRM - Open Source CRM application. * Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko * Website: https://www.espocrm.com * * EspoCRM is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * EspoCRM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with EspoCRM. If not, see http://www.gnu.org/licenses/. ************************************************************************/ /** * * `grunt` - full build * * `grunt dev` - build only items needed for development (takes less time) * * `grunt offline` - build but skip *composer install* * * `grant release` - full build plus upgrade packages` * * `grant test` - build for test running * * `grant run-tests` - build and run unit and integratino tests */ module.exports = function (grunt) { var jsFilesToMinify = [ 'client/lib/jquery-2.1.4.min.js', 'client/lib/underscore-min.js', 'client/lib/es6-promise.min.js', 'client/lib/backbone-min.js', 'client/lib/handlebars.js', 'client/lib/base64.js', 'client/lib/jquery-ui.min.js', 'client/lib/jquery.ui.touch-punch.min.js', 'client/lib/moment.min.js', 'client/lib/moment-timezone.min.js', 'client/lib/moment-timezone-data.js', 'client/lib/jquery.timepicker.min.js', 'client/lib/jquery.autocomplete.js', 'client/lib/bootstrap.min.js', 'client/lib/bootstrap-datepicker.js', 'client/lib/bull.js', 'client/lib/marked.min.js', 'client/lib/autobahn.js', 'client/src/namespace.js', 'client/src/exceptions.js', 'client/src/loader.js', 'client/src/utils.js', 'client/src/acl.js', 'client/src/model.js', 'client/src/model-offline.js', 'client/src/ajax.js', 'client/src/controller.js', 'client/src/ui.js', 'client/src/acl-manager.js', 'client/src/cache.js', 'client/src/storage.js', 'client/src/models/settings.js', 'client/src/language.js', 'client/src/metadata.js', 'client/src/field-manager.js', 'client/src/models/user.js', 'client/src/models/preferences.js', 'client/src/model-factory.js', 'client/src/collection-factory.js', 'client/src/pre-loader.js', 'client/src/controllers/base.js', 'client/src/router.js', 'client/src/date-time.js', 'client/src/layout-manager.js', 'client/src/theme-manager.js', 'client/src/session-storage.js', 'client/src/view-helper.js', 'client/src/page-title.js', 'client/src/app.js' ]; function camelCaseToHyphen (string){ if (string == null) { return string; } return string.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); } var fs = require('fs'); var cp = require('child_process'); var path = require('path'); var currentPath = path.dirname(fs.realpathSync(__filename)); var themeList = []; fs.readdirSync('application/Espo/Resources/metadata/themes').forEach(function (file) { themeList.push(file.substr(0, file.length - 5)); }); var cssminFilesData = {}; var lessData = {}; themeList.forEach(function (theme) { var name = camelCaseToHyphen(theme); var files = {}; files['client/css/espo/'+name+'.css'] = 'frontend/less/'+name+'/main.less'; files['client/css/espo/'+name+'-iframe.css'] = 'frontend/less/'+name+'/iframe/main.less'; cssminFilesData['client/css/espo/'+name+'.css'] = 'client/css/espo/'+name+'.css'; cssminFilesData['client/css/espo/'+name+'-iframe.css'] = 'client/css/espo/'+name+'-iframe.css'; var o = { options: { yuicompress: true, }, files: files }; lessData[theme] = o; }); var pkg = grunt.file.readJSON('package.json'); grunt.initConfig({ pkg: pkg, mkdir: { tmp: { options: { mode: 0755, create: [ 'build/tmp', ] }, } }, clean: { start: ['build/EspoCRM-*'], final: ['build/tmp'], release: ['build/EspoCRM-' + pkg.version], beforeFinal: { src: [ 'build/tmp/custom/Espo/Custom/*', '!build/tmp/custom/Espo/Custom/.htaccess', 'build/tmp/install/config.php', ] } }, less: lessData, cssmin: { themes: { files: cssminFilesData } }, uglify: { options: { mangle: false, sourceMap: true, banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n', }, 'build/tmp/client/espo.min.js': jsFilesToMinify.map(function (item) { return '' + item; }) }, copy: { options: { mode: true, }, frontendFolders: { expand: true, cwd: 'client', src: [ 'src/**', 'res/**', 'fonts/**', 'cfg/**', 'modules/**', 'img/**', 'css/**', 'sounds/**', 'custom/**' ], dest: 'build/tmp/client', }, frontendLib: { expand: true, dot: true, cwd: 'client/lib', src: '**', dest: 'build/tmp/client/lib/', }, backend: { expand: true, dot: true, src: [ 'api/**', 'application/**', 'custom/**', 'data/.data', 'install/**', 'portal/**', 'vendor/**', 'html/**', 'bootstrap.php', 'cron.php', 'daemon.php', 'rebuild.php', 'clear_cache.php', 'upgrade.php', 'extension.php', 'websocket.php', 'command.php', 'oauth-callback.php', 'index.php', 'LICENSE.txt', '.htaccess', 'web.config', ], dest: 'build/tmp/', }, final: { expand: true, dot: true, src: '**', cwd: 'build/tmp', dest: 'build/EspoCRM-<%= pkg.version %>/', }, }, chmod: { php: { options: { mode: '644' }, src: [ 'build/EspoCRM-<%= pkg.version %>/**/*.php', 'build/EspoCRM-<%= pkg.version %>/**/*.json', 'build/EspoCRM-<%= pkg.version %>/**/*.config', 'build/EspoCRM-<%= pkg.version %>/**/.htaccess', 'build/EspoCRM-<%= pkg.version %>/client/**/*.js', 'build/EspoCRM-<%= pkg.version %>/client/**/*.css', 'build/EspoCRM-<%= pkg.version %>/client/**/*.tpl', 'build/EspoCRM-<%= pkg.version %>/**/*.html', 'build/EspoCRM-<%= pkg.version %>/**/*.txt', ] }, folders: { options: { mode: '755' }, src: [ 'build/EspoCRM-<%= pkg.version %>/install', 'build/EspoCRM-<%= pkg.version %>/portal', 'build/EspoCRM-<%= pkg.version %>/api', 'build/EspoCRM-<%= pkg.version %>/api/v1', 'build/EspoCRM-<%= pkg.version %>/api/v1/portal-access', 'build/EspoCRM-<%= pkg.version %>', ] }, foldersWritable: { options: { mode: '775' }, src: [ 'build/EspoCRM-<%= pkg.version %>/data', 'build/EspoCRM-<%= pkg.version %>/custom', 'build/EspoCRM-<%= pkg.version %>/custom/Espo', 'build/EspoCRM-<%= pkg.version %>/custom/Espo/Custom', 'build/EspoCRM-<%= pkg.version %>/client/custom', 'build/EspoCRM-<%= pkg.version %>/client/modules', 'build/EspoCRM-<%= pkg.version %>/application/Espo/Modules', ] }, }, replace: { version: { options: { patterns: [ { match: 'version', replacement: '<%= pkg.version %>' } ] }, files: [ { src: 'build/tmp/application/Espo/Core/defaults/config.php', dest: 'build/tmp/application/Espo/Core/defaults/config.php' } ] } }, }); grunt.registerTask("chmod-folders", function() { cp.execSync("find . -type d -exec chmod 755 {} + ", {stdio: 'ignore', cwd: 'build/EspoCRM-' + pkg.version}); }); grunt.registerTask("composer", function() { cp.execSync("composer install --ignore-platform-reqs --no-dev", {stdio: 'ignore'}); }); grunt.registerTask("composer-dev", function() { cp.execSync("composer install --ignore-platform-reqs", {stdio: 'ignore'}); }); grunt.registerTask("upgrade", function() { cp.execSync("node diff --all --vendor", {stdio: 'inherit'}); }); grunt.registerTask("unit-tests-run", function() { cp.execSync("vendor/bin/phpunit --bootstrap=./vendor/autoload.php tests/unit", {stdio: 'inherit'}); }); grunt.registerTask("integration-tests-run", function() { cp.execSync("vendor/bin/phpunit --bootstrap=./vendor/autoload.php tests/integration", {stdio: 'inherit'}); }); grunt.registerTask("zip", function() { var fs = require('fs'); var resolve = this.async(); var folder = 'EspoCRM-' + pkg.version; var zipPath = 'build/' + folder +'.zip'; if (fs.existsSync(zipPath)) fs.unlinkSync(zipPath); var archiver = require('archiver'); var archive = archiver('zip'); archive.on('error', function (err) { grunt.fail.warn(err); }); var zipOutput = fs.createWriteStream(zipPath); zipOutput.on('close', function () { console.log("EspoCRM package has been built."); resolve(); }); archive.directory(currentPath + '/build/' + folder, folder).pipe(zipOutput); archive.finalize(); }); grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-mkdir'); grunt.loadNpmTasks('grunt-contrib-less'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-replace'); grunt.loadNpmTasks('grunt-chmod'); grunt.registerTask('offline', [ 'clean:start', 'mkdir:tmp', 'less', 'cssmin', 'uglify', 'copy:frontendFolders', 'copy:frontendLib', 'copy:backend', 'replace', 'clean:beforeFinal', 'copy:final', 'chmod-folders', 'chmod:php', 'chmod:folders', 'chmod:foldersWritable', 'clean:final', ]); grunt.registerTask('default', [ 'composer', 'offline', ]); grunt.registerTask('release', [ 'default', 'upgrade', 'zip', 'clean:release', ]); grunt.registerTask('run-tests', [ 'test', 'unit-tests-run', 'integration-tests-run', ]); grunt.registerTask('run-unit-tests', [ 'composer-dev', 'unit-tests-run', ]); grunt.registerTask('run-integration-tests', [ 'test', 'integration-tests-run', ]); grunt.registerTask('dev', [ 'composer-dev', 'less', ]); grunt.registerTask('test', [ 'composer-dev', 'offline', ]); };