# @endo/trampoline

> Multicolor trampolining for recursive operations

Latest version **1.0.5** (published 2025-06-17) · Apache-2.0 license · 0 weekly downloads

## Install

```sh
npm install @endo/trampoline
pnpm add @endo/trampoline
yarn add @endo/trampoline
bun add @endo/trampoline
```

## Health

**Score 55/100 (C)** — status: stable.

Positive: has types; esm support; no vulnerabilities; high maintenance score; high quality score.

Warnings: low downloads.

Negative: stale.

## Facts

| | |
|---|---|
| Version | 1.0.5 |
| Published | 2025-06-17 |
| First published | 2024-10-01 |
| Weekly downloads | 0 |
| License | Apache-2.0 |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 23.1 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 1054 |
| Author | Endo contributors |
| Maintainers | kriskowal, michaelfig, erights, warner, mhofman |
| Keywords | trampoline, recursive, async, sync, generator |

## Links

- npm: https://www.npmjs.com/package/@endo/trampoline
- Repository: https://github.com/endojs/endo
- Homepage: https://github.com/endojs/endo/blob/master/packages/trampoline/README.md
- Issues: https://github.com/endojs/endo/issues
- npm.io page: https://npm.io/package/@endo/trampoline

## Alternatives

- [@commercetools/sync-actions](https://npm.io/package/@commercetools/sync-actions.md) — 25.1K weekly downloads
- [cwait](https://npm.io/package/cwait.md) — 21.4K weekly downloads
- [@ledgerhq/hw-app-cosmos](https://npm.io/package/@ledgerhq/hw-app-cosmos.md) — 4.2K weekly downloads
- [@financial-times/o-loading](https://npm.io/package/@financial-times/o-loading.md) — 2.8K weekly downloads
- [fa](https://npm.io/package/fa.md) — 185 weekly downloads

## Recent versions

- 1.0.5 (latest) — 2025-06-17
- 1.0.4 — 2025-06-02
- 1.0.3 — 2024-11-13
- 1.0.2 — 2024-10-10
- 1.0.1 — 2024-10-01

## README

# @endo/trampoline

> Multicolor trampolining using generators

**@endo/trampoline** is a utility library which helps share code between synchronous and asynchronous variations of the same algorithm.

## Example Usage

```js
import { asyncTrampoline, syncTrampoline } from '@endo/trampoline';

/**
 * This function "reads a file synchronously" and returns "a list of its imports"
 *
 * @param {string} filepath Source file path
 * @returns {string[]} List of imports found in source
 */
const findImportsSync = filepath => {
  // read a file, parse it for imports, return a list of import specifiers
  // (synchronously)
  // ...
};

/**
 * This function "reads a file asynchronously" and returns "a list of its imports"
 *
 * @param {string} filepath Source file path
 * @returns {Promise<string[]>} List of imports found in source
 */
const findImportsAsync = async filepath => {
  // read a file, parse it for imports, return a list of import specifiers
  // (asynchronously)
  // ...
};

/**
 * Recursively crawls a dependency tree to find all dependencies
 *
 * @template {string[] | Promise<string[]>} TResult Type of result (list of imports)
 * @param {(filepath: string) => TResult} finder Function which reads a file and returns its imports
 * @param {string} filename File to start from; entry point
 * @returns {Generator<TResult, string[], string[]>} Generator yielding list of imports
 */
function* findAllImports(finder, filename) {
  // it doesn't matter if finder is sync or async!
  let specifiers = yield finder(filename);

  // pretend there's some de-duping, caching,
  // scrubbing, etc. happening here

  for (const specifier of specifiers) {
    // it's okay to be recursive
    specifiers = [...specifiers, ...(yield* findAllImports(finder, specifier))];
  }
  return specifiers;
}

// results are an array of all imports found in some.js' dependency tree
const asyncResult = await asyncTrampoline(
  findAllImports,
  findImports,
  './some.js',
);

// same thing, but synchronously
const syncResult = syncTrampoline(
  findAllImports,
  findImportsAsync,
  './some.js',
);

asyncResult === syncResult; // true
```

In the above example, **@endo/trampoline** allows us to re-use the operations in `loadRecursive()` for _both_ sync and async execution. An implementation _without_ **@endo/trampoline** would need to duplicate the operations into two (2) discrete recursive functions—a synchronous-colored function and an asynchronous-colored function. Over time, this situation commonly leads to diverging implementations. If that _doesn't_ sound like a big deal for _whatever you're trying to do here_, then you probably don't need **@endo/trampoline**.

## What is this?

The pattern exposed by this library—known as [trampolining][]—helps manage control flow in a way that avoids deep recursion and potential stack overflows.

**@endo/trampoline** provides the trampolining pattern, but in such a way that a consumer can execute _either_ synchronous _or_ asynchronous operations _paired with operations common to both_.

In other words, **@endo/trampoline** can help _reduce code duplication_ when operations must be executed _in both sync and async_ contexts.

## Install

The usual sort of thing:

```sh
npm install @endo/trampoline
```

## License

Apache-2.0

## Disclaimer

By using this library, you agree to indemnify and hold harmless the authors of `@endo/trampoline` from any and all losses, liabilities and risk of bodily injury _including but not limited to_ broken bones, sprains, bruises or other hematomas, fibromas, teratomas, mesotheliomas, cooties, bubonic plague, psychic trauma or warts due to the inherent danger of trampolining.

[trampolining]: https://raganwald.com/2013/03/28/trampolines-in-javascript.html

---
_Source: https://npm.io/package/@endo/trampoline · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
