@dotenvx/dotenvx-ops 0.18.0 → 0.19.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,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.18.0...main)
5
+ [Unreleased](https://github.com/dotenvx/dotenvx-ops/compare/v0.19.0...main)
6
+
7
+ ## [0.19.0](https://github.com/dotenvx/dotenvx-ops/compare/v0.18.0...v0.19.0) (2025-10-07)
8
+
9
+ ### Added
10
+
11
+ * Surface any conflicts during `sync` ([#3](https://github.com/dotenvx/dotenvx-ops/pull3))
6
12
 
7
13
  ## [0.18.0](https://github.com/dotenvx/dotenvx-ops/compare/v0.17.1...v0.18.0) (2025-10-06)
8
14
 
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.18.0",
2
+ "version": "0.19.0",
3
3
  "name": "@dotenvx/dotenvx-ops",
4
4
  "description": "Dotenvx Ops",
5
5
  "author": "@motdotla",
@@ -5,18 +5,13 @@ const { logger } = require('@dotenvx/dotenvx')
5
5
 
6
6
  const { createSpinner } = require('./../../lib/helpers/createSpinner')
7
7
  const smartMask = require('./../../lib/helpers/smartMask')
8
+ const pluralize = require('./../../lib/helpers/pluralize')
8
9
 
9
10
  const Sync = require('./../../lib/services/sync')
10
-
11
- const GetSynchronization = require('./../../lib/api/getSynchronization')
11
+ const SyncConflict = require('./../../lib/services/syncConflict')
12
12
 
13
13
  const spinner = createSpinner('syncing')
14
14
 
15
- // move soon
16
- const Session = require('./../../db/session')
17
- const sesh = new Session()
18
- const token = sesh.token()
19
-
20
15
  function sha256File (filepath) {
21
16
  const buf = fs.readFileSync(filepath)
22
17
  return crypto.createHash('sha256').update(buf).digest('hex')
@@ -73,16 +68,36 @@ async function sync () {
73
68
  logger.debug(error.stack)
74
69
  }
75
70
 
76
- // display conflict diff
77
- if (error.code === 'DOTENVX_SYNC_CONFLICT') {
78
- const synchronizationId = error.meta.synchronization_id
79
- const data = await new GetSynchronization(options.hostname, token, synchronizationId).run()
80
- const conflictedFile = data.files.find(f => f.status === 'conflicted')
81
- if (conflictedFile) {
82
- console.log(conflictedFile.filepath)
83
- console.log(conflictedFile.diff_ansi)
71
+ try {
72
+ if (error.code === 'DOTENVX_SYNC_CONFLICT') {
73
+ spinner.start()
74
+
75
+ const synchronizationId = error.meta.synchronization_id
76
+ const { conflictedFiles } = await new SyncConflict(options.hostname, synchronizationId).run()
77
+
78
+ spinner.stop()
79
+
80
+ // loop through any conflicted files
81
+ for (const conflictedFile of conflictedFiles) {
82
+ logger.info('')
83
+ logger.info(`✖ conflict [${conflictedFile.filepath}]`)
84
+ console.log(conflictedFile.diffAnsi)
85
+ }
86
+
87
+ logger.info(`Review and edit the ${pluralize('file', conflictedFiles.length)} as needed, then confirm your version with [dotenvx-ops sync --force]`)
88
+ }
89
+ } catch (error) {
90
+ spinner.stop()
91
+ if (error.message) {
92
+ logger.error(error.message)
84
93
  } else {
85
- console.log('No conflicted files found.')
94
+ logger.error(error)
95
+ }
96
+ if (error.help) {
97
+ logger.help(error.help)
98
+ }
99
+ if (error.stack) {
100
+ logger.debug(error.stack)
86
101
  }
87
102
  }
88
103
 
@@ -0,0 +1,10 @@
1
+ function pluralize (word, count) {
2
+ // simple pluralization: add 's' at the end
3
+ if (count === 0 || count > 1) {
4
+ return word + 's'
5
+ } else {
6
+ return word
7
+ }
8
+ }
9
+
10
+ module.exports = pluralize
@@ -0,0 +1,36 @@
1
+ const Session = require('./../../db/session')
2
+
3
+ // api calls
4
+ const GetSynchronization = require('./../api/getSynchronization')
5
+
6
+ class SyncConflict {
7
+ constructor (hostname, synchronizationId) {
8
+ this.hostname = hostname
9
+ this.synchronizationId = synchronizationId
10
+ }
11
+
12
+ async run () {
13
+ const sesh = new Session()
14
+ const token = sesh.token()
15
+ const synchronizationId = this.synchronizationId
16
+
17
+ const data = await new GetSynchronization(this.hostname, token, synchronizationId).run()
18
+
19
+ const conflictedFiles = []
20
+ for (const file of data.files) {
21
+ if (file.status === 'conflicted') {
22
+ conflictedFiles.push({
23
+ filepath: file.filepath,
24
+ diffAnsi: file.diff_ansi
25
+ })
26
+ }
27
+ }
28
+
29
+ return {
30
+ id: data.id,
31
+ conflictedFiles
32
+ }
33
+ }
34
+ }
35
+
36
+ module.exports = SyncConflict