events-ex 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/.babelrc +1 -1
  2. package/CHANGELOG.md +25 -0
  3. package/README.cn.md +114 -3
  4. package/README.md +106 -5
  5. package/coverage/all-off.js.html +133 -0
  6. package/coverage/base.css +224 -0
  7. package/coverage/block-navigation.js +87 -0
  8. package/coverage/clover.xml +572 -0
  9. package/coverage/consts.js.html +154 -0
  10. package/coverage/default-methods.js.html +2068 -0
  11. package/coverage/event-emitter.js.html +121 -0
  12. package/coverage/event.js.html +286 -0
  13. package/coverage/eventable.js.html +355 -0
  14. package/coverage/favicon.png +0 -0
  15. package/coverage/has-listeners.js.html +166 -0
  16. package/coverage/index.html +281 -0
  17. package/coverage/lcov-report/all-off.js.html +133 -0
  18. package/coverage/lcov-report/base.css +224 -0
  19. package/coverage/lcov-report/block-navigation.js +87 -0
  20. package/coverage/lcov-report/consts.js.html +154 -0
  21. package/coverage/lcov-report/default-methods.js.html +2068 -0
  22. package/coverage/lcov-report/event-emitter.js.html +121 -0
  23. package/coverage/lcov-report/event.js.html +286 -0
  24. package/coverage/lcov-report/eventable.js.html +355 -0
  25. package/coverage/lcov-report/favicon.png +0 -0
  26. package/coverage/lcov-report/has-listeners.js.html +166 -0
  27. package/coverage/lcov-report/index.html +281 -0
  28. package/coverage/lcov-report/once-promise.js.html +325 -0
  29. package/coverage/lcov-report/pipe-async.js.html +385 -0
  30. package/coverage/lcov-report/pipe.js.html +244 -0
  31. package/coverage/lcov-report/prettify.css +1 -0
  32. package/coverage/lcov-report/prettify.js +2 -0
  33. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  34. package/coverage/lcov-report/sorter.js +210 -0
  35. package/coverage/lcov-report/unify.js.html +259 -0
  36. package/coverage/lcov-report/wrap-event-emitter.js.html +223 -0
  37. package/coverage/lcov.info +1201 -0
  38. package/coverage/once-promise.js.html +325 -0
  39. package/coverage/pipe-async.js.html +385 -0
  40. package/coverage/pipe.js.html +244 -0
  41. package/coverage/prettify.css +1 -0
  42. package/coverage/prettify.js +2 -0
  43. package/coverage/sort-arrow-sprite.png +0 -0
  44. package/coverage/sorter.js +210 -0
  45. package/coverage/unify.js.html +259 -0
  46. package/coverage/wrap-event-emitter.js.html +223 -0
  47. package/docs/README.md +106 -5
  48. package/docs/all-off/functions/allOff.md +1 -1
  49. package/docs/consts/README.md +4 -0
  50. package/docs/consts/functions/createAbortError.md +18 -0
  51. package/docs/consts/variables/RegExpEventSymbol.md +1 -1
  52. package/docs/consts/variables/states.md +2 -2
  53. package/docs/default-methods/functions/getEventableMethods.md +34 -18
  54. package/docs/event/classes/Event.md +23 -13
  55. package/docs/event-emitter/classes/EventEmitter-1.md +2 -2
  56. package/docs/event-emitter/classes/EventEmitter.md +28 -28
  57. package/docs/eventable/functions/eventable.md +1 -1
  58. package/docs/has-listeners/functions/hasListeners.md +2 -2
  59. package/docs/index/README.md +12 -0
  60. package/docs/modules.md +1 -0
  61. package/docs/once-promise/README.md +17 -0
  62. package/docs/once-promise/functions/oncePromise.md +60 -0
  63. package/docs/pipe/functions/pipe.md +3 -3
  64. package/docs/pipe-async/functions/pipeAsync.md +3 -3
  65. package/docs/unify/functions/unify.md +1 -1
  66. package/docs/util/array-remove/functions/remove.md +1 -1
  67. package/docs/util/object-for-each/functions/forEach.md +1 -1
  68. package/docs/util/string-pad/functions/pad.md +1 -1
  69. package/docs/util/to-int/functions/toInt.md +1 -1
  70. package/docs/util/valid-callable/functions/validCallable.md +1 -1
  71. package/docs/util/valid-object/functions/validObject.md +1 -1
  72. package/docs/wrap-event-emitter/functions/wrapEventEmitter.md +3 -3
  73. package/docs/wrap-event-emitter/variables/methods.md +1 -1
  74. package/lib/all-off.mjs +16 -0
  75. package/lib/consts.d.ts +7 -1
  76. package/lib/consts.js +17 -2
  77. package/lib/consts.mjs +23 -0
  78. package/lib/default-methods.d.ts +12 -4
  79. package/lib/default-methods.js +174 -22
  80. package/lib/default-methods.mjs +661 -0
  81. package/lib/event-emitter.mjs +12 -0
  82. package/lib/event.d.ts +10 -4
  83. package/lib/event.js +6 -0
  84. package/lib/event.mjs +67 -0
  85. package/lib/eventable.d.ts +1 -1
  86. package/lib/eventable.mjs +90 -0
  87. package/lib/has-listeners.d.ts +1 -1
  88. package/lib/has-listeners.mjs +27 -0
  89. package/lib/index.d.ts +1 -0
  90. package/lib/index.js +12 -0
  91. package/lib/index.mjs +16 -0
  92. package/lib/once-promise.d.ts +23 -0
  93. package/lib/once-promise.js +82 -0
  94. package/lib/once-promise.mjs +80 -0
  95. package/lib/pipe-async.d.ts +4 -2
  96. package/lib/pipe-async.js +16 -3
  97. package/lib/pipe-async.mjs +100 -0
  98. package/lib/pipe.d.ts +1 -1
  99. package/lib/pipe.mjs +53 -0
  100. package/lib/unify.js +1 -1
  101. package/lib/unify.mjs +58 -0
  102. package/lib/util/array-remove.mjs +16 -0
  103. package/lib/util/object-for-each.mjs +20 -0
  104. package/lib/util/promise-any.mjs +45 -0
  105. package/lib/util/string-pad.mjs +19 -0
  106. package/lib/util/to-int.mjs +9 -0
  107. package/lib/util/valid-callable.mjs +6 -0
  108. package/lib/util/valid-object.mjs +8 -0
  109. package/lib/wrap-event-emitter.d.ts +1 -1
  110. package/lib/wrap-event-emitter.mjs +46 -0
  111. package/package.json +29 -20
  112. package/scripts/copy-to-mjs.mjs +79 -0
  113. package/src/consts.js +10 -0
  114. package/src/default-methods.js +169 -24
  115. package/src/event.js +6 -0
  116. package/src/index.js +1 -0
  117. package/src/once-promise.js +80 -0
  118. package/src/pipe-async.js +16 -3
  119. package/src/unify.js +1 -1
  120. package/tsconfig.json +2 -1
  121. package/vitest.config.js +61 -0
  122. package/.mocharc.yml +0 -3
package/lib/pipe.mjs ADDED
@@ -0,0 +1,53 @@
1
+ import defineProperty from 'util-ex/lib/defineProperty'
2
+
3
+ import {methods} from './wrap-event-emitter.mjs'
4
+ import arrRemove from './util/array-remove.mjs'
5
+ import validObject from './util/valid-object.mjs'
6
+
7
+ const hasOwnProperty = Object.prototype.hasOwnProperty
8
+ const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor
9
+ const arrFrom = Array.from
10
+ const emit = methods.emit
11
+
12
+ /**
13
+ * Creates a pipeline between two event emitters, so that any events emitted by the first emitter are also emitted by the second emitter.
14
+ *
15
+ * @param {import('./event-emitter').EventEmitter} e1 - The first event emitter.
16
+ * @param {import('./event-emitter').EventEmitter} e2 - The second event emitter.
17
+ * @param {string} [name='emit'] - The name of the event to pipe (defaults to 'emit').
18
+ * @returns {Object} - An object with a `close` method that removes the pipeline between the two event emitters.
19
+ * @throws {TypeError} - If either of the arguments is not an event emitter object.
20
+ */
21
+ export function pipe(e1, e2/* , name */) {
22
+ let pipes
23
+
24
+ (validObject(e1) && validObject(e2))
25
+ let name = arguments[2]
26
+ if (name === undefined) {name = 'emit'}
27
+
28
+ const result = {
29
+ close() { arrRemove.call(pipes, e2) }
30
+ };
31
+ if (hasOwnProperty.call(e1, '__eePipes__')) {
32
+ (pipes = e1.__eePipes__).push(e2)
33
+ return result
34
+ }
35
+ defineProperty(e1, '__eePipes__', pipes = [e2])
36
+ let desc = getOwnPropertyDescriptor(e1, name)
37
+ if (!desc) {
38
+ desc = {}
39
+ } else {
40
+ delete desc.get
41
+ delete desc.set
42
+ }
43
+ desc.value = function () {
44
+ const data = arrFrom(pipes)
45
+ emit.apply(this, arguments)
46
+ let emitter
47
+ for (let i = 0; (emitter = data[i]); ++i) emit.apply(emitter, arguments)
48
+ }
49
+ defineProperty(e1, name, desc.value, desc)
50
+ return result
51
+ };
52
+
53
+ export default pipe
package/lib/unify.js CHANGED
@@ -8,7 +8,7 @@ exports.unify = unify;
8
8
  var _validObject = _interopRequireDefault(require("./util/valid-object"));
9
9
  var _objectForEach = _interopRequireDefault(require("./util/object-for-each"));
10
10
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
- const push = Array.prototype.apply;
11
+ const push = Array.prototype.push;
12
12
  const defineProperty = Object.defineProperty;
13
13
  const create = Object.create;
14
14
  const hasOwnProperty = Object.prototype.hasOwnProperty;
package/lib/unify.mjs ADDED
@@ -0,0 +1,58 @@
1
+ import validObject from './util/valid-object.mjs'
2
+ import forEach from './util/object-for-each.mjs'
3
+
4
+ const push = Array.prototype.push
5
+ const defineProperty = Object.defineProperty
6
+ const create = Object.create
7
+ const hasOwnProperty = Object.prototype.hasOwnProperty
8
+ const d = { configurable: true, enumerable: false, writable: true }
9
+
10
+ /**
11
+ * Unifies the event listeners of two event emitter objects so that they share the same set of listeners for each event.
12
+ *
13
+ * @param {import('./event-emitter').EventEmitter} e1 - The first event emitter object.
14
+ * @param {import('./event-emitter').EventEmitter} e2 - The second event emitter object.
15
+ * @throws {TypeError} - If either of the arguments is not an event emitter object.
16
+ */
17
+ export function unify(e1, e2) {
18
+ (validObject(e1) && validObject(e2))
19
+ if (!hasOwnProperty.call(e1, '_events')) {
20
+ if (!hasOwnProperty.call(e2, '_events')) {
21
+ d.value = create(null);
22
+ defineProperty(e1, '_events', d)
23
+ defineProperty(e2, '_events', d)
24
+ d.value = null
25
+ return
26
+ }
27
+ d.value = e2._events
28
+ defineProperty(e1, '_events', d)
29
+ d.value = null
30
+ return
31
+ }
32
+ const data = d.value = e1._events;
33
+ if (!hasOwnProperty.call(e2, '_events')) {
34
+ defineProperty(e2, '_events', d)
35
+ d.value = null
36
+ return
37
+ }
38
+ if (data === e2._events) {return}
39
+ forEach(e2._events, function (listener, name) {
40
+ if (!data[name]) {
41
+ data[name] = listener
42
+ return
43
+ }
44
+ if (typeof data[name] === 'object') {
45
+ if (typeof listener === 'object') {push.apply(data[name], listener)}
46
+ else data[name].push(listener)
47
+ } else if (typeof listener === 'object') {
48
+ listener.unshift(data[name])
49
+ data[name] = listener
50
+ } else {
51
+ data[name] = [data[name], listener]
52
+ }
53
+ });
54
+ defineProperty(e2, '_events', d)
55
+ d.value = null
56
+ }
57
+
58
+ export default unify
@@ -0,0 +1,16 @@
1
+ const indexOf = Array.prototype.indexOf
2
+ const forEach = Array.prototype.forEach
3
+ const splice = Array.prototype.splice
4
+
5
+ export function remove(/* ...itemsToRemove */) {
6
+ forEach.call(
7
+ arguments,
8
+ function (item) {
9
+ const index = indexOf.call(this, item)
10
+ if (index !== -1) {splice.call(this, index, 1)}
11
+ },
12
+ this
13
+ )
14
+ }
15
+
16
+ export default remove
@@ -0,0 +1,20 @@
1
+ import value from './valid-object.mjs'
2
+
3
+ const bind = Function.prototype.bind
4
+ const keys = Object.keys
5
+
6
+ export function forEach(obj, cb /* , thisArg, compareFn */) {
7
+ const thisArg = arguments[2]
8
+ const compareFn = arguments[3]
9
+ obj = Object(value(obj))
10
+
11
+ const list = keys(obj)
12
+ if (compareFn) {
13
+ list.sort(typeof compareFn === "function" ? bind.call(compareFn, obj) : undefined)
14
+ }
15
+ return list.forEach(function (key, index) {
16
+ return cb.call(thisArg, obj[key], key, obj, index)
17
+ });
18
+ }
19
+
20
+ export default forEach
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Simple polyfill for AggregateError if it doesn't exist.
3
+ */
4
+ const _AggregateError = typeof AggregateError !== 'undefined'
5
+ ? AggregateError
6
+ : function AggregateError(errors, message) {
7
+ const error = new Error(message);
8
+ error.name = 'AggregateError';
9
+ error.errors = errors;
10
+ return error;
11
+ };
12
+
13
+ /**
14
+ * Ensures Promise.any exists, or provides a polyfill.
15
+ */
16
+ if (typeof Promise.any !== 'function') {
17
+ Promise.any = function (promises) {
18
+ return new Promise((resolve, reject) => {
19
+ promises = Array.from(promises);
20
+ const len = promises.length;
21
+ let errors = [];
22
+ let rejectedCount = 0;
23
+
24
+ if (len === 0) {
25
+ return reject(new _AggregateError(errors, 'All promises were rejected'));
26
+ }
27
+
28
+ promises.forEach((promise, index) => {
29
+ Promise.resolve(promise)
30
+ .then((value) => {
31
+ resolve(value);
32
+ })
33
+ .catch((error) => {
34
+ errors[index] = error;
35
+ rejectedCount++;
36
+ if (rejectedCount === len) {
37
+ reject(new _AggregateError(errors, 'All promises were rejected'));
38
+ }
39
+ });
40
+ });
41
+ });
42
+ };
43
+ }
44
+
45
+ export default Promise.any;
@@ -0,0 +1,19 @@
1
+ import toInteger from "./to-int.mjs"
2
+ import value from "./valid-object.mjs"
3
+
4
+ const repeat = String.prototype.repeat
5
+ const abs = Math.abs
6
+ const max = Math.max
7
+
8
+ export function pad(fill /* , length */) {
9
+ const self = String(value(this))
10
+ const sLength = self.length
11
+ let length = arguments[1]
12
+
13
+ length = isNaN(length) ? 1 : toInteger(length)
14
+ fill = repeat.call(String(fill), abs(length))
15
+ if (length >= 0) {return fill.slice(0, max(0, length - sLength)) + self}
16
+ return self + (sLength + length >= 0 ? "" : fill.slice(length + sLength))
17
+ }
18
+
19
+ export default pad
@@ -0,0 +1,9 @@
1
+ const round = Math.round
2
+ export function toInt(value) {
3
+ if (isNaN(value)) {return 0}
4
+ value = Number(value)
5
+ if (value === 0 || !isFinite(value)) {return value}
6
+ return round(value)
7
+ }
8
+
9
+ export default toInt
@@ -0,0 +1,6 @@
1
+ export function validCallable(fn) {
2
+ if (typeof fn !== "function") {throw new TypeError(fn + " is not a function")}
3
+ return fn
4
+ }
5
+
6
+ export default validCallable
@@ -0,0 +1,8 @@
1
+ import {isObject} from 'util-ex'
2
+
3
+ export function validObject(value) {
4
+ if (!isObject(value)) {throw new TypeError(value + " is not an Object")}
5
+ return value
6
+ }
7
+
8
+ export default validObject
@@ -4,6 +4,6 @@
4
4
  * @param {Object} [options] optional configuration for the emitter
5
5
  * @returns o or new Event instance
6
6
  */
7
- export function wrapEventEmitter(o?: any, options?: any): any;
7
+ export function wrapEventEmitter(o?: Object, options?: Object): any;
8
8
  export const methods: any;
9
9
  export default wrapEventEmitter;
@@ -0,0 +1,46 @@
1
+ import {defineProperty} from 'util-ex'
2
+ import eventable from './eventable.mjs'
3
+
4
+ const create = Object.create;
5
+ const defineProperties = Object.defineProperties;
6
+
7
+ export const methods = eventable().methods;
8
+
9
+ /**
10
+ * Minimal set of core methods to be injected into an existing object.
11
+ */
12
+ const descriptors = {
13
+ on: { value: methods.on },
14
+ once: { value: methods.once },
15
+ off: { value: methods.off },
16
+ emit: { value: methods.emit },
17
+ emitAsync: { value: methods.emitAsync },
18
+ setEmitterOptions: { value: methods.setEmitterOptions },
19
+ };
20
+
21
+ /**
22
+ * Full set of all available methods from eventable for standalone instances.
23
+ */
24
+ const fullDescriptors = {};
25
+ Object.keys(methods).forEach(key => {
26
+ fullDescriptors[key] = { value: methods[key] };
27
+ });
28
+
29
+ const base = defineProperties({}, fullDescriptors);
30
+
31
+ /**
32
+ * Create or inject the eventable instance into the object
33
+ * @param {Object} [o] the optional instance to eventable
34
+ * @param {Object} [options] optional configuration for the emitter
35
+ * @returns o or new Event instance
36
+ */
37
+ export function wrapEventEmitter(o, options) {
38
+ const result = o == null ? create(base) : defineProperties(Object(o), descriptors)
39
+ defineProperty(result, '_events', {})
40
+ if (options && options.emitterOptions) {
41
+ result.setEmitterOptions(options.emitterOptions)
42
+ }
43
+ return result
44
+ };
45
+
46
+ export default wrapEventEmitter
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "events-ex",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "Browser-friendly enhanced events most compatible with standard node.js, it's powerful eventable ability.",
5
5
  "contributors": [
6
6
  {
@@ -35,31 +35,38 @@
35
35
  "url": "git://github.com/snowyu/events-ex.js.git"
36
36
  },
37
37
  "main": "./lib/index.js",
38
- "module": "./src/index.js",
38
+ "module": "./lib/index.mjs",
39
+ "exports": {
40
+ ".": {
41
+ "import": "./lib/index.mjs",
42
+ "require": "./lib/index.js"
43
+ }
44
+ },
39
45
  "dependencies": {
40
- "custom-ability": "^2.1.0",
41
- "util-ex": "^2.5.1"
46
+ "custom-ability": "^2.2.0",
47
+ "util-ex": "^2.7.0"
42
48
  },
43
49
  "devDependencies": {
44
- "@antfu/eslint-config": "^7.7.0",
45
- "@babel/cli": "^7.28.6",
46
- "@babel/core": "^7.29.0",
47
- "@babel/plugin-proposal-dynamic-import": "^7.18.6",
48
- "@babel/plugin-transform-modules-commonjs": "^7.28.6",
49
- "@babel/register": "^7.28.6",
50
- "chai": "~4.3.10",
51
- "eslint": "^10.0.3",
50
+ "@antfu/eslint-config": "^9.1.0",
51
+ "@babel/cli": "^8.0.1",
52
+ "@babel/core": "^8.0.1",
53
+ "@babel/plugin-transform-dynamic-import": "^8.0.1",
54
+ "@babel/plugin-transform-modules-commonjs": "^8.0.1",
55
+ "@babel/register": "^8.0.1",
56
+ "@vitest/coverage-v8": "^4.1.10",
57
+ "chai": "~6.2.2",
58
+ "eslint": "^10.4.0",
52
59
  "eslint-config-prettier": "^10.1.8",
53
60
  "eslint-plugin-tsdoc": "^0.5.2",
54
- "mocha": "^11.7.5",
55
- "prettier": "^3.8.1",
56
- "typedoc": "^0.28.17",
57
- "typedoc-plugin-markdown": "^4.10.0",
58
- "typescript": "~5.7.3"
61
+ "prettier": "^3.9.4",
62
+ "typedoc": "^0.28.19",
63
+ "typedoc-plugin-markdown": "^4.11.0",
64
+ "typescript": "~6.0.3",
65
+ "vitest": "^4.1.10"
59
66
  },
60
67
  "scripts": {
61
68
  "build": "npm run build.cjs && npm run build.ts && npm run doc.md",
62
- "build.cjs": "babel src --out-dir lib --config-file ./.babelrc",
69
+ "build.cjs": "babel src --out-dir lib --config-file ./.babelrc && node scripts/copy-to-mjs.mjs",
63
70
  "build.ts": "tsc --declaration --emitDeclarationOnly --outDir lib && cp src/event-emitter.d.ts lib/",
64
71
  "clean": "rm -fr web docs lib",
65
72
  "clean.doc": "rm -fr web docs",
@@ -69,9 +76,11 @@
69
76
  "doc.md": "typedoc --plugin typedoc-plugin-markdown --out docs ./src",
70
77
  "lint": "npx eslint --config .eslintrc.yml src",
71
78
  "lint.fix": "npm run lint -- --fix",
72
- "release": "npm run clean && npm run build && git add docs && git ci -m 'docs: update API docs' && npx commit-and-tag-version -s",
79
+ "release": "npm run clean && npm run build && git add docs -f && git ci -m 'docs: update API docs' && npx commit-and-tag-version -s",
73
80
  "release.alpha": "npm run release -- --prerelease alpha",
74
- "test": "mocha"
81
+ "test": "vitest run",
82
+ "test:watch": "vitest",
83
+ "test:coverage": "vitest run --coverage"
75
84
  },
76
85
  "pre-commit": {
77
86
  "run": [
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Copies all .js files from src/ to lib/ as .mjs files,
3
+ * rewriting relative import/export paths from .js to .mjs
4
+ * (and adding .mjs to bare relative paths missing an extension).
5
+ *
6
+ * This ensures Node.js recognizes the ESM source files natively
7
+ * (via .mjs extension) without needing "type": "module" in
8
+ * package.json.
9
+ */
10
+ import fs from 'fs'
11
+ import path from 'path'
12
+
13
+ const SRC_DIR = "src";
14
+ const LIB_DIR = "lib";
15
+
16
+ // Matches: from './foo.js' from "../bar.js" from './baz'
17
+ // Does NOT match bare specifiers like: from "inherits-ex"
18
+ const IMPORT_RE = /(from\s+['"])(\.\.?\/[^'"]*?)(\.js)?(['"])/g;
19
+
20
+ function ensureDir(dirPath) {
21
+ if (!fs.existsSync(dirPath)) {
22
+ fs.mkdirSync(dirPath, { recursive: true });
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Recursively walk a directory and process all .js files.
28
+ */
29
+ function walkDir(currentDir, relativeDir) {
30
+ const entries = fs.readdirSync(currentDir, { withFileTypes: true });
31
+
32
+ for (const entry of entries) {
33
+ const fullPath = path.join(currentDir, entry.name);
34
+ const relativePath = relativeDir
35
+ ? path.join(relativeDir, entry.name)
36
+ : entry.name;
37
+
38
+ if (entry.isDirectory()) {
39
+ walkDir(fullPath, relativePath);
40
+ } else if (entry.name.endsWith(".js")) {
41
+ processFile(fullPath, relativePath);
42
+ }
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Read a .js source file, rewrite import paths, and write as .mjs.
48
+ */
49
+ function processFile(srcPath, relativePath) {
50
+ const content = fs.readFileSync(srcPath, "utf8");
51
+ const mjsContent = content.replace(
52
+ IMPORT_RE,
53
+ (match, prefix, modulePath, dotJs, suffix) => {
54
+ // prefix: from " or from '
55
+ // modulePath: ./foo or ../bar/baz
56
+ // dotJs: .js (if present)
57
+ // suffix: " or '
58
+ return `${prefix}${modulePath}.mjs${suffix}`;
59
+ },
60
+ );
61
+
62
+ const mjsName = entryNameToMjs(relativePath);
63
+ const destPath = path.join(LIB_DIR, mjsName);
64
+
65
+ ensureDir(path.dirname(destPath));
66
+ fs.writeFileSync(destPath, mjsContent, "utf8");
67
+
68
+ console.log(` ✓ ${relativePath} → ${path.join("lib", mjsName)}`);
69
+ }
70
+
71
+ function entryNameToMjs(name) {
72
+ return name.replace(/\.js$/, ".mjs");
73
+ }
74
+
75
+ // --- Main ---
76
+ console.log("Copying ESM files (.mjs) from src/ to lib/ ...");
77
+ ensureDir(LIB_DIR);
78
+ walkDir(SRC_DIR, "");
79
+ console.log("Done.");
package/src/consts.js CHANGED
@@ -10,4 +10,14 @@ export const states = {
10
10
  ABORT,
11
11
  }
12
12
 
13
+ /* v8 ignore next — false branch only reachable without Symbol, which is impossible in Node.js */
13
14
  export const RegExpEventSymbol = typeof Symbol === 'function' ? Symbol('RegExpEvent') : '@@RegExpEvent'
15
+
16
+ /**
17
+ * Creates an AbortError with name 'AbortError'.
18
+ * Ensures a fresh Error instance each call for proper stack traces.
19
+ * @returns {Error}
20
+ */
21
+ export function createAbortError() {
22
+ return Object.assign(new Error('The operation was aborted'), { name: 'AbortError' })
23
+ }