From b04eb1543df10eef6e8890b10c70e3101b903865 Mon Sep 17 00:00:00 2001 From: Ben Moroze Date: Fri, 11 Feb 2022 11:39:06 -0500 Subject: [PATCH] Release 12.0.0 --- CONTRIBUTING.md | 2 +- LICENSE | 2 +- README.md | 6 +- RELEASENOTES.md | 11 + bin/ojet | 2 +- common/component.js | 219 +- common/hookRunner.js | 6 +- common/index.js | 99 +- common/messages.js | 2 +- common/restore.js | 24 +- common/template/common.js | 10 +- common/template/index.js | 20 +- common/template/local.js | 2 +- common/template/npm.js | 6 +- common/template/url.js | 4 +- config.js | 9 +- config.json | 2 +- generators/add-component/index.js | 17 +- generators/add-hybrid/index.js | 15 +- generators/add-pcss-theme/index.js | 16 +- .../templates/mytheme/web/mytheme.scss | 12 +- generators/add-theme/index.js | 10 +- generators/app/index.js | 20 +- generators/app/templates/common/package.json | 4 +- generators/hybrid/index.js | 24 +- .../hybrid/templates/common/package.json | 4 +- .../templates/common/src/js/cordovaMocks.js | 2 +- hybrid/cordova.js | 6 +- hybrid/graphics.js | 2 +- hybrid/index.js | 8 +- hybrid/platforms.js | 31 +- lib/scopes/app.js | 87 +- lib/scopes/platform.plugin.js | 8 +- lib/tasks/add.js | 14 +- lib/tasks/build.serve.js | 8 +- lib/tasks/clean.js | 10 +- lib/tasks/configure.js | 12 +- lib/tasks/create.js | 14 +- lib/tasks/help.js | 4 +- lib/tasks/index.js | 4 +- lib/tasks/list.js | 4 +- lib/tasks/package.js | 4 +- lib/tasks/publish.js | 4 +- lib/tasks/remove.js | 4 +- lib/tasks/restore.js | 4 +- lib/tasks/search.js | 4 +- lib/tasks/strip.js | 10 +- lib/tooling/build.js | 12 +- lib/tooling/index.js | 4 +- lib/tooling/serve.js | 8 +- {util => lib/util}/constants.js | 119 +- {util => lib/util}/fetchZip.js | 2 +- lib/{utils.injectors.js => util/injectors.js} | 2 +- {util => lib/util}/paths.js | 7 +- lib/{ => util}/utils.js | 93 +- lib/utils.constants.js | 111 - lib/utils.paths.js | 126 - ojet.js | 2 +- package.json | 8 +- template/common/_gitignore | 1 + .../common/scripts/config/oraclejet-build.js | 2 +- .../common/scripts/config/oraclejet-serve.js | 2 +- .../common/scripts/hooks/after_app_create.js | 2 +- .../common/scripts/hooks/after_app_restore.js | 2 +- .../scripts/hooks/after_app_typescript.js | 2 +- template/common/scripts/hooks/after_build.js | 2 +- .../scripts/hooks/after_component_build.js | 2 +- .../scripts/hooks/after_component_create.js | 2 +- .../scripts/hooks/after_component_package.js | 13 + .../hooks/after_component_typescript.js | 2 +- template/common/scripts/hooks/after_serve.js | 2 +- template/common/scripts/hooks/after_watch.js | 2 +- .../scripts/hooks/before_app_typescript.js | 2 +- template/common/scripts/hooks/before_build.js | 2 +- .../hooks/before_component_optimize.js | 2 +- .../scripts/hooks/before_component_package.js | 13 + .../hooks/before_component_typescript.js | 2 +- .../scripts/hooks/before_hybrid_build.js | 2 +- .../common/scripts/hooks/before_optimize.js | 2 +- .../scripts/hooks/before_release_build.js | 2 +- template/common/scripts/hooks/before_serve.js | 2 +- template/common/scripts/hooks/before_watch.js | 2 +- .../common/scripts/hooks/before_webpack.js | 2 +- template/common/scripts/hooks/hooks.json | 2 + template/component/css/@component@-styles.css | 5 + template/component/js/@component@-view.html | 2 +- .../component/js/@component@-viewModel.js | 2 +- template/component/js/component.json | 2 +- template/component/js/loader.js | 2 +- .../js/resources/nls/@component@-strings.js | 2 +- template/component/ts/@component@-view.html | 2 +- template/component/ts/component.json | 2 +- .../tsx/@component@-functional-template.tsx | 19 + template/component/tsx/@component@.tsx | 12 +- template/component/tsx/loader.ts | 2 +- template/resource-component/component.json | 13 + test/apiTest.js | 67 +- test/buildConfig.json | 4 +- test/componentTest.js | 2025 +++++++++++++---- test/customizationTest.js | 87 - test/hybridTest.js | 18 +- test/jetpackTest.js | 727 ------ test/miscTest.js | 2 +- test/pwaTest.js | 30 +- test/setup.js | 167 +- .../resource-component/component.json | 5 - .../templates/resource-component/js/logger.js | 11 - .../resource-component/js/resource.js | 11 - .../templates/resource-component/resource.css | 3 - .../templates/resource-component/ts/logger.ts | 3 - .../resource-component/ts/resource.ts | 5 - .../webTsApiTest/oraclejetconfig.json | 1 - test/templates/webTsApiTest/package.json | 9 +- .../scripts/config/oraclejet-build.js | 2 +- .../scripts/config/oraclejet-serve.js | 2 +- .../scripts/hooks/after_app_create.js | 2 +- .../scripts/hooks/after_app_restore.js | 2 +- .../scripts/hooks/after_app_typescript.js | 2 +- .../webTsApiTest/scripts/hooks/after_build.js | 2 +- .../scripts/hooks/after_component_build.js | 2 +- .../scripts/hooks/after_component_create.js | 2 +- .../hooks/after_component_typescript.js | 2 +- .../webTsApiTest/scripts/hooks/after_serve.js | 2 +- .../webTsApiTest/scripts/hooks/after_watch.js | 2 +- .../scripts/hooks/before_app_typescript.js | 2 +- .../scripts/hooks/before_build.js | 2 +- .../hooks/before_component_optimize.js | 2 +- .../hooks/before_component_typescript.js | 2 +- .../scripts/hooks/before_hybrid_build.js | 2 +- .../scripts/hooks/before_optimize.js | 2 +- .../scripts/hooks/before_release_build.js | 2 +- .../scripts/hooks/before_serve.js | 2 +- .../scripts/hooks/before_watch.js | 2 +- test/templates/webTsApiTest/src/index.html | 2 +- test/templates/webTsApiTest/src/js/main.js | 2 +- .../webTsApiTest/src/js/path_mapping.json | 20 +- .../my-component/my-component-view.html | 2 +- .../my-pack/component/component-view.html | 2 +- .../webTsApiTest/src/ts/views/about.html | 2 +- .../webTsApiTest/src/ts/views/customers.html | 2 +- .../webTsApiTest/src/ts/views/dashboard.html | 2 +- .../webTsApiTest/src/ts/views/incidents.html | 2 +- test/templates/webpackLegacyTest/.gitignore | 19 + .../webpackLegacyTest/oraclejetconfig.json | 26 + test/templates/webpackLegacyTest/package.json | 23 + .../webpackLegacyTest/path_mapping.json | 377 +++ .../scripts/config/oraclejet-build.js | 155 ++ .../scripts/config/oraclejet-serve.js | 88 + .../scripts/hooks/after_app_create.js | 20 + .../scripts/hooks/after_app_restore.js | 20 + .../scripts/hooks/after_app_typescript.js | 20 + .../scripts/hooks/after_build.js | 21 + .../scripts/hooks/after_component_build.js | 21 + .../scripts/hooks/after_component_create.js | 21 + .../hooks/after_component_typescript.js | 20 + .../scripts/hooks/after_serve.js | 21 + .../scripts/hooks/after_watch.js | 21 + .../scripts/hooks/before_app_typescript.js | 21 + .../scripts/hooks/before_build.js | 21 + .../hooks/before_component_optimize.js | 21 + .../hooks/before_component_typescript.js | 21 + .../scripts/hooks/before_hybrid_build.js | 21 + .../scripts/hooks/before_optimize.js | 21 + .../scripts/hooks/before_release_build.js | 21 + .../scripts/hooks/before_serve.js | 43 + .../scripts/hooks/before_watch.js | 21 + .../scripts/hooks/before_webpack.js | 22 + .../scripts/hooks/hooks.json | 25 + .../webpackLegacyTest/src/components/app.tsx | 36 + .../src/components/content/index.tsx | 8 + .../src/components/footer.tsx | 60 + .../src/components/header.tsx | 94 + .../webpackLegacyTest/src/index.html | 55 + test/templates/webpackLegacyTest/src/index.ts | 1 + test/templates/webpackLegacyTest/src/main.js | 63 + .../webpackLegacyTest/src/styles/app.css | 43 + .../src/styles/fonts/App_iconfont.woff | Bin 0 -> 5104 bytes .../src/styles/images/avatar_24px.png | Bin 0 -> 1576 bytes .../src/styles/images/avatar_24px_2x.png | Bin 0 -> 2170 bytes .../src/styles/images/favicon.ico | Bin 0 -> 58937 bytes .../src/styles/images/oracle_logo.svg | 21 + .../templates/webpackLegacyTest/tsconfig.json | 31 + test/themeTest.js | 65 +- test/tsTest.js | 60 +- test/util/index.js | 140 +- test/vdomTest.js | 116 +- test/webTest.js | 171 +- test/webpackTest.js | 161 ++ util/index.js | 29 - 189 files changed, 4650 insertions(+), 2308 deletions(-) rename {util => lib/util}/constants.js (50%) rename {util => lib/util}/fetchZip.js (94%) rename lib/{utils.injectors.js => util/injectors.js} (92%) rename {util => lib/util}/paths.js (94%) rename lib/{ => util}/utils.js (89%) delete mode 100644 lib/utils.constants.js delete mode 100644 lib/utils.paths.js create mode 100644 template/common/scripts/hooks/after_component_package.js create mode 100644 template/common/scripts/hooks/before_component_package.js create mode 100644 template/component/tsx/@component@-functional-template.tsx create mode 100644 template/resource-component/component.json delete mode 100644 test/customizationTest.js delete mode 100644 test/jetpackTest.js delete mode 100644 test/templates/resource-component/component.json delete mode 100644 test/templates/resource-component/js/logger.js delete mode 100644 test/templates/resource-component/js/resource.js delete mode 100644 test/templates/resource-component/resource.css delete mode 100644 test/templates/resource-component/ts/logger.ts delete mode 100644 test/templates/resource-component/ts/resource.ts create mode 100644 test/templates/webpackLegacyTest/.gitignore create mode 100644 test/templates/webpackLegacyTest/oraclejetconfig.json create mode 100644 test/templates/webpackLegacyTest/package.json create mode 100644 test/templates/webpackLegacyTest/path_mapping.json create mode 100644 test/templates/webpackLegacyTest/scripts/config/oraclejet-build.js create mode 100644 test/templates/webpackLegacyTest/scripts/config/oraclejet-serve.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/after_app_create.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/after_app_restore.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/after_app_typescript.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/after_build.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/after_component_build.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/after_component_create.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/after_component_typescript.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/after_serve.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/after_watch.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/before_app_typescript.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/before_build.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/before_component_optimize.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/before_component_typescript.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/before_hybrid_build.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/before_optimize.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/before_release_build.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/before_serve.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/before_watch.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/before_webpack.js create mode 100644 test/templates/webpackLegacyTest/scripts/hooks/hooks.json create mode 100644 test/templates/webpackLegacyTest/src/components/app.tsx create mode 100644 test/templates/webpackLegacyTest/src/components/content/index.tsx create mode 100644 test/templates/webpackLegacyTest/src/components/footer.tsx create mode 100644 test/templates/webpackLegacyTest/src/components/header.tsx create mode 100644 test/templates/webpackLegacyTest/src/index.html create mode 100644 test/templates/webpackLegacyTest/src/index.ts create mode 100644 test/templates/webpackLegacyTest/src/main.js create mode 100644 test/templates/webpackLegacyTest/src/styles/app.css create mode 100644 test/templates/webpackLegacyTest/src/styles/fonts/App_iconfont.woff create mode 100644 test/templates/webpackLegacyTest/src/styles/images/avatar_24px.png create mode 100644 test/templates/webpackLegacyTest/src/styles/images/avatar_24px_2x.png create mode 100644 test/templates/webpackLegacyTest/src/styles/images/favicon.ico create mode 100644 test/templates/webpackLegacyTest/src/styles/images/oracle_logo.svg create mode 100644 test/templates/webpackLegacyTest/tsconfig.json create mode 100644 test/webpackTest.js delete mode 100644 util/index.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eef58bd..4b0b07a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing to ojet-cli -*Copyright (c) 2014, 2021 Oracle and/or its affiliates +*Copyright (c) 2014, 2022 Oracle and/or its affiliates Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/* diff --git a/LICENSE b/LICENSE index 42b900a..8f546c0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ # ojet-cli -Copyright (c) 2021 Oracle and/or its affiliates. +Copyright (c) 2022 Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/README.md b/README.md index 6449074..818c975 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# @oracle/ojet-cli 11.1.0 +# @oracle/ojet-cli 12.0.0 ## About the module This module contains a command line interface for Oracle JET web and hybrid mobile application development. @@ -64,11 +64,11 @@ Or view help on adding a plugin: ojet help add plugin ``` -For more information on the Oracle JET CLI, refer to the [Oracle JET Developers Guide](http://www.oracle.com/pls/topic/lookup?ctx=jet1110&id=homepage). +For more information on the Oracle JET CLI, refer to the [Oracle JET Developers Guide](http://www.oracle.com/pls/topic/lookup?ctx=jet1200&id=homepage). ## [Contributing](https://github.com/oracle/ojet-cli/blob/master/CONTRIBUTING.md) Oracle JET is an open source project. Pull Requests are currently not being accepted. See [CONTRIBUTING](https://github.com/oracle/ojet-cli/blob/master/CONTRIBUTING.md) for details. ## [License](https://github.com/oracle/ojet-cli/blob/master/LICENSE) -Copyright (c) 2021 Oracle and/or its affiliates and released under the +Copyright (c) 2022 Oracle and/or its affiliates and released under the [Universal Permissive License (UPL)](https://oss.oracle.com/licenses/upl/), Version 1.0 \ No newline at end of file diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 113ab7e..b101ebb 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,5 +1,16 @@ ## Release Notes for ojet-cli ## +### 12.0.0 + +* Add optional 'stripList' property to oraclejetconfig.json to allow providing the list of files/directories to delete instead of using .gitignore +* Add optional '--ci' flag to restore to use npm ci instead of the default npm install +* The third party library 'svgo' by oraclejet-tooling was updated. If you run into problems during an 'ojet build' surrounding 'svgo', ensure that you have version svgo 2.7.0+ installed in your application's node_modules. If in the rare case you have an svgMin section in your oraclejetconfig.json, its plugin section may need to be updated per the svgo 2.7.0 documentation +* Custom hooks have been added to run before/after package creation +* Webpack support has been expanded to both debug and release builds +* Added --installer option/installer property for oraclejetconfig.json +* Updated default typescript version to 4.5.4 +* Remove obsolete "generatorVersion" from oraclejetconfig.json + ### 11.1.0 * ojs/ojcss is supported as a name for the ojcss plugin diff --git a/bin/ojet b/bin/ojet index 88c5f22..f1b2389 100644 --- a/bin/ojet +++ b/bin/ojet @@ -4,7 +4,7 @@ const argv = require('minimist')(process.argv.slice(2)); const tasks = require('../lib/tasks'); -const utils = require('../lib/utils'); +const utils = require('../lib/util/utils'); // Extract commands const commands = [...argv._]; // Delete commands leaving only options diff --git a/common/component.js b/common/component.js index 2e1b184..423f3d1 100644 --- a/common/component.js +++ b/common/component.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -8,8 +8,9 @@ const fs = require('fs-extra'); const path = require('path'); -const CONSTANTS = require('../util/constants'); -const paths = require('../util/paths'); +const constants = require('../lib/util/constants'); +const paths = require('../lib/util/paths'); +const utils = require('../lib/util/utils'); const commonMessages = require('./messages'); module.exports = { @@ -23,43 +24,51 @@ module.exports = { * @param {object} utils object with helper methods * @returns {Promise} */ - writeComponentTemplate: function _writeComponentTemplate(generator, utils) { + writeComponentTemplate: function _writeComponentTemplate(generator) { return new Promise((resolve) => { const componentName = _getComponentName(generator); - const componentTemplateSrc = _getComponentTemplatePath(generator, utils); + const componentTemplateSrc = _getComponentTemplatePath(generator); const componentThemeTemplateSrc = _getComponentThemeTemplatePath('theme'); - const componentDestDirectory = _getComponentDestPath(generator, utils); + const componentDestDirectory = _getComponentDestPath(generator); const pack = generator.options.pack; // avoid overwrite component if (fs.existsSync(componentDestDirectory)) { utils.log.error(`Component with name '${componentName}' already exists.`); } - if (_isVComponent(generator, utils) && !utils.isTypescriptApplication()) { + if (_isVComponent(generator) && !utils.isTypescriptApplication()) { utils.log.error('Cannot create a vcomponent in a Javascript application. Please run \'ojet add typescript\' to add Typescript support to your application.'); } fs.ensureDirSync(componentDestDirectory); fs.copySync(componentTemplateSrc, componentDestDirectory); - fs.copySync(componentThemeTemplateSrc, componentDestDirectory); - // Copy theming template for composit components - if (utils.validCustomProperties()) { - const componentTemplateScssSrc = _getComponentThemeTemplatePath('pcss'); - fs.copySync(componentTemplateScssSrc, componentDestDirectory); + if (_isResourceComponent(generator)) { + const fileContent = constants.RESOURCE_COMPONENT_INDEX_FILE_CONTENT; + fs.writeFileSync(path.join(componentDestDirectory, `index.${utils.isTypescriptApplication() ? 'ts' : 'js'}`), fileContent); } else { - const componentTemplateCssSrc = _getComponentThemeTemplatePath('css'); - fs.copySync(componentTemplateCssSrc, componentDestDirectory); + // Only copy theming files for none-resource components + fs.copySync(componentThemeTemplateSrc, componentDestDirectory); + // Copy theming template for composit components + if (utils.validCustomProperties()) { + const componentTemplateScssSrc = _getComponentThemeTemplatePath('pcss'); + fs.copySync(componentTemplateScssSrc, componentDestDirectory); + } else { + const componentTemplateCssSrc = _getComponentThemeTemplatePath('css'); + fs.copySync(componentTemplateCssSrc, componentDestDirectory); + } } // replace tokens in template files and file names - _renameComponentTemplatePrefix(generator, utils); - _replaceComponentTemplateToken(generator, utils, pack); + _renameComponentTemplatePrefix(generator); + _replaceComponentTemplateToken(generator, pack); + _filterTsxTemplates(generator, componentDestDirectory); if (pack) { // update pack info - _updatePackInfo({ generator, utils, pack }); - } else if (_isVComponent(generator, utils)) { + _updatePackInfo({ generator, pack }); + } else if (_isVComponent(generator)) { // remove pack metadata from vcomponent template - _stripPackFromVComponet({ generator, utils, pack }); + _stripPackFromVComponent({ generator, pack }); } + // if in a typescript app, create path mapping in tsconfig.json - _addComponentToTsconfigPathMapping(generator, utils); + _addComponentToTsconfigPathMapping(generator); resolve(); }); }, @@ -73,34 +82,35 @@ module.exports = { * @param {object} generator object with build options * @param {object} utils object with helper methods */ - validateComponentName: (generator, utils) => { + validateComponentName: (generator) => { const componentName = _getComponentName(generator); const pack = generator.options.pack; let errorMessage; if (componentName === undefined || componentName === null) { errorMessage = 'Invalid component name: must not be null or undefined.'; utils.log.error(errorMessage); + } else if (!pack && _isResourceComponent(generator)) { + errorMessage = 'Cannot create resource component: please re-run the command with --pack and provide an existing JET pack'; + utils.log.error(errorMessage); } else if (!pack && (componentName !== componentName.toLowerCase() || componentName.indexOf('-') < 0 || !/^[a-z]/.test(componentName))) { errorMessage = 'Invalid component name: must be all lowercase letters and contain at least one hyphen.'; utils.log.error(errorMessage); } else if (pack && (componentName !== componentName.toLowerCase() || !/^[a-z]/.test(componentName))) { errorMessage = 'Invalid component name: must be all lowercase letters.'; utils.log.error(errorMessage); - } else if (pack && !fs.existsSync(_getPathToJETPack(generator, utils, pack))) { + } else if (pack && !fs.existsSync(_getPathToJETPack(generator, pack))) { errorMessage = 'Invalid pack name: please provide an existing JET pack'; utils.log.error(errorMessage); } }, - /** * ## checkThatAppExists * * Make sure command is being run inside of a JET app * - * @param {object} utils object with helper methods */ - checkThatAppExists: (utils) => { + checkThatAppExists: () => { const errorMessage = 'Please create an application first, then create the component from within that app.'; // eslint-disable-line max-len if (!utils.isCwdJetApp()) { utils.log.error(errorMessage); @@ -113,9 +123,8 @@ module.exports = { * Log success message indicating that component has been * created * @param {object} generator object with build options - * @param {object} utils object with helper methods */ - logSuccessMessage: (generator, utils) => { + logSuccessMessage: (generator) => { utils.log(commonMessages.appendJETPrefix(`Add component '${_getComponentName(generator)}' finished.`)); }, @@ -125,11 +134,10 @@ module.exports = { * Return the dest path of the component. * * @param {object} generator object with build options - * @param {object} utils object with helper methods */ - getComponentDestPath: (generator, utils) => ( - _getComponentDestPath(generator, utils) - ) + getComponentDestPath: (generator) => { + _getComponentDestPath(generator); + } }; /** @@ -143,20 +151,25 @@ module.exports = { * @returns {string} component template path */ -function _getComponentTemplatePath(generator, utils) { - let componentType; - if (_isVComponent(generator, utils)) { - componentType = 'tsx'; +function _getComponentTemplatePath(generator) { + const templateBasePath = path.join(__dirname, '../template'); + let componentTemplatePath; + if (_isResourceComponent(generator)) { + componentTemplatePath = path.join(templateBasePath, 'resource-component'); } else { - componentType = utils.isTypescriptApplication() ? 'ts' : 'js'; + let componentType; + if (_isVComponent(generator)) { + componentType = 'tsx'; + } else { + componentType = utils.isTypescriptApplication() ? 'ts' : 'js'; + } + componentTemplatePath = path.join( + templateBasePath, + 'component', + componentType + ); } - const componentTemplatePath = path.join( - '..', - 'template', - 'component', - componentType - ); - return path.resolve(__dirname, componentTemplatePath); + return path.resolve(componentTemplatePath); } /** @@ -176,25 +189,23 @@ function _getComponentThemeTemplatePath(directoryPath) { * ## _getPathToJETPack * * @param {object} generator object with build options - * @param {object} utils object with helper methods * @param {string} pack optional name of JET pack that the component * @returns {string} */ -function _getPathToJETPack(generator, utils, pack) { - return path.join(_getComponentsBasePath(generator, utils), pack); +function _getPathToJETPack(generator, pack) { + return path.join(_getComponentsBasePath(generator), pack); } /** * ## _getComponentDestPath * * @param {object} generator object with build options - * @param {object} utils object with helper methods * @returns {string} component destination path */ -function _getComponentDestPath(generator, utils) { +function _getComponentDestPath(generator) { const pack = generator.options.pack; const destBase = pack ? - _getPathToJETPack(generator, utils, pack) : _getComponentsBasePath(generator, utils); + _getPathToJETPack(generator, pack) : _getComponentsBasePath(generator); return path.join(destBase, _getComponentName(generator)); } @@ -204,12 +215,11 @@ function _getComponentDestPath(generator, utils) { * Replace tokens (@component-name@ & @full-component-name@) in component templates * * @param {object} generator object with build options - * @param {object} utils object with helper methods * @param {string} pack name of pack that component will belong to */ -function _replaceComponentTemplateToken(generator, utils, pack) { +function _replaceComponentTemplateToken(generator, pack) { const componentName = _getComponentName(generator); - const componentBasePath = _getComponentDestPath(generator, utils); + const componentBasePath = _getComponentDestPath(generator); const folderPaths = [ componentBasePath, path.join(componentBasePath, 'resources/nls'), @@ -262,11 +272,11 @@ function _replaceComponentTokenInFileList(componentDir, componentName, pack) { ); // replace @component-name@ with component name fileContent = fileContent.replace(new RegExp('@component-name@', 'g'), componentName); - // Camel Case component name replacements are + // Camel Case component name or class name replacements are // needed only for vcomponent .tsx files. if (file && (fileExt === '.tsx' || fileExt === '.ts')) { fileContent = fileContent.replace( - new RegExp('@camelcase-component-name@', 'g'), + new RegExp('@camelcasecomponent-name@', 'g'), _toCamelCase(componentName)); } @@ -282,7 +292,7 @@ function _replaceComponentTokenInFileList(componentDir, componentName, pack) { * @param {object} utils object with helper methods * @returns {string} component base path */ -function _getComponentsBasePath(generator, utils) { +function _getComponentsBasePath(generator) { const appDir = generator.appDir === undefined ? process.cwd() : path.resolve(generator.appDir); const _configPaths = generator.appDir === undefined @@ -310,10 +320,9 @@ function _getComponentName(generator) { * Replace token (@component@) in component file names * * @param {object} generator object with build options - * @param {object} utils object with helper methods */ -function _renameComponentTemplatePrefix(generator, utils) { - const componentBasePath = _getComponentDestPath(generator, utils); +function _renameComponentTemplatePrefix(generator) { + const componentBasePath = _getComponentDestPath(generator); const componentName = _getComponentName(generator); const folderPaths = [ componentBasePath, @@ -353,31 +362,29 @@ function _renameComponentTemplatePrefixFile(componentDir, file, componentName) { * to the provided pack * * @param {object} generator object with build options - * @param {object} utils object with helper methods * @param {string} pack name of JET pack that the component belongs to */ -function _updatePackInfo({ generator, utils, pack }) { +function _updatePackInfo({ generator, pack }) { // set pack of component - if (_isVComponent(generator, utils)) { - _setVComponentPack({ generator, utils, pack }); + if (_isVComponent(generator)) { + _setVComponentPack({ generator, pack }); } else { - _setCompositeComponentPack({ generator, utils, pack }); + _setCompositeComponentPack({ generator, pack }); } // add component to dependencies of pack - _addComponentToPackDependencies({ generator, utils, pack }); + _addComponentToPackDependencies({ generator, pack }); } /** * ## _updateVComponentPack * * @param {object} options.generator - * @param {object} options.utils * @param {object} options.pack * @param {object} options.strip */ -function _updateVComponentPack({ generator, utils, pack, strip }) { +function _updateVComponentPack({ generator, pack, strip }) { const vComponentPath = path.join( - _getComponentDestPath(generator, utils), + _getComponentDestPath(generator), `${_getComponentName(generator)}.tsx` ); let vComponentContent = fs.readFileSync(vComponentPath, 'utf-8'); @@ -394,35 +401,32 @@ function _updateVComponentPack({ generator, utils, pack, strip }) { * ## _stripPackFromVComponent * * @param {object} options.generator - * @param {object} options.utils * @param {object} options.pack */ -function _stripPackFromVComponet({ generator, utils, pack }) { - _updateVComponentPack({ generator, utils, pack, strip: true }); +function _stripPackFromVComponent({ generator, pack }) { + _updateVComponentPack({ generator, pack, strip: true }); } /** * ## _setVCompponentPack * * @param {object} options.generator - * @param {object} options.utils * @param {object} options.pack */ -function _setVComponentPack({ generator, utils, pack }) { - _updateVComponentPack({ generator, utils, pack, strip: false }); +function _setVComponentPack({ generator, pack }) { + _updateVComponentPack({ generator, pack, strip: false }); } /** * ## _setCompositeComponentPack * * @param {object} options.generator - * @param {object} options.utils * @param {object} options.pack */ -function _setCompositeComponentPack({ generator, utils, pack }) { +function _setCompositeComponentPack({ generator, pack }) { const componentJsonPath = path.join( - _getComponentDestPath(generator, utils), - CONSTANTS.COMPONENT_JSON + _getComponentDestPath(generator), + constants.COMPONENT_JSON ); const componentJson = fs.readJSONSync(componentJsonPath); componentJson.pack = pack; @@ -433,20 +437,24 @@ function _setCompositeComponentPack({ generator, utils, pack }) { * ## _addComponentToPackDependencies * * @param {object} options.generator - * @param {object} options.utils * @param {object} options.pack */ -function _addComponentToPackDependencies({ generator, utils, pack }) { +function _addComponentToPackDependencies({ generator, pack }) { const componentName = _getComponentName(generator); const packComponentJsonPath = path.join( - _getPathToJETPack(generator, utils, pack), - CONSTANTS.COMPONENT_JSON); + _getPathToJETPack(generator, pack), + constants.COMPONENT_JSON); const packComponentJson = fs.readJSONSync(packComponentJsonPath); - packComponentJson.dependencies = { - ...(packComponentJson.dependencies || {}), - [`${pack}-${componentName}`]: '1.0.0' - }; - fs.writeJSONSync(packComponentJsonPath, packComponentJson, { spaces: 2 }); + const hasDependenciesToken = utils.loadToolingUtil().hasDependenciesToken(packComponentJson); + if (!hasDependenciesToken) { + // Only add component to dependnecies if the component.json does not have the dependencies + // token. If it does, the build will take care of adding all JET pack dependencies at build time + packComponentJson.dependencies = { + ...(packComponentJson.dependencies || {}), + [`${pack}-${componentName}`]: '1.0.0' + }; + fs.writeJSONSync(packComponentJsonPath, packComponentJson, { spaces: 2 }); + } } /** @@ -456,9 +464,8 @@ function _addComponentToPackDependencies({ generator, utils, pack }) { * in the tsconfig.json file * * @param {object} generator object with build options - * @param {object} utils object with helper methods */ -function _addComponentToTsconfigPathMapping(generator, utils) { +function _addComponentToTsconfigPathMapping(generator) { // dont create path mapping if not in a typescript application // or if component will be in a pack. The pack will already have a // path mapping that the component can be accessed through i.e @@ -479,8 +486,40 @@ function _addComponentToTsconfigPathMapping(generator, utils) { * @param {object} generator object with build options * @returns {boolean} */ -function _isVComponent(generator, utils) { +function _isVComponent(generator) { const type = generator.options.type; const vcomponent = generator.options.vcomponent; - return (type && type === CONSTANTS.VCOMPONENT) || vcomponent || utils.isVDOMApplication(); + // type can now be vcomponent or resource so need to cover + // that case + if (type !== undefined) { + return type === constants.VCOMPONENT; + } + return vcomponent || utils.loadToolingUtil().isVDOMApplication(); +} + +/** + * ## _isResourceComponent + * + * @param {object} generator object with build options + * @returns {boolean} + */ +function _isResourceComponent(generator) { + return generator.options.type === constants.RESOURCE_COMPONENT; +} + +function _filterTsxTemplates(generator, destPath) { + const componentName = _getComponentName(generator); + const pathToClassBasedTemplate = path.join(destPath, `${componentName}.tsx`); + const pathToFunctionalBasedTemplate = path.join(destPath, `${componentName}-functional-template.tsx`); + if (generator.options.vcomponent === 'function') { + // .tsx now has functional based template after overwriting it + // with .tsx contents. We need to do this because, + // once the chosen template is vcomponent, then we need to use the functional + // based template and not the class based one in .tsx . However, + // the staging folder needs to have only one file: .tsx. Hence, + // the need to overwrite the file and delete .tsx after + // overwriting. + fs.renameSync(pathToFunctionalBasedTemplate, pathToClassBasedTemplate); + } + fs.removeSync(pathToFunctionalBasedTemplate); } diff --git a/common/hookRunner.js b/common/hookRunner.js index b4acfeb..d3db67a 100644 --- a/common/hookRunner.js +++ b/common/hookRunner.js @@ -1,12 +1,12 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ */ 'use strict'; -const CONSTANTS = require('../util/constants'); +const constants = require('../lib/util/constants'); const fs = require('fs'); const path = require('path'); @@ -56,7 +56,7 @@ module.exports = { * @private */ function _getHooksConfigObj() { - const configFilePath = path.resolve(CONSTANTS.PATH_TO_HOOKS_CONFIG); + const configFilePath = path.resolve(constants.PATH_TO_HOOKS_CONFIG); if (fs.existsSync(configFilePath)) { const configFileContent = fs.readFileSync(configFilePath, 'utf8'); let configFileContentAsJson = {}; diff --git a/common/index.js b/common/index.js index 97a4689..47188b0 100644 --- a/common/index.js +++ b/common/index.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -9,10 +9,9 @@ const fs = require('fs-extra'); const path = require('path'); const commonMessages = require('./messages'); -const CONSTANTS = require('../util/constants'); -const constants = require('../lib/utils.constants'); +const constants = require('../lib/util/constants'); const app = require('../lib/scopes/app'); -const utils = require('../lib/utils'); +const utils = require('../lib/util/utils'); module.exports = { @@ -36,7 +35,7 @@ module.exports = const templateDest = path.resolve('.'); return new Promise((resolve, reject) => { function filter(src, dest) { - const isOracleJetConfigJson = path.basename(src) === CONSTANTS.APP_CONFIG_JSON; + const isOracleJetConfigJson = path.basename(src) === constants.APP_CONFIG_JSON; const isVDOMTemplate = utils.isVDOMTemplate(generator); if (isVDOMTemplate && isOracleJetConfigJson) { // for vdom templates, update the oracljetconfig.json to @@ -133,7 +132,7 @@ module.exports = validateFlags: function _validateFlags(generator) { return new Promise((resolve, reject) => { const flags = generator.options; - const SUPPORTED_FLAGS = CONSTANTS.SUPPORTED_FLAGS(flags.namespace); + const SUPPORTED_FLAGS = constants.SUPPORTED_FLAGS(flags.namespace); Object.keys(flags).forEach((key) => { if (SUPPORTED_FLAGS.indexOf(key) === -1) { if (['platforms', 'platform', 'appid', 'appname'].indexOf(key) !== -1) { @@ -149,7 +148,12 @@ module.exports = addTypescript: (generator) => { if (generator.options.typescript) { - return app.addTypescript(); + return app.addTypescript(generator.options) + .then(() => { + if (generator.options.webpack && utils.isVDOMTemplate(generator)) { + _customizeVDOMTemplateTsconfigForWebpack(); + } + }); } return Promise.resolve(); }, @@ -163,7 +167,12 @@ module.exports = addwebpack: (generator) => { if (generator.options.webpack) { - return app.addwebpack(); + return app.addwebpack(generator.options) + .then(() => { + if (utils.isVDOMTemplate(generator)) { + _customizeVDOMTemplateForWebpack(); + } + }); } return Promise.resolve(); } @@ -202,14 +211,84 @@ function _updateJSON(generator, jsonPath) { const json = fs.readJSONSync(path.resolve('.', jsonPath)); // space in app name will result in npm install failure json.name = _removeSpaceInAppName(generator.options.appname); - if (generator.options['use-global-tooling']) { + if (generator.options[constants.USE_GLOBAL_TOOLING]) { // If create wants to use the global oraclejet-tooling, // then remove the dependency link in the created package.json delete json.devDependencies[constants.ORACLEJET_TOOLING_PACKAGE_JSON_NAME]; } - fs.writeJSONSync(path.resolve('.', jsonPath), json); + utils.loadToolingUtil().writeObjectAsJsonFile(path.resolve('.', jsonPath), json); } function _removeSpaceInAppName(appName) { return appName.replace(/\s/g, '-'); } + +function _customizeVDOMTemplateTsconfigForWebpack() { + // Add resolveJsonModule and esModuleInterop to app's tsconfig.json + const pathToApp = '.'; + const pathToOraclejetConfigJson = path.join(pathToApp, 'oraclejetconfig.json'); + const oraclejetConfigJson = fs.readJSONSync(pathToOraclejetConfigJson); + const pathToTsconfigJson = path.join(pathToApp, 'tsconfig.json'); + const tsconfigJson = fs.readJSONSync(pathToTsconfigJson); + tsconfigJson.compilerOptions.rootDir = `./${oraclejetConfigJson.paths.source.common}`; + tsconfigJson.compilerOptions.outDir = `./${oraclejetConfigJson.paths.staging.web}`; + tsconfigJson.compilerOptions.typeRoots.unshift('./types'); + tsconfigJson.compilerOptions.resolveJsonModule = true; + tsconfigJson.compilerOptions.esModuleInterop = true; + tsconfigJson.compilerOptions.paths.react = [ + './node_modules/preact/compat/src/index.d.ts' + ]; + tsconfigJson.compilerOptions.paths['react-dom'] = [ + './node_modules/preact/compat/src/index.d.ts' + ]; + fs.writeJSONSync(pathToTsconfigJson, tsconfigJson, { spaces: 2 }); +} + +function _customizeVDOMTemplateForWebpack() { + const pathToApp = '.'; + const pathToOraclejetConfigJson = path.join(pathToApp, 'oraclejetconfig.json'); + const oraclejetConfigJson = fs.readJSONSync(pathToOraclejetConfigJson); + // Remove injector tokens from index.html + const pathToIndexHtml = path.join( + pathToApp, + oraclejetConfigJson.paths.source.common, + 'index.html' + ); + let indexHtmlContent = fs.readFileSync(pathToIndexHtml, { encoding: 'utf-8' }).toString(); + indexHtmlContent = indexHtmlContent.replace(//gm, '').replace(/^\s*\n/gm, ''); + indexHtmlContent = indexHtmlContent.replace(/()/, '$1\n '); + fs.outputFileSync(pathToIndexHtml, indexHtmlContent); + // Delete ./src/main.js since webpack entry point is index.ts + const pathToMainJs = path.join( + pathToApp, + oraclejetConfigJson.paths.source.common, + oraclejetConfigJson.paths.source.javascript, + 'main.js' + ); + fs.removeSync(pathToMainJs); + // Delete ./scripts since not used by webpack build + const pathToScriptsFolder = path.join(pathToApp, 'scripts'); + fs.removeSync(pathToScriptsFolder); + // Delete ./path_mapping.json since not used by webpack build + const pathToPathMappingJson = path.join(pathToApp, 'path_mapping.json'); + fs.removeSync(pathToPathMappingJson); + // Replace ./.gitignore and replace + const pathToGitIgnore = path.join(pathToApp, '.gitignore'); + const gitIgnoreContent = + `/node_modules +/${oraclejetConfigJson.paths.source.exchangeComponents} +/${oraclejetConfigJson.paths.staging.web} +.DS_Store`.trim(); + fs.outputFileSync(pathToGitIgnore, gitIgnoreContent); + // Inject ./types/components/index.ts + const pathToComponentTypes = path.join(pathToApp, 'types/components/index.d.ts'); + const componentTypesContent = ` + // Add custom element entries to preact.JSX.IntrinsicElements for custom elements + // used in JSX that do not have the required type definitions + declare namespace preact.JSX { + interface IntrinsicElements { + + } + }`; + fs.outputFileSync(pathToComponentTypes, componentTypesContent); +} diff --git a/common/messages.js b/common/messages.js index de55509..8eda557 100644 --- a/common/messages.js +++ b/common/messages.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/common/restore.js b/common/restore.js index 8ffba27..6ae0e15 100644 --- a/common/restore.js +++ b/common/restore.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -10,37 +10,37 @@ const execSync = require('child_process').execSync; const fs = require('fs-extra'); const path = require('path'); const commonMessages = require('./messages'); -const generatorJSON = require('../package.json'); -const CONSTANTS = require('../lib/utils.constants'); +const constants = require('../lib/util/constants'); +const utils = require('../lib/util/utils'); module.exports = { - writeOracleJetConfigFile: function _writeOracleJetConfigFile(generator, utils) { + writeOracleJetConfigFile: function _writeOracleJetConfigFile() { const destinationRoot = path.resolve('.'); - const configPath = path.resolve(destinationRoot, CONSTANTS.APP_CONFIG_JSON); + const configPath = path.resolve(destinationRoot, constants.APP_CONFIG_JSON); return new Promise((resolve) => { - const generatorVersion = generatorJSON.version; let configJson; if (!fs.existsSync(configPath)) { - utils.log(`${commonMessages.appendJETPrefix()}No ${CONSTANTS.APP_CONFIG_JSON}, writing default`); + utils.log(`${commonMessages.appendJETPrefix()}No ${constants.APP_CONFIG_JSON}, writing default`); configJson = utils.readJsonAndReturnObject(path.join( __dirname, '../../template/common', - CONSTANTS.APP_CONFIG_JSON + constants.APP_CONFIG_JSON )); } else { - utils.log(`${commonMessages.appendJETPrefix() + CONSTANTS.APP_CONFIG_JSON} file exists, updating generatorVersion`); + utils.log(`${commonMessages.appendJETPrefix() + constants.APP_CONFIG_JSON} file exists`); configJson = utils.readJsonAndReturnObject(configPath); } - configJson.generatorVersion = generatorVersion; fs.writeFileSync(configPath, JSON.stringify(configJson, null, 2)); resolve(); }); }, - npmInstall: function _npmInstall() { + npmInstall: function _npmInstall(app, opt) { return new Promise((resolve) => { - const cmd = 'npm install'; + const installer = utils.getInstallerCommand(opt); + + const cmd = `${installer.installer} ${installer.verbs.install}`; fs.ensureDirSync(path.join('node_modules')); execSync(cmd, null); resolve(); diff --git a/common/template/common.js b/common/template/common.js index f1d64e2..5f4e463 100644 --- a/common/template/common.js +++ b/common/template/common.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -10,8 +10,8 @@ const Admzip = require('adm-zip'); const fs = require('fs-extra'); const path = require('path'); const graphics = require('../../hybrid/graphics'); -const utils = require('../../lib/utils'); -const CONSTANTS = require('../../lib/utils.constants'); +const utils = require('../../lib/util/utils'); +const constants = require('../../lib/util/constants'); /** * Inject template files into scaffolded application depending @@ -23,7 +23,7 @@ const CONSTANTS = require('../../lib/utils.constants'); function _injectTemplateFiles({ generator, namespace }) { const pathToTemplates = path.resolve(__dirname, `../../generators/${namespace}/templates/common`); const pathToApp = path.resolve(generator.appDir); - const template = generator.options.template || CONSTANTS.BLANK_TEMPLATE; + const template = generator.options.template || constants.BLANK_TEMPLATE; function _templateFileFilter(file) { const screenPath = path.join(graphics.PATH, 'screen'); const iconPath = path.join(graphics.PATH, 'icon'); @@ -79,7 +79,7 @@ function _injectTemplateFiles({ generator, namespace }) { const { ORACLEJET_PACKAGE_JSON_NAME: oraclejet, ORACLEJET_TOOLING_PACKAGE_JSON_NAME: oraclejetTooling - } = CONSTANTS; + } = constants; let updatedAppPackageJson = false; if (!appDependencies[oraclejet]) { // app's package.json does not have an entry for @oracle/oraclejet in depedencies. diff --git a/common/template/index.js b/common/template/index.js index 087e30c..a488365 100644 --- a/common/template/index.js +++ b/common/template/index.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -11,18 +11,18 @@ const commonTemplate = require('./common'); const npmTemplate = require('./npm'); const localTemplate = require('./local'); const path = require('path'); -const util = require('../../util'); -const CONSTANTS = require('../../lib/utils.constants'); +const utils = require('../../lib/util/utils'); +const constants = require('../../lib/util/constants'); const _HYBRID = 'hybrid'; const _WEB = 'web'; -const _TEMPLATES_NPM_URL = '@oracle/oraclejet-templates@~11.1.0'; +const _TEMPLATES_NPM_URL = '@oracle/oraclejet-templates@~12.0.0'; module.exports = { - handleTemplate: function _handleTemplate(generator, utils, templateDestDirectory) { - const template = generator.options.template || CONSTANTS.BLANK_TEMPLATE; + handleTemplate: function _handleTemplate(generator, templateDestDirectory) { + const template = generator.options.template || constants.BLANK_TEMPLATE; utils.log(`Processing template: ${template}`); const templateHandler = _getHandler(generator, template, templateDestDirectory); return commonTemplate.handle(templateHandler, generator.options.namespace); @@ -38,7 +38,7 @@ function _getHandler(generator, template, templateDestDirectory) { } // Template is an existing local path, but can not point to application itself - if (templateLocalPath && CONSTANTS.NPM_TEMPLATES.indexOf(template) === -1) { + if (templateLocalPath && constants.NPM_TEMPLATES.indexOf(template) === -1) { return localTemplate.handle(generator, templateLocalPath, templateDestDirectory); } const templateSpec = _resolveTemplateSpec(generator, template); @@ -81,9 +81,9 @@ function _resolveTemplateSpec(generator, template) { } function _validateTemplateName(templateName) { - if (CONSTANTS.NPM_TEMPLATES.indexOf(templateName) < 0) { + if (constants.NPM_TEMPLATES.indexOf(templateName) < 0) { let templateList = ''; - CONSTANTS.NPM_TEMPLATES.forEach((value) => { + constants.NPM_TEMPLATES.forEach((value) => { templateList += `\n ${value}`; }); const msg = `\nA URL or one of the following names is expected: ${templateList}`; @@ -106,5 +106,5 @@ function _getLocalFileAbsolutePath(templatePath) { : path.join(process.env.HOME, templatePath.slice(1)); const absolutePath = path.isAbsolute(tempPath) ? tempPath : path.resolve(process.cwd(), tempPath); - return util.fsExistsSync(absolutePath) ? absolutePath : null; + return utils.fsExistsSync(absolutePath) ? absolutePath : null; } diff --git a/common/template/local.js b/common/template/local.js index f90a550..8442904 100644 --- a/common/template/local.js +++ b/common/template/local.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/common/template/npm.js b/common/template/npm.js index 28023b3..dfd564b 100644 --- a/common/template/npm.js +++ b/common/template/npm.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -9,8 +9,8 @@ const fs = require('fs-extra'); const path = require('path'); const execSync = require('child_process').execSync; -const utils = require('../../lib/utils'); -const injectorUtils = require('../../lib/utils.injectors'); +const utils = require('../../lib/util/utils'); +const injectorUtils = require('../../lib/util/injectors'); module.exports = { diff --git a/common/template/url.js b/common/template/url.js index dbba2ca..b32524b 100644 --- a/common/template/url.js +++ b/common/template/url.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -8,7 +8,7 @@ const commonTemplateHandler = require('./common'); const fs = require('fs-extra'); -const fetchZip = require('../../util/fetchZip'); +const fetchZip = require('../../lib/util/fetchZip'); const path = require('path'); module.exports = { diff --git a/config.js b/config.js index 9ae0c1c..33cd10a 100644 --- a/config.js +++ b/config.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -521,6 +521,10 @@ const config = { password: { aliases: ['p'], description: 'The user\'s registered password' + }, + ci: { + description: 'Use npm ci instead of npm install', + default: 'false' } }, examples: [ @@ -706,6 +710,9 @@ const config = { aliases: ['h'], description: 'Print help for the command' }, + installer: { + description: 'Specify an alternate package installer such as yarn' + }, verbose: { description: 'Print details' }, diff --git a/config.json b/config.json index 3ac9399..cb8a813 100644 --- a/config.json +++ b/config.json @@ -1,3 +1,3 @@ {"eslintDirs": ["../ojet-cli"], - "eslintFilter": ["!../ojet-cli/test/**", "!../ojet-cli/generators/**/*template*/**/*.js", "!../ojet-cli/Gruntfile.js", "!../ojet-cli/test/**/*.js", "!../ojet-cli/config/**/*.js", "!../ojet-cli/template/**/*.js"], + "eslintFilter": ["!../ojet-cli/dist/**", "!../ojet-cli/test/**", "!../ojet-cli/generators/**/*template*/**/*.js", "!../ojet-cli/Gruntfile.js", "!../ojet-cli/test/**/*.js", "!../ojet-cli/config/**/*.js", "!../ojet-cli/template/**/*.js"], "fixup": ["package.json", "index.js"]} \ No newline at end of file diff --git a/generators/add-component/index.js b/generators/add-component/index.js index 4784a8d..371987d 100644 --- a/generators/add-component/index.js +++ b/generators/add-component/index.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -9,6 +9,8 @@ const common = require('../../common'); const commonComponent = require('../../common/component'); const commonHookRunner = require('../../common/hookRunner'); +const utils = require('../../lib/util/utils'); + /** * # Entry point for 'add component' task @@ -16,20 +18,19 @@ const commonHookRunner = require('../../common/hookRunner'); * @public * @param {Array} parameters * @param {Object} options - * @param {utils} utility module */ -module.exports = function (parameters, opt, utils) { +module.exports = function (parameters, opt) { const addComponent = { arguments: parameters, options: Object.assign({ namespace: 'add-component', componentName: parameters }, opt) }; return common.validateFlags(addComponent) - .then(() => commonComponent.checkThatAppExists(utils)) - .then(() => commonComponent.validateComponentName(addComponent, utils)) - .then(() => commonComponent.writeComponentTemplate(addComponent, utils)) + .then(() => commonComponent.checkThatAppExists) + .then(() => commonComponent.validateComponentName(addComponent)) + .then(() => commonComponent.writeComponentTemplate(addComponent)) .then(() => commonHookRunner.runAfterComponentCreateHook( - { componentPath: commonComponent.getComponentDestPath(addComponent, utils) })) - .then(() => commonComponent.logSuccessMessage(addComponent, utils)) + { componentPath: commonComponent.getComponentDestPath(addComponent) })) + .then(() => commonComponent.logSuccessMessage(addComponent)) .catch((error) => { utils.log.error(error); return Promise.reject(); diff --git a/generators/add-hybrid/index.js b/generators/add-hybrid/index.js index fecbd77..79e7b8b 100644 --- a/generators/add-hybrid/index.js +++ b/generators/add-hybrid/index.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -10,12 +10,12 @@ const childProcess = require('child_process'); const fs = require('fs-extra'); const path = require('path'); const common = require('../../common'); -const paths = require('../../util/paths'); +const paths = require('../../lib/util/paths'); const commonMessages = require('../../common/messages'); const commonHybrid = require('../../hybrid'); const cordovaHelper = require('../../hybrid/cordova'); const platformsHelper = require('../../hybrid/platforms'); -const util = require('../../util'); +const utils = require('../../lib/util/utils'); const _configPaths = {}; @@ -96,7 +96,7 @@ function _copyCordovaMocks() { const dest = path.resolve(`./${srcHybridPath}/${srcJsPath}/`); return new Promise((resolve, reject) => { - if (util.fsExistsSync(source)) { + if (utils.fsExistsSync(source)) { fs.copy(source, dest, (err) => { if (err) { reject(err); @@ -117,9 +117,8 @@ function _copyCordovaMocks() { * @public * @param {Array} parameters * @param {Object} options - * @param {utils} utility module */ -module.exports = function (parameters, opt, utils) { +module.exports = function (parameters, opt) { const addHybrid = { arguments: parameters, options: Object.assign({ namespace: 'add-hybrid' }, opt) @@ -134,14 +133,14 @@ module.exports = function (parameters, opt, utils) { addHybrid.appDir = path.basename(path.resolve('.')); commonHybrid.setupHybridEnv(addHybrid); }) - .then(() => platformsHelper.getPlatforms(addHybrid, utils)) + .then(() => platformsHelper.getPlatforms(addHybrid)) .then(() => _createExtraSrcDirs(addHybrid)) .then(() => cordovaHelper.create(addHybrid)) .then(() => commonHybrid.copyHooks()) .then(() => commonHybrid.copyResources()) .then(_copyCordovaMocks) .then(() => commonHybrid.removeExtraCordovaFiles()) - .then(() => platformsHelper.addPlatforms(addHybrid, utils)) + .then(() => platformsHelper.addPlatforms(addHybrid)) .then(() => commonHybrid.updateConfigXml(addHybrid)) .then(() => { utils.log(commonMessages.appendJETPrefix('Add hybrid finished.')); diff --git a/generators/add-pcss-theme/index.js b/generators/add-pcss-theme/index.js index 420c4a9..4ab61f4 100644 --- a/generators/add-pcss-theme/index.js +++ b/generators/add-pcss-theme/index.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -8,9 +8,10 @@ const fs = require('fs-extra'); const path = require('path'); -const constants = require('../../util/constants'); +const constants = require('../../lib/util/constants'); const common = require('../../common'); -const paths = require('../../util/paths'); +const paths = require('../../lib/util/paths'); +const utils = require('../../lib/util/utils'); const commonMessages = require('../../common/messages'); const DEFAULT_THEME = 'mytheme'; @@ -199,12 +200,13 @@ function _addPcssTheme(addTheme) { _loadComponentRefrence(addTheme, themeDestPath); resolve(addTheme); } catch (err) { + utils.log.error(err); reject(); } }); } -function _updateBaseTheme(themeAdded, utils) { +function _updateBaseTheme(themeAdded) { const themeName = themeAdded.themeName; const _configpaths = paths.getConfiguredPaths(path.resolve('.')); const srcPath = _configpaths.source; @@ -221,6 +223,7 @@ function _updateBaseTheme(themeAdded, utils) { fs.writeFileSync(themeConfigPath, JSON.stringify(themeConfigJson, null, 2)); resolve(themeAdded); } catch (err) { + utils.log.error(err); reject(); } }); @@ -232,9 +235,8 @@ function _updateBaseTheme(themeAdded, utils) { * @public * @param {Array} parameters * @param {Object} options - * @param {utils} utility module */ -module.exports = function (parameters, opt, utils) { +module.exports = function (parameters, opt) { const pcssTheme = { themeOption: Object.prototype.hasOwnProperty.call(opt, constants.PCSS_THEME_FLAG), themeOptionValue: opt[constants.PCSS_THEME_FLAG], @@ -268,7 +270,7 @@ module.exports = function (parameters, opt, utils) { return common.validateArgs(pcssTheme) .then(common.validateFlags) .then(_addPcssTheme(pcssTheme)) - .then(_updateBaseTheme(pcssTheme, utils)) + .then(_updateBaseTheme(pcssTheme)) .then(() => { utils.log.success(commonMessages.appendJETPrefix(`${pcssTheme.themeName} theme added, with css variables support.`)); }) diff --git a/generators/add-pcss-theme/templates/mytheme/web/mytheme.scss b/generators/add-pcss-theme/templates/mytheme/web/mytheme.scss index daee183..b496ad5 100644 --- a/generators/add-pcss-theme/templates/mytheme/web/mytheme.scss +++ b/generators/add-pcss-theme/templates/mytheme/web/mytheme.scss @@ -3,19 +3,19 @@ // If you uncomment other imports please set generatedFileType to 'combined' in theme.json. // Please see the developer guide link below for more information // http://www.oracle.com/pls/topic/lookup?ctx=jetlatest&id=GUID-12A65AC0-4784-46FE-AC8C-09FA509737E4 - + // import SASS custom variable overrides // @import "_<%= themename %>.sass.settings.scss"; - + // Imports all jet components styles // @import "<%= importcomponents %>"; - + // To optimize performance, consider commenting out the above oj-all-components // import and uncomment _<%= themename %>.components.scss below. // Then in _<%= themename %>.components.scss uncomment only the component // imports that your application needs. - + // @import "_<%= themename %>.optimize-components.scss"; - + // import CSS Custom properties -@import "_<%= themename %>.cssvars.settings.scss"; \ No newline at end of file +@import "_<%= themename %>.cssvars.settings.scss"; diff --git a/generators/add-theme/index.js b/generators/add-theme/index.js index 12d4205..0613f55 100644 --- a/generators/add-theme/index.js +++ b/generators/add-theme/index.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -8,9 +8,10 @@ const fs = require('fs-extra'); const path = require('path'); -const constants = require('../../util/constants'); +const constants = require('../../lib/util/constants'); const common = require('../../common'); -const paths = require('../../util/paths'); +const paths = require('../../lib/util/paths'); +const utils = require('../../lib/util/utils'); const commonMessages = require('../../common/messages'); const DEFAULT_THEME = 'mytheme'; @@ -25,9 +26,8 @@ const THEMENAME_TOKEN = '<%= themename %>'; * @public * @param {Array} parameters * @param {Object} options - * @param {utils} utility module */ -module.exports = function (parameters, opt, utils) { +module.exports = function (parameters, opt) { const addTheme = { themeName: parameters, arguments: [parameters], diff --git a/generators/app/index.js b/generators/app/index.js index 4831737..49fa608 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -12,13 +12,14 @@ const commonMessages = require('../../common/messages'); const commonRestore = require('../../common/restore'); const templateHandler = require('../../common/template'); const scopesApp = require('../../lib/scopes/app'); +const utils = require('../../lib/util/utils'); const fs = require('fs'); const path = require('path'); -function _writeTemplate(generator, utils) { +function _writeTemplate(generator) { return new Promise((resolve, reject) => { const appDirectory = path.resolve(path.join(generator.appDir, 'src')); - templateHandler.handleTemplate(generator, utils, appDirectory) + templateHandler.handleTemplate(generator, appDirectory) .then(() => { resolve(); }) @@ -34,9 +35,8 @@ function _writeTemplate(generator, utils) { * @public * @param {Array} parameters * @param {Object} options - * @param {utils} utility module */ -module.exports = function (parameters, opt, utils) { +module.exports = function (parameters, opt) { const app = { options: Object.assign({ namespace: 'app' }, opt), appDir: parameters @@ -52,17 +52,17 @@ module.exports = function (parameters, opt, utils) { .then(() => common.writeCommonTemplates(app)) .then(() => common.writeGitIgnore()) .then(() => common.switchFromAppDirectory()) - .then(() => _writeTemplate(app, utils)) + .then(() => _writeTemplate(app)) .then(() => common.switchToAppDirectory(app)) .then(() => common.updatePackageJSON(app)) .then(() => { utils.log(commonMessages.scaffoldComplete()); if (!app.options.norestore) { - return commonRestore.npmInstall(app) - .then(() => commonRestore.writeOracleJetConfigFile(app, utils)) - .then(() => common.addTypescript(app)) + return commonRestore.npmInstall(app, opt) + .then(() => commonRestore.writeOracleJetConfigFile()) + .then(() => common.addTypescript(app, opt)) .then(() => common.addpwa(app)) - .then(() => common.addwebpack(app)) + .then(() => common.addwebpack(app, opt)) .then(scopesApp.addComponents) .then(commonHookRunner.runAfterAppCreateHook) .then(() => { diff --git a/generators/app/templates/common/package.json b/generators/app/templates/common/package.json index a26427b..1365bf8 100644 --- a/generators/app/templates/common/package.json +++ b/generators/app/templates/common/package.json @@ -3,13 +3,13 @@ "version": "1.0.0", "description": "An Oracle JavaScript Extension Toolkit(JET) web app", "dependencies": { - "@oracle/oraclejet": "~11.1.0" + "@oracle/oraclejet": "~12.0.0" }, "devDependencies": { "fs-extra": "^8.1.0", "glob": "^7.1.1", "underscore": "^1.10.2", - "@oracle/oraclejet-tooling": "~11.1.0" + "@oracle/oraclejet-tooling": "~12.0.0" }, "engines": { "node": ">=12.21.0" diff --git a/generators/hybrid/index.js b/generators/hybrid/index.js index fda33ae..b03cd17 100644 --- a/generators/hybrid/index.js +++ b/generators/hybrid/index.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -7,7 +7,7 @@ 'use strict'; const exec = require('child_process').exec; -const paths = require('../../util/paths'); +const paths = require('../../lib/util/paths'); const path = require('path'); const templateHandler = require('../../common/template/'); const common = require('../../common'); @@ -17,6 +17,7 @@ const commonMessages = require('../../common/messages'); const commonRestore = require('../../common/restore'); const cordovaHelper = require('../../hybrid/cordova'); const platformsHelper = require('../../hybrid/platforms'); +const utils = require('../../lib/util/utils'); const fs = require('fs-extra'); /* @@ -49,11 +50,11 @@ function _invokeCordovaPrepare(generator) { }); } -function _writeTemplate(generator, utils) { +function _writeTemplate(generator) { return new Promise((resolve, reject) => { const appDir = generator.appDir; const appDirectory = path.resolve(appDir, 'src'); - templateHandler.handleTemplate(generator, utils, appDirectory) + templateHandler.handleTemplate(generator, appDirectory) .then(() => { resolve(); }) @@ -69,9 +70,8 @@ function _writeTemplate(generator, utils) { * @public * @param {Array} parameters * @param {Object} options - * @param {utils} utility module */ -module.exports = function (parameters, opt, utils) { +module.exports = function (parameters, opt) { const app = { options: Object.assign({ namespace: 'hybrid' }, opt), appDir: parameters @@ -85,7 +85,7 @@ module.exports = function (parameters, opt, utils) { commonHybrid.setupHybridEnv(app); fs.mkdirSync(path.resolve(app.appDir)); }) - .then(() => platformsHelper.getPlatforms(app, utils)) + .then(() => platformsHelper.getPlatforms(app)) .then(() => common.switchToAppDirectory(app)) .then(() => common.writeCommonTemplates(app)) .then(() => common.writeGitIgnore()) @@ -93,19 +93,19 @@ module.exports = function (parameters, opt, utils) { .then(() => commonHybrid.copyResources()) .then(() => commonHybrid.removeExtraCordovaFiles()) .then(() => common.switchFromAppDirectory()) - .then(() => _writeTemplate(app, utils)) + .then(() => _writeTemplate(app)) .then(() => common.switchToAppDirectory(app)) .then(() => common.updatePackageJSON(app)) - .then(() => platformsHelper.addPlatforms(app, utils)) + .then(() => platformsHelper.addPlatforms(app)) .then(() => commonHybrid.updateConfigXml(app)) .then(() => { utils.log(commonMessages.scaffoldComplete()); if (!app.options.norestore) { - return commonRestore.npmInstall(app) + return commonRestore.npmInstall(app, opt) .then(() => commonHybrid.copyHooks()) - .then(() => commonRestore.writeOracleJetConfigFile(app, utils)) + .then(() => commonRestore.writeOracleJetConfigFile()) .then(() => _invokeCordovaPrepare(app)) - .then(() => common.addTypescript(app)) + .then(() => common.addTypescript(app, opt)) .then(() => commonHookRunner.runAfterAppCreateHook()) .then(() => utils.log(commonMessages.restoreComplete( app.options.invokedByRestore, diff --git a/generators/hybrid/templates/common/package.json b/generators/hybrid/templates/common/package.json index a9a73d6..7b63c59 100644 --- a/generators/hybrid/templates/common/package.json +++ b/generators/hybrid/templates/common/package.json @@ -3,13 +3,13 @@ "version": "1.0.0", "description": "An Oracle JavaScript Extension Toolkit (JET) mobile app", "dependencies": { - "@oracle/oraclejet": "~11.1.0" + "@oracle/oraclejet": "~12.0.0" }, "devDependencies": { "fs-extra": "^8.1.0", "glob": "^7.1.1", "underscore": "^1.10.2", - "@oracle/oraclejet-tooling": "~11.1.0" + "@oracle/oraclejet-tooling": "~12.0.0" }, "engines": { "node": ">=12.21.0" diff --git a/generators/hybrid/templates/common/src/js/cordovaMocks.js b/generators/hybrid/templates/common/src/js/cordovaMocks.js index 8323fda..6f5b443 100644 --- a/generators/hybrid/templates/common/src/js/cordovaMocks.js +++ b/generators/hybrid/templates/common/src/js/cordovaMocks.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/hybrid/cordova.js b/hybrid/cordova.js index a89499f..cb36f93 100644 --- a/hybrid/cordova.js +++ b/hybrid/cordova.js @@ -1,13 +1,13 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ */ 'use strict'; -const paths = require('../util/paths'); -const utils = require('../lib/utils'); +const paths = require('../lib/util/paths'); +const utils = require('../lib/util/utils'); const fs = require('fs-extra'); const path = require('path'); const childProcess = require('child_process'); diff --git a/hybrid/graphics.js b/hybrid/graphics.js index dc22e14..22df1cd 100644 --- a/hybrid/graphics.js +++ b/hybrid/graphics.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/hybrid/index.js b/hybrid/index.js index fbab2ab..e457437 100644 --- a/hybrid/index.js +++ b/hybrid/index.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -8,13 +8,13 @@ const fs = require('fs-extra'); const path = require('path'); -const constants = require('../util/constants'); +const constants = require('../lib/util/constants'); const commonMessages = require('../common/messages'); const DOMParser = require('xmldom').DOMParser; const endOfLine = require('os').EOL; const graphics = require('./graphics'); -const paths = require('../util/paths'); -const utils = require('../lib/utils'); +const paths = require('../lib/util/paths'); +const utils = require('../lib/util/utils'); const ORACLEJET_APP_ID = 'org.oraclejet.'; const iOSPlugins = ['cordova-plugin-wkwebview-file-xhr', diff --git a/hybrid/platforms.js b/hybrid/platforms.js index 93c3dc0..9722a57 100644 --- a/hybrid/platforms.js +++ b/hybrid/platforms.js @@ -1,15 +1,16 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ */ 'use strict'; -const constants = require('../util/constants'); +const constants = require('../lib/util/constants'); const path = require('path'); -const paths = require('../util/paths'); +const paths = require('../lib/util/paths'); const commonMessages = require('../common/messages'); +const utils = require('../lib/util/utils'); const inquirer = require('inquirer'); const childProcess = require('child_process'); @@ -52,14 +53,14 @@ const TEST_COMMAND = module.exports = { - getPlatforms: function _getPlatforms(generatorArg, utils) { + getPlatforms: function _getPlatforms(generatorArg) { const generator = generatorArg; if (generator.options.platforms || generator.options.platform) { // platforms = generator.options.platforms || generator.options.platform; return new Promise((resolve) => { - _validatePlatforms(generator, utils) + _validatePlatforms(generator) .then((processedPlatforms) => { generator._platformsToInstall = processedPlatforms; resolve(generator); @@ -69,7 +70,7 @@ module.exports = return new Promise((resolve, reject) => { // if platforms option is not provided do prompt - _testPlatforms(constants.SUPPORTED_HYBRID_PLATFORMS, utils) + _testPlatforms(constants.SUPPORTED_HYBRID_PLATFORMS) .then((possiblePlatforms) => { if (!possiblePlatforms.length) { resolve(generator); @@ -93,7 +94,7 @@ module.exports = }); }, - addPlatforms: function _addPlatforms(generator, utils) { + addPlatforms: function _addPlatforms(generator) { const platforms = generator._platformsToInstall; // always add the browser platform @@ -129,12 +130,12 @@ module.exports = * @param {type} generator * @return {Promise} */ -function _validatePlatforms(generator, utils) { +function _validatePlatforms(generator) { const platformOptions = generator.options.platforms || generator.options.platform; - const platforms = _processPlatformOptions(platformOptions, utils); + const platforms = _processPlatformOptions(platformOptions); return new Promise((resolve) => { - _testPlatforms(platforms, utils) + _testPlatforms(platforms) .then((availablePlatforms) => { const failedPlatforms = []; platforms.forEach((entry) => { @@ -164,9 +165,9 @@ function _validatePlatforms(generator, utils) { * @param {Array} platforms array of requested platforms * @return {Promise} a promise object */ -function _testPlatforms(platforms, utils) { +function _testPlatforms(platforms) { const filteredTestCommands = _getFilteredTestCommands(platforms); - const platformTests = _getPlatformTests(filteredTestCommands, utils); + const platformTests = _getPlatformTests(filteredTestCommands); // note there exists no reject since want to test all the filteredTestCommands // and when there are errors (i.e. test command fails) it will resolve w/o that platform return new Promise((resolve) => { @@ -190,7 +191,7 @@ function _filterPromptingPlatforms(promptPlatforms) { promptPlatforms.indexOf(type.value) !== -1); } -function _processPlatformOptions(platforms, utils) { +function _processPlatformOptions(platforms) { if (!platforms) { return []; } @@ -216,11 +217,11 @@ function _getFilteredTestCommands(platforms) { return TEST_COMMAND.filter(type => platforms.indexOf(type.platform) !== -1); } -function _getPlatformTests(platforms, utils) { +function _getPlatformTests(platforms) { const platformTests = []; platforms.forEach((info) => { - platformTests.push(_createPlatformTest(info, utils)); + platformTests.push(_createPlatformTest(info)); }); return platformTests; diff --git a/lib/scopes/app.js b/lib/scopes/app.js index 37a0d3e..db3ba68 100644 --- a/lib/scopes/app.js +++ b/lib/scopes/app.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -15,11 +15,10 @@ const path = require('path'); // Oracle const config = require('../../config'); -const CONSTANTS = require('../utils.constants'); -const paths = require('../utils.paths'); -const pckg = require('../../package.json'); +const constants = require('../util/constants'); +const paths = require('../util/paths'); const tooling = require('../tooling'); -const utils = require('../utils'); +const utils = require('../util/utils'); const addTheme = require('../../generators/add-theme'); const addPcssTheme = require('../../generators/add-pcss-theme'); const addHybrid = require('../../generators/add-hybrid'); @@ -41,38 +40,38 @@ const app = module.exports; * @param {string} [parameter] * @param {Object} [options] */ -app.create = function (parameter, options, util) { +app.create = function (parameter, options) { const opts = options; if (opts && utils.hasProperty(opts, 'hybrid')) { // Deleting 'hybrid' flag delete opts.hybrid; - return addAppHybrid(parameter, opts, util); + return addAppHybrid(parameter, opts); } // Deleting 'web' flag if (opts && utils.hasProperty(opts, 'web')) { delete opts.web; } - return addApp(parameter, opts, util); + return addApp(parameter, opts); }; -app.createComponent = function (parameter, options, util) { - return addComponent(parameter, options, util); +app.createComponent = function (parameter, options) { + return addComponent(parameter, options); }; -app.createTheme = function (parameter, options, util) { +app.createTheme = function (parameter, options) { if (!utils.validCustomProperties()) { - return addTheme(parameter, options, util); + return addTheme(parameter, options); } - return addPcssTheme(parameter, options, util); + return addPcssTheme(parameter, options); }; -app.addHybrid = function (parameters, options, util) { - return addHybrid(parameters, options, util); +app.addHybrid = function (parameters, options) { + return addHybrid(parameters, options); }; -app.addSass = function () { +app.addSass = function (options) { const toolingModule = utils.loadTooling(); - return toolingModule.addsass() + return toolingModule.addsass(options) .then(() => { utils.log.success('add sass complete'); }) @@ -82,9 +81,9 @@ app.addSass = function () { }); }; -app.addPcss = function () { +app.addPcss = function (options) { const toolingModule = utils.loadTooling(); - return toolingModule.addpcss() + return toolingModule.addpcss(options) .then(() => { utils.log.success('add pcss complete'); }) @@ -94,9 +93,9 @@ app.addPcss = function () { }); }; -app.addTypescript = function () { +app.addTypescript = function (options) { const toolingModule = utils.loadTooling(); - return toolingModule.addtypescript() + return toolingModule.addtypescript(options) .then(() => { utils.log.success('add typescript complete'); }) @@ -118,9 +117,9 @@ app.addpwa = function () { }); }; -app.addwebpack = function () { +app.addwebpack = function (options) { const toolingModule = utils.loadTooling(); - return toolingModule.addwebpack() + return toolingModule.addwebpack(options) .then(() => { utils.log.success('add webpack complete'); }) @@ -140,17 +139,18 @@ app.restore = function (options) { process.env.options = JSON.stringify(options); // if the project contains cordova's config.xml, consider it to be a hybrid; otherwise web const cordovaDir = paths.getConfiguredPaths(process.cwd()).stagingHybrid; - const isHybrid = fs.existsSync(path.resolve(cordovaDir, CONSTANTS.CORDOVA_CONFIG_XML)); - const appType = CONSTANTS.APP_TYPE; + const isHybrid = fs.existsSync(path.resolve(cordovaDir, constants.CORDOVA_CONFIG_XML)); + + const appType = constants.APP_TYPE; const restoreType = isHybrid ? appType.HYBRID : appType.WEB; if (restoreType === 'web') { - return _restoreWeb(); + return _restoreWeb(options); } - return _restoreHybrid(); + return _restoreHybrid(options); }; app.addComponents = function () { - const configPath = path.join(process.cwd(), CONSTANTS.APP_CONFIG_JSON); + const configPath = path.join(process.cwd(), constants.APP_CONFIG_JSON); const configJson = utils.readJsonAndReturnObject(configPath); const componentList = configJson.components; if (!utils.isObjectEmpty(componentList)) { @@ -172,9 +172,10 @@ app.addComponents = function () { * ## _restoreWeb * * @private + * @param {Object} [options] */ -function _restoreWeb() { - return _npmInstall() +function _restoreWeb(options) { + return _npmInstall(options) .then(_writeOracleJetConfigFile) .then(app.addComponents) .then(_runAfterAppRestoreHook) @@ -191,10 +192,13 @@ function _restoreWeb() { * ## _npmInstall * * @private + * @param {Object} [options] */ -function _npmInstall() { - utils.log('Performing \'npm install\' may take a bit.'); - return utils.spawn('npm', ['install']); +function _npmInstall(options) { + const installer = utils.getInstallerCommand(options); + + utils.log(`Performing '${installer.installer} ${installer.verbs.install}' may take a bit.`); + return utils.spawn(installer.installer, [installer.verbs.install]); } /** @@ -204,22 +208,20 @@ function _npmInstall() { */ function _writeOracleJetConfigFile() { return new Promise((resolve) => { - utils.log(`Checking '${CONSTANTS.APP_CONFIG_JSON}'config file.`); - const configPath = path.join(process.cwd(), CONSTANTS.APP_CONFIG_JSON); - const generatorVersion = pckg.version; + utils.log(`Checking '${constants.APP_CONFIG_JSON}'config file.`); + const configPath = path.join(process.cwd(), constants.APP_CONFIG_JSON); let configJson; if (!fs.existsSync(configPath)) { utils.log('No config file. Adding the default.'); configJson = utils.readJsonAndReturnObject(path.join( __dirname, '../../template/common', - CONSTANTS.APP_CONFIG_JSON + constants.APP_CONFIG_JSON )); } else { - utils.log(`'${CONSTANTS.APP_CONFIG_JSON}' file exists. Adding/updating version.`); + utils.log(`'${constants.APP_CONFIG_JSON}' file exists.`); configJson = utils.readJsonAndReturnObject(configPath); } - configJson.generatorVersion = generatorVersion; fs.writeFileSync(configPath, JSON.stringify(configJson, null, 2)); resolve(); }); @@ -229,9 +231,10 @@ function _writeOracleJetConfigFile() { * ## _restoreHybrid * * @private + * @param {Object} [options] */ -function _restoreHybrid() { - return _npmInstall() +function _restoreHybrid(options) { + return _npmInstall(options) .then(_writeOracleJetConfigFile) .then(app.addComponents) .then(_invokeCordovaPrepare) @@ -299,7 +302,7 @@ function _runAfterAppRestoreHook() { * @private */ function _getHooksConfigObj() { - const configFilePath = path.resolve(CONSTANTS.PATH_TO_HOOKS_CONFIG); + const configFilePath = path.resolve(constants.PATH_TO_HOOKS_CONFIG); if (fs.existsSync(configFilePath)) { const hooksObj = utils.readJsonAndReturnObject(configFilePath); return hooksObj.hooks || {}; diff --git a/lib/scopes/platform.plugin.js b/lib/scopes/platform.plugin.js index 7dce20d..9ef6afa 100644 --- a/lib/scopes/platform.plugin.js +++ b/lib/scopes/platform.plugin.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -11,8 +11,8 @@ /** * ## Dependencies */ -const utils = require('../utils'); -const CONSTANTS = require('../utils.constants'); +const utils = require('../util/utils'); +const constants = require('../util/constants'); /** * # Platform @@ -48,7 +48,7 @@ module.exports = function (task, scope, param, options) { function _validatePlatform(scope, param) { if (scope === 'platform') { param.forEach((platform) => { - if (CONSTANTS.SUPPORTED_PLATFORMS.indexOf(platform) < 0) utils.log.error(`Platform ${platform} not supported!`); + if (constants.SUPPORTED_PLATFORMS.indexOf(platform) < 0) utils.log.error(`Platform ${platform} not supported!`); }); } } diff --git a/lib/tasks/add.js b/lib/tasks/add.js index 33aaf96..e2b97cd 100644 --- a/lib/tasks/add.js +++ b/lib/tasks/add.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -14,7 +14,7 @@ const app = require('../scopes/app'); const config = require('../../config'); const platformAndPlugin = require('../scopes/platform.plugin'); -const utils = require('../utils'); +const utils = require('../util/utils'); /** * # Switch for 'add' task @@ -44,7 +44,7 @@ module.exports = function (scope, parameters, options) { utils.log.error(utils.toNotSupportedMessage(`${task} ${scope} ${parameter}`)); return Promise.reject(); } - return app.addHybrid(parameters, options, utils); + return app.addHybrid(parameters, options); case scopes.platform.name: case scopes.plugin.name: { utils.ensureParameters(parameters); @@ -63,7 +63,7 @@ module.exports = function (scope, parameters, options) { utils.log.error(utils.toNotSupportedMessage(`${task} ${scope} ${parameter}`)); return Promise.reject(); } - return app.addSass(); + return app.addSass(options); case scopes.theming.name: utils.validateParametersCount(parameters, 0); utils.ensureJetApp(); @@ -71,7 +71,7 @@ module.exports = function (scope, parameters, options) { utils.log.error(utils.toNotSupportedMessage(`${task} ${scope} ${parameter}`)); return Promise.reject(); } - return app.addPcss(); + return app.addPcss(options); case scopes.typescript.name: utils.validateParametersCount(parameters, 0); utils.ensureJetApp(); @@ -79,7 +79,7 @@ module.exports = function (scope, parameters, options) { utils.log.error(utils.toNotSupportedMessage(`${task} ${scope} ${parameter}`)); return Promise.reject(); } - return app.addTypescript(); + return app.addTypescript(options); case scopes.pwa.name: utils.validateParametersCount(parameters, 0); utils.ensureJetApp(); @@ -95,7 +95,7 @@ module.exports = function (scope, parameters, options) { utils.log.error(utils.toNotSupportedMessage(`${task} ${scope} ${parameter}`)); return Promise.reject(); } - return app.addwebpack(); + return app.addwebpack(options); case scopes.web.name: utils.validateParametersCount(parameters, 0); utils.ensureJetHybridApp(); diff --git a/lib/tasks/build.serve.js b/lib/tasks/build.serve.js index 6e22961..478ad06 100644 --- a/lib/tasks/build.serve.js +++ b/lib/tasks/build.serve.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -11,8 +11,8 @@ */ const app = require('../scopes/app'); const config = require('../../config'); -const utils = require('../utils'); -const CONSTANTS = require('../utils.constants'); +const utils = require('../util/utils'); +const constants = require('../util/constants'); /** * # Switch for 'build' and 'serve' tasks @@ -40,7 +40,7 @@ module.exports = function (task, scope, parameters, options) { case undefined: return app.runTooling(task, scope, parameter, options); default: - if (CONSTANTS.SUPPORTED_PLATFORMS.indexOf(scope) > -1) { + if (constants.SUPPORTED_PLATFORMS.indexOf(scope) > -1) { // ojet (build|serve) (web|ios|android|windows) return app.runTooling(task, scope, parameter, options); } diff --git a/lib/tasks/clean.js b/lib/tasks/clean.js index dd41506..c9cf00c 100644 --- a/lib/tasks/clean.js +++ b/lib/tasks/clean.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -14,8 +14,8 @@ // Oracle const config = require('../../config'); -const CONSTANTS = require('../utils.constants'); -const utils = require('../utils'); +const constants = require('../util/constants'); +const utils = require('../util/utils'); /** * # Invoked platform clean @@ -33,7 +33,7 @@ module.exports = function (scope, parameters) { // Oracle command libs let tooling; try { - tooling = require(CONSTANTS.ORACLEJET_TOOLING_PACKAGE_JSON_NAME); // eslint-disable-line + tooling = require(constants.ORACLEJET_TOOLING_PACKAGE_JSON_NAME); // eslint-disable-line } catch (e) { utils.log.error('Your JET project does not have oraclejet-tooling installed.'); return Promise.reject(); @@ -43,7 +43,7 @@ module.exports = function (scope, parameters) { case config.tasks.clean.scopes.app.name: case undefined: default: - if (CONSTANTS.SUPPORTED_PLATFORMS.indexOf(platform) > -1) { + if (constants.SUPPORTED_PLATFORMS.indexOf(platform) > -1) { return tooling.clean.platform(platform); } utils.log.error(`Invalid platform ${platform}`); diff --git a/lib/tasks/configure.js b/lib/tasks/configure.js index f7f61e3..8048541 100644 --- a/lib/tasks/configure.js +++ b/lib/tasks/configure.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -18,8 +18,8 @@ const path = require('path'); // Oracle const config = require('../../config'); -const CONSTANTS = require('../utils.constants'); -const utils = require('../utils'); +const constants = require('../util/constants'); +const utils = require('../util/utils'); /** * # Switch for 'configure' task @@ -37,17 +37,17 @@ module.exports = function (task, scope, parameters, options) { if (options && utils.hasProperty(options, config.exchangeUrlParam)) { if (utils.hasGlobalOption(options)) { // Ensure storage dir - const storeDir = path.join(homedir, CONSTANTS.OJET_LOCAL_STORAGE_DIR); + const storeDir = path.join(homedir, constants.OJET_LOCAL_STORAGE_DIR); if (!fs.existsSync(storeDir)) { fs.mkdirSync(storeDir, { recursive: true }); } const data = {}; - data[CONSTANTS.EXCHANGE_GLOBAL_URL_KEY] = options[config.exchangeUrlParam]; + data[constants.EXCHANGE_GLOBAL_URL_KEY] = options[config.exchangeUrlParam]; // Write file const content = JSON.stringify(data, null, 2); - const pathToFile = path.join(storeDir, CONSTANTS.EXCHANGE_URL_FILE); + const pathToFile = path.join(storeDir, constants.EXCHANGE_URL_FILE); try { fs.writeFileSync(pathToFile, content); } catch (error) { diff --git a/lib/tasks/create.js b/lib/tasks/create.js index 28a6b6a..bd0c4da 100644 --- a/lib/tasks/create.js +++ b/lib/tasks/create.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -11,7 +11,7 @@ */ const app = require('../scopes/app'); const config = require('../../config'); -const utils = require('../utils'); +const utils = require('../util/utils'); /** * # Switch for 'create' task @@ -30,13 +30,13 @@ module.exports = function (scope, parameters, options) { if (!utils.ensureJetApp()) { return Promise.reject(); } - return app.createTheme(parameter, options, utils); + return app.createTheme(parameter, options); } case scopes.component.name: { if (!utils.ensureJetApp()) { return Promise.reject(); } - return app.createComponent(parameter, options, utils); + return app.createComponent(parameter, options); } case scopes.pack.name: { if (!utils.ensureJetApp()) { @@ -47,12 +47,12 @@ module.exports = function (scope, parameters, options) { } case scopes.app.name: // ojet create app TestApp: scope = app, parameters = [TestApp] - return app.create(parameter, options, utils); + return app.create(parameter, options); case undefined: // ojet create TestApp (API): scope = undefined, parameters = [TestApp] - return app.create(parameter, options, utils); + return app.create(parameter, options); default: // ojet create TestApp (CLI): scope = TestApp, parameters = [] - return app.create(scope, options, utils); + return app.create(scope, options); } }; diff --git a/lib/tasks/help.js b/lib/tasks/help.js index dec53e5..4a2eb22 100644 --- a/lib/tasks/help.js +++ b/lib/tasks/help.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -12,7 +12,7 @@ * ## Dependencies */ const config = require('../../config'); -const utils = require('../utils'); +const utils = require('../util/utils'); /** * # Help diff --git a/lib/tasks/index.js b/lib/tasks/index.js index cd09804..f10a95f 100644 --- a/lib/tasks/index.js +++ b/lib/tasks/index.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -10,7 +10,7 @@ const config = require('../../config'); const pckg = require('../../package.json'); -const utils = require('../utils'); +const utils = require('../util/utils'); const add = require('./add'); const buildAndServe = require('./build.serve'); const clean = require('./clean'); diff --git a/lib/tasks/list.js b/lib/tasks/list.js index c5aa431..c1ebacf 100644 --- a/lib/tasks/list.js +++ b/lib/tasks/list.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -13,7 +13,7 @@ */ const config = require('../../config'); const platformAndPlugin = require('../scopes/platform.plugin'); -const utils = require('../utils'); +const utils = require('../util/utils'); /** * # Switch for 'list' task diff --git a/lib/tasks/package.js b/lib/tasks/package.js index 201b043..567a9b5 100644 --- a/lib/tasks/package.js +++ b/lib/tasks/package.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -12,7 +12,7 @@ * ## Dependencies */ const config = require('../../config'); -const utils = require('../utils'); +const utils = require('../util/utils'); /** * # Package * diff --git a/lib/tasks/publish.js b/lib/tasks/publish.js index 2d9d436..6250d39 100644 --- a/lib/tasks/publish.js +++ b/lib/tasks/publish.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -12,7 +12,7 @@ * ## Dependencies */ const config = require('../../config'); -const utils = require('../utils'); +const utils = require('../util/utils'); /** * # Switch for 'publish' task diff --git a/lib/tasks/remove.js b/lib/tasks/remove.js index da376b9..d931a53 100644 --- a/lib/tasks/remove.js +++ b/lib/tasks/remove.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -13,7 +13,7 @@ */ const config = require('../../config'); const platformAndPlugin = require('../scopes/platform.plugin'); -const utils = require('../utils'); +const utils = require('../util/utils'); /** * # Switch for 'remove' task diff --git a/lib/tasks/restore.js b/lib/tasks/restore.js index 9a8d27e..c788a94 100644 --- a/lib/tasks/restore.js +++ b/lib/tasks/restore.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -12,7 +12,7 @@ // Oracle const app = require('../scopes/app'); const config = require('../../config'); -const utils = require('../utils'); +const utils = require('../util/utils'); /** * # Switch for 'restore' task diff --git a/lib/tasks/search.js b/lib/tasks/search.js index c8558af..efc4185 100644 --- a/lib/tasks/search.js +++ b/lib/tasks/search.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -13,7 +13,7 @@ */ // Oracle const config = require('../../config'); -const utils = require('../utils'); +const utils = require('../util/utils'); /** * # Switch for 'search' task diff --git a/lib/tasks/strip.js b/lib/tasks/strip.js index 7c90bc1..fa76bf1 100644 --- a/lib/tasks/strip.js +++ b/lib/tasks/strip.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -14,10 +14,10 @@ // Node const fs = require('fs'); const path = require('path'); -const CONSTANTS = require('../utils.constants'); +const constants = require('../util/constants'); // Oracle -const utils = require('../utils'); +const utils = require('../util/utils'); /** * # Invoke 'strip' task * @@ -29,14 +29,14 @@ module.exports = function (parameters) { return Promise.reject(); } utils.validateParametersCount(parameters, 0); - const toolingPath = path.join(process.cwd(), CONSTANTS.TOOLING_PATH); + const toolingPath = path.join(process.cwd(), constants.TOOLING_PATH); if (fs.existsSync(toolingPath)) { const tooling = require(toolingPath); // eslint-disable-line return tooling.strip(); } try { // Use global install if available - const tooling = require(CONSTANTS.ORACLEJET_TOOLING_PACKAGE_JSON_NAME); // eslint-disable-line + const tooling = require(constants.ORACLEJET_TOOLING_PACKAGE_JSON_NAME); // eslint-disable-line return tooling.strip(); } catch (e) { // Don't error diff --git a/lib/tooling/build.js b/lib/tooling/build.js index cafc96a..a78b675 100644 --- a/lib/tooling/build.js +++ b/lib/tooling/build.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -9,8 +9,8 @@ /* * Options and Arguments processing before Invoking tooling APIs */ -const utils = require('../utils'); -const CONSTANTS = require('../utils.constants'); +const utils = require('../util/utils'); +const constants = require('../util/constants'); module.exports = function (platform, options) { utils.validateOptions(options, 'build'); @@ -47,7 +47,11 @@ module.exports = function (platform, options) { // pass on no-optimize-flag // eslint-disable-next-line max-len - buildOptions[CONSTANTS.OMIT_COMPONENT_VERSION_FLAG] = options[CONSTANTS.OMIT_COMPONENT_VERSION_FLAG]; + buildOptions[constants.OMIT_COMPONENT_VERSION_FLAG] = options[constants.OMIT_COMPONENT_VERSION_FLAG]; + + // do not pass buildOptions.sass down because it will override + // defaultconfig.build.sass during the options merge process + delete buildOptions.sass; const tooling = utils.loadTooling(); return tooling.build(buildOptions.platform, buildOptions) diff --git a/lib/tooling/index.js b/lib/tooling/index.js index 4754a0b..a09dd3a 100644 --- a/lib/tooling/index.js +++ b/lib/tooling/index.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -8,7 +8,7 @@ const build = require('./build'); const serve = require('./serve'); -const utils = require('../utils'); +const utils = require('../util/utils'); /* * Options and Arguments processing before Invoking tooling APIs */ diff --git a/lib/tooling/serve.js b/lib/tooling/serve.js index af0f8ac..a309ad8 100644 --- a/lib/tooling/serve.js +++ b/lib/tooling/serve.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -10,8 +10,8 @@ * # Dependencies */ -const utils = require('../utils'); -const CONSTANTS = require('../utils.constants'); +const utils = require('../util/utils'); +const constants = require('../util/constants'); /** * # ojet serve command @@ -67,7 +67,7 @@ module.exports = (platform, options) => { // pass on no-optimize-flag // eslint-disable-next-line max-len - serveOptions[CONSTANTS.OMIT_COMPONENT_VERSION_FLAG] = options[CONSTANTS.OMIT_COMPONENT_VERSION_FLAG]; + serveOptions[constants.OMIT_COMPONENT_VERSION_FLAG] = options[constants.OMIT_COMPONENT_VERSION_FLAG]; const tooling = utils.loadTooling(); return tooling.serve(serveOptions.platform, serveOptions) diff --git a/util/constants.js b/lib/util/constants.js similarity index 50% rename from util/constants.js rename to lib/util/constants.js index 867f869..09b3e22 100644 --- a/util/constants.js +++ b/lib/util/constants.js @@ -1,35 +1,127 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ */ 'use strict'; -// constants to be used for the generator +/** + * # Constants + * + */ +const OMIT_COMPONENT_VERSION_FLAG = 'omit-component-version'; + +const SHARED_BUILD_AND_SERVE_OPTIONS = [ + 'release', + 'sass', + 'nosass', + 'pcss', + 'device', + 'emulator', + 'destination', + 'build-config', + 'platform-options', + 'optimize', + 'theme', + 'themes', + 'svg', + 'user-options', + 'notscompile', + 'dbg', + OMIT_COMPONENT_VERSION_FLAG +]; module.exports = { - SUPPORTED_PLATFORMS: ['android', 'ios', 'windows', 'web'], - SUPPORTED_HYBRID_PLATFORMS: ['android', 'ios', 'windows'], + APP_CONFIG_JSON: 'oraclejetconfig.json', + + APP_TYPE: { + HYBRID: 'hybrid', + WEB: 'web' + }, + + APP_PROTECTED_OBJECTS: [ + '.gitignore', + 'hybrid/', // Disable overwriting with an empty directory + 'hybrid/config.xml', + 'oraclejetconfig.json', + 'package.json' + ], + CORDOVA_CONFIG_XML: 'config.xml', + + SYSTEM_OPTIONS: [ + 'verbose', + 'installer' + ], + + BUILD_OPTIONS: [ + 'component', + ...SHARED_BUILD_AND_SERVE_OPTIONS + ], + + SERVE_OPTIONS: [ + 'browser', + 'build', + 'livereload', + 'livereload-port', + 'server-only', + 'server-port', + ...SHARED_BUILD_AND_SERVE_OPTIONS + ], + + CONFIG_SCRIPT_PATH: 'scripts/config', + + BUILD_SCRIPT: 'oraclejet-build.js', + + SERVE_SCRIPT: 'oraclejet-serve.js', + + SUPPORTED_PLATFORMS: ['web', 'ios', 'android', 'windows'], + + PATH_TO_HOOKS_CONFIG: 'scripts/hooks/hooks.json', + + APP_STAGED_THEMES_DIRECTORY: 'staged-themes', + + TOOLING_PATH: 'node_modules/@oracle/oraclejet-tooling', + + OJET_LOCAL_STORAGE_DIR: '.ojet', + + EXCHANGE_URL_FILE: 'exchange-url.json', + + EXCHANGE_GLOBAL_URL_KEY: 'global', + + BLANK_TEMPLATE: 'blank', + + NPM_TEMPLATES: ['blank', 'blank-ts', 'basic', 'basic-ts', 'basic-vdom', 'navbar', 'navbar-ts', 'navdrawer', 'navdrawer-ts'], + + ORACLEJET_PACKAGE_JSON_NAME: '@oracle/oraclejet', + + ORACLEJET_TOOLING_PACKAGE_JSON_NAME: '@oracle/oraclejet-tooling', + + OMIT_COMPONENT_VERSION_FLAG, + + APPLICATION_ARCHITECTURE: 'architecture', + + VDOM_ARCHITECTURE: 'vdom', + + MVVM_ARCHITECTURE: 'mvvm', + + SUPPORTED_HYBRID_PLATFORMS: ['android', 'ios', 'windows'], + DEFAULT_INSTALLER: 'npm', DEFAULT_THEME: 'alta', DEFAULT_PCSS_THEME: 'web', DEFAULT_PCSS_NAME: 'redwood', PCSS_STABLE_FLAG: 'stable', PCSS_THEME_FLAG: 'basetheme', - APP_CONFIG_JSON: 'oraclejetconfig.json', COMPONENT_JSON: 'component.json', JET_COMPOSITES: 'jet-composites', JET_COMPONENTS: 'jet_components', COMPONENT_FILES: ['component.json', 'loader.js', 'styles.css'], - PATH_TO_HOOKS_CONFIG: 'scripts/hooks/hooks.json', TSCONFIG_JSON: 'tsconfig.json', VCOMPONENT: 'vcomponent', - APP_TYPE: - { - HYBRID: 'hybrid', - WEB: 'web' - }, + RESOURCE_COMPONENT: 'resource', + RESOURCE_COMPONENT_INDEX_FILE_CONTENT: '//Write your code here. In case you do not need this file, please remove it from the publicModules property list in your component.json file.\n', + USE_GLOBAL_TOOLING: 'use-global-tooling', SUPPORTED_FLAGS: (namespace) => { const systemFlags = [ @@ -67,11 +159,12 @@ module.exports = { 'pwa', 'webpack', 'vdom', - 'use-global-tooling' + 'use-global-tooling', + 'installer' ]; const restoreFlags = [ - 'invokedByRestore', + 'invokedByRestore' ]; const addComponentFlags = [ diff --git a/util/fetchZip.js b/lib/util/fetchZip.js similarity index 94% rename from util/fetchZip.js rename to lib/util/fetchZip.js index 03d9883..d4b7ea5 100644 --- a/util/fetchZip.js +++ b/lib/util/fetchZip.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/lib/utils.injectors.js b/lib/util/injectors.js similarity index 92% rename from lib/utils.injectors.js rename to lib/util/injectors.js index b88e6e2..0af507c 100644 --- a/lib/utils.injectors.js +++ b/lib/util/injectors.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/util/paths.js b/lib/util/paths.js similarity index 94% rename from util/paths.js rename to lib/util/paths.js index 1aaf505..fd68a69 100644 --- a/util/paths.js +++ b/lib/util/paths.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -8,8 +8,9 @@ const path = require('path'); const fs = require('fs-extra'); + const constants = require('./constants'); -const util = require('./index'); +const util = require('./utils'); const _cachedPathsMap = {}; const _defaultPaths = _getDefaultPaths(); @@ -59,7 +60,7 @@ function _getDefaultPaths() { Object.defineProperty(defaultPaths, 'sourceThemes', _getValueObj('themes')); Object.defineProperty(defaultPaths, 'stagingHybrid', _getValueObj('hybrid')); Object.defineProperty(defaultPaths, 'stagingWeb', _getValueObj('web')); - Object.defineProperty(defaultPaths, 'stagingThemes', _getValueObj('themes')); + Object.defineProperty(defaultPaths, 'stagingThemes', _getValueObj(constants.APP_STAGED_THEMES_DIRECTORY)); Object.defineProperty(defaultPaths, 'components', _getValueObj(constants.JET_COMPOSITES)); Object.defineProperty(defaultPaths, 'exchangeComponents', _getValueObj(constants.JET_COMPONENTS)); return defaultPaths; diff --git a/lib/utils.js b/lib/util/utils.js similarity index 89% rename from lib/utils.js rename to lib/util/utils.js index a5600c6..a5ae0cb 100644 --- a/lib/utils.js +++ b/lib/util/utils.js @@ -1,6 +1,6 @@ #! /usr/bin/env node /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -18,9 +18,8 @@ const path = require('path'); const StringDecoder = require('string_decoder').StringDecoder; // Oracle -const config = require('../config'); -const CONSTANTS = require('./utils.constants'); -const util = require('../util'); +const config = require('../../config'); +const constants = require('./constants'); /** * # Utils @@ -348,7 +347,7 @@ utils.hasProperty = function (object, propertyName) { utils.isCwdJetApp = function () { const cwd = process.cwd(); // Check if includes oraclejet-tooling - return fs.existsSync(path.join(cwd, CONSTANTS.APP_CONFIG_JSON)); + return fs.existsSync(path.join(cwd, constants.APP_CONFIG_JSON)); }; /** @@ -444,7 +443,8 @@ utils.log.warning = function (message) { * @param {string} message */ utils.log.error = function (message) { - utils.log(`Error: ${message}`); + const msgString = (message && message.stack) ? message.stack : message; + utils.log(`Error: ${msgString}`); if (!process.env.OJET) { process.exit(1); } @@ -624,7 +624,7 @@ function _addHelpMessage() { * @returns {Object} options */ utils.validateOptions = (options, jobType) => { - const validKeys = CONSTANTS.SYSTEM_OPTIONS.concat(jobType === 'build' ? CONSTANTS.BUILD_OPTIONS : CONSTANTS.SERVE_OPTIONS); + const validKeys = constants.SYSTEM_OPTIONS.concat(jobType === 'build' ? constants.BUILD_OPTIONS : constants.SERVE_OPTIONS); Object.keys(options).forEach((key) => { if (validKeys.indexOf(key) === -1) { utils.log.error(`Option ${key} not valid for ojet ${jobType} command`); @@ -652,10 +652,12 @@ utils.validatePlatform = (platform) => { let validPlatform; if (!platform) { validPlatform = utils.getDefaultPlatform(); - utils.log.warning(`Command is missing platform. Default to ${validPlatform}.`); + if (!utils.loadToolingUtil().buildWithWebpack()) { + utils.log.warning(`Command is missing platform. Default to ${validPlatform}.`); + } return validPlatform; } - if (CONSTANTS.SUPPORTED_PLATFORMS.indexOf(platform) > -1) { + if (constants.SUPPORTED_PLATFORMS.indexOf(platform) > -1) { return platform; } utils.log.error(`Invalid platform: ${platform}.`); @@ -674,7 +676,7 @@ utils.getDefaultPlatform = () => { const ojetConfig = utils.loadTooling().config; const pathConfig = ojetConfig.getConfiguredPaths(); const isHybrid = fs.existsSync( - path.resolve(pathConfig.staging.hybrid, CONSTANTS.CORDOVA_CONFIG_XML)); + path.resolve(pathConfig.staging.hybrid, constants.CORDOVA_CONFIG_XML)); const isAddHybrid = fs.existsSync(path.resolve(pathConfig.src.web)) || fs.existsSync(path.resolve(pathConfig.src.hybrid)); @@ -685,7 +687,7 @@ utils.getDefaultPlatform = () => { return platforms[0]; } // if multiple platforms are installed, log error - const supportedPlatforms = CONSTANTS.SUPPORTED_PLATFORMS.toString().replace(/,/g, '||'); + const supportedPlatforms = constants.SUPPORTED_PLATFORMS.toString().replace(/,/g, '||'); utils.log.error(`Command is missing platform. Please specify one of "<${supportedPlatforms}>"`); } return 'web'; @@ -723,14 +725,14 @@ utils.validatePlatformOptions = (platformOptions, platform) => { utils.getBuildCustomizedConfig = (options) => { let customConfig = {}; const optParam = options || {}; - const scriptPath = path.join(process.cwd(), CONSTANTS.CONFIG_SCRIPT_PATH, CONSTANTS.BUILD_SCRIPT); + const scriptPath = path.join(process.cwd(), constants.CONFIG_SCRIPT_PATH, constants.BUILD_SCRIPT); // const scriptPathBackUp = path.join(process.cwd(), - // CONSTANTS.CONFIG_SCRIPT_PATH_BACKUP, CONSTANTS.BUILD_SCRIPT); + // constants.CONFIG_SCRIPT_PATH_BACKUP, constants.BUILD_SCRIPT); if (fs.existsSync(scriptPath)) { customConfig = require(scriptPath)(); // eslint-disable-line // } else if (fs.existsSync(scriptPathBackUp)) { // customConfig = require(scriptPathBackUp)(); // eslint-disable-line - } else { + } else if (!utils.loadToolingUtil().buildWithWebpack()) { utils.log.warning(`No build configuration script found at ${scriptPath}.`); } return { ...customConfig, ...optParam }; @@ -738,14 +740,14 @@ utils.getBuildCustomizedConfig = (options) => { utils.getServeCustomizedConfig = () => { let customConfig = {}; - const scriptPath = path.join(process.cwd(), CONSTANTS.CONFIG_SCRIPT_PATH, CONSTANTS.SERVE_SCRIPT); + const scriptPath = path.join(process.cwd(), constants.CONFIG_SCRIPT_PATH, constants.SERVE_SCRIPT); // const scriptPathBackUp = path.join(process.cwd(), - // CONSTANTS.CONFIG_SCRIPT_PATH_BACKUP, CONSTANTS.SERVE_SCRIPT); + // constants.CONFIG_SCRIPT_PATH_BACKUP, constants.SERVE_SCRIPT); if (fs.existsSync(scriptPath)) { customConfig = require(scriptPath)(); // eslint-disable-line // } else if (fs.existsSync(scriptPathBackUp)) { // customConfig = require(scriptPathBackUp)(); // eslint-disable-line - } else { + } else if (!utils.loadToolingUtil().buildWithWebpack()) { utils.log.warning(`No serve configuration script found at ${scriptPath}.`); } return customConfig; @@ -771,7 +773,7 @@ utils.validCustomProperties = () => { }; utils.loadTooling = () => { - const toolingPath = path.join(process.cwd(), CONSTANTS.TOOLING_PATH); + const toolingPath = path.join(process.cwd(), constants.TOOLING_PATH); // Oracle command libs if (fs.existsSync(toolingPath)) { const tooling = require(toolingPath); // eslint-disable-line @@ -779,7 +781,7 @@ utils.loadTooling = () => { } try { // Use global install if available - const tooling = require(CONSTANTS.ORACLEJET_TOOLING_PACKAGE_JSON_NAME); // eslint-disable-line + const tooling = require(constants.ORACLEJET_TOOLING_PACKAGE_JSON_NAME); // eslint-disable-line return tooling; } catch (e) { utils.log.error('Your JET project does not have oraclejet-tooling installed.'); @@ -797,13 +799,13 @@ utils.loadTooling = () => { * @returns {object} tooling util object */ utils.loadToolingUtil = () => { - const toolingPath = path.join(process.cwd(), CONSTANTS.TOOLING_PATH); + const toolingPath = path.join(process.cwd(), constants.TOOLING_PATH); if (fs.existsSync(toolingPath)) { return require(path.join(toolingPath, 'lib', 'util')); // eslint-disable-line } try { // Use global install if available - const tooling = require(`${CONSTANTS.ORACLEJET_TOOLING_PACKAGE_JSON_NAME}/lib/util`); // eslint-disable-line + const tooling = require(`${constants.ORACLEJET_TOOLING_PACKAGE_JSON_NAME}/lib/util`); // eslint-disable-line return tooling; } catch (e) { utils.log.error('Your JET project does not have oraclejet-tooling installed.'); @@ -821,7 +823,7 @@ utils.loadToolingUtil = () => { * @returns {boolean} true if is Typescript application, * false otherwise */ -utils.isTypescriptApplication = () => fs.existsSync(path.join('.', CONSTANTS.TSCONFIG_JSON)); +utils.isTypescriptApplication = () => fs.existsSync(path.join('.', constants.TSCONFIG_JSON)); /** * Determine whether the provided template corresponds @@ -832,7 +834,7 @@ utils.isTypescriptApplication = () => fs.existsSync(path.join('.', CONSTANTS.TSC * to an NPM template * */ -utils.isNPMTemplate = template => CONSTANTS.NPM_TEMPLATES.indexOf(template) !== -1; +utils.isNPMTemplate = template => constants.NPM_TEMPLATES.indexOf(template) !== -1; /** * @@ -892,37 +894,54 @@ utils.isVDOMTemplate = ({ options }) => { }; /** - * Determine whether the current application is a VDOm - * application i.e is built using the VDOM architecture - * + * Determine if filePath exists + * @param {String} filePath * @returns {boolean} */ -utils.isVDOMApplication = () => { - const pathToOraclejetConfig = path.join('.', CONSTANTS.APP_CONFIG_JSON); - const oraclejetConfig = utils.readJsonAndReturnObject(pathToOraclejetConfig); - if (utils.hasProperty(oraclejetConfig, CONSTANTS.APPLICATION_ARCHITECTURE) - && oraclejetConfig[CONSTANTS.APPLICATION_ARCHITECTURE] === CONSTANTS.VDOM_ARCHITECTURE) { +utils.fsExistsSync = (filePath) => { + try { + fs.statSync(filePath); return true; + } catch (err) { + // file/directory does not exist + return false; } - return false; }; - /** * Determine the proper @oracle/oraclejet-tooling module location path (global or local) * @returns {string} path to @oracle/oraclejet, preferring local */ utils.getToolingPath = () => { - let source = path.resolve(`${CONSTANTS.TOOLING_PATH}`); + let source = path.resolve(`${constants.TOOLING_PATH}`); - if (util.fsExistsSync(source)) { + if (utils.fsExistsSync(source)) { return source; } - source = path.dirname(require.resolve(`${CONSTANTS.ORACLEJET_TOOLING_PACKAGE_JSON_NAME}/package.json`)); - if (util.fsExistsSync(source)) { + source = path.dirname(require.resolve(`${constants.ORACLEJET_TOOLING_PACKAGE_JSON_NAME}/package.json`)); + if (utils.fsExistsSync(source)) { return source; } // Not found anywhere return null; }; + +/** + * Return the proper installer command + * @param {Object} options + * @returns {Object} installer command & verb + */ +utils.getInstallerCommand = (options) => { + const useCI = utils.hasProperty(options, 'ci'); + if (useCI) { + return { installer: 'npm', verbs: { install: 'ci' } }; + } + let installerCmd = options.installer; + if (!installerCmd) { + const configPath = path.join(process.cwd(), constants.APP_CONFIG_JSON); + const configJson = utils.readJsonAndReturnObject(configPath); + installerCmd = configJson.installer || constants.DEFAULT_INSTALLER; + } + return installerCmd === 'yarn' ? { installer: 'yarn', verbs: { install: 'install' } } : { installer: 'npm', verbs: { install: 'install' } }; +}; diff --git a/lib/utils.constants.js b/lib/utils.constants.js deleted file mode 100644 index 849de78..0000000 --- a/lib/utils.constants.js +++ /dev/null @@ -1,111 +0,0 @@ -/** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. - Licensed under The Universal Permissive License (UPL), Version 1.0 - as shown at https://oss.oracle.com/licenses/upl/ - -*/ -'use strict'; - -/** - * # Constants - * - * @public - */ - -const OMIT_COMPONENT_VERSION_FLAG = 'omit-component-version'; - -const SHARED_BUILD_AND_SERVE_OPTIONS = [ - 'release', - 'sass', - 'nosass', - 'pcss', - 'device', - 'emulator', - 'destination', - 'build-config', - 'platform-options', - 'optimize', - 'theme', - 'themes', - 'svg', - 'user-options', - 'notscompile', - 'dbg', - OMIT_COMPONENT_VERSION_FLAG -]; - -module.exports = { - APP_CONFIG_JSON: 'oraclejetconfig.json', - - APP_TYPE: { - HYBRID: 'hybrid', - WEB: 'web' - }, - - APP_PROTECTED_OBJECTS: [ - '.gitignore', - 'hybrid/', // Disable overwriting with an empty directory - 'hybrid/config.xml', - 'oraclejetconfig.json', - 'package.json' - ], - - CORDOVA_CONFIG_XML: 'config.xml', - - SYSTEM_OPTIONS: [ - 'verbose' - ], - - BUILD_OPTIONS: [ - 'component', - ...SHARED_BUILD_AND_SERVE_OPTIONS - ], - - SERVE_OPTIONS: [ - 'browser', - 'build', - 'livereload', - 'livereload-port', - 'server-only', - 'server-port', - ...SHARED_BUILD_AND_SERVE_OPTIONS - ], - - CONFIG_SCRIPT_PATH: 'scripts/config', - - BUILD_SCRIPT: 'oraclejet-build.js', - - SERVE_SCRIPT: 'oraclejet-serve.js', - - SUPPORTED_PLATFORMS: ['web', 'ios', 'android', 'windows'], - - PATH_TO_HOOKS_CONFIG: 'scripts/hooks/hooks.json', - - TSCONFIG_JSON: 'tsconfig.json', - - APP_STAGED_THEMES_DIRECTORY: 'staged-themes', - - TOOLING_PATH: 'node_modules/@oracle/oraclejet-tooling', - - OJET_LOCAL_STORAGE_DIR: '.ojet', - - EXCHANGE_URL_FILE: 'exchange-url.json', - - EXCHANGE_GLOBAL_URL_KEY: 'global', - - BLANK_TEMPLATE: 'blank', - - NPM_TEMPLATES: ['blank', 'blank-ts', 'basic', 'basic-ts', 'basic-vdom', 'navbar', 'navbar-ts', 'navdrawer', 'navdrawer-ts'], - - ORACLEJET_PACKAGE_JSON_NAME: '@oracle/oraclejet', - - ORACLEJET_TOOLING_PACKAGE_JSON_NAME: '@oracle/oraclejet-tooling', - - OMIT_COMPONENT_VERSION_FLAG, - - APPLICATION_ARCHITECTURE: 'architecture', - - VDOM_ARCHITECTURE: 'vdom', - - MVVM_ARCHITECTURE: 'mvvm' -}; diff --git a/lib/utils.paths.js b/lib/utils.paths.js deleted file mode 100644 index 2d04fa7..0000000 --- a/lib/utils.paths.js +++ /dev/null @@ -1,126 +0,0 @@ -#! /usr/bin/env node -/** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. - Licensed under The Universal Permissive License (UPL), Version 1.0 - as shown at https://oss.oracle.com/licenses/upl/ - -*/ - -'use strict'; - -/** - * ## Dependencies - */ -// Node -const fs = require('fs'); -const path = require('path'); - -// Oracle -const CONSTANTS = require('./utils.constants'); -const utils = require('./utils'); - -/** - * # Paths - * - * @public - */ - -const paths = module.exports; - -/** - * ## getConfiguredPaths - * - * @public - * @param {string} appDir - * @returns {Promise} - */ -paths.getConfiguredPaths = function (appDir) { - const cachedPathsMap = {}; - let resultPaths = cachedPathsMap[appDir]; - if (!resultPaths) { - resultPaths = _deriveConfiguredPaths(appDir); - cachedPathsMap[appDir] = resultPaths; - } - return resultPaths; -}; - -/** - * ## getDefaultPaths - * - * @public - * @returns {Object} defaultPaths - */ -paths.getDefaultPaths = function () { - const defaultPaths = {}; - Object.defineProperty(defaultPaths, 'source', _getValueObj('src')); - Object.defineProperty(defaultPaths, 'sourceWeb', _getValueObj('src-web')); - Object.defineProperty(defaultPaths, 'sourceHybrid', _getValueObj('src-hybrid')); - Object.defineProperty(defaultPaths, 'sourceJavascript', _getValueObj('js')); - Object.defineProperty(defaultPaths, 'sourceThemes', _getValueObj('themes')); - Object.defineProperty(defaultPaths, 'stagingHybrid', _getValueObj('hybrid')); - Object.defineProperty(defaultPaths, 'stagingWeb', _getValueObj('web')); - Object.defineProperty(defaultPaths, 'stagingThemes', _getValueObj(CONSTANTS.APP_STAGED_THEMES_DIRECTORY)); - return defaultPaths; -}; - -/** - * ## _deriveConfiguredPaths - * - * @private - * @param {string} appDir - * @returns {Object} configurePaths - */ -function _deriveConfiguredPaths(appDir) { - const defaultPaths = paths.getDefaultPaths(); - const configurePaths = {}; - const conf = _getPathsFromOraclejetConfig(appDir); - Object.defineProperty(configurePaths, 'source', _getValueObj(conf.source.common, defaultPaths.source)); - Object.defineProperty(configurePaths, 'sourceWeb', _getValueObj(conf.source.web, defaultPaths.sourceWeb)); - Object.defineProperty(configurePaths, 'sourceHybrid', _getValueObj(conf.source.hybrid, defaultPaths.sourceHybrid)); - Object.defineProperty(configurePaths, 'sourceJavascript', _getValueObj(conf.source.javascript, defaultPaths.sourceJavascript)); - Object.defineProperty(configurePaths, 'sourceThemes', _getValueObj(conf.source.themes, defaultPaths.sourceThemes)); - Object.defineProperty(configurePaths, 'stagingHybrid', _getValueObj(conf.staging.hybrid, defaultPaths.stagingHybrid)); - Object.defineProperty(configurePaths, 'stagingWeb', _getValueObj(conf.staging.web, defaultPaths.stagingWeb)); - Object.defineProperty(configurePaths, 'stagingThemes', _getValueObj(conf.staging.themes, defaultPaths.stagingThemes)); - return configurePaths; -} - -/** - * ## _getValueObj - * - * @private - * @param {string} value - * @param {string} defaultValue - * @returns {Object} - */ -function _getValueObj(value, defaultValue) { - return { - value: _normPath(value) || defaultValue, - enumerable: true - }; -} - -/** - * ## _normPath - * - * @private - * @param {string} rawValue - * @returns {string || null} - */ -function _normPath(rawValue) { - return (rawValue) ? path.normalize(rawValue) : null; -} - -/** - * ## _getPathsFromOraclejetConfig - * - * @private - * @param {string} appDir - * @returns {Object} - */ -function _getPathsFromOraclejetConfig(appDir) { - const configJsonPath = path.resolve(appDir, CONSTANTS.APP_CONFIG_JSON); - const configJson = fs.existsSync(configJsonPath) ? - utils.readJsonAndReturnObject(configJsonPath) : {}; - return configJson.paths; -} diff --git a/ojet.js b/ojet.js index 7e11eb0..e1f9b04 100644 --- a/ojet.js +++ b/ojet.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/package.json b/package.json index cb7c4b8..c3453af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@oracle/ojet-cli", - "version": "11.1.0", + "version": "12.0.0", "description": "Oracle JET Command Line Interface", "license": "UPL-1.0", "homepage": "http://www.oracle.com/jet", @@ -10,11 +10,11 @@ "main": "ojet.js", "dependencies": { "adm-zip": "~0.4.7", - "fs-extra": "^8.1.0", + "fs-extra": "~8.1.0", "inquirer": "~6.2.2", - "minimist": "^1.2.0", + "minimist": "~1.2.0", "xmldom": "0.5.0", - "@oracle/oraclejet-tooling": "~11.1.0" + "@oracle/oraclejet-tooling": "~12.0.0" }, "engines": { "node": ">=12.21.0" diff --git a/template/common/_gitignore b/template/common/_gitignore index 21faa2a..84ea2b7 100644 --- a/template/common/_gitignore +++ b/template/common/_gitignore @@ -1,4 +1,5 @@ /jet_components +/exchange_components /node_modules /bower_components /dist diff --git a/template/common/scripts/config/oraclejet-build.js b/template/common/scripts/config/oraclejet-build.js index 51222ad..15d6946 100644 --- a/template/common/scripts/config/oraclejet-build.js +++ b/template/common/scripts/config/oraclejet-build.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/config/oraclejet-serve.js b/template/common/scripts/config/oraclejet-serve.js index 377eaa9..d3a81b8 100644 --- a/template/common/scripts/config/oraclejet-serve.js +++ b/template/common/scripts/config/oraclejet-serve.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/after_app_create.js b/template/common/scripts/hooks/after_app_create.js index 5c2ec33..18b9e27 100644 --- a/template/common/scripts/hooks/after_app_create.js +++ b/template/common/scripts/hooks/after_app_create.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/after_app_restore.js b/template/common/scripts/hooks/after_app_restore.js index 45f43a3..2f00201 100644 --- a/template/common/scripts/hooks/after_app_restore.js +++ b/template/common/scripts/hooks/after_app_restore.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/after_app_typescript.js b/template/common/scripts/hooks/after_app_typescript.js index 88ddf8f..dd912e9 100644 --- a/template/common/scripts/hooks/after_app_typescript.js +++ b/template/common/scripts/hooks/after_app_typescript.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/after_build.js b/template/common/scripts/hooks/after_build.js index 5b88d55..0d86b24 100644 --- a/template/common/scripts/hooks/after_build.js +++ b/template/common/scripts/hooks/after_build.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/after_component_build.js b/template/common/scripts/hooks/after_component_build.js index 2acb2b6..a458d9a 100644 --- a/template/common/scripts/hooks/after_component_build.js +++ b/template/common/scripts/hooks/after_component_build.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/after_component_create.js b/template/common/scripts/hooks/after_component_create.js index 9f8226c..0310937 100644 --- a/template/common/scripts/hooks/after_component_create.js +++ b/template/common/scripts/hooks/after_component_create.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/after_component_package.js b/template/common/scripts/hooks/after_component_package.js new file mode 100644 index 0000000..06c8c01 --- /dev/null +++ b/template/common/scripts/hooks/after_component_package.js @@ -0,0 +1,13 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +module.exports = function (configObj) { + return new Promise((resolve) => { + console.log('Running after_component_package hook.'); + // const componentName = configObj.component. + resolve(configObj); + }); + }; \ No newline at end of file diff --git a/template/common/scripts/hooks/after_component_typescript.js b/template/common/scripts/hooks/after_component_typescript.js index aa48aa3..71e704c 100644 --- a/template/common/scripts/hooks/after_component_typescript.js +++ b/template/common/scripts/hooks/after_component_typescript.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/after_serve.js b/template/common/scripts/hooks/after_serve.js index 8c56a0c..d5467e5 100644 --- a/template/common/scripts/hooks/after_serve.js +++ b/template/common/scripts/hooks/after_serve.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/after_watch.js b/template/common/scripts/hooks/after_watch.js index 656abd4..96d01b0 100644 --- a/template/common/scripts/hooks/after_watch.js +++ b/template/common/scripts/hooks/after_watch.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/before_app_typescript.js b/template/common/scripts/hooks/before_app_typescript.js index 90b8aa4..b472997 100644 --- a/template/common/scripts/hooks/before_app_typescript.js +++ b/template/common/scripts/hooks/before_app_typescript.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/before_build.js b/template/common/scripts/hooks/before_build.js index 087273e..e3d566d 100644 --- a/template/common/scripts/hooks/before_build.js +++ b/template/common/scripts/hooks/before_build.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/before_component_optimize.js b/template/common/scripts/hooks/before_component_optimize.js index c4975a3..73ed378 100644 --- a/template/common/scripts/hooks/before_component_optimize.js +++ b/template/common/scripts/hooks/before_component_optimize.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/before_component_package.js b/template/common/scripts/hooks/before_component_package.js new file mode 100644 index 0000000..ee8802d --- /dev/null +++ b/template/common/scripts/hooks/before_component_package.js @@ -0,0 +1,13 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +module.exports = function (configObj) { + return new Promise((resolve) => { + console.log('Running before_component_package hook.'); + // const componentName = configObj.component. + resolve(configObj); + }); + }; \ No newline at end of file diff --git a/template/common/scripts/hooks/before_component_typescript.js b/template/common/scripts/hooks/before_component_typescript.js index 280e887..8b8bd58 100644 --- a/template/common/scripts/hooks/before_component_typescript.js +++ b/template/common/scripts/hooks/before_component_typescript.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/before_hybrid_build.js b/template/common/scripts/hooks/before_hybrid_build.js index 7128ae0..3e0c086 100644 --- a/template/common/scripts/hooks/before_hybrid_build.js +++ b/template/common/scripts/hooks/before_hybrid_build.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/before_optimize.js b/template/common/scripts/hooks/before_optimize.js index e2cbb55..8194e15 100644 --- a/template/common/scripts/hooks/before_optimize.js +++ b/template/common/scripts/hooks/before_optimize.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/before_release_build.js b/template/common/scripts/hooks/before_release_build.js index 577b3c8..8392b7a 100644 --- a/template/common/scripts/hooks/before_release_build.js +++ b/template/common/scripts/hooks/before_release_build.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/before_serve.js b/template/common/scripts/hooks/before_serve.js index 6dfbe0b..7db6c27 100644 --- a/template/common/scripts/hooks/before_serve.js +++ b/template/common/scripts/hooks/before_serve.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/before_watch.js b/template/common/scripts/hooks/before_watch.js index abf8f4b..1df2eb0 100644 --- a/template/common/scripts/hooks/before_watch.js +++ b/template/common/scripts/hooks/before_watch.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/before_webpack.js b/template/common/scripts/hooks/before_webpack.js index a1ff3f7..6617133 100644 --- a/template/common/scripts/hooks/before_webpack.js +++ b/template/common/scripts/hooks/before_webpack.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ diff --git a/template/common/scripts/hooks/hooks.json b/template/common/scripts/hooks/hooks.json index 410da8e..5ff8af1 100644 --- a/template/common/scripts/hooks/hooks.json +++ b/template/common/scripts/hooks/hooks.json @@ -4,9 +4,11 @@ "after_app_create": "scripts/hooks/after_app_create.js", "after_app_restore": "scripts/hooks/after_app_restore.js", "after_component_create": "scripts/hooks/after_component_create.js", + "after_component_package": "scripts/hooks/after_component_package.js", "before_build": "scripts/hooks/before_build.js", "before_optimize": "scripts/hooks/before_optimize.js", "before_component_optimize": "scripts/hooks/before_component_optimize.js", + "before_component_package": "scripts/hooks/before_component_package.js", "before_release": "scripts/hooks/before_release.js", "before_watch": "scripts/hooks/before_watch.js", "after_build": "scripts/hooks/after_build.js", diff --git a/template/component/css/@component@-styles.css b/template/component/css/@component@-styles.css index f2095df..701d09b 100644 --- a/template/component/css/@component@-styles.css +++ b/template/component/css/@component@-styles.css @@ -14,4 +14,9 @@ @full-component-name@{ min-height: 50px; width: 50px; +} + +@full-component-name@[hidden] +{ + display: none; } \ No newline at end of file diff --git a/template/component/js/@component@-view.html b/template/component/js/@component@-view.html index 7cdeb2d..5d7aef2 100644 --- a/template/component/js/@component@-view.html +++ b/template/component/js/@component@-view.html @@ -1,5 +1,5 @@ ', + // endTag: '' + // } + +/** + * # injectPaths + * Configuration for path injection during build in release mode + * This task reads the release paths from the mainReleasePaths json file and injects the path configuration in main.js when run in release mode. + */ + // injectPaths: paths => ({ + // startTag: '// injector:mainReleasePaths', + // endTag: '// endinjector', + // mainJs: 'path to mainjs', + // destMainJs: 'path to the inject destination', + // }), + +/** + * # uglify + * This task minifies source files and libraries that don't have minified distributions. + * It runs only when build in release mode. Support input of fileList that contains an array of file objects. + * See the example in copyCustomLibsToStaging for configuring the fileList. + * See detailed uglify options at https://github.com/mishoo/UglifyJS + */ + // uglify: { + // fileList: [{}], + // options: {} + // }, + +/** + * # requireJs + * This task runs requirejs optimizer to bundle all scripts in to a large minified main.js for release. + * It runs only when build in release mode. + * The task mirrors the configuration in this link https://github.com/gruntjs/grunt-contrib-requirejs + */ + // requireJs: { + // baseUrl: 'path to the js directory in staging area', + // name: 'the main.js file name', + // mainConfigFile: `the main configuration file`, + // optimize: 'option for optimize', + // out: 'output file path' + // }, + +/** + * # sass + * This task runs sass compile for scss files. + * It takes a fileList as input, see copyCustomLibsToStaging section for examples of fileList + * See detailed node sass options available here https://github.com/sass/node-sass + */ + // sass: { + // fileList: [], + // options: {} + // }, + +/** + * This is the web specific configuration. You can specify configurations targeted only for web apps. + * The web specific configurations will override the general configuration. + */ + web: { + // copyCustomLibsToStaging: { + // fileList: [ + // { + // cwd:'node_modules/oraclejet/', + // src: ['*'], + // dest: 'web/js/libs/oraclejet' + // } + // ] + // } + }, + +/** + * This is the hybrid specific configuration. You can specify configurations targeted only hybrid apps. + * The hybrid specific configurations will override the general configuration. + */ + hybrid: { + // copyCustomLibsToStaging: { + // fileList: [ + // { + // cwd:'node_modules/oraclejet/', + // src: ['*'], + // dest: 'hybrid/www/js/libs/oraclejet' + // } + // ] + // } + } + }; +}; diff --git a/test/templates/webpackLegacyTest/scripts/config/oraclejet-serve.js b/test/templates/webpackLegacyTest/scripts/config/oraclejet-serve.js new file mode 100644 index 0000000..8384b53 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/config/oraclejet-serve.js @@ -0,0 +1,88 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +'use strict'; +/** + * # oraclejet-serve.js + * This script allows users to configure and customize the serve tasks. + * Configurable tasks: connect, watch. + * To configure a task, uncomment the corresponding sections below, and pass in your configurations. + * Any options will be merged with default configuration found in node_modules/@oracle/oraclejet-tooling/lib/defaultconfig.js + * Any fileList will replace the default configuration. + */ + +module.exports = function () { + return { +/** + * # watch + * This task watches a set of files and defines a series of customizable tasks if a change is detected. + * Within the watch task config, by default there are three targets, sourceFiles, sass, themes. + * Users are encouraged to edit or add their own watch targets, be careful if rewrite the three default targets. + * Within each watch target, users can specify three properties. + * 1. The files entry takes a list of glob patterns that identifies the set of files to watch + * 2. The options.livereload specifies a boolean that indicates whether the browser should reload when files in this target are modified. + * 3. The options.tasks property specifies custom commands to run. 'compileSass' and 'copyThemes' are reserved internal tasks. + * Example commands: ['grunt copy', 'mocha test]. Once a change is detected, it will run grunt copy followed by mocha test + * once the custom tasks completed, tooling will reload the browser if liverealod is set to true, then resume watching + */ + // // Sub task watch default options + // watch: { + // sourceFiles: + // { + // files: [], + // options: { + // livereload: true + // } + // }, + + // sass: { + // files: [], + // commands: ['compileSass'] + // }, + + // themes: { + // files: [], + // options: { + // livereload: true + // }, + // commands: ['copyThemes'] + // }, + // } + +/** + * This is the web specific configuration. You can specify configurations targeted only for web apps. + * The web specific configurations will override the general configuration. + */ + web: { +/** + * # connect + * This task launches a web server for web App, does not work for hybrid App. + * Support five connect options: + * port, port number, default 8000 + * hostname, a string of the domain name, default localhost + * livereload, a boolean for livereload, default true in dev mode, false in release mode (overwritten when ) + * open, a boolean for wheather to launch browser, default to true + * base, a string of the target directory to be served, default to the staging area + */ + // connect: { + // options: {} + // }, + }, + +/** + * This is the hybrid specific configuration. You can specify configurations targeted only for hybrid apps. + * The hybrid specific configurations will override the general configuration. + */ + hybrid: { + } + }; +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/after_app_create.js b/test/templates/webpackLegacyTest/scripts/hooks/after_app_create.js new file mode 100644 index 0000000..3c20183 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/after_app_create.js @@ -0,0 +1,20 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +'use strict'; + +module.exports = function () { + return new Promise((resolve) => { + console.log('Running after_app_create hook.'); + resolve(); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/after_app_restore.js b/test/templates/webpackLegacyTest/scripts/hooks/after_app_restore.js new file mode 100644 index 0000000..7884dd3 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/after_app_restore.js @@ -0,0 +1,20 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +'use strict'; + +module.exports = function () { + return new Promise((resolve) => { + console.log('Running after_app_restore hook.'); + resolve(); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/after_app_typescript.js b/test/templates/webpackLegacyTest/scripts/hooks/after_app_typescript.js new file mode 100644 index 0000000..cb8090f --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/after_app_typescript.js @@ -0,0 +1,20 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve) => { + console.log("Running after_app_typescript hook."); + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/after_build.js b/test/templates/webpackLegacyTest/scripts/hooks/after_build.js new file mode 100644 index 0000000..9093060 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/after_build.js @@ -0,0 +1,21 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ + +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve, reject) => { + console.log("Running after_build hook."); + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/after_component_build.js b/test/templates/webpackLegacyTest/scripts/hooks/after_component_build.js new file mode 100644 index 0000000..e6b4498 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/after_component_build.js @@ -0,0 +1,21 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ + +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve, reject) => { + console.log("Running after_component_build hook."); + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/after_component_create.js b/test/templates/webpackLegacyTest/scripts/hooks/after_component_create.js new file mode 100644 index 0000000..65b16b6 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/after_component_create.js @@ -0,0 +1,21 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve) => { + console.log('Running after_component_create hook.'); + // const componentPath = configObj.componentPath; + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/after_component_typescript.js b/test/templates/webpackLegacyTest/scripts/hooks/after_component_typescript.js new file mode 100644 index 0000000..6ad7cde --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/after_component_typescript.js @@ -0,0 +1,20 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve) => { + console.log("Running after_component_typescript hook."); + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/after_serve.js b/test/templates/webpackLegacyTest/scripts/hooks/after_serve.js new file mode 100644 index 0000000..bccb384 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/after_serve.js @@ -0,0 +1,21 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ + +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve, reject) => { + console.log("Running after_serve hook."); + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/after_watch.js b/test/templates/webpackLegacyTest/scripts/hooks/after_watch.js new file mode 100644 index 0000000..93638be --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/after_watch.js @@ -0,0 +1,21 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ + +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve, reject) => { + console.log("Running after_watch hook."); + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/before_app_typescript.js b/test/templates/webpackLegacyTest/scripts/hooks/before_app_typescript.js new file mode 100644 index 0000000..df007b6 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/before_app_typescript.js @@ -0,0 +1,21 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve) => { + console.log("Running before_app_typescript hook."); + //const { tsconfigJson } = configObj.typescript; + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/before_build.js b/test/templates/webpackLegacyTest/scripts/hooks/before_build.js new file mode 100644 index 0000000..5e6a7c0 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/before_build.js @@ -0,0 +1,21 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ + +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve, reject) => { + console.log("Running before_build hook."); + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/before_component_optimize.js b/test/templates/webpackLegacyTest/scripts/hooks/before_component_optimize.js new file mode 100644 index 0000000..d837020 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/before_component_optimize.js @@ -0,0 +1,21 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ + +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve, reject) => { + console.log("Running before_component_optimize hook."); + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/before_component_typescript.js b/test/templates/webpackLegacyTest/scripts/hooks/before_component_typescript.js new file mode 100644 index 0000000..11f037b --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/before_component_typescript.js @@ -0,0 +1,21 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve) => { + console.log("Running before_component_typescript hook."); + //const { tsconfigJson } = configObj.typescript; + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/before_hybrid_build.js b/test/templates/webpackLegacyTest/scripts/hooks/before_hybrid_build.js new file mode 100644 index 0000000..d5ebe55 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/before_hybrid_build.js @@ -0,0 +1,21 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ + +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve, reject) => { + console.log("Running before_hybrid_build hook."); + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/before_optimize.js b/test/templates/webpackLegacyTest/scripts/hooks/before_optimize.js new file mode 100644 index 0000000..4ca8b17 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/before_optimize.js @@ -0,0 +1,21 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ + +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve, reject) => { + console.log("Running before_optimize hook."); + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/before_release_build.js b/test/templates/webpackLegacyTest/scripts/hooks/before_release_build.js new file mode 100644 index 0000000..cedb774 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/before_release_build.js @@ -0,0 +1,21 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ + +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve, reject) => { + console.log("Running before_release_build hook."); + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/before_serve.js b/test/templates/webpackLegacyTest/scripts/hooks/before_serve.js new file mode 100644 index 0000000..1428920 --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/before_serve.js @@ -0,0 +1,43 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ + +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve, reject) => { + console.log('Running before_serve hook.'); + // ojet custom connect and serve options + // { connectOpts, serveOpts } = configObj; + // const express = require('express'); + // const http = require('http'); + // pass back custom http + // configObj['http'] = http; + // pass back custom express app + // configObj['express'] = express(); + // pass back custom options for http.createServer + // const serverOptions = {...}; + // configObj['serverOptions'] = serverOptions; + // pass back custom server + // configObj['server'] = http.createServer(serverOptions, express()); + // const tinylr = require('tiny-lr'); + // pass back custom live reload server + // configObj['liveReloadServer'] = tinylr({ port: PORT }); + // pass back a replacement set of middleware + // configObj['middleware'] = [...]; + // pass back a set of middleware that goes before the default middleware + // configObj['preMiddleware'] = [...]; + // pass back a set of middleware that goes after the default middleware + // configObj['postMiddleware'] = [...]; + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/before_watch.js b/test/templates/webpackLegacyTest/scripts/hooks/before_watch.js new file mode 100644 index 0000000..826e53e --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/before_watch.js @@ -0,0 +1,21 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ + +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve, reject) => { + console.log("Running before_watch hook."); + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/before_webpack.js b/test/templates/webpackLegacyTest/scripts/hooks/before_webpack.js new file mode 100644 index 0000000..61cc4ab --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/before_webpack.js @@ -0,0 +1,22 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ + +'use strict'; + +module.exports = function (configObj) { + return new Promise((resolve, reject) => { + console.log("Running before_webpack hook."); + // const { config } = configObj.webpack; + resolve(configObj); + }); +}; diff --git a/test/templates/webpackLegacyTest/scripts/hooks/hooks.json b/test/templates/webpackLegacyTest/scripts/hooks/hooks.json new file mode 100644 index 0000000..410da8e --- /dev/null +++ b/test/templates/webpackLegacyTest/scripts/hooks/hooks.json @@ -0,0 +1,25 @@ +{ + "description": "OJET-CLI hooks configuration file", + "hooks": { + "after_app_create": "scripts/hooks/after_app_create.js", + "after_app_restore": "scripts/hooks/after_app_restore.js", + "after_component_create": "scripts/hooks/after_component_create.js", + "before_build": "scripts/hooks/before_build.js", + "before_optimize": "scripts/hooks/before_optimize.js", + "before_component_optimize": "scripts/hooks/before_component_optimize.js", + "before_release": "scripts/hooks/before_release.js", + "before_watch": "scripts/hooks/before_watch.js", + "after_build": "scripts/hooks/after_build.js", + "after_component_build": "scripts/hooks/after_component_build.js", + "before_hybrid_build": "scripts/hooks/before_hybrid_build.js", + "before_release_build": "scripts/hooks/before_release_build.js", + "before_serve": "scripts/hooks/before_serve.js", + "after_serve": "scripts/hooks/after_serve.js", + "after_watch": "scripts/hooks/after_watch.js", + "before_app_typescript": "scripts/hooks/before_app_typescript.js", + "before_component_typescript": "scripts/hooks/before_component_typescript.js", + "after_app_typescript": "scripts/hooks/after_app_typescript.js", + "after_component_typescript": "scripts/hooks/after_component_typescript.js", + "before_webpack": "scripts/hooks/before_webpack.js" + } +} diff --git a/test/templates/webpackLegacyTest/src/components/app.tsx b/test/templates/webpackLegacyTest/src/components/app.tsx new file mode 100644 index 0000000..351e217 --- /dev/null +++ b/test/templates/webpackLegacyTest/src/components/app.tsx @@ -0,0 +1,36 @@ +import { customElement, ExtendGlobalProps } from "ojs/ojvcomponent"; +import { h, Component, ComponentChild } from "preact"; +import Context = require("ojs/ojcontext"); +import { Footer } from "./footer"; +import { Header } from "./header"; +import { Content } from "./content/index"; + +type Props = { + appName?: string; + userLogin?: string; +} + +@customElement("app-root") +export class App extends Component> { + static defaultProps: Props = { + appName: 'App Name', + userLogin: "john.hancock@oracle.com" + }; + + render(props: ExtendGlobalProps): ComponentChild { + return ( +
+
+ +
+
+ ); + } + + componentDidMount() { + Context.getPageContext().getBusyContext().applicationBootstrapComplete(); + } +} diff --git a/test/templates/webpackLegacyTest/src/components/content/index.tsx b/test/templates/webpackLegacyTest/src/components/content/index.tsx new file mode 100644 index 0000000..f9805b9 --- /dev/null +++ b/test/templates/webpackLegacyTest/src/components/content/index.tsx @@ -0,0 +1,8 @@ +import { h } from "preact"; + +export function Content() { + return ( +
+
+ ); +}; diff --git a/test/templates/webpackLegacyTest/src/components/footer.tsx b/test/templates/webpackLegacyTest/src/components/footer.tsx new file mode 100644 index 0000000..88a7651 --- /dev/null +++ b/test/templates/webpackLegacyTest/src/components/footer.tsx @@ -0,0 +1,60 @@ +import { h } from "preact"; + +type Props = { + links?: FooterLink[] +} + +type FooterLink = { + name: string; + linkId: string; + linkTarget: string; +} + +const _DEFAULT_LINKS: FooterLink[] = [ + { + name: "About Oracle", + linkId: "aboutOracle", + linkTarget: "http://www.oracle.com/us/corporate/index.html#menu-about" + }, + { + name: "Contact Us", + linkId: "contactUs", + linkTarget: "http://www.oracle.com/us/corporate/contact/index.html" + }, + { + name: "Legal Notices", + linkId: "legalNotices", + linkTarget: "http://www.oracle.com/us/legal/index.html" + }, + { + name: "Terms Of Use", + linkId: "termsOfUse", + linkTarget: "http://www.oracle.com/us/legal/terms/index.html" + }, + { + name: "Your Privacy Rights", + linkId: "yourPrivacyRights", + linkTarget: "http://www.oracle.com/us/legal/privacy/index.html" + } +] + +export function Footer({ links = _DEFAULT_LINKS } : Props ) { + return ( +
+ + +
+ ); +} diff --git a/test/templates/webpackLegacyTest/src/components/header.tsx b/test/templates/webpackLegacyTest/src/components/header.tsx new file mode 100644 index 0000000..464a7f9 --- /dev/null +++ b/test/templates/webpackLegacyTest/src/components/header.tsx @@ -0,0 +1,94 @@ +import { h, Component, ComponentChild } from "preact"; +import * as ResponsiveUtils from "ojs/ojresponsiveutils"; +import "ojs/ojtoolbar"; +import "ojs/ojmenu"; +import "ojs/ojbutton"; + +type Props = { + appName: string, + userLogin: string +} + +type State = { + displayType: "all" | "icons", + endIconClass: string +} + +export class Header extends Component { + private mediaQuery: MediaQueryList; + + constructor(props: Props) { + super(props); + const smallOnlyQuery = ResponsiveUtils.getFrameworkQuery("sm-only"); + this.mediaQuery = window.matchMedia(smallOnlyQuery); + this._mediaQueryChangeListener = this._mediaQueryChangeListener.bind(this); + const displayType = this._getDisplayTypeFromMediaQuery(this.mediaQuery); + const endIconClass = this._getEndIconClassFromDisplayType(displayType); + this.state = { + displayType, + endIconClass + }; + } + + render(props: Readonly, state: Readonly): ComponentChild { + return ( + + ); + } + + componentDidMount() { + this.mediaQuery.addEventListener("change", this._mediaQueryChangeListener); + } + + componentWillUnmount() { + this.mediaQuery.removeEventListener("change", this._mediaQueryChangeListener); + } + + _mediaQueryChangeListener(mediaQuery) { + const displayType = this._getDisplayTypeFromMediaQuery(mediaQuery); + const endIconClass = this._getEndIconClassFromDisplayType(displayType); + this.setState({ + displayType, + endIconClass + }); + } + + _getDisplayTypeFromMediaQuery(mediaQuery) { + return mediaQuery.matches ? "icons" : "all"; + } + + _getEndIconClassFromDisplayType(displayType) { + return displayType === "icons" ? + "oj-icon demo-appheader-avatar" : + "oj-component-icon oj-button-menu-dropdown-icon" + } +} \ No newline at end of file diff --git a/test/templates/webpackLegacyTest/src/index.html b/test/templates/webpackLegacyTest/src/index.html new file mode 100644 index 0000000..4268ebd --- /dev/null +++ b/test/templates/webpackLegacyTest/src/index.html @@ -0,0 +1,55 @@ + + + + + + + + + Oracle JET VDOM Starter Template - Basic + + + + + + + + + + + + + + + + + + + diff --git a/test/templates/webpackLegacyTest/src/index.ts b/test/templates/webpackLegacyTest/src/index.ts new file mode 100644 index 0000000..42ab79c --- /dev/null +++ b/test/templates/webpackLegacyTest/src/index.ts @@ -0,0 +1 @@ +import './components/app'; \ No newline at end of file diff --git a/test/templates/webpackLegacyTest/src/main.js b/test/templates/webpackLegacyTest/src/main.js new file mode 100644 index 0000000..f332dc6 --- /dev/null +++ b/test/templates/webpackLegacyTest/src/main.js @@ -0,0 +1,63 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +/** + * @license + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. + * Licensed under The Universal Permissive License (UPL), Version 1.0 + * as shown at https://oss.oracle.com/licenses/upl/ + * @ignore + */ +'use strict'; + +/** + * Example of Require.js boostrap javascript + */ + + +(function () { + requirejs.config( + { + // injector:baseUrl + baseUrl: '.', + // endinjector + paths: + /* DO NOT MODIFY + ** All paths are dynamicaly generated from the path_mappings.json file. + ** Add any new library dependencies in path_mappings json file + */ + // injector:mainReleasePaths + { + 'ojs': 'libs/oj/v12.0.0/debug', + 'ojL10n': 'libs/oj/v12.0.0/ojL10n', + 'ojtranslations': 'libs/oj/v12.0.0/resources', + 'knockout': 'libs/knockout/knockout-3.5.1.debug', + 'jquery': 'libs/jquery/jquery-3.6.0', + 'jqueryui-amd': 'libs/jquery/jqueryui-amd-1.12.1', + 'text': 'libs/require/text', + 'hammerjs': 'libs/hammer/hammer-2.0.8', + 'signals': 'libs/js-signals/signals', + 'ojdnd': 'libs/dnd-polyfill/dnd-polyfill-1.0.2', + 'css': 'libs/require-css/css.min', + 'css-builder': 'libs/require-css/css-builder', + 'normalize': 'libs/require-css/normalize', + '@oracle/oraclejet-preact': 'libs/oraclejet-preact/amd', + 'preact': 'libs/preact/dist/preact.umd', + 'preact/hooks': 'libs/preact/hooks/dist/hooks.umd', + 'proj4': 'libs/proj4js/dist/proj4-src', + 'touchr': 'libs/touchr/touchr' + , + 'chai': 'libs/chai/chai-4.3.4' + } + // endinjector + } + ); +}()); + +/** + * Load the application's entry point file + */ +require(['./index']); diff --git a/test/templates/webpackLegacyTest/src/styles/app.css b/test/templates/webpackLegacyTest/src/styles/app.css new file mode 100644 index 0000000..f5aef33 --- /dev/null +++ b/test/templates/webpackLegacyTest/src/styles/app.css @@ -0,0 +1,43 @@ +/* + Document : override + Created on : + Author : + Description: + This is where any of your application specific styles should be included +*/ +.demo-oracle-icon { + width:137px; + height:18px +} + +.demo-oracle-icon:before { + content:url("images/oracle_logo.svg") +} + +html:not([dir="rtl"]) .demo-oracle-icon { + padding-right:4px +} + +html[dir="rtl"] .demo-oracle-icon { + padding-left:4px +} + +.demo-oracle-icon:before { + display:inline +} + +.demo-appheader-avatar { + width:24px; + height:24px +} + +.demo-appheader-avatar:before { + content:url("images/avatar_24px.png") +} +@media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 144dpi), (min-resolution: 1.5dppx) { + .demo-appheader-avatar:before { + content:url("images/avatar_24px_2x.png"); + -webkit-transform:translate(-25%, -25%) scale(0.5); + transform:translate(-25%, -25%) scale(0.5) + } +} \ No newline at end of file diff --git a/test/templates/webpackLegacyTest/src/styles/fonts/App_iconfont.woff b/test/templates/webpackLegacyTest/src/styles/fonts/App_iconfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..11e71bc27fce2a5a5e09a7fa08e2f84cebbbf195 GIT binary patch literal 5104 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 ME}R(8&%fmR4|0_aHUIzs literal 0 HcmV?d00001 diff --git a/test/templates/webpackLegacyTest/src/styles/images/avatar_24px.png b/test/templates/webpackLegacyTest/src/styles/images/avatar_24px.png new file mode 100644 index 0000000000000000000000000000000000000000..2838dc1adf7c097ce9ef9517e3f3eb7181c3476a GIT binary patch literal 1576 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 literal 0 HcmV?d00001 diff --git a/test/templates/webpackLegacyTest/src/styles/images/favicon.ico b/test/templates/webpackLegacyTest/src/styles/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..abdc1bb0247fff8bc793f4b27b6866aa9502706f GIT binary patch literal 58937 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 J&i~tg{~tNreN+Gd literal 0 HcmV?d00001 diff --git a/test/templates/webpackLegacyTest/src/styles/images/oracle_logo.svg b/test/templates/webpackLegacyTest/src/styles/images/oracle_logo.svg new file mode 100644 index 0000000..b4a3b6a --- /dev/null +++ b/test/templates/webpackLegacyTest/src/styles/images/oracle_logo.svg @@ -0,0 +1,21 @@ + + + + + diff --git a/test/templates/webpackLegacyTest/tsconfig.json b/test/templates/webpackLegacyTest/tsconfig.json new file mode 100644 index 0000000..bda8891 --- /dev/null +++ b/test/templates/webpackLegacyTest/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compileOnSave": true, + "compilerOptions": { + "baseUrl": ".", + "target": "es6", + "module": "amd", + "moduleResolution": "node", + "jsx": "react", + "jsxFactory": "h", + "lib": [ + "es2015", + "dom", + "esnext.asynciterable" + ], + "typeRoots": [ + "./node_modules/@oracle/oraclejet/dist/types", + "./node_modules/@types" + ], + "paths": { + "ojs/*": [ + "./node_modules/@oracle/oraclejet/dist/types/*" + ] + }, + "declaration": true, + "noEmitOnError": true, + "experimentalDecorators": true + }, + "include": [ + "./src/**/*" + ] +} diff --git a/test/themeTest.js b/test/themeTest.js index 8b8c2da..28467db 100644 --- a/test/themeTest.js +++ b/test/themeTest.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -9,10 +9,47 @@ const fs = require('fs-extra'); const path = require('path'); const util = require('./util'); -const testDir = path.resolve('../test_result'); -const appDir = path.resolve(testDir, util.THEME_APP_NAME); +const appDir = util.getAppDir(util.THEME_APP_NAME); describe('PCSS Theme Test', () => { + before(async () => { + if (!util.noScaffold()) { + util.removeAppDir(util.THEME_APP_NAME); + + // Scaffold a basic web app + let result = await util.execCmd(`${util.OJET_COMMAND} create ${util.THEME_APP_NAME} --use-global-tooling --norestore=true`, { cwd: util.testDir }); + console.log(result.stdout); + // Check that it output the right text to the command line + assert.strictEqual(util.norestoreSuccess(result.stdout), true, result.stderr); + // Restore + result = await util.execCmd(`${util.OJET_APP_COMMAND} restore`, { cwd: util.getAppDir(util.THEME_APP_NAME) }); + } + }); + + it('should run ojet build --sass in an app with no *.scss files and not fail', async () => { + const result = await util.execCmd(`${util.OJET_APP_COMMAND} build --sass`, {cwd: appDir}); + assert.equal(util.buildSuccess(result.stdout), true, result.error); + }); + + it('should run ojet build --sass in an app with *.scss files and fail with correct error message', async () => { + const testComponentName = 'test-component'; + // make a temporary jet-composites folder in the app folder + await util.execCmd(`${util.OJET_APP_COMMAND} create component ${testComponentName}`, {cwd: appDir}); + const { pathToApp, sourceFolder, javascriptFolder, componentsFolder} = util.getAppPathData(util.THEME_APP_NAME); + const pathToJetCompositeFolder = path.join(pathToApp, sourceFolder, javascriptFolder, componentsFolder); + const pathToTestComponent = path.join(pathToJetCompositeFolder,`${testComponentName}`); + const testComponentCssFile = `${testComponentName}-styles.css`; + // get .css and .scss file paths and rename .css to .scss + const cssFilePath = path.join(pathToTestComponent, testComponentCssFile); + const scssFilePath = cssFilePath.replace('.css', '.scss'); + fs.renameSync(cssFilePath, scssFilePath); + // set squelch to true to not catch anything on resolving the promise + const result = await util.execCmd(`${util.OJET_APP_COMMAND} build --sass`, {cwd: appDir}, true); + // Delete the jet-composite folder created after running ojet build --sass + fs.rmdirSync(pathToJetCompositeFolder, {recursive : true}); + assert.ok(/node-sass is not installed. To install it, run: ojet add sass./.test(result.stdout), true, result.stdout); + }); + it('Should add theming to enable node-sass, postcss-custom-theme, postcss-calc, autoprefixer', async () => { const result = await util.execCmd(`${util.OJET_APP_COMMAND} add theming`, { cwd: appDir }); assert.equal(/add pcss complete/.test(result.stdout), true, result.stdout); @@ -44,6 +81,26 @@ describe('PCSS Theme Test', () => { const result = await util.execCmd(`${util.OJET_APP_COMMAND} create theme demotheme`, {cwd: appDir}, true); assert.equal(/basetheme is required/.test(result.stdout), true, result.stdout); }); - + + it('Should run build with --theme=all and check that redwood files are present in staging location', async () => { + await util.execCmd(`${util.OJET_APP_COMMAND} build --themes=all`, {cwd: appDir}); + const { stagingFolder, stylesFolder, pathToNodeModules, pathToApp } = util.getAppPathData(util.THEME_APP_NAME); + const pathToRedwoodInStaging = path.join(pathToApp, stagingFolder, stylesFolder, 'redwood', util.getJetVersion(util.THEME_APP_NAME),'web'); + const pathToRedwoodInNodeModules = path.join(pathToNodeModules, '@oracle/oraclejet/dist/css/redwood'); + const everyExpectedEntryIsPresent = fs.readdirSync(pathToRedwoodInNodeModules).every(dirEntry => { + // oj-redwood.css is renamed to redwood.css in the staging location so + // we have to update the existence check: + if (dirEntry === 'oj-redwood.css') { + return fs.existsSync(path.join(pathToRedwoodInStaging, 'redwood.css')); + } + // Similarly, oj-redwood-min.css is renamed to redwood.min.css in the staging + // location so we have to update the existence check: + else if (dirEntry === 'oj-redwood-min.css') { + return fs.existsSync(path.join(pathToRedwoodInStaging, 'redwood.min.css')); + } + return fs.existsSync(path.join(pathToRedwoodInStaging, dirEntry)); + }); + assert.ok(everyExpectedEntryIsPresent, "Not all redwood files are present in staging location."); + }); }); }); \ No newline at end of file diff --git a/test/tsTest.js b/test/tsTest.js index 10a5eca..53bd648 100644 --- a/test/tsTest.js +++ b/test/tsTest.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -7,14 +7,25 @@ const assert = require('assert'); const fs = require('fs-extra'); const path = require('path'); - +const glob = require('glob'); const util = require('./util'); let filelist; -const testDir = path.resolve('../test_result'); -const appDir = path.resolve(testDir, util.TS_APP_NAME); +const appDir = util.getAppDir(util.TS_APP_NAME); describe('Typescript Test', () => { + before(async () => { + if (!util.noScaffold()) { + util.removeAppDir(util.TS_APP_NAME); + + // Scaffold TS app from scratch + const result = await util.execCmd(`${util.OJET_COMMAND} create ${util.TS_APP_NAME} --use-global-tooling --template=navbar --typescript`, { cwd: util.testDir }); + console.log(result.stdout); + // Check output + assert.equal(util.norestoreSuccess(result.stdout) || /Your app is/.test(result.stdout), true, result.error); + } + }); + describe('Scaffold with norestore flag', () => { it('should have tsconfig.json file', () => { const pathToTsconfigJson = path.resolve(appDir, 'tsconfig.json'); @@ -76,4 +87,45 @@ describe('Typescript Test', () => { assert.ok(!fs.pathExistsSync(pathToTSFolder), pathToTSFolder); }); }); + describe('Tsconfig "extends" option', () => { + if (!util.noBuild()) { + it('should build ts app after adding "extends" to tsconfig.json', async () => { + const BASE_TSCONFIG_JSON = 'base_tsconfig.json'; + const { pathToApp } = util.getAppPathData(util.TS_APP_NAME); + // Create base_tsconfig.json and add "extends" option to tsconfig.json + const baseTsconfigJsonPath = path.join(pathToApp, BASE_TSCONFIG_JSON); + const baseTsconfigJson = { + compilerOptions: { + noEmit: true + } + }; + fs.writeJSONSync(baseTsconfigJsonPath, baseTsconfigJson, { spaces: 2 }); + const tsconfigJsonPath = path.join(pathToApp, util.TSCONFIG_JSON); + const tsconfigJson = fs.readJSONSync(tsconfigJsonPath); + tsconfigJson.extends = `./${BASE_TSCONFIG_JSON}`; + fs.writeJSONSync(tsconfigJsonPath, tsconfigJson, { spaces: 2 }); + // Run build and ensure that it was successful + const result = await util.execCmd(`${util.OJET_APP_COMMAND} build`, { cwd: util.getAppDir(util.TS_APP_NAME) }); + assert.equal(util.buildSuccess(result.stdout), true, result.error); + // Delete base_tsconfig.json and revert tsconfig.json change + fs.removeSync(baseTsconfigJsonPath); + delete tsconfigJson.extends; + fs.writeJSONSync(tsconfigJsonPath, tsconfigJson, { spaces: 2 }); + }); + } + it('should not have *.ts compiled to *.js because of noEmit in base_tsconfig.json', () => { + const { pathToApp, sourceFolder, typescriptFolder, stagingFolder, javascriptFolder } = util.getAppPathData(util.TS_APP_NAME); + const typescriptFilesPattern = path.join(pathToApp, sourceFolder, typescriptFolder, '**/*.ts'); + const typescriptFiles = glob.sync(typescriptFilesPattern); + typescriptFiles.forEach((file) => { + const stagingPath = path.normalize(file) + .replace( + path.join(pathToApp, sourceFolder, typescriptFolder), + path.join(pathToApp, stagingFolder, javascriptFolder) + ) + .replace('.ts', '.js'); + assert.ok(!fs.existsSync(stagingPath), `${stagingPath} found`); + }); + }); + }); }); diff --git a/test/util/index.js b/test/util/index.js index 63f8d6a..f56728e 100644 --- a/test/util/index.js +++ b/test/util/index.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -12,7 +12,9 @@ const path = require('path'); const exec = require('child_process').exec; -const td = path.resolve('../test_result'); +const TEST_DIR = 'test_result'; + +const td = path.resolve(`../${TEST_DIR}`); const pkg = require('../../package.json'); function _isQuick() { @@ -26,22 +28,49 @@ const JAVASCRIPT_COMPONENT_APP_CONFIG = { appName: COMPONENT_APP_NAME, scriptsFo const TYPESCRIPT_COMPONENT_APP_CONFIG = { appName: COMPONENT_TS_APP_NAME, scriptsFolder: 'ts' }; const COMPONENT_TEST_APP_CONFIGS = [JAVASCRIPT_COMPONENT_APP_CONFIG, TYPESCRIPT_COMPONENT_APP_CONFIG]; -function runComponentTestInAllTestApps({ test, pack, component, vcomponent, release, bundle, resourceComponent }) { +function runComponentTestInAllTestApps(options) { COMPONENT_TEST_APP_CONFIGS.forEach((config) => { - runComponentTestInTestApp({ config, test, pack, component, vcomponent, release, bundle, resourceComponent }); + runComponentTestInTestApp(config, options); }) } -function runComponentTestInTestApp({ config, test, pack, component, vcomponent, release, bundle, resourceComponent }) { +function runComponentTestInTestApp(config, options) { describe(config.appName, () => { - test({...config, pack, component, vcomponent, release, bundle, resourceComponent }); + options.test({...config, ...options}); }); } -const ORACLJET_CONFIG_JSON = 'oraclejetconfig.json'; +function _replaceOraclejetToolingProp(packageJson) { + packageJson.devDependencies['@oracle/oraclejet-tooling'] = `file:${path.join('..', '..', + 'ojet-cli', 'node_modules', '@oracle', 'oraclejet-tooling')}`; +} + +const ORACLEJET_CONFIG_JSON = 'oraclejetconfig.json'; const DEFAULT_COMPONENTS_FOLDER = 'jet-composites'; const OMIT_COMPONENT_VERSION_FLAG = 'omit-component-version'; -const WEBPACK_DEPENDENCIES = ['webpack', 'css-loader', 'style-loader', 'text-loader']; +const WEBPACK_LEGACY_DEPENDENCIES = ['webpack', 'css-loader', 'style-loader', 'text-loader']; +const WEBPACK_DEPENDENCIES = [ + 'webpack', + 'webpack-dev-server', + 'style-loader', + 'css-loader', + 'ts-loader', + 'raw-loader', + 'noop-loader', + 'html-webpack-plugin', + 'html-replace-webpack-plugin', + 'copy-webpack-plugin', + '@prefresh/webpack', + '@prefresh/babel-plugin', + 'webpack-merge', + 'compression-webpack-plugin', + 'mini-css-extract-plugin', + 'zlib' +]; +const COMPONENT_JSON_DEPENDENCIES_TOKEN = '@dependencies@'; +const COMPONENT_JSON = 'component.json'; +const OJET_CONFIG_JS = 'ojet.config.js'; +const TSCONFIG_JSON = 'tsconfig.json'; module.exports = { OJET_COMMAND: 'node ../ojet-cli/bin/ojet', @@ -54,16 +83,24 @@ module.exports = { PWA_APP_NAME: 'webJsPwaTest', API_APP_NAME: 'webTsApiTest', VDOM_APP_NAME: 'vdomTest', + WEBPACK_APP_NAME: 'webpackTest', + WEBPACK_LEGACY_APP_NAME: 'webpackLegacyTest', COMPONENT_APP_NAME, COMPONENT_TS_APP_NAME, JAVASCRIPT_COMPONENT_APP_CONFIG, TYPESCRIPT_COMPONENT_APP_CONFIG, EXCHANGE_URL: 'https://exchange.oraclecorp.com/api/0.2.0', - ORACLJET_CONFIG_JSON, + ORACLEJET_CONFIG_JSON, DEFAULT_COMPONENTS_FOLDER, OMIT_COMPONENT_VERSION_FLAG, + TEST_DIR, WEBPACK_DEPENDENCIES, - execCmd: function _execCmd(cmd, options, squelch, logCommand = true) { + WEBPACK_LEGACY_DEPENDENCIES, + COMPONENT_JSON_DEPENDENCIES_TOKEN, + COMPONENT_JSON, + OJET_CONFIG_JS, + TSCONFIG_JSON, + execCmd: function _execCmd(cmd, options, squelch = false, logCommand = true) { if (logCommand) { console.log(cmd); } @@ -80,6 +117,23 @@ module.exports = { }) }, + makePackageSymlink: function _makePackageSymlink() { + function _updatePackageFile(dir) { + let src = path.resolve('generators', dir, 'templates', 'common', 'package.json'); + let json = fs.readJSONSync(src); + // Replace the property + _replaceOraclejetToolingProp(json); + // Write it back out + fs.writeJsonSync(src, json); + } + + // Update the two package.json files in our built ojet-cli common templates + _updatePackageFile('app'); + + // do hybrid + _updatePackageFile('hybrid'); + }, + // Copy over oraclejet-tooling's build to the installation of ojet-cli copyOracleJetTooling: function _copyOracleJetTooling(app) { try { @@ -204,28 +258,72 @@ module.exports = { return regex.test(stdout); }, + removeAppDir: function _removeAppDir(appName) { + const appDir = path.join(td, appName); + fs.emptyDirSync(appDir); + fs.rmdirSync(appDir); + }, + runComponentTestInAllTestApps, runComponentTestInTestApp, - getOracleJetConfigJson: function _getOracleJetConfigJson({ appName }) { - const oraclejetConfigJsonPath = path.join(this.getAppDir(appName), ORACLJET_CONFIG_JSON); - const oraclejetConfigJson = fs.readJSONSync(oraclejetConfigJsonPath); + getOracleJetConfigPath: function _getOracleJetConfigPath(appName) { + return path.join(this.getAppDir(appName), ORACLEJET_CONFIG_JSON); + }, + + getOracleJetConfigJson: function _getOracleJetConfigJson(appName) { + const oraclejetConfigJson = fs.readJSONSync(this.getOracleJetConfigPath(appName)); return oraclejetConfigJson; }, - getAppPathData: function _getAppPathData({ appName }) { - const oraclejetConfigJson = this.getOracleJetConfigJson({ appName }); + writeOracleJetConfigJson: function _writeOracleJetConfigJson(appName, oraclejetConfigJson) { + fs.writeJsonSync(this.getOracleJetConfigPath(appName), oraclejetConfigJson); + }, + + writeCustomHookContents: function _writeCustomHookContents({hookName, filePath}) { + const customHookContent = `module.exports = function (configObj) { + return new Promise((resolve) => { + const componentName = configObj.component; + console.log('Running ${hookName}_component_package for component: component being packaged is', componentName); + resolve(configObj); + }); + }` + fs.writeFileSync(filePath, customHookContent); + }, + + getHooksPathAndContent: function _getHooksPathAndContent(appName) { + const { pathToAppHooks } = this.getAppPathData(appName); + const beforePackageHookPath = path.join(pathToAppHooks, `before_component_package.js`); + const afterPackageHookPath = path.join(pathToAppHooks, `after_component_package.js`); + const defaultBeforeHookContent = fs.readFileSync(beforePackageHookPath); + const defaultAfterHookContent = fs.readFileSync(afterPackageHookPath); + return { + beforePackageHookPath, + afterPackageHookPath, + defaultBeforeHookContent, + defaultAfterHookContent + } + }, + + getAppPathData: function _getAppPathData(appName, scriptsFolder='') { + const oraclejetConfigJson = this.getOracleJetConfigJson(appName); const componentsFolder = oraclejetConfigJson.paths.source.components || DEFAULT_COMPONENTS_FOLDER; const stagingFolder = oraclejetConfigJson.paths.staging.web; const javascriptFolder = oraclejetConfigJson.paths.source.javascript; - const typescriptFolder = oraclejetConfigJson.paths.source.javascript; + const typescriptFolder = oraclejetConfigJson.paths.source.typescript; const sourceFolder = oraclejetConfigJson.paths.source.common; const pathToApp = this.getAppDir(appName); const pathToBuiltComponents = path.join(pathToApp, stagingFolder, javascriptFolder, componentsFolder); + const pathToSourceComponents = path.join(pathToApp, sourceFolder, scriptsFolder, componentsFolder); const pathToMainJs = path.join(pathToApp, stagingFolder, javascriptFolder, 'main.js'); const pathToBundleJs = path.join(pathToApp, stagingFolder, javascriptFolder, 'bundle.js'); + const exchangeComponentsFolder = oraclejetConfigJson.paths.source.exchangeComponents || 'jet_components'; + const pathToNodeModules = path.join(pathToApp, 'node_modules'); + const pathToAppHooks = path.join(pathToApp, `scripts/hooks`); + const pathToExchangeComponents = path.join(pathToApp, exchangeComponentsFolder); const pathToIndexHtml = path.join(pathToApp, stagingFolder, 'index.html'); + const stylesFolder = oraclejetConfigJson.paths.source.styles; return { componentsFolder, stagingFolder, @@ -234,13 +332,19 @@ module.exports = { typescriptFolder, pathToApp, pathToBuiltComponents, + pathToSourceComponents, pathToMainJs, pathToBundleJs, - pathToIndexHtml + exchangeComponentsFolder, + pathToNodeModules, + pathToExchangeComponents, + pathToIndexHtml, + pathToAppHooks, + stylesFolder } }, getTemplatesDir: function _getTempatesDir() { return path.resolve(__dirname, '..', 'templates'); } -}; +}; \ No newline at end of file diff --git a/test/vdomTest.js b/test/vdomTest.js index 92771d1..1116f2b 100644 --- a/test/vdomTest.js +++ b/test/vdomTest.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -7,14 +7,38 @@ const assert = require('assert'); const fs = require('fs-extra'); const path = require('path'); - const Ojet = require('../ojet'); const util = require('./util'); -const testDir = path.resolve('../test_result'); -const appDir = path.resolve(testDir, util.VDOM_APP_NAME); +const appDir = util.getAppDir(util.VDOM_APP_NAME); describe('VDOM Test', () => { + before(async () => { + if (!util.noScaffold()) { + util.removeAppDir(util.VDOM_APP_NAME); + + // Scaffold vdomTest application using API + const ojet = new Ojet({ cwd: util.testDir, logs: false }); + let executeOptions = {}; + try { + executeOptions = { + task: 'create', + parameters: [util.VDOM_APP_NAME], + options: { + template: 'basic', + vdom: true + } + }; + await ojet.execute(executeOptions); + + assert.ok(true); + } catch (e) { + console.log(e); + assert.ok(false, `Error running ojet.execute with ${executeOptions}`); + } + } + }); + describe('Scaffold', () => { it('should have path_mapping.json at root of the app with no baseUrl', () => { const pathToPathMappingJson = path.resolve(appDir, 'path_mapping.json'); @@ -50,7 +74,7 @@ describe('VDOM Test', () => { sourceFolder, typescriptFolder, componentsFolder - } = util.getAppPathData({ appName: util.VDOM_APP_NAME }) + } = util.getAppPathData(util.VDOM_APP_NAME) const componentName = 'vcomp-1'; const pathToComponentTsx = path.join( pathToApp, @@ -104,70 +128,24 @@ describe('VDOM Test', () => { } }); - describe('Webpack', () => { - describe('Add webpack', () => { - if (!util.noScaffold()) { - it('should run "ojet add webpack"', async () => { - const { pathToApp } = util.getAppPathData({ appName: util.VDOM_APP_NAME }); - const ojet = new Ojet({ cwd: pathToApp, logs: false }); - try { - await ojet.execute({ - task: 'add', - parameters: ['webpack'] - }); - assert.ok(true); - } catch { - assert.ok(false); - } - }); - } - it('should check that webpack and its dependencies are listed in package.json', () => { - const { pathToApp } = util.getAppPathData({ appName: util.VDOM_APP_NAME }); - const packageJson = fs.readJsonSync(path.join(pathToApp, 'package.json')); - util.WEBPACK_DEPENDENCIES.forEach((dependency) => { - assert.ok(packageJson.devDependencies[dependency], `${dependency} not installed`); - }); - }); - it('should check that bundler and bundleName properties were added to oraclejetconfig.json', () => { - const oraclejetConfigJson = util.getOracleJetConfigJson({ appName: util.VDOM_APP_NAME }); - assert.ok(oraclejetConfigJson.bundler === 'webpack', 'bundler not equal to "webpack"'); - assert.ok(oraclejetConfigJson.bundleName === 'bundle.js', 'bundleName not equal to "bundle.js'); - }); - }); - describe('Build debug', () => { - it('should build in debug mode', async () => { - const { pathToApp } = util.getAppPathData({ appName: util.VDOM_APP_NAME }); - const ojet = new Ojet({ cwd: pathToApp, logs: false }); - try { - await ojet.execute({ task: 'build' }); - assert.ok(true); - } catch { - assert.ok(false); - } - }); - }); - describe('Build release', () => { - it('should build in release mode', async () => { - const { pathToApp } = util.getAppPathData({ appName: util.VDOM_APP_NAME }); - const ojet = new Ojet({ cwd: pathToApp, logs: false }); - try { - await ojet.execute({ task: 'build', options: { release: true }}); - assert.ok(true); - } catch { - assert.ok(false); - } - }); - it('should have bundle file', () => { - const { pathToBundleJs } = util.getAppPathData({ appName: util.VDOM_APP_NAME }); - const bundleFileExists = fs.existsSync(pathToBundleJs); - assert.ok(bundleFileExists, `${pathToBundleJs} does not exist`); - }); - it('should not load require.js in index.html', () => { - const { pathToIndexHtml } = util.getAppPathData({ appName: util.VDOM_APP_NAME }); - const indexHtmlContent = fs.readFileSync(pathToIndexHtml, { encoding: 'utf-8' }); - const loadsRequireJs = /require\/require\.js'><\/script>/.test(indexHtmlContent); - assert.ok(!loadsRequireJs, `${pathToIndexHtml} loads require.js`); + describe('Add (pwa)', () => { + if (!util.noBuild()) { + it('should have appropriate vdom files and folders to cache in sw.js on running ojet add pwa', async () => { + await util.execCmd(`${util.OJET_APP_COMMAND} add pwa`, { cwd: appDir }, true, true); + await util.execCmd(`${util.OJET_APP_COMMAND} build --release`, { cwd: appDir }, true, true); + const {pathToApp, stagingFolder} = util.getAppPathData(util.VDOM_APP_NAME); + const pathToSWFile = path.join(pathToApp, stagingFolder, 'sw.js'); + const swJsContent = fs.readFileSync(pathToSWFile, { encoding: 'utf-8' }); + const regex = /resourcesToCache=(?.*)\;self/gm; + const match = regex.exec(swJsContent); + const retrievedResourcesToCache = match.groups.resourcesToCache; + const requiredResourcesToCache = ['index.js', 'index.html', 'bundle.js', 'manifest.json', 'components/', 'libs/', 'styles/']; + const swJSHasRequiredResourcesTocache = requiredResourcesToCache.every((resource) => { + return retrievedResourcesToCache.includes(resource); + }) + const errorMessage = `sw.js does not contain right files and folders to cache for a vdom app.`; + assert.equal(swJSHasRequiredResourcesTocache, true, errorMessage); }); - }); + } }); }); diff --git a/test/webTest.js b/test/webTest.js index 2ef0dae..c5fb9f2 100644 --- a/test/webTest.js +++ b/test/webTest.js @@ -1,5 +1,5 @@ /** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2015, 2022, Oracle and/or its affiliates. Licensed under The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -9,13 +9,45 @@ const fs = require('fs-extra'); const path = require('path'); const _ = require('lodash'); +const constants = require('../lib/util/constants'); +const ojetUtil = require('../lib/util/utils'); +const ojetPaths = require('../lib/util/paths'); + const util = require('./util'); let filelist; -const testDir = path.resolve('../test_result'); -const appDir = path.resolve(testDir, util.APP_NAME); +const appDir = util.getAppDir(util.APP_NAME); describe('Web Test', () => { + before(async () => { + if (!util.noScaffold()) { + const platform = util.getPlatform(process.env.OS); + + util.removeAppDir(util.APP_NAME); + util.removeAppDir(util.TEST_DIR); + + // Scaffold a basic web app + let result = await util.execCmd(`${util.OJET_COMMAND} create ${util.APP_NAME} --norestore=true`, { cwd: util.testDir }); + console.log(result.stdout); + // Check that it output the right text to the command line + assert.strictEqual(util.norestoreSuccess(result.stdout), true, result.stderr); + // Restore + result = await util.execCmd(`${util.OJET_APP_COMMAND} restore`, { cwd: util.getAppDir(util.APP_NAME) }); + console.log(result.stdout); + + // Scaffold a basic app without a name + result = await util.execCmd(`${util.OJET_COMMAND} create --norestore=true`, { cwd: util.testDir }); + // Check that it worked + assert.equal(util.norestoreSuccess(result.stdout) || /Your app is/.test(result.stdout), true, result.error); + + if (!util.noHybrid()) { + // Add hybrid + let result = await util.execCmd(`${util.OJET_APP_COMMAND} add hybrid --platform=${platform}`, { cwd: util.getAppDir(util.APP_NAME) }); + console.log(result.stdout); + } + } + }); + describe('Check essential files', () => { it('should have package.json', () => { filelist = fs.readdirSync(appDir); @@ -38,13 +70,13 @@ describe('Web Test', () => { }); } it('should not have bundle.js', async () => { - const{ pathToBundleJs } = util.getAppPathData({ appName: util.APP_NAME }) + const{ pathToBundleJs } = util.getAppPathData(util.APP_NAME) const hasBundleJs = fs.existsSync(pathToBundleJs); assert.ok(!hasBundleJs, pathToBundleJs); }) }); - describe('Build (Release)', () => { + describe('Build (Release) without the bundle name attribute', () => { if (!util.noBuild()) { it('should build release js app', async () => { const result = await util.execCmd(`${util.OJET_APP_COMMAND} build web --release`, { cwd: util.getAppDir(util.APP_NAME) }); @@ -52,17 +84,64 @@ describe('Web Test', () => { }); } it('should have bundle.js', async () => { - const{ pathToBundleJs } = util.getAppPathData({ appName: util.APP_NAME }) + const{ pathToBundleJs } = util.getAppPathData(util.APP_NAME) const hasBundleJs = fs.existsSync(pathToBundleJs); assert.ok(hasBundleJs, pathToBundleJs); }) it('should not have main.js', async () => { - const{ pathToMainJs } = util.getAppPathData({ appName: util.APP_NAME }) + const{ pathToMainJs } = util.getAppPathData(util.APP_NAME) const hasMainJs = fs.existsSync(pathToMainJs); assert.ok(!hasMainJs, pathToMainJs); }) }); + describe('Build (Release) with any given bundle name other than main.js', () => { + if (!util.noBuild()) { + it('should build release js app', async () => { + // get the oraclejetconfig.json file and add bundleName attribute value to .js: + const oracleJetConfigJSON = util.getOracleJetConfigJson(util.APP_NAME); + oracleJetConfigJSON.bundleName = `${util.API_APP_NAME}.js`; + util.writeOracleJetConfigJson(util.APP_NAME, oracleJetConfigJSON); + const result = await (util.execCmd(`${util.OJET_APP_COMMAND} build web --release`, { cwd: util.getAppDir(util.APP_NAME) })); + // Delete the bundleName attribute. Having it might cause the subsequent case(s) to fail: + delete oracleJetConfigJSON.bundleName; + util.writeOracleJetConfigJson(util.APP_NAME, oracleJetConfigJSON); + assert.equal(util.buildSuccess(result.stdout), true, result.error); + }); + } + it(`should have ${util.API_APP_NAME}.js`, async () => { + // retrieve the path for the created js file and check its presence: + const{ pathToApp, stagingFolder, javascriptFolder } = util.getAppPathData(util.APP_NAME) + const pathToBundleNameJs = path.join(pathToApp, stagingFolder, javascriptFolder, `${util.API_APP_NAME}.js`); + const hasBundleNameJs = fs.existsSync(pathToBundleNameJs); + assert.ok(hasBundleNameJs, pathToBundleNameJs); + }) + it('should not have main.js', async () => { + const{ pathToMainJs } = util.getAppPathData(util.APP_NAME) + const hasMainJs = fs.existsSync(pathToMainJs); + assert.ok(!hasMainJs, pathToMainJs); + }) + }); + + describe('Build (Release) with main.js as the bundleName', () => { + if (!util.noBuild()) { + it('should build release js app', async () => { + const oracleJetConfigJSON = util.getOracleJetConfigJson(util.APP_NAME); + oracleJetConfigJSON.bundleName = 'main.js'; + util.writeOracleJetConfigJson(util.APP_NAME, oracleJetConfigJSON); + const result = await util.execCmd(`${util.OJET_APP_COMMAND} build web --release`, { cwd: util.getAppDir(util.APP_NAME) }); + delete oracleJetConfigJSON.bundleName; + util.writeOracleJetConfigJson(util.APP_NAME, oracleJetConfigJSON); + assert.equal(util.buildSuccess(result.stdout), true, result.error); + }); + } + it('should have main.js', async () => { + const{ pathToMainJs } = util.getAppPathData(util.APP_NAME) + const hasMainJs = fs.existsSync(pathToMainJs); + assert.ok(hasMainJs, pathToMainJs); + }) + }); + // // BuildWithComponent verifies that proper path mapping is set for a component. // @@ -103,7 +182,7 @@ describe('Web Test', () => { }); it('release build: path mapping to minified component', async () => { await util.execCmd(`${util.OJET_APP_COMMAND} build web --release`, { cwd: util.getAppDir(util.APP_NAME) }); - const{ pathToBundleJs } = util.getAppPathData({ appName: util.APP_NAME }) + const{ pathToBundleJs } = util.getAppPathData(util.APP_NAME); const bundleContent = fs.readFileSync(pathToBundleJs); assert.equal(bundleContent.toString().match(`jet-composites/${testComp}/1.0.0/min`), `jet-composites/${testComp}/1.0.0/min`, `bundle.js should contain the minified component ${testComp}`); @@ -220,7 +299,7 @@ describe('Paths Mapping Test', () => { if (!util.noServe()) { describe('serve', () => { it('should serve with nobuild', async () => { - const result = await util.execCmd(`${util.OJET_APP_COMMAND} serve web --no-build`, { cwd: util.getAppDir(util.APP_NAME), maxBuffer: 1024 * 30000, timeout:40000, killSignal:'SIGTERM' }, true); + const result = await util.execCmd(`${util.OJET_APP_COMMAND} serve web --no-build`, { cwd: util.getAppDir(util.APP_NAME), maxBuffer: 1024 * 20000, timeout:30000, killSignal:'SIGTERM' }, true); assert.equal(/Watching files/i.test(result.stdout), true, result.stdout); result.process.kill(); }); @@ -231,9 +310,6 @@ describe('add theming', () => { it('should add pcss generator', async () => { const result = await util.execCmd(`${util.OJET_APP_COMMAND} add theming`, { cwd: appDir }); assert.equal(/add pcss complete/.test(result.stdout), true, result.stdout); - - // Recopy oraclejet-tooling - util.copyOracleJetTooling(`${util.APP_NAME}`); }); }); @@ -294,4 +370,75 @@ describe('Build with cdn', () => { assert.ok(!hasLibNotInWhitelist, 'libs should not contain libraries referenced from the cdn'); }); }); + + describe('Customization Test', () => { + it('should load oraclejet build config', () => { + const wd = process.cwd(); + process.chdir(util.getAppDir(util.APP_NAME)); + const buildOps = ojetUtil.getBuildCustomizedConfig(); + process.chdir(wd); + assert(!_.isEmpty(buildOps)); + }); + + it('should load oraclejet serve config', () => { + const wd = process.cwd(); + process.chdir(util.getAppDir(util.APP_NAME)); + const serveOps = ojetUtil.getServeCustomizedConfig(); + process.chdir(wd); + assert(!_.isEmpty(serveOps)); + }); + + it('should validate serve config', () => { + const wd = process.cwd(); + process.chdir(util.getAppDir(util.APP_NAME)); + const serveOps = ojetUtil.getServeCustomizedConfig(); + process.chdir(wd); + const validServe = ojetUtil.validateServeOptions(serveOps); + assert(_.isEmpty(validServe)); + }); + + + it('should get default paths', () => { + const defaultPaths = ojetPaths.getDefaultPaths(); + assert(!_.isEmpty(defaultPaths)); + }); + + it('should validate configured paths', () => { + const defaultPaths = ojetPaths.getDefaultPaths(); + assert(defaultPaths.source == 'src'); + assert(defaultPaths.sourceWeb == 'src-web'); + assert(defaultPaths.sourceHybrid == 'src-hybrid'); + assert(defaultPaths.sourceJavascript == 'js'); + assert(defaultPaths.sourceThemes == 'themes'); + assert(defaultPaths.stagingHybrid == 'hybrid'); + assert(defaultPaths.stagingWeb == 'web'); + assert(defaultPaths.stagingThemes == constants.APP_STAGED_THEMES_DIRECTORY); + }); + + + it('should get configured paths', () => { + const confPaths = ojetPaths.getConfiguredPaths(util.getAppDir(util.APP_NAME)); + assert(!_.isEmpty(confPaths)); + }); + + it('should validate configured paths', () => { + const defaultPaths = ojetPaths.getDefaultPaths(); + const confPaths = ojetPaths.getConfiguredPaths(util.getAppDir(util.APP_NAME)); + assert(_.isEqual(confPaths, defaultPaths)); + }); + + it('should validate is cwd is JET App', () => { + const wd = process.cwd(); + process.chdir(util.getAppDir(util.APP_NAME)); + const isJetApp = ojetUtil.ensureJetApp(); + process.chdir(wd); + assert(isJetApp); + }); + + it('should validate util ensure parameters', () => { + assert.doesNotThrow(() => { + ojetUtil.ensureParameters('component'); + }); + }); + }); }); diff --git a/test/webpackTest.js b/test/webpackTest.js new file mode 100644 index 0000000..2bcae4c --- /dev/null +++ b/test/webpackTest.js @@ -0,0 +1,161 @@ +/** + Copyright (c) 2015, 2022, Oracle and/or its affiliates. + Licensed under The Universal Permissive License (UPL), Version 1.0 + as shown at https://oss.oracle.com/licenses/upl/ + +*/ +const assert = require('assert'); +const fs = require('fs-extra'); +const path = require('path'); +const Ojet = require('../ojet'); +const util = require('./util'); + +describe('Webpack Test', () => { + before(async () => { + if (!util.noScaffold()) { + // Create legacy webpack app. Will remove once end-to-end webpack + // support is complete + util.removeAppDir(util.WEBPACK_LEGACY_APP_NAME); + // Scaffold vdomTest application using API + const ojet = new Ojet({ cwd: util.testDir, logs: false }); + let executeOptions = {}; + try { + executeOptions = { + task: 'create', + parameters: [util.WEBPACK_LEGACY_APP_NAME], + options: { + template: path.join(util.getTemplatesDir(), util.WEBPACK_LEGACY_APP_NAME) + } + }; + await ojet.execute(executeOptions); + assert.ok(true); + // We need the locally built copy of oraclejet-tooling before the merge + // to pick up the latest changes. Will remove after the merge + util.copyOracleJetTooling(util.WEBPACK_LEGACY_APP_NAME); + } catch (e) { + console.log(e); + assert.ok(false, `Error running ojet.execute with ${executeOptions}`); + } + } + if (!util.noScaffold()) { + // Create end-to-end webpack app + util.removeAppDir(util.WEBPACK_APP_NAME); + // Scaffold vdomTest application using API + const ojet = new Ojet({ cwd: util.testDir, logs: false }); + let executeOptions = {}; + try { + executeOptions = { + task: 'create', + parameters: [util.WEBPACK_APP_NAME], + options: { + template: 'basic', + vdom: true, + webpack: true + } + }; + await ojet.execute(executeOptions); + assert.ok(true); + } catch (e) { + console.log(e); + assert.ok(false, `Error running ojet.execute with ${executeOptions}`); + } + } + }); + describe('Webpack', () => { + describe('Scaffold', () => { + it('should check that webpack and its dependencies are listed in package.json', () => { + const { pathToApp } = util.getAppPathData(util.WEBPACK_APP_NAME); + const packageJson = fs.readJsonSync(path.join(pathToApp, 'package.json')); + util.WEBPACK_DEPENDENCIES.forEach((dependency) => { + assert.ok(packageJson.devDependencies[dependency], `${dependency} not installed`); + }); + }); + it(`should check that ${util.OJET_CONFIG_JS} was added`, () => { + const { pathToApp } = util.getAppPathData(util.WEBPACK_APP_NAME); + const pathToOjetConfigJs = path.join(pathToApp, util.OJET_CONFIG_JS); + assert.ok(fs.existsSync(pathToOjetConfigJs), `${util.OJET_CONFIG_JS} not in application`); + }); + }); + describe('Build (Debug)', () => { + it('should build in debug mode', async () => { + const { pathToApp } = util.getAppPathData(util.WEBPACK_APP_NAME); + const ojet = new Ojet({ cwd: pathToApp, logs: false }); + try { + await ojet.execute({ task: 'build' }); + assert.ok(true); + } catch { + assert.ok(false); + } + }); + }); + describe('Build (Release)', () => { + it('should build in release mode', async () => { + const { pathToApp } = util.getAppPathData(util.WEBPACK_APP_NAME); + const ojet = new Ojet({ cwd: pathToApp, logs: false }); + try { + await ojet.execute({ task: 'build', options: { release: true }}); + assert.ok(true); + } catch { + assert.ok(false); + } + }); + }); + }); + describe('Webpack (Legacy)', () => { + describe('Scaffold', () => { + it('should check that webpack and its dependencies are listed in package.json', () => { + const { pathToApp } = util.getAppPathData(util.WEBPACK_LEGACY_APP_NAME); + const packageJson = fs.readJsonSync(path.join(pathToApp, 'package.json')); + util.WEBPACK_LEGACY_DEPENDENCIES.forEach((dependency) => { + assert.ok(packageJson.devDependencies[dependency], `${dependency} not installed`); + }); + }); + it('should check that bundler and bundleName properties were added to oraclejetconfig.json', () => { + const oraclejetConfigJson = util.getOracleJetConfigJson(util.WEBPACK_LEGACY_APP_NAME); + assert.ok(oraclejetConfigJson.bundler === 'webpack', 'bundler not equal to "webpack"'); + assert.ok(oraclejetConfigJson.bundleName === 'bundle.js', 'bundleName not equal to "bundle.js'); + }); + }); + describe('Build (Debug)', () => { + it('should build in debug mode', async () => { + const { pathToApp } = util.getAppPathData(util.WEBPACK_LEGACY_APP_NAME); + const ojet = new Ojet({ cwd: pathToApp, logs: false }); + try { + await ojet.execute({ task: 'build' }); + assert.ok(true); + } catch { + assert.ok(false); + } + }); + }); + describe('Build (Release)', () => { + it('should build in release mode', async () => { + const { pathToApp } = util.getAppPathData(util.WEBPACK_LEGACY_APP_NAME); + const ojet = new Ojet({ cwd: pathToApp, logs: false }); + try { + await ojet.execute({ task: 'build', options: { release: true }}); + assert.ok(true); + } catch { + assert.ok(false); + } + }); + it('should have bundle.js file', () => { + const { pathToBundleJs } = util.getAppPathData(util.WEBPACK_LEGACY_APP_NAME); + const bundleFileExists = fs.existsSync(pathToBundleJs); + assert.ok(bundleFileExists, `${pathToBundleJs} does not exist`); + }); + it('should have bundle.js script in index.html', () => { + const { pathToIndexHtml } = util.getAppPathData(util.WEBPACK_LEGACY_APP_NAME); + const indexHtmlContent = fs.readFileSync(pathToIndexHtml, { encoding: 'utf-8' }); + const loadsBundleJs = /bundle\.js(?:'|")><\/script>/.test(indexHtmlContent); + assert.ok(loadsBundleJs, `${pathToIndexHtml} does not load bundle.js`); + }); + it('should not load require.js in index.html', () => { + const { pathToIndexHtml } = util.getAppPathData(util.WEBPACK_LEGACY_APP_NAME); + const indexHtmlContent = fs.readFileSync(pathToIndexHtml, { encoding: 'utf-8' }); + const loadsRequireJs = /require\/require\.js(?:'|")><\/script>/.test(indexHtmlContent); + assert.ok(!loadsRequireJs, `${pathToIndexHtml} loads require.js`); + }) + }); + }); +}); \ No newline at end of file diff --git a/util/index.js b/util/index.js deleted file mode 100644 index d1859ca..0000000 --- a/util/index.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - Copyright (c) 2015, 2021, Oracle and/or its affiliates. - Licensed under The Universal Permissive License (UPL), Version 1.0 - as shown at https://oss.oracle.com/licenses/upl/ - -*/ -'use strict'; - -const path = require('path'); -const fs = require('fs-extra'); - -module.exports = -{ - getDirectories(source) { - // util function to get directories listing - return fs.readdirSync(source).filter(file => - fs.statSync(path.join(source, file)).isDirectory()); - }, - fsExistsSync(filePath) { - try { - fs.statSync(filePath); - return true; - } catch (err) { - // file/directory does not exist - return false; - } - } -}; -