-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 777c881
Showing
8 changed files
with
596 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.env | ||
.vscode | ||
test.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2024 cross-org <https://github.com/cross-org> | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
## **Flexible Environment Variable Management for Deno, Bun, and Node.js** | ||
|
||
This library provides a consistent and simple interface for managing environment variables across multiple runtimes, | ||
making it ideal for cross-platform development. | ||
|
||
## **Features** | ||
|
||
- **Cross-runtime support:** Works seamlessly within Deno, Bun, and Node.js environments. | ||
- **Get and Set environment variables:** Retrieve and Modify environment variables in a consistent interface across | ||
multiple runtimes. | ||
- **Validation:** Ensures environment variables are valid before usage. | ||
- **Error handling:** Provides clear error messages for unsupported runtimes or validation failures. | ||
- **Optional environmental file loading:** Supports loading variables from custom .env files _(experimental)_ | ||
|
||
## **Installation** | ||
|
||
```bash | ||
#For Deno | ||
deno add @cross/env | ||
|
||
#For Bun | ||
bunx jsr add @cross/env | ||
|
||
#For Node.js | ||
npx jsr add @cross/env | ||
``` | ||
|
||
## Getting Started | ||
|
||
**Usage Examples** | ||
|
||
import relevant functions. | ||
|
||
```javascript | ||
import { getEnv, setEnv, validateEnv } from "@cross/env"; | ||
``` | ||
|
||
Simple get example. | ||
|
||
```javascript | ||
const apiKey = getEnv("API_KEY"); | ||
|
||
// or | ||
console.log(`Home directory: ${getEnv("HOME")}`); | ||
``` | ||
|
||
Simple set example. | ||
|
||
```javascript | ||
setEnv("ENVIRONMENT", "development"); | ||
setEnv("THE_COLOUR", "red"); | ||
``` | ||
|
||
Checking if a variable exists. | ||
|
||
```javascript | ||
if (hasEnv("DB_USER")) { | ||
// Handle database connection logic | ||
} | ||
``` | ||
|
||
Getting all environment variables. | ||
|
||
```javascript | ||
// getting all variables | ||
const allVariables = getAllEnv(); | ||
// getting all variables prefixed with API_ | ||
const apiVariables = getAllEnv("API_"); | ||
// Output: | ||
// { API_KEY: 'abc123', API_VERSION: 'v2' } | ||
``` | ||
|
||
Validation through custom functions. | ||
|
||
```javascript | ||
// Validate a colour and execute conditional code. | ||
const colourTest: ValidatorFunction = (value) => value === "red" || value === "green"; | ||
if (validateEnv("THE_COLOUR", colourTest)) { | ||
console.log("Yep, its red or green."); | ||
} | ||
``` | ||
|
||
Validation through custom functions and getting the variable content. | ||
|
||
```javascript | ||
// or validating and getting a port number. | ||
const isValidPort = (value: string): boolean => /^\d+$/.test(value); | ||
const port = validateAndGetEnv("PORT", isValidPort); | ||
|
||
// or checking it we are reading a positive number. | ||
function isPositiveNumber(value: string): boolean { | ||
return !isNaN(Number(value)) && Number(value) > 0; | ||
} | ||
const timeout = validateAndGetEnv("TIMEOUT", isPositiveNumber); | ||
``` | ||
|
||
## **Configuration (optional):** | ||
|
||
For more advanced use cases you can configure the behaviour of the library. The library defaults to showing console | ||
warnings but not throwing errors. | ||
|
||
```javascript | ||
await setupEnv({ | ||
throwErrors: true, // Throw errors in unsupported runtimes | ||
logWarnings: false, // Disable warnings | ||
loadDotEnv: true, // Load from a .env file (experimental) | ||
dotEnvFile: ".env.local", // Specify an alternate .env file (experimental) | ||
}); | ||
``` | ||
|
||
**Experimental .env File Support** | ||
|
||
Use the `loadDotEnv` parameter and optionally `dotEnvFile` in `setupEnv()` to automatically load environment variables | ||
from a .env file. Currently, this feature might have runtime-specific limitations. | ||
|
||
## Issues | ||
|
||
Issues or questions concerning the library can be raised at the | ||
[github repository](https://github.com/cross-org/env/issues) page. | ||
|
||
## License | ||
|
||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"tasks": { | ||
"publish": "deno publish --config jsr.json" | ||
}, | ||
"fmt": { | ||
"lineWidth": 120, | ||
"indentWidth": 4 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"name": "@cross/env", | ||
"version": "0.1.0", | ||
"exports": "./mod.ts" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { FileReadError, Runtimes, UnsupportedEnvironmentError } from "./helpers.ts"; | ||
|
||
//Simulates/shims the Deno runtime for development purposes. | ||
declare const Deno: { | ||
readTextFileSync(filePath: string): string; | ||
env: { | ||
get(key: string): string | undefined; | ||
set(key: string, value: string): void; | ||
toObject(): Record<string, string | undefined>; | ||
}; | ||
}; | ||
|
||
//Simulates/shims the Bun runtime for development purposes. | ||
declare const Bun: { | ||
file(filePath: string): { text(): string }; | ||
env: Record<string, string>; | ||
}; | ||
|
||
//Simulates/shims Node.js function to load modules for development purposes. | ||
// deno-lint-ignore no-explicit-any | ||
declare const require: (module: string) => any; | ||
|
||
//Simulates/shims Node.js process object for development purposes. | ||
declare const process: { env: Record<string, string> }; | ||
|
||
//Simulates/shims the Node.js fs namespace for development purposes. | ||
// deno-lint-ignore no-explicit-any | ||
declare const fs: any; | ||
|
||
/** | ||
* Loads environment variables from a .env file, handling file existence, | ||
* runtime differences, and errors. | ||
* | ||
* @param {Runtimes} currentRuntime - The current runtime environment. | ||
* @param {string} [filePath=".env"] - The path to the file to load, defaults to .env | ||
* @param {boolean} throwErrors - Controls whether errors are thrown | ||
* @param {boolean} logWarnings - Controls whether warnings are logged. | ||
* @returns {Record<string, string>} A object of parsed environment variables. | ||
* @throws {UnsupportedEnvironmentError} If the runtime is unsupported and the 'throwErrors' flag is set. | ||
* @throws {FileReadError} If there's an error reading the .env file and the 'throwErrors' flag is set. | ||
*/ | ||
export async function loadEnvFile( | ||
currentRuntime: Runtimes, | ||
filePath: string = ".env", | ||
throwErrors: boolean, | ||
logWarnings: boolean, | ||
): Promise<Record<string, string>> { | ||
let fileContent = ""; | ||
|
||
try { | ||
switch (currentRuntime) { | ||
case Runtimes.Deno: | ||
fileContent = Deno.readTextFileSync(filePath); | ||
break; | ||
case Runtimes.Bun: | ||
fileContent = await Bun.file(filePath).text(); | ||
break; | ||
case Runtimes.Node: { | ||
if (typeof fs === "undefined") { | ||
const fs = require("fs"); | ||
fileContent = fs.readFileSync(filePath, "utf-8"); | ||
} else { | ||
throw new Error("Node.js 'fs' module is not available in this environment."); | ||
} | ||
break; | ||
} | ||
default: | ||
{ | ||
if (throwErrors) { | ||
throw new UnsupportedEnvironmentError(); | ||
} | ||
if (logWarnings) { | ||
console.warn("Unsupported runtime"); | ||
} | ||
} | ||
break; | ||
} | ||
} catch (err) { | ||
if (throwErrors) { | ||
throw new FileReadError(err.message); | ||
} | ||
if (logWarnings) { | ||
console.warn(err.message); | ||
} | ||
} | ||
|
||
return parseEnvFile(fileContent); | ||
} | ||
|
||
/** | ||
* Parses a string representing the content of a .env file and creates a | ||
* dictionary of environment variables. | ||
* | ||
* @param {string} content - The string content of the .env file. | ||
* @returns {Record<string, string>} A object of parsed environment variables. | ||
*/ | ||
function parseEnvFile(content: string): Record<string, string> { | ||
const envVars: Record<string, string> = {}; | ||
|
||
if (content.length > 0) { | ||
content.split("\n").forEach((line) => { | ||
const trimmedLine = line.trim(); | ||
|
||
// Ignore comments and empty lines | ||
if (!trimmedLine || trimmedLine.startsWith("#")) { | ||
return; | ||
} | ||
|
||
const [key, value] = trimmedLine.split("="); | ||
envVars[key] = value; | ||
}); | ||
} | ||
|
||
return envVars; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/** | ||
* Enum of supported runtimes. | ||
*/ | ||
export enum Runtimes { | ||
Deno = "deno", | ||
Bun = "bun", | ||
Node = "node", | ||
Unsupported = "unsupported", | ||
} | ||
|
||
/** | ||
* Type alias for a validator function used in environment variable checks. | ||
*/ | ||
export type ValidatorFunction = (value: string) => boolean; | ||
|
||
/** Env setup options. */ | ||
export interface EnvOptions { | ||
/** (default: false) - If true, throws an errors in unsupported runtimes. */ | ||
throwErrors?: boolean; | ||
/** (default: true) - If true, logs a warning to the console when environment variables | ||
* are accessed in unsupported runtimes. */ | ||
logWarnings?: boolean; | ||
/** (default: false) - If true, read and load environment variables a file. | ||
* (default file: ".env") **@experimental** Support for loading .env files may have | ||
* limitations in certain runtimes. */ | ||
loadDotEnv?: boolean; | ||
/** (default: ".env") - filename of the file containing environment variables to load. */ | ||
dotEnvFile?: string; | ||
} | ||
|
||
/** | ||
* Error thrown when attempting to set or retrieve environment variables in | ||
* unsupported runtimes. | ||
*/ | ||
export class UnsupportedEnvironmentError extends Error { | ||
constructor() { | ||
super("Unsupported runtime environment."); | ||
} | ||
} | ||
|
||
/** | ||
* Error thrown when attempting to validate an environment variable. | ||
*/ | ||
export class ValidationError extends Error { | ||
constructor(message: string) { | ||
super(message); | ||
} | ||
} | ||
|
||
/** | ||
* Error thrown when attempting to read file with environment variables. | ||
*/ | ||
export class FileReadError extends Error { | ||
constructor(message: string) { | ||
super(message); | ||
} | ||
} |
Oops, something went wrong.