Skip to content
This repository has been archived by the owner on Nov 7, 2024. It is now read-only.

Commit

Permalink
Implement CrossEnv
Browse files Browse the repository at this point in the history
  • Loading branch information
hugoalh committed Mar 24, 2024
1 parent 1131abf commit 5b3d704
Show file tree
Hide file tree
Showing 11 changed files with 162 additions and 73 deletions.
40 changes: 32 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,43 @@ A TypeScript module for cross runtime environment variables interface.
## 🧩 API

- ```ts
function deleteEnv(key: string): void;
const env: CrossEnv;
```
- ```ts
function getAllEnv(): { [key: string]: string; };
function isEnvironmentCI(): boolean;
```
- ```ts
function getEnv(key: string): string | undefined;
function isEnvironmentDocker(): Promise<boolean>;
```
- ```ts
function hasEnv(key: string): boolean;
function isEnvironmentHeroku(): boolean;
```
- ```ts
function setEnv(key: string, value: string): void;
function isEnvironmentHyper(): boolean;
```
- ```ts
function isEnvironmentPodman(): Promise<boolean>;
```
- ```ts
function isEnvironmentRoot(): boolean;
```
- ```ts
function isEnvironmentSSH(): boolean;
```
- ```ts
function isEnvironmentTravis(): boolean;
```
- ```ts
function isEnvironmentWSL(): Promise<boolean>;
```
- ```ts
interface CrossEnv {
delete(key: string): void;
get(key: string): string | undefined;
getAll(): { [key: string]: string; };
has(key: string): boolean;
set(key: string, value: string): void;
}
```

> **ℹ️ Note**
Expand All @@ -124,13 +148,13 @@ A TypeScript module for cross runtime environment variables interface.
## ✍️ Example

- ```ts
deleteEnv("SOME_VAR");
env.delete("SOME_VAR");
```
- ```ts
getEnv("HOME");
env.get("HOME");
//=> "/home/alice"
```
- ```ts
getEnv("SOME_VAR");
env.get("SOME_VAR");
//=> undefined
```
8 changes: 4 additions & 4 deletions _delimitation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { delimiter as pathDelimiter } from "node:path";
import { getEnv, setEnv } from "./env.ts";
import env from "./env.ts";
/**
* Join the environment variable value with inter handle of the operate system specific delimiter.
* @access private
Expand Down Expand Up @@ -33,11 +33,11 @@ function splitEnvDelimitation(item: string): Set<string> {
* @returns {void}
*/
export function addEnvDelimitation(key: string, ...values: string[]): void {
const targetValues: Set<string> = splitEnvDelimitation(getEnv(key) ?? "");
const targetValues: Set<string> = splitEnvDelimitation(env.get(key) ?? "");
for (const value of values) {
targetValues.add(value);
}
setEnv(key, joinEnvDelimitation(targetValues));
env.set(key, joinEnvDelimitation(targetValues));
}
/**
* Get the value of an environment variable with inter handle of the operate system specific delimiter.
Expand All @@ -49,5 +49,5 @@ export function addEnvDelimitation(key: string, ...values: string[]): void {
* @returns {string[]} Values of the environment variable.
*/
export function getEnvDelimitation(key: string): string[] {
return Array.from<string>(splitEnvDelimitation(getEnv(key) ?? "").values());
return Array.from<string>(splitEnvDelimitation(env.get(key) ?? "").values());
}
6 changes: 3 additions & 3 deletions env.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { getAllEnv } from "./env.ts";
Deno.test("All", {
import env from "./env.ts";
Deno.test("Get All", {
permissions: {
env: true
}
}, () => {
console.log(getAllEnv());
console.log(env.getAll());
});
149 changes: 108 additions & 41 deletions env.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,102 @@
import process from "node:process";
/**
* Cross runtime environment variables interface.
*
* > **🛡️ Require Permission**
* >
* > - Environment Variable (`allow-env`)
*/
export interface CrossEnv {
/**
* Delete an environment variable.
*
* > **🛡️ Require Permission**
* >
* > - Environment Variable (`allow-env`)
* @param {string} key Key of the environment variable.
* @returns {void}
*/
delete(key: string): void;
/**
* Get the value of an environment variable.
*
* > **🛡️ Require Permission**
* >
* > - Environment Variable (`allow-env`)
* @param {string} key Key of the environment variable.
* @returns {string | undefined} Value of the environment variable.
*/
get(key: string): string | undefined;
/**
* Get a snapshot of the environment variables at invocation as a simple object of keys and values.
*
* > **🛡️ Require Permission**
* >
* > - Environment Variable (`allow-env`)
* @returns {{ [key: string]: string; }} A snapshot of the environment variables.
*/
getAll(): { [key: string]: string; };
/**
* Check whether an environment variable is present.
*
* > **🛡️ Require Permission**
* >
* > - Environment Variable (`allow-env`)
* @param {string} key Key of the environment variable.
* @returns {boolean} Determine result.
*/
has(key: string): boolean;
/**
* Set an environment variable.
*
* > **🛡️ Require Permission**
* >
* > - Environment Variable (`allow-env`)
* @param {string} key Key of the environment variable.
* @param {string} value Value of the environment variable.
* @returns {void}
*/
set(key: string, value: string): void;
}
class CrossEnvDeno implements CrossEnv {
delete = Deno.env.delete;
get = Deno.env.get;
getAll = Deno.env.toObject;
has = Deno.env.has;
set = Deno.env.set;
}
class CrossEnvProcess implements CrossEnv {
delete(key: string): void {
process.env[key] = undefined;
}
get(key: string): string | undefined {
return process.env[key];
}
getAll(): { [key: string]: string; } {
const result: { [key: string]: string; } = {};
for (const [key, value] of Object.entries(process.env)) {
if (typeof value !== "undefined") {
result[key] = value;
}
}
return result;
}
has(key: string): boolean {
return (typeof process.env[key] !== "undefined");
}
set(key: string, value: string): void {
process.env[key] = value;
}
}
/**
* Cross runtime environment variables interface.
*
* > **🛡️ Require Permission**
* >
* > - Environment Variable (`allow-env`)
*/
export const env: CrossEnv = (typeof Deno === "undefined") ? new CrossEnvProcess() : new CrossEnvDeno();
export default env;
/**
* Delete an environment variable.
*
Expand All @@ -7,39 +105,23 @@ import process from "node:process";
* > - Environment Variable (`allow-env`)
* @param {string} key Key of the environment variable.
* @returns {void}
* @deprecated Replaced by method {@linkcode env.delete}.
*/
export function deleteEnv(key: string): void {
if (typeof Deno !== "undefined") {
return Deno.env.delete(key);
}
process.env[key] = undefined;
return env.delete(key);
}
export {
deleteEnv as deleteEnvironmentVariable
};
/**
* Get a snapshot of the environment variables at invocation as a simple object of keys and values.
*
* > **🛡️ Require Permission**
* >
* > - Environment Variable (`allow-env`)
* @returns {{ [key: string]: string; }} A snapshot of the environment variables.
* @deprecated Replaced by method {@linkcode env.getAll}.
*/
export function getAllEnv(): { [key: string]: string; } {
if (typeof Deno !== "undefined") {
return Deno.env.toObject();
}
const result: { [key: string]: string; } = {};
for (const [key, value] of Object.entries(process.env)) {
if (typeof value !== "undefined") {
result[key] = value;
}
}
return result;
return env.getAll();
}
export {
getAllEnv as getAllEnvironmentVariable
};
/**
* Get the value of an environment variable.
*
Expand All @@ -48,34 +130,24 @@ export {
* > - Environment Variable (`allow-env`)
* @param {string} key Key of the environment variable.
* @returns {string | undefined} Value of the environment variable.
* @deprecated Replaced by method {@linkcode env.get}.
*/
export function getEnv(key: string): string | undefined {
if (typeof Deno !== "undefined") {
return Deno.env.get(key);
}
return process.env[key];
return env.get(key);
}
export {
getEnv as getEnvironmentVariable
};
/**
* Check whether an environment variable is present.
*
* > **🛡️ Require Permission**
* >
* > - Environment Variable (`allow-env`)
* @param {string} key Key of the environment variable.
* @deprecated Replaced by method {@linkcode env.has}.
* @returns {boolean} Determine result.
*/
export function hasEnv(key: string): boolean {
if (typeof Deno !== "undefined") {
return Deno.env.has(key);
}
return (typeof process.env[key] !== "undefined");
return env.has(key);
}
export {
hasEnv as hasEnvironmentVariable
};
/**
* Set an environment variable.
*
Expand All @@ -85,13 +157,8 @@ export {
* @param {string} key Key of the environment variable.
* @param {string} value Value of the environment variable.
* @returns {void}
* @deprecated Replaced by method {@linkcode env.set}.
*/
export function setEnv(key: string, value: string): void {
if (typeof Deno !== "undefined") {
return Deno.env.set(key, value);
}
process.env[key] = value;
return env.set(key, value);
}
export {
setEnv as setEnvironmentVariable
};
8 changes: 4 additions & 4 deletions is_ci.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getAllEnv, getEnv } from "./env.ts";
import env from "./env.ts";
const regexpEnvFalsy = /^(?:0|false)$/i;
/**
* Determine whether this process is in CI (Continuous Integration) mode.
Expand All @@ -9,15 +9,15 @@ const regexpEnvFalsy = /^(?:0|false)$/i;
* @returns {boolean} Determine result.
*/
export function isEnvironmentCI(): boolean {
const envCIShort: string | undefined = getEnv("CI");
const envCIShort: string | undefined = env.get("CI");
if (typeof envCIShort !== "undefined" && !regexpEnvFalsy.test(envCIShort)) {
return true;
}
const envCILong: string | undefined = getEnv("CONTINUOUS_INTEGRATION");
const envCILong: string | undefined = env.get("CONTINUOUS_INTEGRATION");
if (typeof envCILong !== "undefined" && !regexpEnvFalsy.test(envCILong)) {
return true;
}
return Object.entries(getAllEnv()).some(([key, value]: [string, string]): boolean => {
return Object.entries(env.getAll()).some(([key, value]: [string, string]): boolean => {
return (key.startsWith("CI_") && !regexpEnvFalsy.test(value));
});
}
Expand Down
6 changes: 3 additions & 3 deletions is_heroku.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getEnv, hasEnv } from "./env.ts";
import env from "./env.ts";
/**
* Determine whether this process is inside Heroku.
*
Expand All @@ -12,8 +12,8 @@ import { getEnv, hasEnv } from "./env.ts";
*/
export function isEnvironmentHeroku(): boolean {
return (
hasEnv("HEROKU") ||
(hasEnv("DYNO") && getEnv("HOME") === "/app")
env.has("HEROKU") ||
(env.has("DYNO") && env.get("HOME") === "/app")
);
}
export default isEnvironmentHeroku;
4 changes: 2 additions & 2 deletions is_hyper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getEnv } from "./env.ts";
import env from "./env.ts";
/**
* Determine whether this process is inside [Hyper](https://hyper.is).
*
Expand All @@ -9,7 +9,7 @@ import { getEnv } from "./env.ts";
* @returns {boolean} Determine result.
*/
export function isEnvironmentHyper(): boolean {
const value: string | undefined = getEnv("TERM_PROGRAM");
const value: string | undefined = env.get("TERM_PROGRAM");
return (
value === "Hyper" ||
value === "HyperTerm"
Expand Down
4 changes: 1 addition & 3 deletions is_root.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { isEnvironmentRoot } from "./is_root.ts";
Deno.test("Main", {
permissions: {
sys: [
"uid"
]
sys: ["uid"]
}
}, () => {
console.log(isEnvironmentRoot());
Expand Down
4 changes: 2 additions & 2 deletions is_ssh.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { hasEnv } from "./env.ts";
import env from "./env.ts";
/**
* Determine whether this process is inside SSH.
*
Expand All @@ -9,6 +9,6 @@ import { hasEnv } from "./env.ts";
* @returns {boolean} Determine result.
*/
export function isEnvironmentSSH(): boolean {
return hasEnv("SSH_CLIENT");
return env.has("SSH_CLIENT");
}
export default isEnvironmentSSH;
Loading

0 comments on commit 5b3d704

Please sign in to comment.