@dotenvx/dotenvx 2.7.0 → 2.7.1

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 CHANGED
@@ -2,7 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
- [Unreleased](https://github.com/dotenvx/dotenvx/compare/v2.7.0...main)
5
+ [Unreleased](https://github.com/dotenvx/dotenvx/compare/v2.7.1...main)
6
+
7
+ ## [2.7.1](https://github.com/dotenvx/dotenvx/compare/v2.7.0...v2.7.1) (2026-07-13)
8
+
9
+ ### Changed
10
+
11
+ * Security Improvement: `dotenvx armor login` attempts to set the `DOTENVX_ARMOR_TOKEN` in your native OS secret store going forward. For current Armor users run `dotenvx armor logout` and then `dotenvx armor login` to make use of this immediately. ([#886](https://github.com/dotenvx/dotenvx/pull/886))
6
12
 
7
13
  ## [2.7.0](https://github.com/dotenvx/dotenvx/compare/v2.6.0...v2.7.0) (2026-07-13)
8
14
 
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.7.0",
2
+ "version": "2.7.1",
3
3
  "name": "@dotenvx/dotenvx",
4
4
  "description": "a secure dotenv–from the creator of `dotenv`",
5
5
  "author": "@motdotla",
@@ -0,0 +1,23 @@
1
+ const { logger } = require('../../../shared/logger')
2
+ const Session = require('../../../db/session')
3
+ const mask = require('../../../lib/helpers/mask')
4
+
5
+ function device () {
6
+ const options = this.opts()
7
+
8
+ try {
9
+ const value = new Session().devicePublicKey()
10
+ if (value && value.length > 1) {
11
+ console.log(options.unmask ? value : mask(value, 6))
12
+ return
13
+ }
14
+
15
+ logger.error('missing device. Try generating one with [dotenvx armor login].')
16
+ process.exit(1)
17
+ } catch (error) {
18
+ logger.error(error.message)
19
+ process.exit(1)
20
+ }
21
+ }
22
+
23
+ module.exports = device
@@ -0,0 +1,20 @@
1
+ const { logger } = require('../../../shared/logger')
2
+ const Session = require('../../../db/session')
3
+
4
+ function hostname () {
5
+ try {
6
+ const value = new Session().hostname()
7
+ if (value && value.length > 1) {
8
+ console.log(value)
9
+ return
10
+ }
11
+
12
+ logger.error('missing hostname. Try running [dotenvx armor login].')
13
+ process.exit(1)
14
+ } catch (error) {
15
+ logger.error(error.message)
16
+ process.exit(1)
17
+ }
18
+ }
19
+
20
+ module.exports = hostname
@@ -0,0 +1,14 @@
1
+ const { logger } = require('../../../shared/logger')
2
+ const Session = require('../../../db/session')
3
+
4
+ function off () {
5
+ try {
6
+ new Session().turnOff()
7
+ logger.success('✔ armor: off')
8
+ } catch (error) {
9
+ logger.error(error.message)
10
+ process.exit(1)
11
+ }
12
+ }
13
+
14
+ module.exports = off
@@ -0,0 +1,14 @@
1
+ const { logger } = require('../../../shared/logger')
2
+ const Session = require('../../../db/session')
3
+
4
+ function on () {
5
+ try {
6
+ new Session().turnOn()
7
+ logger.success('✔ armor: on')
8
+ } catch (error) {
9
+ logger.error(error.message)
10
+ process.exit(1)
11
+ }
12
+ }
13
+
14
+ module.exports = on
@@ -0,0 +1,20 @@
1
+ const { logger } = require('../../../shared/logger')
2
+ const Session = require('../../../db/session')
3
+
4
+ function path () {
5
+ try {
6
+ const value = new Session().path()
7
+ if (value && value.length > 1) {
8
+ console.log(value)
9
+ return
10
+ }
11
+
12
+ logger.error('missing path. Try running [dotenvx armor login].')
13
+ process.exit(1)
14
+ } catch (error) {
15
+ logger.error(error.message)
16
+ process.exit(1)
17
+ }
18
+ }
19
+
20
+ module.exports = path
@@ -0,0 +1,23 @@
1
+ const { logger } = require('../../../shared/logger')
2
+ const Session = require('../../../db/session')
3
+ const mask = require('../../../lib/helpers/mask')
4
+
5
+ function token () {
6
+ const options = this.opts()
7
+
8
+ try {
9
+ const value = new Session().token()
10
+ if (value && value.length > 1) {
11
+ console.log(options.unmask ? value : mask(value))
12
+ return
13
+ }
14
+
15
+ logger.error('missing token. Try generating one with [dotenvx armor login].')
16
+ process.exit(1)
17
+ } catch (error) {
18
+ logger.error(error.message)
19
+ process.exit(1)
20
+ }
21
+ }
22
+
23
+ module.exports = token
@@ -0,0 +1,20 @@
1
+ const { logger } = require('../../../shared/logger')
2
+ const Session = require('../../../db/session')
3
+
4
+ function username () {
5
+ try {
6
+ const value = new Session().username()
7
+ if (value) {
8
+ console.log(value)
9
+ return
10
+ }
11
+
12
+ logger.error('login required. Try running [dotenvx armor login].')
13
+ process.exit(1)
14
+ } catch (error) {
15
+ logger.error(error.message)
16
+ process.exit(1)
17
+ }
18
+ }
19
+
20
+ module.exports = username
@@ -91,6 +91,9 @@ function configureArmorCommand (armor) {
91
91
  return require('./../actions/logout').apply(this, args)
92
92
  })
93
93
 
94
+ // dotenvx armor settings
95
+ require('./settings')(armor.command('settings'))
96
+
94
97
  return armor
95
98
  }
96
99
 
@@ -1,4 +1,10 @@
1
1
  function configureLockCommand (lock) {
2
+ lock.hook('preAction', async () => {
3
+ const Session = require('./../../db/session')
4
+ const sesh = new Session()
5
+ await sesh.notifyUpdate()
6
+ })
7
+
2
8
  lock
3
9
  .description('lock private keys with a local passphrase')
4
10
  .action(function () {
@@ -1,4 +1,10 @@
1
1
  function configureNativeCommand (native) {
2
+ native.hook('preAction', async () => {
3
+ const Session = require('./../../db/session')
4
+ const sesh = new Session()
5
+ await sesh.notifyUpdate()
6
+ })
7
+
2
8
  native
3
9
  .description('move private keys into your OS secret store')
4
10
  .action(function () {
@@ -0,0 +1,62 @@
1
+ function configureSettingsCommand (settings) {
2
+ settings
3
+ .description('settings')
4
+ .action(function () {
5
+ this.help()
6
+ })
7
+
8
+ settings
9
+ .command('username')
10
+ .description('print your username')
11
+ .action(function (...args) {
12
+ return require('./../actions/settings/username').apply(this, args)
13
+ })
14
+
15
+ settings
16
+ .command('token')
17
+ .description('print your access token (--unmask)')
18
+ .option('--unmask', 'unmask access token')
19
+ .action(function (...args) {
20
+ return require('./../actions/settings/token').apply(this, args)
21
+ })
22
+
23
+ settings
24
+ .command('device')
25
+ .description('print your device pubkey (--unmask)')
26
+ .option('--unmask', 'unmask device pubkey')
27
+ .action(function (...args) {
28
+ return require('./../actions/settings/device').apply(this, args)
29
+ })
30
+
31
+ settings
32
+ .command('hostname')
33
+ .description('print hostname')
34
+ .action(function (...args) {
35
+ return require('./../actions/settings/hostname').apply(this, args)
36
+ })
37
+
38
+ settings
39
+ .command('path')
40
+ .description('print path to settings file')
41
+ .action(function (...args) {
42
+ return require('./../actions/settings/path').apply(this, args)
43
+ })
44
+
45
+ settings
46
+ .command('on')
47
+ .description('turn armor on')
48
+ .action(function (...args) {
49
+ return require('./../actions/settings/on').apply(this, args)
50
+ })
51
+
52
+ settings
53
+ .command('off')
54
+ .description('turn armor off')
55
+ .action(function (...args) {
56
+ return require('./../actions/settings/off').apply(this, args)
57
+ })
58
+
59
+ return settings
60
+ }
61
+
62
+ module.exports = configureSettingsCommand
package/src/db/session.js CHANGED
@@ -5,6 +5,7 @@ const { Conf, dotenv, envPaths } = require('@dotenvx/tooling')
5
5
  const jsonToEnv = require('./../lib/helpers/jsonToEnv')
6
6
  const packageJson = require('./../lib/helpers/packageJson')
7
7
  const { http } = require('./../lib/helpers/http')
8
+ const nativeProvider = require('./../lib/providers/native')
8
9
  const { logger } = require('./../shared/logger')
9
10
 
10
11
  const HOURS_24 = 60 * 60 * 24 * 1000
@@ -14,7 +15,8 @@ const ARMOR = {
14
15
  HOSTNAME: 'DOTENVX_ARMOR_HOSTNAME',
15
16
  USER: 'DOTENVX_ARMOR_USER',
16
17
  USERNAME: 'DOTENVX_ARMOR_USERNAME',
17
- TOKEN: 'DOTENVX_ARMOR_TOKEN'
18
+ TOKEN: 'DOTENVX_ARMOR_TOKEN',
19
+ ON: 'DOTENVX_ARMOR_ON'
18
20
  }
19
21
 
20
22
  const DOTENVX = {
@@ -100,7 +102,7 @@ class Session {
100
102
 
101
103
  status () {
102
104
  // if logged in
103
- if (this.username() && this.token()) {
105
+ if (this.username() && this.token() && this.on()) {
104
106
  return 'on'
105
107
  }
106
108
 
@@ -133,7 +135,15 @@ class Session {
133
135
  }
134
136
 
135
137
  token () {
136
- return this.readSetting('TOKEN') || undefined
138
+ return this.getFromSecretStore(ARMOR.TOKEN) || undefined
139
+ }
140
+
141
+ on () {
142
+ return (this.readSetting('ON') || 'true') === 'true'
143
+ }
144
+
145
+ off () {
146
+ return (this.readSetting('ON') || 'true') === 'false'
137
147
  }
138
148
 
139
149
  devicePublicKey () {
@@ -187,7 +197,7 @@ class Session {
187
197
  store.set(DOTENVX.VERSION_LAST_CHECK, now)
188
198
 
189
199
  if (versionGreaterThan(remote, packageJson.version)) {
190
- console.error('⛆ update available [npm install @dotenvx/dotenvx@latest]')
200
+ console.error('⛆ update available [curl -sfS https://dotenvx.sh | sh]')
191
201
  }
192
202
  } catch (error) {
193
203
  logger.debug(error.message)
@@ -222,6 +232,47 @@ class Session {
222
232
  //
223
233
  // Set/Delete
224
234
  //
235
+ getFromSecretStore (key) {
236
+ try {
237
+ const value = nativeProvider.get(key)
238
+ if (value) return value
239
+ } catch {}
240
+
241
+ const store = this.openStore()
242
+ if (!store) return undefined
243
+
244
+ return store.get(key)
245
+ }
246
+
247
+ setInSecretStore (key, value) {
248
+ try {
249
+ nativeProvider.set(key, value)
250
+ return value
251
+ } catch {
252
+ this.createStore().set(key, value)
253
+ return value
254
+ }
255
+ }
256
+
257
+ deleteFromSecretStore (key) {
258
+ try {
259
+ nativeProvider.delete(key)
260
+ } catch {}
261
+
262
+ const store = this.openStore()
263
+ if (store) store.delete(key)
264
+ }
265
+
266
+ turnOn () {
267
+ this.createStore().set(ARMOR.ON, 'true')
268
+ return 'true'
269
+ }
270
+
271
+ turnOff () {
272
+ this.createStore().set(ARMOR.ON, 'false')
273
+ return 'false'
274
+ }
275
+
225
276
  login (hostname, id, username, accessToken) {
226
277
  if (!hostname) {
227
278
  throw new Error('DOTENVX_ARMOR_HOSTNAME not set. Run [dotenvx armor login]')
@@ -242,8 +293,9 @@ class Session {
242
293
  const store = this.createStore()
243
294
  store.set(ARMOR.USER, id)
244
295
  store.set(ARMOR.USERNAME, username)
245
- store.set(ARMOR.TOKEN, accessToken)
296
+ this.setInSecretStore(ARMOR.TOKEN, accessToken)
246
297
  store.set(ARMOR.HOSTNAME, hostname)
298
+ store.set(ARMOR.ON, 'true')
247
299
 
248
300
  return accessToken
249
301
  }
@@ -261,13 +313,14 @@ class Session {
261
313
  throw new Error('DOTENVX_ARMOR_TOKEN not set. Run [dotenvx armor login]')
262
314
  }
263
315
 
316
+ this.deleteFromSecretStore(ARMOR.TOKEN)
317
+
264
318
  const store = this.openStore()
265
319
  if (!store) return true
266
-
267
320
  store.delete(ARMOR.USER)
268
321
  store.delete(ARMOR.USERNAME)
269
- store.delete(ARMOR.TOKEN)
270
322
  store.delete(ARMOR.HOSTNAME)
323
+ store.delete(ARMOR.ON)
271
324
  store.delete(DOTENVX.VERSION)
272
325
  store.delete(DOTENVX.VERSION_LAST_CHECK)
273
326
  return true
@@ -7,7 +7,7 @@ function attributes (publicKey) {
7
7
  return ['service', SERVICE, 'public-key', publicKey]
8
8
  }
9
9
 
10
- function findGenericPassword (publicKey) {
10
+ function get (publicKey) {
11
11
  try {
12
12
  return execFileSync(SECRET_TOOL_BIN, ['lookup', ...attributes(publicKey)], {
13
13
  encoding: 'utf8',
@@ -18,7 +18,7 @@ function findGenericPassword (publicKey) {
18
18
  }
19
19
  }
20
20
 
21
- function addGenericPassword (publicKey, label, privateKey) {
21
+ function set (publicKey, privateKey, label) {
22
22
  try {
23
23
  execFileSync(SECRET_TOOL_BIN, ['store', `--label=${label}`, ...attributes(publicKey)], {
24
24
  input: privateKey,
@@ -30,14 +30,16 @@ function addGenericPassword (publicKey, label, privateKey) {
30
30
  }
31
31
  }
32
32
 
33
- function deleteGenericPassword (publicKey) {
34
- try {
35
- execFileSync(SECRET_TOOL_BIN, ['clear', ...attributes(publicKey)], {
36
- stdio: ['ignore', 'ignore', 'pipe']
37
- })
38
- } catch {
39
- throw new Error('failed to delete private key from Linux Secret Service')
33
+ module.exports = {
34
+ get,
35
+ set,
36
+ delete (publicKey) {
37
+ try {
38
+ execFileSync(SECRET_TOOL_BIN, ['clear', ...attributes(publicKey)], {
39
+ stdio: ['ignore', 'ignore', 'pipe']
40
+ })
41
+ } catch {
42
+ throw new Error('failed to delete private key from Linux Secret Service')
43
+ }
40
44
  }
41
45
  }
42
-
43
- module.exports = { findGenericPassword, addGenericPassword, deleteGenericPassword }
@@ -0,0 +1,26 @@
1
+ const { execFileSync } = require('child_process')
2
+
3
+ const SECURITY_BIN = '/usr/bin/security'
4
+ const SERVICE = 'dotenvx'
5
+
6
+ module.exports = {
7
+ get (key) {
8
+ return execFileSync(SECURITY_BIN, ['find-generic-password', '-s', SERVICE, '-a', key, '-w'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim()
9
+ },
10
+
11
+ set (key, value, label) {
12
+ try {
13
+ execFileSync(SECURITY_BIN, ['add-generic-password', '-U', '-s', SERVICE, '-a', key, '-l', label, '-w', value], { stdio: 'ignore' })
14
+ } catch {
15
+ throw new Error('failed to save private key to macOS Keychain')
16
+ }
17
+ },
18
+
19
+ delete (key) {
20
+ try {
21
+ execFileSync(SECURITY_BIN, ['delete-generic-password', '-s', SERVICE, '-a', key], { stdio: 'ignore' })
22
+ } catch {
23
+ throw new Error('failed to delete private key from macOS Keychain')
24
+ }
25
+ }
26
+ }
@@ -134,7 +134,7 @@ function run (payload) {
134
134
  })
135
135
  }
136
136
 
137
- function findGenericPassword (publicKey) {
137
+ function get (publicKey) {
138
138
  try {
139
139
  return run({ action: 'read', target: target(publicKey) }).trim() || null
140
140
  } catch {
@@ -142,7 +142,7 @@ function findGenericPassword (publicKey) {
142
142
  }
143
143
  }
144
144
 
145
- function addGenericPassword (publicKey, privateKey) {
145
+ function set (publicKey, privateKey) {
146
146
  try {
147
147
  run({ action: 'write', target: target(publicKey), username: publicKey, secret: privateKey })
148
148
  } catch {
@@ -150,12 +150,14 @@ function addGenericPassword (publicKey, privateKey) {
150
150
  }
151
151
  }
152
152
 
153
- function deleteGenericPassword (publicKey) {
154
- try {
155
- run({ action: 'delete', target: target(publicKey) })
156
- } catch {
157
- throw new Error('failed to delete private key from Windows Credential Manager')
153
+ module.exports = {
154
+ get,
155
+ set,
156
+ delete (publicKey) {
157
+ try {
158
+ run({ action: 'delete', target: target(publicKey) })
159
+ } catch {
160
+ throw new Error('failed to delete private key from Windows Credential Manager')
161
+ }
158
162
  }
159
163
  }
160
-
161
- module.exports = { findGenericPassword, addGenericPassword, deleteGenericPassword }
@@ -1,27 +1,52 @@
1
- const { execFileSync } = require('child_process')
2
-
1
+ const macosKeychain = require('../../helpers/macosKeychain')
3
2
  const windowsCredentialManager = require('../../helpers/windowsCredentialManager')
4
3
  const linuxSecretService = require('../../helpers/linuxSecretService')
5
4
 
6
- const SECURITY_BIN = '/usr/bin/security'
7
- const SERVICE = 'dotenvx'
5
+ function get (key) {
6
+ if (process.platform === 'win32') {
7
+ return windowsCredentialManager.get(key)
8
+ }
8
9
 
9
- function findMacosPrivateKey (publicKeyHex) {
10
- return execFileSync(SECURITY_BIN, ['find-generic-password', '-s', SERVICE, '-a', publicKeyHex, '-w'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim()
10
+ if (process.platform === 'linux') {
11
+ return linuxSecretService.get(key)
12
+ }
13
+
14
+ return macosKeychain.get(key)
15
+ }
16
+
17
+ function set (key, value, label = key) {
18
+ if (process.platform === 'win32') {
19
+ windowsCredentialManager.set(key, value, label)
20
+ return
21
+ }
22
+
23
+ if (process.platform === 'linux') {
24
+ linuxSecretService.set(key, value, label)
25
+ return
26
+ }
27
+
28
+ macosKeychain.set(key, value, label)
29
+ }
30
+
31
+ index.delete = function (key) {
32
+ if (process.platform === 'win32') {
33
+ windowsCredentialManager.delete(key)
34
+ return
35
+ }
36
+
37
+ if (process.platform === 'linux') {
38
+ linuxSecretService.delete(key)
39
+ return
40
+ }
41
+
42
+ macosKeychain.delete(key)
11
43
  }
12
44
 
13
45
  function index (publicKeyHex) {
14
46
  if (!['darwin', 'linux', 'win32'].includes(process.platform)) return {}
15
47
 
16
48
  try {
17
- let privateKeyHex
18
- if (process.platform === 'win32') {
19
- privateKeyHex = windowsCredentialManager.findGenericPassword(publicKeyHex)
20
- } else if (process.platform === 'linux') {
21
- privateKeyHex = linuxSecretService.findGenericPassword(publicKeyHex)
22
- } else {
23
- privateKeyHex = findMacosPrivateKey(publicKeyHex)
24
- }
49
+ const privateKeyHex = get(publicKeyHex)
25
50
 
26
51
  if (!privateKeyHex) return {}
27
52
 
@@ -31,4 +56,7 @@ function index (publicKeyHex) {
31
56
  }
32
57
  }
33
58
 
59
+ index.set = set
60
+ index.get = get
61
+
34
62
  module.exports = index
@@ -1,40 +1,8 @@
1
- const { execFileSync } = require('child_process')
2
-
3
1
  const keynames = require('../conventions/keynames')
4
2
  const readEnvKey = require('../helpers/readEnvKey')
5
3
  const upsertEnvKey = require('../helpers/upsertEnvKey')
6
4
  const armoredKeyDisplay = require('../helpers/armoredKeyDisplay')
7
- const windowsCredentialManager = require('../helpers/windowsCredentialManager')
8
- const linuxSecretService = require('../helpers/linuxSecretService')
9
-
10
- const SECURITY_BIN = '/usr/bin/security'
11
- const SERVICE = 'dotenvx'
12
-
13
- function findGenericPassword (publicKey) {
14
- if (process.platform === 'win32') {
15
- return windowsCredentialManager.findGenericPassword(publicKey)
16
- }
17
-
18
- if (process.platform === 'linux') {
19
- return linuxSecretService.findGenericPassword(publicKey)
20
- }
21
-
22
- return execFileSync(SECURITY_BIN, ['find-generic-password', '-s', SERVICE, '-a', publicKey, '-w'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim()
23
- }
24
-
25
- function deleteGenericPassword (publicKey) {
26
- if (process.platform === 'win32') {
27
- windowsCredentialManager.deleteGenericPassword(publicKey)
28
- return
29
- }
30
-
31
- if (process.platform === 'linux') {
32
- linuxSecretService.deleteGenericPassword(publicKey)
33
- return
34
- }
35
-
36
- execFileSync(SECURITY_BIN, ['delete-generic-password', '-s', SERVICE, '-a', publicKey], { stdio: 'ignore' })
37
- }
5
+ const nativeProvider = require('../providers/native')
38
6
 
39
7
  class KeychainDown {
40
8
  constructor (envFile = '.env', envKeysFile = '.env.keys') {
@@ -55,7 +23,7 @@ class KeychainDown {
55
23
  let privateKey
56
24
 
57
25
  try {
58
- privateKey = findGenericPassword(publicKey)
26
+ privateKey = nativeProvider.get(publicKey)
59
27
  if (!privateKey) {
60
28
  const secretStore = process.platform === 'win32'
61
29
  ? 'Windows Credential Manager'
@@ -78,7 +46,7 @@ class KeychainDown {
78
46
  }
79
47
 
80
48
  upsertEnvKey(privateKeyName, privateKey, envKeysFile)
81
- deleteGenericPassword(publicKey)
49
+ nativeProvider.delete(publicKey)
82
50
 
83
51
  return {
84
52
  changed: true,
@@ -1,26 +1,8 @@
1
- const { execFileSync } = require('child_process')
2
-
3
1
  const keynames = require('../conventions/keynames')
4
2
  const readEnvKey = require('../helpers/readEnvKey')
5
3
  const upsertEnvKey = require('../helpers/upsertEnvKey')
6
4
  const armoredKeyDisplay = require('../helpers/armoredKeyDisplay')
7
- const windowsCredentialManager = require('../helpers/windowsCredentialManager')
8
- const linuxSecretService = require('../helpers/linuxSecretService')
9
-
10
- const SECURITY_BIN = '/usr/bin/security'
11
- const SERVICE = 'dotenvx'
12
-
13
- function findGenericPassword (publicKey) {
14
- if (process.platform === 'win32') {
15
- return windowsCredentialManager.findGenericPassword(publicKey)
16
- }
17
-
18
- if (process.platform === 'linux') {
19
- return linuxSecretService.findGenericPassword(publicKey)
20
- }
21
-
22
- return execFileSync(SECURITY_BIN, ['find-generic-password', '-s', SERVICE, '-a', publicKey, '-w'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim()
23
- }
5
+ const nativeProvider = require('../providers/native')
24
6
 
25
7
  class KeychainPull {
26
8
  constructor (envFile = '.env', envKeysFile = '.env.keys') {
@@ -41,7 +23,7 @@ class KeychainPull {
41
23
  let privateKey
42
24
 
43
25
  try {
44
- privateKey = findGenericPassword(publicKey)
26
+ privateKey = nativeProvider.get(publicKey)
45
27
  if (!privateKey) throw new Error('not found')
46
28
  } catch {
47
29
  const secretStore = process.platform === 'win32'
@@ -1,43 +1,7 @@
1
- const { execFileSync } = require('child_process')
2
-
3
1
  const keynames = require('../conventions/keynames')
4
2
  const readEnvKey = require('../helpers/readEnvKey')
5
3
  const armoredKeyDisplay = require('../helpers/armoredKeyDisplay')
6
- const windowsCredentialManager = require('../helpers/windowsCredentialManager')
7
- const linuxSecretService = require('../helpers/linuxSecretService')
8
-
9
- const SECURITY_BIN = '/usr/bin/security'
10
- const SERVICE = 'dotenvx'
11
-
12
- function addGenericPassword (publicKey, label, privateKey) {
13
- if (process.platform === 'win32') {
14
- windowsCredentialManager.addGenericPassword(publicKey, privateKey)
15
- return
16
- }
17
-
18
- if (process.platform === 'linux') {
19
- linuxSecretService.addGenericPassword(publicKey, label, privateKey)
20
- return
21
- }
22
-
23
- try {
24
- execFileSync(SECURITY_BIN, ['add-generic-password', '-U', '-s', SERVICE, '-a', publicKey, '-l', label, '-w', privateKey], { stdio: 'ignore' })
25
- } catch {
26
- throw new Error('failed to save private key to macOS Keychain')
27
- }
28
- }
29
-
30
- function findGenericPassword (publicKey) {
31
- if (process.platform === 'win32') {
32
- return windowsCredentialManager.findGenericPassword(publicKey)
33
- }
34
-
35
- if (process.platform === 'linux') {
36
- return linuxSecretService.findGenericPassword(publicKey)
37
- }
38
-
39
- return execFileSync(SECURITY_BIN, ['find-generic-password', '-s', SERVICE, '-a', publicKey, '-w'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim()
40
- }
4
+ const nativeProvider = require('../providers/native')
41
5
 
42
6
  class KeychainPush {
43
7
  constructor (envFile = '.env', envKeysFile = '.env.keys') {
@@ -59,7 +23,7 @@ class KeychainPush {
59
23
  const label = `dotenvx (${armoredKeyDisplay(publicKey)})`
60
24
 
61
25
  try {
62
- const existingPrivateKey = findGenericPassword(publicKey)
26
+ const existingPrivateKey = nativeProvider.get(publicKey)
63
27
 
64
28
  if (existingPrivateKey === privateKey) {
65
29
  return {
@@ -72,7 +36,7 @@ class KeychainPush {
72
36
  }
73
37
  } catch {}
74
38
 
75
- addGenericPassword(publicKey, label, privateKey)
39
+ nativeProvider.set(publicKey, privateKey, label)
76
40
 
77
41
  return {
78
42
  changed: true,
@@ -1,44 +1,8 @@
1
- const { execFileSync } = require('child_process')
2
-
3
1
  const keynames = require('../conventions/keynames')
4
2
  const readEnvKey = require('../helpers/readEnvKey')
5
3
  const removeEnvKey = require('../helpers/removeEnvKey')
6
4
  const armoredKeyDisplay = require('../helpers/armoredKeyDisplay')
7
- const windowsCredentialManager = require('../helpers/windowsCredentialManager')
8
- const linuxSecretService = require('../helpers/linuxSecretService')
9
-
10
- const SECURITY_BIN = '/usr/bin/security'
11
- const SERVICE = 'dotenvx'
12
-
13
- function addGenericPassword (publicKey, label, privateKey) {
14
- if (process.platform === 'win32') {
15
- windowsCredentialManager.addGenericPassword(publicKey, privateKey)
16
- return
17
- }
18
-
19
- if (process.platform === 'linux') {
20
- linuxSecretService.addGenericPassword(publicKey, label, privateKey)
21
- return
22
- }
23
-
24
- try {
25
- execFileSync(SECURITY_BIN, ['add-generic-password', '-U', '-s', SERVICE, '-a', publicKey, '-l', label, '-w', privateKey], { stdio: 'ignore' })
26
- } catch {
27
- throw new Error('failed to save private key to macOS Keychain')
28
- }
29
- }
30
-
31
- function findGenericPassword (publicKey) {
32
- if (process.platform === 'win32') {
33
- return windowsCredentialManager.findGenericPassword(publicKey)
34
- }
35
-
36
- if (process.platform === 'linux') {
37
- return linuxSecretService.findGenericPassword(publicKey)
38
- }
39
-
40
- return execFileSync(SECURITY_BIN, ['find-generic-password', '-s', SERVICE, '-a', publicKey, '-w'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim()
41
- }
5
+ const nativeProvider = require('../providers/native')
42
6
 
43
7
  class KeychainUp {
44
8
  constructor (envFile = '.env', envKeysFile = '.env.keys') {
@@ -60,7 +24,7 @@ class KeychainUp {
60
24
  let existingPrivateKey
61
25
 
62
26
  try {
63
- existingPrivateKey = findGenericPassword(publicKey)
27
+ existingPrivateKey = nativeProvider.get(publicKey)
64
28
  } catch {}
65
29
 
66
30
  const privateKey = readEnvKey(privateKeyName, envKeysFile, { strict: !existingPrivateKey })
@@ -89,7 +53,7 @@ class KeychainUp {
89
53
  }
90
54
  }
91
55
 
92
- addGenericPassword(publicKey, label, privateKey)
56
+ nativeProvider.set(publicKey, privateKey, label)
93
57
  removeEnvKey(privateKeyName, envKeysFile)
94
58
 
95
59
  return {