Need to create a dynamically updating tube with Three.js

I am working on a project requiring a dynamically updating 3D tube. I have successfully set up a cylinder that is dynamically updated with the GUI, but need help turning this into a tube with CSG.

Example of tube
The idea is that both the outer cylinder and the inner cylinder (which is subtracted from the outer) are both controllable so that a user can set the outer diameter and the inner diameter.

Here is a code pen with my approach to creating the outer cylinder, if anyone could give me any tips for using CSG to get the desired result, or if there is a better approach to the desired end product, I would greatly appreciate it!

    var BoxGeometry,
    gui,
                BufferGeometry,
                CapsuleGeometry,
                CircleGeometry,
                Color,
                ConeGeometry,
                Curve,
                CylinderGeometry,
                DirectionalLight,
                DodecahedronGeometry,
                DoubleSide,
                ExtrudeGeometry,
                Float32BufferAttribute,
                Group,
                IcosahedronGeometry,
                LatheGeometry,
                LineSegments,
                LineBasicMaterial,
                Mesh,
                MeshPhongMaterial,
                OctahedronGeometry,
                PerspectiveCamera,
                PlaneGeometry,
                RingGeometry,
                Scene,
                Shape,
                ShapeGeometry,
                SphereGeometry,
                TetrahedronGeometry,
                TorusGeometry,
                TorusKnotGeometry,
                TubeGeometry,
                Vector2,
                Vector3,
                WireframeGeometry,
                WebGLRenderer,
        ThreeBSP;




    const twoPi = Math.PI * 2;
    function updateGroupGeometry( mesh, geometry ) {

                mesh.children[ 0 ].geometry.dispose();
                mesh.children[ 1 ].geometry.dispose();

                mesh.children[ 0 ].geometry = new THREE.WireframeGeometry( geometry );
                mesh.children[ 1 ].geometry = geometry;

                // these do not update nicely together if shared

            }
    const guis = {

    CylinderGeometry: function( mesh ) {

                    const data = {
                        radiusTop: 5,
                        radiusBottom: 5,
                        height: 10,
                        radialSegments:40,
                        heightSegments: 1,
                        openEnded: false,
                        thetaStart: 0,
                        thetaLength: twoPi
                    };

                    function generateGeometry() {
          
                        updateGroupGeometry( mesh,
                            new THREE.CylinderGeometry(
                                data.radiusTop,
                                data.radiusTop,
                                data.height,
                                data.radialSegments,
                                data.heightSegments,
                                data.openEnded,
                                data.thetaStart,
                                data.thetaLength
                            )
                        );
                    }

                    const folder = gui.addFolder( 'THREE.CylinderGeometry' );

                    folder.add( data, 'radiusTop', 0, 30 ).onChange( generateGeometry     );
                    
                    folder.add( data, 'height', 1, 50 ).onChange( generateGeometry );
                    


                    generateGeometry();

                },
     }
  
     function chooseFromHash( mesh ) {

                const selectedGeometry = 'CylinderGeometry';
       

                if ( guis[ selectedGeometry ] !== undefined ) {

                    guis[ selectedGeometry ]( mesh );
          

                }

            }


    gui = new dat.GUI();

            const scene = new THREE.Scene();
            scene.background = new THREE.Color( 0x444444 );

            const camera = new THREE.PerspectiveCamera( 75, window.innerWidth /      window.innerHeight, 0.1, 50 );
            camera.position.z = 30;

            const renderer = new THREE.WebGLRenderer( { antialias: true } );
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );

            const orbit = new THREE.OrbitControls( camera, renderer.domElement );
            orbit.enableZoom = false;

            const lights = [];
            lights[ 0 ] = new THREE.DirectionalLight( 0xffffff, 3 );
            lights[ 1 ] = new THREE.DirectionalLight( 0xffffff, 3 );
            lights[ 2 ] = new THREE.DirectionalLight( 0xffffff, 3 );

            lights[ 0 ].position.set( 0, 200, 0 );
            lights[ 1 ].position.set( 100, 200, 100 );
            lights[ 2 ].position.set( - 100, - 200, - 100 );

            scene.add( lights[ 0 ] );
            scene.add( lights[ 1 ] );
            scene.add( lights[ 2 ] );

            const group = new THREE.Group();


            const geometry = new THREE.BufferGeometry();
      
            geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [], 3 ) );


            const lineMaterial = new THREE.LineBasicMaterial( { color: 0xffffff, transparent:   true, opacity: 0.5 } );
            const meshMaterial = new THREE.MeshPhongMaterial( { color: 0x156289, emissive:   0x072534, flatShading: true } );

            group.add( new THREE.LineSegments( geometry, lineMaterial ) );
            group.add( new THREE.Mesh( geometry, meshMaterial ) );


            
    chooseFromHash( group );



            scene.add( group );
            // scene.add(group2)

            function render() {

                requestAnimationFrame( render );

                //group.rotation.x += 0.005;
                //group.rotation.y += 0.005;

                renderer.render( scene, camera );

            }

            window.addEventListener( 'resize', function () {

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth, window.innerHeight );

            }, false );

            render();

Codepen