driftdetect-dashboard 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/assets/main-DQAs4VF9.js +59 -0
- package/dist/client/assets/main-DQAs4VF9.js.map +1 -0
- package/dist/client/assets/main-Du5_09U3.css +2 -0
- package/dist/client/index.html +19 -0
- package/dist/server/api-routes.d.ts +50 -0
- package/dist/server/api-routes.d.ts.map +1 -0
- package/dist/server/api-routes.js +478 -0
- package/dist/server/api-routes.js.map +1 -0
- package/dist/server/dashboard-server.d.ts +64 -0
- package/dist/server/dashboard-server.d.ts.map +1 -0
- package/dist/server/dashboard-server.js +154 -0
- package/dist/server/dashboard-server.js.map +1 -0
- package/dist/server/drift-data-reader.d.ts +411 -0
- package/dist/server/drift-data-reader.d.ts.map +1 -0
- package/dist/server/drift-data-reader.js +1151 -0
- package/dist/server/drift-data-reader.js.map +1 -0
- package/dist/server/express-app.d.ts +24 -0
- package/dist/server/express-app.d.ts.map +1 -0
- package/dist/server/express-app.js +74 -0
- package/dist/server/express-app.js.map +1 -0
- package/dist/server/index.d.ts +20 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +14 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/pattern-watcher.d.ts +55 -0
- package/dist/server/pattern-watcher.d.ts.map +1 -0
- package/dist/server/pattern-watcher.js +157 -0
- package/dist/server/pattern-watcher.js.map +1 -0
- package/dist/server/websocket-server.d.ts +83 -0
- package/dist/server/websocket-server.d.ts.map +1 -0
- package/dist/server/websocket-server.js +189 -0
- package/dist/server/websocket-server.js.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com
|
|
2
|
+
*/*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,system-ui,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:JetBrains Mono,Fira Code,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}html{font-family:Inter,system-ui,sans-serif}code,pre{font-family:JetBrains Mono,Fira Code,monospace}.badge-error{border-width:1px;border-color:#ef44444d;background-color:#ef444433;--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.badge-warning{border-width:1px;border-color:#eab3084d;background-color:#eab30833;--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.badge-info{border-width:1px;border-color:#3b82f64d;background-color:#3b82f633;--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.badge-hint{border-width:1px;border-color:#6b72804d;background-color:#6b728033;--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.badge-discovered{border-width:1px;border-color:#8b5cf64d;background-color:#8b5cf633;--tw-text-opacity: 1;color:rgb(139 92 246 / var(--tw-text-opacity, 1))}.badge-approved{border-width:1px;border-color:#22c55e4d;background-color:#22c55e33;--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.badge-ignored{border-width:1px;border-color:#6b72804d;background-color:#6b728033;--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.card{border-radius:.5rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1));padding:1rem}.btn{border-radius:.375rem;padding:.5rem 1rem;font-weight:500;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.btn-primary{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-primary:hover{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.btn-secondary{--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(248 250 252 / var(--tw-text-opacity, 1))}.btn-secondary:hover{background-color:#94a3b833}.btn-danger{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-danger:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.-right-1{right:-.25rem}.-top-1{top:-.25rem}.left-3{left:.75rem}.top-1\/2{top:50%}.top-4{top:1rem}.z-10{z-index:10}.z-50{z-index:50}.mx-2{margin-left:.5rem;margin-right:.5rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.ml-1{margin-left:.25rem}.ml-10{margin-left:2.5rem}.ml-14{margin-left:3.5rem}.ml-2{margin-left:.5rem}.ml-6{margin-left:1.5rem}.ml-7{margin-left:1.75rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1\.5{height:.375rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-8{height:2rem}.h-\[60vh\]{height:60vh}.h-full{height:100%}.max-h-32{max-height:8rem}.max-h-48{max-height:12rem}.max-h-64{max-height:16rem}.max-h-\[600px\]{max-height:600px}.max-h-\[90vh\]{max-height:90vh}.max-h-\[calc\(100vh-400px\)\]{max-height:calc(100vh - 400px)}.min-h-screen{min-height:100vh}.w-12{width:3rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-80{width:20rem}.w-96{width:24rem}.w-full{width:100%}.min-w-0{min-width:0px}.max-w-3xl{max-width:48rem}.max-w-5xl{max-width:64rem}.max-w-md{max-width:28rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0\.5{--tw-translate-x: .125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-6{--tw-translate-x: 1.5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes ping{75%,to{transform:scale(2);opacity:0}}.animate-ping{animation:ping 1s cubic-bezier(0,0,.2,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-pointer{cursor:pointer}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-blue-500{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.border-blue-500\/20{border-color:#3b82f633}.border-blue-500\/30{border-color:#3b82f64d}.border-dark-border{--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity, 1))}.border-dark-border\/30{border-color:#3341554d}.border-dark-border\/50{border-color:#33415580}.border-dark-muted\/20{border-color:#94a3b833}.border-dark-muted\/30{border-color:#94a3b84d}.border-severity-error\/20{border-color:#ef444433}.border-severity-error\/30{border-color:#ef44444d}.border-severity-info\/30{border-color:#3b82f64d}.border-severity-warning\/20{border-color:#eab30833}.border-severity-warning\/30{border-color:#eab3084d}.border-status-approved\/20{border-color:#22c55e33}.border-transparent{border-color:transparent}.border-t-transparent{border-top-color:transparent}.bg-amber-500\/10{background-color:#f59e0b1a}.bg-black\/60{background-color:#0009}.bg-blue-400{--tw-bg-opacity: 1;background-color:rgb(96 165 250 / var(--tw-bg-opacity, 1))}.bg-blue-400\/10{background-color:#60a5fa1a}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-blue-500\/10{background-color:#3b82f61a}.bg-blue-500\/20{background-color:#3b82f633}.bg-cyan-500\/10{background-color:#06b6d41a}.bg-dark-bg{--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity, 1))}.bg-dark-bg\/50{background-color:#0f172a80}.bg-dark-border{--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity, 1))}.bg-dark-muted{--tw-bg-opacity: 1;background-color:rgb(148 163 184 / var(--tw-bg-opacity, 1))}.bg-dark-muted\/10{background-color:#94a3b81a}.bg-dark-surface{--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.bg-gray-500\/10{background-color:#6b72801a}.bg-green-400\/10{background-color:#4ade801a}.bg-green-500\/10{background-color:#22c55e1a}.bg-orange-400\/10{background-color:#fb923c1a}.bg-orange-500\/10{background-color:#f973161a}.bg-pink-500\/10{background-color:#ec48991a}.bg-purple-500\/10{background-color:#a855f71a}.bg-red-400\/10{background-color:#f871711a}.bg-red-500\/10{background-color:#ef44441a}.bg-severity-error{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-severity-error\/10{background-color:#ef44441a}.bg-severity-error\/20{background-color:#ef444433}.bg-severity-info\/10{background-color:#3b82f61a}.bg-severity-info\/20{background-color:#3b82f633}.bg-severity-warning{--tw-bg-opacity: 1;background-color:rgb(234 179 8 / var(--tw-bg-opacity, 1))}.bg-severity-warning\/10{background-color:#eab3081a}.bg-severity-warning\/20{background-color:#eab30833}.bg-slate-500\/10{background-color:#64748b1a}.bg-status-approved{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-status-approved\/10{background-color:#22c55e1a}.bg-teal-500\/10{background-color:#14b8a61a}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-yellow-400\/10{background-color:#facc151a}.bg-yellow-500\/10{background-color:#eab3081a}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-3{padding-bottom:.75rem}.pl-10{padding-left:2.5rem}.pl-3{padding-left:.75rem}.pr-2{padding-right:.5rem}.pt-0{padding-top:0}.pt-4{padding-top:1rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:JetBrains Mono,Fira Code,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-wide{letter-spacing:.025em}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-cyan-400{--tw-text-opacity: 1;color:rgb(34 211 238 / var(--tw-text-opacity, 1))}.text-dark-border{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-dark-muted{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-dark-text{--tw-text-opacity: 1;color:rgb(248 250 252 / var(--tw-text-opacity, 1))}.text-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.text-fuchsia-400{--tw-text-opacity: 1;color:rgb(232 121 249 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.text-indigo-400{--tw-text-opacity: 1;color:rgb(129 140 248 / var(--tw-text-opacity, 1))}.text-lime-400{--tw-text-opacity: 1;color:rgb(163 230 53 / var(--tw-text-opacity, 1))}.text-neutral-400{--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}.text-orange-400{--tw-text-opacity: 1;color:rgb(251 146 60 / var(--tw-text-opacity, 1))}.text-pink-400{--tw-text-opacity: 1;color:rgb(244 114 182 / var(--tw-text-opacity, 1))}.text-purple-400{--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-rose-400{--tw-text-opacity: 1;color:rgb(251 113 133 / var(--tw-text-opacity, 1))}.text-severity-error{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-severity-hint{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-severity-info{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-severity-warning{--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-status-approved{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-teal-400{--tw-text-opacity: 1;color:rgb(45 212 191 / var(--tw-text-opacity, 1))}.text-yellow-400{--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.line-through{text-decoration-line:line-through}.opacity-50{opacity:.5}.opacity-75{opacity:.75}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.scrollbar-dark{scrollbar-width:thin;scrollbar-color:#334155 transparent}.scrollbar-dark::-webkit-scrollbar{width:8px;height:8px}.scrollbar-dark::-webkit-scrollbar-track{background:transparent}.scrollbar-dark::-webkit-scrollbar-thumb{background-color:#334155;border-radius:4px}.scrollbar-dark::-webkit-scrollbar-thumb:hover{background-color:#94a3b8}.hover\:border-dark-border:hover{--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity, 1))}.hover\:border-dark-muted:hover{--tw-border-opacity: 1;border-color:rgb(148 163 184 / var(--tw-border-opacity, 1))}.hover\:bg-dark-border\/10:hover{background-color:#3341551a}.hover\:bg-dark-border\/20:hover{background-color:#33415533}.hover\:bg-dark-border\/30:hover{background-color:#3341554d}.hover\:bg-dark-border\/50:hover{background-color:#33415580}.hover\:bg-dark-surface:hover{--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.hover\:bg-severity-warning\/20:hover{background-color:#eab30833}.hover\:bg-status-approved\/20:hover{background-color:#22c55e33}.hover\:text-blue-300:hover{--tw-text-opacity: 1;color:rgb(147 197 253 / var(--tw-text-opacity, 1))}.hover\:text-dark-text:hover{--tw-text-opacity: 1;color:rgb(248 250 252 / var(--tw-text-opacity, 1))}.hover\:text-severity-error:hover{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.focus\:border-blue-500:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.group:hover .group-hover\:scale-110{--tw-scale-x: 1.1;--tw-scale-y: 1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}@media (min-width: 768px){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width: 1024px){.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" class="dark">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Drift Dashboard</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
9
|
+
<link
|
|
10
|
+
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
|
|
11
|
+
rel="stylesheet"
|
|
12
|
+
/>
|
|
13
|
+
<script type="module" crossorigin src="/assets/main-DQAs4VF9.js"></script>
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/assets/main-Du5_09U3.css">
|
|
15
|
+
</head>
|
|
16
|
+
<body class="bg-dark-bg text-dark-text">
|
|
17
|
+
<div id="root"></div>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Routes for the Drift Dashboard
|
|
3
|
+
*
|
|
4
|
+
* Provides REST API endpoints for patterns, violations, files, stats, and config.
|
|
5
|
+
*
|
|
6
|
+
* @requirements 8.1 - GET `/api/patterns` to list all patterns
|
|
7
|
+
* @requirements 8.2 - GET `/api/patterns/:id` to get pattern details with locations
|
|
8
|
+
* @requirements 8.3 - POST `/api/patterns/:id/approve` to approve a pattern
|
|
9
|
+
* @requirements 8.4 - POST `/api/patterns/:id/ignore` to ignore a pattern
|
|
10
|
+
* @requirements 8.5 - DELETE `/api/patterns/:id` to delete a pattern
|
|
11
|
+
* @requirements 8.6 - GET `/api/violations` to list all violations
|
|
12
|
+
* @requirements 8.7 - GET `/api/files` to get the file tree
|
|
13
|
+
* @requirements 8.8 - GET `/api/files/:path` to get patterns and violations for a specific file
|
|
14
|
+
* @requirements 8.9 - GET `/api/stats` to get overview statistics
|
|
15
|
+
* @requirements 8.10 - GET `/api/config` to get configuration
|
|
16
|
+
* @requirements 8.11 - PUT `/api/config` to update configuration
|
|
17
|
+
* @requirements 8.12 - Return appropriate HTTP status codes and error messages
|
|
18
|
+
*/
|
|
19
|
+
import { Router, type Request, type Response, type NextFunction } from 'express';
|
|
20
|
+
import { DriftDataReader } from './drift-data-reader.js';
|
|
21
|
+
export interface ApiError extends Error {
|
|
22
|
+
statusCode: number;
|
|
23
|
+
}
|
|
24
|
+
export declare class NotFoundError extends Error implements ApiError {
|
|
25
|
+
statusCode: number;
|
|
26
|
+
constructor(message: string);
|
|
27
|
+
}
|
|
28
|
+
export declare class BadRequestError extends Error implements ApiError {
|
|
29
|
+
statusCode: number;
|
|
30
|
+
constructor(message: string);
|
|
31
|
+
}
|
|
32
|
+
export declare class InternalServerError extends Error implements ApiError {
|
|
33
|
+
statusCode: number;
|
|
34
|
+
constructor(message: string);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Create API routes for the dashboard
|
|
38
|
+
* @param reader - DriftDataReader instance for accessing drift data
|
|
39
|
+
*/
|
|
40
|
+
export declare function createApiRoutes(reader: DriftDataReader): Router;
|
|
41
|
+
/**
|
|
42
|
+
* Error handling middleware for API routes
|
|
43
|
+
* @requirements 8.12 - Return appropriate HTTP status codes and error messages
|
|
44
|
+
*/
|
|
45
|
+
export declare function errorHandler(err: Error | ApiError, _req: Request, res: Response, _next: NextFunction): void;
|
|
46
|
+
/**
|
|
47
|
+
* 404 handler for unknown routes
|
|
48
|
+
*/
|
|
49
|
+
export declare function notFoundHandler(req: Request, res: Response): void;
|
|
50
|
+
//# sourceMappingURL=api-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-routes.d.ts","sourceRoot":"","sources":["../../src/server/api-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,MAAM,EAAE,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AACjF,OAAO,EAAE,eAAe,EAA4D,MAAM,wBAAwB,CAAC;AAMnH,MAAM,WAAW,QAAS,SAAQ,KAAK;IACrC,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD,qBAAa,aAAc,SAAQ,KAAM,YAAW,QAAQ;IAC1D,UAAU,SAAO;gBACL,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,eAAgB,SAAQ,KAAM,YAAW,QAAQ;IAC5D,UAAU,SAAO;gBACL,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,mBAAoB,SAAQ,KAAM,YAAW,QAAQ;IAChE,UAAU,SAAO;gBACL,OAAO,EAAE,MAAM;CAI5B;AAMD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAib/D;AAMD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,KAAK,GAAG,QAAQ,EACrB,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,YAAY,GAClB,IAAI,CAeN;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CAMjE"}
|
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Routes for the Drift Dashboard
|
|
3
|
+
*
|
|
4
|
+
* Provides REST API endpoints for patterns, violations, files, stats, and config.
|
|
5
|
+
*
|
|
6
|
+
* @requirements 8.1 - GET `/api/patterns` to list all patterns
|
|
7
|
+
* @requirements 8.2 - GET `/api/patterns/:id` to get pattern details with locations
|
|
8
|
+
* @requirements 8.3 - POST `/api/patterns/:id/approve` to approve a pattern
|
|
9
|
+
* @requirements 8.4 - POST `/api/patterns/:id/ignore` to ignore a pattern
|
|
10
|
+
* @requirements 8.5 - DELETE `/api/patterns/:id` to delete a pattern
|
|
11
|
+
* @requirements 8.6 - GET `/api/violations` to list all violations
|
|
12
|
+
* @requirements 8.7 - GET `/api/files` to get the file tree
|
|
13
|
+
* @requirements 8.8 - GET `/api/files/:path` to get patterns and violations for a specific file
|
|
14
|
+
* @requirements 8.9 - GET `/api/stats` to get overview statistics
|
|
15
|
+
* @requirements 8.10 - GET `/api/config` to get configuration
|
|
16
|
+
* @requirements 8.11 - PUT `/api/config` to update configuration
|
|
17
|
+
* @requirements 8.12 - Return appropriate HTTP status codes and error messages
|
|
18
|
+
*/
|
|
19
|
+
import { Router } from 'express';
|
|
20
|
+
import { DriftDataReader } from './drift-data-reader.js';
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Error Classes
|
|
23
|
+
// ============================================================================
|
|
24
|
+
export class NotFoundError extends Error {
|
|
25
|
+
statusCode = 404;
|
|
26
|
+
constructor(message) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = 'NotFoundError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export class BadRequestError extends Error {
|
|
32
|
+
statusCode = 400;
|
|
33
|
+
constructor(message) {
|
|
34
|
+
super(message);
|
|
35
|
+
this.name = 'BadRequestError';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class InternalServerError extends Error {
|
|
39
|
+
statusCode = 500;
|
|
40
|
+
constructor(message) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.name = 'InternalServerError';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// API Routes Factory
|
|
47
|
+
// ============================================================================
|
|
48
|
+
/**
|
|
49
|
+
* Create API routes for the dashboard
|
|
50
|
+
* @param reader - DriftDataReader instance for accessing drift data
|
|
51
|
+
*/
|
|
52
|
+
export function createApiRoutes(reader) {
|
|
53
|
+
const router = Router();
|
|
54
|
+
// ==========================================================================
|
|
55
|
+
// Pattern Routes
|
|
56
|
+
// ==========================================================================
|
|
57
|
+
/**
|
|
58
|
+
* GET /api/patterns - List all patterns with optional filters
|
|
59
|
+
* @requirements 8.1
|
|
60
|
+
*/
|
|
61
|
+
router.get('/patterns', async (req, res, next) => {
|
|
62
|
+
try {
|
|
63
|
+
const query = {};
|
|
64
|
+
if (req.query['category']) {
|
|
65
|
+
query.category = req.query['category'];
|
|
66
|
+
}
|
|
67
|
+
if (req.query['status']) {
|
|
68
|
+
query.status = req.query['status'];
|
|
69
|
+
}
|
|
70
|
+
if (req.query['minConfidence']) {
|
|
71
|
+
query.minConfidence = parseFloat(req.query['minConfidence']);
|
|
72
|
+
}
|
|
73
|
+
if (req.query['search']) {
|
|
74
|
+
query.search = req.query['search'];
|
|
75
|
+
}
|
|
76
|
+
const patterns = await reader.getPatterns(query);
|
|
77
|
+
res.json(patterns);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
next(error);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
/**
|
|
84
|
+
* GET /api/patterns/:id - Get pattern with locations
|
|
85
|
+
* @requirements 8.2
|
|
86
|
+
*/
|
|
87
|
+
router.get('/patterns/:id', async (req, res, next) => {
|
|
88
|
+
try {
|
|
89
|
+
const { id } = req.params;
|
|
90
|
+
if (!id) {
|
|
91
|
+
throw new BadRequestError('Pattern ID is required');
|
|
92
|
+
}
|
|
93
|
+
const pattern = await reader.getPattern(id);
|
|
94
|
+
if (!pattern) {
|
|
95
|
+
throw new NotFoundError(`Pattern not found: ${id}`);
|
|
96
|
+
}
|
|
97
|
+
res.json(pattern);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
next(error);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
/**
|
|
104
|
+
* POST /api/patterns/:id/approve - Approve a pattern
|
|
105
|
+
* @requirements 8.3
|
|
106
|
+
*/
|
|
107
|
+
router.post('/patterns/:id/approve', async (req, res, next) => {
|
|
108
|
+
try {
|
|
109
|
+
const { id } = req.params;
|
|
110
|
+
if (!id) {
|
|
111
|
+
throw new BadRequestError('Pattern ID is required');
|
|
112
|
+
}
|
|
113
|
+
await reader.approvePattern(id);
|
|
114
|
+
res.json({ success: true, message: `Pattern ${id} approved` });
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
if (error instanceof Error && error.message.includes('not found')) {
|
|
118
|
+
next(new NotFoundError(error.message));
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
next(error);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
/**
|
|
126
|
+
* POST /api/patterns/:id/ignore - Ignore a pattern
|
|
127
|
+
* @requirements 8.4
|
|
128
|
+
*/
|
|
129
|
+
router.post('/patterns/:id/ignore', async (req, res, next) => {
|
|
130
|
+
try {
|
|
131
|
+
const { id } = req.params;
|
|
132
|
+
if (!id) {
|
|
133
|
+
throw new BadRequestError('Pattern ID is required');
|
|
134
|
+
}
|
|
135
|
+
await reader.ignorePattern(id);
|
|
136
|
+
res.json({ success: true, message: `Pattern ${id} ignored` });
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
if (error instanceof Error && error.message.includes('not found')) {
|
|
140
|
+
next(new NotFoundError(error.message));
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
next(error);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
/**
|
|
148
|
+
* POST /api/patterns/bulk-approve - Bulk approve multiple patterns
|
|
149
|
+
* Accepts an array of pattern IDs to approve at once
|
|
150
|
+
*/
|
|
151
|
+
router.post('/patterns/bulk-approve', async (req, res, next) => {
|
|
152
|
+
try {
|
|
153
|
+
const { ids } = req.body;
|
|
154
|
+
if (!ids || !Array.isArray(ids) || ids.length === 0) {
|
|
155
|
+
throw new BadRequestError('Array of pattern IDs is required');
|
|
156
|
+
}
|
|
157
|
+
const results = [];
|
|
158
|
+
for (const id of ids) {
|
|
159
|
+
try {
|
|
160
|
+
await reader.approvePattern(id);
|
|
161
|
+
results.push({ id, success: true });
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
results.push({
|
|
165
|
+
id,
|
|
166
|
+
success: false,
|
|
167
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const successCount = results.filter(r => r.success).length;
|
|
172
|
+
res.json({
|
|
173
|
+
success: true,
|
|
174
|
+
message: `Approved ${successCount} of ${ids.length} patterns`,
|
|
175
|
+
results
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
next(error);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
/**
|
|
183
|
+
* DELETE /api/patterns/:id - Delete a pattern
|
|
184
|
+
* @requirements 8.5
|
|
185
|
+
*/
|
|
186
|
+
router.delete('/patterns/:id', async (req, res, next) => {
|
|
187
|
+
try {
|
|
188
|
+
const { id } = req.params;
|
|
189
|
+
if (!id) {
|
|
190
|
+
throw new BadRequestError('Pattern ID is required');
|
|
191
|
+
}
|
|
192
|
+
await reader.deletePattern(id);
|
|
193
|
+
res.json({ success: true, message: `Pattern ${id} deleted` });
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
if (error instanceof Error && error.message.includes('not found')) {
|
|
197
|
+
next(new NotFoundError(error.message));
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
next(error);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
// ==========================================================================
|
|
205
|
+
// Violation Routes
|
|
206
|
+
// ==========================================================================
|
|
207
|
+
/**
|
|
208
|
+
* GET /api/violations - List all violations with optional filters
|
|
209
|
+
* @requirements 8.6
|
|
210
|
+
*/
|
|
211
|
+
router.get('/violations', async (req, res, next) => {
|
|
212
|
+
try {
|
|
213
|
+
const query = {};
|
|
214
|
+
if (req.query['severity']) {
|
|
215
|
+
query.severity = req.query['severity'];
|
|
216
|
+
}
|
|
217
|
+
if (req.query['file']) {
|
|
218
|
+
query.file = req.query['file'];
|
|
219
|
+
}
|
|
220
|
+
if (req.query['patternId']) {
|
|
221
|
+
query.patternId = req.query['patternId'];
|
|
222
|
+
}
|
|
223
|
+
if (req.query['search']) {
|
|
224
|
+
query.search = req.query['search'];
|
|
225
|
+
}
|
|
226
|
+
const violations = await reader.getViolations(query);
|
|
227
|
+
res.json(violations);
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
next(error);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
/**
|
|
234
|
+
* GET /api/snippet - Get code snippet for a file location
|
|
235
|
+
*/
|
|
236
|
+
router.get('/snippet', async (req, res, next) => {
|
|
237
|
+
try {
|
|
238
|
+
const file = req.query['file'];
|
|
239
|
+
const line = parseInt(req.query['line'], 10);
|
|
240
|
+
const context = parseInt(req.query['context'], 10) || 3;
|
|
241
|
+
if (!file) {
|
|
242
|
+
throw new BadRequestError('File path is required');
|
|
243
|
+
}
|
|
244
|
+
if (isNaN(line)) {
|
|
245
|
+
throw new BadRequestError('Line number is required');
|
|
246
|
+
}
|
|
247
|
+
const snippet = await reader.getCodeSnippet(file, line, context);
|
|
248
|
+
if (!snippet) {
|
|
249
|
+
throw new NotFoundError(`Could not read file: ${file}`);
|
|
250
|
+
}
|
|
251
|
+
res.json(snippet);
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
next(error);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
// ==========================================================================
|
|
258
|
+
// File Routes
|
|
259
|
+
// ==========================================================================
|
|
260
|
+
/**
|
|
261
|
+
* GET /api/files - Get file tree
|
|
262
|
+
* @requirements 8.7
|
|
263
|
+
*/
|
|
264
|
+
router.get('/files', async (_req, res, next) => {
|
|
265
|
+
try {
|
|
266
|
+
const fileTree = await reader.getFileTree();
|
|
267
|
+
res.json(fileTree);
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
next(error);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
/**
|
|
274
|
+
* GET /api/files/* - Get file details (wildcard path)
|
|
275
|
+
* @requirements 8.8
|
|
276
|
+
*/
|
|
277
|
+
router.get('/files/*', async (req, res, next) => {
|
|
278
|
+
try {
|
|
279
|
+
// Extract the file path from the wildcard
|
|
280
|
+
const filePath = req.params[0];
|
|
281
|
+
if (!filePath) {
|
|
282
|
+
throw new BadRequestError('File path is required');
|
|
283
|
+
}
|
|
284
|
+
const fileDetails = await reader.getFileDetails(filePath);
|
|
285
|
+
if (!fileDetails) {
|
|
286
|
+
throw new NotFoundError(`File not found or has no patterns/violations: ${filePath}`);
|
|
287
|
+
}
|
|
288
|
+
res.json(fileDetails);
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
next(error);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
// ==========================================================================
|
|
295
|
+
// Stats Routes
|
|
296
|
+
// ==========================================================================
|
|
297
|
+
/**
|
|
298
|
+
* GET /api/stats - Get dashboard statistics
|
|
299
|
+
* @requirements 8.9
|
|
300
|
+
*/
|
|
301
|
+
router.get('/stats', async (_req, res, next) => {
|
|
302
|
+
try {
|
|
303
|
+
const stats = await reader.getStats();
|
|
304
|
+
res.json(stats);
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
next(error);
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
// ==========================================================================
|
|
311
|
+
// Config Routes
|
|
312
|
+
// ==========================================================================
|
|
313
|
+
/**
|
|
314
|
+
* GET /api/config - Get configuration
|
|
315
|
+
* @requirements 8.10
|
|
316
|
+
*/
|
|
317
|
+
router.get('/config', async (_req, res, next) => {
|
|
318
|
+
try {
|
|
319
|
+
const config = await reader.getConfig();
|
|
320
|
+
res.json(config);
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
next(error);
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
/**
|
|
327
|
+
* PUT /api/config - Update configuration
|
|
328
|
+
* @requirements 8.11
|
|
329
|
+
*/
|
|
330
|
+
router.put('/config', async (req, res, next) => {
|
|
331
|
+
try {
|
|
332
|
+
const partialConfig = req.body;
|
|
333
|
+
if (!partialConfig || typeof partialConfig !== 'object') {
|
|
334
|
+
throw new BadRequestError('Invalid configuration format');
|
|
335
|
+
}
|
|
336
|
+
await reader.updateConfig(partialConfig);
|
|
337
|
+
const updatedConfig = await reader.getConfig();
|
|
338
|
+
res.json(updatedConfig);
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
next(error);
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
// ==========================================================================
|
|
345
|
+
// Contract Routes (BE↔FE mismatch detection)
|
|
346
|
+
// ==========================================================================
|
|
347
|
+
/**
|
|
348
|
+
* GET /api/contracts - List all contracts with optional filters
|
|
349
|
+
*/
|
|
350
|
+
router.get('/contracts', async (req, res, next) => {
|
|
351
|
+
try {
|
|
352
|
+
const query = {};
|
|
353
|
+
if (req.query['status']) {
|
|
354
|
+
query.status = req.query['status'];
|
|
355
|
+
}
|
|
356
|
+
if (req.query['method']) {
|
|
357
|
+
query.method = req.query['method'];
|
|
358
|
+
}
|
|
359
|
+
if (req.query['hasMismatches'] !== undefined) {
|
|
360
|
+
query.hasMismatches = req.query['hasMismatches'] === 'true';
|
|
361
|
+
}
|
|
362
|
+
if (req.query['search']) {
|
|
363
|
+
query.search = req.query['search'];
|
|
364
|
+
}
|
|
365
|
+
const contracts = await reader.getContracts(query);
|
|
366
|
+
res.json(contracts);
|
|
367
|
+
}
|
|
368
|
+
catch (error) {
|
|
369
|
+
next(error);
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
/**
|
|
373
|
+
* GET /api/contracts/stats - Get contract statistics
|
|
374
|
+
*/
|
|
375
|
+
router.get('/contracts/stats', async (_req, res, next) => {
|
|
376
|
+
try {
|
|
377
|
+
const stats = await reader.getContractStats();
|
|
378
|
+
res.json(stats);
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
next(error);
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
/**
|
|
385
|
+
* GET /api/contracts/:id - Get contract details
|
|
386
|
+
*/
|
|
387
|
+
router.get('/contracts/:id', async (req, res, next) => {
|
|
388
|
+
try {
|
|
389
|
+
const { id } = req.params;
|
|
390
|
+
if (!id) {
|
|
391
|
+
throw new BadRequestError('Contract ID is required');
|
|
392
|
+
}
|
|
393
|
+
const contract = await reader.getContract(id);
|
|
394
|
+
if (!contract) {
|
|
395
|
+
throw new NotFoundError(`Contract not found: ${id}`);
|
|
396
|
+
}
|
|
397
|
+
res.json(contract);
|
|
398
|
+
}
|
|
399
|
+
catch (error) {
|
|
400
|
+
next(error);
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
/**
|
|
404
|
+
* POST /api/contracts/:id/verify - Verify a contract
|
|
405
|
+
*/
|
|
406
|
+
router.post('/contracts/:id/verify', async (req, res, next) => {
|
|
407
|
+
try {
|
|
408
|
+
const { id } = req.params;
|
|
409
|
+
if (!id) {
|
|
410
|
+
throw new BadRequestError('Contract ID is required');
|
|
411
|
+
}
|
|
412
|
+
await reader.verifyContract(id);
|
|
413
|
+
res.json({ success: true, message: `Contract ${id} verified` });
|
|
414
|
+
}
|
|
415
|
+
catch (error) {
|
|
416
|
+
if (error instanceof Error && error.message.includes('not found')) {
|
|
417
|
+
next(new NotFoundError(error.message));
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
next(error);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
/**
|
|
425
|
+
* POST /api/contracts/:id/ignore - Ignore a contract
|
|
426
|
+
*/
|
|
427
|
+
router.post('/contracts/:id/ignore', async (req, res, next) => {
|
|
428
|
+
try {
|
|
429
|
+
const { id } = req.params;
|
|
430
|
+
if (!id) {
|
|
431
|
+
throw new BadRequestError('Contract ID is required');
|
|
432
|
+
}
|
|
433
|
+
await reader.ignoreContract(id);
|
|
434
|
+
res.json({ success: true, message: `Contract ${id} ignored` });
|
|
435
|
+
}
|
|
436
|
+
catch (error) {
|
|
437
|
+
if (error instanceof Error && error.message.includes('not found')) {
|
|
438
|
+
next(new NotFoundError(error.message));
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
next(error);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
return router;
|
|
446
|
+
}
|
|
447
|
+
// ============================================================================
|
|
448
|
+
// Error Handling Middleware
|
|
449
|
+
// ============================================================================
|
|
450
|
+
/**
|
|
451
|
+
* Error handling middleware for API routes
|
|
452
|
+
* @requirements 8.12 - Return appropriate HTTP status codes and error messages
|
|
453
|
+
*/
|
|
454
|
+
export function errorHandler(err, _req, res, _next) {
|
|
455
|
+
// Determine status code
|
|
456
|
+
const statusCode = 'statusCode' in err ? err.statusCode : 500;
|
|
457
|
+
// Log server errors
|
|
458
|
+
if (statusCode >= 500) {
|
|
459
|
+
console.error('Server error:', err);
|
|
460
|
+
}
|
|
461
|
+
// Send JSON error response
|
|
462
|
+
res.status(statusCode).json({
|
|
463
|
+
error: err.name || 'Error',
|
|
464
|
+
message: err.message || 'An unexpected error occurred',
|
|
465
|
+
statusCode,
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* 404 handler for unknown routes
|
|
470
|
+
*/
|
|
471
|
+
export function notFoundHandler(req, res) {
|
|
472
|
+
res.status(404).json({
|
|
473
|
+
error: 'NotFound',
|
|
474
|
+
message: `Route not found: ${req.method} ${req.path}`,
|
|
475
|
+
statusCode: 404,
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
//# sourceMappingURL=api-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-routes.js","sourceRoot":"","sources":["../../src/server/api-routes.ts"],"names":[],"mappings":"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"}
|