infra-kit 0.1.74 → 0.1.76

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "infra-kit",
3
3
  "type": "module",
4
- "version": "0.1.74",
4
+ "version": "0.1.76",
5
5
  "description": "infra-kit",
6
6
  "main": "dist/cli.js",
7
7
  "module": "dist/cli.js",
@@ -3,24 +3,26 @@ import path from 'node:path'
3
3
  import process from 'node:process'
4
4
  import { z } from 'zod'
5
5
 
6
- import type { EnvCache } from 'src/lib/constants'
7
6
  import {
8
- ENV_CACHE_DIR,
9
- ENV_CACHE_FILE,
7
+ ENV_CLEAR_FILE,
8
+ ENV_LOAD_FILE,
10
9
  INFRA_KIT_ENV_CONFIG_VAR,
11
10
  INFRA_KIT_ENV_LOADED_AT_VAR,
12
11
  INFRA_KIT_ENV_PROJECT_VAR,
12
+ getSessionCacheDir,
13
+ parseVarNamesFromEnvFile,
13
14
  } from 'src/lib/constants'
14
15
  import { logger } from 'src/lib/logger'
15
16
  import type { ToolsExecutionResult } from 'src/types'
16
17
 
17
18
  /**
18
- * Clear previously loaded environment variables. Usage: source <(infra-kit env-clear)
19
+ * Clear loaded env vars. Prints a file path to stdout that must be sourced to apply. The env-clear shell alias does this automatically.
19
20
  */
20
21
  export const envClear = async (): Promise<ToolsExecutionResult> => {
21
- const cachePath = path.join(ENV_CACHE_DIR, ENV_CACHE_FILE)
22
+ const cacheDir = getSessionCacheDir()
23
+ const envLoadPath = path.join(cacheDir, ENV_LOAD_FILE)
22
24
 
23
- if (!process.env[INFRA_KIT_ENV_CONFIG_VAR]) {
25
+ if (!fs.existsSync(envLoadPath)) {
24
26
  logger.error('No loaded environment found. Run `env-load` first.')
25
27
 
26
28
  return {
@@ -33,46 +35,33 @@ export const envClear = async (): Promise<ToolsExecutionResult> => {
33
35
  }
34
36
  }
35
37
 
36
- const cache: EnvCache = JSON.parse(fs.readFileSync(cachePath, 'utf-8'))
37
- const varNames = cache.varNames
38
+ const varNames = parseVarNamesFromEnvFile(envLoadPath)
38
39
 
39
- // Only unset vars that are actually set in the current session
40
- const activeVars = varNames.filter((v) => {
41
- return v in process.env
42
- })
43
-
44
- if (activeVars.length === 0) {
45
- fs.unlinkSync(cachePath)
46
- logger.info('Current session is clear, no environment variables to unset.')
40
+ // Build unset script
41
+ const unsetLines = [
42
+ ...varNames.map((v) => {
43
+ return `unset ${v}`
44
+ }),
45
+ `unset ${INFRA_KIT_ENV_CONFIG_VAR}`,
46
+ `unset ${INFRA_KIT_ENV_PROJECT_VAR}`,
47
+ `unset ${INFRA_KIT_ENV_LOADED_AT_VAR}`,
48
+ ]
47
49
 
48
- return {
49
- content: [
50
- {
51
- type: 'text',
52
- text: 'Current session is clear, no environment variables to unset.',
53
- },
54
- ],
55
- }
56
- }
50
+ // Write unset script to cache
51
+ const clearFilePath = path.resolve(cacheDir, ENV_CLEAR_FILE)
57
52
 
58
- // Output unset statements for shell sourcing
59
- for (const varName of activeVars) {
60
- process.stdout.write(`unset ${varName}\n`)
61
- }
62
- process.stdout.write(`unset ${INFRA_KIT_ENV_CONFIG_VAR}\n`)
63
- process.stdout.write(`unset ${INFRA_KIT_ENV_PROJECT_VAR}\n`)
64
- process.stdout.write(`unset ${INFRA_KIT_ENV_LOADED_AT_VAR}\n`)
53
+ fs.mkdirSync(cacheDir, { recursive: true })
54
+ fs.writeFileSync(clearFilePath, `${unsetLines.join('\n')}\n`)
65
55
 
66
- // Remove cache file
67
- fs.unlinkSync(cachePath)
56
+ // REQUIRED
57
+ process.stdout.write(`${clearFilePath}\n`)
68
58
 
69
- logger.info(`Cleared ${activeVars.length} environment variables`)
59
+ // Remove env load file so env-clear can detect "no env loaded" next time
60
+ fs.unlinkSync(envLoadPath)
70
61
 
71
62
  const structuredContent = {
72
- variableCount: activeVars.length,
73
- unsetStatements: activeVars.map((v) => {
74
- return `unset ${v}`
75
- }),
63
+ variableCount: varNames.length,
64
+ unsetStatements: unsetLines,
76
65
  }
77
66
 
78
67
  return {
@@ -89,9 +78,11 @@ export const envClear = async (): Promise<ToolsExecutionResult> => {
89
78
  // MCP Tool Registration
90
79
  export const envClearMcpTool = {
91
80
  name: 'env-clear',
92
- description: 'Clear previously loaded environment variables. Usage: source <(infra-kit env-clear)',
81
+ description:
82
+ 'Clear loaded env vars. Returns a file path that must be sourced (source <path>) to apply. The env-clear shell alias does this automatically.',
93
83
  inputSchema: {},
94
84
  outputSchema: {
85
+ filePath: z.string().describe('Path to the file that must be sourced to apply'),
95
86
  variableCount: z.number().describe('Number of variables cleared'),
96
87
  unsetStatements: z.array(z.string()).describe('Unset statements generated'),
97
88
  },
@@ -0,0 +1,69 @@
1
+ import fs from 'node:fs'
2
+ import os from 'node:os'
3
+ import path from 'node:path'
4
+
5
+ import { logger } from 'src/lib/logger'
6
+
7
+ const MARKER_COMMENT = '# infra-kit shell functions'
8
+
9
+ /**
10
+ * Append infra-kit shell functions directly to .zshrc.
11
+ */
12
+ export const envInit = async (): Promise<void> => {
13
+ const zshrcPath = path.join(os.homedir(), '.zshrc')
14
+ const shellBlock = buildShellBlock()
15
+
16
+ if (fs.existsSync(zshrcPath)) {
17
+ const content = fs.readFileSync(zshrcPath, 'utf-8')
18
+ const cleaned = removeExistingBlock(content)
19
+
20
+ fs.writeFileSync(zshrcPath, cleaned)
21
+ }
22
+
23
+ fs.appendFileSync(zshrcPath, `\n${shellBlock}\n`)
24
+ logger.info(`Added infra-kit shell functions to ${zshrcPath}`)
25
+ logger.info('Run `source ~/.zshrc` or open a new terminal to activate.')
26
+ }
27
+
28
+ const isBlockLine = (line: string): boolean => {
29
+ return (
30
+ line.startsWith('#') ||
31
+ line.startsWith('env-load') ||
32
+ line.startsWith('env-clear') ||
33
+ line.startsWith('if ') ||
34
+ line.startsWith(' export INFRA_KIT_SESSION') ||
35
+ line.startsWith('fi')
36
+ )
37
+ }
38
+
39
+ const removeExistingBlock = (content: string): string => {
40
+ const markerIdx = content.indexOf(MARKER_COMMENT)
41
+
42
+ if (markerIdx === -1) return content
43
+
44
+ const before = content.slice(0, markerIdx).replace(/\n+$/, '')
45
+ const afterLines = content.slice(markerIdx).split('\n')
46
+
47
+ let i = 0
48
+
49
+ while (i < afterLines.length && isBlockLine(afterLines[i]!)) {
50
+ i++
51
+ }
52
+
53
+ const remaining = afterLines.slice(i).join('\n')
54
+
55
+ return before + (remaining ? `\n${remaining}` : '')
56
+ }
57
+
58
+ const buildShellBlock = (): string => {
59
+ const runCmd = 'pnpm dlx infra-kit'
60
+
61
+ return [
62
+ MARKER_COMMENT,
63
+ 'if [[ -z "${INFRA_KIT_SESSION}" ]]; then',
64
+ ' export INFRA_KIT_SESSION=$(head -c 4 /dev/urandom | xxd -p)',
65
+ 'fi',
66
+ `env-load() { local f; f=$(${runCmd} env-load "$@") && source "$f" && ${runCmd} env-status; }`,
67
+ `env-clear() { local f; f=$(${runCmd} env-clear) && source "$f" && ${runCmd} env-status; }`,
68
+ ].join('\n')
69
+ }
@@ -0,0 +1 @@
1
+ export { envInit } from './env-init'
@@ -1,3 +1,4 @@
1
+ import select from '@inquirer/select'
1
2
  import fs from 'node:fs'
2
3
  import path from 'node:path'
3
4
  import process from 'node:process'
@@ -6,19 +7,19 @@ import { $ } from 'zx'
6
7
 
7
8
  import { validateDopplerCliAndAuth } from 'src/integrations/doppler'
8
9
  import { getDopplerProject } from 'src/integrations/doppler/doppler-project'
9
- import type { EnvCache } from 'src/lib/constants'
10
+ import { commandEcho } from 'src/lib/command-echo'
10
11
  import {
11
- ENV_CACHE_DIR,
12
- ENV_CACHE_FILE,
12
+ ENV_LOAD_FILE,
13
+ ENVs,
13
14
  INFRA_KIT_ENV_CONFIG_VAR,
14
15
  INFRA_KIT_ENV_LOADED_AT_VAR,
15
16
  INFRA_KIT_ENV_PROJECT_VAR,
17
+ getSessionCacheDir,
16
18
  } from 'src/lib/constants'
17
- import { logger } from 'src/lib/logger'
18
19
  import type { ToolsExecutionResult } from 'src/types'
19
20
 
20
21
  interface EnvLoadArgs {
21
- config: string
22
+ config?: string
22
23
  }
23
24
 
24
25
  /**
@@ -29,42 +30,67 @@ export const envLoad = async (args: EnvLoadArgs): Promise<ToolsExecutionResult>
29
30
 
30
31
  const { config } = args
31
32
 
33
+ commandEcho.start('env-load')
34
+
35
+ let selectedConfig = ''
36
+
37
+ if (config) {
38
+ selectedConfig = config
39
+ } else {
40
+ commandEcho.setInteractive()
41
+ selectedConfig = await select(
42
+ {
43
+ message: 'Select environment config',
44
+ choices: ENVs.map((env) => {
45
+ return { name: env, value: env }
46
+ }),
47
+ },
48
+ // Render to stderr so the prompt is visible when stdout is captured via $() in the shell function.
49
+ // Only env-load and env-clear use the $() stdout-capture shell pattern.
50
+ { output: process.stderr },
51
+ )
52
+ }
53
+
54
+ commandEcho.addOption('--config', selectedConfig)
55
+
32
56
  const project = await getDopplerProject()
33
57
 
34
- const result = await $`doppler secrets download --no-file --format env --project ${project} --config ${config}`
35
- const envContent = result.stdout.trim()
58
+ $.quiet = true
59
+ const result =
60
+ await $`doppler secrets download --no-file --format env --project ${project} --config ${selectedConfig}`
36
61
 
37
- // Output shell-sourceable format
38
- process.stdout.write('set -a\n')
39
- process.stdout.write(`${envContent}\n`)
40
- process.stdout.write('set +a\n')
41
- process.stdout.write(`export ${INFRA_KIT_ENV_CONFIG_VAR}=${config}\n`)
42
- process.stdout.write(`export ${INFRA_KIT_ENV_PROJECT_VAR}=${project}\n`)
43
- process.stdout.write(`export ${INFRA_KIT_ENV_LOADED_AT_VAR}=${new Date().toISOString()}\n`)
62
+ $.quiet = false
63
+ const envContent = result.stdout.trim()
44
64
 
45
- // Extract variable names and save to cache
46
- const varNames = envContent
47
- .split('\n')
48
- .filter((line) => {
49
- return line.includes('=')
50
- })
51
- .map((line) => {
52
- return line.split('=')[0]!
53
- })
65
+ // Build env file content in dotenv format
66
+ const loadedAt = new Date().toISOString()
67
+ const envFileLines = [
68
+ 'set -a',
69
+ envContent,
70
+ `${INFRA_KIT_ENV_CONFIG_VAR}=${selectedConfig}`,
71
+ `${INFRA_KIT_ENV_PROJECT_VAR}=${project}`,
72
+ `${INFRA_KIT_ENV_LOADED_AT_VAR}=${loadedAt}`,
73
+ 'set +a',
74
+ ]
54
75
 
55
- const cachePath = path.join(ENV_CACHE_DIR, ENV_CACHE_FILE)
76
+ // Write env file to cache
77
+ const cacheDir = getSessionCacheDir()
78
+ const envFilePath = path.resolve(cacheDir, ENV_LOAD_FILE)
56
79
 
57
- const cache: EnvCache = { config, loadedAt: new Date().toISOString(), varNames }
80
+ fs.mkdirSync(cacheDir, { recursive: true })
81
+ fs.writeFileSync(envFilePath, `${envFileLines.join('\n')}\n`)
58
82
 
59
- fs.mkdirSync(ENV_CACHE_DIR, { recursive: true })
60
- fs.writeFileSync(cachePath, JSON.stringify(cache, null, 2))
83
+ // REQUIRED
84
+ process.stdout.write(`${envFilePath}\n`)
61
85
 
62
- logger.info(`Loaded ${varNames.length} variables from ${project}/${config}`)
86
+ const varCount = envContent.split('\n').filter((line) => {
87
+ return line.includes('=')
88
+ }).length
63
89
 
64
90
  const structuredContent = {
65
- variableCount: varNames.length,
91
+ variableCount: varCount,
66
92
  project,
67
- config,
93
+ config: selectedConfig,
68
94
  }
69
95
 
70
96
  return {
@@ -81,11 +107,13 @@ export const envLoad = async (args: EnvLoadArgs): Promise<ToolsExecutionResult>
81
107
  // MCP Tool Registration
82
108
  export const envLoadMcpTool = {
83
109
  name: 'env-load',
84
- description: 'Load environment variables from Doppler for a given config. Usage: source <(infra-kit env-load -c dev)',
110
+ description:
111
+ 'Load Doppler env vars for a config. Returns a file path that must be sourced (source <path>) to apply variables. The env-load shell alias does this automatically.',
85
112
  inputSchema: {
86
113
  config: z.string().describe('Environment config name to load (e.g. dev, arthur, renana)'),
87
114
  },
88
115
  outputSchema: {
116
+ filePath: z.string().describe('Path to the file that must be sourced to apply variables'),
89
117
  variableCount: z.number().describe('Number of variables loaded'),
90
118
  project: z.string().describe('Doppler project name'),
91
119
  config: z.string().describe('Doppler config name'),
@@ -1,18 +1,16 @@
1
- import fs from 'node:fs'
2
1
  import path from 'node:path'
3
2
  import process from 'node:process'
4
3
  import { z } from 'zod'
5
4
 
6
5
  import { validateDopplerCliAndAuth } from 'src/integrations/doppler'
7
- import { getDopplerProject } from 'src/integrations/doppler/doppler-project'
8
- import type { EnvCache } from 'src/lib/constants'
9
6
  import {
10
- ENV_CACHE_DIR,
11
- ENV_CACHE_FILE,
12
- ENVs,
7
+ ENV_LOAD_FILE,
13
8
  INFRA_KIT_ENV_CONFIG_VAR,
14
9
  INFRA_KIT_ENV_LOADED_AT_VAR,
15
10
  INFRA_KIT_ENV_PROJECT_VAR,
11
+ INFRA_KIT_SESSION_VAR,
12
+ getSessionCacheDir,
13
+ parseVarNamesFromEnvFile,
16
14
  } from 'src/lib/constants'
17
15
  import { logger } from 'src/lib/logger'
18
16
  import type { ToolsExecutionResult } from 'src/types'
@@ -23,15 +21,13 @@ import type { ToolsExecutionResult } from 'src/types'
23
21
  export const envStatus = async (): Promise<ToolsExecutionResult> => {
24
22
  await validateDopplerCliAndAuth()
25
23
 
26
- const project = await getDopplerProject()
24
+ logger.info('Environment Session Status:\n')
27
25
 
28
- logger.info('Doppler Environment Status:\n')
29
- logger.info(` Authenticated: yes`)
30
- logger.info(` Detected Project: ${project}`)
31
- logger.info(` Available Configs: ${ENVs.join(', ')}`)
26
+ // Check session-loaded vars — getSessionCacheDir() throws if INFRA_KIT_SESSION is unset
27
+ const cacheDir = getSessionCacheDir()
32
28
 
33
- // Check session-loaded vars
34
- const cachePath = path.join(ENV_CACHE_DIR, ENV_CACHE_FILE)
29
+ const sessionId = process.env[INFRA_KIT_SESSION_VAR]!
30
+ const envLoadPath = path.join(cacheDir, ENV_LOAD_FILE)
35
31
 
36
32
  let sessionLoadedCount = 0
37
33
  let sessionTotalCount = 0
@@ -40,11 +36,11 @@ export const envStatus = async (): Promise<ToolsExecutionResult> => {
40
36
  const sessionLoadedAt = process.env[INFRA_KIT_ENV_LOADED_AT_VAR] ?? null
41
37
 
42
38
  if (sessionConfig) {
43
- if (fs.existsSync(cachePath)) {
44
- const cache: EnvCache = JSON.parse(fs.readFileSync(cachePath, 'utf-8'))
39
+ const varNames = parseVarNamesFromEnvFile(envLoadPath)
45
40
 
46
- sessionTotalCount = cache.varNames.length
47
- sessionLoadedCount = cache.varNames.filter((v) => {
41
+ if (varNames.length > 0) {
42
+ sessionTotalCount = varNames.length
43
+ sessionLoadedCount = varNames.filter((v) => {
48
44
  return v in process.env
49
45
  }).length
50
46
  }
@@ -55,11 +51,10 @@ export const envStatus = async (): Promise<ToolsExecutionResult> => {
55
51
  } else {
56
52
  logger.info(' Session: no env loaded')
57
53
  }
54
+ logger.info(` Session ID: ${sessionId}`)
58
55
 
59
56
  const structuredContent = {
60
- authenticated: true,
61
- project,
62
- configs: ENVs,
57
+ sessionId,
63
58
  sessionLoadedCount,
64
59
  sessionTotalCount,
65
60
  sessionConfig,
@@ -84,9 +79,7 @@ export const envStatusMcpTool = {
84
79
  description: 'Show Doppler authentication status and detected project info',
85
80
  inputSchema: {},
86
81
  outputSchema: {
87
- authenticated: z.boolean().describe('Whether the user is authenticated'),
88
- project: z.string().describe('Detected Doppler project name'),
89
- configs: z.array(z.string()).describe('Available environment configs'),
82
+ sessionId: z.string().describe('Current terminal session ID'),
90
83
  sessionLoadedCount: z.number().describe('Number of cached vars active in the current session'),
91
84
  sessionTotalCount: z.number().describe('Total number of cached var names'),
92
85
  sessionConfig: z.string().nullable().describe('Doppler config name of the loaded session'),
package/src/entry/cli.ts CHANGED
@@ -2,6 +2,7 @@ import { Command } from 'commander'
2
2
 
3
3
  import { doctor } from 'src/commands/doctor'
4
4
  import { envClear } from 'src/commands/env-clear'
5
+ import { envInit } from 'src/commands/env-init'
5
6
  import { envList } from 'src/commands/env-list'
6
7
  import { envLoad } from 'src/commands/env-load'
7
8
  import { envStatus } from 'src/commands/env-status'
@@ -18,10 +19,6 @@ import { worktreesAdd } from 'src/commands/worktrees-add'
18
19
  import { worktreesList } from 'src/commands/worktrees-list'
19
20
  import { worktreesRemove } from 'src/commands/worktrees-remove'
20
21
  import { worktreesSync } from 'src/commands/worktrees-sync'
21
- import { loadEnvFromGitRoot } from 'src/lib/load-env'
22
-
23
- // Load .env before anything else
24
- await loadEnvFromGitRoot()
25
22
 
26
23
  const program = new Command()
27
24
 
@@ -177,17 +174,24 @@ program
177
174
  await envList()
178
175
  })
179
176
 
177
+ program
178
+ .command('env-init')
179
+ .description('Set up shell functions for env-load/env-clear in .zshrc')
180
+ .action(async () => {
181
+ await envInit()
182
+ })
183
+
180
184
  program
181
185
  .command('env-load')
182
- .description('Load environment variables from Doppler. Usage: source <(infra-kit env-load -c dev)')
183
- .requiredOption('-c, --config <config>', 'Environment config name to load (e.g. dev, arthur)')
186
+ .description('Load Doppler env vars for a config. Prints a file path to stdout — auto-sourced by the env-load shell alias, or run source <path> manually')
187
+ .option('-c, --config <config>', 'Environment config name to load (e.g. dev, arthur)')
184
188
  .action(async (options) => {
185
189
  await envLoad({ config: options.config })
186
190
  })
187
191
 
188
192
  program
189
193
  .command('env-clear')
190
- .description('Clear previously loaded environment variables. Usage: source <(infra-kit env-clear)')
194
+ .description('Clear loaded env vars. Prints a file path to stdout — auto-sourced by the env-clear shell alias, or run source <path> manually')
191
195
  .action(async () => {
192
196
  await envClear()
193
197
  })
package/src/entry/mcp.ts CHANGED
@@ -1,16 +1,11 @@
1
- /* eslint-disable antfu/no-top-level-await */
2
1
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
3
2
  import process from 'node:process'
4
3
 
5
4
  import { setupErrorHandlers } from 'src/lib/error-handlers'
6
- import { loadEnvFromGitRoot } from 'src/lib/load-env'
7
5
  import { initLoggerMcp } from 'src/lib/logger'
8
6
 
9
7
  import { createMcpServer } from '../mcp/server'
10
8
 
11
- // Load .env before anything else
12
- await loadEnvFromGitRoot()
13
-
14
9
  const logger = initLoggerMcp()
15
10
 
16
11
  const startServer = async () => {
@@ -1,3 +1,7 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import process from 'node:process'
4
+
1
5
  /**
2
6
  * List of environments for the project deployment
3
7
  */
@@ -9,16 +13,37 @@ export const DOPPLER_PROJECT_MAP: Record<string, string> = {
9
13
  }
10
14
 
11
15
  export const ENV_CACHE_DIR = './node_modules/.cache/infra-kit'
12
- export const ENV_CACHE_FILE = 'env-cache.json'
16
+ export const ENV_LOAD_FILE = 'env-load.sh'
17
+ export const ENV_CLEAR_FILE = 'env-clear.sh'
13
18
 
19
+ export const INFRA_KIT_SESSION_VAR = 'INFRA_KIT_SESSION'
14
20
  export const INFRA_KIT_ENV_CONFIG_VAR = 'INFRA_KIT_ENV_CONFIG'
15
21
  export const INFRA_KIT_ENV_PROJECT_VAR = 'INFRA_KIT_ENV_PROJECT'
16
22
  export const INFRA_KIT_ENV_LOADED_AT_VAR = 'INFRA_KIT_ENV_LOADED_AT'
17
23
 
18
- export interface EnvCache {
19
- config: string
20
- loadedAt: string
21
- varNames: string[]
24
+ export const parseVarNamesFromEnvFile = (filePath: string): string[] => {
25
+ if (!fs.existsSync(filePath)) return []
26
+
27
+ const content = fs.readFileSync(filePath, 'utf-8')
28
+
29
+ return content
30
+ .split('\n')
31
+ .filter((line) => {
32
+ return line.includes('=') && !line.startsWith('set ')
33
+ })
34
+ .map((line) => {
35
+ return line.split('=')[0]!
36
+ })
37
+ }
38
+
39
+ export const getSessionCacheDir = (): string => {
40
+ const session = process.env[INFRA_KIT_SESSION_VAR]
41
+
42
+ if (!session) {
43
+ throw new Error('INFRA_KIT_SESSION is not set. Run `source ~/.zshrc` or `infra-kit env-init` first.')
44
+ }
45
+
46
+ return path.join(ENV_CACHE_DIR, session)
22
47
  }
23
48
 
24
49
  export const WORKTREES_DIR_SUFFIX = '-worktrees'
@@ -27,6 +27,7 @@ export const initLoggerCLI = () => {
27
27
  const logger = pino(
28
28
  { level: logLevel },
29
29
  pretty({
30
+ destination: 2,
30
31
  ignore: ignoreFields.join(','),
31
32
  colorize: true,
32
33
  }),
@@ -1 +0,0 @@
1
- export { loadEnvFromGitRoot } from './load-env'
@@ -1,28 +0,0 @@
1
- import { config } from 'dotenv'
2
- import { resolve } from 'node:path'
3
- import { $ } from 'zx'
4
-
5
- import { getProjectRoot } from 'src/lib/git-utils'
6
- import { logger } from 'src/lib/logger'
7
-
8
- /**
9
- * Load .env file from git repository root
10
- * Uses getProjectRoot to find the repository root, works regardless of where package is installed
11
- */
12
- export const loadEnvFromGitRoot = async (): Promise<void> => {
13
- try {
14
- $.quiet = true
15
-
16
- const gitRoot = await getProjectRoot()
17
-
18
- // TODO: remove this after new env managemement
19
- config({ path: resolve(gitRoot, '.env'), quiet: true })
20
-
21
- logger.info('Loaded .env file from git repository root')
22
- } catch {
23
- // Git command failed - not in a git repository or git not available
24
- // This is acceptable, env vars might be provided another way
25
- } finally {
26
- $.quiet = false
27
- }
28
- }