mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-02-09 02:49:29 +08:00
feat(shadcn): add envVars to schema (#7902)
* feat(shadcn): add envVars to schema * fix(shadcn): tests * chore: changeset
This commit is contained in:
5
.changeset/chilled-comics-beam.md
Normal file
5
.changeset/chilled-comics-beam.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"shadcn": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
add support for envVars in schema
|
||||||
@@ -191,6 +191,13 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"envVars": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Environment variables required by the registry item. Key-value pairs that will be added to the project's .env file.",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Additional metadata for the registry item. This is an object with any key value pairs.",
|
"description": "Additional metadata for the registry item. This is an object with any key value pairs.",
|
||||||
|
|||||||
@@ -476,7 +476,12 @@ export async function registryResolveItemsTree(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return registryResolvedItemsTreeSchema.parse({
|
let envVars = {}
|
||||||
|
payload.forEach((item) => {
|
||||||
|
envVars = deepmerge(envVars, item.envVars ?? {})
|
||||||
|
})
|
||||||
|
|
||||||
|
const parsed = registryResolvedItemsTreeSchema.parse({
|
||||||
dependencies: deepmerge.all(
|
dependencies: deepmerge.all(
|
||||||
payload.map((item) => item.dependencies ?? [])
|
payload.map((item) => item.dependencies ?? [])
|
||||||
),
|
),
|
||||||
@@ -489,6 +494,12 @@ export async function registryResolveItemsTree(
|
|||||||
css,
|
css,
|
||||||
docs,
|
docs,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (Object.keys(envVars).length > 0) {
|
||||||
|
parsed.envVars = envVars
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsed
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(error)
|
handleError(error)
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ export const registryItemCssSchema = z.record(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const registryItemEnvVarsSchema = z.record(z.string(), z.string())
|
||||||
|
|
||||||
export const registryItemSchema = z.object({
|
export const registryItemSchema = z.object({
|
||||||
$schema: z.string().optional(),
|
$schema: z.string().optional(),
|
||||||
extends: z.string().optional(),
|
extends: z.string().optional(),
|
||||||
@@ -80,6 +82,7 @@ export const registryItemSchema = z.object({
|
|||||||
tailwind: registryItemTailwindSchema.optional(),
|
tailwind: registryItemTailwindSchema.optional(),
|
||||||
cssVars: registryItemCssVarsSchema.optional(),
|
cssVars: registryItemCssVarsSchema.optional(),
|
||||||
css: registryItemCssSchema.optional(),
|
css: registryItemCssSchema.optional(),
|
||||||
|
envVars: registryItemEnvVarsSchema.optional(),
|
||||||
meta: z.record(z.string(), z.any()).optional(),
|
meta: z.record(z.string(), z.any()).optional(),
|
||||||
docs: z.string().optional(),
|
docs: z.string().optional(),
|
||||||
categories: z.array(z.string()).optional(),
|
categories: z.array(z.string()).optional(),
|
||||||
@@ -127,5 +130,6 @@ export const registryResolvedItemsTreeSchema = registryItemSchema.pick({
|
|||||||
tailwind: true,
|
tailwind: true,
|
||||||
cssVars: true,
|
cssVars: true,
|
||||||
css: true,
|
css: true,
|
||||||
|
envVars: true,
|
||||||
docs: true,
|
docs: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import { spinner } from "@/src/utils/spinner"
|
|||||||
import { updateCss } from "@/src/utils/updaters/update-css"
|
import { updateCss } from "@/src/utils/updaters/update-css"
|
||||||
import { updateCssVars } from "@/src/utils/updaters/update-css-vars"
|
import { updateCssVars } from "@/src/utils/updaters/update-css-vars"
|
||||||
import { updateDependencies } from "@/src/utils/updaters/update-dependencies"
|
import { updateDependencies } from "@/src/utils/updaters/update-dependencies"
|
||||||
|
import { updateEnvVars } from "@/src/utils/updaters/update-env-vars"
|
||||||
import { updateFiles } from "@/src/utils/updaters/update-files"
|
import { updateFiles } from "@/src/utils/updaters/update-files"
|
||||||
import { updateTailwindConfig } from "@/src/utils/updaters/update-tailwind-config"
|
import { updateTailwindConfig } from "@/src/utils/updaters/update-tailwind-config"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
@@ -116,6 +117,10 @@ async function addProjectComponents(
|
|||||||
silent: options.silent,
|
silent: options.silent,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await updateEnvVars(tree.envVars, config, {
|
||||||
|
silent: options.silent,
|
||||||
|
})
|
||||||
|
|
||||||
await updateDependencies(tree.dependencies, tree.devDependencies, config, {
|
await updateDependencies(tree.dependencies, tree.devDependencies, config, {
|
||||||
silent: options.silent,
|
silent: options.silent,
|
||||||
})
|
})
|
||||||
@@ -232,7 +237,14 @@ async function addWorkspaceComponents(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Update dependencies.
|
// 4. Update environment variables
|
||||||
|
if (component.envVars) {
|
||||||
|
await updateEnvVars(component.envVars, targetConfig, {
|
||||||
|
silent: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Update dependencies.
|
||||||
await updateDependencies(
|
await updateDependencies(
|
||||||
component.dependencies,
|
component.dependencies,
|
||||||
component.devDependencies,
|
component.devDependencies,
|
||||||
@@ -242,7 +254,7 @@ async function addWorkspaceComponents(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// 5. Update files.
|
// 6. Update files.
|
||||||
const files = await updateFiles(component.files, targetConfig, {
|
const files = await updateFiles(component.files, targetConfig, {
|
||||||
overwrite: options.overwrite,
|
overwrite: options.overwrite,
|
||||||
silent: true,
|
silent: true,
|
||||||
|
|||||||
@@ -309,19 +309,7 @@ describe("findExistingEnvFile", () => {
|
|||||||
vi.clearAllMocks()
|
vi.clearAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should return .env if it exists", () => {
|
test("should return .env.local if it exists", () => {
|
||||||
vi.mocked(existsSync).mockImplementation((path) => {
|
|
||||||
const pathStr = typeof path === "string" ? path : path.toString()
|
|
||||||
return pathStr.endsWith(".env")
|
|
||||||
})
|
|
||||||
|
|
||||||
const result = findExistingEnvFile("/test/dir")
|
|
||||||
expect(result).toBe("/test/dir/.env")
|
|
||||||
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env")
|
|
||||||
expect(existsSync).toHaveBeenCalledTimes(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("should return .env.local if .env doesn't exist", () => {
|
|
||||||
vi.mocked(existsSync).mockImplementation((path) => {
|
vi.mocked(existsSync).mockImplementation((path) => {
|
||||||
const pathStr = typeof path === "string" ? path : path.toString()
|
const pathStr = typeof path === "string" ? path : path.toString()
|
||||||
return pathStr.endsWith(".env.local")
|
return pathStr.endsWith(".env.local")
|
||||||
@@ -329,8 +317,20 @@ describe("findExistingEnvFile", () => {
|
|||||||
|
|
||||||
const result = findExistingEnvFile("/test/dir")
|
const result = findExistingEnvFile("/test/dir")
|
||||||
expect(result).toBe("/test/dir/.env.local")
|
expect(result).toBe("/test/dir/.env.local")
|
||||||
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env")
|
|
||||||
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env.local")
|
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env.local")
|
||||||
|
expect(existsSync).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should return .env if .env.local doesn't exist", () => {
|
||||||
|
vi.mocked(existsSync).mockImplementation((path) => {
|
||||||
|
const pathStr = typeof path === "string" ? path : path.toString()
|
||||||
|
return pathStr.endsWith(".env")
|
||||||
|
})
|
||||||
|
|
||||||
|
const result = findExistingEnvFile("/test/dir")
|
||||||
|
expect(result).toBe("/test/dir/.env")
|
||||||
|
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env.local")
|
||||||
|
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env")
|
||||||
expect(existsSync).toHaveBeenCalledTimes(2)
|
expect(existsSync).toHaveBeenCalledTimes(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -342,8 +342,8 @@ describe("findExistingEnvFile", () => {
|
|||||||
|
|
||||||
const result = findExistingEnvFile("/test/dir")
|
const result = findExistingEnvFile("/test/dir")
|
||||||
expect(result).toBe("/test/dir/.env.development.local")
|
expect(result).toBe("/test/dir/.env.development.local")
|
||||||
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env")
|
|
||||||
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env.local")
|
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env.local")
|
||||||
|
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env")
|
||||||
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env.development.local")
|
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env.development.local")
|
||||||
expect(existsSync).toHaveBeenCalledTimes(3)
|
expect(existsSync).toHaveBeenCalledTimes(3)
|
||||||
})
|
})
|
||||||
@@ -361,8 +361,8 @@ describe("findExistingEnvFile", () => {
|
|||||||
|
|
||||||
findExistingEnvFile("/test/dir")
|
findExistingEnvFile("/test/dir")
|
||||||
|
|
||||||
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env")
|
|
||||||
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env.local")
|
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env.local")
|
||||||
|
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env")
|
||||||
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env.development.local")
|
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env.development.local")
|
||||||
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env.development")
|
expect(existsSync).toHaveBeenCalledWith("/test/dir/.env.development")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ export function isEnvFile(filePath: string) {
|
|||||||
*/
|
*/
|
||||||
export function findExistingEnvFile(targetDir: string) {
|
export function findExistingEnvFile(targetDir: string) {
|
||||||
const variants = [
|
const variants = [
|
||||||
".env",
|
|
||||||
".env.local",
|
".env.local",
|
||||||
|
".env",
|
||||||
".env.development.local",
|
".env.development.local",
|
||||||
".env.development",
|
".env.development",
|
||||||
]
|
]
|
||||||
|
|||||||
183
packages/shadcn/src/utils/updaters/update-env-vars.test.ts
Normal file
183
packages/shadcn/src/utils/updaters/update-env-vars.test.ts
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
import { existsSync, promises as fs } from "fs"
|
||||||
|
import type { Config } from "@/src/utils/get-config"
|
||||||
|
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"
|
||||||
|
|
||||||
|
import { updateEnvVars } from "./update-env-vars"
|
||||||
|
|
||||||
|
vi.mock("fs", () => ({
|
||||||
|
existsSync: vi.fn(),
|
||||||
|
promises: {
|
||||||
|
readFile: vi.fn(),
|
||||||
|
writeFile: vi.fn(),
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
vi.mock("@/src/utils/logger", () => ({
|
||||||
|
logger: {
|
||||||
|
info: vi.fn(),
|
||||||
|
log: vi.fn(),
|
||||||
|
success: vi.fn(),
|
||||||
|
break: vi.fn(),
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
vi.mock("@/src/utils/spinner", () => ({
|
||||||
|
spinner: vi.fn(() => ({
|
||||||
|
start: vi.fn().mockReturnThis(),
|
||||||
|
stop: vi.fn(),
|
||||||
|
succeed: vi.fn(),
|
||||||
|
})),
|
||||||
|
}))
|
||||||
|
|
||||||
|
const mockConfig: Config = {
|
||||||
|
style: "default",
|
||||||
|
rsc: false,
|
||||||
|
tailwind: {
|
||||||
|
config: "tailwind.config.js",
|
||||||
|
css: "app/globals.css",
|
||||||
|
baseColor: "slate",
|
||||||
|
prefix: "",
|
||||||
|
cssVariables: false,
|
||||||
|
},
|
||||||
|
tsx: true,
|
||||||
|
aliases: {
|
||||||
|
components: "@/components",
|
||||||
|
ui: "@/components/ui",
|
||||||
|
lib: "@/lib",
|
||||||
|
hooks: "@/hooks",
|
||||||
|
utils: "@/utils",
|
||||||
|
},
|
||||||
|
resolvedPaths: {
|
||||||
|
cwd: "/test/project",
|
||||||
|
tailwindConfig: "/test/project/tailwind.config.js",
|
||||||
|
tailwindCss: "/test/project/app/globals.css",
|
||||||
|
components: "/test/project/components",
|
||||||
|
ui: "/test/project/components/ui",
|
||||||
|
lib: "/test/project/lib",
|
||||||
|
hooks: "/test/project/hooks",
|
||||||
|
utils: "/test/project/utils",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("updateEnvVars", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.resetAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should create new .env.local file when none exists", async () => {
|
||||||
|
vi.mocked(existsSync).mockReturnValue(false)
|
||||||
|
|
||||||
|
const envVars = {
|
||||||
|
API_KEY: "test-key",
|
||||||
|
API_URL: "https://api.example.com",
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await updateEnvVars(envVars, mockConfig, { silent: true })
|
||||||
|
|
||||||
|
expect(vi.mocked(fs.writeFile)).toHaveBeenCalledWith(
|
||||||
|
"/test/project/.env.local",
|
||||||
|
"API_KEY=test-key\nAPI_URL=https://api.example.com\n",
|
||||||
|
"utf-8"
|
||||||
|
)
|
||||||
|
expect(result).toEqual({
|
||||||
|
envVarsAdded: ["API_KEY", "API_URL"],
|
||||||
|
envFileUpdated: null,
|
||||||
|
envFileCreated: ".env.local",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should update existing .env.local file with new variables", async () => {
|
||||||
|
vi.mocked(existsSync).mockReturnValue(true)
|
||||||
|
vi.mocked(fs.readFile).mockResolvedValue("EXISTING_KEY=existing-value\n")
|
||||||
|
|
||||||
|
const envVars = {
|
||||||
|
NEW_KEY: "new-value",
|
||||||
|
ANOTHER_KEY: "another-value",
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await updateEnvVars(envVars, mockConfig, { silent: true })
|
||||||
|
|
||||||
|
expect(vi.mocked(fs.writeFile)).toHaveBeenCalledWith(
|
||||||
|
"/test/project/.env.local",
|
||||||
|
"EXISTING_KEY=existing-value\n\nNEW_KEY=new-value\nANOTHER_KEY=another-value\n",
|
||||||
|
"utf-8"
|
||||||
|
)
|
||||||
|
expect(result).toEqual({
|
||||||
|
envVarsAdded: ["NEW_KEY", "ANOTHER_KEY"],
|
||||||
|
envFileUpdated: ".env.local",
|
||||||
|
envFileCreated: null,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should skip when all variables already exist", async () => {
|
||||||
|
vi.mocked(existsSync).mockReturnValue(true)
|
||||||
|
vi.mocked(fs.readFile).mockResolvedValue(
|
||||||
|
"API_KEY=existing-key\nAPI_URL=existing-url\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
const envVars = {
|
||||||
|
API_KEY: "new-key",
|
||||||
|
API_URL: "new-url",
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await updateEnvVars(envVars, mockConfig, { silent: true })
|
||||||
|
|
||||||
|
expect(vi.mocked(fs.writeFile)).not.toHaveBeenCalled()
|
||||||
|
expect(result).toEqual({
|
||||||
|
envVarsAdded: [],
|
||||||
|
envFileUpdated: null,
|
||||||
|
envFileCreated: null,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should find and use .env.local when .env doesn't exist", async () => {
|
||||||
|
vi.mocked(existsSync).mockImplementation((path) => {
|
||||||
|
const pathStr = typeof path === "string" ? path : path.toString()
|
||||||
|
return pathStr.endsWith(".env.local")
|
||||||
|
})
|
||||||
|
vi.mocked(fs.readFile).mockResolvedValue("EXISTING_VAR=value\n")
|
||||||
|
|
||||||
|
const envVars = {
|
||||||
|
NEW_VAR: "new-value",
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await updateEnvVars(envVars, mockConfig, { silent: true })
|
||||||
|
|
||||||
|
expect(vi.mocked(fs.writeFile)).toHaveBeenCalledWith(
|
||||||
|
"/test/project/.env.local",
|
||||||
|
"EXISTING_VAR=value\n\nNEW_VAR=new-value\n",
|
||||||
|
"utf-8"
|
||||||
|
)
|
||||||
|
expect(result).toEqual({
|
||||||
|
envVarsAdded: ["NEW_VAR"],
|
||||||
|
envFileUpdated: ".env.local",
|
||||||
|
envFileCreated: null,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should return early when no env vars provided", async () => {
|
||||||
|
const result = await updateEnvVars(undefined, mockConfig, { silent: true })
|
||||||
|
|
||||||
|
expect(vi.mocked(fs.writeFile)).not.toHaveBeenCalled()
|
||||||
|
expect(result).toEqual({
|
||||||
|
envVarsAdded: [],
|
||||||
|
envFileUpdated: null,
|
||||||
|
envFileCreated: null,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should return early when empty env vars object provided", async () => {
|
||||||
|
const result = await updateEnvVars({}, mockConfig, { silent: true })
|
||||||
|
|
||||||
|
expect(vi.mocked(fs.writeFile)).not.toHaveBeenCalled()
|
||||||
|
expect(result).toEqual({
|
||||||
|
envVarsAdded: [],
|
||||||
|
envFileUpdated: null,
|
||||||
|
envFileCreated: null,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
108
packages/shadcn/src/utils/updaters/update-env-vars.ts
Normal file
108
packages/shadcn/src/utils/updaters/update-env-vars.ts
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import { existsSync, promises as fs } from "fs"
|
||||||
|
import path from "path"
|
||||||
|
import { registryItemEnvVarsSchema } from "@/src/registry/schema"
|
||||||
|
import {
|
||||||
|
findExistingEnvFile,
|
||||||
|
getNewEnvKeys,
|
||||||
|
mergeEnvContent,
|
||||||
|
} from "@/src/utils/env-helpers"
|
||||||
|
import { Config } from "@/src/utils/get-config"
|
||||||
|
import { highlighter } from "@/src/utils/highlighter"
|
||||||
|
import { logger } from "@/src/utils/logger"
|
||||||
|
import { spinner } from "@/src/utils/spinner"
|
||||||
|
import { z } from "zod"
|
||||||
|
|
||||||
|
export async function updateEnvVars(
|
||||||
|
envVars: z.infer<typeof registryItemEnvVarsSchema> | undefined,
|
||||||
|
config: Config,
|
||||||
|
options: {
|
||||||
|
silent?: boolean
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
if (!envVars || Object.keys(envVars).length === 0) {
|
||||||
|
return {
|
||||||
|
envVarsAdded: [],
|
||||||
|
envFileUpdated: null,
|
||||||
|
envFileCreated: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
options = {
|
||||||
|
silent: false,
|
||||||
|
...options,
|
||||||
|
}
|
||||||
|
|
||||||
|
const envSpinner = spinner(`Adding environment variables.`, {
|
||||||
|
silent: options.silent,
|
||||||
|
})?.start()
|
||||||
|
|
||||||
|
const projectRoot = config.resolvedPaths.cwd
|
||||||
|
|
||||||
|
// Find existing env file or use .env.local as default.
|
||||||
|
let envFilePath = path.join(projectRoot, ".env.local")
|
||||||
|
const existingEnvFile = findExistingEnvFile(projectRoot)
|
||||||
|
|
||||||
|
if (existingEnvFile) {
|
||||||
|
envFilePath = existingEnvFile
|
||||||
|
}
|
||||||
|
|
||||||
|
const envFileExists = existsSync(envFilePath)
|
||||||
|
const envFileName = path.basename(envFilePath)
|
||||||
|
|
||||||
|
// Convert envVars object to env file format
|
||||||
|
const newEnvContent = Object.entries(envVars)
|
||||||
|
.map(([key, value]) => `${key}=${value}`)
|
||||||
|
.join("\n")
|
||||||
|
|
||||||
|
let envVarsAdded: string[] = []
|
||||||
|
let envFileUpdated: string | null = null
|
||||||
|
let envFileCreated: string | null = null
|
||||||
|
|
||||||
|
if (envFileExists) {
|
||||||
|
const existingContent = await fs.readFile(envFilePath, "utf-8")
|
||||||
|
const mergedContent = mergeEnvContent(existingContent, newEnvContent)
|
||||||
|
envVarsAdded = getNewEnvKeys(existingContent, newEnvContent)
|
||||||
|
|
||||||
|
if (envVarsAdded.length > 0) {
|
||||||
|
await fs.writeFile(envFilePath, mergedContent, "utf-8")
|
||||||
|
envFileUpdated = path.relative(projectRoot, envFilePath)
|
||||||
|
|
||||||
|
envSpinner?.succeed(
|
||||||
|
`Added the following variables to ${highlighter.info(envFileName)}:`
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!options.silent) {
|
||||||
|
for (const key of envVarsAdded) {
|
||||||
|
logger.log(` ${highlighter.success("+")} ${key}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
envSpinner?.stop()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Create new env file
|
||||||
|
await fs.writeFile(envFilePath, newEnvContent + "\n", "utf-8")
|
||||||
|
envFileCreated = path.relative(projectRoot, envFilePath)
|
||||||
|
envVarsAdded = Object.keys(envVars)
|
||||||
|
|
||||||
|
envSpinner?.succeed(
|
||||||
|
`Added the following variables to ${highlighter.info(envFileName)}:`
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!options.silent) {
|
||||||
|
for (const key of envVarsAdded) {
|
||||||
|
logger.log(` ${highlighter.success("+")} ${key}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.silent && envVarsAdded.length > 0) {
|
||||||
|
logger.break()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
envVarsAdded,
|
||||||
|
envFileUpdated,
|
||||||
|
envFileCreated,
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user