tasuku 2.0.0 → 2.0.2
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.
- package/README.md +16 -8
- package/dist/index.cjs +13 -0
- package/dist/{index.d.ts → index.d.cts} +37 -12
- package/dist/index.d.mts +108 -0
- package/dist/index.mjs +13 -70
- package/package.json +42 -85
- package/dist/index.js +0 -70
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
→ [Try it out online](https://stackblitz.com/edit/tasuku-demo?file=index.js&devtoolsheight=50&view=editor)
|
|
14
14
|
|
|
15
|
-
<sub>
|
|
15
|
+
<sub>Found this package useful? Show your support & appreciation by [sponsoring](https://github.com/sponsors/privatenumber)! ❤️</sub>
|
|
16
16
|
|
|
17
17
|
## Install
|
|
18
18
|
```sh
|
|
@@ -25,7 +25,7 @@ npm i tasuku
|
|
|
25
25
|
For example, here's a simple script that copies a file from path A to B.
|
|
26
26
|
|
|
27
27
|
```ts
|
|
28
|
-
import { copyFile } from 'fs/promises'
|
|
28
|
+
import { copyFile } from 'node:fs/promises'
|
|
29
29
|
import task from 'tasuku'
|
|
30
30
|
|
|
31
31
|
task('Copying file from path A to B', async ({ setTitle }) => {
|
|
@@ -230,7 +230,7 @@ Returns a Promise that resolves with object:
|
|
|
230
230
|
```ts
|
|
231
231
|
type TaskAPI = {
|
|
232
232
|
// Result from taskFunction
|
|
233
|
-
result:
|
|
233
|
+
result: unknown
|
|
234
234
|
|
|
235
235
|
// State of the task
|
|
236
236
|
state: 'error' | 'warning' | 'success'
|
|
@@ -257,7 +257,7 @@ type TaskFunction = (taskInnerApi: {
|
|
|
257
257
|
setOutput(output: string | { message: string }): void
|
|
258
258
|
setWarning(warning: Error | string): void
|
|
259
259
|
setError(error: Error | string): void
|
|
260
|
-
}) => Promise<
|
|
260
|
+
}) => Promise<unknown>
|
|
261
261
|
```
|
|
262
262
|
|
|
263
263
|
Required: true
|
|
@@ -292,7 +292,7 @@ Returns a Promise that resolves with object:
|
|
|
292
292
|
// The results from the taskFunctions
|
|
293
293
|
type TaskGroupAPI = {
|
|
294
294
|
// Result from taskFunction
|
|
295
|
-
result:
|
|
295
|
+
result: unknown
|
|
296
296
|
|
|
297
297
|
// State of the task
|
|
298
298
|
state: 'error' | 'warning' | 'success'
|
|
@@ -339,11 +339,11 @@ _Tasuku_ or タスク is the phonetic Japanese pronounciation of the word "task
|
|
|
339
339
|
|
|
340
340
|
### Why did you make this?
|
|
341
341
|
|
|
342
|
-
|
|
342
|
+
I built _Tasuku_ as a lightweight task runner for scripts and CLI tools. It's designed to show task progress clearly without forcing a rigid structure on how you write your code.
|
|
343
343
|
|
|
344
|
-
|
|
344
|
+
Big thanks to [listr](https://github.com/SamVerschueren/listr) and [listr2](https://github.com/cenk1cenk2/listr2), which inspired both the visuals and the idea—I've relied on them for years. But over time, I found their declarative approach too restrictive for my workflow, so I created something simpler and more flexible.
|
|
345
345
|
|
|
346
|
-
|
|
346
|
+
_Tasuku_ uses its own minimal ANSI-based renderer for terminal output, giving you smooth `console.log()` integration with zero runtime dependencies. The rendering model was originally inspired by [ink](https://github.com/vadimdemedes/ink)'s approach to terminal UIs.
|
|
347
347
|
|
|
348
348
|
### Doesn't the usage of nested `task` functions violate ESLint's [no-shadow](https://eslint.org/docs/rules/no-shadow)?
|
|
349
349
|
Yes, but it should be fine as you don't need access to other `task` functions aside from the immediate one.
|
|
@@ -351,3 +351,11 @@ Yes, but it should be fine as you don't need access to other `task` functions as
|
|
|
351
351
|
Put `task` in the allow list:
|
|
352
352
|
- `"no-shadow": ["error", { "allow": ["task"] }]`
|
|
353
353
|
- `"@typescript-eslint/no-shadow": ["error", { "allow": ["task"] }]`
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
## Sponsors
|
|
357
|
+
<p align="center">
|
|
358
|
+
<a href="https://github.com/sponsors/privatenumber">
|
|
359
|
+
<img src="https://cdn.jsdelivr.net/gh/privatenumber/sponsors/sponsorkit/sponsors.svg">
|
|
360
|
+
</a>
|
|
361
|
+
</p>
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";var Ye=Object.defineProperty;var s=(e,t)=>Ye(e,"name",{value:t,configurable:!0});var V=require("os"),K=require("stream"),W=require("process"),ze=require("tty");function He(e,t=1,r={}){const{indent:n=" ",includeEmptyLines:o=!1}=r;if(typeof e!="string")throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof e}\``);if(typeof t!="number")throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof t}\``);if(t<0)throw new RangeError(`Expected \`count\` to be at least 0, got \`${t}\``);if(typeof n!="string")throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof n}\``);if(t===0)return e;const a=o?/^/gm:/^(?!\s*$)/gm;return e.replace(a,n.repeat(t))}s(He,"indentString");function Ve(e){if(typeof e!="string")throw new TypeError("Expected a string");return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}s(Ve,"escapeStringRegexp");const Q=/\s+at.*[(\s](.*)\)?/,Ke=/^(?:(?:(?:node|node:[\w/]+|(?:(?:node:)?internal\/[\w/]*|.*node_modules\/(?:babel-polyfill|pirates)\/.*)?\w+)(?:\.js)?:\d+:\d+)|native)/,Qe=typeof V.homedir=="undefined"?"":V.homedir().replace(/\\/g,"/");function Je(e,{pretty:t=!1,basePath:r}={}){const n=r&&new RegExp(`(at | \\()${Ve(r.replace(/\\/g,"/"))}`,"g");if(typeof e=="string")return e.replace(/\\/g,"/").split(`
|
|
2
|
+
`).filter(o=>{const a=o.match(Q);if(a===null||!a[1])return!0;const l=a[1];return l.includes(".app/Contents/Resources/electron.asar")||l.includes(".app/Contents/Resources/default_app.asar")||l.includes("node_modules/electron/dist/resources/electron.asar")||l.includes("node_modules/electron/dist/resources/default_app.asar")?!1:!Ke.test(l)}).filter(o=>o.trim()!=="").map(o=>(n&&(o=o.replace(n,"$1")),t&&(o=o.replace(Q,(a,l)=>a.replace(l,l.replace(Qe,"~")))),o)).join(`
|
|
3
|
+
`)}s(Je,"cleanStack");var Xe=Object.defineProperty,J=s(e=>{throw TypeError(e)},"__typeError"),Ze=s((e,t,r)=>t in e?Xe(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,"__defNormalProp"),et=s((e,t,r)=>Ze(e,t+"",r),"__publicField"),X=s((e,t,r)=>t.has(e)||J("Cannot "+r),"__accessCheck"),tt=s((e,t,r)=>(X(e,t,"read from private field"),r?r.call(e):t.get(e)),"__privateGet"),rt=s((e,t,r)=>t.has(e)?J("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,r),"__privateAdd"),nt=s((e,t,r,n)=>(X(e,t,"write to private field"),t.set(e,r),r),"__privateSet"),O;const ot=s(e=>e.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g,""),"cleanInternalStack"),z=class z extends Error{constructor(t){if(!Array.isArray(t))throw new TypeError(`Expected input to be an Array, got ${typeof t}`);t=t.map(n=>n instanceof Error?n:n!==null&&typeof n=="object"?Object.assign(new Error(n.message),n):new Error(n));let r=t.map(n=>typeof n.stack=="string"&&n.stack.length>0?ot(Je(n.stack)):String(n)).join(`
|
|
4
|
+
`);r=`
|
|
5
|
+
`+He(r,4),super(r),rt(this,O),et(this,"name","AggregateError"),nt(this,O,t)}get errors(){return tt(this,O).slice()}};s(z,"AggregateError");let F=z;O=new WeakMap;const H=class H extends Error{constructor(t){super(),this.name="AbortError",this.message=t}};s(H,"AbortError");let k=H;const Z=s(e=>globalThis.DOMException===void 0?new k(e):new DOMException(e),"getDOMException"),ee=s(e=>{const t=e.reason===void 0?Z("This operation was aborted."):e.reason;return t instanceof Error?t:Z(t)},"getAbortedReason");async function st(e,t,{concurrency:r=Number.POSITIVE_INFINITY,stopOnError:n=!0,signal:o}={}){return new Promise((a,l)=>{if(e[Symbol.iterator]===void 0&&e[Symbol.asyncIterator]===void 0)throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof e})`);if(typeof t!="function")throw new TypeError("Mapper function is required");if(!((Number.isSafeInteger(r)||r===Number.POSITIVE_INFINITY)&&r>=1))throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${r}\` (${typeof r})`);const p=[],f=[],v=new Map;let d=!1,_=!1,S=!1,T=0,R=0;const M=e[Symbol.iterator]===void 0?e[Symbol.asyncIterator]():e[Symbol.iterator](),h=s(i=>{d=!0,_=!0,l(i)},"reject");o&&(o.aborted&&h(ee(o)),o.addEventListener("abort",()=>{h(ee(o))}));const y=s(async()=>{if(_)return;const i=await M.next(),c=R;if(R++,i.done){if(S=!0,T===0&&!_){if(!n&&f.length>0){h(new F(f));return}if(_=!0,v.size===0){a(p);return}const u=[];for(const[g,P]of p.entries())v.get(g)!==te&&u.push(P);a(u)}return}T++,(async()=>{try{const u=await i.value;if(_)return;const g=await t(u,c);g===te&&v.set(c,g),p[c]=g,T--,await y()}catch(u){if(n)h(u);else{f.push(u),T--;try{await y()}catch(g){h(g)}}}})()},"next");(async()=>{for(let i=0;i<r;i++){try{await y()}catch(c){h(c);break}if(S||d)break}})()})}s(st,"pMap");const te=Symbol("skip"),re=["assert","count","countReset","debug","dir","dirxml","error","group","groupCollapsed","groupEnd","info","log","table","time","timeEnd","timeLog","trace","warn"];let G={};const it=s(e=>{const t=new K.PassThrough,r=new K.PassThrough;t.write=o=>{e("stdout",o)},r.write=o=>{e("stderr",o)};const n=new console.Console(t,r);for(const o of re)G[o]=console[o],console[o]=n[o];return()=>{for(const o of re)console[o]=G[o];G={}}},"patchConsole");var ne,oe,se,ie,le,ae,ce,ue,de,pe,fe,ge,ve,he,we,me,_e,Te,ye,be,xe,Ee,Ce,Ie,Se,Re,Oe,$e,Ae,Ne,Me;const B=((ne=globalThis.window)==null?void 0:ne.document)!==void 0;(se=(oe=globalThis.process)==null?void 0:oe.versions)==null||se.node,(le=(ie=globalThis.process)==null?void 0:ie.versions)==null||le.bun,(ce=(ae=globalThis.Deno)==null?void 0:ae.version)==null||ce.deno,(de=(ue=globalThis.process)==null?void 0:ue.versions)==null||de.electron,(fe=(pe=globalThis.navigator)==null?void 0:pe.userAgent)==null||fe.includes("jsdom"),typeof WorkerGlobalScope!="undefined"&&globalThis instanceof WorkerGlobalScope,typeof DedicatedWorkerGlobalScope!="undefined"&&globalThis instanceof DedicatedWorkerGlobalScope,typeof SharedWorkerGlobalScope!="undefined"&&globalThis instanceof SharedWorkerGlobalScope,typeof ServiceWorkerGlobalScope!="undefined"&&globalThis instanceof ServiceWorkerGlobalScope;const E=(ve=(ge=globalThis.navigator)==null?void 0:ge.userAgentData)==null?void 0:ve.platform;E==="macOS"||((he=globalThis.navigator)==null?void 0:he.platform)==="MacIntel"||((me=(we=globalThis.navigator)==null?void 0:we.userAgent)==null?void 0:me.includes(" Mac "))===!0||((_e=globalThis.process)==null||_e.platform),E==="Windows"||((Te=globalThis.navigator)==null?void 0:Te.platform)==="Win32"||((ye=globalThis.process)==null||ye.platform),E==="Linux"||((xe=(be=globalThis.navigator)==null?void 0:be.platform)==null?void 0:xe.startsWith("Linux"))===!0||((Ce=(Ee=globalThis.navigator)==null?void 0:Ee.userAgent)==null?void 0:Ce.includes(" Linux "))===!0||((Ie=globalThis.process)==null||Ie.platform),E==="iOS"||((Se=globalThis.navigator)==null?void 0:Se.platform)==="MacIntel"&&((Re=globalThis.navigator)==null?void 0:Re.maxTouchPoints)>1||/iPad|iPhone|iPod/.test((Oe=globalThis.navigator)==null?void 0:Oe.platform),E==="Android"||(($e=globalThis.navigator)==null?void 0:$e.platform)==="Android"||((Ne=(Ae=globalThis.navigator)==null?void 0:Ae.userAgent)==null?void 0:Ne.includes(" Android "))===!0||((Me=globalThis.process)==null||Me.platform);const $="\x1B[";!B&&W.env.TERM_PROGRAM,!B&&W.platform,B||W.cwd;const j=s((e=1)=>$+e+"A","cursorUp"),lt=$+"?25l",at=$+"?25h",C=$+"2K";var Pe,De,q,We,Fe;const ct=(Fe=(We=(q=(De=(Pe=ze)==null?void 0:Pe.WriteStream)==null?void 0:De.prototype)==null?void 0:q.hasColors)==null?void 0:We.call(q))!=null?Fe:!1,I=s((e,t)=>{if(!ct)return o=>o;const r=`\x1B[${e}m`,n=`\x1B[${t}m`;return o=>{const a=o+"";let l=a.indexOf(n);if(l===-1)return r+a+n;let p=r,f=0;const d=(t===22?n:"")+r;for(;l!==-1;)p+=a.slice(f,l)+d,f=l+n.length,l=a.indexOf(n,f);return p+=a.slice(f)+n,p}},"format"),ut=I(2,22),ke=I(31,39),dt=I(32,39),A=I(33,39),L=I(90,39),Ge=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],N=!!(process.env.CI||process.env.CONTINUOUS_INTEGRATION||process.env.BUILD_NUMBER),pt=s(e=>process.env.NO_COLOR||process.env.NODE_DISABLE_COLORS?!1:e.hasColors?e.hasColors():process.env.FORCE_COLOR!==void 0?process.env.FORCE_COLOR!=="0":e.isTTY!==!1,"detectColors"),w=s((e,t,r)=>e?t(r):r,"colorize"),Be=s(e=>{for(const t of e)if(t.state==="loading"||t.state==="pending"||t.children&&t.children.length>0&&!Be(t.children))return!1;return!0},"areAllTasksDone"),ft=s((e,t=process.stdout)=>{let r=0,n,o,a="",l=0,p,f=!1;const v=t.isTTY!==!1,d=pt(t),_=s((i,c)=>i==="pending"?w(d,L,"\u25FC"):i==="loading"?c?w(d,A,"\u276F"):w(d,A,Ge[r]):i==="success"?c?w(d,A,"\u276F"):w(d,dt,"\u2714"):i==="error"?c?w(d,ke,"\u276F"):w(d,ke,"\u2716"):i==="warning"?w(d,A,"\u26A0"):w(d,L,"\u25FC"),"getIcon"),S=s((i,c)=>{const u=" ".repeat(c),g=i.children&&i.children.length>0,P=_(i.state,g);let b=`${u}${P} ${i.title}`;if(i.status){const D=d?ut(`[${i.status}]`):`[${i.status}]`;b+=` ${D}`}if(b+=`
|
|
6
|
+
`,i.output){const D=`${u} `,Le=s(x=>d?L(x):x,"styleText");b+=`${i.output.split(`
|
|
7
|
+
`).map((x,Ue)=>`${D}${Le(Ue===0?`\u2192 ${x}`:x)}`).join(`
|
|
8
|
+
`)}
|
|
9
|
+
`}return g&&(b+=T(i.children,c+1)),b},"renderTask"),T=s((i,c=0)=>i.map(u=>S(u,c)).join(""),"renderTaskList"),R=s((i,c)=>{if(l>0){for(let u=0;u<l;u+=1)t.write(C),t.write(j());t.write(C),t.write("\x1B[G"),l=0}t.write(c),e.length>0&&(t.write(`
|
|
10
|
+
`),a=`
|
|
11
|
+
`,l=1)},"handleConsoleOutput"),M=s(()=>{const i=T(e),c=Be(e);if(c&&n&&(clearInterval(n),n=void 0),N){i!==a&&(t.write(i),a=i);return}if(!f&&v&&i!==""&&i!==`
|
|
12
|
+
`&&!c&&(t.write(lt),f=!0),l>0){for(let u=0;u<l;u+=1)t.write(C),t.write(j());t.write(C),t.write("\x1B[G")}t.write(i),a=i,l=i.split(`
|
|
13
|
+
`).length-1},"render"),h=s(()=>{o||(o=setTimeout(()=>{o=void 0,M()},33))},"scheduleRender"),y=s(()=>{if(n&&clearInterval(n),o&&clearTimeout(o),p&&p(),!N&&v&&l>0)for(let i=0;i<l;i+=1)t.write(C),t.write(j());!N&&v&&t.write(at)},"destroy");return N||(p=it(R),v&&(n=setInterval(()=>{r=(r+1)%Ge.length,h()},80))),{triggerRender:h,destroy:y}},"createRenderer");let U;const gt=s(e=>{U=e},"setRenderCallback"),vt=s(e=>new Proxy(e,{set(t,r,n){return Reflect.set(t,r,n),U&&U(),!0}}),"reactive"),Y=Symbol("run"),ht=s(e=>{const t={task:qe(e.children),setTitle(r){e.title=r},setStatus(r){e.status=r},setOutput(r){e.output=typeof r=="string"?r:"message"in r?r.message:""},setWarning(r){e.state="warning",r!==void 0&&t.setOutput(r)},setError(r){e.state="error",r!==void 0&&t.setOutput(r)}};return t},"createTaskInnerApi");let m;const je=s((e,t,r)=>{m||(m=ft(e),gt(()=>m.triggerRender()),e.isRoot=!0);const n=vt({title:t,state:"pending",children:[]});return e.push(n),{task:n,[Y]:async()=>{const o=ht(n);n.state="loading";let a;try{a=await r(o)}catch(l){throw o.setError(l),l}return n.state==="loading"&&(n.state="success"),a},clear:s(()=>{const o=e.indexOf(n);o!==-1&&e.splice(o,1),m&&m.triggerRender(),e.isRoot&&e.length===0&&m&&(m.destroy(),m=void 0)},"clear")}},"registerTask");function qe(e){const t=s(async(r,n)=>{const o=je(e,r,n);return{result:await o[Y](),get state(){return o.task.state},clear:o.clear}},"task");return t.group=(async(r,n)=>{const o=r((l,p)=>je(e,l,p)),a=await st(o,async l=>({result:await l[Y](),get state(){return l.task.state},clear:l.clear}),{concurrency:1,...n});return Object.assign(a,{clear:s(()=>{for(const l of o)l.clear()},"clear")})}),t}s(qe,"createTaskFunction");const wt=[];var mt=qe(wt);module.exports=mt;
|
|
@@ -18,17 +18,41 @@ interface Options {
|
|
|
18
18
|
@default true
|
|
19
19
|
*/
|
|
20
20
|
readonly stopOnError?: boolean;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
You can abort the promises using [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController).
|
|
24
|
+
|
|
25
|
+
**Requires Node.js 16 or later.*
|
|
26
|
+
|
|
27
|
+
@example
|
|
28
|
+
```
|
|
29
|
+
import pMap from 'p-map';
|
|
30
|
+
import delay from 'delay';
|
|
31
|
+
|
|
32
|
+
const abortController = new AbortController();
|
|
33
|
+
|
|
34
|
+
setTimeout(() => {
|
|
35
|
+
abortController.abort();
|
|
36
|
+
}, 500);
|
|
37
|
+
|
|
38
|
+
const mapper = async value => value;
|
|
39
|
+
|
|
40
|
+
await pMap([delay(1000), delay(1000)], mapper, {signal: abortController.signal});
|
|
41
|
+
// Throws AbortError (DOMException) after 500 ms.
|
|
42
|
+
```
|
|
43
|
+
*/
|
|
44
|
+
readonly signal?: AbortSignal;
|
|
21
45
|
}
|
|
22
46
|
|
|
23
|
-
|
|
24
|
-
|
|
47
|
+
type State = 'pending' | 'loading' | 'error' | 'warning' | 'success';
|
|
48
|
+
type TaskObject = {
|
|
25
49
|
title: string;
|
|
26
50
|
state: State;
|
|
27
51
|
children: TaskObject[];
|
|
28
52
|
status?: string;
|
|
29
53
|
output?: string;
|
|
30
54
|
};
|
|
31
|
-
|
|
55
|
+
type TaskInnerAPI = {
|
|
32
56
|
task: Task;
|
|
33
57
|
setTitle(title: string): void;
|
|
34
58
|
setStatus(status?: string): void;
|
|
@@ -38,19 +62,19 @@ declare type TaskInnerAPI = {
|
|
|
38
62
|
message: string;
|
|
39
63
|
}): void;
|
|
40
64
|
};
|
|
41
|
-
|
|
65
|
+
type TaskFunction<T> = (innerApi: TaskInnerAPI) => Promise<T>;
|
|
42
66
|
declare const runSymbol: unique symbol;
|
|
43
|
-
|
|
67
|
+
type RegisteredTask<T = unknown> = {
|
|
44
68
|
[runSymbol]: () => Promise<T>;
|
|
45
69
|
task: TaskObject;
|
|
46
70
|
clear: () => void;
|
|
47
71
|
};
|
|
48
|
-
|
|
72
|
+
type TaskAPI<Result = unknown> = {
|
|
49
73
|
result: Result;
|
|
50
74
|
state: State;
|
|
51
75
|
clear: () => void;
|
|
52
76
|
};
|
|
53
|
-
|
|
77
|
+
type Task = (<TaskReturnType>(
|
|
54
78
|
/**
|
|
55
79
|
* The task title
|
|
56
80
|
*/
|
|
@@ -61,13 +85,13 @@ title: string,
|
|
|
61
85
|
taskFunction: TaskFunction<TaskReturnType>) => Promise<TaskAPI<TaskReturnType>>) & {
|
|
62
86
|
group: TaskGroup;
|
|
63
87
|
};
|
|
64
|
-
|
|
88
|
+
type TaskGroupResults<RegisteredTasks extends RegisteredTask[]> = {
|
|
65
89
|
[Key in keyof RegisteredTasks]: (RegisteredTasks[Key] extends RegisteredTask<infer ReturnType> ? TaskAPI<ReturnType> : unknown);
|
|
66
90
|
};
|
|
67
|
-
|
|
91
|
+
type TaskGroupAPI<Results = unknown[]> = Results & {
|
|
68
92
|
clear(): void;
|
|
69
93
|
};
|
|
70
|
-
|
|
94
|
+
type CreateTask = <ReturnType>(
|
|
71
95
|
/**
|
|
72
96
|
* The task title
|
|
73
97
|
*/
|
|
@@ -76,8 +100,9 @@ title: string,
|
|
|
76
100
|
* The task function
|
|
77
101
|
*/
|
|
78
102
|
taskFunction: TaskFunction<ReturnType>) => RegisteredTask<ReturnType>;
|
|
79
|
-
|
|
103
|
+
type TaskGroup = <RegisteredTasks extends RegisteredTask[]>(createTasks: (taskCreator: CreateTask) => readonly [...RegisteredTasks], options?: Options) => Promise<TaskGroupAPI<TaskGroupResults<RegisteredTasks>>>;
|
|
80
104
|
|
|
81
105
|
declare const _default: Task;
|
|
82
106
|
|
|
83
|
-
export {
|
|
107
|
+
export { _default as default };
|
|
108
|
+
export type { Task, TaskAPI, TaskFunction, TaskGroupAPI, TaskInnerAPI };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
interface Options {
|
|
2
|
+
/**
|
|
3
|
+
Number of concurrently pending promises returned by `mapper`.
|
|
4
|
+
|
|
5
|
+
Must be an integer from 1 and up or `Infinity`.
|
|
6
|
+
|
|
7
|
+
@default Infinity
|
|
8
|
+
*/
|
|
9
|
+
readonly concurrency?: number;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
When `true`, the first mapper rejection will be rejected back to the consumer.
|
|
13
|
+
|
|
14
|
+
When `false`, instead of stopping when a promise rejects, it will wait for all the promises to settle and then reject with an [aggregated error](https://github.com/sindresorhus/aggregate-error) containing all the errors from the rejected promises.
|
|
15
|
+
|
|
16
|
+
Caveat: When `true`, any already-started async mappers will continue to run until they resolve or reject. In the case of infinite concurrency with sync iterables, *all* mappers are invoked on startup and will continue after the first rejection. [Issue #51](https://github.com/sindresorhus/p-map/issues/51) can be implemented for abort control.
|
|
17
|
+
|
|
18
|
+
@default true
|
|
19
|
+
*/
|
|
20
|
+
readonly stopOnError?: boolean;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
You can abort the promises using [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController).
|
|
24
|
+
|
|
25
|
+
**Requires Node.js 16 or later.*
|
|
26
|
+
|
|
27
|
+
@example
|
|
28
|
+
```
|
|
29
|
+
import pMap from 'p-map';
|
|
30
|
+
import delay from 'delay';
|
|
31
|
+
|
|
32
|
+
const abortController = new AbortController();
|
|
33
|
+
|
|
34
|
+
setTimeout(() => {
|
|
35
|
+
abortController.abort();
|
|
36
|
+
}, 500);
|
|
37
|
+
|
|
38
|
+
const mapper = async value => value;
|
|
39
|
+
|
|
40
|
+
await pMap([delay(1000), delay(1000)], mapper, {signal: abortController.signal});
|
|
41
|
+
// Throws AbortError (DOMException) after 500 ms.
|
|
42
|
+
```
|
|
43
|
+
*/
|
|
44
|
+
readonly signal?: AbortSignal;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type State = 'pending' | 'loading' | 'error' | 'warning' | 'success';
|
|
48
|
+
type TaskObject = {
|
|
49
|
+
title: string;
|
|
50
|
+
state: State;
|
|
51
|
+
children: TaskObject[];
|
|
52
|
+
status?: string;
|
|
53
|
+
output?: string;
|
|
54
|
+
};
|
|
55
|
+
type TaskInnerAPI = {
|
|
56
|
+
task: Task;
|
|
57
|
+
setTitle(title: string): void;
|
|
58
|
+
setStatus(status?: string): void;
|
|
59
|
+
setWarning(warning?: Error | string): void;
|
|
60
|
+
setError(error?: Error | string): void;
|
|
61
|
+
setOutput(output: string | {
|
|
62
|
+
message: string;
|
|
63
|
+
}): void;
|
|
64
|
+
};
|
|
65
|
+
type TaskFunction<T> = (innerApi: TaskInnerAPI) => Promise<T>;
|
|
66
|
+
declare const runSymbol: unique symbol;
|
|
67
|
+
type RegisteredTask<T = unknown> = {
|
|
68
|
+
[runSymbol]: () => Promise<T>;
|
|
69
|
+
task: TaskObject;
|
|
70
|
+
clear: () => void;
|
|
71
|
+
};
|
|
72
|
+
type TaskAPI<Result = unknown> = {
|
|
73
|
+
result: Result;
|
|
74
|
+
state: State;
|
|
75
|
+
clear: () => void;
|
|
76
|
+
};
|
|
77
|
+
type Task = (<TaskReturnType>(
|
|
78
|
+
/**
|
|
79
|
+
* The task title
|
|
80
|
+
*/
|
|
81
|
+
title: string,
|
|
82
|
+
/**
|
|
83
|
+
* The task function
|
|
84
|
+
*/
|
|
85
|
+
taskFunction: TaskFunction<TaskReturnType>) => Promise<TaskAPI<TaskReturnType>>) & {
|
|
86
|
+
group: TaskGroup;
|
|
87
|
+
};
|
|
88
|
+
type TaskGroupResults<RegisteredTasks extends RegisteredTask[]> = {
|
|
89
|
+
[Key in keyof RegisteredTasks]: (RegisteredTasks[Key] extends RegisteredTask<infer ReturnType> ? TaskAPI<ReturnType> : unknown);
|
|
90
|
+
};
|
|
91
|
+
type TaskGroupAPI<Results = unknown[]> = Results & {
|
|
92
|
+
clear(): void;
|
|
93
|
+
};
|
|
94
|
+
type CreateTask = <ReturnType>(
|
|
95
|
+
/**
|
|
96
|
+
* The task title
|
|
97
|
+
*/
|
|
98
|
+
title: string,
|
|
99
|
+
/**
|
|
100
|
+
* The task function
|
|
101
|
+
*/
|
|
102
|
+
taskFunction: TaskFunction<ReturnType>) => RegisteredTask<ReturnType>;
|
|
103
|
+
type TaskGroup = <RegisteredTasks extends RegisteredTask[]>(createTasks: (taskCreator: CreateTask) => readonly [...RegisteredTasks], options?: Options) => Promise<TaskGroupAPI<TaskGroupResults<RegisteredTasks>>>;
|
|
104
|
+
|
|
105
|
+
declare const _default: Task;
|
|
106
|
+
|
|
107
|
+
export { _default as default };
|
|
108
|
+
export type { Task, TaskAPI, TaskFunction, TaskGroupAPI, TaskInnerAPI };
|