Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

classenv

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

classenv - npm Package Compare versions

Comparing version 1.3.1 to 1.4.0

2

dist/env.d.ts

@@ -1,2 +0,2 @@

export declare function Env(variableName?: string): any;
export declare function Env(variableName?: string | string[]): any;
//# sourceMappingURL=env.d.ts.map

@@ -10,24 +10,37 @@ "use strict";

}
const FALSEY_VALUES = ['false', '0'];
function Env(variableName) {
return (target, key) => {
variableName !== null && variableName !== void 0 ? variableName : (variableName = upperSnakeCase(key));
let value = process.env[variableName];
if (typeof value === 'undefined') {
let envVarValue = void 0;
if (Array.isArray(variableName)) {
const existingKey = variableName.find((k) => typeof process.env[k] === 'string');
if (typeof existingKey === 'string') {
envVarValue = process.env[existingKey];
}
}
else {
envVarValue = process.env[variableName];
}
let outValue;
if (typeof envVarValue === 'undefined') {
if (typeof target[key] === 'undefined') {
throw new Error(`Environment variable ${variableName} is undefined`);
throw new Error(`CLASSENV: Environment variable ${JSON.stringify(variableName)} is undefined and default value for field ${JSON.stringify(key)} not set`);
}
else {
value = target[key];
outValue = target[key];
}
}
const designType = Reflect.getMetadata('design:type', target, key);
if ([String, Number, Boolean].includes(designType)) {
if (designType === Boolean && ['false', 'FALSE', '0'].includes(value)) {
value = false;
else {
outValue = envVarValue;
}
const DesignType = Reflect.getMetadata('design:type', target, key);
if ([String, Number, Boolean].includes(DesignType)) {
if (DesignType === Boolean &&
FALSEY_VALUES.includes(outValue.toLowerCase())) {
outValue = '';
}
else {
value = designType(value);
}
outValue = DesignType(outValue);
Object.defineProperty(target, key, {
value,
value: outValue,
writable: false,

@@ -39,3 +52,3 @@ enumerable: true,

else {
throw new Error(`${key} type must be one of [String, Number, Boolean]. Got ${designType.name}`);
throw new Error(`CLASSENV: ${key} type must be one of [String, Number, Boolean]. Got ${DesignType.name}`);
}

@@ -42,0 +55,0 @@ };

{
"name": "classenv",
"version": "1.3.1",
"description": "Describe your environment variables contract with TypeScript class",
"version": "1.4.0",
"description": "Describe your environment variables contract with TypeScript class decorator",
"main": "dist/index.js",

@@ -27,5 +27,5 @@ "types": "dist/index.d.ts",

"jest": "^25.1.0",
"prettier": "^2.6.2",
"prettier": "^2.7.1",
"ts-jest": "^25.2.1",
"typescript": "^4.6.4"
"typescript": "^4.8.4"
},

@@ -36,7 +36,10 @@ "peerDependencies": {

"keywords": [
"typescript",
"class",
"environment",
"env",
"variables",
"decorator",
"dotenv",
"env",
".env",
"environment",
"variables",
"config",

@@ -46,7 +49,4 @@ "settings",

"process.env",
"typescript",
"class",
"decorator",
"defaults"
]
}

@@ -1,4 +0,4 @@

# classenv
# TypeScript environment variable decorator
A perfect typescript class environment variables library.
A perfect TypeScript environment variables library.

@@ -11,73 +11,143 @@ - Strongly-typed declarative class containing your environment data

- Throws runtime error if variable doesn't exist
- Default values support
- Supports default values
- Makes decorated properties read-only in runtime
- ❤️ You will like it
## 💼 Use cases
## Description
Let's pretend we have very simple
### 🪞 Type-casting Using TypeScript metadata reflection
**.env**
Just specify class field type and `classenv` will cast the environment variable string value to the value of your field type.
Only `string`, `number`, and `boolean` is supported.
```ts
process.env['PORT'] = '3000';
class ServerSettings {
// Field name will be auto-converted to POSTGRES_URL for checking the process.env
@Env('PORT')
portNumber!: number; // 3000
@Env('PORT')
portString!: string; // "3000"
@Env('PORT') // Why not?!
portBoolean!: boolean; // true
}
```
IS_SOMETHING_ENABLED=1
### 🐍 Auto UPPER_SNAKE_CASE from camelCase conversion
No need to manually specify the environment variable name
```ts
process.env['POSTGRES_URL'] = 'postgres://127.0.0.1:5432';
class PostgresAdapter {
// Field name will be auto-converted to POSTGRES_URL for checking the process.env
@Env()
postgresUrl!: string; // postgres://127.0.0.1:5432
}
```
How can we describe it using **classenv**
### 🫙 Use default value in case of environment variable absence
**environment.ts**
```typescript
import { Env } from 'classenv';
```ts
class ServerSettings {
@Env()
port: number = 3000;
}
```
export class Environment {
@Env() // Auto UPPER_SNAKE_CASE conversion
static isSomethingEnabled: number; // process.env.IS_SOMETHING_ENABLED
### 🚔 Throw runtime error if no value provided
@Env() // Instance properties supported
isSomethingEnabled: number;
One could say `"It's a bad practice to throw runtime error"`, and it's a right assertion, but not in this case.
Most of the time your application can't work without all the environment variables.
You don't want to run application in an indefinite state and then debug these strange things.
So `classenv` will throw runtime error and your application should shut down with an informative message of what's going wrong.
@Env() // Won't throw, because got default value
static withDefault: string = 'yeah its me'
```ts
class PostgresAdapter {
@Env()
// Will throw a runtime error, because your app can't work without DB connection
postgresUrl!: string;
}
```
@Env('IS_SOMETHING_ENABLED')
static isEnabledStr: string;
But in case the environment variable is not required – you can just assign a default value for the field, and it will not throw.
@Env('IS_SOMETHING_ENABLED')
static isEnabledNmbr: number;
```ts
class PostgresAdapter {
@Env()
postgresUrl: string = 'postgres://127.0.0.1:5432'; // Everything is ok here
}
```
@Env('IS_SOMETHING_ENABLED')
static isEnabledBln: boolean;
### 🔘 Pick one of the name from array
```ts
process.env['POSTGRES_URL'] = 'postgres://127.0.0.1:5432';
class PostgresAdapter {
@Env(['POSTGRESQL_URI', 'PG_URL', 'POSTGRES_URL'])
url!: string; // postgres://127.0.0.1:5432
}
```
`@Env` property data type should be scalar (string, number or boolean).
### ✨ `static` field also supported
**main.ts**
```typescript
import {Environment} from './environment.ts'
```ts
process.env['PORT'] = '3000';
console.log(typeof Environment.isEnabledStr, Environment.isEnabledStr)
// string 1
class ServerSettings {
@Env()
static port: number = 3000;
}
```
console.log(typeof Environment.isEnabledNmbr, Environment.isEnabledNmbr)
// number 1
### 1️⃣ Boolean type casting 0️⃣
console.log(typeof Environment.isEnabledBln, Environment.isEnabledBln)
// boolean true
If value is `0` of `false` in any case (`FaLsE` also included, since it's `.toLowerCase()`'d under the hood) – it becomes `false`.
Otherwise - `true`
console.log(typeof Environment.isSomethingEnabled, Environment.isSomethingEnabled)
// number 1
```ts
process.env['FALSE'] = 'false';
process.env['ZERO'] = '0';
process.env['TRUE'] = 'true';
process.env['ANYTHING'] = 'Jast a random string';
Environment.isEnabledBln = false;
// TypeError: Cannot assign to read only property 'isEnabledBln' of function 'class Test{}'
class Common {
@Env()
static FALSE!: boolean; // false
@Env()
static zero!: boolean; // false
@Env()
static TRUE!: boolean; // true
@Env()
static anything!: boolean; // true
}
```
### 🛑 `@Env()` decorated properties are read-only in runtime
// Let's check instance properties
const env = new Environment();
Environment is something established from outside, so you definitely should not modify it in your application.
console.log(env.isSomethingEnabled) // 1
```ts
process.env['PORT'] = '3000';
class ServerSettings {
@Env()
static port!: number;
}
// TypeError: Cannot assign to read only property 'port' of function 'class ServerSettings{}'
ServerSettings.port = 5000;
```
## Dependencies
## ❗Dependencies❗
It is important, `classenv` can not work without it.
### reflect-metadata
```

@@ -87,3 +157,3 @@ npm i reflect-metadata

And then import it somewhere close to your entry point (`index.ts`/`main.ts`/etc...).
And then import it somewhere close to your entry point (`index.ts`/`main.ts`/etc...).
Should be imported before any of your environment classes.

@@ -90,0 +160,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc