yini-cli 1.3.0-beta → 1.3.1-beta
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/dist/commands/parseCommand.js +57 -12
- package/package.json +1 -1
|
@@ -3,8 +3,23 @@ import fs from 'node:fs';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import YINI from 'yini-parser';
|
|
5
5
|
import { getSerializer } from '../serializers/index.js';
|
|
6
|
-
import { debugPrint, printObject
|
|
6
|
+
import { debugPrint, printObject } from '../utils/print.js';
|
|
7
7
|
// -------------------------------------------------------------------------
|
|
8
|
+
const reportAction = (action, file, reason) => {
|
|
9
|
+
let txt = '';
|
|
10
|
+
if (reason) {
|
|
11
|
+
txt = `${action.padEnd(6)} "${file}" (${reason})`;
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
txt = `${action.padEnd(6)} "${file}"`;
|
|
15
|
+
}
|
|
16
|
+
if (action === 'skip') {
|
|
17
|
+
console.warn(txt);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
console.log(txt);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
8
23
|
/*
|
|
9
24
|
TODO / SHOULD-DO:
|
|
10
25
|
|
|
@@ -91,24 +106,46 @@ const doParseFile = (file, commandOptions, outputFormat, outputFile = '') => {
|
|
|
91
106
|
debugPrint('outputFormat = ' + outputFormat);
|
|
92
107
|
const parseOptions = {
|
|
93
108
|
strictMode: commandOptions.strict ?? false,
|
|
94
|
-
failLevel:
|
|
95
|
-
includeMetadata:
|
|
109
|
+
failLevel: commandOptions.bestEffort ? 'ignore-errors' : 'auto',
|
|
110
|
+
includeMetadata: false,
|
|
96
111
|
};
|
|
97
112
|
// If --best-effort then override fail-level.
|
|
98
|
-
if (commandOptions.bestEffort) {
|
|
99
|
-
|
|
100
|
-
}
|
|
113
|
+
// if (commandOptions.bestEffort) {
|
|
114
|
+
// parseOptions.failLevel = 'ignore-errors'
|
|
115
|
+
// }
|
|
101
116
|
try {
|
|
102
117
|
const parsed = YINI.parseFile(file, parseOptions);
|
|
103
118
|
const serializer = getSerializer(outputFormat);
|
|
104
119
|
const output = serializer.serialize(parsed);
|
|
105
120
|
if (outputFile) {
|
|
106
121
|
const resolved = path.resolve(outputFile);
|
|
107
|
-
enforceWritePolicy(file, resolved, commandOptions.overwrite);
|
|
122
|
+
const canWrite = enforceWritePolicy(file, resolved, commandOptions.overwrite);
|
|
123
|
+
if (!canWrite) {
|
|
124
|
+
if (commandOptions.verbose) {
|
|
125
|
+
console.log(`skip Skipping write to "${resolved}"`);
|
|
126
|
+
}
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
// Double check, if the file was actually changed by comparing the contents.
|
|
130
|
+
if (fs.existsSync(resolved) && fs.statSync(resolved).isFile()) {
|
|
131
|
+
const existing = fs.readFileSync(resolved, 'utf-8');
|
|
132
|
+
// Only write the output file if the content actually changed.
|
|
133
|
+
// Prevents constantly showing meaningless rewrites, in some cases.
|
|
134
|
+
if (existing === output) {
|
|
135
|
+
if (commandOptions.verbose) {
|
|
136
|
+
// console.log(
|
|
137
|
+
// `skip Output unchanged. Skipping write: "${resolved}"`,
|
|
138
|
+
// )
|
|
139
|
+
reportAction('skip', resolved, 'output unchanged');
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
108
144
|
// Write JSON output to file instead of stdout.
|
|
109
145
|
fs.writeFileSync(resolved, output, 'utf-8');
|
|
110
146
|
if (commandOptions.verbose) {
|
|
111
|
-
console.log(`Output written to file: "${outputFile}"`)
|
|
147
|
+
// console.log(`write Output written to file: "${outputFile}"`)
|
|
148
|
+
reportAction('write', resolved);
|
|
112
149
|
}
|
|
113
150
|
}
|
|
114
151
|
else {
|
|
@@ -123,19 +160,27 @@ const doParseFile = (file, commandOptions, outputFormat, outputFile = '') => {
|
|
|
123
160
|
};
|
|
124
161
|
const enforceWritePolicy = (srcPath, destPath, overwrite) => {
|
|
125
162
|
if (!fs.existsSync(destPath)) {
|
|
126
|
-
return; // File does not exist, OK to write.
|
|
163
|
+
return true; // File does not exist, OK to write.
|
|
127
164
|
}
|
|
128
165
|
const srcStat = fs.statSync(srcPath);
|
|
129
166
|
const destStat = fs.statSync(destPath);
|
|
130
|
-
|
|
167
|
+
// Only strictly newer triggers skip overwrite.
|
|
168
|
+
const destIsNewer = destStat.mtimeMs > srcStat.mtimeMs;
|
|
131
169
|
if (overwrite === true) {
|
|
132
|
-
return; // Explicit overwrite, OK.
|
|
170
|
+
return true; // Explicit overwrite, OK.
|
|
133
171
|
}
|
|
134
172
|
if (overwrite === false) {
|
|
135
173
|
throw new Error(`File "${destPath}" already exists. Overwriting disabled (--no-overwrite).`);
|
|
136
174
|
}
|
|
137
175
|
// Default policy (overwrite undefined).
|
|
138
176
|
if (destIsNewer) {
|
|
139
|
-
|
|
177
|
+
// console.warn(
|
|
178
|
+
// // `Destination file "${destPath}" is newer than source. Use --overwrite to force.`,
|
|
179
|
+
// //`Warning: destination file "${destPath}" is newer than source. Skipping write. Use --overwrite to force.`,
|
|
180
|
+
// `Warning: destination "${destPath}" is newer than source "${srcPath}". Skipping write. Use --overwrite to force.`,
|
|
181
|
+
// )
|
|
182
|
+
reportAction('skip', destPath, `newer than source "${srcPath}"`);
|
|
183
|
+
return false;
|
|
140
184
|
}
|
|
185
|
+
return true;
|
|
141
186
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yini-cli",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1-beta",
|
|
4
4
|
"description": "CLI tool for validating and converting YINI configuration files - an INI-like format with real structure, nested sections and strict or lenient modes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"yini",
|