open-index/open-npm huggingface dataset:
npm package: @jsenv/abort
Description: Help to write code compatible with abort signals
Author: dmail
Latest version: 4.3.1

# Abort [![npm package](https://img.shields.io/npm/v/@jsenv/abort.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/abort)

Help to write code accepting an [abortSignal](https://nodejs.org/api/globals.html#class-abortsignal).

- Designed to cleanup by default (removing event listeners, clearing timeouts, ...)
- Allow to safely bypass max listeners warning when needed
  - Code can do 20 abortable fetch requests in parallel without warnings
- Manage multiple abort signals
  - Compose abort signals from multiple sources
  - Code can do differents things depending on which signal aborted the operation

# Example

_fetch_demo.mjs_

```js
import { customFetch } from "./fetch_custom.mjs";

const abortController = new AbortController();
const signal = abortController.signal;
process.on("warning", () => {
  abortController.abort();
});
await customFetch("http://example.com", { signal });
```

Code above pass an abort signal to `customFetch`.

Let's see how `"@jsenv/abort"` helps to manage the signal received.

_fetch_custom.mjs_

```js
import { Abort } from "@jsenv/abort"

export const customFetch = (
  url,
  { signal = new AbortController().signal } = {},
) => {
  // create an operation
  const fetchOperation = Abort.startOperation()

  // abort according to signal received in param
  fetchOperation.addAbortSignal(signal)

  // also abort on SIGINT
  const SIGINTAbortSource = fetchOperation.addAbortSource((abort) => {
    process.on("SIGINT", abort)
    return () => {
      process.removeListener("SIGINT", abort)
    }
  })

  // also abort after 5s
  const timeoutAbortSource = fetchOperation.timeout(5000)

  try {
    const response = await fetch(url, { signal: fetchOperation.signal })
    return response
  } catch (e) {
    if (Abort.isAbortError(e)) {
      if (SIGINTAbortSource.signal.aborted) {
        // aborted by SIGINT
      }
      if (timeoutAbortSource.signal.aborted) {
        // aborted by timeout
      }
      if (signal.aborted) {
        // aborted from outside
      }
    }
    throw e
  } finally {
    await fetchOperation.end()
  }
}
```
npm package: @jsenv/auto-publish
Description: Auto publish package to github and npm
Latest version: 2.0.0

# Continuous package publish

[![github package](https://img.shields.io/github/package-json/v/jsenv/jsenv-auto-publish.svg?logo=github&label=package)](https://github.com/jsenv/jsenv-auto-publish/packages)
[![npm package](https://img.shields.io/npm/v/@jsenv/auto-publish.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/auto-publish)
[![github ci](https://github.com/jsenv/jsenv-auto-publish/workflows/ci/badge.svg)](https://github.com/jsenv/jsenv-auto-publish/actions?workflow=ci)
[![codecov coverage](https://codecov.io/gh/jsenv/jsenv-auto-publish/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-auto-publish)

Auto publish your package to npm and github registry whenever package.json version changes on master.

## Table of contents

- [Presentation](#Presentation)
- [Usage](#Usage)
- [Installation](#installation)

## Presentation

This github repository corresponds to `@jsenv/continuous-package-publish` package published on github and npm package registries.

TODO: one more sentence to explain why it exists and what it does

## Usage

TODO

## Installation

TODO
npm package: @jsenv/auto-publish-package
Description: Auto publish package to github and npm
Latest version: 1.0.0

# Continuous package publish

[![github package](https://img.shields.io/github/package-json/v/jsenv/jsenv-auto-publish.svg?logo=github&label=package)](https://github.com/jsenv/jsenv-auto-publish/packages)
[![npm package](https://img.shields.io/npm/v/@jsenv/auto-publish.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/auto-publish)
[![github ci](https://github.com/jsenv/jsenv-auto-publish/workflows/ci/badge.svg)](https://github.com/jsenv/jsenv-auto-publish/actions?workflow=ci)
[![codecov coverage](https://codecov.io/gh/jsenv/jsenv-auto-publish/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-auto-publish)

Auto publish your package to npm and github registry whenever package.json version changes on master.

## Table of contents

- [Presentation](#Presentation)
- [Usage](#Usage)
- [Installation](#installation)

## Presentation

This github repository corresponds to `@jsenv/continuous-package-publish` package published on github and npm package registries.

TODO: one more sentence to explain why it exists and what it does

## Usage

TODO

## Installation

TODO
npm package: @jsenv/babel-config-map
Description: [![npm package](https://img.shields.io/npm/v/@jsenv/babel-config-map.svg)](https://www.npmjs.com/package/@jsenv/babel-config-map) [![build](https://travis-ci.com/jsenv/jsenv-babel-config-map.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-babel-confi
Latest version: 1.0.0

# jsenv-babel-plugin-description

[![npm package](https://img.shields.io/npm/v/@jsenv/babel-config-map.svg)](https://www.npmjs.com/package/@jsenv/babel-config-map)
[![build](https://travis-ci.com/jsenv/jsenv-babel-config-map.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-babel-config-map)
npm package: @jsenv/babel-plugin-description
Description: [![npm package](https://img.shields.io/npm/v/@jsenv/babel-plugin-description.svg)](https://www.npmjs.com/package/@jsenv/babel-plugin-description) [![build](https://travis-ci.com/jsenv/jsenv-babel-plugin-description.svg?branch=master)](http://travis-ci.com
Latest version: 3.0.0

# jsenv-babel-plugin-description

[![npm package](https://img.shields.io/npm/v/@jsenv/babel-plugin-description.svg)](https://www.npmjs.com/package/@jsenv/babel-plugin-description)
[![build](https://travis-ci.com/jsenv/jsenv-babel-plugin-description.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-babel-plugin-description)
npm package: @jsenv/babel-plugin-map
Description: [![npm package](https://img.shields.io/npm/v/@jsenv/babel-plugin-map.svg)](https://www.npmjs.com/package/@jsenv/babel-plugin-map) [![build](https://travis-ci.com/jsenv/jsenv-babel-plugin-map.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-babel-plugi
Latest version: 3.1.0

# jsenv-babel-plugin-map

[![npm package](https://img.shields.io/npm/v/@jsenv/babel-plugin-map.svg)](https://www.npmjs.com/package/@jsenv/babel-plugin-map)
[![build](https://travis-ci.com/jsenv/jsenv-babel-plugin-map.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-babel-plugin-map)
npm package: @jsenv/babel-preset
Description: Set of babel plugins to use with jsenv
Latest version: 1.1.3

# @jsenv/babel-preset [![npm package](https://img.shields.io/npm/v/@jsenv/babel-preset.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/babel-preset)

`@jsenv/babel-preset` is equivalent to [@babel/preset-env](https://babeljs.io/docs/en/babel-preset-env) with the following differences:

1 - Prefer [transform-async-to-promises](https://www.npmjs.com/package/babel-plugin-transform-async-to-promises) over [transform-async-to-generator](https://babeljs.io/docs/en/babel-plugin-transform-async-to-generator) [^1]

2 - List only babel plugins with at least one browser implementing the feature

[^1]: This is because generator are more verbose and slow than promises. See https://github.com/babel/babel/issues/8121

## Usage

```console
npm install --save-dev @jsenv/babel-preset
```

_babel.config.cjs:_

```js
module.exports = {
  presets: ["@jsenv/babel-preset"],
}
```
npm package: @jsenv/browser-detection
Description: Browser detection script.
Latest version: 1.0.0

# browser detection

Browser detection script.

[![github package](https://img.shields.io/github/package-json/v/jsenv/jsenv-browser-detection.svg?logo=github&label=package)](https://github.com/jsenv/jsenv-browser-detection/packages)
[![npm package](https://img.shields.io/npm/v/@jsenv/browser-detection.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/browser-detection)
[![github ci](https://github.com/jsenv/jsenv-browser-detection/workflows/ci/badge.svg)](https://github.com/jsenv/jsenv-browser-detection/actions?workflow=ci)
[![codecov coverage](https://codecov.io/gh/jsenv/jsenv-browser-detection/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-browser-detection)

## Example

```html
<html>
  <head>
    <script type="module">
      import { detectBrowser } from "https://unpkg.com/@jsenv/browser-detection@latest/dist/esmodule/main.js"

      console.log(detectBrowser())
    </script>
  </head>
</html>
```
npm package: @jsenv/chromium-launcher
Description: [![npm package](https://img.shields.io/npm/v/@jsenv/chromium-launcher.svg)](https://www.npmjs.com/package/@jsenv/chromium-launcher) [![build](https://travis-ci.com/jsenv/jsenv-chromium-launcher.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-chromium
Latest version: 3.9.0

# jsenv chromium launcher

[![npm package](https://img.shields.io/npm/v/@jsenv/chromium-launcher.svg)](https://www.npmjs.com/package/@jsenv/chromium-launcher)
[![build](https://travis-ci.com/jsenv/jsenv-chromium-launcher.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-chromium-launcher)
[![codecov](https://codecov.io/gh/jsenv/jsenv-chromium-launcher/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-chromium-launcher)

This module exports a function called `launchChromium` you can use together with `jsenv`.<br />
— see [jsenv project on github](https://github.com/jsenv/jsenv-core)

## `launchChromium` options

### headless

> Controls launched chromium headless mode.

```js
import { launchChromium } from "@jsenv/chromium-launcher"

const launchChromiumWithInterface = (options) => launchChromium({ ...options, headless: false })
```

When true, launched chromium browser will be headless.<br />
When false, launched chromium browser will have a graphic interface.

If you don't pass `headless` option, its value will be:

```js
true
```
npm package: @jsenv/cli
Description: Command Line Interface for jsenv
Author: dmail
Latest version: 0.3.92

# @jsenv/cli

[![npm package](https://img.shields.io/npm/v/@jsenv/cli.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/cli)

## Overview

_@jsenv/cli_ is a command-line tool for quickly setting up JavaScript projects with jsenv configurations and best practices.

It provides templates for various project types to get you started immediately.

## Installation & Usage

Run the CLI directly with npx:

```console
npx @jsenv/cli
```

> `npx` command is installed with Node.js. If you don't have it, you must [install Node.js](https://nodejs.org/en/download/package-manager).

## Getting Started

The command initializes jsenv in a directory. It can be a new directory or an existing one.

```console
> npx @jsenv/cli
Welcome in jsenv CLI
? Enter a directory: ›
```

## Templates

After specifying a directory, you'll be prompted to select a template:

```console
> npx @jsenv/cli
✔ Enter a directory: › demo
? Select a template: › - Use arrow-keys. Return to submit.
❯   web
    web-components
    web-react
    web-preact
    node-package
```

### Available Templates

- **web**: Basic web application with HTML, CSS, and JavaScript
- **web-components**: Project setup for creating reusable web components
- **web-react**: React-based web application configuration
- **web-preact**: Preact-based web application (lighter alternative to React)
- **node-package**: Configuration for creating a Node.js package

A template is a project pre-configured with jsenv. For example, selecting "web" would initialize the [web template](https://github.com/jsenv/core/tree/main/packages/related/cli/template-web):

```console
> npx @jsenv/cli
✔ Enter a directory: › demo
✔ Select a template: › web
✔ init jsenv in "[...]/demo/" (done in 0.01 second)
----- 3 commands to run -----
cd demo
npm install
npm start
-----------------------------
```

## Next Steps

After initialization:

1. Navigate to your project directory: `cd your-directory`
2. Install dependencies: `npm install`
3. Start the development server: `npm start`
npm package: @jsenv/codecov-upload
Description: Upload coverage to codecov.io during a github workflow.
Latest version: 3.5.0

# codecov-upload

Upload coverage to codecov.io during a GitHub workflow.

[![npm package](https://img.shields.io/npm/v/@jsenv/codecov-upload.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/codecov-upload)
[![github ci](https://github.com/jsenv/jsenv-codecov-upload/workflows/ci/badge.svg)](https://github.com/jsenv/jsenv-codecov-upload/actions?workflow=ci)
[![codecov coverage](https://codecov.io/gh/jsenv/jsenv-codecov-upload/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-codecov-upload)
npm package: @jsenv/commonjs-converter
Description: Convert commonjs to ES modules
Latest version: 3.0.0

# commonjs converter

[![github package](https://img.shields.io/github/package-json/v/jsenv/jsenv-commonjs-converter.svg?logo=github&label=package)](https://github.com/jsenv/jsenv-commonjs-converter/packages)
[![npm package](https://img.shields.io/npm/v/@jsenv/commonjs-converter.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/commonjs-converter)
[![github ci](https://github.com/jsenv/jsenv-commonjs-converter/workflows/ci/badge.svg)](https://github.com/jsenv/jsenv-commonjs-converter/actions?workflow=ci)
[![codecov coverage](https://codecov.io/gh/jsenv/jsenv-commonjs-converter/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-commonjs-converter)

Convert commonjs to ES modules.
npm package: @jsenv/compile-server
Description: [![github package](https://img.shields.io/github/package-json/v/jsenv/jsenv-compile-server.svg?label=package&logo=github)](https://github.com/jsenv/jsenv-compile-server/packages) [![ci status](https://github.com/jsenv/jsenv-compile-server/workflows/ci/bad
Latest version: 6.19.0

# jsenv-compile-server

[![github package](https://img.shields.io/github/package-json/v/jsenv/jsenv-compile-server.svg?label=package&logo=github)](https://github.com/jsenv/jsenv-compile-server/packages)
[![ci status](https://github.com/jsenv/jsenv-compile-server/workflows/ci/badge.svg)](https://github.com/jsenv/jsenv-compile-server/actions)
[![codecov](https://codecov.io/gh/jsenv/jsenv-compile-server/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-compile-server)
npm package: @jsenv/core
Description: Tool to develop, test and build js projects
Author: dmail
Latest version: 40.12.13

# @jsenv/core

[![npm package](https://img.shields.io/npm/v/@jsenv/core.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/core)

## Overview

Jsenv is a suite of tools for JavaScript projects that prioritizes standards and simplicity, making it ideal for both beginners and those who need straightforward tools.

## Installation

```console
npm install --save-dev @jsenv/core
```

> **Compatibility**: Mac, Windows, and Linux with Node.js 25.

## Documentation

For comprehensive documentation, see the full [user documentation](https://github.com/jsenv/core/blob/main/docs/users/users.md).

## Basic Usage

Start a development server:

```js
import { startDevServer } from "@jsenv/core";

await startDevServer({
  sourceDirectoryUrl: import.meta.resolve("./"),
});
```

## Core Features

`@jsenv/core` provides four main tools:

1. **Dev Server**: Serves source files with live reloading to facilitate development
2. **Build**: Optimizes source files into a specified directory for production
3. **Build Server**: Serves the built files, allowing for testing and verifying the production build
4. **Test Runner**: Runs test files concurrently to ensure code reliability

## Key Advantages

- **Standards-first approach**: Built on web standards rather than custom abstractions
- **Robust versioning**: Avoids cascading hash changes during builds
- **Broad browser compatibility**: Works with modern and older browsers
- **Isolated testing**: Prevents cross-test contamination
- **Simple API**: Designed for clarity and ease of use

## Quick Start

The easiest way to try jsenv is with the CLI:

```console
npx @jsenv/cli
```

The CLI provides templates for web applications, React projects, and Node.js packages to get you started quickly.

Read more in [@jsenv/cli](https://github.com/jsenv/core/tree/main/packages/related/cli#jsenvcli).
npm package: @jsenv/custom-elements-redefine
Description: Allow WebComponent re-definition at runtime
Author: dmail
Latest version: 0.0.1

# custom-elements-redefine [![npm package](https://img.shields.io/npm/v/@jsenv/custom-elements-redefine.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/custom-elements-redefine)

This package overrides [customElements.define](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define) to allow re-defining an element constructor.

It prevents the following error to happen:

```console
Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry': the name "my-test" has already been used with this registry
```

The goal is to make code using custom elements compatible with hot reloading: ability to reload js instead of having to reload the whole page.

It fixes issues like https://github.com/lit/lit/issues/1844
This package is a modified version of https://github.com/vegarringdal/custom-elements-hmr-polyfill

```js
import { allowCustomElementsRedefine } from "@jsenv/custom-elements-redefine";

allowCustomElementsRedefine();

customElements.define(
  "my-element",
  class extends HTMLElement {
    version = 1;
  },
);
document.createElement("my-element").version; // 1
customElements.define(
  "my-element",
  class extends HTMLElement {
    version = 2;
  },
);
document.createElement("my-element").version; // 2
```
npm package: @jsenv/dynamic-import-worker
Description: Bypass node cache on dynamic import thanks to worker
Author: dmail
Latest version: 1.2.1

# Dynamic import worker [![npm package](https://img.shields.io/npm/v/@jsenv/dynamic-import-worker.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/dynamic-import-worker)

Bypass node cache on dynamic import thanks to worker

# Example

_docs/demo/random_number.mjs_

```js
export const randomNumber = Math.random();
```

_docs/demo/demo.mjs_

```js
import { importOneExportFromFile } from "@jsenv/dynamic-import-worker";

const randomNumberFileUrl = new URL(
  "./random_number.mjs#randomNumber",
  import.meta.url,
);

const randomNumberA = await importOneExportFromFile(randomNumberExportUrl);
const randomNumberB = await importOneExportFromFile(randomNumberExportUrl);

console.log(randomNumberA);
console.log(randomNumberB);
```

```console
> node ./docs/demo/demo.mjs
0.5362418125287491
0.35129949391010595
```
npm package: @jsenv/error-stack-sourcemap
Description: [![npm package](https://img.shields.io/npm/v/@jsenv/error-stack-sourcemap.svg)](https://www.npmjs.com/package/@jsenv/error-stack-sourcemap) [![build](https://travis-ci.com/jsenv/jsenv-error-stack-sourcemap.svg?branch=master)](http://travis-ci.com/jsenv/js
Latest version: 3.3.0

# jsenv error stack sourcemap

[![npm package](https://img.shields.io/npm/v/@jsenv/error-stack-sourcemap.svg)](https://www.npmjs.com/package/@jsenv/error-stack-sourcemap)
[![build](https://travis-ci.com/jsenv/jsenv-error-stack-sourcemap.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-error-stack-sourcemap)
[![codecov](https://codecov.io/gh/jsenv/jsenv-error-stack-sourcemap/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-error-stack-sourcemap)
npm package: @jsenv/eslint-config-relax
Description: A pleaseant ESLint configuration for any project
Author: dmail
Latest version: 1.8.1

# eslint-config-relax

[![npm package](https://img.shields.io/npm/v/@jsenv/eslint-config-relax.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/eslint-config-relax)

A pragmatic ESLint configuration that focuses on meaningful errors while giving you freedom to write code your way.

## Why Choose eslint-config-relax?

If you're tired of:

- Fighting with ESLint configuration
- Being forced to code in a specific style
- Module resolution errors in ESLint
- Noisy linting that focuses on trivial issues

eslint-config-relax lets you focus on writing code while still catching potential bugs and serious issues.

## Quick setup

```console
npm i --save-dev @jsenv/eslint-config-relax
```

Create an `eslint.config.js` file at your project root:

```js
import { eslintConfigRelax } from "@jsenv/eslint-config-relax";

export default eslintConfigRelax({
  rootDirectoryUrl: import.meta.resolve("./"),
  browserDirectoryUrl: import.meta.resolve("./src/"), // optional
});
```

## Key Features

### Focus on Real Issues

We disable rules that are:

- Purely stylistic
- Too opinionated
- More annoying than helpful

So you only see warnings that actually matter for code quality.

### Working Import Resolution

Full implementation of Node.js ESM resolution algorithm means:

- No more "Unable to resolve path to module" errors for valid imports
- Correct browser vs Node.js environment detection
- Proper handling of package exports

### Modern & Simple

- Uses ESLint's flat config system
- No complex plugin chains or configuration inheritance
- Works across various project types with minimal setup

### Environment Aware

Automatically adjusts rules based on your code's environment:

- Browser-specific checks for browser code
- Node.js-specific checks for server code

## Technical Notes

- Requires ESLint 8.0 or higher (uses flat config)
- TypeScript support planned for future releases
- Works with any project structure

## Example project structure

```
your-project/
├── eslint.config.js
├── package.json
├── src/                // Browser code
│   └── browser-specific-code.js
└── server/             // Node.js code
    └── node-specific-code.js
```

Migrate from traditional ESLint and enjoy writing code that's checked for what matters, not how it looks.
npm package: @jsenv/eslint-import-resolver
Description: Implement Node.js import resolution algorithm for ESLint.
Author: dmail
Latest version: 8.4.3

# @jsenv/eslint-import-resolver [![npm package](https://img.shields.io/npm/v/@jsenv/eslint-import-resolver.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/eslint-import-resolver)

Implement Node.js import resolution algorithm for ESLint.

# Usage

This section shows how to create a very basic ESLint configuration doing the following:

1. Enable [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import)
2. Enable [import/no-unresolved](https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-unresolved.md)
3. Configure [import/resolver](https://github.com/import-js/eslint-plugin-import#resolvers) with `@jsenv/eslint-import-resolver`

```console
npm install --save-dev eslint-plugin-import
npm install --save-dev @jsenv/eslint-import-resolver
```

```cjs
// .eslintrc.cjs
module.exports = {
  plugins: ["import"],
  rules: {
    "import/no-unresolved": ["error"],
  },
  settings: {
    "import/resolver": {
      "@jsenv/eslint-import-resolver": {
        rootDirectoryUrl: __dirname,
        packageConditions: ["browser", "import"],
      },
    },
  },
};
```

See also https://github.com/jsenv/eslint-config#advanced-configuration-example
npm package: @jsenv/exploring-server
Description: [![npm package](https://img.shields.io/npm/v/@jsenv/exploring-server.svg)](https://www.npmjs.com/package/@jsenv/exploring-server) [![build](https://travis-ci.com/jsenv/jsenv-exploring-server.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-exploring-s
Latest version: 3.11.0

# jsenv exploring server

[![npm package](https://img.shields.io/npm/v/@jsenv/exploring-server.svg)](https://www.npmjs.com/package/@jsenv/exploring-server)
[![build](https://travis-ci.com/jsenv/jsenv-exploring-server.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-exploring-server)
[![codecov](https://codecov.io/gh/jsenv/jsenv-exploring-server/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-exploring-server)

## Introduction

`@jsenv/exploring-server` starts a server creating an html page listing your project files.<br />
Each link goes to an url where your JavaScript file will be executed.<br />
Thanks to this, any file or your project can become an entry point. You can use it to debug a file in isolation or even to create a storybook.

It has the following exports:

- `startExploringServer`

## How to use

To understand how to use jsenv exploring server let's use it on a "real" project.<br />
We will setup a basic project and start an exploring server inside it.

### Steps to start exploring server on a basic project

1. Create basic project file structure

   — see [./docs/basic-project](./docs/basic-project)

2. Install dependencies

   ```console
   npm install
   ```

3. Start the exploring server

   ```console
   node ./start-exploring-server.js
   ```

### Using the exploring server

A first main server will start. This one is used by the whole jsenv project.<br />
A second server will start. That's the one we're interested in right now. The url `http://127.0.0.1:3456` is logged in your terminal.<br />

Once server is started you can navigate to `http://127.0.0.1:3456` and you will see an html page listing the files you can explore.

![exploring server chome screenshot](./docs/exploring-server-chrome-screenshot.png)

- If you go to `http://127.0.0.1:3456/src/hello.js` page displays `Hello world`.
  It shows that if your file execution renders something, you can see the effect in your browser.
- If you go to `http://127.0.0.1:3456/src/text.js` nothing special will happen because `/src/text.js` is just a module with an export default.<br />
  It shows that even if your file do not render anything, you still can use this functionnality to debug your file.

Here is a gif showing me browing basic project files:

![recording of me exploring a project using chrome](./docs/exploring-with-chrome-recording.gif)

If you want to know more about `startExploringServer`, there is a dedicated page for that.<br />
— see [`startExploringServer` documentation](./docs/start-exploring-server-doc.md)

## Installation

```console
npm install --save-dev @jsenv/exploring-server@3.7.0
```

```console
yarn add @jsenv/exploring-server@3.7.0 --dev
```
npm package: @jsenv/fetch
Description: Unified url fetcher (http, http, file, data)
Author: dmail
Latest version: 1.3.19

# fetchUrl

`fetchUrl` is an async function requesting an url and returning a response object. It is a small wrapper on top of [node-fetch](https://github.com/node-fetch/node-fetch). It was created to provide a unified approach to request file and data urls.

```js
import { fetchUrl } from "@jsenv/fetch";

const responseForFile = await fetchUrl("file:///Users/you/index.html", {
  method: "GET",
  headers: {
    "if-modified-since": "Wed, 21 Oct 2015 07:28:00 GMT",
  },
});

const responseForHttp = await fetchUrl("http://example.com/file.js", {
  method: "GET",
  headers: {
    "if-modified-since": "Wed, 21 Oct 2015 07:28:00 GMT",
  },
});
```
npm package: @jsenv/git-hooks
Description: Declare git hooks in your package.json.
Latest version: 1.3.3

# git-hooks

Declare git hooks in your package.json.

[![github package](https://img.shields.io/github/package-json/v/jsenv/jsenv-git-hooks.svg?logo=github&label=package)](https://github.com/jsenv/jsenv-git-hooks/packages)
[![npm package](https://img.shields.io/npm/v/@jsenv/git-hooks.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/git-hooks)
[![github ci](https://github.com/jsenv/jsenv-git-hooks/workflows/ci/badge.svg)](https://github.com/jsenv/jsenv-git-hooks/actions?workflow=ci)
[![codecov coverage](https://codecov.io/gh/jsenv/jsenv-git-hooks/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-git-hooks)

# Table of contents

- [Presentation](#Presentation)
- [Installation](#Installation)
- [Documentation](#Documentation)
  - [installGitHooks](#installGitHooks)
    - [projectDirectoryUrl](#projectDirectoryUrl)
    - [logLevel](#logLevel)
  - [uninstallGitHooks](#uninstallGitHooks)
- [Why](#Why)

# Presentation

`@jsenv/git-hooks` create a git hook for every scripts your package.json matching `git-hook-*`.

# Installation

```console
npm install @jsenv/git-hooks@1.3.0
```

```js
import { installGitHooks } from "@jsenv/git-hooks"

installGitHooks({
  projectDirectoryUrl: "file:///directory",
})
```

If you use node < 13 you can use the commonjs export.

```js
const { installGitHooks } = require("@jsenv/git-hooks")
```

# Documentation

## installGitHooks

`installGitHooks` is an async function writing a hook file for every git hook script declared in a project package.json.

```js
import { installGitHooks } from "@jsenv/git-hooks"

await installGitHooks({
  projectDirectoryUrl: "file:///directory",
  logLevel: "info",
})
```

— source code at [src/installGitHooks.js](./src/installGitHooks.js).

### projectDirectoryUrl

`projectDirectoryUrl` parameter is a string leading to a directory as documented in https://github.com/jsenv/jsenv-util#assertandnormalizedirectoryurl. It is used to locate your package.json and the directory where git hooks will be written.

### logLevel

`logLevel` parameter is a string controlling the verbosity of logs during function exectuion as documented in https://github.com/jsenv/jsenv-logger#logLevel.

## uninstallGitHooks

`uninstallGitHooks` is an async function removing all git hooks installed by installGitHooks.

```js
import { uninstallGitHooks } from "@jsenv/git-hooks"

await uninstallGitHooks({
  projectDirectoryUrl: "file:///directory",
  logLevel: "info",
})
```

— source code at [src/uninstallGitHooks.js](./src/uninstallGitHooks.js).

# Why

I wanted a git precommit hook to run prettier on staged files as documented in https://prettier.io/docs/en/precommit.html.

I wanted to declare my hooks in package.json script to benefit from vscode script explorer feature, see [npm.enableScriptExplorer](https://code.visualstudio.com/docs/getstarted/tips-and-tricks#_run-npm-scripts-as-tasks-from-the-explorer).

After that I discovered husky, https://github.com/typicode/husky, which could do the job but they have deprecated declaring hooks inside scripts field.
npm package: @jsenv/github-check-run
Description: Interact with GitHub check rest API
Author: dmail
Latest version: 0.3.9

# GitHub check run [![npm package](https://img.shields.io/npm/v/@jsenv/github-check-run.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/github-check-run)

```js
import { startGithubCheckRun } from "@jsenv/github-check-run";

const values = [1_000, 2_000, 4_000];

const githubCheck = await startGithubCheckRun({
  githubToken: "",
  repositoryOwner: "dmail",
  repositoryName: "repo-name",
  commitSha: "",
  checkName: "demo",
  checkTitle: "Running demo",
  checkSummary: `preparing execution of ${values.length} timeouts`,
});

try {
  let index = 0;
  for (const value of values) {
    githubCheck.progress({
      summary: `executing timeout ${index + 1}/${values.length}`,
    });
    await new Promise((resolve) => {
      setTimeout(resolve, value);
    });
    index++;
  }
  await githubCheck.pass({
    summary: `${values.length} timeout execution done`,
  });
} catch (e) {
  await githubCheck.fail({
    summary: `error while executing timeout number ${index + 1}: ${e.stack}`,
  });
}
```

If the code is executed inside a Github workflow, several parameters can be retrieved using `readGitHubWorkflowEnv`:

```js
import {
  startGithubCheckRun,
  readGitHubWorkflowEnv,
} from "@jsenv/github-check-run";

const githubCheck = await startGithubCheckRun({
  ...readGitHubWorkflowEnv(),
  checkName: "demo",
  checkTitle: "Running demo",
  checkSummary: `Executing ${values.length} setTimeouts`,
});
```
npm package: @jsenv/github-pull-request-impact
Description: Report pull request impact on something
Latest version: 1.8.42

# GitHub pull request impact [![npm package](https://img.shields.io/npm/v/@jsenv/github-pull-request-impact.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/github-pull-request-impact)

Report pull request impact on something.

# Presentation

Under construction.

This repository publishes `@jsenv/github-pull-request-impact` on NPM. This package is reused internally by:

- [@jsenv/performance-impact](../performance-impact)
- [@jsenv/file-size-impact](../file-size-impact)
- [@jsenv/lighthouse-impact](../lighthouse-impact)
npm package: @jsenv/github-release-package
Description: Create github release when package version changes.
Latest version: 1.6.42

# Github Release Package [![npm package](https://img.shields.io/npm/v/@jsenv/github-release-package.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/github-release-package)

Create github release for package version updates.
npm package: @jsenv/grouping
Description: [![npm package](https://img.shields.io/npm/v/@jsenv/grouping.svg)](https://www.npmjs.com/package/@jsenv/grouping) [![build](https://travis-ci.com/jsenv/jsenv-grouping.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-grouping) [![codecov](https://codec
Latest version: 2.1.0

# jsenv grouping

[![npm package](https://img.shields.io/npm/v/@jsenv/grouping.svg)](https://www.npmjs.com/package/@jsenv/grouping)
[![build](https://travis-ci.com/jsenv/jsenv-grouping.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-grouping)
[![codecov](https://codecov.io/gh/jsenv/jsenv-grouping/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-grouping)
npm package: @jsenv/href
Description: url helpers not relying on URL constructor
Latest version: 1.2.0

# Href

[![github package](https://img.shields.io/github/package-json/v/jsenv/jsenv-href.svg?logo=github&label=package)](https://github.com/jsenv/jsenv-href/packages)
[![npm package](https://img.shields.io/npm/v/@jsenv/href.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/href)
[![github ci](https://github.com/jsenv/jsenv-href/workflows/ci/badge.svg)](https://github.com/jsenv/jsenv-href/actions?workflow=ci)
[![codecov coverage](https://codecov.io/gh/jsenv/jsenv-href/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-href)

url helpers not relying on URL constructor.
npm package: @jsenv/humanize
Description: Generate messages meant to read by humans
Latest version: 1.7.6

# humanize [![npm package](https://img.shields.io/npm/v/@jsenv/humanize.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/humanize)

`@jsenv/humanize` helps to generate messages meant to be read by humans

It is written in ES6 and compatible with browsers and Node.js.

# API

## humanize(jsValue)

Turns a JavaScript value into a string meant to be read by a human.

```js
import { humanize } from "@jsenv/humanize";

console.log(
  humanize({
    boolean: true,
    number: 10,
    string: "hello world",
  }),
);
```

```console
{
  "boolean": true,
  "number": 10,
  "string": "hello world"
}
```

### Comparison with JSON.stringify

Table comparing `JSON.stringify` and `humanize()` to demonstrates how inspect focuses on readability and accuracy.

| value     | JSON.stringify | humanize    |
| --------- | -------------- | ----------- |
| 123456789 | "123456789"    | 123_456_789 |
| Infinity  | "null"         | Infinity    |
| -0        | "0"            | -0          |
| '"'       | '"\\""'        | '"'         |

## humanizeDuration(ms, options)

```js
import { humanizeDuration } from "@jsenv/humanize";

humanizeDuration(61_421); // "1 minute and 1 second"
```
npm package: @jsenv/inspect
Description: Convert a value into a readable string
Latest version: 2.0.0

# inspect [![npm package](https://img.shields.io/npm/v/@jsenv/inspect.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/inspect)

`@jsenv/inspect` turns a JavaScript value into a string meant to be read by a human. It is written in ES6 and compatible with browsers and Node.js.

```js
import { inspect } from "@jsenv/inspect";

console.log(
  inspect({
    boolean: true,
    number: 10,
    string: "hello world",
  }),
);
```

```console
❯ node ./docs/demo.mjs
{
  "boolean": true,
  "number": 10,
  "string": "hello world"
}
```

# Comparison with JSON.stringify

Table comparing `JSON.stringify` and `@jsenv/inspect` to demonstrates how inspect focuses on readability and accuracy.

| value     | JSON.stringify | jsenv inspect |
| --------- | -------------- | ------------- |
| 123456789 | "123456789"    | 123_456_789   |
| Infinity  | "null"         | Infinity      |
| -0        | "0"            | -0            |
| '"'       | '"\\""'        | '"'           |
npm package: @jsenv/log
Description: Nice and dynamic logs in the terminal
Author: dmail
Latest version: 3.5.2

# Log [![npm package](https://img.shields.io/npm/v/@jsenv/log.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/log)

This packages is used by jsenv to create beautiful logs in the console. It is available as a standalone package to be used in other contexts.

This package helps to:

- add symbols via unicode
- make dynamic logs
- add color to logs

# Task log example

(Click image to play the gif)

![img](./docs/demo_task.gif)

Code used to produce these logs:

```js
import { createTaskLog } from "@jsenv/log";

const task = createTaskLog("Doing something");
setTimeout(() => {
  task.done();
}, 1_000);
```

# Unicode example

![img](./docs/demo_unicode.png)

Code used to produce these logs:

```js
import { UNICODE } from "@jsenv/log";

console.log(`${UNICODE.COMMAND} cd dir/`);
console.log(`${UNICODE.DEBUG} debug`);
console.log(`${UNICODE.INFO} info`);
console.log(`${UNICODE.WARNING} warning`);
console.log(`${UNICODE.FAILURE} failure`);
console.log(`${UNICODE.OK} ok`);
```

# Installation

```console
npm install @jsenv/log
```
npm package: @jsenv/logger
Description: Control verbosity of logs during a function execution.
Author: dmail
Latest version: 4.1.1

# logger

Control verbosity of logs during a function execution.

[![npm package](https://img.shields.io/npm/v/@jsenv/logger.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/logger)

You want to use `@jsenv/logger` when you have many logs with different purposes and controls which type of logs are actually written.

# Installation

```console
npm install @jsenv/logger
```

# Documentation

## createLogger

`createLogger` is a function receiving a `logLevel` and returning a `logger` object.

```js
import { createLogger } from "@jsenv/logger"

const functionWithLogs = ({ logLevel }) => {
  const logger = createLogger({ logLevel })

  logger.debug("start doing whetevr")
  logger.info("some useful info")
  logger.debug("doing whatever is done")
  logger.warn("be careful about blah-blah")
  logger.error("oops an error occured while doing whatever")
}

functionWithLogs({ logLevel: "debug" })
functionWithLogs({ logLevel: "info" })
functionWithLogs({ logLevel: "warn" })
functionWithLogs({ logLevel: "error" })
functionWithLogs({ logLevel: "off" })
```

— source code at [src/createLogger.js](./src/createLogger.js).

### logLevel

`logLevel` parameter is a string controlling verbosity of the returned `logger`.

The possible logLevel values are:

- `"off"`
- `"debug"`
- `"info"`
- `"warn"`
- `"error"`

If you are rigorous, each logLevel value is exported as a constant that you can use like this:

```js
import { createLogger, LOG_LEVEL_INFO } from "@jsenv/logger"

createLogger({ logLevel: LOG_LEVEL_INFO })
```

## logger

`logger` is an object with methods logging a message with a given level.<br />
It is returned by `createLogger`, and has the following shape: `{ debug, info, warn, error }`. Each method calls the corresponding console method or do nothing depending on the `logLevel`.

```js
import { createLogger } from "@jsenv/logger"

const logger = createLogger({ logLevel: "info" })
logger.debug("hello")
```

Logs nothing

```js
import { createLogger } from "@jsenv/logger"

const logger = createLogger({ logLevel: "info" })
logger.info("hello")
```

Logs `Hello`

## Migration from console

Using `@jsenv/logger` means converting console methods into logger methods. `console.info` becomes `logger.info` and so on.

But keep in mind there is no `logger.log`. This is because a log level named "log" would not fit into the log level hierachy below.

```
error > warn > info > debug
```

It means you have to convert `console.log` into `logger.debug` or `logger.info`.
npm package: @jsenv/module-resolution
Description: [![npm package](https://img.shields.io/npm/v/@jsenv/module-resolution.svg)](https://www.npmjs.com/package/@jsenv/module-resolution) [![build](https://travis-ci.com/jsenv/jsenv-module-resolution.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-module-r
Latest version: 5.3.0

# jsenv module resolution

[![npm package](https://img.shields.io/npm/v/@jsenv/module-resolution.svg)](https://www.npmjs.com/package/@jsenv/module-resolution)
[![build](https://travis-ci.com/jsenv/jsenv-module-resolution.svg?branch=master)](http://travis-ci.com/jsenv/jsenv-module-resolution)
[![codecov](https://codecov.io/gh/jsenv/jsenv-module-resolution/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-module-resolution)

> import resolution and remapping.

## Introduction

This module exports a `resolvePath` you can use to resolve an import.<br />
It is used by jsenv to find every import statement files.

## Installation

```console
npm install @jsenv/module-resolution
```

## `resolvePath`

> takes { specifier, importer, importMap, defaultExtension } and returns a resolved path.

##### basic example

```js
import { resolvePath } from "@jsenv/module-resolution"

const resolvePath = resolveImport({
  importer: "http://domain.com/folder/file.js",
  specifier: "../index.js",
})

console.log(resolvePath)
```

The code above logs `http://domain.com/index.js`.

##### remapping example

```js
import { resolvePath } from "@jsenv/module-resolution"

const resolvedPath = resolvePath({
  importer: "http://domain.com/folder/file.js",
  specifier: "../index.js",
  importMap: {
    imports: {
      "/index.js": "/foo.js",
    },
  },
})

console.log(resolvedPath)
```

code above logs `http://domain.com/foo.js`.

#### scoped remapping example

```js
import { resolvedPath } from "@jsenv/module-resolution"

const resolvedPath = resolvePath({
  importer: "http://domain.com/folder/file.js",
  specifier: "../index.js",
  importMap: {
    imports: {
      "/index.js": "/foo.js",
    },
    scopes: {
      "/folder/": {
        "/index.js": "/bar.js",
      },
    },
  },
})

console.log(remappedImport)
```

code above logs `http://domain.com/bar.js`.
npm package: @jsenv/navi
Description: Library of components including navigation to create frontend applications
Author: dmail
Latest version: 0.20.15

# @jsenv/navi

A frontend framework for building modern web applications, focused on routing, async data, and UI components.

## Routing

Routing is signal-based, which means URL state — including search params — can be bound to signals with two-way synchronization. Change a signal, the URL updates. Navigate to a URL, the signals update. Search params can also be validated and typed, so you always work with the right shape of data.

Routes are flexible: you can create route groups to share logic, state, or UI across multiple routes. Nested routing is supported, and the structure naturally maps to how your application is organized.

## Actions

Actions are async operations with lifecycle management — pending, success, error. You can declare actions that run when navigating to a route, and any component can subscribe to them via `useAsyncData` to reflect what is happening: loading states, results, errors. No manual wiring.

## Layout & Typography

**`Box`** is the main layout primitive. It wraps CSS Flexbox with a friendlier API: `flex` for horizontal layout, `flex="y"` for vertical (no more guessing what `flex-direction: column` does visually). Supports `grid`, `inline`, alignment via `alignX`/`alignY`, and spacing props.

**`Text`** and related components (`Title`, `Paragraph`, `Code`, `Caption`) handle typography consistently across the app.

## Icons

Icons are a piece that is often missing or painful in web projects. The `Icon` component makes icons behave like text — they scale with font size, inherit color, and align naturally in any layout. No sizing hacks, no SVG wrangling.

## Fields & Forms

UI field components (`Input`, `Select`, `Checkbox`, `Radio`, etc.) accept an `action` prop — the standard way to respond to user interaction. Composing fields into forms is natural, and form submission flows through the same action system.

Validation goes beyond native browser constraints: custom rules, better error positioning, real-time feedback, and a UX that doesn't punish users before they've finished typing.

## Table

A capable `Table` component that handles what you'd expect from a spreadsheet-like interface: column management, sorting, multi-selection with keyboard shortcuts, and more.

## Other

Dialogs, badges, details/collapsible, separators, keyboard shortcuts, popovers, copy-to-clipboard, and other utilities.

---

Named after Navi, the fairy guide from Zelda — it helps you navigate through the complexities of building modern web applications.
npm package: @jsenv/node-launcher
Description: [![github package](https://img.shields.io/github/package-json/v/jsenv/jsenv-node-launcher.svg?label=package&logo=github)](https://github.com/jsenv/jsenv-node-launcher/packages) [![ci status](https://github.com/jsenv/jsenv-node-launcher/workflows/ci/badge.
Latest version: 4.19.0

# jsenv node launcher

[![github package](https://img.shields.io/github/package-json/v/jsenv/jsenv-node-launcher.svg?label=package&logo=github)](https://github.com/jsenv/jsenv-node-launcher/packages)
[![ci status](https://github.com/jsenv/jsenv-node-launcher/workflows/ci/badge.svg)](https://github.com/jsenv/jsenv-node-launcher/actions)
[![codecov](https://codecov.io/gh/jsenv/jsenv-node-launcher/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-node-launcher)

This module exports a function called `launchNode` you can use together with `jsenv`.<br />
— see [jsenv project on github](https://github.com/jsenv/jsenv-core)

## `launchNode` options

### env

> Object that will be merged into `process.ENV` of child process.

If you don't pass `env` options, its value will be:

<!-- prettier-ignore -->
```js
{}
```

### debugPort

> Set debug port of child process.

If child process `debugMode` is `"none"` this option has no effect.<br />
The number `0` means debug port will be randomly assigned to an available port.

If you don't pass `debugPort` options, its value will be:

```js
0
```

### debugMode

> Force or prevent a debugging session of child process.

Possibles values:

- `"inspect"`: like passing `--inspect` to child process except port is set by `debugPort` option.
- `"inspect-brk"`: like passing `--inspect-brk` to child process except port is set by `debugPort` option.
- `"debug"`: like passing `--debug` to child process except port is set by `debugPort` option.
- `"debug-brk"`: like passing `--debug-brk` to child process except port is set by `debugPort` option.
- `"none"`: pass nothing related to debug to child process.
- `"inherit"`: `debugMode` value will be any debug option found into `process.execArgv`, otherwise it will be `"none"`.

If you don't pass `debugMode` options, its value will be:

```js
"inherit"
```

### debugModeInheritBreak

> Force or prevent `-brk` option on child process

This option has an effect only when `debugMode` option is `"inherit"`.<br />

`debugModeInheritBreak` controls if `debugMode` will inherit the `-brk` suffix.

If you don't pass `debugModeInheritBreak`, its value will be:

```js
true
```

### traceWarnings

> Pass `--trace-warnings` to child process or not.

If you don't pass `traceWarnings`, its value will be:

```js
true
```