Upload folder using huggingface_hub
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- bunx-1000-wrangler@latest/node_modules/@cloudflare/kv-asset-handler/README.md +346 -0
- bunx-1000-wrangler@latest/node_modules/@cloudflare/unenv-preset/README.md +24 -0
- bunx-1000-wrangler@latest/node_modules/@cloudflare/workerd-linux-arm64/README.md +6 -0
- bunx-1000-wrangler@latest/node_modules/@cspotcode/source-map-support/LICENSE.md +21 -0
- bunx-1000-wrangler@latest/node_modules/@cspotcode/source-map-support/README.md +289 -0
- bunx-1000-wrangler@latest/node_modules/@esbuild/linux-arm64/README.md +3 -0
- bunx-1000-wrangler@latest/node_modules/@img/colour/LICENSE.md +82 -0
- bunx-1000-wrangler@latest/node_modules/@img/colour/README.md +15 -0
- bunx-1000-wrangler@latest/node_modules/@img/sharp-libvips-linux-arm64/README.md +46 -0
- bunx-1000-wrangler@latest/node_modules/@img/sharp-libvips-linuxmusl-arm64/README.md +46 -0
- bunx-1000-wrangler@latest/node_modules/@img/sharp-linux-arm64/README.md +18 -0
- bunx-1000-wrangler@latest/node_modules/@img/sharp-linuxmusl-arm64/README.md +18 -0
- bunx-1000-wrangler@latest/node_modules/@jridgewell/resolve-uri/README.md +40 -0
- bunx-1000-wrangler@latest/node_modules/@jridgewell/sourcemap-codec/README.md +264 -0
- bunx-1000-wrangler@latest/node_modules/@jridgewell/trace-mapping/README.md +193 -0
- bunx-1000-wrangler@latest/node_modules/@poppinss/colors/LICENSE.md +9 -0
- bunx-1000-wrangler@latest/node_modules/@poppinss/colors/README.md +95 -0
- bunx-1000-wrangler@latest/node_modules/@poppinss/dumper/LICENSE.md +9 -0
- bunx-1000-wrangler@latest/node_modules/@poppinss/dumper/README.md +387 -0
- bunx-1000-wrangler@latest/node_modules/@poppinss/exception/LICENSE.md +9 -0
- bunx-1000-wrangler@latest/node_modules/@poppinss/exception/README.md +64 -0
- bunx-1000-wrangler@latest/node_modules/@sindresorhus/is/readme.md +844 -0
- bunx-1000-wrangler@latest/node_modules/@speed-highlight/core/README.md +201 -0
- bunx-1000-wrangler@latest/node_modules/blake3-wasm/changelog.md +60 -0
- bunx-1000-wrangler@latest/node_modules/blake3-wasm/readme.md +406 -0
- bunx-1000-wrangler@latest/node_modules/cookie/README.md +295 -0
- bunx-1000-wrangler@latest/node_modules/detect-libc/README.md +163 -0
- bunx-1000-wrangler@latest/node_modules/error-stack-parser-es/README.md +40 -0
- bunx-1000-wrangler@latest/node_modules/esbuild/LICENSE.md +21 -0
- bunx-1000-wrangler@latest/node_modules/esbuild/README.md +3 -0
- bunx-1000-wrangler@latest/node_modules/kleur/readme.md +232 -0
- bunx-1000-wrangler@latest/node_modules/miniflare/README.md +957 -0
- bunx-1000-wrangler@latest/node_modules/path-to-regexp/Readme.md +350 -0
- bunx-1000-wrangler@latest/node_modules/pathe/README.md +73 -0
- bunx-1000-wrangler@latest/node_modules/semver/README.md +680 -0
- bunx-1000-wrangler@latest/node_modules/sharp/README.md +118 -0
- bunx-1000-wrangler@latest/node_modules/supports-color/readme.md +75 -0
- bunx-1000-wrangler@latest/node_modules/undici/README.md +741 -0
- bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/Agent.md +84 -0
- bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/BalancedPool.md +99 -0
- bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/CacheStorage.md +30 -0
- bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/CacheStore.md +164 -0
- bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/Client.md +288 -0
- bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/ClientStats.md +27 -0
- bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/Connector.md +115 -0
- bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/ContentType.md +57 -0
- bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/Cookies.md +128 -0
- bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/Debug.md +62 -0
- bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +315 -0
- bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/Dispatcher.md +1392 -0
bunx-1000-wrangler@latest/node_modules/@cloudflare/kv-asset-handler/README.md
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# @cloudflare/kv-asset-handler
|
| 2 |
+
|
| 3 |
+
[](https://www.npmjs.com/package/@cloudflare/kv-asset-handler)
|
| 4 |
+
[](https://github.com/cloudflare/kv-asset-handler/actions/workflows/test.yml)
|
| 5 |
+
[](https://github.com/cloudflare/kv-asset-handler/actions/workflows/lint.yml)
|
| 6 |
+
|
| 7 |
+
`kv-asset-handler` is an open-source library for managing the retrieval of static assets from [Workers KV](https://developers.cloudflare.com/workers/runtime-apis/kv) inside of a [Cloudflare Workers](https://workers.dev) function. `kv-asset-handler` is designed for use with [Workers Sites](https://developers.cloudflare.com/workers/platform/sites), a feature included in [Wrangler](https://github.com/cloudflare/wrangler), our command-line tool for deploying Workers projects.
|
| 8 |
+
|
| 9 |
+
`kv-asset-handler` runs as part of a Cloudflare Workers function, so it allows you to customize _how_ and _when_ your static assets are loaded, as well as customize how those assets behave before they're sent to the client.
|
| 10 |
+
|
| 11 |
+
Most users and sites will not need these customizations, and just want to serve their statically built applications. For that simple use-case, you can check out [Cloudflare Pages](https://pages.cloudflare.com), our batteries-included approach to deploying static sites on Cloudflare's edge network. Workers Sites was designed as a precursor to Cloudflare Pages, so check out Pages if you just want to deploy your static site without any special customizations!
|
| 12 |
+
|
| 13 |
+
For users who _do_ want to customize their assets, and want to build complex experiences on top of their static assets, `kv-asset-handler` (and the default [Workers Sites template](https://github.com/cloudflare/worker-sites-template), which is provided for use with Wrangler + Workers Sites) allows you to customize caching behavior, headers, and anything else about how your Workers function loads the static assets for your site stored in Workers KV.
|
| 14 |
+
|
| 15 |
+
The Cloudflare Workers Discord server is an active place where Workers users get help, share feedback, and collaborate on making our platform better. The `#workers` channel in particular is a great place to chat about `kv-asset-handler`, and building cool experiences for your users using these tools! If you have questions, want to share what you're working on, or give feedback, [join us in Discord and say hello](https://discord.cloudflare.com)!
|
| 16 |
+
|
| 17 |
+
- [Installation](#installation)
|
| 18 |
+
- [Usage](#usage)
|
| 19 |
+
- [`getAssetFromKV`](#getassetfromkv)
|
| 20 |
+
- [Example](#example)
|
| 21 |
+
* [Return](#return)
|
| 22 |
+
* [Optional Arguments](#optional-arguments)
|
| 23 |
+
- [`mapRequestToAsset`](#maprequesttoasset)
|
| 24 |
+
- [Example](#example-1)
|
| 25 |
+
- [`cacheControl`](#cachecontrol)
|
| 26 |
+
- [`browserTTL`](#browserttl)
|
| 27 |
+
- [`edgeTTL`](#edgettl)
|
| 28 |
+
- [`bypassCache`](#bypasscache)
|
| 29 |
+
- [`ASSET_NAMESPACE` (required for ES Modules)](#asset_namespace-required-for-es-modules)
|
| 30 |
+
- [`ASSET_MANIFEST` (required for ES Modules)](#asset_manifest-required-for-es-modules)
|
| 31 |
+
- [`defaultETag`](#defaultetag-optional)
|
| 32 |
+
|
| 33 |
+
* [Helper functions](#helper-functions)
|
| 34 |
+
- [`mapRequestToAsset`](#maprequesttoasset-1)
|
| 35 |
+
- [`serveSinglePageApp`](#servesinglepageapp)
|
| 36 |
+
* [Cache revalidation and etags](#cache-revalidation-and-etags)
|
| 37 |
+
|
| 38 |
+
## Installation
|
| 39 |
+
|
| 40 |
+
Add this package to your `package.json` by running this in the root of your
|
| 41 |
+
project's directory:
|
| 42 |
+
|
| 43 |
+
```
|
| 44 |
+
npm i @cloudflare/kv-asset-handler
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
## Usage
|
| 48 |
+
|
| 49 |
+
This package was designed to work with [Worker Sites](https://workers.cloudflare.com/sites).
|
| 50 |
+
|
| 51 |
+
## `getAssetFromKV`
|
| 52 |
+
|
| 53 |
+
getAssetFromKV(Evt) => Promise<Response>
|
| 54 |
+
|
| 55 |
+
`getAssetFromKV` is an async function that takes an `Evt` object (containing a `Request` and a [`waitUntil`](https://developers.cloudflare.com/workers/runtime-apis/fetch-event#waituntil)) and returns a `Response` object if the request matches an asset in KV, otherwise it will throw a `KVError`.
|
| 56 |
+
|
| 57 |
+
#### Example
|
| 58 |
+
|
| 59 |
+
This example checks for the existence of a value in KV, and returns it if it's there, and returns a 404 if it is not. It also serves index.html from `/`.
|
| 60 |
+
|
| 61 |
+
### Return
|
| 62 |
+
|
| 63 |
+
`getAssetFromKV` returns a `Promise<Response>` with `Response` being the body of the asset requested.
|
| 64 |
+
|
| 65 |
+
Known errors to be thrown are:
|
| 66 |
+
|
| 67 |
+
- MethodNotAllowedError
|
| 68 |
+
- NotFoundError
|
| 69 |
+
- InternalError
|
| 70 |
+
|
| 71 |
+
#### ES Modules
|
| 72 |
+
|
| 73 |
+
```js
|
| 74 |
+
import manifestJSON from "__STATIC_CONTENT_MANIFEST";
|
| 75 |
+
import {
|
| 76 |
+
getAssetFromKV,
|
| 77 |
+
MethodNotAllowedError,
|
| 78 |
+
NotFoundError,
|
| 79 |
+
} from "@cloudflare/kv-asset-handler";
|
| 80 |
+
|
| 81 |
+
const assetManifest = JSON.parse(manifestJSON);
|
| 82 |
+
|
| 83 |
+
export default {
|
| 84 |
+
async fetch(request, env, ctx) {
|
| 85 |
+
if (request.url.includes("/docs")) {
|
| 86 |
+
try {
|
| 87 |
+
return await getAssetFromKV(
|
| 88 |
+
{
|
| 89 |
+
request,
|
| 90 |
+
waitUntil(promise) {
|
| 91 |
+
return ctx.waitUntil(promise);
|
| 92 |
+
},
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
ASSET_NAMESPACE: env.__STATIC_CONTENT,
|
| 96 |
+
ASSET_MANIFEST: assetManifest,
|
| 97 |
+
}
|
| 98 |
+
);
|
| 99 |
+
} catch (e) {
|
| 100 |
+
if (e instanceof NotFoundError) {
|
| 101 |
+
// ...
|
| 102 |
+
} else if (e instanceof MethodNotAllowedError) {
|
| 103 |
+
// ...
|
| 104 |
+
} else {
|
| 105 |
+
return new Response("An unexpected error occurred", { status: 500 });
|
| 106 |
+
}
|
| 107 |
+
}
|
| 108 |
+
} else return fetch(request);
|
| 109 |
+
},
|
| 110 |
+
};
|
| 111 |
+
```
|
| 112 |
+
|
| 113 |
+
#### Service Worker
|
| 114 |
+
|
| 115 |
+
```js
|
| 116 |
+
import {
|
| 117 |
+
getAssetFromKV,
|
| 118 |
+
MethodNotAllowedError,
|
| 119 |
+
NotFoundError,
|
| 120 |
+
} from "@cloudflare/kv-asset-handler";
|
| 121 |
+
|
| 122 |
+
addEventListener("fetch", (event) => {
|
| 123 |
+
event.respondWith(handleEvent(event));
|
| 124 |
+
});
|
| 125 |
+
|
| 126 |
+
async function handleEvent(event) {
|
| 127 |
+
if (event.request.url.includes("/docs")) {
|
| 128 |
+
try {
|
| 129 |
+
return await getAssetFromKV(event);
|
| 130 |
+
} catch (e) {
|
| 131 |
+
if (e instanceof NotFoundError) {
|
| 132 |
+
// ...
|
| 133 |
+
} else if (e instanceof MethodNotAllowedError) {
|
| 134 |
+
// ...
|
| 135 |
+
} else {
|
| 136 |
+
return new Response("An unexpected error occurred", { status: 500 });
|
| 137 |
+
}
|
| 138 |
+
}
|
| 139 |
+
} else return fetch(event.request);
|
| 140 |
+
}
|
| 141 |
+
```
|
| 142 |
+
|
| 143 |
+
### Optional Arguments
|
| 144 |
+
|
| 145 |
+
You can customize the behavior of `getAssetFromKV` by passing the following properties as an object into the second argument.
|
| 146 |
+
|
| 147 |
+
```
|
| 148 |
+
getAssetFromKV(event, { mapRequestToAsset: ... })
|
| 149 |
+
```
|
| 150 |
+
|
| 151 |
+
#### `mapRequestToAsset`
|
| 152 |
+
|
| 153 |
+
mapRequestToAsset(Request) => Request
|
| 154 |
+
|
| 155 |
+
Maps the incoming request to the value that will be looked up in Cloudflare's KV
|
| 156 |
+
|
| 157 |
+
By default, mapRequestToAsset is set to the exported function [`mapRequestToAsset`](#maprequesttoasset-1). This works for most static site generators, but you can customize this behavior by passing your own function as `mapRequestToAsset`. The function should take a `Request` object as its only argument, and return a new `Request` object with an updated path to be looked up in the asset manifest/KV.
|
| 158 |
+
|
| 159 |
+
For SPA mapping pass in the [`serveSinglePageApp`](#servesinglepageapp) function
|
| 160 |
+
|
| 161 |
+
#### Example
|
| 162 |
+
|
| 163 |
+
Strip `/docs` from any incoming request before looking up an asset in Cloudflare's KV.
|
| 164 |
+
|
| 165 |
+
```js
|
| 166 |
+
import { getAssetFromKV, mapRequestToAsset } from '@cloudflare/kv-asset-handler'
|
| 167 |
+
...
|
| 168 |
+
const customKeyModifier = request => {
|
| 169 |
+
let url = request.url
|
| 170 |
+
//custom key mapping optional
|
| 171 |
+
url = url.replace('/docs', '').replace(/^\/+/, '')
|
| 172 |
+
return mapRequestToAsset(new Request(url, request))
|
| 173 |
+
}
|
| 174 |
+
let asset = await getAssetFromKV(event, { mapRequestToAsset: customKeyModifier })
|
| 175 |
+
```
|
| 176 |
+
|
| 177 |
+
#### `cacheControl`
|
| 178 |
+
|
| 179 |
+
type: object
|
| 180 |
+
|
| 181 |
+
`cacheControl` allows you to configure options for both the Cloudflare Cache accessed by your Worker, and the browser cache headers sent along with your Workers' responses. The default values are as follows:
|
| 182 |
+
|
| 183 |
+
```javascript
|
| 184 |
+
let cacheControl = {
|
| 185 |
+
browserTTL: null, // do not set cache control ttl on responses
|
| 186 |
+
edgeTTL: 2 * 60 * 60 * 24, // 2 days
|
| 187 |
+
bypassCache: false, // do not bypass Cloudflare's cache
|
| 188 |
+
};
|
| 189 |
+
```
|
| 190 |
+
|
| 191 |
+
##### `browserTTL`
|
| 192 |
+
|
| 193 |
+
type: number | null
|
| 194 |
+
nullable: true
|
| 195 |
+
|
| 196 |
+
Sets the `Cache-Control: max-age` header on the response returned from the Worker. By default set to `null` which will not add the header at all.
|
| 197 |
+
|
| 198 |
+
##### `edgeTTL`
|
| 199 |
+
|
| 200 |
+
type: number | null
|
| 201 |
+
nullable: true
|
| 202 |
+
|
| 203 |
+
Sets the `Cache-Control: max-age` header on the response used as the edge cache key. By default set to 2 days (`2 * 60 * 60 * 24`). When null will not cache on the edge at all.
|
| 204 |
+
|
| 205 |
+
##### `bypassCache`
|
| 206 |
+
|
| 207 |
+
type: boolean
|
| 208 |
+
|
| 209 |
+
Determines whether to cache requests on Cloudflare's edge cache. By default set to `false` (recommended for production builds). Useful for development when you need to eliminate the cache's effect on testing.
|
| 210 |
+
|
| 211 |
+
#### `ASSET_NAMESPACE` (required for ES Modules)
|
| 212 |
+
|
| 213 |
+
type: KV Namespace Binding
|
| 214 |
+
|
| 215 |
+
The binding name to the KV Namespace populated with key/value entries of files for the Worker to serve. By default, Workers Sites uses a [binding to a Workers KV Namespace](https://developers.cloudflare.com/workers/reference/storage/api/#namespaces) named `__STATIC_CONTENT`.
|
| 216 |
+
|
| 217 |
+
It is further assumed that this namespace consists of static assets such as HTML, CSS, JavaScript, or image files, keyed off of a relative path that roughly matches the assumed URL pathname of the incoming request.
|
| 218 |
+
|
| 219 |
+
In ES Modules format, this argument is required, and can be gotten from `env`.
|
| 220 |
+
|
| 221 |
+
##### ES Module
|
| 222 |
+
|
| 223 |
+
```js
|
| 224 |
+
return getAssetFromKV(
|
| 225 |
+
{
|
| 226 |
+
request,
|
| 227 |
+
waitUntil(promise) {
|
| 228 |
+
return ctx.waitUntil(promise);
|
| 229 |
+
},
|
| 230 |
+
},
|
| 231 |
+
{
|
| 232 |
+
ASSET_NAMESPACE: env.__STATIC_CONTENT,
|
| 233 |
+
}
|
| 234 |
+
);
|
| 235 |
+
```
|
| 236 |
+
|
| 237 |
+
##### Service Worker
|
| 238 |
+
|
| 239 |
+
```
|
| 240 |
+
return getAssetFromKV(event, { ASSET_NAMESPACE: MY_NAMESPACE })
|
| 241 |
+
```
|
| 242 |
+
|
| 243 |
+
#### `ASSET_MANIFEST` (required for ES Modules)
|
| 244 |
+
|
| 245 |
+
type: text blob (JSON formatted) or object
|
| 246 |
+
|
| 247 |
+
The mapping of requested file path to the key stored on Cloudflare.
|
| 248 |
+
|
| 249 |
+
Workers Sites with Wrangler bundles up a text blob that maps request paths to content-hashed keys that are generated by Wrangler as a cache-busting measure. If this option/binding is not present, the function will fallback to using the raw pathname to look up your asset in KV. If, for whatever reason, you have rolled your own implementation of this, you can include your own by passing a stringified JSON object where the keys are expected paths, and the values are the expected keys in your KV namespace.
|
| 250 |
+
|
| 251 |
+
In ES Modules format, this argument is required, and can be imported.
|
| 252 |
+
|
| 253 |
+
##### ES Module
|
| 254 |
+
|
| 255 |
+
```js
|
| 256 |
+
import manifestJSON from "__STATIC_CONTENT_MANIFEST";
|
| 257 |
+
let manifest = JSON.parse(manifestJSON);
|
| 258 |
+
manifest["index.html"] = "index.special.html";
|
| 259 |
+
|
| 260 |
+
return getAssetFromKV(
|
| 261 |
+
{
|
| 262 |
+
request,
|
| 263 |
+
waitUntil(promise) {
|
| 264 |
+
return ctx.waitUntil(promise);
|
| 265 |
+
},
|
| 266 |
+
},
|
| 267 |
+
{
|
| 268 |
+
ASSET_MANIFEST: manifest,
|
| 269 |
+
// ...
|
| 270 |
+
}
|
| 271 |
+
);
|
| 272 |
+
```
|
| 273 |
+
|
| 274 |
+
##### Service Worker
|
| 275 |
+
|
| 276 |
+
```
|
| 277 |
+
let assetManifest = { "index.html": "index.special.html" }
|
| 278 |
+
return getAssetFromKV(event, { ASSET_MANIFEST: assetManifest })
|
| 279 |
+
```
|
| 280 |
+
|
| 281 |
+
#### `defaultMimeType` (optional)
|
| 282 |
+
|
| 283 |
+
type: string
|
| 284 |
+
|
| 285 |
+
This is the mime type that will be used for files with unrecognized or missing extensions. The default value is `'text/plain'`.
|
| 286 |
+
|
| 287 |
+
If you are serving a static site and would like to use extensionless HTML files instead of index.html files, set this to `'text/html'`.
|
| 288 |
+
|
| 289 |
+
#### `defaultDocument` (optional)
|
| 290 |
+
|
| 291 |
+
type: string
|
| 292 |
+
|
| 293 |
+
This is the default document that will be concatenated for requests ends in `'/'` or without a valid mime type like `'/about'` or `'/about.me'`. The default value is `'index.html'`.
|
| 294 |
+
|
| 295 |
+
#### `defaultETag` (optional)
|
| 296 |
+
|
| 297 |
+
type: `'strong' | 'weak'`
|
| 298 |
+
|
| 299 |
+
This determines the format of the response [ETag header](https://developer.mozilla.org/docs/Web/HTTP/Headers/ETag). If the resource is in the cache, the ETag will always be weakened before being returned.
|
| 300 |
+
The default value is `'strong'`.
|
| 301 |
+
|
| 302 |
+
# Helper functions
|
| 303 |
+
|
| 304 |
+
## `mapRequestToAsset`
|
| 305 |
+
|
| 306 |
+
mapRequestToAsset(Request) => Request
|
| 307 |
+
|
| 308 |
+
The default function for mapping incoming requests to keys in Cloudflare's KV.
|
| 309 |
+
|
| 310 |
+
Takes any path that ends in `/` or evaluates to an HTML file and appends `index.html` or `/index.html` for lookup in your Workers KV namespace.
|
| 311 |
+
|
| 312 |
+
## `serveSinglePageApp`
|
| 313 |
+
|
| 314 |
+
serveSinglePageApp(Request) => Request
|
| 315 |
+
|
| 316 |
+
A custom handler for mapping requests to a single root: `index.html`. The most common use case is single-page applications - frameworks with in-app routing - such as React Router, VueJS, etc. It takes zero arguments.
|
| 317 |
+
|
| 318 |
+
```js
|
| 319 |
+
import { getAssetFromKV, serveSinglePageApp } from '@cloudflare/kv-asset-handler'
|
| 320 |
+
...
|
| 321 |
+
let asset = await getAssetFromKV(event, { mapRequestToAsset: serveSinglePageApp })
|
| 322 |
+
```
|
| 323 |
+
|
| 324 |
+
# Cache revalidation and etags
|
| 325 |
+
|
| 326 |
+
All responses served from cache (including those with `cf-cache-status: MISS`) include an `etag` response header that identifies the version of the resource. The `etag` value is identical to the path key used in the `ASSET_MANIFEST`. It is updated each time an asset changes and looks like this: `etag: <filename>.<hash of file contents>.<extension>` (ex. `etag: index.54321.html`).
|
| 327 |
+
|
| 328 |
+
Resources served with an `etag` allow browsers to use the `if-none-match` request header to make conditional requests for that resource in the future. This has two major benefits:
|
| 329 |
+
|
| 330 |
+
- When a request's `if-none-match` value matches the `etag` of the resource in Cloudflare cache, Cloudflare will send a `304 Not Modified` response without a body, saving bandwidth.
|
| 331 |
+
- Changes to a file on the server are immediately reflected in the browser - even when the cache control directive `max-age` is unexpired.
|
| 332 |
+
|
| 333 |
+
#### Disable the `etag`
|
| 334 |
+
|
| 335 |
+
To turn `etags` **off**, you must bypass cache:
|
| 336 |
+
|
| 337 |
+
```js
|
| 338 |
+
/* Turn etags off */
|
| 339 |
+
let cacheControl = {
|
| 340 |
+
bypassCache: true,
|
| 341 |
+
};
|
| 342 |
+
```
|
| 343 |
+
|
| 344 |
+
#### Syntax and comparison context
|
| 345 |
+
|
| 346 |
+
`kv-asset-handler` sets and evaluates etags as [strong validators](https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests#Strong_validation). To preserve `etag` integrity, the format of the value deviates from the [RFC2616 recommendation to enclose the `etag` with quotation marks](https://tools.ietf.org/html/rfc2616#section-3.11). This is intentional. Cloudflare cache applies the `W/` prefix to all `etags` that use quoted-strings -- a process that converts the `etag` to a "weak validator" when served to a client.
|
bunx-1000-wrangler@latest/node_modules/@cloudflare/unenv-preset/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# @cloudflare/unenv-preset
|
| 2 |
+
|
| 3 |
+
[unenv](https://github.com/unjs/unenv) preset for cloudflare.
|
| 4 |
+
|
| 5 |
+
unenv provides polyfills to add [Node.js](https://nodejs.org/) compatibility for any JavaScript runtime, including browsers and edge workers.
|
| 6 |
+
|
| 7 |
+
## Usage
|
| 8 |
+
|
| 9 |
+
```ts
|
| 10 |
+
import { cloudflare } from "@cloudflare/unenv-preset";
|
| 11 |
+
import { defineEnv } from "unenv";
|
| 12 |
+
|
| 13 |
+
const { env } = defineEnv({
|
| 14 |
+
presets: [cloudflare],
|
| 15 |
+
});
|
| 16 |
+
|
| 17 |
+
const { alias, inject, external, polyfill } = env;
|
| 18 |
+
```
|
| 19 |
+
|
| 20 |
+
See the unenv [README](https://github.com/unjs/unenv/blob/main/README.md) for more details.
|
| 21 |
+
|
| 22 |
+
## Tests
|
| 23 |
+
|
| 24 |
+
This package is tested via wrangler e2e tests.
|
bunx-1000-wrangler@latest/node_modules/@cloudflare/workerd-linux-arm64/README.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 👷 `workerd` for Linux ARM 64-bit, Cloudflare's JavaScript/Wasm Runtime
|
| 2 |
+
|
| 3 |
+
`workerd` is a JavaScript / Wasm server runtime based on the same code that powers
|
| 4 |
+
[Cloudflare Workers](https://workers.dev).
|
| 5 |
+
|
| 6 |
+
See https://github.com/cloudflare/workerd for details.
|
bunx-1000-wrangler@latest/node_modules/@cspotcode/source-map-support/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
The MIT License (MIT)
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2014 Evan Wallace
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
bunx-1000-wrangler@latest/node_modules/@cspotcode/source-map-support/README.md
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Source Map Support
|
| 2 |
+
|
| 3 |
+
[](https://npmjs.org/package/@cspotcode/source-map-support)
|
| 4 |
+
[](https://npmjs.org/package/@cspotcode/source-map-support)
|
| 5 |
+
[](https://github.com/cspotcode/node-source-map-support/actions?query=workflow%3A%22Continuous+Integration%22)
|
| 6 |
+
|
| 7 |
+
This module provides source map support for stack traces in node via the [V8 stack trace API](https://github.com/v8/v8/wiki/Stack-Trace-API). It uses the [source-map](https://github.com/mozilla/source-map) module to replace the paths and line numbers of source-mapped files with their original paths and line numbers. The output mimics node's stack trace format with the goal of making every compile-to-JS language more of a first-class citizen. Source maps are completely general (not specific to any one language) so you can use source maps with multiple compile-to-JS languages in the same node process.
|
| 8 |
+
|
| 9 |
+
## Installation and Usage
|
| 10 |
+
|
| 11 |
+
#### Node support
|
| 12 |
+
|
| 13 |
+
```
|
| 14 |
+
$ npm install @cspotcode/source-map-support
|
| 15 |
+
```
|
| 16 |
+
|
| 17 |
+
Source maps can be generated using libraries such as [source-map-index-generator](https://github.com/twolfson/source-map-index-generator). Once you have a valid source map, place a source mapping comment somewhere in the file (usually done automatically or with an option by your transpiler):
|
| 18 |
+
|
| 19 |
+
```
|
| 20 |
+
//# sourceMappingURL=path/to/source.map
|
| 21 |
+
```
|
| 22 |
+
|
| 23 |
+
If multiple sourceMappingURL comments exist in one file, the last sourceMappingURL comment will be
|
| 24 |
+
respected (e.g. if a file mentions the comment in code, or went through multiple transpilers).
|
| 25 |
+
The path should either be absolute or relative to the compiled file.
|
| 26 |
+
|
| 27 |
+
From here you have two options.
|
| 28 |
+
|
| 29 |
+
##### CLI Usage
|
| 30 |
+
|
| 31 |
+
```bash
|
| 32 |
+
node -r @cspotcode/source-map-support/register compiled.js
|
| 33 |
+
# Or to enable hookRequire
|
| 34 |
+
node -r @cspotcode/source-map-support/register-hook-require compiled.js
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
##### Programmatic Usage
|
| 38 |
+
|
| 39 |
+
Put the following line at the top of the compiled file.
|
| 40 |
+
|
| 41 |
+
```js
|
| 42 |
+
require('@cspotcode/source-map-support').install();
|
| 43 |
+
```
|
| 44 |
+
|
| 45 |
+
It is also possible to install the source map support directly by
|
| 46 |
+
requiring the `register` module which can be handy with ES6:
|
| 47 |
+
|
| 48 |
+
```js
|
| 49 |
+
import '@cspotcode/source-map-support/register'
|
| 50 |
+
|
| 51 |
+
// Instead of:
|
| 52 |
+
import sourceMapSupport from '@cspotcode/source-map-support'
|
| 53 |
+
sourceMapSupport.install()
|
| 54 |
+
```
|
| 55 |
+
Note: if you're using babel-register, it includes source-map-support already.
|
| 56 |
+
|
| 57 |
+
It is also very useful with Mocha:
|
| 58 |
+
|
| 59 |
+
```
|
| 60 |
+
$ mocha --require @cspotcode/source-map-support/register tests/
|
| 61 |
+
```
|
| 62 |
+
|
| 63 |
+
#### Browser support
|
| 64 |
+
|
| 65 |
+
This library also works in Chrome. While the DevTools console already supports source maps, the V8 engine doesn't and `Error.prototype.stack` will be incorrect without this library. Everything will just work if you deploy your source files using [browserify](http://browserify.org/). Just make sure to pass the `--debug` flag to the browserify command so your source maps are included in the bundled code.
|
| 66 |
+
|
| 67 |
+
This library also works if you use another build process or just include the source files directly. In this case, include the file `browser-source-map-support.js` in your page and call `sourceMapSupport.install()`. It contains the whole library already bundled for the browser using browserify.
|
| 68 |
+
|
| 69 |
+
```html
|
| 70 |
+
<script src="browser-source-map-support.js"></script>
|
| 71 |
+
<script>sourceMapSupport.install();</script>
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
This library also works if you use AMD (Asynchronous Module Definition), which is used in tools like [RequireJS](http://requirejs.org/). Just list `browser-source-map-support` as a dependency:
|
| 75 |
+
|
| 76 |
+
```html
|
| 77 |
+
<script>
|
| 78 |
+
define(['browser-source-map-support'], function(sourceMapSupport) {
|
| 79 |
+
sourceMapSupport.install();
|
| 80 |
+
});
|
| 81 |
+
</script>
|
| 82 |
+
```
|
| 83 |
+
|
| 84 |
+
## Options
|
| 85 |
+
|
| 86 |
+
This module installs two things: a change to the `stack` property on `Error` objects and a handler for uncaught exceptions that mimics node's default exception handler (the handler can be seen in the demos below). You may want to disable the handler if you have your own uncaught exception handler. This can be done by passing an argument to the installer:
|
| 87 |
+
|
| 88 |
+
```js
|
| 89 |
+
require('@cspotcode/source-map-support').install({
|
| 90 |
+
handleUncaughtExceptions: false
|
| 91 |
+
});
|
| 92 |
+
```
|
| 93 |
+
|
| 94 |
+
This module loads source maps from the filesystem by default. You can provide alternate loading behavior through a callback as shown below. For example, [Meteor](https://github.com/meteor) keeps all source maps cached in memory to avoid disk access.
|
| 95 |
+
|
| 96 |
+
```js
|
| 97 |
+
require('@cspotcode/source-map-support').install({
|
| 98 |
+
retrieveSourceMap: function(source) {
|
| 99 |
+
if (source === 'compiled.js') {
|
| 100 |
+
return {
|
| 101 |
+
url: 'original.js',
|
| 102 |
+
map: fs.readFileSync('compiled.js.map', 'utf8')
|
| 103 |
+
};
|
| 104 |
+
}
|
| 105 |
+
return null;
|
| 106 |
+
}
|
| 107 |
+
});
|
| 108 |
+
```
|
| 109 |
+
|
| 110 |
+
The module will by default assume a browser environment if XMLHttpRequest and window are defined. If either of these do not exist it will instead assume a node environment.
|
| 111 |
+
In some rare cases, e.g. when running a browser emulation and where both variables are also set, you can explictly specify the environment to be either 'browser' or 'node'.
|
| 112 |
+
|
| 113 |
+
```js
|
| 114 |
+
require('@cspotcode/source-map-support').install({
|
| 115 |
+
environment: 'node'
|
| 116 |
+
});
|
| 117 |
+
```
|
| 118 |
+
|
| 119 |
+
To support files with inline source maps, the `hookRequire` options can be specified, which will monitor all source files for inline source maps.
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
```js
|
| 123 |
+
require('@cspotcode/source-map-support').install({
|
| 124 |
+
hookRequire: true
|
| 125 |
+
});
|
| 126 |
+
```
|
| 127 |
+
|
| 128 |
+
This monkey patches the `require` module loading chain, so is not enabled by default and is not recommended for any sort of production usage.
|
| 129 |
+
|
| 130 |
+
## Demos
|
| 131 |
+
|
| 132 |
+
#### Basic Demo
|
| 133 |
+
|
| 134 |
+
original.js:
|
| 135 |
+
|
| 136 |
+
```js
|
| 137 |
+
throw new Error('test'); // This is the original code
|
| 138 |
+
```
|
| 139 |
+
|
| 140 |
+
compiled.js:
|
| 141 |
+
|
| 142 |
+
```js
|
| 143 |
+
require('@cspotcode/source-map-support').install();
|
| 144 |
+
|
| 145 |
+
throw new Error('test'); // This is the compiled code
|
| 146 |
+
// The next line defines the sourceMapping.
|
| 147 |
+
//# sourceMappingURL=compiled.js.map
|
| 148 |
+
```
|
| 149 |
+
|
| 150 |
+
compiled.js.map:
|
| 151 |
+
|
| 152 |
+
```json
|
| 153 |
+
{
|
| 154 |
+
"version": 3,
|
| 155 |
+
"file": "compiled.js",
|
| 156 |
+
"sources": ["original.js"],
|
| 157 |
+
"names": [],
|
| 158 |
+
"mappings": ";;AAAA,MAAM,IAAI"
|
| 159 |
+
}
|
| 160 |
+
```
|
| 161 |
+
|
| 162 |
+
Run compiled.js using node (notice how the stack trace uses original.js instead of compiled.js):
|
| 163 |
+
|
| 164 |
+
```
|
| 165 |
+
$ node compiled.js
|
| 166 |
+
|
| 167 |
+
original.js:1
|
| 168 |
+
throw new Error('test'); // This is the original code
|
| 169 |
+
^
|
| 170 |
+
Error: test
|
| 171 |
+
at Object.<anonymous> (original.js:1:7)
|
| 172 |
+
at Module._compile (module.js:456:26)
|
| 173 |
+
at Object.Module._extensions..js (module.js:474:10)
|
| 174 |
+
at Module.load (module.js:356:32)
|
| 175 |
+
at Function.Module._load (module.js:312:12)
|
| 176 |
+
at Function.Module.runMain (module.js:497:10)
|
| 177 |
+
at startup (node.js:119:16)
|
| 178 |
+
at node.js:901:3
|
| 179 |
+
```
|
| 180 |
+
|
| 181 |
+
#### TypeScript Demo
|
| 182 |
+
|
| 183 |
+
demo.ts:
|
| 184 |
+
|
| 185 |
+
```typescript
|
| 186 |
+
declare function require(name: string);
|
| 187 |
+
require('@cspotcode/source-map-support').install();
|
| 188 |
+
class Foo {
|
| 189 |
+
constructor() { this.bar(); }
|
| 190 |
+
bar() { throw new Error('this is a demo'); }
|
| 191 |
+
}
|
| 192 |
+
new Foo();
|
| 193 |
+
```
|
| 194 |
+
|
| 195 |
+
Compile and run the file using the TypeScript compiler from the terminal:
|
| 196 |
+
|
| 197 |
+
```
|
| 198 |
+
$ npm install source-map-support typescript
|
| 199 |
+
$ node_modules/typescript/bin/tsc -sourcemap demo.ts
|
| 200 |
+
$ node demo.js
|
| 201 |
+
|
| 202 |
+
demo.ts:5
|
| 203 |
+
bar() { throw new Error('this is a demo'); }
|
| 204 |
+
^
|
| 205 |
+
Error: this is a demo
|
| 206 |
+
at Foo.bar (demo.ts:5:17)
|
| 207 |
+
at new Foo (demo.ts:4:24)
|
| 208 |
+
at Object.<anonymous> (demo.ts:7:1)
|
| 209 |
+
at Module._compile (module.js:456:26)
|
| 210 |
+
at Object.Module._extensions..js (module.js:474:10)
|
| 211 |
+
at Module.load (module.js:356:32)
|
| 212 |
+
at Function.Module._load (module.js:312:12)
|
| 213 |
+
at Function.Module.runMain (module.js:497:10)
|
| 214 |
+
at startup (node.js:119:16)
|
| 215 |
+
at node.js:901:3
|
| 216 |
+
```
|
| 217 |
+
|
| 218 |
+
There is also the option to use `-r source-map-support/register` with typescript, without the need add the `require('@cspotcode/source-map-support').install()` in the code base:
|
| 219 |
+
|
| 220 |
+
```
|
| 221 |
+
$ npm install source-map-support typescript
|
| 222 |
+
$ node_modules/typescript/bin/tsc -sourcemap demo.ts
|
| 223 |
+
$ node -r source-map-support/register demo.js
|
| 224 |
+
|
| 225 |
+
demo.ts:5
|
| 226 |
+
bar() { throw new Error('this is a demo'); }
|
| 227 |
+
^
|
| 228 |
+
Error: this is a demo
|
| 229 |
+
at Foo.bar (demo.ts:5:17)
|
| 230 |
+
at new Foo (demo.ts:4:24)
|
| 231 |
+
at Object.<anonymous> (demo.ts:7:1)
|
| 232 |
+
at Module._compile (module.js:456:26)
|
| 233 |
+
at Object.Module._extensions..js (module.js:474:10)
|
| 234 |
+
at Module.load (module.js:356:32)
|
| 235 |
+
at Function.Module._load (module.js:312:12)
|
| 236 |
+
at Function.Module.runMain (module.js:497:10)
|
| 237 |
+
at startup (node.js:119:16)
|
| 238 |
+
at node.js:901:3
|
| 239 |
+
```
|
| 240 |
+
|
| 241 |
+
#### CoffeeScript Demo
|
| 242 |
+
|
| 243 |
+
demo.coffee:
|
| 244 |
+
|
| 245 |
+
```coffee
|
| 246 |
+
require('@cspotcode/source-map-support').install()
|
| 247 |
+
foo = ->
|
| 248 |
+
bar = -> throw new Error 'this is a demo'
|
| 249 |
+
bar()
|
| 250 |
+
foo()
|
| 251 |
+
```
|
| 252 |
+
|
| 253 |
+
Compile and run the file using the CoffeeScript compiler from the terminal:
|
| 254 |
+
|
| 255 |
+
```sh
|
| 256 |
+
$ npm install @cspotcode/source-map-support coffeescript
|
| 257 |
+
$ node_modules/.bin/coffee --map --compile demo.coffee
|
| 258 |
+
$ node demo.js
|
| 259 |
+
|
| 260 |
+
demo.coffee:3
|
| 261 |
+
bar = -> throw new Error 'this is a demo'
|
| 262 |
+
^
|
| 263 |
+
Error: this is a demo
|
| 264 |
+
at bar (demo.coffee:3:22)
|
| 265 |
+
at foo (demo.coffee:4:3)
|
| 266 |
+
at Object.<anonymous> (demo.coffee:5:1)
|
| 267 |
+
at Object.<anonymous> (demo.coffee:1:1)
|
| 268 |
+
at Module._compile (module.js:456:26)
|
| 269 |
+
at Object.Module._extensions..js (module.js:474:10)
|
| 270 |
+
at Module.load (module.js:356:32)
|
| 271 |
+
at Function.Module._load (module.js:312:12)
|
| 272 |
+
at Function.Module.runMain (module.js:497:10)
|
| 273 |
+
at startup (node.js:119:16)
|
| 274 |
+
```
|
| 275 |
+
|
| 276 |
+
## Tests
|
| 277 |
+
|
| 278 |
+
This repo contains both automated tests for node and manual tests for the browser. The automated tests can be run using mocha (type `mocha` in the root directory). To run the manual tests:
|
| 279 |
+
|
| 280 |
+
* Build the tests using `build.js`
|
| 281 |
+
* Launch the HTTP server (`npm run serve-tests`) and visit
|
| 282 |
+
* http://127.0.0.1:1336/amd-test
|
| 283 |
+
* http://127.0.0.1:1336/browser-test
|
| 284 |
+
* http://127.0.0.1:1336/browserify-test - **Currently not working** due to a bug with browserify (see [pull request #66](https://github.com/evanw/node-source-map-support/pull/66) for details).
|
| 285 |
+
* For `header-test`, run `server.js` inside that directory and visit http://127.0.0.1:1337/
|
| 286 |
+
|
| 287 |
+
## License
|
| 288 |
+
|
| 289 |
+
This code is available under the [MIT license](http://opensource.org/licenses/MIT).
|
bunx-1000-wrangler@latest/node_modules/@esbuild/linux-arm64/README.md
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# esbuild
|
| 2 |
+
|
| 3 |
+
This is the Linux ARM 64-bit binary for esbuild, a JavaScript bundler and minifier. See https://github.com/evanw/esbuild for details.
|
bunx-1000-wrangler@latest/node_modules/@img/colour/LICENSE.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Licensing
|
| 2 |
+
|
| 3 |
+
## color
|
| 4 |
+
|
| 5 |
+
Copyright (c) 2012 Heather Arthur
|
| 6 |
+
|
| 7 |
+
Permission is hereby granted, free of charge, to any person obtaining
|
| 8 |
+
a copy of this software and associated documentation files (the
|
| 9 |
+
"Software"), to deal in the Software without restriction, including
|
| 10 |
+
without limitation the rights to use, copy, modify, merge, publish,
|
| 11 |
+
distribute, sublicense, and/or sell copies of the Software, and to
|
| 12 |
+
permit persons to whom the Software is furnished to do so, subject to
|
| 13 |
+
the following conditions:
|
| 14 |
+
|
| 15 |
+
The above copyright notice and this permission notice shall be
|
| 16 |
+
included in all copies or substantial portions of the Software.
|
| 17 |
+
|
| 18 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| 19 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
| 20 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
| 21 |
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
| 22 |
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
| 23 |
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
| 24 |
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
| 25 |
+
|
| 26 |
+
## color-convert
|
| 27 |
+
|
| 28 |
+
Copyright (c) 2011-2016 Heather Arthur <fayearthur@gmail.com>.
|
| 29 |
+
Copyright (c) 2016-2021 Josh Junon <josh@junon.me>.
|
| 30 |
+
|
| 31 |
+
Permission is hereby granted, free of charge, to any person obtaining
|
| 32 |
+
a copy of this software and associated documentation files (the
|
| 33 |
+
"Software"), to deal in the Software without restriction, including
|
| 34 |
+
without limitation the rights to use, copy, modify, merge, publish,
|
| 35 |
+
distribute, sublicense, and/or sell copies of the Software, and to
|
| 36 |
+
permit persons to whom the Software is furnished to do so, subject to
|
| 37 |
+
the following conditions:
|
| 38 |
+
|
| 39 |
+
The above copyright notice and this permission notice shall be
|
| 40 |
+
included in all copies or substantial portions of the Software.
|
| 41 |
+
|
| 42 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| 43 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
| 44 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
| 45 |
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
| 46 |
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
| 47 |
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
| 48 |
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
| 49 |
+
|
| 50 |
+
## color-string
|
| 51 |
+
|
| 52 |
+
Copyright (c) 2011 Heather Arthur <fayearthur@gmail.com>
|
| 53 |
+
|
| 54 |
+
Permission is hereby granted, free of charge, to any person obtaining
|
| 55 |
+
a copy of this software and associated documentation files (the
|
| 56 |
+
"Software"), to deal in the Software without restriction, including
|
| 57 |
+
without limitation the rights to use, copy, modify, merge, publish,
|
| 58 |
+
distribute, sublicense, and/or sell copies of the Software, and to
|
| 59 |
+
permit persons to whom the Software is furnished to do so, subject to
|
| 60 |
+
the following conditions:
|
| 61 |
+
|
| 62 |
+
The above copyright notice and this permission notice shall be
|
| 63 |
+
included in all copies or substantial portions of the Software.
|
| 64 |
+
|
| 65 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| 66 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
| 67 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
| 68 |
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
| 69 |
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
| 70 |
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
| 71 |
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
| 72 |
+
|
| 73 |
+
## color-name
|
| 74 |
+
|
| 75 |
+
The MIT License (MIT)
|
| 76 |
+
Copyright (c) 2015 Dmitry Ivanov
|
| 77 |
+
|
| 78 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
| 79 |
+
|
| 80 |
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
| 81 |
+
|
| 82 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
bunx-1000-wrangler@latest/node_modules/@img/colour/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# `@img/colour`
|
| 2 |
+
|
| 3 |
+
The latest version of the
|
| 4 |
+
[color](https://www.npmjs.com/package/color)
|
| 5 |
+
package is now ESM-only,
|
| 6 |
+
however some JavaScript runtimes do not yet support this,
|
| 7 |
+
which includes versions of Node.js prior to 20.19.0.
|
| 8 |
+
|
| 9 |
+
This package converts the `color` package and its dependencies,
|
| 10 |
+
all of which are MIT-licensed, to CommonJS.
|
| 11 |
+
|
| 12 |
+
- [color](https://www.npmjs.com/package/color)
|
| 13 |
+
- [color-convert](https://www.npmjs.com/package/color-convert)
|
| 14 |
+
- [color-string](https://www.npmjs.com/package/color-string)
|
| 15 |
+
- [color-name](https://www.npmjs.com/package/color-name)
|
bunx-1000-wrangler@latest/node_modules/@img/sharp-libvips-linux-arm64/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# `@img/sharp-libvips-linux-arm64`
|
| 2 |
+
|
| 3 |
+
Prebuilt libvips and dependencies for use with sharp on Linux (glibc) 64-bit ARM.
|
| 4 |
+
|
| 5 |
+
## Licensing
|
| 6 |
+
|
| 7 |
+
This software contains third-party libraries
|
| 8 |
+
used under the terms of the following licences:
|
| 9 |
+
|
| 10 |
+
| Library | Used under the terms of |
|
| 11 |
+
|---------------|-----------------------------------------------------------------------------------------------------------|
|
| 12 |
+
| aom | BSD 2-Clause + [Alliance for Open Media Patent License 1.0](https://aomedia.org/license/patent-license/) |
|
| 13 |
+
| cairo | Mozilla Public License 2.0 |
|
| 14 |
+
| cgif | MIT Licence |
|
| 15 |
+
| expat | MIT Licence |
|
| 16 |
+
| fontconfig | [fontconfig Licence](https://gitlab.freedesktop.org/fontconfig/fontconfig/blob/main/COPYING) (BSD-like) |
|
| 17 |
+
| freetype | [freetype Licence](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT) (BSD-like) |
|
| 18 |
+
| fribidi | LGPLv3 |
|
| 19 |
+
| glib | LGPLv3 |
|
| 20 |
+
| harfbuzz | MIT Licence |
|
| 21 |
+
| highway | Apache-2.0 License, BSD 3-Clause |
|
| 22 |
+
| lcms | MIT Licence |
|
| 23 |
+
| libarchive | BSD 2-Clause |
|
| 24 |
+
| libexif | LGPLv3 |
|
| 25 |
+
| libffi | MIT Licence |
|
| 26 |
+
| libheif | LGPLv3 |
|
| 27 |
+
| libimagequant | [BSD 2-Clause](https://github.com/lovell/libimagequant/blob/main/COPYRIGHT) |
|
| 28 |
+
| libnsgif | MIT Licence |
|
| 29 |
+
| libpng | [libpng License](https://github.com/pnggroup/libpng/blob/master/LICENSE) |
|
| 30 |
+
| librsvg | LGPLv3 |
|
| 31 |
+
| libspng | [BSD 2-Clause, libpng License](https://github.com/randy408/libspng/blob/master/LICENSE) |
|
| 32 |
+
| libtiff | [libtiff License](https://gitlab.com/libtiff/libtiff/blob/master/LICENSE.md) (BSD-like) |
|
| 33 |
+
| libvips | LGPLv3 |
|
| 34 |
+
| libwebp | New BSD License |
|
| 35 |
+
| libxml2 | MIT Licence |
|
| 36 |
+
| mozjpeg | [zlib License, IJG License, BSD-3-Clause](https://github.com/mozilla/mozjpeg/blob/master/LICENSE.md) |
|
| 37 |
+
| pango | LGPLv3 |
|
| 38 |
+
| pixman | MIT Licence |
|
| 39 |
+
| proxy-libintl | LGPLv3 |
|
| 40 |
+
| zlib-ng | [zlib Licence](https://github.com/zlib-ng/zlib-ng/blob/develop/LICENSE.md) |
|
| 41 |
+
|
| 42 |
+
Use of libraries under the terms of the LGPLv3 is via the
|
| 43 |
+
"any later version" clause of the LGPLv2 or LGPLv2.1.
|
| 44 |
+
|
| 45 |
+
Please report any errors or omissions via
|
| 46 |
+
https://github.com/lovell/sharp-libvips/issues/new
|
bunx-1000-wrangler@latest/node_modules/@img/sharp-libvips-linuxmusl-arm64/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# `@img/sharp-libvips-linuxmusl-arm64`
|
| 2 |
+
|
| 3 |
+
Prebuilt libvips and dependencies for use with sharp on Linux (musl) 64-bit ARM.
|
| 4 |
+
|
| 5 |
+
## Licensing
|
| 6 |
+
|
| 7 |
+
This software contains third-party libraries
|
| 8 |
+
used under the terms of the following licences:
|
| 9 |
+
|
| 10 |
+
| Library | Used under the terms of |
|
| 11 |
+
|---------------|-----------------------------------------------------------------------------------------------------------|
|
| 12 |
+
| aom | BSD 2-Clause + [Alliance for Open Media Patent License 1.0](https://aomedia.org/license/patent-license/) |
|
| 13 |
+
| cairo | Mozilla Public License 2.0 |
|
| 14 |
+
| cgif | MIT Licence |
|
| 15 |
+
| expat | MIT Licence |
|
| 16 |
+
| fontconfig | [fontconfig Licence](https://gitlab.freedesktop.org/fontconfig/fontconfig/blob/main/COPYING) (BSD-like) |
|
| 17 |
+
| freetype | [freetype Licence](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT) (BSD-like) |
|
| 18 |
+
| fribidi | LGPLv3 |
|
| 19 |
+
| glib | LGPLv3 |
|
| 20 |
+
| harfbuzz | MIT Licence |
|
| 21 |
+
| highway | Apache-2.0 License, BSD 3-Clause |
|
| 22 |
+
| lcms | MIT Licence |
|
| 23 |
+
| libarchive | BSD 2-Clause |
|
| 24 |
+
| libexif | LGPLv3 |
|
| 25 |
+
| libffi | MIT Licence |
|
| 26 |
+
| libheif | LGPLv3 |
|
| 27 |
+
| libimagequant | [BSD 2-Clause](https://github.com/lovell/libimagequant/blob/main/COPYRIGHT) |
|
| 28 |
+
| libnsgif | MIT Licence |
|
| 29 |
+
| libpng | [libpng License](https://github.com/pnggroup/libpng/blob/master/LICENSE) |
|
| 30 |
+
| librsvg | LGPLv3 |
|
| 31 |
+
| libspng | [BSD 2-Clause, libpng License](https://github.com/randy408/libspng/blob/master/LICENSE) |
|
| 32 |
+
| libtiff | [libtiff License](https://gitlab.com/libtiff/libtiff/blob/master/LICENSE.md) (BSD-like) |
|
| 33 |
+
| libvips | LGPLv3 |
|
| 34 |
+
| libwebp | New BSD License |
|
| 35 |
+
| libxml2 | MIT Licence |
|
| 36 |
+
| mozjpeg | [zlib License, IJG License, BSD-3-Clause](https://github.com/mozilla/mozjpeg/blob/master/LICENSE.md) |
|
| 37 |
+
| pango | LGPLv3 |
|
| 38 |
+
| pixman | MIT Licence |
|
| 39 |
+
| proxy-libintl | LGPLv3 |
|
| 40 |
+
| zlib-ng | [zlib Licence](https://github.com/zlib-ng/zlib-ng/blob/develop/LICENSE.md) |
|
| 41 |
+
|
| 42 |
+
Use of libraries under the terms of the LGPLv3 is via the
|
| 43 |
+
"any later version" clause of the LGPLv2 or LGPLv2.1.
|
| 44 |
+
|
| 45 |
+
Please report any errors or omissions via
|
| 46 |
+
https://github.com/lovell/sharp-libvips/issues/new
|
bunx-1000-wrangler@latest/node_modules/@img/sharp-linux-arm64/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# `@img/sharp-linux-arm64`
|
| 2 |
+
|
| 3 |
+
Prebuilt sharp for use with Linux (glibc) 64-bit ARM.
|
| 4 |
+
|
| 5 |
+
## Licensing
|
| 6 |
+
|
| 7 |
+
Copyright 2013 Lovell Fuller and others.
|
| 8 |
+
|
| 9 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
you may not use this file except in compliance with the License.
|
| 11 |
+
You may obtain a copy of the License at
|
| 12 |
+
[https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
| 13 |
+
|
| 14 |
+
Unless required by applicable law or agreed to in writing, software
|
| 15 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 16 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 17 |
+
See the License for the specific language governing permissions and
|
| 18 |
+
limitations under the License.
|
bunx-1000-wrangler@latest/node_modules/@img/sharp-linuxmusl-arm64/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# `@img/sharp-linuxmusl-arm64`
|
| 2 |
+
|
| 3 |
+
Prebuilt sharp for use with Linux (musl) 64-bit ARM.
|
| 4 |
+
|
| 5 |
+
## Licensing
|
| 6 |
+
|
| 7 |
+
Copyright 2013 Lovell Fuller and others.
|
| 8 |
+
|
| 9 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 10 |
+
you may not use this file except in compliance with the License.
|
| 11 |
+
You may obtain a copy of the License at
|
| 12 |
+
[https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
| 13 |
+
|
| 14 |
+
Unless required by applicable law or agreed to in writing, software
|
| 15 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 16 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 17 |
+
See the License for the specific language governing permissions and
|
| 18 |
+
limitations under the License.
|
bunx-1000-wrangler@latest/node_modules/@jridgewell/resolve-uri/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# @jridgewell/resolve-uri
|
| 2 |
+
|
| 3 |
+
> Resolve a URI relative to an optional base URI
|
| 4 |
+
|
| 5 |
+
Resolve any combination of absolute URIs, protocol-realtive URIs, absolute paths, or relative paths.
|
| 6 |
+
|
| 7 |
+
## Installation
|
| 8 |
+
|
| 9 |
+
```sh
|
| 10 |
+
npm install @jridgewell/resolve-uri
|
| 11 |
+
```
|
| 12 |
+
|
| 13 |
+
## Usage
|
| 14 |
+
|
| 15 |
+
```typescript
|
| 16 |
+
function resolve(input: string, base?: string): string;
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
```js
|
| 20 |
+
import resolve from '@jridgewell/resolve-uri';
|
| 21 |
+
|
| 22 |
+
resolve('foo', 'https://example.com'); // => 'https://example.com/foo'
|
| 23 |
+
```
|
| 24 |
+
|
| 25 |
+
| Input | Base | Resolution | Explanation |
|
| 26 |
+
|-----------------------|-------------------------|--------------------------------|--------------------------------------------------------------|
|
| 27 |
+
| `https://example.com` | _any_ | `https://example.com/` | Input is normalized only |
|
| 28 |
+
| `//example.com` | `https://base.com/` | `https://example.com/` | Input inherits the base's protocol |
|
| 29 |
+
| `//example.com` | _rest_ | `//example.com/` | Input is normalized only |
|
| 30 |
+
| `/example` | `https://base.com/` | `https://base.com/example` | Input inherits the base's origin |
|
| 31 |
+
| `/example` | `//base.com/` | `//base.com/example` | Input inherits the base's host and remains protocol relative |
|
| 32 |
+
| `/example` | _rest_ | `/example` | Input is normalized only |
|
| 33 |
+
| `example` | `https://base.com/dir/` | `https://base.com/dir/example` | Input is joined with the base |
|
| 34 |
+
| `example` | `https://base.com/file` | `https://base.com/example` | Input is joined with the base without its file |
|
| 35 |
+
| `example` | `//base.com/dir/` | `//base.com/dir/example` | Input is joined with the base's last directory |
|
| 36 |
+
| `example` | `//base.com/file` | `//base.com/example` | Input is joined with the base without its file |
|
| 37 |
+
| `example` | `/base/dir/` | `/base/dir/example` | Input is joined with the base's last directory |
|
| 38 |
+
| `example` | `/base/file` | `/base/example` | Input is joined with the base without its file |
|
| 39 |
+
| `example` | `base/dir/` | `base/dir/example` | Input is joined with the base's last directory |
|
| 40 |
+
| `example` | `base/file` | `base/example` | Input is joined with the base without its file |
|
bunx-1000-wrangler@latest/node_modules/@jridgewell/sourcemap-codec/README.md
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# @jridgewell/sourcemap-codec
|
| 2 |
+
|
| 3 |
+
Encode/decode the `mappings` property of a [sourcemap](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit).
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
## Why?
|
| 7 |
+
|
| 8 |
+
Sourcemaps are difficult to generate and manipulate, because the `mappings` property – the part that actually links the generated code back to the original source – is encoded using an obscure method called [Variable-length quantity](https://en.wikipedia.org/wiki/Variable-length_quantity). On top of that, each segment in the mapping contains offsets rather than absolute indices, which means that you can't look at a segment in isolation – you have to understand the whole sourcemap.
|
| 9 |
+
|
| 10 |
+
This package makes the process slightly easier.
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
## Installation
|
| 14 |
+
|
| 15 |
+
```bash
|
| 16 |
+
npm install @jridgewell/sourcemap-codec
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
## Usage
|
| 21 |
+
|
| 22 |
+
```js
|
| 23 |
+
import { encode, decode } from '@jridgewell/sourcemap-codec';
|
| 24 |
+
|
| 25 |
+
var decoded = decode( ';EAEEA,EAAE,EAAC,CAAE;ECQY,UACC' );
|
| 26 |
+
|
| 27 |
+
assert.deepEqual( decoded, [
|
| 28 |
+
// the first line (of the generated code) has no mappings,
|
| 29 |
+
// as shown by the starting semi-colon (which separates lines)
|
| 30 |
+
[],
|
| 31 |
+
|
| 32 |
+
// the second line contains four (comma-separated) segments
|
| 33 |
+
[
|
| 34 |
+
// segments are encoded as you'd expect:
|
| 35 |
+
// [ generatedCodeColumn, sourceIndex, sourceCodeLine, sourceCodeColumn, nameIndex ]
|
| 36 |
+
|
| 37 |
+
// i.e. the first segment begins at column 2, and maps back to the second column
|
| 38 |
+
// of the second line (both zero-based) of the 0th source, and uses the 0th
|
| 39 |
+
// name in the `map.names` array
|
| 40 |
+
[ 2, 0, 2, 2, 0 ],
|
| 41 |
+
|
| 42 |
+
// the remaining segments are 4-length rather than 5-length,
|
| 43 |
+
// because they don't map a name
|
| 44 |
+
[ 4, 0, 2, 4 ],
|
| 45 |
+
[ 6, 0, 2, 5 ],
|
| 46 |
+
[ 7, 0, 2, 7 ]
|
| 47 |
+
],
|
| 48 |
+
|
| 49 |
+
// the final line contains two segments
|
| 50 |
+
[
|
| 51 |
+
[ 2, 1, 10, 19 ],
|
| 52 |
+
[ 12, 1, 11, 20 ]
|
| 53 |
+
]
|
| 54 |
+
]);
|
| 55 |
+
|
| 56 |
+
var encoded = encode( decoded );
|
| 57 |
+
assert.equal( encoded, ';EAEEA,EAAE,EAAC,CAAE;ECQY,UACC' );
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
## Benchmarks
|
| 61 |
+
|
| 62 |
+
```
|
| 63 |
+
node v20.10.0
|
| 64 |
+
|
| 65 |
+
amp.js.map - 45120 segments
|
| 66 |
+
|
| 67 |
+
Decode Memory Usage:
|
| 68 |
+
local code 5815135 bytes
|
| 69 |
+
@jridgewell/sourcemap-codec 1.4.15 5868160 bytes
|
| 70 |
+
sourcemap-codec 5492584 bytes
|
| 71 |
+
source-map-0.6.1 13569984 bytes
|
| 72 |
+
source-map-0.8.0 6390584 bytes
|
| 73 |
+
chrome dev tools 8011136 bytes
|
| 74 |
+
Smallest memory usage is sourcemap-codec
|
| 75 |
+
|
| 76 |
+
Decode speed:
|
| 77 |
+
decode: local code x 492 ops/sec ±1.22% (90 runs sampled)
|
| 78 |
+
decode: @jridgewell/sourcemap-codec 1.4.15 x 499 ops/sec ±1.16% (89 runs sampled)
|
| 79 |
+
decode: sourcemap-codec x 376 ops/sec ±1.66% (89 runs sampled)
|
| 80 |
+
decode: source-map-0.6.1 x 34.99 ops/sec ±0.94% (48 runs sampled)
|
| 81 |
+
decode: source-map-0.8.0 x 351 ops/sec ±0.07% (95 runs sampled)
|
| 82 |
+
chrome dev tools x 165 ops/sec ±0.91% (86 runs sampled)
|
| 83 |
+
Fastest is decode: @jridgewell/sourcemap-codec 1.4.15
|
| 84 |
+
|
| 85 |
+
Encode Memory Usage:
|
| 86 |
+
local code 444248 bytes
|
| 87 |
+
@jridgewell/sourcemap-codec 1.4.15 623024 bytes
|
| 88 |
+
sourcemap-codec 8696280 bytes
|
| 89 |
+
source-map-0.6.1 8745176 bytes
|
| 90 |
+
source-map-0.8.0 8736624 bytes
|
| 91 |
+
Smallest memory usage is local code
|
| 92 |
+
|
| 93 |
+
Encode speed:
|
| 94 |
+
encode: local code x 796 ops/sec ±0.11% (97 runs sampled)
|
| 95 |
+
encode: @jridgewell/sourcemap-codec 1.4.15 x 795 ops/sec ±0.25% (98 runs sampled)
|
| 96 |
+
encode: sourcemap-codec x 231 ops/sec ±0.83% (86 runs sampled)
|
| 97 |
+
encode: source-map-0.6.1 x 166 ops/sec ±0.57% (86 runs sampled)
|
| 98 |
+
encode: source-map-0.8.0 x 203 ops/sec ±0.45% (88 runs sampled)
|
| 99 |
+
Fastest is encode: local code,encode: @jridgewell/sourcemap-codec 1.4.15
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
***
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
babel.min.js.map - 347793 segments
|
| 106 |
+
|
| 107 |
+
Decode Memory Usage:
|
| 108 |
+
local code 35424960 bytes
|
| 109 |
+
@jridgewell/sourcemap-codec 1.4.15 35424696 bytes
|
| 110 |
+
sourcemap-codec 36033464 bytes
|
| 111 |
+
source-map-0.6.1 62253704 bytes
|
| 112 |
+
source-map-0.8.0 43843920 bytes
|
| 113 |
+
chrome dev tools 45111400 bytes
|
| 114 |
+
Smallest memory usage is @jridgewell/sourcemap-codec 1.4.15
|
| 115 |
+
|
| 116 |
+
Decode speed:
|
| 117 |
+
decode: local code x 38.18 ops/sec ±5.44% (52 runs sampled)
|
| 118 |
+
decode: @jridgewell/sourcemap-codec 1.4.15 x 38.36 ops/sec ±5.02% (52 runs sampled)
|
| 119 |
+
decode: sourcemap-codec x 34.05 ops/sec ±4.45% (47 runs sampled)
|
| 120 |
+
decode: source-map-0.6.1 x 4.31 ops/sec ±2.76% (15 runs sampled)
|
| 121 |
+
decode: source-map-0.8.0 x 55.60 ops/sec ±0.13% (73 runs sampled)
|
| 122 |
+
chrome dev tools x 16.94 ops/sec ±3.78% (46 runs sampled)
|
| 123 |
+
Fastest is decode: source-map-0.8.0
|
| 124 |
+
|
| 125 |
+
Encode Memory Usage:
|
| 126 |
+
local code 2606016 bytes
|
| 127 |
+
@jridgewell/sourcemap-codec 1.4.15 2626440 bytes
|
| 128 |
+
sourcemap-codec 21152576 bytes
|
| 129 |
+
source-map-0.6.1 25023928 bytes
|
| 130 |
+
source-map-0.8.0 25256448 bytes
|
| 131 |
+
Smallest memory usage is local code
|
| 132 |
+
|
| 133 |
+
Encode speed:
|
| 134 |
+
encode: local code x 127 ops/sec ±0.18% (83 runs sampled)
|
| 135 |
+
encode: @jridgewell/sourcemap-codec 1.4.15 x 128 ops/sec ±0.26% (83 runs sampled)
|
| 136 |
+
encode: sourcemap-codec x 29.31 ops/sec ±2.55% (53 runs sampled)
|
| 137 |
+
encode: source-map-0.6.1 x 18.85 ops/sec ±3.19% (36 runs sampled)
|
| 138 |
+
encode: source-map-0.8.0 x 19.34 ops/sec ±1.97% (36 runs sampled)
|
| 139 |
+
Fastest is encode: @jridgewell/sourcemap-codec 1.4.15
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
***
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
preact.js.map - 1992 segments
|
| 146 |
+
|
| 147 |
+
Decode Memory Usage:
|
| 148 |
+
local code 261696 bytes
|
| 149 |
+
@jridgewell/sourcemap-codec 1.4.15 244296 bytes
|
| 150 |
+
sourcemap-codec 302816 bytes
|
| 151 |
+
source-map-0.6.1 939176 bytes
|
| 152 |
+
source-map-0.8.0 336 bytes
|
| 153 |
+
chrome dev tools 587368 bytes
|
| 154 |
+
Smallest memory usage is source-map-0.8.0
|
| 155 |
+
|
| 156 |
+
Decode speed:
|
| 157 |
+
decode: local code x 17,782 ops/sec ±0.32% (97 runs sampled)
|
| 158 |
+
decode: @jridgewell/sourcemap-codec 1.4.15 x 17,863 ops/sec ±0.40% (100 runs sampled)
|
| 159 |
+
decode: sourcemap-codec x 12,453 ops/sec ±0.27% (101 runs sampled)
|
| 160 |
+
decode: source-map-0.6.1 x 1,288 ops/sec ±1.05% (96 runs sampled)
|
| 161 |
+
decode: source-map-0.8.0 x 9,289 ops/sec ±0.27% (101 runs sampled)
|
| 162 |
+
chrome dev tools x 4,769 ops/sec ±0.18% (100 runs sampled)
|
| 163 |
+
Fastest is decode: @jridgewell/sourcemap-codec 1.4.15
|
| 164 |
+
|
| 165 |
+
Encode Memory Usage:
|
| 166 |
+
local code 262944 bytes
|
| 167 |
+
@jridgewell/sourcemap-codec 1.4.15 25544 bytes
|
| 168 |
+
sourcemap-codec 323048 bytes
|
| 169 |
+
source-map-0.6.1 507808 bytes
|
| 170 |
+
source-map-0.8.0 507480 bytes
|
| 171 |
+
Smallest memory usage is @jridgewell/sourcemap-codec 1.4.15
|
| 172 |
+
|
| 173 |
+
Encode speed:
|
| 174 |
+
encode: local code x 24,207 ops/sec ±0.79% (95 runs sampled)
|
| 175 |
+
encode: @jridgewell/sourcemap-codec 1.4.15 x 24,288 ops/sec ±0.48% (96 runs sampled)
|
| 176 |
+
encode: sourcemap-codec x 6,761 ops/sec ±0.21% (100 runs sampled)
|
| 177 |
+
encode: source-map-0.6.1 x 5,374 ops/sec ±0.17% (99 runs sampled)
|
| 178 |
+
encode: source-map-0.8.0 x 5,633 ops/sec ±0.32% (99 runs sampled)
|
| 179 |
+
Fastest is encode: @jridgewell/sourcemap-codec 1.4.15,encode: local code
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
***
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
react.js.map - 5726 segments
|
| 186 |
+
|
| 187 |
+
Decode Memory Usage:
|
| 188 |
+
local code 678816 bytes
|
| 189 |
+
@jridgewell/sourcemap-codec 1.4.15 678816 bytes
|
| 190 |
+
sourcemap-codec 816400 bytes
|
| 191 |
+
source-map-0.6.1 2288864 bytes
|
| 192 |
+
source-map-0.8.0 721360 bytes
|
| 193 |
+
chrome dev tools 1012512 bytes
|
| 194 |
+
Smallest memory usage is local code
|
| 195 |
+
|
| 196 |
+
Decode speed:
|
| 197 |
+
decode: local code x 6,178 ops/sec ±0.19% (98 runs sampled)
|
| 198 |
+
decode: @jridgewell/sourcemap-codec 1.4.15 x 6,261 ops/sec ±0.22% (100 runs sampled)
|
| 199 |
+
decode: sourcemap-codec x 4,472 ops/sec ±0.90% (99 runs sampled)
|
| 200 |
+
decode: source-map-0.6.1 x 449 ops/sec ±0.31% (95 runs sampled)
|
| 201 |
+
decode: source-map-0.8.0 x 3,219 ops/sec ±0.13% (100 runs sampled)
|
| 202 |
+
chrome dev tools x 1,743 ops/sec ±0.20% (99 runs sampled)
|
| 203 |
+
Fastest is decode: @jridgewell/sourcemap-codec 1.4.15
|
| 204 |
+
|
| 205 |
+
Encode Memory Usage:
|
| 206 |
+
local code 140960 bytes
|
| 207 |
+
@jridgewell/sourcemap-codec 1.4.15 159808 bytes
|
| 208 |
+
sourcemap-codec 969304 bytes
|
| 209 |
+
source-map-0.6.1 930520 bytes
|
| 210 |
+
source-map-0.8.0 930248 bytes
|
| 211 |
+
Smallest memory usage is local code
|
| 212 |
+
|
| 213 |
+
Encode speed:
|
| 214 |
+
encode: local code x 8,013 ops/sec ±0.19% (100 runs sampled)
|
| 215 |
+
encode: @jridgewell/sourcemap-codec 1.4.15 x 7,989 ops/sec ±0.20% (101 runs sampled)
|
| 216 |
+
encode: sourcemap-codec x 2,472 ops/sec ±0.21% (99 runs sampled)
|
| 217 |
+
encode: source-map-0.6.1 x 2,200 ops/sec ±0.17% (99 runs sampled)
|
| 218 |
+
encode: source-map-0.8.0 x 2,220 ops/sec ±0.37% (99 runs sampled)
|
| 219 |
+
Fastest is encode: local code
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
***
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
vscode.map - 2141001 segments
|
| 226 |
+
|
| 227 |
+
Decode Memory Usage:
|
| 228 |
+
local code 198955264 bytes
|
| 229 |
+
@jridgewell/sourcemap-codec 1.4.15 199175352 bytes
|
| 230 |
+
sourcemap-codec 199102688 bytes
|
| 231 |
+
source-map-0.6.1 386323432 bytes
|
| 232 |
+
source-map-0.8.0 244116432 bytes
|
| 233 |
+
chrome dev tools 293734280 bytes
|
| 234 |
+
Smallest memory usage is local code
|
| 235 |
+
|
| 236 |
+
Decode speed:
|
| 237 |
+
decode: local code x 3.90 ops/sec ±22.21% (15 runs sampled)
|
| 238 |
+
decode: @jridgewell/sourcemap-codec 1.4.15 x 3.95 ops/sec ±23.53% (15 runs sampled)
|
| 239 |
+
decode: sourcemap-codec x 3.82 ops/sec ±17.94% (14 runs sampled)
|
| 240 |
+
decode: source-map-0.6.1 x 0.61 ops/sec ±7.81% (6 runs sampled)
|
| 241 |
+
decode: source-map-0.8.0 x 9.54 ops/sec ±0.28% (28 runs sampled)
|
| 242 |
+
chrome dev tools x 2.18 ops/sec ±10.58% (10 runs sampled)
|
| 243 |
+
Fastest is decode: source-map-0.8.0
|
| 244 |
+
|
| 245 |
+
Encode Memory Usage:
|
| 246 |
+
local code 13509880 bytes
|
| 247 |
+
@jridgewell/sourcemap-codec 1.4.15 13537648 bytes
|
| 248 |
+
sourcemap-codec 32540104 bytes
|
| 249 |
+
source-map-0.6.1 127531040 bytes
|
| 250 |
+
source-map-0.8.0 127535312 bytes
|
| 251 |
+
Smallest memory usage is local code
|
| 252 |
+
|
| 253 |
+
Encode speed:
|
| 254 |
+
encode: local code x 20.10 ops/sec ±0.19% (38 runs sampled)
|
| 255 |
+
encode: @jridgewell/sourcemap-codec 1.4.15 x 20.26 ops/sec ±0.32% (38 runs sampled)
|
| 256 |
+
encode: sourcemap-codec x 5.44 ops/sec ±1.64% (18 runs sampled)
|
| 257 |
+
encode: source-map-0.6.1 x 2.30 ops/sec ±4.79% (10 runs sampled)
|
| 258 |
+
encode: source-map-0.8.0 x 2.46 ops/sec ±6.53% (10 runs sampled)
|
| 259 |
+
Fastest is encode: @jridgewell/sourcemap-codec 1.4.15
|
| 260 |
+
```
|
| 261 |
+
|
| 262 |
+
# License
|
| 263 |
+
|
| 264 |
+
MIT
|
bunx-1000-wrangler@latest/node_modules/@jridgewell/trace-mapping/README.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# @jridgewell/trace-mapping
|
| 2 |
+
|
| 3 |
+
> Trace the original position through a source map
|
| 4 |
+
|
| 5 |
+
`trace-mapping` allows you to take the line and column of an output file and trace it to the
|
| 6 |
+
original location in the source file through a source map.
|
| 7 |
+
|
| 8 |
+
You may already be familiar with the [`source-map`][source-map] package's `SourceMapConsumer`. This
|
| 9 |
+
provides the same `originalPositionFor` and `generatedPositionFor` API, without requiring WASM.
|
| 10 |
+
|
| 11 |
+
## Installation
|
| 12 |
+
|
| 13 |
+
```sh
|
| 14 |
+
npm install @jridgewell/trace-mapping
|
| 15 |
+
```
|
| 16 |
+
|
| 17 |
+
## Usage
|
| 18 |
+
|
| 19 |
+
```typescript
|
| 20 |
+
import { TraceMap, originalPositionFor, generatedPositionFor } from '@jridgewell/trace-mapping';
|
| 21 |
+
|
| 22 |
+
const tracer = new TraceMap({
|
| 23 |
+
version: 3,
|
| 24 |
+
sources: ['input.js'],
|
| 25 |
+
names: ['foo'],
|
| 26 |
+
mappings: 'KAyCIA',
|
| 27 |
+
});
|
| 28 |
+
|
| 29 |
+
// Lines start at line 1, columns at column 0.
|
| 30 |
+
const traced = originalPositionFor(tracer, { line: 1, column: 5 });
|
| 31 |
+
assert.deepEqual(traced, {
|
| 32 |
+
source: 'input.js',
|
| 33 |
+
line: 42,
|
| 34 |
+
column: 4,
|
| 35 |
+
name: 'foo',
|
| 36 |
+
});
|
| 37 |
+
|
| 38 |
+
const generated = generatedPositionFor(tracer, {
|
| 39 |
+
source: 'input.js',
|
| 40 |
+
line: 42,
|
| 41 |
+
column: 4,
|
| 42 |
+
});
|
| 43 |
+
assert.deepEqual(generated, {
|
| 44 |
+
line: 1,
|
| 45 |
+
column: 5,
|
| 46 |
+
});
|
| 47 |
+
```
|
| 48 |
+
|
| 49 |
+
We also provide a lower level API to get the actual segment that matches our line and column. Unlike
|
| 50 |
+
`originalPositionFor`, `traceSegment` uses a 0-base for `line`:
|
| 51 |
+
|
| 52 |
+
```typescript
|
| 53 |
+
import { traceSegment } from '@jridgewell/trace-mapping';
|
| 54 |
+
|
| 55 |
+
// line is 0-base.
|
| 56 |
+
const traced = traceSegment(tracer, /* line */ 0, /* column */ 5);
|
| 57 |
+
|
| 58 |
+
// Segments are [outputColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex]
|
| 59 |
+
// Again, line is 0-base and so is sourceLine
|
| 60 |
+
assert.deepEqual(traced, [5, 0, 41, 4, 0]);
|
| 61 |
+
```
|
| 62 |
+
|
| 63 |
+
### SectionedSourceMaps
|
| 64 |
+
|
| 65 |
+
The sourcemap spec defines a special `sections` field that's designed to handle concatenation of
|
| 66 |
+
output code with associated sourcemaps. This type of sourcemap is rarely used (no major build tool
|
| 67 |
+
produces it), but if you are hand coding a concatenation you may need it. We provide an `AnyMap`
|
| 68 |
+
helper that can receive either a regular sourcemap or a `SectionedSourceMap` and returns a
|
| 69 |
+
`TraceMap` instance:
|
| 70 |
+
|
| 71 |
+
```typescript
|
| 72 |
+
import { AnyMap } from '@jridgewell/trace-mapping';
|
| 73 |
+
const fooOutput = 'foo';
|
| 74 |
+
const barOutput = 'bar';
|
| 75 |
+
const output = [fooOutput, barOutput].join('\n');
|
| 76 |
+
|
| 77 |
+
const sectioned = new AnyMap({
|
| 78 |
+
version: 3,
|
| 79 |
+
sections: [
|
| 80 |
+
{
|
| 81 |
+
// 0-base line and column
|
| 82 |
+
offset: { line: 0, column: 0 },
|
| 83 |
+
// fooOutput's sourcemap
|
| 84 |
+
map: {
|
| 85 |
+
version: 3,
|
| 86 |
+
sources: ['foo.js'],
|
| 87 |
+
names: ['foo'],
|
| 88 |
+
mappings: 'AAAAA',
|
| 89 |
+
},
|
| 90 |
+
},
|
| 91 |
+
{
|
| 92 |
+
// barOutput's sourcemap will not affect the first line, only the second
|
| 93 |
+
offset: { line: 1, column: 0 },
|
| 94 |
+
map: {
|
| 95 |
+
version: 3,
|
| 96 |
+
sources: ['bar.js'],
|
| 97 |
+
names: ['bar'],
|
| 98 |
+
mappings: 'AAAAA',
|
| 99 |
+
},
|
| 100 |
+
},
|
| 101 |
+
],
|
| 102 |
+
});
|
| 103 |
+
|
| 104 |
+
const traced = originalPositionFor(sectioned, {
|
| 105 |
+
line: 2,
|
| 106 |
+
column: 0,
|
| 107 |
+
});
|
| 108 |
+
|
| 109 |
+
assert.deepEqual(traced, {
|
| 110 |
+
source: 'bar.js',
|
| 111 |
+
line: 1,
|
| 112 |
+
column: 0,
|
| 113 |
+
name: 'bar',
|
| 114 |
+
});
|
| 115 |
+
```
|
| 116 |
+
|
| 117 |
+
## Benchmarks
|
| 118 |
+
|
| 119 |
+
```
|
| 120 |
+
node v18.0.0
|
| 121 |
+
|
| 122 |
+
amp.js.map
|
| 123 |
+
trace-mapping: decoded JSON input x 183 ops/sec ±0.41% (87 runs sampled)
|
| 124 |
+
trace-mapping: encoded JSON input x 384 ops/sec ±0.89% (89 runs sampled)
|
| 125 |
+
trace-mapping: decoded Object input x 3,085 ops/sec ±0.24% (100 runs sampled)
|
| 126 |
+
trace-mapping: encoded Object input x 452 ops/sec ±0.80% (84 runs sampled)
|
| 127 |
+
source-map-js: encoded Object input x 88.82 ops/sec ±0.45% (77 runs sampled)
|
| 128 |
+
source-map-0.6.1: encoded Object input x 38.39 ops/sec ±1.88% (52 runs sampled)
|
| 129 |
+
Fastest is trace-mapping: decoded Object input
|
| 130 |
+
|
| 131 |
+
trace-mapping: decoded originalPositionFor x 4,025,347 ops/sec ±0.15% (97 runs sampled)
|
| 132 |
+
trace-mapping: encoded originalPositionFor x 3,333,136 ops/sec ±1.26% (90 runs sampled)
|
| 133 |
+
source-map-js: encoded originalPositionFor x 824,978 ops/sec ±1.06% (94 runs sampled)
|
| 134 |
+
source-map-0.6.1: encoded originalPositionFor x 741,300 ops/sec ±0.93% (92 runs sampled)
|
| 135 |
+
source-map-0.8.0: encoded originalPositionFor x 2,587,603 ops/sec ±0.75% (97 runs sampled)
|
| 136 |
+
Fastest is trace-mapping: decoded originalPositionFor
|
| 137 |
+
|
| 138 |
+
***
|
| 139 |
+
|
| 140 |
+
babel.min.js.map
|
| 141 |
+
trace-mapping: decoded JSON input x 17.43 ops/sec ±8.81% (33 runs sampled)
|
| 142 |
+
trace-mapping: encoded JSON input x 34.18 ops/sec ±4.67% (50 runs sampled)
|
| 143 |
+
trace-mapping: decoded Object input x 1,010 ops/sec ±0.41% (98 runs sampled)
|
| 144 |
+
trace-mapping: encoded Object input x 39.45 ops/sec ±4.01% (52 runs sampled)
|
| 145 |
+
source-map-js: encoded Object input x 6.57 ops/sec ±3.04% (21 runs sampled)
|
| 146 |
+
source-map-0.6.1: encoded Object input x 4.23 ops/sec ±2.93% (15 runs sampled)
|
| 147 |
+
Fastest is trace-mapping: decoded Object input
|
| 148 |
+
|
| 149 |
+
trace-mapping: decoded originalPositionFor x 7,576,265 ops/sec ±0.74% (96 runs sampled)
|
| 150 |
+
trace-mapping: encoded originalPositionFor x 5,019,743 ops/sec ±0.74% (94 runs sampled)
|
| 151 |
+
source-map-js: encoded originalPositionFor x 3,396,137 ops/sec ±42.32% (95 runs sampled)
|
| 152 |
+
source-map-0.6.1: encoded originalPositionFor x 3,753,176 ops/sec ±0.72% (95 runs sampled)
|
| 153 |
+
source-map-0.8.0: encoded originalPositionFor x 6,423,633 ops/sec ±0.74% (95 runs sampled)
|
| 154 |
+
Fastest is trace-mapping: decoded originalPositionFor
|
| 155 |
+
|
| 156 |
+
***
|
| 157 |
+
|
| 158 |
+
preact.js.map
|
| 159 |
+
trace-mapping: decoded JSON input x 3,499 ops/sec ±0.18% (98 runs sampled)
|
| 160 |
+
trace-mapping: encoded JSON input x 6,078 ops/sec ±0.25% (99 runs sampled)
|
| 161 |
+
trace-mapping: decoded Object input x 254,788 ops/sec ±0.13% (100 runs sampled)
|
| 162 |
+
trace-mapping: encoded Object input x 14,063 ops/sec ±0.27% (94 runs sampled)
|
| 163 |
+
source-map-js: encoded Object input x 2,465 ops/sec ±0.25% (98 runs sampled)
|
| 164 |
+
source-map-0.6.1: encoded Object input x 1,174 ops/sec ±1.90% (95 runs sampled)
|
| 165 |
+
Fastest is trace-mapping: decoded Object input
|
| 166 |
+
|
| 167 |
+
trace-mapping: decoded originalPositionFor x 7,720,171 ops/sec ±0.14% (97 runs sampled)
|
| 168 |
+
trace-mapping: encoded originalPositionFor x 6,864,485 ops/sec ±0.16% (101 runs sampled)
|
| 169 |
+
source-map-js: encoded originalPositionFor x 2,387,219 ops/sec ±0.28% (98 runs sampled)
|
| 170 |
+
source-map-0.6.1: encoded originalPositionFor x 1,565,339 ops/sec ±0.32% (101 runs sampled)
|
| 171 |
+
source-map-0.8.0: encoded originalPositionFor x 3,819,732 ops/sec ±0.38% (98 runs sampled)
|
| 172 |
+
Fastest is trace-mapping: decoded originalPositionFor
|
| 173 |
+
|
| 174 |
+
***
|
| 175 |
+
|
| 176 |
+
react.js.map
|
| 177 |
+
trace-mapping: decoded JSON input x 1,719 ops/sec ±0.19% (99 runs sampled)
|
| 178 |
+
trace-mapping: encoded JSON input x 4,284 ops/sec ±0.51% (99 runs sampled)
|
| 179 |
+
trace-mapping: decoded Object input x 94,668 ops/sec ±0.08% (99 runs sampled)
|
| 180 |
+
trace-mapping: encoded Object input x 5,287 ops/sec ±0.24% (99 runs sampled)
|
| 181 |
+
source-map-js: encoded Object input x 814 ops/sec ±0.20% (98 runs sampled)
|
| 182 |
+
source-map-0.6.1: encoded Object input x 429 ops/sec ±0.24% (94 runs sampled)
|
| 183 |
+
Fastest is trace-mapping: decoded Object input
|
| 184 |
+
|
| 185 |
+
trace-mapping: decoded originalPositionFor x 28,927,989 ops/sec ±0.61% (94 runs sampled)
|
| 186 |
+
trace-mapping: encoded originalPositionFor x 27,394,475 ops/sec ±0.55% (97 runs sampled)
|
| 187 |
+
source-map-js: encoded originalPositionFor x 16,856,730 ops/sec ±0.45% (96 runs sampled)
|
| 188 |
+
source-map-0.6.1: encoded originalPositionFor x 12,258,950 ops/sec ±0.41% (97 runs sampled)
|
| 189 |
+
source-map-0.8.0: encoded originalPositionFor x 22,272,990 ops/sec ±0.58% (95 runs sampled)
|
| 190 |
+
Fastest is trace-mapping: decoded originalPositionFor
|
| 191 |
+
```
|
| 192 |
+
|
| 193 |
+
[source-map]: https://www.npmjs.com/package/source-map
|
bunx-1000-wrangler@latest/node_modules/@poppinss/colors/LICENSE.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# The MIT License
|
| 2 |
+
|
| 3 |
+
Copyright 2021 Harminder Virk, contributors
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
| 6 |
+
|
| 7 |
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
| 8 |
+
|
| 9 |
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
bunx-1000-wrangler@latest/node_modules/@poppinss/colors/README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# @poppinss/colors
|
| 2 |
+
> Wrapper over [kleur](https://www.npmjs.com/package/kleur) with better support for testing
|
| 3 |
+
|
| 4 |
+
[![gh-workflow-image]][gh-workflow-url] [![typescript-image]][typescript-url] [![npm-image]][npm-url] [![license-image]][license-url]
|
| 5 |
+
|
| 6 |
+
## Why this package exists?
|
| 7 |
+
This package is a wrapper over [kleur](https://www.npmjs.com/package/kleur) with additional implementations to make testing easier and work seamlessly with terminals/stdout streams that do not support colors.
|
| 8 |
+
|
| 9 |
+
## Usage
|
| 10 |
+
Install the package from the npm registry as follows.
|
| 11 |
+
|
| 12 |
+
```sh
|
| 13 |
+
npm i @poppinss/colors
|
| 14 |
+
```
|
| 15 |
+
|
| 16 |
+
And use it as follows. The `ansi` method returns an instance of the [kleur](https://www.npmjs.com/package/kleur) package.
|
| 17 |
+
|
| 18 |
+
```ts
|
| 19 |
+
import useColors from '@poppinss/colors'
|
| 20 |
+
const colors = useColors.ansi()
|
| 21 |
+
|
| 22 |
+
console.log(colors.red('this is an error'))
|
| 23 |
+
console.log(colors.cyan('hello world'))
|
| 24 |
+
```
|
| 25 |
+
|
| 26 |
+
Chaining methods
|
| 27 |
+
|
| 28 |
+
```ts
|
| 29 |
+
const colors = useColors.ansi()
|
| 30 |
+
console.log(colors.red().bgBlack('this is an error'))
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
### Raw implementation
|
| 34 |
+
The raw implementation is ideal for testing. Instead of outputting ANSI escape codes, we wrap the string with transformation names. For example:
|
| 35 |
+
|
| 36 |
+
```ts
|
| 37 |
+
import useColors from '@poppinss/colors'
|
| 38 |
+
const colors = useColors.raw()
|
| 39 |
+
|
| 40 |
+
console.log(colors.red('hello world'))
|
| 41 |
+
// OUTPUT: red(hello world)
|
| 42 |
+
|
| 43 |
+
console.log(colors.bgBlack().red('hello world'))
|
| 44 |
+
// OUTPUT: bgBlack(red(hello world))
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
As you can notice, the output is a plain text value, so it is easier to write assertions against it.
|
| 48 |
+
|
| 49 |
+
```ts
|
| 50 |
+
assert.equal(colors.red('hello world'), 'red(hello world)')
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
### Silent output
|
| 54 |
+
The silent mode does not perform any transformations on the string and returns the value. This is helpful when the output terminal or stdout stream does not support colors.
|
| 55 |
+
|
| 56 |
+
```ts
|
| 57 |
+
import useColors from '@poppinss/colors'
|
| 58 |
+
const colors = useColors.silent()
|
| 59 |
+
|
| 60 |
+
console.log(colors.red('hello world'))
|
| 61 |
+
// OUTPUT: hello world
|
| 62 |
+
|
| 63 |
+
console.log(colors.bgBlack().red('hello world'))
|
| 64 |
+
// OUTPUT: hello world
|
| 65 |
+
```
|
| 66 |
+
|
| 67 |
+
## Pick based on the runtime environment
|
| 68 |
+
Ideally, you will use one of the available implementations based on some runtime environment. For example:
|
| 69 |
+
|
| 70 |
+
```ts
|
| 71 |
+
import useColors from '@poppinss/colors'
|
| 72 |
+
import supportsColor from 'supports-color'
|
| 73 |
+
|
| 74 |
+
const isTestEnv = process.env.NODE_ENV === 'test'
|
| 75 |
+
|
| 76 |
+
const colors = isTestEnv
|
| 77 |
+
? useColors.raw() // use raw in test environment
|
| 78 |
+
: supportsColor.stdout
|
| 79 |
+
? useColors.ansi() // use kleur when stdout has colors
|
| 80 |
+
: useColors.silent() // use silent mode
|
| 81 |
+
|
| 82 |
+
export default colors
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
[gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/poppinss/colors/checks.yml?style=for-the-badge
|
| 86 |
+
[gh-workflow-url]: https://github.com/poppinss/colors/actions/workflows/checks.yml "Github action"
|
| 87 |
+
|
| 88 |
+
[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
|
| 89 |
+
[typescript-url]: "typescript"
|
| 90 |
+
|
| 91 |
+
[npm-image]: https://img.shields.io/npm/v/@poppinss/colors.svg?style=for-the-badge&logo=npm
|
| 92 |
+
[npm-url]: https://npmjs.org/package/@poppinss/colors 'npm'
|
| 93 |
+
|
| 94 |
+
[license-image]: https://img.shields.io/npm/l/@poppinss/colors?color=blueviolet&style=for-the-badge
|
| 95 |
+
[license-url]: LICENSE.md 'license'
|
bunx-1000-wrangler@latest/node_modules/@poppinss/dumper/LICENSE.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# The MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2023
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
| 6 |
+
|
| 7 |
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
| 8 |
+
|
| 9 |
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
bunx-1000-wrangler@latest/node_modules/@poppinss/dumper/README.md
ADDED
|
@@ -0,0 +1,387 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# @poppinss/dumper
|
| 2 |
+
|
| 3 |
+
> Pretty print JavaScript data types in the terminal and the browser
|
| 4 |
+
|
| 5 |
+
<br />
|
| 6 |
+
|
| 7 |
+
[![gh-workflow-image]][gh-workflow-url] [![npm-image]][npm-url] ![][typescript-image] [![license-image]][license-url]
|
| 8 |
+
|
| 9 |
+
Dumper is similar to Node.js [util.inspect](https://nodejs.org/api/util.html#utilinspectobject-options), but it provides more control over the output. You can use Dumper to generate [HTML output](#html-formatter), [CLI output](#cli-formatter), or use its [low-level API](#using-parser-directly) to create inspection tokens and render them using a custom formatter.
|
| 10 |
+
|
| 11 |
+

|
| 12 |
+
|
| 13 |
+
> [!IMPORTANT]
|
| 14 |
+
> Dumper is a low-level utility. You may have to write a wrapper around it for the framework of your choice.
|
| 15 |
+
|
| 16 |
+
## Installation
|
| 17 |
+
|
| 18 |
+
Install the package from the npm registry as follows.
|
| 19 |
+
|
| 20 |
+
```sh
|
| 21 |
+
npm i @poppinss/dumper
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
## HTML formatter
|
| 25 |
+
|
| 26 |
+
You can dump values to HTML output using the `dump` helper from the HTML sub-module. For example:
|
| 27 |
+
|
| 28 |
+
```ts
|
| 29 |
+
import { dump } from '@poppinss/dumper/html'
|
| 30 |
+
|
| 31 |
+
const values = {
|
| 32 |
+
a: 0,
|
| 33 |
+
b: 'string',
|
| 34 |
+
c: {
|
| 35 |
+
nested: 'object',
|
| 36 |
+
},
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
const html = dump(values)
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
The HTML output contains a `pre` tag and a `script` tag. The `script` tag invokes a JavaScript function (for collapse/expand behavior) that must be present in the `<HEAD>` element of the HTML document.
|
| 43 |
+
|
| 44 |
+
You can grab the JavaScript snippet and the required global styles using the `createStyleSheet` and `createScript` helper methods. Following is a complete example of the same.
|
| 45 |
+
|
| 46 |
+
```ts
|
| 47 |
+
import { dump, createStyleSheet, createScript } from '@poppinss/dumper/html'
|
| 48 |
+
|
| 49 |
+
const values = {
|
| 50 |
+
a: 0,
|
| 51 |
+
b: 'string',
|
| 52 |
+
c: {
|
| 53 |
+
nested: 'object',
|
| 54 |
+
},
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
const html = dump(values)
|
| 58 |
+
|
| 59 |
+
const output = `<!DOCTYPE html>
|
| 60 |
+
<html>
|
| 61 |
+
<head>
|
| 62 |
+
<meta charset="utf-8">
|
| 63 |
+
<meta name="viewport" content="width=device-width">
|
| 64 |
+
<style>
|
| 65 |
+
${createStyleSheet()}
|
| 66 |
+
</style>
|
| 67 |
+
<script>
|
| 68 |
+
${createScript()}
|
| 69 |
+
</script>
|
| 70 |
+
</head>
|
| 71 |
+
<body>
|
| 72 |
+
${html}
|
| 73 |
+
</body>
|
| 74 |
+
</html>`
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
### Options
|
| 78 |
+
|
| 79 |
+
You may pass all of the [Parser options](#parser-options) alongside the following options as the second argument to the `dump` method.
|
| 80 |
+
|
| 81 |
+
- `styles`: The styles property is a key-value pair that contains CSS properties to style HTML elements. You can either define custom styles or use one of the pre-existing themes as a reference.
|
| 82 |
+
- `cspNonce`: If your application has CSP enabled, then you must define the [CSP nonce](https://content-security-policy.com/nonce/) for the inline `script` tag output alongside the `pre` tag.
|
| 83 |
+
- `expand`: Render the dumped output expanded (instead of collapsed). By default, only the first level is expanded. However, you can expand recursively using the `expand: 'all'` option.
|
| 84 |
+
|
| 85 |
+
Following is an example of using a pre-existing theme.
|
| 86 |
+
|
| 87 |
+
```ts
|
| 88 |
+
import { dump, themes } from '@poppinss/dumper/html'
|
| 89 |
+
|
| 90 |
+
dump(value, {
|
| 91 |
+
styles: themes.catppuccin,
|
| 92 |
+
})
|
| 93 |
+
```
|
| 94 |
+
|
| 95 |
+
To have support for dark and light modes, you must use the `cssVariables` theme and define the colors using CSS variables. For example:
|
| 96 |
+
|
| 97 |
+
```ts
|
| 98 |
+
import { dump, themes } from '@poppinss/dumper/html'
|
| 99 |
+
|
| 100 |
+
dump(value, {
|
| 101 |
+
styles: themes.cssVariables,
|
| 102 |
+
})
|
| 103 |
+
```
|
| 104 |
+
|
| 105 |
+
**List of CSS variables**
|
| 106 |
+
|
| 107 |
+
```css
|
| 108 |
+
:root {
|
| 109 |
+
--pre-bg-color
|
| 110 |
+
--pre-fg-color
|
| 111 |
+
--toggle-fg-color
|
| 112 |
+
--braces-fg-color
|
| 113 |
+
--brackets-fg-color
|
| 114 |
+
--dt-number-fg-color
|
| 115 |
+
--dt-bigint-fg-color
|
| 116 |
+
--dt-boolean-fg-color
|
| 117 |
+
--dt-string-fg-color
|
| 118 |
+
--dt-null-fg-color
|
| 119 |
+
--dt-undefined-fg-color
|
| 120 |
+
--prototype-label-fg-color
|
| 121 |
+
--dt-symbol-fg-color
|
| 122 |
+
--dt-regex-fg-color
|
| 123 |
+
--dt-date-fg-color
|
| 124 |
+
--dt-buffer-fg-color
|
| 125 |
+
--function-label-fg-color
|
| 126 |
+
--array-label-fg-color
|
| 127 |
+
--object-label-fg-color
|
| 128 |
+
--map-label-fg-color
|
| 129 |
+
--set-label-fg-color
|
| 130 |
+
--object-key-fg-color
|
| 131 |
+
--object-key-prefix-fg-color
|
| 132 |
+
--class-label-fg-color
|
| 133 |
+
--collpase-label-fg-color
|
| 134 |
+
--getter-label-fg-color
|
| 135 |
+
--circular-label-fg-color
|
| 136 |
+
--weakset-label-fg-color
|
| 137 |
+
--weakref-label-fg-color
|
| 138 |
+
--weakmap-label-fg-color
|
| 139 |
+
--observable-label-fg-color
|
| 140 |
+
--promise-label-fg-color
|
| 141 |
+
--generator-label-fg-color
|
| 142 |
+
--blob-label-fg-color
|
| 143 |
+
--unknown-label-fg-color
|
| 144 |
+
}
|
| 145 |
+
```
|
| 146 |
+
|
| 147 |
+
Following is an example of rendering the expanded output.
|
| 148 |
+
|
| 149 |
+
```ts
|
| 150 |
+
import { dump } from '@poppinss/dumper/html'
|
| 151 |
+
|
| 152 |
+
dump(value, {
|
| 153 |
+
expand: true, // expand first-level
|
| 154 |
+
})
|
| 155 |
+
|
| 156 |
+
dump(value, {
|
| 157 |
+
expand: 'all', // expand recursively
|
| 158 |
+
})
|
| 159 |
+
```
|
| 160 |
+
|
| 161 |
+
### Creating custom themes
|
| 162 |
+
|
| 163 |
+
You can also define your own themes as an object. Make sure to consult one of the [existing themes](https://github.com/poppinss/dumper/blob/1.x/formatters/html/themes.ts) to view all the available tokens.
|
| 164 |
+
|
| 165 |
+
```ts
|
| 166 |
+
import { dump } from '@poppinss/dumper/html'
|
| 167 |
+
import { HTMLPrinterStyles } from '@poppinss/dumper/html/types'
|
| 168 |
+
|
| 169 |
+
const myTheme: HTMLPrinterStyles = {
|
| 170 |
+
pre: 'background-color: #1e1e2e; color: #94e2d5;',
|
| 171 |
+
boolean: 'color: #cba6f7; font-style: italic;'
|
| 172 |
+
string: 'color: #a6e3a1;',
|
| 173 |
+
symbol: 'color: #f9e2af;',
|
| 174 |
+
// ...rest of the styles
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
dump(value, {
|
| 178 |
+
styles: myTheme,
|
| 179 |
+
})
|
| 180 |
+
```
|
| 181 |
+
|
| 182 |
+
## CLI formatter
|
| 183 |
+
|
| 184 |
+
You can dump values to the terminal using the `dump` helper from the console sub-module. For example:
|
| 185 |
+
|
| 186 |
+
```ts
|
| 187 |
+
import { dump } from '@poppinss/dumper/console'
|
| 188 |
+
|
| 189 |
+
const values = {
|
| 190 |
+
a: 0,
|
| 191 |
+
b: 'string',
|
| 192 |
+
c: {
|
| 193 |
+
nested: 'object',
|
| 194 |
+
},
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
const ansiOutput = dump(values)
|
| 198 |
+
console.log(ansiOutput)
|
| 199 |
+
```
|
| 200 |
+
|
| 201 |
+
### Options
|
| 202 |
+
|
| 203 |
+
You may pass all of the [Parser options](#parser-options) alongside the following options as the second argument to the `dump` method.
|
| 204 |
+
|
| 205 |
+
- `styles`: The styles property contains a set of functions for different tokens. Each function receives a string input and must return a styled output string.
|
| 206 |
+
|
| 207 |
+
Following is an example of using a pre-existing theme.
|
| 208 |
+
|
| 209 |
+
```ts
|
| 210 |
+
import { dump, themes } from '@poppinss/dumper/console'
|
| 211 |
+
|
| 212 |
+
dump(value, {
|
| 213 |
+
styles: themes.default,
|
| 214 |
+
})
|
| 215 |
+
```
|
| 216 |
+
|
| 217 |
+
You may create a custom theme as follows. Make sure to consult an [existing theme](https://github.com/poppinss/dumper/blob/1.x/formatters/console/themes.ts) to view all the available tokens.
|
| 218 |
+
|
| 219 |
+
```ts
|
| 220 |
+
import { styleText } from 'node:util'
|
| 221 |
+
import { dump } from '@poppinss/dumper/console'
|
| 222 |
+
import { ConsolePrinterStyles } from '@poppinss/dumper/console/types'
|
| 223 |
+
|
| 224 |
+
const myTheme: ConsolePrinterStyles = {
|
| 225 |
+
number: (value) => styleText('yellow', value),
|
| 226 |
+
bigInt: (value) => styleText('yellow', styleText('bold', value)),
|
| 227 |
+
boolean: (value) => styleText('yellow', styleText('italic', value)),
|
| 228 |
+
// ... styles for the rest of the tokens
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
dump(value, {
|
| 232 |
+
styles: myTheme,
|
| 233 |
+
})
|
| 234 |
+
```
|
| 235 |
+
|
| 236 |
+
## Supported data types
|
| 237 |
+
|
| 238 |
+
Following is the list of data types supported by Dumper. All other data types will be converted to their String representation by wrapping them inside the `String` function.
|
| 239 |
+
|
| 240 |
+
- Object
|
| 241 |
+
- Array
|
| 242 |
+
- Map
|
| 243 |
+
- Set
|
| 244 |
+
- Function
|
| 245 |
+
- string
|
| 246 |
+
- URL
|
| 247 |
+
- URLSearchParams
|
| 248 |
+
- Error
|
| 249 |
+
- FormData
|
| 250 |
+
- undefined
|
| 251 |
+
- null
|
| 252 |
+
- symbol
|
| 253 |
+
- number
|
| 254 |
+
- boolean
|
| 255 |
+
- BigInt
|
| 256 |
+
- Date
|
| 257 |
+
- RegExp
|
| 258 |
+
- Buffer
|
| 259 |
+
- WeakSet
|
| 260 |
+
- WeakMap
|
| 261 |
+
- WeakRef
|
| 262 |
+
- Generator
|
| 263 |
+
- AsyncGenerator
|
| 264 |
+
- GeneratorFunction
|
| 265 |
+
- AsyncGeneratorFunction
|
| 266 |
+
- AsyncFunction
|
| 267 |
+
- Observable
|
| 268 |
+
- Blob
|
| 269 |
+
- Promise
|
| 270 |
+
- NaN
|
| 271 |
+
- Int8Array
|
| 272 |
+
- Uint8Array
|
| 273 |
+
- Int16Array
|
| 274 |
+
- Uint16Array
|
| 275 |
+
- Int32Array
|
| 276 |
+
- Uint32Array
|
| 277 |
+
- Float32Array
|
| 278 |
+
- Float64Array
|
| 279 |
+
- BigInt64Array
|
| 280 |
+
- BigUint64Array
|
| 281 |
+
|
| 282 |
+
## Parser options
|
| 283 |
+
|
| 284 |
+
Regardless of the output format, you can use one of the following options to tweak the parsing behavior.
|
| 285 |
+
|
| 286 |
+
```ts
|
| 287 |
+
import { dump } from '@poppinss/dumper/console'
|
| 288 |
+
|
| 289 |
+
dump(values, {
|
| 290 |
+
showHidden: false,
|
| 291 |
+
depth: 5,
|
| 292 |
+
inspectObjectPrototype: false,
|
| 293 |
+
inspectArrayPrototype: false,
|
| 294 |
+
inspectStaticMembers: false,
|
| 295 |
+
maxArrayLength: 100,
|
| 296 |
+
maxStringLength: 1000,
|
| 297 |
+
})
|
| 298 |
+
```
|
| 299 |
+
|
| 300 |
+
- `showHidden`: When set to true, the non-enumerable properties of an object will be processed. **Default: `false`**.
|
| 301 |
+
- `depth`: The depth at which to stop parsing nested values. The depth is shared among all tree-like data structures. For example: Objects, Arrays, Maps, and Sets. **Default: `5`**.
|
| 302 |
+
- `inspectObjectPrototype`: Inspect prototype properties of an object. The non-enumerable properties of the prototype are included by default. **Default: `false`**.
|
| 303 |
+
- `inspectArrayPrototype`: Inspect prototype properties of an Array. This flag could help inspect prototype properties of extended arrays. **Default: `unless-plain-object`**. The `unless-plain-object` object value will inspect the prototype when the prototype of the value is not the global `Object`.
|
| 304 |
+
- `inspectStaticMembers`: Inspect static members of a class. Even though functions and classes are technically the same, this config only applies to functions defined using the `[class]` keyword. **Default: `false`**.
|
| 305 |
+
- `maxArrayLength`: Maximum number of members to process for Arrays, Maps, and Sets. **Default: `100`**.
|
| 306 |
+
- `maxStringLength`: Maximum number of characters to display for a string. **Default: `1000`**.
|
| 307 |
+
|
| 308 |
+
## Using Parser directly
|
| 309 |
+
|
| 310 |
+
For advanced use cases, use the Parser directly and create a custom formatter on top of it. Following is an example of the same. Also, feel free to consult the implementation of the existing formatters.
|
| 311 |
+
|
| 312 |
+
```ts
|
| 313 |
+
import { Parser } from '@poppinss/dumper'
|
| 314 |
+
import { ParserConfig } from '@poppinss/dumper/types'
|
| 315 |
+
|
| 316 |
+
const config: ParserConfig = {}
|
| 317 |
+
const parser = new Parser(config)
|
| 318 |
+
|
| 319 |
+
const values = {
|
| 320 |
+
a: 0,
|
| 321 |
+
b: 'string',
|
| 322 |
+
c: {
|
| 323 |
+
nested: 'object',
|
| 324 |
+
},
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
parser.parse(values)
|
| 328 |
+
const tokens = parser.flush()
|
| 329 |
+
|
| 330 |
+
console.log(tokens)
|
| 331 |
+
```
|
| 332 |
+
|
| 333 |
+
The `parser.flush` method returns a flat array of [tokens](https://github.com/poppinss/dumper/blob/1.x/src/types.ts#L30), and they must be printed in the same order as they are defined.
|
| 334 |
+
|
| 335 |
+
The official implementations (shipped with Dumper) use the concept of printers, where we have defined one printer for each token type that is responsible for returning the formatted value.
|
| 336 |
+
|
| 337 |
+
Following is an oversimplified example of creating custom printers. Once again, feel free to reference the implementation of existing [formatters](https://github.com/poppinss/dumper/blob/1.x/formatters/html/printers/formatter.ts) and [printers](https://github.com/poppinss/dumper/blob/1.x/formatters/html/printers/main.ts).
|
| 338 |
+
|
| 339 |
+
```ts
|
| 340 |
+
const myCustomPrinters: [K in keyof TokensMap]: (
|
| 341 |
+
token: TokensMap[K],
|
| 342 |
+
) => string = {
|
| 343 |
+
'object-start': (token) => {
|
| 344 |
+
return `Object {`
|
| 345 |
+
},
|
| 346 |
+
'object-end': (token) => {
|
| 347 |
+
return `}`
|
| 348 |
+
},
|
| 349 |
+
'object-key': (token) => {
|
| 350 |
+
return token.value
|
| 351 |
+
},
|
| 352 |
+
'object-value-start': (token) => {
|
| 353 |
+
return ': '
|
| 354 |
+
},
|
| 355 |
+
'object-value-end': (token) => {
|
| 356 |
+
return ', '
|
| 357 |
+
}
|
| 358 |
+
}
|
| 359 |
+
|
| 360 |
+
const tokens = parser.flush()
|
| 361 |
+
const output = tokens.map((token) => {
|
| 362 |
+
return myCustomPrinters[token.type](token)
|
| 363 |
+
}).join('')
|
| 364 |
+
```
|
| 365 |
+
|
| 366 |
+
## Contributing
|
| 367 |
+
|
| 368 |
+
One of the primary goals of Poppinss is to have a vibrant community of users and contributors who believe in the principles of the framework.
|
| 369 |
+
|
| 370 |
+
We encourage you to read the [contribution guide](https://github.com/poppinss/.github/blob/main/docs/CONTRIBUTING.md) before contributing to the framework.
|
| 371 |
+
|
| 372 |
+
## Code of Conduct
|
| 373 |
+
|
| 374 |
+
In order to ensure that the Poppinss community is welcoming to all, please review and abide by the [Code of Conduct](https://github.com/poppinss/.github/blob/main/docs/CODE_OF_CONDUCT.md).
|
| 375 |
+
|
| 376 |
+
## License
|
| 377 |
+
|
| 378 |
+
Poppinss dumper is open-sourced software licensed under the [MIT license](LICENSE.md).
|
| 379 |
+
|
| 380 |
+
[gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/poppinss/dumper/checks.yml?style=for-the-badge
|
| 381 |
+
[gh-workflow-url]: https://github.com/poppinss/dumper/actions/workflows/checks.yml 'Github action'
|
| 382 |
+
[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
|
| 383 |
+
[typescript-url]: "typescript"
|
| 384 |
+
[npm-image]: https://img.shields.io/npm/v/@poppinss/dumper.svg?style=for-the-badge&logo=npm
|
| 385 |
+
[npm-url]: https://npmjs.org/package/@poppinss/dumper 'npm'
|
| 386 |
+
[license-image]: https://img.shields.io/npm/l/@poppinss/dumper?color=blueviolet&style=for-the-badge
|
| 387 |
+
[license-url]: LICENSE.md 'license'
|
bunx-1000-wrangler@latest/node_modules/@poppinss/exception/LICENSE.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# The MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2023
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
| 6 |
+
|
| 7 |
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
| 8 |
+
|
| 9 |
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
bunx-1000-wrangler@latest/node_modules/@poppinss/exception/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# @poppinss/exception
|
| 2 |
+
|
| 3 |
+
> Create custom exceptions with error code, status, and the help description.
|
| 4 |
+
|
| 5 |
+
<br />
|
| 6 |
+
|
| 7 |
+
[![gh-workflow-image]][gh-workflow-url] [![npm-image]][npm-url] ![][typescript-image] [![license-image]][license-url]
|
| 8 |
+
|
| 9 |
+
## Introduction
|
| 10 |
+
|
| 11 |
+
The `@poppinss/exception` package provides with a base `Exception` class that can be used to create custom errors with support for defining the **error status**, **error code**, and **help description**.
|
| 12 |
+
|
| 13 |
+
```ts
|
| 14 |
+
import { Exception } from '@poppinss/exception'
|
| 15 |
+
|
| 16 |
+
class ResourceNotFound extends Exception {
|
| 17 |
+
static code = 'E_RESOURCE_NOT_FOUND'
|
| 18 |
+
static status = 404
|
| 19 |
+
static message = 'Unable to find resource'
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
throw new ResourceNotFound()
|
| 23 |
+
```
|
| 24 |
+
|
| 25 |
+
### Anonymous error classes
|
| 26 |
+
|
| 27 |
+
You can also create an anonymous exception class using the `createError` method. The return value is a class constructor that accepts an array of values to use for message interpolation.
|
| 28 |
+
|
| 29 |
+
The interpolation of error message is performed using the [`util.format`](https://nodejs.org/api/util.html#utilformatformat-args) method.
|
| 30 |
+
|
| 31 |
+
```ts
|
| 32 |
+
import { createError } from '@poppinss/exception'
|
| 33 |
+
|
| 34 |
+
const E_RESOURCE_NOT_FOUND = createError<[number]>(
|
| 35 |
+
'Unable to find resource with id %d',
|
| 36 |
+
'E_RESOURCE_NOT_FOUND'
|
| 37 |
+
)
|
| 38 |
+
|
| 39 |
+
const id = 1
|
| 40 |
+
throw new E_RESOURCE_NOT_FOUND([id])
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
## Contributing
|
| 44 |
+
|
| 45 |
+
One of the primary goals of poppinss is to have a vibrant community of users and contributors who believes in the principles of the framework.
|
| 46 |
+
|
| 47 |
+
We encourage you to read the [contribution guide](https://github.com/poppinss/.github/blob/main/docs/CONTRIBUTING.md) before contributing to the framework.
|
| 48 |
+
|
| 49 |
+
## Code of Conduct
|
| 50 |
+
|
| 51 |
+
In order to ensure that the poppinss community is welcoming to all, please review and abide by the [Code of Conduct](https://github.com/poppinss/.github/blob/main/docs/CODE_OF_CONDUCT.md).
|
| 52 |
+
|
| 53 |
+
## License
|
| 54 |
+
|
| 55 |
+
Poppinss exception is open-sourced software licensed under the [MIT license](LICENSE.md).
|
| 56 |
+
|
| 57 |
+
[gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/poppinss/exception/checks.yml?style=for-the-badge
|
| 58 |
+
[gh-workflow-url]: https://github.com/poppinss/exception/actions/workflows/checks.yml 'Github action'
|
| 59 |
+
[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
|
| 60 |
+
[typescript-url]: "typescript"
|
| 61 |
+
[npm-image]: https://img.shields.io/npm/v/@poppinss/exception.svg?style=for-the-badge&logo=npm
|
| 62 |
+
[npm-url]: https://npmjs.org/package/@poppinss/exception 'npm'
|
| 63 |
+
[license-image]: https://img.shields.io/npm/l/@poppinss/exception?color=blueviolet&style=for-the-badge
|
| 64 |
+
[license-url]: LICENSE.md 'license'
|
bunx-1000-wrangler@latest/node_modules/@sindresorhus/is/readme.md
ADDED
|
@@ -0,0 +1,844 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# is
|
| 2 |
+
|
| 3 |
+
> Type check values
|
| 4 |
+
|
| 5 |
+
For example, `is.string('🦄') //=> true`
|
| 6 |
+
|
| 7 |
+
<img src="header.gif" width="182" align="right">
|
| 8 |
+
|
| 9 |
+
## Highlights
|
| 10 |
+
|
| 11 |
+
- Written in TypeScript
|
| 12 |
+
- [Extensive use of type guards](#type-guards)
|
| 13 |
+
- [Supports type assertions](#type-assertions)
|
| 14 |
+
- [Aware of generic type parameters](#generic-type-parameters) (use with caution)
|
| 15 |
+
- Actively maintained
|
| 16 |
+
- 
|
| 17 |
+
|
| 18 |
+
## Install
|
| 19 |
+
|
| 20 |
+
```sh
|
| 21 |
+
npm install @sindresorhus/is
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
## Usage
|
| 25 |
+
|
| 26 |
+
```js
|
| 27 |
+
import is from '@sindresorhus/is';
|
| 28 |
+
|
| 29 |
+
is('🦄');
|
| 30 |
+
//=> 'string'
|
| 31 |
+
|
| 32 |
+
is(new Map());
|
| 33 |
+
//=> 'Map'
|
| 34 |
+
|
| 35 |
+
is.number(6);
|
| 36 |
+
//=> true
|
| 37 |
+
```
|
| 38 |
+
|
| 39 |
+
[Assertions](#type-assertions) perform the same type checks, but throw an error if the type does not match.
|
| 40 |
+
|
| 41 |
+
```js
|
| 42 |
+
import {assert} from '@sindresorhus/is';
|
| 43 |
+
|
| 44 |
+
assert.string(2);
|
| 45 |
+
//=> Error: Expected value which is `string`, received value of type `number`.
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
Assertions (except `assertAll` and `assertAny`) also support an optional custom error message.
|
| 49 |
+
|
| 50 |
+
```js
|
| 51 |
+
import {assert} from '@sindresorhus/is';
|
| 52 |
+
|
| 53 |
+
assert.nonEmptyString(process.env.API_URL, 'The API_URL environment variable is required.');
|
| 54 |
+
//=> Error: The API_URL environment variable is required.
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
And with TypeScript:
|
| 58 |
+
|
| 59 |
+
```ts
|
| 60 |
+
import {assert} from '@sindresorhus/is';
|
| 61 |
+
|
| 62 |
+
assert.string(foo);
|
| 63 |
+
// `foo` is now typed as a `string`.
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
### Named exports
|
| 67 |
+
|
| 68 |
+
Named exports allow tooling to perform tree-shaking, potentially reducing bundle size by including only code from the methods that are used.
|
| 69 |
+
|
| 70 |
+
Every method listed below is available as a named export. Each method is prefixed by either `is` or `assert` depending on usage.
|
| 71 |
+
|
| 72 |
+
For example:
|
| 73 |
+
|
| 74 |
+
```js
|
| 75 |
+
import {assertNull, isUndefined} from '@sindresorhus/is';
|
| 76 |
+
```
|
| 77 |
+
|
| 78 |
+
## API
|
| 79 |
+
|
| 80 |
+
### is(value)
|
| 81 |
+
|
| 82 |
+
Returns the type of `value`.
|
| 83 |
+
|
| 84 |
+
Primitives are lowercase and object types are camelcase.
|
| 85 |
+
|
| 86 |
+
Example:
|
| 87 |
+
|
| 88 |
+
- `'undefined'`
|
| 89 |
+
- `'null'`
|
| 90 |
+
- `'string'`
|
| 91 |
+
- `'symbol'`
|
| 92 |
+
- `'Array'`
|
| 93 |
+
- `'Function'`
|
| 94 |
+
- `'Object'`
|
| 95 |
+
|
| 96 |
+
This method is also exported as `detect`. You can import it like this:
|
| 97 |
+
|
| 98 |
+
```js
|
| 99 |
+
import {detect} from '@sindresorhus/is';
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
Note: It will throw an error if you try to feed it object-wrapped primitives, as that's a bad practice. For example `new String('foo')`.
|
| 103 |
+
|
| 104 |
+
### is.{method}
|
| 105 |
+
|
| 106 |
+
All the below methods accept a value and return a boolean for whether the value is of the desired type.
|
| 107 |
+
|
| 108 |
+
#### Primitives
|
| 109 |
+
|
| 110 |
+
##### .undefined(value)
|
| 111 |
+
##### .null(value)
|
| 112 |
+
|
| 113 |
+
##### .string(value)
|
| 114 |
+
##### .number(value)
|
| 115 |
+
|
| 116 |
+
Note: `is.number(NaN)` returns `false`. This intentionally deviates from `typeof` behavior to increase user-friendliness of `is` type checks.
|
| 117 |
+
|
| 118 |
+
##### .boolean(value)
|
| 119 |
+
##### .symbol(value)
|
| 120 |
+
##### .bigint(value)
|
| 121 |
+
|
| 122 |
+
#### Built-in types
|
| 123 |
+
|
| 124 |
+
##### .array(value, assertion?)
|
| 125 |
+
|
| 126 |
+
Returns true if `value` is an array and all of its items match the assertion (if provided).
|
| 127 |
+
|
| 128 |
+
```js
|
| 129 |
+
is.array(value); // Validate `value` is an array.
|
| 130 |
+
is.array(value, is.number); // Validate `value` is an array and all of its items are numbers.
|
| 131 |
+
```
|
| 132 |
+
|
| 133 |
+
##### .function(value)
|
| 134 |
+
|
| 135 |
+
##### .buffer(value)
|
| 136 |
+
|
| 137 |
+
> [!NOTE]
|
| 138 |
+
> [Prefer using `Uint8Array` instead of `Buffer`.](https://sindresorhus.com/blog/goodbye-nodejs-buffer)
|
| 139 |
+
|
| 140 |
+
##### .blob(value)
|
| 141 |
+
##### .object(value)
|
| 142 |
+
|
| 143 |
+
Keep in mind that [functions are objects too](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions).
|
| 144 |
+
|
| 145 |
+
##### .numericString(value)
|
| 146 |
+
|
| 147 |
+
Returns `true` for a string that represents a number satisfying `is.number`, for example, `'42'` and `'-8.3'`.
|
| 148 |
+
|
| 149 |
+
Note: `'NaN'` returns `false`, but `'Infinity'` and `'-Infinity'` return `true`.
|
| 150 |
+
|
| 151 |
+
##### .regExp(value)
|
| 152 |
+
##### .date(value)
|
| 153 |
+
##### .error(value)
|
| 154 |
+
##### .nativePromise(value)
|
| 155 |
+
##### .promise(value)
|
| 156 |
+
|
| 157 |
+
Returns `true` for any object with a `.then()` and `.catch()` method. Prefer this one over `.nativePromise()` as you usually want to allow userland promise implementations too.
|
| 158 |
+
|
| 159 |
+
##### .generator(value)
|
| 160 |
+
|
| 161 |
+
Returns `true` for any object that implements its own `.next()` and `.throw()` methods and has a function definition for `Symbol.iterator`.
|
| 162 |
+
|
| 163 |
+
##### .generatorFunction(value)
|
| 164 |
+
|
| 165 |
+
##### .asyncFunction(value)
|
| 166 |
+
|
| 167 |
+
Returns `true` for any `async` function that can be called with the `await` operator.
|
| 168 |
+
|
| 169 |
+
```js
|
| 170 |
+
is.asyncFunction(async () => {});
|
| 171 |
+
//=> true
|
| 172 |
+
|
| 173 |
+
is.asyncFunction(() => {});
|
| 174 |
+
//=> false
|
| 175 |
+
```
|
| 176 |
+
|
| 177 |
+
##### .asyncGenerator(value)
|
| 178 |
+
|
| 179 |
+
```js
|
| 180 |
+
is.asyncGenerator(
|
| 181 |
+
(async function * () {
|
| 182 |
+
yield 4;
|
| 183 |
+
})()
|
| 184 |
+
);
|
| 185 |
+
//=> true
|
| 186 |
+
|
| 187 |
+
is.asyncGenerator(
|
| 188 |
+
(function * () {
|
| 189 |
+
yield 4;
|
| 190 |
+
})()
|
| 191 |
+
);
|
| 192 |
+
//=> false
|
| 193 |
+
```
|
| 194 |
+
|
| 195 |
+
##### .asyncGeneratorFunction(value)
|
| 196 |
+
|
| 197 |
+
```js
|
| 198 |
+
is.asyncGeneratorFunction(async function * () {
|
| 199 |
+
yield 4;
|
| 200 |
+
});
|
| 201 |
+
//=> true
|
| 202 |
+
|
| 203 |
+
is.asyncGeneratorFunction(function * () {
|
| 204 |
+
yield 4;
|
| 205 |
+
});
|
| 206 |
+
//=> false
|
| 207 |
+
```
|
| 208 |
+
|
| 209 |
+
##### .boundFunction(value)
|
| 210 |
+
|
| 211 |
+
Returns `true` for any `bound` function.
|
| 212 |
+
|
| 213 |
+
```js
|
| 214 |
+
is.boundFunction(() => {});
|
| 215 |
+
//=> true
|
| 216 |
+
|
| 217 |
+
is.boundFunction(function () {}.bind(null));
|
| 218 |
+
//=> true
|
| 219 |
+
|
| 220 |
+
is.boundFunction(function () {});
|
| 221 |
+
//=> false
|
| 222 |
+
```
|
| 223 |
+
|
| 224 |
+
##### .map(value)
|
| 225 |
+
##### .set(value)
|
| 226 |
+
##### .weakMap(value)
|
| 227 |
+
##### .weakSet(value)
|
| 228 |
+
##### .weakRef(value)
|
| 229 |
+
|
| 230 |
+
#### Typed arrays
|
| 231 |
+
|
| 232 |
+
##### .int8Array(value)
|
| 233 |
+
##### .uint8Array(value)
|
| 234 |
+
##### .uint8ClampedArray(value)
|
| 235 |
+
##### .int16Array(value)
|
| 236 |
+
##### .uint16Array(value)
|
| 237 |
+
##### .int32Array(value)
|
| 238 |
+
##### .uint32Array(value)
|
| 239 |
+
##### .float32Array(value)
|
| 240 |
+
##### .float64Array(value)
|
| 241 |
+
##### .bigInt64Array(value)
|
| 242 |
+
##### .bigUint64Array(value)
|
| 243 |
+
|
| 244 |
+
#### Structured data
|
| 245 |
+
|
| 246 |
+
##### .arrayBuffer(value)
|
| 247 |
+
##### .sharedArrayBuffer(value)
|
| 248 |
+
##### .dataView(value)
|
| 249 |
+
|
| 250 |
+
##### .enumCase(value, enum)
|
| 251 |
+
|
| 252 |
+
TypeScript-only. Returns `true` if `value` is a member of `enum`.
|
| 253 |
+
|
| 254 |
+
```ts
|
| 255 |
+
enum Direction {
|
| 256 |
+
Ascending = 'ascending',
|
| 257 |
+
Descending = 'descending'
|
| 258 |
+
}
|
| 259 |
+
|
| 260 |
+
is.enumCase('ascending', Direction);
|
| 261 |
+
//=> true
|
| 262 |
+
|
| 263 |
+
is.enumCase('other', Direction);
|
| 264 |
+
//=> false
|
| 265 |
+
```
|
| 266 |
+
|
| 267 |
+
#### Emptiness
|
| 268 |
+
|
| 269 |
+
##### .emptyString(value)
|
| 270 |
+
|
| 271 |
+
Returns `true` if the value is a `string` and the `.length` is 0.
|
| 272 |
+
|
| 273 |
+
##### .emptyStringOrWhitespace(value)
|
| 274 |
+
|
| 275 |
+
Returns `true` if `is.emptyString(value)` or if it's a `string` that is all whitespace.
|
| 276 |
+
|
| 277 |
+
##### .nonEmptyString(value)
|
| 278 |
+
|
| 279 |
+
Returns `true` if the value is a `string` and the `.length` is more than 0.
|
| 280 |
+
|
| 281 |
+
##### .nonEmptyStringAndNotWhitespace(value)
|
| 282 |
+
|
| 283 |
+
Returns `true` if the value is a `string` that is not empty and not whitespace.
|
| 284 |
+
|
| 285 |
+
```js
|
| 286 |
+
const values = ['property1', '', null, 'property2', ' ', undefined];
|
| 287 |
+
|
| 288 |
+
values.filter(is.nonEmptyStringAndNotWhitespace);
|
| 289 |
+
//=> ['property1', 'property2']
|
| 290 |
+
```
|
| 291 |
+
|
| 292 |
+
##### .emptyArray(value)
|
| 293 |
+
|
| 294 |
+
Returns `true` if the value is an `Array` and the `.length` is 0.
|
| 295 |
+
|
| 296 |
+
##### .nonEmptyArray(value)
|
| 297 |
+
|
| 298 |
+
Returns `true` if the value is an `Array` and the `.length` is more than 0.
|
| 299 |
+
|
| 300 |
+
##### .emptyObject(value)
|
| 301 |
+
|
| 302 |
+
Returns `true` if the value is an `Object` and `Object.keys(value).length` is 0.
|
| 303 |
+
|
| 304 |
+
Please note that `Object.keys` returns only own enumerable properties. Hence something like this can happen:
|
| 305 |
+
|
| 306 |
+
```js
|
| 307 |
+
const object1 = {};
|
| 308 |
+
|
| 309 |
+
Object.defineProperty(object1, 'property1', {
|
| 310 |
+
value: 42,
|
| 311 |
+
writable: true,
|
| 312 |
+
enumerable: false,
|
| 313 |
+
configurable: true
|
| 314 |
+
});
|
| 315 |
+
|
| 316 |
+
is.emptyObject(object1);
|
| 317 |
+
//=> true
|
| 318 |
+
```
|
| 319 |
+
|
| 320 |
+
##### .nonEmptyObject(value)
|
| 321 |
+
|
| 322 |
+
Returns `true` if the value is an `Object` and `Object.keys(value).length` is more than 0.
|
| 323 |
+
|
| 324 |
+
##### .emptySet(value)
|
| 325 |
+
|
| 326 |
+
Returns `true` if the value is a `Set` and the `.size` is 0.
|
| 327 |
+
|
| 328 |
+
##### .nonEmptySet(Value)
|
| 329 |
+
|
| 330 |
+
Returns `true` if the value is a `Set` and the `.size` is more than 0.
|
| 331 |
+
|
| 332 |
+
##### .emptyMap(value)
|
| 333 |
+
|
| 334 |
+
Returns `true` if the value is a `Map` and the `.size` is 0.
|
| 335 |
+
|
| 336 |
+
##### .nonEmptyMap(value)
|
| 337 |
+
|
| 338 |
+
Returns `true` if the value is a `Map` and the `.size` is more than 0.
|
| 339 |
+
|
| 340 |
+
#### Miscellaneous
|
| 341 |
+
|
| 342 |
+
##### .directInstanceOf(value, class)
|
| 343 |
+
|
| 344 |
+
Returns `true` if `value` is a direct instance of `class`.
|
| 345 |
+
|
| 346 |
+
```js
|
| 347 |
+
is.directInstanceOf(new Error(), Error);
|
| 348 |
+
//=> true
|
| 349 |
+
|
| 350 |
+
class UnicornError extends Error {}
|
| 351 |
+
|
| 352 |
+
is.directInstanceOf(new UnicornError(), Error);
|
| 353 |
+
//=> false
|
| 354 |
+
```
|
| 355 |
+
|
| 356 |
+
##### .urlInstance(value)
|
| 357 |
+
|
| 358 |
+
Returns `true` if `value` is an instance of the [`URL` class](https://developer.mozilla.org/en-US/docs/Web/API/URL).
|
| 359 |
+
|
| 360 |
+
```js
|
| 361 |
+
const url = new URL('https://example.com');
|
| 362 |
+
|
| 363 |
+
is.urlInstance(url);
|
| 364 |
+
//=> true
|
| 365 |
+
```
|
| 366 |
+
|
| 367 |
+
##### .urlString(value)
|
| 368 |
+
|
| 369 |
+
Returns `true` if `value` is a URL string.
|
| 370 |
+
|
| 371 |
+
Note: this only does basic checking using the [`URL` class](https://developer.mozilla.org/en-US/docs/Web/API/URL) constructor.
|
| 372 |
+
|
| 373 |
+
```js
|
| 374 |
+
const url = 'https://example.com';
|
| 375 |
+
|
| 376 |
+
is.urlString(url);
|
| 377 |
+
//=> true
|
| 378 |
+
|
| 379 |
+
is.urlString(new URL(url));
|
| 380 |
+
//=> false
|
| 381 |
+
```
|
| 382 |
+
|
| 383 |
+
##### .truthy(value)
|
| 384 |
+
|
| 385 |
+
Returns `true` for all values that evaluate to true in a boolean context:
|
| 386 |
+
|
| 387 |
+
```js
|
| 388 |
+
is.truthy('🦄');
|
| 389 |
+
//=> true
|
| 390 |
+
|
| 391 |
+
is.truthy(undefined);
|
| 392 |
+
//=> false
|
| 393 |
+
```
|
| 394 |
+
|
| 395 |
+
##### .falsy(value)
|
| 396 |
+
|
| 397 |
+
Returns `true` if `value` is one of: `false`, `0`, `''`, `null`, `undefined`, `NaN`.
|
| 398 |
+
|
| 399 |
+
##### .nan(value)
|
| 400 |
+
##### .nullOrUndefined(value)
|
| 401 |
+
##### .primitive(value)
|
| 402 |
+
|
| 403 |
+
JavaScript primitives are as follows:
|
| 404 |
+
|
| 405 |
+
- `null`
|
| 406 |
+
- `undefined`
|
| 407 |
+
- `string`
|
| 408 |
+
- `number`
|
| 409 |
+
- `boolean`
|
| 410 |
+
- `symbol`
|
| 411 |
+
- `bigint`
|
| 412 |
+
|
| 413 |
+
##### .integer(value)
|
| 414 |
+
|
| 415 |
+
##### .safeInteger(value)
|
| 416 |
+
|
| 417 |
+
Returns `true` if `value` is a [safe integer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger).
|
| 418 |
+
|
| 419 |
+
##### .plainObject(value)
|
| 420 |
+
|
| 421 |
+
An object is plain if it's created by either `{}`, `new Object()`, or `Object.create(null)`.
|
| 422 |
+
|
| 423 |
+
##### .iterable(value)
|
| 424 |
+
##### .asyncIterable(value)
|
| 425 |
+
##### .class(value)
|
| 426 |
+
|
| 427 |
+
Returns `true` if the value is a class constructor.
|
| 428 |
+
|
| 429 |
+
##### .typedArray(value)
|
| 430 |
+
|
| 431 |
+
##### .arrayLike(value)
|
| 432 |
+
|
| 433 |
+
A `value` is array-like if it is not a function and has a `value.length` that is a safe integer greater than or equal to 0.
|
| 434 |
+
|
| 435 |
+
```js
|
| 436 |
+
is.arrayLike(document.forms);
|
| 437 |
+
//=> true
|
| 438 |
+
|
| 439 |
+
function foo() {
|
| 440 |
+
is.arrayLike(arguments);
|
| 441 |
+
//=> true
|
| 442 |
+
}
|
| 443 |
+
foo();
|
| 444 |
+
```
|
| 445 |
+
|
| 446 |
+
##### .tupleLike(value, guards)
|
| 447 |
+
|
| 448 |
+
A `value` is tuple-like if it matches the provided `guards` array both in `.length` and in types.
|
| 449 |
+
|
| 450 |
+
```js
|
| 451 |
+
is.tupleLike([1], [is.number]);
|
| 452 |
+
//=> true
|
| 453 |
+
```
|
| 454 |
+
|
| 455 |
+
```js
|
| 456 |
+
function foo() {
|
| 457 |
+
const tuple = [1, '2', true];
|
| 458 |
+
if (is.tupleLike(tuple, [is.number, is.string, is.boolean])) {
|
| 459 |
+
tuple // [number, string, boolean]
|
| 460 |
+
}
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
foo();
|
| 464 |
+
```
|
| 465 |
+
|
| 466 |
+
##### .positiveNumber(value)
|
| 467 |
+
|
| 468 |
+
Check if `value` is a number and is more than 0.
|
| 469 |
+
|
| 470 |
+
##### .negativeNumber(value)
|
| 471 |
+
|
| 472 |
+
Check if `value` is a number and is less than 0.
|
| 473 |
+
|
| 474 |
+
##### .inRange(value, range)
|
| 475 |
+
|
| 476 |
+
Check if `value` (number) is in the given `range`. The range is an array of two values, lower bound and upper bound, in no specific order.
|
| 477 |
+
|
| 478 |
+
```js
|
| 479 |
+
is.inRange(3, [0, 5]);
|
| 480 |
+
is.inRange(3, [5, 0]);
|
| 481 |
+
is.inRange(0, [-2, 2]);
|
| 482 |
+
```
|
| 483 |
+
|
| 484 |
+
##### .inRange(value, upperBound)
|
| 485 |
+
|
| 486 |
+
Check if `value` (number) is in the range of `0` to `upperBound`.
|
| 487 |
+
|
| 488 |
+
```js
|
| 489 |
+
is.inRange(3, 10);
|
| 490 |
+
```
|
| 491 |
+
|
| 492 |
+
##### .htmlElement(value)
|
| 493 |
+
|
| 494 |
+
Returns `true` if `value` is an [HTMLElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement).
|
| 495 |
+
|
| 496 |
+
##### .nodeStream(value)
|
| 497 |
+
|
| 498 |
+
Returns `true` if `value` is a Node.js [stream](https://nodejs.org/api/stream.html).
|
| 499 |
+
|
| 500 |
+
```js
|
| 501 |
+
import fs from 'node:fs';
|
| 502 |
+
|
| 503 |
+
is.nodeStream(fs.createReadStream('unicorn.png'));
|
| 504 |
+
//=> true
|
| 505 |
+
```
|
| 506 |
+
|
| 507 |
+
##### .observable(value)
|
| 508 |
+
|
| 509 |
+
Returns `true` if `value` is an `Observable`.
|
| 510 |
+
|
| 511 |
+
```js
|
| 512 |
+
import {Observable} from 'rxjs';
|
| 513 |
+
|
| 514 |
+
is.observable(new Observable());
|
| 515 |
+
//=> true
|
| 516 |
+
```
|
| 517 |
+
|
| 518 |
+
##### .infinite(value)
|
| 519 |
+
|
| 520 |
+
Check if `value` is `Infinity` or `-Infinity`.
|
| 521 |
+
|
| 522 |
+
##### .evenInteger(value)
|
| 523 |
+
|
| 524 |
+
Returns `true` if `value` is an even integer.
|
| 525 |
+
|
| 526 |
+
##### .oddInteger(value)
|
| 527 |
+
|
| 528 |
+
Returns `true` if `value` is an odd integer.
|
| 529 |
+
|
| 530 |
+
##### .propertyKey(value)
|
| 531 |
+
|
| 532 |
+
Returns `true` if `value` can be used as an object property key (either `string`, `number`, or `symbol`).
|
| 533 |
+
|
| 534 |
+
##### .formData(value)
|
| 535 |
+
|
| 536 |
+
Returns `true` if `value` is an instance of the [`FormData` class](https://developer.mozilla.org/en-US/docs/Web/API/FormData).
|
| 537 |
+
|
| 538 |
+
```js
|
| 539 |
+
const data = new FormData();
|
| 540 |
+
|
| 541 |
+
is.formData(data);
|
| 542 |
+
//=> true
|
| 543 |
+
```
|
| 544 |
+
|
| 545 |
+
##### .urlSearchParams(value)
|
| 546 |
+
|
| 547 |
+
Returns `true` if `value` is an instance of the [`URLSearchParams` class](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams).
|
| 548 |
+
|
| 549 |
+
```js
|
| 550 |
+
const searchParams = new URLSearchParams();
|
| 551 |
+
|
| 552 |
+
is.urlSearchParams(searchParams);
|
| 553 |
+
//=> true
|
| 554 |
+
```
|
| 555 |
+
|
| 556 |
+
##### .any(predicate | predicate[], ...values)
|
| 557 |
+
|
| 558 |
+
Using a single `predicate` argument, returns `true` if **any** of the input `values` returns true in the `predicate`:
|
| 559 |
+
|
| 560 |
+
```js
|
| 561 |
+
is.any(is.string, {}, true, '🦄');
|
| 562 |
+
//=> true
|
| 563 |
+
|
| 564 |
+
is.any(is.boolean, 'unicorns', [], new Map());
|
| 565 |
+
//=> false
|
| 566 |
+
```
|
| 567 |
+
|
| 568 |
+
Using an array of `predicate[]`, returns `true` if **any** of the input `values` returns true for **any** of the `predicates` provided in an array:
|
| 569 |
+
|
| 570 |
+
```js
|
| 571 |
+
is.any([is.string, is.number], {}, true, '🦄');
|
| 572 |
+
//=> true
|
| 573 |
+
|
| 574 |
+
is.any([is.boolean, is.number], 'unicorns', [], new Map());
|
| 575 |
+
//=> false
|
| 576 |
+
```
|
| 577 |
+
|
| 578 |
+
##### .any(predicate[])
|
| 579 |
+
|
| 580 |
+
Using an array of `predicate[]` without values, returns a combined type guard that checks if a value matches **any** of the predicates:
|
| 581 |
+
|
| 582 |
+
```js
|
| 583 |
+
const isStringOrNumber = is.any([is.string, is.number]);
|
| 584 |
+
|
| 585 |
+
isStringOrNumber('hello');
|
| 586 |
+
//=> true
|
| 587 |
+
|
| 588 |
+
isStringOrNumber(123);
|
| 589 |
+
//=> true
|
| 590 |
+
|
| 591 |
+
isStringOrNumber(true);
|
| 592 |
+
//=> false
|
| 593 |
+
```
|
| 594 |
+
|
| 595 |
+
This is useful for composing with other methods like `is.optional`:
|
| 596 |
+
|
| 597 |
+
```js
|
| 598 |
+
is.optional(value, is.any([is.string, is.number]));
|
| 599 |
+
```
|
| 600 |
+
|
| 601 |
+
An empty predicate array currently returns a predicate that always returns `false`. This will throw in the next major release.
|
| 602 |
+
|
| 603 |
+
##### .all(predicate, ...values)
|
| 604 |
+
|
| 605 |
+
Returns `true` if **all** of the input `values` returns true in the `predicate`:
|
| 606 |
+
|
| 607 |
+
```js
|
| 608 |
+
is.all(is.object, {}, new Map(), new Set());
|
| 609 |
+
//=> true
|
| 610 |
+
|
| 611 |
+
is.all(is.string, '🦄', [], 'unicorns');
|
| 612 |
+
//=> false
|
| 613 |
+
```
|
| 614 |
+
|
| 615 |
+
##### .all(predicate[])
|
| 616 |
+
|
| 617 |
+
Using an array of `predicate[]` without values, returns a combined type guard that checks if a value matches **all** of the predicates:
|
| 618 |
+
|
| 619 |
+
```js
|
| 620 |
+
const isArrayAndNonEmpty = is.all([is.array, is.nonEmptyArray]);
|
| 621 |
+
|
| 622 |
+
isArrayAndNonEmpty(['hello']);
|
| 623 |
+
//=> true
|
| 624 |
+
|
| 625 |
+
isArrayAndNonEmpty([]);
|
| 626 |
+
//=> false
|
| 627 |
+
```
|
| 628 |
+
|
| 629 |
+
This is useful for composing with other methods like `is.optional`:
|
| 630 |
+
|
| 631 |
+
```js
|
| 632 |
+
is.optional(value, is.all([is.object, is.plainObject]));
|
| 633 |
+
```
|
| 634 |
+
|
| 635 |
+
An empty predicate array currently returns a predicate that always returns `true`. This will throw in the next major release.
|
| 636 |
+
|
| 637 |
+
##### .optional(value, predicate)
|
| 638 |
+
|
| 639 |
+
Returns `true` if `value` is `undefined` or satisfies the given `predicate`.
|
| 640 |
+
|
| 641 |
+
```js
|
| 642 |
+
is.optional(undefined, is.string);
|
| 643 |
+
//=> true
|
| 644 |
+
|
| 645 |
+
is.optional('🦄', is.string);
|
| 646 |
+
//=> true
|
| 647 |
+
|
| 648 |
+
is.optional(123, is.string);
|
| 649 |
+
//=> false
|
| 650 |
+
```
|
| 651 |
+
|
| 652 |
+
##### .validDate(value)
|
| 653 |
+
|
| 654 |
+
Returns `true` if the value is a valid date.
|
| 655 |
+
|
| 656 |
+
All [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date) objects have an internal timestamp value which is the number of milliseconds since the [Unix epoch](https://developer.mozilla.org/en-US/docs/Glossary/Unix_time). When a new `Date` is constructed with bad inputs, no error is thrown. Instead, a new `Date` object is returned. But the internal timestamp value is set to `NaN`, which is an `'Invalid Date'`. Bad inputs can be an non-parsable date string, a non-numeric value or a number that is outside of the expected range for a date value.
|
| 657 |
+
|
| 658 |
+
```js
|
| 659 |
+
const valid = new Date('2000-01-01');
|
| 660 |
+
|
| 661 |
+
is.date(valid);
|
| 662 |
+
//=> true
|
| 663 |
+
valid.getTime();
|
| 664 |
+
//=> 946684800000
|
| 665 |
+
valid.toUTCString();
|
| 666 |
+
//=> 'Sat, 01 Jan 2000 00:00:00 GMT'
|
| 667 |
+
is.validDate(valid);
|
| 668 |
+
//=> true
|
| 669 |
+
|
| 670 |
+
const invalid = new Date('Not a parsable date string');
|
| 671 |
+
|
| 672 |
+
is.date(invalid);
|
| 673 |
+
//=> true
|
| 674 |
+
invalid.getTime();
|
| 675 |
+
//=> NaN
|
| 676 |
+
invalid.toUTCString();
|
| 677 |
+
//=> 'Invalid Date'
|
| 678 |
+
is.validDate(invalid);
|
| 679 |
+
//=> false
|
| 680 |
+
```
|
| 681 |
+
|
| 682 |
+
##### .validLength(value)
|
| 683 |
+
|
| 684 |
+
Returns `true` if the value is a safe integer that is greater than or equal to zero.
|
| 685 |
+
|
| 686 |
+
This can be useful to confirm that a value is a valid count of something, ie. 0 or more.
|
| 687 |
+
|
| 688 |
+
##### .whitespaceString(value)
|
| 689 |
+
|
| 690 |
+
Returns `true` if the value is a string with only whitespace characters.
|
| 691 |
+
|
| 692 |
+
## Type guards
|
| 693 |
+
|
| 694 |
+
When using `is` together with TypeScript, [type guards](http://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types) are being used extensively to infer the correct type inside if-else statements.
|
| 695 |
+
|
| 696 |
+
```ts
|
| 697 |
+
import is from '@sindresorhus/is';
|
| 698 |
+
|
| 699 |
+
const padLeft = (value: string, padding: string | number) => {
|
| 700 |
+
if (is.number(padding)) {
|
| 701 |
+
// `padding` is typed as `number`
|
| 702 |
+
return Array(padding + 1).join(' ') + value;
|
| 703 |
+
}
|
| 704 |
+
|
| 705 |
+
if (is.string(padding)) {
|
| 706 |
+
// `padding` is typed as `string`
|
| 707 |
+
return padding + value;
|
| 708 |
+
}
|
| 709 |
+
|
| 710 |
+
throw new TypeError(`Expected 'padding' to be of type 'string' or 'number', got '${is(padding)}'.`);
|
| 711 |
+
}
|
| 712 |
+
|
| 713 |
+
padLeft('🦄', 3);
|
| 714 |
+
//=> ' 🦄'
|
| 715 |
+
|
| 716 |
+
padLeft('🦄', '🌈');
|
| 717 |
+
//=> '🌈🦄'
|
| 718 |
+
```
|
| 719 |
+
|
| 720 |
+
## Type assertions
|
| 721 |
+
|
| 722 |
+
The type guards are also available as [type assertions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions), which throw an error for unexpected types. It is a convenient one-line version of the often repetitive "if-not-expected-type-throw" pattern.
|
| 723 |
+
|
| 724 |
+
```ts
|
| 725 |
+
import {assert} from '@sindresorhus/is';
|
| 726 |
+
|
| 727 |
+
const handleMovieRatingApiResponse = (response: unknown) => {
|
| 728 |
+
assert.plainObject(response);
|
| 729 |
+
// `response` is now typed as a plain `object` with `unknown` properties.
|
| 730 |
+
|
| 731 |
+
assert.number(response.rating);
|
| 732 |
+
// `response.rating` is now typed as a `number`.
|
| 733 |
+
|
| 734 |
+
assert.string(response.title);
|
| 735 |
+
// `response.title` is now typed as a `string`.
|
| 736 |
+
|
| 737 |
+
return `${response.title} (${response.rating * 10})`;
|
| 738 |
+
};
|
| 739 |
+
|
| 740 |
+
handleMovieRatingApiResponse({rating: 0.87, title: 'The Matrix'});
|
| 741 |
+
//=> 'The Matrix (8.7)'
|
| 742 |
+
|
| 743 |
+
// This throws an error.
|
| 744 |
+
handleMovieRatingApiResponse({rating: '🦄'});
|
| 745 |
+
```
|
| 746 |
+
|
| 747 |
+
### Optional assertion
|
| 748 |
+
|
| 749 |
+
Asserts that `value` is `undefined` or satisfies the provided `assertion`.
|
| 750 |
+
|
| 751 |
+
```ts
|
| 752 |
+
import {assert} from '@sindresorhus/is';
|
| 753 |
+
|
| 754 |
+
assert.optional(undefined, assert.string);
|
| 755 |
+
// Passes without throwing
|
| 756 |
+
|
| 757 |
+
assert.optional('🦄', assert.string);
|
| 758 |
+
// Passes without throwing
|
| 759 |
+
|
| 760 |
+
assert.optional(123, assert.string);
|
| 761 |
+
// Throws: Expected value which is `string`, received value of type `number`
|
| 762 |
+
```
|
| 763 |
+
|
| 764 |
+
## Generic type parameters
|
| 765 |
+
|
| 766 |
+
The type guards and type assertions are aware of [generic type parameters](https://www.typescriptlang.org/docs/handbook/generics.html), such as `Promise<T>` and `Map<Key, Value>`. The default is `unknown` for most cases, since `is` cannot check them at runtime. If the generic type is known at compile-time, either implicitly (inferred) or explicitly (provided), `is` propagates the type so it can be used later.
|
| 767 |
+
|
| 768 |
+
Use generic type parameters with caution. They are only checked by the TypeScript compiler, and not checked by `is` at runtime. This can lead to unexpected behavior, where the generic type is _assumed_ at compile-time, but actually is something completely different at runtime. It is best to use `unknown` (default) and type-check the value of the generic type parameter at runtime with `is` or `assert`.
|
| 769 |
+
|
| 770 |
+
```ts
|
| 771 |
+
import {assert} from '@sindresorhus/is';
|
| 772 |
+
|
| 773 |
+
async function badNumberAssumption(input: unknown) {
|
| 774 |
+
// Bad assumption about the generic type parameter fools the compile-time type system.
|
| 775 |
+
assert.promise<number>(input);
|
| 776 |
+
// `input` is a `Promise` but only assumed to be `Promise<number>`.
|
| 777 |
+
|
| 778 |
+
const resolved = await input;
|
| 779 |
+
// `resolved` is typed as `number` but was not actually checked at runtime.
|
| 780 |
+
|
| 781 |
+
// Multiplication will return NaN if the input promise did not actually contain a number.
|
| 782 |
+
return 2 * resolved;
|
| 783 |
+
}
|
| 784 |
+
|
| 785 |
+
async function goodNumberAssertion(input: unknown) {
|
| 786 |
+
assert.promise(input);
|
| 787 |
+
// `input` is typed as `Promise<unknown>`
|
| 788 |
+
|
| 789 |
+
const resolved = await input;
|
| 790 |
+
// `resolved` is typed as `unknown`
|
| 791 |
+
|
| 792 |
+
assert.number(resolved);
|
| 793 |
+
// `resolved` is typed as `number`
|
| 794 |
+
|
| 795 |
+
// Uses runtime checks so only numbers will reach the multiplication.
|
| 796 |
+
return 2 * resolved;
|
| 797 |
+
}
|
| 798 |
+
|
| 799 |
+
badNumberAssumption(Promise.resolve('An unexpected string'));
|
| 800 |
+
//=> NaN
|
| 801 |
+
|
| 802 |
+
// This correctly throws an error because of the unexpected string value.
|
| 803 |
+
goodNumberAssertion(Promise.resolve('An unexpected string'));
|
| 804 |
+
```
|
| 805 |
+
|
| 806 |
+
## FAQ
|
| 807 |
+
|
| 808 |
+
### Why yet another type checking module?
|
| 809 |
+
|
| 810 |
+
There are hundreds of type checking modules on npm, unfortunately, I couldn't find any that fit my needs:
|
| 811 |
+
|
| 812 |
+
- Includes both type methods and ability to get the type
|
| 813 |
+
- Types of primitives returned as lowercase and object types as camelcase
|
| 814 |
+
- Covers all built-ins
|
| 815 |
+
- Unsurprising behavior
|
| 816 |
+
- Well-maintained
|
| 817 |
+
- Comprehensive test suite
|
| 818 |
+
|
| 819 |
+
For the ones I found, pick 3 of these.
|
| 820 |
+
|
| 821 |
+
The most common mistakes I noticed in these modules was using `instanceof` for type checking, forgetting that functions are objects, and omitting `symbol` as a primitive.
|
| 822 |
+
|
| 823 |
+
### Why not just use `instanceof` instead of this package?
|
| 824 |
+
|
| 825 |
+
`instanceof` does not work correctly for all types and it does not work across [realms](https://stackoverflow.com/a/49832343/64949). Examples of realms are iframes, windows, web workers, and the `vm` module in Node.js.
|
| 826 |
+
|
| 827 |
+
## Related
|
| 828 |
+
|
| 829 |
+
- [environment](https://github.com/sindresorhus/environment) - Check which JavaScript environment your code is running in at runtime
|
| 830 |
+
- [is-stream](https://github.com/sindresorhus/is-stream) - Check if something is a Node.js stream
|
| 831 |
+
- [is-observable](https://github.com/sindresorhus/is-observable) - Check if a value is an Observable
|
| 832 |
+
- [file-type](https://github.com/sindresorhus/file-type) - Detect the file type of a Buffer/Uint8Array
|
| 833 |
+
- [is-ip](https://github.com/sindresorhus/is-ip) - Check if a string is an IP address
|
| 834 |
+
- [is-array-sorted](https://github.com/sindresorhus/is-array-sorted) - Check if an Array is sorted
|
| 835 |
+
- [is-error-constructor](https://github.com/sindresorhus/is-error-constructor) - Check if a value is an error constructor
|
| 836 |
+
- [is-empty-iterable](https://github.com/sindresorhus/is-empty-iterable) - Check if an Iterable is empty
|
| 837 |
+
- [is-blob](https://github.com/sindresorhus/is-blob) - Check if a value is a Blob - File-like object of immutable, raw data
|
| 838 |
+
- [has-emoji](https://github.com/sindresorhus/has-emoji) - Check whether a string has any emoji
|
| 839 |
+
|
| 840 |
+
## Maintainers
|
| 841 |
+
|
| 842 |
+
- [Sindre Sorhus](https://github.com/sindresorhus)
|
| 843 |
+
- [Giora Guttsait](https://github.com/gioragutt)
|
| 844 |
+
- [Brandon Smith](https://github.com/brandon93s)
|
bunx-1000-wrangler@latest/node_modules/@speed-highlight/core/README.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Speed Highlight JS
|
| 2 |
+
|
| 3 |
+
<p align="center">
|
| 4 |
+
<a href="https://speed-highlight.github.io/core/examples">Demo</a> |
|
| 5 |
+
<a href="https://github.com/speed-highlight/core/wiki">Wiki</a> |
|
| 6 |
+
<a href="https://speed-highlight.github.io/core/docs">Docs</a>
|
| 7 |
+
</p>
|
| 8 |
+
|
| 9 |
+

|
| 10 |
+
|
| 11 |
+
- 🪶 Lightweight (**~2kB** for the core + **~1kB** by language)
|
| 12 |
+
- ⚡ Fast (faster than prism and highlight.js on average)
|
| 13 |
+
- 🧹 Minimal Codebase
|
| 14 |
+
|
| 15 |
+
## Simple setup 🚀
|
| 16 |
+
|
| 17 |
+
### Web
|
| 18 |
+
|
| 19 |
+
Style/theme (in the header of your html file):
|
| 20 |
+
|
| 21 |
+
```html
|
| 22 |
+
<link rel="stylesheet" href="/path/dist/themes/default.css">
|
| 23 |
+
```
|
| 24 |
+
|
| 25 |
+
In the body of your html file:
|
| 26 |
+
|
| 27 |
+
```html
|
| 28 |
+
<div class='shj-lang-[code-language]'>[code]</div>
|
| 29 |
+
or
|
| 30 |
+
<code class='shj-lang-[code-language]'>[inline code]</code>
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
Highlight the code (in your javascript):
|
| 34 |
+
|
| 35 |
+
```js
|
| 36 |
+
import { highlightAll } from '/path/dist/index.js';
|
| 37 |
+
highlightAll();
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
Auto language detection
|
| 41 |
+
|
| 42 |
+
```js
|
| 43 |
+
import { highlightElement } from '../dist/index.js';
|
| 44 |
+
import { detectLanguage } from '../dist/detect.js';
|
| 45 |
+
|
| 46 |
+
elm.textContent = code;
|
| 47 |
+
highlightElement(elm, detectLanguage(code));
|
| 48 |
+
```
|
| 49 |
+
|
| 50 |
+
Load custom language
|
| 51 |
+
|
| 52 |
+
```js
|
| 53 |
+
import { loadLanguage } from '../dist/index.js';
|
| 54 |
+
|
| 55 |
+
loadLanguage('language-name', customLanguage);
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
---
|
| 59 |
+
|
| 60 |
+
#### CDN
|
| 61 |
+
|
| 62 |
+
```html
|
| 63 |
+
<link rel="stylesheet" href="https://unpkg.com/@speed-highlight/core/dist/themes/default.css">
|
| 64 |
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/speed-highlight/core/dist/themes/default.css">
|
| 65 |
+
```
|
| 66 |
+
|
| 67 |
+
```js
|
| 68 |
+
import ... from 'https://unpkg.com/@speed-highlight/core/dist/index.js';
|
| 69 |
+
import ... from 'https://cdn.jsdelivr.net/gh/speed-highlight/core/dist/index.js';
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
---
|
| 73 |
+
|
| 74 |
+
### Deno
|
| 75 |
+
|
| 76 |
+
Use the [deno module](https://deno.land/x/speed_highlight_js)
|
| 77 |
+
|
| 78 |
+
```js
|
| 79 |
+
import { setTheme, printHighlight } from 'https://deno.land/x/speed_highlight_js/dist/terminal.js';
|
| 80 |
+
|
| 81 |
+
await setTheme('[theme-name]');
|
| 82 |
+
printHighlight('console.log("hello")', 'js');
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
---
|
| 86 |
+
|
| 87 |
+
### Node
|
| 88 |
+
|
| 89 |
+
Use the [npm package](https://www.npmjs.com/package/@speed-highlight/core)
|
| 90 |
+
|
| 91 |
+
```bash
|
| 92 |
+
npm i @speed-highlight/core
|
| 93 |
+
```
|
| 94 |
+
|
| 95 |
+
```js
|
| 96 |
+
const { setTheme, printHighlight } = require('@speed-highlight/core/terminal');
|
| 97 |
+
|
| 98 |
+
setTheme('[theme-name]');
|
| 99 |
+
printHighlight('console.log("hello")', 'js');
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
## Migrating from prism
|
| 103 |
+
|
| 104 |
+
Speed-highlight JS is a lighter and faster version of prism that share a similar API
|
| 105 |
+
|
| 106 |
+
### Style
|
| 107 |
+
|
| 108 |
+
Remove the prism stylesheet in the head of your html file
|
| 109 |
+
Clone this repository or use a cdn to load our stylesheet
|
| 110 |
+
|
| 111 |
+
```diff
|
| 112 |
+
<head>
|
| 113 |
+
- <link href="themes/prism.css" rel="stylesheet" />
|
| 114 |
+
+ <link rel="stylesheet" href="https://unpkg.com/@speed-highlight/core/dist/themes/default.css">
|
| 115 |
+
</head>
|
| 116 |
+
```
|
| 117 |
+
|
| 118 |
+
### Script
|
| 119 |
+
|
| 120 |
+
For the script part remove the prism.js script and replace it by a import and a call to `highlightAll`
|
| 121 |
+
|
| 122 |
+
```diff
|
| 123 |
+
<body>
|
| 124 |
+
- <script src="prism.js"></script>
|
| 125 |
+
+<script>
|
| 126 |
+
+ import { highlightAll } from 'https://unpkg.com/@speed-highlight/core/dist/index.js';
|
| 127 |
+
+ highlightAll();
|
| 128 |
+
+</script>
|
| 129 |
+
</body>
|
| 130 |
+
```
|
| 131 |
+
|
| 132 |
+
If you want to highlight only a specific element you can use the `highlightElement` function instead
|
| 133 |
+
|
| 134 |
+
### Code block
|
| 135 |
+
|
| 136 |
+
For the code blocks replace the `<pre><code>` by only one `<div>`
|
| 137 |
+
And use `shj-lang-` prefix instead of `language-` for the class property
|
| 138 |
+
|
| 139 |
+
```diff
|
| 140 |
+
-<pre><code class="language-css">p { color: red }</code></pre>
|
| 141 |
+
+<div class="shj-lang-css">p { color: red }</div>
|
| 142 |
+
```
|
| 143 |
+
|
| 144 |
+
And for inline code block you just have to change the class property
|
| 145 |
+
|
| 146 |
+
```diff
|
| 147 |
+
-<code class="language-css">p { color: red }</code>
|
| 148 |
+
+<code class="shj-lang-css">p { color: red }</code>
|
| 149 |
+
```
|
| 150 |
+
|
| 151 |
+
## Languages supported 🌐
|
| 152 |
+
|
| 153 |
+
| Name | Class name | Support | Language detection |
|
| 154 |
+
| ---------- | ------------------- | --------------------------------------------------- | ------------------ |
|
| 155 |
+
| asm | shj-lang-asm | | ✅ |
|
| 156 |
+
| bash | shj-lang-bash | | ✅ |
|
| 157 |
+
| brainfuck | shj-lang-bf | increment, operator, print, comment | ❌ |
|
| 158 |
+
| c | shj-lang-c | | ✅ |
|
| 159 |
+
| css | shj-lang-css | comment, str, selector, units, function, ... | ✅ |
|
| 160 |
+
| csv | shj-lang-csv | punctuation, ... | ❌ |
|
| 161 |
+
| diff | shj-lang-diff | | ✅ |
|
| 162 |
+
| docker | shj-lang-docker | | ✅ |
|
| 163 |
+
| git | shj-lang-git | comment, insert, deleted, string, ... | ❌ |
|
| 164 |
+
| go | shj-lang-go | | ✅ |
|
| 165 |
+
| html | shj-lang-html | | ✅ |
|
| 166 |
+
| http | shj-lang-http | keywork, string, punctuation, variable, version | ✅ |
|
| 167 |
+
| ini | shj-lang-ini | | ❌ |
|
| 168 |
+
| java | shj-lang-java | | ✅ |
|
| 169 |
+
| javascipt | shj-lang-js | basic syntax, regex, jsdoc, json, template literals | ✅ |
|
| 170 |
+
| jsdoc | shj-lang-jsdoc | | ❌ |
|
| 171 |
+
| json | shj-lang-json | string, number, bool, ... | ❌ |
|
| 172 |
+
| leanpub-md | shj-lang-leanpub-md | | ❌ |
|
| 173 |
+
| log | shj-lang-log | number, string, comment, errors | ❌ |
|
| 174 |
+
| lua | shj-lang-lua | | ✅ |
|
| 175 |
+
| makefile | shj-lang-make | | ✅ |
|
| 176 |
+
| markdown | shj-lang-md | | ✅ |
|
| 177 |
+
| perl | shj-lang-pl | | ✅ |
|
| 178 |
+
| plain | shj-lang-plain | | ❌ |
|
| 179 |
+
| python | shj-lang-py | | ✅ |
|
| 180 |
+
| regex | shj-lang-regex | count, set, ... | ❌ |
|
| 181 |
+
| rust | shj-lang-rs | | ✅ |
|
| 182 |
+
| sql | shj-lang-sql | number, string, function, ... | ✅ |
|
| 183 |
+
| todo | shj-lang-todo | | ❌ |
|
| 184 |
+
| toml | shj-lang-toml | comment, table, string, bool, variable | ❌ |
|
| 185 |
+
| typescript | shj-lang-ts | js syntax, ts keyword, types | ✅ |
|
| 186 |
+
| uri | shj-lang-uri | | ✅ |
|
| 187 |
+
| xml | shj-lang-xml | | ✅ |
|
| 188 |
+
| yaml | shj-lang-yaml | comment, numbers, variable, string, bool | ❌ |
|
| 189 |
+
|
| 190 |
+
## Themes 🌈
|
| 191 |
+
|
| 192 |
+
A modern theme by default
|
| 193 |
+
|
| 194 |
+
| Name | Terminal | Web |
|
| 195 |
+
| ------------------- | -------- | --- |
|
| 196 |
+
| default | ✅ | ✅ |
|
| 197 |
+
| github-dark | ❌ | ✅ |
|
| 198 |
+
| github-light | ❌ | ✅ |
|
| 199 |
+
| github-dim | ❌ | ✅ |
|
| 200 |
+
| atom-dark | ✅ | ✅ |
|
| 201 |
+
| visual-studio-dark | ❌ | ✅ |
|
bunx-1000-wrangler@latest/node_modules/blake3-wasm/changelog.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Changelog
|
| 2 |
+
|
| 3 |
+
## 2.1.5 - 2020-11-28
|
| 4 |
+
|
| 5 |
+
- fix version matching on postinstall
|
| 6 |
+
- build for node 15
|
| 7 |
+
|
| 8 |
+
## 2.1.4 - 2020-05-11
|
| 9 |
+
|
| 10 |
+
- add support for Node 14
|
| 11 |
+
- validate native bindings before switching to them
|
| 12 |
+
|
| 13 |
+
## 2.1.3 - 2020-03-06
|
| 14 |
+
|
| 15 |
+
- update to BLAKE3@0.2, providing significant speed improvements for native Node
|
| 16 |
+
- fixed missing file causing installation of native Node extensions to fail
|
| 17 |
+
|
| 18 |
+
## 2.1.2 - 2020-03-01
|
| 19 |
+
|
| 20 |
+
- fix missing createKeyed function in browsers
|
| 21 |
+
|
| 22 |
+
## 2.1.1 - 2020-02-11
|
| 23 |
+
|
| 24 |
+
- allow importing the module without a bundler or with tools like Parcel
|
| 25 |
+
|
| 26 |
+
## 2.1.0 - 2020-01-23
|
| 27 |
+
|
| 28 |
+
- add keyed hash and key derivation support (fixes [#2](https://github.com/connor4312/blake3/issues/2), [#9](https://github.com/connor4312/blake3/issues/9))
|
| 29 |
+
- fixed a bug in hex encoding in the browser
|
| 30 |
+
|
| 31 |
+
## 2.0.1 - 2020-01-23
|
| 32 |
+
|
| 33 |
+
- fix browser bundle to use pure es modules (fixes [#8](https://github.com/connor4312/blake3/issues/8))
|
| 34 |
+
|
| 35 |
+
## 2.0.0 - 2020-01-19
|
| 36 |
+
|
| 37 |
+
- **breaking** the simple `hash` function no longer takes an encoding in its second parameter. Use `hash(data).toString(<encoding>)` instead.
|
| 38 |
+
- allow configuring the hash length in `hash()` and `hasher.digest()`
|
| 39 |
+
- add `using()` helper to deal with disposables
|
| 40 |
+
- add `dispose: boolean` option to Hashers' `.digest()` methods, so that you can read a head while continuing to update it
|
| 41 |
+
- add `hasher.reader()` method to retrieve a hash reader object, which allows seeking through and reading arbitrary amounts of data from the hash
|
| 42 |
+
- add helper methods for encoding and constant-time equality checking in the returned Hash within the browser
|
| 43 |
+
|
| 44 |
+
## 1.2.0 - 2020-01-14
|
| 45 |
+
|
| 46 |
+
- add native Node.js bindings
|
| 47 |
+
|
| 48 |
+
## 1.2.0-0 - 2020-01-14 (prerelease)
|
| 49 |
+
|
| 50 |
+
- add native Node.js bindings
|
| 51 |
+
|
| 52 |
+
## 1.1.0 - 2020-01-12
|
| 53 |
+
|
| 54 |
+
- add support for usage in browsers
|
| 55 |
+
- fix potential memory unsafety in WebAssembly land
|
| 56 |
+
- add support for output encoding in `Hash.digest([encoding])`
|
| 57 |
+
|
| 58 |
+
## 1.0.0 - 2020-01-09
|
| 59 |
+
|
| 60 |
+
Initial release
|
bunx-1000-wrangler@latest/node_modules/blake3-wasm/readme.md
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# BLAKE3
|
| 2 |
+
|
| 3 |
+
[BLAKE3](https://github.com/BLAKE3-team/BLAKE3) running in JavaScript (node.js and browsers) via native bindings, where available, or WebAssembly.
|
| 4 |
+
|
| 5 |
+
npm install blake3
|
| 6 |
+
|
| 7 |
+
Additionally, there's a flavor of the package which is identical except that it will not download native Node.js bindings:
|
| 8 |
+
|
| 9 |
+
npm install blake3-wasm
|
| 10 |
+
|
| 11 |
+
## Table of Contents
|
| 12 |
+
|
| 13 |
+
- [Quickstart](#quickstart)
|
| 14 |
+
- [API](#api)
|
| 15 |
+
- [Node.js](#nodejs)
|
| 16 |
+
- [`hash(data: BinaryLike, options?: { length: number }): Buffer`](#hashdata-binarylike-options--length-number--buffer)
|
| 17 |
+
- [`keyedHash(key: Buffer, data: BinaryLike, options?: { length: number }): Buffer`](#keyedhashkey-buffer-data-binarylike-options--length-number--buffer)
|
| 18 |
+
- [`deriveKey(context: string, material: BinaryLike, options?: { length: number }): Buffer`](#derivekeycontext-string-material-binarylike-options--length-number--buffer)
|
| 19 |
+
- [Hasher](#hasher)
|
| 20 |
+
- [`createHash(): Hasher`](#createhash-hasher)
|
| 21 |
+
- [`createKeyed(key: Buffer): Hasher`](#createkeyedkey-buffer-hasher)
|
| 22 |
+
- [`createDeriveKey(context: string): Hasher`](#createderivekeycontext-string-hasher)
|
| 23 |
+
- [`hasher.update(data: BinaryLike): this`](#hasherupdatedata-binarylike-this)
|
| 24 |
+
- [`hasher.digest(encoding?: string, options?: { length: number, dispose: boolean })): Buffer | string`](#hasherdigestencoding-string-options--length-number-dispose-boolean--buffer--string)
|
| 25 |
+
- [`hasher.reader(options?: { dispose: boolean }): HashReader`](#hasherreaderoptions--dispose-boolean--hashreader)
|
| 26 |
+
- [`hasher.dispose()`](#hasherdispose)
|
| 27 |
+
- [HashReader](#hashreader)
|
| 28 |
+
- [`reader.position: bigint`](#readerposition-bigint)
|
| 29 |
+
- [`reader.readInto(target: Buffer): void`](#readerreadintotarget-buffer-void)
|
| 30 |
+
- [`reader.read(bytes: number): Buffer`](#readerreadbytes-number-buffer)
|
| 31 |
+
- [`reader.toString([encoding]): string`](#readertostringencoding-string)
|
| 32 |
+
- [`reader.toBuffer(): Buffer`](#readertobuffer-buffer)
|
| 33 |
+
- [`reader.dispose()`](#readerdispose)
|
| 34 |
+
- [`using(disposable: IDisposable, fn: disposable => T): T`](#usingdisposable-idisposable-fn-disposable--t-t)
|
| 35 |
+
- [Browser](#browser)
|
| 36 |
+
- [`hash(data: BinaryLike, options?: { length: number }): Hash`](#hashdata-binarylike-options--length-number--hash)
|
| 37 |
+
- [`keyedHash(key: Buffer, data: BinaryLike, options?: { length: number }): Hash`](#keyedhashkey-buffer-data-binarylike-options--length-number--hash)
|
| 38 |
+
- [`deriveKey(context: string, material: BinaryLike, options?: { length: number }): Hash`](#derivekeycontext-string-material-binarylike-options--length-number--hash)
|
| 39 |
+
- [`Hash`](#hash)
|
| 40 |
+
- [`hash.equals(other: Uint8Array)`](#hashequalsother-uint8array)
|
| 41 |
+
- [`hash.toString(encoding: 'hex' | 'base64' | 'utf8'): string`](#hashtostringencoding-hex--base64--utf8-string)
|
| 42 |
+
- [Hasher](#hasher-1)
|
| 43 |
+
- [`createHash(): Hasher`](#createhash-hasher-1)
|
| 44 |
+
- [`createKeyed(key: Buffer): Hasher`](#createkeyedkey-buffer-hasher-1)
|
| 45 |
+
- [`createDeriveKey(context: string): Hasher`](#createderivekeycontext-string-hasher-1)
|
| 46 |
+
- [`hasher.update(data: BinaryLike): this`](#hasherupdatedata-binarylike-this-1)
|
| 47 |
+
- [`hasher.digest(encoding?: 'hex' | 'base64' | 'utf8', options?: { length: number, dispose: boolean })): Hash | string`](#hasherdigestencoding-hex--base64--utf8-options--length-number-dispose-boolean--hash--string)
|
| 48 |
+
- [`hasher.reader(options?: { dispose: boolean }): HashReader`](#hasherreaderoptions--dispose-boolean--hashreader-1)
|
| 49 |
+
- [`hasher.dispose()`](#hasherdispose-1)
|
| 50 |
+
- [HashReader](#hashreader-1)
|
| 51 |
+
- [`reader.position: bigint`](#readerposition-bigint-1)
|
| 52 |
+
- [`reader.readInto(target: Uint8Array): void`](#readerreadintotarget-uint8array-void)
|
| 53 |
+
- [`reader.read(bytes: number): Hash`](#readerreadbytes-number-hash)
|
| 54 |
+
- [`reader.toString(encoding?: string): string`](#readertostringencoding-string-string)
|
| 55 |
+
- [`reader.toArray(): Uint8Array`](#readertoarray-uint8array)
|
| 56 |
+
- [`reader.dispose()`](#readerdispose-1)
|
| 57 |
+
- [`using(disposable: IDisposable, fn: disposable => T): T`](#usingdisposable-idisposable-fn-disposable--t-t-1)
|
| 58 |
+
- [Speed](#speed)
|
| 59 |
+
- [Contributing](#contributing)
|
| 60 |
+
- [Publishing](#publishing)
|
| 61 |
+
|
| 62 |
+
## Quickstart
|
| 63 |
+
|
| 64 |
+
If you're on Node, import the module via
|
| 65 |
+
|
| 66 |
+
```js
|
| 67 |
+
const blake3 = require('blake3');
|
| 68 |
+
|
| 69 |
+
blake3.hash('foo'); // => Buffer
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
If you're in the browser, import `blake3/browser`. This includes a WebAssembly binary, so you probably want to import it asynchronously, like so:
|
| 73 |
+
|
| 74 |
+
```js
|
| 75 |
+
import('blake3/browser').then(blake3 => {
|
| 76 |
+
blake3.hash('foo'); // => Uint8Array
|
| 77 |
+
});
|
| 78 |
+
```
|
| 79 |
+
|
| 80 |
+
The API is very similar in Node.js and browsers, but Node supports and returns Buffers and a wider range of input and output encoding.
|
| 81 |
+
|
| 82 |
+
More complete example:
|
| 83 |
+
|
| 84 |
+
```js
|
| 85 |
+
const { hash, createHash } = require('blake3');
|
| 86 |
+
|
| 87 |
+
hash('some string'); // => hash a string to a uint8array
|
| 88 |
+
|
| 89 |
+
// Update incrementally (Node and Browsers):
|
| 90 |
+
const hash = createHash();
|
| 91 |
+
stream.on('data', d => hash.update(d));
|
| 92 |
+
stream.on('error', err => {
|
| 93 |
+
// hashes use unmanaged memory in WebAssembly, always free them if you don't digest()!
|
| 94 |
+
hash.dispose();
|
| 95 |
+
throw err;
|
| 96 |
+
});
|
| 97 |
+
stream.on('end', () => finishedHash(hash.digest()));
|
| 98 |
+
|
| 99 |
+
// Or, in Node, it's also a transform stream:
|
| 100 |
+
createReadStream('file.txt')
|
| 101 |
+
.pipe(createHash())
|
| 102 |
+
.on('data', hash => console.log(hash.toString('hex')));
|
| 103 |
+
```
|
| 104 |
+
|
| 105 |
+
## API
|
| 106 |
+
|
| 107 |
+
### Node.js
|
| 108 |
+
|
| 109 |
+
The Node API can be imported via `require('blake3')`.
|
| 110 |
+
|
| 111 |
+
#### `hash(data: BinaryLike, options?: { length: number }): Buffer`
|
| 112 |
+
|
| 113 |
+
Returns a hash for the given data. The data can be a string, buffer, typedarray, array buffer, or array. By default, it generates the first 32 bytes of the hash for the data, but this is configurable. It returns a Buffer.
|
| 114 |
+
|
| 115 |
+
#### `keyedHash(key: Buffer, data: BinaryLike, options?: { length: number }): Buffer`
|
| 116 |
+
|
| 117 |
+
Returns keyed a hash for the given data. The key must be exactly 32 bytes. The data can be a string, buffer, typedarray, array buffer, or array. By default, it generates the first 32 bytes of the hash for the data, but this is configurable. It returns a Buffer.
|
| 118 |
+
|
| 119 |
+
For more information, see [the blake3 docs](https://docs.rs/blake3/0.1.3/blake3/fn.keyed_hash.html).
|
| 120 |
+
|
| 121 |
+
#### `deriveKey(context: string, material: BinaryLike, options?: { length: number }): Buffer`
|
| 122 |
+
|
| 123 |
+
The key derivation function. The data can be a string, buffer, typedarray, array buffer, or array. By default, it generates the first 32 bytes of the hash for the data, but this is configurable. It returns a Buffer.
|
| 124 |
+
|
| 125 |
+
For more information, see [the blake3 docs](https://docs.rs/blake3/0.1.3/blake3/fn.derive_key.html).
|
| 126 |
+
|
| 127 |
+
#### Hasher
|
| 128 |
+
|
| 129 |
+
The hasher is a type that lets you incrementally build a hash. It's compatible with Node's crypto hash instance. For instance, it implements a transform stream, so you could do something like:
|
| 130 |
+
|
| 131 |
+
```js
|
| 132 |
+
createReadStream('file.txt')
|
| 133 |
+
.pipe(createHash())
|
| 134 |
+
.on('data', hash => console.log(hash.toString('hex')));
|
| 135 |
+
```
|
| 136 |
+
|
| 137 |
+
##### `createHash(): Hasher`
|
| 138 |
+
|
| 139 |
+
Creates a new hasher instance using the standard hash function.
|
| 140 |
+
|
| 141 |
+
##### `createKeyed(key: Buffer): Hasher`
|
| 142 |
+
|
| 143 |
+
Creates a new hasher instance for a keyed hash. For more information, see [the blake3 docs](https://docs.rs/blake3/0.1.3/blake3/fn.keyed_hash.html).
|
| 144 |
+
|
| 145 |
+
##### `createDeriveKey(context: string): Hasher`
|
| 146 |
+
|
| 147 |
+
Creates a new hasher instance for the key derivation function. For more information, see [the blake3 docs](https://docs.rs/blake3/0.1.3/blake3/fn.derive_key.html).
|
| 148 |
+
|
| 149 |
+
##### `hasher.update(data: BinaryLike): this`
|
| 150 |
+
|
| 151 |
+
Adds data to a hash. The data can be a string, buffer, typedarray, array buffer, or array. This will throw if called after `digest()` or `dispose()`.
|
| 152 |
+
|
| 153 |
+
##### `hasher.digest(encoding?: string, options?: { length: number, dispose: boolean })): Buffer | string`
|
| 154 |
+
|
| 155 |
+
Returns the hash of the data. If an `encoding` is given, a string will be returned. Otherwise, a Buffer is returned. Optionally, you can specify the requested byte length of the hash.
|
| 156 |
+
|
| 157 |
+
If `dispose: false` is given in the options, the hash will not automatically be disposed of, allowing you to continue updating it after obtaining the current reader.
|
| 158 |
+
|
| 159 |
+
##### `hasher.reader(options?: { dispose: boolean }): HashReader`
|
| 160 |
+
|
| 161 |
+
Returns a [HashReader](#HashReader) for the current hash.
|
| 162 |
+
|
| 163 |
+
If `dispose: false` is given in the options, the hash will not automatically be disposed of, allowing you to continue updating it after obtaining the current reader.
|
| 164 |
+
|
| 165 |
+
##### `hasher.dispose()`
|
| 166 |
+
|
| 167 |
+
Disposes of unmanaged resources. You should _always_ call this if you don't call `digest()` to free umanaged (WebAssembly-based) memory.
|
| 168 |
+
|
| 169 |
+
#### HashReader
|
| 170 |
+
|
| 171 |
+
The hash reader can be returned from hashing functions. Up to 2<sup>64</sup>-1 bytes of data can be read from BLAKE3 hashes; this structure lets you read those. Note that, like `hash`, this is an object which needs to be manually disposed of.
|
| 172 |
+
|
| 173 |
+
##### `reader.position: bigint`
|
| 174 |
+
|
| 175 |
+
A property which gets or sets the position of the reader in the output stream. A `RangeError` is thrown if setting this to a value less than 0 or greater than 2<sup>64</sup>-1. Note that this is a bigint, not a standard number.
|
| 176 |
+
|
| 177 |
+
```js
|
| 178 |
+
reader.position += 32n; // advance the reader 32 bytes
|
| 179 |
+
```
|
| 180 |
+
|
| 181 |
+
##### `reader.readInto(target: Buffer): void`
|
| 182 |
+
|
| 183 |
+
Reads bytes into the target array, filling it up and advancing the reader's position. A `RangeError` is thrown if reading this data puts the reader past 2<sup>64</sup>-1 bytes.
|
| 184 |
+
|
| 185 |
+
##### `reader.read(bytes: number): Buffer`
|
| 186 |
+
|
| 187 |
+
Reads and returns the given number of bytes from the reader, and advances the position. A `RangeError` is thrown if reading this data puts the reader past 2<sup>64</sup>-1 bytes.
|
| 188 |
+
|
| 189 |
+
##### `reader.toString([encoding]): string`
|
| 190 |
+
|
| 191 |
+
Converts first 32 bytes of the hash to a string with the given encoding. Defaults to hex encoding.
|
| 192 |
+
|
| 193 |
+
##### `reader.toBuffer(): Buffer`
|
| 194 |
+
|
| 195 |
+
Converts first 32 bytes of the hash to a Buffer.
|
| 196 |
+
|
| 197 |
+
##### `reader.dispose()`
|
| 198 |
+
|
| 199 |
+
Disposes of unmanaged resources. You should _always_ call this to free umanaged (WebAssembly-based) memory, or you application will leak memory.
|
| 200 |
+
|
| 201 |
+
#### `using(disposable: IDisposable, fn: disposable => T): T`
|
| 202 |
+
|
| 203 |
+
A helper method that takes a disposable, and automatically calls the dispose method when the function returns, or the promise returned from the function is settled.
|
| 204 |
+
|
| 205 |
+
```js
|
| 206 |
+
// read and auto-dispose the first 64 bytes
|
| 207 |
+
const first64Bytes = using(hash.reader(), reader => reader.toBuffer(64));
|
| 208 |
+
|
| 209 |
+
// you can also return promises/use async methods:
|
| 210 |
+
using(hash.reader(), async reader => {
|
| 211 |
+
do {
|
| 212 |
+
await send(reader.read(64));
|
| 213 |
+
} while (needsMoreData());
|
| 214 |
+
});
|
| 215 |
+
```
|
| 216 |
+
|
| 217 |
+
### Browser
|
| 218 |
+
|
| 219 |
+
The browser API can be imported via `import('blake3/browser')`, which works well with Webpack.
|
| 220 |
+
|
| 221 |
+
If you aren't using a bundler or using a more "pure" bundler like Parcel, you can import `blake3/browser-async` which exports a function to asynchronously load the WebAssembly code and resolves to the package contents.
|
| 222 |
+
|
| 223 |
+
```js
|
| 224 |
+
import load from 'blake3/browser-async';
|
| 225 |
+
|
| 226 |
+
load().then(blake3 => {
|
| 227 |
+
console.log(blake3.hash('hello world'));
|
| 228 |
+
});
|
| 229 |
+
```
|
| 230 |
+
|
| 231 |
+
#### `hash(data: BinaryLike, options?: { length: number }): Hash`
|
| 232 |
+
|
| 233 |
+
Returns a hash for the given data. The data can be a string, typedarray, array buffer, or array. By default, it generates the first 32 bytes of the hash for the data, but this is configurable. It returns a [Hash](#Hash) instance.
|
| 234 |
+
|
| 235 |
+
#### `keyedHash(key: Buffer, data: BinaryLike, options?: { length: number }): Hash`
|
| 236 |
+
|
| 237 |
+
Returns keyed a hash for the given data. The key must be exactly 32 bytes. The data can be a string, typedarray, array buffer, or array. By default, it generates the first 32 bytes of the hash for the data, but this is configurable. It returns a [Hash](#Hash) instance.
|
| 238 |
+
|
| 239 |
+
For more information, see [the blake3 docs](https://docs.rs/blake3/0.1.3/blake3/fn.keyed_hash.html).
|
| 240 |
+
|
| 241 |
+
#### `deriveKey(context: string, material: BinaryLike, options?: { length: number }): Hash`
|
| 242 |
+
|
| 243 |
+
The key derivation function. The data can be a string, typedarray, array buffer, or array. By default, it generates the first 32 bytes of the hash for the data, but this is configurable. It returns a [Hash](#Hash) instance.
|
| 244 |
+
|
| 245 |
+
For more information, see [the blake3 docs](https://docs.rs/blake3/0.1.3/blake3/fn.derive_key.html).
|
| 246 |
+
|
| 247 |
+
#### `Hash`
|
| 248 |
+
|
| 249 |
+
A Hash is the type returned from hash functions and the hasher in the browser. It's a `Uint8Array` with a few additional helper methods.
|
| 250 |
+
|
| 251 |
+
##### `hash.equals(other: Uint8Array)`
|
| 252 |
+
|
| 253 |
+
Returns whether this hash equals the other hash, via a constant-time equality check.
|
| 254 |
+
|
| 255 |
+
##### `hash.toString(encoding: 'hex' | 'base64' | 'utf8'): string`
|
| 256 |
+
|
| 257 |
+
#### Hasher
|
| 258 |
+
|
| 259 |
+
The hasher is a type that lets you incrementally build a hash. For instance, you can hash a `fetch`ed page like:
|
| 260 |
+
|
| 261 |
+
```js
|
| 262 |
+
const res = await fetch('https://example.com');
|
| 263 |
+
const body = await res.body;
|
| 264 |
+
|
| 265 |
+
const hasher = blake3.createHash();
|
| 266 |
+
const reader = body.getReader();
|
| 267 |
+
|
| 268 |
+
while (true) {
|
| 269 |
+
const { done, value } = await reader.read();
|
| 270 |
+
if (done) {
|
| 271 |
+
break;
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
hasher.update(value);
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
console.log('Hash of', res.url, 'is', hasher.digest('hex'));
|
| 278 |
+
```
|
| 279 |
+
|
| 280 |
+
Converts the hash to a string with the given encoding.
|
| 281 |
+
|
| 282 |
+
##### `createHash(): Hasher`
|
| 283 |
+
|
| 284 |
+
Creates a new hasher instance using the standard hash function.
|
| 285 |
+
|
| 286 |
+
##### `createKeyed(key: Buffer): Hasher`
|
| 287 |
+
|
| 288 |
+
Creates a new hasher instance for a keyed hash. For more information, see [the blake3 docs](https://docs.rs/blake3/0.1.3/blake3/fn.keyed_hash.html).
|
| 289 |
+
|
| 290 |
+
##### `createDeriveKey(context: string): Hasher`
|
| 291 |
+
|
| 292 |
+
Creates a new hasher instance for the key derivation function. For more information, see [the blake3 docs](https://docs.rs/blake3/0.1.3/blake3/fn.derive_key.html).
|
| 293 |
+
|
| 294 |
+
##### `hasher.update(data: BinaryLike): this`
|
| 295 |
+
|
| 296 |
+
Adds data to a hash. The data can be a string, buffer, typedarray, array buffer, or array. This will throw if called after `digest()` or `dispose()`.
|
| 297 |
+
|
| 298 |
+
##### `hasher.digest(encoding?: 'hex' | 'base64' | 'utf8', options?: { length: number, dispose: boolean })): Hash | string`
|
| 299 |
+
|
| 300 |
+
Returns the hash of the data. If an `encoding` is given, a string will be returned. Otherwise, a [Hash](#hash) is returned. Optionally, you can specify the requested byte length of the hash.
|
| 301 |
+
|
| 302 |
+
If `dispose: false` is given in the options, the hash will not automatically be disposed of, allowing you to continue updating it after obtaining the current reader.
|
| 303 |
+
|
| 304 |
+
##### `hasher.reader(options?: { dispose: boolean }): HashReader`
|
| 305 |
+
|
| 306 |
+
Returns a [HashReader](#HashReader) for the current hash.
|
| 307 |
+
|
| 308 |
+
If `dispose: false` is given in the options, the hash will not automatically be disposed of, allowing you to continue updating it after obtaining the current reader.
|
| 309 |
+
|
| 310 |
+
##### `hasher.dispose()`
|
| 311 |
+
|
| 312 |
+
Disposes of unmanaged resources. You should _always_ call this if you don't call `digest()` to free umanaged (WebAssembly-based) memory.
|
| 313 |
+
|
| 314 |
+
#### HashReader
|
| 315 |
+
|
| 316 |
+
The hash reader can be returned from hashing functions. Up to 2<sup>64</sup>-1 bytes of data can be read from BLAKE3 hashes; this structure lets you read those. Note that, like `hash`, this is an object which needs to be manually disposed of.
|
| 317 |
+
|
| 318 |
+
##### `reader.position: bigint`
|
| 319 |
+
|
| 320 |
+
A property which gets or sets the position of the reader in the output stream. A `RangeError` is thrown if setting this to a value less than 0 or greater than 2<sup>64</sup>-1. Note that this is a bigint, not a standard number.
|
| 321 |
+
|
| 322 |
+
```js
|
| 323 |
+
reader.position += 32n; // advance the reader 32 bytes
|
| 324 |
+
```
|
| 325 |
+
|
| 326 |
+
##### `reader.readInto(target: Uint8Array): void`
|
| 327 |
+
|
| 328 |
+
Reads bytes into the target array, filling it up and advancing the reader's position. A `RangeError` is thrown if reading this data puts the reader past 2<sup>64</sup>-1 bytes.
|
| 329 |
+
|
| 330 |
+
##### `reader.read(bytes: number): Hash`
|
| 331 |
+
|
| 332 |
+
Reads and returns the given number of bytes from the reader, and advances the position. A `RangeError` is thrown if reading this data puts the reader past 2<sup>64</sup>-1 bytes.
|
| 333 |
+
|
| 334 |
+
##### `reader.toString(encoding?: string): string`
|
| 335 |
+
|
| 336 |
+
Converts first 32 bytes of the hash to a string with the given encoding. Defaults to hex encoding.
|
| 337 |
+
|
| 338 |
+
##### `reader.toArray(): Uint8Array`
|
| 339 |
+
|
| 340 |
+
Converts first 32 bytes of the hash to an array.
|
| 341 |
+
|
| 342 |
+
##### `reader.dispose()`
|
| 343 |
+
|
| 344 |
+
Disposes of unmanaged resources. You should _always_ call this to free umanaged (WebAssembly-based) memory, or you application will leak memory.
|
| 345 |
+
|
| 346 |
+
#### `using(disposable: IDisposable, fn: disposable => T): T`
|
| 347 |
+
|
| 348 |
+
A helper method that takes a disposable, and automatically calls the dispose method when the function returns, or the promise returned from the function is settled.
|
| 349 |
+
|
| 350 |
+
```js
|
| 351 |
+
// read and auto-dispose the first 64 bytes
|
| 352 |
+
const first64Bytes = using(hash.reader(), reader => reader.toArray(64));
|
| 353 |
+
|
| 354 |
+
// you can also return promises/use async methods:
|
| 355 |
+
using(hash.reader(), async reader => {
|
| 356 |
+
do {
|
| 357 |
+
await send(reader.read(64));
|
| 358 |
+
} while (needsMoreData());
|
| 359 |
+
});
|
| 360 |
+
```
|
| 361 |
+
|
| 362 |
+
## Speed
|
| 363 |
+
|
| 364 |
+
> Native Node.js bindings are a work in progress.
|
| 365 |
+
|
| 366 |
+
You can run benchmarks by installing `npm install -g @c4312/matcha`, then running `matcha benchmark.js`. These are the results running on Node 12 on my MacBook. Blake3 is significantly faster than Node's built-in hashing.
|
| 367 |
+
|
| 368 |
+
276,000 ops/sec > 64B#md5 (4,240x)
|
| 369 |
+
263,000 ops/sec > 64B#sha1 (4,040x)
|
| 370 |
+
271,000 ops/sec > 64B#sha256 (4,160x)
|
| 371 |
+
1,040,000 ops/sec > 64B#blake3 wasm (15,900x)
|
| 372 |
+
625,000 ops/sec > 64B#blake3 native (9,590x)
|
| 373 |
+
|
| 374 |
+
9,900 ops/sec > 64KB#md5 (152x)
|
| 375 |
+
13,900 ops/sec > 64KB#sha1 (214x)
|
| 376 |
+
6,470 ops/sec > 64KB#sha256 (99.2x)
|
| 377 |
+
6,410 ops/sec > 64KB#blake3 wasm (98.4x)
|
| 378 |
+
48,900 ops/sec > 64KB#blake3 native (750x)
|
| 379 |
+
|
| 380 |
+
106 ops/sec > 6MB#md5 (1.63x)
|
| 381 |
+
150 ops/sec > 6MB#sha1 (2.3x)
|
| 382 |
+
69.2 ops/sec > 6MB#sha256 (1.06x)
|
| 383 |
+
65.2 ops/sec > 6MB#blake3 wasm (1x)
|
| 384 |
+
502 ops/sec > 6MB#blake3 native (7.7x)
|
| 385 |
+
|
| 386 |
+
## Contributing
|
| 387 |
+
|
| 388 |
+
This build is a little esoteric due to the mixing of languages. We use a `Makefile` to coodinate things.
|
| 389 |
+
|
| 390 |
+
To get set up, you'll want to open the repository in VS Code. Make sure you have [Remote Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) installed, and then accept the "Reopen in Container" prompt when opening the folder. This will get the environment set up with everything you need. Then, run `make prepare` to install local dependencies.
|
| 391 |
+
|
| 392 |
+
Finally, `make` will create a build for you; you can run `make MODE=release` for a production release, and certainly should if you want to [benchmark it](#speed).
|
| 393 |
+
|
| 394 |
+
- Rust code is compiled from `src/lib.rs` to `pkg/browser` and `pkg/node`
|
| 395 |
+
- TypeScript code is compiled from `ts/*.ts` into `dist`
|
| 396 |
+
|
| 397 |
+
### Publishing
|
| 398 |
+
|
| 399 |
+
In case I get hit by a bus or get other contributors, these are the steps for publishing:
|
| 400 |
+
|
| 401 |
+
1. Get all your code ready to go in master, pushed up to Github.
|
| 402 |
+
2. Run `make prepare-binaries`. This will update the branch `generate-binary`, which kicks off a build via Github actions to create `.node` binaries for every relevant Node.js version.
|
| 403 |
+
3. When the build completes, it'll generate a zip file of artifacts. Download those.
|
| 404 |
+
4. Back on master, run `npm version <type>` to update the version in git. `git push --tags`.
|
| 405 |
+
5. On Github, upload the contents of the artifacts folder to the release for the newly tagged version.
|
| 406 |
+
6. Run `npm publish`.
|
bunx-1000-wrangler@latest/node_modules/cookie/README.md
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# cookie
|
| 2 |
+
|
| 3 |
+
[![NPM Version][npm-version-image]][npm-url]
|
| 4 |
+
[![NPM Downloads][npm-downloads-image]][npm-url]
|
| 5 |
+
[![Build Status][ci-image]][ci-url]
|
| 6 |
+
[![Coverage Status][coverage-image]][coverage-url]
|
| 7 |
+
|
| 8 |
+
Basic HTTP cookie parser and serializer for HTTP servers.
|
| 9 |
+
|
| 10 |
+
## Installation
|
| 11 |
+
|
| 12 |
+
```sh
|
| 13 |
+
$ npm install cookie
|
| 14 |
+
```
|
| 15 |
+
|
| 16 |
+
## API
|
| 17 |
+
|
| 18 |
+
```js
|
| 19 |
+
const cookie = require("cookie");
|
| 20 |
+
// import * as cookie from 'cookie';
|
| 21 |
+
```
|
| 22 |
+
|
| 23 |
+
### cookie.parseCookie(str, options)
|
| 24 |
+
|
| 25 |
+
Parse an HTTP `Cookie` header string and return an [object](#cookie-object) of all cookie name-value pairs.
|
| 26 |
+
The `str` argument is the string representing a `Cookie` header value and `options` is an
|
| 27 |
+
optional object containing additional parsing options.
|
| 28 |
+
|
| 29 |
+
```js
|
| 30 |
+
const cookieObject = cookie.parseCookie("foo=bar; equation=E%3Dmc%5E2");
|
| 31 |
+
// { foo: 'bar', equation: 'E=mc^2' }
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
#### Options
|
| 35 |
+
|
| 36 |
+
- `decode` Specifies the function to decode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1). Defaults to [`decodeURIComponent`](#encode-and-decode).
|
| 37 |
+
|
| 38 |
+
### cookie.stringifyCookie(cookieObj, options)
|
| 39 |
+
|
| 40 |
+
Stringifies a [cookie object](#cookie-object) into an HTTP `Cookie` header.
|
| 41 |
+
|
| 42 |
+
```js
|
| 43 |
+
const cookieHeader = cookie.stringify({ a: "foo", b: "bar" });
|
| 44 |
+
// a=foo; b=bar
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
#### Options
|
| 48 |
+
|
| 49 |
+
- `encode` Specifies the function to encode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1). Defaults to [`encodeURIComponent`](#encode-and-decode).
|
| 50 |
+
|
| 51 |
+
### cookie.parseSetCookie(str, options)
|
| 52 |
+
|
| 53 |
+
Parse an HTTP `Set-Cookie` header string and return an [object](#set-cookie-object) of the options.
|
| 54 |
+
|
| 55 |
+
```js
|
| 56 |
+
const setCookieObject = cookie.parseSetCookie("foo=bar; httpOnly");
|
| 57 |
+
// { name: "foo", value: "bar", httpOnly: true }
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
**Note:** Cookie follows the specification and ignores invalid attributes, but does not attempt to normalize or modify any attributes as a browser might. For example:
|
| 61 |
+
|
| 62 |
+
```js
|
| 63 |
+
cookie.parseSetCookie(
|
| 64 |
+
"session=abc; max-age=1.5; expires=invalid; custom=value; domain=example.com",
|
| 65 |
+
);
|
| 66 |
+
// { name: "session", value: "abc", domain: "example.com" }
|
| 67 |
+
```
|
| 68 |
+
|
| 69 |
+
#### Options
|
| 70 |
+
|
| 71 |
+
- `decode` Specifies the function to decode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1). Defaults to [`decodeURIComponent`](#encode-and-decode).
|
| 72 |
+
|
| 73 |
+
### cookie.stringifySetCookie(setCookieObj, options)
|
| 74 |
+
|
| 75 |
+
Stringifies a [`Set-Cookie` object](#set-cookie-object) into a `Set-Cookie` header string.
|
| 76 |
+
|
| 77 |
+
```js
|
| 78 |
+
const setCookieHeader = cookie.stringifySetCookie({
|
| 79 |
+
name: "foo",
|
| 80 |
+
value: "bar",
|
| 81 |
+
});
|
| 82 |
+
// foo=bar
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
#### Options
|
| 86 |
+
|
| 87 |
+
- `encode` Specifies the function to encode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1). Defaults to [`encodeURIComponent`](#encode-and-decode).
|
| 88 |
+
|
| 89 |
+
## Cookie object
|
| 90 |
+
|
| 91 |
+
The cookie object represents all cookie name-value pairs in a `Cookie` header, where `{ name: "value" }` is used for `name=value`.
|
| 92 |
+
|
| 93 |
+
## `Set-Cookie` object
|
| 94 |
+
|
| 95 |
+
The `Set-Cookie` object represents all the options in a `Set-Cookie` header.
|
| 96 |
+
|
| 97 |
+
### name
|
| 98 |
+
|
| 99 |
+
The name of the cookie.
|
| 100 |
+
|
| 101 |
+
### value
|
| 102 |
+
|
| 103 |
+
The value of a cookie after it has been [decoded](#encode-and-decode).
|
| 104 |
+
|
| 105 |
+
### maxAge
|
| 106 |
+
|
| 107 |
+
Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.2).
|
| 108 |
+
|
| 109 |
+
The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and
|
| 110 |
+
`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
|
| 111 |
+
so if both are set, they should point to the same date and time.
|
| 112 |
+
|
| 113 |
+
### expires
|
| 114 |
+
|
| 115 |
+
Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.1).
|
| 116 |
+
When no expiration is set, clients consider this a "non-persistent cookie" and delete it when the current session is over.
|
| 117 |
+
|
| 118 |
+
The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and
|
| 119 |
+
`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
|
| 120 |
+
so if both are set, they should point to the same date and time.
|
| 121 |
+
|
| 122 |
+
### domain
|
| 123 |
+
|
| 124 |
+
Specifies the value for the [`Domain` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.3).
|
| 125 |
+
When no domain is set, clients consider the cookie to apply to the current domain only.
|
| 126 |
+
|
| 127 |
+
### path
|
| 128 |
+
|
| 129 |
+
Specifies the value for the [`Path` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.4).
|
| 130 |
+
When no path is set, the path is considered the ["default path"](https://tools.ietf.org/html/rfc6265#section-5.1.4).
|
| 131 |
+
|
| 132 |
+
### httpOnly
|
| 133 |
+
|
| 134 |
+
Enables the [`HttpOnly` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.6).
|
| 135 |
+
When enabled, clients will not allow client-side JavaScript to see the cookie in `document.cookie`.
|
| 136 |
+
|
| 137 |
+
### secure
|
| 138 |
+
|
| 139 |
+
Enables the [`Secure` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.5).
|
| 140 |
+
When enabled, clients will only send the cookie back if the browser has an HTTPS connection.
|
| 141 |
+
|
| 142 |
+
### partitioned
|
| 143 |
+
|
| 144 |
+
Enables the [`Partitioned` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/).
|
| 145 |
+
When enabled, clients will only send the cookie back when the current domain _and_ top-level domain matches.
|
| 146 |
+
|
| 147 |
+
This is an attribute that has not yet been fully standardized, and may change in the future.
|
| 148 |
+
This also means clients may ignore this attribute until they understand it. More information
|
| 149 |
+
about can be found in [the proposal](https://github.com/privacycg/CHIPS).
|
| 150 |
+
|
| 151 |
+
### priority
|
| 152 |
+
|
| 153 |
+
Specifies the value for the [`Priority` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).
|
| 154 |
+
|
| 155 |
+
- `'low'` will set the `Priority` attribute to `Low`.
|
| 156 |
+
- `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.
|
| 157 |
+
- `'high'` will set the `Priority` attribute to `High`.
|
| 158 |
+
|
| 159 |
+
More information about priority levels can be found in [the specification](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).
|
| 160 |
+
|
| 161 |
+
### sameSite
|
| 162 |
+
|
| 163 |
+
Specifies the value for the [`SameSite` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).
|
| 164 |
+
|
| 165 |
+
- `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
| 166 |
+
- `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
|
| 167 |
+
- `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
|
| 168 |
+
- `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
| 169 |
+
|
| 170 |
+
More information about enforcement levels can be found in [the specification](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).
|
| 171 |
+
|
| 172 |
+
## Encode and decode
|
| 173 |
+
|
| 174 |
+
Cookie accepts `encode` or `decode` options for processing a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1).
|
| 175 |
+
Since the value of a cookie has a limited character set (and must be a simple string), these functions are used to transform values into strings suitable for a cookies value.
|
| 176 |
+
|
| 177 |
+
The default `encode` function is the global `encodeURIComponent`.
|
| 178 |
+
|
| 179 |
+
The default `decode` function is the global `decodeURIComponent`, wrapped in a `try..catch`. If an error
|
| 180 |
+
is thrown it will return the cookie's original value. If you provide your own encode/decode
|
| 181 |
+
scheme you must ensure errors are appropriately handled.
|
| 182 |
+
|
| 183 |
+
## Example
|
| 184 |
+
|
| 185 |
+
The following example uses this module in conjunction with the Node.js core HTTP server
|
| 186 |
+
to prompt a user for their name and display it back on future visits.
|
| 187 |
+
|
| 188 |
+
```js
|
| 189 |
+
var cookie = require("cookie");
|
| 190 |
+
var escapeHtml = require("escape-html");
|
| 191 |
+
var http = require("http");
|
| 192 |
+
var url = require("url");
|
| 193 |
+
|
| 194 |
+
function onRequest(req, res) {
|
| 195 |
+
// Parse the query string
|
| 196 |
+
var query = url.parse(req.url, true, true).query;
|
| 197 |
+
|
| 198 |
+
if (query && query.name) {
|
| 199 |
+
// Set a new cookie with the name
|
| 200 |
+
res.setHeader(
|
| 201 |
+
"Set-Cookie",
|
| 202 |
+
cookie.stringifySetCookie({
|
| 203 |
+
name: "name",
|
| 204 |
+
value: String(query.name),
|
| 205 |
+
httpOnly: true,
|
| 206 |
+
maxAge: 60 * 60 * 24 * 7, // 1 week
|
| 207 |
+
}),
|
| 208 |
+
);
|
| 209 |
+
|
| 210 |
+
// Redirect back after setting cookie
|
| 211 |
+
res.statusCode = 302;
|
| 212 |
+
res.setHeader("Location", req.headers.referer || "/");
|
| 213 |
+
res.end();
|
| 214 |
+
return;
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
// Parse the cookies on the request
|
| 218 |
+
var cookies = cookie.parseCookie(req.headers.cookie || "");
|
| 219 |
+
|
| 220 |
+
// Get the visitor name set in the cookie
|
| 221 |
+
var name = cookies.name;
|
| 222 |
+
|
| 223 |
+
res.setHeader("Content-Type", "text/html; charset=UTF-8");
|
| 224 |
+
|
| 225 |
+
if (name) {
|
| 226 |
+
res.write("<p>Welcome back, <b>" + escapeHtml(name) + "</b>!</p>");
|
| 227 |
+
} else {
|
| 228 |
+
res.write("<p>Hello, new visitor!</p>");
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
res.write('<form method="GET">');
|
| 232 |
+
res.write(
|
| 233 |
+
'<input placeholder="enter your name" name="name"> <input type="submit" value="Set Name">',
|
| 234 |
+
);
|
| 235 |
+
res.end("</form>");
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
http.createServer(onRequest).listen(3000);
|
| 239 |
+
```
|
| 240 |
+
|
| 241 |
+
## Testing
|
| 242 |
+
|
| 243 |
+
```sh
|
| 244 |
+
npm test
|
| 245 |
+
```
|
| 246 |
+
|
| 247 |
+
## Benchmark
|
| 248 |
+
|
| 249 |
+
```sh
|
| 250 |
+
npm run bench
|
| 251 |
+
```
|
| 252 |
+
|
| 253 |
+
```
|
| 254 |
+
name hz min max mean p75 p99 p995 p999 rme samples
|
| 255 |
+
· simple 8,566,313.09 0.0000 0.3694 0.0001 0.0001 0.0002 0.0002 0.0003 ±0.64% 4283157 fastest
|
| 256 |
+
· decode 3,834,348.85 0.0001 0.2465 0.0003 0.0003 0.0003 0.0004 0.0006 ±0.38% 1917175
|
| 257 |
+
· unquote 8,315,355.96 0.0000 0.3824 0.0001 0.0001 0.0002 0.0002 0.0003 ±0.72% 4157880
|
| 258 |
+
· duplicates 1,944,765.97 0.0004 0.2959 0.0005 0.0005 0.0006 0.0006 0.0008 ±0.24% 972384
|
| 259 |
+
· 10 cookies 675,345.67 0.0012 0.4328 0.0015 0.0015 0.0019 0.0020 0.0058 ±0.75% 337673
|
| 260 |
+
· 100 cookies 61,040.71 0.0152 0.4092 0.0164 0.0160 0.0196 0.0228 0.2260 ±0.71% 30521 slowest
|
| 261 |
+
✓ parse top-sites (15) 22945ms
|
| 262 |
+
name hz min max mean p75 p99 p995 p999 rme samples
|
| 263 |
+
· parse accounts.google.com 7,164,349.17 0.0000 0.0929 0.0001 0.0002 0.0002 0.0002 0.0003 ±0.09% 3582184
|
| 264 |
+
· parse apple.com 7,817,686.84 0.0000 0.6048 0.0001 0.0001 0.0002 0.0002 0.0003 ±1.05% 3908844
|
| 265 |
+
· parse cloudflare.com 7,189,841.70 0.0000 0.0390 0.0001 0.0002 0.0002 0.0002 0.0003 ±0.06% 3594921
|
| 266 |
+
· parse docs.google.com 7,051,765.61 0.0000 0.0296 0.0001 0.0002 0.0002 0.0002 0.0003 ±0.06% 3525883
|
| 267 |
+
· parse drive.google.com 7,349,104.77 0.0000 0.0368 0.0001 0.0001 0.0002 0.0002 0.0003 ±0.05% 3674553
|
| 268 |
+
· parse en.wikipedia.org 1,929,909.49 0.0004 0.3598 0.0005 0.0005 0.0007 0.0007 0.0012 ±0.16% 964955
|
| 269 |
+
· parse linkedin.com 2,225,658.01 0.0003 0.0595 0.0004 0.0005 0.0005 0.0005 0.0006 ±0.06% 1112830
|
| 270 |
+
· parse maps.google.com 4,423,511.68 0.0001 0.0942 0.0002 0.0003 0.0003 0.0003 0.0005 ±0.08% 2211756
|
| 271 |
+
· parse microsoft.com 3,387,601.88 0.0002 0.0725 0.0003 0.0003 0.0004 0.0004 0.0005 ±0.09% 1693801
|
| 272 |
+
· parse play.google.com 7,375,980.86 0.0000 0.1994 0.0001 0.0001 0.0002 0.0002 0.0003 ±0.12% 3687991
|
| 273 |
+
· parse support.google.com 4,912,267.94 0.0001 2.8958 0.0002 0.0002 0.0003 0.0003 0.0005 ±1.28% 2456134
|
| 274 |
+
· parse www.google.com 3,443,035.87 0.0002 0.2783 0.0003 0.0003 0.0004 0.0004 0.0007 ±0.51% 1721518
|
| 275 |
+
· parse youtu.be 1,910,492.87 0.0004 0.3490 0.0005 0.0005 0.0007 0.0007 0.0011 ±0.46% 955247
|
| 276 |
+
· parse youtube.com 1,895,082.62 0.0004 0.7454 0.0005 0.0005 0.0006 0.0007 0.0013 ±0.64% 947542 slowest
|
| 277 |
+
· parse example.com 21,582,835.27 0.0000 0.1095 0.0000 0.0000 0.0001 0.0001 0.0001 ±0.13% 10791418
|
| 278 |
+
```
|
| 279 |
+
|
| 280 |
+
## References
|
| 281 |
+
|
| 282 |
+
- [RFC 6265: HTTP State Management Mechanism](https://tools.ietf.org/html/rfc6265)
|
| 283 |
+
- [Same-site Cookies](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7)
|
| 284 |
+
|
| 285 |
+
## License
|
| 286 |
+
|
| 287 |
+
[MIT](LICENSE)
|
| 288 |
+
|
| 289 |
+
[ci-image]: https://img.shields.io/github/actions/workflow/status/jshttp/cookie/ci.yml
|
| 290 |
+
[ci-url]: https://github.com/jshttp/cookie/actions/workflows/ci.yml?query=branch%3Amaster
|
| 291 |
+
[coverage-image]: https://img.shields.io/codecov/c/github/jshttp/cookie/master
|
| 292 |
+
[coverage-url]: https://app.codecov.io/gh/jshttp/cookie
|
| 293 |
+
[npm-downloads-image]: https://img.shields.io/npm/dm/cookie
|
| 294 |
+
[npm-url]: https://npmjs.org/package/cookie
|
| 295 |
+
[npm-version-image]: https://img.shields.io/npm/v/cookie
|
bunx-1000-wrangler@latest/node_modules/detect-libc/README.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# detect-libc
|
| 2 |
+
|
| 3 |
+
Node.js module to detect details of the C standard library (libc)
|
| 4 |
+
implementation provided by a given Linux system.
|
| 5 |
+
|
| 6 |
+
Currently supports detection of GNU glibc and MUSL libc.
|
| 7 |
+
|
| 8 |
+
Provides asychronous and synchronous functions for the
|
| 9 |
+
family (e.g. `glibc`, `musl`) and version (e.g. `1.23`, `1.2.3`).
|
| 10 |
+
|
| 11 |
+
The version numbers of libc implementations
|
| 12 |
+
are not guaranteed to be semver-compliant.
|
| 13 |
+
|
| 14 |
+
For previous v1.x releases, please see the
|
| 15 |
+
[v1](https://github.com/lovell/detect-libc/tree/v1) branch.
|
| 16 |
+
|
| 17 |
+
## Install
|
| 18 |
+
|
| 19 |
+
```sh
|
| 20 |
+
npm install detect-libc
|
| 21 |
+
```
|
| 22 |
+
|
| 23 |
+
## API
|
| 24 |
+
|
| 25 |
+
### GLIBC
|
| 26 |
+
|
| 27 |
+
```ts
|
| 28 |
+
const GLIBC: string = 'glibc';
|
| 29 |
+
```
|
| 30 |
+
|
| 31 |
+
A String constant containing the value `glibc`.
|
| 32 |
+
|
| 33 |
+
### MUSL
|
| 34 |
+
|
| 35 |
+
```ts
|
| 36 |
+
const MUSL: string = 'musl';
|
| 37 |
+
```
|
| 38 |
+
|
| 39 |
+
A String constant containing the value `musl`.
|
| 40 |
+
|
| 41 |
+
### family
|
| 42 |
+
|
| 43 |
+
```ts
|
| 44 |
+
function family(): Promise<string | null>;
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
Resolves asychronously with:
|
| 48 |
+
|
| 49 |
+
* `glibc` or `musl` when the libc family can be determined
|
| 50 |
+
* `null` when the libc family cannot be determined
|
| 51 |
+
* `null` when run on a non-Linux platform
|
| 52 |
+
|
| 53 |
+
```js
|
| 54 |
+
const { family, GLIBC, MUSL } = require('detect-libc');
|
| 55 |
+
|
| 56 |
+
switch (await family()) {
|
| 57 |
+
case GLIBC: ...
|
| 58 |
+
case MUSL: ...
|
| 59 |
+
case null: ...
|
| 60 |
+
}
|
| 61 |
+
```
|
| 62 |
+
|
| 63 |
+
### familySync
|
| 64 |
+
|
| 65 |
+
```ts
|
| 66 |
+
function familySync(): string | null;
|
| 67 |
+
```
|
| 68 |
+
|
| 69 |
+
Synchronous version of `family()`.
|
| 70 |
+
|
| 71 |
+
```js
|
| 72 |
+
const { familySync, GLIBC, MUSL } = require('detect-libc');
|
| 73 |
+
|
| 74 |
+
switch (familySync()) {
|
| 75 |
+
case GLIBC: ...
|
| 76 |
+
case MUSL: ...
|
| 77 |
+
case null: ...
|
| 78 |
+
}
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
### version
|
| 82 |
+
|
| 83 |
+
```ts
|
| 84 |
+
function version(): Promise<string | null>;
|
| 85 |
+
```
|
| 86 |
+
|
| 87 |
+
Resolves asychronously with:
|
| 88 |
+
|
| 89 |
+
* The version when it can be determined
|
| 90 |
+
* `null` when the libc family cannot be determined
|
| 91 |
+
* `null` when run on a non-Linux platform
|
| 92 |
+
|
| 93 |
+
```js
|
| 94 |
+
const { version } = require('detect-libc');
|
| 95 |
+
|
| 96 |
+
const v = await version();
|
| 97 |
+
if (v) {
|
| 98 |
+
const [major, minor, patch] = v.split('.');
|
| 99 |
+
}
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
### versionSync
|
| 103 |
+
|
| 104 |
+
```ts
|
| 105 |
+
function versionSync(): string | null;
|
| 106 |
+
```
|
| 107 |
+
|
| 108 |
+
Synchronous version of `version()`.
|
| 109 |
+
|
| 110 |
+
```js
|
| 111 |
+
const { versionSync } = require('detect-libc');
|
| 112 |
+
|
| 113 |
+
const v = versionSync();
|
| 114 |
+
if (v) {
|
| 115 |
+
const [major, minor, patch] = v.split('.');
|
| 116 |
+
}
|
| 117 |
+
```
|
| 118 |
+
|
| 119 |
+
### isNonGlibcLinux
|
| 120 |
+
|
| 121 |
+
```ts
|
| 122 |
+
function isNonGlibcLinux(): Promise<boolean>;
|
| 123 |
+
```
|
| 124 |
+
|
| 125 |
+
Resolves asychronously with:
|
| 126 |
+
|
| 127 |
+
* `false` when the libc family is `glibc`
|
| 128 |
+
* `true` when the libc family is not `glibc`
|
| 129 |
+
* `false` when run on a non-Linux platform
|
| 130 |
+
|
| 131 |
+
```js
|
| 132 |
+
const { isNonGlibcLinux } = require('detect-libc');
|
| 133 |
+
|
| 134 |
+
if (await isNonGlibcLinux()) { ... }
|
| 135 |
+
```
|
| 136 |
+
|
| 137 |
+
### isNonGlibcLinuxSync
|
| 138 |
+
|
| 139 |
+
```ts
|
| 140 |
+
function isNonGlibcLinuxSync(): boolean;
|
| 141 |
+
```
|
| 142 |
+
|
| 143 |
+
Synchronous version of `isNonGlibcLinux()`.
|
| 144 |
+
|
| 145 |
+
```js
|
| 146 |
+
const { isNonGlibcLinuxSync } = require('detect-libc');
|
| 147 |
+
|
| 148 |
+
if (isNonGlibcLinuxSync()) { ... }
|
| 149 |
+
```
|
| 150 |
+
|
| 151 |
+
## Licensing
|
| 152 |
+
|
| 153 |
+
Copyright 2017 Lovell Fuller and others.
|
| 154 |
+
|
| 155 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 156 |
+
you may not use this file except in compliance with the License.
|
| 157 |
+
You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0.html)
|
| 158 |
+
|
| 159 |
+
Unless required by applicable law or agreed to in writing, software
|
| 160 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 161 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 162 |
+
See the License for the specific language governing permissions and
|
| 163 |
+
limitations under the License.
|
bunx-1000-wrangler@latest/node_modules/error-stack-parser-es/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# error-stack-parser-es
|
| 2 |
+
|
| 3 |
+
[](https://www.npmjs.com/package/error-stack-parser-es)
|
| 4 |
+
|
| 5 |
+
A port of [stacktracejs/error-stack-parser](https://github.com/stacktracejs/error-stack-parser), rewrite with TypeScript and ES Modules.
|
| 6 |
+
|
| 7 |
+
## Usage
|
| 8 |
+
|
| 9 |
+
```ts
|
| 10 |
+
import { parse } from 'error-stack-parser-es'
|
| 11 |
+
|
| 12 |
+
const stacktrace = parse(new Error('BOOM!'))
|
| 13 |
+
```
|
| 14 |
+
|
| 15 |
+
Refer to [stacktracejs/error-stack-parser](https://github.com/stacktracejs/error-stack-parser) for more details.
|
| 16 |
+
|
| 17 |
+
### Lite API
|
| 18 |
+
|
| 19 |
+
Additionally, this fork added a lite version of the API representation for the stack frames. You can import it from `error-stack-parser-es/lite`. For example, `line` and `col` instead of `lineNumber` and `columnNumber`.
|
| 20 |
+
|
| 21 |
+
```ts
|
| 22 |
+
import { parse } from 'error-stack-parser-es/lite'
|
| 23 |
+
|
| 24 |
+
const stacktrace = parse(new Error('BOOM!'))
|
| 25 |
+
// [{ file: 'file.js', name: 'method', line: 1, col: 2}]
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
It also allows you to parse directly from a stacktrace string (which does not support Opera stacktrace format).
|
| 29 |
+
|
| 30 |
+
```ts
|
| 31 |
+
import { parseStack } from 'error-stack-parser-es/lite'
|
| 32 |
+
|
| 33 |
+
const stacktrace = parseStack('Error\n at method (file.js:1:2)')
|
| 34 |
+
// [{ file: 'file.js', name: 'method', line: 1, col: 2}]
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
## License
|
| 38 |
+
|
| 39 |
+
[MIT](./LICENSE) License © 2023-PRESENT [Anthony Fu](https://github.com/antfu)
|
| 40 |
+
[MIT](./LICENSE) License © 2017 [Eric Wendelin](https://github.com/eriwen)
|
bunx-1000-wrangler@latest/node_modules/esbuild/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2020 Evan Wallace
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
bunx-1000-wrangler@latest/node_modules/esbuild/README.md
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# esbuild
|
| 2 |
+
|
| 3 |
+
This is a JavaScript bundler and minifier. See https://github.com/evanw/esbuild and the [JavaScript API documentation](https://esbuild.github.io/api/) for details.
|
bunx-1000-wrangler@latest/node_modules/kleur/readme.md
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<div align="center">
|
| 2 |
+
<img src="shots/logo.png" alt="kleur" height="120" />
|
| 3 |
+
</div>
|
| 4 |
+
|
| 5 |
+
<div align="center">
|
| 6 |
+
<a href="https://npmjs.org/package/kleur">
|
| 7 |
+
<img src="https://badgen.now.sh/npm/v/kleur" alt="version" />
|
| 8 |
+
</a>
|
| 9 |
+
<a href="https://github.com/lukeed/kleur/actions?query=workflow%3ACI">
|
| 10 |
+
<img src="https://github.com/lukeed/kleur/workflows/CI/badge.svg?event=push" alt="CI" />
|
| 11 |
+
</a>
|
| 12 |
+
<a href="https://npmjs.org/package/kleur">
|
| 13 |
+
<img src="https://badgen.now.sh/npm/dm/kleur" alt="downloads" />
|
| 14 |
+
</a>
|
| 15 |
+
<a href="https://packagephobia.now.sh/result?p=kleur">
|
| 16 |
+
<img src="https://packagephobia.now.sh/badge?p=kleur" alt="install size" />
|
| 17 |
+
</a>
|
| 18 |
+
</div>
|
| 19 |
+
|
| 20 |
+
<div align="center">The fastest Node.js library for formatting terminal text with ANSI colors~!</div>
|
| 21 |
+
|
| 22 |
+
## Features
|
| 23 |
+
|
| 24 |
+
* No dependencies
|
| 25 |
+
* Super [lightweight](#load-time) & [performant](#performance)
|
| 26 |
+
* Supports [nested](#nested-methods) & [chained](#chained-methods) colors
|
| 27 |
+
* No `String.prototype` modifications
|
| 28 |
+
* Conditional [color support](#conditional-support)
|
| 29 |
+
* [Fully treeshakable](#individual-colors)
|
| 30 |
+
* Familiar [API](#api)
|
| 31 |
+
|
| 32 |
+
---
|
| 33 |
+
|
| 34 |
+
As of `v3.0` the Chalk-style syntax (magical getter) is no longer used.<br>Please visit [History](#history) for migration paths supporting that syntax.
|
| 35 |
+
|
| 36 |
+
---
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
## Install
|
| 40 |
+
|
| 41 |
+
```
|
| 42 |
+
$ npm install --save kleur
|
| 43 |
+
```
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
## Usage
|
| 47 |
+
|
| 48 |
+
```js
|
| 49 |
+
import kleur from 'kleur';
|
| 50 |
+
|
| 51 |
+
// basic usage
|
| 52 |
+
kleur.red('red text');
|
| 53 |
+
|
| 54 |
+
// chained methods
|
| 55 |
+
kleur.blue().bold().underline('howdy partner');
|
| 56 |
+
|
| 57 |
+
// nested methods
|
| 58 |
+
kleur.bold(`${ white().bgRed('[ERROR]') } ${ kleur.red().italic('Something happened')}`);
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
### Chained Methods
|
| 62 |
+
|
| 63 |
+
```js
|
| 64 |
+
const { bold, green } = require('kleur');
|
| 65 |
+
|
| 66 |
+
console.log(bold().red('this is a bold red message'));
|
| 67 |
+
console.log(bold().italic('this is a bold italicized message'));
|
| 68 |
+
console.log(bold().yellow().bgRed().italic('this is a bold yellow italicized message'));
|
| 69 |
+
console.log(green().bold().underline('this is a bold green underlined message'));
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
<img src="shots/1.png" width="300" />
|
| 73 |
+
|
| 74 |
+
### Nested Methods
|
| 75 |
+
|
| 76 |
+
```js
|
| 77 |
+
const { yellow, red, cyan } = require('kleur');
|
| 78 |
+
|
| 79 |
+
console.log(yellow(`foo ${red().bold('red')} bar ${cyan('cyan')} baz`));
|
| 80 |
+
console.log(yellow('foo ' + red().bold('red') + ' bar ' + cyan('cyan') + ' baz'));
|
| 81 |
+
```
|
| 82 |
+
|
| 83 |
+
<img src="shots/2.png" width="300" />
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
### Conditional Support
|
| 87 |
+
|
| 88 |
+
Toggle color support as needed; `kleur` includes simple auto-detection which may not cover all cases.
|
| 89 |
+
|
| 90 |
+
> **Note:** Both `kleur` and `kleur/colors` share the same detection logic.
|
| 91 |
+
|
| 92 |
+
```js
|
| 93 |
+
import kleur from 'kleur';
|
| 94 |
+
|
| 95 |
+
// manually disable
|
| 96 |
+
kleur.enabled = false;
|
| 97 |
+
|
| 98 |
+
// or use another library to detect support
|
| 99 |
+
kleur.enabled = require('color-support').level > 0;
|
| 100 |
+
|
| 101 |
+
console.log(kleur.red('I will only be colored red if the terminal supports colors'));
|
| 102 |
+
```
|
| 103 |
+
|
| 104 |
+
> **Important:** <br>Colors will be disabled automatically in non [TTY contexts](https://nodejs.org/api/process.html#process_a_note_on_process_i_o). For example, spawning another process or piping output into another process will disable colorization automatically. To force colors in your piped output, you may do so with the `FORCE_COLOR=1` environment variable:
|
| 105 |
+
|
| 106 |
+
```sh
|
| 107 |
+
$ node app.js #=> COLORS
|
| 108 |
+
$ node app.js > log.txt #=> NO COLORS
|
| 109 |
+
$ FORCE_COLOR=1 node app.js > log.txt #=> COLORS
|
| 110 |
+
$ FORCE_COLOR=0 node app.js > log.txt #=> NO COLORS
|
| 111 |
+
```
|
| 112 |
+
|
| 113 |
+
## API
|
| 114 |
+
|
| 115 |
+
Any `kleur` method returns a `String` when invoked with input; otherwise chaining is expected.
|
| 116 |
+
|
| 117 |
+
> It's up to the developer to pass the output to destinations like `console.log`, `process.stdout.write`, etc.
|
| 118 |
+
|
| 119 |
+
The methods below are grouped by type for legibility purposes only. They each can be [chained](#chained-methods) or [nested](#nested-methods) with one another.
|
| 120 |
+
|
| 121 |
+
***Colors:***
|
| 122 |
+
> black — red — green — yellow — blue — magenta — cyan — white — gray — grey
|
| 123 |
+
|
| 124 |
+
***Backgrounds:***
|
| 125 |
+
> bgBlack — bgRed — bgGreen — bgYellow — bgBlue — bgMagenta — bgCyan — bgWhite
|
| 126 |
+
|
| 127 |
+
***Modifiers:***
|
| 128 |
+
> reset — bold — dim — italic* — underline — inverse — hidden — strikethrough*
|
| 129 |
+
|
| 130 |
+
<sup>* <em>Not widely supported</em></sup>
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
## Individual Colors
|
| 134 |
+
|
| 135 |
+
When you only need a few colors, it doesn't make sense to import _all_ of `kleur` because, as small as it is, `kleur` is not treeshakeable, and so most of its code will be doing nothing. In order to fix this, you can import from the `kleur/colors` submodule which _fully_ supports tree-shaking.
|
| 136 |
+
|
| 137 |
+
The caveat with this approach is that color functions **are not** chainable~!<br>Each function receives and colorizes its input. You may combine colors, backgrounds, and modifiers by nesting function calls within other functions.
|
| 138 |
+
|
| 139 |
+
```js
|
| 140 |
+
// or: import * as kleur from 'kleur/colors';
|
| 141 |
+
import { red, underline, bgWhite } from 'kleur/colors';
|
| 142 |
+
|
| 143 |
+
red('red text');
|
| 144 |
+
//~> kleur.red('red text');
|
| 145 |
+
|
| 146 |
+
underline(red('red underlined text'));
|
| 147 |
+
//~> kleur.underline().red('red underlined text');
|
| 148 |
+
|
| 149 |
+
bgWhite(underline(red('red underlined text w/ white background')));
|
| 150 |
+
//~> kleur.bgWhite().underline().red('red underlined text w/ white background');
|
| 151 |
+
```
|
| 152 |
+
|
| 153 |
+
> **Note:** All the same [colors, backgrounds, and modifiers](#api) are available.
|
| 154 |
+
|
| 155 |
+
***Conditional Support***
|
| 156 |
+
|
| 157 |
+
The `kleur/colors` submodule also allows you to toggle color support, as needed.<br>
|
| 158 |
+
It includes the same initial assumptions as `kleur`, in an attempt to have colors enabled by default.
|
| 159 |
+
|
| 160 |
+
Unlike `kleur`, this setting exists as `kleur.$.enabled` instead of `kleur.enabled`:
|
| 161 |
+
|
| 162 |
+
```js
|
| 163 |
+
import * as kleur from 'kleur/colors';
|
| 164 |
+
// or: import { $, red } from 'kleur/colors';
|
| 165 |
+
|
| 166 |
+
// manually disabled
|
| 167 |
+
kleur.$.enabled = false;
|
| 168 |
+
|
| 169 |
+
// or use another library to detect support
|
| 170 |
+
kleur.$.enabled = require('color-support').level > 0;
|
| 171 |
+
|
| 172 |
+
console.log(red('I will only be colored red if the terminal supports colors'));
|
| 173 |
+
```
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
## Benchmarks
|
| 177 |
+
|
| 178 |
+
> Using Node v10.13.0
|
| 179 |
+
|
| 180 |
+
### Load time
|
| 181 |
+
|
| 182 |
+
```
|
| 183 |
+
chalk :: 5.303ms
|
| 184 |
+
kleur :: 0.488ms
|
| 185 |
+
kleur/colors :: 0.369ms
|
| 186 |
+
ansi-colors :: 1.504ms
|
| 187 |
+
```
|
| 188 |
+
|
| 189 |
+
### Performance
|
| 190 |
+
|
| 191 |
+
```
|
| 192 |
+
# All Colors
|
| 193 |
+
ansi-colors x 177,625 ops/sec ±1.47% (92 runs sampled)
|
| 194 |
+
chalk x 611,907 ops/sec ±0.20% (92 runs sampled)
|
| 195 |
+
kleur x 742,509 ops/sec ±1.47% (93 runs sampled)
|
| 196 |
+
kleur/colors x 881,742 ops/sec ±0.19% (98 runs sampled)
|
| 197 |
+
|
| 198 |
+
# Stacked colors
|
| 199 |
+
ansi-colors x 23,331 ops/sec ±1.81% (94 runs sampled)
|
| 200 |
+
chalk x 337,178 ops/sec ±0.20% (98 runs sampled)
|
| 201 |
+
kleur x 78,299 ops/sec ±1.01% (97 runs sampled)
|
| 202 |
+
kleur/colors x 104,431 ops/sec ±0.22% (97 runs sampled)
|
| 203 |
+
|
| 204 |
+
# Nested colors
|
| 205 |
+
ansi-colors x 67,181 ops/sec ±1.15% (92 runs sampled)
|
| 206 |
+
chalk x 116,361 ops/sec ±0.63% (94 runs sampled)
|
| 207 |
+
kleur x 139,514 ops/sec ±0.76% (95 runs sampled)
|
| 208 |
+
kleur/colors x 145,716 ops/sec ±0.97% (97 runs sampled)
|
| 209 |
+
```
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
## History
|
| 213 |
+
|
| 214 |
+
This project originally forked [`ansi-colors`](https://github.com/doowb/ansi-colors).
|
| 215 |
+
|
| 216 |
+
Beginning with `kleur@3.0`, the Chalk-style syntax (magical getter) has been replaced with function calls per key:
|
| 217 |
+
|
| 218 |
+
```js
|
| 219 |
+
// Old:
|
| 220 |
+
c.red.bold.underline('old');
|
| 221 |
+
|
| 222 |
+
// New:
|
| 223 |
+
c.red().bold().underline('new');
|
| 224 |
+
```
|
| 225 |
+
> <sup><em>As I work more with Rust, the newer syntax feels so much better & more natural!</em></sup>
|
| 226 |
+
|
| 227 |
+
If you prefer the old syntax, you may migrate to `ansi-colors` or newer `chalk` releases.<br>Versions below `kleur@3.0` have been officially deprecated.
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
## License
|
| 231 |
+
|
| 232 |
+
MIT © [Luke Edwards](https://lukeed.com)
|
bunx-1000-wrangler@latest/node_modules/miniflare/README.md
ADDED
|
@@ -0,0 +1,957 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🔥 Miniflare
|
| 2 |
+
|
| 3 |
+
**Miniflare** is a simulator for developing and testing
|
| 4 |
+
[**Cloudflare Workers**](https://workers.cloudflare.com/), powered by
|
| 5 |
+
[`workerd`](https://github.com/cloudflare/workerd).
|
| 6 |
+
|
| 7 |
+
> :warning: Miniflare is a lower level API designed for tools creators, for
|
| 8 |
+
> locally developing Workers use tools built on top of Miniflare such
|
| 9 |
+
> as [Wrangler](../wrangler/README.md) or the [Cloudflare Vite plugin](../vite-plugin-cloudflare/README.md).
|
| 10 |
+
|
| 11 |
+
## Quick Start
|
| 12 |
+
|
| 13 |
+
```shell
|
| 14 |
+
$ npm install miniflare --save-dev
|
| 15 |
+
```
|
| 16 |
+
|
| 17 |
+
```js
|
| 18 |
+
import { Miniflare } from "miniflare";
|
| 19 |
+
|
| 20 |
+
// Create a new Miniflare instance, starting a workerd server
|
| 21 |
+
const mf = new Miniflare({
|
| 22 |
+
script: `addEventListener("fetch", (event) => {
|
| 23 |
+
event.respondWith(new Response("Hello Miniflare!"));
|
| 24 |
+
})`,
|
| 25 |
+
});
|
| 26 |
+
|
| 27 |
+
// Send a request to the workerd server, the host is ignored
|
| 28 |
+
const response = await mf.dispatchFetch("http://localhost:8787/");
|
| 29 |
+
console.log(await response.text()); // Hello Miniflare!
|
| 30 |
+
|
| 31 |
+
// Cleanup Miniflare, shutting down the workerd server
|
| 32 |
+
await mf.dispose();
|
| 33 |
+
```
|
| 34 |
+
|
| 35 |
+
## API
|
| 36 |
+
|
| 37 |
+
### `type Awaitable<T>`
|
| 38 |
+
|
| 39 |
+
`T | Promise<T>`
|
| 40 |
+
|
| 41 |
+
Represents a value that can be `await`ed. Used in callback types to allow
|
| 42 |
+
`Promise`s to be returned if necessary.
|
| 43 |
+
|
| 44 |
+
### `type Json`
|
| 45 |
+
|
| 46 |
+
`string | number | boolean | null | Record<string, Json> | Json[]`
|
| 47 |
+
|
| 48 |
+
Represents a JSON-serialisable value.
|
| 49 |
+
|
| 50 |
+
### `type ModuleRuleType`
|
| 51 |
+
|
| 52 |
+
`"ESModule" | "CommonJS" | "Text" | "Data" | "CompiledWasm"`
|
| 53 |
+
|
| 54 |
+
Represents how a module's contents should be interpreted.
|
| 55 |
+
|
| 56 |
+
- `"ESModule"`: interpret as
|
| 57 |
+
[ECMAScript module](https://tc39.es/ecma262/#sec-modules)
|
| 58 |
+
- `"CommonJS"`: interpret as
|
| 59 |
+
[CommonJS module](https://nodejs.org/api/modules.html#modules-commonjs-modules)
|
| 60 |
+
- `"Text"`: interpret as UTF8-encoded data, expose in runtime with
|
| 61 |
+
`string`-typed `default` export
|
| 62 |
+
- `"Data"`: interpret as arbitrary binary data, expose in runtime with
|
| 63 |
+
`ArrayBuffer`-typed `default` export
|
| 64 |
+
- `"CompiledWasm"`: interpret as binary WebAssembly module data, expose in
|
| 65 |
+
runtime with `WebAssembly.Module`-typed `default` export
|
| 66 |
+
|
| 67 |
+
### `interface ModuleDefinition`
|
| 68 |
+
|
| 69 |
+
Represents a manually defined module.
|
| 70 |
+
|
| 71 |
+
- `type: ModuleRuleType`
|
| 72 |
+
|
| 73 |
+
How this module's contents should be interpreted.
|
| 74 |
+
|
| 75 |
+
- `path: string`
|
| 76 |
+
|
| 77 |
+
Path of this module. The module's "name" will be obtained by converting this
|
| 78 |
+
to a relative path. The original path will be used to read `contents` if it's
|
| 79 |
+
omitted.
|
| 80 |
+
|
| 81 |
+
- `contents?: string | Uint8Array`
|
| 82 |
+
|
| 83 |
+
Contents override for this module. Binary data should be passed as
|
| 84 |
+
`Uint8Array`s. If omitted, will be read from `path`.
|
| 85 |
+
|
| 86 |
+
### `interface ModuleRule`
|
| 87 |
+
|
| 88 |
+
Represents a rule for identifying the `ModuleRuleType` of automatically located
|
| 89 |
+
modules.
|
| 90 |
+
|
| 91 |
+
- `type: ModuleRuleType`
|
| 92 |
+
|
| 93 |
+
How to interpret modules that match the `include` patterns.
|
| 94 |
+
|
| 95 |
+
- `include: string[]`
|
| 96 |
+
|
| 97 |
+
Glob patterns to match located module paths against (e.g. `["**/*.txt"]`).
|
| 98 |
+
|
| 99 |
+
- `fallthrough?: boolean`
|
| 100 |
+
|
| 101 |
+
If `true`, ignore any further rules of this `type`. This is useful for
|
| 102 |
+
disabling the built-in `ESModule` and `CommonJS` rules that match `*.mjs` and
|
| 103 |
+
`*.js`/`*.cjs` files respectively.
|
| 104 |
+
|
| 105 |
+
### `type Persistence`
|
| 106 |
+
|
| 107 |
+
`boolean | string | undefined`
|
| 108 |
+
|
| 109 |
+
Represents where data should be persisted, if anywhere.
|
| 110 |
+
|
| 111 |
+
- If this is `undefined`, it defaults to `true` if `defaultPersistRoot` is set
|
| 112 |
+
or otherwise defaults to `false`.
|
| 113 |
+
- If this is`false`, data will be stored in-memory and only
|
| 114 |
+
persist between `Miniflare#setOptions()` calls, not restarts nor
|
| 115 |
+
`new Miniflare` instances.
|
| 116 |
+
- If this is `true`, data will be stored in a subdirectory of the `defaultPersistRoot` path if `defaultPersistRoot` is set
|
| 117 |
+
or otherwise will be stored in a subdirectory of `$PWD/.mf`.
|
| 118 |
+
- If this looks like a URL, then:
|
| 119 |
+
- If the protocol is `memory:`, data will be stored in-memory as above.
|
| 120 |
+
- If the protocol is `file:`, data will be stored on the file-system, in the
|
| 121 |
+
specified directory (e.g. `file:///path/to/directory`).
|
| 122 |
+
- Otherwise, if this is just a regular `string`, data will be stored on the
|
| 123 |
+
file-system, using the value as the directory path.
|
| 124 |
+
|
| 125 |
+
### `enum LogLevel`
|
| 126 |
+
|
| 127 |
+
`NONE, ERROR, WARN, INFO, DEBUG, VERBOSE`
|
| 128 |
+
|
| 129 |
+
Controls which messages Miniflare logs. All messages at or below the selected
|
| 130 |
+
level will be logged.
|
| 131 |
+
|
| 132 |
+
### `interface LogOptions`
|
| 133 |
+
|
| 134 |
+
- `prefix?: string`
|
| 135 |
+
|
| 136 |
+
String to add before the level prefix when logging messages. Defaults to `mf`.
|
| 137 |
+
|
| 138 |
+
- `suffix?: string`
|
| 139 |
+
|
| 140 |
+
String to add after the level prefix when logging messages.
|
| 141 |
+
|
| 142 |
+
### `class Log`
|
| 143 |
+
|
| 144 |
+
- `constructor(level?: LogLevel, opts?: LogOptions)`
|
| 145 |
+
|
| 146 |
+
Creates a new logger that logs all messages at or below the specified level to
|
| 147 |
+
the `console`.
|
| 148 |
+
|
| 149 |
+
- `error(message: Error)`
|
| 150 |
+
|
| 151 |
+
Logs a message at the `ERROR` level. If the constructed log `level` is less
|
| 152 |
+
than `ERROR`, `throw`s the `message` instead.
|
| 153 |
+
|
| 154 |
+
- `warn(message: string)`
|
| 155 |
+
|
| 156 |
+
Logs a message at the `WARN` level.
|
| 157 |
+
|
| 158 |
+
- `info(message: string)`
|
| 159 |
+
|
| 160 |
+
Logs a message at the `INFO` level.
|
| 161 |
+
|
| 162 |
+
- `debug(message: string)`
|
| 163 |
+
|
| 164 |
+
Logs a message at the `DEBUG` level.
|
| 165 |
+
|
| 166 |
+
- `verbose(message: string)`
|
| 167 |
+
|
| 168 |
+
Logs a message at the `VERBOSE` level.
|
| 169 |
+
|
| 170 |
+
### `class NoOpLog extends Log`
|
| 171 |
+
|
| 172 |
+
- `constructor()`
|
| 173 |
+
|
| 174 |
+
Creates a new logger that logs nothing to the `console`, and always `throw`s
|
| 175 |
+
`message`s logged at the `ERROR` level.
|
| 176 |
+
|
| 177 |
+
### `interface QueueProducerOptions`
|
| 178 |
+
|
| 179 |
+
- `queueName: string`
|
| 180 |
+
|
| 181 |
+
The name of the queue where messages will be sent by the producer.
|
| 182 |
+
|
| 183 |
+
- `deliveryDelay?: number`
|
| 184 |
+
|
| 185 |
+
Default number of seconds to delay the delivery of messages to consumers.
|
| 186 |
+
Value between `0` (no delay) and `42300` (12 hours).
|
| 187 |
+
|
| 188 |
+
### `interface QueueConsumerOptions`
|
| 189 |
+
|
| 190 |
+
- `maxBatchSize?: number`
|
| 191 |
+
|
| 192 |
+
Maximum number of messages allowed in each batch. Defaults to `5`.
|
| 193 |
+
|
| 194 |
+
- `maxBatchTimeout?: number`
|
| 195 |
+
|
| 196 |
+
Maximum number of seconds to wait for a full batch. If a message is sent, and
|
| 197 |
+
this timeout elapses, a partial batch will be dispatched. Defaults to `1`.
|
| 198 |
+
|
| 199 |
+
- `maxRetries?: number`
|
| 200 |
+
|
| 201 |
+
Maximum number of times to retry dispatching a message, if handling it throws,
|
| 202 |
+
or it is explicitly retried. Defaults to `2`.
|
| 203 |
+
|
| 204 |
+
- `deadLetterQueue?: string`
|
| 205 |
+
|
| 206 |
+
Name of another Queue to send a message on if it fails processing after
|
| 207 |
+
`maxRetries`. If this isn't specified, failed messages will be discarded.
|
| 208 |
+
|
| 209 |
+
- `retryDelay?: number`
|
| 210 |
+
|
| 211 |
+
Number of seconds to delay the (re-)delivery of messages by default. Value
|
| 212 |
+
between `0` (no delay) and `42300` (12 hours).
|
| 213 |
+
|
| 214 |
+
### `interface WorkerOptions`
|
| 215 |
+
|
| 216 |
+
Options for an individual Worker/"nanoservice". All bindings are accessible on
|
| 217 |
+
the global scope in service-worker format Workers, or via the 2nd `env`
|
| 218 |
+
parameter in module format Workers.
|
| 219 |
+
|
| 220 |
+
### `interface WorkflowOptions`
|
| 221 |
+
|
| 222 |
+
- `name: string`
|
| 223 |
+
|
| 224 |
+
The name of the Workflow.
|
| 225 |
+
|
| 226 |
+
- `className: string`
|
| 227 |
+
|
| 228 |
+
The name of the class exported from the Worker that implements the `WorkflowEntrypoint`.
|
| 229 |
+
|
| 230 |
+
- `scriptName?`: string
|
| 231 |
+
|
| 232 |
+
The name of the script that includes the `WorkflowEntrypoint`. This is optional because it defaults to the current script if not set.
|
| 233 |
+
|
| 234 |
+
#### Core
|
| 235 |
+
|
| 236 |
+
- `name?: string`
|
| 237 |
+
|
| 238 |
+
Unique name for this worker. Only required if multiple `workers` are
|
| 239 |
+
specified.
|
| 240 |
+
|
| 241 |
+
- `rootPath?: string`
|
| 242 |
+
|
| 243 |
+
Path against which all other path options for this Worker are resolved
|
| 244 |
+
relative to. This path is itself resolved relative to the `rootPath` from
|
| 245 |
+
`SharedOptions` if multiple workers are specified. Defaults to the current
|
| 246 |
+
working directory.
|
| 247 |
+
|
| 248 |
+
- `script?: string`
|
| 249 |
+
|
| 250 |
+
JavaScript code for this worker. If this is a service worker format Worker, it
|
| 251 |
+
must not have any imports. If this is a modules format Worker, it must not
|
| 252 |
+
have any _npm_ imports, and `modules: true` must be set. If it does have
|
| 253 |
+
imports, `scriptPath` must also be set so Miniflare knows where to resolve
|
| 254 |
+
them relative to.
|
| 255 |
+
|
| 256 |
+
- `scriptPath?: string`
|
| 257 |
+
|
| 258 |
+
Path of JavaScript entrypoint. If this is a service worker format Worker, it
|
| 259 |
+
must not have any imports. If this is a modules format Worker, it must not
|
| 260 |
+
have any _npm_ imports, and `modules: true` must be set.
|
| 261 |
+
|
| 262 |
+
- `modules?: boolean | ModuleDefinition[]`
|
| 263 |
+
- If `true`, Miniflare will treat `script`/`scriptPath` as an ES Module and
|
| 264 |
+
automatically locate transitive module dependencies according to
|
| 265 |
+
`modulesRules`. Note that automatic location is not perfect: if the
|
| 266 |
+
specifier to a dynamic `import()` or `require()` is not a string literal, an
|
| 267 |
+
exception will be thrown.
|
| 268 |
+
|
| 269 |
+
- If set to an array, modules can be defined manually. Transitive dependencies
|
| 270 |
+
must also be defined. Note the first module must be the entrypoint and have
|
| 271 |
+
type `"ESModule"`.
|
| 272 |
+
|
| 273 |
+
- `modulesRoot?: string`
|
| 274 |
+
|
| 275 |
+
If `modules` is set to `true` or an array, modules' "name"s will be their
|
| 276 |
+
`path`s relative to this value. This ensures file paths in stack traces are
|
| 277 |
+
correct.
|
| 278 |
+
|
| 279 |
+
<!-- prettier-ignore-start -->
|
| 280 |
+
<!-- (for disabling `;` insertion in `js` code block) -->
|
| 281 |
+
|
| 282 |
+
- `modulesRules?: ModuleRule[]`
|
| 283 |
+
|
| 284 |
+
Rules for identifying the `ModuleRuleType` of automatically located modules
|
| 285 |
+
when `modules: true` is set. Note the following default rules are always
|
| 286 |
+
included at the end:
|
| 287 |
+
|
| 288 |
+
```js
|
| 289 |
+
[
|
| 290 |
+
{ type: "ESModule", include: ["**/*.mjs"] },
|
| 291 |
+
{ type: "CommonJS", include: ["**/*.js", "**/*.cjs"] },
|
| 292 |
+
]
|
| 293 |
+
```
|
| 294 |
+
|
| 295 |
+
> If `script` and `scriptPath` are set, and `modules` is set to an array,
|
| 296 |
+
> `modules` takes priority for a Worker's code, followed by `script`, then
|
| 297 |
+
> `scriptPath`.
|
| 298 |
+
|
| 299 |
+
<!-- prettier-ignore-end -->
|
| 300 |
+
|
| 301 |
+
- `compatibilityDate?: string`
|
| 302 |
+
|
| 303 |
+
[Compatibility date](https://developers.cloudflare.com/workers/platform/compatibility-dates/)
|
| 304 |
+
to use for this Worker. Defaults to a date far in the past.
|
| 305 |
+
|
| 306 |
+
- `compatibilityFlags?: string[]`
|
| 307 |
+
|
| 308 |
+
[Compatibility flags](https://developers.cloudflare.com/workers/platform/compatibility-dates/)
|
| 309 |
+
to use for this Worker.
|
| 310 |
+
|
| 311 |
+
- `bindings?: Record<string, Json>`
|
| 312 |
+
|
| 313 |
+
Record mapping binding name to arbitrary JSON-serialisable values to inject as
|
| 314 |
+
bindings into this Worker.
|
| 315 |
+
|
| 316 |
+
- `wasmBindings?: Record<string, string>`
|
| 317 |
+
|
| 318 |
+
Record mapping binding name to paths containing binary WebAssembly module data
|
| 319 |
+
to inject as `WebAssembly.Module` bindings into this Worker.
|
| 320 |
+
|
| 321 |
+
- `textBlobBindings?: Record<string, string>`
|
| 322 |
+
|
| 323 |
+
Record mapping binding name to paths containing UTF8-encoded data to inject as
|
| 324 |
+
`string` bindings into this Worker.
|
| 325 |
+
|
| 326 |
+
- `dataBlobBindings?: Record<string, string>`
|
| 327 |
+
|
| 328 |
+
Record mapping binding name to paths containing arbitrary binary data to
|
| 329 |
+
inject as `ArrayBuffer` bindings into this Worker.
|
| 330 |
+
|
| 331 |
+
- `serviceBindings?: Record<string, string | typeof kCurrentWorker | { name: string | typeof kCurrentWorker, entrypoint?: string } | { network: Network } | { external: ExternalServer } | { disk: DiskDirectory } | { node: (req: http.IncomingMessage, res: http.ServerResponse, miniflare: Miniflare) => Awaitable<void> } | (request: Request, miniflare: Miniflare) => Awaitable<Response>>`
|
| 332 |
+
|
| 333 |
+
Record mapping binding name to service designators to inject as
|
| 334 |
+
`{ fetch: typeof fetch }`
|
| 335 |
+
[service bindings](https://developers.cloudflare.com/workers/platform/bindings/about-service-bindings/)
|
| 336 |
+
into this Worker.
|
| 337 |
+
- If the designator is a `string`, requests will be dispatched to the Worker
|
| 338 |
+
with that `name`.
|
| 339 |
+
- If the designator is `(await import("miniflare")).kCurrentWorker`, requests
|
| 340 |
+
will be dispatched to the Worker defining the binding.
|
| 341 |
+
- If the designator is an object of the form `{ name: ..., entrypoint: ... }`,
|
| 342 |
+
requests will be dispatched to the entrypoint named `entrypoint` in the
|
| 343 |
+
Worker named `name`. The `entrypoint` defaults to `default`, meaning
|
| 344 |
+
`{ name: "a" }` is the same as `"a"`. If `name` is
|
| 345 |
+
`(await import("miniflare")).kCurrentWorker`, requests will be dispatched to
|
| 346 |
+
the Worker defining the binding.
|
| 347 |
+
- If the designator is an object of the form `{ network: { ... } }`, where
|
| 348 |
+
`network` is a
|
| 349 |
+
[`workerd` `Network` struct](https://github.com/cloudflare/workerd/blob/bdbd6075c7c53948050c52d22f2dfa37bf376253/src/workerd/server/workerd.capnp#L555-L598),
|
| 350 |
+
requests will be dispatched according to the `fetch`ed URL.
|
| 351 |
+
- If the designator is an object of the form `{ external: { ... } }` where
|
| 352 |
+
`external` is a
|
| 353 |
+
[`workerd` `ExternalServer` struct](https://github.com/cloudflare/workerd/blob/bdbd6075c7c53948050c52d22f2dfa37bf376253/src/workerd/server/workerd.capnp#L504-L553),
|
| 354 |
+
requests will be dispatched to the specified remote server.
|
| 355 |
+
- If the designator is an object of the form `{ disk: { ... } }` where `disk`
|
| 356 |
+
is a
|
| 357 |
+
[`workerd` `DiskDirectory` struct](https://github.com/cloudflare/workerd/blob/bdbd6075c7c53948050c52d22f2dfa37bf376253/src/workerd/server/workerd.capnp#L600-L643),
|
| 358 |
+
requests will be dispatched to an HTTP service backed by an on-disk
|
| 359 |
+
directory.
|
| 360 |
+
- If the designator is an object of the form `{ node: (req: http.IncomingMessage, res: http.ServerResponse, miniflare: Miniflare) => Awaitable<void> }`, requests will be dispatched to your custom Node handler. This allows you to access data and functions defined in Node.js from your Worker using Node.js `req` and `res` objects. Note, `miniflare` will be the `Miniflare` instance dispatching the request.
|
| 361 |
+
- If the designator is a function with the signature `(request: Request, miniflare: Miniflare) => Response`, requests will be dispatched to your custom
|
| 362 |
+
fetch handler. This allows you to access data and functions defined in Node.js
|
| 363 |
+
from your Worker using fetch `Request` and `Response` objects. Note, `miniflare` will be the `Miniflare` instance
|
| 364 |
+
dispatching the request.
|
| 365 |
+
|
| 366 |
+
<!--prettier-ignore-start-->
|
| 367 |
+
|
| 368 |
+
- `wrappedBindings?: Record<string, string | { scriptName: string, entrypoint?: string, bindings?: Record<string, Json> }>`
|
| 369 |
+
|
| 370 |
+
Record mapping binding name to designators to inject as
|
| 371 |
+
[wrapped bindings](https://github.com/cloudflare/workerd/blob/bfcef2d850514c569c039cb84c43bc046af4ffb9/src/workerd/server/workerd.capnp#L469-L487) into this Worker.
|
| 372 |
+
Wrapped bindings allow custom bindings to be written as JavaScript functions
|
| 373 |
+
accepting an `env` parameter of "inner bindings" and returning the value to
|
| 374 |
+
bind. A `string` designator is equivalent to `{ scriptName: <string> }`.
|
| 375 |
+
`scriptName`'s bindings will be used as "inner bindings". JSON `bindings` in
|
| 376 |
+
the `designator` also become "inner bindings" and will override any of
|
| 377 |
+
`scriptName` bindings with the same name. The Worker named `scriptName`...
|
| 378 |
+
|
| 379 |
+
- Must define a single `ESModule` as its source, using
|
| 380 |
+
`{ modules: true, script: "..." }`, `{ modules: true, scriptPath: "..." }`,
|
| 381 |
+
or `{ modules: [...] }`
|
| 382 |
+
- Must provide the function to use for the wrapped binding as an `entrypoint`
|
| 383 |
+
named export or a default export if `entrypoint` is omitted
|
| 384 |
+
- Must not be the first/entrypoint worker
|
| 385 |
+
- Must not be bound to with service or Durable Object bindings
|
| 386 |
+
- Must not define `compatibilityDate` or `compatibilityFlags`
|
| 387 |
+
- Must not define `outboundService`
|
| 388 |
+
- Must not directly or indirectly have a wrapped binding to itself
|
| 389 |
+
- Must not be used as an argument to `Miniflare#getWorker()`
|
| 390 |
+
|
| 391 |
+
<details>
|
| 392 |
+
<summary><b>Wrapped Bindings Example</b></summary>
|
| 393 |
+
|
| 394 |
+
```ts
|
| 395 |
+
import { Miniflare } from "miniflare";
|
| 396 |
+
const store = new Map<string, string>();
|
| 397 |
+
const mf = new Miniflare({
|
| 398 |
+
workers: [
|
| 399 |
+
{
|
| 400 |
+
wrappedBindings: {
|
| 401 |
+
MINI_KV: {
|
| 402 |
+
scriptName: "mini-kv", // Use Worker named `mini-kv` for implementation
|
| 403 |
+
bindings: { NAMESPACE: "ns" }, // Override `NAMESPACE` inner binding
|
| 404 |
+
},
|
| 405 |
+
},
|
| 406 |
+
modules: true,
|
| 407 |
+
script: `export default {
|
| 408 |
+
async fetch(request, env, ctx) {
|
| 409 |
+
// Example usage of wrapped binding
|
| 410 |
+
await env.MINI_KV.set("key", "value");
|
| 411 |
+
return new Response(await env.MINI_KV.get("key"));
|
| 412 |
+
}
|
| 413 |
+
}`,
|
| 414 |
+
},
|
| 415 |
+
{
|
| 416 |
+
name: "mini-kv",
|
| 417 |
+
serviceBindings: {
|
| 418 |
+
// Function-valued service binding for accessing Node.js state
|
| 419 |
+
async STORE(request) {
|
| 420 |
+
const { pathname } = new URL(request.url);
|
| 421 |
+
const key = pathname.substring(1);
|
| 422 |
+
if (request.method === "GET") {
|
| 423 |
+
const value = store.get(key);
|
| 424 |
+
const status = value === undefined ? 404 : 200;
|
| 425 |
+
return new Response(value ?? null, { status });
|
| 426 |
+
} else if (request.method === "PUT") {
|
| 427 |
+
const value = await request.text();
|
| 428 |
+
store.set(key, value);
|
| 429 |
+
return new Response(null, { status: 204 });
|
| 430 |
+
} else if (request.method === "DELETE") {
|
| 431 |
+
store.delete(key);
|
| 432 |
+
return new Response(null, { status: 204 });
|
| 433 |
+
} else {
|
| 434 |
+
return new Response(null, { status: 405 });
|
| 435 |
+
}
|
| 436 |
+
},
|
| 437 |
+
},
|
| 438 |
+
modules: true,
|
| 439 |
+
script: `
|
| 440 |
+
// Implementation of binding
|
| 441 |
+
class MiniKV {
|
| 442 |
+
constructor(env) {
|
| 443 |
+
this.STORE = env.STORE;
|
| 444 |
+
this.baseURL = "http://x/" + (env.NAMESPACE ?? "") + ":";
|
| 445 |
+
}
|
| 446 |
+
async get(key) {
|
| 447 |
+
const res = await this.STORE.fetch(this.baseURL + key);
|
| 448 |
+
return res.status === 404 ? null : await res.text();
|
| 449 |
+
}
|
| 450 |
+
async set(key, body) {
|
| 451 |
+
await this.STORE.fetch(this.baseURL + key, { method: "PUT", body });
|
| 452 |
+
}
|
| 453 |
+
async delete(key) {
|
| 454 |
+
await this.STORE.fetch(this.baseURL + key, { method: "DELETE" });
|
| 455 |
+
}
|
| 456 |
+
}
|
| 457 |
+
|
| 458 |
+
// env has the type { STORE: Fetcher, NAMESPACE?: string }
|
| 459 |
+
export default function (env) {
|
| 460 |
+
return new MiniKV(env);
|
| 461 |
+
}
|
| 462 |
+
`,
|
| 463 |
+
},
|
| 464 |
+
],
|
| 465 |
+
});
|
| 466 |
+
```
|
| 467 |
+
|
| 468 |
+
</details>
|
| 469 |
+
|
| 470 |
+
> :warning: `wrappedBindings` are only supported in modules format Workers.
|
| 471 |
+
|
| 472 |
+
<!--prettier-ignore-end-->
|
| 473 |
+
|
| 474 |
+
- `outboundService?: string | { network: Network } | { external: ExternalServer } | { disk: DiskDirectory } | { node: (req: http.IncomingMessage, res: http.ServerResponse, miniflare: Miniflare) => Awaitable<void> } | (request: Request, miniflare: Miniflare) => Awaitable<Response>`
|
| 475 |
+
|
| 476 |
+
Dispatch this Worker's global `fetch()` and `connect()` requests to the
|
| 477 |
+
configured service. Service designators follow the same rules above for
|
| 478 |
+
`serviceBindings`.
|
| 479 |
+
|
| 480 |
+
- `fetchMock?: import("undici").MockAgent`
|
| 481 |
+
|
| 482 |
+
An [`undici` `MockAgent`](https://undici.nodejs.org/#/docs/api/MockAgent) to
|
| 483 |
+
dispatch this Worker's global `fetch()` requests through.
|
| 484 |
+
|
| 485 |
+
> :warning: `outboundService` and `fetchMock` are mutually exclusive options.
|
| 486 |
+
> At most one of them may be specified per Worker.
|
| 487 |
+
|
| 488 |
+
- `routes?: string[]`
|
| 489 |
+
|
| 490 |
+
Array of route patterns for this Worker. These follow the same
|
| 491 |
+
[routing rules](https://developers.cloudflare.com/workers/platform/triggers/routes/#matching-behavior)
|
| 492 |
+
as deployed Workers. If no routes match, Miniflare will fallback to the Worker
|
| 493 |
+
defined first.
|
| 494 |
+
|
| 495 |
+
- `defaultPersistRoot?: string`
|
| 496 |
+
|
| 497 |
+
Specifies the default directory where Miniflare will write persisted data when persistence is enabled.
|
| 498 |
+
|
| 499 |
+
```js
|
| 500 |
+
// Without `defaultPersistRoot`
|
| 501 |
+
new Miniflare({
|
| 502 |
+
kvPersist: undefined, // → "/(tmp)/kv"
|
| 503 |
+
d1Persist: true, // → "$PWD/.mf/d1"
|
| 504 |
+
r2Persist: false, // → "/(tmp)/r2"
|
| 505 |
+
cachePersist: "/my-cache", // → "/my-cache"
|
| 506 |
+
});
|
| 507 |
+
|
| 508 |
+
// With `defaultPersistRoot`
|
| 509 |
+
new Miniflare({
|
| 510 |
+
defaultPersistRoot: "/storage",
|
| 511 |
+
kvPersist: undefined, // → "/storage/kv"
|
| 512 |
+
d1Persist: true, // → "/storage/d1"
|
| 513 |
+
r2Persist: false, // → "/(tmp)/r2"
|
| 514 |
+
cachePersist: "/my-cache", // → "/my-cache"
|
| 515 |
+
});
|
| 516 |
+
```
|
| 517 |
+
|
| 518 |
+
#### Cache
|
| 519 |
+
|
| 520 |
+
- `cache?: boolean`
|
| 521 |
+
|
| 522 |
+
If `false`, default and named caches will be disabled. The Cache API will
|
| 523 |
+
still be available, it just won't cache anything.
|
| 524 |
+
|
| 525 |
+
- `cacheWarnUsage?: boolean`
|
| 526 |
+
|
| 527 |
+
If `true`, the first use of the Cache API will log a warning stating that the
|
| 528 |
+
Cache API is unsupported on `workers.dev` subdomains.
|
| 529 |
+
|
| 530 |
+
#### Durable Objects
|
| 531 |
+
|
| 532 |
+
- `durableObjects?: Record<string, string | { className: string, scriptName?: string, useSQLite?: boolean }>`
|
| 533 |
+
|
| 534 |
+
Record mapping binding name to Durable Object class designators to inject as
|
| 535 |
+
`DurableObjectNamespace` bindings into this Worker.
|
| 536 |
+
- If the designator is a `string`, it should be the name of a `class` exported
|
| 537 |
+
by this Worker.
|
| 538 |
+
- If the designator is an object, and `scriptName` is `undefined`, `className`
|
| 539 |
+
should be the name of a `class` exported by this Worker.
|
| 540 |
+
- Otherwise, `className` should be the name of a `class` exported by the
|
| 541 |
+
Worker with a `name` of `scriptName`.
|
| 542 |
+
- To use the Durable Object SQLite API you must pass `useSQLite: true`.
|
| 543 |
+
|
| 544 |
+
#### KV
|
| 545 |
+
|
| 546 |
+
- `kvNamespaces?: Record<string, string> | string[]`
|
| 547 |
+
|
| 548 |
+
Record mapping binding name to KV namespace IDs to inject as `KVNamespace`
|
| 549 |
+
bindings into this Worker. Different Workers may bind to the same namespace ID
|
| 550 |
+
with different binding names. If a `string[]` of binding names is specified,
|
| 551 |
+
the binding name and KV namespace ID are assumed to be the same.
|
| 552 |
+
|
| 553 |
+
- `sitePath?: string`
|
| 554 |
+
|
| 555 |
+
Path to serve Workers Sites files from. If set, `__STATIC_CONTENT` and
|
| 556 |
+
`__STATIC_CONTENT_MANIFEST` bindings will be injected into this Worker. In
|
| 557 |
+
modules mode, `__STATIC_CONTENT_MANIFEST` will also be exposed as a module
|
| 558 |
+
with a `string`-typed `default` export, containing the JSON-stringified
|
| 559 |
+
manifest. Note Workers Sites files are never cached in Miniflare.
|
| 560 |
+
|
| 561 |
+
- `siteInclude?: string[]`
|
| 562 |
+
|
| 563 |
+
If set, only files with paths matching these glob patterns will be served.
|
| 564 |
+
|
| 565 |
+
- `siteExclude?: string[]`
|
| 566 |
+
|
| 567 |
+
If set, only files with paths _not_ matching these glob patterns will be
|
| 568 |
+
served.
|
| 569 |
+
- `assetsPath?: string`
|
| 570 |
+
|
| 571 |
+
Path to serve Workers assets from.
|
| 572 |
+
- `assetsKVBindingName?: string`
|
| 573 |
+
Name of the binding to the KV namespace that the assets are in. If `assetsPath` is set, this binding will be injected into this Worker.
|
| 574 |
+
|
| 575 |
+
- `assetsManifestBindingName?: string`
|
| 576 |
+
Name of the binding to an `ArrayBuffer` containing the binary-encoded assets manifest. If `assetsPath` is set, this binding will be injected into this Worker.
|
| 577 |
+
|
| 578 |
+
#### R2
|
| 579 |
+
|
| 580 |
+
- `r2Buckets?: Record<string, string> | string[]`
|
| 581 |
+
|
| 582 |
+
Record mapping binding name to R2 bucket names to inject as `R2Bucket`
|
| 583 |
+
bindings into this Worker. Different Workers may bind to the same bucket name
|
| 584 |
+
with different binding names. If a `string[]` of binding names is specified,
|
| 585 |
+
the binding name and bucket name are assumed to be the same.
|
| 586 |
+
|
| 587 |
+
#### D1
|
| 588 |
+
|
| 589 |
+
- `d1Databases?: Record<string, string> | string[]`
|
| 590 |
+
|
| 591 |
+
Record mapping binding name to D1 database IDs to inject as `D1Database`
|
| 592 |
+
bindings into this Worker. Note binding names starting with `__D1_BETA__` are
|
| 593 |
+
injected as `Fetcher` bindings instead, and must be wrapped with a facade to
|
| 594 |
+
provide the expected `D1Database` API. Different Workers may bind to the same
|
| 595 |
+
database ID with different binding names. If a `string[]` of binding names is
|
| 596 |
+
specified, the binding name and database ID are assumed to be the same.
|
| 597 |
+
|
| 598 |
+
#### Queues
|
| 599 |
+
|
| 600 |
+
- `queueProducers?: Record<string, QueueProducerOptions> | string[]`
|
| 601 |
+
|
| 602 |
+
Record mapping binding name to queue options to inject as `WorkerQueue` bindings
|
| 603 |
+
into this Worker. Different Workers may bind to the same queue name with
|
| 604 |
+
different binding names. If a `string[]` of binding names is specified, the
|
| 605 |
+
binding name and queue name (part of the queue options) are assumed to be the same.
|
| 606 |
+
|
| 607 |
+
- `queueConsumers?: Record<string, QueueConsumerOptions> | string[]`
|
| 608 |
+
|
| 609 |
+
Record mapping queue name to consumer options. Messages enqueued on the
|
| 610 |
+
corresponding queues will be dispatched to this Worker. Note each queue can
|
| 611 |
+
have at most one consumer. If a `string[]` of queue names is specified,
|
| 612 |
+
default consumer options will be used.
|
| 613 |
+
|
| 614 |
+
#### Assets
|
| 615 |
+
|
| 616 |
+
- `directory?: string`
|
| 617 |
+
Path to serve Workers static asset files from.
|
| 618 |
+
|
| 619 |
+
- `binding?: string`
|
| 620 |
+
Binding name to inject as a `Fetcher` binding to allow access to static assets from within the Worker.
|
| 621 |
+
|
| 622 |
+
- `assetOptions?: { html_handling?: HTMLHandlingOptions, not_found_handling?: NotFoundHandlingOptions}`
|
| 623 |
+
Configuration for file-based asset routing - see [docs](https://developers.cloudflare.com/workers/static-assets/routing/#routing-configuration) for options
|
| 624 |
+
|
| 625 |
+
#### Pipelines
|
| 626 |
+
|
| 627 |
+
- `pipelines?: Record<string, PipelineOptions> | string[]`
|
| 628 |
+
|
| 629 |
+
Record mapping binding name to a Pipeline. Different workers may bind to the same Pipeline with different bindings
|
| 630 |
+
names. If a `string[]` of pipeline names, the binding and Pipeline name are assumed to be the same.
|
| 631 |
+
|
| 632 |
+
#### Workflows
|
| 633 |
+
|
| 634 |
+
- `workflows?: WorkflowOptions[]`
|
| 635 |
+
Configuration for one or more Workflows in your project.
|
| 636 |
+
|
| 637 |
+
#### Browser Run
|
| 638 |
+
|
| 639 |
+
- `browserRendering: BrowserRenderingOptions`
|
| 640 |
+
|
| 641 |
+
#### Analytics Engine, Sending Email, Vectorize and Workers for Platforms
|
| 642 |
+
|
| 643 |
+
_Not yet supported_
|
| 644 |
+
|
| 645 |
+
If you need support for these locally, consider using the `wrappedBindings`
|
| 646 |
+
option to mock them out.
|
| 647 |
+
|
| 648 |
+
#### Workers AI
|
| 649 |
+
|
| 650 |
+
_Not yet supported_
|
| 651 |
+
|
| 652 |
+
If you need support for these locally, consider using the `serviceBindings`
|
| 653 |
+
option to mock them out.
|
| 654 |
+
|
| 655 |
+
### `interface SharedOptions`
|
| 656 |
+
|
| 657 |
+
Options shared between all Workers/"nanoservices".
|
| 658 |
+
|
| 659 |
+
#### Core
|
| 660 |
+
|
| 661 |
+
- `rootPath?: string`
|
| 662 |
+
|
| 663 |
+
Path against which all other path options for this instance are resolved
|
| 664 |
+
relative to. Defaults to the current working directory.
|
| 665 |
+
|
| 666 |
+
- `host?: string`
|
| 667 |
+
|
| 668 |
+
Hostname that the `workerd` server should listen on. Defaults to `127.0.0.1`.
|
| 669 |
+
|
| 670 |
+
- `port?: number`
|
| 671 |
+
|
| 672 |
+
Port that the `workerd` server should listen on. Tries to default to `8787`,
|
| 673 |
+
but falls back to a random free port if this is in use. Note if a manually
|
| 674 |
+
specified port is in use, Miniflare throws an error, rather than attempting to
|
| 675 |
+
find a free port.
|
| 676 |
+
|
| 677 |
+
- `https?: boolean`
|
| 678 |
+
|
| 679 |
+
If `true`, start an HTTPS server using a pre-generated self-signed certificate
|
| 680 |
+
for `localhost`. Note this certificate is not valid for any other hostnames or
|
| 681 |
+
IP addresses. If you need to access the HTTPS server from another device,
|
| 682 |
+
you'll need to generate your own certificate and use the other `https*`
|
| 683 |
+
options below.
|
| 684 |
+
|
| 685 |
+
```shell
|
| 686 |
+
$ openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out cert.pem
|
| 687 |
+
```
|
| 688 |
+
|
| 689 |
+
```js
|
| 690 |
+
new Miniflare({
|
| 691 |
+
httpsKeyPath: "key.pem",
|
| 692 |
+
httpsCertPath: "cert.pem",
|
| 693 |
+
});
|
| 694 |
+
```
|
| 695 |
+
|
| 696 |
+
- `httpsKey?: string`
|
| 697 |
+
|
| 698 |
+
When one of `httpsCert` or `httpCertPath` is also specified, starts an HTTPS
|
| 699 |
+
server using the value of this option as the PEM encoded private key.
|
| 700 |
+
|
| 701 |
+
- `httpsKeyPath?: string`
|
| 702 |
+
|
| 703 |
+
When one of `httpsCert` or `httpCertPath` is also specified, starts an HTTPS
|
| 704 |
+
server using the PEM encoded private key stored at this file path.
|
| 705 |
+
|
| 706 |
+
- `httpsCert?: string`
|
| 707 |
+
|
| 708 |
+
When one of `httpsKey` or `httpsKeyPath` is also specified, starts an HTTPS
|
| 709 |
+
server using the value of this option as the PEM encoded certificate chain.
|
| 710 |
+
|
| 711 |
+
- `httpsCertPath?: string`
|
| 712 |
+
|
| 713 |
+
When one of `httpsKey` or `httpsKeyPath` is also specified, starts an HTTPS
|
| 714 |
+
server using the PEM encoded certificate chain stored at this file path.
|
| 715 |
+
|
| 716 |
+
- `inspectorPort?: number`
|
| 717 |
+
|
| 718 |
+
Port that `workerd` should start a DevTools inspector server on. Visit
|
| 719 |
+
`chrome://inspect` in a Chromium-based browser to connect to this. This can be
|
| 720 |
+
used to see detailed `console.log`s, profile CPU usage, and will eventually
|
| 721 |
+
allow step-through debugging.
|
| 722 |
+
|
| 723 |
+
- `verbose?: boolean`
|
| 724 |
+
|
| 725 |
+
Enable `workerd`'s `--verbose` flag for verbose logging. This can be used to
|
| 726 |
+
see simplified `console.log`s.
|
| 727 |
+
|
| 728 |
+
- `log?: Log`
|
| 729 |
+
|
| 730 |
+
Logger implementation for Miniflare's errors, warnings and informative
|
| 731 |
+
messages.
|
| 732 |
+
|
| 733 |
+
- `upstream?: string`
|
| 734 |
+
|
| 735 |
+
URL to use as the origin for incoming requests. If specified, all incoming
|
| 736 |
+
`request.url`s will be rewritten to start with this string. This is especially
|
| 737 |
+
useful when testing Workers that act as a proxy, and not as origins
|
| 738 |
+
themselves.
|
| 739 |
+
|
| 740 |
+
When `upstream` is set, the `Host` header is rewritten to match the upstream
|
| 741 |
+
server. To preserve the original hostname, Miniflare adds an
|
| 742 |
+
`MF-Original-Hostname` header containing the original `Host` value:
|
| 743 |
+
|
| 744 |
+
```js
|
| 745 |
+
export default {
|
| 746 |
+
async fetch(request) {
|
| 747 |
+
// When upstream is set, Host header contains the upstream hostname
|
| 748 |
+
const upstreamHost = request.headers.get("Host");
|
| 749 |
+
// Original hostname is preserved in MF-Original-Hostname
|
| 750 |
+
const originalHost = request.headers.get("MF-Original-Hostname");
|
| 751 |
+
return new Response(
|
| 752 |
+
`Original: ${originalHost}, Upstream: ${upstreamHost}`
|
| 753 |
+
);
|
| 754 |
+
},
|
| 755 |
+
};
|
| 756 |
+
```
|
| 757 |
+
|
| 758 |
+
- `cf?: boolean | string | Record<string, any>`
|
| 759 |
+
|
| 760 |
+
Controls the object returned from incoming `Request`'s `cf` property.
|
| 761 |
+
- If set to a falsy value, an object with default placeholder values will be
|
| 762 |
+
used
|
| 763 |
+
- If set to an object, that object will be used
|
| 764 |
+
- If set to `true`, a real `cf` object will be fetched from a trusted
|
| 765 |
+
Cloudflare endpoint and cached in `node_modules/.mf` for 30 days
|
| 766 |
+
- If set to a `string`, a real `cf` object will be fetched and cached at the
|
| 767 |
+
provided path for 30 days
|
| 768 |
+
|
| 769 |
+
- `liveReload?: boolean`
|
| 770 |
+
|
| 771 |
+
If `true`, Miniflare will inject a script into HTML responses that
|
| 772 |
+
automatically reloads the page in-browser whenever the Miniflare instance's
|
| 773 |
+
options are updated.
|
| 774 |
+
|
| 775 |
+
- `unsafeDevRegistryPath?: string`
|
| 776 |
+
|
| 777 |
+
Path to the dev registry directory. This allows Miniflare to automatically
|
| 778 |
+
discover external services and Durable Objects running on another miniflare instance and connect them.
|
| 779 |
+
|
| 780 |
+
- `unsafeDevRegistryDurableObjectProxy?: boolean`
|
| 781 |
+
|
| 782 |
+
If `true`, Miniflare will automatically proxy requests to Durable Objects
|
| 783 |
+
bound to external services and register all Workers' Durable Objects in the dev registry.
|
| 784 |
+
|
| 785 |
+
- `unsafeHandleDevRegistryUpdate?: (registry: WorkerRegistry) => void`
|
| 786 |
+
|
| 787 |
+
Callback invoked when the dev registry is updated with changes to bound services.
|
| 788 |
+
Receives a copy of the updated registry object. Useful for reacting to external
|
| 789 |
+
service changes during development.
|
| 790 |
+
|
| 791 |
+
- `unsafeRuntimeEnv?: Record<string, string>`
|
| 792 |
+
|
| 793 |
+
Extra environment variables to set on the spawned `workerd` subprocess.
|
| 794 |
+
Merged on top of `process.env` and Miniflare's own defaults — most notably
|
| 795 |
+
`TZ=UTC`, which Miniflare sets to match the production Cloudflare runtime so
|
| 796 |
+
that `Date` and `Intl` APIs inside the Worker observe UTC during local
|
| 797 |
+
development. Use this option to override those defaults, for example to test
|
| 798 |
+
timezone-dependent code with `unsafeRuntimeEnv: { TZ: "Europe/London" }`.
|
| 799 |
+
|
| 800 |
+
#### Cache, Durable Objects, KV, R2 and D1
|
| 801 |
+
|
| 802 |
+
- `cachePersist?: Persistence`
|
| 803 |
+
|
| 804 |
+
Where to persist data cached in default or named caches. See docs for
|
| 805 |
+
`Persistence`.
|
| 806 |
+
|
| 807 |
+
- `durableObjectsPersist?: Persistence`
|
| 808 |
+
|
| 809 |
+
Where to persist data stored in Durable Objects. See docs for `Persistence`.
|
| 810 |
+
|
| 811 |
+
- `kvPersist?: Persistence`
|
| 812 |
+
|
| 813 |
+
Where to persist data stored in KV namespaces. See docs for `Persistence`.
|
| 814 |
+
|
| 815 |
+
- `r2Persist?: Persistence`
|
| 816 |
+
|
| 817 |
+
Where to persist data stored in R2 buckets. See docs for `Persistence`.
|
| 818 |
+
|
| 819 |
+
- `d1Persist?: Persistence`
|
| 820 |
+
|
| 821 |
+
Where to persist data stored in D1 databases. See docs for `Persistence`.
|
| 822 |
+
|
| 823 |
+
- `workflowsPersist?: Persistence`
|
| 824 |
+
|
| 825 |
+
Where to persist data stored in Workflows. See docs for `Persistence`.
|
| 826 |
+
|
| 827 |
+
#### Analytics Engine, Sending Email, Vectorize, Workers AI and Workers for Platforms
|
| 828 |
+
|
| 829 |
+
_Not yet supported_
|
| 830 |
+
|
| 831 |
+
### `type MiniflareOptions`
|
| 832 |
+
|
| 833 |
+
`SharedOptions & (WorkerOptions | { workers: WorkerOptions[] })`
|
| 834 |
+
|
| 835 |
+
Miniflare accepts either a single Worker configuration or multiple Worker
|
| 836 |
+
configurations in the `workers` array. When specifying an array of Workers, the
|
| 837 |
+
first Worker is designated the entrypoint and will receive all incoming HTTP
|
| 838 |
+
requests. Some options are shared between all workers and should always be
|
| 839 |
+
defined at the top-level.
|
| 840 |
+
|
| 841 |
+
### `class Miniflare`
|
| 842 |
+
|
| 843 |
+
- `constructor(opts: MiniflareOptions)`
|
| 844 |
+
|
| 845 |
+
Creates a Miniflare instance and starts a new `workerd` HTTP server
|
| 846 |
+
listening on the configured `host` and `port`.
|
| 847 |
+
|
| 848 |
+
- `setOptions(opts: MiniflareOptions)`
|
| 849 |
+
|
| 850 |
+
Updates the configuration for this Miniflare instance and restarts the
|
| 851 |
+
`workerd` server. Note unlike Miniflare 2, this does _not_ merge the new
|
| 852 |
+
configuration with the old configuration. Note that calling this function will
|
| 853 |
+
invalidate any existing values returned by the `Miniflare#get*()` methods,
|
| 854 |
+
preventing them from being used.
|
| 855 |
+
|
| 856 |
+
- `ready: Promise<URL>`
|
| 857 |
+
|
| 858 |
+
Returns a `Promise` that resolves with a `http` `URL` to the `workerd` server
|
| 859 |
+
once it has started and is able to accept requests.
|
| 860 |
+
|
| 861 |
+
- `dispatchFetch(input: RequestInfo, init?: RequestInit): Promise<Response>`
|
| 862 |
+
|
| 863 |
+
Sends a HTTP request to the `workerd` server, dispatching a `fetch` event in
|
| 864 |
+
the entrypoint Worker. Returns a `Promise` that resolves with the response.
|
| 865 |
+
Note that this implicitly waits for the `ready` `Promise` to resolve, there's
|
| 866 |
+
no need to do that yourself first. Additionally, the host of the request's URL
|
| 867 |
+
is always ignored and replaced with the `workerd` server's.
|
| 868 |
+
|
| 869 |
+
- `getBindings<Env extends Record<string, unknown> = Record<string, unknown>>(workerName?: string): Promise<Env>`
|
| 870 |
+
|
| 871 |
+
Returns a `Promise` that resolves with a record mapping binding names to
|
| 872 |
+
bindings, for all bindings in the Worker with the specified `workerName`. If
|
| 873 |
+
`workerName` is not specified, defaults to the entrypoint Worker.
|
| 874 |
+
|
| 875 |
+
- `getWorker(workerName?: string): Promise<Fetcher>`
|
| 876 |
+
|
| 877 |
+
Returns a `Promise` that resolves with a
|
| 878 |
+
[`Fetcher`](https://workers-types.pages.dev/experimental/#Fetcher) pointing to
|
| 879 |
+
the specified `workerName`. If `workerName` is not specified, defaults to the
|
| 880 |
+
entrypoint Worker. Note this `Fetcher` uses the experimental
|
| 881 |
+
[`service_binding_extra_handlers`](https://github.com/cloudflare/workerd/blob/1d9158af7ca1389474982c76ace9e248320bec77/src/workerd/io/compatibility-date.capnp#L290-L297)
|
| 882 |
+
compatibility flag to expose
|
| 883 |
+
[`scheduled()`](https://workers-types.pages.dev/experimental/#Fetcher.scheduled)
|
| 884 |
+
and [`queue()`](https://workers-types.pages.dev/experimental/#Fetcher.queue)
|
| 885 |
+
methods for dispatching `scheduled` and `queue` events.
|
| 886 |
+
|
| 887 |
+
- `getCaches(): Promise<CacheStorage>`
|
| 888 |
+
|
| 889 |
+
Returns a `Promise` that resolves with the
|
| 890 |
+
[`CacheStorage`](https://developers.cloudflare.com/workers/runtime-apis/cache/)
|
| 891 |
+
instance of the entrypoint Worker. This means if `cache: false` is set on the
|
| 892 |
+
entrypoint, calling methods on the resolved value won't do anything.
|
| 893 |
+
|
| 894 |
+
- `getD1Database(bindingName: string, workerName?: string): Promise<D1Database>`
|
| 895 |
+
|
| 896 |
+
Returns a `Promise` that resolves with the
|
| 897 |
+
[`D1Database`](https://developers.cloudflare.com/d1/platform/client-api/)
|
| 898 |
+
instance corresponding to the specified `bindingName` of `workerName`. Note
|
| 899 |
+
`bindingName` must not begin with `__D1_BETA__`. If `workerName` is not
|
| 900 |
+
specified, defaults to the entrypoint Worker.
|
| 901 |
+
|
| 902 |
+
- `getDurableObjectNamespace(bindingName: string, workerName?: string): Promise<DurableObjectNamespace>`
|
| 903 |
+
|
| 904 |
+
Returns a `Promise` that resolves with the
|
| 905 |
+
[`DurableObjectNamespace`](https://developers.cloudflare.com/workers/runtime-apis/durable-objects/#access-a-durable-object-from-a-worker)
|
| 906 |
+
instance corresponding to the specified `bindingName` of `workerName`. If
|
| 907 |
+
`workerName` is not specified, defaults to the entrypoint Worker.
|
| 908 |
+
|
| 909 |
+
- `getKVNamespace(bindingName: string, workerName?: string): Promise<KVNamespace>`
|
| 910 |
+
|
| 911 |
+
Returns a `Promise` that resolves with the
|
| 912 |
+
[`KVNamespace`](https://developers.cloudflare.com/workers/runtime-apis/kv/)
|
| 913 |
+
instance corresponding to the specified `bindingName` of `workerName`. If
|
| 914 |
+
`workerName` is not specified, defaults to the entrypoint Worker.
|
| 915 |
+
|
| 916 |
+
- `getQueueProducer<Body>(bindingName: string, workerName?: string): Promise<Queue<Body>>`
|
| 917 |
+
|
| 918 |
+
Returns a `Promise` that resolves with the
|
| 919 |
+
[`Queue`](https://developers.cloudflare.com/queues/platform/javascript-apis/)
|
| 920 |
+
producer instance corresponding to the specified `bindingName` of
|
| 921 |
+
`workerName`. If `workerName` is not specified, defaults to the entrypoint
|
| 922 |
+
Worker.
|
| 923 |
+
|
| 924 |
+
- `getR2Bucket(bindingName: string, workerName?: string): Promise<R2Bucket>`
|
| 925 |
+
|
| 926 |
+
Returns a `Promise` that resolves with the
|
| 927 |
+
[`R2Bucket`](https://developers.cloudflare.com/r2/api/workers/workers-api-reference/)
|
| 928 |
+
producer instance corresponding to the specified `bindingName` of
|
| 929 |
+
`workerName`. If `workerName` is not specified, defaults to the entrypoint
|
| 930 |
+
Worker.
|
| 931 |
+
|
| 932 |
+
- `dispose(): Promise<void>`
|
| 933 |
+
|
| 934 |
+
Cleans up the Miniflare instance, and shuts down the `workerd` server. Note
|
| 935 |
+
that after this is called, `Miniflare#setOptions()` and
|
| 936 |
+
`Miniflare#dispatchFetch()` cannot be called. Additionally, calling this
|
| 937 |
+
function will invalidate any values returned by the `Miniflare#get*()`
|
| 938 |
+
methods, preventing them from being used.
|
| 939 |
+
|
| 940 |
+
- `getCf(): Promise<Record<string, any>>`
|
| 941 |
+
|
| 942 |
+
Returns the same object returned from incoming `Request`'s `cf` property. This
|
| 943 |
+
object depends on the `cf` property from `SharedOptions`.
|
| 944 |
+
|
| 945 |
+
## Configuration
|
| 946 |
+
|
| 947 |
+
### Local `workerd`
|
| 948 |
+
|
| 949 |
+
You can override the `workerd` binary being used by miniflare with a your own local build by setting the `MINIFLARE_WORKERD_PATH` environment variable.
|
| 950 |
+
|
| 951 |
+
For example:
|
| 952 |
+
|
| 953 |
+
```shell
|
| 954 |
+
$ export MINIFLARE_WORKERD_PATH="<WORKERD_REPO_DIR>/bazel-bin/src/workerd/server/workerd"
|
| 955 |
+
```
|
| 956 |
+
|
| 957 |
+
For debugging purposes, you can also set `MINIFLARE_WORKERD_CONFIG_DEBUG=<file_path>` which will dump the workerd config to the specified file path.
|
bunx-1000-wrangler@latest/node_modules/path-to-regexp/Readme.md
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Path-to-RegExp
|
| 2 |
+
|
| 3 |
+
> Turn a path string such as `/user/:name` into a regular expression.
|
| 4 |
+
|
| 5 |
+
[![NPM version][npm-image]][npm-url]
|
| 6 |
+
[![NPM downloads][downloads-image]][downloads-url]
|
| 7 |
+
[![Build status][build-image]][build-url]
|
| 8 |
+
[![Build coverage][coverage-image]][coverage-url]
|
| 9 |
+
[![License][license-image]][license-url]
|
| 10 |
+
|
| 11 |
+
## Installation
|
| 12 |
+
|
| 13 |
+
```
|
| 14 |
+
npm install path-to-regexp --save
|
| 15 |
+
```
|
| 16 |
+
|
| 17 |
+
## Usage
|
| 18 |
+
|
| 19 |
+
```javascript
|
| 20 |
+
const { pathToRegexp, match, parse, compile } = require("path-to-regexp");
|
| 21 |
+
|
| 22 |
+
// pathToRegexp(path, keys?, options?)
|
| 23 |
+
// match(path)
|
| 24 |
+
// parse(path)
|
| 25 |
+
// compile(path)
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
### Path to regexp
|
| 29 |
+
|
| 30 |
+
The `pathToRegexp` function will return a regular expression object based on the provided `path` argument. It accepts the following arguments:
|
| 31 |
+
|
| 32 |
+
- **path** A string, array of strings, or a regular expression.
|
| 33 |
+
- **keys** _(optional)_ An array to populate with keys found in the path.
|
| 34 |
+
- **options** _(optional)_
|
| 35 |
+
- **sensitive** When `true` the regexp will be case sensitive. (default: `false`)
|
| 36 |
+
- **strict** When `true` the regexp won't allow an optional trailing delimiter to match. (default: `false`)
|
| 37 |
+
- **end** When `true` the regexp will match to the end of the string. (default: `true`)
|
| 38 |
+
- **start** When `true` the regexp will match from the beginning of the string. (default: `true`)
|
| 39 |
+
- **delimiter** The default delimiter for segments, e.g. `[^/#?]` for `:named` patterns. (default: `'/#?'`)
|
| 40 |
+
- **endsWith** Optional character, or list of characters, to treat as "end" characters.
|
| 41 |
+
- **encode** A function to encode strings before inserting into `RegExp`. (default: `x => x`)
|
| 42 |
+
- **prefixes** List of characters to automatically consider prefixes when parsing. (default: `./`)
|
| 43 |
+
|
| 44 |
+
```javascript
|
| 45 |
+
const keys = [];
|
| 46 |
+
const regexp = pathToRegexp("/foo/:bar", keys);
|
| 47 |
+
// regexp = /^\/foo(?:\/([^\/#\?]+?))[\/#\?]?$/i
|
| 48 |
+
// keys = [{ name: 'bar', prefix: '/', suffix: '', pattern: '[^\\/#\\?]+?', modifier: '' }]
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
**Please note:** The `RegExp` returned by `path-to-regexp` is intended for ordered data (e.g. pathnames, hostnames). It can not handle arbitrarily ordered data (e.g. query strings, URL fragments, JSON, etc). When using paths that contain query strings, you need to escape the question mark (`?`) to ensure it does not flag the parameter as [optional](#optional).
|
| 52 |
+
|
| 53 |
+
### Parameters
|
| 54 |
+
|
| 55 |
+
The path argument is used to define parameters and populate keys.
|
| 56 |
+
|
| 57 |
+
#### Named Parameters
|
| 58 |
+
|
| 59 |
+
Named parameters are defined by prefixing a colon to the parameter name (`:foo`).
|
| 60 |
+
|
| 61 |
+
```js
|
| 62 |
+
const regexp = pathToRegexp("/:foo/:bar");
|
| 63 |
+
// keys = [{ name: 'foo', prefix: '/', ... }, { name: 'bar', prefix: '/', ... }]
|
| 64 |
+
|
| 65 |
+
regexp.exec("/test/route");
|
| 66 |
+
//=> [ '/test/route', 'test', 'route', index: 0, input: '/test/route', groups: undefined ]
|
| 67 |
+
```
|
| 68 |
+
|
| 69 |
+
**Please note:** Parameter names must use "word characters" (`[A-Za-z0-9_]`).
|
| 70 |
+
|
| 71 |
+
##### Custom Matching Parameters
|
| 72 |
+
|
| 73 |
+
Parameters can have a custom regexp, which overrides the default match (`[^/]+`). For example, you can match digits or names in a path:
|
| 74 |
+
|
| 75 |
+
```js
|
| 76 |
+
const regexpNumbers = pathToRegexp("/icon-:foo(\\d+).png");
|
| 77 |
+
// keys = [{ name: 'foo', ... }]
|
| 78 |
+
|
| 79 |
+
regexpNumbers.exec("/icon-123.png");
|
| 80 |
+
//=> ['/icon-123.png', '123']
|
| 81 |
+
|
| 82 |
+
regexpNumbers.exec("/icon-abc.png");
|
| 83 |
+
//=> null
|
| 84 |
+
|
| 85 |
+
const regexpWord = pathToRegexp("/(user|u)");
|
| 86 |
+
// keys = [{ name: 0, ... }]
|
| 87 |
+
|
| 88 |
+
regexpWord.exec("/u");
|
| 89 |
+
//=> ['/u', 'u']
|
| 90 |
+
|
| 91 |
+
regexpWord.exec("/users");
|
| 92 |
+
//=> null
|
| 93 |
+
```
|
| 94 |
+
|
| 95 |
+
**Tip:** Backslashes need to be escaped with another backslash in JavaScript strings.
|
| 96 |
+
|
| 97 |
+
##### Custom Prefix and Suffix
|
| 98 |
+
|
| 99 |
+
Parameters can be wrapped in `{}` to create custom prefixes or suffixes for your segment:
|
| 100 |
+
|
| 101 |
+
```js
|
| 102 |
+
const regexp = pathToRegexp("/:attr1?{-:attr2}?{-:attr3}?");
|
| 103 |
+
|
| 104 |
+
regexp.exec("/test");
|
| 105 |
+
// => ['/test', 'test', undefined, undefined]
|
| 106 |
+
|
| 107 |
+
regexp.exec("/test-test");
|
| 108 |
+
// => ['/test', 'test', 'test', undefined]
|
| 109 |
+
```
|
| 110 |
+
|
| 111 |
+
#### Unnamed Parameters
|
| 112 |
+
|
| 113 |
+
It is possible to write an unnamed parameter that only consists of a regexp. It works the same the named parameter, except it will be numerically indexed:
|
| 114 |
+
|
| 115 |
+
```js
|
| 116 |
+
const regexp = pathToRegexp("/:foo/(.*)");
|
| 117 |
+
// keys = [{ name: 'foo', ... }, { name: 0, ... }]
|
| 118 |
+
|
| 119 |
+
regexp.exec("/test/route");
|
| 120 |
+
//=> [ '/test/route', 'test', 'route', index: 0, input: '/test/route', groups: undefined ]
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
+
#### Modifiers
|
| 124 |
+
|
| 125 |
+
Modifiers must be placed after the parameter (e.g. `/:foo?`, `/(test)?`, `/:foo(test)?`, or `{-:foo(test)}?`).
|
| 126 |
+
|
| 127 |
+
##### Optional
|
| 128 |
+
|
| 129 |
+
Parameters can be suffixed with a question mark (`?`) to make the parameter optional.
|
| 130 |
+
|
| 131 |
+
```js
|
| 132 |
+
const regexp = pathToRegexp("/:foo/:bar?");
|
| 133 |
+
// keys = [{ name: 'foo', ... }, { name: 'bar', prefix: '/', modifier: '?' }]
|
| 134 |
+
|
| 135 |
+
regexp.exec("/test");
|
| 136 |
+
//=> [ '/test', 'test', undefined, index: 0, input: '/test', groups: undefined ]
|
| 137 |
+
|
| 138 |
+
regexp.exec("/test/route");
|
| 139 |
+
//=> [ '/test/route', 'test', 'route', index: 0, input: '/test/route', groups: undefined ]
|
| 140 |
+
```
|
| 141 |
+
|
| 142 |
+
**Tip:** The prefix is also optional, escape the prefix `\/` to make it required.
|
| 143 |
+
|
| 144 |
+
When dealing with query strings, escape the question mark (`?`) so it doesn't mark the parameter as optional. Handling unordered data is outside the scope of this library.
|
| 145 |
+
|
| 146 |
+
```js
|
| 147 |
+
const regexp = pathToRegexp("/search/:tableName\\?useIndex=true&term=amazing");
|
| 148 |
+
|
| 149 |
+
regexp.exec("/search/people?useIndex=true&term=amazing");
|
| 150 |
+
//=> [ '/search/people?useIndex=true&term=amazing', 'people', index: 0, input: '/search/people?useIndex=true&term=amazing', groups: undefined ]
|
| 151 |
+
|
| 152 |
+
// This library does not handle query strings in different orders
|
| 153 |
+
regexp.exec("/search/people?term=amazing&useIndex=true");
|
| 154 |
+
//=> null
|
| 155 |
+
```
|
| 156 |
+
|
| 157 |
+
##### Zero or more
|
| 158 |
+
|
| 159 |
+
Parameters can be suffixed with an asterisk (`*`) to denote a zero or more parameter matches.
|
| 160 |
+
|
| 161 |
+
```js
|
| 162 |
+
const regexp = pathToRegexp("/:foo*");
|
| 163 |
+
// keys = [{ name: 'foo', prefix: '/', modifier: '*' }]
|
| 164 |
+
|
| 165 |
+
regexp.exec("/");
|
| 166 |
+
//=> [ '/', undefined, index: 0, input: '/', groups: undefined ]
|
| 167 |
+
|
| 168 |
+
regexp.exec("/bar/baz");
|
| 169 |
+
//=> [ '/bar/baz', 'bar/baz', index: 0, input: '/bar/baz', groups: undefined ]
|
| 170 |
+
```
|
| 171 |
+
|
| 172 |
+
##### One or more
|
| 173 |
+
|
| 174 |
+
Parameters can be suffixed with a plus sign (`+`) to denote a one or more parameter matches.
|
| 175 |
+
|
| 176 |
+
```js
|
| 177 |
+
const regexp = pathToRegexp("/:foo+");
|
| 178 |
+
// keys = [{ name: 'foo', prefix: '/', modifier: '+' }]
|
| 179 |
+
|
| 180 |
+
regexp.exec("/");
|
| 181 |
+
//=> null
|
| 182 |
+
|
| 183 |
+
regexp.exec("/bar/baz");
|
| 184 |
+
//=> [ '/bar/baz','bar/baz', index: 0, input: '/bar/baz', groups: undefined ]
|
| 185 |
+
```
|
| 186 |
+
|
| 187 |
+
### Match
|
| 188 |
+
|
| 189 |
+
The `match` function will return a function for transforming paths into parameters:
|
| 190 |
+
|
| 191 |
+
```js
|
| 192 |
+
// Make sure you consistently `decode` segments.
|
| 193 |
+
const fn = match("/user/:id", { decode: decodeURIComponent });
|
| 194 |
+
|
| 195 |
+
fn("/user/123"); //=> { path: '/user/123', index: 0, params: { id: '123' } }
|
| 196 |
+
fn("/invalid"); //=> false
|
| 197 |
+
fn("/user/caf%C3%A9"); //=> { path: '/user/caf%C3%A9', index: 0, params: { id: 'café' } }
|
| 198 |
+
```
|
| 199 |
+
|
| 200 |
+
The `match` function can be used to custom match named parameters. For example, this can be used to whitelist a small number of valid paths:
|
| 201 |
+
|
| 202 |
+
```js
|
| 203 |
+
const urlMatch = match("/users/:id/:tab(home|photos|bio)", {
|
| 204 |
+
decode: decodeURIComponent,
|
| 205 |
+
});
|
| 206 |
+
|
| 207 |
+
urlMatch("/users/1234/photos");
|
| 208 |
+
//=> { path: '/users/1234/photos', index: 0, params: { id: '1234', tab: 'photos' } }
|
| 209 |
+
|
| 210 |
+
urlMatch("/users/1234/bio");
|
| 211 |
+
//=> { path: '/users/1234/bio', index: 0, params: { id: '1234', tab: 'bio' } }
|
| 212 |
+
|
| 213 |
+
urlMatch("/users/1234/otherstuff");
|
| 214 |
+
//=> false
|
| 215 |
+
```
|
| 216 |
+
|
| 217 |
+
#### Process Pathname
|
| 218 |
+
|
| 219 |
+
You should make sure variations of the same path match the expected `path`. Here's one possible solution using `encode`:
|
| 220 |
+
|
| 221 |
+
```js
|
| 222 |
+
const fn = match("/café", { encode: encodeURI });
|
| 223 |
+
|
| 224 |
+
fn("/caf%C3%A9"); //=> { path: '/caf%C3%A9', index: 0, params: {} }
|
| 225 |
+
```
|
| 226 |
+
|
| 227 |
+
**Note:** [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) encodes paths, so `/café` would be normalized to `/caf%C3%A9` and match in the above example.
|
| 228 |
+
|
| 229 |
+
##### Alternative Using Normalize
|
| 230 |
+
|
| 231 |
+
Sometimes you won't have already normalized paths to use, so you could normalize it yourself before matching:
|
| 232 |
+
|
| 233 |
+
```js
|
| 234 |
+
/**
|
| 235 |
+
* Normalize a pathname for matching, replaces multiple slashes with a single
|
| 236 |
+
* slash and normalizes unicode characters to "NFC". When using this method,
|
| 237 |
+
* `decode` should be an identity function so you don't decode strings twice.
|
| 238 |
+
*/
|
| 239 |
+
function normalizePathname(pathname: string) {
|
| 240 |
+
return (
|
| 241 |
+
decodeURI(pathname)
|
| 242 |
+
// Replaces repeated slashes in the URL.
|
| 243 |
+
.replace(/\/+/g, "/")
|
| 244 |
+
// Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
|
| 245 |
+
// Note: Missing native IE support, may want to skip this step.
|
| 246 |
+
.normalize()
|
| 247 |
+
);
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
// Two possible ways of writing `/café`:
|
| 251 |
+
const re = pathToRegexp("/caf\u00E9");
|
| 252 |
+
const input = encodeURI("/cafe\u0301");
|
| 253 |
+
|
| 254 |
+
re.test(input); //=> false
|
| 255 |
+
re.test(normalizePathname(input)); //=> true
|
| 256 |
+
```
|
| 257 |
+
|
| 258 |
+
### Parse
|
| 259 |
+
|
| 260 |
+
The `parse` function will return a list of strings and keys from a path string:
|
| 261 |
+
|
| 262 |
+
```js
|
| 263 |
+
const tokens = parse("/route/:foo/(.*)");
|
| 264 |
+
|
| 265 |
+
console.log(tokens[0]);
|
| 266 |
+
//=> "/route"
|
| 267 |
+
|
| 268 |
+
console.log(tokens[1]);
|
| 269 |
+
//=> { name: 'foo', prefix: '/', suffix: '', pattern: '[^\\/#\\?]+?', modifier: '' }
|
| 270 |
+
|
| 271 |
+
console.log(tokens[2]);
|
| 272 |
+
//=> { name: 0, prefix: '/', suffix: '', pattern: '.*', modifier: '' }
|
| 273 |
+
```
|
| 274 |
+
|
| 275 |
+
**Note:** This method only works with strings.
|
| 276 |
+
|
| 277 |
+
### Compile ("Reverse" Path-To-RegExp)
|
| 278 |
+
|
| 279 |
+
The `compile` function will return a function for transforming parameters into a valid path:
|
| 280 |
+
|
| 281 |
+
```js
|
| 282 |
+
// Make sure you encode your path segments consistently.
|
| 283 |
+
const toPath = compile("/user/:id", { encode: encodeURIComponent });
|
| 284 |
+
|
| 285 |
+
toPath({ id: 123 }); //=> "/user/123"
|
| 286 |
+
toPath({ id: "café" }); //=> "/user/caf%C3%A9"
|
| 287 |
+
toPath({ id: ":/" }); //=> "/user/%3A%2F"
|
| 288 |
+
|
| 289 |
+
// Without `encode`, you need to make sure inputs are encoded correctly.
|
| 290 |
+
// (Note: You can use `validate: false` to create an invalid paths.)
|
| 291 |
+
const toPathRaw = compile("/user/:id", { validate: false });
|
| 292 |
+
|
| 293 |
+
toPathRaw({ id: "%3A%2F" }); //=> "/user/%3A%2F"
|
| 294 |
+
toPathRaw({ id: ":/" }); //=> "/user/:/"
|
| 295 |
+
|
| 296 |
+
const toPathRepeated = compile("/:segment+");
|
| 297 |
+
|
| 298 |
+
toPathRepeated({ segment: "foo" }); //=> "/foo"
|
| 299 |
+
toPathRepeated({ segment: ["a", "b", "c"] }); //=> "/a/b/c"
|
| 300 |
+
|
| 301 |
+
const toPathRegexp = compile("/user/:id(\\d+)");
|
| 302 |
+
|
| 303 |
+
toPathRegexp({ id: 123 }); //=> "/user/123"
|
| 304 |
+
toPathRegexp({ id: "123" }); //=> "/user/123"
|
| 305 |
+
```
|
| 306 |
+
|
| 307 |
+
**Note:** The generated function will throw on invalid input.
|
| 308 |
+
|
| 309 |
+
### Working with Tokens
|
| 310 |
+
|
| 311 |
+
Path-To-RegExp exposes the two functions used internally that accept an array of tokens:
|
| 312 |
+
|
| 313 |
+
- `tokensToRegexp(tokens, keys?, options?)` Transform an array of tokens into a matching regular expression.
|
| 314 |
+
- `tokensToFunction(tokens)` Transform an array of tokens into a path generator function.
|
| 315 |
+
|
| 316 |
+
#### Token Information
|
| 317 |
+
|
| 318 |
+
- `name` The name of the token (`string` for named or `number` for unnamed index)
|
| 319 |
+
- `prefix` The prefix string for the segment (e.g. `"/"`)
|
| 320 |
+
- `suffix` The suffix string for the segment (e.g. `""`)
|
| 321 |
+
- `pattern` The RegExp used to match this token (`string`)
|
| 322 |
+
- `modifier` The modifier character used for the segment (e.g. `?`)
|
| 323 |
+
|
| 324 |
+
## Compatibility with Express <= 4.x
|
| 325 |
+
|
| 326 |
+
Path-To-RegExp breaks compatibility with Express <= `4.x`:
|
| 327 |
+
|
| 328 |
+
- RegExp special characters can only be used in a parameter
|
| 329 |
+
- Express.js 4.x supported `RegExp` special characters regardless of position - this is considered a bug
|
| 330 |
+
- Parameters have suffixes that augment meaning - `*`, `+` and `?`. E.g. `/:user*`
|
| 331 |
+
- No wildcard asterisk (`*`) - use parameters instead (`(.*)` or `:splat*`)
|
| 332 |
+
|
| 333 |
+
## Live Demo
|
| 334 |
+
|
| 335 |
+
You can see a live demo of this library in use at [express-route-tester](http://forbeslindesay.github.io/express-route-tester/).
|
| 336 |
+
|
| 337 |
+
## License
|
| 338 |
+
|
| 339 |
+
MIT
|
| 340 |
+
|
| 341 |
+
[npm-image]: https://img.shields.io/npm/v/path-to-regexp
|
| 342 |
+
[npm-url]: https://npmjs.org/package/path-to-regexp
|
| 343 |
+
[downloads-image]: https://img.shields.io/npm/dm/path-to-regexp
|
| 344 |
+
[downloads-url]: https://npmjs.org/package/path-to-regexp
|
| 345 |
+
[build-image]: https://img.shields.io/github/actions/workflow/status/pillarjs/path-to-regexp/ci.yml?branch=master
|
| 346 |
+
[build-url]: https://github.com/pillarjs/path-to-regexp/actions/workflows/ci.yml?query=branch%3Amaster
|
| 347 |
+
[coverage-image]: https://img.shields.io/codecov/c/gh/pillarjs/path-to-regexp
|
| 348 |
+
[coverage-url]: https://codecov.io/gh/pillarjs/path-to-regexp
|
| 349 |
+
[license-image]: http://img.shields.io/npm/l/path-to-regexp.svg?style=flat
|
| 350 |
+
[license-url]: LICENSE.md
|
bunx-1000-wrangler@latest/node_modules/pathe/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🛣️ pathe
|
| 2 |
+
|
| 3 |
+
> Universal filesystem path utils
|
| 4 |
+
|
| 5 |
+
[![version][npm-v-src]][npm-v-href]
|
| 6 |
+
[![downloads][npm-d-src]][npm-d-href]
|
| 7 |
+
[![size][size-src]][size-href]
|
| 8 |
+
|
| 9 |
+
## ❓ Why
|
| 10 |
+
|
| 11 |
+
For [historical reasons](https://docs.microsoft.com/en-us/archive/blogs/larryosterman/why-is-the-dos-path-character), windows followed MS-DOS and used backslash for separating paths rather than slash used for macOS, Linux, and other Posix operating systems. Nowadays, [Windows](https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN) supports both Slash and Backslash for paths. [Node.js's built-in `path` module](https://nodejs.org/api/path.html) in the default operation of the path module varies based on the operating system on which a Node.js application is running. Specifically, when running on a Windows operating system, the path module will assume that Windows-style paths are being used. **This makes inconsistent code behavior between Windows and POSIX.**
|
| 12 |
+
|
| 13 |
+
Compared to popular [upath](https://github.com/anodynos/upath), pathe provides **identical exports** of Node.js with normalization on **all operations** and is written in modern **ESM/TypeScript** and has **no dependency on Node.js**!
|
| 14 |
+
|
| 15 |
+
This package is a drop-in replacement of the Node.js's [path module](https://nodejs.org/api/path.html) module and ensures paths are normalized with slash `/` and work in environments including Node.js.
|
| 16 |
+
|
| 17 |
+
## 💿 Usage
|
| 18 |
+
|
| 19 |
+
Install using npm or yarn:
|
| 20 |
+
|
| 21 |
+
```bash
|
| 22 |
+
# npm
|
| 23 |
+
npm i pathe
|
| 24 |
+
|
| 25 |
+
# yarn
|
| 26 |
+
yarn add pathe
|
| 27 |
+
|
| 28 |
+
# pnpm
|
| 29 |
+
pnpm i pathe
|
| 30 |
+
```
|
| 31 |
+
|
| 32 |
+
Import:
|
| 33 |
+
|
| 34 |
+
```js
|
| 35 |
+
// ESM / Typescript
|
| 36 |
+
import { resolve, matchesGlob } from "pathe";
|
| 37 |
+
|
| 38 |
+
// CommonJS
|
| 39 |
+
const { resolve, matchesGlob } = require("pathe");
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
Read more about path utils from [Node.js documentation](https://nodejs.org/api/path.html) and rest assured behavior is consistently like POSIX regardless of your input paths format and running platform (the only exception is `delimiter` constant export, it will be set to `;` on windows platform).
|
| 43 |
+
|
| 44 |
+
### Extra utilities
|
| 45 |
+
|
| 46 |
+
Pathe exports some extra utilities that do not exist in standard Node.js [path module](https://nodejs.org/api/path.html).
|
| 47 |
+
In order to use them, you can import from `pathe/utils` subpath:
|
| 48 |
+
|
| 49 |
+
```js
|
| 50 |
+
import {
|
| 51 |
+
filename,
|
| 52 |
+
normalizeAliases,
|
| 53 |
+
resolveAlias,
|
| 54 |
+
reverseResolveAlias,
|
| 55 |
+
} from "pathe/utils";
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
## License
|
| 59 |
+
|
| 60 |
+
Made with 💛 Published under the [MIT](./LICENSE) license.
|
| 61 |
+
|
| 62 |
+
Some code was used from the Node.js project. Glob supported is powered by [zeptomatch](https://github.com/fabiospampinato/zeptomatch).
|
| 63 |
+
|
| 64 |
+
<!-- Refs -->
|
| 65 |
+
|
| 66 |
+
[npm-v-src]: https://img.shields.io/npm/v/pathe?style=flat-square
|
| 67 |
+
[npm-v-href]: https://npmjs.com/package/pathe
|
| 68 |
+
[npm-d-src]: https://img.shields.io/npm/dm/pathe?style=flat-square
|
| 69 |
+
[npm-d-href]: https://npmjs.com/package/pathe
|
| 70 |
+
[github-actions-src]: https://img.shields.io/github/workflow/status/unjs/pathe/ci/main?style=flat-square
|
| 71 |
+
[github-actions-href]: https://github.com/unjs/pathe/actions?query=workflow%3Aci
|
| 72 |
+
[size-src]: https://packagephobia.now.sh/badge?p=pathe
|
| 73 |
+
[size-href]: https://packagephobia.now.sh/result?p=pathe
|
bunx-1000-wrangler@latest/node_modules/semver/README.md
ADDED
|
@@ -0,0 +1,680 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
semver(1) -- The semantic versioner for npm
|
| 2 |
+
===========================================
|
| 3 |
+
|
| 4 |
+
## Install
|
| 5 |
+
|
| 6 |
+
```bash
|
| 7 |
+
npm install semver
|
| 8 |
+
````
|
| 9 |
+
|
| 10 |
+
## Usage
|
| 11 |
+
|
| 12 |
+
As a node module:
|
| 13 |
+
|
| 14 |
+
```js
|
| 15 |
+
const semver = require('semver')
|
| 16 |
+
|
| 17 |
+
semver.valid('1.2.3') // '1.2.3'
|
| 18 |
+
semver.valid('a.b.c') // null
|
| 19 |
+
semver.clean(' =v1.2.3 ') // '1.2.3'
|
| 20 |
+
semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
|
| 21 |
+
semver.gt('1.2.3', '9.8.7') // false
|
| 22 |
+
semver.lt('1.2.3', '9.8.7') // true
|
| 23 |
+
semver.minVersion('>=1.0.0') // '1.0.0'
|
| 24 |
+
semver.valid(semver.coerce('v2')) // '2.0.0'
|
| 25 |
+
semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7'
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
You can also just load the module for the function that you care about if
|
| 29 |
+
you'd like to minimize your footprint.
|
| 30 |
+
|
| 31 |
+
```js
|
| 32 |
+
// load the whole API at once in a single object
|
| 33 |
+
const semver = require('semver')
|
| 34 |
+
|
| 35 |
+
// or just load the bits you need
|
| 36 |
+
// all of them listed here, just pick and choose what you want
|
| 37 |
+
|
| 38 |
+
// classes
|
| 39 |
+
const SemVer = require('semver/classes/semver')
|
| 40 |
+
const Comparator = require('semver/classes/comparator')
|
| 41 |
+
const Range = require('semver/classes/range')
|
| 42 |
+
|
| 43 |
+
// functions for working with versions
|
| 44 |
+
const semverParse = require('semver/functions/parse')
|
| 45 |
+
const semverValid = require('semver/functions/valid')
|
| 46 |
+
const semverClean = require('semver/functions/clean')
|
| 47 |
+
const semverInc = require('semver/functions/inc')
|
| 48 |
+
const semverDiff = require('semver/functions/diff')
|
| 49 |
+
const semverMajor = require('semver/functions/major')
|
| 50 |
+
const semverMinor = require('semver/functions/minor')
|
| 51 |
+
const semverPatch = require('semver/functions/patch')
|
| 52 |
+
const semverPrerelease = require('semver/functions/prerelease')
|
| 53 |
+
const semverCompare = require('semver/functions/compare')
|
| 54 |
+
const semverRcompare = require('semver/functions/rcompare')
|
| 55 |
+
const semverCompareLoose = require('semver/functions/compare-loose')
|
| 56 |
+
const semverCompareBuild = require('semver/functions/compare-build')
|
| 57 |
+
const semverSort = require('semver/functions/sort')
|
| 58 |
+
const semverRsort = require('semver/functions/rsort')
|
| 59 |
+
const semverTruncate = require('semver/functions/truncate')
|
| 60 |
+
|
| 61 |
+
// low-level comparators between versions
|
| 62 |
+
const semverGt = require('semver/functions/gt')
|
| 63 |
+
const semverLt = require('semver/functions/lt')
|
| 64 |
+
const semverEq = require('semver/functions/eq')
|
| 65 |
+
const semverNeq = require('semver/functions/neq')
|
| 66 |
+
const semverGte = require('semver/functions/gte')
|
| 67 |
+
const semverLte = require('semver/functions/lte')
|
| 68 |
+
const semverCmp = require('semver/functions/cmp')
|
| 69 |
+
const semverCoerce = require('semver/functions/coerce')
|
| 70 |
+
|
| 71 |
+
// working with ranges
|
| 72 |
+
const semverSatisfies = require('semver/functions/satisfies')
|
| 73 |
+
const semverMaxSatisfying = require('semver/ranges/max-satisfying')
|
| 74 |
+
const semverMinSatisfying = require('semver/ranges/min-satisfying')
|
| 75 |
+
const semverToComparators = require('semver/ranges/to-comparators')
|
| 76 |
+
const semverMinVersion = require('semver/ranges/min-version')
|
| 77 |
+
const semverValidRange = require('semver/ranges/valid')
|
| 78 |
+
const semverOutside = require('semver/ranges/outside')
|
| 79 |
+
const semverGtr = require('semver/ranges/gtr')
|
| 80 |
+
const semverLtr = require('semver/ranges/ltr')
|
| 81 |
+
const semverIntersects = require('semver/ranges/intersects')
|
| 82 |
+
const semverSimplifyRange = require('semver/ranges/simplify')
|
| 83 |
+
const semverRangeSubset = require('semver/ranges/subset')
|
| 84 |
+
```
|
| 85 |
+
|
| 86 |
+
As a command-line utility:
|
| 87 |
+
|
| 88 |
+
```
|
| 89 |
+
$ semver -h
|
| 90 |
+
|
| 91 |
+
A JavaScript implementation of the https://semver.org/ specification
|
| 92 |
+
Copyright Isaac Z. Schlueter
|
| 93 |
+
|
| 94 |
+
Usage: semver [options] <version> [<version> [...]]
|
| 95 |
+
Prints valid versions sorted by SemVer precedence
|
| 96 |
+
|
| 97 |
+
Options:
|
| 98 |
+
-r --range <range>
|
| 99 |
+
Print versions that match the specified range.
|
| 100 |
+
|
| 101 |
+
-i --increment [<level>]
|
| 102 |
+
Increment a version by the specified level. Level can
|
| 103 |
+
be one of: major, minor, patch, premajor, preminor,
|
| 104 |
+
prepatch, prerelease, or release. Default level is 'patch'.
|
| 105 |
+
Only one version may be specified.
|
| 106 |
+
|
| 107 |
+
--preid <identifier>
|
| 108 |
+
Identifier to be used to prefix premajor, preminor,
|
| 109 |
+
prepatch or prerelease version increments.
|
| 110 |
+
|
| 111 |
+
-l --loose
|
| 112 |
+
Interpret versions and ranges loosely
|
| 113 |
+
|
| 114 |
+
-n <0|1|false>
|
| 115 |
+
Base number for prerelease identifier (default: 0).
|
| 116 |
+
Use false to omit the number altogether.
|
| 117 |
+
|
| 118 |
+
-p --include-prerelease
|
| 119 |
+
Always include prerelease versions in range matching
|
| 120 |
+
|
| 121 |
+
-c --coerce
|
| 122 |
+
Coerce a string into SemVer if possible
|
| 123 |
+
(does not imply --loose)
|
| 124 |
+
|
| 125 |
+
--rtl
|
| 126 |
+
Coerce version strings right to left
|
| 127 |
+
|
| 128 |
+
--ltr
|
| 129 |
+
Coerce version strings left to right (default)
|
| 130 |
+
|
| 131 |
+
Program exits successfully if any valid version satisfies
|
| 132 |
+
all supplied ranges, and prints all satisfying versions.
|
| 133 |
+
|
| 134 |
+
If no satisfying versions are found, then exits failure.
|
| 135 |
+
|
| 136 |
+
Versions are printed in ascending order, so supplying
|
| 137 |
+
multiple versions to the utility will just sort them.
|
| 138 |
+
```
|
| 139 |
+
|
| 140 |
+
## Versions
|
| 141 |
+
|
| 142 |
+
A "version" is described by the `v2.0.0` specification found at
|
| 143 |
+
<https://semver.org/>.
|
| 144 |
+
|
| 145 |
+
A leading `"="` or `"v"` character is stripped off and ignored.
|
| 146 |
+
Support for stripping a leading "v" is kept for compatibility with `v1.0.0` of the SemVer
|
| 147 |
+
specification but should not be used anymore.
|
| 148 |
+
|
| 149 |
+
## Ranges
|
| 150 |
+
|
| 151 |
+
A `version range` is a set of `comparators` that specify versions
|
| 152 |
+
that satisfy the range.
|
| 153 |
+
|
| 154 |
+
A `comparator` is composed of an `operator` and a `version`. The set
|
| 155 |
+
of primitive `operators` is:
|
| 156 |
+
|
| 157 |
+
* `<` Less than
|
| 158 |
+
* `<=` Less than or equal to
|
| 159 |
+
* `>` Greater than
|
| 160 |
+
* `>=` Greater than or equal to
|
| 161 |
+
* `=` Equal. If no operator is specified, then equality is assumed,
|
| 162 |
+
so this operator is optional but MAY be included.
|
| 163 |
+
|
| 164 |
+
For example, the comparator `>=1.2.7` would match the versions
|
| 165 |
+
`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6`
|
| 166 |
+
or `1.1.0`. The comparator `>1` is equivalent to `>=2.0.0` and
|
| 167 |
+
would match the versions `2.0.0` and `3.1.0`, but not the versions
|
| 168 |
+
`1.0.1` or `1.1.0`.
|
| 169 |
+
|
| 170 |
+
Comparators can be joined by whitespace to form a `comparator set`,
|
| 171 |
+
which is satisfied by the **intersection** of all of the comparators
|
| 172 |
+
it includes.
|
| 173 |
+
|
| 174 |
+
A range is composed of one or more comparator sets, joined by `||`. A
|
| 175 |
+
version matches a range if and only if every comparator in at least
|
| 176 |
+
one of the `||`-separated comparator sets is satisfied by the version.
|
| 177 |
+
|
| 178 |
+
For example, the range `>=1.2.7 <1.3.0` would match the versions
|
| 179 |
+
`1.2.7`, `1.2.8`, and `1.2.99`, but not the versions `1.2.6`, `1.3.0`,
|
| 180 |
+
or `1.1.0`.
|
| 181 |
+
|
| 182 |
+
The range `1.2.7 || >=1.2.9 <2.0.0` would match the versions `1.2.7`,
|
| 183 |
+
`1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0`.
|
| 184 |
+
|
| 185 |
+
### Prerelease Tags
|
| 186 |
+
|
| 187 |
+
If a version has a prerelease tag (for example, `1.2.3-alpha.3`) then
|
| 188 |
+
it will only be allowed to satisfy comparator sets if at least one
|
| 189 |
+
comparator with the same `[major, minor, patch]` tuple also has a
|
| 190 |
+
prerelease tag.
|
| 191 |
+
|
| 192 |
+
For example, the range `>1.2.3-alpha.3` would be allowed to match the
|
| 193 |
+
version `1.2.3-alpha.7`, but it would *not* be satisfied by
|
| 194 |
+
`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater
|
| 195 |
+
than" `1.2.3-alpha.3` according to the SemVer sort rules. The version
|
| 196 |
+
range only accepts prerelease tags on the `1.2.3` version.
|
| 197 |
+
Version `3.4.5` *would* satisfy the range because it does not have a
|
| 198 |
+
prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`.
|
| 199 |
+
|
| 200 |
+
The purpose of this behavior is twofold. First, prerelease versions
|
| 201 |
+
frequently are updated very quickly, and contain many breaking changes
|
| 202 |
+
that are (by the author's design) not yet fit for public consumption.
|
| 203 |
+
Therefore, by default, they are excluded from range-matching
|
| 204 |
+
semantics.
|
| 205 |
+
|
| 206 |
+
Second, a user who has opted into using a prerelease version has
|
| 207 |
+
indicated the intent to use *that specific* set of
|
| 208 |
+
alpha/beta/rc versions. By including a prerelease tag in the range,
|
| 209 |
+
the user is indicating that they are aware of the risk. However, it
|
| 210 |
+
is still not appropriate to assume that they have opted into taking a
|
| 211 |
+
similar risk on the *next* set of prerelease versions.
|
| 212 |
+
|
| 213 |
+
Note that this behavior can be suppressed (treating all prerelease
|
| 214 |
+
versions as if they were normal versions, for range-matching)
|
| 215 |
+
by setting the `includePrerelease` flag on the options
|
| 216 |
+
object to any
|
| 217 |
+
[functions](https://github.com/npm/node-semver#functions) that do
|
| 218 |
+
range matching.
|
| 219 |
+
|
| 220 |
+
#### Prerelease Identifiers
|
| 221 |
+
|
| 222 |
+
The method `.inc` takes an additional `identifier` string argument that
|
| 223 |
+
will append the value of the string as a prerelease identifier:
|
| 224 |
+
|
| 225 |
+
```javascript
|
| 226 |
+
semver.inc('1.2.3', 'prerelease', 'beta')
|
| 227 |
+
// '1.2.4-beta.0'
|
| 228 |
+
```
|
| 229 |
+
|
| 230 |
+
command-line example:
|
| 231 |
+
|
| 232 |
+
```bash
|
| 233 |
+
$ semver 1.2.3 -i prerelease --preid beta
|
| 234 |
+
1.2.4-beta.0
|
| 235 |
+
```
|
| 236 |
+
|
| 237 |
+
Which then can be used to increment further:
|
| 238 |
+
|
| 239 |
+
```bash
|
| 240 |
+
$ semver 1.2.4-beta.0 -i prerelease
|
| 241 |
+
1.2.4-beta.1
|
| 242 |
+
```
|
| 243 |
+
|
| 244 |
+
To get out of the prerelease phase, use the `release` option:
|
| 245 |
+
|
| 246 |
+
```bash
|
| 247 |
+
$ semver 1.2.4-beta.1 -i release
|
| 248 |
+
1.2.4
|
| 249 |
+
```
|
| 250 |
+
|
| 251 |
+
#### Prerelease Identifier Base
|
| 252 |
+
|
| 253 |
+
The method `.inc` takes an optional parameter 'identifierBase' string
|
| 254 |
+
that will let you let your prerelease number as zero-based or one-based.
|
| 255 |
+
Set to `false` to omit the prerelease number altogether.
|
| 256 |
+
If you do not specify this parameter, it will default to zero-based.
|
| 257 |
+
|
| 258 |
+
```javascript
|
| 259 |
+
semver.inc('1.2.3', 'prerelease', 'beta', '1')
|
| 260 |
+
// '1.2.4-beta.1'
|
| 261 |
+
```
|
| 262 |
+
|
| 263 |
+
```javascript
|
| 264 |
+
semver.inc('1.2.3', 'prerelease', 'beta', false)
|
| 265 |
+
// '1.2.4-beta'
|
| 266 |
+
```
|
| 267 |
+
|
| 268 |
+
command-line example:
|
| 269 |
+
|
| 270 |
+
```bash
|
| 271 |
+
$ semver 1.2.3 -i prerelease --preid beta -n 1
|
| 272 |
+
1.2.4-beta.1
|
| 273 |
+
```
|
| 274 |
+
|
| 275 |
+
```bash
|
| 276 |
+
$ semver 1.2.3 -i prerelease --preid beta -n false
|
| 277 |
+
1.2.4-beta
|
| 278 |
+
```
|
| 279 |
+
|
| 280 |
+
### Advanced Range Syntax
|
| 281 |
+
|
| 282 |
+
Advanced range syntax desugars to primitive comparators in
|
| 283 |
+
deterministic ways.
|
| 284 |
+
|
| 285 |
+
Advanced ranges may be combined in the same way as primitive
|
| 286 |
+
comparators using white space or `||`.
|
| 287 |
+
|
| 288 |
+
#### Hyphen Ranges `X.Y.Z - A.B.C`
|
| 289 |
+
|
| 290 |
+
Specifies an inclusive set.
|
| 291 |
+
|
| 292 |
+
* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`
|
| 293 |
+
|
| 294 |
+
If a partial version is provided as the first version in the inclusive
|
| 295 |
+
range, then the missing pieces are replaced with zeroes.
|
| 296 |
+
|
| 297 |
+
* `1.2 - 2.3.4` := `>=1.2.0 <=2.3.4`
|
| 298 |
+
|
| 299 |
+
If a partial version is provided as the second version in the
|
| 300 |
+
inclusive range, then all versions that start with the supplied parts
|
| 301 |
+
of the tuple are accepted, but nothing that would be greater than the
|
| 302 |
+
provided tuple parts.
|
| 303 |
+
|
| 304 |
+
* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0-0`
|
| 305 |
+
* `1.2.3 - 2` := `>=1.2.3 <3.0.0-0`
|
| 306 |
+
|
| 307 |
+
#### X-Ranges `1.2.x` `1.X` `1.2.*` `*`
|
| 308 |
+
|
| 309 |
+
Any of `X`, `x`, or `*` may be used to "stand in" for one of the
|
| 310 |
+
numeric values in the `[major, minor, patch]` tuple.
|
| 311 |
+
|
| 312 |
+
* `*` := `>=0.0.0` (Any non-prerelease version satisfies, unless
|
| 313 |
+
`includePrerelease` is specified, in which case any version at all
|
| 314 |
+
satisfies)
|
| 315 |
+
* `1.x` := `>=1.0.0 <2.0.0-0` (Matching major version)
|
| 316 |
+
* `1.2.x` := `>=1.2.0 <1.3.0-0` (Matching major and minor versions)
|
| 317 |
+
|
| 318 |
+
A partial version range is treated as an X-Range, so the special
|
| 319 |
+
character is in fact optional.
|
| 320 |
+
|
| 321 |
+
* `""` (empty string) := `*` := `>=0.0.0`
|
| 322 |
+
* `1` := `1.x.x` := `>=1.0.0 <2.0.0-0`
|
| 323 |
+
* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0-0`
|
| 324 |
+
|
| 325 |
+
#### Tilde Ranges `~1.2.3` `~1.2` `~1`
|
| 326 |
+
|
| 327 |
+
Allows patch-level changes if a minor version is specified on the
|
| 328 |
+
comparator. Allows minor-level changes if not.
|
| 329 |
+
|
| 330 |
+
* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0-0`
|
| 331 |
+
* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0-0` (Same as `1.2.x`)
|
| 332 |
+
* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0-0` (Same as `1.x`)
|
| 333 |
+
* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0-0`
|
| 334 |
+
* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0-0` (Same as `0.2.x`)
|
| 335 |
+
* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0-0` (Same as `0.x`)
|
| 336 |
+
* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0-0` Note that prereleases in
|
| 337 |
+
the `1.2.3` version will be allowed, if they are greater than or
|
| 338 |
+
equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but
|
| 339 |
+
`1.2.4-beta.2` would not, because it is a prerelease of a
|
| 340 |
+
different `[major, minor, patch]` tuple.
|
| 341 |
+
|
| 342 |
+
#### Caret Ranges `^1.2.3` `^0.2.5` `^0.0.4`
|
| 343 |
+
|
| 344 |
+
Allows changes that do not modify the left-most non-zero element in the
|
| 345 |
+
`[major, minor, patch]` tuple. In other words, this allows patch and
|
| 346 |
+
minor updates for versions `1.0.0` and above, patch updates for
|
| 347 |
+
versions `0.X >=0.1.0`, and *no* updates for versions `0.0.X`.
|
| 348 |
+
|
| 349 |
+
Many authors treat a `0.x` version as if the `x` were the major
|
| 350 |
+
"breaking-change" indicator.
|
| 351 |
+
|
| 352 |
+
Caret ranges are ideal when an author may make breaking changes
|
| 353 |
+
between `0.2.4` and `0.3.0` releases, which is a common practice.
|
| 354 |
+
However, it presumes that there will *not* be breaking changes between
|
| 355 |
+
`0.2.4` and `0.2.5`. It allows for changes that are presumed to be
|
| 356 |
+
additive (but non-breaking), according to commonly observed practices.
|
| 357 |
+
|
| 358 |
+
* `^1.2.3` := `>=1.2.3 <2.0.0-0`
|
| 359 |
+
* `^0.2.3` := `>=0.2.3 <0.3.0-0`
|
| 360 |
+
* `^0.0.3` := `>=0.0.3 <0.0.4-0`
|
| 361 |
+
* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0-0` Note that prereleases in
|
| 362 |
+
the `1.2.3` version will be allowed, if they are greater than or
|
| 363 |
+
equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but
|
| 364 |
+
`1.2.4-beta.2` would not, because it is a prerelease of a
|
| 365 |
+
different `[major, minor, patch]` tuple.
|
| 366 |
+
* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4-0` Note that prereleases in the
|
| 367 |
+
`0.0.3` version *only* will be allowed, if they are greater than or
|
| 368 |
+
equal to `beta`. So, `0.0.3-pr.2` would be allowed.
|
| 369 |
+
|
| 370 |
+
When parsing caret ranges, a missing `patch` value desugars to the
|
| 371 |
+
number `0`, but will allow flexibility within that value, even if the
|
| 372 |
+
major and minor versions are both `0`.
|
| 373 |
+
|
| 374 |
+
* `^1.2.x` := `>=1.2.0 <2.0.0-0`
|
| 375 |
+
* `^0.0.x` := `>=0.0.0 <0.1.0-0`
|
| 376 |
+
* `^0.0` := `>=0.0.0 <0.1.0-0`
|
| 377 |
+
|
| 378 |
+
A missing `minor` and `patch` values will desugar to zero, but also
|
| 379 |
+
allow flexibility within those values, even if the major version is
|
| 380 |
+
zero.
|
| 381 |
+
|
| 382 |
+
* `^1.x` := `>=1.0.0 <2.0.0-0`
|
| 383 |
+
* `^0.x` := `>=0.0.0 <1.0.0-0`
|
| 384 |
+
|
| 385 |
+
### Range Grammar
|
| 386 |
+
|
| 387 |
+
Putting all this together, here is a Backus-Naur grammar for ranges,
|
| 388 |
+
for the benefit of parser authors:
|
| 389 |
+
|
| 390 |
+
```bnf
|
| 391 |
+
range-set ::= range ( logical-or range ) *
|
| 392 |
+
logical-or ::= ( ' ' ) * '||' ( ' ' ) *
|
| 393 |
+
range ::= hyphen | simple ( ' ' simple ) * | ''
|
| 394 |
+
hyphen ::= partial ' - ' partial
|
| 395 |
+
simple ::= primitive | partial | tilde | caret
|
| 396 |
+
primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial
|
| 397 |
+
partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )?
|
| 398 |
+
xr ::= 'x' | 'X' | '*' | nr
|
| 399 |
+
nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) *
|
| 400 |
+
tilde ::= '~' partial
|
| 401 |
+
caret ::= '^' partial
|
| 402 |
+
qualifier ::= ( '-' pre )? ( '+' build )?
|
| 403 |
+
pre ::= prepart ( '.' prepart ) *
|
| 404 |
+
prepart ::= nr | alphanumid
|
| 405 |
+
build ::= buildid ( '.' buildid ) *
|
| 406 |
+
alphanumid ::= ( ['0'-'9'] ) * [-A-Za-z] [-0-9A-Za-z] *
|
| 407 |
+
buildid ::= [-0-9A-Za-z]+
|
| 408 |
+
```
|
| 409 |
+
|
| 410 |
+
Note: Prerelease identifiers (`pre`) use `nr` for numeric parts, which
|
| 411 |
+
disallows leading zeros (e.g., `1.2.3-00` is invalid). Build metadata
|
| 412 |
+
identifiers (`build`) allow any alphanumeric string including leading
|
| 413 |
+
zeros (e.g., `1.2.3+00` is valid). This matches the
|
| 414 |
+
[SemVer 2.0.0 specification](https://semver.org/#spec-item-9).
|
| 415 |
+
|
| 416 |
+
## Functions
|
| 417 |
+
|
| 418 |
+
All methods and classes take a final `options` object argument. All
|
| 419 |
+
options in this object are `false` by default. The options supported
|
| 420 |
+
are:
|
| 421 |
+
|
| 422 |
+
- `loose`: Be more forgiving about not-quite-valid semver strings.
|
| 423 |
+
(Any resulting output will always be 100% strict compliant, of
|
| 424 |
+
course.) For backwards compatibility reasons, if the `options`
|
| 425 |
+
argument is a boolean value instead of an object, it is interpreted
|
| 426 |
+
to be the `loose` param.
|
| 427 |
+
- `includePrerelease`: Set to suppress the [default
|
| 428 |
+
behavior](https://github.com/npm/node-semver#prerelease-tags) of
|
| 429 |
+
excluding prerelease tagged versions from ranges unless they are
|
| 430 |
+
explicitly opted into.
|
| 431 |
+
|
| 432 |
+
Strict-mode Comparators and Ranges will be strict about the SemVer
|
| 433 |
+
strings that they parse.
|
| 434 |
+
|
| 435 |
+
* `valid(v)`: Return the parsed version, or null if it's not valid.
|
| 436 |
+
* `inc(v, releaseType, options, identifier, identifierBase)`:
|
| 437 |
+
Return the version incremented by the release
|
| 438 |
+
type (`major`, `premajor`, `minor`, `preminor`, `patch`,
|
| 439 |
+
`prepatch`, `prerelease`, or `release`), or null if it's not valid
|
| 440 |
+
* `premajor` in one call will bump the version up to the next major
|
| 441 |
+
version and down to a prerelease of that major version.
|
| 442 |
+
`preminor`, and `prepatch` work the same way.
|
| 443 |
+
* If called from a non-prerelease version, `prerelease` will work the
|
| 444 |
+
same as `prepatch`. It increments the patch version and then makes a
|
| 445 |
+
prerelease. If the input version is already a prerelease it simply
|
| 446 |
+
increments it.
|
| 447 |
+
* `release` will remove any prerelease part of the version.
|
| 448 |
+
* `identifier` can be used to prefix `premajor`, `preminor`,
|
| 449 |
+
`prepatch`, or `prerelease` version increments. `identifierBase`
|
| 450 |
+
is the base to be used for the `prerelease` identifier.
|
| 451 |
+
* `prerelease(v)`: Returns an array of prerelease components, or null
|
| 452 |
+
if none exist. Example: `prerelease('1.2.3-alpha.1') -> ['alpha', 1]`
|
| 453 |
+
* `major(v)`: Return the major version number.
|
| 454 |
+
* `minor(v)`: Return the minor version number.
|
| 455 |
+
* `patch(v)`: Return the patch version number.
|
| 456 |
+
* `intersects(r1, r2, loose)`: Return true if the two supplied ranges
|
| 457 |
+
or comparators intersect.
|
| 458 |
+
* `parse(v)`: Attempt to parse a string as a semantic version, returning either
|
| 459 |
+
a `SemVer` object or `null`.
|
| 460 |
+
* `truncate(v, releaseType)`: Return the version with components _lower_
|
| 461 |
+
than `releaseType` dropped off, e.g.:
|
| 462 |
+
* `major` removes build & prerelease info and sets minor & patch to 0.
|
| 463 |
+
* `minor` removes build & prerelease info, and sets patch to 0
|
| 464 |
+
* `patch` removes build & prerelease info
|
| 465 |
+
* All prerelease types remove build info only
|
| 466 |
+
|
| 467 |
+
### Comparison
|
| 468 |
+
|
| 469 |
+
* `gt(v1, v2)`: `v1 > v2`
|
| 470 |
+
* `gte(v1, v2)`: `v1 >= v2`
|
| 471 |
+
* `lt(v1, v2)`: `v1 < v2`
|
| 472 |
+
* `lte(v1, v2)`: `v1 <= v2`
|
| 473 |
+
* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent,
|
| 474 |
+
even if they're not the same string. You already know how to
|
| 475 |
+
compare strings.
|
| 476 |
+
* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`.
|
| 477 |
+
* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call
|
| 478 |
+
the corresponding function above. `"==="` and `"!=="` do simple
|
| 479 |
+
string comparison, but are included for completeness. Throws if an
|
| 480 |
+
invalid comparison string is provided.
|
| 481 |
+
* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if
|
| 482 |
+
`v2` is greater. Sorts in ascending order if passed to `Array.sort()`.
|
| 483 |
+
* `rcompare(v1, v2)`: The reverse of `compare`. Sorts an array of versions
|
| 484 |
+
in descending order when passed to `Array.sort()`.
|
| 485 |
+
* `compareBuild(v1, v2)`: The same as `compare` but considers `build` when two versions
|
| 486 |
+
are equal. Sorts in ascending order if passed to `Array.sort()`.
|
| 487 |
+
* `compareLoose(v1, v2)`: Short for `compare(v1, v2, { loose: true })`.
|
| 488 |
+
* `diff(v1, v2)`: Returns the difference between two versions by the release type
|
| 489 |
+
(`major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, or `prerelease`),
|
| 490 |
+
or null if the versions are the same.
|
| 491 |
+
|
| 492 |
+
### Sorting
|
| 493 |
+
|
| 494 |
+
* `sort(versions)`: Returns a sorted array of versions based on the `compareBuild`
|
| 495 |
+
function.
|
| 496 |
+
* `rsort(versions)`: The reverse of `sort`. Returns an array of versions based on
|
| 497 |
+
the `compareBuild` function in descending order.
|
| 498 |
+
|
| 499 |
+
### Comparators
|
| 500 |
+
|
| 501 |
+
* `intersects(comparator)`: Return true if the comparators intersect
|
| 502 |
+
|
| 503 |
+
### Ranges
|
| 504 |
+
|
| 505 |
+
* `validRange(range)`: Return the valid range or null if it's not valid.
|
| 506 |
+
* `satisfies(version, range)`: Return true if the version satisfies the
|
| 507 |
+
range.
|
| 508 |
+
* `maxSatisfying(versions, range)`: Return the highest version in the list
|
| 509 |
+
that satisfies the range, or `null` if none of them do.
|
| 510 |
+
* `minSatisfying(versions, range)`: Return the lowest version in the list
|
| 511 |
+
that satisfies the range, or `null` if none of them do.
|
| 512 |
+
* `minVersion(range)`: Return the lowest version that can match
|
| 513 |
+
the given range.
|
| 514 |
+
* `gtr(version, range)`: Return `true` if the version is greater than all the
|
| 515 |
+
versions possible in the range.
|
| 516 |
+
* `ltr(version, range)`: Return `true` if the version is less than all the
|
| 517 |
+
versions possible in the range.
|
| 518 |
+
* `outside(version, range, hilo)`: Return true if the version is outside
|
| 519 |
+
the bounds of the range in either the high or low direction. The
|
| 520 |
+
`hilo` argument must be either the string `'>'` or `'<'`. (This is
|
| 521 |
+
the function called by `gtr` and `ltr`.)
|
| 522 |
+
* `intersects(range)`: Return true if any of the range comparators intersect.
|
| 523 |
+
* `simplifyRange(versions, range)`: Return a "simplified" range that
|
| 524 |
+
matches the same items in the `versions` list as the range specified. Note
|
| 525 |
+
that it does *not* guarantee that it would match the same versions in all
|
| 526 |
+
cases, only for the set of versions provided. This is useful when
|
| 527 |
+
generating ranges by joining together multiple versions with `||`
|
| 528 |
+
programmatically, to provide the user with something a bit more
|
| 529 |
+
ergonomic. If the provided range is shorter in string-length than the
|
| 530 |
+
generated range, then that is returned.
|
| 531 |
+
* `subset(subRange, superRange)`: Return `true` if the `subRange` range is
|
| 532 |
+
entirely contained by the `superRange` range.
|
| 533 |
+
|
| 534 |
+
Note that, since ranges may be non-contiguous, a version might not be
|
| 535 |
+
greater than a range, less than a range, *or* satisfy a range! For
|
| 536 |
+
example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9`
|
| 537 |
+
until `2.0.0`, so version `1.2.10` would not be greater than the
|
| 538 |
+
range (because `2.0.1` satisfies, which is higher), nor less than the
|
| 539 |
+
range (since `1.2.8` satisfies, which is lower), and it also does not
|
| 540 |
+
satisfy the range.
|
| 541 |
+
|
| 542 |
+
If you want to know if a version satisfies or does not satisfy a
|
| 543 |
+
range, use the `satisfies(version, range)` function.
|
| 544 |
+
|
| 545 |
+
### Coercion
|
| 546 |
+
|
| 547 |
+
* `coerce(version, options)`: Coerces a string to semver if possible
|
| 548 |
+
|
| 549 |
+
This aims to provide a very forgiving translation of a non-semver string to
|
| 550 |
+
semver. It looks for the first digit in a string and consumes all
|
| 551 |
+
remaining characters which satisfy at least a partial semver (e.g., `1`,
|
| 552 |
+
`1.2`, `1.2.3`) up to the max permitted length (256 characters). Longer
|
| 553 |
+
versions are simply truncated (`4.6.3.9.2-alpha2` becomes `4.6.3`). All
|
| 554 |
+
surrounding text is simply ignored (`v3.4 replaces v3.3.1` becomes
|
| 555 |
+
`3.4.0`). Only text which lacks digits will fail coercion (`version one`
|
| 556 |
+
is not valid). The maximum length for any semver component considered for
|
| 557 |
+
coercion is 16 characters; longer components will be ignored
|
| 558 |
+
(`10000000000000000.4.7.4` becomes `4.7.4`). The maximum value for any
|
| 559 |
+
semver component is `Number.MAX_SAFE_INTEGER || (2**53 - 1)`; higher value
|
| 560 |
+
components are invalid (`9999999999999999.4.7.4` is likely invalid).
|
| 561 |
+
|
| 562 |
+
If the `options.rtl` flag is set, then `coerce` will return the right-most
|
| 563 |
+
coercible tuple that does not share an ending index with a longer coercible
|
| 564 |
+
tuple. For example, `1.2.3.4` will return `2.3.4` in rtl mode, not
|
| 565 |
+
`4.0.0`. `1.2.3/4` will return `4.0.0`, because the `4` is not a part of
|
| 566 |
+
any other overlapping SemVer tuple.
|
| 567 |
+
|
| 568 |
+
If the `options.includePrerelease` flag is set, then the `coerce` result will contain
|
| 569 |
+
prerelease and build parts of a version. For example, `1.2.3.4-rc.1+rev.2`
|
| 570 |
+
will preserve prerelease `rc.1` and build `rev.2` in the result.
|
| 571 |
+
|
| 572 |
+
### Clean
|
| 573 |
+
|
| 574 |
+
* `clean(version)`: Clean a string to be a valid semver if possible
|
| 575 |
+
|
| 576 |
+
This will return a cleaned and trimmed semver version. If the provided
|
| 577 |
+
version is not valid a null will be returned. This does not work for
|
| 578 |
+
ranges.
|
| 579 |
+
|
| 580 |
+
ex.
|
| 581 |
+
* `s.clean(' = v 2.1.5foo')`: `null`
|
| 582 |
+
* `s.clean(' = v 2.1.5foo', { loose: true })`: `'2.1.5-foo'`
|
| 583 |
+
* `s.clean(' = v 2.1.5-foo')`: `null`
|
| 584 |
+
* `s.clean(' = v 2.1.5-foo', { loose: true })`: `'2.1.5-foo'`
|
| 585 |
+
* `s.clean('=v2.1.5')`: `'2.1.5'`
|
| 586 |
+
* `s.clean(' =v2.1.5')`: `'2.1.5'`
|
| 587 |
+
* `s.clean(' 2.1.5 ')`: `'2.1.5'`
|
| 588 |
+
* `s.clean('~1.0.0')`: `null`
|
| 589 |
+
|
| 590 |
+
## Constants
|
| 591 |
+
|
| 592 |
+
As a convenience, helper constants are exported to provide information about what `node-semver` supports:
|
| 593 |
+
|
| 594 |
+
### `RELEASE_TYPES`
|
| 595 |
+
|
| 596 |
+
- major
|
| 597 |
+
- premajor
|
| 598 |
+
- minor
|
| 599 |
+
- preminor
|
| 600 |
+
- patch
|
| 601 |
+
- prepatch
|
| 602 |
+
- prerelease
|
| 603 |
+
|
| 604 |
+
```
|
| 605 |
+
const semver = require('semver');
|
| 606 |
+
|
| 607 |
+
if (semver.RELEASE_TYPES.includes(arbitraryUserInput)) {
|
| 608 |
+
console.log('This is a valid release type!');
|
| 609 |
+
} else {
|
| 610 |
+
console.warn('This is NOT a valid release type!');
|
| 611 |
+
}
|
| 612 |
+
```
|
| 613 |
+
|
| 614 |
+
### `SEMVER_SPEC_VERSION`
|
| 615 |
+
|
| 616 |
+
2.0.0
|
| 617 |
+
|
| 618 |
+
```
|
| 619 |
+
const semver = require('semver');
|
| 620 |
+
|
| 621 |
+
console.log('We are currently using the semver specification version:', semver.SEMVER_SPEC_VERSION);
|
| 622 |
+
```
|
| 623 |
+
|
| 624 |
+
## Exported Modules
|
| 625 |
+
|
| 626 |
+
<!--
|
| 627 |
+
TODO: Make sure that all of these items are documented (classes aren't,
|
| 628 |
+
eg), and then pull the module name into the documentation for that specific
|
| 629 |
+
thing.
|
| 630 |
+
-->
|
| 631 |
+
|
| 632 |
+
You may pull in just the part of this semver utility that you need if you
|
| 633 |
+
are sensitive to packing and tree-shaking concerns. The main
|
| 634 |
+
`require('semver')` export uses getter functions to lazily load the parts
|
| 635 |
+
of the API that are used.
|
| 636 |
+
|
| 637 |
+
The following modules are available:
|
| 638 |
+
|
| 639 |
+
* `require('semver')`
|
| 640 |
+
* `require('semver/classes')`
|
| 641 |
+
* `require('semver/classes/comparator')`
|
| 642 |
+
* `require('semver/classes/range')`
|
| 643 |
+
* `require('semver/classes/semver')`
|
| 644 |
+
* `require('semver/functions/clean')`
|
| 645 |
+
* `require('semver/functions/cmp')`
|
| 646 |
+
* `require('semver/functions/coerce')`
|
| 647 |
+
* `require('semver/functions/compare')`
|
| 648 |
+
* `require('semver/functions/compare-build')`
|
| 649 |
+
* `require('semver/functions/compare-loose')`
|
| 650 |
+
* `require('semver/functions/diff')`
|
| 651 |
+
* `require('semver/functions/eq')`
|
| 652 |
+
* `require('semver/functions/gt')`
|
| 653 |
+
* `require('semver/functions/gte')`
|
| 654 |
+
* `require('semver/functions/inc')`
|
| 655 |
+
* `require('semver/functions/lt')`
|
| 656 |
+
* `require('semver/functions/lte')`
|
| 657 |
+
* `require('semver/functions/major')`
|
| 658 |
+
* `require('semver/functions/minor')`
|
| 659 |
+
* `require('semver/functions/neq')`
|
| 660 |
+
* `require('semver/functions/parse')`
|
| 661 |
+
* `require('semver/functions/patch')`
|
| 662 |
+
* `require('semver/functions/prerelease')`
|
| 663 |
+
* `require('semver/functions/rcompare')`
|
| 664 |
+
* `require('semver/functions/rsort')`
|
| 665 |
+
* `require('semver/functions/satisfies')`
|
| 666 |
+
* `require('semver/functions/sort')`
|
| 667 |
+
* `require('semver/functions/truncate')`
|
| 668 |
+
* `require('semver/functions/valid')`
|
| 669 |
+
* `require('semver/ranges/gtr')`
|
| 670 |
+
* `require('semver/ranges/intersects')`
|
| 671 |
+
* `require('semver/ranges/ltr')`
|
| 672 |
+
* `require('semver/ranges/max-satisfying')`
|
| 673 |
+
* `require('semver/ranges/min-satisfying')`
|
| 674 |
+
* `require('semver/ranges/min-version')`
|
| 675 |
+
* `require('semver/ranges/outside')`
|
| 676 |
+
* `require('semver/ranges/simplify')`
|
| 677 |
+
* `require('semver/ranges/subset')`
|
| 678 |
+
* `require('semver/ranges/to-comparators')`
|
| 679 |
+
* `require('semver/ranges/valid')`
|
| 680 |
+
|
bunx-1000-wrangler@latest/node_modules/sharp/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# sharp
|
| 2 |
+
|
| 3 |
+
<img src="https://sharp.pixelplumbing.com/sharp-logo.svg" width="160" height="160" alt="sharp logo" align="right">
|
| 4 |
+
|
| 5 |
+
The typical use case for this high speed Node-API module
|
| 6 |
+
is to convert large images in common formats to
|
| 7 |
+
smaller, web-friendly JPEG, PNG, WebP, GIF and AVIF images of varying dimensions.
|
| 8 |
+
|
| 9 |
+
It can be used with all JavaScript runtimes
|
| 10 |
+
that provide support for Node-API v9, including
|
| 11 |
+
Node.js (^18.17.0 or >= 20.3.0), Deno and Bun.
|
| 12 |
+
|
| 13 |
+
Resizing an image is typically 4x-5x faster than using the
|
| 14 |
+
quickest ImageMagick and GraphicsMagick settings
|
| 15 |
+
due to its use of [libvips](https://github.com/libvips/libvips).
|
| 16 |
+
|
| 17 |
+
Colour spaces, embedded ICC profiles and alpha transparency channels are all handled correctly.
|
| 18 |
+
Lanczos resampling ensures quality is not sacrificed for speed.
|
| 19 |
+
|
| 20 |
+
As well as image resizing, operations such as
|
| 21 |
+
rotation, extraction, compositing and gamma correction are available.
|
| 22 |
+
|
| 23 |
+
Most modern macOS, Windows and Linux systems
|
| 24 |
+
do not require any additional install or runtime dependencies.
|
| 25 |
+
|
| 26 |
+
## Documentation
|
| 27 |
+
|
| 28 |
+
Visit [sharp.pixelplumbing.com](https://sharp.pixelplumbing.com/) for complete
|
| 29 |
+
[installation instructions](https://sharp.pixelplumbing.com/install),
|
| 30 |
+
[API documentation](https://sharp.pixelplumbing.com/api-constructor),
|
| 31 |
+
[benchmark tests](https://sharp.pixelplumbing.com/performance) and
|
| 32 |
+
[changelog](https://sharp.pixelplumbing.com/changelog).
|
| 33 |
+
|
| 34 |
+
## Examples
|
| 35 |
+
|
| 36 |
+
```sh
|
| 37 |
+
npm install sharp
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
```javascript
|
| 41 |
+
const sharp = require('sharp');
|
| 42 |
+
```
|
| 43 |
+
|
| 44 |
+
### Callback
|
| 45 |
+
|
| 46 |
+
```javascript
|
| 47 |
+
sharp(inputBuffer)
|
| 48 |
+
.resize(320, 240)
|
| 49 |
+
.toFile('output.webp', (err, info) => { ... });
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
### Promise
|
| 53 |
+
|
| 54 |
+
```javascript
|
| 55 |
+
sharp('input.jpg')
|
| 56 |
+
.rotate()
|
| 57 |
+
.resize(200)
|
| 58 |
+
.jpeg({ mozjpeg: true })
|
| 59 |
+
.toBuffer()
|
| 60 |
+
.then( data => { ... })
|
| 61 |
+
.catch( err => { ... });
|
| 62 |
+
```
|
| 63 |
+
|
| 64 |
+
### Async/await
|
| 65 |
+
|
| 66 |
+
```javascript
|
| 67 |
+
const semiTransparentRedPng = await sharp({
|
| 68 |
+
create: {
|
| 69 |
+
width: 48,
|
| 70 |
+
height: 48,
|
| 71 |
+
channels: 4,
|
| 72 |
+
background: { r: 255, g: 0, b: 0, alpha: 0.5 }
|
| 73 |
+
}
|
| 74 |
+
})
|
| 75 |
+
.png()
|
| 76 |
+
.toBuffer();
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
### Stream
|
| 80 |
+
|
| 81 |
+
```javascript
|
| 82 |
+
const roundedCorners = Buffer.from(
|
| 83 |
+
'<svg><rect x="0" y="0" width="200" height="200" rx="50" ry="50"/></svg>'
|
| 84 |
+
);
|
| 85 |
+
|
| 86 |
+
const roundedCornerResizer =
|
| 87 |
+
sharp()
|
| 88 |
+
.resize(200, 200)
|
| 89 |
+
.composite([{
|
| 90 |
+
input: roundedCorners,
|
| 91 |
+
blend: 'dest-in'
|
| 92 |
+
}])
|
| 93 |
+
.png();
|
| 94 |
+
|
| 95 |
+
readableStream
|
| 96 |
+
.pipe(roundedCornerResizer)
|
| 97 |
+
.pipe(writableStream);
|
| 98 |
+
```
|
| 99 |
+
|
| 100 |
+
## Contributing
|
| 101 |
+
|
| 102 |
+
A [guide for contributors](https://github.com/lovell/sharp/blob/main/.github/CONTRIBUTING.md)
|
| 103 |
+
covers reporting bugs, requesting features and submitting code changes.
|
| 104 |
+
|
| 105 |
+
## Licensing
|
| 106 |
+
|
| 107 |
+
Copyright 2013 Lovell Fuller and others.
|
| 108 |
+
|
| 109 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 110 |
+
you may not use this file except in compliance with the License.
|
| 111 |
+
You may obtain a copy of the License at
|
| 112 |
+
[https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
| 113 |
+
|
| 114 |
+
Unless required by applicable law or agreed to in writing, software
|
| 115 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 116 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 117 |
+
See the License for the specific language governing permissions and
|
| 118 |
+
limitations under the License.
|
bunx-1000-wrangler@latest/node_modules/supports-color/readme.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# supports-color
|
| 2 |
+
|
| 3 |
+
> Detect whether a terminal supports color
|
| 4 |
+
|
| 5 |
+
## Install
|
| 6 |
+
|
| 7 |
+
```sh
|
| 8 |
+
npm install supports-color
|
| 9 |
+
```
|
| 10 |
+
|
| 11 |
+
## Usage
|
| 12 |
+
|
| 13 |
+
```js
|
| 14 |
+
import supportsColor from 'supports-color';
|
| 15 |
+
|
| 16 |
+
if (supportsColor.stdout) {
|
| 17 |
+
console.log('Terminal stdout supports color');
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
if (supportsColor.stdout.has256) {
|
| 21 |
+
console.log('Terminal stdout supports 256 colors');
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
if (supportsColor.stderr.has16m) {
|
| 25 |
+
console.log('Terminal stderr supports 16 million colors (truecolor)');
|
| 26 |
+
}
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
## API
|
| 30 |
+
|
| 31 |
+
Returns an `object` with a `stdout` and `stderr` property for testing either streams. Each property is an `Object`, or `false` if color is not supported.
|
| 32 |
+
|
| 33 |
+
The `stdout`/`stderr` objects specifies a level of support for color through a `.level` property and a corresponding flag:
|
| 34 |
+
|
| 35 |
+
- `.level = 1` and `.hasBasic = true`: Basic color support (16 colors)
|
| 36 |
+
- `.level = 2` and `.has256 = true`: 256 color support
|
| 37 |
+
- `.level = 3` and `.has16m = true`: Truecolor support (16 million colors)
|
| 38 |
+
|
| 39 |
+
### Custom instance
|
| 40 |
+
|
| 41 |
+
The package also exposes the named export `createSupportColor` function that takes an arbitrary write stream (for example, `process.stdout`) and an optional options object to (re-)evaluate color support for an arbitrary stream.
|
| 42 |
+
|
| 43 |
+
```js
|
| 44 |
+
import {createSupportsColor} from 'supports-color';
|
| 45 |
+
|
| 46 |
+
const stdoutSupportsColor = createSupportsColor(process.stdout);
|
| 47 |
+
|
| 48 |
+
if (stdoutSupportsColor) {
|
| 49 |
+
console.log('Terminal stdout supports color');
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
// `stdoutSupportsColor` is the same as `supportsColor.stdout`
|
| 53 |
+
```
|
| 54 |
+
|
| 55 |
+
The options object supports a single boolean property `sniffFlags`. By default it is `true`, which instructs the detection to sniff `process.argv` for the multitude of `--color` flags (see _Info_ below). If `false`, then `process.argv` is not considered when determining color support.
|
| 56 |
+
|
| 57 |
+
## Info
|
| 58 |
+
|
| 59 |
+
It obeys the `--color` and `--no-color` CLI flags.
|
| 60 |
+
|
| 61 |
+
For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
|
| 62 |
+
|
| 63 |
+
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
|
| 64 |
+
|
| 65 |
+
## Related
|
| 66 |
+
|
| 67 |
+
- [supports-color-cli](https://github.com/chalk/supports-color-cli) - CLI for this module
|
| 68 |
+
- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right
|
| 69 |
+
- [is-unicode-supported](https://github.com/sindresorhus/is-unicode-supported) - Detect whether the terminal supports Unicode
|
| 70 |
+
- [is-interactive](https://github.com/sindresorhus/is-interactive) - Check if stdout or stderr is interactive
|
| 71 |
+
|
| 72 |
+
## Maintainers
|
| 73 |
+
|
| 74 |
+
- [Sindre Sorhus](https://github.com/sindresorhus)
|
| 75 |
+
- [Josh Junon](https://github.com/qix-)
|
bunx-1000-wrangler@latest/node_modules/undici/README.md
ADDED
|
@@ -0,0 +1,741 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# undici
|
| 2 |
+
|
| 3 |
+
[](https://github.com/nodejs/undici/actions/workflows/nodejs.yml) [](https://github.com/neostandard/neostandard) [](https://badge.fury.io/js/undici) [](https://codecov.io/gh/nodejs/undici)
|
| 4 |
+
|
| 5 |
+
An HTTP/1.1 client, written from scratch for Node.js.
|
| 6 |
+
|
| 7 |
+
> Undici means eleven in Italian. 1.1 -> 11 -> Eleven -> Undici.
|
| 8 |
+
It is also a Stranger Things reference.
|
| 9 |
+
|
| 10 |
+
## How to get involved
|
| 11 |
+
|
| 12 |
+
Have a question about using Undici? Open a [Q&A Discussion](https://github.com/nodejs/undici/discussions/new) or join our official OpenJS [Slack](https://openjs-foundation.slack.com/archives/C01QF9Q31QD) channel.
|
| 13 |
+
|
| 14 |
+
Looking to contribute? Start by reading the [contributing guide](./CONTRIBUTING.md)
|
| 15 |
+
|
| 16 |
+
## Install
|
| 17 |
+
|
| 18 |
+
```
|
| 19 |
+
npm i undici
|
| 20 |
+
```
|
| 21 |
+
|
| 22 |
+
## Benchmarks
|
| 23 |
+
|
| 24 |
+
The benchmark is a simple getting data [example](https://github.com/nodejs/undici/blob/main/benchmarks/benchmark.js) using a
|
| 25 |
+
50 TCP connections with a pipelining depth of 10 running on Node 22.11.0.
|
| 26 |
+
|
| 27 |
+
```
|
| 28 |
+
┌────────────────────────┬─────────┬────────────────────┬────────────┬─────────────────────────┐
|
| 29 |
+
│ Tests │ Samples │ Result │ Tolerance │ Difference with slowest │
|
| 30 |
+
├────────────────────────┼─────────┼────────────────────┼────────────┼─────────────────────────┤
|
| 31 |
+
│ 'axios' │ 15 │ '5708.26 req/sec' │ '± 2.91 %' │ '-' │
|
| 32 |
+
│ 'http - no keepalive' │ 10 │ '5809.80 req/sec' │ '± 2.30 %' │ '+ 1.78 %' │
|
| 33 |
+
│ 'request' │ 30 │ '5828.80 req/sec' │ '± 2.91 %' │ '+ 2.11 %' │
|
| 34 |
+
│ 'undici - fetch' │ 40 │ '5903.78 req/sec' │ '± 2.87 %' │ '+ 3.43 %' │
|
| 35 |
+
│ 'node-fetch' │ 10 │ '5945.40 req/sec' │ '± 2.13 %' │ '+ 4.15 %' │
|
| 36 |
+
│ 'got' │ 35 │ '6511.45 req/sec' │ '± 2.84 %' │ '+ 14.07 %' │
|
| 37 |
+
│ 'http - keepalive' │ 65 │ '9193.24 req/sec' │ '± 2.92 %' │ '+ 61.05 %' │
|
| 38 |
+
│ 'superagent' │ 35 │ '9339.43 req/sec' │ '± 2.95 %' │ '+ 63.61 %' │
|
| 39 |
+
│ 'undici - pipeline' │ 50 │ '13364.62 req/sec' │ '± 2.93 %' │ '+ 134.13 %' │
|
| 40 |
+
│ 'undici - stream' │ 95 │ '18245.36 req/sec' │ '± 2.99 %' │ '+ 219.63 %' │
|
| 41 |
+
│ 'undici - request' │ 50 │ '18340.17 req/sec' │ '± 2.84 %' │ '+ 221.29 %' │
|
| 42 |
+
│ 'undici - dispatch' │ 40 │ '22234.42 req/sec' │ '± 2.94 %' │ '+ 289.51 %' │
|
| 43 |
+
└────────────────────────┴─────────┴────────────────────┴────────────┴─────────────────────────┘
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
## Undici vs. Fetch
|
| 47 |
+
|
| 48 |
+
### Overview
|
| 49 |
+
|
| 50 |
+
Node.js includes a built-in `fetch()` implementation powered by undici starting from Node.js v18. However, there are important differences between using the built-in fetch and installing undici as a separate module.
|
| 51 |
+
|
| 52 |
+
### Built-in Fetch (Node.js v18+)
|
| 53 |
+
|
| 54 |
+
Node.js's built-in fetch is powered by a bundled version of undici:
|
| 55 |
+
|
| 56 |
+
```js
|
| 57 |
+
// Available globally in Node.js v18+
|
| 58 |
+
const response = await fetch('https://api.example.com/data');
|
| 59 |
+
const data = await response.json();
|
| 60 |
+
|
| 61 |
+
// Check the bundled undici version
|
| 62 |
+
console.log(process.versions.undici); // e.g., "5.28.4"
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
**Pros:**
|
| 66 |
+
- No additional dependencies required
|
| 67 |
+
- Works across different JavaScript runtimes
|
| 68 |
+
- Automatic compression handling (gzip, deflate, br)
|
| 69 |
+
- Built-in caching support (in development)
|
| 70 |
+
|
| 71 |
+
**Cons:**
|
| 72 |
+
- Limited to the undici version bundled with your Node.js version
|
| 73 |
+
- Less control over connection pooling and advanced features
|
| 74 |
+
- Error handling follows Web API standards (errors wrapped in `TypeError`)
|
| 75 |
+
- Performance overhead due to Web Streams implementation
|
| 76 |
+
|
| 77 |
+
### Undici Module
|
| 78 |
+
|
| 79 |
+
Installing undici as a separate module gives you access to the latest features and APIs:
|
| 80 |
+
|
| 81 |
+
```bash
|
| 82 |
+
npm install undici
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
```js
|
| 86 |
+
import { request, fetch, Agent, setGlobalDispatcher } from 'undici';
|
| 87 |
+
|
| 88 |
+
// Use undici.request for maximum performance
|
| 89 |
+
const { statusCode, headers, body } = await request('https://api.example.com/data');
|
| 90 |
+
const data = await body.json();
|
| 91 |
+
|
| 92 |
+
// Or use undici.fetch with custom configuration
|
| 93 |
+
const agent = new Agent({ keepAliveTimeout: 10000 });
|
| 94 |
+
setGlobalDispatcher(agent);
|
| 95 |
+
const response = await fetch('https://api.example.com/data');
|
| 96 |
+
```
|
| 97 |
+
|
| 98 |
+
**Pros:**
|
| 99 |
+
- Latest undici features and bug fixes
|
| 100 |
+
- Access to advanced APIs (`request`, `stream`, `pipeline`)
|
| 101 |
+
- Fine-grained control over connection pooling
|
| 102 |
+
- Better error handling with clearer error messages
|
| 103 |
+
- Superior performance, especially with `undici.request`
|
| 104 |
+
- HTTP/1.1 pipelining support
|
| 105 |
+
- Custom interceptors and middleware
|
| 106 |
+
- Advanced features like `ProxyAgent`, `Socks5Agent`, `MockAgent`
|
| 107 |
+
|
| 108 |
+
**Cons:**
|
| 109 |
+
- Additional dependency to manage
|
| 110 |
+
- Larger bundle size
|
| 111 |
+
|
| 112 |
+
### When to Use Each
|
| 113 |
+
|
| 114 |
+
#### Use Built-in Fetch When:
|
| 115 |
+
- You want zero dependencies
|
| 116 |
+
- Building isomorphic code that runs in browsers and Node.js
|
| 117 |
+
- Publishing to npm and want to maximize compatibility with JS runtimes
|
| 118 |
+
- Simple HTTP requests without advanced configuration
|
| 119 |
+
- You're publishing to npm and you want to maximize compatiblity
|
| 120 |
+
- You don't depend on features from a specific version of undici
|
| 121 |
+
|
| 122 |
+
#### Use Undici Module When:
|
| 123 |
+
- You need the latest undici features and performance improvements
|
| 124 |
+
- You require advanced connection pooling configuration
|
| 125 |
+
- You need APIs not available in the built-in fetch (`ProxyAgent`, `Socks5Agent`, `MockAgent`, etc.)
|
| 126 |
+
- Performance is critical (use `undici.request` for maximum speed)
|
| 127 |
+
- You want better error handling and debugging capabilities
|
| 128 |
+
- You need HTTP/1.1 pipelining or advanced interceptors
|
| 129 |
+
- You prefer decoupled protocol and API interfaces
|
| 130 |
+
|
| 131 |
+
### Performance Comparison
|
| 132 |
+
|
| 133 |
+
Based on benchmarks, here's the typical performance hierarchy:
|
| 134 |
+
|
| 135 |
+
1. **`undici.request()`** - Fastest, most efficient
|
| 136 |
+
2. **`undici.fetch()`** - Good performance, standard compliance
|
| 137 |
+
3. **Node.js `http`/`https`** - Baseline performance
|
| 138 |
+
|
| 139 |
+
### Migration Guide
|
| 140 |
+
|
| 141 |
+
If you're currently using built-in fetch and want to migrate to undici:
|
| 142 |
+
|
| 143 |
+
```js
|
| 144 |
+
// Before: Built-in fetch
|
| 145 |
+
const response = await fetch('https://api.example.com/data');
|
| 146 |
+
|
| 147 |
+
// After: Undici fetch (drop-in replacement)
|
| 148 |
+
import { fetch } from 'undici';
|
| 149 |
+
const response = await fetch('https://api.example.com/data');
|
| 150 |
+
|
| 151 |
+
// Or: Undici request (better performance)
|
| 152 |
+
import { request } from 'undici';
|
| 153 |
+
const { statusCode, body } = await request('https://api.example.com/data');
|
| 154 |
+
const data = await body.json();
|
| 155 |
+
```
|
| 156 |
+
|
| 157 |
+
### Keep `fetch` and `FormData` together
|
| 158 |
+
|
| 159 |
+
When you send a `FormData` body, keep `fetch` and `FormData` from the same
|
| 160 |
+
implementation.
|
| 161 |
+
|
| 162 |
+
Use one of these patterns:
|
| 163 |
+
|
| 164 |
+
```js
|
| 165 |
+
// Built-in globals
|
| 166 |
+
const body = new FormData()
|
| 167 |
+
body.set('name', 'some')
|
| 168 |
+
await fetch('https://example.com', {
|
| 169 |
+
method: 'POST',
|
| 170 |
+
body
|
| 171 |
+
})
|
| 172 |
+
```
|
| 173 |
+
|
| 174 |
+
```js
|
| 175 |
+
// undici module imports
|
| 176 |
+
import { fetch, FormData } from 'undici'
|
| 177 |
+
|
| 178 |
+
const body = new FormData()
|
| 179 |
+
body.set('name', 'some')
|
| 180 |
+
await fetch('https://example.com', {
|
| 181 |
+
method: 'POST',
|
| 182 |
+
body
|
| 183 |
+
})
|
| 184 |
+
```
|
| 185 |
+
|
| 186 |
+
If you want the installed `undici` package to provide the globals, call
|
| 187 |
+
`install()` first:
|
| 188 |
+
|
| 189 |
+
```js
|
| 190 |
+
import { install } from 'undici'
|
| 191 |
+
|
| 192 |
+
install()
|
| 193 |
+
|
| 194 |
+
const body = new FormData()
|
| 195 |
+
body.set('name', 'some')
|
| 196 |
+
await fetch('https://example.com', {
|
| 197 |
+
method: 'POST',
|
| 198 |
+
body
|
| 199 |
+
})
|
| 200 |
+
```
|
| 201 |
+
|
| 202 |
+
`install()` replaces the global `fetch`, `Headers`, `Response`, `Request`, and
|
| 203 |
+
`FormData` implementations with undici's versions, so they all match.
|
| 204 |
+
|
| 205 |
+
Avoid mixing a global `FormData` with `undici.fetch()`, or `undici.FormData`
|
| 206 |
+
with the built-in global `fetch()`.
|
| 207 |
+
|
| 208 |
+
### Version Compatibility
|
| 209 |
+
|
| 210 |
+
You can check which version of undici is bundled with your Node.js version:
|
| 211 |
+
|
| 212 |
+
```js
|
| 213 |
+
console.log(process.versions.undici);
|
| 214 |
+
```
|
| 215 |
+
|
| 216 |
+
Installing undici as a module allows you to use a newer version than what's bundled with Node.js, giving you access to the latest features and performance improvements.
|
| 217 |
+
|
| 218 |
+
## Quick Start
|
| 219 |
+
|
| 220 |
+
### Basic Request
|
| 221 |
+
|
| 222 |
+
```js
|
| 223 |
+
import { request } from 'undici'
|
| 224 |
+
|
| 225 |
+
const {
|
| 226 |
+
statusCode,
|
| 227 |
+
headers,
|
| 228 |
+
trailers,
|
| 229 |
+
body
|
| 230 |
+
} = await request('http://localhost:3000/foo')
|
| 231 |
+
|
| 232 |
+
console.log('response received', statusCode)
|
| 233 |
+
console.log('headers', headers)
|
| 234 |
+
|
| 235 |
+
for await (const data of body) { console.log('data', data) }
|
| 236 |
+
|
| 237 |
+
console.log('trailers', trailers)
|
| 238 |
+
```
|
| 239 |
+
|
| 240 |
+
### Using Cache Interceptor
|
| 241 |
+
|
| 242 |
+
Undici provides a powerful HTTP caching interceptor that follows HTTP caching best practices. Here's how to use it:
|
| 243 |
+
|
| 244 |
+
```js
|
| 245 |
+
import { fetch, Agent, interceptors, cacheStores } from 'undici';
|
| 246 |
+
|
| 247 |
+
// Create a client with cache interceptor
|
| 248 |
+
const client = new Agent().compose(interceptors.cache({
|
| 249 |
+
// Optional: Configure cache store (defaults to MemoryCacheStore)
|
| 250 |
+
store: new cacheStores.MemoryCacheStore({
|
| 251 |
+
maxSize: 100 * 1024 * 1024, // 100MB
|
| 252 |
+
maxCount: 1000,
|
| 253 |
+
maxEntrySize: 5 * 1024 * 1024 // 5MB
|
| 254 |
+
}),
|
| 255 |
+
|
| 256 |
+
// Optional: Specify which HTTP methods to cache (default: ['GET', 'HEAD'])
|
| 257 |
+
methods: ['GET', 'HEAD']
|
| 258 |
+
}));
|
| 259 |
+
|
| 260 |
+
// Set the global dispatcher to use our caching client
|
| 261 |
+
setGlobalDispatcher(client);
|
| 262 |
+
|
| 263 |
+
// Now all fetch requests will use the cache
|
| 264 |
+
async function getData() {
|
| 265 |
+
const response = await fetch('https://api.example.com/data');
|
| 266 |
+
// The server should set appropriate Cache-Control headers in the response
|
| 267 |
+
// which the cache will respect based on the cache policy
|
| 268 |
+
return response.json();
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
// First request - fetches from origin
|
| 272 |
+
const data1 = await getData();
|
| 273 |
+
|
| 274 |
+
// Second request - served from cache if within max-age
|
| 275 |
+
const data2 = await getData();
|
| 276 |
+
```
|
| 277 |
+
|
| 278 |
+
#### Key Features:
|
| 279 |
+
- **Automatic Caching**: Respects `Cache-Control` and `Expires` headers
|
| 280 |
+
- **Validation**: Supports `ETag` and `Last-Modified` validation
|
| 281 |
+
- **Storage Options**: In-memory or persistent SQLite storage
|
| 282 |
+
- **Flexible**: Configure cache size, TTL, and more
|
| 283 |
+
|
| 284 |
+
## Global Installation
|
| 285 |
+
|
| 286 |
+
Undici provides an `install()` function to add all WHATWG fetch classes to `globalThis`, making them available globally:
|
| 287 |
+
|
| 288 |
+
```js
|
| 289 |
+
import { install } from 'undici'
|
| 290 |
+
|
| 291 |
+
// Install all WHATWG fetch classes globally
|
| 292 |
+
install()
|
| 293 |
+
|
| 294 |
+
// Now you can use fetch classes globally without importing
|
| 295 |
+
const response = await fetch('https://api.example.com/data')
|
| 296 |
+
const data = await response.json()
|
| 297 |
+
|
| 298 |
+
// All classes are available globally:
|
| 299 |
+
const headers = new Headers([['content-type', 'application/json']])
|
| 300 |
+
const request = new Request('https://example.com')
|
| 301 |
+
const formData = new FormData()
|
| 302 |
+
const ws = new WebSocket('wss://example.com')
|
| 303 |
+
const eventSource = new EventSource('https://example.com/events')
|
| 304 |
+
```
|
| 305 |
+
|
| 306 |
+
The `install()` function adds the following classes to `globalThis`:
|
| 307 |
+
|
| 308 |
+
- `fetch` - The fetch function
|
| 309 |
+
- `Headers` - HTTP headers management
|
| 310 |
+
- `Response` - HTTP response representation
|
| 311 |
+
- `Request` - HTTP request representation
|
| 312 |
+
- `FormData` - Form data handling
|
| 313 |
+
- `WebSocket` - WebSocket client
|
| 314 |
+
- `CloseEvent`, `ErrorEvent`, `MessageEvent` - WebSocket events
|
| 315 |
+
- `EventSource` - Server-sent events client
|
| 316 |
+
|
| 317 |
+
When you call `install()`, these globals come from the same undici
|
| 318 |
+
implementation. For example, global `fetch` and global `FormData` will both be
|
| 319 |
+
undici's versions, which is the recommended setup if you want to use undici
|
| 320 |
+
through globals.
|
| 321 |
+
|
| 322 |
+
This is useful for:
|
| 323 |
+
- Polyfilling environments that don't have fetch
|
| 324 |
+
- Ensuring consistent fetch behavior across different Node.js versions
|
| 325 |
+
- Making undici's implementations available globally for libraries that expect them
|
| 326 |
+
|
| 327 |
+
## Body Mixins
|
| 328 |
+
|
| 329 |
+
The `body` mixins are the most common way to format the request/response body. Mixins include:
|
| 330 |
+
|
| 331 |
+
- [`.arrayBuffer()`](https://fetch.spec.whatwg.org/#dom-body-arraybuffer)
|
| 332 |
+
- [`.blob()`](https://fetch.spec.whatwg.org/#dom-body-blob)
|
| 333 |
+
- [`.bytes()`](https://fetch.spec.whatwg.org/#dom-body-bytes)
|
| 334 |
+
- [`.json()`](https://fetch.spec.whatwg.org/#dom-body-json)
|
| 335 |
+
- [`.text()`](https://fetch.spec.whatwg.org/#dom-body-text)
|
| 336 |
+
|
| 337 |
+
> [!NOTE]
|
| 338 |
+
> The body returned from `undici.request` does not implement `.formData()`.
|
| 339 |
+
|
| 340 |
+
Example usage:
|
| 341 |
+
|
| 342 |
+
```js
|
| 343 |
+
import { request } from 'undici'
|
| 344 |
+
|
| 345 |
+
const {
|
| 346 |
+
statusCode,
|
| 347 |
+
headers,
|
| 348 |
+
trailers,
|
| 349 |
+
body
|
| 350 |
+
} = await request('http://localhost:3000/foo')
|
| 351 |
+
|
| 352 |
+
console.log('response received', statusCode)
|
| 353 |
+
console.log('headers', headers)
|
| 354 |
+
console.log('data', await body.json())
|
| 355 |
+
console.log('trailers', trailers)
|
| 356 |
+
```
|
| 357 |
+
|
| 358 |
+
_Note: Once a mixin has been called then the body cannot be reused, thus calling additional mixins on `.body`, e.g. `.body.json(); .body.text()` will result in an error `TypeError: unusable` being thrown and returned through the `Promise` rejection._
|
| 359 |
+
|
| 360 |
+
Should you need to access the `body` in plain-text after using a mixin, the best practice is to use the `.text()` mixin first and then manually parse the text to the desired format.
|
| 361 |
+
|
| 362 |
+
For more information about their behavior, please reference the body mixin from the [Fetch Standard](https://fetch.spec.whatwg.org/#body-mixin).
|
| 363 |
+
|
| 364 |
+
## Common API Methods
|
| 365 |
+
|
| 366 |
+
This section documents our most commonly used API methods. Additional APIs are documented in their own files within the [docs](./docs/) folder and are accessible via the navigation list on the left side of the docs site.
|
| 367 |
+
|
| 368 |
+
### `undici.request([url, options]): Promise`
|
| 369 |
+
|
| 370 |
+
Arguments:
|
| 371 |
+
|
| 372 |
+
* **url** `string | URL | UrlObject`
|
| 373 |
+
* **options** [`RequestOptions`](./docs/docs/api/Dispatcher.md#parameter-requestoptions)
|
| 374 |
+
* **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)
|
| 375 |
+
* **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`
|
| 376 |
+
|
| 377 |
+
Returns a promise with the result of the `Dispatcher.request` method.
|
| 378 |
+
|
| 379 |
+
Calls `options.dispatcher.request(options)`.
|
| 380 |
+
|
| 381 |
+
See [Dispatcher.request](./docs/docs/api/Dispatcher.md#dispatcherrequestoptions-callback) for more details, and [request examples](./docs/examples/README.md) for examples.
|
| 382 |
+
|
| 383 |
+
### `undici.stream([url, options, ]factory): Promise`
|
| 384 |
+
|
| 385 |
+
Arguments:
|
| 386 |
+
|
| 387 |
+
* **url** `string | URL | UrlObject`
|
| 388 |
+
* **options** [`StreamOptions`](./docs/docs/api/Dispatcher.md#parameter-streamoptions)
|
| 389 |
+
* **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)
|
| 390 |
+
* **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`
|
| 391 |
+
* **factory** `Dispatcher.stream.factory`
|
| 392 |
+
|
| 393 |
+
Returns a promise with the result of the `Dispatcher.stream` method.
|
| 394 |
+
|
| 395 |
+
Calls `options.dispatcher.stream(options, factory)`.
|
| 396 |
+
|
| 397 |
+
See [Dispatcher.stream](./docs/docs/api/Dispatcher.md#dispatcherstreamoptions-factory-callback) for more details.
|
| 398 |
+
|
| 399 |
+
### `undici.pipeline([url, options, ]handler): Duplex`
|
| 400 |
+
|
| 401 |
+
Arguments:
|
| 402 |
+
|
| 403 |
+
* **url** `string | URL | UrlObject`
|
| 404 |
+
* **options** [`PipelineOptions`](./docs/docs/api/Dispatcher.md#parameter-pipelineoptions)
|
| 405 |
+
* **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)
|
| 406 |
+
* **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`
|
| 407 |
+
* **handler** `Dispatcher.pipeline.handler`
|
| 408 |
+
|
| 409 |
+
Returns: `stream.Duplex`
|
| 410 |
+
|
| 411 |
+
Calls `options.dispatch.pipeline(options, handler)`.
|
| 412 |
+
|
| 413 |
+
See [Dispatcher.pipeline](./docs/docs/api/Dispatcher.md#dispatcherpipelineoptions-handler) for more details.
|
| 414 |
+
|
| 415 |
+
### `undici.connect([url, options]): Promise`
|
| 416 |
+
|
| 417 |
+
Starts two-way communications with the requested resource using [HTTP CONNECT](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/CONNECT).
|
| 418 |
+
|
| 419 |
+
Arguments:
|
| 420 |
+
|
| 421 |
+
* **url** `string | URL | UrlObject`
|
| 422 |
+
* **options** [`ConnectOptions`](./docs/docs/api/Dispatcher.md#parameter-connectoptions)
|
| 423 |
+
* **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)
|
| 424 |
+
* **callback** `(err: Error | null, data: ConnectData | null) => void` (optional)
|
| 425 |
+
|
| 426 |
+
Returns a promise with the result of the `Dispatcher.connect` method.
|
| 427 |
+
|
| 428 |
+
Calls `options.dispatch.connect(options)`.
|
| 429 |
+
|
| 430 |
+
See [Dispatcher.connect](./docs/docs/api/Dispatcher.md#dispatcherconnectoptions-callback) for more details.
|
| 431 |
+
|
| 432 |
+
### `undici.fetch(input[, init]): Promise`
|
| 433 |
+
|
| 434 |
+
Implements [fetch](https://fetch.spec.whatwg.org/#fetch-method).
|
| 435 |
+
|
| 436 |
+
* https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
|
| 437 |
+
* https://fetch.spec.whatwg.org/#fetch-method
|
| 438 |
+
|
| 439 |
+
Basic usage example:
|
| 440 |
+
|
| 441 |
+
```js
|
| 442 |
+
import { fetch } from 'undici'
|
| 443 |
+
|
| 444 |
+
|
| 445 |
+
const res = await fetch('https://example.com')
|
| 446 |
+
const json = await res.json()
|
| 447 |
+
console.log(json)
|
| 448 |
+
```
|
| 449 |
+
|
| 450 |
+
You can pass an optional dispatcher to `fetch` as:
|
| 451 |
+
|
| 452 |
+
```js
|
| 453 |
+
import { fetch, Agent } from 'undici'
|
| 454 |
+
|
| 455 |
+
const res = await fetch('https://example.com', {
|
| 456 |
+
// Mocks are also supported
|
| 457 |
+
dispatcher: new Agent({
|
| 458 |
+
keepAliveTimeout: 10,
|
| 459 |
+
keepAliveMaxTimeout: 10
|
| 460 |
+
})
|
| 461 |
+
})
|
| 462 |
+
const json = await res.json()
|
| 463 |
+
console.log(json)
|
| 464 |
+
```
|
| 465 |
+
|
| 466 |
+
#### `request.body`
|
| 467 |
+
|
| 468 |
+
A body can be of the following types:
|
| 469 |
+
|
| 470 |
+
- ArrayBuffer
|
| 471 |
+
- ArrayBufferView
|
| 472 |
+
- AsyncIterables
|
| 473 |
+
- Blob
|
| 474 |
+
- Iterables
|
| 475 |
+
- String
|
| 476 |
+
- URLSearchParams
|
| 477 |
+
- FormData
|
| 478 |
+
|
| 479 |
+
In this implementation of fetch, ```request.body``` now accepts ```Async Iterables```. It is not present in the [Fetch Standard](https://fetch.spec.whatwg.org).
|
| 480 |
+
|
| 481 |
+
```js
|
| 482 |
+
import { fetch } from 'undici'
|
| 483 |
+
|
| 484 |
+
const data = {
|
| 485 |
+
async *[Symbol.asyncIterator]() {
|
| 486 |
+
yield 'hello'
|
| 487 |
+
yield 'world'
|
| 488 |
+
},
|
| 489 |
+
}
|
| 490 |
+
|
| 491 |
+
await fetch('https://example.com', { body: data, method: 'POST', duplex: 'half' })
|
| 492 |
+
```
|
| 493 |
+
|
| 494 |
+
[FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) besides text data and buffers can also utilize streams via [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects:
|
| 495 |
+
|
| 496 |
+
```js
|
| 497 |
+
import { openAsBlob } from 'node:fs'
|
| 498 |
+
|
| 499 |
+
const file = await openAsBlob('./big.csv')
|
| 500 |
+
const body = new FormData()
|
| 501 |
+
body.set('file', file, 'big.csv')
|
| 502 |
+
|
| 503 |
+
await fetch('http://example.com', { method: 'POST', body })
|
| 504 |
+
```
|
| 505 |
+
|
| 506 |
+
#### `request.duplex`
|
| 507 |
+
|
| 508 |
+
- `'half'`
|
| 509 |
+
|
| 510 |
+
In this implementation of fetch, `request.duplex` must be set if `request.body` is `ReadableStream` or `Async Iterables`, however, even though the value must be set to `'half'`, it is actually a _full_ duplex. For more detail refer to the [Fetch Standard](https://fetch.spec.whatwg.org/#dom-requestinit-duplex).
|
| 511 |
+
|
| 512 |
+
#### `response.body`
|
| 513 |
+
|
| 514 |
+
Nodejs has two kinds of streams: [web streams](https://nodejs.org/api/webstreams.html), which follow the API of the WHATWG web standard found in browsers, and an older Node-specific [streams API](https://nodejs.org/api/stream.html). `response.body` returns a readable web stream. If you would prefer to work with a Node stream you can convert a web stream using `.fromWeb()`.
|
| 515 |
+
|
| 516 |
+
```js
|
| 517 |
+
import { fetch } from 'undici'
|
| 518 |
+
import { Readable } from 'node:stream'
|
| 519 |
+
|
| 520 |
+
const response = await fetch('https://example.com')
|
| 521 |
+
const readableWebStream = response.body
|
| 522 |
+
const readableNodeStream = Readable.fromWeb(readableWebStream)
|
| 523 |
+
```
|
| 524 |
+
|
| 525 |
+
## Specification Compliance
|
| 526 |
+
|
| 527 |
+
This section documents parts of the [HTTP/1.1](https://www.rfc-editor.org/rfc/rfc9110.html) and [Fetch Standard](https://fetch.spec.whatwg.org) that Undici does
|
| 528 |
+
not support or does not fully implement.
|
| 529 |
+
|
| 530 |
+
#### CORS
|
| 531 |
+
|
| 532 |
+
Unlike browsers, Undici does not implement CORS (Cross-Origin Resource Sharing) checks by default. This means:
|
| 533 |
+
|
| 534 |
+
- No preflight requests are automatically sent for cross-origin requests
|
| 535 |
+
- No validation of `Access-Control-Allow-Origin` headers is performed
|
| 536 |
+
- Requests to any origin are allowed regardless of the source
|
| 537 |
+
|
| 538 |
+
This behavior is intentional for server-side environments where CORS restrictions are typically unnecessary. If your application requires CORS-like protections, you will need to implement these checks manually.
|
| 539 |
+
|
| 540 |
+
#### Garbage Collection
|
| 541 |
+
|
| 542 |
+
* https://fetch.spec.whatwg.org/#garbage-collection
|
| 543 |
+
|
| 544 |
+
The [Fetch Standard](https://fetch.spec.whatwg.org) allows users to skip consuming the response body by relying on
|
| 545 |
+
[garbage collection](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management#garbage_collection) to release connection resources.
|
| 546 |
+
|
| 547 |
+
Garbage collection in Node is less aggressive and deterministic
|
| 548 |
+
(due to the lack of clear idle periods that browsers have through the rendering refresh rate)
|
| 549 |
+
which means that leaving the release of connection resources to the garbage collector can lead
|
| 550 |
+
to excessive connection usage, reduced performance (due to less connection re-use), and even
|
| 551 |
+
stalls or deadlocks when running out of connections.
|
| 552 |
+
Therefore, __it is important to always either consume or cancel the response body anyway__.
|
| 553 |
+
|
| 554 |
+
```js
|
| 555 |
+
// Do
|
| 556 |
+
const { body, headers } = await fetch(url);
|
| 557 |
+
for await (const chunk of body) {
|
| 558 |
+
// force consumption of body
|
| 559 |
+
}
|
| 560 |
+
|
| 561 |
+
// Do not
|
| 562 |
+
const { headers } = await fetch(url);
|
| 563 |
+
```
|
| 564 |
+
|
| 565 |
+
However, if you want to get only headers, it might be better to use `HEAD` request method. Usage of this method will obviate the need for consumption or cancelling of the response body. See [MDN - HTTP - HTTP request methods - HEAD](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD) for more details.
|
| 566 |
+
|
| 567 |
+
```js
|
| 568 |
+
const headers = await fetch(url, { method: 'HEAD' })
|
| 569 |
+
.then(res => res.headers)
|
| 570 |
+
```
|
| 571 |
+
|
| 572 |
+
Note that consuming the response body is _mandatory_ for `request`:
|
| 573 |
+
|
| 574 |
+
```js
|
| 575 |
+
// Do
|
| 576 |
+
const { body, headers } = await request(url);
|
| 577 |
+
await body.dump(); // force consumption of body
|
| 578 |
+
|
| 579 |
+
// Do not
|
| 580 |
+
const { headers } = await request(url);
|
| 581 |
+
```
|
| 582 |
+
|
| 583 |
+
#### Forbidden and Safelisted Header Names
|
| 584 |
+
|
| 585 |
+
* https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
|
| 586 |
+
* https://fetch.spec.whatwg.org/#forbidden-header-name
|
| 587 |
+
* https://fetch.spec.whatwg.org/#forbidden-response-header-name
|
| 588 |
+
* https://github.com/wintercg/fetch/issues/6
|
| 589 |
+
|
| 590 |
+
The [Fetch Standard](https://fetch.spec.whatwg.org) requires implementations to exclude certain headers from requests and responses. In browser environments, some headers are forbidden so the user agent remains in full control over them. In Undici, these constraints are removed to give more control to the user.
|
| 591 |
+
|
| 592 |
+
#### Content-Encoding
|
| 593 |
+
|
| 594 |
+
* https://www.rfc-editor.org/rfc/rfc9110#field.content-encoding
|
| 595 |
+
|
| 596 |
+
Undici limits the number of `Content-Encoding` layers in a response to **5** to prevent resource exhaustion attacks. If a server responds with more than 5 content-encodings (e.g., `Content-Encoding: gzip, gzip, gzip, gzip, gzip, gzip`), the fetch will be rejected with an error. This limit matches the approach taken by [curl](https://curl.se/docs/CVE-2022-32206.html) and [urllib3](https://github.com/advisories/GHSA-gm62-xv2j-4rw9).
|
| 597 |
+
|
| 598 |
+
#### `undici.upgrade([url, options]): Promise`
|
| 599 |
+
|
| 600 |
+
Upgrade to a different protocol. See [MDN - HTTP - Protocol upgrade mechanism](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism) for more details.
|
| 601 |
+
|
| 602 |
+
Arguments:
|
| 603 |
+
|
| 604 |
+
* **url** `string | URL | UrlObject`
|
| 605 |
+
* **options** [`UpgradeOptions`](./docs/docs/api/Dispatcher.md#parameter-upgradeoptions)
|
| 606 |
+
* **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)
|
| 607 |
+
* **callback** `(error: Error | null, data: UpgradeData) => void` (optional)
|
| 608 |
+
|
| 609 |
+
Returns a promise with the result of the `Dispatcher.upgrade` method.
|
| 610 |
+
|
| 611 |
+
Calls `options.dispatcher.upgrade(options)`.
|
| 612 |
+
|
| 613 |
+
See [Dispatcher.upgrade](./docs/docs/api/Dispatcher.md#dispatcherupgradeoptions-callback) for more details.
|
| 614 |
+
|
| 615 |
+
### `undici.setGlobalDispatcher(dispatcher)`
|
| 616 |
+
|
| 617 |
+
* dispatcher `Dispatcher`
|
| 618 |
+
|
| 619 |
+
Sets the global dispatcher used by Common API Methods. Global dispatcher is shared among compatible undici modules,
|
| 620 |
+
including undici that is bundled internally with node.js.
|
| 621 |
+
|
| 622 |
+
### `undici.getGlobalDispatcher()`
|
| 623 |
+
|
| 624 |
+
Gets the global dispatcher used by Common API Methods.
|
| 625 |
+
|
| 626 |
+
Returns: `Dispatcher`
|
| 627 |
+
|
| 628 |
+
### `undici.setGlobalOrigin(origin)`
|
| 629 |
+
|
| 630 |
+
* origin `string | URL | undefined`
|
| 631 |
+
|
| 632 |
+
Sets the global origin used in `fetch`.
|
| 633 |
+
|
| 634 |
+
If `undefined` is passed, the global origin will be reset. This will cause `Response.redirect`, `new Request()`, and `fetch` to throw an error when a relative path is passed.
|
| 635 |
+
|
| 636 |
+
```js
|
| 637 |
+
setGlobalOrigin('http://localhost:3000')
|
| 638 |
+
|
| 639 |
+
const response = await fetch('/api/ping')
|
| 640 |
+
|
| 641 |
+
console.log(response.url) // http://localhost:3000/api/ping
|
| 642 |
+
```
|
| 643 |
+
|
| 644 |
+
### `undici.getGlobalOrigin()`
|
| 645 |
+
|
| 646 |
+
Gets the global origin used in `fetch`.
|
| 647 |
+
|
| 648 |
+
Returns: `URL`
|
| 649 |
+
|
| 650 |
+
### `UrlObject`
|
| 651 |
+
|
| 652 |
+
* **port** `string | number` (optional)
|
| 653 |
+
* **path** `string` (optional)
|
| 654 |
+
* **pathname** `string` (optional)
|
| 655 |
+
* **hostname** `string` (optional)
|
| 656 |
+
* **origin** `string` (optional)
|
| 657 |
+
* **protocol** `string` (optional)
|
| 658 |
+
* **search** `string` (optional)
|
| 659 |
+
|
| 660 |
+
#### Expect
|
| 661 |
+
|
| 662 |
+
Undici does not support the `Expect` request header field. The request
|
| 663 |
+
body is always immediately sent and the `100 Continue` response will be
|
| 664 |
+
ignored.
|
| 665 |
+
|
| 666 |
+
Refs: https://tools.ietf.org/html/rfc7231#section-5.1.1
|
| 667 |
+
|
| 668 |
+
#### Pipelining
|
| 669 |
+
|
| 670 |
+
Undici will only use pipelining if configured with a `pipelining` factor
|
| 671 |
+
greater than `1`. Also it is important to pass `blocking: false` to the
|
| 672 |
+
request options to properly pipeline requests.
|
| 673 |
+
|
| 674 |
+
Undici always assumes that connections are persistent and will immediately
|
| 675 |
+
pipeline requests, without checking whether the connection is persistent.
|
| 676 |
+
Hence, automatic fallback to HTTP/1.0 or HTTP/1.1 without pipelining is
|
| 677 |
+
not supported.
|
| 678 |
+
|
| 679 |
+
Undici will immediately pipeline when retrying requests after a failed
|
| 680 |
+
connection. However, Undici will not retry the first remaining requests in
|
| 681 |
+
the prior pipeline and instead error the corresponding callback/promise/stream.
|
| 682 |
+
|
| 683 |
+
Undici will abort all running requests in the pipeline when any of them are
|
| 684 |
+
aborted.
|
| 685 |
+
|
| 686 |
+
* Refs: https://tools.ietf.org/html/rfc2616#section-8.1.2.2
|
| 687 |
+
* Refs: https://tools.ietf.org/html/rfc7230#section-6.3.2
|
| 688 |
+
|
| 689 |
+
#### Manual Redirect
|
| 690 |
+
|
| 691 |
+
Since it is not possible to manually follow an HTTP redirect on the server-side,
|
| 692 |
+
Undici returns the actual response instead of an `opaqueredirect` filtered one
|
| 693 |
+
when invoked with a `manual` redirect. This aligns `fetch()` with the other
|
| 694 |
+
implementations in Deno and Cloudflare Workers.
|
| 695 |
+
|
| 696 |
+
Refs: https://fetch.spec.whatwg.org/#atomic-http-redirect-handling
|
| 697 |
+
|
| 698 |
+
### Workarounds
|
| 699 |
+
|
| 700 |
+
#### Network address family autoselection.
|
| 701 |
+
|
| 702 |
+
If you experience problem when connecting to a remote server that is resolved by your DNS servers to a IPv6 (AAAA record)
|
| 703 |
+
first, there are chances that your local router or ISP might have problem connecting to IPv6 networks. In that case
|
| 704 |
+
undici will throw an error with code `UND_ERR_CONNECT_TIMEOUT`.
|
| 705 |
+
|
| 706 |
+
If the target server resolves to both a IPv6 and IPv4 (A records) address and you are using a compatible Node version
|
| 707 |
+
(18.3.0 and above), you can fix the problem by providing the `autoSelectFamily` option (support by both `undici.request`
|
| 708 |
+
and `undici.Agent`) which will enable the family autoselection algorithm when establishing the connection.
|
| 709 |
+
|
| 710 |
+
## Collaborators
|
| 711 |
+
|
| 712 |
+
* [__Daniele Belardi__](https://github.com/dnlup), <https://www.npmjs.com/~dnlup>
|
| 713 |
+
* [__Ethan Arrowood__](https://github.com/ethan-arrowood), <https://www.npmjs.com/~ethan_arrowood>
|
| 714 |
+
* [__Matteo Collina__](https://github.com/mcollina), <https://www.npmjs.com/~matteo.collina>
|
| 715 |
+
* [__Matthew Aitken__](https://github.com/KhafraDev), <https://www.npmjs.com/~khaf>
|
| 716 |
+
* [__Robert Nagy__](https://github.com/ronag), <https://www.npmjs.com/~ronag>
|
| 717 |
+
* [__Szymon Marczak__](https://github.com/szmarczak), <https://www.npmjs.com/~szmarczak>
|
| 718 |
+
|
| 719 |
+
## Past Collaborators
|
| 720 |
+
* [__Tomas Della Vedova__](https://github.com/delvedor), <https://www.npmjs.com/~delvedor>
|
| 721 |
+
|
| 722 |
+
### Releasers
|
| 723 |
+
|
| 724 |
+
* [__Ethan Arrowood__](https://github.com/ethan-arrowood), <https://www.npmjs.com/~ethan_arrowood>
|
| 725 |
+
* [__Matteo Collina__](https://github.com/mcollina), <https://www.npmjs.com/~matteo.collina>
|
| 726 |
+
* [__Robert Nagy__](https://github.com/ronag), <https://www.npmjs.com/~ronag>
|
| 727 |
+
* [__Matthew Aitken__](https://github.com/KhafraDev), <https://www.npmjs.com/~khaf>
|
| 728 |
+
|
| 729 |
+
## Long Term Support
|
| 730 |
+
|
| 731 |
+
Undici aligns with the Node.js LTS schedule. The following table shows the supported versions:
|
| 732 |
+
|
| 733 |
+
| Undici Version | Bundled in Node.js | Node.js Versions Supported | End of Life |
|
| 734 |
+
|----------------|-------------------|----------------------------|-------------|
|
| 735 |
+
| 5.x | 18.x | ≥14.0 (tested: 14, 16, 18) | 2024-04-30 |
|
| 736 |
+
| 6.x | 20.x, 22.x | ≥18.17 (tested: 18, 20, 21, 22) | 2026-04-30 |
|
| 737 |
+
| 7.x | 24.x | ≥20.18.1 (tested: 20, 22, 24) | 2027-04-30 |
|
| 738 |
+
|
| 739 |
+
## License
|
| 740 |
+
|
| 741 |
+
MIT
|
bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/Agent.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Agent
|
| 2 |
+
|
| 3 |
+
Extends: `undici.Dispatcher`
|
| 4 |
+
|
| 5 |
+
Agent allows dispatching requests against multiple different origins.
|
| 6 |
+
|
| 7 |
+
Requests are not guaranteed to be dispatched in order of invocation.
|
| 8 |
+
|
| 9 |
+
## `new undici.Agent([options])`
|
| 10 |
+
|
| 11 |
+
Arguments:
|
| 12 |
+
|
| 13 |
+
* **options** `AgentOptions` (optional)
|
| 14 |
+
|
| 15 |
+
Returns: `Agent`
|
| 16 |
+
|
| 17 |
+
### Parameter: `AgentOptions`
|
| 18 |
+
|
| 19 |
+
Extends: [`PoolOptions`](/docs/docs/api/Pool.md#parameter-pooloptions)
|
| 20 |
+
|
| 21 |
+
* **factory** `(origin: URL, opts: Object) => Dispatcher` - Default: `(origin, opts) => new Pool(origin, opts)`
|
| 22 |
+
* **maxOrigins** `number` (optional) - Default: `Infinity` - Limits the total number of origins that can receive requests at a time, throwing an `MaxOriginsReachedError` error when attempting to dispatch when the max is reached. If `Infinity`, no limit is enforced.
|
| 23 |
+
|
| 24 |
+
## Instance Properties
|
| 25 |
+
|
| 26 |
+
### `Agent.closed`
|
| 27 |
+
|
| 28 |
+
Implements [Client.closed](/docs/docs/api/Client.md#clientclosed)
|
| 29 |
+
|
| 30 |
+
### `Agent.destroyed`
|
| 31 |
+
|
| 32 |
+
Implements [Client.destroyed](/docs/docs/api/Client.md#clientdestroyed)
|
| 33 |
+
|
| 34 |
+
## Instance Methods
|
| 35 |
+
|
| 36 |
+
### `Agent.close([callback])`
|
| 37 |
+
|
| 38 |
+
Implements [`Dispatcher.close([callback])`](/docs/docs/api/Dispatcher.md#dispatcherclosecallback-promise).
|
| 39 |
+
|
| 40 |
+
### `Agent.destroy([error, callback])`
|
| 41 |
+
|
| 42 |
+
Implements [`Dispatcher.destroy([error, callback])`](/docs/docs/api/Dispatcher.md#dispatcherdestroyerror-callback-promise).
|
| 43 |
+
|
| 44 |
+
### `Agent.dispatch(options, handler: AgentDispatchOptions)`
|
| 45 |
+
|
| 46 |
+
Implements [`Dispatcher.dispatch(options, handler)`](/docs/docs/api/Dispatcher.md#dispatcherdispatchoptions-handler).
|
| 47 |
+
|
| 48 |
+
#### Parameter: `AgentDispatchOptions`
|
| 49 |
+
|
| 50 |
+
Extends: [`DispatchOptions`](/docs/docs/api/Dispatcher.md#parameter-dispatchoptions)
|
| 51 |
+
|
| 52 |
+
* **origin** `string | URL`
|
| 53 |
+
|
| 54 |
+
Implements [`Dispatcher.destroy([error, callback])`](/docs/docs/api/Dispatcher.md#dispatcherdestroyerror-callback-promise).
|
| 55 |
+
|
| 56 |
+
### `Agent.connect(options[, callback])`
|
| 57 |
+
|
| 58 |
+
See [`Dispatcher.connect(options[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherconnectoptions-callback).
|
| 59 |
+
|
| 60 |
+
### `Agent.dispatch(options, handler)`
|
| 61 |
+
|
| 62 |
+
Implements [`Dispatcher.dispatch(options, handler)`](/docs/docs/api/Dispatcher.md#dispatcherdispatchoptions-handler).
|
| 63 |
+
|
| 64 |
+
### `Agent.pipeline(options, handler)`
|
| 65 |
+
|
| 66 |
+
See [`Dispatcher.pipeline(options, handler)`](/docs/docs/api/Dispatcher.md#dispatcherpipelineoptions-handler).
|
| 67 |
+
|
| 68 |
+
### `Agent.request(options[, callback])`
|
| 69 |
+
|
| 70 |
+
See [`Dispatcher.request(options [, callback])`](/docs/docs/api/Dispatcher.md#dispatcherrequestoptions-callback).
|
| 71 |
+
|
| 72 |
+
### `Agent.stream(options, factory[, callback])`
|
| 73 |
+
|
| 74 |
+
See [`Dispatcher.stream(options, factory[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherstreamoptions-factory-callback).
|
| 75 |
+
|
| 76 |
+
### `Agent.upgrade(options[, callback])`
|
| 77 |
+
|
| 78 |
+
See [`Dispatcher.upgrade(options[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherupgradeoptions-callback).
|
| 79 |
+
|
| 80 |
+
### `Agent.stats()`
|
| 81 |
+
|
| 82 |
+
Returns an object of stats by origin in the format of `Record<string, TClientStats | TPoolStats>`
|
| 83 |
+
|
| 84 |
+
See [`PoolStats`](/docs/docs/api/PoolStats.md) and [`ClientStats`](/docs/docs/api/ClientStats.md).
|
bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/BalancedPool.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Class: BalancedPool
|
| 2 |
+
|
| 3 |
+
Extends: `undici.Dispatcher`
|
| 4 |
+
|
| 5 |
+
A pool of [Pool](/docs/docs/api/Pool.md) instances connected to multiple upstreams.
|
| 6 |
+
|
| 7 |
+
Requests are not guaranteed to be dispatched in order of invocation.
|
| 8 |
+
|
| 9 |
+
## `new BalancedPool(upstreams [, options])`
|
| 10 |
+
|
| 11 |
+
Arguments:
|
| 12 |
+
|
| 13 |
+
* **upstreams** `URL | string | string[]` - It should only include the **protocol, hostname, and port**.
|
| 14 |
+
* **options** `BalancedPoolOptions` (optional)
|
| 15 |
+
|
| 16 |
+
### Parameter: `BalancedPoolOptions`
|
| 17 |
+
|
| 18 |
+
Extends: [`PoolOptions`](/docs/docs/api/Pool.md#parameter-pooloptions)
|
| 19 |
+
|
| 20 |
+
* **factory** `(origin: URL, opts: Object) => Dispatcher` - Default: `(origin, opts) => new Pool(origin, opts)`
|
| 21 |
+
|
| 22 |
+
The `PoolOptions` are passed to each of the `Pool` instances being created.
|
| 23 |
+
## Instance Properties
|
| 24 |
+
|
| 25 |
+
### `BalancedPool.upstreams`
|
| 26 |
+
|
| 27 |
+
Returns an array of upstreams that were previously added.
|
| 28 |
+
|
| 29 |
+
### `BalancedPool.closed`
|
| 30 |
+
|
| 31 |
+
Implements [Client.closed](/docs/docs/api/Client.md#clientclosed)
|
| 32 |
+
|
| 33 |
+
### `BalancedPool.destroyed`
|
| 34 |
+
|
| 35 |
+
Implements [Client.destroyed](/docs/docs/api/Client.md#clientdestroyed)
|
| 36 |
+
|
| 37 |
+
### `Pool.stats`
|
| 38 |
+
|
| 39 |
+
Returns [`PoolStats`](/docs/docs/api/PoolStats.md) instance for this pool.
|
| 40 |
+
|
| 41 |
+
## Instance Methods
|
| 42 |
+
|
| 43 |
+
### `BalancedPool.addUpstream(upstream)`
|
| 44 |
+
|
| 45 |
+
Add an upstream.
|
| 46 |
+
|
| 47 |
+
Arguments:
|
| 48 |
+
|
| 49 |
+
* **upstream** `string` - It should only include the **protocol, hostname, and port**.
|
| 50 |
+
|
| 51 |
+
### `BalancedPool.removeUpstream(upstream)`
|
| 52 |
+
|
| 53 |
+
Removes an upstream that was previously added.
|
| 54 |
+
|
| 55 |
+
### `BalancedPool.close([callback])`
|
| 56 |
+
|
| 57 |
+
Implements [`Dispatcher.close([callback])`](/docs/docs/api/Dispatcher.md#dispatcherclosecallback-promise).
|
| 58 |
+
|
| 59 |
+
### `BalancedPool.destroy([error, callback])`
|
| 60 |
+
|
| 61 |
+
Implements [`Dispatcher.destroy([error, callback])`](/docs/docs/api/Dispatcher.md#dispatcherdestroyerror-callback-promise).
|
| 62 |
+
|
| 63 |
+
### `BalancedPool.connect(options[, callback])`
|
| 64 |
+
|
| 65 |
+
See [`Dispatcher.connect(options[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherconnectoptions-callback).
|
| 66 |
+
|
| 67 |
+
### `BalancedPool.dispatch(options, handlers)`
|
| 68 |
+
|
| 69 |
+
Implements [`Dispatcher.dispatch(options, handlers)`](/docs/docs/api/Dispatcher.md#dispatcherdispatchoptions-handler).
|
| 70 |
+
|
| 71 |
+
### `BalancedPool.pipeline(options, handler)`
|
| 72 |
+
|
| 73 |
+
See [`Dispatcher.pipeline(options, handler)`](/docs/docs/api/Dispatcher.md#dispatcherpipelineoptions-handler).
|
| 74 |
+
|
| 75 |
+
### `BalancedPool.request(options[, callback])`
|
| 76 |
+
|
| 77 |
+
See [`Dispatcher.request(options [, callback])`](/docs/docs/api/Dispatcher.md#dispatcherrequestoptions-callback).
|
| 78 |
+
|
| 79 |
+
### `BalancedPool.stream(options, factory[, callback])`
|
| 80 |
+
|
| 81 |
+
See [`Dispatcher.stream(options, factory[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherstreamoptions-factory-callback).
|
| 82 |
+
|
| 83 |
+
### `BalancedPool.upgrade(options[, callback])`
|
| 84 |
+
|
| 85 |
+
See [`Dispatcher.upgrade(options[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherupgradeoptions-callback).
|
| 86 |
+
|
| 87 |
+
## Instance Events
|
| 88 |
+
|
| 89 |
+
### Event: `'connect'`
|
| 90 |
+
|
| 91 |
+
See [Dispatcher Event: `'connect'`](/docs/docs/api/Dispatcher.md#event-connect).
|
| 92 |
+
|
| 93 |
+
### Event: `'disconnect'`
|
| 94 |
+
|
| 95 |
+
See [Dispatcher Event: `'disconnect'`](/docs/docs/api/Dispatcher.md#event-disconnect).
|
| 96 |
+
|
| 97 |
+
### Event: `'drain'`
|
| 98 |
+
|
| 99 |
+
See [Dispatcher Event: `'drain'`](/docs/docs/api/Dispatcher.md#event-drain).
|
bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/CacheStorage.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CacheStorage
|
| 2 |
+
|
| 3 |
+
Undici exposes a W3C spec-compliant implementation of [CacheStorage](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage) and [Cache](https://developer.mozilla.org/en-US/docs/Web/API/Cache).
|
| 4 |
+
|
| 5 |
+
## Opening a Cache
|
| 6 |
+
|
| 7 |
+
Undici exports a top-level CacheStorage instance. You can open a new Cache, or duplicate a Cache with an existing name, by using `CacheStorage.prototype.open`. If you open a Cache with the same name as an already-existing Cache, its list of cached Responses will be shared between both instances.
|
| 8 |
+
|
| 9 |
+
```mjs
|
| 10 |
+
import { caches } from 'undici'
|
| 11 |
+
|
| 12 |
+
const cache_1 = await caches.open('v1')
|
| 13 |
+
const cache_2 = await caches.open('v1')
|
| 14 |
+
|
| 15 |
+
// Although .open() creates a new instance,
|
| 16 |
+
assert(cache_1 !== cache_2)
|
| 17 |
+
// The same Response is matched in both.
|
| 18 |
+
assert.deepStrictEqual(await cache_1.match('/req'), await cache_2.match('/req'))
|
| 19 |
+
```
|
| 20 |
+
|
| 21 |
+
## Deleting a Cache
|
| 22 |
+
|
| 23 |
+
If a Cache is deleted, the cached Responses/Requests can still be used.
|
| 24 |
+
|
| 25 |
+
```mjs
|
| 26 |
+
const response = await cache_1.match('/req')
|
| 27 |
+
await caches.delete('v1')
|
| 28 |
+
|
| 29 |
+
await response.text() // the Response's body
|
| 30 |
+
```
|
bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/CacheStore.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Cache Store
|
| 2 |
+
|
| 3 |
+
A Cache Store is responsible for storing and retrieving cached responses.
|
| 4 |
+
It is also responsible for deciding which specific response to use based off of
|
| 5 |
+
a response's `Vary` header (if present). It is expected to be compliant with
|
| 6 |
+
[RFC-9111](https://www.rfc-editor.org/rfc/rfc9111.html).
|
| 7 |
+
|
| 8 |
+
## Pre-built Cache Stores
|
| 9 |
+
|
| 10 |
+
### `MemoryCacheStore`
|
| 11 |
+
|
| 12 |
+
The `MemoryCacheStore` stores the responses in-memory.
|
| 13 |
+
|
| 14 |
+
**Options**
|
| 15 |
+
|
| 16 |
+
- `maxSize` - The maximum total size in bytes of all stored responses. Default `104857600` (100MB).
|
| 17 |
+
- `maxCount` - The maximum amount of responses to store. Default `1024`.
|
| 18 |
+
- `maxEntrySize` - The maximum size in bytes that a response's body can be. If a response's body is greater than or equal to this, the response will not be cached. Default `5242880` (5MB).
|
| 19 |
+
|
| 20 |
+
### Getters
|
| 21 |
+
|
| 22 |
+
#### `MemoryCacheStore.size`
|
| 23 |
+
|
| 24 |
+
Returns the current total size in bytes of all stored responses.
|
| 25 |
+
|
| 26 |
+
### Methods
|
| 27 |
+
|
| 28 |
+
#### `MemoryCacheStore.isFull()`
|
| 29 |
+
|
| 30 |
+
Returns a boolean indicating whether the cache has reached its maximum size or count.
|
| 31 |
+
|
| 32 |
+
### Events
|
| 33 |
+
|
| 34 |
+
#### `'maxSizeExceeded'`
|
| 35 |
+
|
| 36 |
+
Emitted when the cache exceeds its maximum size or count limits. The event payload contains `size`, `maxSize`, `count`, and `maxCount` properties.
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
### `SqliteCacheStore`
|
| 40 |
+
|
| 41 |
+
The `SqliteCacheStore` stores the responses in a SQLite database.
|
| 42 |
+
Under the hood, it uses Node.js' [`node:sqlite`](https://nodejs.org/api/sqlite.html) api.
|
| 43 |
+
The `SqliteCacheStore` is only exposed if the `node:sqlite` api is present.
|
| 44 |
+
|
| 45 |
+
**Options**
|
| 46 |
+
|
| 47 |
+
- `location` - The location of the SQLite database to use. Default `:memory:`.
|
| 48 |
+
- `maxCount` - The maximum number of entries to store in the database. Default `Infinity`.
|
| 49 |
+
- `maxEntrySize` - The maximum size in bytes that a response's body can be. If a response's body is greater than or equal to this, the response will not be cached. Default `Infinity`.
|
| 50 |
+
|
| 51 |
+
## Defining a Custom Cache Store
|
| 52 |
+
|
| 53 |
+
The store must implement the following functions:
|
| 54 |
+
|
| 55 |
+
### Getter: `isFull`
|
| 56 |
+
|
| 57 |
+
Optional. This tells the cache interceptor if the store is full or not. If this is true,
|
| 58 |
+
the cache interceptor will not attempt to cache the response.
|
| 59 |
+
|
| 60 |
+
### Function: `get`
|
| 61 |
+
|
| 62 |
+
Parameters:
|
| 63 |
+
|
| 64 |
+
* **req** `Dispatcher.RequestOptions` - Incoming request
|
| 65 |
+
|
| 66 |
+
Returns: `GetResult | Promise<GetResult | undefined> | undefined` - If the request is cached, the cached response is returned. If the request's method is anything other than HEAD, the response is also returned.
|
| 67 |
+
If the request isn't cached, `undefined` is returned.
|
| 68 |
+
|
| 69 |
+
The `get` method may return a `Promise` for async cache stores (e.g. Redis-backed or remote stores). The cache interceptor handles both synchronous and asynchronous return values, including in revalidation paths (304 Not Modified handling and stale-while-revalidate background revalidation).
|
| 70 |
+
|
| 71 |
+
Response properties:
|
| 72 |
+
|
| 73 |
+
* **response** `CacheValue` - The cached response data.
|
| 74 |
+
* **body** `Readable | Iterable<Buffer> | undefined` - The response's body. This can be an array of `Buffer` chunks (with a `.values()` method) or a `Readable` stream. Both formats are supported in all code paths, including 304 revalidation.
|
| 75 |
+
|
| 76 |
+
### Function: `createWriteStream`
|
| 77 |
+
|
| 78 |
+
Parameters:
|
| 79 |
+
|
| 80 |
+
* **req** `Dispatcher.RequestOptions` - Incoming request
|
| 81 |
+
* **value** `CacheValue` - Response to store
|
| 82 |
+
|
| 83 |
+
Returns: `Writable | undefined` - If the store is full, return `undefined`. Otherwise, return a writable so that the cache interceptor can stream the body and trailers to the store.
|
| 84 |
+
|
| 85 |
+
## `CacheValue`
|
| 86 |
+
|
| 87 |
+
This is an interface containing the majority of a response's data (minus the body).
|
| 88 |
+
|
| 89 |
+
### Property `statusCode`
|
| 90 |
+
|
| 91 |
+
`number` - The response's HTTP status code.
|
| 92 |
+
|
| 93 |
+
### Property `statusMessage`
|
| 94 |
+
|
| 95 |
+
`string` - The response's HTTP status message.
|
| 96 |
+
|
| 97 |
+
### Property `rawHeaders`
|
| 98 |
+
|
| 99 |
+
`Buffer[]` - The response's headers.
|
| 100 |
+
|
| 101 |
+
### Property `vary`
|
| 102 |
+
|
| 103 |
+
`Record<string, string | string[] | null> | undefined` - The headers defined by the response's `Vary` header
|
| 104 |
+
and their respective values for later comparison. Values are `null` when the
|
| 105 |
+
header specified in `Vary` was not present in the original request. These `null`
|
| 106 |
+
values are automatically filtered out during revalidation so they are not sent
|
| 107 |
+
as request headers.
|
| 108 |
+
|
| 109 |
+
For example, for a response like
|
| 110 |
+
```
|
| 111 |
+
Vary: content-encoding, accepts
|
| 112 |
+
content-encoding: utf8
|
| 113 |
+
accepts: application/json
|
| 114 |
+
```
|
| 115 |
+
|
| 116 |
+
This would be
|
| 117 |
+
```js
|
| 118 |
+
{
|
| 119 |
+
'content-encoding': 'utf8',
|
| 120 |
+
accepts: 'application/json'
|
| 121 |
+
}
|
| 122 |
+
```
|
| 123 |
+
|
| 124 |
+
If the original request did not include the `accepts` header:
|
| 125 |
+
```js
|
| 126 |
+
{
|
| 127 |
+
'content-encoding': 'utf8',
|
| 128 |
+
accepts: null
|
| 129 |
+
}
|
| 130 |
+
```
|
| 131 |
+
|
| 132 |
+
### Property `cachedAt`
|
| 133 |
+
|
| 134 |
+
`number` - Time in millis that this value was cached.
|
| 135 |
+
|
| 136 |
+
### Property `staleAt`
|
| 137 |
+
|
| 138 |
+
`number` - Time in millis that this value is considered stale.
|
| 139 |
+
|
| 140 |
+
### Property `deleteAt`
|
| 141 |
+
|
| 142 |
+
`number` - Time in millis that this value is to be deleted from the cache. This
|
| 143 |
+
is either the same sa staleAt or the `max-stale` caching directive.
|
| 144 |
+
|
| 145 |
+
The store must not return a response after the time defined in this property.
|
| 146 |
+
|
| 147 |
+
## `CacheStoreReadable`
|
| 148 |
+
|
| 149 |
+
This extends Node's [`Readable`](https://nodejs.org/api/stream.html#class-streamreadable)
|
| 150 |
+
and defines extra properties relevant to the cache interceptor.
|
| 151 |
+
|
| 152 |
+
### Getter: `value`
|
| 153 |
+
|
| 154 |
+
The response's [`CacheStoreValue`](/docs/docs/api/CacheStore.md#cachestorevalue)
|
| 155 |
+
|
| 156 |
+
## `CacheStoreWriteable`
|
| 157 |
+
|
| 158 |
+
This extends Node's [`Writable`](https://nodejs.org/api/stream.html#class-streamwritable)
|
| 159 |
+
and defines extra properties relevant to the cache interceptor.
|
| 160 |
+
|
| 161 |
+
### Setter: `rawTrailers`
|
| 162 |
+
|
| 163 |
+
If the response has trailers, the cache interceptor will pass them to the cache
|
| 164 |
+
interceptor through this method.
|
bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/Client.md
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Class: Client
|
| 2 |
+
|
| 3 |
+
Extends: `undici.Dispatcher`
|
| 4 |
+
|
| 5 |
+
A basic HTTP/1.1 client, mapped on top a single TCP/TLS connection. Pipelining is disabled by default.
|
| 6 |
+
|
| 7 |
+
Requests are not guaranteed to be dispatched in order of invocation.
|
| 8 |
+
|
| 9 |
+
## `new Client(url[, options])`
|
| 10 |
+
|
| 11 |
+
Arguments:
|
| 12 |
+
|
| 13 |
+
* **url** `URL | string` - Should only include the **protocol, hostname, and port**.
|
| 14 |
+
* **options** `ClientOptions` (optional)
|
| 15 |
+
|
| 16 |
+
Returns: `Client`
|
| 17 |
+
|
| 18 |
+
### Parameter: `ClientOptions`
|
| 19 |
+
|
| 20 |
+
* **bodyTimeout** `number | null` (optional) - Default: `300e3` - The timeout after which a request will time out, in milliseconds. Monitors time between receiving body data. Use `0` to disable it entirely. Defaults to 300 seconds. Please note the `timeout` will be reset if you keep writing data to the socket everytime.
|
| 21 |
+
* **headersTimeout** `number | null` (optional) - Default: `300e3` - The amount of time, in milliseconds, the parser will wait to receive the complete HTTP headers while not sending the request. Defaults to 300 seconds.
|
| 22 |
+
* **keepAliveMaxTimeout** `number | null` (optional) - Default: `600e3` - The maximum allowed `keepAliveTimeout`, in milliseconds, when overridden by *keep-alive* hints from the server. Defaults to 10 minutes.
|
| 23 |
+
* **keepAliveTimeout** `number | null` (optional) - Default: `4e3` - The timeout, in milliseconds, after which a socket without active requests will time out. Monitors time between activity on a connected socket. This value may be overridden by *keep-alive* hints from the server. See [MDN: HTTP - Headers - Keep-Alive directives](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive#directives) for more details. Defaults to 4 seconds.
|
| 24 |
+
* **keepAliveTimeoutThreshold** `number | null` (optional) - Default: `2e3` - A number of milliseconds subtracted from server *keep-alive* hints when overriding `keepAliveTimeout` to account for timing inaccuracies caused by e.g. transport latency. Defaults to 2 seconds.
|
| 25 |
+
* **maxHeaderSize** `number | null` (optional) - Default: `--max-http-header-size` or `16384` - The maximum length of request headers in bytes. Defaults to Node.js' --max-http-header-size or 16KiB.
|
| 26 |
+
* **maxResponseSize** `number | null` (optional) - Default: `-1` - The maximum length of response body in bytes. Set to `-1` to disable.
|
| 27 |
+
* **webSocket** `WebSocketOptions` (optional) - WebSocket-specific configuration options.
|
| 28 |
+
* **maxFragments** `number` (optional) - Default: `131072` - Maximum number of fragments in a message. Set to 0 to disable the limit.
|
| 29 |
+
* **maxPayloadSize** `number` (optional) - Default: `134217728` (128 MB) - Maximum allowed payload size in bytes for WebSocket messages. Applied to uncompressed messages, compressed frame payloads, and decompressed (permessage-deflate) messages. Set to 0 to disable the limit.
|
| 30 |
+
* **pipelining** `number | null` (optional) - Default: `1` - The amount of concurrent requests to be sent over the single TCP/TLS connection according to [RFC7230](https://tools.ietf.org/html/rfc7230#section-6.3.2). Carefully consider your workload and environment before enabling concurrent requests as pipelining may reduce performance if used incorrectly. Pipelining is sensitive to network stack settings as well as head of line blocking caused by e.g. long running requests. Set to `0` to disable keep-alive connections.
|
| 31 |
+
* **connect** `ConnectOptions | Function | null` (optional) - Default: `null`.
|
| 32 |
+
* **strictContentLength** `Boolean` (optional) - Default: `true` - Whether to treat request content length mismatches as errors. If true, an error is thrown when the request content-length header doesn't match the length of the request body. **Security Warning:** Disabling this option can expose your application to HTTP Request Smuggling attacks, where mismatched content-length headers cause servers and proxies to interpret request boundaries differently. This can lead to cache poisoning, credential hijacking, and bypassing security controls. Only disable this in controlled environments where you fully trust the request source.
|
| 33 |
+
* **autoSelectFamily**: `boolean` (optional) - Default: depends on local Node version, on Node 18.13.0 and above is `false`. Enables a family autodetection algorithm that loosely implements section 5 of [RFC 8305](https://tools.ietf.org/html/rfc8305#section-5). See [here](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) for more details. This option is ignored if not supported by the current Node version.
|
| 34 |
+
* **autoSelectFamilyAttemptTimeout**: `number` - Default: depends on local Node version, on Node 18.13.0 and above is `250`. The amount of time in milliseconds to wait for a connection attempt to finish before trying the next address when using the `autoSelectFamily` option. See [here](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) for more details.
|
| 35 |
+
* **allowH2**: `boolean` - Default: `false`. Enables support for H2 if the server has assigned bigger priority to it through ALPN negotiation.
|
| 36 |
+
* **useH2c**: `boolean` - Default: `false`. Enforces h2c for non-https connections.
|
| 37 |
+
* **maxConcurrentStreams**: `number` - Default: `100`. Dictates the maximum number of concurrent streams for a single H2 session. It can be overridden by a SETTINGS remote frame.
|
| 38 |
+
* **initialWindowSize**: `number` (optional) - Default: `262144` (256KB). Sets the HTTP/2 stream-level flow-control window size (SETTINGS_INITIAL_WINDOW_SIZE). Must be a positive integer greater than 0. This default is higher than Node.js core's default (65535 bytes) to improve throughput, Node's choice is very conservative for current high-bandwith networks. See [RFC 7540 Section 6.9.2](https://datatracker.ietf.org/doc/html/rfc7540#section-6.9.2) for more details.
|
| 39 |
+
* **connectionWindowSize**: `number` (optional) - Default `524288` (512KB). Sets the HTTP/2 connection-level flow-control window size using `ClientHttp2Session.setLocalWindowSize()`. Must be a positive integer greater than 0. This provides better flow control for the entire connection across multiple streams. See [Node.js HTTP/2 documentation](https://nodejs.org/api/http2.html#clienthttp2sessionsetlocalwindowsize) for more details.
|
| 40 |
+
* **pingInterval**: `number` - Default: `60e3`. The time interval in milliseconds between PING frames sent to the server. Set to `0` to disable PING frames. This is only applicable for HTTP/2 connections. This will emit a `ping` event on the client with the duration of the ping in milliseconds.
|
| 41 |
+
|
| 42 |
+
> **Notes about HTTP/2**
|
| 43 |
+
> - It only works under TLS connections. h2c is not supported.
|
| 44 |
+
> - The server must support HTTP/2 and choose it as the protocol during the ALPN negotiation.
|
| 45 |
+
> - The server must not have a bigger priority for HTTP/1.1 than HTTP/2.
|
| 46 |
+
> - Pseudo headers are automatically attached to the request. If you try to set them, they will be overwritten.
|
| 47 |
+
> - The `:path` header is automatically set to the request path.
|
| 48 |
+
> - The `:method` header is automatically set to the request method.
|
| 49 |
+
> - The `:scheme` header is automatically set to the request scheme.
|
| 50 |
+
> - The `:authority` header is automatically set to the request `host[:port]`.
|
| 51 |
+
> - `PUSH` frames are yet not supported.
|
| 52 |
+
|
| 53 |
+
#### Parameter: `ConnectOptions`
|
| 54 |
+
|
| 55 |
+
Every Tls option, see [here](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback).
|
| 56 |
+
Furthermore, the following options can be passed:
|
| 57 |
+
|
| 58 |
+
* **socketPath** `string | null` (optional) - Default: `null` - An IPC endpoint, either Unix domain socket or Windows named pipe.
|
| 59 |
+
* **maxCachedSessions** `number | null` (optional) - Default: `100` - Maximum number of TLS cached sessions. Use 0 to disable TLS session caching. Default: 100.
|
| 60 |
+
* **timeout** `number | null` (optional) - In milliseconds, Default `10e3`.
|
| 61 |
+
* **servername** `string | null` (optional)
|
| 62 |
+
* **keepAlive** `boolean | null` (optional) - Default: `true` - TCP keep-alive enabled
|
| 63 |
+
* **keepAliveInitialDelay** `number | null` (optional) - Default: `60000` - TCP keep-alive interval for the socket in milliseconds
|
| 64 |
+
|
| 65 |
+
### Example - Basic Client instantiation
|
| 66 |
+
|
| 67 |
+
This will instantiate the undici Client, but it will not connect to the origin until something is queued. Consider using `client.connect` to prematurely connect to the origin, or just call `client.request`.
|
| 68 |
+
|
| 69 |
+
```js
|
| 70 |
+
'use strict'
|
| 71 |
+
import { Client } from 'undici'
|
| 72 |
+
|
| 73 |
+
const client = new Client('http://localhost:3000')
|
| 74 |
+
```
|
| 75 |
+
|
| 76 |
+
### Example - Custom connector
|
| 77 |
+
|
| 78 |
+
This will allow you to perform some additional check on the socket that will be used for the next request.
|
| 79 |
+
|
| 80 |
+
```js
|
| 81 |
+
'use strict'
|
| 82 |
+
import { Client, buildConnector } from 'undici'
|
| 83 |
+
|
| 84 |
+
const connector = buildConnector({ rejectUnauthorized: false })
|
| 85 |
+
const client = new Client('https://localhost:3000', {
|
| 86 |
+
connect (opts, cb) {
|
| 87 |
+
connector(opts, (err, socket) => {
|
| 88 |
+
if (err) {
|
| 89 |
+
cb(err)
|
| 90 |
+
} else if (/* assertion */) {
|
| 91 |
+
socket.destroy()
|
| 92 |
+
cb(new Error('kaboom'))
|
| 93 |
+
} else {
|
| 94 |
+
cb(null, socket)
|
| 95 |
+
}
|
| 96 |
+
})
|
| 97 |
+
}
|
| 98 |
+
})
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
## Instance Methods
|
| 102 |
+
|
| 103 |
+
### `Client.close([callback])`
|
| 104 |
+
|
| 105 |
+
Implements [`Dispatcher.close([callback])`](/docs/docs/api/Dispatcher.md#dispatcherclosecallback-promise).
|
| 106 |
+
|
| 107 |
+
### `Client.destroy([error, callback])`
|
| 108 |
+
|
| 109 |
+
Implements [`Dispatcher.destroy([error, callback])`](/docs/docs/api/Dispatcher.md#dispatcherdestroyerror-callback-promise).
|
| 110 |
+
|
| 111 |
+
Waits until socket is closed before invoking the callback (or returning a promise if no callback is provided).
|
| 112 |
+
|
| 113 |
+
### `Client.connect(options[, callback])`
|
| 114 |
+
|
| 115 |
+
See [`Dispatcher.connect(options[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherconnectoptions-callback).
|
| 116 |
+
|
| 117 |
+
### `Client.dispatch(options, handlers)`
|
| 118 |
+
|
| 119 |
+
Implements [`Dispatcher.dispatch(options, handlers)`](/docs/docs/api/Dispatcher.md#dispatcherdispatchoptions-handler).
|
| 120 |
+
|
| 121 |
+
### `Client.pipeline(options, handler)`
|
| 122 |
+
|
| 123 |
+
See [`Dispatcher.pipeline(options, handler)`](/docs/docs/api/Dispatcher.md#dispatcherpipelineoptions-handler).
|
| 124 |
+
|
| 125 |
+
### `Client.request(options[, callback])`
|
| 126 |
+
|
| 127 |
+
See [`Dispatcher.request(options [, callback])`](/docs/docs/api/Dispatcher.md#dispatcherrequestoptions-callback).
|
| 128 |
+
|
| 129 |
+
### `Client.stream(options, factory[, callback])`
|
| 130 |
+
|
| 131 |
+
See [`Dispatcher.stream(options, factory[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherstreamoptions-factory-callback).
|
| 132 |
+
|
| 133 |
+
### `Client.upgrade(options[, callback])`
|
| 134 |
+
|
| 135 |
+
See [`Dispatcher.upgrade(options[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherupgradeoptions-callback).
|
| 136 |
+
|
| 137 |
+
## Instance Properties
|
| 138 |
+
|
| 139 |
+
### `Client.closed`
|
| 140 |
+
|
| 141 |
+
* `boolean`
|
| 142 |
+
|
| 143 |
+
`true` after `client.close()` has been called.
|
| 144 |
+
|
| 145 |
+
### `Client.destroyed`
|
| 146 |
+
|
| 147 |
+
* `boolean`
|
| 148 |
+
|
| 149 |
+
`true` after `client.destroyed()` has been called or `client.close()` has been called and the client shutdown has completed.
|
| 150 |
+
|
| 151 |
+
### `Client.pipelining`
|
| 152 |
+
|
| 153 |
+
* `number`
|
| 154 |
+
|
| 155 |
+
Property to get and set the pipelining factor.
|
| 156 |
+
|
| 157 |
+
## Instance Events
|
| 158 |
+
|
| 159 |
+
### Event: `'connect'`
|
| 160 |
+
|
| 161 |
+
See [Dispatcher Event: `'connect'`](/docs/docs/api/Dispatcher.md#event-connect).
|
| 162 |
+
|
| 163 |
+
Parameters:
|
| 164 |
+
|
| 165 |
+
* **origin** `URL`
|
| 166 |
+
* **targets** `Array<Dispatcher>`
|
| 167 |
+
|
| 168 |
+
Emitted when a socket has been created and connected. The client will connect once `client.size > 0`.
|
| 169 |
+
|
| 170 |
+
#### Example - Client connect event
|
| 171 |
+
|
| 172 |
+
```js
|
| 173 |
+
import { createServer } from 'http'
|
| 174 |
+
import { Client } from 'undici'
|
| 175 |
+
import { once } from 'events'
|
| 176 |
+
|
| 177 |
+
const server = createServer((request, response) => {
|
| 178 |
+
response.end('Hello, World!')
|
| 179 |
+
}).listen()
|
| 180 |
+
|
| 181 |
+
await once(server, 'listening')
|
| 182 |
+
|
| 183 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 184 |
+
|
| 185 |
+
client.on('connect', (origin) => {
|
| 186 |
+
console.log(`Connected to ${origin}`) // should print before the request body statement
|
| 187 |
+
})
|
| 188 |
+
|
| 189 |
+
try {
|
| 190 |
+
const { body } = await client.request({
|
| 191 |
+
path: '/',
|
| 192 |
+
method: 'GET'
|
| 193 |
+
})
|
| 194 |
+
body.setEncoding('utf-8')
|
| 195 |
+
body.on('data', console.log)
|
| 196 |
+
client.close()
|
| 197 |
+
server.close()
|
| 198 |
+
} catch (error) {
|
| 199 |
+
console.error(error)
|
| 200 |
+
client.close()
|
| 201 |
+
server.close()
|
| 202 |
+
}
|
| 203 |
+
```
|
| 204 |
+
|
| 205 |
+
### Event: `'disconnect'`
|
| 206 |
+
|
| 207 |
+
See [Dispatcher Event: `'disconnect'`](/docs/docs/api/Dispatcher.md#event-disconnect).
|
| 208 |
+
|
| 209 |
+
Parameters:
|
| 210 |
+
|
| 211 |
+
* **origin** `URL`
|
| 212 |
+
* **targets** `Array<Dispatcher>`
|
| 213 |
+
* **error** `Error`
|
| 214 |
+
|
| 215 |
+
Emitted when socket has disconnected. The error argument of the event is the error which caused the socket to disconnect. The client will reconnect if or once `client.size > 0`.
|
| 216 |
+
|
| 217 |
+
#### Example - Client disconnect event
|
| 218 |
+
|
| 219 |
+
```js
|
| 220 |
+
import { createServer } from 'http'
|
| 221 |
+
import { Client } from 'undici'
|
| 222 |
+
import { once } from 'events'
|
| 223 |
+
|
| 224 |
+
const server = createServer((request, response) => {
|
| 225 |
+
response.destroy()
|
| 226 |
+
}).listen()
|
| 227 |
+
|
| 228 |
+
await once(server, 'listening')
|
| 229 |
+
|
| 230 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 231 |
+
|
| 232 |
+
client.on('disconnect', (origin) => {
|
| 233 |
+
console.log(`Disconnected from ${origin}`)
|
| 234 |
+
})
|
| 235 |
+
|
| 236 |
+
try {
|
| 237 |
+
await client.request({
|
| 238 |
+
path: '/',
|
| 239 |
+
method: 'GET'
|
| 240 |
+
})
|
| 241 |
+
} catch (error) {
|
| 242 |
+
console.error(error.message)
|
| 243 |
+
client.close()
|
| 244 |
+
server.close()
|
| 245 |
+
}
|
| 246 |
+
```
|
| 247 |
+
|
| 248 |
+
### Event: `'drain'`
|
| 249 |
+
|
| 250 |
+
Emitted when pipeline is no longer busy.
|
| 251 |
+
|
| 252 |
+
See [Dispatcher Event: `'drain'`](/docs/docs/api/Dispatcher.md#event-drain).
|
| 253 |
+
|
| 254 |
+
#### Example - Client drain event
|
| 255 |
+
|
| 256 |
+
```js
|
| 257 |
+
import { createServer } from 'http'
|
| 258 |
+
import { Client } from 'undici'
|
| 259 |
+
import { once } from 'events'
|
| 260 |
+
|
| 261 |
+
const server = createServer((request, response) => {
|
| 262 |
+
response.end('Hello, World!')
|
| 263 |
+
}).listen()
|
| 264 |
+
|
| 265 |
+
await once(server, 'listening')
|
| 266 |
+
|
| 267 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 268 |
+
|
| 269 |
+
client.on('drain', () => {
|
| 270 |
+
console.log('drain event')
|
| 271 |
+
client.close()
|
| 272 |
+
server.close()
|
| 273 |
+
})
|
| 274 |
+
|
| 275 |
+
const requests = [
|
| 276 |
+
client.request({ path: '/', method: 'GET' }),
|
| 277 |
+
client.request({ path: '/', method: 'GET' }),
|
| 278 |
+
client.request({ path: '/', method: 'GET' })
|
| 279 |
+
]
|
| 280 |
+
|
| 281 |
+
await Promise.all(requests)
|
| 282 |
+
|
| 283 |
+
console.log('requests completed')
|
| 284 |
+
```
|
| 285 |
+
|
| 286 |
+
### Event: `'error'`
|
| 287 |
+
|
| 288 |
+
Invoked for users errors such as throwing in the `onError` handler.
|
bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/ClientStats.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Class: ClientStats
|
| 2 |
+
|
| 3 |
+
Stats for a [Client](/docs/docs/api/Client.md).
|
| 4 |
+
|
| 5 |
+
## `new ClientStats(client)`
|
| 6 |
+
|
| 7 |
+
Arguments:
|
| 8 |
+
|
| 9 |
+
* **client** `Client` - Client from which to return stats.
|
| 10 |
+
|
| 11 |
+
## Instance Properties
|
| 12 |
+
|
| 13 |
+
### `ClientStats.connected`
|
| 14 |
+
|
| 15 |
+
Boolean if socket as open connection by this client.
|
| 16 |
+
|
| 17 |
+
### `ClientStats.pending`
|
| 18 |
+
|
| 19 |
+
Number of pending requests of this client.
|
| 20 |
+
|
| 21 |
+
### `ClientStats.running`
|
| 22 |
+
|
| 23 |
+
Number of currently active requests across this client.
|
| 24 |
+
|
| 25 |
+
### `ClientStats.size`
|
| 26 |
+
|
| 27 |
+
Number of active, pending, or queued requests of this clients.
|
bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/Connector.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Connector
|
| 2 |
+
|
| 3 |
+
Undici creates the underlying socket via the connector builder.
|
| 4 |
+
Normally, this happens automatically and you don't need to care about this,
|
| 5 |
+
but if you need to perform some additional check over the currently used socket,
|
| 6 |
+
this is the right place.
|
| 7 |
+
|
| 8 |
+
If you want to create a custom connector, you must import the `buildConnector` utility.
|
| 9 |
+
|
| 10 |
+
#### Parameter: `buildConnector.BuildOptions`
|
| 11 |
+
|
| 12 |
+
Every Tls option, see [here](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback).
|
| 13 |
+
Furthermore, the following options can be passed:
|
| 14 |
+
|
| 15 |
+
* **socketPath** `string | null` (optional) - Default: `null` - An IPC endpoint, either Unix domain socket or Windows named pipe.
|
| 16 |
+
* **maxCachedSessions** `number | null` (optional) - Default: `100` - Maximum number of TLS cached sessions. Use 0 to disable TLS session caching. Default: `100`.
|
| 17 |
+
* **timeout** `number | null` (optional) - In milliseconds. Default `10e3`.
|
| 18 |
+
* **servername** `string | null` (optional)
|
| 19 |
+
|
| 20 |
+
Once you call `buildConnector`, it will return a connector function, which takes the following parameters.
|
| 21 |
+
|
| 22 |
+
#### Parameter: `connector.Options`
|
| 23 |
+
|
| 24 |
+
* **hostname** `string` (required)
|
| 25 |
+
* **host** `string` (optional)
|
| 26 |
+
* **protocol** `string` (required)
|
| 27 |
+
* **port** `string` (required)
|
| 28 |
+
* **servername** `string` (optional)
|
| 29 |
+
* **localAddress** `string | null` (optional) Local address the socket should connect from.
|
| 30 |
+
* **httpSocket** `Socket` (optional) Establish secure connection on a given socket rather than creating a new socket. It can only be sent on TLS update.
|
| 31 |
+
|
| 32 |
+
### Basic example
|
| 33 |
+
|
| 34 |
+
```js
|
| 35 |
+
'use strict'
|
| 36 |
+
|
| 37 |
+
import { Client, buildConnector } from 'undici'
|
| 38 |
+
|
| 39 |
+
const connector = buildConnector({ rejectUnauthorized: false })
|
| 40 |
+
const client = new Client('https://localhost:3000', {
|
| 41 |
+
connect (opts, cb) {
|
| 42 |
+
connector(opts, (err, socket) => {
|
| 43 |
+
if (err) {
|
| 44 |
+
cb(err)
|
| 45 |
+
} else if (/* assertion */) {
|
| 46 |
+
socket.destroy()
|
| 47 |
+
cb(new Error('kaboom'))
|
| 48 |
+
} else {
|
| 49 |
+
cb(null, socket)
|
| 50 |
+
}
|
| 51 |
+
})
|
| 52 |
+
}
|
| 53 |
+
})
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
### Example: validate the CA fingerprint
|
| 57 |
+
|
| 58 |
+
```js
|
| 59 |
+
'use strict'
|
| 60 |
+
|
| 61 |
+
import { Client, buildConnector } from 'undici'
|
| 62 |
+
|
| 63 |
+
const caFingerprint = 'FO:OB:AR'
|
| 64 |
+
const connector = buildConnector({ rejectUnauthorized: false })
|
| 65 |
+
const client = new Client('https://localhost:3000', {
|
| 66 |
+
connect (opts, cb) {
|
| 67 |
+
connector(opts, (err, socket) => {
|
| 68 |
+
if (err) {
|
| 69 |
+
cb(err)
|
| 70 |
+
} else if (getIssuerCertificate(socket).fingerprint256 !== caFingerprint) {
|
| 71 |
+
socket.destroy()
|
| 72 |
+
cb(new Error('Fingerprint does not match or malformed certificate'))
|
| 73 |
+
} else {
|
| 74 |
+
cb(null, socket)
|
| 75 |
+
}
|
| 76 |
+
})
|
| 77 |
+
}
|
| 78 |
+
})
|
| 79 |
+
|
| 80 |
+
client.request({
|
| 81 |
+
path: '/',
|
| 82 |
+
method: 'GET'
|
| 83 |
+
}, (err, data) => {
|
| 84 |
+
if (err) throw err
|
| 85 |
+
|
| 86 |
+
const bufs = []
|
| 87 |
+
data.body.on('data', (buf) => {
|
| 88 |
+
bufs.push(buf)
|
| 89 |
+
})
|
| 90 |
+
data.body.on('end', () => {
|
| 91 |
+
console.log(Buffer.concat(bufs).toString('utf8'))
|
| 92 |
+
client.close()
|
| 93 |
+
})
|
| 94 |
+
})
|
| 95 |
+
|
| 96 |
+
function getIssuerCertificate (socket) {
|
| 97 |
+
let certificate = socket.getPeerCertificate(true)
|
| 98 |
+
while (certificate && Object.keys(certificate).length > 0) {
|
| 99 |
+
// invalid certificate
|
| 100 |
+
if (certificate.issuerCertificate == null) {
|
| 101 |
+
return null
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
// We have reached the root certificate.
|
| 105 |
+
// In case of self-signed certificates, `issuerCertificate` may be a circular reference.
|
| 106 |
+
if (certificate.fingerprint256 === certificate.issuerCertificate.fingerprint256) {
|
| 107 |
+
break
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
// continue the loop
|
| 111 |
+
certificate = certificate.issuerCertificate
|
| 112 |
+
}
|
| 113 |
+
return certificate
|
| 114 |
+
}
|
| 115 |
+
```
|
bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/ContentType.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# MIME Type Parsing
|
| 2 |
+
|
| 3 |
+
## `MIMEType` interface
|
| 4 |
+
|
| 5 |
+
* **type** `string`
|
| 6 |
+
* **subtype** `string`
|
| 7 |
+
* **parameters** `Map<string, string>`
|
| 8 |
+
* **essence** `string`
|
| 9 |
+
|
| 10 |
+
## `parseMIMEType(input)`
|
| 11 |
+
|
| 12 |
+
Implements [parse a MIME type](https://mimesniff.spec.whatwg.org/#parse-a-mime-type).
|
| 13 |
+
|
| 14 |
+
Parses a MIME type, returning its type, subtype, and any associated parameters. If the parser can't parse an input it returns the string literal `'failure'`.
|
| 15 |
+
|
| 16 |
+
```js
|
| 17 |
+
import { parseMIMEType } from 'undici'
|
| 18 |
+
|
| 19 |
+
parseMIMEType('text/html; charset=gbk')
|
| 20 |
+
// {
|
| 21 |
+
// type: 'text',
|
| 22 |
+
// subtype: 'html',
|
| 23 |
+
// parameters: Map(1) { 'charset' => 'gbk' },
|
| 24 |
+
// essence: 'text/html'
|
| 25 |
+
// }
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
Arguments:
|
| 29 |
+
|
| 30 |
+
* **input** `string`
|
| 31 |
+
|
| 32 |
+
Returns: `MIMEType|'failure'`
|
| 33 |
+
|
| 34 |
+
## `serializeAMimeType(input)`
|
| 35 |
+
|
| 36 |
+
Implements [serialize a MIME type](https://mimesniff.spec.whatwg.org/#serialize-a-mime-type).
|
| 37 |
+
|
| 38 |
+
Serializes a MIMEType object.
|
| 39 |
+
|
| 40 |
+
```js
|
| 41 |
+
import { serializeAMimeType } from 'undici'
|
| 42 |
+
|
| 43 |
+
serializeAMimeType({
|
| 44 |
+
type: 'text',
|
| 45 |
+
subtype: 'html',
|
| 46 |
+
parameters: new Map([['charset', 'gbk']]),
|
| 47 |
+
essence: 'text/html'
|
| 48 |
+
})
|
| 49 |
+
// text/html;charset=gbk
|
| 50 |
+
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
Arguments:
|
| 54 |
+
|
| 55 |
+
* **mimeType** `MIMEType`
|
| 56 |
+
|
| 57 |
+
Returns: `string`
|
bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/Cookies.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Cookie Handling
|
| 2 |
+
|
| 3 |
+
## `Cookie` interface
|
| 4 |
+
|
| 5 |
+
* **name** `string`
|
| 6 |
+
* **value** `string`
|
| 7 |
+
* **expires** `Date|number` (optional)
|
| 8 |
+
* **maxAge** `number` (optional)
|
| 9 |
+
* **domain** `string` (optional)
|
| 10 |
+
* **path** `string` (optional)
|
| 11 |
+
* **secure** `boolean` (optional)
|
| 12 |
+
* **httpOnly** `boolean` (optional)
|
| 13 |
+
* **sameSite** `'String'|'Lax'|'None'` (optional)
|
| 14 |
+
* **unparsed** `string[]` (optional) Left over attributes that weren't parsed.
|
| 15 |
+
|
| 16 |
+
## `deleteCookie(headers, name[, attributes])`
|
| 17 |
+
|
| 18 |
+
Sets the expiry time of the cookie to the unix epoch, causing browsers to delete it when received.
|
| 19 |
+
|
| 20 |
+
```js
|
| 21 |
+
import { deleteCookie, Headers } from 'undici'
|
| 22 |
+
|
| 23 |
+
const headers = new Headers()
|
| 24 |
+
deleteCookie(headers, 'name')
|
| 25 |
+
|
| 26 |
+
console.log(headers.get('set-cookie')) // name=; Expires=Thu, 01 Jan 1970 00:00:00 GMT
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
Arguments:
|
| 30 |
+
|
| 31 |
+
* **headers** `Headers`
|
| 32 |
+
* **name** `string`
|
| 33 |
+
* **attributes** `{ path?: string, domain?: string }` (optional)
|
| 34 |
+
|
| 35 |
+
Returns: `void`
|
| 36 |
+
|
| 37 |
+
## `getCookies(headers)`
|
| 38 |
+
|
| 39 |
+
Parses the `Cookie` header and returns a list of attributes and values.
|
| 40 |
+
|
| 41 |
+
```js
|
| 42 |
+
import { getCookies, Headers } from 'undici'
|
| 43 |
+
|
| 44 |
+
const headers = new Headers({
|
| 45 |
+
cookie: 'get=cookies; and=attributes'
|
| 46 |
+
})
|
| 47 |
+
|
| 48 |
+
console.log(getCookies(headers)) // { get: 'cookies', and: 'attributes' }
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
Arguments:
|
| 52 |
+
|
| 53 |
+
* **headers** `Headers`
|
| 54 |
+
|
| 55 |
+
Returns: `Record<string, string>`
|
| 56 |
+
|
| 57 |
+
## `getSetCookies(headers)`
|
| 58 |
+
|
| 59 |
+
Parses all `Set-Cookie` headers.
|
| 60 |
+
|
| 61 |
+
```js
|
| 62 |
+
import { getSetCookies, Headers } from 'undici'
|
| 63 |
+
|
| 64 |
+
const headers = new Headers({ 'set-cookie': 'undici=getSetCookies; Secure' })
|
| 65 |
+
|
| 66 |
+
console.log(getSetCookies(headers))
|
| 67 |
+
// [
|
| 68 |
+
// {
|
| 69 |
+
// name: 'undici',
|
| 70 |
+
// value: 'getSetCookies',
|
| 71 |
+
// secure: true
|
| 72 |
+
// }
|
| 73 |
+
// ]
|
| 74 |
+
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
Arguments:
|
| 78 |
+
|
| 79 |
+
* **headers** `Headers`
|
| 80 |
+
|
| 81 |
+
Returns: `Cookie[]`
|
| 82 |
+
|
| 83 |
+
## `parseCookie(cookie)`
|
| 84 |
+
|
| 85 |
+
Parses a single `Set-Cookie` header value into a `Cookie` object.
|
| 86 |
+
|
| 87 |
+
```js
|
| 88 |
+
import { parseCookie } from 'undici'
|
| 89 |
+
|
| 90 |
+
console.log(parseCookie('undici=getSetCookies; Secure; SameSite=Lax'))
|
| 91 |
+
// {
|
| 92 |
+
// name: 'undici',
|
| 93 |
+
// value: 'getSetCookies',
|
| 94 |
+
// secure: true,
|
| 95 |
+
// sameSite: 'Lax'
|
| 96 |
+
// }
|
| 97 |
+
```
|
| 98 |
+
|
| 99 |
+
Notes:
|
| 100 |
+
|
| 101 |
+
* The cookie value is returned as it appears in the header. Percent-encoded sequences such as `%20` or `%0D%0A` are **not** decoded.
|
| 102 |
+
* `sameSite` is only set for exact case-insensitive matches of `Strict`, `Lax`, or `None`.
|
| 103 |
+
|
| 104 |
+
Arguments:
|
| 105 |
+
|
| 106 |
+
* **cookie** `string`
|
| 107 |
+
|
| 108 |
+
Returns: `Cookie | null`
|
| 109 |
+
|
| 110 |
+
## `setCookie(headers, cookie)`
|
| 111 |
+
|
| 112 |
+
Appends a cookie to the `Set-Cookie` header.
|
| 113 |
+
|
| 114 |
+
```js
|
| 115 |
+
import { setCookie, Headers } from 'undici'
|
| 116 |
+
|
| 117 |
+
const headers = new Headers()
|
| 118 |
+
setCookie(headers, { name: 'undici', value: 'setCookie' })
|
| 119 |
+
|
| 120 |
+
console.log(headers.get('Set-Cookie')) // undici=setCookie
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
+
Arguments:
|
| 124 |
+
|
| 125 |
+
* **headers** `Headers`
|
| 126 |
+
* **cookie** `Cookie`
|
| 127 |
+
|
| 128 |
+
Returns: `void`
|
bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/Debug.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Debug
|
| 2 |
+
|
| 3 |
+
Undici (and subsenquently `fetch` and `websocket`) exposes a debug statement that can be enabled by setting `NODE_DEBUG` within the environment.
|
| 4 |
+
|
| 5 |
+
The flags available are:
|
| 6 |
+
|
| 7 |
+
## `undici`
|
| 8 |
+
|
| 9 |
+
This flag enables debug statements for the core undici library.
|
| 10 |
+
|
| 11 |
+
```sh
|
| 12 |
+
NODE_DEBUG=undici node script.js
|
| 13 |
+
|
| 14 |
+
UNDICI 16241: connecting to nodejs.org using https:h1
|
| 15 |
+
UNDICI 16241: connecting to nodejs.org using https:h1
|
| 16 |
+
UNDICI 16241: connected to nodejs.org using https:h1
|
| 17 |
+
UNDICI 16241: sending request to GET https://nodejs.org/
|
| 18 |
+
UNDICI 16241: received response to GET https://nodejs.org/ - HTTP 307
|
| 19 |
+
UNDICI 16241: connecting to nodejs.org using https:h1
|
| 20 |
+
UNDICI 16241: trailers received from GET https://nodejs.org/
|
| 21 |
+
UNDICI 16241: connected to nodejs.org using https:h1
|
| 22 |
+
UNDICI 16241: sending request to GET https://nodejs.org/en
|
| 23 |
+
UNDICI 16241: received response to GET https://nodejs.org/en - HTTP 200
|
| 24 |
+
UNDICI 16241: trailers received from GET https://nodejs.org/en
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
## `fetch`
|
| 28 |
+
|
| 29 |
+
This flag enables debug statements for the `fetch` API.
|
| 30 |
+
|
| 31 |
+
> **Note**: statements are pretty similar to the ones in the `undici` flag, but scoped to `fetch`
|
| 32 |
+
|
| 33 |
+
```sh
|
| 34 |
+
NODE_DEBUG=fetch node script.js
|
| 35 |
+
|
| 36 |
+
FETCH 16241: connecting to nodejs.org using https:h1
|
| 37 |
+
FETCH 16241: connecting to nodejs.org using https:h1
|
| 38 |
+
FETCH 16241: connected to nodejs.org using https:h1
|
| 39 |
+
FETCH 16241: sending request to GET https://nodejs.org/
|
| 40 |
+
FETCH 16241: received response to GET https://nodejs.org/ - HTTP 307
|
| 41 |
+
FETCH 16241: connecting to nodejs.org using https:h1
|
| 42 |
+
FETCH 16241: trailers received from GET https://nodejs.org/
|
| 43 |
+
FETCH 16241: connected to nodejs.org using https:h1
|
| 44 |
+
FETCH 16241: sending request to GET https://nodejs.org/en
|
| 45 |
+
FETCH 16241: received response to GET https://nodejs.org/en - HTTP 200
|
| 46 |
+
FETCH 16241: trailers received from GET https://nodejs.org/en
|
| 47 |
+
```
|
| 48 |
+
|
| 49 |
+
## `websocket`
|
| 50 |
+
|
| 51 |
+
This flag enables debug statements for the `Websocket` API.
|
| 52 |
+
|
| 53 |
+
> **Note**: statements can overlap with `UNDICI` ones if `undici` or `fetch` flag has been enabled as well.
|
| 54 |
+
|
| 55 |
+
```sh
|
| 56 |
+
NODE_DEBUG=websocket node script.js
|
| 57 |
+
|
| 58 |
+
WEBSOCKET 18309: connecting to echo.websocket.org using https:h1
|
| 59 |
+
WEBSOCKET 18309: connected to echo.websocket.org using https:h1
|
| 60 |
+
WEBSOCKET 18309: sending request to GET https://echo.websocket.org/
|
| 61 |
+
WEBSOCKET 18309: connection opened <ip_address>
|
| 62 |
+
```
|
bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/DiagnosticsChannel.md
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Diagnostics Channel Support
|
| 2 |
+
|
| 3 |
+
Stability: Experimental.
|
| 4 |
+
|
| 5 |
+
Undici supports the [`diagnostics_channel`](https://nodejs.org/api/diagnostics_channel.html) (currently available only on Node.js v16+).
|
| 6 |
+
It is the preferred way to instrument Undici and retrieve internal information.
|
| 7 |
+
|
| 8 |
+
The channels available are the following.
|
| 9 |
+
|
| 10 |
+
## `undici:request:create`
|
| 11 |
+
|
| 12 |
+
This message is published when a new outgoing request is created.
|
| 13 |
+
|
| 14 |
+
```js
|
| 15 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 16 |
+
|
| 17 |
+
diagnosticsChannel.channel('undici:request:create').subscribe(({ request }) => {
|
| 18 |
+
console.log('origin', request.origin)
|
| 19 |
+
console.log('completed', request.completed)
|
| 20 |
+
console.log('method', request.method)
|
| 21 |
+
console.log('path', request.path)
|
| 22 |
+
console.log('headers', request.headers) // array of strings, e.g: ['foo', 'bar']
|
| 23 |
+
request.addHeader('hello', 'world')
|
| 24 |
+
console.log('headers', request.headers) // e.g. ['foo', 'bar', 'hello', 'world']
|
| 25 |
+
})
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
Note: a request is only loosely completed to a given socket.
|
| 29 |
+
|
| 30 |
+
## `undici:request:bodyChunkSent`
|
| 31 |
+
|
| 32 |
+
This message is published when a chunk of the request body is being sent.
|
| 33 |
+
|
| 34 |
+
```js
|
| 35 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 36 |
+
|
| 37 |
+
diagnosticsChannel.channel('undici:request:bodyChunkSent').subscribe(({ request, chunk }) => {
|
| 38 |
+
// request is the same object undici:request:create
|
| 39 |
+
})
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
## `undici:request:bodySent`
|
| 43 |
+
|
| 44 |
+
This message is published after the request body has been fully sent.
|
| 45 |
+
|
| 46 |
+
```js
|
| 47 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 48 |
+
|
| 49 |
+
diagnosticsChannel.channel('undici:request:bodySent').subscribe(({ request }) => {
|
| 50 |
+
// request is the same object undici:request:create
|
| 51 |
+
})
|
| 52 |
+
```
|
| 53 |
+
|
| 54 |
+
## `undici:request:headers`
|
| 55 |
+
|
| 56 |
+
This message is published after the response headers have been received.
|
| 57 |
+
|
| 58 |
+
```js
|
| 59 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 60 |
+
|
| 61 |
+
diagnosticsChannel.channel('undici:request:headers').subscribe(({ request, response }) => {
|
| 62 |
+
// request is the same object undici:request:create
|
| 63 |
+
console.log('statusCode', response.statusCode)
|
| 64 |
+
console.log(response.statusText)
|
| 65 |
+
// response.headers are buffers.
|
| 66 |
+
console.log(response.headers.map((x) => x.toString()))
|
| 67 |
+
})
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
## `undici:request:bodyChunkReceived`
|
| 71 |
+
|
| 72 |
+
This message is published after a chunk of the response body has been received.
|
| 73 |
+
|
| 74 |
+
```js
|
| 75 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 76 |
+
|
| 77 |
+
diagnosticsChannel.channel('undici:request:bodyChunkReceived').subscribe(({ request, chunk }) => {
|
| 78 |
+
// request is the same object undici:request:create
|
| 79 |
+
})
|
| 80 |
+
```
|
| 81 |
+
|
| 82 |
+
## `undici:request:trailers`
|
| 83 |
+
|
| 84 |
+
This message is published after the response body and trailers have been received, i.e. the response has been completed.
|
| 85 |
+
|
| 86 |
+
```js
|
| 87 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 88 |
+
|
| 89 |
+
diagnosticsChannel.channel('undici:request:trailers').subscribe(({ request, trailers }) => {
|
| 90 |
+
// request is the same object undici:request:create
|
| 91 |
+
console.log('completed', request.completed)
|
| 92 |
+
// trailers are buffers.
|
| 93 |
+
console.log(trailers.map((x) => x.toString()))
|
| 94 |
+
})
|
| 95 |
+
```
|
| 96 |
+
|
| 97 |
+
## `undici:request:error`
|
| 98 |
+
|
| 99 |
+
This message is published if the request is going to error, but it has not errored yet.
|
| 100 |
+
|
| 101 |
+
```js
|
| 102 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 103 |
+
|
| 104 |
+
diagnosticsChannel.channel('undici:request:error').subscribe(({ request, error }) => {
|
| 105 |
+
// request is the same object undici:request:create
|
| 106 |
+
})
|
| 107 |
+
```
|
| 108 |
+
|
| 109 |
+
## `undici:client:sendHeaders`
|
| 110 |
+
|
| 111 |
+
This message is published right before the first byte of the request is written to the socket.
|
| 112 |
+
|
| 113 |
+
*Note*: It will publish the exact headers that will be sent to the server in raw format.
|
| 114 |
+
|
| 115 |
+
```js
|
| 116 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 117 |
+
|
| 118 |
+
diagnosticsChannel.channel('undici:client:sendHeaders').subscribe(({ request, headers, socket }) => {
|
| 119 |
+
// request is the same object undici:request:create
|
| 120 |
+
console.log(`Full headers list ${headers.split('\r\n')}`);
|
| 121 |
+
})
|
| 122 |
+
```
|
| 123 |
+
|
| 124 |
+
## `undici:client:beforeConnect`
|
| 125 |
+
|
| 126 |
+
This message is published before creating a new connection for **any** request.
|
| 127 |
+
You can not assume that this event is related to any specific request.
|
| 128 |
+
|
| 129 |
+
```js
|
| 130 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 131 |
+
|
| 132 |
+
diagnosticsChannel.channel('undici:client:beforeConnect').subscribe(({ connectParams, connector }) => {
|
| 133 |
+
// const { host, hostname, protocol, port, servername, version } = connectParams
|
| 134 |
+
// connector is a function that creates the socket
|
| 135 |
+
})
|
| 136 |
+
```
|
| 137 |
+
|
| 138 |
+
## `undici:client:connected`
|
| 139 |
+
|
| 140 |
+
This message is published after a connection is established.
|
| 141 |
+
|
| 142 |
+
```js
|
| 143 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 144 |
+
|
| 145 |
+
diagnosticsChannel.channel('undici:client:connected').subscribe(({ socket, connectParams, connector }) => {
|
| 146 |
+
// const { host, hostname, protocol, port, servername, version } = connectParams
|
| 147 |
+
// connector is a function that creates the socket
|
| 148 |
+
})
|
| 149 |
+
```
|
| 150 |
+
|
| 151 |
+
## `undici:client:connectError`
|
| 152 |
+
|
| 153 |
+
This message is published if it did not succeed to create new connection
|
| 154 |
+
|
| 155 |
+
```js
|
| 156 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 157 |
+
|
| 158 |
+
diagnosticsChannel.channel('undici:client:connectError').subscribe(({ error, socket, connectParams, connector }) => {
|
| 159 |
+
// const { host, hostname, protocol, port, servername, version } = connectParams
|
| 160 |
+
// connector is a function that creates the socket
|
| 161 |
+
console.log(`Connect failed with ${error.message}`)
|
| 162 |
+
})
|
| 163 |
+
```
|
| 164 |
+
|
| 165 |
+
## `undici:websocket:open`
|
| 166 |
+
|
| 167 |
+
This message is published after the client has successfully connected to a server.
|
| 168 |
+
|
| 169 |
+
```js
|
| 170 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 171 |
+
|
| 172 |
+
diagnosticsChannel.channel('undici:websocket:open').subscribe(({
|
| 173 |
+
address, // { address: string, family: string, port: number }
|
| 174 |
+
protocol, // string - negotiated subprotocol
|
| 175 |
+
extensions, // string - negotiated extensions
|
| 176 |
+
websocket, // WebSocket - the WebSocket instance
|
| 177 |
+
handshakeResponse // object - HTTP response that upgraded the connection
|
| 178 |
+
}) => {
|
| 179 |
+
console.log(address) // address, family, and port
|
| 180 |
+
console.log(protocol) // negotiated subprotocols
|
| 181 |
+
console.log(extensions) // negotiated extensions
|
| 182 |
+
console.log(websocket) // the WebSocket instance
|
| 183 |
+
|
| 184 |
+
// Handshake response details
|
| 185 |
+
console.log(handshakeResponse.status) // 101 for HTTP/1.1, 200 for HTTP/2 extended CONNECT
|
| 186 |
+
console.log(handshakeResponse.statusText) // 'Switching Protocols' for HTTP/1.1, commonly 'OK' for HTTP/2 in Node.js
|
| 187 |
+
console.log(handshakeResponse.headers) // Object containing response headers
|
| 188 |
+
})
|
| 189 |
+
```
|
| 190 |
+
|
| 191 |
+
### Handshake Response Object
|
| 192 |
+
|
| 193 |
+
The `handshakeResponse` object contains the HTTP response that established the WebSocket connection:
|
| 194 |
+
|
| 195 |
+
- `status` (number): The HTTP status code (`101` for HTTP/1.1 upgrade, `200` for HTTP/2 extended CONNECT)
|
| 196 |
+
- `statusText` (string): The HTTP status message (`'Switching Protocols'` for HTTP/1.1, commonly `'OK'` for HTTP/2 in Node.js)
|
| 197 |
+
- `headers` (object): The HTTP response headers from the server, including:
|
| 198 |
+
- `sec-websocket-accept` and other WebSocket-related headers
|
| 199 |
+
- `upgrade: 'websocket'`
|
| 200 |
+
- `connection: 'upgrade'`
|
| 201 |
+
|
| 202 |
+
The `upgrade` and `connection` headers are only present for HTTP/1.1 handshakes.
|
| 203 |
+
|
| 204 |
+
This information is particularly useful for debugging and monitoring WebSocket connections, as it provides access to the initial HTTP handshake response that established the WebSocket connection.
|
| 205 |
+
|
| 206 |
+
## `undici:websocket:close`
|
| 207 |
+
|
| 208 |
+
This message is published after the connection has closed.
|
| 209 |
+
|
| 210 |
+
```js
|
| 211 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 212 |
+
|
| 213 |
+
diagnosticsChannel.channel('undici:websocket:close').subscribe(({ websocket, code, reason }) => {
|
| 214 |
+
console.log(websocket) // the WebSocket instance
|
| 215 |
+
console.log(code) // the closing status code
|
| 216 |
+
console.log(reason) // the closing reason
|
| 217 |
+
})
|
| 218 |
+
```
|
| 219 |
+
|
| 220 |
+
## `undici:websocket:socket_error`
|
| 221 |
+
|
| 222 |
+
This message is published if the socket experiences an error.
|
| 223 |
+
|
| 224 |
+
```js
|
| 225 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 226 |
+
|
| 227 |
+
diagnosticsChannel.channel('undici:websocket:socket_error').subscribe((error) => {
|
| 228 |
+
console.log(error)
|
| 229 |
+
})
|
| 230 |
+
```
|
| 231 |
+
|
| 232 |
+
## `undici:websocket:ping`
|
| 233 |
+
|
| 234 |
+
This message is published after the client receives a ping frame, if the connection is not closing.
|
| 235 |
+
|
| 236 |
+
```js
|
| 237 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 238 |
+
|
| 239 |
+
diagnosticsChannel.channel('undici:websocket:ping').subscribe(({ payload, websocket }) => {
|
| 240 |
+
// a Buffer or undefined, containing the optional application data of the frame
|
| 241 |
+
console.log(payload)
|
| 242 |
+
console.log(websocket) // the WebSocket instance
|
| 243 |
+
})
|
| 244 |
+
```
|
| 245 |
+
|
| 246 |
+
## `undici:websocket:pong`
|
| 247 |
+
|
| 248 |
+
This message is published after the client receives a pong frame.
|
| 249 |
+
|
| 250 |
+
```js
|
| 251 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 252 |
+
|
| 253 |
+
diagnosticsChannel.channel('undici:websocket:pong').subscribe(({ payload, websocket }) => {
|
| 254 |
+
// a Buffer or undefined, containing the optional application data of the frame
|
| 255 |
+
console.log(payload)
|
| 256 |
+
console.log(websocket) // the WebSocket instance
|
| 257 |
+
})
|
| 258 |
+
```
|
| 259 |
+
|
| 260 |
+
## `undici:proxy:connected`
|
| 261 |
+
|
| 262 |
+
This message is published after the `ProxyAgent` establishes a connection to the proxy server.
|
| 263 |
+
|
| 264 |
+
```js
|
| 265 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 266 |
+
|
| 267 |
+
diagnosticsChannel.channel('undici:proxy:connected').subscribe(({ socket, connectParams }) => {
|
| 268 |
+
console.log(socket)
|
| 269 |
+
console.log(connectParams)
|
| 270 |
+
// const { origin, port, path, signal, headers, servername } = connectParams
|
| 271 |
+
})
|
| 272 |
+
```
|
| 273 |
+
|
| 274 |
+
## `undici:request:pending-requests`
|
| 275 |
+
|
| 276 |
+
This message is published when the deduplicate interceptor's pending request map changes. This is useful for monitoring and debugging request deduplication behavior.
|
| 277 |
+
|
| 278 |
+
The deduplicate interceptor automatically deduplicates concurrent requests for the same resource. When multiple identical requests are made while one is already in-flight, only one request is sent to the origin server, and all waiting handlers receive the same response.
|
| 279 |
+
|
| 280 |
+
```js
|
| 281 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 282 |
+
|
| 283 |
+
diagnosticsChannel.channel('undici:request:pending-requests').subscribe(({ type, size, key }) => {
|
| 284 |
+
console.log(type) // 'added' or 'removed'
|
| 285 |
+
console.log(size) // current number of pending requests
|
| 286 |
+
console.log(key) // the deduplication key for this request
|
| 287 |
+
})
|
| 288 |
+
```
|
| 289 |
+
|
| 290 |
+
### Event Properties
|
| 291 |
+
|
| 292 |
+
- `type` (`string`): Either `'added'` when a new pending request is registered, or `'removed'` when a pending request completes (successfully or with an error).
|
| 293 |
+
- `size` (`number`): The current number of pending requests after the change.
|
| 294 |
+
- `key` (`string`): The deduplication key for the request, composed of the origin, method, path, and request headers.
|
| 295 |
+
|
| 296 |
+
### Example: Monitoring Request Deduplication
|
| 297 |
+
|
| 298 |
+
```js
|
| 299 |
+
import diagnosticsChannel from 'diagnostics_channel'
|
| 300 |
+
|
| 301 |
+
const channel = diagnosticsChannel.channel('undici:request:pending-requests')
|
| 302 |
+
|
| 303 |
+
channel.subscribe(({ type, size, key }) => {
|
| 304 |
+
if (type === 'added') {
|
| 305 |
+
console.log(`New pending request: ${key} (${size} total pending)`)
|
| 306 |
+
} else {
|
| 307 |
+
console.log(`Request completed: ${key} (${size} remaining)`)
|
| 308 |
+
}
|
| 309 |
+
})
|
| 310 |
+
```
|
| 311 |
+
|
| 312 |
+
This can be useful for:
|
| 313 |
+
- Verifying that request deduplication is working as expected
|
| 314 |
+
- Monitoring the number of concurrent in-flight requests
|
| 315 |
+
- Debugging deduplication behavior in production environments
|
bunx-1000-wrangler@latest/node_modules/undici/docs/docs/api/Dispatcher.md
ADDED
|
@@ -0,0 +1,1392 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Dispatcher
|
| 2 |
+
|
| 3 |
+
Extends: `events.EventEmitter`
|
| 4 |
+
|
| 5 |
+
Dispatcher is the core API used to dispatch requests.
|
| 6 |
+
|
| 7 |
+
Requests are not guaranteed to be dispatched in order of invocation.
|
| 8 |
+
|
| 9 |
+
## Instance Methods
|
| 10 |
+
|
| 11 |
+
### `Dispatcher.close([callback]): Promise`
|
| 12 |
+
|
| 13 |
+
Closes the dispatcher and gracefully waits for enqueued requests to complete before resolving.
|
| 14 |
+
|
| 15 |
+
Arguments:
|
| 16 |
+
|
| 17 |
+
* **callback** `(error: Error | null, data: null) => void` (optional)
|
| 18 |
+
|
| 19 |
+
Returns: `void | Promise<null>` - Only returns a `Promise` if no `callback` argument was passed
|
| 20 |
+
|
| 21 |
+
```js
|
| 22 |
+
dispatcher.close() // -> Promise
|
| 23 |
+
dispatcher.close(() => {}) // -> void
|
| 24 |
+
```
|
| 25 |
+
|
| 26 |
+
#### Example - Request resolves before Client closes
|
| 27 |
+
|
| 28 |
+
```js
|
| 29 |
+
import { createServer } from 'http'
|
| 30 |
+
import { Client } from 'undici'
|
| 31 |
+
import { once } from 'events'
|
| 32 |
+
|
| 33 |
+
const server = createServer((request, response) => {
|
| 34 |
+
response.end('undici')
|
| 35 |
+
}).listen()
|
| 36 |
+
|
| 37 |
+
await once(server, 'listening')
|
| 38 |
+
|
| 39 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 40 |
+
|
| 41 |
+
try {
|
| 42 |
+
const { body } = await client.request({
|
| 43 |
+
path: '/',
|
| 44 |
+
method: 'GET'
|
| 45 |
+
})
|
| 46 |
+
body.setEncoding('utf8')
|
| 47 |
+
body.on('data', console.log)
|
| 48 |
+
} catch (error) {}
|
| 49 |
+
|
| 50 |
+
await client.close()
|
| 51 |
+
|
| 52 |
+
console.log('Client closed')
|
| 53 |
+
server.close()
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
### `Dispatcher.connect(options[, callback])`
|
| 57 |
+
|
| 58 |
+
Starts two-way communications with the requested resource using [HTTP CONNECT](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/CONNECT).
|
| 59 |
+
|
| 60 |
+
Arguments:
|
| 61 |
+
|
| 62 |
+
* **options** `ConnectOptions`
|
| 63 |
+
* **callback** `(err: Error | null, data: ConnectData | null) => void` (optional)
|
| 64 |
+
|
| 65 |
+
Returns: `void | Promise<ConnectData>` - Only returns a `Promise` if no `callback` argument was passed
|
| 66 |
+
|
| 67 |
+
#### Parameter: `ConnectOptions`
|
| 68 |
+
|
| 69 |
+
* **path** `string`
|
| 70 |
+
* **headers** `UndiciHeaders` (optional) - Default: `null`
|
| 71 |
+
* **signal** `AbortSignal | events.EventEmitter | null` (optional) - Default: `null`
|
| 72 |
+
* **opaque** `unknown` (optional) - This argument parameter is passed through to `ConnectData`
|
| 73 |
+
|
| 74 |
+
#### Parameter: `ConnectData`
|
| 75 |
+
|
| 76 |
+
* **statusCode** `number`
|
| 77 |
+
* **headers** `Record<string, string | string[] | undefined>`
|
| 78 |
+
* **socket** `stream.Duplex`
|
| 79 |
+
* **opaque** `unknown`
|
| 80 |
+
|
| 81 |
+
#### Example - Connect request with echo
|
| 82 |
+
|
| 83 |
+
```js
|
| 84 |
+
import { createServer } from 'http'
|
| 85 |
+
import { Client } from 'undici'
|
| 86 |
+
import { once } from 'events'
|
| 87 |
+
|
| 88 |
+
const server = createServer((request, response) => {
|
| 89 |
+
throw Error('should never get here')
|
| 90 |
+
}).listen()
|
| 91 |
+
|
| 92 |
+
server.on('connect', (req, socket, head) => {
|
| 93 |
+
socket.write('HTTP/1.1 200 Connection established\r\n\r\n')
|
| 94 |
+
|
| 95 |
+
let data = head.toString()
|
| 96 |
+
socket.on('data', (buf) => {
|
| 97 |
+
data += buf.toString()
|
| 98 |
+
})
|
| 99 |
+
|
| 100 |
+
socket.on('end', () => {
|
| 101 |
+
socket.end(data)
|
| 102 |
+
})
|
| 103 |
+
})
|
| 104 |
+
|
| 105 |
+
await once(server, 'listening')
|
| 106 |
+
|
| 107 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 108 |
+
|
| 109 |
+
try {
|
| 110 |
+
const { socket } = await client.connect({
|
| 111 |
+
path: '/'
|
| 112 |
+
})
|
| 113 |
+
const wanted = 'Body'
|
| 114 |
+
let data = ''
|
| 115 |
+
socket.on('data', d => { data += d })
|
| 116 |
+
socket.on('end', () => {
|
| 117 |
+
console.log(`Data received: ${data.toString()} | Data wanted: ${wanted}`)
|
| 118 |
+
client.close()
|
| 119 |
+
server.close()
|
| 120 |
+
})
|
| 121 |
+
socket.write(wanted)
|
| 122 |
+
socket.end()
|
| 123 |
+
} catch (error) { }
|
| 124 |
+
```
|
| 125 |
+
|
| 126 |
+
### `Dispatcher.destroy([error, callback]): Promise`
|
| 127 |
+
|
| 128 |
+
Destroy the dispatcher abruptly with the given error. All the pending and running requests will be asynchronously aborted and error. Since this operation is asynchronously dispatched there might still be some progress on dispatched requests.
|
| 129 |
+
|
| 130 |
+
Both arguments are optional; the method can be called in four different ways:
|
| 131 |
+
|
| 132 |
+
Arguments:
|
| 133 |
+
|
| 134 |
+
* **error** `Error | null` (optional)
|
| 135 |
+
* **callback** `(error: Error | null, data: null) => void` (optional)
|
| 136 |
+
|
| 137 |
+
Returns: `void | Promise<void>` - Only returns a `Promise` if no `callback` argument was passed
|
| 138 |
+
|
| 139 |
+
```js
|
| 140 |
+
dispatcher.destroy() // -> Promise
|
| 141 |
+
dispatcher.destroy(new Error()) // -> Promise
|
| 142 |
+
dispatcher.destroy(() => {}) // -> void
|
| 143 |
+
dispatcher.destroy(new Error(), () => {}) // -> void
|
| 144 |
+
```
|
| 145 |
+
|
| 146 |
+
#### Example - Request is aborted when Client is destroyed
|
| 147 |
+
|
| 148 |
+
```js
|
| 149 |
+
import { createServer } from 'http'
|
| 150 |
+
import { Client } from 'undici'
|
| 151 |
+
import { once } from 'events'
|
| 152 |
+
|
| 153 |
+
const server = createServer((request, response) => {
|
| 154 |
+
response.end()
|
| 155 |
+
}).listen()
|
| 156 |
+
|
| 157 |
+
await once(server, 'listening')
|
| 158 |
+
|
| 159 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 160 |
+
|
| 161 |
+
try {
|
| 162 |
+
const request = client.request({
|
| 163 |
+
path: '/',
|
| 164 |
+
method: 'GET'
|
| 165 |
+
})
|
| 166 |
+
client.destroy()
|
| 167 |
+
.then(() => {
|
| 168 |
+
console.log('Client destroyed')
|
| 169 |
+
server.close()
|
| 170 |
+
})
|
| 171 |
+
await request
|
| 172 |
+
} catch (error) {
|
| 173 |
+
console.error(error)
|
| 174 |
+
}
|
| 175 |
+
```
|
| 176 |
+
|
| 177 |
+
### `Dispatcher.dispatch(options, handler)`
|
| 178 |
+
|
| 179 |
+
This is the low level API which all the preceding APIs are implemented on top of.
|
| 180 |
+
This API is expected to evolve through semver-major versions and is less stable than the preceding higher level APIs.
|
| 181 |
+
It is primarily intended for library developers who implement higher level APIs on top of this.
|
| 182 |
+
|
| 183 |
+
Arguments:
|
| 184 |
+
|
| 185 |
+
* **options** `DispatchOptions`
|
| 186 |
+
* **handler** `DispatchHandler`
|
| 187 |
+
|
| 188 |
+
Returns: `Boolean` - `false` if dispatcher is busy and further dispatch calls won't make any progress until the `'drain'` event has been emitted.
|
| 189 |
+
|
| 190 |
+
#### Parameter: `DispatchOptions`
|
| 191 |
+
|
| 192 |
+
* **origin** `string | URL`
|
| 193 |
+
* **path** `string`
|
| 194 |
+
* **method** `string`
|
| 195 |
+
* **reset** `boolean` (optional) - Default: `false` - If `false`, the request will attempt to create a long-living connection by sending the `connection: keep-alive` header,otherwise will attempt to close it immediately after response by sending `connection: close` within the request and closing the socket afterwards.
|
| 196 |
+
* **body** `string | Buffer | Uint8Array | stream.Readable | Iterable | AsyncIterable | null` (optional) - Default: `null`
|
| 197 |
+
* **headers** `UndiciHeaders` (optional) - Default: `null`.
|
| 198 |
+
* **query** `Record<string, any> | null` (optional) - Default: `null` - Query string params to be embedded in the request URL. Note that both keys and values of query are encoded using `encodeURIComponent`. If for some reason you need to send them unencoded, embed query params into path directly instead.
|
| 199 |
+
* **idempotent** `boolean` (optional) - Default: `true` if `method` is `'HEAD'` or `'GET'` - Whether the requests can be safely retried or not. If `false` the request won't be sent until all preceding requests in the pipeline has completed.
|
| 200 |
+
* **blocking** `boolean` (optional) - Default: `method !== 'HEAD'` - Whether the response is expected to take a long time and would end up blocking the pipeline. When this is set to `true` further pipelining will be avoided on the same connection until headers have been received.
|
| 201 |
+
* **upgrade** `string | null` (optional) - Default: `null` - Upgrade the request. Should be used to specify the kind of upgrade i.e. `'Websocket'`.
|
| 202 |
+
* **bodyTimeout** `number | null` (optional) - The timeout after which a request will time out, in milliseconds. Monitors time between receiving body data. Use `0` to disable it entirely. Defaults to 300 seconds.
|
| 203 |
+
* **headersTimeout** `number | null` (optional) - The amount of time, in milliseconds, the parser will wait to receive the complete HTTP headers while not sending the request. Defaults to 300 seconds.
|
| 204 |
+
* **expectContinue** `boolean` (optional) - Default: `false` - For H2, it appends the expect: 100-continue header, and halts the request body until a 100-continue is received from the remote server
|
| 205 |
+
|
| 206 |
+
#### Parameter: `DispatchHandler`
|
| 207 |
+
|
| 208 |
+
* **onRequestStart** `(controller: DispatchController, context: object) => void` - Invoked before request is dispatched on socket. May be invoked multiple times when a request is retried when the request at the head of the pipeline fails.
|
| 209 |
+
* **onRequestUpgrade** `(controller: DispatchController, statusCode: number, headers: Record<string, string | string[]>, socket: Duplex) => void` (optional) - Invoked when request is upgraded. Required if `DispatchOptions.upgrade` is defined or `DispatchOptions.method === 'CONNECT'`.
|
| 210 |
+
* **onResponseStart** `(controller: DispatchController, statusCode: number, headers: Record<string, string | string []>, statusMessage?: string) => void` - Invoked when statusCode and headers have been received. May be invoked multiple times due to 1xx informational headers. Not required for `upgrade` requests. Any return value is ignored.
|
| 211 |
+
* **onResponseData** `(controller: DispatchController, chunk: Buffer) => void` - Invoked when response payload data is received. Not required for `upgrade` requests.
|
| 212 |
+
* **onResponseEnd** `(controller: DispatchController, trailers: Record<string, string | string[]>) => void` - Invoked when response payload and trailers have been received and the request has completed. Not required for `upgrade` requests.
|
| 213 |
+
* **onResponseError** `(controller: DispatchController, error: Error) => void` - Invoked when an error has occurred. May not throw.
|
| 214 |
+
|
| 215 |
+
#### Example 1 - Dispatch GET request
|
| 216 |
+
|
| 217 |
+
```js
|
| 218 |
+
import { createServer } from 'http'
|
| 219 |
+
import { Client } from 'undici'
|
| 220 |
+
import { once } from 'events'
|
| 221 |
+
|
| 222 |
+
const server = createServer((request, response) => {
|
| 223 |
+
response.end('Hello, World!')
|
| 224 |
+
}).listen()
|
| 225 |
+
|
| 226 |
+
await once(server, 'listening')
|
| 227 |
+
|
| 228 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 229 |
+
|
| 230 |
+
const data = []
|
| 231 |
+
|
| 232 |
+
client.dispatch({
|
| 233 |
+
path: '/',
|
| 234 |
+
method: 'GET',
|
| 235 |
+
headers: {
|
| 236 |
+
'x-foo': 'bar'
|
| 237 |
+
}
|
| 238 |
+
}, {
|
| 239 |
+
onConnect: () => {
|
| 240 |
+
console.log('Connected!')
|
| 241 |
+
},
|
| 242 |
+
onError: (error) => {
|
| 243 |
+
console.error(error)
|
| 244 |
+
},
|
| 245 |
+
onHeaders: (statusCode, headers) => {
|
| 246 |
+
console.log(`onHeaders | statusCode: ${statusCode} | headers: ${headers}`)
|
| 247 |
+
},
|
| 248 |
+
onData: (chunk) => {
|
| 249 |
+
console.log('onData: chunk received')
|
| 250 |
+
data.push(chunk)
|
| 251 |
+
},
|
| 252 |
+
onComplete: (trailers) => {
|
| 253 |
+
console.log(`onComplete | trailers: ${trailers}`)
|
| 254 |
+
const res = Buffer.concat(data).toString('utf8')
|
| 255 |
+
console.log(`Data: ${res}`)
|
| 256 |
+
client.close()
|
| 257 |
+
server.close()
|
| 258 |
+
}
|
| 259 |
+
})
|
| 260 |
+
```
|
| 261 |
+
|
| 262 |
+
#### Example 2 - Dispatch Upgrade Request
|
| 263 |
+
|
| 264 |
+
```js
|
| 265 |
+
import { createServer } from 'http'
|
| 266 |
+
import { Client } from 'undici'
|
| 267 |
+
import { once } from 'events'
|
| 268 |
+
|
| 269 |
+
const server = createServer((request, response) => {
|
| 270 |
+
response.end()
|
| 271 |
+
}).listen()
|
| 272 |
+
|
| 273 |
+
await once(server, 'listening')
|
| 274 |
+
|
| 275 |
+
server.on('upgrade', (request, socket, head) => {
|
| 276 |
+
console.log('Node.js Server - upgrade event')
|
| 277 |
+
socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n')
|
| 278 |
+
socket.write('Upgrade: WebSocket\r\n')
|
| 279 |
+
socket.write('Connection: Upgrade\r\n')
|
| 280 |
+
socket.write('\r\n')
|
| 281 |
+
socket.end()
|
| 282 |
+
})
|
| 283 |
+
|
| 284 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 285 |
+
|
| 286 |
+
client.dispatch({
|
| 287 |
+
path: '/',
|
| 288 |
+
method: 'GET',
|
| 289 |
+
upgrade: 'websocket'
|
| 290 |
+
}, {
|
| 291 |
+
onConnect: () => {
|
| 292 |
+
console.log('Undici Client - onConnect')
|
| 293 |
+
},
|
| 294 |
+
onError: (error) => {
|
| 295 |
+
console.log('onError') // shouldn't print
|
| 296 |
+
},
|
| 297 |
+
onUpgrade: (statusCode, headers, socket) => {
|
| 298 |
+
console.log('Undici Client - onUpgrade')
|
| 299 |
+
console.log(`onUpgrade Headers: ${headers}`)
|
| 300 |
+
socket.on('data', buffer => {
|
| 301 |
+
console.log(buffer.toString('utf8'))
|
| 302 |
+
})
|
| 303 |
+
socket.on('end', () => {
|
| 304 |
+
client.close()
|
| 305 |
+
server.close()
|
| 306 |
+
})
|
| 307 |
+
socket.end()
|
| 308 |
+
}
|
| 309 |
+
})
|
| 310 |
+
```
|
| 311 |
+
|
| 312 |
+
#### Example 3 - Dispatch POST request
|
| 313 |
+
|
| 314 |
+
```js
|
| 315 |
+
import { createServer } from 'http'
|
| 316 |
+
import { Client } from 'undici'
|
| 317 |
+
import { once } from 'events'
|
| 318 |
+
|
| 319 |
+
const server = createServer((request, response) => {
|
| 320 |
+
request.on('data', (data) => {
|
| 321 |
+
console.log(`Request Data: ${data.toString('utf8')}`)
|
| 322 |
+
const body = JSON.parse(data)
|
| 323 |
+
body.message = 'World'
|
| 324 |
+
response.end(JSON.stringify(body))
|
| 325 |
+
})
|
| 326 |
+
}).listen()
|
| 327 |
+
|
| 328 |
+
await once(server, 'listening')
|
| 329 |
+
|
| 330 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 331 |
+
|
| 332 |
+
const data = []
|
| 333 |
+
|
| 334 |
+
client.dispatch({
|
| 335 |
+
path: '/',
|
| 336 |
+
method: 'POST',
|
| 337 |
+
headers: {
|
| 338 |
+
'content-type': 'application/json'
|
| 339 |
+
},
|
| 340 |
+
body: JSON.stringify({ message: 'Hello' })
|
| 341 |
+
}, {
|
| 342 |
+
onConnect: () => {
|
| 343 |
+
console.log('Connected!')
|
| 344 |
+
},
|
| 345 |
+
onError: (error) => {
|
| 346 |
+
console.error(error)
|
| 347 |
+
},
|
| 348 |
+
onHeaders: (statusCode, headers) => {
|
| 349 |
+
console.log(`onHeaders | statusCode: ${statusCode} | headers: ${headers}`)
|
| 350 |
+
},
|
| 351 |
+
onData: (chunk) => {
|
| 352 |
+
console.log('onData: chunk received')
|
| 353 |
+
data.push(chunk)
|
| 354 |
+
},
|
| 355 |
+
onComplete: (trailers) => {
|
| 356 |
+
console.log(`onComplete | trailers: ${trailers}`)
|
| 357 |
+
const res = Buffer.concat(data).toString('utf8')
|
| 358 |
+
console.log(`Response Data: ${res}`)
|
| 359 |
+
client.close()
|
| 360 |
+
server.close()
|
| 361 |
+
}
|
| 362 |
+
})
|
| 363 |
+
```
|
| 364 |
+
|
| 365 |
+
### `Dispatcher.pipeline(options, handler)`
|
| 366 |
+
|
| 367 |
+
For easy use with [stream.pipeline](https://nodejs.org/api/stream.html#streampipelinesource-transforms-destination-options). The `handler` argument should return a `Readable` from which the result will be read. Usually it should just return the `body` argument unless some kind of transformation needs to be performed based on e.g. `headers` or `statusCode`. The `handler` should validate the response and save any required state. If there is an error, it should be thrown. The function returns a `Duplex` which writes to the request and reads from the response.
|
| 368 |
+
|
| 369 |
+
Arguments:
|
| 370 |
+
|
| 371 |
+
* **options** `PipelineOptions`
|
| 372 |
+
* **handler** `(data: PipelineHandlerData) => stream.Readable`
|
| 373 |
+
|
| 374 |
+
Returns: `stream.Duplex`
|
| 375 |
+
|
| 376 |
+
#### Parameter: PipelineOptions
|
| 377 |
+
|
| 378 |
+
Extends: [`RequestOptions`](/docs/docs/api/Dispatcher.md#parameter-requestoptions)
|
| 379 |
+
|
| 380 |
+
* **objectMode** `boolean` (optional) - Default: `false` - Set to `true` if the `handler` will return an object stream.
|
| 381 |
+
|
| 382 |
+
#### Parameter: PipelineHandlerData
|
| 383 |
+
|
| 384 |
+
* **statusCode** `number`
|
| 385 |
+
* **headers** `Record<string, string | string[] | undefined>`
|
| 386 |
+
* **opaque** `unknown`
|
| 387 |
+
* **body** `stream.Readable`
|
| 388 |
+
* **context** `object`
|
| 389 |
+
* **onInfo** `({statusCode: number, headers: Record<string, string | string[]>}) => void | null` (optional) - Default: `null` - Callback collecting all the info headers (HTTP 100-199) received.
|
| 390 |
+
|
| 391 |
+
#### Example 1 - Pipeline Echo
|
| 392 |
+
|
| 393 |
+
```js
|
| 394 |
+
import { Readable, Writable, PassThrough, pipeline } from 'stream'
|
| 395 |
+
import { createServer } from 'http'
|
| 396 |
+
import { Client } from 'undici'
|
| 397 |
+
import { once } from 'events'
|
| 398 |
+
|
| 399 |
+
const server = createServer((request, response) => {
|
| 400 |
+
request.pipe(response)
|
| 401 |
+
}).listen()
|
| 402 |
+
|
| 403 |
+
await once(server, 'listening')
|
| 404 |
+
|
| 405 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 406 |
+
|
| 407 |
+
let res = ''
|
| 408 |
+
|
| 409 |
+
pipeline(
|
| 410 |
+
new Readable({
|
| 411 |
+
read () {
|
| 412 |
+
this.push(Buffer.from('undici'))
|
| 413 |
+
this.push(null)
|
| 414 |
+
}
|
| 415 |
+
}),
|
| 416 |
+
client.pipeline({
|
| 417 |
+
path: '/',
|
| 418 |
+
method: 'GET'
|
| 419 |
+
}, ({ statusCode, headers, body }) => {
|
| 420 |
+
console.log(`response received ${statusCode}`)
|
| 421 |
+
console.log('headers', headers)
|
| 422 |
+
return pipeline(body, new PassThrough(), () => {})
|
| 423 |
+
}),
|
| 424 |
+
new Writable({
|
| 425 |
+
write (chunk, _, callback) {
|
| 426 |
+
res += chunk.toString()
|
| 427 |
+
callback()
|
| 428 |
+
},
|
| 429 |
+
final (callback) {
|
| 430 |
+
console.log(`Response pipelined to writable: ${res}`)
|
| 431 |
+
callback()
|
| 432 |
+
}
|
| 433 |
+
}),
|
| 434 |
+
error => {
|
| 435 |
+
if (error) {
|
| 436 |
+
console.error(error)
|
| 437 |
+
}
|
| 438 |
+
|
| 439 |
+
client.close()
|
| 440 |
+
server.close()
|
| 441 |
+
}
|
| 442 |
+
)
|
| 443 |
+
```
|
| 444 |
+
|
| 445 |
+
### `Dispatcher.request(options[, callback])`
|
| 446 |
+
|
| 447 |
+
Performs a HTTP request.
|
| 448 |
+
|
| 449 |
+
Non-idempotent requests will not be pipelined in order
|
| 450 |
+
to avoid indirect failures.
|
| 451 |
+
|
| 452 |
+
Idempotent requests will be automatically retried if
|
| 453 |
+
they fail due to indirect failure from the request
|
| 454 |
+
at the head of the pipeline. This does not apply to
|
| 455 |
+
idempotent requests with a stream request body.
|
| 456 |
+
|
| 457 |
+
All response bodies must always be fully consumed or destroyed.
|
| 458 |
+
|
| 459 |
+
Arguments:
|
| 460 |
+
|
| 461 |
+
* **options** `RequestOptions`
|
| 462 |
+
* **callback** `(error: Error | null, data: ResponseData) => void` (optional)
|
| 463 |
+
|
| 464 |
+
Returns: `void | Promise<ResponseData>` - Only returns a `Promise` if no `callback` argument was passed.
|
| 465 |
+
|
| 466 |
+
#### Parameter: `RequestOptions`
|
| 467 |
+
|
| 468 |
+
Extends: [`DispatchOptions`](/docs/docs/api/Dispatcher.md#parameter-dispatchoptions)
|
| 469 |
+
|
| 470 |
+
* **opaque** `unknown` (optional) - Default: `null` - Used for passing through context to `ResponseData`.
|
| 471 |
+
* **signal** `AbortSignal | events.EventEmitter | null` (optional) - Default: `null`.
|
| 472 |
+
* **onInfo** `({statusCode: number, headers: Record<string, string | string[]>}) => void | null` (optional) - Default: `null` - Callback collecting all the info headers (HTTP 100-199) received.
|
| 473 |
+
|
| 474 |
+
The `RequestOptions.method` property should not be value `'CONNECT'`.
|
| 475 |
+
|
| 476 |
+
#### Parameter: `ResponseData`
|
| 477 |
+
|
| 478 |
+
* **statusCode** `number`
|
| 479 |
+
* **statusText** `string` - The status message from the response (e.g., "OK", "Not Found").
|
| 480 |
+
* **headers** `Record<string, string | string[]>` - Note that all header keys are lower-cased, e.g. `content-type`.
|
| 481 |
+
* **body** `stream.Readable` which also implements [the body mixin from the Fetch Standard](https://fetch.spec.whatwg.org/#body-mixin).
|
| 482 |
+
* **trailers** `Record<string, string>` - This object starts out
|
| 483 |
+
as empty and will be mutated to contain trailers after `body` has emitted `'end'`.
|
| 484 |
+
* **opaque** `unknown`
|
| 485 |
+
* **context** `object`
|
| 486 |
+
|
| 487 |
+
`body` contains the following additional [body mixin](https://fetch.spec.whatwg.org/#body-mixin) methods and properties:
|
| 488 |
+
|
| 489 |
+
* [`.arrayBuffer()`](https://fetch.spec.whatwg.org/#dom-body-arraybuffer)
|
| 490 |
+
* [`.blob()`](https://fetch.spec.whatwg.org/#dom-body-blob)
|
| 491 |
+
* [`.bytes()`](https://fetch.spec.whatwg.org/#dom-body-bytes)
|
| 492 |
+
* [`.json()`](https://fetch.spec.whatwg.org/#dom-body-json)
|
| 493 |
+
* [`.text()`](https://fetch.spec.whatwg.org/#dom-body-text)
|
| 494 |
+
* `body`
|
| 495 |
+
* `bodyUsed`
|
| 496 |
+
|
| 497 |
+
`body` can not be consumed twice. For example, calling `text()` after `json()` throws `TypeError`.
|
| 498 |
+
|
| 499 |
+
`body` contains the following additional extensions:
|
| 500 |
+
|
| 501 |
+
- `dump({ limit: Integer })`, dump the response by reading up to `limit` bytes without killing the socket (optional) - Default: 262144.
|
| 502 |
+
|
| 503 |
+
Note that body will still be a `Readable` even if it is empty, but attempting to deserialize it with `json()` will result in an exception. Recommended way to ensure there is a body to deserialize is to check if status code is not 204, and `content-type` header starts with `application/json`.
|
| 504 |
+
|
| 505 |
+
#### Example 1 - Basic GET Request
|
| 506 |
+
|
| 507 |
+
```js
|
| 508 |
+
import { createServer } from 'http'
|
| 509 |
+
import { Client } from 'undici'
|
| 510 |
+
import { once } from 'events'
|
| 511 |
+
|
| 512 |
+
const server = createServer((request, response) => {
|
| 513 |
+
response.end('Hello, World!')
|
| 514 |
+
}).listen()
|
| 515 |
+
|
| 516 |
+
await once(server, 'listening')
|
| 517 |
+
|
| 518 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 519 |
+
|
| 520 |
+
try {
|
| 521 |
+
const { body, headers, statusCode, statusText, trailers } = await client.request({
|
| 522 |
+
path: '/',
|
| 523 |
+
method: 'GET'
|
| 524 |
+
})
|
| 525 |
+
console.log(`response received ${statusCode}`)
|
| 526 |
+
console.log('headers', headers)
|
| 527 |
+
body.setEncoding('utf8')
|
| 528 |
+
body.on('data', console.log)
|
| 529 |
+
body.on('error', console.error)
|
| 530 |
+
body.on('end', () => {
|
| 531 |
+
console.log('trailers', trailers)
|
| 532 |
+
})
|
| 533 |
+
|
| 534 |
+
client.close()
|
| 535 |
+
server.close()
|
| 536 |
+
} catch (error) {
|
| 537 |
+
console.error(error)
|
| 538 |
+
}
|
| 539 |
+
```
|
| 540 |
+
|
| 541 |
+
#### Example 2 - Aborting a request
|
| 542 |
+
|
| 543 |
+
> Node.js v15+ is required to run this example
|
| 544 |
+
|
| 545 |
+
```js
|
| 546 |
+
import { createServer } from 'http'
|
| 547 |
+
import { Client } from 'undici'
|
| 548 |
+
import { once } from 'events'
|
| 549 |
+
|
| 550 |
+
const server = createServer((request, response) => {
|
| 551 |
+
response.end('Hello, World!')
|
| 552 |
+
}).listen()
|
| 553 |
+
|
| 554 |
+
await once(server, 'listening')
|
| 555 |
+
|
| 556 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 557 |
+
const abortController = new AbortController()
|
| 558 |
+
|
| 559 |
+
try {
|
| 560 |
+
client.request({
|
| 561 |
+
path: '/',
|
| 562 |
+
method: 'GET',
|
| 563 |
+
signal: abortController.signal
|
| 564 |
+
})
|
| 565 |
+
} catch (error) {
|
| 566 |
+
console.error(error) // should print an RequestAbortedError
|
| 567 |
+
client.close()
|
| 568 |
+
server.close()
|
| 569 |
+
}
|
| 570 |
+
|
| 571 |
+
abortController.abort()
|
| 572 |
+
```
|
| 573 |
+
|
| 574 |
+
Alternatively, any `EventEmitter` that emits an `'abort'` event may be used as an abort controller:
|
| 575 |
+
|
| 576 |
+
```js
|
| 577 |
+
import { createServer } from 'http'
|
| 578 |
+
import { Client } from 'undici'
|
| 579 |
+
import EventEmitter, { once } from 'events'
|
| 580 |
+
|
| 581 |
+
const server = createServer((request, response) => {
|
| 582 |
+
response.end('Hello, World!')
|
| 583 |
+
}).listen()
|
| 584 |
+
|
| 585 |
+
await once(server, 'listening')
|
| 586 |
+
|
| 587 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 588 |
+
const ee = new EventEmitter()
|
| 589 |
+
|
| 590 |
+
try {
|
| 591 |
+
client.request({
|
| 592 |
+
path: '/',
|
| 593 |
+
method: 'GET',
|
| 594 |
+
signal: ee
|
| 595 |
+
})
|
| 596 |
+
} catch (error) {
|
| 597 |
+
console.error(error) // should print an RequestAbortedError
|
| 598 |
+
client.close()
|
| 599 |
+
server.close()
|
| 600 |
+
}
|
| 601 |
+
|
| 602 |
+
ee.emit('abort')
|
| 603 |
+
```
|
| 604 |
+
|
| 605 |
+
Destroying the request or response body will have the same effect.
|
| 606 |
+
|
| 607 |
+
```js
|
| 608 |
+
import { createServer } from 'http'
|
| 609 |
+
import { Client } from 'undici'
|
| 610 |
+
import { once } from 'events'
|
| 611 |
+
|
| 612 |
+
const server = createServer((request, response) => {
|
| 613 |
+
response.end('Hello, World!')
|
| 614 |
+
}).listen()
|
| 615 |
+
|
| 616 |
+
await once(server, 'listening')
|
| 617 |
+
|
| 618 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 619 |
+
|
| 620 |
+
try {
|
| 621 |
+
const { body } = await client.request({
|
| 622 |
+
path: '/',
|
| 623 |
+
method: 'GET'
|
| 624 |
+
})
|
| 625 |
+
body.destroy()
|
| 626 |
+
} catch (error) {
|
| 627 |
+
console.error(error) // should print an RequestAbortedError
|
| 628 |
+
client.close()
|
| 629 |
+
server.close()
|
| 630 |
+
}
|
| 631 |
+
```
|
| 632 |
+
|
| 633 |
+
#### Example 3 - Conditionally reading the body
|
| 634 |
+
|
| 635 |
+
Remember to fully consume the body even in the case when it is not read.
|
| 636 |
+
|
| 637 |
+
```js
|
| 638 |
+
const { body, statusCode } = await client.request({
|
| 639 |
+
path: '/',
|
| 640 |
+
method: 'GET'
|
| 641 |
+
})
|
| 642 |
+
|
| 643 |
+
if (statusCode === 200) {
|
| 644 |
+
return await body.arrayBuffer()
|
| 645 |
+
}
|
| 646 |
+
|
| 647 |
+
await body.dump()
|
| 648 |
+
|
| 649 |
+
return null
|
| 650 |
+
```
|
| 651 |
+
|
| 652 |
+
### `Dispatcher.stream(options, factory[, callback])`
|
| 653 |
+
|
| 654 |
+
A faster version of `Dispatcher.request`. This method expects the second argument `factory` to return a [`stream.Writable`](https://nodejs.org/api/stream.html#stream_class_stream_writable) stream which the response will be written to. This improves performance by avoiding creating an intermediate [`stream.Readable`](https://nodejs.org/api/stream.html#stream_readable_streams) stream when the user expects to directly pipe the response body to a [`stream.Writable`](https://nodejs.org/api/stream.html#stream_class_stream_writable) stream.
|
| 655 |
+
|
| 656 |
+
As demonstrated in [Example 1 - Basic GET stream request](/docs/docs/api/Dispatcher.md#example-1-basic-get-stream-request), it is recommended to use the `option.opaque` property to avoid creating a closure for the `factory` method. This pattern works well with Node.js Web Frameworks such as [Fastify](https://fastify.io). See [Example 2 - Stream to Fastify Response](/docs/docs/api/Dispatch.md#example-2-stream-to-fastify-response) for more details.
|
| 657 |
+
|
| 658 |
+
Arguments:
|
| 659 |
+
|
| 660 |
+
* **options** `RequestOptions`
|
| 661 |
+
* **factory** `(data: StreamFactoryData) => stream.Writable`
|
| 662 |
+
* **callback** `(error: Error | null, data: StreamData) => void` (optional)
|
| 663 |
+
|
| 664 |
+
Returns: `void | Promise<StreamData>` - Only returns a `Promise` if no `callback` argument was passed
|
| 665 |
+
|
| 666 |
+
#### Parameter: `StreamFactoryData`
|
| 667 |
+
|
| 668 |
+
* **statusCode** `number`
|
| 669 |
+
* **headers** `Record<string, string | string[] | undefined>`
|
| 670 |
+
* **opaque** `unknown`
|
| 671 |
+
* **onInfo** `({statusCode: number, headers: Record<string, string | string[]>}) => void | null` (optional) - Default: `null` - Callback collecting all the info headers (HTTP 100-199) received.
|
| 672 |
+
|
| 673 |
+
#### Parameter: `StreamData`
|
| 674 |
+
|
| 675 |
+
* **opaque** `unknown`
|
| 676 |
+
* **trailers** `Record<string, string>`
|
| 677 |
+
* **context** `object`
|
| 678 |
+
|
| 679 |
+
#### Example 1 - Basic GET stream request
|
| 680 |
+
|
| 681 |
+
```js
|
| 682 |
+
import { createServer } from 'http'
|
| 683 |
+
import { Client } from 'undici'
|
| 684 |
+
import { once } from 'events'
|
| 685 |
+
import { Writable } from 'stream'
|
| 686 |
+
|
| 687 |
+
const server = createServer((request, response) => {
|
| 688 |
+
response.end('Hello, World!')
|
| 689 |
+
}).listen()
|
| 690 |
+
|
| 691 |
+
await once(server, 'listening')
|
| 692 |
+
|
| 693 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 694 |
+
|
| 695 |
+
const bufs = []
|
| 696 |
+
|
| 697 |
+
try {
|
| 698 |
+
await client.stream({
|
| 699 |
+
path: '/',
|
| 700 |
+
method: 'GET',
|
| 701 |
+
opaque: { bufs }
|
| 702 |
+
}, ({ statusCode, headers, opaque: { bufs } }) => {
|
| 703 |
+
console.log(`response received ${statusCode}`)
|
| 704 |
+
console.log('headers', headers)
|
| 705 |
+
return new Writable({
|
| 706 |
+
write (chunk, encoding, callback) {
|
| 707 |
+
bufs.push(chunk)
|
| 708 |
+
callback()
|
| 709 |
+
}
|
| 710 |
+
})
|
| 711 |
+
})
|
| 712 |
+
|
| 713 |
+
console.log(Buffer.concat(bufs).toString('utf-8'))
|
| 714 |
+
|
| 715 |
+
client.close()
|
| 716 |
+
server.close()
|
| 717 |
+
} catch (error) {
|
| 718 |
+
console.error(error)
|
| 719 |
+
}
|
| 720 |
+
```
|
| 721 |
+
|
| 722 |
+
#### Example 2 - Stream to Fastify Response
|
| 723 |
+
|
| 724 |
+
In this example, a (fake) request is made to the fastify server using `fastify.inject()`. This request then executes the fastify route handler which makes a subsequent request to the raw Node.js http server using `undici.dispatcher.stream()`. The fastify response is passed to the `opaque` option so that undici can tap into the underlying writable stream using `response.raw`. This methodology demonstrates how one could use undici and fastify together to create fast-as-possible requests from one backend server to another.
|
| 725 |
+
|
| 726 |
+
```js
|
| 727 |
+
import { createServer } from 'http'
|
| 728 |
+
import { Client } from 'undici'
|
| 729 |
+
import { once } from 'events'
|
| 730 |
+
import fastify from 'fastify'
|
| 731 |
+
|
| 732 |
+
const nodeServer = createServer((request, response) => {
|
| 733 |
+
response.end('Hello, World! From Node.js HTTP Server')
|
| 734 |
+
}).listen()
|
| 735 |
+
|
| 736 |
+
await once(nodeServer, 'listening')
|
| 737 |
+
|
| 738 |
+
console.log('Node Server listening')
|
| 739 |
+
|
| 740 |
+
const nodeServerUndiciClient = new Client(`http://localhost:${nodeServer.address().port}`)
|
| 741 |
+
|
| 742 |
+
const fastifyServer = fastify()
|
| 743 |
+
|
| 744 |
+
fastifyServer.route({
|
| 745 |
+
url: '/',
|
| 746 |
+
method: 'GET',
|
| 747 |
+
handler: (request, response) => {
|
| 748 |
+
nodeServerUndiciClient.stream({
|
| 749 |
+
path: '/',
|
| 750 |
+
method: 'GET',
|
| 751 |
+
opaque: response
|
| 752 |
+
}, ({ opaque }) => opaque.raw)
|
| 753 |
+
}
|
| 754 |
+
})
|
| 755 |
+
|
| 756 |
+
await fastifyServer.listen()
|
| 757 |
+
|
| 758 |
+
console.log('Fastify Server listening')
|
| 759 |
+
|
| 760 |
+
const fastifyServerUndiciClient = new Client(`http://localhost:${fastifyServer.server.address().port}`)
|
| 761 |
+
|
| 762 |
+
try {
|
| 763 |
+
const { statusCode, body } = await fastifyServerUndiciClient.request({
|
| 764 |
+
path: '/',
|
| 765 |
+
method: 'GET'
|
| 766 |
+
})
|
| 767 |
+
|
| 768 |
+
console.log(`response received ${statusCode}`)
|
| 769 |
+
body.setEncoding('utf8')
|
| 770 |
+
body.on('data', console.log)
|
| 771 |
+
|
| 772 |
+
nodeServerUndiciClient.close()
|
| 773 |
+
fastifyServerUndiciClient.close()
|
| 774 |
+
fastifyServer.close()
|
| 775 |
+
nodeServer.close()
|
| 776 |
+
} catch (error) { }
|
| 777 |
+
```
|
| 778 |
+
|
| 779 |
+
### `Dispatcher.upgrade(options[, callback])`
|
| 780 |
+
|
| 781 |
+
Upgrade to a different protocol. Visit [MDN - HTTP - Protocol upgrade mechanism](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism) for more details.
|
| 782 |
+
|
| 783 |
+
Arguments:
|
| 784 |
+
|
| 785 |
+
* **options** `UpgradeOptions`
|
| 786 |
+
|
| 787 |
+
* **callback** `(error: Error | null, data: UpgradeData) => void` (optional)
|
| 788 |
+
|
| 789 |
+
Returns: `void | Promise<UpgradeData>` - Only returns a `Promise` if no `callback` argument was passed
|
| 790 |
+
|
| 791 |
+
#### Parameter: `UpgradeOptions`
|
| 792 |
+
|
| 793 |
+
* **path** `string`
|
| 794 |
+
* **method** `string` (optional) - Default: `'GET'`
|
| 795 |
+
* **headers** `UndiciHeaders` (optional) - Default: `null`
|
| 796 |
+
* **protocol** `string` (optional) - Default: `'Websocket'` - A string of comma separated protocols, in descending preference order.
|
| 797 |
+
* **signal** `AbortSignal | EventEmitter | null` (optional) - Default: `null`
|
| 798 |
+
|
| 799 |
+
#### Parameter: `UpgradeData`
|
| 800 |
+
|
| 801 |
+
* **headers** `http.IncomingHeaders`
|
| 802 |
+
* **socket** `stream.Duplex`
|
| 803 |
+
* **opaque** `unknown`
|
| 804 |
+
|
| 805 |
+
#### Example 1 - Basic Upgrade Request
|
| 806 |
+
|
| 807 |
+
```js
|
| 808 |
+
import { createServer } from 'http'
|
| 809 |
+
import { Client } from 'undici'
|
| 810 |
+
import { once } from 'events'
|
| 811 |
+
|
| 812 |
+
const server = createServer((request, response) => {
|
| 813 |
+
response.statusCode = 101
|
| 814 |
+
response.setHeader('connection', 'upgrade')
|
| 815 |
+
response.setHeader('upgrade', request.headers.upgrade)
|
| 816 |
+
response.end()
|
| 817 |
+
}).listen()
|
| 818 |
+
|
| 819 |
+
await once(server, 'listening')
|
| 820 |
+
|
| 821 |
+
const client = new Client(`http://localhost:${server.address().port}`)
|
| 822 |
+
|
| 823 |
+
try {
|
| 824 |
+
const { headers, socket } = await client.upgrade({
|
| 825 |
+
path: '/',
|
| 826 |
+
})
|
| 827 |
+
socket.on('end', () => {
|
| 828 |
+
console.log(`upgrade: ${headers.upgrade}`) // upgrade: Websocket
|
| 829 |
+
client.close()
|
| 830 |
+
server.close()
|
| 831 |
+
})
|
| 832 |
+
socket.end()
|
| 833 |
+
} catch (error) {
|
| 834 |
+
console.error(error)
|
| 835 |
+
client.close()
|
| 836 |
+
server.close()
|
| 837 |
+
}
|
| 838 |
+
```
|
| 839 |
+
|
| 840 |
+
### `Dispatcher.compose(interceptors[, interceptor])`
|
| 841 |
+
|
| 842 |
+
Compose a new dispatcher from the current dispatcher and the given interceptors.
|
| 843 |
+
|
| 844 |
+
> _Notes_:
|
| 845 |
+
> - The order of the interceptors matters. The last interceptor will be the first to be called.
|
| 846 |
+
> - It is important to note that the `interceptor` function should return a function that follows the `Dispatcher.dispatch` signature.
|
| 847 |
+
> - Any fork of the chain of `interceptors` can lead to unexpected results.
|
| 848 |
+
>
|
| 849 |
+
> **Interceptor Stack Visualization:**
|
| 850 |
+
> ```
|
| 851 |
+
> compose([interceptor1, interceptor2, interceptor3])
|
| 852 |
+
>
|
| 853 |
+
> Request Flow:
|
| 854 |
+
> ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
| 855 |
+
> │ Request │───▶│interceptor3 │───▶│interceptor2 │───▶│interceptor1 │───▶│ dispatcher │
|
| 856 |
+
> └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ .dispatch │
|
| 857 |
+
> ▲ ▲ ▲ └─────────────┘
|
| 858 |
+
> │ │ │ ▲
|
| 859 |
+
> (called first) (called second) (called last) │
|
| 860 |
+
> │
|
| 861 |
+
> ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
| 862 |
+
> │ Response │◀───│interceptor3 │◀───│interceptor2 │◀───│interceptor1 │◀─────────┘
|
| 863 |
+
> └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
|
| 864 |
+
>
|
| 865 |
+
> The interceptors are composed in reverse order due to function composition.
|
| 866 |
+
> ```
|
| 867 |
+
|
| 868 |
+
Arguments:
|
| 869 |
+
|
| 870 |
+
* **interceptors** `Interceptor[interceptor[]]`: It is an array of `Interceptor` functions passed as only argument, or several interceptors passed as separate arguments.
|
| 871 |
+
|
| 872 |
+
Returns: `Dispatcher`.
|
| 873 |
+
|
| 874 |
+
#### Parameter: `Interceptor`
|
| 875 |
+
|
| 876 |
+
A function that takes a `dispatch` method and returns a `dispatch`-like function.
|
| 877 |
+
|
| 878 |
+
#### Example 1 - Basic Compose
|
| 879 |
+
|
| 880 |
+
```js
|
| 881 |
+
const { Client, RedirectHandler } = require('undici')
|
| 882 |
+
|
| 883 |
+
const redirectInterceptor = dispatch => {
|
| 884 |
+
return (opts, handler) => {
|
| 885 |
+
const { maxRedirections } = opts
|
| 886 |
+
|
| 887 |
+
if (!maxRedirections) {
|
| 888 |
+
return dispatch(opts, handler)
|
| 889 |
+
}
|
| 890 |
+
|
| 891 |
+
const redirectHandler = new RedirectHandler(
|
| 892 |
+
dispatch,
|
| 893 |
+
maxRedirections,
|
| 894 |
+
opts,
|
| 895 |
+
handler
|
| 896 |
+
)
|
| 897 |
+
opts = { ...opts, maxRedirections: 0 } // Stop sub dispatcher from also redirecting.
|
| 898 |
+
return dispatch(opts, redirectHandler)
|
| 899 |
+
}
|
| 900 |
+
}
|
| 901 |
+
|
| 902 |
+
const client = new Client('http://localhost:3000')
|
| 903 |
+
.compose(redirectInterceptor)
|
| 904 |
+
|
| 905 |
+
await client.request({ path: '/', method: 'GET' })
|
| 906 |
+
```
|
| 907 |
+
|
| 908 |
+
#### Example 2 - Chained Compose
|
| 909 |
+
|
| 910 |
+
```js
|
| 911 |
+
const { Client, RedirectHandler, RetryHandler } = require('undici')
|
| 912 |
+
|
| 913 |
+
const redirectInterceptor = dispatch => {
|
| 914 |
+
return (opts, handler) => {
|
| 915 |
+
const { maxRedirections } = opts
|
| 916 |
+
|
| 917 |
+
if (!maxRedirections) {
|
| 918 |
+
return dispatch(opts, handler)
|
| 919 |
+
}
|
| 920 |
+
|
| 921 |
+
const redirectHandler = new RedirectHandler(
|
| 922 |
+
dispatch,
|
| 923 |
+
maxRedirections,
|
| 924 |
+
opts,
|
| 925 |
+
handler
|
| 926 |
+
)
|
| 927 |
+
opts = { ...opts, maxRedirections: 0 }
|
| 928 |
+
return dispatch(opts, redirectHandler)
|
| 929 |
+
}
|
| 930 |
+
}
|
| 931 |
+
|
| 932 |
+
const retryInterceptor = dispatch => {
|
| 933 |
+
return function retryInterceptor (opts, handler) {
|
| 934 |
+
return dispatch(
|
| 935 |
+
opts,
|
| 936 |
+
new RetryHandler(opts, {
|
| 937 |
+
handler,
|
| 938 |
+
dispatch
|
| 939 |
+
})
|
| 940 |
+
)
|
| 941 |
+
}
|
| 942 |
+
}
|
| 943 |
+
|
| 944 |
+
const client = new Client('http://localhost:3000')
|
| 945 |
+
.compose(redirectInterceptor)
|
| 946 |
+
.compose(retryInterceptor)
|
| 947 |
+
|
| 948 |
+
await client.request({ path: '/', method: 'GET' })
|
| 949 |
+
```
|
| 950 |
+
|
| 951 |
+
#### Pre-built interceptors
|
| 952 |
+
|
| 953 |
+
##### `redirect`
|
| 954 |
+
|
| 955 |
+
The `redirect` interceptor allows you to customize the way your dispatcher handles redirects.
|
| 956 |
+
|
| 957 |
+
It accepts the same arguments as the [`RedirectHandler` constructor](/docs/docs/api/RedirectHandler.md).
|
| 958 |
+
|
| 959 |
+
**Example - Basic Redirect Interceptor**
|
| 960 |
+
|
| 961 |
+
```js
|
| 962 |
+
const { Client, interceptors } = require("undici");
|
| 963 |
+
const { redirect } = interceptors;
|
| 964 |
+
|
| 965 |
+
const client = new Client("http://service.example").compose(
|
| 966 |
+
redirect({ maxRedirections: 3, throwOnMaxRedirect: true })
|
| 967 |
+
);
|
| 968 |
+
client.request({ path: "/" })
|
| 969 |
+
```
|
| 970 |
+
|
| 971 |
+
##### `retry`
|
| 972 |
+
|
| 973 |
+
The `retry` interceptor allows you to customize the way your dispatcher handles retries.
|
| 974 |
+
|
| 975 |
+
It accepts the same arguments as the [`RetryHandler` constructor](/docs/docs/api/RetryHandler.md).
|
| 976 |
+
|
| 977 |
+
**Example - Basic Redirect Interceptor**
|
| 978 |
+
|
| 979 |
+
```js
|
| 980 |
+
const { Client, interceptors } = require("undici");
|
| 981 |
+
const { retry } = interceptors;
|
| 982 |
+
|
| 983 |
+
const client = new Client("http://service.example").compose(
|
| 984 |
+
retry({
|
| 985 |
+
maxRetries: 3,
|
| 986 |
+
minTimeout: 1000,
|
| 987 |
+
maxTimeout: 10000,
|
| 988 |
+
timeoutFactor: 2,
|
| 989 |
+
retryAfter: true,
|
| 990 |
+
})
|
| 991 |
+
);
|
| 992 |
+
```
|
| 993 |
+
|
| 994 |
+
##### `dump`
|
| 995 |
+
|
| 996 |
+
The `dump` interceptor enables you to dump the response body from a request upon a given limit.
|
| 997 |
+
|
| 998 |
+
**Options**
|
| 999 |
+
- `maxSize` - The maximum size (in bytes) of the response body to dump. If the size of the request's body exceeds this value then the connection will be closed. Default: `1048576`.
|
| 1000 |
+
|
| 1001 |
+
> The `Dispatcher#options` also gets extended with the options `dumpMaxSize`, `abortOnDumped`, and `waitForTrailers` which can be used to configure the interceptor at a request-per-request basis.
|
| 1002 |
+
|
| 1003 |
+
**Example - Basic Dump Interceptor**
|
| 1004 |
+
|
| 1005 |
+
```js
|
| 1006 |
+
const { Client, interceptors } = require("undici");
|
| 1007 |
+
const { dump } = interceptors;
|
| 1008 |
+
|
| 1009 |
+
const client = new Client("http://service.example").compose(
|
| 1010 |
+
dump({
|
| 1011 |
+
maxSize: 1024,
|
| 1012 |
+
})
|
| 1013 |
+
);
|
| 1014 |
+
|
| 1015 |
+
// or
|
| 1016 |
+
client.dispatch(
|
| 1017 |
+
{
|
| 1018 |
+
path: "/",
|
| 1019 |
+
method: "GET",
|
| 1020 |
+
dumpMaxSize: 1024,
|
| 1021 |
+
},
|
| 1022 |
+
handler
|
| 1023 |
+
);
|
| 1024 |
+
```
|
| 1025 |
+
|
| 1026 |
+
##### `dns`
|
| 1027 |
+
|
| 1028 |
+
The `dns` interceptor enables you to cache DNS lookups for a given duration, per origin.
|
| 1029 |
+
|
| 1030 |
+
>It is well suited for scenarios where you want to cache DNS lookups to avoid the overhead of resolving the same domain multiple times
|
| 1031 |
+
|
| 1032 |
+
**Options**
|
| 1033 |
+
- `maxTTL` - The maximum time-to-live (in milliseconds) of the DNS cache. It should be a positive integer. Default: `10000`.
|
| 1034 |
+
- Set `0` to disable TTL.
|
| 1035 |
+
- `maxItems` - The maximum number of items to cache. It should be a positive integer. Default: `Infinity`.
|
| 1036 |
+
- `dualStack` - Whether to resolve both IPv4 and IPv6 addresses. Default: `true`.
|
| 1037 |
+
- It will also attempt a happy-eyeballs-like approach to connect to the available addresses in case of a connection failure.
|
| 1038 |
+
- `affinity` - Whether to use IPv4 or IPv6 addresses. Default: `4`.
|
| 1039 |
+
- It can be either `4` or `6`.
|
| 1040 |
+
- It will only take effect if `dualStack` is `false`.
|
| 1041 |
+
- `lookup: (hostname: string, options: LookupOptions, callback: (err: NodeJS.ErrnoException | null, addresses: DNSInterceptorRecord[]) => void) => void` - Custom lookup function. Default: `dns.lookup`.
|
| 1042 |
+
- For more info see [dns.lookup](https://nodejs.org/api/dns.html#dnslookuphostname-options-callback).
|
| 1043 |
+
- `pick: (origin: URL, records: DNSInterceptorRecords, affinity: 4 | 6) => DNSInterceptorRecord` - Custom pick function. Default: `RoundRobin`.
|
| 1044 |
+
- The function should return a single record from the records array.
|
| 1045 |
+
- By default a simplified version of Round Robin is used.
|
| 1046 |
+
- The `records` property can be mutated to store the state of the balancing algorithm.
|
| 1047 |
+
- `storage: DNSStorage` - Custom storage for resolved DNS records
|
| 1048 |
+
|
| 1049 |
+
> The `Dispatcher#options` also gets extended with the options `dns.affinity`, `dns.dualStack`, `dns.lookup` and `dns.pick` which can be used to configure the interceptor at a request-per-request basis.
|
| 1050 |
+
|
| 1051 |
+
|
| 1052 |
+
**DNSInterceptorRecord**
|
| 1053 |
+
It represents a DNS record.
|
| 1054 |
+
- `family` - (`number`) The IP family of the address. It can be either `4` or `6`.
|
| 1055 |
+
- `address` - (`string`) The IP address.
|
| 1056 |
+
|
| 1057 |
+
**DNSInterceptorOriginRecords**
|
| 1058 |
+
It represents a map of DNS IP addresses records for a single origin.
|
| 1059 |
+
- `4.ips` - (`DNSInterceptorRecord[] | null`) The IPv4 addresses.
|
| 1060 |
+
- `6.ips` - (`DNSInterceptorRecord[] | null`) The IPv6 addresses.
|
| 1061 |
+
|
| 1062 |
+
**DNSStorage**
|
| 1063 |
+
It represents a storage object for resolved DNS records.
|
| 1064 |
+
- `size` - (`number`) current size of the storage.
|
| 1065 |
+
- `get` - (`(origin: string) => DNSInterceptorOriginRecords | null`) method to get the records for a given origin.
|
| 1066 |
+
- `set` - (`(origin: string, records: DNSInterceptorOriginRecords | null, options: { ttl: number }) => void`) method to set the records for a given origin.
|
| 1067 |
+
- `delete` - (`(origin: string) => void`) method to delete records for a given origin.
|
| 1068 |
+
- `full` - (`() => boolean`) method to check if the storage is full, if returns `true`, DNS lookup will be skipped in this interceptor and new records will not be stored.
|
| 1069 |
+
|
| 1070 |
+
**Example - Basic DNS Interceptor**
|
| 1071 |
+
|
| 1072 |
+
```js
|
| 1073 |
+
const { Client, interceptors } = require("undici");
|
| 1074 |
+
const { dns } = interceptors;
|
| 1075 |
+
|
| 1076 |
+
const client = new Agent().compose([
|
| 1077 |
+
dns({ ...opts })
|
| 1078 |
+
])
|
| 1079 |
+
|
| 1080 |
+
const response = await client.request({
|
| 1081 |
+
origin: `http://localhost:3030`,
|
| 1082 |
+
...requestOpts
|
| 1083 |
+
})
|
| 1084 |
+
```
|
| 1085 |
+
|
| 1086 |
+
**Example - DNS Interceptor and LRU cache as a storage**
|
| 1087 |
+
|
| 1088 |
+
```js
|
| 1089 |
+
const { Client, interceptors } = require("undici");
|
| 1090 |
+
const QuickLRU = require("quick-lru");
|
| 1091 |
+
const { dns } = interceptors;
|
| 1092 |
+
|
| 1093 |
+
const lru = new QuickLRU({ maxSize: 100 });
|
| 1094 |
+
|
| 1095 |
+
const lruAdapter = {
|
| 1096 |
+
get size() {
|
| 1097 |
+
return lru.size;
|
| 1098 |
+
},
|
| 1099 |
+
get(origin) {
|
| 1100 |
+
return lru.get(origin);
|
| 1101 |
+
},
|
| 1102 |
+
set(origin, records, { ttl }) {
|
| 1103 |
+
lru.set(origin, records, { maxAge: ttl });
|
| 1104 |
+
},
|
| 1105 |
+
delete(origin) {
|
| 1106 |
+
lru.delete(origin);
|
| 1107 |
+
},
|
| 1108 |
+
full() {
|
| 1109 |
+
// For LRU cache, we can always store new records,
|
| 1110 |
+
// old records will be evicted automatically
|
| 1111 |
+
return false;
|
| 1112 |
+
}
|
| 1113 |
+
}
|
| 1114 |
+
|
| 1115 |
+
const client = new Agent().compose([
|
| 1116 |
+
dns({ storage: lruAdapter })
|
| 1117 |
+
])
|
| 1118 |
+
|
| 1119 |
+
const response = await client.request({
|
| 1120 |
+
origin: `http://localhost:3030`,
|
| 1121 |
+
...requestOpts
|
| 1122 |
+
})
|
| 1123 |
+
```
|
| 1124 |
+
|
| 1125 |
+
##### `responseError`
|
| 1126 |
+
|
| 1127 |
+
The `responseError` interceptor throws an error for responses with status code errors (>= 400).
|
| 1128 |
+
|
| 1129 |
+
**Example**
|
| 1130 |
+
|
| 1131 |
+
```js
|
| 1132 |
+
const { Client, interceptors } = require("undici");
|
| 1133 |
+
const { responseError } = interceptors;
|
| 1134 |
+
|
| 1135 |
+
const client = new Client("http://service.example").compose(
|
| 1136 |
+
responseError()
|
| 1137 |
+
);
|
| 1138 |
+
|
| 1139 |
+
// Will throw a ResponseError for status codes >= 400
|
| 1140 |
+
await client.request({
|
| 1141 |
+
method: "GET",
|
| 1142 |
+
path: "/"
|
| 1143 |
+
});
|
| 1144 |
+
```
|
| 1145 |
+
|
| 1146 |
+
##### `decompress`
|
| 1147 |
+
|
| 1148 |
+
⚠️ The decompress interceptor is experimental and subject to change.
|
| 1149 |
+
|
| 1150 |
+
The `decompress` interceptor automatically decompresses response bodies that are compressed with gzip, deflate, brotli, or zstd compression. It removes the `content-encoding` and `content-length` headers from decompressed responses and supports RFC-9110 compliant multiple encodings.
|
| 1151 |
+
|
| 1152 |
+
**Options**
|
| 1153 |
+
|
| 1154 |
+
- `skipErrorResponses` - Whether to skip decompression for error responses (status codes >= 400). Default: `true`.
|
| 1155 |
+
- `skipStatusCodes` - Array of status codes to skip decompression for. Default: `[204, 304]`.
|
| 1156 |
+
|
| 1157 |
+
**Example - Basic Decompress Interceptor**
|
| 1158 |
+
|
| 1159 |
+
```js
|
| 1160 |
+
const { Client, interceptors } = require("undici");
|
| 1161 |
+
const { decompress } = interceptors;
|
| 1162 |
+
|
| 1163 |
+
const client = new Client("http://service.example").compose(
|
| 1164 |
+
decompress()
|
| 1165 |
+
);
|
| 1166 |
+
|
| 1167 |
+
// Automatically decompresses gzip/deflate/brotli/zstd responses
|
| 1168 |
+
const response = await client.request({
|
| 1169 |
+
method: "GET",
|
| 1170 |
+
path: "/"
|
| 1171 |
+
});
|
| 1172 |
+
```
|
| 1173 |
+
|
| 1174 |
+
**Example - Custom Options**
|
| 1175 |
+
|
| 1176 |
+
```js
|
| 1177 |
+
const { Client, interceptors } = require("undici");
|
| 1178 |
+
const { decompress } = interceptors;
|
| 1179 |
+
|
| 1180 |
+
const client = new Client("http://service.example").compose(
|
| 1181 |
+
decompress({
|
| 1182 |
+
skipErrorResponses: false, // Decompress 5xx responses
|
| 1183 |
+
skipStatusCodes: [204, 304, 201] // Skip these status codes
|
| 1184 |
+
})
|
| 1185 |
+
);
|
| 1186 |
+
```
|
| 1187 |
+
|
| 1188 |
+
**Supported Encodings**
|
| 1189 |
+
|
| 1190 |
+
- `gzip` / `x-gzip` - GZIP compression
|
| 1191 |
+
- `deflate` / `x-compress` - DEFLATE compression
|
| 1192 |
+
- `br` - Brotli compression
|
| 1193 |
+
- `zstd` - Zstandard compression
|
| 1194 |
+
- Multiple encodings (e.g., `gzip, deflate`) are supported per RFC-9110
|
| 1195 |
+
|
| 1196 |
+
**Behavior**
|
| 1197 |
+
|
| 1198 |
+
- Skips decompression for status codes < 200 or >= 400 (configurable)
|
| 1199 |
+
- Skips decompression for 204 No Content and 304 Not Modified by default
|
| 1200 |
+
- Removes `content-encoding` and `content-length` headers when decompressing
|
| 1201 |
+
- Passes through unsupported encodings unchanged
|
| 1202 |
+
- Handles case-insensitive encoding names
|
| 1203 |
+
- Supports streaming decompression without buffering
|
| 1204 |
+
|
| 1205 |
+
##### `Cache Interceptor`
|
| 1206 |
+
|
| 1207 |
+
The `cache` interceptor implements client-side response caching as described in
|
| 1208 |
+
[RFC9111](https://www.rfc-editor.org/rfc/rfc9111.html).
|
| 1209 |
+
|
| 1210 |
+
**Options**
|
| 1211 |
+
|
| 1212 |
+
- `store` - The [`CacheStore`](/docs/docs/api/CacheStore.md) to store and retrieve responses from. Default is [`MemoryCacheStore`](/docs/docs/api/CacheStore.md#memorycachestore).
|
| 1213 |
+
- `methods` - The [**safe** HTTP methods](https://www.rfc-editor.org/rfc/rfc9110#section-9.2.1) to cache the response of.
|
| 1214 |
+
- `cacheByDefault` - The default expiration time to cache responses by if they don't have an explicit expiration and cannot have an heuristic expiry computed. If this isn't present, responses neither with an explicit expiration nor heuristically cacheable will not be cached. Default `undefined`.
|
| 1215 |
+
- `type` - The [type of cache](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching#types_of_caches) for Undici to act as. Can be `shared` or `private`. Default `shared`. `private` implies privately cacheable responses will be cached and potentially shared with other users of your application.
|
| 1216 |
+
|
| 1217 |
+
**Usage with `fetch`**
|
| 1218 |
+
|
| 1219 |
+
```js
|
| 1220 |
+
const { Agent, cacheStores, interceptors, setGlobalDispatcher } = require('undici')
|
| 1221 |
+
|
| 1222 |
+
const client = new Agent().compose(interceptors.cache({
|
| 1223 |
+
store: new cacheStores.MemoryCacheStore({
|
| 1224 |
+
maxSize: 100 * 1024 * 1024, // 100MB
|
| 1225 |
+
maxCount: 1000,
|
| 1226 |
+
maxEntrySize: 5 * 1024 * 1024 // 5MB
|
| 1227 |
+
})
|
| 1228 |
+
}))
|
| 1229 |
+
|
| 1230 |
+
setGlobalDispatcher(client)
|
| 1231 |
+
|
| 1232 |
+
// First request goes to the network and is cached when cache headers allow it.
|
| 1233 |
+
const first = await fetch('https://example.com/data')
|
| 1234 |
+
|
| 1235 |
+
// Second request can be served from cache according to RFC9111 rules.
|
| 1236 |
+
const second = await fetch('https://example.com/data')
|
| 1237 |
+
```
|
| 1238 |
+
|
| 1239 |
+
##### `Deduplicate Interceptor`
|
| 1240 |
+
|
| 1241 |
+
The `deduplicate` interceptor deduplicates concurrent identical requests. When multiple identical requests are made while one is already in-flight, only one request is sent to the origin server, and all waiting handlers receive the same response. This reduces server load and improves performance.
|
| 1242 |
+
|
| 1243 |
+
**Options**
|
| 1244 |
+
|
| 1245 |
+
- `methods` - The [**safe** HTTP methods](https://www.rfc-editor.org/rfc/rfc9110#section-9.2.1) to deduplicate. Default `['GET']`.
|
| 1246 |
+
- `skipHeaderNames` - Header names that, if present in a request, will cause the request to skip deduplication entirely. Useful for headers like `idempotency-key` where presence indicates unique processing. Header name matching is case-insensitive. Default `[]`.
|
| 1247 |
+
- `excludeHeaderNames` - Header names to exclude from the deduplication key. Requests with different values for these headers will still be deduplicated together. Useful for headers like `x-request-id` that vary per request but shouldn't affect deduplication. Header name matching is case-insensitive. Default `[]`.
|
| 1248 |
+
- `maxBufferSize` - Maximum bytes buffered per paused waiting deduplicated handler. If a waiting handler remains paused and exceeds this threshold, it is failed with an abort error to prevent unbounded memory growth. Default `5 * 1024 * 1024`.
|
| 1249 |
+
|
| 1250 |
+
**Usage**
|
| 1251 |
+
|
| 1252 |
+
```js
|
| 1253 |
+
const { Client, interceptors } = require("undici");
|
| 1254 |
+
const { deduplicate, cache } = interceptors;
|
| 1255 |
+
|
| 1256 |
+
// Deduplicate only
|
| 1257 |
+
const client = new Client("http://service.example").compose(
|
| 1258 |
+
deduplicate()
|
| 1259 |
+
);
|
| 1260 |
+
|
| 1261 |
+
// Deduplicate with caching
|
| 1262 |
+
const clientWithCache = new Client("http://service.example").compose(
|
| 1263 |
+
deduplicate(),
|
| 1264 |
+
cache()
|
| 1265 |
+
);
|
| 1266 |
+
```
|
| 1267 |
+
|
| 1268 |
+
Requests are considered identical if they have the same:
|
| 1269 |
+
- Origin
|
| 1270 |
+
- HTTP method
|
| 1271 |
+
- Path
|
| 1272 |
+
- Request headers (excluding any headers specified in `excludeHeaderNames`)
|
| 1273 |
+
|
| 1274 |
+
All deduplicated requests receive the complete response including status code, headers, and body.
|
| 1275 |
+
|
| 1276 |
+
For observability, request deduplication events are published to the `undici:request:pending-requests` [diagnostic channel](/docs/docs/api/DiagnosticsChannel.md#undicirequestpending-requests).
|
| 1277 |
+
|
| 1278 |
+
## Instance Events
|
| 1279 |
+
|
| 1280 |
+
### Event: `'connect'`
|
| 1281 |
+
|
| 1282 |
+
Parameters:
|
| 1283 |
+
|
| 1284 |
+
* **origin** `URL`
|
| 1285 |
+
* **targets** `Array<Dispatcher>`
|
| 1286 |
+
|
| 1287 |
+
### Event: `'disconnect'`
|
| 1288 |
+
|
| 1289 |
+
Parameters:
|
| 1290 |
+
|
| 1291 |
+
* **origin** `URL`
|
| 1292 |
+
* **targets** `Array<Dispatcher>`
|
| 1293 |
+
* **error** `Error`
|
| 1294 |
+
|
| 1295 |
+
Emitted when the dispatcher has been disconnected from the origin.
|
| 1296 |
+
|
| 1297 |
+
> **Note**: For HTTP/2, this event is also emitted when the dispatcher has received the [GOAWAY Frame](https://webconcepts.info/concepts/http2-frame-type/0x7) with an Error with the message `HTTP/2: "GOAWAY" frame received` and the code `UND_ERR_INFO`.
|
| 1298 |
+
> Due to nature of the protocol of using binary frames, it is possible that requests gets hanging as a frame can be received between the `HEADER` and `DATA` frames.
|
| 1299 |
+
> It is recommended to handle this event and close the dispatcher to create a new HTTP/2 session.
|
| 1300 |
+
|
| 1301 |
+
### Event: `'connectionError'`
|
| 1302 |
+
|
| 1303 |
+
Parameters:
|
| 1304 |
+
|
| 1305 |
+
* **origin** `URL`
|
| 1306 |
+
* **targets** `Array<Dispatcher>`
|
| 1307 |
+
* **error** `Error`
|
| 1308 |
+
|
| 1309 |
+
Emitted when dispatcher fails to connect to
|
| 1310 |
+
origin.
|
| 1311 |
+
|
| 1312 |
+
### Event: `'drain'`
|
| 1313 |
+
|
| 1314 |
+
Parameters:
|
| 1315 |
+
|
| 1316 |
+
* **origin** `URL`
|
| 1317 |
+
|
| 1318 |
+
Emitted when dispatcher is no longer busy.
|
| 1319 |
+
|
| 1320 |
+
## Parameter: `UndiciHeaders`
|
| 1321 |
+
|
| 1322 |
+
* `Record<string, string | string[] | undefined> | string[] | Iterable<[string, string | string[] | undefined]> | null`
|
| 1323 |
+
|
| 1324 |
+
Header arguments such as `options.headers` in [`Client.dispatch`](/docs/docs/api/Client.md#clientdispatchoptions-handlers) can be specified in three forms:
|
| 1325 |
+
* As an object specified by the `Record<string, string | string[] | undefined>` (`IncomingHttpHeaders`) type.
|
| 1326 |
+
* As an array of strings. An array representation of a header list must have an even length, or an `InvalidArgumentError` will be thrown.
|
| 1327 |
+
* As an iterable that can encompass `Headers`, `Map`, or a custom iterator returning key-value pairs.
|
| 1328 |
+
Keys are lowercase and values are not modified.
|
| 1329 |
+
|
| 1330 |
+
Undici validates header syntax at the protocol level (for example, invalid header names and invalid control characters in string values), but it does not sanitize untrusted application input. Validate and sanitize any user-provided header names and values before passing them to Undici to prevent header/body injection vulnerabilities.
|
| 1331 |
+
|
| 1332 |
+
When using the array header format (`string[]`), Undici processes only indexed elements. Additional properties assigned to the array object are ignored.
|
| 1333 |
+
|
| 1334 |
+
Response headers will derive a `host` from the `url` of the [Client](/docs/docs/api/Client.md#class-client) instance if no `host` header was previously specified.
|
| 1335 |
+
|
| 1336 |
+
### Example 1 - Object
|
| 1337 |
+
|
| 1338 |
+
```js
|
| 1339 |
+
{
|
| 1340 |
+
'content-length': '123',
|
| 1341 |
+
'content-type': 'text/plain',
|
| 1342 |
+
connection: 'keep-alive',
|
| 1343 |
+
host: 'mysite.com',
|
| 1344 |
+
accept: '*/*'
|
| 1345 |
+
}
|
| 1346 |
+
```
|
| 1347 |
+
|
| 1348 |
+
### Example 2 - Array
|
| 1349 |
+
|
| 1350 |
+
```js
|
| 1351 |
+
[
|
| 1352 |
+
'content-length', '123',
|
| 1353 |
+
'content-type', 'text/plain',
|
| 1354 |
+
'connection', 'keep-alive',
|
| 1355 |
+
'host', 'mysite.com',
|
| 1356 |
+
'accept', '*/*'
|
| 1357 |
+
]
|
| 1358 |
+
```
|
| 1359 |
+
|
| 1360 |
+
### Example 3 - Iterable
|
| 1361 |
+
|
| 1362 |
+
```js
|
| 1363 |
+
new Headers({
|
| 1364 |
+
'content-length': '123',
|
| 1365 |
+
'content-type': 'text/plain',
|
| 1366 |
+
connection: 'keep-alive',
|
| 1367 |
+
host: 'mysite.com',
|
| 1368 |
+
accept: '*/*'
|
| 1369 |
+
})
|
| 1370 |
+
```
|
| 1371 |
+
or
|
| 1372 |
+
```js
|
| 1373 |
+
new Map([
|
| 1374 |
+
['content-length', '123'],
|
| 1375 |
+
['content-type', 'text/plain'],
|
| 1376 |
+
['connection', 'keep-alive'],
|
| 1377 |
+
['host', 'mysite.com'],
|
| 1378 |
+
['accept', '*/*']
|
| 1379 |
+
])
|
| 1380 |
+
```
|
| 1381 |
+
or
|
| 1382 |
+
```js
|
| 1383 |
+
{
|
| 1384 |
+
*[Symbol.iterator] () {
|
| 1385 |
+
yield ['content-length', '123']
|
| 1386 |
+
yield ['content-type', 'text/plain']
|
| 1387 |
+
yield ['connection', 'keep-alive']
|
| 1388 |
+
yield ['host', 'mysite.com']
|
| 1389 |
+
yield ['accept', '*/*']
|
| 1390 |
+
}
|
| 1391 |
+
}
|
| 1392 |
+
```
|