@xstd/async-function 0.0.0-stage → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CONTRIBUTING.md +127 -0
  2. package/LICENSE +21 -0
  3. package/README.md +283 -2
  4. package/package.json +21 -3
  5. package/src/async-function.d.ts +154 -0
  6. package/src/async-function.js +231 -0
  7. package/src/async-function.js.map +1 -0
  8. package/src/index.d.ts +9 -0
  9. package/src/index.js +10 -0
  10. package/src/index.js.map +1 -0
  11. package/src/types/async-function-like.d.ts +3 -0
  12. package/src/types/async-function-like.js +3 -0
  13. package/src/types/async-function-like.js.map +1 -0
  14. package/src/types/call-async-function.d.ts +13 -0
  15. package/src/types/call-async-function.js +2 -0
  16. package/src/types/call-async-function.js.map +1 -0
  17. package/src/types/methods/map-arguments/map-function-arguments.d.ts +3 -0
  18. package/src/types/methods/map-arguments/map-function-arguments.js +2 -0
  19. package/src/types/methods/map-arguments/map-function-arguments.js.map +1 -0
  20. package/src/types/methods/share-concurent-calls/share-concurent-calls-options.d.ts +6 -0
  21. package/src/types/methods/share-concurent-calls/share-concurent-calls-options.js +2 -0
  22. package/src/types/methods/share-concurent-calls/share-concurent-calls-options.js.map +1 -0
  23. package/src/types/methods/then/async-function.then.on-fulfilled-function.d.ts +3 -0
  24. package/src/types/methods/then/async-function.then.on-fulfilled-function.js +2 -0
  25. package/src/types/methods/then/async-function.then.on-fulfilled-function.js.map +1 -0
  26. package/src/types/methods/then/async-function.then.on-rejected-function.d.ts +3 -0
  27. package/src/types/methods/then/async-function.then.on-rejected-function.js +2 -0
  28. package/src/types/methods/then/async-function.then.on-rejected-function.js.map +1 -0
  29. package/src/types/methods/then/default.async-function.then.on-fulfilled-function.private.d.ts +2 -0
  30. package/src/types/methods/then/default.async-function.then.on-fulfilled-function.private.js +3 -0
  31. package/src/types/methods/then/default.async-function.then.on-fulfilled-function.private.js.map +1 -0
  32. package/src/types/methods/then/default.async-function.then.on-rejected-function.private.d.ts +2 -0
  33. package/src/types/methods/then/default.async-function.then.on-rejected-function.private.js +5 -0
  34. package/src/types/methods/then/default.async-function.then.on-rejected-function.private.js.map +1 -0
  35. package/src/types/methods/transform/transform-async-function-function.d.ts +4 -0
  36. package/src/types/methods/transform/transform-async-function-function.js +2 -0
  37. package/src/types/methods/transform/transform-async-function-function.js.map +1 -0
  38. package/src/types/static-methods/from-send-and-receive/async-function-from-send-and-receive-options.d.ts +5 -0
  39. package/src/types/static-methods/from-send-and-receive/async-function-from-send-and-receive-options.js +2 -0
  40. package/src/types/static-methods/from-send-and-receive/async-function-from-send-and-receive-options.js.map +1 -0
@@ -0,0 +1,127 @@
1
+ # Contributing
2
+
3
+ This projet is open to everyone. Feel free to test the library, share it, improve it, and create merge requests.
4
+
5
+ ## Getting started
6
+
7
+ ### Tools
8
+
9
+ #### [nvm](https://github.com/nvm-sh/nvm)
10
+
11
+ We recommend using [nvm](https://github.com/nvm-sh/nvm) to manage your Node.js versions.
12
+
13
+ ```shell
14
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
15
+ ```
16
+
17
+ #### [Node](https://nodejs.org)
18
+
19
+ ```shell
20
+ nvm use
21
+
22
+ # Verify the Node.js version:
23
+ node -v
24
+ ```
25
+
26
+ #### [Yarn](https://yarnpkg.com)
27
+
28
+ ```shell
29
+ corepack enable yarn
30
+
31
+ # Verify Yarn version:
32
+ yarn -v
33
+
34
+ # Install the dependencies:
35
+ yarn install
36
+ ```
37
+
38
+ ### Code
39
+
40
+ - The source code is located in the `src` directory.
41
+ - The projet uses [prettier](https://prettier.io/) to format the code. You'll want to enable and configure it in your IDE.
42
+ - The tests run with [vitest](https://vitest.dev)
43
+
44
+ ### Commands
45
+
46
+ - `fb:build`: builds the library.
47
+ - converts the typescript files into javascript files, copies the scss files, and assembles all the assets to create a package ready to be published.
48
+ - some files are handled differently:
49
+ - `*.protected.{ts,scss}` or `**/*.protected/**`: these files are exported under `package-name/protected`
50
+ - this is indented to expose parts of the code that should be restricted to advanced users only, or shared to other libraries requiring _internal_ control.
51
+ - `*.private.{ts,scss}` or `/*.private/**`: these files are **not** exported.
52
+ - this is indented to consume parts of the code internally, and not expose them publicly.
53
+ - `fb:format`: formats the code using `prettier`.
54
+ - `fb:test`: runs the tests using `vitest`.
55
+ - `fb:test:coverage`: runs the tests with coverage.
56
+ - by default, 100% code coverage is required, to enforce good quality.
57
+ - `fb:bench`: runs the bench tests.
58
+ - `fb:typedoc`: generates the documentation.
59
+ - if the library exposes publicly only a few and/or simple parts, the documentation may be defined in the `README.md` instead.
60
+
61
+ ### To create a PR
62
+
63
+ 1. fork the repository
64
+ 1. add the feature/fix by modifying the code in the `src/` directory
65
+ 1. add/write some tests until 100% code coverage is reached (run the tests with `yarn fb:test:coverage`)
66
+ 1. format the code, using the command `yarn fb:format`
67
+ 1. commit and push your work following the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) convention
68
+ 1. create a PR from your repository to the upstream repository, explaining clearly what was added/fixed.
69
+
70
+ ## Release Workflow
71
+
72
+ > The `release.yml` workflow runs on `pull_request` and `push` events on the `main` and `develop` branches.
73
+ > It invokes the `yarn fb:ci:release` used to build and publish the package.
74
+ > Note that the `publish` step runs only if the equivalent stable version (`x.y.z`) does not already exist on npm
75
+
76
+ ### 1. Pull Request to `main` or `develop`
77
+
78
+ - The `dev` label is added to the PR
79
+ - Impacted packages are published as: `x.y.z-dev.<timestamp>`
80
+ - npm dist-tag: `dev`
81
+
82
+ > Use the `dev` versions only if required.
83
+
84
+ ### 2. Push to `develop`
85
+
86
+ - Impacted packages are published as: `x.y.z-rc.<timestamp>`
87
+ - npm dist-tag: `rc`
88
+
89
+ ### 3. Push to `main`
90
+
91
+ - Stable publication: `x.y.z`
92
+ - npm dist-tag: `latest`
93
+
94
+ ### Graph
95
+
96
+ ```mermaid
97
+ flowchart LR
98
+ EVENT("WORKFLOW TRIGGER")
99
+ HAS_DEV_TAG{"has &quotdev&quot tag ?"}
100
+ SKIP_BUILD(["skip build"])
101
+ BUILD_DEV_PACKAGES["build &quotdev&quot package"]
102
+ PUBLISH_DEV_PACKAGES["publish &quotdev&quot package"]
103
+ BUILD_RC_PACKAGES["build &quotrc&quot package"]
104
+ PUBLISH_RC_PACKAGES["publish &quotrc&quot package"]
105
+ BUILD_PROD_PACKAGES["build &quotprod&quot package"]
106
+ PUBLISH_PROD_PACKAGES["publish &quotprod&quot package"]
107
+ TARGET_BRANCH{"branch"}
108
+
109
+ EVENT -- "pull_request" --> HAS_DEV_TAG
110
+ HAS_DEV_TAG -- "no" --> SKIP_BUILD
111
+ HAS_DEV_TAG -- "yes" --> BUILD_DEV_PACKAGES
112
+ BUILD_DEV_PACKAGES --> PUBLISH_DEV_PACKAGES
113
+
114
+ EVENT -- "push" --> TARGET_BRANCH
115
+
116
+ TARGET_BRANCH -- "develop" --> BUILD_RC_PACKAGES
117
+ BUILD_RC_PACKAGES --> PUBLISH_RC_PACKAGES
118
+
119
+ TARGET_BRANCH -- "main" --> BUILD_PROD_PACKAGES
120
+ BUILD_PROD_PACKAGES --> PUBLISH_PROD_PACKAGES
121
+ ```
122
+
123
+ ## Important Rules
124
+
125
+ - if an equivalent **stable** version already exists on npm: the release is skipped
126
+ - the `package.json` file in the repo must keep stable versions (`x.y.z`)
127
+ - `-dev` / `-rc` suffixes are generated in CI
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2026 Valentin Richard
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
13
+ all 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
21
+ THE SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,284 @@
1
- # Temporary Holding Version
1
+ [![npm (scoped)](https://img.shields.io/npm/v/@xstd/async-function.svg)](https://www.npmjs.com/package/@xstd/async-function)
2
+ ![npm](https://img.shields.io/npm/dm/@xstd/async-function.svg)
3
+ ![NPM](https://img.shields.io/npm/l/@xstd/async-function.svg)
4
+ ![npm type definitions](https://img.shields.io/npm/types/@xstd/async-function.svg)
5
+ ![coverage](https://img.shields.io/badge/coverage-100%25-green)
6
+ ![AI generation](https://img.shields.io/badge/AI_generation-low-yellow)
2
7
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
8
+ <picture>
9
+ <source height="64" media="(prefers-color-scheme: dark)" srcset="https://github.com/xstd-js/website/blob/main/assets/logo/png/logo-large-dark.png?raw=true">
10
+ <source height="64" media="(prefers-color-scheme: light)" srcset="https://github.com/xstd-js/website/blob/main/assets/logo/png/logo-large-light.png?raw=true">
11
+ <img height="64" alt="Shows a black logo in light color mode and a white one in dark color mode." src="https://github.com/xstd-js/website/blob/main/assets/logo/png/logo-large-light.png?raw=true">
12
+ </picture>
13
+
14
+ ## @xstd/async-function
15
+
16
+ Universal API around async functions
17
+
18
+ ## 📦 Installation
19
+
20
+ ```shell
21
+ yarn add @xstd/async-function
22
+ # or
23
+ npm install @xstd/async-function --save
24
+ ```
25
+
26
+ ## 🚀 Usage
27
+
28
+ ```ts
29
+ import { AsyncFunction } from '@xstd/async-function';
30
+
31
+ const fetchJson = new AsyncFunction(async (signal, url: string) => {
32
+ const response = await fetch(url, { signal });
33
+ return response.json();
34
+ });
35
+
36
+ // transform the resolved value, like Promise.then, but it stays callable:
37
+ const fetchUser = fetchJson
38
+ .then((data) => (data as { user: unknown }).user)
39
+ .catch((error) => {
40
+ console.error(error);
41
+ return null;
42
+ });
43
+
44
+ // deduplicate concurrent calls for the same key:
45
+ const getUser = fetchUser.shareConcurentCalls({ keyGenerator: ([id]) => id as string });
46
+
47
+ const controller = new AbortController();
48
+ const user = await getUser.call(controller.signal, '42');
49
+
50
+ setTimeout(() => controller.abort(), 3000); // aborts the pending call
51
+ ```
52
+
53
+ ## 📜 Documentation
54
+
55
+ ### `AsyncFunction`
56
+
57
+ Represents an asynchronous and abortable function with configurable arguments and specific return value.
58
+
59
+ - **Type parameters**
60
+ - `GArguments extends readonly unknown[]` — The tuple type of arguments passed to the function.
61
+ - `GReturn` — The type of the return value.
62
+
63
+ Every call requires a leading `AbortSignal` argument, making the function abortable and composable.
64
+
65
+ ```ts
66
+ import { AsyncFunction } from '@xstd/async-function';
67
+
68
+ const fetchJson = new AsyncFunction(async (signal, url: string) => {
69
+ const response = await fetch(url, { signal });
70
+ return response.json();
71
+ });
72
+
73
+ const data = await fetchJson.call(new AbortController().signal, 'https://example.com/data.json');
74
+ ```
75
+
76
+ #### Constructor
77
+
78
+ ```ts
79
+ new AsyncFunction<GArguments, GReturn>(call: AsyncFunctionLike<GArguments, GReturn>)
80
+ ```
81
+
82
+ Creates an instance of the `AsyncFunction` class.
83
+
84
+ - **Parameters**
85
+ - `call: AsyncFunctionLike<GArguments, GReturn>` — A call function, or an existing `AsyncFunction`, which defines the action to perform on invocation. It receives the call's `AbortSignal` as first argument, followed by the call's arguments, and returns the result (or a promise of it). If an `AsyncFunction` is provided, its underlying call function is reused instead of being wrapped.
86
+
87
+ ```ts
88
+ // from a call function:
89
+ const fnc = new AsyncFunction(async (signal, url: string) => fetch(url, { signal }));
90
+
91
+ // from an existing AsyncFunction (reuses its underlying call function):
92
+ const copy = new AsyncFunction(fnc);
93
+ ```
94
+
95
+ #### Static methods
96
+
97
+ ##### `AsyncFunction.of`
98
+
99
+ ```ts
100
+ AsyncFunction.of<GArguments, GReturn>(input: AsyncFunctionLike<GArguments, GReturn>): AsyncFunction<GArguments, GReturn>
101
+ ```
102
+
103
+ Returns the given input if it is already an `AsyncFunction`, otherwise wraps it into a new `AsyncFunction` instance.
104
+
105
+ - **Parameters**
106
+ - `input: AsyncFunctionLike<GArguments, GReturn>` — An `AsyncFunction` instance or a plain call function to wrap.
107
+ - **Returns** The `AsyncFunction` instance corresponding to `input`.
108
+
109
+ ```ts
110
+ AsyncFunction.of(asyncFunction); // returns asyncFunction
111
+ AsyncFunction.of(async (signal) => 42); // returns a new AsyncFunction wrapping the function
112
+ ```
113
+
114
+ ##### `AsyncFunction.fromSendAndReceive`
115
+
116
+ ```ts
117
+ AsyncFunction.fromSendAndReceive<GArguments, GReturn>(
118
+ options: AsyncFunctionFromSendAndReceiveOptions<GArguments, GReturn>,
119
+ ): AsyncFunction<GArguments, GReturn>
120
+ ```
121
+
122
+ Creates an async function that concurrently triggers a "send" (push) operation and waits for a "receive" (pull) result, returning the received value once both complete. This is ideal for command-response, RPC, or event-driven patterns where you must initiate an action and await its corresponding outcome.
123
+
124
+ The returned async function is abortable — cancellation via `AbortSignal` will propagate to both the send and receive operations.
125
+
126
+ - **Parameters** `options` — Configuration object containing the send and receive async functions.
127
+ - `send: AsyncFunctionLike<GArguments, void>` — The "push" async function to trigger (e.g., sending a command or message). Must not return a value.
128
+ - `receive: AsyncFunctionLike<GArguments, GReturn>` — The "pull" async function to await (e.g., listening for a response or event). Returns the result.
129
+ - **Returns** An async function that, when called, returns a promise resolving to the value from `receive`. The promise is rejected if either operation fails or is aborted.
130
+
131
+ ```ts
132
+ const fnc = AsyncFunction.fromSendAndReceive({
133
+ send: new AsyncFunction((signal) => sendMessage('hello', { signal })),
134
+ receive: new AsyncFunction((signal) => waitForResponse({ signal })),
135
+ });
136
+
137
+ const result = await fnc.call(signal); // returns response from waitForResponse()
138
+ ```
139
+
140
+ ```ts
141
+ const controller = new AbortController();
142
+ const result = await fnc.call(controller.signal);
143
+ // cancel mid-operation:
144
+ controller.abort(); // both send and receive will be aborted.
145
+ ```
146
+
147
+ #### Instance methods
148
+
149
+ ##### `call`
150
+
151
+ ```ts
152
+ call(signal: AbortSignal, ...args: GArguments): Promise<GReturn>
153
+ ```
154
+
155
+ Executes the async function with the provided arguments and options.
156
+
157
+ - **Parameters**
158
+ - `signal: AbortSignal` — A signal to abort the action execution.
159
+ - `...args: GArguments` — The arguments to be provided to the async function.
160
+ - **Returns** A promise that resolves with the result of the async function.
161
+
162
+ ##### `transform`
163
+
164
+ ```ts
165
+ transform<GReturn>(transformFnc: TransformAsyncFunctionFunction<this, GReturn>): GReturn
166
+ ```
167
+
168
+ Applies a transformation function to the current instance and returns the result.
169
+
170
+ - **Parameters**
171
+ - `transformFnc` — A function that takes the current instance and returns a transformed value.
172
+ - **Returns** The result of applying the transformation function to the current instance.
173
+
174
+ ##### `mapArguments`
175
+
176
+ ```ts
177
+ mapArguments<GNewArguments extends readonly unknown[]>(
178
+ mapFnc: MapFunctionArguments<GArguments, GNewArguments>,
179
+ ): AsyncFunction<GNewArguments, GReturn>
180
+ ```
181
+
182
+ Maps and transforms the arguments of the current async function using the provided mapping function.
183
+
184
+ - **Type parameters**
185
+ - `GNewArguments` — The tuple type of the new arguments to be provided to the async function.
186
+ - **Parameters**
187
+ - `mapFnc` — A function that receives the arguments for the new async function and transforms them into arguments for the current async function.
188
+ - **Returns** A new async function instance that uses the specified mapping function to map its arguments.
189
+
190
+ ```ts
191
+ const fnc = new AsyncFunction(async (signal, a: number, b: number) => a + b);
192
+ const doubled = fnc.mapArguments(
193
+ (...args: [number]) => [args[0], args[0]] satisfies [number, number],
194
+ );
195
+ const result = await doubled.call(signal, 21); // 42
196
+ ```
197
+
198
+ ##### `then`
199
+
200
+ ```ts
201
+ then(onFulfilled?: undefined, onRejectedFunction?: undefined): AsyncFunction<GArguments, GReturn>
202
+ then<GNewReturn>(
203
+ onFulfilled: AsyncFunctionThenOnFulfilledFunction<GReturn, GNewReturn>,
204
+ onRejectedFunction?: AsyncFunctionThenOnRejectedFunction<GNewReturn> | undefined,
205
+ ): AsyncFunction<GArguments, GNewReturn>
206
+ then<GNewReturn>(
207
+ onFulfilled: undefined,
208
+ onRejectedFunction: AsyncFunctionThenOnRejectedFunction<GNewReturn>,
209
+ ): AsyncFunction<GArguments, GReturn | GNewReturn>
210
+ ```
211
+
212
+ Chains handlers on the outcome of this async function, like `Promise.then`, but returns a new `AsyncFunction` instead of a `Promise`.
213
+
214
+ The handlers are applied on each call of the returned async function. The `AbortSignal` received by the call is forwarded to `onFulfilled` and `onRejectedFunction`. If no handler is provided, the value or error is passed through unchanged.
215
+
216
+ - **Type parameters**
217
+ - `GNewReturn` — The new type of the return value.
218
+ - **Parameters**
219
+ - `onFulfilled` — A function invoked with the resolved value and the call's `AbortSignal`, returning the new value (or a promise of it).
220
+ - `onRejectedFunction` — A function invoked with the thrown error and the call's `AbortSignal`, returning a fallback value (or a promise of it). Defaults to re-throwing the error.
221
+ - **Returns** A new async function resolving with the transformed value.
222
+
223
+ ```ts
224
+ const fnc = new AsyncFunction(async (signal, url: string) => fetch(url, { signal }));
225
+ const status = fnc.then((response) => response.status);
226
+
227
+ const result = await status.call(signal, 'https://example.com'); // e.g. 200
228
+ ```
229
+
230
+ ##### `catch`
231
+
232
+ ```ts
233
+ catch(onRejectedFunction?: undefined): AsyncFunction<GArguments, GReturn>
234
+ catch<GNewReturn>(
235
+ onRejectedFunction: AsyncFunctionThenOnRejectedFunction<GNewReturn>,
236
+ ): AsyncFunction<GArguments, GReturn | GNewReturn>
237
+ ```
238
+
239
+ Handles the errors thrown by this async function, like `Promise.catch`, but returns a new `AsyncFunction` instead of a `Promise`.
240
+
241
+ The rejection handler is applied on each call of the returned async function. The `AbortSignal` received by the call is forwarded to `onRejectedFunction`. The resolved values are passed through unchanged.
242
+
243
+ - **Type parameters**
244
+ - `GNewReturn` — The new type of the return value in case of error.
245
+ - **Parameters**
246
+ - `onRejectedFunction` — A function invoked with the thrown error and the call's `AbortSignal`, returning a fallback value (or a promise of it). If `undefined`, errors are passed through unchanged.
247
+ - **Returns** A new async function resolving with the original value, or the fallback value when an error occurs.
248
+
249
+ ```ts
250
+ const fnc = new AsyncFunction(async (signal) => fetch('https://example.com', { signal }));
251
+ const safe = fnc.catch((error) => null);
252
+
253
+ const result = await safe.call(signal); // Response, or null if the request failed
254
+ ```
255
+
256
+ ##### `shareConcurentCalls` (experimental)
257
+
258
+ ```ts
259
+ shareConcurentCalls(options: ShareConcurentCallsOptions<GArguments>): AsyncFunction<GArguments, GReturn>
260
+ ```
261
+
262
+ Returns a new async function that deduplicates concurrent calls sharing the same key: while a call is in-flight, subsequent calls with the same key await the same underlying promise instead of triggering a new call.
263
+
264
+ The first call starts the underlying call with its own `AbortController`. Each caller may abort its own wait without affecting the shared call. When the last consumer settles, the shared controller is aborted, the entry is removed, and a subsequent call starts a new one.
265
+
266
+ - **Parameters** `options` — Configuration object.
267
+ - `keyGenerator: (args: GArguments) => string` — A function that generates a cache key from the call's arguments. Calls producing the same key share their result.
268
+ - **Returns** A new async function sharing concurrent calls with identical keys.
269
+
270
+ ```ts
271
+ const loadUser = new AsyncFunction(async (signal, id: string) =>
272
+ fetchUser(id, { signal }),
273
+ ).shareConcurentCalls({ keyGenerator: ([id]) => id });
274
+
275
+ // 'fetchUser' is called once, both calls await the same result:
276
+ const [a, b] = await Promise.all([loadUser.call(signal, 'a'), loadUser.call(signal, 'a')]);
277
+ ```
278
+
279
+ #### Types
280
+
281
+ | Type | Description |
282
+ | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
283
+ | `CallAsyncFunction<GArguments, GReturn>` | `(signal: AbortSignal, ...args: GArguments) => PromiseLike<GReturn> \| GReturn` — the shape of the underlying call function. |
284
+ | `AsyncFunctionLike<GArguments, GReturn>` | `AsyncFunction<GArguments, GReturn> \| CallAsyncFunction<GArguments, GReturn>` — accepted by the constructor, `of` and `fromSendAndReceive`. |
package/package.json CHANGED
@@ -1,6 +1,24 @@
1
1
  {
2
2
  "name": "@xstd/async-function",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "1.1.0",
4
+ "type": "module",
5
+ "description": "Universal API around async functions",
6
+ "keywords": [],
7
+ "author": "Valentin Richard",
8
+ "license": "MIT",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/xstd-js/async-function.git"
12
+ },
13
+ "main": "./src/index.js",
14
+ "types": "./src/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./src/index.d.ts",
18
+ "default": "./src/index.js"
19
+ }
20
+ },
21
+ "dependencies": {
22
+ "@xstd/abortable": "^1.2.3"
23
+ }
6
24
  }
@@ -0,0 +1,154 @@
1
+ import { type AsyncFunctionLike } from './types/async-function-like.ts';
2
+ import { type MapFunctionArguments } from './types/methods/map-arguments/map-function-arguments.ts';
3
+ import { type ShareConcurentCallsOptions } from './types/methods/share-concurent-calls/share-concurent-calls-options.js';
4
+ import { type AsyncFunctionThenOnFulfilledFunction } from './types/methods/then/async-function.then.on-fulfilled-function.ts';
5
+ import { type AsyncFunctionThenOnRejectedFunction } from './types/methods/then/async-function.then.on-rejected-function.ts';
6
+ import { type TransformAsyncFunctionFunction } from './types/methods/transform/transform-async-function-function.ts';
7
+ import { type AsyncFunctionFromSendAndReceiveOptions } from './types/static-methods/from-send-and-receive/async-function-from-send-and-receive-options.ts';
8
+ /**
9
+ * Represents an asynchronous and abortable function with configurable arguments and specific return value.
10
+ *
11
+ * @template GArguments The tuple type of arguments passed to the function.
12
+ * @template GReturn The type of the return value.
13
+ */
14
+ export declare class AsyncFunction<GArguments extends readonly unknown[], GReturn> {
15
+ #private;
16
+ /**
17
+ * Returns the given input if it is already an `AsyncFunction`, otherwise wraps it into a new `AsyncFunction` instance.
18
+ *
19
+ * @template GArguments The tuple type of arguments passed to the function.
20
+ * @template GReturn The type of the return value.
21
+ * @param {AsyncFunctionLike<GArguments, GReturn>} input An `AsyncFunction` instance or a plain call function to wrap.
22
+ * @returns {AsyncFunction<GArguments, GReturn>} The `AsyncFunction` instance corresponding to `input`.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * AsyncFunction.of(asyncFunction); // returns asyncFunction
27
+ * AsyncFunction.of(async (signal) => 42); // returns a new AsyncFunction wrapping the function
28
+ * ```
29
+ */
30
+ static of<GArguments extends readonly unknown[], GReturn>(input: AsyncFunctionLike<GArguments, GReturn>): AsyncFunction<GArguments, GReturn>;
31
+ /**
32
+ * Creates an async function that concurrently triggers a "send" (push) operation and waits for a "receive" (pull) result,
33
+ * returning the received value once both complete. This is ideal for command-response, RPC, or event-driven patterns
34
+ * where you must initiate an action and await its corresponding outcome.
35
+ *
36
+ * The returned async function is abortable - cancellation via `AbortSignal` will propagate to both the send and receive operations.
37
+ *
38
+ * @template GArguments The tuple type of arguments passed to the send and receive async functions.
39
+ * @template GReturn The type of value returned by the receive operation.
40
+ * @param {AsyncFunctionFromSendAndReceiveOptions<GReturn>} options Configuration object containing the send and receive async functions.
41
+ * @param {AsyncFunction<GArguments, void>} options.send The "push" async function to trigger (e.g., sending a command or message). Must not return a value.
42
+ * @param {AsyncFunction<GArguments, GReturn>} options.receive The "pull" async function to await (e.g., listening for a response or event). Returns the result.
43
+ * @returns {AsyncFunction<GArguments, GReturn>} An async function that, when called, returns a promise resolving to the value from `receive`.
44
+ * The promise is rejected if either operation fails or is aborted.
45
+ *
46
+ * @example
47
+ *
48
+ * ```ts
49
+ * const fnc = AsyncFunction.fromSendAndReceive({
50
+ * send: new AsyncFunction((signal) => sendMessage("hello", { signal })),
51
+ * receive: new AsyncFunction((signal) => waitForResponse({ signal ))
52
+ * });
53
+ *
54
+ * const result = await fnc.call(signal); // returns response from waitForResponse()
55
+ * ```
56
+ *
57
+ * @example with abortion
58
+ *
59
+ * ```ts
60
+ * const controller = new AbortController();
61
+ * const result = await fnc.call(controller.signal);
62
+ * // cancel mid-operation:
63
+ * controller.abort(); // both send and receive will be aborted.
64
+ * ```
65
+ */
66
+ static fromSendAndReceive<GArguments extends readonly unknown[], GReturn>({ send, receive, }: AsyncFunctionFromSendAndReceiveOptions<GArguments, GReturn>): AsyncFunction<GArguments, GReturn>;
67
+ /**
68
+ * Creates an instance of the `AsyncFunction` class.
69
+ *
70
+ * @param {AsyncFunctionLike<GArguments, GReturn>} call A call function, or an existing `AsyncFunction`, to be invoked, which defines the action to perform on invocation. If an `AsyncFunction` is provided, its underlying call function is reused instead of being wrapped.
71
+ */
72
+ constructor(call: AsyncFunctionLike<GArguments, GReturn>);
73
+ /**
74
+ * Executes the specified async function with the provided arguments and options.
75
+ *
76
+ * @param {AbortSignal} signal A signal to abort the action execution.
77
+ * @param {...GArguments} args The arguments to be provided to the async function.
78
+ * @return {Promise<GReturn>} A promise that resolves with the result of the async function.
79
+ */
80
+ call(signal: AbortSignal, ...args: GArguments): Promise<GReturn>;
81
+ /**
82
+ * Applies a transformation function to the current instance and returns the result.
83
+ *
84
+ * @param {TransformAsyncFunctionFunction<this, GReturn>} transformFnc A function that takes the current instance and returns a transformed value.
85
+ * @return {GReturn} The result of applying the transformation function to the current instance.
86
+ */
87
+ transform<GReturn>(transformFnc: TransformAsyncFunctionFunction<this, GReturn>): GReturn;
88
+ /**
89
+ * Maps and transforms the arguments of the current async function using the provided mapping function.
90
+ *
91
+ * @template GNewArguments The tuple type of the new arguments to be provided to the async function.
92
+ * @param {MapFunctionArguments<GArguments, GNewArguments>} mapFnc A function that receives the arguments for the new async function and transforms them into arguments for the current async function.
93
+ * @return {AsyncFunction<GNewArguments, GReturn>} A new async function instance that uses the specified mapping function to map its arguments.
94
+ */
95
+ mapArguments<GNewArguments extends readonly unknown[]>(mapFnc: MapFunctionArguments<GArguments, GNewArguments>): AsyncFunction<GNewArguments, GReturn>;
96
+ /**
97
+ * Creates a new async function with the same behaviour as this one (neither a fulfilment nor a rejection handler provided).
98
+ *
99
+ * @returns {AsyncFunction<GArguments, GReturn>} A new async function equivalent to this one.
100
+ */
101
+ then(onFulfilled?: undefined, onRejectedFunction?: undefined): AsyncFunction<GArguments, GReturn>;
102
+ /**
103
+ * Transforms the resolved value of this async function, and optionally handles its errors.
104
+ *
105
+ * @template GNewReturn The new type of the return value.
106
+ * @param {AsyncFunctionThenOnFulfilledFunction<GReturn, GNewReturn>} onFulfilled A function invoked with the resolved value and the call's `AbortSignal`, returning the new value (or a promise of it).
107
+ * @param {AsyncFunctionThenOnRejectedFunction<GNewReturn>} onRejectedFunction An optional function invoked with the thrown error and the call's `AbortSignal`, returning a fallback value (or a promise of it). Defaults to re-throwing the error.
108
+ * @returns {AsyncFunction<GArguments, GNewReturn>} A new async function resolving with the transformed value.
109
+ */
110
+ then<GNewReturn>(onFulfilled: AsyncFunctionThenOnFulfilledFunction<GReturn, GNewReturn>, onRejectedFunction?: AsyncFunctionThenOnRejectedFunction<GNewReturn> | undefined): AsyncFunction<GArguments, GNewReturn>;
111
+ /**
112
+ * Handles the errors thrown by this async function without transforming its resolved value.
113
+ *
114
+ * @template GNewReturn The new type of the return value in case of error.
115
+ * @param {undefined} onFulfilled Must be left `undefined`.
116
+ * @param {AsyncFunctionThenOnRejectedFunction<GNewReturn>} onRejectedFunction A function invoked with the thrown error and the call's `AbortSignal`, returning a fallback value (or a promise of it).
117
+ * @returns {AsyncFunction<GArguments, GReturn | GNewReturn>} A new async function resolving with the original value, or the fallback value when an error occurs.
118
+ */
119
+ then<GNewReturn>(onFulfilled: undefined, onRejectedFunction: AsyncFunctionThenOnRejectedFunction<GNewReturn>): AsyncFunction<GArguments, GReturn | GNewReturn>;
120
+ /**
121
+ * Creates a new async function with the same behaviour as this one (no rejection handler provided).
122
+ *
123
+ * @returns {AsyncFunction<GArguments, GReturn>} A new async function equivalent to this one.
124
+ */
125
+ catch(onRejectedFunction?: undefined): AsyncFunction<GArguments, GReturn>;
126
+ /**
127
+ * Handles the errors thrown by this async function, like `Promise.catch`, but returns a new `AsyncFunction` instead of a `Promise`.
128
+ *
129
+ * @template GNewReturn The new type of the return value in case of error.
130
+ * @param {AsyncFunctionThenOnRejectedFunction<GNewReturn>} onRejectedFunction A function invoked with the thrown error and the call's `AbortSignal`, returning a fallback value (or a promise of it).
131
+ * @returns {AsyncFunction<GArguments, GReturn | GNewReturn>} A new async function resolving with the original value, or the fallback value when an error occurs.
132
+ */
133
+ catch<GNewReturn>(onRejectedFunction: AsyncFunctionThenOnRejectedFunction<GNewReturn>): AsyncFunction<GArguments, GReturn | GNewReturn>;
134
+ /**
135
+ * Returns a new async function that deduplicates concurrent calls sharing the same key: while a call is in-flight, subsequent calls with the same key await the same underlying promise instead of triggering a new call.
136
+ *
137
+ * The first call starts the underlying call with its own `AbortController`. Each caller may abort its own wait without affecting the shared call. When the last consumer settles, the shared controller is aborted, the entry is removed, and a subsequent call starts a new one.
138
+ *
139
+ * @experimental
140
+ * @param {ShareConcurentCallsOptions<GArguments>} options Configuration object.
141
+ * @param {ShareConcurentCallsKeyGenerator<GArguments>} options.keyGenerator A function that generates a cache key from the call's arguments. Calls producing the same key share their result.
142
+ * @returns {AsyncFunction<GArguments, GReturn>} A new async function sharing concurrent calls with identical keys.
143
+ *
144
+ * @example
145
+ * ```ts
146
+ * const loadUser = new AsyncFunction(async (signal, id: string) => fetchUser(id, { signal }))
147
+ * .shareConcurentCalls({ keyGenerator: ([id]) => id });
148
+ *
149
+ * // 'fetchUser' is called once, both calls await the same result:
150
+ * const [a, b] = await Promise.all([loadUser.call(signal, 'a'), loadUser.call(signal, 'a')]);
151
+ * ```
152
+ */
153
+ shareConcurentCalls({ keyGenerator, }: ShareConcurentCallsOptions<GArguments>): AsyncFunction<GArguments, GReturn>;
154
+ }
@@ -0,0 +1,231 @@
1
+ import { abortify } from '@xstd/abortable';
2
+ import {} from './types/async-function-like.js';
3
+ import {} from './types/call-async-function.js';
4
+ import {} from './types/methods/map-arguments/map-function-arguments.js';
5
+ import {} from './types/methods/share-concurent-calls/share-concurent-calls-options.js';
6
+ import {} from './types/methods/then/async-function.then.on-fulfilled-function.js';
7
+ import {} from './types/methods/then/async-function.then.on-rejected-function.js';
8
+ import { DEFAULT_ASYNC_FUNCTION_THEN_ON_FULFILLED_FUNCTION } from './types/methods/then/default.async-function.then.on-fulfilled-function.private.js';
9
+ import { DEFAULT_ASYNC_FUNCTION_THEN_ON_REJECTED_FUNCTION } from './types/methods/then/default.async-function.then.on-rejected-function.private.js';
10
+ import {} from './types/methods/transform/transform-async-function-function.js';
11
+ import {} from './types/static-methods/from-send-and-receive/async-function-from-send-and-receive-options.js';
12
+ /**
13
+ * Represents an asynchronous and abortable function with configurable arguments and specific return value.
14
+ *
15
+ * @template GArguments The tuple type of arguments passed to the function.
16
+ * @template GReturn The type of the return value.
17
+ */
18
+ export class AsyncFunction {
19
+ /**
20
+ * Returns the given input if it is already an `AsyncFunction`, otherwise wraps it into a new `AsyncFunction` instance.
21
+ *
22
+ * @template GArguments The tuple type of arguments passed to the function.
23
+ * @template GReturn The type of the return value.
24
+ * @param {AsyncFunctionLike<GArguments, GReturn>} input An `AsyncFunction` instance or a plain call function to wrap.
25
+ * @returns {AsyncFunction<GArguments, GReturn>} The `AsyncFunction` instance corresponding to `input`.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * AsyncFunction.of(asyncFunction); // returns asyncFunction
30
+ * AsyncFunction.of(async (signal) => 42); // returns a new AsyncFunction wrapping the function
31
+ * ```
32
+ */
33
+ static of(input) {
34
+ return input instanceof AsyncFunction ? input : new AsyncFunction(input);
35
+ }
36
+ /**
37
+ * Creates an async function that concurrently triggers a "send" (push) operation and waits for a "receive" (pull) result,
38
+ * returning the received value once both complete. This is ideal for command-response, RPC, or event-driven patterns
39
+ * where you must initiate an action and await its corresponding outcome.
40
+ *
41
+ * The returned async function is abortable - cancellation via `AbortSignal` will propagate to both the send and receive operations.
42
+ *
43
+ * @template GArguments The tuple type of arguments passed to the send and receive async functions.
44
+ * @template GReturn The type of value returned by the receive operation.
45
+ * @param {AsyncFunctionFromSendAndReceiveOptions<GReturn>} options Configuration object containing the send and receive async functions.
46
+ * @param {AsyncFunction<GArguments, void>} options.send The "push" async function to trigger (e.g., sending a command or message). Must not return a value.
47
+ * @param {AsyncFunction<GArguments, GReturn>} options.receive The "pull" async function to await (e.g., listening for a response or event). Returns the result.
48
+ * @returns {AsyncFunction<GArguments, GReturn>} An async function that, when called, returns a promise resolving to the value from `receive`.
49
+ * The promise is rejected if either operation fails or is aborted.
50
+ *
51
+ * @example
52
+ *
53
+ * ```ts
54
+ * const fnc = AsyncFunction.fromSendAndReceive({
55
+ * send: new AsyncFunction((signal) => sendMessage("hello", { signal })),
56
+ * receive: new AsyncFunction((signal) => waitForResponse({ signal ))
57
+ * });
58
+ *
59
+ * const result = await fnc.call(signal); // returns response from waitForResponse()
60
+ * ```
61
+ *
62
+ * @example with abortion
63
+ *
64
+ * ```ts
65
+ * const controller = new AbortController();
66
+ * const result = await fnc.call(controller.signal);
67
+ * // cancel mid-operation:
68
+ * controller.abort(); // both send and receive will be aborted.
69
+ * ```
70
+ */
71
+ static fromSendAndReceive({ send, receive, }) {
72
+ send = AsyncFunction.of(send);
73
+ receive = AsyncFunction.of(receive);
74
+ return new AsyncFunction(async (signal, ...args) => {
75
+ const controller = new AbortController();
76
+ const sharedSignal = AbortSignal.any([signal, controller.signal]);
77
+ try {
78
+ return (await Promise.all([
79
+ receive.#call(sharedSignal, ...args),
80
+ send.#call(sharedSignal, ...args),
81
+ ]))[0];
82
+ }
83
+ finally {
84
+ controller.abort();
85
+ }
86
+ });
87
+ }
88
+ /**
89
+ * The underlying call function invoked when this async function is called.
90
+ */
91
+ #call;
92
+ /**
93
+ * Creates an instance of the `AsyncFunction` class.
94
+ *
95
+ * @param {AsyncFunctionLike<GArguments, GReturn>} call A call function, or an existing `AsyncFunction`, to be invoked, which defines the action to perform on invocation. If an `AsyncFunction` is provided, its underlying call function is reused instead of being wrapped.
96
+ */
97
+ constructor(call) {
98
+ this.#call = call instanceof AsyncFunction ? call.#call : call;
99
+ }
100
+ /**
101
+ * Executes the specified async function with the provided arguments and options.
102
+ *
103
+ * @param {AbortSignal} signal A signal to abort the action execution.
104
+ * @param {...GArguments} args The arguments to be provided to the async function.
105
+ * @return {Promise<GReturn>} A promise that resolves with the result of the async function.
106
+ */
107
+ call(signal, ...args) {
108
+ return Promise.try(this.#call, signal, ...args);
109
+ }
110
+ /* TRANSFORM */
111
+ /**
112
+ * Applies a transformation function to the current instance and returns the result.
113
+ *
114
+ * @param {TransformAsyncFunctionFunction<this, GReturn>} transformFnc A function that takes the current instance and returns a transformed value.
115
+ * @return {GReturn} The result of applying the transformation function to the current instance.
116
+ */
117
+ transform(transformFnc) {
118
+ return transformFnc(this);
119
+ }
120
+ /* ARGUMENTS BASED */
121
+ /**
122
+ * Maps and transforms the arguments of the current async function using the provided mapping function.
123
+ *
124
+ * @template GNewArguments The tuple type of the new arguments to be provided to the async function.
125
+ * @param {MapFunctionArguments<GArguments, GNewArguments>} mapFnc A function that receives the arguments for the new async function and transforms them into arguments for the current async function.
126
+ * @return {AsyncFunction<GNewArguments, GReturn>} A new async function instance that uses the specified mapping function to map its arguments.
127
+ */
128
+ mapArguments(mapFnc) {
129
+ return new AsyncFunction((signal, ...args) => {
130
+ return this.#call(signal, ...mapFnc(...args));
131
+ });
132
+ }
133
+ /**
134
+ * Chains handlers on the outcome of this async function, like `Promise.then`, but returns a new `AsyncFunction` instead of a `Promise`.
135
+ *
136
+ * The handlers are applied on each call of the returned async function. The `AbortSignal` received by the call is forwarded to `onFulfilled` and `onRejectedFunction`. If no handler is provided, the value or error is passed through unchanged.
137
+ *
138
+ * @template GNewReturn The new type of the return value.
139
+ * @param {AsyncFunctionThenOnFulfilledFunction<GReturn, GNewReturn> | undefined} onFulfilled A function invoked with the resolved value and the call's `AbortSignal`, returning the new value (or a promise of it).
140
+ * @param {AsyncFunctionThenOnRejectedFunction<GNewReturn> | undefined} onRejectedFunction A function invoked with the thrown error and the call's `AbortSignal`, returning a fallback value (or a promise of it).
141
+ * @returns {AsyncFunction<GArguments, GNewReturn>} A new async function resolving with the transformed value.
142
+ *
143
+ * @example
144
+ * ```ts
145
+ * const fnc = new AsyncFunction(async (signal, url: string) => fetch(url, { signal }));
146
+ * const status = fnc.then((response) => response.status);
147
+ *
148
+ * const result = await status.call(signal, 'https://example.com'); // e.g. 200
149
+ * ```
150
+ */
151
+ then(onFulfilled = DEFAULT_ASYNC_FUNCTION_THEN_ON_FULFILLED_FUNCTION, onRejectedFunction = DEFAULT_ASYNC_FUNCTION_THEN_ON_REJECTED_FUNCTION) {
152
+ return new AsyncFunction((signal, ...args) => {
153
+ return this.call(signal, ...args).then((value) => {
154
+ return onFulfilled(value, signal);
155
+ }, (error) => {
156
+ return onRejectedFunction(error, signal);
157
+ });
158
+ });
159
+ }
160
+ /**
161
+ * Handles the errors thrown by this async function, like `Promise.catch`, but returns a new `AsyncFunction` instead of a `Promise`.
162
+ *
163
+ * The rejection handler is applied on each call of the returned async function. The `AbortSignal` received by the call is forwarded to `onRejectedFunction`. The resolved values are passed through unchanged.
164
+ *
165
+ * @template GNewReturn The new type of the return value in case of error.
166
+ * @param {AsyncFunctionThenOnRejectedFunction<GNewReturn> | undefined} onRejectedFunction A function invoked with the thrown error and the call's `AbortSignal`, returning a fallback value (or a promise of it). If `undefined`, errors are passed through unchanged.
167
+ * @returns {AsyncFunction<GArguments, GReturn | GNewReturn>} A new async function resolving with the original value, or the fallback value when an error occurs.
168
+ *
169
+ * @example
170
+ * ```ts
171
+ * const fnc = new AsyncFunction(async (signal) => fetch('https://example.com', { signal }));
172
+ * const safe = fnc.catch((error) => null);
173
+ *
174
+ * const result = await safe.call(signal); // Response, or null if the request failed
175
+ * ```
176
+ */
177
+ catch(onRejectedFunction) {
178
+ return this.then(undefined, onRejectedFunction);
179
+ }
180
+ /* CONCURRENT */
181
+ /**
182
+ * Returns a new async function that deduplicates concurrent calls sharing the same key: while a call is in-flight, subsequent calls with the same key await the same underlying promise instead of triggering a new call.
183
+ *
184
+ * The first call starts the underlying call with its own `AbortController`. Each caller may abort its own wait without affecting the shared call. When the last consumer settles, the shared controller is aborted, the entry is removed, and a subsequent call starts a new one.
185
+ *
186
+ * @experimental
187
+ * @param {ShareConcurentCallsOptions<GArguments>} options Configuration object.
188
+ * @param {ShareConcurentCallsKeyGenerator<GArguments>} options.keyGenerator A function that generates a cache key from the call's arguments. Calls producing the same key share their result.
189
+ * @returns {AsyncFunction<GArguments, GReturn>} A new async function sharing concurrent calls with identical keys.
190
+ *
191
+ * @example
192
+ * ```ts
193
+ * const loadUser = new AsyncFunction(async (signal, id: string) => fetchUser(id, { signal }))
194
+ * .shareConcurentCalls({ keyGenerator: ([id]) => id });
195
+ *
196
+ * // 'fetchUser' is called once, both calls await the same result:
197
+ * const [a, b] = await Promise.all([loadUser.call(signal, 'a'), loadUser.call(signal, 'a')]);
198
+ * ```
199
+ */
200
+ shareConcurentCalls({ keyGenerator, }) {
201
+ const map = new Map();
202
+ return new AsyncFunction(async (signal, ...args) => {
203
+ signal.throwIfAborted();
204
+ const key = keyGenerator(args);
205
+ let entry = map.get(key);
206
+ if (entry === undefined) {
207
+ const controller = new AbortController();
208
+ entry = {
209
+ controller,
210
+ promise: this.call(controller.signal, ...args),
211
+ consumers: 1,
212
+ };
213
+ map.set(key, entry);
214
+ }
215
+ else {
216
+ entry.consumers++;
217
+ }
218
+ try {
219
+ return await abortify(entry.promise, { signal });
220
+ }
221
+ finally {
222
+ entry.consumers--;
223
+ if (entry.consumers === 0) {
224
+ entry.controller.abort();
225
+ map.delete(key);
226
+ }
227
+ }
228
+ });
229
+ }
230
+ }
231
+ //# sourceMappingURL=async-function.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async-function.js","sourceRoot":"","sources":["../../src/async-function.ts"],"names":[],"mappings":"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"}
package/src/index.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export * from './async-function.ts';
2
+ export * from './types/async-function-like.ts';
3
+ export * from './types/call-async-function.ts';
4
+ export * from './types/static-methods/from-send-and-receive/async-function-from-send-and-receive-options.ts';
5
+ export * from './types/methods/transform/transform-async-function-function.ts';
6
+ export * from './types/methods/then/async-function.then.on-fulfilled-function.ts';
7
+ export * from './types/methods/then/async-function.then.on-rejected-function.ts';
8
+ export * from './types/methods/share-concurent-calls/share-concurent-calls-options.ts';
9
+ export * from './types/methods/map-arguments/map-function-arguments.ts';
package/src/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export * from './async-function.js';
2
+ export * from './types/async-function-like.js';
3
+ export * from './types/call-async-function.js';
4
+ export * from './types/static-methods/from-send-and-receive/async-function-from-send-and-receive-options.js';
5
+ export * from './types/methods/transform/transform-async-function-function.js';
6
+ export * from './types/methods/then/async-function.then.on-fulfilled-function.js';
7
+ export * from './types/methods/then/async-function.then.on-rejected-function.js';
8
+ export * from './types/methods/share-concurent-calls/share-concurent-calls-options.js';
9
+ export * from './types/methods/map-arguments/map-function-arguments.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8FAA8F,CAAC;AAC7G,cAAc,gEAAgE,CAAC;AAC/E,cAAc,mEAAmE,CAAC;AAClF,cAAc,kEAAkE,CAAC;AACjF,cAAc,wEAAwE,CAAC;AACvF,cAAc,yDAAyD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type AsyncFunction } from '../async-function.ts';
2
+ import { type CallAsyncFunction } from './call-async-function.ts';
3
+ export type AsyncFunctionLike<GArguments extends readonly unknown[], GReturn> = AsyncFunction<GArguments, GReturn> | CallAsyncFunction<GArguments, GReturn>;
@@ -0,0 +1,3 @@
1
+ import {} from '../async-function.js';
2
+ import {} from './call-async-function.js';
3
+ //# sourceMappingURL=async-function-like.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async-function-like.js","sourceRoot":"","sources":["../../../src/types/async-function-like.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAA0B,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Represents an interface for calling an async function with specific arguments and result.
3
+ *
4
+ * @template GArguments The tuple type representing the arguments to be provided to the function.
5
+ * @template GReturn The type of the value returned by the async function.
6
+ *
7
+ * @param {AbortSignal} signal A signal to abort the async function execution.
8
+ * @param {...GArguments} args The arguments to be provided to the function.
9
+ * @returns {PromiseLike<GReturn> | GReturn} The result of the async function execution, which can be either a resolved value or a Promise-like object resolving the value.
10
+ */
11
+ export interface CallAsyncFunction<GArguments extends readonly unknown[], GReturn> {
12
+ (signal: AbortSignal, ...args: GArguments): PromiseLike<GReturn> | GReturn;
13
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=call-async-function.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-async-function.js","sourceRoot":"","sources":["../../../src/types/call-async-function.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export interface MapFunctionArguments<GArguments extends readonly unknown[], GNewArguments extends readonly unknown[]> {
2
+ (...args: GNewArguments): GArguments;
3
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=map-function-arguments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map-function-arguments.js","sourceRoot":"","sources":["../../../../../src/types/methods/map-arguments/map-function-arguments.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ export interface ShareConcurentCallsOptions<GArguments extends readonly unknown[]> {
2
+ readonly keyGenerator: ShareConcurentCallsKeyGenerator<GArguments>;
3
+ }
4
+ export interface ShareConcurentCallsKeyGenerator<GArguments extends readonly unknown[]> {
5
+ (args: GArguments): string;
6
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=share-concurent-calls-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"share-concurent-calls-options.js","sourceRoot":"","sources":["../../../../../src/types/methods/share-concurent-calls/share-concurent-calls-options.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export interface AsyncFunctionThenOnFulfilledFunction<GReturn, GNewReturn> {
2
+ (value: GReturn, signal: AbortSignal): PromiseLike<GNewReturn> | GNewReturn;
3
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=async-function.then.on-fulfilled-function.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async-function.then.on-fulfilled-function.js","sourceRoot":"","sources":["../../../../../src/types/methods/then/async-function.then.on-fulfilled-function.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export interface AsyncFunctionThenOnRejectedFunction<GNewReturn> {
2
+ (error: unknown, signal: AbortSignal): PromiseLike<GNewReturn> | GNewReturn;
3
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=async-function.then.on-rejected-function.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async-function.then.on-rejected-function.js","sourceRoot":"","sources":["../../../../../src/types/methods/then/async-function.then.on-rejected-function.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ import { type AsyncFunctionThenOnFulfilledFunction } from './async-function.then.on-fulfilled-function.ts';
2
+ export declare const DEFAULT_ASYNC_FUNCTION_THEN_ON_FULFILLED_FUNCTION: AsyncFunctionThenOnFulfilledFunction<any, any>;
@@ -0,0 +1,3 @@
1
+ import {} from './async-function.then.on-fulfilled-function.js';
2
+ export const DEFAULT_ASYNC_FUNCTION_THEN_ON_FULFILLED_FUNCTION = (value) => value;
3
+ //# sourceMappingURL=default.async-function.then.on-fulfilled-function.private.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default.async-function.then.on-fulfilled-function.private.js","sourceRoot":"","sources":["../../../../../src/types/methods/then/default.async-function.then.on-fulfilled-function.private.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6C,MAAM,gDAAgD,CAAC;AAE3G,MAAM,CAAC,MAAM,iDAAiD,GAAmD,CAC/G,KAAU,EACL,EAAE,CAAC,KAAK,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { type AsyncFunctionThenOnRejectedFunction } from './async-function.then.on-rejected-function.ts';
2
+ export declare const DEFAULT_ASYNC_FUNCTION_THEN_ON_REJECTED_FUNCTION: AsyncFunctionThenOnRejectedFunction<any>;
@@ -0,0 +1,5 @@
1
+ import {} from './async-function.then.on-rejected-function.js';
2
+ export const DEFAULT_ASYNC_FUNCTION_THEN_ON_REJECTED_FUNCTION = (error) => {
3
+ throw error;
4
+ };
5
+ //# sourceMappingURL=default.async-function.then.on-rejected-function.private.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default.async-function.then.on-rejected-function.private.js","sourceRoot":"","sources":["../../../../../src/types/methods/then/default.async-function.then.on-rejected-function.private.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4C,MAAM,+CAA+C,CAAC;AAEzG,MAAM,CAAC,MAAM,gDAAgD,GAA6C,CACxG,KAAU,EACL,EAAE;IACP,MAAM,KAAK,CAAC;AACd,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type AsyncFunction } from '../../../async-function.ts';
2
+ export interface TransformAsyncFunctionFunction<GSelf extends AsyncFunction<any, any>, GReturn> {
3
+ (self: GSelf): GReturn;
4
+ }
@@ -0,0 +1,2 @@
1
+ import {} from '../../../async-function.js';
2
+ //# sourceMappingURL=transform-async-function-function.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform-async-function-function.js","sourceRoot":"","sources":["../../../../../src/types/methods/transform/transform-async-function-function.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { type AsyncFunctionLike } from '../../async-function-like.ts';
2
+ export interface AsyncFunctionFromSendAndReceiveOptions<GArguments extends readonly unknown[], GReturn> {
3
+ readonly send: AsyncFunctionLike<GArguments, void>;
4
+ readonly receive: AsyncFunctionLike<GArguments, GReturn>;
5
+ }
@@ -0,0 +1,2 @@
1
+ import {} from '../../async-function-like.js';
2
+ //# sourceMappingURL=async-function-from-send-and-receive-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async-function-from-send-and-receive-options.js","sourceRoot":"","sources":["../../../../../src/types/static-methods/from-send-and-receive/async-function-from-send-and-receive-options.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,MAAM,8BAA8B,CAAC"}