@bintvn/lite-env 1.0.8 → 1.0.9

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/index.cjs CHANGED
@@ -152,12 +152,14 @@ function loadEnv(allowedEnvKeys = {}, bypassUnknownEnvKeys = true, NODE_ENV) {
152
152
  if (globalThis.liteEnv)
153
153
  return globalThis.liteEnv;
154
154
  if (NODE_ENV) {
155
+ NODE_ENV = NODE_ENV.trim();
155
156
  process.env.NODE_ENV = NODE_ENV;
156
157
  } else {
157
158
  if (!process.env.NODE_ENV) {
158
159
  process.env.NODE_ENV = "production";
159
160
  NODE_ENV = "production";
160
161
  } else {
162
+ process.env.NODE_ENV = process.env.NODE_ENV.trim();
161
163
  NODE_ENV = process.env.NODE_ENV;
162
164
  }
163
165
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/helper.ts"],"sourcesContent":["import path from 'path'\r\nimport { existsSync } from 'fs'\r\nimport { formatError, getUnknownEnvKeys, readEnvFile, safeParse } from './helper.js'\r\nimport { AllowedEnvKeys, LoadedEnv } from \"./types.js\";\r\n\r\nexport type { AllowedEnvKeys, EnvKind, EnvKindMap, LoadedEnv } from \"./types.js\"\r\n\r\ndeclare global {\r\n var liteEnv: unknown\r\n}\r\n\r\nexport function loadEnv<TSchema extends AllowedEnvKeys = {}>(\r\n allowedEnvKeys: TSchema = {} as TSchema,\r\n bypassUnknownEnvKeys: boolean = true,\r\n NODE_ENV?: string\r\n): LoadedEnv<TSchema> {\r\n if (globalThis.liteEnv)\r\n return globalThis.liteEnv as LoadedEnv<TSchema>\r\n\r\n if (NODE_ENV) {\r\n process.env.NODE_ENV = NODE_ENV\r\n } else {\r\n if (!process.env.NODE_ENV) {\r\n process.env.NODE_ENV = 'production'\r\n\r\n NODE_ENV = 'production'\r\n } else {\r\n NODE_ENV = process.env.NODE_ENV\r\n }\r\n }\r\n\r\n const defaultEnvPath = path.join(process.cwd(), '.env')\r\n const nodeEnvPath = path.join(process.cwd(), `.env.${NODE_ENV}`)\r\n\r\n if (!existsSync(defaultEnvPath))\r\n throw new Error('Default Environment file not found')\r\n\r\n if (!existsSync(nodeEnvPath))\r\n throw new Error(`Environment file not found: .env.${NODE_ENV}`)\r\n\r\n const defaultEnvSource = readEnvFile(defaultEnvPath)\r\n const nodeEnvSource = readEnvFile(nodeEnvPath)\r\n\r\n const mergedEnv: Record<string, string> = {}\r\n\r\n if (defaultEnvSource)\r\n Object.assign(mergedEnv, defaultEnvSource)\r\n if (nodeEnvSource)\r\n Object.assign(mergedEnv, nodeEnvSource)\r\n\r\n if (!bypassUnknownEnvKeys) {\r\n const unknownKeys = [...new Set([...getUnknownEnvKeys(mergedEnv, new Set(Object.keys(allowedEnvKeys)))])]\r\n\r\n if (unknownKeys.length > 0)\r\n throw new Error(`Unknown environment variables in env files: ${unknownKeys.join(', ')}`)\r\n } else {\r\n process.env = {\r\n ...({ NODE_ENV: process.env.NODE_ENV ? process.env.NODE_ENV : 'production' }),\r\n ...process.env,\r\n ...mergedEnv\r\n }\r\n }\r\n\r\n const parsedEnv = safeParse(allowedEnvKeys, mergedEnv)\r\n\r\n if (!parsedEnv.success)\r\n throw new Error(`Environment validation failed: ${formatError(parsedEnv.error)}`)\r\n\r\n globalThis.liteEnv = parsedEnv.data\r\n\r\n parsedEnv.data = {\r\n ...parsedEnv.data,\r\n NODE_ENV\r\n }\r\n\r\n console.log('Loaded env file', `${defaultEnvPath}, ${nodeEnvPath}`)\r\n\r\n return parsedEnv.data as LoadedEnv<TSchema>\r\n}\r\n","import { existsSync, readFileSync } from \"fs\"\nimport { AllowedEnvKeys, EnvKind, EnvKindMap, LoadedEnv } from \"./types.js\"\n\r\nexport function toString(value: string): string {\r\n return String(value)\r\n}\r\n\r\nexport function toNumber(value: string): number {\n const parsed = Number(value)\n if (Number.isNaN(parsed))\n throw new Error('Value is not supported for number')\n\n return parsed\n}\n\r\nexport function toArray(value: string): string[] {\r\n if (!value.includes(','))\r\n throw new Error('Valur is not supported for array')\r\n\r\n return value.split(',')\r\n}\r\n\r\nexport function toBoolean(value: string): boolean {\n if (value === 'true' || value === '1')\n return true\n\n if (value === 'false' || value === '0')\n return false\n\n throw new Error('Value is not supported for boolean')\n}\n\r\nexport function toObject<T>(value: string): T {\r\n try {\r\n return JSON.parse(value)\r\n } catch (error) {\r\n throw new Error('Value is not supported for object')\r\n }\r\n}\r\n\r\nexport function toBuffer(value: string, encoding?: BufferEncoding): Buffer {\r\n try {\r\n return Buffer.from(value, encoding || 'base64')\r\n } catch (error) {\r\n throw new Error('Value is not supported for buffer')\r\n }\r\n}\r\n\r\nexport function toDate(value: string): Date {\n const parsed = new Date(value)\n if (Number.isNaN(parsed.getTime()))\n throw new Error('Value is not supported for date')\n\n return parsed\n}\n\nfunction parseEnvValue<TKind extends EnvKind>(kind: TKind, value: string): EnvKindMap[TKind] {\n switch (kind) {\n case \"string\":\n return toString(value) as EnvKindMap[TKind]\n case \"number\":\n return toNumber(value) as EnvKindMap[TKind]\n case \"boolean\":\n return toBoolean(value) as EnvKindMap[TKind]\n case \"array\":\n return toArray(value) as EnvKindMap[TKind]\n case \"object\":\n return toObject(value) as EnvKindMap[TKind]\n case \"buffer\":\n return toBuffer(value) as EnvKindMap[TKind]\n case \"date\":\n return toDate(value) as EnvKindMap[TKind]\n default: {\n const exhaustiveCheck: never = kind\n throw new Error(`Unsupported env kind: ${exhaustiveCheck}`)\n }\n }\n}\n\nexport function safeParse<TSchema extends AllowedEnvKeys>(allowedEnvKeys: TSchema, values: Record<string, string>) {\n const data: Partial<LoadedEnv<TSchema>> = {}\n const error: string[] = []\n\n for (const key of Object.keys(allowedEnvKeys) as Array<keyof TSchema>) {\n const value = values[key as string]\n if (value === undefined) continue\n\n try {\n data[key] = parseEnvValue(allowedEnvKeys[key], value)\n } catch (e) {\n if (e instanceof Error)\n error.push(`${String(key)}: ${e.message}`)\n else\n error.push(`${String(key)}: Unknown error occurred`)\n }\n }\n\n return {\n success: error.length === 0,\n data: data as LoadedEnv<TSchema>,\n error\n }\n}\n\r\nexport function formatError(message: string[]): string {\r\n return message.join('\\n')\r\n}\r\n\r\nexport function parseRawEnv(rawEnv: string): Record<string, string> {\r\n const result: Record<string, string> = {}\r\n const lines = rawEnv.split(/\\r?\\n/)\r\n\r\n for (const line of lines) {\r\n const normalized = line.trim()\r\n if (!normalized || normalized.startsWith('#')) continue\r\n\r\n const separatorIndex = normalized.indexOf('=')\r\n if (separatorIndex <= 0) continue\r\n\r\n const key = normalized.slice(0, separatorIndex).trim()\r\n const value = normalized.slice(separatorIndex + 1).trim()\r\n if (!key) continue\r\n\r\n result[key] = value\r\n }\r\n\r\n return result\r\n}\r\n\r\nexport function readEnvFile(filePath: string): false | Record<string, string> {\r\n if (!existsSync(filePath)) return false\r\n return parseRawEnv(readFileSync(filePath, 'utf-8'))\r\n}\r\n\r\nexport function getUnknownEnvKeys(source: Record<string, string>, allowedEnvKeys: Set<string>): string[] {\r\n return Object.keys(source).filter((key) => !allowedEnvKeys.has(key))\r\n}\r\n"],"mappings":"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","names":["import_fs","path"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/helper.ts"],"sourcesContent":["import path from 'path'\r\nimport { existsSync } from 'fs'\r\nimport { formatError, getUnknownEnvKeys, readEnvFile, safeParse } from './helper.js'\r\nimport { AllowedEnvKeys, LoadedEnv } from \"./types.js\";\r\n\r\nexport type { AllowedEnvKeys, EnvKind, EnvKindMap, LoadedEnv } from \"./types.js\"\r\n\r\ndeclare global {\r\n var liteEnv: unknown\r\n}\r\n\r\nexport function loadEnv<TSchema extends AllowedEnvKeys = {}>(\r\n allowedEnvKeys: TSchema = {} as TSchema,\r\n bypassUnknownEnvKeys: boolean = true,\r\n NODE_ENV?: string\r\n): LoadedEnv<TSchema> {\r\n if (globalThis.liteEnv)\r\n return globalThis.liteEnv as LoadedEnv<TSchema>\r\n\r\n if (NODE_ENV) {\r\n NODE_ENV = NODE_ENV.trim()\r\n\r\n process.env.NODE_ENV = NODE_ENV\r\n } else {\r\n if (!process.env.NODE_ENV) {\r\n process.env.NODE_ENV = 'production'\r\n\r\n NODE_ENV = 'production'\r\n } else {\r\n process.env.NODE_ENV = process.env.NODE_ENV.trim()\r\n NODE_ENV = process.env.NODE_ENV\r\n }\r\n }\r\n\r\n const defaultEnvPath = path.join(process.cwd(), '.env')\r\n const nodeEnvPath = path.join(process.cwd(), `.env.${NODE_ENV}`)\r\n\r\n if (!existsSync(defaultEnvPath))\r\n throw new Error('Default Environment file not found')\r\n\r\n if (!existsSync(nodeEnvPath))\r\n throw new Error(`Environment file not found: .env.${NODE_ENV}`)\r\n\r\n const defaultEnvSource = readEnvFile(defaultEnvPath)\r\n const nodeEnvSource = readEnvFile(nodeEnvPath)\r\n\r\n const mergedEnv: Record<string, string> = {}\r\n\r\n if (defaultEnvSource)\r\n Object.assign(mergedEnv, defaultEnvSource)\r\n if (nodeEnvSource)\r\n Object.assign(mergedEnv, nodeEnvSource)\r\n\r\n if (!bypassUnknownEnvKeys) {\r\n const unknownKeys = [...new Set([...getUnknownEnvKeys(mergedEnv, new Set(Object.keys(allowedEnvKeys)))])]\r\n\r\n if (unknownKeys.length > 0)\r\n throw new Error(`Unknown environment variables in env files: ${unknownKeys.join(', ')}`)\r\n } else {\r\n process.env = {\r\n ...({ NODE_ENV: process.env.NODE_ENV ? process.env.NODE_ENV : 'production' }),\r\n ...process.env,\r\n ...mergedEnv\r\n }\r\n }\r\n\r\n const parsedEnv = safeParse(allowedEnvKeys, mergedEnv)\r\n\r\n if (!parsedEnv.success)\r\n throw new Error(`Environment validation failed: ${formatError(parsedEnv.error)}`)\r\n\r\n globalThis.liteEnv = parsedEnv.data\r\n\r\n parsedEnv.data = {\r\n ...parsedEnv.data,\r\n NODE_ENV\r\n }\r\n\r\n console.log('Loaded env file', `${defaultEnvPath}, ${nodeEnvPath}`)\r\n\r\n return parsedEnv.data as LoadedEnv<TSchema>\r\n}\r\n","import { existsSync, readFileSync } from \"fs\"\nimport { AllowedEnvKeys, EnvKind, EnvKindMap, LoadedEnv } from \"./types.js\"\n\r\nexport function toString(value: string): string {\r\n return String(value)\r\n}\r\n\r\nexport function toNumber(value: string): number {\n const parsed = Number(value)\n if (Number.isNaN(parsed))\n throw new Error('Value is not supported for number')\n\n return parsed\n}\n\r\nexport function toArray(value: string): string[] {\r\n if (!value.includes(','))\r\n throw new Error('Valur is not supported for array')\r\n\r\n return value.split(',')\r\n}\r\n\r\nexport function toBoolean(value: string): boolean {\n if (value === 'true' || value === '1')\n return true\n\n if (value === 'false' || value === '0')\n return false\n\n throw new Error('Value is not supported for boolean')\n}\n\r\nexport function toObject<T>(value: string): T {\r\n try {\r\n return JSON.parse(value)\r\n } catch (error) {\r\n throw new Error('Value is not supported for object')\r\n }\r\n}\r\n\r\nexport function toBuffer(value: string, encoding?: BufferEncoding): Buffer {\r\n try {\r\n return Buffer.from(value, encoding || 'base64')\r\n } catch (error) {\r\n throw new Error('Value is not supported for buffer')\r\n }\r\n}\r\n\r\nexport function toDate(value: string): Date {\n const parsed = new Date(value)\n if (Number.isNaN(parsed.getTime()))\n throw new Error('Value is not supported for date')\n\n return parsed\n}\n\nfunction parseEnvValue<TKind extends EnvKind>(kind: TKind, value: string): EnvKindMap[TKind] {\n switch (kind) {\n case \"string\":\n return toString(value) as EnvKindMap[TKind]\n case \"number\":\n return toNumber(value) as EnvKindMap[TKind]\n case \"boolean\":\n return toBoolean(value) as EnvKindMap[TKind]\n case \"array\":\n return toArray(value) as EnvKindMap[TKind]\n case \"object\":\n return toObject(value) as EnvKindMap[TKind]\n case \"buffer\":\n return toBuffer(value) as EnvKindMap[TKind]\n case \"date\":\n return toDate(value) as EnvKindMap[TKind]\n default: {\n const exhaustiveCheck: never = kind\n throw new Error(`Unsupported env kind: ${exhaustiveCheck}`)\n }\n }\n}\n\nexport function safeParse<TSchema extends AllowedEnvKeys>(allowedEnvKeys: TSchema, values: Record<string, string>) {\n const data: Partial<LoadedEnv<TSchema>> = {}\n const error: string[] = []\n\n for (const key of Object.keys(allowedEnvKeys) as Array<keyof TSchema>) {\n const value = values[key as string]\n if (value === undefined) continue\n\n try {\n data[key] = parseEnvValue(allowedEnvKeys[key], value)\n } catch (e) {\n if (e instanceof Error)\n error.push(`${String(key)}: ${e.message}`)\n else\n error.push(`${String(key)}: Unknown error occurred`)\n }\n }\n\n return {\n success: error.length === 0,\n data: data as LoadedEnv<TSchema>,\n error\n }\n}\n\r\nexport function formatError(message: string[]): string {\r\n return message.join('\\n')\r\n}\r\n\r\nexport function parseRawEnv(rawEnv: string): Record<string, string> {\r\n const result: Record<string, string> = {}\r\n const lines = rawEnv.split(/\\r?\\n/)\r\n\r\n for (const line of lines) {\r\n const normalized = line.trim()\r\n if (!normalized || normalized.startsWith('#')) continue\r\n\r\n const separatorIndex = normalized.indexOf('=')\r\n if (separatorIndex <= 0) continue\r\n\r\n const key = normalized.slice(0, separatorIndex).trim()\r\n const value = normalized.slice(separatorIndex + 1).trim()\r\n if (!key) continue\r\n\r\n result[key] = value\r\n }\r\n\r\n return result\r\n}\r\n\r\nexport function readEnvFile(filePath: string): false | Record<string, string> {\r\n if (!existsSync(filePath)) return false\r\n return parseRawEnv(readFileSync(filePath, 'utf-8'))\r\n}\r\n\r\nexport function getUnknownEnvKeys(source: Record<string, string>, allowedEnvKeys: Set<string>): string[] {\r\n return Object.keys(source).filter((key) => !allowedEnvKeys.has(key))\r\n}\r\n"],"mappings":"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","names":["import_fs","path"]}
package/dist/index.js CHANGED
@@ -119,12 +119,14 @@ function loadEnv(allowedEnvKeys = {}, bypassUnknownEnvKeys = true, NODE_ENV) {
119
119
  if (globalThis.liteEnv)
120
120
  return globalThis.liteEnv;
121
121
  if (NODE_ENV) {
122
+ NODE_ENV = NODE_ENV.trim();
122
123
  process.env.NODE_ENV = NODE_ENV;
123
124
  } else {
124
125
  if (!process.env.NODE_ENV) {
125
126
  process.env.NODE_ENV = "production";
126
127
  NODE_ENV = "production";
127
128
  } else {
129
+ process.env.NODE_ENV = process.env.NODE_ENV.trim();
128
130
  NODE_ENV = process.env.NODE_ENV;
129
131
  }
130
132
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/helper.ts"],"sourcesContent":["import path from 'path'\r\nimport { existsSync } from 'fs'\r\nimport { formatError, getUnknownEnvKeys, readEnvFile, safeParse } from './helper.js'\r\nimport { AllowedEnvKeys, LoadedEnv } from \"./types.js\";\r\n\r\nexport type { AllowedEnvKeys, EnvKind, EnvKindMap, LoadedEnv } from \"./types.js\"\r\n\r\ndeclare global {\r\n var liteEnv: unknown\r\n}\r\n\r\nexport function loadEnv<TSchema extends AllowedEnvKeys = {}>(\r\n allowedEnvKeys: TSchema = {} as TSchema,\r\n bypassUnknownEnvKeys: boolean = true,\r\n NODE_ENV?: string\r\n): LoadedEnv<TSchema> {\r\n if (globalThis.liteEnv)\r\n return globalThis.liteEnv as LoadedEnv<TSchema>\r\n\r\n if (NODE_ENV) {\r\n process.env.NODE_ENV = NODE_ENV\r\n } else {\r\n if (!process.env.NODE_ENV) {\r\n process.env.NODE_ENV = 'production'\r\n\r\n NODE_ENV = 'production'\r\n } else {\r\n NODE_ENV = process.env.NODE_ENV\r\n }\r\n }\r\n\r\n const defaultEnvPath = path.join(process.cwd(), '.env')\r\n const nodeEnvPath = path.join(process.cwd(), `.env.${NODE_ENV}`)\r\n\r\n if (!existsSync(defaultEnvPath))\r\n throw new Error('Default Environment file not found')\r\n\r\n if (!existsSync(nodeEnvPath))\r\n throw new Error(`Environment file not found: .env.${NODE_ENV}`)\r\n\r\n const defaultEnvSource = readEnvFile(defaultEnvPath)\r\n const nodeEnvSource = readEnvFile(nodeEnvPath)\r\n\r\n const mergedEnv: Record<string, string> = {}\r\n\r\n if (defaultEnvSource)\r\n Object.assign(mergedEnv, defaultEnvSource)\r\n if (nodeEnvSource)\r\n Object.assign(mergedEnv, nodeEnvSource)\r\n\r\n if (!bypassUnknownEnvKeys) {\r\n const unknownKeys = [...new Set([...getUnknownEnvKeys(mergedEnv, new Set(Object.keys(allowedEnvKeys)))])]\r\n\r\n if (unknownKeys.length > 0)\r\n throw new Error(`Unknown environment variables in env files: ${unknownKeys.join(', ')}`)\r\n } else {\r\n process.env = {\r\n ...({ NODE_ENV: process.env.NODE_ENV ? process.env.NODE_ENV : 'production' }),\r\n ...process.env,\r\n ...mergedEnv\r\n }\r\n }\r\n\r\n const parsedEnv = safeParse(allowedEnvKeys, mergedEnv)\r\n\r\n if (!parsedEnv.success)\r\n throw new Error(`Environment validation failed: ${formatError(parsedEnv.error)}`)\r\n\r\n globalThis.liteEnv = parsedEnv.data\r\n\r\n parsedEnv.data = {\r\n ...parsedEnv.data,\r\n NODE_ENV\r\n }\r\n\r\n console.log('Loaded env file', `${defaultEnvPath}, ${nodeEnvPath}`)\r\n\r\n return parsedEnv.data as LoadedEnv<TSchema>\r\n}\r\n","import { existsSync, readFileSync } from \"fs\"\nimport { AllowedEnvKeys, EnvKind, EnvKindMap, LoadedEnv } from \"./types.js\"\n\r\nexport function toString(value: string): string {\r\n return String(value)\r\n}\r\n\r\nexport function toNumber(value: string): number {\n const parsed = Number(value)\n if (Number.isNaN(parsed))\n throw new Error('Value is not supported for number')\n\n return parsed\n}\n\r\nexport function toArray(value: string): string[] {\r\n if (!value.includes(','))\r\n throw new Error('Valur is not supported for array')\r\n\r\n return value.split(',')\r\n}\r\n\r\nexport function toBoolean(value: string): boolean {\n if (value === 'true' || value === '1')\n return true\n\n if (value === 'false' || value === '0')\n return false\n\n throw new Error('Value is not supported for boolean')\n}\n\r\nexport function toObject<T>(value: string): T {\r\n try {\r\n return JSON.parse(value)\r\n } catch (error) {\r\n throw new Error('Value is not supported for object')\r\n }\r\n}\r\n\r\nexport function toBuffer(value: string, encoding?: BufferEncoding): Buffer {\r\n try {\r\n return Buffer.from(value, encoding || 'base64')\r\n } catch (error) {\r\n throw new Error('Value is not supported for buffer')\r\n }\r\n}\r\n\r\nexport function toDate(value: string): Date {\n const parsed = new Date(value)\n if (Number.isNaN(parsed.getTime()))\n throw new Error('Value is not supported for date')\n\n return parsed\n}\n\nfunction parseEnvValue<TKind extends EnvKind>(kind: TKind, value: string): EnvKindMap[TKind] {\n switch (kind) {\n case \"string\":\n return toString(value) as EnvKindMap[TKind]\n case \"number\":\n return toNumber(value) as EnvKindMap[TKind]\n case \"boolean\":\n return toBoolean(value) as EnvKindMap[TKind]\n case \"array\":\n return toArray(value) as EnvKindMap[TKind]\n case \"object\":\n return toObject(value) as EnvKindMap[TKind]\n case \"buffer\":\n return toBuffer(value) as EnvKindMap[TKind]\n case \"date\":\n return toDate(value) as EnvKindMap[TKind]\n default: {\n const exhaustiveCheck: never = kind\n throw new Error(`Unsupported env kind: ${exhaustiveCheck}`)\n }\n }\n}\n\nexport function safeParse<TSchema extends AllowedEnvKeys>(allowedEnvKeys: TSchema, values: Record<string, string>) {\n const data: Partial<LoadedEnv<TSchema>> = {}\n const error: string[] = []\n\n for (const key of Object.keys(allowedEnvKeys) as Array<keyof TSchema>) {\n const value = values[key as string]\n if (value === undefined) continue\n\n try {\n data[key] = parseEnvValue(allowedEnvKeys[key], value)\n } catch (e) {\n if (e instanceof Error)\n error.push(`${String(key)}: ${e.message}`)\n else\n error.push(`${String(key)}: Unknown error occurred`)\n }\n }\n\n return {\n success: error.length === 0,\n data: data as LoadedEnv<TSchema>,\n error\n }\n}\n\r\nexport function formatError(message: string[]): string {\r\n return message.join('\\n')\r\n}\r\n\r\nexport function parseRawEnv(rawEnv: string): Record<string, string> {\r\n const result: Record<string, string> = {}\r\n const lines = rawEnv.split(/\\r?\\n/)\r\n\r\n for (const line of lines) {\r\n const normalized = line.trim()\r\n if (!normalized || normalized.startsWith('#')) continue\r\n\r\n const separatorIndex = normalized.indexOf('=')\r\n if (separatorIndex <= 0) continue\r\n\r\n const key = normalized.slice(0, separatorIndex).trim()\r\n const value = normalized.slice(separatorIndex + 1).trim()\r\n if (!key) continue\r\n\r\n result[key] = value\r\n }\r\n\r\n return result\r\n}\r\n\r\nexport function readEnvFile(filePath: string): false | Record<string, string> {\r\n if (!existsSync(filePath)) return false\r\n return parseRawEnv(readFileSync(filePath, 'utf-8'))\r\n}\r\n\r\nexport function getUnknownEnvKeys(source: Record<string, string>, allowedEnvKeys: Set<string>): string[] {\r\n return Object.keys(source).filter((key) => !allowedEnvKeys.has(key))\r\n}\r\n"],"mappings":"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","names":["existsSync","existsSync"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/helper.ts"],"sourcesContent":["import path from 'path'\r\nimport { existsSync } from 'fs'\r\nimport { formatError, getUnknownEnvKeys, readEnvFile, safeParse } from './helper.js'\r\nimport { AllowedEnvKeys, LoadedEnv } from \"./types.js\";\r\n\r\nexport type { AllowedEnvKeys, EnvKind, EnvKindMap, LoadedEnv } from \"./types.js\"\r\n\r\ndeclare global {\r\n var liteEnv: unknown\r\n}\r\n\r\nexport function loadEnv<TSchema extends AllowedEnvKeys = {}>(\r\n allowedEnvKeys: TSchema = {} as TSchema,\r\n bypassUnknownEnvKeys: boolean = true,\r\n NODE_ENV?: string\r\n): LoadedEnv<TSchema> {\r\n if (globalThis.liteEnv)\r\n return globalThis.liteEnv as LoadedEnv<TSchema>\r\n\r\n if (NODE_ENV) {\r\n NODE_ENV = NODE_ENV.trim()\r\n\r\n process.env.NODE_ENV = NODE_ENV\r\n } else {\r\n if (!process.env.NODE_ENV) {\r\n process.env.NODE_ENV = 'production'\r\n\r\n NODE_ENV = 'production'\r\n } else {\r\n process.env.NODE_ENV = process.env.NODE_ENV.trim()\r\n NODE_ENV = process.env.NODE_ENV\r\n }\r\n }\r\n\r\n const defaultEnvPath = path.join(process.cwd(), '.env')\r\n const nodeEnvPath = path.join(process.cwd(), `.env.${NODE_ENV}`)\r\n\r\n if (!existsSync(defaultEnvPath))\r\n throw new Error('Default Environment file not found')\r\n\r\n if (!existsSync(nodeEnvPath))\r\n throw new Error(`Environment file not found: .env.${NODE_ENV}`)\r\n\r\n const defaultEnvSource = readEnvFile(defaultEnvPath)\r\n const nodeEnvSource = readEnvFile(nodeEnvPath)\r\n\r\n const mergedEnv: Record<string, string> = {}\r\n\r\n if (defaultEnvSource)\r\n Object.assign(mergedEnv, defaultEnvSource)\r\n if (nodeEnvSource)\r\n Object.assign(mergedEnv, nodeEnvSource)\r\n\r\n if (!bypassUnknownEnvKeys) {\r\n const unknownKeys = [...new Set([...getUnknownEnvKeys(mergedEnv, new Set(Object.keys(allowedEnvKeys)))])]\r\n\r\n if (unknownKeys.length > 0)\r\n throw new Error(`Unknown environment variables in env files: ${unknownKeys.join(', ')}`)\r\n } else {\r\n process.env = {\r\n ...({ NODE_ENV: process.env.NODE_ENV ? process.env.NODE_ENV : 'production' }),\r\n ...process.env,\r\n ...mergedEnv\r\n }\r\n }\r\n\r\n const parsedEnv = safeParse(allowedEnvKeys, mergedEnv)\r\n\r\n if (!parsedEnv.success)\r\n throw new Error(`Environment validation failed: ${formatError(parsedEnv.error)}`)\r\n\r\n globalThis.liteEnv = parsedEnv.data\r\n\r\n parsedEnv.data = {\r\n ...parsedEnv.data,\r\n NODE_ENV\r\n }\r\n\r\n console.log('Loaded env file', `${defaultEnvPath}, ${nodeEnvPath}`)\r\n\r\n return parsedEnv.data as LoadedEnv<TSchema>\r\n}\r\n","import { existsSync, readFileSync } from \"fs\"\nimport { AllowedEnvKeys, EnvKind, EnvKindMap, LoadedEnv } from \"./types.js\"\n\r\nexport function toString(value: string): string {\r\n return String(value)\r\n}\r\n\r\nexport function toNumber(value: string): number {\n const parsed = Number(value)\n if (Number.isNaN(parsed))\n throw new Error('Value is not supported for number')\n\n return parsed\n}\n\r\nexport function toArray(value: string): string[] {\r\n if (!value.includes(','))\r\n throw new Error('Valur is not supported for array')\r\n\r\n return value.split(',')\r\n}\r\n\r\nexport function toBoolean(value: string): boolean {\n if (value === 'true' || value === '1')\n return true\n\n if (value === 'false' || value === '0')\n return false\n\n throw new Error('Value is not supported for boolean')\n}\n\r\nexport function toObject<T>(value: string): T {\r\n try {\r\n return JSON.parse(value)\r\n } catch (error) {\r\n throw new Error('Value is not supported for object')\r\n }\r\n}\r\n\r\nexport function toBuffer(value: string, encoding?: BufferEncoding): Buffer {\r\n try {\r\n return Buffer.from(value, encoding || 'base64')\r\n } catch (error) {\r\n throw new Error('Value is not supported for buffer')\r\n }\r\n}\r\n\r\nexport function toDate(value: string): Date {\n const parsed = new Date(value)\n if (Number.isNaN(parsed.getTime()))\n throw new Error('Value is not supported for date')\n\n return parsed\n}\n\nfunction parseEnvValue<TKind extends EnvKind>(kind: TKind, value: string): EnvKindMap[TKind] {\n switch (kind) {\n case \"string\":\n return toString(value) as EnvKindMap[TKind]\n case \"number\":\n return toNumber(value) as EnvKindMap[TKind]\n case \"boolean\":\n return toBoolean(value) as EnvKindMap[TKind]\n case \"array\":\n return toArray(value) as EnvKindMap[TKind]\n case \"object\":\n return toObject(value) as EnvKindMap[TKind]\n case \"buffer\":\n return toBuffer(value) as EnvKindMap[TKind]\n case \"date\":\n return toDate(value) as EnvKindMap[TKind]\n default: {\n const exhaustiveCheck: never = kind\n throw new Error(`Unsupported env kind: ${exhaustiveCheck}`)\n }\n }\n}\n\nexport function safeParse<TSchema extends AllowedEnvKeys>(allowedEnvKeys: TSchema, values: Record<string, string>) {\n const data: Partial<LoadedEnv<TSchema>> = {}\n const error: string[] = []\n\n for (const key of Object.keys(allowedEnvKeys) as Array<keyof TSchema>) {\n const value = values[key as string]\n if (value === undefined) continue\n\n try {\n data[key] = parseEnvValue(allowedEnvKeys[key], value)\n } catch (e) {\n if (e instanceof Error)\n error.push(`${String(key)}: ${e.message}`)\n else\n error.push(`${String(key)}: Unknown error occurred`)\n }\n }\n\n return {\n success: error.length === 0,\n data: data as LoadedEnv<TSchema>,\n error\n }\n}\n\r\nexport function formatError(message: string[]): string {\r\n return message.join('\\n')\r\n}\r\n\r\nexport function parseRawEnv(rawEnv: string): Record<string, string> {\r\n const result: Record<string, string> = {}\r\n const lines = rawEnv.split(/\\r?\\n/)\r\n\r\n for (const line of lines) {\r\n const normalized = line.trim()\r\n if (!normalized || normalized.startsWith('#')) continue\r\n\r\n const separatorIndex = normalized.indexOf('=')\r\n if (separatorIndex <= 0) continue\r\n\r\n const key = normalized.slice(0, separatorIndex).trim()\r\n const value = normalized.slice(separatorIndex + 1).trim()\r\n if (!key) continue\r\n\r\n result[key] = value\r\n }\r\n\r\n return result\r\n}\r\n\r\nexport function readEnvFile(filePath: string): false | Record<string, string> {\r\n if (!existsSync(filePath)) return false\r\n return parseRawEnv(readFileSync(filePath, 'utf-8'))\r\n}\r\n\r\nexport function getUnknownEnvKeys(source: Record<string, string>, allowedEnvKeys: Set<string>): string[] {\r\n return Object.keys(source).filter((key) => !allowedEnvKeys.has(key))\r\n}\r\n"],"mappings":"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","names":["existsSync","existsSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bintvn/lite-env",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "TypeScript based environment variable loader.",
5
5
  "keywords": [
6
6
  "util",