AK-21/Graphite-Industrial-Intelligence
0
1# trough2 3[![Build][badge-build-image]][badge-build-url]4[![Coverage][badge-coverage-image]][badge-coverage-url]5[![Downloads][badge-downloads-image]][badge-downloads-url]6[![Size][badge-size-image]][badge-size-url]7 8`trough` is middleware.9 10## Contents11 12* [What is this?](#what-is-this)13* [When should I use this?](#when-should-i-use-this)14* [Install](#install)15* [Use](#use)16* [API](#api)17 * [`trough()`](#trough-1)18 * [`wrap(middleware, callback)`](#wrapmiddleware-callback)19 * [`Callback`](#callback)20 * [`Middleware`](#middleware)21 * [`Pipeline`](#pipeline)22 * [`Run`](#run)23 * [`Use`](#use-1)24* [Compatibility](#compatibility)25* [Security](#security)26* [Contribute](#contribute)27* [License](#license)28 29## What is this?30 31`trough` is like [`ware`][github-segmentio-ware] with less sugar.32Middleware functions can also change the input of the next.33 34The word **trough** (`/trôf/`) means a channel used to convey a liquid.35 36## When should I use this?37 38You can use this package when you’re building something that accepts “plugins”,39which are functions, that can be sync or async, promises or callbacks.40 41## Install42 43This package is [ESM only][github-gist-esm].44In Node.js (version 16+),45install with [npm][npm-install]:46 47```sh48npm install trough49```50 51In Deno with [`esm.sh`][esm-sh]:52 53```js54import {trough, wrap} from 'https://esm.sh/trough@2'55```56 57In browsers with [`esm.sh`][esm-sh]:58 59```html60<script type="module">61 import {trough, wrap} from 'https://esm.sh/trough@2?bundle'62</script>63```64 65## Use66 67```js68import fs from 'node:fs'69import path from 'node:path'70import process from 'node:process'71import {trough} from 'trough'72 73const pipeline = trough()74 .use(function (fileName) {75 console.log('Checking… ' + fileName)76 })77 .use(function (fileName) {78 return path.join(process.cwd(), fileName)79 })80 .use(function (filePath, next) {81 fs.stat(filePath, function (error, stats) {82 next(error, {filePath, stats})83 })84 })85 .use(function (ctx, next) {86 if (ctx.stats.isFile()) {87 fs.readFile(ctx.filePath, next)88 } else {89 next(new Error('Expected file'))90 }91 })92 93pipeline.run('readme.md', console.log)94pipeline.run('node_modules', console.log)95```96 97Yields:98 99```txt100Checking… readme.md101Checking… node_modules102Error: Expected file103 at ~/example.js:22:12104 at wrapped (~/node_modules/trough/index.js:111:16)105 at next (~/node_modules/trough/index.js:62:23)106 at done (~/node_modules/trough/index.js:145:7)107 at ~/example.js:15:7108 at FSReqCallback.oncomplete (node:fs:199:5)109null <Buffer 23 20 74 72 6f 75 67 68 0a 0a 5b 21 5b 42 75 69 6c 64 5d 5b 62 75 69 6c 64 2d 62 61 64 67 65 5d 5d 5b 62 75 69 6c 64 5d 0a 5b 21 5b 43 6f 76 65 72 61 ... 7994 more bytes>110```111 112## API113 114This package exports the identifiers115[`trough`][api-trough] and116[`wrap`][api-wrap].117There is no default export.118 119It exports the [TypeScript][] types120[`Callback`][api-callback],121[`Middleware`][api-middleware],122[`Pipeline`][api-pipeline],123[`Run`][api-run],124and [`Use`][api-use].125 126### `trough()`127 128Create new middleware.129 130###### Parameters131 132There are no parameters.133 134###### Returns135 136[`Pipeline`][api-pipeline].137 138### `wrap(middleware, callback)`139 140Wrap `middleware` into a uniform interface.141 142You can pass all input to the resulting function.143`callback` is then called with the output of `middleware`.144 145If `middleware` accepts more arguments than the later given in input,146an extra `done` function is passed to it after that input,147which must be called by `middleware`.148 149The first value in `input` is the main input value.150All other input values are the rest input values.151The values given to `callback` are the input values,152merged with every non-nullish output value.153 154* if `middleware` throws an error,155 returns a promise that is rejected,156 or calls the given `done` function with an error,157 `callback` is called with that error158* if `middleware` returns a value or returns a promise that is resolved,159 that value is the main output value160* if `middleware` calls `done`,161 all non-nullish values except for the first one (the error) overwrite the162 output values163 164###### Parameters165 166* `middleware` ([`Middleware`][api-middleware])167 — function to wrap168* `callback` ([`Callback`][api-callback])169 — callback called with the output of `middleware`170 171###### Returns172 173Wrapped middleware ([`Run`][api-run]).174 175### `Callback`176 177Callback function (TypeScript type).178 179###### Parameters180 181* `error` (`Error`, optional)182 — error, if any183* `...output` (`Array<unknown>`, optional)184 — output values185 186###### Returns187 188Nothing (`undefined`).189 190### `Middleware`191 192A middleware function called with the output of its predecessor (TypeScript193type).194 195###### Synchronous196 197If `fn` returns or throws an error,198the pipeline fails and `done` is called with that error.199 200If `fn` returns a value (neither `null` nor `undefined`),201the first `input` of the next function is set to that value202(all other `input` is passed through).203 204The following example shows how returning an error stops the pipeline:205 206```js207import {trough} from 'trough'208 209trough()210 .use(function (thing) {211 return new Error('Got: ' + thing)212 })213 .run('some value', console.log)214```215 216Yields:217 218```txt219Error: Got: some value220 at ~/example.js:5:12221 …222```223 224The following example shows how throwing an error stops the pipeline:225 226```js227import {trough} from 'trough'228 229trough()230 .use(function (thing) {231 throw new Error('Got: ' + thing)232 })233 .run('more value', console.log)234```235 236Yields:237 238```txt239Error: Got: more value240 at ~/example.js:5:11241 …242```243 244The following example shows how the first output can be modified:245 246```js247import {trough} from 'trough'248 249trough()250 .use(function (thing) {251 return 'even ' + thing252 })253 .run('more value', 'untouched', console.log)254```255 256Yields:257 258```txt259null 'even more value' 'untouched'260```261 262###### Promise263 264If `fn` returns a promise,265and that promise rejects,266the pipeline fails and `done` is called with the rejected value.267 268If `fn` returns a promise,269and that promise resolves with a value (neither `null` nor `undefined`),270the first `input` of the next function is set to that value (all other `input`271is passed through).272 273The following example shows how rejecting a promise stops the pipeline:274 275```js276import {trough} from 'trough'277 278trough()279 .use(function (thing) {280 return new Promise(function (resolve, reject) {281 reject('Got: ' + thing)282 })283 })284 .run('thing', console.log)285```286 287Yields:288 289```txt290Got: thing291```292 293The following example shows how the input isn’t touched by resolving to `null`.294 295```js296import {trough} from 'trough'297 298trough()299 .use(function () {300 return new Promise(function (resolve) {301 setTimeout(function () {302 resolve(null)303 }, 100)304 })305 })306 .run('Input', console.log)307```308 309Yields:310 311```txt312null 'Input'313```314 315###### Asynchronous316 317If `fn` accepts one more argument than the given `input`,318a `next` function is given (after the input).319`next` must be called, but doesn’t have to be called async.320 321If `next` is given a value (neither `null` nor `undefined`) as its first322argument,323the pipeline fails and `done` is called with that value.324 325If `next` is given no value (either `null` or `undefined`) as the first326argument,327all following non-nullish values change the input of the following328function,329and all nullish values default to the `input`.330 331The following example shows how passing a first argument stops the pipeline:332 333```js334import {trough} from 'trough'335 336trough()337 .use(function (thing, next) {338 next(new Error('Got: ' + thing))339 })340 .run('thing', console.log)341```342 343Yields:344 345```txt346Error: Got: thing347 at ~/example.js:5:10348```349 350The following example shows how more values than the input are passed.351 352```js353import {trough} from 'trough'354 355trough()356 .use(function (thing, next) {357 setTimeout(function () {358 next(null, null, 'values')359 }, 100)360 })361 .run('some', console.log)362```363 364Yields:365 366```txt367null 'some' 'values'368```369 370###### Parameters371 372* `...input` (`Array<any>`, optional)373 — input values374 375###### Returns376 377Output, promise, etc (`any`).378 379### `Pipeline`380 381Pipeline (TypeScript type).382 383###### Properties384 385* `run` ([`Run`][api-run])386 — run the pipeline387* `use` ([`Use`][api-use])388 — add middleware389 390### `Run`391 392Call all middleware (TypeScript type).393 394Calls `done` on completion with either an error or the output of the395last middleware.396 397> 👉 **Note**: as the length of input defines whether async functions get a398> `next` function,399> it’s recommended to keep `input` at one value normally.400 401###### Parameters402 403* `...input` (`Array<any>`, optional)404 — input values405* `done` ([`Callback`][api-callback])406 — callback called when done407 408###### Returns409 410Nothing (`undefined`).411 412### `Use`413 414Add middleware (TypeScript type).415 416###### Parameters417 418* `middleware` ([`Middleware`][api-middleware])419 — middleware function420 421###### Returns422 423Current pipeline ([`Pipeline`][api-pipeline]).424 425## Compatibility426 427This projects is compatible with maintained versions of Node.js.428 429When we cut a new major release,430we drop support for unmaintained versions of Node.431This means we try to keep the current release line,432`trough@2`,433compatible with Node.js 12.434 435## Security436 437This package is safe.438 439## Contribute440 441Yes please!442See [How to Contribute to Open Source][open-source-guide-contribute].443 444## License445 446[MIT][file-license] © [Titus Wormer][wooorm]447 448<!-- Definitions -->449 450[api-callback]: #callback451 452[api-middleware]: #middleware453 454[api-pipeline]: #pipeline455 456[api-run]: #run457 458[api-trough]: #trough459 460[api-use]: #use461 462[api-wrap]: #wrapmiddleware-callback463 464[badge-build-image]: https://github.com/wooorm/trough/workflows/main/badge.svg465 466[badge-build-url]: https://github.com/wooorm/trough/actions467 468[badge-coverage-image]: https://img.shields.io/codecov/c/github/wooorm/trough.svg469 470[badge-coverage-url]: https://codecov.io/github/wooorm/trough471 472[badge-downloads-image]: https://img.shields.io/npm/dm/trough.svg473 474[badge-downloads-url]: https://www.npmjs.com/package/trough475 476[badge-size-image]: https://img.shields.io/bundlejs/size/trough477 478[badge-size-url]: https://bundlejs.com/?q=trough479 480[npm-install]: https://docs.npmjs.com/cli/install481 482[esm-sh]: https://esm.sh483 484[file-license]: license485 486[github-gist-esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c487 488[github-segmentio-ware]: https://github.com/segmentio/ware489 490[open-source-guide-contribute]: https://opensource.guide/how-to-contribute/491 492[typescript]: https://www.typescriptlang.org493 494[wooorm]: https://wooorm.com495 