Skip to content

service

dev_tool.services.bun.service

log = logging.getLogger(__name__) module-attribute

BunService

Bases: BaseService

A service class for Bun/JavaScript operations.

This class provides methods for managing JavaScript packages, running tests, linting, and type checking.

The constructor for the BunService class.

Parameters:

  • runner (CommandRunnerProtocol) –

    The command runner for executing commands.

  • config (dict[str, Any] | None, default: None ) –

    The configuration dictionary for Bun settings.

Source code in dev_tool/services/bun/service.py
def __init__(self, runner: CommandRunnerProtocol, config: dict[str, Any] | None = None) -> None:
    """
    The constructor for the BunService class.

    :param runner: The command runner for executing commands.
    :param config: The configuration dictionary for Bun settings.
    """

    super().__init__()

    self.runner = runner
    self.config = config or {}
    self.test_directories = self.config.get('test_directories', ['tests/js'])
    self.source_directories = self.config.get('source_directories', ['static/js'])

runner = runner instance-attribute

config = config or {} instance-attribute

test_directories = self.config.get('test_directories', ['tests/js']) instance-attribute

source_directories = self.config.get('source_directories', ['static/js']) instance-attribute

build

A method that builds JavaScript bundles.

Raises:

  • BunBuildError

    If the build fails.

Source code in dev_tool/services/bun/service.py
def build(self) -> None:
    """
    A method that builds JavaScript bundles.

    :raises BunBuildError: If the build fails.
    """

    if not self._has_script('build'):
        message = 'No build script found in package.json'
        self.notification.warning_text(message)

        log.debug(message)
        return

    message = 'Building JavaScript bundles...'
    self.notification.normal_text(message)

    log.debug(message)

    result = self.runner.run_bun_command(['run', 'build'], check=False)

    if result.returncode != 0:
        message = 'JavaScript build failed'
        log.exception(message)

        raise BunBuildError(message)

    message = 'JavaScript build completed successfully'
    self.notification.normal_text(message)

    log.debug(message)

create_runner

A method that creates a Bun watcher runner.

Returns:

  • BunWatcherRunner | None

    A watcher runner if a dev script exists, None otherwise.

Source code in dev_tool/services/bun/service.py
def create_runner(self) -> BunWatcherRunner | None:
    """
    A method that creates a Bun watcher runner.

    :return: A watcher runner if a dev script exists, None otherwise.
    """

    if not self._has_script('dev'):
        return None

    from dev_tool.context import CONTEXT  # noqa: PLC0415
    from dev_tool.services.bun.runner import BunWatcherRunner  # noqa: PLC0415

    project_name = CONTEXT.configuration.get_project_name()
    return BunWatcherRunner(project_name=project_name)

format_code

A method that formats JavaScript/TypeScript code.

Parameters:

  • check_only (bool, default: False ) –

    Whether to only check formatting without making changes.

Source code in dev_tool/services/bun/service.py
def format_code(self, check_only: bool = False) -> None:
    """
    A method that formats JavaScript/TypeScript code.

    :param check_only: Whether to only check formatting without making changes.
    """

    message = 'Checking code formatting...' if check_only else 'Formatting code...'
    self.notification.normal_text(message)

    log.debug(message)

    if self._has_script('format'):
        script = 'format:check' if check_only and self._has_script('format:check') else 'format'
        self.runner.run_bun_command(['run', script], check=False)
    else:
        message = 'No format script found in package.json'
        self.notification.warning_text(message)

        log.debug(message)

install_dependencies

A method that installs JavaScript dependencies.

Parameters:

  • frozen (bool, default: False ) –

    Whether to use frozen lockfile (for CI).

Raises:

  • BunInstallError

    If installation fails.

Source code in dev_tool/services/bun/service.py
def install_dependencies(self, frozen: bool = False) -> None:
    """
    A method that installs JavaScript dependencies.

    :param frozen: Whether to use frozen lockfile (for CI).
    :raises BunInstallError: If installation fails.
    """

    message = 'Installing JavaScript dependencies...'
    self.notification.normal_text(message)

    log.debug(message)

    command = ['install']

    if frozen:
        command.append('--frozen-lockfile')

    result = self.runner.run_bun_command(command, check=False)

    if result.returncode != 0:
        message = 'Failed to install JavaScript dependencies'
        log.exception(message)

        raise BunInstallError(message)

    message = 'JavaScript dependencies installed successfully'
    self.notification.normal_text(message)

    log.debug(message)

install_package

A method that installs a single JavaScript package.

Parameters:

  • package (str) –

    The name of the package to install.

  • dev (bool, default: False ) –

    Whether to install as a dev dependency.

Raises:

  • BunInstallError

    If installation fails.

Source code in dev_tool/services/bun/service.py
def install_package(self, package: str, dev: bool = False) -> None:
    """
    A method that installs a single JavaScript package.

    :param package: The name of the package to install.
    :param dev: Whether to install as a dev dependency.
    :raises BunInstallError: If installation fails.
    """

    message = f'Installing {package}...'
    self.notification.normal_text(message)

    log.debug(message)

    command = ['add', package]

    if dev:
        command.append('--dev')

    result = self.runner.run_bun_command(command, check=False)

    if result.returncode != 0:
        message = f'Failed to install {package}'
        log.exception(message)

        raise BunInstallError(message)

    message = f'{package} installed successfully'
    self.notification.normal_text(message)

    log.debug(message)

is_available

A method that checks if Bun is available.

Returns:

  • bool

    True if Bun is available, False otherwise.

Source code in dev_tool/services/bun/service.py
def is_available(self) -> bool:
    """
    A method that checks if Bun is available.

    :return: True if Bun is available, False otherwise.
    """

    return shutil.which('bun') is not None

lint

A method that runs the linter on JavaScript/TypeScript code.

Parameters:

  • fix (bool, default: False ) –

    Whether to automatically fix linting issues.

Raises:

  • BunLintError

    If linting fails with errors.

Source code in dev_tool/services/bun/service.py
def lint(self, fix: bool = False) -> None:
    """
    A method that runs the linter on JavaScript/TypeScript code.

    :param fix: Whether to automatically fix linting issues.
    :raises BunLintError: If linting fails with errors.
    """

    message = 'Running linter...'
    self.notification.normal_text(message)

    log.debug(message)

    if self._has_script('lint'):
        script = 'lint:fix' if fix and self._has_script('lint:fix') else 'lint'
        result = self.runner.run_bun_command(['run', script], check=False)

        if result.returncode != 0 and not fix:
            message = 'Linting found issues'
            log.exception(message)

            raise BunLintError(message)
    else:
        message = 'No lint script found in package.json'
        self.notification.warning_text(message)

        log.debug(message)

outdated

A method that checks for outdated packages.

Source code in dev_tool/services/bun/service.py
def outdated(self) -> None:
    """A method that checks for outdated packages."""

    message = 'Checking for outdated packages...'
    self.notification.normal_text(message)

    log.debug(message)

    self.runner.run_bun_command(['outdated'], check=False)

run_tests

A method that runs JavaScript tests using Bun's test runner.

Parameters:

  • watch (bool, default: False ) –

    Whether to run tests in watch mode.

  • coverage (bool, default: False ) –

    Whether to collect coverage.

  • bail (bool, default: False ) –

    Whether to stop on first failure.

Raises:

  • BunTestError

    If tests fail.

Source code in dev_tool/services/bun/service.py
def run_tests(self, watch: bool = False, coverage: bool = False, bail: bool = False) -> None:
    """
    A method that runs JavaScript tests using Bun's test runner.

    :param watch: Whether to run tests in watch mode.
    :param coverage: Whether to collect coverage.
    :param bail: Whether to stop on first failure.
    :raises BunTestError: If tests fail.
    """

    message = 'Running JavaScript tests...'
    self.notification.normal_text(message)

    log.debug(message)

    command = ['test']

    for directory in self.test_directories:
        path = BASE / directory

        if path.exists():
            command.append(directory)

    if watch:
        command.append('--watch')

    if coverage:
        command.append('--coverage')

    if bail:
        command.append('--bail')

    result = self.runner.run_bun_command(command, check=False)

    if result.returncode != 0:
        message = 'JavaScript tests failed'
        log.exception(message)

        raise BunTestError(message)

    if result.stdout:
        print(result.stdout.decode() if isinstance(result.stdout, bytes) else result.stdout)  # noqa: T201

    message = 'JavaScript tests passed'
    self.notification.normal_text(message)

    log.debug(message)

uninstall_package

A method that uninstalls a JavaScript package.

Parameters:

  • package (str) –

    The name of the package to uninstall.

Source code in dev_tool/services/bun/service.py
def uninstall_package(self, package: str) -> None:
    """
    A method that uninstalls a JavaScript package.

    :param package: The name of the package to uninstall.
    """

    message = f'Uninstalling {package}...'
    self.notification.normal_text(message)

    log.debug(message)

    self.runner.run_bun_command(['remove', package], check=False)

    message = f'{package} uninstalled successfully'
    self.notification.normal_text(message)

    log.debug(message)

upgrade_packages

A method that upgrades all JavaScript packages to their latest versions.

Source code in dev_tool/services/bun/service.py
def upgrade_packages(self) -> None:
    """A method that upgrades all JavaScript packages to their latest versions."""

    message = 'Upgrading JavaScript packages...'
    self.notification.normal_text(message)

    log.debug(message)

    self.runner.run_bun_command(['update'], check=False)

    message = 'JavaScript packages upgraded successfully'
    self.notification.normal_text(message)

    log.debug(message)