@dotenvx/dotenvx-ops 0.32.0 → 0.34.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 CHANGED
@@ -2,7 +2,19 @@
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.32.0...main)
5
+ [Unreleased](https://github.com/dotenvx/dotenvx-ops/compare/v0.34.0...main)
6
+
7
+ ## [0.34.0](https://github.com/dotenvx/dotenvx-ops/compare/v0.33.0...v0.34.0) (2026-03-12)
8
+
9
+ ### Added
10
+
11
+ * Run keypair against existing `public_key` as a lookup mechanism ([#28](https://github.com/dotenvx/dotenvx-ops/pull/28))
12
+
13
+ ## [0.33.0](https://github.com/dotenvx/dotenvx-ops/compare/v0.32.0...v0.33.0) (2026-03-11)
14
+
15
+ ### Added
16
+
17
+ * Add internal `keypair` command that calls remotely ([#27](https://github.com/dotenvx/dotenvx-ops/pull/27))
6
18
 
7
19
  ## [0.32.0](https://github.com/dotenvx/dotenvx-ops/compare/v0.31.2...v0.32.0) (2026-03-11)
8
20
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  [![dotenvx-ops](https://dotenvx.com/dotenvx-ops-banner.png?v=2)](https://dotenvx.com/ops)
2
2
 
3
- > production grade dotenvxwith operational primitives
3
+ > keep keys off computepowered by `dotenvx`
4
4
 
5
5
  [Learn more](https://dotenvx.com/docs/ops)
6
6
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "version": "0.32.0",
2
+ "version": "0.34.0",
3
3
  "name": "@dotenvx/dotenvx-ops",
4
- "description": "production grade dotenvxwith operational primitives",
4
+ "description": "keep keys off computepowered by `dotenvx`",
5
5
  "author": "@motdotla",
6
6
  "keywords": [
7
7
  "dotenv",
@@ -0,0 +1,41 @@
1
+ const { logger } = require('@dotenvx/dotenvx')
2
+
3
+ const main = require('./../../lib/main')
4
+
5
+ async function keypair (publicKey) {
6
+ // debug opts
7
+ const options = this.opts()
8
+ logger.debug(`options: ${JSON.stringify(options)}`)
9
+
10
+ const hostname = options.hostname
11
+ const token = options.token
12
+ try {
13
+ const kp = await main.keypair(publicKey, { hostname, token })
14
+ const output = {
15
+ public_key: kp.publicKey,
16
+ private_key: kp.privateKey
17
+ }
18
+
19
+ let space = 0
20
+ if (options.prettyPrint) {
21
+ space = 2
22
+ }
23
+
24
+ console.log(JSON.stringify(output, null, space))
25
+ } catch (error) {
26
+ if (error.message) {
27
+ logger.error(error.message)
28
+ } else {
29
+ logger.error(error)
30
+ }
31
+ if (error.help) {
32
+ logger.help(error.help)
33
+ }
34
+ if (error.stack) {
35
+ logger.debug(error.stack)
36
+ }
37
+ process.exit(1)
38
+ }
39
+ }
40
+
41
+ module.exports = keypair
@@ -43,7 +43,7 @@ async function login () {
43
43
 
44
44
  const data = await pollPromise
45
45
  spinner.succeed(`logged in [${data.username}] to this device and activated token [${truncate(data.access_token, 11)}]`)
46
- logger.help('⮕ next run [dotenvx-ops backup]')
46
+ // logger.help('⮕ next run [dotenvx-ops backup]')
47
47
  process.exit(0)
48
48
  } catch (error) {
49
49
  spinner.stop()
@@ -117,6 +117,17 @@ program
117
117
  .description('[INTERNAL] status')
118
118
  .action(statusAction)
119
119
 
120
+ // dotenvx-ops keypair
121
+ const keypairAction = require('./actions/keypair')
122
+ program
123
+ .command('keypair')
124
+ .description('[INTERNAL] generate keypair')
125
+ .argument('[publicKey]', 'existing public key')
126
+ .option('-h, --hostname <url>', 'set hostname', sesh.hostname())
127
+ .option('--token <token>', 'set token')
128
+ .option('--pp, --pretty-print', 'pretty print output')
129
+ .action(keypairAction)
130
+
120
131
  program.addCommand(require('./commands/gateway'))
121
132
  program.addCommand(require('./commands/settings'))
122
133
 
@@ -0,0 +1,47 @@
1
+ const { http } = require('../../lib/helpers/http')
2
+ const buildApiError = require('../../lib/helpers/buildApiError')
3
+ const packageJson = require('../../lib/helpers/packageJson')
4
+
5
+ class PostKeypair {
6
+ constructor (hostname, token, devicePublicKey, publicKey) {
7
+ this.hostname = hostname || 'https://ops.dotenvx.com'
8
+ this.token = token
9
+ this.devicePublicKey = devicePublicKey
10
+ this.publicKey = publicKey
11
+ }
12
+
13
+ async run () {
14
+ const token = this.token
15
+ const devicePublicKey = this.devicePublicKey
16
+ const publicKey = this.publicKey
17
+ const url = `${this.hostname}/api/keypair`
18
+
19
+ const body = {
20
+ device_public_key: devicePublicKey,
21
+ cli_version: packageJson.version
22
+ }
23
+
24
+ if (publicKey) {
25
+ body.public_key = publicKey
26
+ }
27
+
28
+ const resp = await http(url, {
29
+ method: 'POST',
30
+ headers: {
31
+ Authorization: `Bearer ${token}`,
32
+ 'Content-Type': 'application/json'
33
+ },
34
+ body: JSON.stringify(body)
35
+ })
36
+
37
+ const json = await resp.body.json()
38
+
39
+ if (resp.statusCode >= 400) {
40
+ throw buildApiError(resp.statusCode, json)
41
+ }
42
+
43
+ return json
44
+ }
45
+ }
46
+
47
+ module.exports = PostKeypair
package/src/lib/main.d.ts CHANGED
@@ -9,6 +9,27 @@ import type { URL } from 'url';
9
9
  */
10
10
  export function observe(payload: string): string;
11
11
 
12
+ export interface DotenvOpsOptions {
13
+ hostname?: string;
14
+ token?: string;
15
+ }
16
+
17
+ export type DotenvOpsKeypairOptions = DotenvOpsOptions;
18
+
19
+ export interface DotenvOpsKeypairOutput {
20
+ publicKey: string;
21
+ privateKey: string;
22
+ }
23
+
24
+ /**
25
+ * Creates a remote keypair for the current authenticated device.
26
+ *
27
+ * @param publicKey - optional existing public key to fetch
28
+ * @param options - optional hostname/token overrides
29
+ * @returns generated public and private keys
30
+ */
31
+ export function keypair(publicKey?: string, options?: DotenvOpsKeypairOptions): Promise<DotenvOpsKeypairOutput>;
32
+
12
33
  export interface DotenvConfigOptions {
13
34
  /**
14
35
  * Specify a custom path if your file containing environment variables is located elsewhere.
package/src/lib/main.js CHANGED
@@ -5,6 +5,7 @@ const Session = require('./../db/session')
5
5
  const PostObserve = require('./api/postObserve')
6
6
  const PostGet = require('./api/postGet')
7
7
  const PostSet = require('./api/postSet')
8
+ const PostKeypair = require('./api/postKeypair')
8
9
 
9
10
  const gitUrl = require('./helpers/gitUrl')
10
11
  const gitBranch = require('./helpers/gitBranch')
@@ -76,6 +77,29 @@ const set = async function (uri, value, options = {}) {
76
77
  return await new PostSet(hostname, token, devicePublicKey, uri, value).run()
77
78
  }
78
79
 
80
+ const keypair = async function (publicKey, options = {}) {
81
+ const sesh = new Session() // TODO: handle scenario where constructor fails
82
+
83
+ let hostname = process.env.DOTENVX_OPS_HOSTNAME || options.hostname
84
+ if (!hostname) {
85
+ hostname = sesh.hostname()
86
+ }
87
+
88
+ let token = process.env.DOTENVX_OPS_TOKEN || options.token
89
+ if (!token) {
90
+ token = sesh.token()
91
+ }
92
+
93
+ const devicePublicKey = sesh.devicePublicKey()
94
+
95
+ const json = await new PostKeypair(hostname, token, devicePublicKey, publicKey).run()
96
+
97
+ return {
98
+ publicKey: json.public_key,
99
+ privateKey: json.private_key
100
+ }
101
+ }
102
+
79
103
  const config = function (options = {}) {
80
104
  return dotenvx.config(options)
81
105
  }
@@ -84,6 +108,7 @@ module.exports = {
84
108
  observe,
85
109
  get,
86
110
  set,
111
+ keypair,
87
112
  // dotenv proxies
88
113
  config
89
114
  }