diff --git a/.editorconfig b/.editorconfig index 540caa2..119ab31 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,7 +13,7 @@ tab_width = 4 trim_trailing_whitespace = true ij_continuation_indent_size = 4 -[{*.cjs,*.js,*.ts,*.jsx,*.tsx}] +[{*.cjs,*.js,*.mjs,*.ts,*.jsx,*.tsx}] max_line_length = 240 ij_continuation_indent_size = 4 ij_javascript_align_imports = false @@ -34,7 +34,7 @@ ij_javascript_array_initializer_wrap = off ij_javascript_assignment_wrap = off ij_javascript_binary_operation_sign_on_next_line = false ij_javascript_binary_operation_wrap = off -ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/** +ij_javascript_blacklist_imports = rxjs/Rx, node_modules/**, **/node_modules/**, @angular/material, @angular/material/typings/** ij_javascript_blank_lines_after_imports = 1 ij_javascript_blank_lines_around_class = 1 ij_javascript_blank_lines_around_field = 0 @@ -153,7 +153,7 @@ ij_javascript_spaces_within_brackets = false ij_javascript_spaces_within_catch_parentheses = false ij_javascript_spaces_within_for_parentheses = false ij_javascript_spaces_within_if_parentheses = false -ij_javascript_spaces_within_imports = false +ij_javascript_spaces_within_imports = true ij_javascript_spaces_within_interpolation_expressions = false ij_javascript_spaces_within_method_call_parentheses = false ij_javascript_spaces_within_method_parentheses = false diff --git a/babel.config.json b/babel.config.json index 56fd7ab..b8fe5fb 100644 --- a/babel.config.json +++ b/babel.config.json @@ -21,6 +21,16 @@ "@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript" + ], + "plugins": [ + [ + "babel-plugin-replace-import-extension", + { + "extMapping": { + ".js": ".cjs" + } + } + ] ] }, "test": { diff --git a/package-lock.json b/package-lock.json index 42df396..63fa7a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "devDependencies": { "babel-plugin-named-asset-import": "^0.3.8", + "babel-plugin-replace-import-extension": "^1.1.4", "cross-env": "^6.0.3", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-react-hooks": "^4.3.0", @@ -8055,6 +8056,13 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/babel-plugin-replace-import-extension": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/babel-plugin-replace-import-extension/-/babel-plugin-replace-import-extension-1.1.4.tgz", + "integrity": "sha512-UJi5YV31JxoaHHxhytRhQqOQN3+ZsaoXVia7e58yc35pe4tNjNr7BdznnDvIPbEG/4u5kf+lLDk9peaxsOPxGw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/babel-preset-current-node-syntax": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", diff --git a/package.json b/package.json index 348fa66..cac1678 100644 --- a/package.json +++ b/package.json @@ -7,22 +7,22 @@ "scripts": { "start": "npm run clean-dist && npm run serve -- demo", "docs": "npm run serve -- docs", - "serve": "cross-env NODE_ENV=development node packerConfig.js --serve", + "serve": "cross-env NODE_ENV=development node packerConfig.mjs --serve", "prebuild": "npm run clean-dist && npm run static-gen", "build_": "npm run build-all && npm run dtsgen", "build": "npm run build-babel && npm run dtsgen && npm run build-webpack", - "build-all": "cross-env NODE_ENV=production CI=true node packerConfig.js --build --babel --webpack", - "build-babel": "cross-env NODE_ENV=production CI=true node packerConfig.js --build --babel", - "build-webpack": "cross-env NODE_ENV=production CI=true node packerConfig.js --build --webpack", + "build-all": "cross-env NODE_ENV=production CI=true node packerConfig.mjs --build --babel --webpack", + "build-babel": "cross-env NODE_ENV=production CI=true node packerConfig.mjs --build --babel", + "build-webpack": "cross-env NODE_ENV=production CI=true node packerConfig.mjs --build --webpack", "static-gen": "npm run sitemaps && npm run doc-gen && npm run page-index", "sitemaps": "lerna run sitemap", "doc-gen": "lerna run doc-gen", "page-index": "lerna run page-index", "dtsgen": "lerna run dtsgen", "tscheck": "lerna run tscheck", - "profile": "cross-env NODE_OPTIONS='--max-old-space-size=4096' NODE_ENV=production node packerConfig.js --build --profile", + "profile": "cross-env NODE_OPTIONS='--max-old-space-size=4096' NODE_ENV=production node packerConfig.mjs --build --profile", "clean": "npm run clean-dist && lerna clean -y", - "clean-dist": "node packerConfig.js --clean", + "clean-dist": "node packerConfig.mjs --clean", "clean-lock": "rimraf --glob packages/*/package-lock.json", "bootstrap": "lerna bootstrap --force-local", "link": "lerna link --force-local", @@ -38,6 +38,7 @@ "license": "MIT", "devDependencies": { "babel-plugin-named-asset-import": "^0.3.8", + "babel-plugin-replace-import-extension": "^1.1.4", "cross-env": "^6.0.3", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-react-hooks": "^4.3.0", diff --git a/packages/demo/package-lock.json b/packages/demo/package-lock.json index 9835f01..ffcca59 100644 --- a/packages/demo/package-lock.json +++ b/packages/demo/package-lock.json @@ -483,9 +483,9 @@ } }, "node_modules/@codemirror/search": { - "version": "6.5.6", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz", - "integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==", + "version": "6.5.7", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.7.tgz", + "integrity": "sha512-6+iLsXvITWKHYlkgHPCs/qiX4dNzn8N78YfhOFvPtPYCkuXqZq10rAfsUMhOq7O/1VjJqdXRflyExlfVcu/9VQ==", "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", diff --git a/packages/demo/package.json b/packages/demo/package.json index b80c644..5a4628e 100644 --- a/packages/demo/package.json +++ b/packages/demo/package.json @@ -29,8 +29,8 @@ "@codemirror/language": "^6.1.0", "@ui-schema/dictionary": "~0.0.10", "@ui-schema/ds-material": "~0.4.0-alpha.5", - "@ui-schema/kit-codemirror": "~0.1.0", - "@ui-schema/material-code": "~0.4.3", + "@ui-schema/kit-codemirror": "~0.2.0", + "@ui-schema/material-code": "~0.4.5", "@ui-schema/ui-schema": "~0.4.1", "immutable": "^4.0.0", "react": "^18.0", diff --git a/packages/kit-codemirror/package-lock.json b/packages/kit-codemirror/package-lock.json index bc9e8d5..fc54a91 100644 --- a/packages/kit-codemirror/package-lock.json +++ b/packages/kit-codemirror/package-lock.json @@ -1,12 +1,12 @@ { "name": "@ui-schema/kit-codemirror", - "version": "0.1.2", + "version": "0.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@ui-schema/kit-codemirror", - "version": "0.1.2", + "version": "0.2.0", "license": "MIT", "devDependencies": { "@codemirror/state": "^6.0.0", diff --git a/packages/kit-codemirror/package.json b/packages/kit-codemirror/package.json index 5ff33f0..2c9cd05 100644 --- a/packages/kit-codemirror/package.json +++ b/packages/kit-codemirror/package.json @@ -1,6 +1,6 @@ { "name": "@ui-schema/kit-codemirror", - "version": "0.1.2", + "version": "0.2.0", "description": "CodeMirror v6 as React Component, with hooks and stuff - but only the necessities.", "homepage": "https://ui-schema.bemit.codes/docs/kit-codemirror/kit-codemirror", "author": { @@ -28,11 +28,24 @@ "bugs": { "url": "https://github.com/ui-schema/react-codemirror/issues" }, - "main": "./index.js", - "module": "./esm/index.js", + "type": "module", + "main": "./index.cjs", + "module": "./index.js", "types": "./index.d.ts", + "exports": { + ".": { + "types": "./index.d.ts", + "import": "./index.js", + "require": "./index.cjs" + }, + "./*": { + "types": "./*/index.d.ts", + "import": "./*/index.js", + "require": "./*/index.cjs" + } + }, "scripts": { - "dtsgen": "tsc -d --emitDeclarationOnly --pretty && merge-dirs build/dts build && rm -rf build/dts && rm -rf build/**/*.test.*" + "dtsgen": "tsc -d --emitDeclarationOnly --pretty && merge-dirs build/dts/kit-codemirror/src build && rm -rf build/dts && rm -rf build/**/*.test.*" }, "sideEffects": false, "devDependencies": { diff --git a/packages/kit-codemirror/src/CodeMirror/index.ts b/packages/kit-codemirror/src/CodeMirror/index.ts index 1766a2a..87bf1a9 100644 --- a/packages/kit-codemirror/src/CodeMirror/index.ts +++ b/packages/kit-codemirror/src/CodeMirror/index.ts @@ -1 +1 @@ -export * from './CodeMirror' +export * from './CodeMirror.js' diff --git a/packages/kit-codemirror/src/createEditorView/index.ts b/packages/kit-codemirror/src/createEditorView/index.ts index 673e60c..22457ca 100644 --- a/packages/kit-codemirror/src/createEditorView/index.ts +++ b/packages/kit-codemirror/src/createEditorView/index.ts @@ -1 +1 @@ -export * from './createEditorView' +export * from './createEditorView.js' diff --git a/packages/kit-codemirror/src/index.ts b/packages/kit-codemirror/src/index.ts index 0590b63..295a298 100644 --- a/packages/kit-codemirror/src/index.ts +++ b/packages/kit-codemirror/src/index.ts @@ -1,5 +1,5 @@ -export * from './CodeMirror' -export * from './createEditorView' -export * from './useCodeMirror' -export * from './useEditorClasses' -export * from './useExtension' +export * from './CodeMirror/index.js' +export * from './createEditorView/index.js' +export * from './useCodeMirror/index.js' +export * from './useEditorClasses/index.js' +export * from './useExtension/index.js' diff --git a/packages/kit-codemirror/src/useCodeMirror/index.ts b/packages/kit-codemirror/src/useCodeMirror/index.ts index 0575477..bb2e28a 100644 --- a/packages/kit-codemirror/src/useCodeMirror/index.ts +++ b/packages/kit-codemirror/src/useCodeMirror/index.ts @@ -1 +1 @@ -export * from './useCodeMirror' +export * from './useCodeMirror.js' diff --git a/packages/kit-codemirror/src/useEditorClasses/index.ts b/packages/kit-codemirror/src/useEditorClasses/index.ts index 08500f6..7f80e0a 100644 --- a/packages/kit-codemirror/src/useEditorClasses/index.ts +++ b/packages/kit-codemirror/src/useEditorClasses/index.ts @@ -1 +1 @@ -export * from './useEditorClasses' +export * from './useEditorClasses.js' diff --git a/packages/kit-codemirror/src/useExtension/index.ts b/packages/kit-codemirror/src/useExtension/index.ts index 971f0d0..01a8746 100644 --- a/packages/kit-codemirror/src/useExtension/index.ts +++ b/packages/kit-codemirror/src/useExtension/index.ts @@ -1 +1 @@ -export * from './useExtension' +export * from './useExtension.js' diff --git a/packages/kit-codemirror/tsconfig.json b/packages/kit-codemirror/tsconfig.json index 32c3dd8..d79563b 100644 --- a/packages/kit-codemirror/tsconfig.json +++ b/packages/kit-codemirror/tsconfig.json @@ -4,6 +4,8 @@ "src" ], "compilerOptions": { - "outDir": "build/dts" + "outDir": "build/dts", + "module": "Node16", + "moduleResolution": "Node16" } } diff --git a/packages/material-code/package-lock.json b/packages/material-code/package-lock.json index 3ded535..2740720 100644 --- a/packages/material-code/package-lock.json +++ b/packages/material-code/package-lock.json @@ -28,7 +28,7 @@ "@mui/icons-material": "^5.1", "@mui/material": "^5.1", "@ui-schema/ds-material": "~0.4.0-alpha", - "@ui-schema/kit-codemirror": "~0.1.0-alpha.1", + "@ui-schema/kit-codemirror": "~0.1.0-alpha.1 || ~0.2.0", "@ui-schema/ui-schema": "~0.4.0-alpha", "immutable": "^4.0.0", "react": "^17.0 || ^18.0" @@ -443,9 +443,9 @@ } }, "node_modules/@ui-schema/kit-codemirror": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@ui-schema/kit-codemirror/-/kit-codemirror-0.1.1.tgz", - "integrity": "sha512-Xg/X/+TudlBZIn2L/kfkTLVoCRXpNZpCPqpHddsjQTXfdeMbT/8iieCYgWtSUoWRegx63yWxe++s0S+2rFCXkw==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@ui-schema/kit-codemirror/-/kit-codemirror-0.1.2.tgz", + "integrity": "sha512-ryvwtbT38Mk3x0dl6LTIRoy5AJHfIcuz9oqsC2psjNHzkQcBm2i34/YlvQ+QBgytx30T6B8jla7+k6cD2b5j/w==", "license": "MIT", "peer": true, "peerDependencies": { diff --git a/packages/material-code/package.json b/packages/material-code/package.json index 5abf830..85ba529 100644 --- a/packages/material-code/package.json +++ b/packages/material-code/package.json @@ -51,7 +51,7 @@ "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@codemirror/language": "^6.1.0", - "@ui-schema/kit-codemirror": "~0.1.0-alpha.1", + "@ui-schema/kit-codemirror": "~0.2.0", "@ui-schema/ds-material": "~0.4.0-alpha", "@ui-schema/ui-schema": "~0.4.0-alpha", "immutable": "^4.0.0", @@ -64,7 +64,7 @@ "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@codemirror/language": "^6.1.0", - "@ui-schema/kit-codemirror": "~0.1.0-alpha.1", + "@ui-schema/kit-codemirror": "~0.1.0-alpha.1 || ~0.2.0", "@ui-schema/ds-material": "~0.4.0-alpha", "@ui-schema/ui-schema": "~0.4.0-alpha", "immutable": "^4.0.0", diff --git a/packages/tsconfig.json b/packages/tsconfig.json index 2a18b4e..0e3d1da 100644 --- a/packages/tsconfig.json +++ b/packages/tsconfig.json @@ -1,30 +1,30 @@ { "compilerOptions": { - "module": "esnext", - "target": "es2015", + "module": "ESNext", + "target": "ES2022", "jsx": "preserve", "removeComments": false, - "moduleResolution": "node", + "moduleResolution": "Bundler", "forceConsistentCasingInFileNames": true, "strict": true, - "noEmit": false, "experimentalDecorators": true, "baseUrl": "./", + "rootDir": "./", "allowSyntheticDefaultImports": true, "noErrorTruncation": true, - "allowJs": true, + "allowJs": false, "declaration": true, - "resolveJsonModule": true, + "resolveJsonModule": false, "skipLibCheck": true, "noUnusedLocals": true, "noImplicitAny": false, "noUnusedParameters": true, "paths": { "@ui-schema/kit-codemirror": [ - "kit-codemirror/src" + "kit-codemirror/src/index.ts" ], "@ui-schema/kit-codemirror/*": [ - "kit-codemirror/src/*" + "kit-codemirror/src/*/index.ts" ], "@ui-schema/material-code": [ "material-code/src" diff --git a/packerConfig.js b/packerConfig.js deleted file mode 100644 index 7a1bbed..0000000 --- a/packerConfig.js +++ /dev/null @@ -1,66 +0,0 @@ -const path = require('path'); -const {packer, webpack} = require('lerna-packer'); -const {babelTargetsLegacyCjsFirst} = require('lerna-packer/packer/babelEsModules'); -const {makeModulePackageJson, copyRootPackageJson, transformerForLegacyCjsFirst} = require('lerna-packer/packer/modulePackages'); - -packer({ - apps: { - demo: { - root: path.resolve(__dirname, 'packages', 'demo'), - template: path.resolve(__dirname, 'packages', 'demo/public/index.html'), - contentBase: path.resolve(__dirname, 'packages', 'demo/public'),// dev-server - port: 4203, - main: path.resolve(__dirname, 'packages', 'demo/src/index.tsx'), - dist: path.resolve(__dirname, 'dist', 'demo'), - devServer: { - client: { - overlay: false, - progress: false, - }, - }, - publicPath: '/', - plugins: [ - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'), - }), - ], - aliasPackagesBuild: 'production', - }, - }, - packages: { - // the keys are the commonjs names that is applied to externals - // this is the same as `@babel/plugin-transform-modules-commonjs` applies - kitCode: { - name: '@ui-schema/kit-codemirror', - root: path.resolve(__dirname, 'packages', 'kit-codemirror'), - entry: path.resolve(__dirname, 'packages', 'kit-codemirror/src/'), - babelTargets: babelTargetsLegacyCjsFirst, - }, - materialCode: { - name: '@ui-schema/material-code', - root: path.resolve(__dirname, 'packages', 'material-code'), - entry: path.resolve(__dirname, 'packages', 'material-code/src/'), - babelTargets: babelTargetsLegacyCjsFirst, - }, - }, -}, __dirname, { - afterEsModules: (packages, pathBuild) => { - return Promise.all([ - makeModulePackageJson(transformerForLegacyCjsFirst)(packages, pathBuild), - copyRootPackageJson()(packages, pathBuild), - ]).then(() => undefined) - }, -}) - .then(([execs, elapsed]) => { - if(execs.indexOf('doServe') !== -1) { - console.log('[packer] is now serving (after ' + elapsed + 'ms)') - } else { - console.log('[packer] finished successfully (after ' + elapsed + 'ms)', execs) - process.exit(0) - } - }) - .catch((e) => { - console.error('[packer] finished with error(s)', e) - process.exit(1) - }) - diff --git a/packerConfig.mjs b/packerConfig.mjs new file mode 100644 index 0000000..283cebc --- /dev/null +++ b/packerConfig.mjs @@ -0,0 +1,151 @@ +import path from 'path' +import { packer, webpack } from 'lerna-packer' +import { babelTargetsLegacyCjsFirst } from 'lerna-packer/packer/babelEsModules.js' +import { + makeModulePackageJson, + copyRootPackageJson, + transformerForLegacyCjsFirst +} from 'lerna-packer/packer/modulePackages.js' +import { dirname } from 'node:path' +import { fileURLToPath } from 'node:url' + +const __dirname = dirname(fileURLToPath(import.meta.url)) + +const babelTargetsEsmCjs = [ + { + distSuffix: '', + args: [ + '--env-name', 'cjs', '--no-comments', // '--copy-files', '--no-copy-ignored', + // note: even with defined extension, the extensions of `import` are still `.js` + // which would break relative imports, as they then import ESM instead of the CJS file; + // thus added `babel-plugin-replace-import-extension` for the CJS environment + // it's not validated how it behaves for external imports for third-party modules, + // which can be problematic in other projects, + // here `import` to 3rd party modules are done purely by package name + '--out-file-extension', '.cjs', + '--extensions', '.ts', '--extensions', '.tsx', '--extensions', '.js', '--extensions', '.jsx', + '--ignore', '**/*.d.ts', + '--ignore', '**/*.test.tsx', '--ignore', '**/*.test.ts', '--ignore', '**/*.test.js', + ], + }, + { + distSuffix: '', + args: [ + '--no-comments', + '--extensions', '.ts', '--extensions', '.tsx', '--extensions', '.js', '--extensions', '.jsx', + '--ignore', '**/*.d.ts', + '--ignore', '**/*.test.tsx', '--ignore', '**/*.test.ts', '--ignore', '**/*.test.js', + ], + }, +] + +/** + * @todo this shouldn't be needed, or not working or used by TS/node at all, + * added for fallbacks for the moment, + * it seems for `cjs` fallbacks, `main` can still be used if using `.cjs` extension (like in @codemirror/view), + * while the Node.js spec says "`main` can be used as fallback with `type: module`, it will be interpreted as esm (with .js extension)", + * - `main` is used for "directory" imports/require, thus wanted to keep it for such legacy projects + * - as Node.js with ESM support would use the `exports`, it should be better to go the "main as .cjs" way + * - as Node.js with ESM support would use the `exports` in the root directory, the `exports` below will never have any effect when importing the package, + * yet it may be used in the built bundle and relative imports inside of it, + * which only was observed with jest and ESM, + * as `export * from './useExtension/index.js';` in `/index.js` does not follow the `exports` defined in the nested `package.json`, + * it should fail if Node.js really uses these nested `package.json`, yet it works correctly, + * without `exports` all files are available for imports + * - the same `main`/`module` pattern is used in the `package.json` of `kit-codemirror` + */ +const transformerForEsmCjs = () => { + return { + sideEffects: false, + type: 'module', + main: './index.cjs', + module: './index.js', + /*exports: { + types: './index.d.ts', + import: './index.js', + require: './index.cjs', + },*/ + // this should be enough or even better, to force ESM instead of CJS fallbacks: + /* + sideEffects: false, + type: 'module', + main: './index.js', + types: './index.d.ts' + */ + } +} + +packer({ + apps: { + demo: { + root: path.resolve(__dirname, 'packages', 'demo'), + template: path.resolve(__dirname, 'packages', 'demo/public/index.html'), + contentBase: path.resolve(__dirname, 'packages', 'demo/public'),// dev-server + port: 4203, + main: path.resolve(__dirname, 'packages', 'demo/src/index.tsx'), + dist: path.resolve(__dirname, 'dist', 'demo'), + devServer: { + client: { + overlay: false, + progress: false, + }, + }, + publicPath: '/', + plugins: [ + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'), + }), + ], + aliasPackagesBuild: 'production', + }, + }, + packages: { + // the keys are the commonjs names that is applied to externals + // this is the same as `@babel/plugin-transform-modules-commonjs` applies + kitCode: { + name: '@ui-schema/kit-codemirror', + root: path.resolve(__dirname, 'packages', 'kit-codemirror'), + entry: path.resolve(__dirname, 'packages', 'kit-codemirror/src/'), + babelTargets: babelTargetsEsmCjs, + }, + materialCode: { + name: '@ui-schema/material-code', + root: path.resolve(__dirname, 'packages', 'material-code'), + entry: path.resolve(__dirname, 'packages', 'material-code/src/'), + babelTargets: babelTargetsLegacyCjsFirst, + }, + }, +}, __dirname, { + webpackStatsConfig: { + modulesSpace: 200, + orphanModules: true, + exclude: [ + '@lezer', + '@codemirror', + '@babel', + '@emotion', + ], + }, + afterEsModules: (packages, pathBuild) => { + const legacyCjsEsm = {materialCode: packages.materialCode} + const strictEsmCjs = {kitCode: packages.kitCode} + return Promise.all([ + makeModulePackageJson(transformerForLegacyCjsFirst)(legacyCjsEsm, pathBuild), + makeModulePackageJson(transformerForEsmCjs)(strictEsmCjs, pathBuild), + copyRootPackageJson()(packages, pathBuild), + ]).then(() => undefined) + }, +}) + .then(([execs, elapsed]) => { + if(execs.indexOf('doServe') !== -1) { + console.log('[packer] is now serving (after ' + elapsed + 'ms)') + } else { + console.log('[packer] finished successfully (after ' + elapsed + 'ms)', execs) + process.exit(0) + } + }) + .catch((e) => { + console.error('[packer] finished with error(s)', e) + process.exit(1) + }) +