evty 1.0.0
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/README.md +82 -0
- package/index.js +92 -0
- package/package.json +12 -0
package/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# โก evty
|
|
2
|
+
|
|
3
|
+
A smart, zero-config CLI tool that automatically generates TypeScript definitions from your `.env` fileโcomplete with **smart type inference** and **JSDoc support** for a better Developer Experience (DX).
|
|
4
|
+
|
|
5
|
+
No installation required. Just run it via `npx`.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## โจ Features
|
|
10
|
+
|
|
11
|
+
- โก **Zero Config**: Works out of the box. No complex JSON setups.
|
|
12
|
+
- ๐ฎ **Smart Type Inference**: Automatically converts `PORT=3000` to `string | "3000"` and `DEBUG=true` to `"true" | "false"`.
|
|
13
|
+
- ๐ **Auto JSDoc Comments**: Turns your `.env` comments (`# comment`) into TypeScript JSDoc code documentation. Hover over `process.env.VAR` in your editor to see descriptions instantly.
|
|
14
|
+
- ๐ **Watch Mode**: Live-monitors changes in your `.env` file and updates types in real time.
|
|
15
|
+
- ๐ถ **Friendly Defaults**: If you don't have a `.env` file yet, it gracefully generates a clean sample template for you.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## ๐ Quick Start
|
|
20
|
+
|
|
21
|
+
Run the following single command in your project's root folder:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx evty
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
That's it! `evty` will scan your `.env`, generate an `env.d.ts` file, and start watching for any future changes.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## ๐ก How It Works
|
|
32
|
+
|
|
33
|
+
### 1. Your `.env` file:
|
|
34
|
+
```env
|
|
35
|
+
# The port number your local server runs on
|
|
36
|
+
PORT=3000
|
|
37
|
+
|
|
38
|
+
# Toggle development features
|
|
39
|
+
DEBUG=true
|
|
40
|
+
|
|
41
|
+
# MongoDB connection string
|
|
42
|
+
DATABASE_URL=mongodb://localhost:27017/mydb
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 2. Auto-generated `env.d.ts`:
|
|
46
|
+
```typescript
|
|
47
|
+
declare global {
|
|
48
|
+
namespace NodeJS {
|
|
49
|
+
interface ProcessEnv {
|
|
50
|
+
/**
|
|
51
|
+
* The port number your local server runs on
|
|
52
|
+
*/
|
|
53
|
+
PORT: "3000" | string;
|
|
54
|
+
/**
|
|
55
|
+
* Toggle development features
|
|
56
|
+
*/
|
|
57
|
+
DEBUG: "true" | "false";
|
|
58
|
+
/**
|
|
59
|
+
* MongoDB connection string
|
|
60
|
+
*/
|
|
61
|
+
DATABASE_URL: string;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export {};
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 3. Your Editor (Developer Experience):
|
|
69
|
+
When typing `process.env.PORT` in VS Code or any modern IDE, you will get **full autocomplete** and see the precise comment as a hover popup.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## ๐ ๏ธ Requirements
|
|
74
|
+
|
|
75
|
+
- [Node.js](https://nodejs.org) (v16 or higher recommended)
|
|
76
|
+
- A TypeScript project (or JavaScript project using `@ts-check`)
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## ๐ License
|
|
81
|
+
|
|
82
|
+
This project is licensed under the MIT License.
|
package/index.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
7
|
+
const outputPath = path.join(process.cwd(), 'env.d.ts');
|
|
8
|
+
|
|
9
|
+
// Function to infer the best TypeScript type from a .env value
|
|
10
|
+
function inferType(value) {
|
|
11
|
+
const v = value.trim();
|
|
12
|
+
if (!v || v === '""' || v === "''") return 'string';
|
|
13
|
+
|
|
14
|
+
// For Numbers (provides string-literal for autocomplete, but falls back to string)
|
|
15
|
+
if (!isNaN(v) && !isNaN(parseFloat(v))) {
|
|
16
|
+
return `"${v}" | string`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// For Booleans
|
|
20
|
+
if (v === 'true' || v === 'false') {
|
|
21
|
+
return '"true" | "false"';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return 'string';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Main logic to generate TypeScript definitions
|
|
28
|
+
function generateTypes() {
|
|
29
|
+
// If .env doesn't exist, create a friendly default sample
|
|
30
|
+
if (!fs.existsSync(envPath)) {
|
|
31
|
+
const defaultEnv = `# Server port number\nPORT=3000\n\n# Enable debug mode\nDEBUG=true\n\n# Database connection URL\nDATABASE_URL=mongodb://localhost:27017/mydb\n`;
|
|
32
|
+
fs.writeFileSync(envPath, defaultEnv);
|
|
33
|
+
console.log('๐ .env file not found. Created a default sample for you!');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const content = fs.readFileSync(envPath, 'utf8');
|
|
37
|
+
const lines = content.split(/\r?\n/);
|
|
38
|
+
|
|
39
|
+
let typeDefinitions = 'declare global {\n namespace NodeJS {\n interface ProcessEnv {\n';
|
|
40
|
+
let currentComment = '';
|
|
41
|
+
|
|
42
|
+
lines.forEach(line => {
|
|
43
|
+
const trimmed = line.trim();
|
|
44
|
+
|
|
45
|
+
// Reset comment on empty lines
|
|
46
|
+
if (!trimmed) {
|
|
47
|
+
currentComment = '';
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Process comment lines
|
|
52
|
+
if (trimmed.startsWith('#')) {
|
|
53
|
+
const commentText = trimmed.replace(/^#\s*/, '');
|
|
54
|
+
currentComment += currentComment ? `\n * ${commentText}` : commentText;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Split by the first equals sign
|
|
59
|
+
const equalIndex = trimmed.indexOf('=');
|
|
60
|
+
if (equalIndex === -1) return;
|
|
61
|
+
|
|
62
|
+
const key = trimmed.substring(0, equalIndex).trim();
|
|
63
|
+
const value = trimmed.substring(equalIndex + 1).trim();
|
|
64
|
+
|
|
65
|
+
if (key) {
|
|
66
|
+
// Insert JSDoc if a comment exists right above the key
|
|
67
|
+
if (currentComment) {
|
|
68
|
+
typeDefinitions += ` /**\n * ${currentComment}\n */\n`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const smartType = inferType(value);
|
|
72
|
+
typeDefinitions += ` ${key}: ${smartType};\n`;
|
|
73
|
+
currentComment = '';
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
typeDefinitions += ' }\n }\n}\nexport {};\n';
|
|
78
|
+
|
|
79
|
+
fs.writeFileSync(outputPath, typeDefinitions);
|
|
80
|
+
console.log('โก [evty] env.d.ts updated successfully with types and JSDoc!');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Initial execution
|
|
84
|
+
generateTypes();
|
|
85
|
+
|
|
86
|
+
// Start watching the .env file
|
|
87
|
+
console.log('๐ Watching .env file for changes... (Press Ctrl + C to exit)');
|
|
88
|
+
fs.watchFile(envPath, { interval: 1000 }, (curr, prev) => {
|
|
89
|
+
if (curr.mtime !== prev.mtime) {
|
|
90
|
+
generateTypes();
|
|
91
|
+
}
|
|
92
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "evty",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A smart, zero-config CLI tool that automatically generates TypeScript definitions (with typed values and JSDoc) from your .env file.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"evty": "./index.js"
|
|
8
|
+
},
|
|
9
|
+
"keywords": ["env", "typescript", "dx", "cli", "tool", "autocomplete"],
|
|
10
|
+
"author": "Your Name",
|
|
11
|
+
"license": "MIT"
|
|
12
|
+
}
|