diff --git a/lib/error.js b/lib/error.js index 70ccd8e..fefe46b 100644 --- a/lib/error.js +++ b/lib/error.js @@ -8,7 +8,7 @@ 'use strict'; -const { isPlainObject } = require('./utils'); +const { isPlainObject } = require('./utils/type-utils'); /** * @classdesc Represents an error that occurred during video ID extraction. diff --git a/lib/utils.js b/lib/utils/index.js similarity index 51% rename from lib/utils.js rename to lib/utils/index.js index 5c6dabd..fd9e043 100644 --- a/lib/utils.js +++ b/lib/utils/index.js @@ -1,41 +1,24 @@ /** - * Utilities module for **YTMP3** project. + * Main entry for `utils` module of **YTMP3-JS** project. + * + * This module provides a set of submodules for working with various utilities. + * These submodules are: + * + * - {@link module:utils/logger} - A submodule for logging process. + * - {@link module:utils/yt-urlfmt} - A submodule containing all supported YouTube URLs in regular expressions (_deprecated_). + * - {@link module:utils/url-utils} - A submodule for working with YouTube URLs. + * - {@link module:utils/type-utils} - A submodule for type checking and utility functions. * * @module utils + * @requires utils/logger + * @requires utils/yt-urlfmt + * @requires utils/url-utils + * @requires utils/type-utils * @author Ryuu Mitsuki * @license MIT * @since 1.0.0 */ -'use strict'; - -const fs = require('node:fs'); -const os = require('node:os'); -const path = require('node:path'); - -/** - * @typedef {Function} LoggerFunc - * @param {string} msg - The message to be displayed. - * @returns {void} - * @since 1.0.0 - */ - -/** - * The interface of {@link module:utils~logger `logger`} object. - * - * @typedef {Object} LoggerInterface - * @property {string} INFO_PREFIX - The prefix for the info level message. - * @property {string} DONE_PREFIX - The prefix for the done level message. - * @property {string} DEBUG_PREFIX - The prefix for the debug level message. - * @property {string} WARNING_PREFIX - The prefix for the warning level message. - * @property {string} ERROR_PREFIX - The prefix for the error level message. - * @property {LoggerFunc} info - The function to log the info level message to the console. - * @property {LoggerFunc} done - The function to log the done level message to the console. - * @property {LoggerFunc} debug - The function to log the debug level message to the console. - * @property {LoggerFunc} warn - The function to log the warning level message to the console. - * @property {LoggerFunc} error - The function to log the error level message to the console. - * @since 1.0.0 - */ /** * Options object for configuring the progress bar. @@ -61,13 +44,20 @@ const path = require('node:path'); * @since 1.0.0 */ -// region Constants +'use strict'; + +const fs = require('node:fs'); +const os = require('node:os'); +const path = require('node:path'); -const FrozenProperty = { - writable: false, - configurable: false, - enumerable: true -}; +// Local imports +const Logger = require('./logger'); +const TypeUtils = require('./type-utils'); +const URLFmt = require('./yt-urlfmt'); +const URLUtils = require('./url-utils'); + + +// region Constants /** * The root directory of the project. @@ -76,7 +66,8 @@ const FrozenProperty = { * @package * @since 1.0.0 */ -const ROOTDIR = path.join(__dirname, '..'); +const ROOTDIR = path.join(__dirname, '..', '..'); + /** * The output directory for the downloaded audio files. * @type {string} @@ -85,12 +76,14 @@ const ROOTDIR = path.join(__dirname, '..'); * @since 1.0.0 */ const OUTDIR = path.join(ROOTDIR, 'download'); + /** * The home directory path for the YTMP3-JS configuration and data files. * * This path is constructed by joining the user's home directory with the `'.ytmp3-js'` folder. * On POSIX systems, this will typically be `"/home//.ytmp3-js"`, while on Windows systems, - * it will be `"C:\Users\\.ytmp3-js"`. For Termux Android, it will be `"/data/data/com.termux/files/home/.ytmp3-js"`. + * it will be `"C:\Users\\.ytmp3-js"`. For Termux Android, it will be + * `"/data/data/com.termux/files/home/.ytmp3-js"`. * * @type {string} * @constant @@ -113,6 +106,7 @@ const YTMP3_HOMEDIR = path.join(os.homedir(), '.ytmp3-js'); */ const LOGDIR = path.join(YTMP3_HOMEDIR, 'logs'); + // region Utilities Function /** @@ -123,7 +117,7 @@ const LOGDIR = path.join(YTMP3_HOMEDIR, 'logs'); * @returns {Promise} * * @async - * @public + * @package * @since 1.0.0 */ async function createDirIfNotExist(dirpath) { @@ -134,7 +128,7 @@ async function createDirIfNotExist(dirpath) { * Similar with {@link module:utils~createDirIfNotExist `createDirIfNotExist`} * function, but it uses synchronous directory creation. * - * @public + * @package * @since 1.0.1 */ function createDirIfNotExistSync(dirpath) { @@ -157,225 +151,6 @@ function createLogFile(prefix) { } -// region Type Checker - -/** - * Checks if a given value is null or undefined. - * - * @param {any} x - The value to check. - * @returns {boolean} - `true` if the value is null or undefined, otherwise `false`. - * - * @public - * @since 1.0.0 - */ -function isNullOrUndefined(x) { - return (x === null || typeof x === 'undefined'); -} - -/** - * Determines whether the provided value is a non-null object. - * - * This function returns `true` for any value that is of the object type and is not `null`, - * but it does not guarantee that the object is a plain object (`{}`). - * - * @param {any} x - The value to be checked. - * @returns {boolean} `true` if the value is a non-null object, otherwise `false`. - * - * @package - * @since 1.0.0 - * @see {@link module:utils~isPlainObject isPlainObject} - */ -function isObject(x) { - return ( - !isNullOrUndefined(x) && - typeof x === 'object' && - !Array.isArray(x) && - Object.prototype.toString && - /^\[object .+\]$/.test(Object.prototype.toString.call(x)) - ); -} - -/** - * Determines whether the provided value is a plain object (`{}`). - * - * This function returns `true` only if the value is a non-null object with - * a prototype of `Object`. - * - * @param {any} x - The value to be checked. - * @returns {boolean} `true` if the value is a plain object, otherwise `false`. - * - * @package - * @since 1.1.0 - * @see {@link module:utils~isObject isObject} - */ -function isPlainObject(x) { - return ( - !isNullOrUndefined(x) && - typeof x === 'object' && - !Array.isArray(x) && - Object.prototype.toString && - /^\[object Object\]$/.test(Object.prototype.toString.call(x)) - ); -} - -/** - * Returns the type of the provided value as a string. - * - * For `null` values, it returns `'null'`, and for objects, it returns a more detailed - * type such as `'[object Object]'`. - * - * @param {any} x - The value whose type is to be determined. - * @returns {string} A string representing the type of the value. - * - * @package - * @since 1.1.0 - */ -function getType(x) { - return x === null - ? 'null' : typeof x === 'object' - ? Object.prototype.toString.call(x) : typeof x; -} - -/** - * **Logger Namespace** - * @namespace module:utils~Logger - * @public - * @since 1.0.0 - */ - -/** - * A custom logger object for the **YTMP3** project with ANSI color codes. - * - * The logger is using the ANSI color codes to add color to the log messages, - * it might not support on every terminals. - * - * @constant - * @type {module:utils~Logger} - * @public - * @since 1.0.0 - * @see {@link module:utils~Logger Logger (namespace)} - * @see {@link module:utils~LoggerInterface LoggerInterface} - */ -const logger = Object.create(null); -Object.defineProperties(logger, { - /** - * The prefix for the info level message. - * @memberof module:utils~Logger - * @var {string} - * @default
'\x1b[96m[INFO]\x1b[0m'
- */ - INFO_PREFIX: { value: '\x1b[96m[INFO]\x1b[0m', ...FrozenProperty }, - /** - * The prefix for the done level message. - * @memberof module:utils~Logger - * @var {string} - * @default
'\x1b[92m[DONE]\x1b[0m'
- */ - DONE_PREFIX: { value: '\x1b[92m[DONE]\x1b[0m', ...FrozenProperty }, - /** - * The prefix for the debug level message. - * @memberof module:utils~Logger - * @var {string} - * @default
'\x1b[2;37m[DEBUG]\x1b[0m'
- */ - DEBUG_PREFIX: { value: '\x1b[2;37m[DEBUG]\x1b[0m', ...FrozenProperty }, - /** - * The prefix for the warning level message. - * @memberof module:utils~Logger - * @var {string} - * @default
'\x1b[93m[WARNING]\x1b[0m'
- */ - WARNING_PREFIX: { value: '\x1b[93m[WARNING]\x1b[0m', ...FrozenProperty }, - /** - * The prefix for the error level message. - * @memberof module:utils~Logger - * @var {string} - * @default
'\x1b[91m[ERROR]\x1b[0m'
- */ - ERROR_PREFIX: { value: '\x1b[91m[ERROR]\x1b[0m', ...FrozenProperty }, - /** - * The function to log the info level message to the console. - * @memberof module:utils~Logger - * @var {LoggerFunc} - * @function - */ - info: { - value: function (msg) { - console.log(`${this.INFO_PREFIX} ${msg}`); - }, - ...FrozenProperty - }, - /** - * The function to log the done level message to the console. - * @memberof module:utils~Logger - * @function - * @param {string} msg - The message string to be displayed. - * @returns {void} - */ - done: { - value: function (msg) { - console.log(`${this.DONE_PREFIX} ${msg}`); - }, - ...FrozenProperty - }, - /** - * The function to log the debug level message to the console. - * @memberof module:utils~Logger - * @function - * @param {string} msg - The message string to be displayed. - * @returns {void} - */ - debug: { - value: function (msg) { - console.log(`${this.DEBUG_PREFIX} ${msg}`); - }, - ...FrozenProperty - }, - /** - * The function to log the warning level message to the console. - * @memberof module:utils~Logger - * @function - * @param {string} msg - The message string to be displayed. - * @returns {void} - */ - warn: { - value: function (msg) { - console.error(`${this.WARNING_PREFIX} ${msg}`); - }, - ...FrozenProperty - }, - /** - * The function to log the error level message to the console. - * @memberof module:utils~Logger - * @function - * @param {string} msg - The message string to be displayed. - * @returns {void} - */ - error: { - value: function (msg) { - console.error(`${this.ERROR_PREFIX} ${msg}`); - }, - ...FrozenProperty - } -}); - -/** - * Drops null and undefined values from the input object. - * - * @param {Object} obj - The input object to filter null and undefined values from. - * @return {Object} The filtered object without null and undefined values. - * - * @public - * @since 1.0.0 - */ -function dropNullAndUndefined(obj) { - return Object.keys(obj).reduce((acc, key) => { - if (!isNullOrUndefined(obj[key])) acc[key] = obj[key]; - return acc; - }, {}); -} - - // region Utilities Class class ProgressBar { @@ -388,12 +163,13 @@ class ProgressBar { * @class * @param {ProgressBarOptions} options * Options object for configuring the progress bar. + * @package * @since 1.0.0 */ constructor (options) { /** * Options object for configuring the progress bar. - * @var {ResolvedProgressBarOptions} + * @type {ResolvedProgressBarOptions} */ this.options = { barWidth: (typeof options?.barWidth === 'string' @@ -411,12 +187,12 @@ class ProgressBar { }; /** * Index for the loading animation. - * @var {number} + * @type {number} */ this.idxLoading = 0; /** * Characters for the loading animation. - * @var {'\\' | '|' | '/' | '-'} + * @type {'\\' | '|' | '/' | '-'} * @default */ this.loadings = [ '\\', '|', '/', '-' ]; @@ -497,17 +273,30 @@ class ProgressBar { } -module.exports = Object.freeze({ +// Logger module +Object.assign(module.exports, { + Logger, + log: Logger.log, + logger: Logger.logger +}); + +// TypeUtils module +Object.assign(module.exports, { + TypeUtils, + ...TypeUtils +}); + +// URLUtils module +Object.assign(module.exports, { URLUtils }); + +// URLFmt module +Object.assign(module.exports, { URLFmt }); + +// Utils (this) module +Object.assign(module.exports, { ROOTDIR, OUTDIR, LOGDIR, YTMP3_HOMEDIR, - logger, - log: logger, // alias for `logger` - isNullOrUndefined, - isObject, - isPlainObject, createDirIfNotExist, createDirIfNotExistSync, createLogFile, - dropNullAndUndefined, - getType, ProgressBar }); diff --git a/lib/utils/logger.js b/lib/utils/logger.js new file mode 100644 index 0000000..2117cc9 --- /dev/null +++ b/lib/utils/logger.js @@ -0,0 +1,138 @@ +/** + * Utility submodule for logging process. + * + * @module utils/logger + * @author Ryuu Mitsuki + * @license MIT + * @since 1.2.0 + */ + +'use strict'; + +/** + * @classdesc A custom logger object for the **YTMP3-JS** library with ANSI color codes. + * + * The logger is using the ANSI color codes to add color to the log messages, + * it might not support on every terminals. + * + * @class + * @hideconstructor + * @package + * @since 1.0.0 + */ +const Logger = {}; + +/** + * The prefix for the info level message. + * @type {string} + * @default
'\x1b[96m[INFO]\x1b[0m'
+ * @since 1.0.0 + */ +Logger.INFO_PREFIX = '\x1b[96m[INFO]\x1b[0m'; + +/** + * The prefix for the done level message. + * @type {string} + * @default
'\x1b[92m[DONE]\x1b[0m'
+ * @since 1.0.0 + */ +Logger.DONE_PREFIX = '\x1b[92m[DONE]\x1b[0m'; + +/** + * The prefix for the debug level message. + * @type {string} + * @default
'\x1b[2;37m[DEBUG]\x1b[0m'
+ * @since 1.0.0 + */ +Logger.DEBUG_PREFIX = '\x1b[2;37m[DEBUG]\x1b[0m'; + +/** + * The prefix for the warning level message. + * @type {string} + * @default
'\x1b[93m[WARNING]\x1b[0m'
+ * @since 1.0.0 + */ +Logger.WARNING_PREFIX = '\x1b[93m[WARNING]\x1b[0m'; + +/** + * The prefix for the error level message. + * @type {string} + * @default
'\x1b[91m[ERROR]\x1b[0m'
+ * @since 1.0.0 + */ +Logger.ERROR_PREFIX = '\x1b[91m[ERROR]\x1b[0m'; + +/** + * The function to log the **info** level message to the console. + * + * @param {string} [msg] - The message string to log. + * + * @function + * @package + * @since 1.0.0 + */ +Logger.info = function info(msg) { + console.log(`${Logger.INFO_PREFIX} ${msg}`); +}; + +/** + * The function to log the **done** level message to the console. + * + * @param {string} [msg] - The message string to log. + * @returns {void} + * + * @function + * @package + * @since 1.0.0 + */ +Logger.done = function done(msg) { + console.log(`${Logger.DONE_PREFIX} ${msg}`); +}; + +/** + * The function to log the **debug** level message to the console. + * + * @param {string} [msg] - The message string to log. + * @returns {void} + * + * @function + * @package + * @since 1.0.0 + */ +Logger.debug = function debug(msg) { + console.log(`${Logger.DEBUG_PREFIX} ${msg}`); +}; + +/** + * The function to log the **warning** level message to the console. + * + * @param {string} [msg] - The message string to log. + * @returns {void} + * + * @function + * @package + * @since 1.0.0 + */ +Logger.warn = function warn(msg) { + console.error(`${this.WARNING_PREFIX} ${msg}`); +}; + +/** + * The function to log the **error** level message to the console. + * + * @param {string} [msg] - The message string to log. + * @returns {void} + * + * @function + * @package + * @since 1.0.0 + */ +Logger.error = function error(msg) { + console.error(`${this.ERROR_PREFIX} ${msg}`); +}; + +Logger.log = Logger; // Circular reference #1 (new alias) +Logger.logger = Logger; // Circular reference #2 (for backward compatibility) + +// Export the `Logger` object with the circular references +module.exports = Logger; diff --git a/lib/utils/type-utils.js b/lib/utils/type-utils.js new file mode 100644 index 0000000..306642c --- /dev/null +++ b/lib/utils/type-utils.js @@ -0,0 +1,112 @@ +/** + * Utility submodule containing type checker and helper. + * + * @module utils/type-utils + * @author Ryuu Mitsuki + * @license MIT + * @since 1.2.0 + */ + +'use strict'; + +const TypeUtils = {}; + +/** + * Checks if a given value is null or undefined. + * + * @param {any} x - The value to check. + * @returns {boolean} `true` if the value is null or undefined, otherwise `false`. + * + * @package + * @since 1.0.0 + */ +function isNullOrUndefined(x) { + return (x === null || typeof x === 'undefined'); +} +TypeUtils.isNullOrUndefined = isNullOrUndefined; // Assign to `TypeUtils` + +/** + * Determines whether the provided value is a non-null object. + * + * This function returns `true` for any value that is of the object type and is not `null`, + * but it does not guarantee that the object is a plain object (`{}`). + * + * @param {any} x - The value to be checked. + * @returns {boolean} `true` if the value is a non-null object, otherwise `false`. + * + * @package + * @since 1.0.0 + * @see {@link module:utils~isPlainObject isPlainObject} + */ +function isObject(x) { + return ( + !isNullOrUndefined(x) && + typeof x === 'object' && + !Array.isArray(x) && + Object.prototype.toString && + /^\[object .+\]$/.test(Object.prototype.toString.call(x)) + ); +} +TypeUtils.isObject = isObject; // Assign to `TypeUtils` + +/** + * Determines whether the provided value is a plain object (`{}`). + * + * This function returns `true` only if the value is a non-null object with + * a prototype of `Object`. + * + * @param {any} x - The value to be checked. + * @returns {boolean} `true` if the value is a plain object, otherwise `false`. + * + * @package + * @since 1.1.0 + * @see {@link module:utils~isObject isObject} + */ +function isPlainObject(x) { + return ( + !isNullOrUndefined(x) && + typeof x === 'object' && + !Array.isArray(x) && + Object.prototype.toString && + /^\[object Object\]$/.test(Object.prototype.toString.call(x)) + ); +} +TypeUtils.isPlainObject = isPlainObject; // Assign to `TypeUtils` + +/** + * Returns the type of the provided value as a string. + * + * For `null` values, it returns `'null'`, and for objects, it returns a more detailed + * type such as `'[object Object]'`. + * + * @param {any} x - The value whose type is to be determined. + * @returns {string} A string representing the type of the value. + * + * @package + * @since 1.1.0 + */ +function getType(x) { + return x === null + ? 'null' : typeof x === 'object' + ? Object.prototype.toString.call(x) : typeof x; +} +TypeUtils.getType = getType; // Assign to `TypeUtils` + +/** + * Drops null and undefined values from the input object. + * + * @param {Object} obj - The input object to filter null and undefined values from. + * @return {Object} The filtered object without null and undefined values. + * + * @package + * @since 1.0.0 + */ +function dropNullAndUndefined(obj) { + return Object.keys(obj).reduce((acc, key) => { + if (!isNullOrUndefined(obj[key])) acc[key] = obj[key]; + return acc; + }, {}); +} +TypeUtils.dropNullAndUndefined = dropNullAndUndefined; // Assign to `TypeUtils` + +module.exports = TypeUtils; diff --git a/lib/url-utils.js b/lib/utils/url-utils.js similarity index 96% rename from lib/url-utils.js rename to lib/utils/url-utils.js index eeb5900..2034c51 100644 --- a/lib/url-utils.js +++ b/lib/utils/url-utils.js @@ -1,17 +1,16 @@ /** - * A module provides utilities for working with YouTube URLs. + * A submodule provides utilities for working with YouTube URLs. * - * @module url-utils - * @requires utils - * @author Ryuu Mitsuki (https://github.com/mitsuki31) + * @module utils/url-utils + * @author Ryuu Mitsuki * @license MIT * @since 1.1.0 */ 'use strict'; -const { isNullOrUndefined } = require('./utils'); -const { IDExtractorError } = require('./error'); +const { isNullOrUndefined } = require('./type-utils'); +const { IDExtractorError } = require('../error'); /** diff --git a/lib/yt-urlfmt.js b/lib/utils/yt-urlfmt.js similarity index 97% rename from lib/yt-urlfmt.js rename to lib/utils/yt-urlfmt.js index 6f6fd93..f67cb49 100644 --- a/lib/yt-urlfmt.js +++ b/lib/utils/yt-urlfmt.js @@ -16,8 +16,8 @@ * This allows the library to handle a broader range of YouTube-related URLs * effectively. * - * @module yt-urlfmt - * @author Ryuu Mitsuki (https://github.com/mitsuki31) + * @module utils/yt-urlfmt + * @author Ryuu Mitsuki * @license MIT * @since 1.0.0 */ diff --git a/lib/ytmp3.js b/lib/ytmp3.js index db266ce..93a9456 100644 --- a/lib/ytmp3.js +++ b/lib/ytmp3.js @@ -33,8 +33,7 @@ * @version 1.1.0 * @requires audioconv * @requires utils - * @requires url-utils - * @author Ryuu Mitsuki (https://github.com/mitsuki31) + * @author Ryuu Mitsuki * @license MIT * @since 1.0.0 */ @@ -55,6 +54,7 @@ const { LOGDIR, logger: log, ProgressBar, + URLUtils, createDirIfNotExist, createDirIfNotExistSync, createLogFile @@ -64,7 +64,6 @@ const { convertAudio, defaultOptions: defaultAudioConvOptions } = require('./audioconv'); -const URLUtils = require('./url-utils'); /** * The video information object. diff --git a/test/irl.test.mjs b/test/irl.test.mjs index 30d2c51..cc88f6c 100644 --- a/test/irl.test.mjs +++ b/test/irl.test.mjs @@ -13,7 +13,7 @@ import ffmpeg from 'fluent-ffmpeg'; import audioconv from '../lib/audioconv.js'; import ytmp3 from '../lib/ytmp3.js'; -import utils from '../lib/utils.js'; +import utils from '../lib/utils/index.js'; const ffprobe = promisify(ffmpeg.ffprobe); const createTempPath = promisify(_createTempPath); diff --git a/test/unittest/audioconv.spec.mjs b/test/unittest/audioconv.spec.mjs index b6cb56e..88fbba0 100644 --- a/test/unittest/audioconv.spec.mjs +++ b/test/unittest/audioconv.spec.mjs @@ -5,7 +5,7 @@ import childProcess from 'node:child_process'; import { getTempPath } from '@mitsuki31/temppath'; import audioconv from '../../lib/audioconv.js'; -import utils from '../../lib/utils.js'; +import utils from '../../lib/utils/index.js'; describe('module:audioconv', function () { const testMessages = { diff --git a/test/unittest/config.spec.mjs b/test/unittest/config.spec.mjs index f13e2bf..8685b92 100644 --- a/test/unittest/config.spec.mjs +++ b/test/unittest/config.spec.mjs @@ -8,7 +8,7 @@ import { lsFiles } from 'lsfnd'; import { getTempPath } from '@mitsuki31/temppath'; import config from '../../lib/config.js'; -import utils from'../../lib/utils.js'; +import utils from '../../lib/utils/index.js'; import audioconv from '../../lib/audioconv.js'; import error from '../../lib/error.js'; const { diff --git a/test/unittest/url-utils.spec.mjs b/test/unittest/url-utils.spec.mjs index cac11ba..7d26be0 100644 --- a/test/unittest/url-utils.spec.mjs +++ b/test/unittest/url-utils.spec.mjs @@ -1,6 +1,6 @@ import assert from 'node:assert'; -import URLUtils from '../../lib/url-utils.js'; +import URLUtils from '../../lib/utils/url-utils.js'; import error from '../../lib/error.js'; const { IDExtractorError } = error; diff --git a/test/unittest/utils.spec.mjs b/test/unittest/utils.spec.mjs index ac47e0f..01c1b33 100644 --- a/test/unittest/utils.spec.mjs +++ b/test/unittest/utils.spec.mjs @@ -4,7 +4,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { getTempPath } from '@mitsuki31/temppath'; -import utils from '../../lib/utils.js'; +import utils from '../../lib/utils/index.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); diff --git a/test/unittest/yt-urlfmt.spec.mjs b/test/unittest/yt-urlfmt.spec.mjs index 79b5dd6..11437bf 100644 --- a/test/unittest/yt-urlfmt.spec.mjs +++ b/test/unittest/yt-urlfmt.spec.mjs @@ -1,6 +1,6 @@ import assert from 'node:assert'; -import yturlfmt from '../../lib/yt-urlfmt.js'; +import yturlfmt from '../../lib/utils/yt-urlfmt.js'; describe('module:yt-urlfmt', function () { const testMessage = 'check and validate regular expression'; diff --git a/test/unittest/ytmp3.spec.mjs b/test/unittest/ytmp3.spec.mjs index d2939db..cf5537b 100644 --- a/test/unittest/ytmp3.spec.mjs +++ b/test/unittest/ytmp3.spec.mjs @@ -5,7 +5,7 @@ import { getTempPath } from '@mitsuki31/temppath'; import ytmp3 from '../../lib/ytmp3.js'; import audioconv from '../../lib/audioconv.js'; -import utils from '../../lib/utils.js'; +import utils from '../../lib/utils/index.js'; const pkg = JSON.parse( fs.readFileSync(path.join(utils.ROOTDIR, 'package.json'), 'utf8'));