@dotenvx/dotenvx-ops 0.42.1 → 0.43.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 +7 -1
- package/package.json +1 -1
- package/src/cli/actions/armor/move.js +39 -0
- package/src/cli/actions/armor/rotate.js +25 -0
- package/src/cli/actions/backup.js +0 -1
- package/src/cli/commands/armor.js +16 -0
- package/src/lib/api/postArmorMove.js +48 -0
- package/src/lib/services/armorMove.js +50 -0
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-ops/compare/v0.
|
|
5
|
+
[Unreleased](https://github.com/dotenvx/dotenvx-ops/compare/v0.43.0...main)
|
|
6
|
+
|
|
7
|
+
## [0.43.0](https://github.com/dotenvx/dotenvx-ops/compare/v0.42.1...v0.43.0) (2026-05-06)
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
* Add `armor move` for moving keys between teams ([#64](https://github.com/dotenvx/dotenvx-ops/pull/64))
|
|
6
12
|
|
|
7
13
|
## [0.42.1](https://github.com/dotenvx/dotenvx-ops/compare/v0.42.0...v0.42.1) (2026-04-26)
|
|
8
14
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const { logger } = require('@dotenvx/dotenvx')
|
|
2
|
+
const Session = require('./../../../db/session')
|
|
3
|
+
const ArmorMove = require('./../../../lib/services/armorMove')
|
|
4
|
+
const createSpinner = require('../../../lib/helpers/createSpinner2')
|
|
5
|
+
|
|
6
|
+
async function move () {
|
|
7
|
+
const options = this.opts()
|
|
8
|
+
const spinner = await createSpinner({ ...options, text: 'moving' })
|
|
9
|
+
|
|
10
|
+
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
11
|
+
|
|
12
|
+
const sesh = new Session()
|
|
13
|
+
await sesh.notifyUpdate()
|
|
14
|
+
const hostname = options.hostname || sesh.hostname()
|
|
15
|
+
const token = options.token || sesh.token()
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const devicePublicKey = sesh.devicePublicKey()
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
changed,
|
|
22
|
+
privateKeyName,
|
|
23
|
+
team
|
|
24
|
+
} = await new ArmorMove(hostname, token, devicePublicKey, options.envFile).run()
|
|
25
|
+
|
|
26
|
+
if (spinner) spinner.stop()
|
|
27
|
+
if (changed) {
|
|
28
|
+
logger.success(`◈ moved ${privateKeyName} (${team})`)
|
|
29
|
+
} else {
|
|
30
|
+
logger.info(`○ no change ${privateKeyName} (${team})`)
|
|
31
|
+
}
|
|
32
|
+
} catch (error) {
|
|
33
|
+
if (spinner) spinner.stop()
|
|
34
|
+
logger.error(error.message)
|
|
35
|
+
process.exit(1)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = move
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const { logger } = require('@dotenvx/dotenvx')
|
|
2
|
+
const Session = require('./../../../db/session')
|
|
3
|
+
const createSpinner = require('../../../lib/helpers/createSpinner2')
|
|
4
|
+
|
|
5
|
+
async function rotate () {
|
|
6
|
+
const options = this.opts()
|
|
7
|
+
const spinner = await createSpinner({ ...options, text: 'rotating' })
|
|
8
|
+
|
|
9
|
+
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
10
|
+
|
|
11
|
+
const sesh = new Session()
|
|
12
|
+
await sesh.notifyUpdate()
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
if (spinner) spinner.stop()
|
|
16
|
+
|
|
17
|
+
logger.info('◇ coming soon')
|
|
18
|
+
} catch (error) {
|
|
19
|
+
if (spinner) spinner.stop()
|
|
20
|
+
logger.error(error.message)
|
|
21
|
+
process.exit(1)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = rotate
|
|
@@ -44,4 +44,20 @@ armor
|
|
|
44
44
|
.option('-f, --env-file <path>', 'path to your env file')
|
|
45
45
|
.action(pullAction)
|
|
46
46
|
|
|
47
|
+
// dotenvx-ops armor rotate
|
|
48
|
+
const rotateAction = require('./../actions/armor/rotate')
|
|
49
|
+
armor
|
|
50
|
+
.command('rotate')
|
|
51
|
+
.description('rotate armored key and re-encrypt .env file')
|
|
52
|
+
.option('-f, --env-file <path>', 'path to your env file')
|
|
53
|
+
.action(rotateAction)
|
|
54
|
+
|
|
55
|
+
// dotenvx-ops armor move
|
|
56
|
+
const moveAction = require('./../actions/armor/move')
|
|
57
|
+
armor
|
|
58
|
+
.command('move')
|
|
59
|
+
.description('move armored key (to other team)')
|
|
60
|
+
.option('-f, --env-file <path>', 'path to your env file')
|
|
61
|
+
.action(moveAction)
|
|
62
|
+
|
|
47
63
|
module.exports = armor
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const { http } = require('../../lib/helpers/http')
|
|
2
|
+
const buildApiError = require('../../lib/helpers/buildApiError')
|
|
3
|
+
const packageJson = require('../../lib/helpers/packageJson')
|
|
4
|
+
const normalizeToken = require('../../lib/helpers/normalizeToken')
|
|
5
|
+
|
|
6
|
+
class PostArmorMove {
|
|
7
|
+
constructor (hostname, token, devicePublicKey, publicKey, team) {
|
|
8
|
+
this.hostname = hostname || 'https://ops.dotenvx.com'
|
|
9
|
+
this.token = token
|
|
10
|
+
this.devicePublicKey = devicePublicKey
|
|
11
|
+
this.publicKey = publicKey
|
|
12
|
+
this.team = team
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async run () {
|
|
16
|
+
const token = normalizeToken(this.token)
|
|
17
|
+
const devicePublicKey = this.devicePublicKey
|
|
18
|
+
const publicKey = this.publicKey
|
|
19
|
+
const team = this.team
|
|
20
|
+
const url = `${this.hostname}/api/armor/move`
|
|
21
|
+
|
|
22
|
+
const body = {
|
|
23
|
+
device_public_key: devicePublicKey,
|
|
24
|
+
cli_version: packageJson.version,
|
|
25
|
+
public_key: publicKey,
|
|
26
|
+
team
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const resp = await http(url, {
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers: {
|
|
32
|
+
Authorization: `Bearer ${token}`,
|
|
33
|
+
'Content-Type': 'application/json'
|
|
34
|
+
},
|
|
35
|
+
body: JSON.stringify(body)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const json = await resp.body.json()
|
|
39
|
+
|
|
40
|
+
if (resp.statusCode >= 400) {
|
|
41
|
+
throw buildApiError(resp.statusCode, json)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return json
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = PostArmorMove
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const dotenvx = require('@dotenvx/dotenvx')
|
|
2
|
+
const prompts = require('@inquirer/prompts')
|
|
3
|
+
const PostArmorMove = require('../api/postArmorMove')
|
|
4
|
+
const GetAccount = require('../api/getAccount')
|
|
5
|
+
const keyNamesForEnvFile = require('../helpers/keyNamesForEnvFile')
|
|
6
|
+
|
|
7
|
+
class ArmorMove {
|
|
8
|
+
constructor (hostname, token, devicePublicKey, envFile = '.env') {
|
|
9
|
+
this.hostname = hostname
|
|
10
|
+
this.token = token
|
|
11
|
+
this.devicePublicKey = devicePublicKey
|
|
12
|
+
this.envFile = envFile
|
|
13
|
+
|
|
14
|
+
this.team = null // implement
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async run () {
|
|
18
|
+
const hostname = this.hostname
|
|
19
|
+
const token = this.token
|
|
20
|
+
const devicePublicKey = this.devicePublicKey
|
|
21
|
+
const envFile = this.envFile
|
|
22
|
+
let team = this.team
|
|
23
|
+
|
|
24
|
+
const {
|
|
25
|
+
publicKeyName,
|
|
26
|
+
privateKeyName
|
|
27
|
+
} = keyNamesForEnvFile(envFile)
|
|
28
|
+
const publicKey = dotenvx.get(publicKeyName, { path: envFile, strict: true, ignore: ['MISSING_PRIVATE_KEY'], noOps: true })
|
|
29
|
+
|
|
30
|
+
const accountJson = await new GetAccount(hostname, token).run()
|
|
31
|
+
const choices = accountJson.organizations.map(o => ({
|
|
32
|
+
name: o.provider_slug,
|
|
33
|
+
value: o.provider_slug
|
|
34
|
+
}))
|
|
35
|
+
team = await prompts.select({
|
|
36
|
+
message: 'Select team',
|
|
37
|
+
choices
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const json = await new PostArmorMove(hostname, token, devicePublicKey, publicKey, team).run()
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
...json,
|
|
44
|
+
privateKeyName,
|
|
45
|
+
privateKeyValue: json.private_key
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = ArmorMove
|