@@ -3,46 +3,22 @@ import { Button } from "@/components/ui/button";
33import { Checkbox } from "@/components/ui/checkbox" ;
44import { Input } from "@/components/ui/input" ;
55import { Trash2 } from "lucide-react" ;
6- import { Fragment , useEffect , useState } from "react" ;
6+ import { Fragment } from "react" ;
77
88type EnvVars = { name : string ; value : string | null ; isSensitive : boolean } [ ] ;
99
10- // TODO: show error message on duplicate env names
1110export const EnvVarGrid = ( {
1211 value : envVars ,
1312 setValue : setEnvironmentVariables ,
14- fixedSensitiveNames ,
13+ fixedSensitiveVars ,
1514 disabled = false ,
1615} : {
1716 value : EnvVars ;
1817 setValue : ( updater : ( envVars : EnvVars ) => EnvVars ) => void ;
19- fixedSensitiveNames : Set < string > ;
18+ fixedSensitiveVars : Record < string , number > ;
2019 disabled : boolean ;
2120} ) => {
22- const [ error , setError ] = useState ( "" ) ;
23- useEffect ( ( ) => {
24- for ( const i of envVars . keys ( ) ) {
25- if (
26- envVars [ i ] . name === "" &&
27- envVars [ i ] . value === "" &&
28- ! envVars [ i ] . isSensitive &&
29- i < envVars . length - 1
30- ) {
31- setEnvironmentVariables ( ( prev ) => prev . toSpliced ( i , 1 ) ) ;
32- return ;
33- }
34- }
35- if (
36- envVars [ envVars . length - 1 ] ?. name !== "" ||
37- envVars [ envVars . length - 1 ] ?. value !== "" ||
38- envVars [ envVars . length - 1 ] ?. isSensitive
39- ) {
40- setEnvironmentVariables ( ( prev ) => [
41- ...prev ,
42- { name : "" , value : "" , isSensitive : false } ,
43- ] ) ;
44- }
45- } , [ envVars , setEnvironmentVariables ] ) ;
21+ const error = getEnvError ( envVars ) ;
4622
4723 return (
4824 < div className = "grid grid-cols-[1fr_min-content_1fr_min-content_min-content] items-center gap-2" >
@@ -57,7 +33,7 @@ export const EnvVarGrid = ({
5733 </ span >
5834 < span > </ span >
5935 { envVars . map ( ( { name, value, isSensitive } , index ) => {
60- const isFixedSensitive = fixedSensitiveNames . has ( name ) ;
36+ const isFixedSensitive = fixedSensitiveVars [ name ] === index ;
6137 return (
6238 < Fragment key = { index } >
6339 < Input
@@ -76,21 +52,14 @@ export const EnvVarGrid = ({
7652 value = { name }
7753 onChange = { ( e ) => {
7854 const value = e . currentTarget . value ;
79- setEnvironmentVariables ( ( prev ) => {
80- const newList = prev . toSpliced ( index , 1 , {
81- ...prev [ index ] ,
82- name : value ,
83- } ) ;
84- const duplicates = getDuplicates ( newList ) ;
85- if ( duplicates . length != 0 ) {
86- setError (
87- `Duplicate environment variable(s): ${ duplicates . join ( ", " ) } ` ,
88- ) ;
89- } else {
90- setError ( "" ) ;
91- }
92- return newList ;
93- } ) ;
55+ setEnvironmentVariables ( ( prev ) =>
56+ getCorrectEnvBlanks (
57+ prev . toSpliced ( index , 1 , {
58+ ...prev [ index ] ,
59+ name : value ,
60+ } ) ,
61+ ) ,
62+ ) ;
9463 } }
9564 />
9665 < span className = "w-fit align-middle text-xl" > =</ span >
@@ -103,13 +72,14 @@ export const EnvVarGrid = ({
10372 value = { value ?? "" }
10473 onChange = { ( e ) => {
10574 const value = e . currentTarget . value ;
106- setEnvironmentVariables ( ( prev ) => {
107- const newList = prev . toSpliced ( index , 1 , {
108- ...prev [ index ] ,
109- value : value ,
110- } ) ;
111- return newList ;
112- } ) ;
75+ setEnvironmentVariables ( ( prev ) =>
76+ getCorrectEnvBlanks (
77+ prev . toSpliced ( index , 1 , {
78+ ...prev [ index ] ,
79+ value : value ,
80+ } ) ,
81+ ) ,
82+ ) ;
11383 } }
11484 autoComplete = "off"
11585 autoCorrect = "off"
@@ -123,10 +93,12 @@ export const EnvVarGrid = ({
12393 checked = { isSensitive }
12494 onCheckedChange = { ( checked ) => {
12595 setEnvironmentVariables ( ( prev ) =>
126- prev . toSpliced ( index , 1 , {
127- ...prev [ index ] ,
128- isSensitive : checked === true ,
129- } ) ,
96+ getCorrectEnvBlanks (
97+ prev . toSpliced ( index , 1 , {
98+ ...prev [ index ] ,
99+ isSensitive : checked === true ,
100+ } ) ,
101+ ) ,
130102 ) ;
131103 } }
132104 />
@@ -136,7 +108,9 @@ export const EnvVarGrid = ({
136108 variant = "secondary"
137109 type = "button"
138110 onClick = { ( ) =>
139- setEnvironmentVariables ( ( prev ) => prev . toSpliced ( index , 1 ) )
111+ setEnvironmentVariables ( ( prev ) =>
112+ index != prev . length - 1 ? prev . toSpliced ( index , 1 ) : prev ,
113+ )
140114 }
141115 >
142116 < Trash2 />
@@ -149,17 +123,48 @@ export const EnvVarGrid = ({
149123 ) ;
150124} ;
151125
152- const getDuplicates = ( values : EnvVars ) : string [ ] => {
153- const names = new Set ( ) ;
154- const result = [ ] ;
155- for ( const env of values ) {
156- if ( env . name === "" ) {
157- continue ;
126+ export const getCorrectEnvBlanks = ( envVars : EnvVars ) : EnvVars => {
127+ const indicesToDelete = new Set < number > ( ) ;
128+ envVars . forEach ( ( env , idx ) => {
129+ if (
130+ env . name === "" &&
131+ env . value === "" &&
132+ ! env . isSensitive &&
133+ idx < envVars . length - 1
134+ ) {
135+ indicesToDelete . add ( idx ) ;
158136 }
159- if ( names . has ( env . name ) ) {
160- result . push ( env . name ) ;
137+ } ) ;
138+ const cleanedVars = envVars . filter ( ( _ , idx ) => ! indicesToDelete . has ( idx ) ) ;
139+
140+ const last = cleanedVars [ cleanedVars . length - 1 ] ;
141+ if ( last . name !== "" || last . value !== "" || last . isSensitive ) {
142+ cleanedVars . push ( { name : "" , value : "" , isSensitive : false } ) ;
143+ }
144+ return cleanedVars ;
145+ } ;
146+
147+ const getDuplicates = ( values : string [ ] ) => {
148+ const unique = new Set < string > ( ) ;
149+ const duplicates = new Set < string > ( ) ;
150+
151+ values . forEach ( ( value ) => {
152+ if ( unique . has ( value ) ) {
153+ duplicates . add ( value ) ;
154+ } else {
155+ unique . add ( value ) ;
161156 }
162- names . add ( env . name ) ;
157+ } ) ;
158+
159+ return duplicates ;
160+ } ;
161+
162+ export const getEnvError = ( env : EnvVars ) => {
163+ const duplicates = getDuplicates ( env . map ( ( ev ) => ev . name ) . filter ( Boolean ) ) ;
164+
165+ if ( duplicates . size !== 0 ) {
166+ return `Duplicate environment variable(s): ${ [ ...duplicates . values ( ) ] . join ( ", " ) } ` ;
163167 }
164- return result ;
168+
169+ return "" ;
165170} ;
0 commit comments