Skip to content

Commit

Permalink
[hotfix] Fixing problem on update all updated wrong values too
Browse files Browse the repository at this point in the history
  • Loading branch information
erdemkosk committed Nov 6, 2023
1 parent d21821a commit da0a8ee
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 114 deletions.
50 changes: 39 additions & 11 deletions bin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Command } from 'commander'
import inquirer from 'inquirer'
import inquirerPrompt from 'inquirer-autocomplete-prompt'
import chalk from 'chalk'
import { table } from 'table'
import Table from 'cli-table3'
import packages from '../package.json'
import {
getBaseFolder,
Expand Down Expand Up @@ -41,9 +41,20 @@ program
choices: files
})

const { data, config } = await getValuesInEnv({ targetPath })
const { data } = await getValuesInEnv({ targetPath })

console.log(table(data, config))
const table = new Table({
head: ['ENV', 'VALUE'],
colWidths: [20, 30],
wrapOnWordBoundary: false,
wordWrap: true
})

data.forEach(row => {
table.push(row)
})

console.log(table.toString())
})

program
Expand All @@ -58,15 +69,15 @@ program
.description(`${chalk.yellow('UPDATE-ALL')} command is a handy utility for updating a specific environment variable across multiple service-specific .env files.`)
.alias('ua')
.action(async () => {
const oldValueOptions = await promptForEnvVariable()
const envOptions = await promptForEnvVariable()

const { oldValue, newValue } = await inquirer.prompt([
const { envValue, newValue } = await inquirer.prompt([
{
type: 'autocomplete',
name: 'oldValue',
message: 'Select the old value to change:',
name: 'envValue',
message: 'Select the env value to change:',
source: (answers: any, input: string) => {
return oldValueOptions.filter(option => option.includes(input))
return envOptions.filter(option => option.includes(input))
}
},
{
Expand All @@ -76,7 +87,7 @@ program
}
])

const effectedServices = await updateAllEnvFile({ oldValue, newValue })
const effectedServices = await updateAllEnvFile({ envValue, newValue })

effectedServices.forEach((service) => {
console.log(`Environment variables updated in "${chalk.blue(service)}"`)
Expand Down Expand Up @@ -110,9 +121,26 @@ program

const { source, destination } = answers

const differentVariables = await compareEnvFiles({ source, destination })
const {
differentVariables,
sourceServiceName,
destinationServiceName
} = await compareEnvFiles({ source, destination })

const table = new Table({
head: ['VALUES', sourceServiceName, destinationServiceName],
wordWrap: true,
colWidths: [20, 30, 30],
wrapOnWordBoundary: false
})

differentVariables.forEach(row => {
table.push(row)
})

console.log(differentVariables.length > 1 ? table(differentVariables) : chalk.red('There is no diff or two different files do not contain the same variable name'))
if (differentVariables.length > 0) {
console.log(table.toString())
}
})

program
Expand Down
184 changes: 114 additions & 70 deletions lib/env-operations.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as path from 'path'

import {
getBaseFolder,
createFolderIfDoesNotExist,
Expand All @@ -12,27 +11,64 @@ import {
getEnvFiles
} from './file-operations'

async function createEnvFile ({ serviceName, content }: { serviceName: string, content: string }): Promise<void> {
const serviceFolderPath: string = path.join(getBaseFolder(), serviceName)
function getServiceNameFromUrl ({ targetPath }: { targetPath: string }): string {
const parts = targetPath.split('/')
return parts[parts.length - 2]
}

function splitEnvLine (line: string): [string, string] {
const indexOfFirstEqualSign = line.indexOf('=')
if (indexOfFirstEqualSign >= 0) {
const envName = line.substring(0, indexOfFirstEqualSign)
const envValue = line.substring(indexOfFirstEqualSign + 1)
return [envName, envValue]
}
return ['', '']
}

async function createEnvFile ({
serviceName,
content
}: {
serviceName: string
content: string
}): Promise<void> {
const serviceFolderPath = path.join(getBaseFolder(), serviceName)
await createFolderIfDoesNotExist(serviceFolderPath)

const filePath: string = path.join(serviceFolderPath, '.env')
const filePath = path.join(serviceFolderPath, '.env')
await writeFile({ file: filePath, newFileContents: content })
}

async function updateEnvFile ({ file, content }: { file: string, content: string }): Promise<void> {
async function updateEnvFile ({
file,
content
}: {
file: string
content: string
}): Promise<void> {
await writeFile({ file, newFileContents: content })
}

async function updateAllEnvFile ({ oldValue, newValue }: { oldValue: string, newValue: string }): Promise<string[]> {
async function updateAllEnvFile ({
envValue,
newValue
}: {
envValue: string
newValue: string
}): Promise<string[]> {
const files = await getFilesRecursively({ directory: getBaseFolder() })
const effectedServices: string[] = []

for (const file of files) {
const fileContents = await readFile({ file })

if (fileContents !== undefined) {
const newFileContents = changeValuesInEnv({ contents: fileContents, oldValue, newValue })
const newFileContents = changeValuesInEnv({
contents: fileContents,
envValue,
newValue
})

if (newFileContents !== fileContents && newFileContents !== '') {
await writeFile({ file, newFileContents })
Expand All @@ -44,64 +80,58 @@ async function updateAllEnvFile ({ oldValue, newValue }: { oldValue: string, new
return effectedServices
}

async function createSymlink ({ targetPath }: { targetPath: string }): Promise<string> {
const symlinkPath: string = path.join(process.cwd(), '.env')

async function createSymlink ({
targetPath
}: {
targetPath: string
}): Promise<string> {
const symlinkPath = path.join(process.cwd(), '.env')
await generateSymlink({ targetPath: path.join(targetPath), symlinkPath })

return symlinkPath
}

async function getValuesInEnv ({ targetPath }: { targetPath: string }): Promise<{ data: string[][], config: Record<string, any> }> {
const contents: string | undefined = await readFile({ file: targetPath })
async function getValuesInEnv ({
targetPath
}: {
targetPath: string
}): Promise<{ data: string[][] }> {
const contents = await readFile({ file: targetPath })

if (contents == null) {
return { data: [], config: {} }
return { data: [] }
}
const lines: string[] = contents.split('\n')
const lines = contents.split('\n')

const data: string[][] = [['ENV', 'VALUE']]
const data: string[][] = []

for (const line of lines) {
if (line.trim() !== '') {
const indexOfFirstEqualSign = line.indexOf('=')
if (indexOfFirstEqualSign >= 0) {
const envName = line.substring(0, indexOfFirstEqualSign)
const envValue = line.substring(indexOfFirstEqualSign + 1)

data.push([envName, envValue])
}
}
}

const directoryName: string = getServiceNameFromUrl({ targetPath })

const config = {
header: {
alignment: 'center',
content: directoryName
const [envName, envValue] = splitEnvLine(line)
data.push([envName, envValue])
}
}

return {
data, config
data
}
}

function getServiceNameFromUrl ({ targetPath }: { targetPath: string }): string {
const parts: string[] = targetPath.split('/')

return parts[parts.length - 2]
}

function changeValuesInEnv ({ contents, oldValue, newValue }: { contents: string, oldValue: string, newValue: string }): string {
const lines: string[] = contents.split('\n')
const newLines: string[] = []
function changeValuesInEnv ({
contents,
envValue,
newValue
}: {
contents: string
envValue: string
newValue: string
}): string {
const lines = contents.split('\n')
const newLines = []

for (const line of lines) {
if (line.startsWith(oldValue)) {
const parts: string[] = line.split('=')
newLines.push(`${parts[0]}=${newValue}`)
const parts = line.split('=')
if (parts[0] === envValue) {
newLines.push(`${envValue}=${newValue}`)
} else {
newLines.push(line)
}
Expand All @@ -110,48 +140,65 @@ function changeValuesInEnv ({ contents, oldValue, newValue }: { contents: string
return newLines.join('\n')
}

async function compareEnvFiles ({ source, destination }: { source: string, destination: string }): Promise<string[][]> {
const sourceContent: string | undefined = await readFile({ file: source })
const destinationContent: string | undefined = await readFile({ file: destination })
async function compareEnvFiles ({
source,
destination
}: {
source: string
destination: string
}): Promise<{
differentVariables: string[][]
sourceServiceName: string
destinationServiceName: string
}> {
const sourceContent = await readFile({ file: source })
const destinationContent = await readFile({ file: destination })

if (sourceContent === null || destinationContent === null) {
return []
return {
differentVariables: [],
sourceServiceName: '',
destinationServiceName: ''
}
}

const sourceLines: string[] | undefined = sourceContent?.split('\n')
const destinationLines: string[] | undefined = destinationContent?.split('\n')
const sourceLines = sourceContent?.split('\n')
const destinationLines = destinationContent?.split('\n')

const sourceServiceName: string = getServiceNameFromUrl({ targetPath: source })
const destinationServiceName: string = getServiceNameFromUrl({ targetPath: destination })

const differentVariables: string[][] = [['Variable Name', sourceServiceName, destinationServiceName]];
const differentVariables: string[][] = [];

// eslint-disable-next-line no-unexpected-multiline
(sourceLines ?? []).forEach((sourceLine: string) => {
const sourceLineParts: string[] = sourceLine.split('=')
const sourceLineParts = splitEnvLine(sourceLine)
const variableName: string = sourceLineParts[0]
const sourceValue: string = sourceLineParts[1]

const matchingDestinationLine: string | undefined = (destinationLines ?? []).find((destinationLine) => {
const destinationLineParts: string[] = destinationLine.split('=')
const destinationLineParts = splitEnvLine(destinationLine)
return destinationLineParts[0] === variableName
})

if (matchingDestinationLine != null) {
const destinationValue: string = matchingDestinationLine.split('=')[1]
const destinationValue = splitEnvLine(matchingDestinationLine)[1]
if (sourceValue !== destinationValue) {
differentVariables.push([variableName, sourceValue, destinationValue])
}
}
})

return differentVariables
return {
differentVariables,
sourceServiceName,
destinationServiceName
}
}

async function syncEnvFile (): Promise<void> {
const currentDirectory: string = process.cwd()
const directoryName: string = currentDirectory.split('/').pop() ?? ''
const serviceFolderPath: string = path.join(getBaseFolder(), directoryName)
const currentDirectory = process.cwd()
const directoryName = currentDirectory.split('/').pop() ?? ''
const serviceFolderPath = path.join(getBaseFolder(), directoryName)

await createFolderIfDoesNotExist(serviceFolderPath)

Expand All @@ -169,22 +216,17 @@ async function promptForEnvVariable (): Promise<string[]> {
for (const file of files) {
const fileVariables = await readFile({ file })
if (fileVariables != null) {
const sourceLines: string[] = fileVariables.split('\n')
const sourceLines = fileVariables.split('\n')

for (const line of sourceLines) {
if (line.trim() !== '') {
const indexOfFirstEqualSign = line.indexOf('=')
if (indexOfFirstEqualSign >= 0) {
const envName = line.substring(0, indexOfFirstEqualSign)

variables.add(envName)
}
const [envName] = splitEnvLine(line)
variables.add(envName)
}
}
}
}
const uniqueVariables = Array.from(variables)
uniqueVariables.sort()
const uniqueVariables = Array.from(variables).sort()

return uniqueVariables
}
Expand All @@ -197,5 +239,7 @@ export {
getValuesInEnv,
compareEnvFiles,
syncEnvFile,
promptForEnvVariable
promptForEnvVariable,
getServiceNameFromUrl,
splitEnvLine
}
Loading

0 comments on commit da0a8ee

Please sign in to comment.