@grlt-hub/app-compose
Advanced tools
Comparing version 1.3.0 to 1.4.0
@@ -82,3 +82,7 @@ import * as effector from 'effector'; | ||
}; | ||
} | undefined>(__containers: T, __config?: C) => Promise<undefined extends C ? { | ||
onFail?: (_: { | ||
id: AnyContainer["id"]; | ||
error: Error; | ||
}) => unknown; | ||
}>(__containers: T, __config?: C) => Promise<undefined extends C ? { | ||
hasErrors: boolean; | ||
@@ -99,3 +103,3 @@ statuses: { [K in T[number]["id"]]: ContainerStatus; }; | ||
}; | ||
} | undefined) => { | ||
}) => { | ||
[x: string]: { | ||
@@ -102,0 +106,0 @@ strict: AnyContainer["id"][]; |
@@ -1,5 +0,4 @@ | ||
import{createStore as w}from"effector";import"effector";var r={idle:"idle",pending:"pending",done:"done",fail:"fail",off:"off"};var R={CONTAINER_ID_EMPTY_STRING:"Container ID cannot be an empty string.",depsIntersection:(e,i)=>` | ||
Dependency conflict detected in container '${i}': | ||
The following dependencies are listed as both required and optional: [${e.join(", ")}]. | ||
import{createStore as $}from"effector";import"effector";var i={idle:"idle",pending:"pending",done:"done",fail:"fail",off:"off"};var I={CONTAINER_ID_EMPTY_STRING:"Container ID cannot be an empty string.",depsIntersection:(e,s)=>`Dependency conflict detected in container '${s}': | ||
The following dependencies are listed as both required and optional: [${e.join(", ")}]. | ||
Each dependency should be listed only once, as either required or optional.`},P=e=>{if(e.id==="")throw new Error(R.CONTAINER_ID_EMPTY_STRING)},N=e=>{if(!e.dependsOn||!e.optionalDependsOn)return;let i=new Set(e.dependsOn.map(o=>o.id)),s=new Set(e.optionalDependsOn.map(o=>o.id)),p=i.intersection(s);if(p.size>0)throw new Error(R.depsIntersection(Array.from(p),e.id))},g=e=>(P(e),N(e),e);var $=e=>{let i=g(e),s=w(r.idle);return{...i,$status:s}};var m=(e,i=!1)=>{let s=new Set,p=o=>{var y,d;s.has(o)||(s.add(o),(y=o.dependsOn)==null||y.forEach(p),i&&((d=o.optionalDependsOn)==null||d.forEach(p)))};return e.forEach(p),Array.from(s)};var O=e=>{var y,d;let i=new Set,s=[],p=[],o=[];for((e.dependsOn||[]).forEach(a=>o.push([a,[e.id,a.id],"strict"])),(e.optionalDependsOn||[]).forEach(a=>o.push([a,[e.id,a.id],"optional"]));o.length>0;){let[a,l,A]=o.pop();i.has(a.id)||(i.add(a.id),!((y=e.dependsOn)!=null&&y.includes(a))&&!((d=e.optionalDependsOn)!=null&&d.includes(a))&&(A==="strict"?s.push({id:a.id,path:l.join(" -> ")}):p.push({id:a.id,path:l.join(" -> ")})),(a.dependsOn||[]).forEach(t=>{o.push([t,[...l,t.id],A])}),(a.optionalDependsOn||[]).forEach(t=>{o.push([t,[...l,t.id],"optional"])}))}return{strict:s,optional:p}};var _=e=>Object.assign({autoResolveDeps:{strict:!1,optional:!1}},e!=null?e:{}),x=(e,i)=>{var o;let s=_(i);return((o=s.autoResolveDeps)!=null&&o.strict?m(e,s.autoResolveDeps.optional):e).reduce((y,d)=>{let a=(d.dependsOn||[]).map(t=>t.id),l=(d.optionalDependsOn||[]).map(t=>t.id),A=O(d);return y[d.id]={strict:a,optional:l,transitive:{strict:A.strict,optional:A.optional}},y},{})};import{clearNode as j,combine as S,createEffect as h,launch as k,sample as T}from"effector";var F=(e,i)=>{if(i.has(e))throw new Error(`Duplicate container ID found: ${e}`);i.add(e)},c={off:e=>e===r.off,fail:e=>e===r.fail,pending:e=>e===r.pending,done:e=>e===r.done,idle:e=>e===r.idle},K=e=>Object.assign({apis:!1,debug:!1,autoResolveDeps:{strict:!1,optional:!1}},e!=null?e:{}),b=async(e,i)=>{var A;let s=K(i),p=(A=s.autoResolveDeps)!=null&&A.strict?m(e,s.autoResolveDeps.optional):e,o=new Set;for(let t of p)F(t.id,o);let y=p.reduce((t,u)=>(t[u.id]=u.$status,t),{}),d=S(y,t=>{let u=Object.values(t),f=u.every(D=>/^(done|fail|off)$/.test(D)),C=u.some(c.fail);return{done:f,hasErrors:C,statuses:t}});s!=null&&s.debug&&d.watch(t=>{console.debug(`[${new Date().toISOString()}] app-compose:`,JSON.stringify(t.statuses,null,2))});let a=[d],l={};return await Promise.allSettled(p.map(t=>{var v,I;let u=S(((v=t.dependsOn)!=null?v:[]).map(n=>n.$status),n=>n.some(c.off)?r.off:n.some(c.fail)?r.fail:n.some(c.pending)?r.pending:n.every(c.done)||n.length===0?r.done:r.idle),f=S(((I=t.optionalDependsOn)!=null?I:[]).map(n=>n.$status),n=>n.some(c.pending)?r.pending:n.some(c.idle)?r.idle:r.done),C=S([u,f],n=>n.every(c.done)),D=h(async()=>t.enable?await t.enable(l,l):!0),E=h(async()=>{l[t.id]=(await t.start(l,l)).api});T({clock:D.doneData,fn:n=>n?r.pending:r.off,target:t.$status}),T({clock:D.failData,fn:()=>r.fail,target:t.$status}),T({clock:t.$status,filter:c.pending,target:E}),T({clock:E.finally,fn:n=>n.status,target:t.$status}),u.watch(n=>{(c.off(n)||c.fail(n))&&k(t.$status,n)}),C.watch(n=>{n&&D()}),a=[...a,u,f,C,D,E]})),new Promise((t,u)=>{d.watch(f=>{if(f.done===!0){a.forEach(E=>j(E,{deep:!0}));let C=(s==null?void 0:s.apis)===!0;C||(l={});let D={hasErrors:f.hasErrors,statuses:f.statuses,...C?{apis:l}:{}};f.hasErrors&&u(D),t(D)}})})};var V={up:b,graph:x};export{V as compose,$ as createContainer}; | ||
Each dependency should be listed only once, as either required or optional.`},w=e=>{if(e.id==="")throw new Error(I.CONTAINER_ID_EMPTY_STRING)},N=e=>{if(!e.dependsOn||!e.optionalDependsOn)return;let s=new Set(e.dependsOn.map(a=>a.id)),o=new Set(e.optionalDependsOn.map(a=>a.id)),d=s.intersection(o);if(d.size)throw new Error(I.depsIntersection(Array.from(d),e.id))},R=e=>(w(e),N(e),e);var _=e=>{let s=R(e),o=$(i.idle);return{...s,$status:o}};var F=(e,s=!1)=>{let o=new Set,d=a=>{var p,y;o.has(a)||(o.add(a),(p=a.dependsOn)==null||p.forEach(d),s&&((y=a.optionalDependsOn)==null||y.forEach(d)))};return e.forEach(d),Array.from(o)},S=({containers:e,autoResolveDeps:s})=>s.strict?F(e,s.optional):e;var x=e=>{var p,y;let s=new Set,o=[],d=[],a=[];for((e.dependsOn||[]).forEach(r=>a.push([r,[e.id,r.id],"strict"])),(e.optionalDependsOn||[]).forEach(r=>a.push([r,[e.id,r.id],"optional"]));a.length>0;){let[r,u,l]=a.pop();s.has(r.id)||(s.add(r.id),!((p=e.dependsOn)!=null&&p.includes(r))&&!((y=e.optionalDependsOn)!=null&&y.includes(r))&&(l==="strict"?o.push({id:r.id,path:u.join(" -> ")}):d.push({id:r.id,path:u.join(" -> ")})),(r.dependsOn||[]).forEach(t=>{a.push([t,[...u,t.id],l])}),(r.optionalDependsOn||[]).forEach(t=>{a.push([t,[...u,t.id],"optional"])}))}return{strict:o,optional:d}};var k=e=>Object.assign({autoResolveDeps:{strict:!1,optional:!1}},e!=null?e:{}),b=(e,s)=>{let o=k(s);return S({containers:e,autoResolveDeps:o.autoResolveDeps}).reduce((a,p)=>{let y=(p.dependsOn||[]).map(l=>l.id),r=(p.optionalDependsOn||[]).map(l=>l.id),u=x(p);return a[p.id]={strict:y,optional:r,transitive:{strict:u.strict,optional:u.optional}},a},{})};import{clearNode as j,combine as T,createEffect as g,launch as h,sample as m}from"effector";var K=(e,s)=>{if(s.has(e))throw new Error(`Duplicate container ID found: ${e}`);s.add(e)},c={off:e=>e===i.off,fail:e=>e===i.fail,pending:e=>e===i.pending,done:e=>e===i.done,idle:e=>e===i.idle},V=()=>{},G=new Error("Strict dependency failed"),U=e=>Object.assign({apis:!1,debug:!1,autoResolveDeps:{strict:!1,optional:!1},onFail:V},e!=null?e:{}),P=async(e,s)=>{let o=U(s),d=S({containers:e,autoResolveDeps:o.autoResolveDeps}),a=new Set;for(let t of d)K(t.id,a);let p=g(o.onFail),y=d.reduce((t,f)=>(t[f.id]=f.$status,t),{}),r=T(y,t=>({done:Object.values(t).every(C=>/^(done|fail|off)$/.test(C)),statuses:t}));o!=null&&o.debug&&r.watch(t=>{console.debug(`[${new Date().toISOString()}] app-compose:`,JSON.stringify(t.statuses,null,2))});let u=[r,p],l={};return await Promise.allSettled(d.map(t=>{var v,O;let f=T(((v=t.dependsOn)!=null?v:[]).map(n=>n.$status),n=>n.some(c.off)?i.off:n.some(c.fail)?i.fail:n.some(c.pending)?i.pending:n.every(c.done)||n.length===0?i.done:i.idle),D=T(((O=t.optionalDependsOn)!=null?O:[]).map(n=>n.$status),n=>n.some(c.pending)||n.some(c.idle)?i.idle:i.done),C=T([f,D],n=>n.every(c.done)),A=g(async()=>t.enable?await t.enable(l,l):!0),E=g(async()=>{l[t.id]=(await t.start(l,l)).api});m({clock:A.doneData,fn:n=>n?i.pending:i.off,target:t.$status}),m({clock:A.failData,fn:()=>i.fail,target:t.$status}),m({clock:A.fail,fn:n=>({error:n.error,id:t.id}),target:p}),m({clock:t.$status,filter:c.pending,target:E}),m({clock:E.finally,fn:n=>n.status,target:t.$status}),m({clock:E.fail,fn:n=>({error:n.error,id:t.id}),target:p}),f.watch(n=>{if(c.fail(n)){h(t.$status,n),p({id:t.id,error:G});return}c.off(n)&&h(t.$status,n)}),C.watch(n=>{n&&A()}),u.push(f,D,C,A,E)})),new Promise((t,f)=>{r.watch(D=>{if(!D.done)return;u.forEach(A=>j(A,{deep:!0})),u=[],o.apis||(l={});let C={hasErrors:Object.values(D.statuses).some(c.fail),statuses:D.statuses,...o.apis?{apis:l}:{}};C.hasErrors&&f(C),t(C)})})};var q={up:P,graph:b};export{q as compose,_ as createContainer}; |
{ | ||
"name": "@grlt-hub/app-compose", | ||
"version": "1.3.0", | ||
"version": "1.4.0", | ||
"type": "module", | ||
@@ -9,25 +9,12 @@ "private": false, | ||
"types": "dist/index.d.ts", | ||
"files": ["/README.md", "/package.json", "/dist"], | ||
"files": [ | ||
"/README.md", | ||
"/package.json", | ||
"/dist" | ||
], | ||
"author": "Viktor Pasynok", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"@size-limit/preset-small-lib": "11.1.6", | ||
"@vitest/coverage-v8": "2.1.4", | ||
"clean-publish": "5.1.0", | ||
"knip": "5.36.3", | ||
"prettier": "3.3.3", | ||
"prettier-plugin-organize-imports": "4.1.0", | ||
"size-limit": "11.1.6", | ||
"tslib": "2.8.1", | ||
"tsup": "8.3.5", | ||
"typescript": "5.6.3", | ||
"vitest": "2.1.4" | ||
}, | ||
"peerDependencies": { | ||
"effector": "23" | ||
}, | ||
"volta": { | ||
"node": "22.9.0", | ||
"npm": "10.9.0" | ||
}, | ||
"publishConfig": { | ||
@@ -34,0 +21,0 @@ "access": "public" |
0
126
14744