node-vault-client 1.0.1 → 2.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/LICENSE.txt +200 -200
- package/README.md +337 -154
- package/package.json +64 -44
- package/src/Lease.js +57 -57
- package/src/VaultApiClient.js +94 -55
- package/src/VaultClient.js +288 -263
- package/src/VaultNodeConfig.js +104 -105
- package/src/auth/AuthToken.js +141 -94
- package/src/auth/VaultAppRoleAuth.js +49 -40
- package/src/auth/VaultBaseAuth.js +162 -140
- package/src/auth/VaultIAMAuth.js +212 -187
- package/src/auth/VaultKubernetesAuth.js +49 -48
- package/src/auth/VaultTokenAuth.js +35 -34
- package/src/errors.js +21 -21
package/README.md
CHANGED
|
@@ -1,154 +1,337 @@
|
|
|
1
|
-
# Node.js Vault Client
|
|
2
|
-
|
|
3
|
-
[](https://github.com/namecheap/node-vault-client/actions/workflows/pipeline.yaml)
|
|
4
|
+
[](https://www.npmjs.com/package/node-vault-client)
|
|
5
|
+
[](https://www.npmjs.com/package/node-vault-client)
|
|
6
|
+
[](https://github.com/namecheap/node-vault-client/blob/master/LICENSE.txt)
|
|
7
|
+
[](https://libraries.io/npm/node-vault-client/)
|
|
8
|
+
|
|
9
|
+
A Vault Client implemented in pure javascript for [HashiCorp Vault](https://github.com/hashicorp/vault).
|
|
10
|
+
It supports variety of Auth Backends and performs lease renewal for issued auth token.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
```
|
|
14
|
+
npm install --save node-vault-client
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Requirements
|
|
18
|
+
|
|
19
|
+
Node.js >= 18 — the client uses the native `fetch` API.
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
const VaultClient = require('node-vault-client');
|
|
25
|
+
|
|
26
|
+
const vaultClient = VaultClient.boot('main', {
|
|
27
|
+
api: { url: 'https://vault.example.com:8200/' },
|
|
28
|
+
auth: {
|
|
29
|
+
type: 'appRole', // one of: 'appRole' | 'token' | 'iam' | 'kubernetes'
|
|
30
|
+
config: { role_id: '637c065f-c644-5e12-d3d1-e9fa4363af61' }
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
vaultClient.read('secret/tst').then(lease => {
|
|
35
|
+
console.log(lease.getData()); // read() resolves to a Lease; use getData()/getValue(key)
|
|
36
|
+
}).catch(e => console.error(e));
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Supported Auth Backends
|
|
40
|
+
|
|
41
|
+
* [AWS IAM](https://developer.hashicorp.com/vault/docs/auth/aws)
|
|
42
|
+
* [AppRole](https://developer.hashicorp.com/vault/docs/auth/approle)
|
|
43
|
+
* [Token](https://developer.hashicorp.com/vault/docs/auth/token)
|
|
44
|
+
* [Kubernetes](https://developer.hashicorp.com/vault/docs/auth/kubernetes)
|
|
45
|
+
|
|
46
|
+
### AWS IAM auth
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
const vaultClient = VaultClient.boot('main', {
|
|
50
|
+
api: { url: 'https://vault.example.com:8200/' },
|
|
51
|
+
auth: {
|
|
52
|
+
type: 'iam',
|
|
53
|
+
mount: 'aws', // Optional. Vault AWS auth mount point ("aws" by default)
|
|
54
|
+
config: {
|
|
55
|
+
role: 'my_iam_role',
|
|
56
|
+
iam_server_id_header_value: 'https://vault.example.com:8200/', // Optional. X-Vault-AWS-IAM-Server-ID header
|
|
57
|
+
namespace: 'some_namespace', // Optional. X-Vault-Namespace header
|
|
58
|
+
region: 'eu-central-1', // Optional. AWS STS region (see below)
|
|
59
|
+
credentials: { // Optional. Resolved from the AWS provider chain when omitted
|
|
60
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
61
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### `region`
|
|
69
|
+
|
|
70
|
+
By default the signed `GetCallerIdentity` request targets the global STS endpoint
|
|
71
|
+
`sts.amazonaws.com` and the SigV4 credential scope is bound to `us-east-1`. Set
|
|
72
|
+
`config.region` to sign against a regional STS endpoint instead — the request is then sent to
|
|
73
|
+
`sts.<region>.amazonaws.com` and the signature scope is bound to that region. This is required
|
|
74
|
+
when Vault's `sts_region` / `sts_endpoint` is configured for a non-`us-east-1` region (e.g.
|
|
75
|
+
`eu-central-1`); otherwise STS rejects the replayed request with
|
|
76
|
+
`SignatureDoesNotMatch — Credential should be scoped to a valid region`. Omitting `region`
|
|
77
|
+
preserves the previous (global-endpoint) behavior.
|
|
78
|
+
|
|
79
|
+
### AppRole auth
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
const vaultClient = VaultClient.boot('main', {
|
|
83
|
+
api: { url: 'https://vault.example.com:8200/' },
|
|
84
|
+
auth: {
|
|
85
|
+
type: 'appRole',
|
|
86
|
+
mount: 'approle', // Optional. Vault AppRole auth mount point ("approle" by default)
|
|
87
|
+
config: {
|
|
88
|
+
role_id: '637c065f-c644-5e12-d3d1-e9fa4363af61', // Required. RoleID of the AppRole
|
|
89
|
+
secret_id: '...', // Optional. Required when bind_secret_id is enabled
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Token auth
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
const vaultClient = VaultClient.boot('main', {
|
|
99
|
+
api: { url: 'https://vault.example.com:8200/' },
|
|
100
|
+
auth: {
|
|
101
|
+
type: 'token',
|
|
102
|
+
mount: 'token', // Optional. Vault token auth mount point ("token" by default)
|
|
103
|
+
config: {
|
|
104
|
+
token: 's.xxxxxxxxxxxxxxxxxxxxxxxx', // Required. Vault token
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Kubernetes auth
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
const vaultClient = VaultClient.boot('main', {
|
|
114
|
+
api: { url: 'https://vault.example.com:8200/' },
|
|
115
|
+
auth: {
|
|
116
|
+
type: 'kubernetes',
|
|
117
|
+
mount: 'kubernetes', // Optional. Vault Kubernetes auth mount point ("kubernetes" by default)
|
|
118
|
+
config: {
|
|
119
|
+
role: 'my_k8s_role', // Required. Role configured in the Vault Kubernetes auth backend
|
|
120
|
+
tokenPath: '/var/run/secrets/kubernetes.io/serviceaccount/token', // Optional. Defaults to the in-pod service-account token path
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## API
|
|
127
|
+
|
|
128
|
+
<a name="VaultClient"></a>
|
|
129
|
+
|
|
130
|
+
### VaultClient
|
|
131
|
+
|
|
132
|
+
* [VaultClient](#VaultClient)
|
|
133
|
+
* [new VaultClient(options)](#new_VaultClient_new)
|
|
134
|
+
* _instance_
|
|
135
|
+
* [.fillNodeConfig()](#VaultClient+fillNodeConfig)
|
|
136
|
+
* [.read(path)](#VaultClient+read) ⇒ <code>Promise.<Lease></code>
|
|
137
|
+
* [.list(path)](#VaultClient+list) ⇒ <code>Promise.<Lease></code>
|
|
138
|
+
* [.write(path, data)](#VaultClient+write) ⇒ <code>Promise.<Object></code>
|
|
139
|
+
* [.close()](#VaultClient+close)
|
|
140
|
+
* _static_
|
|
141
|
+
* [.boot(name, [options])](#VaultClient.boot) ⇒ <code>VaultClient</code>
|
|
142
|
+
* [.get(name)](#VaultClient.get) ⇒ <code>VaultClient</code>
|
|
143
|
+
* [.clear([name])](#VaultClient.clear)
|
|
144
|
+
* [Lease](#Lease)
|
|
145
|
+
|
|
146
|
+
<a name="new_VaultClient_new"></a>
|
|
147
|
+
|
|
148
|
+
#### new VaultClient(options)
|
|
149
|
+
Client constructor function.
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
| Param | Type | Default | Description |
|
|
153
|
+
| --- | --- | --- | --- |
|
|
154
|
+
| options | `Object` | | |
|
|
155
|
+
| options.api | <code>Object</code> | | |
|
|
156
|
+
| options.api.url | <code>String</code> | | the url of the vault server |
|
|
157
|
+
| [options.api.apiVersion] | <code>String</code> | `v1` | |
|
|
158
|
+
| [options.api.requestOptions] | <code>Object</code> | | extra options merged into every HTTP request (see [Custom transport](#custom-transport-proxy--self-signed-tls)) |
|
|
159
|
+
| options.auth | <code>Object</code> | | |
|
|
160
|
+
| options.auth.type | <code>String</code> | | |
|
|
161
|
+
| [options.auth.mount] | <code>String</code> | | Vault auth backend mount point; default varies per method (e.g. "aws" for iam, "approle", "token", "kubernetes") |
|
|
162
|
+
| options.auth.config | <code>Object</code> | | auth configuration variables |
|
|
163
|
+
| [options.auth.config.namespace] | <code>String</code> | | Optional. Vault namespace, sent as the `X-Vault-Namespace` header on all secret read/list/write requests. Applies to every auth type, not just IAM. |
|
|
164
|
+
| options.logger | <code>Object</code> | `false` | | Logger that supports "error", "info", "warn", "trace", "debug" methods. Uses `console` by default. Pass `false` to disable logging. |
|
|
165
|
+
|
|
166
|
+
##### Custom transport (proxy / self-signed TLS)
|
|
167
|
+
|
|
168
|
+
`options.api.requestOptions` is shallow-merged into every underlying `fetch()` call, so you
|
|
169
|
+
can route traffic through a proxy/SOCKS agent or trust a self-signed / internal-CA Vault.
|
|
170
|
+
Pass an [undici](https://undici.nodejs.org/) `dispatcher` (request semantics like `method`
|
|
171
|
+
and `body` always win; `headers` are merged with per-request headers taking precedence):
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
const { Agent, ProxyAgent } = require('undici');
|
|
175
|
+
|
|
176
|
+
// Trust an internal/self-signed CA (preferred over disabling verification)
|
|
177
|
+
const vaultClient = VaultClient.boot('main', {
|
|
178
|
+
api: {
|
|
179
|
+
url: 'https://vault.internal:8200/',
|
|
180
|
+
requestOptions: {
|
|
181
|
+
dispatcher: new Agent({ connect: { ca: require('fs').readFileSync('/etc/ssl/internal-ca.pem') } }),
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
auth: { type: 'token', config: { token: '...' } },
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Route through an HTTP proxy / SOCKS agent
|
|
188
|
+
const proxied = VaultClient.boot('proxied', {
|
|
189
|
+
api: { url: 'https://vault.example.com:8200/', requestOptions: { dispatcher: new ProxyAgent('http://proxy:8080') } },
|
|
190
|
+
auth: { type: 'token', config: { token: '...' } },
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
For the self-signed-CA case you can also use the process-wide `NODE_EXTRA_CA_CERTS=/path/ca.pem`
|
|
195
|
+
env var with no code change. Only disable verification
|
|
196
|
+
(`new Agent({ connect: { rejectUnauthorized: false } })`) in throwaway/dev setups — it removes
|
|
197
|
+
MITM protection.
|
|
198
|
+
|
|
199
|
+
#### vaultClient.fillNodeConfig() ⇒ <code>Promise</code>
|
|
200
|
+
Populates Vault's values to NPM "config" module
|
|
201
|
+
|
|
202
|
+
Resolves once the npm `config` module has been populated from Vault.
|
|
203
|
+
|
|
204
|
+
**Kind**: instance method of [<code>VaultClient</code>](#VaultClient)
|
|
205
|
+
<a name="VaultClient+read"></a>
|
|
206
|
+
|
|
207
|
+
#### vaultClient.read(path) ⇒ <code>Promise.<Lease></code>
|
|
208
|
+
Read secret from Vault
|
|
209
|
+
|
|
210
|
+
**Kind**: instance method of [<code>VaultClient</code>](#VaultClient)
|
|
211
|
+
|
|
212
|
+
| Param | Type | Description |
|
|
213
|
+
| --- | --- | --- |
|
|
214
|
+
| path | <code>string</code> | path to the secret |
|
|
215
|
+
|
|
216
|
+
<a name="VaultClient+list"></a>
|
|
217
|
+
|
|
218
|
+
#### vaultClient.list(path) ⇒ <code>Promise.<Lease></code>
|
|
219
|
+
Retrieves secrets list
|
|
220
|
+
|
|
221
|
+
**Kind**: instance method of [<code>VaultClient</code>](#VaultClient)
|
|
222
|
+
|
|
223
|
+
| Param | Type | Description |
|
|
224
|
+
| --- | --- | --- |
|
|
225
|
+
| path | <code>string</code> | path to the secret |
|
|
226
|
+
|
|
227
|
+
<a name="VaultClient+write"></a>
|
|
228
|
+
|
|
229
|
+
#### vaultClient.write(path, data) ⇒ <code>Promise.<Object></code>
|
|
230
|
+
Writes data to Vault
|
|
231
|
+
|
|
232
|
+
Resolves to the raw parsed Vault response body, which may be empty/undefined for
|
|
233
|
+
`204 No Content` responses.
|
|
234
|
+
|
|
235
|
+
**Kind**: instance method of [<code>VaultClient</code>](#VaultClient)
|
|
236
|
+
|
|
237
|
+
| Param | Type | Description |
|
|
238
|
+
| --- | --- | --- |
|
|
239
|
+
| path | | path used to write data |
|
|
240
|
+
| data | <code>object</code> | data to write |
|
|
241
|
+
|
|
242
|
+
<a name="VaultClient+close"></a>
|
|
243
|
+
|
|
244
|
+
#### vaultClient.close()
|
|
245
|
+
Release resources held by this client.
|
|
246
|
+
|
|
247
|
+
This client performs lease renewal for renewable auth tokens by arming a background timer.
|
|
248
|
+
That timer keeps the Node.js event loop alive, so a short-lived script (e.g. a one-off
|
|
249
|
+
`read`) never exits on its own. Call `close()` once you are done with the client to cancel
|
|
250
|
+
the timer and let the process exit. It is null-safe and safe to call multiple times. The
|
|
251
|
+
client may still be used afterwards — the next operation that fetches a renewable token
|
|
252
|
+
will arm a new refresh timer.
|
|
253
|
+
|
|
254
|
+
```javascript
|
|
255
|
+
const vaultClient = VaultClient.boot('main', { /* ... */ });
|
|
256
|
+
const secret = await vaultClient.read('secret/tst');
|
|
257
|
+
console.log(secret);
|
|
258
|
+
vaultClient.close(); // process can now exit
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Kind**: instance method of [<code>VaultClient</code>](#VaultClient)
|
|
262
|
+
|
|
263
|
+
<a name="Lease"></a>
|
|
264
|
+
|
|
265
|
+
### Lease
|
|
266
|
+
|
|
267
|
+
The object returned by `read()` and `list()` (they resolve to `Promise<Lease>`). Use its
|
|
268
|
+
accessors to extract the secret data:
|
|
269
|
+
|
|
270
|
+
* `getValue(key)` ⇒ <code>String</code> — value for a single key. Throws `Requested key does not exist` when the key is absent.
|
|
271
|
+
* `getData()` ⇒ <code>Object</code> — a deep-cloned copy of the whole secret data object.
|
|
272
|
+
* `isRenewable()` ⇒ <code>boolean</code> — whether the underlying lease is renewable.
|
|
273
|
+
|
|
274
|
+
<a name="VaultClient.boot"></a>
|
|
275
|
+
|
|
276
|
+
#### VaultClient.boot(name, [options]) ⇒ <code>VaultClient</code>
|
|
277
|
+
Boot an instance of Vault
|
|
278
|
+
|
|
279
|
+
The instance will be stored in a local hash. Calling Vault.boot multiple
|
|
280
|
+
times with the same name will return the same instance.
|
|
281
|
+
|
|
282
|
+
**Kind**: static method of [<code>VaultClient</code>](#VaultClient)
|
|
283
|
+
**Returns**: <code>VaultClient</code>
|
|
284
|
+
|
|
285
|
+
| Param | Type | Description |
|
|
286
|
+
| --- | --- | --- |
|
|
287
|
+
| name | <code>String</code> | Vault instance name |
|
|
288
|
+
| [options] | <code>Object</code> | options for [Vault#constructor](#new_VaultClient_new). |
|
|
289
|
+
|
|
290
|
+
<a name="VaultClient.get"></a>
|
|
291
|
+
|
|
292
|
+
#### VaultClient.get(name) ⇒ <code>VaultClient</code>
|
|
293
|
+
Get an instance of Vault
|
|
294
|
+
|
|
295
|
+
The instance will be stored in a local hash. Calling Vault.pop multiple
|
|
296
|
+
times with the same name will return the same instance.
|
|
297
|
+
|
|
298
|
+
**Kind**: static method of [<code>VaultClient</code>](#VaultClient)
|
|
299
|
+
**Returns**: <code>VaultClient</code>
|
|
300
|
+
|
|
301
|
+
| Param | Type | Description |
|
|
302
|
+
| --- | --- | --- |
|
|
303
|
+
| name | <code>String</code> | Vault instance name |
|
|
304
|
+
|
|
305
|
+
<a name="VaultClient.clear"></a>
|
|
306
|
+
|
|
307
|
+
#### VaultClient.clear([name])
|
|
308
|
+
Clear named Vault instance
|
|
309
|
+
|
|
310
|
+
If no name passed all named instances will be cleared.
|
|
311
|
+
|
|
312
|
+
**Kind**: static method of [<code>VaultClient</code>](#VaultClient)
|
|
313
|
+
|
|
314
|
+
| Param | Type | Description |
|
|
315
|
+
| --- | --- | --- |
|
|
316
|
+
| [name] | <code>String</code> | Vault instance name, all instances will be cleared if no name were passed |
|
|
317
|
+
|
|
318
|
+
## Contributing
|
|
319
|
+
|
|
320
|
+
Contributions are welcome! Please read the [contributing guide](CONTRIBUTING.md) to get started,
|
|
321
|
+
and note that this project requires a [DCO sign-off](CONTRIBUTING.md#dco-sign-off) on every commit.
|
|
322
|
+
|
|
323
|
+
## Getting help
|
|
324
|
+
|
|
325
|
+
Not sure where to start? See [SUPPORT.md](SUPPORT.md).
|
|
326
|
+
|
|
327
|
+
## Code of Conduct
|
|
328
|
+
|
|
329
|
+
This project adheres to the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).
|
|
330
|
+
|
|
331
|
+
## Security
|
|
332
|
+
|
|
333
|
+
To report a security vulnerability, please follow our [Security Policy](SECURITY.md).
|
|
334
|
+
|
|
335
|
+
## License
|
|
336
|
+
|
|
337
|
+
Licensed under the [Apache License 2.0](LICENSE.txt).
|
package/package.json
CHANGED
|
@@ -1,44 +1,64 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "node-vault-client",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "A Vault Client implemented in pure javascript for HashiCorp Vault. It supports variety of Auth Backends and performs lease renewal for issued auth token.",
|
|
5
|
-
"repository": {
|
|
6
|
-
"url": "git+https://github.com/namecheap/node-vault-client.git"
|
|
7
|
-
},
|
|
8
|
-
"engines": {
|
|
9
|
-
"node": ">=
|
|
10
|
-
},
|
|
11
|
-
"main": "src/VaultClient.js",
|
|
12
|
-
"files": [
|
|
13
|
-
"src"
|
|
14
|
-
],
|
|
15
|
-
"scripts": {
|
|
16
|
-
"test": "mocha test/**/*.test.
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
},
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "node-vault-client",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "A Vault Client implemented in pure javascript for HashiCorp Vault. It supports variety of Auth Backends and performs lease renewal for issued auth token.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"url": "git+https://github.com/namecheap/node-vault-client.git"
|
|
7
|
+
},
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=18.0.0"
|
|
10
|
+
},
|
|
11
|
+
"main": "src/VaultClient.js",
|
|
12
|
+
"files": [
|
|
13
|
+
"src"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "mocha --exit \"test/**/*.test.mjs\"",
|
|
17
|
+
"test:unit": "mocha \"test/*.test.mjs\"",
|
|
18
|
+
"coverage": "c8 npm run test:unit",
|
|
19
|
+
"lint": "eslint src/",
|
|
20
|
+
"version": "git add -A ."
|
|
21
|
+
},
|
|
22
|
+
"c8": {
|
|
23
|
+
"include": [
|
|
24
|
+
"src/**/*.js"
|
|
25
|
+
],
|
|
26
|
+
"reporter": [
|
|
27
|
+
"text",
|
|
28
|
+
"html",
|
|
29
|
+
"lcov"
|
|
30
|
+
],
|
|
31
|
+
"all": true
|
|
32
|
+
},
|
|
33
|
+
"author": "Namecheap <opensource@namecheap.com>",
|
|
34
|
+
"license": "Apache-2.0",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@aws-sdk/credential-providers": "^3.382.0",
|
|
37
|
+
"assign-deep": "^1.0.1",
|
|
38
|
+
"aws4": "^1.8.0",
|
|
39
|
+
"bluebird": "^3.7.0",
|
|
40
|
+
"lodash": "^4.17.15",
|
|
41
|
+
"long-timeout": "^0.1.1",
|
|
42
|
+
"pretty-ms": "^2.1.0",
|
|
43
|
+
"url-join": "^2.0.5"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"config": ">=1 <4"
|
|
47
|
+
},
|
|
48
|
+
"overrides": {
|
|
49
|
+
"serialize-javascript": "^7.0.5",
|
|
50
|
+
"glob": "^13.0.0",
|
|
51
|
+
"diff": "^8.0.3"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@eslint/js": "^9.0.0",
|
|
55
|
+
"c8": "^11.0.0",
|
|
56
|
+
"chai": "^6.0.0",
|
|
57
|
+
"deep-freeze": "^0.0.1",
|
|
58
|
+
"eslint": "^9.0.0",
|
|
59
|
+
"globals": "^16.0.0",
|
|
60
|
+
"mocha": "^11.7.6",
|
|
61
|
+
"sinon": "^22.0.0",
|
|
62
|
+
"sinon-chai": "^4.0.0"
|
|
63
|
+
}
|
|
64
|
+
}
|