npm package: @pleger/synccc
Description: Sync/cc-style callback flattening powered by AspectScript
Latest version: 0.1.0

# Synccc

[![npm version](https://img.shields.io/npm/v/@pleger/synccc.svg)](https://www.npmjs.com/package/@pleger/synccc)

`Synccc` is a modern Sync/cc-style package built on top of [AspectScript](https://github.com/pleger/aspectscript). It lets you write callback-based asynchronous flows in a sequential style.

This implementation follows the core idea from the paper: two aspects coordinate suspension/resumption around asynchronous operations and callback execution.

## Install

```bash
npm install @pleger/synccc
```

## Quick Start

```js
const AspectScript = require("aspectscript");
const Synccc = require("@pleger/synccc");

const runtime = AspectScript.createAspectScript(globalThis);
const synccc = new Synccc({ aspectScript: runtime });

const asyncRequest = synccc.setAsyncOperation(function asyncRequest(url, callback) {
  setTimeout(() => callback({ url, body: "ok" }), 20);
});

(async () => {
  const result = await synccc.run(() => {
    const a = asyncRequest("/book", function () {});
    const b = asyncRequest("/chapter/1", function () {});
    return [a, b];
  });

  console.log(result);
})();
```

## Paper-Style Example (Book Handler)

```js
const book = asyncRequest("book:1", function () {});
const chapters = book.chaptersURL.map((chapterURL) => asyncRequest(chapterURL, function () {}));
const images = chapters.map((chapter) => chapter.imagesURL.map((imageURL) => asyncRequest(imageURL, function () {})));
```

This works with `Synccc.run(...)` and preserves the left-to-right call order.

## API

### `new Synccc(options?)`

- `options.aspectScript`: AspectScript runtime instance (default: global AspectScript runtime)
- `options.asyncOperation`: optional async operation to register immediately

### `synccc.setAsyncOperation(fn, options?)`

Registers an asynchronous operation and returns a wrapped function.

Options:
- `callbackIndex` (default: `-1`): callback argument position
- `errorFirst` (default: `false`): Node-style `(err, value)` callback mode
- `responseIndex` (default: `0`, or `1` when `errorFirst: true`)
- `responseSelector(args)`: custom value extractor

### `await synccc.run(handler, ...args)`

Executes a synchronous-looking handler and resolves with its final value.

### `synccc.enable()` / `synccc.disable()`

Manually deploy/undeploy internal aspects.

## Tests

```bash
npm test
```

Current suite includes 16 tests covering:
- single and nested flows
- map-based paper example
- callback position customization
- error-first callbacks
- deterministic ordering
- call join point compatibility
- concurrency guardrails

## Browser Demo Website

Interactive demo is in [`docs/`](./docs).

Run locally:

```bash
npm run website:sync
cd docs
python3 -m http.server 4173
```

Then open `http://127.0.0.1:4173`.

## Citation

If you use this package in research, please cite:

> Continuations and Aspects to Tame Callback Hell on the Web. Paul Leger, Hiroaki Fukuda, Ismael Figueroa. Journal of Universal Computer Science, volume 27, number 9, pp.955-978, September 2021. DOI: https://doi.org/10.3897/jucs.72205

## License

MIT