From 164ebe31306fb76f013734f15f8e1cc4931db680 Mon Sep 17 00:00:00 2001 From: Taye Adeyemi Date: Thu, 7 Dec 2023 02:43:04 +0100 Subject: [PATCH] fix: improve build; check output for ES2018 compatibility Close #1024 # Conflicts: # packages/@interactjs/dev-tools/visualizer/plugin.ts # packages/@interactjs/multi-target/plugin.ts --- .browserslistrc | 6 +- babel.config.js | 13 +- bin/_bundle_shims | 2 - bundle.rollup.config.cjs | 90 +++++++++ esnext.rollup.config.cjs | 165 +++++++++++++++ package.json | 10 +- packages/@interactjs/dev-tools/package.json | 3 +- packages/@interactjs/dev-tools/plugin.ts | 12 -- scripts/bin/bundle_shims.js | 28 --- scripts/bin/release.js | 4 +- scripts/bundleHeader.js | 64 ------ scripts/bundleWriter.js | 74 ------- scripts/bundler.js | 134 ------------- scripts/esnext.js | 210 -------------------- scripts/minify.js | 25 --- scripts/shimBundler.js | 28 --- scripts/utils.js | 9 +- types.tsconfig.json | 13 +- yarn.lock | 81 ++------ 19 files changed, 304 insertions(+), 667 deletions(-) delete mode 100755 bin/_bundle_shims create mode 100644 bundle.rollup.config.cjs create mode 100644 esnext.rollup.config.cjs delete mode 100644 scripts/bin/bundle_shims.js delete mode 100644 scripts/bundleHeader.js delete mode 100644 scripts/bundleWriter.js delete mode 100644 scripts/bundler.js delete mode 100644 scripts/esnext.js delete mode 100644 scripts/minify.js delete mode 100644 scripts/shimBundler.js diff --git a/.browserslistrc b/.browserslistrc index 4fe5cde28..f13183ef8 100644 --- a/.browserslistrc +++ b/.browserslistrc @@ -1,4 +1,2 @@ -maintained node versions -last 5 versions -> 2% -not dead +defaults and fully supports es6-module +node >= 16 \ No newline at end of file diff --git a/babel.config.js b/babel.config.js index 4e7589ee2..15bb96337 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,15 +1,13 @@ const isProd = process.env.NODE_ENV === 'production' module.exports = { - targets: { ie: 9 }, - browserslistConfigFile: false, presets: [ [require.resolve('@babel/preset-env'), { exclude: ['transform-regenerator'] }], [ require.resolve('@babel/preset-typescript'), - { isTSX: false, onlyRemoveTypeImports: true, allExtensions: true, allowDeclareFields: true }, + { isTsx: false, onlyRemoveTypeImports: true, allExtensions: true, allowDeclareFields: true }, ], - ], + ].filter(Boolean), plugins: [ require.resolve('./scripts/babel/vue-sfc'), @@ -20,8 +18,9 @@ module.exports = { regenerator: false, }, ], - isProd && require.resolve('@babel/plugin-transform-optional-catch-binding'), - isProd && [require.resolve('@babel/plugin-transform-optional-chaining'), { loose: true }], - isProd && [require.resolve('@babel/plugin-transform-nullish-coalescing-operator'), { loose: true }], + isProd && require.resolve('./scripts/babel/for-of-array'), + isProd && require.resolve('@babel/plugin-proposal-optional-catch-binding'), + isProd && [require.resolve('@babel/plugin-proposal-optional-chaining'), { loose: true }], + [require.resolve('@babel/plugin-transform-modules-commonjs'), { noInterop: isProd }], ].filter(Boolean), } diff --git a/bin/_bundle_shims b/bin/_bundle_shims deleted file mode 100755 index cc4c512f8..000000000 --- a/bin/_bundle_shims +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env node -require('../scripts/bin/bundle_shims') diff --git a/bundle.rollup.config.cjs b/bundle.rollup.config.cjs new file mode 100644 index 000000000..b5342c743 --- /dev/null +++ b/bundle.rollup.config.cjs @@ -0,0 +1,90 @@ +/* eslint-disable import/no-extraneous-dependencies */ +const { resolve } = require('path') + +const babel = require('@rollup/plugin-babel') +const commonjs = require('@rollup/plugin-commonjs') +const nodeResolve = require('@rollup/plugin-node-resolve') +const replace = require('@rollup/plugin-replace') +const terser = require('@rollup/plugin-terser') +const { defineConfig } = require('rollup') + +const headers = require('./scripts/headers') +const { extendBabelOptions, getModuleDirectories, isPro } = require('./scripts/utils') + +const globals = { + react: 'React', + vue: 'Vue', +} +const external = Object.keys(globals) +const INPUT_EXTENSIONS = ['.ts', '.tsx', '.vue'] + +module.exports = defineConfig(async () => { + const variations = [ + { env: { NODE_ENV: 'development' }, ext: '.js', minify: isPro }, + { env: { NODE_ENV: 'production' }, ext: '.min.js', minify: true }, + ] + + return variations.map(({ minify, ext, env }) => { + const babelConfig = extendBabelOptions({ + babelrc: false, + configFile: false, + browserslistConfigFile: false, + targets: { ie: 9 }, + babelHelpers: 'bundled', + skipPreflightCheck: true, + extensions: INPUT_EXTENSIONS, + plugins: [[require.resolve('@babel/plugin-transform-runtime'), { helpers: false, regenerator: true }]], + }) + + return defineConfig({ + input: resolve(__dirname, 'packages', 'interactjs', 'index.ts'), + external, + plugins: [ + nodeResolve({ + modulePaths: getModuleDirectories(), + extensions: INPUT_EXTENSIONS, + }), + commonjs({ include: '**/node_modules/{rebound,symbol-tree}/**' }), + babel(babelConfig), + replace({ + preventAssignment: true, + values: Object.entries({ + npm_package_version: process.env.npm_package_version, + IJS_BUNDLE: '1', + ...env, + }).reduce((acc, [key, value]) => { + acc[`process.env.${key}`] = JSON.stringify(value) + return acc + }, {}), + }), + minify && + terser({ + module: false, + mangle: true, + compress: { + ecma: 5, + unsafe: true, + unsafe_Function: true, + unsafe_arrows: false, + unsafe_methods: true, + }, + format: { + preamble: headers?.min, + }, + }), + ], + context: 'window', + moduleContext: 'window', + output: { + file: resolve(__dirname, 'packages', 'interactjs', 'dist', `interact${ext}`), + format: 'umd', + name: 'interact', + banner: minify ? headers.min : headers.raw, + minifyInternalExports: true, + inlineDynamicImports: true, + sourcemap: true, + globals, + }, + }) + }) +}) diff --git a/esnext.rollup.config.cjs b/esnext.rollup.config.cjs new file mode 100644 index 000000000..c1b0198aa --- /dev/null +++ b/esnext.rollup.config.cjs @@ -0,0 +1,165 @@ +/* eslint-disable import/no-extraneous-dependencies */ +const { resolve, basename, dirname, relative, extname } = require('path') +const { promisify } = require('util') + +const { transformAsync } = require('@babel/core') +const babel = require('@rollup/plugin-babel') +const commonjs = require('@rollup/plugin-commonjs') +const nodeResolve = require('@rollup/plugin-node-resolve') +const replace = require('@rollup/plugin-replace') +const terser = require('@rollup/plugin-terser') +const { defineConfig } = require('rollup') +const glob = promisify(require('glob')) + +const headers = require('./scripts/headers') +const { + getPackages, + sourcesIgnoreGlobs, + extendBabelOptions, + getEsnextBabelOptions, + getModuleDirectories, + isPro, +} = require('./scripts/utils') + +const BUNDLED_DEPS = ['rebound', 'symbol-tree'] +const INPUT_EXTENSIONS = ['.ts', '.tsx', '.vue'] +const moduleDirectory = getModuleDirectories() + +module.exports = defineConfig(async () => { + const packageDirs = (await getPackages()).map((dir) => resolve(__dirname, dir)) + return ( + await Promise.all( + packageDirs.map(async (packageDir) => { + const packageName = `${basename(dirname(packageDir))}/${basename(packageDir)}` + + const external = (id_, importer) => { + const id = id_.startsWith('.') ? resolve(dirname(importer), id_) : id_ + + // not external if it's a dependency that's intented to be bundled + if (BUNDLED_DEPS.some((dep) => id === dep || id.includes(`/node_modules/${dep}/`))) return false + + // not external if the id is in the current package dir + if ( + [packageName, packageDir].some( + (prefix) => + id.startsWith(prefix) && (id.length === prefix.length || id.charAt(prefix.length) === '/'), + ) + ) + return false + + return true + } + + const entryFiles = await glob('**/*.{ts,tsx}', { + cwd: packageDir, + ignore: sourcesIgnoreGlobs, + strict: false, + nodir: true, + absolute: true, + }) + const input = Object.fromEntries( + entryFiles.map((file) => [ + relative(packageDir, file.slice(0, file.length - extname(file).length)), + file, + ]), + ) + + return [ + // dev unminified + { env: { NODE_ENV: 'development' }, ext: '.js', minify: isPro }, + // prod minified + { env: { NODE_ENV: 'production' }, ext: '.prod.js', minify: true }, + ].map(({ env, ext, minify }) => + defineConfig({ + external, + input, + plugins: [ + commonjs({ include: '**/node_modules/{rebound,symbol-tree}/**' }), + nodeResolve({ + modulePaths: moduleDirectory, + extensions: INPUT_EXTENSIONS, + }), + babel( + extendBabelOptions( + { + babelrc: false, + configFile: false, + babelHelpers: 'bundled', + skipPreflightCheck: true, + extensions: INPUT_EXTENSIONS, + plugins: [ + [ + require.resolve('@babel/plugin-transform-runtime'), + { helpers: false, regenerator: false }, + ], + ], + }, + getEsnextBabelOptions(), + ), + ), + replace({ + preventAssignment: true, + values: Object.entries({ + npm_package_version: process.env.npm_package_version, + IJS_BUNDLE: '', + ...env, + }).reduce((acc, [key, value]) => { + acc[`process.env.${key}`] = JSON.stringify(value) + return acc + }, {}), + }), + ], + context: 'window', + moduleContext: 'window', + preserveEntrySignatures: 'strict', + output: [ + { + dir: packageDir, + entryFileNames: `[name]${ext}`, + format: 'es', + banner: minify ? headers?.min : headers?.raw, + inlineDynamicImports: false, + sourcemap: true, + plugins: [ + { + name: '@interactjs/_dev:output-transforms', + async renderChunk(code, chunk, outputOptions) { + return await transformAsync(code, { + babelrc: false, + configFile: false, + inputSourceMap: chunk.map, + filename: `${packageDir}/${chunk.fileName}`, + plugins: [ + [ + require.resolve('./scripts/babel/relative-imports'), + { extension: ext, moduleDirectory }, + ], + [require.resolve('@babel/plugin-transform-class-properties'), { loose: true }], + ], + }) + }, + }, + minify && + terser({ + module: false, + mangle: true, + compress: { + ecma: '2019', + unsafe: true, + unsafe_Function: true, + unsafe_arrows: false, + unsafe_methods: true, + }, + format: { + preamble: headers?.min, + }, + }), + ], + }, + ], + }), + ) + }), + ) + ).flat() +}) diff --git a/package.json b/package.json index f87f25efe..c2e030461 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,11 @@ "scripts": { "bootstrap": "yarn install --pure-lockfile --prefer-offline --silent && bin/_link", "start": "_add_plugin_indexes && vite serve", - "build:bundle": "_bundle_shims && NODE_ENV=${NODE_ENV:-production} _bundle", - "build": "yarn docs && yarn bundle && _add_plugin_indexes && _types && _esnext", + "build": "yarn build:docs && yarn build:bundle && _add_plugin_indexes && yarn build:types && yarn build:esnext", "build:docs": "yarn typedoc", - "build:esnext": "_add_plugin_indexes && _esnext", + "build:bundle": "rollup -c bundle.rollup.config.cjs", + "build:types": "_types", + "build:esnext": "_add_plugin_indexes && rollup -c esnext.rollup.config.cjs", "test": "jest", "test:debug": "node --inspect node_modules/.bin/jest --no-cache --runInBand ", "tsc_lint_test": "_add_plugin_indexes && tsc -b -f && _lint && yarn test", @@ -24,11 +25,13 @@ "@babel/plugin-proposal-export-default-from": "^7.17.12", "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", "@babel/plugin-proposal-optional-chaining": "^7.17.12", + "@babel/plugin-transform-class-properties": "^7.23.3", "@babel/plugin-transform-runtime": "^7.18.2", "@babel/preset-env": "^7.18.2", "@babel/preset-typescript": "^7.17.12", "@babel/runtime": "^7.18.3", "@rollup/plugin-babel": "^6.0.4", + "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-replace": "^5.0.5", "@rollup/plugin-terser": "^0.4.4", @@ -88,7 +91,6 @@ "rebound": "^0.1.0", "resolve": "^1.22.0", "rollup": "3", - "rollup-plugin-cjs-es": "^3.0.0", "semver": "^7.3.7", "serve-index": "^1.9.1", "shelljs": "^0.8.5", diff --git a/packages/@interactjs/dev-tools/package.json b/packages/@interactjs/dev-tools/package.json index 01f800a6e..632af3f32 100644 --- a/packages/@interactjs/dev-tools/package.json +++ b/packages/@interactjs/dev-tools/package.json @@ -14,7 +14,8 @@ "@interactjs/utils": "1.10.25" }, "optionalDependencies": { - "@interactjs/interact": "1.10.25" + "@interactjs/interact": "1.10.25", + "vue": "3" }, "devDependencies": { "vue": "next" diff --git a/packages/@interactjs/dev-tools/plugin.ts b/packages/@interactjs/dev-tools/plugin.ts index f2ea12c5f..df20c3587 100644 --- a/packages/@interactjs/dev-tools/plugin.ts +++ b/packages/@interactjs/dev-tools/plugin.ts @@ -9,23 +9,12 @@ import isNonNativeEvent from '@interactjs/utils/isNonNativeEvent' import normalizeListeners from '@interactjs/utils/normalizeListeners' import * as win from '@interactjs/utils/window' -/* eslint-disable import/no-duplicates -- for typescript module augmentations */ -import './visualizer/plugin' -import visualizer from './visualizer/plugin' -/* eslint-enable import/no-duplicates */ - declare module '@interactjs/core/scope' { interface Scope { logger: Logger } } -declare module '@interactjs/core/InteractStatic' { - export interface InteractStatic { - visializer: typeof visualizer - } -} - declare module '@interactjs/core/options' { interface BaseDefaults { devTools?: DevToolsOptions @@ -112,7 +101,6 @@ function install(scope: Scope, { logger }: { logger?: Logger } = {}) { return _onOff.call(this, method, normalizedListeners, options) } - scope.usePlugin(visualizer) } const checks: Check[] = [ diff --git a/scripts/bin/bundle_shims.js b/scripts/bin/bundle_shims.js deleted file mode 100644 index 5f4670c11..000000000 --- a/scripts/bin/bundle_shims.js +++ /dev/null @@ -1,28 +0,0 @@ -const os = require('os') - -const { default: PQueue } = require('p-queue') - -const bundleShim = require('../shimBundler') -const { getShims, errorExit } = require('../utils') - -const queue = new PQueue({ concurrency: os.cpus().length }) - -const shims = getShims() - -if (!shims.length) process.exit() - -for (const shimConfig of shims) { - queue.add(() => bundle(shimConfig).catch(errorExit)) -} - -async function bundle(shimConfig) { - const { source } = shimConfig - - console.log(`Bundling ${source}`) - - await bundleShim({ ...shimConfig }) -} - -queue.onIdle().then((bundled) => { - console.log('Done.') -}) diff --git a/scripts/bin/release.js b/scripts/bin/release.js index a49f9d2c9..ae6f61206 100644 --- a/scripts/bin/release.js +++ b/scripts/bin/release.js @@ -109,7 +109,9 @@ async function runBuild() { shell.exec('npx _types') // generate esnext .js modules - shell.exec('npx _esnext') + shell.exec('rollup -c esnext.rollup.config.cjs') + // ensure that the output is valid ES2018 syntax + shell.exec('acorn --silent --module --ecma2018 packages/**/*.js') // set publishConfig await editPackageJsons((pkg) => { diff --git a/scripts/bundleHeader.js b/scripts/bundleHeader.js deleted file mode 100644 index 413eaba94..000000000 --- a/scripts/bundleHeader.js +++ /dev/null @@ -1,64 +0,0 @@ -const path = require('path') - -const combineSourceMap = require('combine-source-map') - -const { getRelativeToRoot } = require('./utils') - -module.exports = function combine(options) { - const headerContent = options.content || '' - const { destDir, filename } = options - const combiner = combineSourceMap.create() - const combinedCode = headerContent + options.code - const offset = { line: newlinesIn(headerContent) } - - combiner.addFile( - { - sourceFile: '_header.js', - source: headerContent, - }, - { line: 1 }, - ) - - if (options.map) { - combiner._addExistingMap('', combinedCode, options.map, offset) - } else if (headerContent) { - combiner.addFile( - { - sourceFile: '', - source: combinedCode, - }, - offset, - ) - } - - const newMap = combiner.generator.toJSON() - newMap.file = filename - - newMap.sources = newMap.sources.map((source) => { - const absolute = path.join(process.cwd(), source) - try { - const { result } = getRelativeToRoot(absolute, [process.cwd(), path.join(__dirname, '..')], '') - - return result - } catch { - return source - } - }) - - return { - destDir, - filename, - code: `${combineSourceMap.removeComments(combinedCode)}\n//# sourceMappingURL=${filename}.map\n`, - map: newMap, - } -} - -function newlinesIn(src) { - if (!src) { - return 0 - } - - const newlines = src.match(/\n/g) - - return newlines ? newlines.length : 0 -} diff --git a/scripts/bundleWriter.js b/scripts/bundleWriter.js deleted file mode 100644 index f521116ea..000000000 --- a/scripts/bundleWriter.js +++ /dev/null @@ -1,74 +0,0 @@ -const fs = require('fs') -const path = require('path') - -const babel = require('@babel/core') -const mkdirp = require('mkdirp') - -const bundleHeader = require('./bundleHeader') -const minify = require('./minify') - -module.exports = async function bundleWriter( - bundleCode, - { bundleStream, headerFile, minHeaderFile, destDir, name, headers = {}, writeMin = true }, -) { - const filenames = { - raw: `${name}.js`, - rawMap: `${name}.js.map`, - min: `${name}.min.js`, - minMap: `${name}.min.js.map`, - } - - const raw = bundleHeader(getHeaderOpts(headers.raw, filenames.raw, bundleCode)) - const rawWritePromise = write(raw, { NODE_ENV: 'development' }) - - if (!writeMin) return - - const minifiedResult = await minify({ - ...raw, - env: { - NODE_ENV: 'production', - npm_package_version: process.env.npm_package_version, - }, - }) - const headerOpts = getHeaderOpts( - headers.min, - filenames.min, - minifiedResult.code, - JSON.parse(minifiedResult.map), - ) - const min = bundleHeader(headerOpts) - - return Promise.all([rawWritePromise, write(min)]) - - function getHeaderOpts(content, filename, code, map) { - return { - destDir, - filename, - code, - map, - content, - } - } -} - -async function write({ destDir, filename, code, map }, env) { - if (env) { - ;({ code, map } = await babel.transformAsync(code, { - filename, - inputSourceMap: map, - plugins: [[require.resolve('./babel/inline-env-vars'), { env }]], - })) - } - - map.sources = map.sources.map((source) => path.relative(process.cwd(), source)) - map.file = filename - - const codeFilename = path.join(destDir, filename) - - await mkdirp(path.dirname(codeFilename)) - - return Promise.all([ - fs.promises.writeFile(codeFilename, code), - fs.promises.writeFile(`${codeFilename}.map`, JSON.stringify(map)), - ]) -} diff --git a/scripts/bundler.js b/scripts/bundler.js deleted file mode 100644 index 4665391a4..000000000 --- a/scripts/bundler.js +++ /dev/null @@ -1,134 +0,0 @@ -const path = require('path') - -const babel = require('@rollup/plugin-babel') -const nodeResolve = require('@rollup/plugin-node-resolve') -const replace = require('@rollup/plugin-replace') -const terser = require('@rollup/plugin-terser') -const { rollup, defineConfig } = require('rollup') -const cjs = require('rollup-plugin-cjs-es') - -const { getModuleDirectories, extendBabelOptions, errorExit, getEsnextBabelOptions } = require('./utils') - -process.env.NODE_PATH = `${process.env.NODE_PATH || ''}:${path.resolve(__dirname, '..', 'node_modules')}` -require('module').Module._initPaths() - -const dir = path.join(__dirname, '..') - -process.env.NODE_PATH = `${process.env.NODE_PATH || ''}:${dir}/node_modules` -require('module')._initPaths() - -const createRollupConfigs = async ({ - entry, - destDir, - name, - headers, - format = 'umd', - ext: ext_ = '.js', - minOnly = false, -}) => { - const variations = minOnly - ? [{ minify: true, env: { NODE_ENV: 'production' }, ext: ext_ }] - : [ - { minify: false, env: { NODE_ENV: 'development' }, ext: ext_ }, - { minify: true, env: { NODE_ENV: 'production' }, ext: `.min${ext_}` }, - ] - - const globals = { - react: 'React', - vue: 'Vue', - } - const external = Object.keys(globals) - - return variations.map(({ minify, ext, env }) => { - const babelConfig = extendBabelOptions( - { - babelrc: false, - configFile: false, - ...(format === 'es' - ? {} - : { - browserslistConfigFile: false, - targets: { ie: 9 }, - }), - babelHelpers: 'bundled', - skipPreflightCheck: true, - extensions: ['.ts', '.tsx', '.js', '.jsx', '.vue'], - plugins: [ - [ - require.resolve('@babel/plugin-transform-runtime'), - { helpers: false, regenerator: format !== 'es' }, - ], - ], - }, - getEsnextBabelOptions(format === 'es' ? { exclude: ['transform-regenerator'] } : {}), - ) - - return defineConfig({ - input: entry, - external, - plugins: [ - nodeResolve({ - modulePaths: getModuleDirectories(), - extensions: ['.mjs', '.js', '.json', '.node', '.ts', '.tsx', '.jsx', '.vue'], - }), - cjs({ - include: '**/node_modules/{rebound,symbol-tree}/**', - nested: true, - }), - babel(babelConfig), - replace({ - preventAssignment: true, - values: Object.entries({ - npm_package_version: process.env.npm_package_version, - IJS_BUNDLE: '1', - ...env, - }).reduce((acc, [key, value]) => { - acc[`process.env.${key}`] = JSON.stringify(value) - return acc - }, {}), - }), - minify && - terser({ - module: false, - mangle: true, - compress: { - ecma: 5, - unsafe: true, - unsafe_Function: true, - unsafe_arrows: false, - unsafe_methods: true, - }, - format: { - preamble: headers?.min, - }, - }), - ], - context: 'window', - moduleContext: 'window', - output: { - file: path.resolve(destDir, `${name}${ext}`), - format, - name, - banner: minify ? undefined : headers?.raw, - minifyInternalExports: true, - inlineDynamicImports: true, - sourcemap: true, - globals, - }, - }) - }) -} - -module.exports = async function (options) { - try { - const rollupConfigs = await createRollupConfigs(options) - await Promise.all( - rollupConfigs.map(async (config) => { - const bundle = await rollup(config) - return bundle.write(config.output) - }), - ) - } catch (error) { - errorExit(error) - } -} diff --git a/scripts/esnext.js b/scripts/esnext.js deleted file mode 100644 index fe8771b4b..000000000 --- a/scripts/esnext.js +++ /dev/null @@ -1,210 +0,0 @@ -const { createWriteStream, promises: fs } = require('fs') -const os = require('os') -const path = require('path') - -const babel = require('@babel/core') -const mkdirp = require('mkdirp') -const PQueue = require('p-queue').default -const temp = require('temp').track() - -const minify = require('./minify') -const { - getSources, - getEsnextBabelOptions, - extendBabelOptions, - getModuleName, - getModuleDirectories, - getRelativeToRoot, - resolveImport, - isPro, -} = require('./utils') - -const postMinify = async (result) => { - const { code, map, error } = await minify(result) - - if (error) { - throw error - } - - return { - code, - map: JSON.parse(map), - } -} -const OUTPUT_VERSIONS = [ - // development - { - extension: '.js', - nodeEnv: 'development', - post: isPro ? postMinify : null, - }, - // production - { - extension: '.prod.js', - nodeEnv: 'production', - post: postMinify, - }, -] - -const queue = new PQueue({ concurrency: os.cpus().length }) -const packagesDir = path.join(process.cwd(), 'packages') -const sourcePromises = new Map() - -async function generate({ - sources, - shim, - babelOptions = getEsnextBabelOptions(), - moduleDirectory = getModuleDirectories(), - serve = false, - watch = false, - serverOptions, - outDir = serve ? temp.mkdirSync('ijs-serve') : packagesDir, -} = {}) { - sources = serve ? [] : sources || (await getSources()) - sources = sources - .filter((s) => moduleDirectory.some((dir) => s.startsWith(dir))) - .filter((s) => !s.endsWith('.stub.ts')) - moduleDirectory = [outDir, ...moduleDirectory] - - if (watch && !serve && !sources.length) { - // eslint-disable-next-line no-throw-literal - throw 'no files to watch' - } - - if (!serve) { - if (sources.length) { - console.log(`generating javascript files for ${sources.length} modules...`) - } - - return Promise.all(sources.map((s) => queueFile(s, watch))) - .then(() => queue.onIdle()) - .catch((error) => { - console.error(error) - - if (!watch) { - queue.clear() - process.exit(1) - } - }) - } - - const browserSync = require('browser-sync').create() - - browserSync.init({ - port: 8081, - open: false, - server: outDir, - serveStatic: [packagesDir, process.cwd()], - reloadOnRestart: true, - middleware: async ({ url }, _res, next) => { - if (url.startsWith('/@interactjs/') && !url.endsWith('.map')) { - const source = resolveImport(url.substring(1).replace(/\.js$/, ''), null, moduleDirectory) - if (!sourcePromises.has(source)) { - queueFile(source, true) - } - - await sourcePromises.get(source) - } - - next() - }, - }) - - const watcher = require('chokidar').watch(sources, { - persistent: true, - ignoreInitial: true, - disableGlobbing: true, - usePolling: true, - }) - - const onChange = (source) => { - queueFile(source).catch((error) => { - console.error(source) - console.error(error) - sourcePromises.delete(source) - }) - - browserSync.reload() - } - - watcher.on('change', onChange) - - if (!serve) { - console.log('watching for changes') - } - - async function queueFile(source, initial) { - if (initial) { - watcher.add(source) - } - - const promise = queue.add(async () => { - const shimResult = await shim?.(source) - const moduleName = getModuleName(source) - const rootRelativeModuleName = getRelativeToRoot(moduleName, moduleDirectory).result - const outModuleName = path.join(outDir, rootRelativeModuleName) - - if (shimResult) { - await mkdirp(path.dirname(outModuleName)) - - return Promise.all( - OUTPUT_VERSIONS.map(({ extension }) => - Promise.all([ - fs.writeFile(`${outModuleName}${extension}`, shimResult.code), - shimResult.map && - fs.writeFile(`${outModuleName}${extension}.map`, JSON.stringify(shimResult.map)), - ]), - ), - ) - } - - const sourceCode = (await fs.readFile(source)).toString() - const ast = babel.parseSync(sourceCode, { ...babelOptions, filename: source }) - - return Promise.all( - OUTPUT_VERSIONS.map(async (version) => { - const { extension, nodeEnv } = version - const env = { NODE_ENV: nodeEnv, INTERACTJS_ESNEXT: true } - const finalBabelOptions = extendBabelOptions( - { - filename: source, - plugins: [ - [require.resolve('./babel/inline-env-vars'), { env }], - [require.resolve('./babel/relative-imports'), { extension, moduleDirectory }], - ], - }, - babelOptions, - ) - const result = { - ...(await babel.transformFromAst(ast, sourceCode, finalBabelOptions)), - modern: true, - } - - const { code, map } = version.post ? await version.post(result) : result - const jsFilename = `${outModuleName}${extension}` - const mapFilename = `${jsFilename}.map` - - await mkdirp(path.dirname(jsFilename)) - - const jsStream = createWriteStream(jsFilename) - - jsStream.write(code) - jsStream.end(`\n//# sourceMappingURL=${path.basename(mapFilename)}`) - - await Promise.all([ - new Promise((resolve, reject) => { - jsStream.on('close', resolve) - jsStream.on('error', reject) - }), - fs.writeFile(mapFilename, JSON.stringify(map, null, '\t')), - ]) - }), - ) - }) - - sourcePromises.set(source, promise) - return promise - } -} - -module.exports = generate diff --git a/scripts/minify.js b/scripts/minify.js deleted file mode 100644 index 01f1eb51f..000000000 --- a/scripts/minify.js +++ /dev/null @@ -1,25 +0,0 @@ -const Terser = require('terser') - -module.exports = ({ code, map, modern = false, env = {} }) => - Terser.minify(code, { - module: true, - sourceMap: { content: map }, - mangle: { - module: true, - }, - compress: { - ecma: modern ? '2019' : '5', - unsafe: true, - unsafe_Function: true, - unsafe_arrows: modern, - unsafe_methods: true, - global_defs: Object.entries(env).reduce((acc, [name, value]) => { - acc[`process.env.${name}`] = value - return acc - }, {}), - passes: 2, - }, - output: { - beautify: false, - }, - }) diff --git a/scripts/shimBundler.js b/scripts/shimBundler.js deleted file mode 100644 index 94024e66c..000000000 --- a/scripts/shimBundler.js +++ /dev/null @@ -1,28 +0,0 @@ -const path = require('path') - -const resolveSync = require('resolve').sync - -const bundler = require('./bundler') -const { getModuleDirectories } = require('./utils') - -const moduleDirectory = getModuleDirectories() - -const destDir = path.join(__dirname, '..', 'dist', 'shims') - -module.exports = async ({ source }) => { - const sourcePath = resolveSync(source, { - moduleDirectory, - extensions: ['.ts', '.tsx', '.js', '.jsx'], - }) - const ext = path.extname(source) - const name = source.slice(0, source.length - ext.length) - - await bundler({ - entry: sourcePath, - name, - ext, - destDir, - format: 'es', - minOnly: true, - }) -} diff --git a/scripts/utils.js b/scripts/utils.js index b8118e006..bfb36aaad 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -41,7 +41,13 @@ function getEsnextBabelOptions(presetEnvOptions) { configFile: false, sourceMaps: true, presets: [ - [require.resolve('@babel/preset-env'), presetEnvOptions], + [ + require.resolve('@babel/preset-env'), + { + shippedProposals: true, + ...presetEnvOptions, + }, + ], [ require.resolve('@babel/preset-typescript'), { isTSX: false, onlyRemoveTypeImports: true, allExtensions: true, allowDeclareFields: true }, @@ -58,6 +64,7 @@ function getEsnextBabelOptions(presetEnvOptions) { iterableIsArray: true, noDocumentAll: true, noNewArrows: true, + setPublicClassFields: true, }, } } diff --git a/types.tsconfig.json b/types.tsconfig.json index 7d4716c82..eef78adf2 100644 --- a/types.tsconfig.json +++ b/types.tsconfig.json @@ -1,17 +1,10 @@ { - "include": [ - "packages/@interactjs" - ], - "exclude": [ - "**/*.spec.ts" - ], + "include": ["packages/@interactjs", "shims.d.ts"], + "exclude": ["**/*.spec.ts"], "compilerOptions": { "target": "esnext", "module": "esnext", - "lib": [ - "esnext", - "dom" - ], + "lib": ["esnext", "dom"], "moduleResolution": "node", "esModuleInterop": true, diff --git a/yarn.lock b/yarn.lock index 1a889e783..7ed974094 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1544,6 +1544,18 @@ "@babel/helper-module-imports" "^7.18.6" "@rollup/pluginutils" "^5.0.1" +"@rollup/plugin-commonjs@^25.0.7": + version "25.0.7" + resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz#145cec7589ad952171aeb6a585bbeabd0fd3b4cf" + integrity sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ== + dependencies: + "@rollup/pluginutils" "^5.0.1" + commondir "^1.0.1" + estree-walker "^2.0.2" + glob "^8.0.3" + is-reference "1.2.1" + magic-string "^0.30.3" + "@rollup/plugin-node-resolve@^15.2.3": version "15.2.3" resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz#e5e0b059bd85ca57489492f295ce88c2d4b0daf9" @@ -1573,15 +1585,7 @@ smob "^1.0.0" terser "^5.17.4" -"@rollup/pluginutils@^4.2.1": - version "4.2.1" - resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" - integrity sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ== - dependencies: - estree-walker "^2.0.1" - picomatch "^2.2.2" - -"@rollup/pluginutils@^5.0.1", "@rollup/pluginutils@^5.0.5": +"@rollup/pluginutils@^5.0.1": version "5.1.0" resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz#7e53eddc8c7f483a4ad0b94afb1f7f5fd3c771e0" integrity sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g== @@ -2811,16 +2815,6 @@ ci-info@^3.2.0: resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== -cjs-es@^0.9.2: - version "0.9.2" - resolved "https://registry.npmjs.org/cjs-es/-/cjs-es-0.9.2.tgz#4dc92971798d278d8695ad8faaa7d9c8ac3656f4" - integrity sha512-b3dU5kkUWO8slt5DHHgKFgV5ghWbyBCQVa6lJnDA3+zfgil6MnL8JtoqoM01xabrDcgoazizriwvObCm1sXFgg== - dependencies: - "@rollup/pluginutils" "^4.2.1" - estree-walker "^3.0.1" - is-reference "^3.0.0" - magic-string "^0.26.2" - cjs-module-lexer@^1.0.0: version "1.2.3" resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" @@ -3434,15 +3428,6 @@ es-get-iterator@^1.1.3: isarray "^2.0.5" stop-iteration-iterator "^1.0.0" -es-info@^0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/es-info/-/es-info-0.4.0.tgz#212309048ecf11dbe4581e919c51d57ff3c0057f" - integrity sha512-fH+6WU7kIhEFM0tkQwMlpVn9N+Kk1oj8IxuwiNj55fEMiSrJG9e73C/WKYvk5Eeg+X3zsr+nfGd1588Th+DmtQ== - dependencies: - "@rollup/pluginutils" "^4.2.1" - estree-walker "^3.0.1" - is-reference "^3.0.0" - es-iterator-helpers@^1.0.12: version "1.0.15" resolved "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz#bd81d275ac766431d19305923707c3efd9f1ae40" @@ -3818,18 +3803,11 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== -estree-walker@^2.0.1, estree-walker@^2.0.2: +estree-walker@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== -estree-walker@^3.0.1: - version "3.0.3" - resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" - integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== - dependencies: - "@types/estree" "^1.0.0" - esutils@^2.0.2: version "2.0.3" resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -4745,10 +4723,10 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-reference@^3.0.0: - version "3.0.2" - resolved "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz#154747a01f45cd962404ee89d43837af2cba247c" - integrity sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg== +is-reference@1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== dependencies: "@types/estree" "*" @@ -5722,13 +5700,6 @@ lz-string@^1.5.0: resolved "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== -magic-string@^0.26.2: - version "0.26.7" - resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz#caf7daf61b34e9982f8228c4527474dac8981d6f" - integrity sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow== - dependencies: - sourcemap-codec "^1.4.8" - magic-string@^0.30.3, magic-string@^0.30.5: version "0.30.5" resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz#1994d980bd1c8835dc6e78db7cbd4ae4f24746f9" @@ -6346,7 +6317,7 @@ picocolors@^1.0.0: resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -6854,15 +6825,6 @@ rimraf@~2.6.2: dependencies: glob "^7.1.3" -rollup-plugin-cjs-es@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/rollup-plugin-cjs-es/-/rollup-plugin-cjs-es-3.0.0.tgz#04cd22ef9de4ff3bcb7bc734abd6e59d0af7ca9a" - integrity sha512-D23Dcq9jQW+UpD1sv6S+i6i9tm1y8FVqGDoHlDKn66MqdRmA/kr9cQr73SVm/KdiLaNM+HtbveF5jZOSDXPEeQ== - dependencies: - "@rollup/pluginutils" "^5.0.5" - cjs-es "^0.9.2" - es-info "^0.4.0" - rollup@3, rollup@^3.27.1: version "3.29.4" resolved "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" @@ -7105,11 +7067,6 @@ source-map@~0.5.3: resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== -sourcemap-codec@^1.4.8: - version "1.4.8" - resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== - spdx-correct@^3.0.0: version "3.2.0" resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c"