feat: update keycloak theme

This commit is contained in:
Jonas Juselius
2024-02-22 09:47:34 +01:00
parent d6fde78f8d
commit f9e012da95
9813 changed files with 611335 additions and 162181 deletions
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2019 RollupJS Plugin Contributors (https://github.com/rollup/plugins/graphs/contributors)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,233 @@
import type { FilterPattern } from '@rollup/pluginutils';
import type { Plugin } from 'rollup';
type RequireReturnsDefaultOption = boolean | 'auto' | 'preferred' | 'namespace';
type DefaultIsModuleExportsOption = boolean | 'auto';
interface RollupCommonJSOptions {
/**
* A picomatch pattern, or array of patterns, which specifies the files in
* the build the plugin should operate on. By default, all files with
* extension `".cjs"` or those in `extensions` are included, but you can
* narrow this list by only including specific files. These files will be
* analyzed and transpiled if either the analysis does not find ES module
* specific statements or `transformMixedEsModules` is `true`.
* @default undefined
*/
include?: FilterPattern;
/**
* A picomatch pattern, or array of patterns, which specifies the files in
* the build the plugin should _ignore_. By default, all files with
* extensions other than those in `extensions` or `".cjs"` are ignored, but you
* can exclude additional files. See also the `include` option.
* @default undefined
*/
exclude?: FilterPattern;
/**
* For extensionless imports, search for extensions other than .js in the
* order specified. Note that you need to make sure that non-JavaScript files
* are transpiled by another plugin first.
* @default [ '.js' ]
*/
extensions?: ReadonlyArray<string>;
/**
* If true then uses of `global` won't be dealt with by this plugin
* @default false
*/
ignoreGlobal?: boolean;
/**
* If false, skips source map generation for CommonJS modules. This will
* improve performance.
* @default true
*/
sourceMap?: boolean;
/**
* Some `require` calls cannot be resolved statically to be translated to
* imports.
* When this option is set to `false`, the generated code will either
* directly throw an error when such a call is encountered or, when
* `dynamicRequireTargets` is used, when such a call cannot be resolved with a
* configured dynamic require target.
* Setting this option to `true` will instead leave the `require` call in the
* code or use it as a fallback for `dynamicRequireTargets`.
* @default false
*/
ignoreDynamicRequires?: boolean;
/**
* Instructs the plugin whether to enable mixed module transformations. This
* is useful in scenarios with modules that contain a mix of ES `import`
* statements and CommonJS `require` expressions. Set to `true` if `require`
* calls should be transformed to imports in mixed modules, or `false` if the
* `require` expressions should survive the transformation. The latter can be
* important if the code contains environment detection, or you are coding
* for an environment with special treatment for `require` calls such as
* ElectronJS. See also the `ignore` option.
* @default false
*/
transformMixedEsModules?: boolean;
/**
* By default, this plugin will try to hoist `require` statements as imports
* to the top of each file. While this works well for many code bases and
* allows for very efficient ESM output, it does not perfectly capture
* CommonJS semantics as the order of side effects like log statements may
* change. But it is especially problematic when there are circular `require`
* calls between CommonJS modules as those often rely on the lazy execution of
* nested `require` calls.
*
* Setting this option to `true` will wrap all CommonJS files in functions
* which are executed when they are required for the first time, preserving
* NodeJS semantics. Note that this can have an impact on the size and
* performance of the generated code.
*
* The default value of `"auto"` will only wrap CommonJS files when they are
* part of a CommonJS dependency cycle, e.g. an index file that is required by
* many of its dependencies. All other CommonJS files are hoisted. This is the
* recommended setting for most code bases.
*
* `false` will entirely prevent wrapping and hoist all files. This may still
* work depending on the nature of cyclic dependencies but will often cause
* problems.
*
* You can also provide a picomatch pattern, or array of patterns, to only
* specify a subset of files which should be wrapped in functions for proper
* `require` semantics.
*
* `"debug"` works like `"auto"` but after bundling, it will display a warning
* containing a list of ids that have been wrapped which can be used as
* picomatch pattern for fine-tuning.
* @default "auto"
*/
strictRequires?: boolean | FilterPattern;
/**
* Sometimes you have to leave require statements unconverted. Pass an array
* containing the IDs or a `id => boolean` function.
* @default []
*/
ignore?: ReadonlyArray<string> | ((id: string) => boolean);
/**
* In most cases, where `require` calls are inside a `try-catch` clause,
* they should be left unconverted as it requires an optional dependency
* that may or may not be installed beside the rolled up package.
* Due to the conversion of `require` to a static `import` - the call is
* hoisted to the top of the file, outside the `try-catch` clause.
*
* - `true`: Default. All `require` calls inside a `try` will be left unconverted.
* - `false`: All `require` calls inside a `try` will be converted as if the
* `try-catch` clause is not there.
* - `remove`: Remove all `require` calls from inside any `try` block.
* - `string[]`: Pass an array containing the IDs to left unconverted.
* - `((id: string) => boolean|'remove')`: Pass a function that controls
* individual IDs.
*
* @default true
*/
ignoreTryCatch?:
| boolean
| 'remove'
| ReadonlyArray<string>
| ((id: string) => boolean | 'remove');
/**
* Controls how to render imports from external dependencies. By default,
* this plugin assumes that all external dependencies are CommonJS. This
* means they are rendered as default imports to be compatible with e.g.
* NodeJS where ES modules can only import a default export from a CommonJS
* dependency.
*
* If you set `esmExternals` to `true`, this plugin assumes that all
* external dependencies are ES modules and respect the
* `requireReturnsDefault` option. If that option is not set, they will be
* rendered as namespace imports.
*
* You can also supply an array of ids to be treated as ES modules, or a
* function that will be passed each external id to determine whether it is
* an ES module.
* @default false
*/
esmExternals?: boolean | ReadonlyArray<string> | ((id: string) => boolean);
/**
* Controls what is returned when requiring an ES module from a CommonJS file.
* When using the `esmExternals` option, this will also apply to external
* modules. By default, this plugin will render those imports as namespace
* imports i.e.
*
* ```js
* // input
* const foo = require('foo');
*
* // output
* import * as foo from 'foo';
* ```
*
* However, there are some situations where this may not be desired.
* For these situations, you can change Rollup's behaviour either globally or
* per module. To change it globally, set the `requireReturnsDefault` option
* to one of the following values:
*
* - `false`: This is the default, requiring an ES module returns its
* namespace. This is the only option that will also add a marker
* `__esModule: true` to the namespace to support interop patterns in
* CommonJS modules that are transpiled ES modules.
* - `"namespace"`: Like `false`, requiring an ES module returns its
* namespace, but the plugin does not add the `__esModule` marker and thus
* creates more efficient code. For external dependencies when using
* `esmExternals: true`, no additional interop code is generated.
* - `"auto"`: This is complementary to how `output.exports: "auto"` works in
* Rollup: If a module has a default export and no named exports, requiring
* that module returns the default export. In all other cases, the namespace
* is returned. For external dependencies when using `esmExternals: true`, a
* corresponding interop helper is added.
* - `"preferred"`: If a module has a default export, requiring that module
* always returns the default export, no matter whether additional named
* exports exist. This is similar to how previous versions of this plugin
* worked. Again for external dependencies when using `esmExternals: true`,
* an interop helper is added.
* - `true`: This will always try to return the default export on require
* without checking if it actually exists. This can throw at build time if
* there is no default export. This is how external dependencies are handled
* when `esmExternals` is not used. The advantage over the other options is
* that, like `false`, this does not add an interop helper for external
* dependencies, keeping the code lean.
*
* To change this for individual modules, you can supply a function for
* `requireReturnsDefault` instead. This function will then be called once for
* each required ES module or external dependency with the corresponding id
* and allows you to return different values for different modules.
* @default false
*/
requireReturnsDefault?:
| RequireReturnsDefaultOption
| ((id: string) => RequireReturnsDefaultOption);
/**
* @default "auto"
*/
defaultIsModuleExports?:
| DefaultIsModuleExportsOption
| ((id: string) => DefaultIsModuleExportsOption);
/**
* Some modules contain dynamic `require` calls, or require modules that
* contain circular dependencies, which are not handled well by static
* imports. Including those modules as `dynamicRequireTargets` will simulate a
* CommonJS (NodeJS-like) environment for them with support for dynamic
* dependencies. It also enables `strictRequires` for those modules.
*
* Note: In extreme cases, this feature may result in some paths being
* rendered as absolute in the final bundle. The plugin tries to avoid
* exposing paths from the local machine, but if you are `dynamicRequirePaths`
* with paths that are far away from your project's folder, that may require
* replacing strings like `"/Users/John/Desktop/foo-project/"` -> `"/"`.
*/
dynamicRequireTargets?: string | ReadonlyArray<string>;
/**
* To avoid long paths when using the `dynamicRequireTargets` option, you can use this option to specify a directory
* that is a common parent for all files that use dynamic require statements. Using a directory higher up such as `/`
* may lead to unnecessarily long paths in the generated code and may expose directory names on your machine like your
* home directory name. By default, it uses the current working directory.
*/
dynamicRequireRoot?: string;
}
/**
* Convert CommonJS modules to ES6, so they can be included in a Rollup bundle
*/
export default function commonjs(options?: RollupCommonJSOptions): Plugin;
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2019 RollupJS Plugin Contributors (https://github.com/rollup/plugins/graphs/contributors)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,113 @@
import type { Plugin } from 'rollup';
export const DEFAULTS: {
customResolveOptions: {};
dedupe: [];
extensions: ['.mjs', '.js', '.json', '.node'];
resolveOnly: [];
};
export interface RollupNodeResolveOptions {
/**
* Additional conditions of the package.json exports field to match when resolving modules.
* By default, this plugin looks for the `'default', 'module', 'import']` conditions when resolving imports.
*
* When using `@rollup/plugin-commonjs` v16 or higher, this plugin will use the
* `['default', 'module', 'import']` conditions when resolving require statements.
*
* Setting this option will add extra conditions on top of the default conditions.
* See https://nodejs.org/api/packages.html#packages_conditional_exports for more information.
*/
exportConditions?: string[];
/**
* If `true`, instructs the plugin to use the `"browser"` property in `package.json`
* files to specify alternative files to load for bundling. This is useful when
* bundling for a browser environment. Alternatively, a value of `'browser'` can be
* added to the `mainFields` option. If `false`, any `"browser"` properties in
* package files will be ignored. This option takes precedence over `mainFields`.
* @default false
*/
browser?: boolean;
/**
* A list of directory names in which to recursively look for modules.
* @default ['node_modules']
*/
moduleDirectories?: string[];
/**
* A list of absolute paths to additional locations to search for modules.
* This is analogous to setting the `NODE_PATH` environment variable for node.
* @default []
*/
modulePaths?: string[];
/**
* An `Array` of modules names, which instructs the plugin to force resolving for the
* specified modules to the root `node_modules`. Helps to prevent bundling the same
* package multiple times if package is imported from dependencies.
*/
dedupe?: string[] | ((importee: string) => boolean);
/**
* Specifies the extensions of files that the plugin will operate on.
* @default [ '.mjs', '.js', '.json', '.node' ]
*/
extensions?: readonly string[];
/**
* Locks the module search within specified path (e.g. chroot). Modules defined
* outside this path will be marked as external.
* @default '/'
*/
jail?: string;
/**
* Specifies the properties to scan within a `package.json`, used to determine the
* bundle entry point.
* @default ['module', 'main']
*/
mainFields?: readonly string[];
/**
* If `true`, inspect resolved files to assert that they are ES2015 modules.
* @default false
*/
modulesOnly?: boolean;
/**
* If `true`, the plugin will prefer built-in modules (e.g. `fs`, `path`). If `false`,
* the plugin will look for locally installed modules of the same name.
* @default true
*/
preferBuiltins?: boolean;
/**
* An `Array` which instructs the plugin to limit module resolution to those whose
* names match patterns in the array.
* @default []
*/
resolveOnly?: ReadonlyArray<string | RegExp> | null | ((module: string) => boolean);
/**
* Specifies the root directory from which to resolve modules. Typically used when
* resolving entry-point imports, and when resolving deduplicated modules.
* @default process.cwd()
*/
rootDir?: string;
/**
* Allow folder mappings in package exports (trailing /)
* This was deprecated in Node 14 and removed with Node 17, see DEP0148.
* So this option might be changed to default to `false` in a future release.
* @default true
*/
allowExportsFolderMapping?: boolean;
}
/**
* Locate modules using the Node resolution algorithm, for using third party modules in node_modules
*/
export function nodeResolve(options?: RollupNodeResolveOptions): Plugin;
export default nodeResolve;
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2019 RollupJS Plugin Contributors (https://github.com/rollup/plugins/graphs/contributors)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,153 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var MagicString = require('magic-string');
var pluginutils = require('@rollup/pluginutils');
function escape(str) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
}
function ensureFunction(functionOrValue) {
if (typeof functionOrValue === 'function') { return functionOrValue; }
return function () { return functionOrValue; };
}
function longest(a, b) {
return b.length - a.length;
}
function getReplacements(options) {
if (options.values) {
return Object.assign({}, options.values);
}
var values = Object.assign({}, options);
delete values.delimiters;
delete values.include;
delete values.exclude;
delete values.sourcemap;
delete values.sourceMap;
delete values.objectGuards;
return values;
}
function mapToFunctions(object) {
return Object.keys(object).reduce(function (fns, key) {
var functions = Object.assign({}, fns);
functions[key] = ensureFunction(object[key]);
return functions;
}, {});
}
var objKeyRegEx =
/^([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)(\.([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*))+$/;
function expandTypeofReplacements(replacements) {
Object.keys(replacements).forEach(function (key) {
var objMatch = key.match(objKeyRegEx);
if (!objMatch) { return; }
var dotIndex = objMatch[1].length;
var lastIndex = 0;
do {
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + " ===")] = '"object" ===';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + " !==")] = '"object" !==';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + "===")] = '"object"===';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + "!==")] = '"object"!==';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + " ==")] = '"object" ===';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + " !=")] = '"object" !==';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + "==")] = '"object"===';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + "!=")] = '"object"!==';
lastIndex = dotIndex + 1;
dotIndex = key.indexOf('.', lastIndex);
} while (dotIndex !== -1);
});
}
function replace(options) {
if ( options === void 0 ) options = {};
var filter = pluginutils.createFilter(options.include, options.exclude);
var delimiters = options.delimiters; if ( delimiters === void 0 ) delimiters = ['\\b', '\\b(?!\\.)'];
var preventAssignment = options.preventAssignment;
var objectGuards = options.objectGuards;
var replacements = getReplacements(options);
if (objectGuards) { expandTypeofReplacements(replacements); }
var functionValues = mapToFunctions(replacements);
var keys = Object.keys(functionValues).sort(longest).map(escape);
var lookahead = preventAssignment ? '(?!\\s*(=[^=]|:[^:]))' : '';
var pattern = new RegExp(
((delimiters[0]) + "(" + (keys.join('|')) + ")" + (delimiters[1]) + lookahead),
'g'
);
return {
name: 'replace',
buildStart: function buildStart() {
if (![true, false].includes(preventAssignment)) {
this.warn({
message:
"@rollup/plugin-replace: 'preventAssignment' currently defaults to false. It is recommended to set this option to `true`, as the next major version will default this option to `true`."
});
}
},
renderChunk: function renderChunk(code, chunk) {
var id = chunk.fileName;
if (!keys.length) { return null; }
if (!filter(id)) { return null; }
return executeReplacement(code, id);
},
transform: function transform(code, id) {
if (!keys.length) { return null; }
if (!filter(id)) { return null; }
return executeReplacement(code, id);
}
};
function executeReplacement(code, id) {
var magicString = new MagicString(code);
if (!codeHasReplacements(code, id, magicString)) {
return null;
}
var result = { code: magicString.toString() };
if (isSourceMapEnabled()) {
result.map = magicString.generateMap({ hires: true });
}
return result;
}
function codeHasReplacements(code, id, magicString) {
var result = false;
var match;
// eslint-disable-next-line no-cond-assign
while ((match = pattern.exec(code))) {
result = true;
var start = match.index;
var end = start + match[0].length;
var replacement = String(functionValues[match[1]](id));
magicString.overwrite(start, end, replacement);
}
return result;
}
function isSourceMapEnabled() {
return options.sourceMap !== false && options.sourcemap !== false;
}
}
exports.default = replace;
module.exports = Object.assign(exports.default, exports);
//# sourceMappingURL=index.js.map
@@ -0,0 +1,148 @@
import MagicString from 'magic-string';
import { createFilter } from '@rollup/pluginutils';
function escape(str) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
}
function ensureFunction(functionOrValue) {
if (typeof functionOrValue === 'function') { return functionOrValue; }
return function () { return functionOrValue; };
}
function longest(a, b) {
return b.length - a.length;
}
function getReplacements(options) {
if (options.values) {
return Object.assign({}, options.values);
}
var values = Object.assign({}, options);
delete values.delimiters;
delete values.include;
delete values.exclude;
delete values.sourcemap;
delete values.sourceMap;
delete values.objectGuards;
return values;
}
function mapToFunctions(object) {
return Object.keys(object).reduce(function (fns, key) {
var functions = Object.assign({}, fns);
functions[key] = ensureFunction(object[key]);
return functions;
}, {});
}
var objKeyRegEx =
/^([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)(\.([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*))+$/;
function expandTypeofReplacements(replacements) {
Object.keys(replacements).forEach(function (key) {
var objMatch = key.match(objKeyRegEx);
if (!objMatch) { return; }
var dotIndex = objMatch[1].length;
var lastIndex = 0;
do {
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + " ===")] = '"object" ===';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + " !==")] = '"object" !==';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + "===")] = '"object"===';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + "!==")] = '"object"!==';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + " ==")] = '"object" ===';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + " !=")] = '"object" !==';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + "==")] = '"object"===';
// eslint-disable-next-line no-param-reassign
replacements[("typeof " + (key.slice(lastIndex, dotIndex)) + "!=")] = '"object"!==';
lastIndex = dotIndex + 1;
dotIndex = key.indexOf('.', lastIndex);
} while (dotIndex !== -1);
});
}
function replace(options) {
if ( options === void 0 ) options = {};
var filter = createFilter(options.include, options.exclude);
var delimiters = options.delimiters; if ( delimiters === void 0 ) delimiters = ['\\b', '\\b(?!\\.)'];
var preventAssignment = options.preventAssignment;
var objectGuards = options.objectGuards;
var replacements = getReplacements(options);
if (objectGuards) { expandTypeofReplacements(replacements); }
var functionValues = mapToFunctions(replacements);
var keys = Object.keys(functionValues).sort(longest).map(escape);
var lookahead = preventAssignment ? '(?!\\s*(=[^=]|:[^:]))' : '';
var pattern = new RegExp(
((delimiters[0]) + "(" + (keys.join('|')) + ")" + (delimiters[1]) + lookahead),
'g'
);
return {
name: 'replace',
buildStart: function buildStart() {
if (![true, false].includes(preventAssignment)) {
this.warn({
message:
"@rollup/plugin-replace: 'preventAssignment' currently defaults to false. It is recommended to set this option to `true`, as the next major version will default this option to `true`."
});
}
},
renderChunk: function renderChunk(code, chunk) {
var id = chunk.fileName;
if (!keys.length) { return null; }
if (!filter(id)) { return null; }
return executeReplacement(code, id);
},
transform: function transform(code, id) {
if (!keys.length) { return null; }
if (!filter(id)) { return null; }
return executeReplacement(code, id);
}
};
function executeReplacement(code, id) {
var magicString = new MagicString(code);
if (!codeHasReplacements(code, id, magicString)) {
return null;
}
var result = { code: magicString.toString() };
if (isSourceMapEnabled()) {
result.map = magicString.generateMap({ hires: true });
}
return result;
}
function codeHasReplacements(code, id, magicString) {
var result = false;
var match;
// eslint-disable-next-line no-cond-assign
while ((match = pattern.exec(code))) {
result = true;
var start = match.index;
var end = start + match[0].length;
var replacement = String(functionValues[match[1]](id));
magicString.overwrite(start, end, replacement);
}
return result;
}
function isSourceMapEnabled() {
return options.sourceMap !== false && options.sourcemap !== false;
}
}
export { replace as default };
//# sourceMappingURL=index.js.map
@@ -0,0 +1,141 @@
import MagicString from 'magic-string';
import { createFilter } from '@rollup/pluginutils';
function escape(str) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
}
function ensureFunction(functionOrValue) {
if (typeof functionOrValue === 'function') return functionOrValue;
return () => functionOrValue;
}
function longest(a, b) {
return b.length - a.length;
}
function getReplacements(options) {
if (options.values) {
return Object.assign({}, options.values);
}
const values = Object.assign({}, options);
delete values.delimiters;
delete values.include;
delete values.exclude;
delete values.sourcemap;
delete values.sourceMap;
delete values.objectGuards;
return values;
}
function mapToFunctions(object) {
return Object.keys(object).reduce((fns, key) => {
const functions = Object.assign({}, fns);
functions[key] = ensureFunction(object[key]);
return functions;
}, {});
}
const objKeyRegEx =
/^([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)(\.([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*))+$/;
function expandTypeofReplacements(replacements) {
Object.keys(replacements).forEach((key) => {
const objMatch = key.match(objKeyRegEx);
if (!objMatch) return;
let dotIndex = objMatch[1].length;
let lastIndex = 0;
do {
// eslint-disable-next-line no-param-reassign
replacements[`typeof ${key.slice(lastIndex, dotIndex)} ===`] = '"object" ===';
// eslint-disable-next-line no-param-reassign
replacements[`typeof ${key.slice(lastIndex, dotIndex)} !==`] = '"object" !==';
// eslint-disable-next-line no-param-reassign
replacements[`typeof ${key.slice(lastIndex, dotIndex)}===`] = '"object"===';
// eslint-disable-next-line no-param-reassign
replacements[`typeof ${key.slice(lastIndex, dotIndex)}!==`] = '"object"!==';
// eslint-disable-next-line no-param-reassign
replacements[`typeof ${key.slice(lastIndex, dotIndex)} ==`] = '"object" ===';
// eslint-disable-next-line no-param-reassign
replacements[`typeof ${key.slice(lastIndex, dotIndex)} !=`] = '"object" !==';
// eslint-disable-next-line no-param-reassign
replacements[`typeof ${key.slice(lastIndex, dotIndex)}==`] = '"object"===';
// eslint-disable-next-line no-param-reassign
replacements[`typeof ${key.slice(lastIndex, dotIndex)}!=`] = '"object"!==';
lastIndex = dotIndex + 1;
dotIndex = key.indexOf('.', lastIndex);
} while (dotIndex !== -1);
});
}
export default function replace(options = {}) {
const filter = createFilter(options.include, options.exclude);
const { delimiters = ['\\b', '\\b(?!\\.)'], preventAssignment, objectGuards } = options;
const replacements = getReplacements(options);
if (objectGuards) expandTypeofReplacements(replacements);
const functionValues = mapToFunctions(replacements);
const keys = Object.keys(functionValues).sort(longest).map(escape);
const lookahead = preventAssignment ? '(?!\\s*(=[^=]|:[^:]))' : '';
const pattern = new RegExp(
`${delimiters[0]}(${keys.join('|')})${delimiters[1]}${lookahead}`,
'g'
);
return {
name: 'replace',
buildStart() {
if (![true, false].includes(preventAssignment)) {
this.warn({
message:
"@rollup/plugin-replace: 'preventAssignment' currently defaults to false. It is recommended to set this option to `true`, as the next major version will default this option to `true`."
});
}
},
renderChunk(code, chunk) {
const id = chunk.fileName;
if (!keys.length) return null;
if (!filter(id)) return null;
return executeReplacement(code, id);
},
transform(code, id) {
if (!keys.length) return null;
if (!filter(id)) return null;
return executeReplacement(code, id);
}
};
function executeReplacement(code, id) {
const magicString = new MagicString(code);
if (!codeHasReplacements(code, id, magicString)) {
return null;
}
const result = { code: magicString.toString() };
if (isSourceMapEnabled()) {
result.map = magicString.generateMap({ hires: true });
}
return result;
}
function codeHasReplacements(code, id, magicString) {
let result = false;
let match;
// eslint-disable-next-line no-cond-assign
while ((match = pattern.exec(code))) {
result = true;
const start = match.index;
const end = start + match[0].length;
const replacement = String(functionValues[match[1]](id));
magicString.overwrite(start, end, replacement);
}
return result;
}
function isSourceMapEnabled() {
return options.sourceMap !== false && options.sourcemap !== false;
}
}
@@ -0,0 +1,50 @@
import type { FilterPattern } from '@rollup/pluginutils';
import type { Plugin } from 'rollup';
type Replacement = string | ((id: string) => string);
export interface RollupReplaceOptions {
/**
* All other options are treated as `string: replacement` replacers,
* or `string: (id) => replacement` functions.
*/
[str: string]:
| Replacement
| RollupReplaceOptions['include']
| RollupReplaceOptions['values']
| RollupReplaceOptions['preventAssignment'];
/**
* A picomatch pattern, or array of patterns, of files that should be
* processed by this plugin (if omitted, all files are included by default)
*/
include?: FilterPattern;
/**
* Files that should be excluded, if `include` is otherwise too permissive.
*/
exclude?: FilterPattern;
/**
* If false, skips source map generation. This will improve performance.
* @default true
*/
sourceMap?: boolean;
/**
* To replace every occurrence of `<@foo@>` instead of every occurrence
* of `foo`, supply delimiters
*/
delimiters?: [string, string];
/**
* Prevents replacing strings where they are followed by a single equals
* sign.
*/
preventAssignment?: boolean;
/**
* You can separate values to replace from other options.
*/
values?: { [str: string]: Replacement };
}
/**
* Replace strings in files while bundling them.
*/
export default function replace(options?: RollupReplaceOptions): Plugin;
@@ -0,0 +1,232 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var worker_threads = require('worker_threads');
var smob = require('smob');
var terser$1 = require('terser');
var url = require('url');
var async_hooks = require('async_hooks');
var os = require('os');
var events = require('events');
var serializeJavascript = require('serialize-javascript');
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
const taskInfo = Symbol('taskInfo');
const freeWorker = Symbol('freeWorker');
const workerPoolWorkerFlag = 'WorkerPoolWorker';
/**
* Duck typing worker context.
*
* @param input
*/
function isWorkerContextSerialized(input) {
return (smob.isObject(input) &&
smob.hasOwnProperty(input, 'code') &&
typeof input.code === 'string' &&
smob.hasOwnProperty(input, 'options') &&
typeof input.options === 'string');
}
function runWorker() {
if (worker_threads.isMainThread || !worker_threads.parentPort || worker_threads.workerData !== workerPoolWorkerFlag) {
return;
}
// eslint-disable-next-line no-eval
const eval2 = eval;
worker_threads.parentPort.on('message', async (data) => {
if (!isWorkerContextSerialized(data)) {
return;
}
const options = eval2(`(${data.options})`);
const result = await terser$1.minify(data.code, options);
const output = {
code: result.code || data.code,
nameCache: options.nameCache
};
if (typeof result.map === 'string') {
output.sourceMap = JSON.parse(result.map);
}
if (smob.isObject(result.map)) {
output.sourceMap = result.map;
}
worker_threads.parentPort === null || worker_threads.parentPort === void 0 ? void 0 : worker_threads.parentPort.postMessage(output);
});
}
class WorkerPoolTaskInfo extends async_hooks.AsyncResource {
constructor(callback) {
super('WorkerPoolTaskInfo');
this.callback = callback;
}
done(err, result) {
this.runInAsyncScope(this.callback, null, err, result);
this.emitDestroy();
}
}
class WorkerPool extends events.EventEmitter {
constructor(options) {
super();
this.tasks = [];
this.workers = [];
this.freeWorkers = [];
this.maxInstances = options.maxWorkers || os.cpus().length;
this.filePath = options.filePath;
this.on(freeWorker, () => {
if (this.tasks.length > 0) {
const { context, cb } = this.tasks.shift();
this.runTask(context, cb);
}
});
}
get numWorkers() {
return this.workers.length;
}
addAsync(context) {
return new Promise((resolve, reject) => {
this.runTask(context, (err, output) => {
if (err) {
reject(err);
return;
}
if (!output) {
reject(new Error('The output is empty'));
return;
}
resolve(output);
});
});
}
close() {
for (let i = 0; i < this.workers.length; i++) {
const worker = this.workers[i];
worker.terminate();
}
}
addNewWorker() {
const worker = new worker_threads.Worker(this.filePath, {
workerData: workerPoolWorkerFlag
});
worker.on('message', (result) => {
var _a;
(_a = worker[taskInfo]) === null || _a === void 0 ? void 0 : _a.done(null, result);
worker[taskInfo] = null;
this.freeWorkers.push(worker);
this.emit(freeWorker);
});
worker.on('error', (err) => {
if (worker[taskInfo]) {
worker[taskInfo].done(err, null);
}
else {
this.emit('error', err);
}
this.workers.splice(this.workers.indexOf(worker), 1);
this.addNewWorker();
});
this.workers.push(worker);
this.freeWorkers.push(worker);
this.emit(freeWorker);
}
runTask(context, cb) {
if (this.freeWorkers.length === 0) {
this.tasks.push({ context, cb });
if (this.numWorkers < this.maxInstances) {
this.addNewWorker();
}
return;
}
const worker = this.freeWorkers.pop();
if (worker) {
worker[taskInfo] = new WorkerPoolTaskInfo(cb);
worker.postMessage({
code: context.code,
options: serializeJavascript(context.options)
});
}
}
}
function terser(input = {}) {
const { maxWorkers, ...options } = input;
let workerPool;
let numOfChunks = 0;
let numOfWorkersUsed = 0;
return {
name: 'terser',
async renderChunk(code, chunk, outputOptions) {
if (!workerPool) {
workerPool = new WorkerPool({
filePath: url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('index.js', document.baseURI).href))),
maxWorkers
});
}
numOfChunks += 1;
const defaultOptions = {
sourceMap: outputOptions.sourcemap === true || typeof outputOptions.sourcemap === 'string'
};
if (outputOptions.format === 'es') {
defaultOptions.module = true;
}
if (outputOptions.format === 'cjs') {
defaultOptions.toplevel = true;
}
try {
const { code: result, nameCache, sourceMap } = await workerPool.addAsync({
code,
options: smob.merge({}, options || {}, defaultOptions)
});
if (options.nameCache && nameCache) {
let vars = {
props: {}
};
if (smob.hasOwnProperty(options.nameCache, 'vars') && smob.isObject(options.nameCache.vars)) {
vars = smob.merge({}, options.nameCache.vars || {}, vars);
}
if (smob.hasOwnProperty(nameCache, 'vars') && smob.isObject(nameCache.vars)) {
vars = smob.merge({}, nameCache.vars, vars);
}
// eslint-disable-next-line no-param-reassign
options.nameCache.vars = vars;
let props = {};
if (smob.hasOwnProperty(options.nameCache, 'props') && smob.isObject(options.nameCache.props)) {
// eslint-disable-next-line prefer-destructuring
props = options.nameCache.props;
}
if (smob.hasOwnProperty(nameCache, 'props') && smob.isObject(nameCache.props)) {
props = smob.merge({}, nameCache.props, props);
}
// eslint-disable-next-line no-param-reassign
options.nameCache.props = props;
}
if ((!!defaultOptions.sourceMap || !!options.sourceMap) && smob.isObject(sourceMap)) {
return {
code: result,
map: sourceMap
};
}
return result;
}
catch (e) {
return Promise.reject(e);
}
finally {
numOfChunks -= 1;
if (numOfChunks === 0) {
numOfWorkersUsed = workerPool.numWorkers;
workerPool.close();
workerPool = null;
}
}
},
get numOfWorkersUsed() {
return numOfWorkersUsed;
}
};
}
runWorker();
exports.default = terser;
module.exports = Object.assign(exports.default, exports);
//# sourceMappingURL=index.js.map
@@ -0,0 +1,226 @@
import { isMainThread, parentPort, workerData, Worker } from 'worker_threads';
import { isObject, hasOwnProperty, merge } from 'smob';
import { minify } from 'terser';
import { fileURLToPath } from 'url';
import { AsyncResource } from 'async_hooks';
import { cpus } from 'os';
import { EventEmitter } from 'events';
import serializeJavascript from 'serialize-javascript';
const taskInfo = Symbol('taskInfo');
const freeWorker = Symbol('freeWorker');
const workerPoolWorkerFlag = 'WorkerPoolWorker';
/**
* Duck typing worker context.
*
* @param input
*/
function isWorkerContextSerialized(input) {
return (isObject(input) &&
hasOwnProperty(input, 'code') &&
typeof input.code === 'string' &&
hasOwnProperty(input, 'options') &&
typeof input.options === 'string');
}
function runWorker() {
if (isMainThread || !parentPort || workerData !== workerPoolWorkerFlag) {
return;
}
// eslint-disable-next-line no-eval
const eval2 = eval;
parentPort.on('message', async (data) => {
if (!isWorkerContextSerialized(data)) {
return;
}
const options = eval2(`(${data.options})`);
const result = await minify(data.code, options);
const output = {
code: result.code || data.code,
nameCache: options.nameCache
};
if (typeof result.map === 'string') {
output.sourceMap = JSON.parse(result.map);
}
if (isObject(result.map)) {
output.sourceMap = result.map;
}
parentPort === null || parentPort === void 0 ? void 0 : parentPort.postMessage(output);
});
}
class WorkerPoolTaskInfo extends AsyncResource {
constructor(callback) {
super('WorkerPoolTaskInfo');
this.callback = callback;
}
done(err, result) {
this.runInAsyncScope(this.callback, null, err, result);
this.emitDestroy();
}
}
class WorkerPool extends EventEmitter {
constructor(options) {
super();
this.tasks = [];
this.workers = [];
this.freeWorkers = [];
this.maxInstances = options.maxWorkers || cpus().length;
this.filePath = options.filePath;
this.on(freeWorker, () => {
if (this.tasks.length > 0) {
const { context, cb } = this.tasks.shift();
this.runTask(context, cb);
}
});
}
get numWorkers() {
return this.workers.length;
}
addAsync(context) {
return new Promise((resolve, reject) => {
this.runTask(context, (err, output) => {
if (err) {
reject(err);
return;
}
if (!output) {
reject(new Error('The output is empty'));
return;
}
resolve(output);
});
});
}
close() {
for (let i = 0; i < this.workers.length; i++) {
const worker = this.workers[i];
worker.terminate();
}
}
addNewWorker() {
const worker = new Worker(this.filePath, {
workerData: workerPoolWorkerFlag
});
worker.on('message', (result) => {
var _a;
(_a = worker[taskInfo]) === null || _a === void 0 ? void 0 : _a.done(null, result);
worker[taskInfo] = null;
this.freeWorkers.push(worker);
this.emit(freeWorker);
});
worker.on('error', (err) => {
if (worker[taskInfo]) {
worker[taskInfo].done(err, null);
}
else {
this.emit('error', err);
}
this.workers.splice(this.workers.indexOf(worker), 1);
this.addNewWorker();
});
this.workers.push(worker);
this.freeWorkers.push(worker);
this.emit(freeWorker);
}
runTask(context, cb) {
if (this.freeWorkers.length === 0) {
this.tasks.push({ context, cb });
if (this.numWorkers < this.maxInstances) {
this.addNewWorker();
}
return;
}
const worker = this.freeWorkers.pop();
if (worker) {
worker[taskInfo] = new WorkerPoolTaskInfo(cb);
worker.postMessage({
code: context.code,
options: serializeJavascript(context.options)
});
}
}
}
function terser(input = {}) {
const { maxWorkers, ...options } = input;
let workerPool;
let numOfChunks = 0;
let numOfWorkersUsed = 0;
return {
name: 'terser',
async renderChunk(code, chunk, outputOptions) {
if (!workerPool) {
workerPool = new WorkerPool({
filePath: fileURLToPath(import.meta.url),
maxWorkers
});
}
numOfChunks += 1;
const defaultOptions = {
sourceMap: outputOptions.sourcemap === true || typeof outputOptions.sourcemap === 'string'
};
if (outputOptions.format === 'es') {
defaultOptions.module = true;
}
if (outputOptions.format === 'cjs') {
defaultOptions.toplevel = true;
}
try {
const { code: result, nameCache, sourceMap } = await workerPool.addAsync({
code,
options: merge({}, options || {}, defaultOptions)
});
if (options.nameCache && nameCache) {
let vars = {
props: {}
};
if (hasOwnProperty(options.nameCache, 'vars') && isObject(options.nameCache.vars)) {
vars = merge({}, options.nameCache.vars || {}, vars);
}
if (hasOwnProperty(nameCache, 'vars') && isObject(nameCache.vars)) {
vars = merge({}, nameCache.vars, vars);
}
// eslint-disable-next-line no-param-reassign
options.nameCache.vars = vars;
let props = {};
if (hasOwnProperty(options.nameCache, 'props') && isObject(options.nameCache.props)) {
// eslint-disable-next-line prefer-destructuring
props = options.nameCache.props;
}
if (hasOwnProperty(nameCache, 'props') && isObject(nameCache.props)) {
props = merge({}, nameCache.props, props);
}
// eslint-disable-next-line no-param-reassign
options.nameCache.props = props;
}
if ((!!defaultOptions.sourceMap || !!options.sourceMap) && isObject(sourceMap)) {
return {
code: result,
map: sourceMap
};
}
return result;
}
catch (e) {
return Promise.reject(e);
}
finally {
numOfChunks -= 1;
if (numOfChunks === 0) {
numOfWorkersUsed = workerPool.numWorkers;
workerPool.close();
workerPool = null;
}
}
},
get numOfWorkersUsed() {
return numOfWorkersUsed;
}
};
}
runWorker();
export { terser as default };
//# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
export const taskInfo = Symbol('taskInfo');
export const freeWorker = Symbol('freeWorker');
export const workerPoolWorkerFlag = 'WorkerPoolWorker';
@@ -0,0 +1,8 @@
import { runWorker } from './worker';
import terser from './module';
runWorker();
export * from './type';
export default terser;
@@ -0,0 +1,105 @@
import { fileURLToPath } from 'url';
import type { NormalizedOutputOptions, RenderedChunk } from 'rollup';
import { hasOwnProperty, isObject, merge } from 'smob';
import type { Options } from './type';
import { WorkerPool } from './worker-pool';
export default function terser(input: Options = {}) {
const { maxWorkers, ...options } = input;
let workerPool: WorkerPool | null | undefined;
let numOfChunks = 0;
let numOfWorkersUsed = 0;
return {
name: 'terser',
async renderChunk(code: string, chunk: RenderedChunk, outputOptions: NormalizedOutputOptions) {
if (!workerPool) {
workerPool = new WorkerPool({
filePath: fileURLToPath(import.meta.url),
maxWorkers
});
}
numOfChunks += 1;
const defaultOptions: Options = {
sourceMap: outputOptions.sourcemap === true || typeof outputOptions.sourcemap === 'string'
};
if (outputOptions.format === 'es') {
defaultOptions.module = true;
}
if (outputOptions.format === 'cjs') {
defaultOptions.toplevel = true;
}
try {
const {
code: result,
nameCache,
sourceMap
} = await workerPool.addAsync({
code,
options: merge({}, options || {}, defaultOptions)
});
if (options.nameCache && nameCache) {
let vars: Record<string, any> = {
props: {}
};
if (hasOwnProperty(options.nameCache, 'vars') && isObject(options.nameCache.vars)) {
vars = merge({}, options.nameCache.vars || {}, vars);
}
if (hasOwnProperty(nameCache, 'vars') && isObject(nameCache.vars)) {
vars = merge({}, nameCache.vars, vars);
}
// eslint-disable-next-line no-param-reassign
options.nameCache.vars = vars;
let props: Record<string, any> = {};
if (hasOwnProperty(options.nameCache, 'props') && isObject(options.nameCache.props)) {
// eslint-disable-next-line prefer-destructuring
props = options.nameCache.props;
}
if (hasOwnProperty(nameCache, 'props') && isObject(nameCache.props)) {
props = merge({}, nameCache.props, props);
}
// eslint-disable-next-line no-param-reassign
options.nameCache.props = props;
}
if ((!!defaultOptions.sourceMap || !!options.sourceMap) && isObject(sourceMap)) {
return {
code: result,
map: sourceMap
};
}
return result;
} catch (e) {
return Promise.reject(e);
} finally {
numOfChunks -= 1;
if (numOfChunks === 0) {
numOfWorkersUsed = workerPool.numWorkers;
workerPool.close();
workerPool = null;
}
}
},
get numOfWorkersUsed() {
return numOfWorkersUsed;
}
};
}
@@ -0,0 +1,45 @@
import type { AsyncResource } from 'async_hooks';
import type { Worker } from 'worker_threads';
import type { MinifyOptions } from 'terser';
import type { taskInfo } from './constants';
export interface Options extends MinifyOptions {
nameCache?: Record<string, any>;
maxWorkers?: number;
}
export interface WorkerContext {
code: string;
options: Options;
}
export type WorkerCallback = (err: Error | null, output?: WorkerOutput) => void;
interface WorkerPoolTaskInfo extends AsyncResource {
done(err: Error | null, result: any): void;
}
export type WorkerWithTaskInfo = Worker & { [taskInfo]?: WorkerPoolTaskInfo | null };
export interface WorkerContextSerialized {
code: string;
options: string;
}
export interface WorkerOutput {
code: string;
nameCache?: Options['nameCache'];
sourceMap?: Record<string, any>;
}
export interface WorkerPoolOptions {
filePath: string;
maxWorkers?: number;
}
export interface WorkerPoolTask {
context: WorkerContext;
cb: WorkerCallback;
}
@@ -0,0 +1,128 @@
import { AsyncResource } from 'async_hooks';
import { Worker } from 'worker_threads';
import { cpus } from 'os';
import { EventEmitter } from 'events';
import serializeJavascript from 'serialize-javascript';
import { freeWorker, taskInfo, workerPoolWorkerFlag } from './constants';
import type {
WorkerCallback,
WorkerContext,
WorkerOutput,
WorkerPoolOptions,
WorkerPoolTask,
WorkerWithTaskInfo
} from './type';
class WorkerPoolTaskInfo extends AsyncResource {
constructor(private callback: WorkerCallback) {
super('WorkerPoolTaskInfo');
}
done(err: Error | null, result: any) {
this.runInAsyncScope(this.callback, null, err, result);
this.emitDestroy();
}
}
export class WorkerPool extends EventEmitter {
protected maxInstances: number;
protected filePath: string;
protected tasks: WorkerPoolTask[] = [];
protected workers: WorkerWithTaskInfo[] = [];
protected freeWorkers: WorkerWithTaskInfo[] = [];
constructor(options: WorkerPoolOptions) {
super();
this.maxInstances = options.maxWorkers || cpus().length;
this.filePath = options.filePath;
this.on(freeWorker, () => {
if (this.tasks.length > 0) {
const { context, cb } = this.tasks.shift()!;
this.runTask(context, cb);
}
});
}
get numWorkers(): number {
return this.workers.length;
}
addAsync(context: WorkerContext): Promise<WorkerOutput> {
return new Promise((resolve, reject) => {
this.runTask(context, (err, output) => {
if (err) {
reject(err);
return;
}
if (!output) {
reject(new Error('The output is empty'));
return;
}
resolve(output);
});
});
}
close() {
for (let i = 0; i < this.workers.length; i++) {
const worker = this.workers[i];
worker.terminate();
}
}
private addNewWorker() {
const worker: WorkerWithTaskInfo = new Worker(this.filePath, {
workerData: workerPoolWorkerFlag
});
worker.on('message', (result) => {
worker[taskInfo]?.done(null, result);
worker[taskInfo] = null;
this.freeWorkers.push(worker);
this.emit(freeWorker);
});
worker.on('error', (err) => {
if (worker[taskInfo]) {
worker[taskInfo].done(err, null);
} else {
this.emit('error', err);
}
this.workers.splice(this.workers.indexOf(worker), 1);
this.addNewWorker();
});
this.workers.push(worker);
this.freeWorkers.push(worker);
this.emit(freeWorker);
}
private runTask(context: WorkerContext, cb: WorkerCallback) {
if (this.freeWorkers.length === 0) {
this.tasks.push({ context, cb });
if (this.numWorkers < this.maxInstances) {
this.addNewWorker();
}
return;
}
const worker = this.freeWorkers.pop();
if (worker) {
worker[taskInfo] = new WorkerPoolTaskInfo(cb);
worker.postMessage({
code: context.code,
options: serializeJavascript(context.options)
});
}
}
}
@@ -0,0 +1,58 @@
import { isMainThread, parentPort, workerData } from 'worker_threads';
import { hasOwnProperty, isObject } from 'smob';
import { minify } from 'terser';
import { workerPoolWorkerFlag } from './constants';
import type { WorkerContextSerialized, WorkerOutput } from './type';
/**
* Duck typing worker context.
*
* @param input
*/
function isWorkerContextSerialized(input: unknown): input is WorkerContextSerialized {
return (
isObject(input) &&
hasOwnProperty(input, 'code') &&
typeof input.code === 'string' &&
hasOwnProperty(input, 'options') &&
typeof input.options === 'string'
);
}
export function runWorker() {
if (isMainThread || !parentPort || workerData !== workerPoolWorkerFlag) {
return;
}
// eslint-disable-next-line no-eval
const eval2 = eval;
parentPort.on('message', async (data: WorkerContextSerialized) => {
if (!isWorkerContextSerialized(data)) {
return;
}
const options = eval2(`(${data.options})`);
const result = await minify(data.code, options);
const output: WorkerOutput = {
code: result.code || data.code,
nameCache: options.nameCache
};
if (typeof result.map === 'string') {
output.sourceMap = JSON.parse(result.map);
}
if (isObject(result.map)) {
output.sourceMap = result.map;
}
parentPort?.postMessage(output);
});
}
@@ -0,0 +1,15 @@
import type { Plugin } from 'rollup';
import type { MinifyOptions } from 'terser';
export interface Options extends MinifyOptions {
nameCache?: Record<string, any>;
maxWorkers?: number;
}
/**
* A Rollup plugin to generate a minified output bundle.
*
* @param options - Plugin options.
* @returns Plugin instance.
*/
export default function terser(options?: Options): Plugin;