diff --git a/packages/babel-settings/babel.config.js b/packages/babel-settings/babel.config.js index 8d0511142..aa752dce9 100644 --- a/packages/babel-settings/babel.config.js +++ b/packages/babel-settings/babel.config.js @@ -31,25 +31,12 @@ function normalizePresetEnvOptions({ }; } -function checkGulp(caller) { - return !!(caller && caller.name === 'babel-gulp'); -} - module.exports = function baseBabelConfig( api, { presetEnvOptions = {}, sourceType = 'module' } = {}, ) { - const isGulp = api.caller(checkGulp); + api.cache(true); const newPlugins = [...plugins]; - if (isGulp) { - // use `babel-plugin-direct-import` to import juno directly at widget lib release - newPlugins.push([ - 'babel-plugin-direct-import', - { - modules: ['@ringcentral/juno', '@ringcentral/juno/icon'], - }, - ]); - } return { presets: [ ['@babel/preset-env', normalizePresetEnvOptions(presetEnvOptions)], diff --git a/packages/babel-settings/package.json b/packages/babel-settings/package.json index b5d553f36..d22e695c7 100644 --- a/packages/babel-settings/package.json +++ b/packages/babel-settings/package.json @@ -1,6 +1,6 @@ { "name": "@ringcentral-integration/babel-settings", - "version": "0.0.1", + "version": "0.1.0", "main": "index.js", "description": "RingCentral Integration shared babel settings", "repository": { @@ -26,7 +26,6 @@ "@babel/preset-typescript": "^7.13.0", "@babel/register": "^7.10.5", "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-direct-import": "^0.9.2", "core-js": "^2.6.11", "typescript": "^4.5.4" }, diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 632c4a91a..6a7ff0fc9 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@ringcentral-integration/i18n", - "version": "2.0.1", + "version": "2.1.1", "description": "A simple I18n implementation used in RingCentral Integration projects.", "main": "index.js", "repository": { diff --git a/packages/ringcentral-integration/package.json b/packages/ringcentral-integration/package.json index 427ebc245..81a970dbc 100644 --- a/packages/ringcentral-integration/package.json +++ b/packages/ringcentral-integration/package.json @@ -95,7 +95,7 @@ }, "peerDependencies": { "@ringcentral-integration/core": "^0.13.0", - "@ringcentral-integration/i18n": "^2.0.1", + "@ringcentral-integration/i18n": "^2.1.1", "@ringcentral-integration/phone-number": "^1.0.4", "@ringcentral/juno": "^1.12.6-beta.5910-6eeb3bdd", "@ringcentral/sdk": "^4.6.0", diff --git a/packages/ringcentral-widgets-cli/templates/Project/package-template.json b/packages/ringcentral-widgets-cli/templates/Project/package-template.json index 65e91c6d3..def222931 100644 --- a/packages/ringcentral-widgets-cli/templates/Project/package-template.json +++ b/packages/ringcentral-widgets-cli/templates/Project/package-template.json @@ -6,43 +6,68 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 0", "start": "npm run dev-server", - "dev-server": "webpack-dev-server --config webpack-dev-server.config.js --progress --colors --inline", - "build": "NODE_ENV=production webpack --config webpack-production.config.js --progress --colors" + "dev-server": "webpack serve --config webpack-dev-server.config.js", + "build": "NODE_ENV=production webpack --config webpack-production.config.js" }, "devDependencies": { - "@ringcentral-integration/babel-settings": "^0.0.1", + "@ringcentral-integration/babel-settings": "^0.1.0", "@ringcentral-integration/locale-loader": "^2.0.0", "@types/classnames": "^2.2.7", "@types/react-dom": "^17.0.11", "@types/react-redux": "^7.0.9", "@types/react-router": "^5.1.2", "autoprefixer": "^9.6.1", + "assert": "^2.0.0", "babel-loader": "^8.2.2", + "browserify": "^14.4.0", + "browserify-zlib": "^0.2.0", + "buffer": "^6.0.3", "copy-webpack-plugin": "^9.0.1", "css-loader": "^2.1.1", + "crypto-browserify": "^3.12.0", + "console-browserify": "^1.2.0", + "constants-browserify": "^1.0.0", "dotenv": "^6.2.0", + "domain-browser": "^4.22.0", + "events": "^3.3.0", "file-loader": "^6.2.0", - "sass": "^1.43.4", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.1", "postcss-loader": "^3.0.0", + "process": "^0.11.10", + "punycode": "^2.1.1", + "querystring-es3": "^0.2.1", "react-svg-loader": "^3.0.3", + "sass": "^1.43.4", "sass-loader": "^7.1.0", "style-loader": "^0.23.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", + "string_decoder": "^1.3.0", + "string-replace-loader": "^3.0.3", + "timers-browserify": "^2.0.12", + "tty-browserify": "^0.0.1", "url-loader": "^4.1.1", + "url": "^0.11.0", + "util": "^0.12.4", + "vm-browserify": "1.1.2", "webpack": "^5.58.1", "webpack-cli": "^4.9.0", "webpack-dev-server": "^4.3.1" }, "dependencies": { "@rc-ex/core": "^0.10.5", - "@ringcentral-integration/commons": "^0.13.0", - "@ringcentral-integration/core": "^0.13.0", - "@ringcentral-integration/i18n": "^2.0.1", + "@ringcentral-integration/commons": "^0.13.3", + "@ringcentral-integration/core": "^0.13.3", + "@ringcentral-integration/i18n": "^2.1.1", "@ringcentral-integration/phone-number": "^1.0.2", + "@ringcentral-integration/widgets": "^0.13.3", "@ringcentral/juno": "^1.12.6-beta.5910-6eeb3bdd", "@ringcentral/sdk": "^4.5.0", "@ringcentral/subscriptions": "^4.5.0", "classnames": "^2.2.5", - "format-message": "^5.1.2", + "format-message": "^6.2.3", "isomorphic-fetch": "^2.2.1", "normalize-css": "^2.3.1", "prop-types": "^15.7.2", @@ -54,7 +79,6 @@ "react-router-redux": "^4.0.7", "redux": "^4.0.4", "ringcentral-client": "^1.0.0-beta.2", - "@ringcentral-integration/widgets": "^0.13.0", "styled-components": "^5.3.3" } } diff --git a/packages/ringcentral-widgets-cli/templates/Project/src/containers/App/index.js b/packages/ringcentral-widgets-cli/templates/Project/src/containers/App/index.js index 4c8a73b21..6d8004999 100644 --- a/packages/ringcentral-widgets-cli/templates/Project/src/containers/App/index.js +++ b/packages/ringcentral-widgets-cli/templates/Project/src/containers/App/index.js @@ -3,8 +3,7 @@ import PropTypes from 'prop-types'; import { Provider } from 'react-redux'; import { Router, Route } from 'react-router'; -import PhoneProvider from '@ringcentral-integration/widgets/lib/PhoneProvider'; - +import { PhoneProvider } from '@ringcentral-integration/widgets/lib/phoneContext'; import { RegionSettingsPage } from '@ringcentral-integration/widgets/containers/RegionSettingsPage'; import SettingsPage from '@ringcentral-integration/widgets/containers/SettingsPage'; diff --git a/packages/ringcentral-widgets-cli/templates/Project/src/modules/Phone/index.js b/packages/ringcentral-widgets-cli/templates/Project/src/modules/Phone/index.js index 1e6d32fa7..bce1c55a6 100644 --- a/packages/ringcentral-widgets-cli/templates/Project/src/modules/Phone/index.js +++ b/packages/ringcentral-widgets-cli/templates/Project/src/modules/Phone/index.js @@ -7,30 +7,30 @@ import { LocalForageStorage } from '@ringcentral-integration/commons/lib/LocalFo import { Alert } from '@ringcentral-integration/commons/modules/Alert'; import { AlertUI } from '@ringcentral-integration/widgets/modules/AlertUI'; -import AccountInfo from '@ringcentral-integration/commons/modules/AccountInfo'; +import { AccountInfo } from '@ringcentral-integration/commons/modules/AccountInfoV2'; import { AppFeatures } from '@ringcentral-integration/commons/modules/AppFeatures'; -import Auth from '@ringcentral-integration/commons/modules/Auth'; +import { Auth } from '@ringcentral-integration/commons/modules/AuthV2'; import { Brand } from '@ringcentral-integration/commons/modules/Brand'; -import ConnectivityMonitor from '@ringcentral-integration/commons/modules/ConnectivityMonitor'; -import DateTimeFormat from '@ringcentral-integration/commons/modules/DateTimeFormat'; +import { ConnectivityMonitor } from '@ringcentral-integration/commons/modules/ConnectivityMonitorV2'; +import { DateTimeFormat } from '@ringcentral-integration/commons/modules/DateTimeFormatV2'; import { DataFetcherV2 } from '@ringcentral-integration/commons/modules/DataFetcherV2'; -import DialingPlan from '@ringcentral-integration/commons/modules/DialingPlan'; -import Environment from '@ringcentral-integration/commons/modules/Environment'; +import { DialingPlan } from '@ringcentral-integration/commons/modules/DialingPlanV2'; +import { Environment } from '@ringcentral-integration/commons/modules/EnvironmentV2'; import { ExtensionFeatures } from '@ringcentral-integration/commons/modules/ExtensionFeatures'; -import ExtensionInfo from '@ringcentral-integration/commons/modules/ExtensionInfo'; -import GlobalStorage from '@ringcentral-integration/commons/modules/GlobalStorage'; +import { ExtensionInfo } from '@ringcentral-integration/commons/modules/ExtensionInfoV2'; +import { GlobalStorage } from '@ringcentral-integration/commons/modules/GlobalStorageV2'; import { Locale } from '@ringcentral-integration/commons/modules/Locale'; -import RateLimiter from '@ringcentral-integration/commons/modules/RateLimiter'; +import { RateLimiter } from '@ringcentral-integration/commons/modules/RateLimiterV2'; import { RegionSettings } from '@ringcentral-integration/commons/modules/RegionSettings'; -import Storage from '@ringcentral-integration/commons/modules/Storage'; +import { Storage } from '@ringcentral-integration/commons/modules/StorageV2'; import { SleepDetector } from '@ringcentral-integration/commons/modules/SleepDetectorV2'; -import Subscription from '@ringcentral-integration/commons/modules/Subscription'; +import { Subscription } from '@ringcentral-integration/commons/modules/SubscriptionV2'; import { ConnectivityBadgeUI } from '@ringcentral-integration/widgets/modules/ConnectivityBadgeUI'; import { ConnectivityManager } from '@ringcentral-integration/widgets/modules/ConnectivityManager'; import { LoginUI } from '@ringcentral-integration/widgets/modules/LoginUI'; import { OAuth } from '@ringcentral-integration/widgets/modules/OAuth'; import { RegionSettingsUI } from '@ringcentral-integration/widgets/modules/RegionSettingsUI'; -import RouterInteraction from '@ringcentral-integration/widgets/modules/RouterInteraction'; +import { RouterInteraction } from '@ringcentral-integration/widgets/modules/RouterInteraction'; import { SettingsUI } from '@ringcentral-integration/widgets/modules/SettingsUI'; // user Dependency Injection with decorator to create a phone class diff --git a/packages/ringcentral-widgets-cli/templates/Project/webpack-dev-server.config.js b/packages/ringcentral-widgets-cli/templates/Project/webpack-dev-server.config.js index 732a53dba..759602ce7 100644 --- a/packages/ringcentral-widgets-cli/templates/Project/webpack-dev-server.config.js +++ b/packages/ringcentral-widgets-cli/templates/Project/webpack-dev-server.config.js @@ -24,9 +24,8 @@ const config = { redirect: './src/redirect.js', }, devServer: { - contentBase: buildPath, + static: buildPath, hot: true, - inline: true, port: 8080, }, devtool: 'eval-source-map', @@ -34,9 +33,48 @@ const config = { path: buildPath, filename: '[name].js', }, + resolve: { + // webpack < 5 used to include polyfills for node.js core modules by default. + // This is no longer the case. Verify if you need this module and configure a polyfill for it. + // + // more doc: https://webpack.js.org/configuration/resolve/#resolvefallback + // + fallback: { + crypto: require.resolve('crypto-browserify'), + stream: require.resolve('stream-browserify'), + vm: require.resolve('vm-browserify'), + timers: require.resolve('timers-browserify'), + process: require.resolve('process/browser'), + assert: require.resolve('assert'), + buffer: require.resolve('buffer'), + console: require.resolve('console-browserify'), + constants: require.resolve('constants-browserify'), + domain: require.resolve('domain-browser'), + events: require.resolve('events'), + http: require.resolve('stream-http'), + https: require.resolve('https-browserify'), + os: require.resolve('os-browserify/browser'), + path: require.resolve('path-browserify'), + punycode: require.resolve('punycode'), + querystring: require.resolve('querystring-es3'), + string_decoder: require.resolve('string_decoder'), + sys: require.resolve('util'), + tty: require.resolve('tty-browserify'), + url: require.resolve('url'), + util: require.resolve('util'), + zlib: require.resolve('browserify-zlib'), + }, + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, plugins: [ new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin(), + new webpack.ProvidePlugin({ + process: 'process/browser.js', + Buffer: ['buffer', 'Buffer'], + setImmediate: ['setimmediate', 'setImmedate'], + clearImmediate: ['setimmediate', 'clearImmedate'], + }), new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify('development'), @@ -83,14 +121,21 @@ const config = { }, { test: /\.woff|\.woff2|.eot|\.ttf/, - use: - 'url-loader?limit=15000&publicPath=./&name=fonts/[name]_[hash].[ext]', + use: { + loader: 'url-loader', + options: { + limit: 15000, + name: 'fonts/[name]_[hash].[ext]', + // TODO: it should be upgrade css-loader and update config + esModule: false, + }, + }, }, { test: /\.png|\.jpg|\.gif|\.svg/, - exclude: /@ringcentral-integration(\/|\\)widgets(\/|\\)assets(\/|\\)images(\/|\\).+\.svg/, - use: - 'url-loader?limit=20000&publicPath=./&name=images/[name]_[hash].[ext]', + exclude: + /@ringcentral-integration(\/|\\)widgets(\/|\\)assets(\/|\\)images(\/|\\).+\.svg/, + use: 'url-loader?limit=20000&publicPath=./&name=images/[name]_[hash].[ext]', }, { test: /\.sass|\.scss/, diff --git a/packages/ringcentral-widgets-cli/templates/Project/webpack-production.config.js b/packages/ringcentral-widgets-cli/templates/Project/webpack-production.config.js index 0c8f9d9c0..b229aa42b 100644 --- a/packages/ringcentral-widgets-cli/templates/Project/webpack-production.config.js +++ b/packages/ringcentral-widgets-cli/templates/Project/webpack-production.config.js @@ -28,7 +28,46 @@ const config = { path: buildPath, filename: '[name].js', }, + resolve: { + // webpack < 5 used to include polyfills for node.js core modules by default. + // This is no longer the case. Verify if you need this module and configure a polyfill for it. + // + // more doc: https://webpack.js.org/configuration/resolve/#resolvefallback + // + fallback: { + crypto: require.resolve('crypto-browserify'), + stream: require.resolve('stream-browserify'), + vm: require.resolve('vm-browserify'), + timers: require.resolve('timers-browserify'), + process: require.resolve('process/browser'), + assert: require.resolve('assert'), + buffer: require.resolve('buffer'), + console: require.resolve('console-browserify'), + constants: require.resolve('constants-browserify'), + domain: require.resolve('domain-browser'), + events: require.resolve('events'), + http: require.resolve('stream-http'), + https: require.resolve('https-browserify'), + os: require.resolve('os-browserify/browser'), + path: require.resolve('path-browserify'), + punycode: require.resolve('punycode'), + querystring: require.resolve('querystring-es3'), + string_decoder: require.resolve('string_decoder'), + sys: require.resolve('util'), + tty: require.resolve('tty-browserify'), + url: require.resolve('url'), + util: require.resolve('util'), + zlib: require.resolve('browserify-zlib'), + }, + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, plugins: [ + new webpack.ProvidePlugin({ + process: 'process/browser.js', + Buffer: ['buffer', 'Buffer'], + setImmediate: ['setimmediate', 'setImmedate'], + clearImmediate: ['setimmediate', 'clearImmedate'], + }), new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify('production'), @@ -81,18 +120,24 @@ const config = { }, { test: /\.woff|\.woff2|.eot|\.ttf/, - use: 'url-loader?limit=15000&publicPath=./&name=fonts/[name]_[hash].[ext]', + // use: + // 'url-loader?limit=15000&publicPath=./&name=fonts/[name]_[hash].[ext]', + use: { + loader: 'url-loader', + options: { + limit: 15000, + name: 'fonts/[name]_[hash].[ext]', + // TODO: it should be upgrade css-loader and update config + esModule: false, + }, + }, }, { test: /\.png|\.jpg|\.gif|\.svg/, exclude: - /ringcentral-integration(\/|\\)widgets(\/|\\)assets(\/|\\)images(\/|\\).+\.svg/, + /@ringcentral-integration(\/|\\)widgets(\/|\\)assets(\/|\\)images(\/|\\).+\.svg/, use: 'url-loader?limit=20000&publicPath=./&name=images/[name]_[hash].[ext]', }, - { - test: /\.ogg$/, - use: 'file-loader?publicPath=./&name=audio/[name]_[hash].[ext]', - }, { test: /\.sass|\.scss/, use: [ @@ -121,6 +166,10 @@ const config = { }, ], }, + { + test: /\.ogg$/, + use: 'file-loader?publicPath=./&name=audio/[name]_[hash].[ext]', + }, ], }, }; diff --git a/yarn.lock b/yarn.lock index 7c3496184..cf3bbe8d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3183,13 +3183,6 @@ babel-plugin-const-enum@^1.0.1: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-typescript" "^7.3.3" -babel-plugin-direct-import@^0.9.2: - version "0.9.2" - resolved "https://registry.yarnpkg.com/babel-plugin-direct-import/-/babel-plugin-direct-import-0.9.2.tgz#108e086b12e76dcc30ca2a628a6f3dd1a9caa943" - integrity sha512-1Y3vul4+L54QJLZ3bg9sHCI7lMjBW6Hkra1JWhVdGWZ7dIPDrICYvdM0KFYyQEg7Au0xip3fbsi/p9aMgbbebA== - dependencies: - resolve "^1.20.0" - babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" @@ -9209,9 +9202,9 @@ loader-utils@^0.2.16: object-assign "^4.0.1" loader-utils@^1.0.1, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== + version "1.4.1" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.1.tgz#278ad7006660bccc4d2c0c1578e17c5c78d5c0e0" + integrity sha512-1Qo97Y2oKaU+Ro2xnDMR26g1BwMT29jNbem1EvcujW2jqt+j5COXyscjM7bLQkM9HaxI7pkWeW7gnI072yMI9Q== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" @@ -9686,16 +9679,16 @@ module-deps@^4.0.8: xtend "^4.0.0" moment-timezone@^0.5.27: - version "0.5.31" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.31.tgz#9c40d8c5026f0c7ab46eda3d63e49c155148de05" - integrity sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA== + version "0.5.35" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.35.tgz#6fa2631bdbe8ff04f6b8753f7199516be6dc9839" + integrity sha512-cY/pBOEXepQvlgli06ttCTKcIf8cD1nmNwOKQQAdHBqYApQSpAqotBMX0RJZNgMp6i0PlZuf1mFtnlyEkwyvFw== dependencies: moment ">= 2.9.0" "moment@>= 2.9.0", moment@^2.24.0: - version "2.26.0" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.26.0.tgz#5e1f82c6bafca6e83e808b30c8705eed0dcbd39a" - integrity sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw== + version "2.29.4" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== moo@^0.5.0: version "0.5.1" @@ -12273,9 +12266,9 @@ shebang-regex@^3.0.0: integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shell-quote@^1.6.1: - version "1.7.2" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" - integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== + version "1.7.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" + integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== side-channel@^1.0.2, side-channel@^1.0.4: version "1.0.4" @@ -13711,9 +13704,9 @@ url-loader@^4.1.1: schema-utils "^3.0.0" url-parse@^1.2.0, url-parse@^1.4.4: - version "1.5.3" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.3.tgz#71c1303d38fb6639ade183c2992c8cc0686df862" - integrity sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ== + version "1.5.9" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.9.tgz#05ff26484a0b5e4040ac64dcee4177223d74675e" + integrity sha512-HpOvhKBvre8wYez+QhHcYiVvVmeF6DVnuSOOPhe3cTum3BnqHhvKaZm8FU5yTiOu/Jut2ZpB2rA/SbBA1JIGlQ== dependencies: querystringify "^2.1.1" requires-port "^1.0.0"