crewx 0.8.3 → 0.8.4-rc.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/bin/crewx-lib.js +27 -0
- package/bin/crewx-ui.js +3 -0
- package/bin/crewx.js +4 -3
- package/dist/assets/{MarketPage-CgIh-di5.js → MarketPage-eJN0_vww.js} +1 -1
- package/dist/assets/{PromptTab-DaJwMHzT.js → PromptTab-Bs_2qNca.js} +1 -1
- package/dist/assets/{_baseUniq-C5jpV1kD.js → _baseUniq-Blapu0Z_.js} +1 -1
- package/dist/assets/{arc-DKwRVrsq.js → arc-B_SJ_hx-.js} +1 -1
- package/dist/assets/{architectureDiagram-Q4EWVU46-Calo4Aq_.js → architectureDiagram-Q4EWVU46-BlwgASxK.js} +1 -1
- package/dist/assets/{blockDiagram-DXYQGD6D-D31Oq6MK.js → blockDiagram-DXYQGD6D-DTAIlB9V.js} +1 -1
- package/dist/assets/{c4Diagram-AHTNJAMY-BSoW7pC2.js → c4Diagram-AHTNJAMY-wymfJCm_.js} +1 -1
- package/dist/assets/channel-Bglz1I8m.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-BRo2QEbJ.js → chunk-4BX2VUAB-C26gOoum.js} +1 -1
- package/dist/assets/{chunk-4TB4RGXK-DLCkA9U5.js → chunk-4TB4RGXK-Br4D9e1Z.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-49jWdBL7.js → chunk-55IACEB6-C-MScsDY.js} +1 -1
- package/dist/assets/{chunk-EDXVE4YY-DA-PXvd8.js → chunk-EDXVE4YY-pbLRv4CB.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-DJoPCzeK.js → chunk-FMBD7UC4-BslWdj94.js} +1 -1
- package/dist/assets/{chunk-OYMX7WX6-CZCnFyvr.js → chunk-OYMX7WX6-BN0mLV1v.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-CeV8Zfgd.js → chunk-QZHKN3VN--Ddr2wgn.js} +1 -1
- package/dist/assets/{chunk-YZCP3GAM-CxUG24Bx.js → chunk-YZCP3GAM-DUuCyA0q.js} +1 -1
- package/dist/assets/classDiagram-6PBFFD2Q-DXJDDREl.js +1 -0
- package/dist/assets/classDiagram-v2-HSJHXN6E-DXJDDREl.js +1 -0
- package/dist/assets/clone-D5y3YnPN.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-Cdr33s2w.js → cose-bilkent-S5V4N54A-bWoSodVW.js} +1 -1
- package/dist/assets/{dagre-KV5264BT-BqhTsV7r.js → dagre-KV5264BT-DuASbUIi.js} +1 -1
- package/dist/assets/{diagram-5BDNPKRD-DgYGiVMN.js → diagram-5BDNPKRD-Bf2I8Sqh.js} +1 -1
- package/dist/assets/{diagram-G4DWMVQ6-C4va13EG.js → diagram-G4DWMVQ6-BVNFF4PK.js} +1 -1
- package/dist/assets/{diagram-MMDJMWI5-DLFpvyiO.js → diagram-MMDJMWI5-CFhEqeuh.js} +1 -1
- package/dist/assets/{diagram-TYMM5635-CQ3Eixxu.js → diagram-TYMM5635-B8cphc_j.js} +1 -1
- package/dist/assets/{erDiagram-SMLLAGMA-OtjeMBrZ.js → erDiagram-SMLLAGMA-9U45QJNH.js} +1 -1
- package/dist/assets/{flowDiagram-DWJPFMVM-xQtVnnjq.js → flowDiagram-DWJPFMVM-ou_OgE3j.js} +1 -1
- package/dist/assets/{ganttDiagram-T4ZO3ILL-B93CGlku.js → ganttDiagram-T4ZO3ILL-C8rqTl4c.js} +1 -1
- package/dist/assets/{gitGraphDiagram-UUTBAWPF-YSlyCHp2.js → gitGraphDiagram-UUTBAWPF-OVW2hVKT.js} +1 -1
- package/dist/assets/{graph-C8rSogVJ.js → graph-CbEx46vt.js} +1 -1
- package/dist/assets/{infoDiagram-42DDH7IO-COGPoqG5.js → infoDiagram-42DDH7IO-BQg0b95s.js} +1 -1
- package/dist/assets/{ishikawaDiagram-UXIWVN3A-B_GGSXoM.js → ishikawaDiagram-UXIWVN3A-Dv_0arSN.js} +1 -1
- package/dist/assets/{journeyDiagram-VCZTEJTY-DzOSsAIu.js → journeyDiagram-VCZTEJTY-Dbuq8QVf.js} +1 -1
- package/dist/assets/{kanban-definition-6JOO6SKY-DkI81Yy3.js → kanban-definition-6JOO6SKY-BnAs2grG.js} +1 -1
- package/dist/assets/{layout-CdEfqKYz.js → layout-Dc9fAO6E.js} +1 -1
- package/dist/assets/{linear-BWbhOyHo.js → linear-DIpJR0RD.js} +1 -1
- package/dist/assets/main-CuJaoUkm.css +10 -0
- package/dist/assets/main-uTENWEI_.js +1160 -0
- package/dist/assets/{min-BQu69iub.js → min-B5nwpvC0.js} +1 -1
- package/dist/assets/{mindmap-definition-QFDTVHPH-Cwl9npIv.js → mindmap-definition-QFDTVHPH-CaTnm9if.js} +1 -1
- package/dist/assets/{pieDiagram-DEJITSTG-BKpLF36F.js → pieDiagram-DEJITSTG-CX7qvasJ.js} +1 -1
- package/dist/assets/{quadrantDiagram-34T5L4WZ-BVHA25ST.js → quadrantDiagram-34T5L4WZ-BNQnIyAG.js} +1 -1
- package/dist/assets/{requirementDiagram-MS252O5E-BfmSOYJi.js → requirementDiagram-MS252O5E-BPGdekGq.js} +1 -1
- package/dist/assets/{sankeyDiagram-XADWPNL6-pe21tEFd.js → sankeyDiagram-XADWPNL6-hdF5aW8A.js} +1 -1
- package/dist/assets/{sequenceDiagram-FGHM5R23-iuskT7_w.js → sequenceDiagram-FGHM5R23-DfW5_Aol.js} +1 -1
- package/dist/assets/{stateDiagram-FHFEXIEX-CkvbzMjM.js → stateDiagram-FHFEXIEX-4mBSJq3p.js} +1 -1
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-CTbowPoU.js +1 -0
- package/dist/assets/{timeline-definition-GMOUNBTQ-Bv89zDlg.js → timeline-definition-GMOUNBTQ-hWKQ6cuT.js} +1 -1
- package/dist/assets/{vennDiagram-DHZGUBPP-DZjMicXC.js → vennDiagram-DHZGUBPP-sjewKdQ7.js} +1 -1
- package/dist/assets/wardley-RL74JXVD-01tKac6d.js +162 -0
- package/dist/assets/{wardleyDiagram-NUSXRM2D-CjJNi38l.js → wardleyDiagram-NUSXRM2D-BCNvQBfc.js} +1 -1
- package/dist/assets/{xychartDiagram-5P7HB3ND-3qACMhVA.js → xychartDiagram-5P7HB3ND-CGHTq7bt.js} +1 -1
- package/dist/index.html +2 -2
- package/dist-server/app.module.js +4 -0
- package/dist-server/domain/fs/dto/mkdir-request.dto.js +47 -0
- package/dist-server/domain/fs/dto/mkdir-response.dto.js +2 -0
- package/dist-server/domain/fs/dto/quick-access.dto.js +2 -0
- package/dist-server/domain/fs/fs.controller.js +19 -0
- package/dist-server/domain/fs/fs.service.js +134 -1
- package/dist-server/domain/workspace/workspace.controller.js +15 -0
- package/dist-server/domain/workspace/workspace.service.js +15 -0
- package/package.json +7 -7
- package/packages/cli/dist/commands/init.js +19 -11
- package/packages/cli/package.json +1 -1
- package/server.js +8 -44
- package/dist/assets/channel-dQGusK25.js +0 -1
- package/dist/assets/classDiagram-6PBFFD2Q-torAGZQx.js +0 -1
- package/dist/assets/classDiagram-v2-HSJHXN6E-torAGZQx.js +0 -1
- package/dist/assets/clone-uZODgkIv.js +0 -1
- package/dist/assets/main-C9alSClx.js +0 -1155
- package/dist/assets/main-CIiDDP50.css +0 -10
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-DbQ2MjMf.js +0 -1
- package/dist/assets/wardley-RL74JXVD-B49MX55P.js +0 -162
package/dist/assets/{wardleyDiagram-NUSXRM2D-CjJNi38l.js → wardleyDiagram-NUSXRM2D-BCNvQBfc.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{s as zt,g as Lt,q as Xt,p as At,a as Ct,b as Et,_ as y,l as et,I as Tt,e as Yt,z as Bt,c as H,i as Rt}from"./main-
|
|
1
|
+
import{s as zt,g as Lt,q as Xt,p as At,a as Ct,b as Et,_ as y,l as et,I as Tt,e as Yt,z as Bt,c as H,i as Rt}from"./main-uTENWEI_.js";import{p as Ft}from"./chunk-4BX2VUAB-C26gOoum.js";import{p as It}from"./wardley-RL74JXVD-01tKac6d.js";import"./min-B5nwpvC0.js";import"./_baseUniq-Blapu0Z_.js";var q=y((a,r)=>{const e=a<=1?a*100:a;if(e<0||e>100)throw new Error(`${r} must be between 0-1 (decimal) or 0-100 (percentage). Received: ${a}`);return e},"toPercent"),Y=y((a,r,e)=>({x:q(r,`${e} evolution`),y:q(a,`${e} visibility`)}),"toCoordinates"),tt=y(a=>{if(a){if(a==="+<>")return"bidirectional";if(a==="+<")return"backward";if(a==="+>")return"forward"}},"getFlowFromPort"),Ot=y(a=>{if(!(a!=null&&a.startsWith("+")))return{};const r=/^\+'([^']*)'/.exec(a),e=r==null?void 0:r[1];return a.includes("<>")?{flow:"bidirectional",label:e}:a.includes("<")?{flow:"backward",label:e}:a.includes(">")?{flow:"forward",label:e}:{label:e}},"extractFlowFromArrow"),Wt=y((a,r)=>{if(Ft(a,r),a.size&&r.setSize(a.size.width,a.size.height),a.evolution){const e=a.evolution.stages.map(o=>o.secondName?`${o.name.trim()} / ${o.secondName.trim()}`:o.name.trim()),h=a.evolution.stages.filter(o=>o.boundary!==void 0).map(o=>o.boundary);r.updateAxes({stages:e,stageBoundaries:h})}if(a.anchors.forEach(e=>{const h=Y(e.visibility,e.evolution,`Anchor "${e.name}"`);r.addNode(e.name,e.name,h.x,h.y,"anchor")}),a.components.forEach(e=>{var v;const h=Y(e.visibility,e.evolution,`Component "${e.name}"`),o=e.label?(e.label.negX?-1:1)*e.label.offsetX:void 0,d=e.label?(e.label.negY?-1:1)*e.label.offsetY:void 0,m=(v=e.decorator)==null?void 0:v.strategy;r.addNode(e.name,e.name,h.x,h.y,"component",o,d,e.inertia,m)}),a.notes.forEach(e=>{const h=Y(e.visibility,e.evolution,`Note "${e.text}"`);r.addNote(e.text,h.x,h.y)}),a.pipelines.forEach(e=>{const h=r.getNode(e.parent);if(!h||typeof h.y!="number")throw new Error(`Pipeline "${e.parent}" must reference an existing component with coordinates.`);const o=h.y;r.startPipeline(e.parent),e.components.forEach(d=>{const m=`${e.parent}_${d.name}`,v=d.label?(d.label.negX?-1:1)*d.label.offsetX:void 0,g=d.label?(d.label.negY?-1:1)*d.label.offsetY:void 0,A=q(d.evolution,`Pipeline component "${d.name}" evolution`);r.addNode(m,d.name,A,o,"pipeline-component",v,g),r.addPipelineComponent(e.parent,m)})}),a.links.forEach(e=>{const h=!!e.arrow&&(e.arrow.includes("-.->")||e.arrow.includes(".-."));let o=tt(e.fromPort)??tt(e.toPort);const{flow:d,label:m}=Ot(e.arrow);!o&&d&&(o=d);const v=e.linkLabel,g=m??v;r.addLink(e.from,e.to,h,g,o)}),a.evolves.forEach(e=>{const h=r.getNode(e.component);if((h==null?void 0:h.y)!==void 0){const o=q(e.target,`Evolve target for "${e.component}"`);r.addTrend(e.component,o,h.y)}}),a.annotations.length>0){const e=a.annotations[0],h=Y(e.x,e.y,"Annotations box");r.setAnnotationsBox(h.x,h.y)}a.annotation.forEach(e=>{const h=Y(e.x,e.y,`Annotation ${e.number}`);r.addAnnotation(e.number,[{x:h.x,y:h.y}],e.text)}),a.accelerators.forEach(e=>{const h=Y(e.x,e.y,`Accelerator "${e.name}"`);r.addAccelerator(e.name,h.x,h.y)}),a.deaccelerators.forEach(e=>{const h=Y(e.x,e.y,`Deaccelerator "${e.name}"`);r.addDeaccelerator(e.name,h.x,h.y)})},"populateDb"),at={parser:{yy:void 0},parse:y(async a=>{var h;const r=await It("wardley",a);et.debug(r);const e=(h=at.parser)==null?void 0:h.yy;if(!e||typeof e.addNode!="function")throw new Error("parser.parser?.yy was not a WardleyDB. This is due to a bug within Mermaid, please report this issue at https://github.com/mermaid-js/mermaid/issues.");Wt(r,e)},"parse")},R,Dt=(R=class{constructor(){this.nodes=new Map,this.links=[],this.trends=new Map,this.pipelines=new Map,this.annotations=[],this.notes=[],this.accelerators=[],this.deaccelerators=[],this.axes={}}addNode(r){const e=this.nodes.get(r.id)??{id:r.id,label:r.label},h={...e,...r,className:r.className??e.className,labelOffsetX:r.labelOffsetX??e.labelOffsetX,labelOffsetY:r.labelOffsetY??e.labelOffsetY};this.nodes.set(r.id,h)}addLink(r){this.links.push(r)}addTrend(r){this.trends.set(r.nodeId,r)}startPipeline(r){this.pipelines.set(r,{nodeId:r,componentIds:[]});const e=this.nodes.get(r);e&&(e.isPipelineParent=!0)}addPipelineComponent(r,e){const h=this.pipelines.get(r);h&&h.componentIds.push(e);const o=this.nodes.get(e);o&&(o.inPipeline=!0)}addAnnotation(r){this.annotations.push(r)}addNote(r){this.notes.push(r)}addAccelerator(r){this.accelerators.push(r)}addDeaccelerator(r){this.deaccelerators.push(r)}setAnnotationsBox(r,e){this.annotationsBox={x:r,y:e}}setAxes(r){this.axes={...this.axes,...r}}setSize(r,e){this.size={width:r,height:e}}getNode(r){return this.nodes.get(r)}build(){const r=[];for(const e of this.nodes.values()){if(typeof e.x!="number"||typeof e.y!="number")throw new Error(`Node "${e.label}" is missing coordinates`);r.push(e)}return{nodes:r,links:[...this.links],trends:[...this.trends.values()],pipelines:[...this.pipelines.values()],annotations:[...this.annotations],notes:[...this.notes],accelerators:[...this.accelerators],deaccelerators:[...this.deaccelerators],annotationsBox:this.annotationsBox,axes:{...this.axes},size:this.size}}clear(){this.nodes.clear(),this.links=[],this.trends.clear(),this.pipelines.clear(),this.annotations=[],this.notes=[],this.accelerators=[],this.deaccelerators=[],this.annotationsBox=void 0,this.axes={},this.size=void 0}},y(R,"WardleyBuilder"),R),P=new Dt;function N(a){const r=H();return Rt(a.trim(),r)}y(N,"textSanitizer");function rt(){return H()["wardley-beta"]}y(rt,"getConfig");function ot(a,r,e,h,o,d,m,v,g){P.addNode({id:a,label:N(r),x:e,y:h,className:o,labelOffsetX:d,labelOffsetY:m,inertia:v,sourceStrategy:g})}y(ot,"addNode");function st(a,r,e=!1,h,o){P.addLink({source:a,target:r,dashed:e,label:h,flow:o})}y(st,"addLink");function nt(a,r,e){P.addTrend({nodeId:a,targetX:r,targetY:e})}y(nt,"addTrend");function it(a,r,e){P.addAnnotation({number:a,coordinates:r,text:e?N(e):void 0})}y(it,"addAnnotation");function dt(a,r,e){P.addNote({text:N(a),x:r,y:e})}y(dt,"addNote");function lt(a,r,e){P.addAccelerator({name:N(a),x:r,y:e})}y(lt,"addAccelerator");function ct(a,r,e){P.addDeaccelerator({name:N(a),x:r,y:e})}y(ct,"addDeaccelerator");function pt(a,r){P.setAnnotationsBox(a,r)}y(pt,"setAnnotationsBox");function ht(a,r){P.setSize(a,r)}y(ht,"setSize");function xt(a){P.startPipeline(a)}y(xt,"startPipeline");function ft(a,r){P.addPipelineComponent(a,r)}y(ft,"addPipelineComponent");function gt(a){const r={};a.xLabel&&(r.xLabel=N(a.xLabel)),a.yLabel&&(r.yLabel=N(a.yLabel)),a.stages&&(r.stages=a.stages.map(e=>N(e))),a.stageBoundaries&&(r.stageBoundaries=a.stageBoundaries),P.setAxes(r)}y(gt,"updateAxes");function ut(a){return P.getNode(a)}y(ut,"getNode");function yt(){return P.build()}y(yt,"getWardleyData");function mt(){P.clear(),Bt()}y(mt,"clear");var Gt={getConfig:rt,addNode:ot,addLink:st,addTrend:nt,addAnnotation:it,addNote:dt,addAccelerator:lt,addDeaccelerator:ct,setAnnotationsBox:pt,setSize:ht,startPipeline:xt,addPipelineComponent:ft,updateAxes:gt,getNode:ut,getWardleyData:yt,clear:mt,setAccTitle:Et,getAccTitle:Ct,setDiagramTitle:At,getDiagramTitle:Xt,getAccDescription:Lt,setAccDescription:zt},qt=["Genesis","Custom Built","Product","Commodity"],Ht=y(()=>{var r,e,h,o,d,m,v,g,A,M,b,z;const{themeVariables:a}=H();return{backgroundColor:((r=a.wardley)==null?void 0:r.backgroundColor)??a.background??"#fff",axisColor:((e=a.wardley)==null?void 0:e.axisColor)??"#000",axisTextColor:((h=a.wardley)==null?void 0:h.axisTextColor)??a.primaryTextColor??"#222",gridColor:((o=a.wardley)==null?void 0:o.gridColor)??"rgba(100, 100, 100, 0.2)",componentFill:((d=a.wardley)==null?void 0:d.componentFill)??"#fff",componentStroke:((m=a.wardley)==null?void 0:m.componentStroke)??"#000",componentLabelColor:((v=a.wardley)==null?void 0:v.componentLabelColor)??a.primaryTextColor??"#222",linkStroke:((g=a.wardley)==null?void 0:g.linkStroke)??"#000",evolutionStroke:((A=a.wardley)==null?void 0:A.evolutionStroke)??"#dc3545",annotationStroke:((M=a.wardley)==null?void 0:M.annotationStroke)??"#000",annotationTextColor:((b=a.wardley)==null?void 0:b.annotationTextColor)??a.primaryTextColor??"#222",annotationFill:((z=a.wardley)==null?void 0:z.annotationFill)??a.background??"#fff"}},"getTheme"),jt=y(()=>{const a=H()["wardley-beta"];return{width:(a==null?void 0:a.width)??900,height:(a==null?void 0:a.height)??600,padding:(a==null?void 0:a.padding)??48,nodeRadius:(a==null?void 0:a.nodeRadius)??6,nodeLabelOffset:(a==null?void 0:a.nodeLabelOffset)??8,axisFontSize:(a==null?void 0:a.axisFontSize)??12,labelFontSize:(a==null?void 0:a.labelFontSize)??10,showGrid:(a==null?void 0:a.showGrid)??!1,useMaxWidth:(a==null?void 0:a.useMaxWidth)??!0}},"getConfigValues"),_t=y((a,r,e,h)=>{var K,Q;et.debug(`Rendering Wardley map
|
|
2
2
|
`+a);const o=jt(),d=Ht(),m=o.nodeRadius*1.6,v=h.db,g=v.getWardleyData(),A=v.getDiagramTitle(),M=((K=g.size)==null?void 0:K.width)??o.width,b=((Q=g.size)==null?void 0:Q.height)??o.height,z=Tt(r);z.selectAll("*").remove(),Yt(z,b,M,o.useMaxWidth),z.attr("viewBox",`0 0 ${M} ${b}`);const S=z.append("g").attr("class","wardley-map"),j=z.append("defs");j.append("marker").attr("id",`arrow-${r}`).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerWidth",6).attr("markerHeight",6).attr("orient","auto-start-reverse").append("path").attr("d","M 0 0 L 10 5 L 0 10 z").attr("fill",d.evolutionStroke).attr("stroke","none"),j.append("marker").attr("id",`link-arrow-end-${r}`).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerWidth",5).attr("markerHeight",5).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z").attr("fill",d.linkStroke).attr("stroke","none"),j.append("marker").attr("id",`link-arrow-start-${r}`).attr("viewBox","0 0 10 10").attr("refX",1).attr("refY",5).attr("markerWidth",5).attr("markerHeight",5).attr("orient","auto").append("path").attr("d","M 10 0 L 0 5 L 10 10 z").attr("fill",d.linkStroke).attr("stroke","none"),S.append("rect").attr("class","wardley-background").attr("width",M).attr("height",b).attr("fill",d.backgroundColor);const F=M-o.padding*2,I=b-o.padding*2;A&&S.append("text").attr("class","wardley-title").attr("x",M/2).attr("y",o.padding/2).attr("fill",d.axisTextColor).attr("font-size",o.axisFontSize*1.05).attr("font-weight","bold").attr("text-anchor","middle").attr("dominant-baseline","middle").text(A);const C=y(t=>o.padding+t/100*F,"projectX"),E=y(t=>b-o.padding-t/100*I,"projectY"),W=S.append("g").attr("class","wardley-axes");W.append("line").attr("x1",o.padding).attr("x2",M-o.padding).attr("y1",b-o.padding).attr("y2",b-o.padding).attr("stroke",d.axisColor).attr("stroke-width",1),W.append("line").attr("x1",o.padding).attr("x2",o.padding).attr("y1",o.padding).attr("y2",b-o.padding).attr("stroke",d.axisColor).attr("stroke-width",1);const wt=g.axes.xLabel??"Evolution",bt=g.axes.yLabel??"Visibility";W.append("text").attr("class","wardley-axis-label wardley-axis-label-x").attr("x",o.padding+F/2).attr("y",b-o.padding/4).attr("fill",d.axisTextColor).attr("font-size",o.axisFontSize).attr("font-weight","bold").attr("text-anchor","middle").text(wt),W.append("text").attr("class","wardley-axis-label wardley-axis-label-y").attr("x",o.padding/3).attr("y",o.padding+I/2).attr("fill",d.axisTextColor).attr("font-size",o.axisFontSize).attr("font-weight","bold").attr("text-anchor","middle").attr("transform",`rotate(-90 ${o.padding/3} ${o.padding+I/2})`).text(bt);const O=g.axes.stages&&g.axes.stages.length>0?g.axes.stages:qt;if(O.length>0){const t=S.append("g").attr("class","wardley-stages"),n=g.axes.stageBoundaries,s=[];if(n&&n.length===O.length){let i=0;n.forEach(p=>{s.push({start:i,end:p}),i=p})}else{const i=1/O.length;O.forEach((p,l)=>{s.push({start:l*i,end:(l+1)*i})})}O.forEach((i,p)=>{const l=s[p],x=o.padding+l.start*F,f=o.padding+l.end*F,u=(x+f)/2;p>0&&t.append("line").attr("x1",x).attr("x2",x).attr("y1",o.padding).attr("y2",b-o.padding).attr("stroke","#000").attr("stroke-width",1).attr("stroke-dasharray","5 5").attr("opacity",.8),t.append("text").attr("class","wardley-stage-label").attr("x",u).attr("y",b-o.padding/1.5).attr("fill",d.axisTextColor).attr("font-size",o.axisFontSize-2).attr("text-anchor","middle").text(i)})}if(o.showGrid){const t=S.append("g").attr("class","wardley-grid");for(let n=1;n<4;n++){const s=n/4,i=o.padding+F*s;t.append("line").attr("x1",i).attr("x2",i).attr("y1",o.padding).attr("y2",b-o.padding).attr("stroke",d.gridColor).attr("stroke-dasharray","2 6"),t.append("line").attr("x1",o.padding).attr("x2",M-o.padding).attr("y1",b-o.padding-I*s).attr("y2",b-o.padding-I*s).attr("stroke",d.gridColor).attr("stroke-dasharray","2 6")}}const c=new Map;if(g.nodes.forEach(t=>{c.set(t.id,{x:C(t.x),y:E(t.y),node:t})}),g.pipelines.length>0){const t=S.append("g").attr("class","wardley-pipelines"),n=S.append("g").attr("class","wardley-pipeline-links");g.pipelines.forEach(s=>{if(s.componentIds.length===0)return;const i=s.componentIds.map(f=>({id:f,pos:c.get(f),node:g.nodes.find(u=>u.id===f)})).filter(f=>f.pos&&f.node).sort((f,u)=>f.node.x-u.node.x);for(let f=0;f<i.length-1;f++){const u=i[f],w=i[f+1];n.append("line").attr("class","wardley-pipeline-evolution-link").attr("x1",u.pos.x).attr("y1",u.pos.y).attr("x2",w.pos.x).attr("y2",w.pos.y).attr("stroke",d.linkStroke).attr("stroke-width",1).attr("stroke-dasharray","4 4")}let p=1/0,l=-1/0,x=0;if(s.componentIds.forEach(f=>{const u=c.get(f);u&&(p=Math.min(p,u.x),l=Math.max(l,u.x),x=u.y)}),p!==1/0&&l!==-1/0){const u=o.nodeRadius*4,w=x-u/2,$=c.get(s.nodeId);if($){const X=(p+l)/2;$.x=X,$.y=w-m/6}t.append("rect").attr("class","wardley-pipeline-box").attr("x",p-15).attr("y",w).attr("width",l-p+15*2).attr("height",u).attr("fill","none").attr("stroke",d.axisColor).attr("stroke-width",1.5).attr("rx",4).attr("ry",4)}})}const Z=S.append("g").attr("class","wardley-links"),U=new Map;g.pipelines.forEach(t=>{U.set(t.nodeId,new Set(t.componentIds))});const J=g.links.filter(t=>{if(!c.has(t.source)||!c.has(t.target))return!1;const n=U.get(t.target);return!(n!=null&&n.has(t.source))});Z.selectAll("line").data(J).enter().append("line").attr("class",t=>`wardley-link${t.dashed?" wardley-link--dashed":""}`).attr("x1",t=>{const n=c.get(t.source),s=c.get(t.target),p=g.nodes.find(u=>u.id===t.source).isPipelineParent?m/Math.sqrt(2):o.nodeRadius,l=s.x-n.x,x=s.y-n.y,f=Math.sqrt(l*l+x*x);return n.x+l/f*p}).attr("y1",t=>{const n=c.get(t.source),s=c.get(t.target),p=g.nodes.find(u=>u.id===t.source).isPipelineParent?m/Math.sqrt(2):o.nodeRadius,l=s.x-n.x,x=s.y-n.y,f=Math.sqrt(l*l+x*x);return n.y+x/f*p}).attr("x2",t=>{const n=c.get(t.source),s=c.get(t.target),p=g.nodes.find(u=>u.id===t.target).isPipelineParent?m/Math.sqrt(2):o.nodeRadius,l=n.x-s.x,x=n.y-s.y,f=Math.sqrt(l*l+x*x);return s.x+l/f*p}).attr("y2",t=>{const n=c.get(t.source),s=c.get(t.target),p=g.nodes.find(u=>u.id===t.target).isPipelineParent?m/Math.sqrt(2):o.nodeRadius,l=n.x-s.x,x=n.y-s.y,f=Math.sqrt(l*l+x*x);return s.y+x/f*p}).attr("stroke",d.linkStroke).attr("stroke-width",1).attr("stroke-dasharray",t=>t.dashed?"6 6":null).attr("marker-end",t=>t.flow==="forward"||t.flow==="bidirectional"?`url(#link-arrow-end-${r})`:null).attr("marker-start",t=>t.flow==="backward"||t.flow==="bidirectional"?`url(#link-arrow-start-${r})`:null),Z.selectAll("text").data(J.filter(t=>t.label)).enter().append("text").attr("class","wardley-link-label").attr("x",t=>{const n=c.get(t.source),s=c.get(t.target),i=(n.x+s.x)/2,p=s.y-n.y,l=s.x-n.x,x=Math.sqrt(l*l+p*p),f=8,u=p/x;return i+u*f}).attr("y",t=>{const n=c.get(t.source),s=c.get(t.target),i=(n.y+s.y)/2,p=s.x-n.x,l=s.y-n.y,x=Math.sqrt(p*p+l*l),f=8,u=-p/x;return i+u*f}).attr("fill",d.axisTextColor).attr("font-size",o.labelFontSize).attr("text-anchor","middle").attr("dominant-baseline","middle").attr("transform",t=>{const n=c.get(t.source),s=c.get(t.target),i=(n.x+s.x)/2,p=(n.y+s.y)/2,l=s.x-n.x,x=s.y-n.y,f=Math.sqrt(l*l+x*x),u=8,w=x/f,$=-l/f,X=i+w*u,D=p+$*u;let B=Math.atan2(x,l)*180/Math.PI;return(B>90||B<-90)&&(B+=180),`rotate(${B} ${X} ${D})`}).text(t=>t.label);const kt=S.append("g").attr("class","wardley-trends"),Pt=g.trends.map(t=>{const n=c.get(t.nodeId);if(!n)return null;const s=C(t.targetX),i=E(t.targetY),p=s-n.x,l=i-n.y,x=Math.sqrt(p*p+l*l),f=o.nodeRadius+2,u=x>f?s-p/x*f:s,w=x>f?i-l/x*f:i;return{origin:n,targetX:s,targetY:i,adjustedX2:u,adjustedY2:w}}).filter(t=>t!==null);kt.selectAll("line").data(Pt).enter().append("line").attr("class","wardley-trend").attr("x1",t=>t.origin.x).attr("y1",t=>t.origin.y).attr("x2",t=>t.adjustedX2).attr("y2",t=>t.adjustedY2).attr("stroke",d.evolutionStroke).attr("stroke-width",1).attr("stroke-dasharray","4 4").attr("marker-end",`url(#arrow-${r})`);const L=S.append("g").attr("class","wardley-nodes").selectAll("g").data(g.nodes).enter().append("g").attr("class",t=>["wardley-node",t.className?`wardley-node--${t.className}`:""].filter(Boolean).join(" "));L.filter(t=>t.sourceStrategy==="outsource").append("circle").attr("class","wardley-outsource-overlay").attr("cx",t=>c.get(t.id).x).attr("cy",t=>c.get(t.id).y).attr("r",o.nodeRadius*2).attr("fill","#666").attr("stroke",d.componentStroke).attr("stroke-width",1),L.filter(t=>t.sourceStrategy==="buy").append("circle").attr("class","wardley-buy-overlay").attr("cx",t=>c.get(t.id).x).attr("cy",t=>c.get(t.id).y).attr("r",o.nodeRadius*2).attr("fill","#ccc").attr("stroke",d.componentStroke).attr("stroke-width",1),L.filter(t=>t.sourceStrategy==="build").append("circle").attr("class","wardley-build-overlay").attr("cx",t=>c.get(t.id).x).attr("cy",t=>c.get(t.id).y).attr("r",o.nodeRadius*2).attr("fill","#eee").attr("stroke","#000").attr("stroke-width",1);const T=L.filter(t=>t.sourceStrategy==="market");T.append("circle").attr("class","wardley-market-overlay").attr("cx",t=>c.get(t.id).x).attr("cy",t=>c.get(t.id).y).attr("r",o.nodeRadius*2).attr("fill","white").attr("stroke",d.componentStroke).attr("stroke-width",1),L.filter(t=>!t.isPipelineParent&&t.sourceStrategy!=="market"&&t.className!=="anchor").append("circle").attr("cx",t=>c.get(t.id).x).attr("cy",t=>c.get(t.id).y).attr("r",o.nodeRadius).attr("fill",d.componentFill).attr("stroke",d.componentStroke).attr("stroke-width",1);const _=o.nodeRadius*.7,k=o.nodeRadius*1.2;if(T.append("line").attr("class","wardley-market-line").attr("x1",t=>c.get(t.id).x).attr("y1",t=>c.get(t.id).y-k).attr("x2",t=>c.get(t.id).x-k*Math.cos(Math.PI/6)).attr("y2",t=>c.get(t.id).y+k*Math.sin(Math.PI/6)).attr("stroke",d.componentStroke).attr("stroke-width",1),T.append("line").attr("class","wardley-market-line").attr("x1",t=>c.get(t.id).x-k*Math.cos(Math.PI/6)).attr("y1",t=>c.get(t.id).y+k*Math.sin(Math.PI/6)).attr("x2",t=>c.get(t.id).x+k*Math.cos(Math.PI/6)).attr("y2",t=>c.get(t.id).y+k*Math.sin(Math.PI/6)).attr("stroke",d.componentStroke).attr("stroke-width",1),T.append("line").attr("class","wardley-market-line").attr("x1",t=>c.get(t.id).x+k*Math.cos(Math.PI/6)).attr("y1",t=>c.get(t.id).y+k*Math.sin(Math.PI/6)).attr("x2",t=>c.get(t.id).x).attr("y2",t=>c.get(t.id).y-k).attr("stroke",d.componentStroke).attr("stroke-width",1),T.append("circle").attr("class","wardley-market-dot").attr("cx",t=>c.get(t.id).x).attr("cy",t=>c.get(t.id).y-k).attr("r",_).attr("fill","white").attr("stroke",d.componentStroke).attr("stroke-width",2),T.append("circle").attr("class","wardley-market-dot").attr("cx",t=>c.get(t.id).x-k*Math.cos(Math.PI/6)).attr("cy",t=>c.get(t.id).y+k*Math.sin(Math.PI/6)).attr("r",_).attr("fill","white").attr("stroke",d.componentStroke).attr("stroke-width",2),T.append("circle").attr("class","wardley-market-dot").attr("cx",t=>c.get(t.id).x+k*Math.cos(Math.PI/6)).attr("cy",t=>c.get(t.id).y+k*Math.sin(Math.PI/6)).attr("r",_).attr("fill","white").attr("stroke",d.componentStroke).attr("stroke-width",2),L.filter(t=>t.isPipelineParent===!0).append("rect").attr("x",t=>c.get(t.id).x-m/2).attr("y",t=>c.get(t.id).y-m/2).attr("width",m).attr("height",m).attr("fill",d.componentFill).attr("stroke",d.componentStroke).attr("stroke-width",1),L.filter(t=>t.inertia===!0).append("line").attr("class","wardley-inertia").attr("x1",t=>{const n=c.get(t.id);let s=t.isPipelineParent?m/2+15:o.nodeRadius+15;return t.sourceStrategy&&(s+=o.nodeRadius+10),n.x+s}).attr("y1",t=>{const n=c.get(t.id),s=t.isPipelineParent?m:o.nodeRadius*2;return n.y-s/2}).attr("x2",t=>{const n=c.get(t.id);let s=t.isPipelineParent?m/2+15:o.nodeRadius+15;return t.sourceStrategy&&(s+=o.nodeRadius+10),n.x+s}).attr("y2",t=>{const n=c.get(t.id),s=t.isPipelineParent?m:o.nodeRadius*2;return n.y+s/2}).attr("stroke",d.componentStroke).attr("stroke-width",6),L.append("text").attr("x",t=>{const n=c.get(t.id);if(t.className==="anchor")return t.labelOffsetX!==void 0?n.x+t.labelOffsetX:n.x;let s=o.nodeLabelOffset;t.sourceStrategy&&t.labelOffsetX===void 0&&(s+=10);const i=t.labelOffsetX??s;return n.x+i}).attr("y",t=>{const n=c.get(t.id);if(t.className==="anchor")return t.labelOffsetY!==void 0?n.y+t.labelOffsetY:n.y-3;let s=-o.nodeLabelOffset;t.sourceStrategy&&t.labelOffsetY===void 0&&(s-=10);const i=t.labelOffsetY??s;return n.y+i}).attr("class","wardley-node-label").attr("fill",t=>t.className==="evolved"?d.evolutionStroke:t.className==="anchor"?"#000":d.componentLabelColor).attr("font-size",o.labelFontSize).attr("font-weight",t=>t.className==="anchor"?"bold":"normal").attr("text-anchor",t=>t.className==="anchor"?"middle":"start").attr("dominant-baseline",t=>t.className==="anchor"?"middle":"auto").text(t=>t.label),g.annotations.length>0){const t=S.append("g").attr("class","wardley-annotations");if(g.annotations.forEach(n=>{const s=n.coordinates.map(i=>({x:C(i.x),y:E(i.y)}));if(s.length>1)for(let i=0;i<s.length-1;i++)t.append("line").attr("class","wardley-annotation-line").attr("x1",s[i].x).attr("y1",s[i].y).attr("x2",s[i+1].x).attr("y2",s[i+1].y).attr("stroke",d.axisColor).attr("stroke-width",1.5).attr("stroke-dasharray","4 4");s.forEach(i=>{const p=t.append("g").attr("class","wardley-annotation");p.append("circle").attr("cx",i.x).attr("cy",i.y).attr("r",10).attr("fill","white").attr("stroke",d.axisColor).attr("stroke-width",1.5),p.append("text").attr("x",i.x).attr("y",i.y).attr("text-anchor","middle").attr("dominant-baseline","central").attr("font-size",10).attr("fill",d.axisTextColor).attr("font-weight","bold").text(n.number)})}),g.annotationsBox){let n=C(g.annotationsBox.x),s=E(g.annotationsBox.y);const i=10,p=16,l=11,x=t.append("g").attr("class","wardley-annotations-box"),f=[...g.annotations].filter(w=>w.text).sort((w,$)=>w.number-$.number),u=[];if(f.forEach((w,$)=>{const X=x.append("text").attr("x",n+i).attr("y",s+i+($+1)*p).attr("font-size",l).attr("fill",d.axisTextColor).attr("text-anchor","start").attr("dominant-baseline","middle").text(`${w.number}. ${w.text}`);u.push(X)}),u.length>0){let w=0,$=0;u.forEach(V=>{const G=V.node(),Mt=G.getComputedTextLength();w=Math.max(w,Mt);const Nt=G.getBBox();$=Math.max($,Nt.height)});const X=w+i*2+105,D=f.length*p+i*2+$/2,B=o.padding,vt=M-o.padding-X,St=o.padding,$t=b-o.padding-D;n=Math.max(B,Math.min(n,vt)),s=Math.max(St,Math.min(s,$t)),u.forEach((V,G)=>{V.attr("x",n+i).attr("y",s+i+(G+1)*p)}),x.insert("rect","text").attr("x",n).attr("y",s).attr("width",X).attr("height",D).attr("fill","white").attr("stroke",d.axisColor).attr("stroke-width",1.5).attr("rx",4).attr("ry",4)}}}if(g.notes.length>0){const t=S.append("g").attr("class","wardley-notes");g.notes.forEach(n=>{const s=C(n.x),i=E(n.y);t.append("text").attr("x",s).attr("y",i).attr("text-anchor","start").attr("font-size",11).attr("fill",d.axisTextColor).attr("font-weight","bold").text(n.text)})}if(g.accelerators.length>0){const t=S.append("g").attr("class","wardley-accelerators");g.accelerators.forEach(n=>{const s=C(n.x),i=E(n.y),p=60,l=30,x=20,f=`
|
|
3
3
|
M ${s} ${i-l/2}
|
|
4
4
|
L ${s+p-x} ${i-l/2}
|
package/dist/assets/{xychartDiagram-5P7HB3ND-3qACMhVA.js → xychartDiagram-5P7HB3ND-CGHTq7bt.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{s as gi,g as xi,q as Xt,p as di,a as fi,b as pi,_ as a,l as Yt,I as mi,e as yi,z as bi,D as _t,i as Ai,F as Nt,G as wi,K as Ci,aC as Si,R as Wt}from"./main-
|
|
1
|
+
import{s as gi,g as xi,q as Xt,p as di,a as fi,b as pi,_ as a,l as Yt,I as mi,e as yi,z as bi,D as _t,i as Ai,F as Nt,G as wi,K as Ci,aC as Si,R as Wt}from"./main-uTENWEI_.js";import{i as _i}from"./init-Gi6I4Gst.js";import{o as ki}from"./ordinal-Cboi1Yqb.js";import{l as zt}from"./linear-DIpJR0RD.js";import"./defaultLocale-DX6XiGOO.js";function Ri(e,t,i){e=+e,t=+t,i=(n=arguments.length)<2?(t=e,e=0,1):n<3?1:+i;for(var s=-1,n=Math.max(0,Math.ceil((t-e)/i))|0,o=new Array(n);++s<n;)o[s]=e+s*i;return o}function bt(){var e=ki().unknown(void 0),t=e.domain,i=e.range,s=0,n=1,o,u,p=!1,f=0,T=0,P=.5;delete e.unknown;function _(){var y=t().length,E=n<s,v=E?n:s,L=E?s:n;o=(L-v)/Math.max(1,y-f+T*2),p&&(o=Math.floor(o)),v+=(L-v-o*(y-f))*P,u=o*(1-f),p&&(v=Math.round(v),u=Math.round(u));var I=Ri(y).map(function(m){return v+o*m});return i(E?I.reverse():I)}return e.domain=function(y){return arguments.length?(t(y),_()):t()},e.range=function(y){return arguments.length?([s,n]=y,s=+s,n=+n,_()):[s,n]},e.rangeRound=function(y){return[s,n]=y,s=+s,n=+n,p=!0,_()},e.bandwidth=function(){return u},e.step=function(){return o},e.round=function(y){return arguments.length?(p=!!y,_()):p},e.padding=function(y){return arguments.length?(f=Math.min(1,T=+y),_()):f},e.paddingInner=function(y){return arguments.length?(f=Math.min(1,y),_()):f},e.paddingOuter=function(y){return arguments.length?(T=+y,_()):T},e.align=function(y){return arguments.length?(P=Math.max(0,Math.min(1,y)),_()):P},e.copy=function(){return bt(t(),[s,n]).round(p).paddingInner(f).paddingOuter(T).align(P)},_i.apply(_(),arguments)}var At=function(){var e=a(function(F,h,c,g){for(c=c||{},g=F.length;g--;c[F[g]]=h);return c},"o"),t=[1,10,12,14,16,18,19,21,23],i=[2,6],s=[1,3],n=[1,5],o=[1,6],u=[1,7],p=[1,5,10,12,14,16,18,19,21,23,34,35,36],f=[1,25],T=[1,26],P=[1,28],_=[1,29],y=[1,30],E=[1,31],v=[1,32],L=[1,33],I=[1,34],m=[1,35],R=[1,36],l=[1,37],W=[1,43],O=[1,42],X=[1,47],Y=[1,50],S=[1,10,12,14,16,18,19,21,23,34,35,36],U=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36],b=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36,41,42,43,44,45,46,47,48,49,50],w=[1,64],V={trace:a(function(){},"trace"),yy:{},symbols_:{error:2,start:3,eol:4,XYCHART:5,chartConfig:6,document:7,CHART_ORIENTATION:8,statement:9,title:10,text:11,X_AXIS:12,parseXAxis:13,Y_AXIS:14,parseYAxis:15,LINE:16,plotData:17,BAR:18,acc_title:19,acc_title_value:20,acc_descr:21,acc_descr_value:22,acc_descr_multiline_value:23,SQUARE_BRACES_START:24,commaSeparatedNumbers:25,SQUARE_BRACES_END:26,NUMBER_WITH_DECIMAL:27,COMMA:28,xAxisData:29,bandData:30,ARROW_DELIMITER:31,commaSeparatedTexts:32,yAxisData:33,NEWLINE:34,SEMI:35,EOF:36,alphaNum:37,STR:38,MD_STR:39,alphaNumToken:40,AMP:41,NUM:42,ALPHA:43,PLUS:44,EQUALS:45,MULT:46,DOT:47,BRKT:48,MINUS:49,UNDERSCORE:50,$accept:0,$end:1},terminals_:{2:"error",5:"XYCHART",8:"CHART_ORIENTATION",10:"title",12:"X_AXIS",14:"Y_AXIS",16:"LINE",18:"BAR",19:"acc_title",20:"acc_title_value",21:"acc_descr",22:"acc_descr_value",23:"acc_descr_multiline_value",24:"SQUARE_BRACES_START",26:"SQUARE_BRACES_END",27:"NUMBER_WITH_DECIMAL",28:"COMMA",31:"ARROW_DELIMITER",34:"NEWLINE",35:"SEMI",36:"EOF",38:"STR",39:"MD_STR",41:"AMP",42:"NUM",43:"ALPHA",44:"PLUS",45:"EQUALS",46:"MULT",47:"DOT",48:"BRKT",49:"MINUS",50:"UNDERSCORE"},productions_:[0,[3,2],[3,3],[3,2],[3,1],[6,1],[7,0],[7,2],[9,2],[9,2],[9,2],[9,2],[9,2],[9,3],[9,2],[9,3],[9,2],[9,2],[9,1],[17,3],[25,3],[25,1],[13,1],[13,2],[13,1],[29,1],[29,3],[30,3],[32,3],[32,1],[15,1],[15,2],[15,1],[33,3],[4,1],[4,1],[4,1],[11,1],[11,1],[11,1],[37,1],[37,2],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1]],performAction:a(function(h,c,g,x,C,r,rt){var d=r.length-1;switch(C){case 5:x.setOrientation(r[d]);break;case 9:x.setDiagramTitle(r[d].text.trim());break;case 12:x.setLineData({text:"",type:"text"},r[d]);break;case 13:x.setLineData(r[d-1],r[d]);break;case 14:x.setBarData({text:"",type:"text"},r[d]);break;case 15:x.setBarData(r[d-1],r[d]);break;case 16:this.$=r[d].trim(),x.setAccTitle(this.$);break;case 17:case 18:this.$=r[d].trim(),x.setAccDescription(this.$);break;case 19:this.$=r[d-1];break;case 20:this.$=[Number(r[d-2]),...r[d]];break;case 21:this.$=[Number(r[d])];break;case 22:x.setXAxisTitle(r[d]);break;case 23:x.setXAxisTitle(r[d-1]);break;case 24:x.setXAxisTitle({type:"text",text:""});break;case 25:x.setXAxisBand(r[d]);break;case 26:x.setXAxisRangeData(Number(r[d-2]),Number(r[d]));break;case 27:this.$=r[d-1];break;case 28:this.$=[r[d-2],...r[d]];break;case 29:this.$=[r[d]];break;case 30:x.setYAxisTitle(r[d]);break;case 31:x.setYAxisTitle(r[d-1]);break;case 32:x.setYAxisTitle({type:"text",text:""});break;case 33:x.setYAxisRangeData(Number(r[d-2]),Number(r[d]));break;case 37:this.$={text:r[d],type:"text"};break;case 38:this.$={text:r[d],type:"text"};break;case 39:this.$={text:r[d],type:"markdown"};break;case 40:this.$=r[d];break;case 41:this.$=r[d-1]+""+r[d];break}},"anonymous"),table:[e(t,i,{3:1,4:2,7:4,5:s,34:n,35:o,36:u}),{1:[3]},e(t,i,{4:2,7:4,3:8,5:s,34:n,35:o,36:u}),e(t,i,{4:2,7:4,6:9,3:10,5:s,8:[1,11],34:n,35:o,36:u}),{1:[2,4],9:12,10:[1,13],12:[1,14],14:[1,15],16:[1,16],18:[1,17],19:[1,18],21:[1,19],23:[1,20]},e(p,[2,34]),e(p,[2,35]),e(p,[2,36]),{1:[2,1]},e(t,i,{4:2,7:4,3:21,5:s,34:n,35:o,36:u}),{1:[2,3]},e(p,[2,5]),e(t,[2,7],{4:22,34:n,35:o,36:u}),{11:23,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:I,48:m,49:R,50:l},{11:39,13:38,24:W,27:O,29:40,30:41,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:I,48:m,49:R,50:l},{11:45,15:44,27:X,33:46,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:I,48:m,49:R,50:l},{11:49,17:48,24:Y,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:I,48:m,49:R,50:l},{11:52,17:51,24:Y,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:I,48:m,49:R,50:l},{20:[1,53]},{22:[1,54]},e(S,[2,18]),{1:[2,2]},e(S,[2,8]),e(S,[2,9]),e(U,[2,37],{40:55,41:P,42:_,43:y,44:E,45:v,46:L,47:I,48:m,49:R,50:l}),e(U,[2,38]),e(U,[2,39]),e(b,[2,40]),e(b,[2,42]),e(b,[2,43]),e(b,[2,44]),e(b,[2,45]),e(b,[2,46]),e(b,[2,47]),e(b,[2,48]),e(b,[2,49]),e(b,[2,50]),e(b,[2,51]),e(S,[2,10]),e(S,[2,22],{30:41,29:56,24:W,27:O}),e(S,[2,24]),e(S,[2,25]),{31:[1,57]},{11:59,32:58,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:I,48:m,49:R,50:l},e(S,[2,11]),e(S,[2,30],{33:60,27:X}),e(S,[2,32]),{31:[1,61]},e(S,[2,12]),{17:62,24:Y},{25:63,27:w},e(S,[2,14]),{17:65,24:Y},e(S,[2,16]),e(S,[2,17]),e(b,[2,41]),e(S,[2,23]),{27:[1,66]},{26:[1,67]},{26:[2,29],28:[1,68]},e(S,[2,31]),{27:[1,69]},e(S,[2,13]),{26:[1,70]},{26:[2,21],28:[1,71]},e(S,[2,15]),e(S,[2,26]),e(S,[2,27]),{11:59,32:72,37:24,38:f,39:T,40:27,41:P,42:_,43:y,44:E,45:v,46:L,47:I,48:m,49:R,50:l},e(S,[2,33]),e(S,[2,19]),{25:73,27:w},{26:[2,28]},{26:[2,20]}],defaultActions:{8:[2,1],10:[2,3],21:[2,2],72:[2,28],73:[2,20]},parseError:a(function(h,c){if(c.recoverable)this.trace(h);else{var g=new Error(h);throw g.hash=c,g}},"parseError"),parse:a(function(h){var c=this,g=[0],x=[],C=[null],r=[],rt=this.table,d="",ct=0,It=0,hi=2,Mt=1,li=r.slice.call(arguments,1),D=Object.create(this.lexer),$={yy:{}};for(var ft in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ft)&&($.yy[ft]=this.yy[ft]);D.setInput(h,$.yy),$.yy.lexer=D,$.yy.parser=this,typeof D.yylloc>"u"&&(D.yylloc={});var pt=D.yylloc;r.push(pt);var ci=D.options&&D.options.ranges;typeof $.yy.parseError=="function"?this.parseError=$.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function ui(B){g.length=g.length-2*B,C.length=C.length-B,r.length=r.length-B}a(ui,"popStack");function Vt(){var B;return B=x.pop()||D.lex()||Mt,typeof B!="number"&&(B instanceof Array&&(x=B,B=x.pop()),B=c.symbols_[B]||B),B}a(Vt,"lex");for(var M,q,z,mt,G={},ut,N,Bt,gt;;){if(q=g[g.length-1],this.defaultActions[q]?z=this.defaultActions[q]:((M===null||typeof M>"u")&&(M=Vt()),z=rt[q]&&rt[q][M]),typeof z>"u"||!z.length||!z[0]){var yt="";gt=[];for(ut in rt[q])this.terminals_[ut]&&ut>hi&>.push("'"+this.terminals_[ut]+"'");D.showPosition?yt="Parse error on line "+(ct+1)+`:
|
|
2
2
|
`+D.showPosition()+`
|
|
3
3
|
Expecting `+gt.join(", ")+", got '"+(this.terminals_[M]||M)+"'":yt="Parse error on line "+(ct+1)+": Unexpected "+(M==Mt?"end of input":"'"+(this.terminals_[M]||M)+"'"),this.parseError(yt,{text:D.match,token:this.terminals_[M]||M,line:D.yylineno,loc:pt,expected:gt})}if(z[0]instanceof Array&&z.length>1)throw new Error("Parse Error: multiple actions possible at state: "+q+", token: "+M);switch(z[0]){case 1:g.push(M),C.push(D.yytext),r.push(D.yylloc),g.push(z[1]),M=null,It=D.yyleng,d=D.yytext,ct=D.yylineno,pt=D.yylloc;break;case 2:if(N=this.productions_[z[1]][1],G.$=C[C.length-N],G._$={first_line:r[r.length-(N||1)].first_line,last_line:r[r.length-1].last_line,first_column:r[r.length-(N||1)].first_column,last_column:r[r.length-1].last_column},ci&&(G._$.range=[r[r.length-(N||1)].range[0],r[r.length-1].range[1]]),mt=this.performAction.apply(G,[d,It,ct,$.yy,z[1],C,r].concat(li)),typeof mt<"u")return mt;N&&(g=g.slice(0,-1*N*2),C=C.slice(0,-1*N),r=r.slice(0,-1*N)),g.push(this.productions_[z[1]][0]),C.push(G.$),r.push(G._$),Bt=rt[g[g.length-2]][g[g.length-1]],g.push(Bt);break;case 3:return!0}}return!0},"parse")},k=function(){var F={EOF:1,parseError:a(function(c,g){if(this.yy.parser)this.yy.parser.parseError(c,g);else throw new Error(c)},"parseError"),setInput:a(function(h,c){return this.yy=c||this.yy||{},this._input=h,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:a(function(){var h=this._input[0];this.yytext+=h,this.yyleng++,this.offset++,this.match+=h,this.matched+=h;var c=h.match(/(?:\r\n?|\n).*/g);return c?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),h},"input"),unput:a(function(h){var c=h.length,g=h.split(/(?:\r\n?|\n)/g);this._input=h+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-c),this.offset-=c;var x=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),g.length-1&&(this.yylineno-=g.length-1);var C=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:g?(g.length===x.length?this.yylloc.first_column:0)+x[x.length-g.length].length-g[0].length:this.yylloc.first_column-c},this.options.ranges&&(this.yylloc.range=[C[0],C[0]+this.yyleng-c]),this.yyleng=this.yytext.length,this},"unput"),more:a(function(){return this._more=!0,this},"more"),reject:a(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
|
|
4
4
|
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:a(function(h){this.unput(this.match.slice(h))},"less"),pastInput:a(function(){var h=this.matched.substr(0,this.matched.length-this.match.length);return(h.length>20?"...":"")+h.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:a(function(){var h=this.match;return h.length<20&&(h+=this._input.substr(0,20-h.length)),(h.substr(0,20)+(h.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:a(function(){var h=this.pastInput(),c=new Array(h.length+1).join("-");return h+this.upcomingInput()+`
|
package/dist/index.html
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
gtag('config', 'G-B8B6SJ01KK', { send_page_view: false });
|
|
14
14
|
</script>
|
|
15
15
|
<!-- ga-end -->
|
|
16
|
-
<script type="module" crossorigin src="./assets/main-
|
|
17
|
-
<link rel="stylesheet" crossorigin href="./assets/main-
|
|
16
|
+
<script type="module" crossorigin src="./assets/main-uTENWEI_.js"></script>
|
|
17
|
+
<link rel="stylesheet" crossorigin href="./assets/main-CuJaoUkm.css">
|
|
18
18
|
</head>
|
|
19
19
|
<body>
|
|
20
20
|
<div id="root"></div>
|
|
@@ -81,6 +81,10 @@ exports.AppModule = AppModule = __decorate([
|
|
|
81
81
|
provide: core_1.APP_FILTER,
|
|
82
82
|
useClass: repository_exception_filter_js_1.RepositoryExceptionFilter,
|
|
83
83
|
},
|
|
84
|
+
{
|
|
85
|
+
provide: core_1.APP_GUARD,
|
|
86
|
+
useClass: throttler_1.ThrottlerGuard,
|
|
87
|
+
},
|
|
84
88
|
{
|
|
85
89
|
provide: core_1.APP_INTERCEPTOR,
|
|
86
90
|
useClass: api_id_header_interceptor_js_1.ApiIdHeaderInterceptor,
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.MkdirRequestDto = void 0;
|
|
13
|
+
const class_validator_1 = require("class-validator");
|
|
14
|
+
/**
|
|
15
|
+
* Filesystem MKDIR request body.
|
|
16
|
+
*
|
|
17
|
+
* Security model:
|
|
18
|
+
* - parentPath must be absolute and pass FsService.assertPathAllowed (BLOCKED_PREFIXES)
|
|
19
|
+
* - name must NOT contain path separators ('/' or '\\'), '..', null bytes, or control chars
|
|
20
|
+
* - Recursive parent creation is NOT supported — parent must already exist
|
|
21
|
+
*/
|
|
22
|
+
class MkdirRequestDto {
|
|
23
|
+
/** Absolute path of the parent directory under which the new folder is created. */
|
|
24
|
+
parentPath;
|
|
25
|
+
/**
|
|
26
|
+
* New folder name (no path separators, no '..', no control chars).
|
|
27
|
+
* Length: 1–255. Disallows: '/', '\\', ':', null bytes, control chars (0x00–0x1f).
|
|
28
|
+
* security_reviewer Medium-3: ':' 차단 (NTFS ADS, cross-platform regex로 강화)
|
|
29
|
+
*/
|
|
30
|
+
name;
|
|
31
|
+
}
|
|
32
|
+
exports.MkdirRequestDto = MkdirRequestDto;
|
|
33
|
+
__decorate([
|
|
34
|
+
(0, class_validator_1.IsString)(),
|
|
35
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
36
|
+
(0, class_validator_1.MaxLength)(4096),
|
|
37
|
+
__metadata("design:type", String)
|
|
38
|
+
], MkdirRequestDto.prototype, "parentPath", void 0);
|
|
39
|
+
__decorate([
|
|
40
|
+
(0, class_validator_1.IsString)(),
|
|
41
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
42
|
+
(0, class_validator_1.MaxLength)(255),
|
|
43
|
+
(0, class_validator_1.Matches)(/^[^\\/:\x00-\x1f]+$/, {
|
|
44
|
+
message: 'name must not contain path separators, colon, or control characters',
|
|
45
|
+
}),
|
|
46
|
+
__metadata("design:type", String)
|
|
47
|
+
], MkdirRequestDto.prototype, "name", void 0);
|
|
@@ -15,7 +15,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.FsController = void 0;
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
17
|
const swagger_1 = require("@nestjs/swagger");
|
|
18
|
+
const throttler_1 = require("@nestjs/throttler");
|
|
18
19
|
const fs_service_js_1 = require("./fs.service.js");
|
|
20
|
+
const mkdir_request_dto_js_1 = require("./dto/mkdir-request.dto.js");
|
|
19
21
|
const tree_query_dto_js_1 = require("./dto/tree-query.dto.js");
|
|
20
22
|
let FsController = class FsController {
|
|
21
23
|
fsService;
|
|
@@ -25,6 +27,12 @@ let FsController = class FsController {
|
|
|
25
27
|
// FS.TREE: Filesystem directory tree
|
|
26
28
|
async getTree(query) {
|
|
27
29
|
const data = await this.fsService.getTree(query.path, query.maxDepth ?? 3);
|
|
30
|
+
const quickAccess = this.fsService.resolveQuickAccess();
|
|
31
|
+
return { success: true, data, quickAccess };
|
|
32
|
+
}
|
|
33
|
+
// FS.MKDIR: Create a new directory
|
|
34
|
+
async mkdir(dto) {
|
|
35
|
+
const data = await this.fsService.mkdir(dto.parentPath, dto.name);
|
|
28
36
|
return { success: true, data };
|
|
29
37
|
}
|
|
30
38
|
};
|
|
@@ -37,6 +45,17 @@ __decorate([
|
|
|
37
45
|
__metadata("design:paramtypes", [tree_query_dto_js_1.TreeQueryDto]),
|
|
38
46
|
__metadata("design:returntype", Promise)
|
|
39
47
|
], FsController.prototype, "getTree", null);
|
|
48
|
+
__decorate([
|
|
49
|
+
(0, swagger_1.ApiOperation)({ operationId: 'FS.MKDIR', summary: 'Create a new directory under parentPath' }),
|
|
50
|
+
(0, throttler_1.Throttle)({ default: { ttl: 60000, limit: 20 } }) // security_reviewer Medium-6: write API용 낮은 한도
|
|
51
|
+
,
|
|
52
|
+
(0, common_1.Post)('mkdir'),
|
|
53
|
+
(0, common_1.HttpCode)(201),
|
|
54
|
+
__param(0, (0, common_1.Body)()),
|
|
55
|
+
__metadata("design:type", Function),
|
|
56
|
+
__metadata("design:paramtypes", [mkdir_request_dto_js_1.MkdirRequestDto]),
|
|
57
|
+
__metadata("design:returntype", Promise)
|
|
58
|
+
], FsController.prototype, "mkdir", null);
|
|
40
59
|
exports.FsController = FsController = __decorate([
|
|
41
60
|
(0, swagger_1.ApiTags)('fs'),
|
|
42
61
|
(0, common_1.Controller)('fs'),
|
|
@@ -46,6 +46,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
46
46
|
exports.FsService = void 0;
|
|
47
47
|
const common_1 = require("@nestjs/common");
|
|
48
48
|
const fs_1 = require("fs");
|
|
49
|
+
const os = __importStar(require("os"));
|
|
49
50
|
const nodePath = __importStar(require("path"));
|
|
50
51
|
const project_repository_js_1 = require("../../repository/project.repository.js");
|
|
51
52
|
let FsService = class FsService {
|
|
@@ -55,7 +56,7 @@ let FsService = class FsService {
|
|
|
55
56
|
/** Hard cap regardless of what caller requests. */
|
|
56
57
|
static MAX_DEPTH = 5;
|
|
57
58
|
/**
|
|
58
|
-
* Prefixes that are unconditionally blocked for security.
|
|
59
|
+
* Prefixes that are unconditionally blocked for security (POSIX).
|
|
59
60
|
* Checked against the resolved (real) absolute path.
|
|
60
61
|
*/
|
|
61
62
|
static BLOCKED_PREFIXES = [
|
|
@@ -68,9 +69,29 @@ let FsService = class FsService {
|
|
|
68
69
|
'/sbin',
|
|
69
70
|
'/dev',
|
|
70
71
|
];
|
|
72
|
+
/**
|
|
73
|
+
* Prefixes blocked on Windows.
|
|
74
|
+
* security_reviewer High-2: Win32 전용 BLOCKED_PREFIXES 분리.
|
|
75
|
+
*/
|
|
76
|
+
static BLOCKED_PREFIXES_WIN = [
|
|
77
|
+
'C:\\Windows',
|
|
78
|
+
'C:\\Program Files',
|
|
79
|
+
'C:\\Program Files (x86)',
|
|
80
|
+
'C:\\System Volume Information',
|
|
81
|
+
'C:\\ProgramData',
|
|
82
|
+
'C:\\Recovery',
|
|
83
|
+
];
|
|
71
84
|
constructor(projectRepo) {
|
|
72
85
|
this.projectRepo = projectRepo;
|
|
73
86
|
}
|
|
87
|
+
resolveQuickAccess() {
|
|
88
|
+
const home = os.homedir();
|
|
89
|
+
const crewxWorkspaces = nodePath.join(home, 'crewx');
|
|
90
|
+
return [
|
|
91
|
+
{ key: 'home', path: home, exists: (0, fs_1.existsSync)(home) },
|
|
92
|
+
{ key: 'workspaces', path: crewxWorkspaces, exists: (0, fs_1.existsSync)(crewxWorkspaces) },
|
|
93
|
+
];
|
|
94
|
+
}
|
|
74
95
|
async getTree(rawPath, maxDepth) {
|
|
75
96
|
// 1. Reject relative paths immediately
|
|
76
97
|
if (!nodePath.isAbsolute(rawPath)) {
|
|
@@ -97,6 +118,118 @@ let FsService = class FsService {
|
|
|
97
118
|
// 7. Recursive walk with symlink-loop detection via visited real paths
|
|
98
119
|
return this.walk(absPath, clampedDepth, 0, registeredPaths, new Set());
|
|
99
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Creates a new directory at parentPath/name.
|
|
123
|
+
*
|
|
124
|
+
* security_reviewer 2026-05-07 권고 반영:
|
|
125
|
+
* - High-1: realpathSync로 symlink traversal 방어
|
|
126
|
+
* - High-2: Win32 BLOCKED_PREFIXES 분기 + UNC path 차단
|
|
127
|
+
* - Medium-3: name에 ':' 차단 (NTFS ADS)
|
|
128
|
+
* - Medium-4: Windows reserved device name 차단
|
|
129
|
+
* - Medium-5: name.trim() === '' 차단
|
|
130
|
+
* - Info-9: 성공 시 audit log
|
|
131
|
+
*/
|
|
132
|
+
async mkdir(parentPath, name) {
|
|
133
|
+
// 1. Validate parent path is absolute
|
|
134
|
+
if (!nodePath.isAbsolute(parentPath)) {
|
|
135
|
+
throw new common_1.BadRequestException({ code: 'PATH_NOT_ABSOLUTE', message: 'parentPath must be absolute' });
|
|
136
|
+
}
|
|
137
|
+
const absParent = nodePath.resolve(parentPath);
|
|
138
|
+
// High-1: resolve symlinks BEFORE blocked-prefix check (parent may be a symlink to /etc, etc.)
|
|
139
|
+
let realParent;
|
|
140
|
+
try {
|
|
141
|
+
realParent = (0, fs_1.realpathSync)(absParent);
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
throw new common_1.NotFoundException({ code: 'PARENT_NOT_FOUND', message: 'parent directory does not exist' });
|
|
145
|
+
}
|
|
146
|
+
// Verify the resolved parent is actually a directory (catches files on all platforms)
|
|
147
|
+
if (!(0, fs_1.statSync)(realParent).isDirectory()) {
|
|
148
|
+
throw new common_1.BadRequestException({ code: 'NOT_A_DIRECTORY', message: 'parent is not a directory' });
|
|
149
|
+
}
|
|
150
|
+
this.assertPathAllowed(realParent);
|
|
151
|
+
// 2. Validate name (defense-in-depth — DTO already validates, but server-side recheck)
|
|
152
|
+
if (name === '' || name === '.' || name === '..') {
|
|
153
|
+
throw new common_1.BadRequestException({ code: 'NAME_INVALID', message: 'name must not be empty, "." or ".."' });
|
|
154
|
+
}
|
|
155
|
+
if (name.trim() === '') {
|
|
156
|
+
// Medium-5: blank-only (spaces/tabs only)
|
|
157
|
+
throw new common_1.BadRequestException({ code: 'NAME_INVALID', message: 'name must not be blank' });
|
|
158
|
+
}
|
|
159
|
+
if (name.includes('/') || name.includes('\\') || /[\x00-\x1f]/.test(name)) {
|
|
160
|
+
throw new common_1.BadRequestException({ code: 'NAME_INVALID', message: 'name must not contain separators or control chars' });
|
|
161
|
+
}
|
|
162
|
+
if (process.platform === 'win32') {
|
|
163
|
+
if (name.includes(':')) {
|
|
164
|
+
// Medium-3: NTFS Alternate Data Streams
|
|
165
|
+
throw new common_1.BadRequestException({ code: 'NAME_INVALID', message: 'name must not contain colon on Windows' });
|
|
166
|
+
}
|
|
167
|
+
if (/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\.|$)/i.test(name)) {
|
|
168
|
+
// Medium-4: reserved device names
|
|
169
|
+
throw new common_1.BadRequestException({ code: 'NAME_INVALID', message: 'reserved device name on Windows' });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// 3. Resolve target against real parent and verify containment
|
|
173
|
+
const target = nodePath.join(realParent, name);
|
|
174
|
+
if (!target.startsWith(realParent + nodePath.sep) && target !== realParent) {
|
|
175
|
+
throw new common_1.BadRequestException({ code: 'PATH_ESCAPE', message: 'resolved target escapes parent' });
|
|
176
|
+
}
|
|
177
|
+
// Re-check blocked prefixes against the resolved target
|
|
178
|
+
this.assertPathAllowed(target);
|
|
179
|
+
// 4. Attempt mkdir (NOT recursive — parent must already exist)
|
|
180
|
+
try {
|
|
181
|
+
(0, fs_1.mkdirSync)(target); // recursive not specified: ENOENT if parent missing, EEXIST if already present
|
|
182
|
+
this.logger.log(`[FS.MKDIR] created: ${target}`); // Info-9: audit log
|
|
183
|
+
return { path: target, created: true };
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
const code = err.code;
|
|
187
|
+
if (code === 'EEXIST') {
|
|
188
|
+
// Idempotent: if it already exists AND is a directory, return created: false
|
|
189
|
+
const stat = (0, fs_1.statSync)(target);
|
|
190
|
+
if (stat.isDirectory()) {
|
|
191
|
+
return { path: target, created: false };
|
|
192
|
+
}
|
|
193
|
+
throw new common_1.ConflictException({ code: 'NOT_A_DIRECTORY', message: 'target exists but is not a directory' });
|
|
194
|
+
}
|
|
195
|
+
if (code === 'EACCES' || code === 'EPERM') {
|
|
196
|
+
throw new common_1.ForbiddenException({ code: 'PERMISSION_DENIED', message: 'permission denied' });
|
|
197
|
+
}
|
|
198
|
+
if (code === 'ENOENT') {
|
|
199
|
+
throw new common_1.NotFoundException({ code: 'PARENT_NOT_FOUND', message: 'parent directory does not exist' });
|
|
200
|
+
}
|
|
201
|
+
if (code === 'ENOTDIR') {
|
|
202
|
+
throw new common_1.BadRequestException({ code: 'NOT_A_DIRECTORY', message: 'parent is not a directory' });
|
|
203
|
+
}
|
|
204
|
+
if (code === 'EROFS') {
|
|
205
|
+
throw new common_1.ForbiddenException({ code: 'READ_ONLY_FS', message: 'filesystem is read-only' });
|
|
206
|
+
}
|
|
207
|
+
if (code === 'ENAMETOOLONG') {
|
|
208
|
+
throw new common_1.BadRequestException({ code: 'NAME_TOO_LONG', message: 'path or name too long' });
|
|
209
|
+
}
|
|
210
|
+
this.logger.error(`mkdir failed: ${err}`);
|
|
211
|
+
throw new common_1.InternalServerErrorException({ code: 'MKDIR_FAILED', message: 'failed to create directory' });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Asserts that the given absolute path is not in a blocked system prefix.
|
|
216
|
+
* Used by both getTree and mkdir.
|
|
217
|
+
*
|
|
218
|
+
* security_reviewer High-2/High-3:
|
|
219
|
+
* - OS-specific BLOCKED_PREFIXES (Win32 vs POSIX)
|
|
220
|
+
* - UNC path block on Windows
|
|
221
|
+
* - Uses nodePath.sep for correct separator per OS
|
|
222
|
+
*/
|
|
223
|
+
assertPathAllowed(absPath) {
|
|
224
|
+
if (process.platform === 'win32' && absPath.startsWith('\\\\')) {
|
|
225
|
+
throw new common_1.ForbiddenException({ code: 'PATH_BLOCKED', message: 'UNC paths are not allowed' });
|
|
226
|
+
}
|
|
227
|
+
const prefixes = process.platform === 'win32' ? FsService_1.BLOCKED_PREFIXES_WIN : FsService_1.BLOCKED_PREFIXES;
|
|
228
|
+
if (prefixes.some((p) => absPath === p || absPath.startsWith(p + nodePath.sep))) {
|
|
229
|
+
this.logger.warn(`Blocked path access attempt: ${absPath}`);
|
|
230
|
+
throw new common_1.ForbiddenException({ code: 'PATH_BLOCKED', message: 'access to this path is not allowed' });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
100
233
|
walk(dir, maxDepth, depth, registered, visited) {
|
|
101
234
|
if (depth >= maxDepth)
|
|
102
235
|
return [];
|
|
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.WorkspaceController = void 0;
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
17
|
const swagger_1 = require("@nestjs/swagger");
|
|
18
|
+
const throttler_1 = require("@nestjs/throttler");
|
|
18
19
|
const workspace_service_js_1 = require("./workspace.service.js");
|
|
19
20
|
const switch_workspace_dto_js_1 = require("./dto/switch-workspace.dto.js");
|
|
20
21
|
const create_workspace_dto_js_1 = require("./dto/create-workspace.dto.js");
|
|
@@ -43,6 +44,10 @@ let WorkspaceController = class WorkspaceController {
|
|
|
43
44
|
const data = await this.workspaceService.createWorkspace(dto);
|
|
44
45
|
return { success: true, data };
|
|
45
46
|
}
|
|
47
|
+
// WKS.DELETE: Delete (deregister) workspace
|
|
48
|
+
deleteWorkspace(id) {
|
|
49
|
+
this.workspaceService.deleteWorkspace(id);
|
|
50
|
+
}
|
|
46
51
|
};
|
|
47
52
|
exports.WorkspaceController = WorkspaceController;
|
|
48
53
|
__decorate([
|
|
@@ -76,6 +81,16 @@ __decorate([
|
|
|
76
81
|
__metadata("design:paramtypes", [create_workspace_dto_js_1.CreateWorkspaceDto]),
|
|
77
82
|
__metadata("design:returntype", Promise)
|
|
78
83
|
], WorkspaceController.prototype, "createWorkspace", null);
|
|
84
|
+
__decorate([
|
|
85
|
+
(0, swagger_1.ApiOperation)({ operationId: 'WKS.DELETE', summary: 'Delete a workspace (workspaces table only, FS untouched)' }),
|
|
86
|
+
(0, throttler_1.Throttle)({ default: { ttl: 60000, limit: 20 } }),
|
|
87
|
+
(0, common_1.Delete)(':id'),
|
|
88
|
+
(0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT),
|
|
89
|
+
__param(0, (0, common_1.Param)('id')),
|
|
90
|
+
__metadata("design:type", Function),
|
|
91
|
+
__metadata("design:paramtypes", [String]),
|
|
92
|
+
__metadata("design:returntype", void 0)
|
|
93
|
+
], WorkspaceController.prototype, "deleteWorkspace", null);
|
|
79
94
|
exports.WorkspaceController = WorkspaceController = __decorate([
|
|
80
95
|
(0, swagger_1.ApiTags)('workspaces'),
|
|
81
96
|
(0, common_1.Controller)('workspaces'),
|
|
@@ -183,6 +183,21 @@ let WorkspaceService = WorkspaceService_1 = class WorkspaceService {
|
|
|
183
183
|
this.logger.log(`Workspace switch validated: ${workspacePath}`);
|
|
184
184
|
return { message: 'Workspace switched', workspace };
|
|
185
185
|
}
|
|
186
|
+
/** WKS.DELETE: Deregister a workspace (removes row; FS untouched) */
|
|
187
|
+
deleteWorkspace(id) {
|
|
188
|
+
const target = this.projectRepo.findById(id);
|
|
189
|
+
if (!target) {
|
|
190
|
+
throw new common_1.NotFoundException({ code: 'WORKSPACE_NOT_FOUND', message: 'workspace not found' });
|
|
191
|
+
}
|
|
192
|
+
if (this.currentWorkspaceId === id) {
|
|
193
|
+
throw new common_1.ConflictException({
|
|
194
|
+
code: 'WORKSPACE_IS_CURRENT',
|
|
195
|
+
message: 'cannot delete the current workspace; switch to another one first',
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
this.projectRepo.delete(id);
|
|
199
|
+
this.logger.log(`[WKS.DELETE] removed: ${id} (${target.name})`);
|
|
200
|
+
}
|
|
186
201
|
/** Map a DB row to the API response shape */
|
|
187
202
|
toWorkspaceInfo(row) {
|
|
188
203
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crewx",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.4-rc.2",
|
|
4
4
|
"description": "CrewX — AI agent team dashboard with Electron UI and CLI (Web + Electron + Global CLI)",
|
|
5
5
|
"main": "server.js",
|
|
6
6
|
"bin": {
|
|
@@ -67,17 +67,17 @@
|
|
|
67
67
|
"wink-nlp-utils": "^2.1.0",
|
|
68
68
|
"yargs": "^17.7.0",
|
|
69
69
|
"zod": "^3.22.0",
|
|
70
|
-
"@crewx/cli": "0.8.
|
|
71
|
-
"@crewx/cron": "0.1.8",
|
|
70
|
+
"@crewx/cli": "0.8.4-rc.2",
|
|
72
71
|
"@crewx/doc": "0.1.8",
|
|
73
|
-
"@crewx/memory": "0.1.10",
|
|
74
72
|
"@crewx/knowledge-core": "0.1.6",
|
|
73
|
+
"@crewx/cron": "0.1.8",
|
|
74
|
+
"@crewx/memory": "0.1.10",
|
|
75
|
+
"@crewx/sdk": "0.8.3-rc.12",
|
|
75
76
|
"@crewx/search": "0.1.9",
|
|
76
77
|
"@crewx/workflow": "0.3.17",
|
|
77
|
-
"@crewx/
|
|
78
|
-
"@crewx/sdk": "0.8.3",
|
|
78
|
+
"@crewx/skill": "0.1.8",
|
|
79
79
|
"@crewx/wbs": "0.1.9",
|
|
80
|
-
"@crewx/
|
|
80
|
+
"@crewx/shared": "0.0.5"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@ccusage/codex": "^0.0.1",
|
|
@@ -21,10 +21,12 @@ const DEFAULT_AGENTS = [
|
|
|
21
21
|
role: 'Product/Architecture Planner',
|
|
22
22
|
team: 'core',
|
|
23
23
|
provider: 'cli/claude',
|
|
24
|
-
default_model: 'claude-opus-4-7',
|
|
25
24
|
working_directory: './',
|
|
26
25
|
description: '요구 분석·설계·작업 분해를 담당',
|
|
27
|
-
|
|
26
|
+
inline: {
|
|
27
|
+
model: 'claude-opus-4-7',
|
|
28
|
+
system_prompt: `You are a planner. Break down user goals into concrete,\ntestable steps. Challenge assumptions. Never write code directly.`,
|
|
29
|
+
},
|
|
28
30
|
},
|
|
29
31
|
{
|
|
30
32
|
id: 'developer',
|
|
@@ -32,10 +34,12 @@ const DEFAULT_AGENTS = [
|
|
|
32
34
|
role: 'Implementation Engineer',
|
|
33
35
|
team: 'core',
|
|
34
36
|
provider: 'cli/claude',
|
|
35
|
-
default_model: 'claude-opus-4-7',
|
|
36
37
|
working_directory: './',
|
|
37
38
|
description: '실제 코드 작성과 테스트',
|
|
38
|
-
|
|
39
|
+
inline: {
|
|
40
|
+
model: 'claude-sonnet-4-6',
|
|
41
|
+
system_prompt: `Implement what the planner specifies. Prefer editing\nexisting files. Run tests before reporting done.`,
|
|
42
|
+
},
|
|
39
43
|
},
|
|
40
44
|
{
|
|
41
45
|
id: 'reviewer',
|
|
@@ -43,16 +47,19 @@ const DEFAULT_AGENTS = [
|
|
|
43
47
|
role: 'Code Reviewer',
|
|
44
48
|
team: 'core',
|
|
45
49
|
provider: 'cli/claude',
|
|
46
|
-
default_model: 'claude-opus-4-7',
|
|
47
50
|
working_directory: './',
|
|
48
51
|
description: '코드 품질·보안·가독성 리뷰',
|
|
49
|
-
|
|
52
|
+
inline: {
|
|
53
|
+
model: 'claude-sonnet-4-6',
|
|
54
|
+
system_prompt: `Review diffs for correctness, security, readability.\nCite file:line. Be blunt, not polite.`,
|
|
55
|
+
},
|
|
50
56
|
},
|
|
51
57
|
];
|
|
52
|
-
function
|
|
58
|
+
function indentBlock(text, spaces) {
|
|
59
|
+
const prefix = ' '.repeat(spaces);
|
|
53
60
|
return text
|
|
54
61
|
.split('\n')
|
|
55
|
-
.map((line) =>
|
|
62
|
+
.map((line) => `${prefix}${line}`)
|
|
56
63
|
.join('\n');
|
|
57
64
|
}
|
|
58
65
|
function generateDefaultYaml(agents) {
|
|
@@ -62,11 +69,12 @@ function generateDefaultYaml(agents) {
|
|
|
62
69
|
role: "${a.role}"
|
|
63
70
|
team: "${a.team}"
|
|
64
71
|
provider: "${a.provider}"
|
|
65
|
-
default_model: "${a.default_model}"
|
|
66
72
|
working_directory: "${a.working_directory}"
|
|
67
73
|
description: "${a.description}"
|
|
68
|
-
|
|
69
|
-
${
|
|
74
|
+
inline:
|
|
75
|
+
model: "${a.inline.model}"
|
|
76
|
+
system_prompt: |
|
|
77
|
+
${indentBlock(a.inline.system_prompt, 8)}`)
|
|
70
78
|
.join('\n\n');
|
|
71
79
|
return `# CrewX Agents Configuration
|
|
72
80
|
# Generated by 'crewx init'
|