@calvear/env 3.0.0 → 3.1.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/CHANGELOG.md +14 -0
- package/README.md +378 -436
- package/arguments.js +1 -1
- package/arguments.js.map +1 -1
- package/assets/logo.svg +30 -0
- package/commands/export.command.js +1 -1
- package/commands/export.command.js.map +1 -1
- package/commands/pull.command.js.map +1 -1
- package/commands/push.command.js.map +1 -1
- package/commands/schema.command.js.map +1 -1
- package/main.js.map +1 -1
- package/package.json +2 -1
- package/providers/index.js.map +1 -1
- package/providers/secrets.provider.js.map +1 -1
- package/schemas/settings.schema.json +2 -2
- package/utils/argv.util.js.map +1 -1
- package/utils/logger.d.ts.map +1 -1
- package/utils/logger.js +14 -9
- package/utils/logger.js.map +1 -1
- package/utils/normalize.util.d.ts +4 -0
- package/utils/normalize.util.d.ts.map +1 -1
- package/utils/normalize.util.js +1 -1
- package/utils/normalize.util.js.map +1 -1
- package/utils/schema.util.d.ts.map +1 -1
- package/utils/schema.util.js +2 -2
- package/utils/schema.util.js.map +1 -1
- package/utils/ui.d.ts.map +1 -1
- package/utils/ui.js +54 -31
- package/utils/ui.js.map +1 -1
package/README.md
CHANGED
|
@@ -1,357 +1,273 @@
|
|
|
1
1
|
<div id="top" align="center">
|
|
2
|
-
<img
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
<img alt="@calvear/env logo" src="assets/logo.svg" width="150" />
|
|
3
|
+
|
|
4
|
+
<h1 align="center"><b>env</b></h1>
|
|
5
|
+
<h4 align="center">Environment variables made easy — load, validate, inject.</h4>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<img src="https://img.shields.io/npm/v/@calvear/env?style=flat-square&color=2563eb&label=version" alt="version" />
|
|
9
|
+
|
|
10
|
+
<img src="https://img.shields.io/badge/module-ESM-f59e0b?style=flat-square" alt="esm" />
|
|
11
|
+
|
|
12
|
+
<img src="https://img.shields.io/badge/TypeScript-007ACC?style=flat-square&logo=typescript&logoColor=white" alt="typescript" />
|
|
13
|
+
|
|
14
|
+
<img src="https://img.shields.io/badge/node->=20-339933?style=flat-square&logo=node.js&logoColor=white" alt="node engine" />
|
|
15
|
+
|
|
16
|
+
<img src="https://img.shields.io/badge/coverage-100%25-22c55e?style=flat-square" alt="coverage" />
|
|
17
|
+
|
|
18
|
+
<img src="https://img.shields.io/npm/l/@calvear/env?style=flat-square&color=eab308" alt="license" />
|
|
19
|
+
</p>
|
|
12
20
|
</div>
|
|
13
21
|
|
|
14
22
|
<br />
|
|
15
23
|
|
|
16
|
-
|
|
17
|
-
<img
|
|
18
|
-
src="https://img.shields.io/badge/version-3.0.0-blue?style=flat-square"
|
|
19
|
-
alt="version"
|
|
20
|
-
/>
|
|
21
|
-
|
|
22
|
-
<img
|
|
23
|
-
src="https://img.shields.io/badge/TypeScript-007ACC?style=flat-square&logo=typescript&logoColor=white"
|
|
24
|
-
alt="typescript"
|
|
25
|
-
/>
|
|
26
|
-
|
|
27
|
-
<img
|
|
28
|
-
src="https://img.shields.io/badge/ESM-only-f7df1e?style=flat-square"
|
|
29
|
-
alt="esm only"
|
|
30
|
-
/>
|
|
31
|
-
|
|
32
|
-
<img
|
|
33
|
-
src="https://img.shields.io/badge/nodejs->=20-darkgreen?style=flat-square"
|
|
34
|
-
alt="nodejs engine"
|
|
35
|
-
/>
|
|
36
|
-
|
|
37
|
-
<img
|
|
38
|
-
src="https://img.shields.io/badge/pnpm->=9-darkgreen?style=flat-square"
|
|
39
|
-
alt="pnpm engine"
|
|
40
|
-
/>
|
|
41
|
-
|
|
42
|
-
<img
|
|
43
|
-
src="https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square"
|
|
44
|
-
alt="license"
|
|
45
|
-
/>
|
|
46
|
-
</p>
|
|
24
|
+
<!-- ABOUT -->
|
|
47
25
|
|
|
48
|
-
|
|
26
|
+
## 📖 About
|
|
49
27
|
|
|
50
|
-
|
|
28
|
+
`@calvear/env` eases **environment variable handling** for NodeJS apps — like
|
|
29
|
+
[env-cmd](https://www.npmjs.com/package/env-cmd) or
|
|
30
|
+
[dotenv](https://www.npmjs.com/package/dotenv), but with **powerful, extensible
|
|
31
|
+
features**: pluggable **providers** to `load`, `pull` and `push` variables from
|
|
32
|
+
different stores, **JSON Schema validation**, value **interpolation**, secret
|
|
33
|
+
**masking** and nested/shared keys.
|
|
51
34
|
|
|
52
|
-
|
|
35
|
+
### ✨ Features
|
|
53
36
|
|
|
54
|
-
|
|
37
|
+
- 🧩 **Provider plugins** — bundled `package-json`, `app-settings`, `secrets`
|
|
38
|
+
and `local` providers, plus your own (NPM package or local script).
|
|
39
|
+
- 💉 **Injection** — load variables into `process.env` and run any command.
|
|
40
|
+
- ✅ **JSON Schema** — auto-generate and validate variables before injecting.
|
|
41
|
+
- 🪆 **Nested & global keys** — `GROUP__VAR` flattening and `$`-prefixed global
|
|
42
|
+
keys (the `$` marker is stripped on injection).
|
|
43
|
+
- 🧵 **Interpolation** — reference other args/vars with `[[ ]]` delimiters.
|
|
44
|
+
- 🙈 **Masking** — hide secrets in the debug output by key name, key regex, or
|
|
45
|
+
value content regex.
|
|
46
|
+
- 🎨 **Pretty output** — colorized, sorted, masked debug render of the resolved
|
|
47
|
+
environment.
|
|
48
|
+
- 📤 **Export** — write the unified environment to a `.env` or JSON file.
|
|
55
49
|
|
|
56
50
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
|
57
51
|
|
|
58
52
|
<!-- REQUIREMENTS -->
|
|
59
53
|
|
|
60
|
-
## 📌
|
|
54
|
+
## 📌 Requirements
|
|
61
55
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
> 🧩 **ESM only**: this package is published as native ECMAScript Modules
|
|
65
|
-
> (`"type": "module"`). Import it from ESM code, and author any custom provider
|
|
66
|
-
> as an ESM module with a `export default`.
|
|
67
|
-
|
|
68
|
-
Validate installed versions of node and pnpm with:
|
|
56
|
+
[NodeJS](https://nodejs.org/) **20 or higher**.
|
|
69
57
|
|
|
70
58
|
```bash
|
|
71
59
|
> node -v
|
|
72
60
|
v20.0.0
|
|
73
|
-
|
|
74
|
-
> pnpm -v
|
|
75
|
-
9.0.0
|
|
76
61
|
```
|
|
77
62
|
|
|
78
|
-
|
|
63
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
|
79
64
|
|
|
80
|
-
|
|
81
|
-
|
|
65
|
+
<!-- ESM -->
|
|
66
|
+
|
|
67
|
+
## 📦 ESM only
|
|
68
|
+
|
|
69
|
+
Since **v3** this package is **ESM-only** (`"type": "module"`). Consumers must
|
|
70
|
+
use ESM `import` syntax, and custom providers must be ESM modules that `export`
|
|
71
|
+
their provider object.
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
// ✅ ESM
|
|
75
|
+
import { EnvProvider } from '@calvear/env';
|
|
76
|
+
|
|
77
|
+
// ❌ CommonJS require is not supported
|
|
78
|
+
// const { EnvProvider } = require('@calvear/env');
|
|
82
79
|
```
|
|
83
80
|
|
|
84
81
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
|
85
82
|
|
|
86
83
|
<!-- QUICK START -->
|
|
87
84
|
|
|
88
|
-
## ⚡️
|
|
85
|
+
## ⚡️ Quick start
|
|
89
86
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
- Installs the package:
|
|
87
|
+
Install the package:
|
|
93
88
|
|
|
94
89
|
```bash
|
|
95
90
|
> npm install @calvear/env
|
|
96
|
-
|
|
97
|
-
added 1 packages, and audited 1 packages in 1s
|
|
98
|
-
|
|
99
|
-
found 0 vulnerabilities
|
|
100
|
-
|
|
101
|
-
> _
|
|
102
91
|
```
|
|
103
92
|
|
|
104
|
-
|
|
93
|
+
Run the binary directly:
|
|
105
94
|
|
|
106
95
|
```bash
|
|
107
|
-
>
|
|
96
|
+
> npx env --help
|
|
108
97
|
|
|
109
98
|
Usage: env [command] [options..] [: subcmd [:]] [options..]
|
|
110
99
|
|
|
111
100
|
Commands:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
> _
|
|
101
|
+
env [options..] [: <subcmd> :]
|
|
102
|
+
env pull [options..]
|
|
103
|
+
env push [options..]
|
|
104
|
+
env schema [options..]
|
|
105
|
+
env export [options..]
|
|
118
106
|
```
|
|
119
107
|
|
|
120
|
-
|
|
108
|
+
Or wire it into your **npm scripts**:
|
|
121
109
|
|
|
122
|
-
```
|
|
110
|
+
```jsonc
|
|
123
111
|
{
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
"build:prod": "env -e prod -m build : tsc",
|
|
133
|
-
...,
|
|
134
|
-
"env:schema": "env schema -e dev --ci",
|
|
135
|
-
// uploads environment "dev" variables
|
|
136
|
-
"env:push:dev": "env push -e dev",
|
|
137
|
-
// downloads environment "dev" variables
|
|
138
|
-
"env:pull:dev": "env pull -e dev"
|
|
139
|
-
},
|
|
140
|
-
...
|
|
112
|
+
"scripts": {
|
|
113
|
+
// inject "dev" variables (debug mode) and start the app
|
|
114
|
+
"start:dev": "env -e dev -m debug : node dist/main.js",
|
|
115
|
+
// inject "prod" variables for the build
|
|
116
|
+
"build:prod": "env -e prod -m build : tsc",
|
|
117
|
+
// regenerate the validation schema
|
|
118
|
+
"env:schema": "env schema -e dev",
|
|
119
|
+
},
|
|
141
120
|
}
|
|
142
121
|
```
|
|
143
122
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
**file**: _dist/main.js_
|
|
147
|
-
|
|
148
|
-
```javascript
|
|
149
|
-
console.log(`My environment loaded is: ${process.env.ENV}`);
|
|
150
|
-
```
|
|
123
|
+
Run it:
|
|
151
124
|
|
|
152
125
|
```bash
|
|
153
126
|
> npm run start:dev
|
|
154
127
|
|
|
155
|
-
|
|
156
|
-
13:31:59.911 DEBUG using package-json provider
|
|
157
|
-
13:31:59.912 DEBUG using app-settings provider
|
|
158
|
-
13:31:59.914 DEBUG using secrets provider
|
|
159
|
-
13:32:00.109 DEBUG environment loaded:
|
|
160
|
-
{
|
|
161
|
-
NODE_ENV: 'development',
|
|
162
|
-
ENV: 'dev',
|
|
163
|
-
VERSION: '1.0.0',
|
|
164
|
-
NAME: '@my-app',
|
|
165
|
-
VAR1: true,
|
|
166
|
-
VAR2: true,
|
|
167
|
-
GROUP1__VAR1: 'G1V2',
|
|
168
|
-
ARR1: '1,val,true',
|
|
169
|
-
SECRET: '***'
|
|
170
|
-
}
|
|
171
|
-
13:32:00.116 INFO executing command > node dist/main.js
|
|
172
|
-
My environment loaded is: dev
|
|
173
|
-
13:32:00.232 INFO process finished successfully
|
|
128
|
+
⚡ env v3.0.0 · 🌎 dev · 🧩 debug
|
|
174
129
|
|
|
175
|
-
|
|
176
|
-
|
|
130
|
+
📦 package-json 6 vars
|
|
131
|
+
🗂️ app-settings 5 vars
|
|
132
|
+
🔐 secrets 1 secrets
|
|
133
|
+
📂 local 1 vars
|
|
177
134
|
|
|
178
|
-
|
|
135
|
+
environment (12 variables)
|
|
136
|
+
ENV = dev
|
|
137
|
+
NODE_ENV = development
|
|
138
|
+
SECRET = *****
|
|
139
|
+
VERSION = 3.0.0
|
|
140
|
+
...
|
|
179
141
|
|
|
180
|
-
|
|
142
|
+
✓ 12 variables loaded in 142ms
|
|
181
143
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
│ │ ├── env.command.ts
|
|
186
|
-
│ │ ├── export.command.ts
|
|
187
|
-
│ │ ├── pull.command.ts
|
|
188
|
-
│ │ ├── push.command.ts
|
|
189
|
-
│ │ └── schema.command.ts
|
|
190
|
-
│ ├── interfaces/ # provider interfaces
|
|
191
|
-
│ ├── providers/ # integrated providers
|
|
192
|
-
│ │ ├── package-json.provider.ts
|
|
193
|
-
│ │ ├── app-settings.provider.ts
|
|
194
|
-
│ │ ├── secrets.provider.ts
|
|
195
|
-
│ │ └── local.provider.ts
|
|
196
|
-
│ ├── utils/
|
|
197
|
-
│ │ ├── command.util.ts
|
|
198
|
-
│ │ ├── interpolate.util.ts
|
|
199
|
-
│ │ ├── json.util.ts
|
|
200
|
-
│ │ ├── normalize.util.ts
|
|
201
|
-
│ │ ├── schema.util.ts
|
|
202
|
-
│ │ └── logger.ts
|
|
203
|
-
│ ├── arguments.ts # global arguments
|
|
204
|
-
│ ├── exec.ts # initialization logic (load config, commands, etc.)
|
|
205
|
-
│ └── main.ts
|
|
206
|
-
├── tests/ # integration tests
|
|
207
|
-
├── eslint.config.js
|
|
208
|
-
├── vite.config.ts
|
|
209
|
-
├── vitest.config.ts
|
|
210
|
-
└── tsconfig.json
|
|
144
|
+
▶ node dist/main.js
|
|
145
|
+
My environment loaded is: dev
|
|
146
|
+
✓ finished in 168ms
|
|
211
147
|
```
|
|
212
148
|
|
|
149
|
+
> The resolved environment is only rendered at `--log debug`. Values are
|
|
150
|
+
> **sorted**, **secrets are masked**, and colored by type — strings in gray,
|
|
151
|
+
> numbers in orange, booleans `true`/`false` in green/red.
|
|
152
|
+
|
|
213
153
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
|
214
154
|
|
|
215
155
|
<!-- COMMANDS AND OPTIONS -->
|
|
216
156
|
|
|
217
|
-
## ⚙️
|
|
157
|
+
## ⚙️ Commands & Options
|
|
218
158
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
_`[[root]]/config-file.[[env]].json`_ will be _`config/config-file.dev.json`_.
|
|
224
|
-
|
|
225
|
-
<div align="center">
|
|
226
|
-
<span style="font-size:20px;font-weight:bold" align="center">Options</span>
|
|
227
|
-
</div>
|
|
159
|
+
> **Interpolation** — any option value can reference other arguments using `[[`
|
|
160
|
+
> and `]]` delimiters. With `root: "config"`, the value `[[root]]/file.json`
|
|
161
|
+
> resolves to `config/file.json`; with `env: "dev"`,
|
|
162
|
+
> `[[root]]/config.[[env]].json` resolves to `config/config.dev.json`.
|
|
228
163
|
|
|
229
164
|
### Global options
|
|
230
165
|
|
|
231
|
-
| Option | Description
|
|
232
|
-
| ---------------------------------- |
|
|
233
|
-
| `--help` |
|
|
234
|
-
|
|
|
235
|
-
| `-m, --modes` | Execution modes
|
|
236
|
-
| `--nd, --nestingDelimiter` | Nesting
|
|
237
|
-
| `--arrDesc, --arrayDescomposition` |
|
|
238
|
-
| `-x, --expand` |
|
|
239
|
-
|
|
|
240
|
-
|
|
241
|
-
</br>
|
|
166
|
+
| Option | Description | Type | Default |
|
|
167
|
+
| ---------------------------------- | ------------------------------------------------- | ---------- | ------- |
|
|
168
|
+
| `--help` | Show help | `boolean` | |
|
|
169
|
+
| `-e, --env` | Environment to load (i.e. `dev`, `prod`) | `string` | |
|
|
170
|
+
| `-m, --modes` | Execution modes (i.e. `debug`, `test`) | `string[]` | `[]` |
|
|
171
|
+
| `--nd, --nestingDelimiter` | Nesting-level delimiter for flatten | `string` | `__` |
|
|
172
|
+
| `--arrDesc, --arrayDescomposition` | Serialize (`false`) or break down (`true`) arrays | `boolean` | `false` |
|
|
173
|
+
| `-x, --expand` | Interpolate environment variables using itself | `boolean` | `false` |
|
|
174
|
+
| `--ci` | Continuous Integration mode (skips local files) | `boolean` | auto |
|
|
242
175
|
|
|
243
176
|
### Workspace options
|
|
244
177
|
|
|
245
|
-
| Option
|
|
246
|
-
|
|
|
247
|
-
| `--root`
|
|
248
|
-
| `-c, --configFile`
|
|
249
|
-
| `-s, --schemaFile`
|
|
178
|
+
| Option | Description | Type | Default |
|
|
179
|
+
| ---------------------- | --------------------------------- | -------- | --------------------------------- |
|
|
180
|
+
| `--root` | Base environment folder path | `string` | `env` |
|
|
181
|
+
| `-c, --configFile` | Config JSON file path | `string` | `[[root]]/settings/settings.json` |
|
|
182
|
+
| `-s, --schemaFile` | Environment schema JSON file path | `string` | `[[root]]/settings/schema.json` |
|
|
183
|
+
| `--pkg, --packageJson` | `package.json` path | `string` | _cwd_ |
|
|
250
184
|
|
|
251
185
|
### JSON Schema options
|
|
252
186
|
|
|
253
|
-
| Option | Description
|
|
254
|
-
| ---------------------- |
|
|
255
|
-
| `-r, --resolve` |
|
|
256
|
-
| `--null, --nullable` | Whether variables are nullable by default
|
|
257
|
-
| `--df, --detectFormat` |
|
|
187
|
+
| Option | Description | Type | Default |
|
|
188
|
+
| ---------------------- | ---------------------------------------------- | ------------------ | ------- |
|
|
189
|
+
| `-r, --resolve` | Merge new schema or override it | `merge`/`override` | `merge` |
|
|
190
|
+
| `--null, --nullable` | Whether variables are nullable by default | `boolean` | `true` |
|
|
191
|
+
| `--df, --detectFormat` | Include string formats in the generated schema | `boolean` | `false` |
|
|
258
192
|
|
|
259
193
|
### Logger options
|
|
260
194
|
|
|
261
|
-
| Option
|
|
262
|
-
|
|
|
263
|
-
| `--log, --logLevel`
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
<span style="font-size:20px;font-weight:bold" align="center">Commands</span>
|
|
267
|
-
</div>
|
|
268
|
-
|
|
269
|
-
- ## **`env`**
|
|
195
|
+
| Option | Description | Type | Default |
|
|
196
|
+
| ------------------------------ | ------------------------------------------------------ | --------------------------------------------- | ------- |
|
|
197
|
+
| `--log, --logLevel` | Log level | `silly`/`trace`/`debug`/`info`/`warn`/`error` | `info` |
|
|
198
|
+
| `--mvk, --logMaskValuesOfKeys` | Mask a value when its **key** matches (exact or regex) | `string[]` | `[]` |
|
|
199
|
+
| `--mrx, --logMaskAnyRegEx` | Mask **value content** matching a regex (every match) | `string[]` | `[]` |
|
|
270
200
|
|
|
271
|
-
|
|
201
|
+
See [🙈 Masking secrets](#-masking-secrets) for the full masking semantics.
|
|
272
202
|
|
|
273
|
-
|
|
274
|
-
env -e [env] [options..] [: subcmd [:]] [options..]
|
|
275
|
-
```
|
|
203
|
+
---
|
|
276
204
|
|
|
277
|
-
|
|
205
|
+
### `env`
|
|
278
206
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
```
|
|
207
|
+
Inject environment variables into `process.env` and execute a command (the
|
|
208
|
+
command goes after `:`).
|
|
282
209
|
|
|
283
210
|
```bash
|
|
284
|
-
|
|
211
|
+
env -e <env> [options..] [: <subcmd> :] [options..]
|
|
285
212
|
```
|
|
286
213
|
|
|
287
214
|
```bash
|
|
288
|
-
> env -e
|
|
215
|
+
> env -e dev -m test unit : npm test
|
|
216
|
+
> env -e dev -m debug : npm start : -c [[root]]/[[env]].env.json
|
|
217
|
+
> env -e prod -m build optimize : npm run build
|
|
289
218
|
```
|
|
290
219
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
```bash
|
|
296
|
-
env pull -e [env] [options..]
|
|
297
|
-
```
|
|
220
|
+
| Option | Description | Type | Default |
|
|
221
|
+
| ------------------------------ | ------------------------------------------ | --------- | ------- |
|
|
222
|
+
| `--validate, --schemaValidate` | Validate variables against the JSON schema | `boolean` | `true` |
|
|
298
223
|
|
|
299
|
-
|
|
300
|
-
| ----------------- | ------------------------- | --------- | ------- | --------- |
|
|
301
|
-
| `-o, --overwrite` | Overwrite local variables | `boolean` | `false` | No |
|
|
224
|
+
### `pull`
|
|
302
225
|
|
|
303
|
-
|
|
226
|
+
Pull environment variables from the providers' stores (for providers that
|
|
227
|
+
implement `pull`, i.e. custom remote providers).
|
|
304
228
|
|
|
305
229
|
```bash
|
|
306
|
-
|
|
230
|
+
env pull -e <env> [options..]
|
|
307
231
|
```
|
|
308
232
|
|
|
309
|
-
|
|
233
|
+
| Option | Description | Type | Default |
|
|
234
|
+
| ----------------- | ------------------------- | --------- | ------- |
|
|
235
|
+
| `-o, --overwrite` | Overwrite local variables | `boolean` | `false` |
|
|
310
236
|
|
|
311
|
-
|
|
237
|
+
### `push`
|
|
312
238
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
| Option | Description | Type | Default | Required? |
|
|
318
|
-
| ------------- | ------------------------------------ | --------- | ------- | --------- |
|
|
319
|
-
| `-f, --force` | Force push for secrets (replace all) | `boolean` | `false` | No |
|
|
320
|
-
|
|
321
|
-
Examples:
|
|
239
|
+
Push environment variables to the providers' stores (for providers that
|
|
240
|
+
implement `push`).
|
|
322
241
|
|
|
323
242
|
```bash
|
|
324
|
-
|
|
243
|
+
env push -e <env> [options..]
|
|
325
244
|
```
|
|
326
245
|
|
|
327
|
-
|
|
246
|
+
| Option | Description | Type | Default |
|
|
247
|
+
| ------------- | ---------------------- | --------- | ------- |
|
|
248
|
+
| `-f, --force` | Force push for secrets | `boolean` | `false` |
|
|
328
249
|
|
|
329
|
-
|
|
250
|
+
### `schema`
|
|
330
251
|
|
|
331
|
-
|
|
332
|
-
env schema -e [env] -m [modes] [options..]
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
Examples:
|
|
252
|
+
Generate (or update) the validation schema from the providers' output.
|
|
336
253
|
|
|
337
254
|
```bash
|
|
338
255
|
> env schema -e dev -m build
|
|
339
256
|
```
|
|
340
257
|
|
|
341
|
-
|
|
258
|
+
### `export`
|
|
342
259
|
|
|
343
|
-
Export unified environment
|
|
260
|
+
Export the unified environment to a file.
|
|
344
261
|
|
|
345
262
|
```bash
|
|
346
|
-
env export -e
|
|
263
|
+
env export -e <env> -m <modes> [options..]
|
|
347
264
|
```
|
|
348
265
|
|
|
349
|
-
| Option | Description
|
|
350
|
-
| --------------- |
|
|
351
|
-
| `-u, -p, --uri` |
|
|
352
|
-
| `-f, --format` |
|
|
353
|
-
|
|
354
|
-
Examples:
|
|
266
|
+
| Option | Description | Type | Default |
|
|
267
|
+
| --------------- | --------------------- | --------------- | -------- |
|
|
268
|
+
| `-u, -p, --uri` | Output file path | `string` | `.env` |
|
|
269
|
+
| `-f, --format` | Output format | `dotenv`/`json` | `dotenv` |
|
|
270
|
+
| `-q, --quotes` | Wrap values in quotes | `boolean` | `false` |
|
|
355
271
|
|
|
356
272
|
```bash
|
|
357
273
|
> env export -e dev -m build -f json --uri [[env]].env.json
|
|
@@ -361,143 +277,99 @@ Examples:
|
|
|
361
277
|
|
|
362
278
|
<!-- PROVIDERS -->
|
|
363
279
|
|
|
364
|
-
## 📡
|
|
280
|
+
## 📡 Providers
|
|
365
281
|
|
|
366
|
-
|
|
367
|
-
|
|
282
|
+
Providers are the core of this library. It ships with **four integrated
|
|
283
|
+
providers**, and you can add your own.
|
|
368
284
|
|
|
369
|
-
|
|
285
|
+
### `package-json`
|
|
370
286
|
|
|
371
|
-
|
|
287
|
+
Loads project info from your `package.json` (`version`, `project`, `name`,
|
|
288
|
+
`title`, `description`) into `ENV`, `VERSION`, `PROJECT`, `NAME`, `TITLE`,
|
|
289
|
+
`DESCRIPTION`.
|
|
372
290
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
{
|
|
377
|
-
"version": "1.0.0",
|
|
378
|
-
"project": "project-name",
|
|
379
|
-
"name": "@package-name",
|
|
380
|
-
"title": "app-name",
|
|
381
|
-
"description": "any description"
|
|
382
|
-
}
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
| Option | Description | Type | Default | Required? |
|
|
386
|
-
| ------------------- | --------------------------- | -------- | ------- | --------- |
|
|
387
|
-
| `--vp, --varPrefix` | Prefix for loaded variables | `string` | `""` | No |
|
|
388
|
-
|
|
389
|
-
Examples:
|
|
291
|
+
| Option | Description | Type | Default |
|
|
292
|
+
| ------------------- | ------------------------------- | -------- | ------- |
|
|
293
|
+
| `--vp, --varPrefix` | Prefix for the loaded variables | `string` | `""` |
|
|
390
294
|
|
|
391
295
|
```bash
|
|
392
|
-
|
|
296
|
+
# i.e. expose them as REACT_APP_* for CRA
|
|
297
|
+
> env -e dev -m build : react-scripts build : --vp REACT_APP_
|
|
393
298
|
```
|
|
394
299
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
- ## **`app-settings`**
|
|
398
|
-
|
|
399
|
-
Non secrets loader for `appsettings.json`.
|
|
300
|
+
### `app-settings`
|
|
400
301
|
|
|
401
|
-
`appsettings.json
|
|
302
|
+
Non-secret loader for `appsettings.json`, organized by sections:
|
|
402
303
|
|
|
403
|
-
```
|
|
304
|
+
```jsonc
|
|
404
305
|
{
|
|
405
|
-
"|DEFAULT|": {},
|
|
406
|
-
"|MODE|": {},
|
|
407
|
-
"|ENV|": {}
|
|
408
|
-
}
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
In example:
|
|
412
|
-
|
|
413
|
-
```json
|
|
414
|
-
{
|
|
415
|
-
"|DEFAULT|": {
|
|
416
|
-
"VAR1": "v1_default"
|
|
417
|
-
},
|
|
306
|
+
"|DEFAULT|": { "VAR1": "v1_default" },
|
|
418
307
|
"|MODE|": {
|
|
419
|
-
"build": {
|
|
420
|
-
|
|
421
|
-
},
|
|
422
|
-
"debug": {
|
|
423
|
-
"NODE_ENV": "development"
|
|
424
|
-
},
|
|
425
|
-
"test": {
|
|
426
|
-
"NODE_ENV": "test"
|
|
427
|
-
}
|
|
308
|
+
"build": { "NODE_ENV": "production" },
|
|
309
|
+
"debug": { "NODE_ENV": "development" },
|
|
428
310
|
},
|
|
429
311
|
"|ENV|": {
|
|
430
312
|
"dev": {
|
|
431
313
|
"C1": "V1",
|
|
432
|
-
"
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
"VAR2": "G1V2",
|
|
437
|
-
"VAR3": true,
|
|
438
|
-
"GROUP2": {
|
|
439
|
-
"VAR1": "G1G2V1"
|
|
440
|
-
}
|
|
441
|
-
},
|
|
442
|
-
"C4": "23"
|
|
443
|
-
}
|
|
444
|
-
}
|
|
314
|
+
"GROUP1": { "VAR2": "G1V2", "GROUP2": { "VAR1": "G1G2V1" } },
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
"|LOCAL|": { "dev": { "LOCAL_VAR": "only-local" } },
|
|
445
318
|
}
|
|
446
319
|
```
|
|
447
320
|
|
|
448
|
-
| Option | Description
|
|
449
|
-
| ----------------- |
|
|
450
|
-
| `--ef, --envFile` |
|
|
321
|
+
| Option | Description | Type | Default |
|
|
322
|
+
| ----------------- | ----------------------------- | -------- | --------------------------- |
|
|
323
|
+
| `--ef, --envFile` | Non-secret settings file path | `string` | `[[root]]/appsettings.json` |
|
|
451
324
|
|
|
452
|
-
|
|
325
|
+
### `secrets`
|
|
453
326
|
|
|
454
|
-
-
|
|
327
|
+
Loads secret variables from a per-environment JSON file
|
|
328
|
+
(`[[root]]/[[env]].env.json`). Keep this file out of version control.
|
|
455
329
|
|
|
456
|
-
|
|
330
|
+
| Option | Description | Type | Default |
|
|
331
|
+
| --------------------- | -------------------------- | -------- | --------------------------- |
|
|
332
|
+
| `--sf, --secretsFile` | Secret variables file path | `string` | `[[root]]/[[env]].env.json` |
|
|
457
333
|
|
|
458
|
-
|
|
459
|
-
| --------------------- | -------------------------- | -------- | --------------------------- | --------- |
|
|
460
|
-
| `--sf, --secretsFile` | Secret variables file path | `string` | `[[root]]/[[env]].env.json` | No |
|
|
334
|
+
### `local`
|
|
461
335
|
|
|
462
|
-
-
|
|
336
|
+
Loads local-only variables (never loaded in `--ci`). The file is auto-created
|
|
337
|
+
if missing.
|
|
463
338
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
|
467
|
-
| ------------------- | ------------------------- | -------- | --------------------------------- | --------- |
|
|
468
|
-
| `--lf, --localFile` | Local variables file path | `string` | `[[root]]/[[env]].local.env.json` | No |
|
|
339
|
+
| Option | Description | Type | Default |
|
|
340
|
+
| ------------------- | ------------------------- | -------- | --------------------------------- |
|
|
341
|
+
| `--lf, --localFile` | Local variables file path | `string` | `[[root]]/[[env]].local.env.json` |
|
|
469
342
|
|
|
470
343
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
|
471
344
|
|
|
472
345
|
<!-- CUSTOM PROVIDERS -->
|
|
473
346
|
|
|
474
|
-
##
|
|
475
|
-
|
|
476
|
-
You can create your custom providers, in two ways:
|
|
347
|
+
## ✒️ Creating custom providers
|
|
477
348
|
|
|
478
|
-
|
|
479
|
-
- **NPM Package**: you must create your custom NPM library and export by default your "provider" using standard interface exported by this lib.
|
|
349
|
+
Create a provider in two ways:
|
|
480
350
|
|
|
481
|
-
|
|
351
|
+
- **Local script** — a `.js` file that `export default`s your provider.
|
|
352
|
+
- **NPM package** — a published module that `export default`s your provider.
|
|
482
353
|
|
|
483
|
-
|
|
354
|
+
Both are wired in the [config file](#-config) via the `providers` list. A custom
|
|
355
|
+
provider can also implement `pull`/`push` to fetch and publish variables from a
|
|
356
|
+
remote store (i.e. a vault, a secrets manager or an API).
|
|
484
357
|
|
|
485
358
|
```typescript
|
|
486
|
-
import { CommandArguments, EnvProvider } from '@calvear/env';
|
|
359
|
+
import type { CommandArguments, EnvProvider } from '@calvear/env';
|
|
487
360
|
import { logger, readJson, writeJson } from '@calvear/env/utils';
|
|
488
361
|
|
|
489
362
|
const KEY = 'my-unique-provider-key';
|
|
490
363
|
|
|
491
|
-
interface
|
|
364
|
+
interface MyProviderArguments extends CommandArguments {
|
|
492
365
|
anyExtraOption: boolean;
|
|
493
366
|
}
|
|
494
367
|
|
|
495
|
-
|
|
496
|
-
// unique identifier
|
|
368
|
+
const MyProvider: EnvProvider<MyProviderArguments> = {
|
|
369
|
+
// unique identifier
|
|
497
370
|
key: KEY,
|
|
498
371
|
|
|
499
|
-
// (optional)
|
|
500
|
-
// to commands using yargs for builder
|
|
372
|
+
// (optional) add custom options to the CLI via yargs
|
|
501
373
|
builder: (builder) => {
|
|
502
374
|
builder.options({
|
|
503
375
|
anyExtraOption: {
|
|
@@ -510,126 +382,194 @@ export const MyProvider: EnvProvider<MyProviderCommandArguments> = {
|
|
|
510
382
|
});
|
|
511
383
|
},
|
|
512
384
|
|
|
513
|
-
//
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
NODE_ENV: 'development',
|
|
519
|
-
};
|
|
520
|
-
|
|
521
|
-
// you can return a list of JSON environment variables for merge
|
|
522
|
-
return [
|
|
523
|
-
{
|
|
524
|
-
NODE_ENV: 'production',
|
|
525
|
-
ANY_VAR: 'ABC', // will be replaced by value below
|
|
526
|
-
},
|
|
527
|
-
{
|
|
528
|
-
ANY_VAR: 'ANY_VALUE',
|
|
529
|
-
ANY_GROUP: {
|
|
530
|
-
INNER_VAR: 12,
|
|
531
|
-
},
|
|
532
|
-
},
|
|
533
|
-
];
|
|
385
|
+
// called on load — may be sync or async, and may return a list to merge
|
|
386
|
+
load: ({ env }) => {
|
|
387
|
+
if (env === 'dev') return { NODE_ENV: 'development' };
|
|
388
|
+
|
|
389
|
+
return [{ NODE_ENV: 'production' }, { ANY_GROUP: { INNER_VAR: 12 } }];
|
|
534
390
|
},
|
|
535
391
|
|
|
536
|
-
// (optional)
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
// anyway you want for pulling variables to cache
|
|
392
|
+
// (optional) called on `env pull`
|
|
393
|
+
pull: (argv, config) => {
|
|
394
|
+
/* fetch variables into your local cache */
|
|
540
395
|
},
|
|
541
396
|
|
|
542
|
-
// (optional)
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
// anyway you should do for pushing or updating your variables
|
|
397
|
+
// (optional) called on `env push`
|
|
398
|
+
push: (argv, config) => {
|
|
399
|
+
/* publish/update your variables */
|
|
546
400
|
},
|
|
547
401
|
};
|
|
402
|
+
|
|
403
|
+
export default MyProvider;
|
|
548
404
|
```
|
|
549
405
|
|
|
550
406
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
|
551
407
|
|
|
552
408
|
<!-- CONFIG -->
|
|
553
409
|
|
|
554
|
-
## 📥
|
|
410
|
+
## 📥 Config
|
|
555
411
|
|
|
556
|
-
|
|
412
|
+
Any CLI argument can be set in your config file
|
|
413
|
+
(`[[root]]/settings/settings.json` by default), but it is mainly used to declare
|
|
414
|
+
**providers**:
|
|
557
415
|
|
|
558
|
-
```
|
|
416
|
+
```jsonc
|
|
559
417
|
{
|
|
560
|
-
"
|
|
561
|
-
//
|
|
562
|
-
"logMaskValuesOfKeys": ["SECRET", "
|
|
563
|
-
|
|
418
|
+
"logLevel": "silly",
|
|
419
|
+
// mask secrets in the debug output (see the Masking section)
|
|
420
|
+
"logMaskValuesOfKeys": ["SECRET", "/token/i", "/api_key/i"],
|
|
421
|
+
"logMaskAnyRegEx": ["AKIA[0-9A-Z]{16}"],
|
|
564
422
|
"providers": [
|
|
565
|
-
{
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
},
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
},
|
|
573
|
-
|
|
574
|
-
"path": "secrets",
|
|
575
|
-
"type": "integrated"
|
|
576
|
-
},
|
|
577
|
-
{
|
|
578
|
-
"path": "local",
|
|
579
|
-
"type": "integrated"
|
|
580
|
-
},
|
|
581
|
-
{
|
|
582
|
-
// custom NPM package
|
|
583
|
-
"path": "@npm-package",
|
|
584
|
-
"type": "module",
|
|
585
|
-
"config": {
|
|
586
|
-
"any-config": "any value"
|
|
587
|
-
}
|
|
588
|
-
},
|
|
589
|
-
{
|
|
590
|
-
// custom script inside project
|
|
591
|
-
"path": "scripts/custom-loader.js",
|
|
592
|
-
"type": "script"
|
|
593
|
-
}
|
|
594
|
-
]
|
|
423
|
+
{ "path": "package-json" },
|
|
424
|
+
{ "path": "app-settings" },
|
|
425
|
+
{ "path": "secrets" },
|
|
426
|
+
{ "path": "local" },
|
|
427
|
+
// custom NPM package
|
|
428
|
+
{ "path": "@my-scope/my-provider", "type": "module", "config": {} },
|
|
429
|
+
// custom local script
|
|
430
|
+
{ "path": "scripts/custom-loader.js", "type": "script" },
|
|
431
|
+
],
|
|
595
432
|
}
|
|
596
433
|
```
|
|
597
434
|
|
|
598
|
-
|
|
435
|
+
> **Provider order matters** — providers are merged in declaration order, so
|
|
436
|
+
> later providers override earlier ones (`package-json` is the base, `local`
|
|
437
|
+
> wins).
|
|
438
|
+
|
|
439
|
+
<p align="right">(<a href="#top">back to top</a>)</p>
|
|
440
|
+
|
|
441
|
+
<!-- SHARED / NESTED -->
|
|
442
|
+
|
|
443
|
+
## 🪆 Nested & global keys
|
|
599
444
|
|
|
600
|
-
|
|
445
|
+
Organize variables in nested objects. They are **flattened** into `process.env`
|
|
446
|
+
using the nesting delimiter (`__` by default):
|
|
601
447
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
448
|
+
```jsonc
|
|
449
|
+
{
|
|
450
|
+
"GROUP1": {
|
|
451
|
+
"VAR": "anyValue1",
|
|
452
|
+
"GROUP2": { "VAR": "anyValue2" },
|
|
453
|
+
},
|
|
454
|
+
"VAR3": "anyValue3",
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
```javascript
|
|
459
|
+
process.env.GROUP1__VAR; // "anyValue1"
|
|
460
|
+
process.env.GROUP1__GROUP2__VAR; // "anyValue2"
|
|
461
|
+
process.env.VAR3; // "anyValue3"
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### `$` global marker
|
|
465
|
+
|
|
466
|
+
Prefix a key with `$` to mark it as **global/shared** — relevant for the
|
|
467
|
+
`secrets` provider, which uses the marker to scope the secret across the project
|
|
468
|
+
rather than per-mode. The marker is **stripped on injection** at any nesting
|
|
469
|
+
depth, while the group prefix is **kept**:
|
|
470
|
+
|
|
471
|
+
```jsonc
|
|
472
|
+
{
|
|
473
|
+
"$TOKEN": "rootValue",
|
|
474
|
+
"GROUP1": {
|
|
475
|
+
"$SHARED": "groupValue",
|
|
476
|
+
"VAR": "anyValue",
|
|
477
|
+
},
|
|
478
|
+
}
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
```javascript
|
|
482
|
+
// the `$` is removed; the nesting prefix is preserved
|
|
483
|
+
process.env.TOKEN; // "rootValue" (was $TOKEN)
|
|
484
|
+
process.env.GROUP1__SHARED; // "groupValue" (was GROUP1.$SHARED)
|
|
485
|
+
process.env.GROUP1__VAR; // "anyValue"
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
> The `$` is removed only from the **process environment** and from JSON Schema
|
|
489
|
+
> validation keys. It is **preserved** in the secrets file storage, so the
|
|
490
|
+
> `secrets` provider round-trips the global marker intact.
|
|
491
|
+
>
|
|
492
|
+
> Skip a key entirely (never injected) by prefixing it with `#`.
|
|
493
|
+
|
|
494
|
+
### Priority (lowest → highest)
|
|
495
|
+
|
|
496
|
+
1. `package-json` info
|
|
497
|
+
2. `appsettings.json` (`app-settings`)
|
|
498
|
+
3. `<env>.env.json` (`secrets`)
|
|
499
|
+
4. `<env>.local.env.json` (`local`, skipped in `--ci`)
|
|
615
500
|
|
|
616
501
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
|
617
502
|
|
|
618
|
-
|
|
503
|
+
<!-- MASKING -->
|
|
504
|
+
|
|
505
|
+
## 🙈 Masking secrets
|
|
506
|
+
|
|
507
|
+
When the resolved environment is rendered (at `--log debug`) and when objects
|
|
508
|
+
are logged, secrets are masked as `*****`. There are two complementary
|
|
509
|
+
mechanisms, configurable via CLI flags or the [config file](#-config):
|
|
619
510
|
|
|
620
|
-
|
|
511
|
+
### By key — `logMaskValuesOfKeys` (`--mvk`)
|
|
621
512
|
|
|
622
|
-
|
|
513
|
+
Masks a variable's **whole value** when its **key** matches. Each entry is
|
|
514
|
+
either an **exact key name** (case-insensitive) or a `/source/flags` **regex**
|
|
515
|
+
matched against the key:
|
|
623
516
|
|
|
624
|
-
|
|
517
|
+
```jsonc
|
|
518
|
+
{
|
|
519
|
+
"logMaskValuesOfKeys": [
|
|
520
|
+
"PASSWORD", // exact key (case-insensitive)
|
|
521
|
+
"/token/i", // any key containing "token"
|
|
522
|
+
"/_secret$/i", // any key ending in "_secret"
|
|
523
|
+
],
|
|
524
|
+
}
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
```bash
|
|
528
|
+
# same, via CLI flag
|
|
529
|
+
> env -e dev --log debug --mvk PASSWORD "/token/i" : node app.js
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### By value content — `logMaskAnyRegEx` (`--mrx`)
|
|
533
|
+
|
|
534
|
+
Masks **only the matching portion** of any string value, wherever it appears.
|
|
535
|
+
The global flag is always forced, so **every** occurrence is masked; use the
|
|
536
|
+
`/source/flags` form for extra flags such as `i`:
|
|
537
|
+
|
|
538
|
+
```jsonc
|
|
539
|
+
{
|
|
540
|
+
"logMaskAnyRegEx": [
|
|
541
|
+
"AKIA[0-9A-Z]{16}", // AWS access key ids
|
|
542
|
+
"/bearer .+/i", // bearer tokens (case-insensitive)
|
|
543
|
+
],
|
|
544
|
+
}
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
| Goal | Use |
|
|
548
|
+
| --------------------------------------------------- | --------------------- |
|
|
549
|
+
| Know the **key** of the secret | `logMaskValuesOfKeys` |
|
|
550
|
+
| Know the **shape** of the secret (token, key, RUT…) | `logMaskAnyRegEx` |
|
|
551
|
+
|
|
552
|
+
> In JSON the backslash must be escaped: write `\\d` for `\d`. Neither mechanism
|
|
553
|
+
> masks the variable **name** — keys are always shown. Masking only affects the
|
|
554
|
+
> output; the real (unmasked) values are still injected into `process.env`.
|
|
625
555
|
|
|
626
556
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
|
627
557
|
|
|
628
|
-
<!--
|
|
558
|
+
<!-- SCRIPTS -->
|
|
629
559
|
|
|
630
|
-
##
|
|
560
|
+
## 🧰 Development scripts
|
|
631
561
|
|
|
632
|
-
|
|
562
|
+
| Script | Description |
|
|
563
|
+
| -------------------- | ------------------------------------------------- |
|
|
564
|
+
| `pnpm build` | Build the library (Vite, ESM) into `dist/` |
|
|
565
|
+
| `pnpm test` | Run unit tests (Vitest) |
|
|
566
|
+
| `pnpm test:cov` | Run unit tests with coverage (100% threshold) |
|
|
567
|
+
| `pnpm test:int` | Run integration tests against the built binary |
|
|
568
|
+
| `pnpm typecheck` | Type-check with `tsc --noEmit` |
|
|
569
|
+
| `pnpm lint` | Lint with ESLint (flat config) |
|
|
570
|
+
| `pnpm format` | Format with Prettier |
|
|
571
|
+
| `pnpm run pub` | Gate + build + publish to npm (`latest`) |
|
|
572
|
+
| `pnpm run pub:alpha` | Gate + build + publish a prerelease (`alpha` tag) |
|
|
633
573
|
|
|
634
574
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
|
635
575
|
|
|
@@ -637,14 +577,13 @@ For last changes see [CHANGELOG.md](CHANGELOG.md) file for details.
|
|
|
637
577
|
|
|
638
578
|
## 🛠️ Built with
|
|
639
579
|
|
|
640
|
-
- [yargs](http://yargs.js.org/)
|
|
641
|
-
- [
|
|
642
|
-
- [
|
|
643
|
-
- [
|
|
644
|
-
- [
|
|
645
|
-
- [
|
|
646
|
-
- [
|
|
647
|
-
- [vite](https://vite.dev/) + [vitest](https://vitest.dev/) (build & test)
|
|
580
|
+
- [yargs](http://yargs.js.org/) — CLI argument parsing
|
|
581
|
+
- [ajv](https://ajv.js.org/) + [to-json-schema](https://www.npmjs.com/package/to-json-schema) — JSON Schema
|
|
582
|
+
- [tslog](https://tslog.js.org/#/) — logging
|
|
583
|
+
- [picocolors](https://github.com/alexeyraspopov/picocolors) — terminal colors
|
|
584
|
+
- [subslate](https://github.com/josh-hemphill/subslate) — interpolation
|
|
585
|
+
- [merge-deep](https://github.com/jonschlinkert/merge-deep) — deep merge
|
|
586
|
+
- [Vite](https://vite.dev/) — build · [Vitest](https://vitest.dev/) — testing
|
|
648
587
|
|
|
649
588
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
|
650
589
|
|
|
@@ -652,10 +591,13 @@ For last changes see [CHANGELOG.md](CHANGELOG.md) file for details.
|
|
|
652
591
|
|
|
653
592
|
## 📄 License
|
|
654
593
|
|
|
655
|
-
This project is licensed under the MIT License
|
|
594
|
+
This project is licensed under the **MIT License** — see [LICENSE.md](LICENSE.md)
|
|
595
|
+
for details.
|
|
656
596
|
|
|
657
597
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
|
658
598
|
|
|
659
599
|
---
|
|
660
600
|
|
|
661
|
-
|
|
601
|
+
<p align="center">
|
|
602
|
+
⌨ with ❤️ by <a href="https://github.com/calvear93">Alvear Candia, Cristopher Alejandro</a>
|
|
603
|
+
</p>
|