Support for onlyAppend mode

master
Dominik Dzienia 2 years ago
parent 57caea14cb
commit 6bf0f19d3d

@ -34,6 +34,8 @@ This can be changed by options:
* `--onlyUpdate` - prevents new keys to be appended, only existing keys are updated
* `--smartAppend` - finds most similar group of variables and appends new variables between them, preserving alphabetical order.
To disable updating (overwriting) existing keys, and only append (supplement with) new keys, use `--onlyAppend`
To operate on files, specify input file(s) with `-i` and output file with `-o`. To modify first input file use `-m`.
### Modify files
@ -57,6 +59,7 @@ Options:
-m, --modify Modify first input file
-b, --beautify Beautifies resulting env file
-u, --onlyUpdate Only updates existing values, without appending new values
-a, --onlyAppend Only append new values, without updating existing values
-p, --smartAppend Smart appends variables depending on their names
-r, --resilient Ignore files that cannot be read during update
-s, --silent Mute all messages and errors
@ -144,6 +147,7 @@ Both `update` as well as `stringifyTokens` take `config` parameter:
type Config = {
beautify?: boolean; // if true, output will be beautified/normalized. Default: false
enforceNewLineEnd?: boolean; // if true, output will have ensured \n character at end. Default: true
noUpdate?: boolean; // if true, only new values will be appended, but existing one wont be updated
modifyMode?: ModifyMode; // decide if new keys should or should not be added, and where. Default: ModifyMode.APPEND
};
```

@ -215,12 +215,24 @@ describe('Update command', () => {
expect(mockStdout).toHaveBeenCalledWith('SERVER_PORT=8080\nSERVER_HOST=localhost\nSERVER_PASSWORD=secret\nCLIENT_HOST=192.168.4.42\nCLIENT_PORT=3000\n');
});
it('merge files without update', () => {
program.parse(['node', 'test', '-a', '-i', 'first.env', 'second.env', 'third.env']);
expect(mockExit).toBeCalled();
expect(mockStdout).toHaveBeenCalledWith('SERVER_PORT=80\nSERVER_HOST=localhost\nSERVER_PASSWORD=secret\nCLIENT_HOST=192.168.4.42\nCLIENT_PORT=3000\n');
});
it('merge files with smart append', () => {
program.parse(['node', 'test', '-p', '-i', 'first.env', 'second.env', 'third.env']);
expect(mockExit).toBeCalled();
expect(mockStdout).toHaveBeenCalledWith('CLIENT_HOST=192.168.4.42\nCLIENT_PORT=3000\nSERVER_PASSWORD=secret\nSERVER_PORT=8080\nSERVER_HOST=localhost\n');
});
it('merge files with smart append without update', () => {
program.parse(['node', 'test', '-p', '-a', '-i', 'first.env', 'second.env', 'third.env']);
expect(mockExit).toBeCalled();
expect(mockStdout).toHaveBeenCalledWith('CLIENT_HOST=192.168.4.42\nCLIENT_PORT=3000\nSERVER_PASSWORD=secret\nSERVER_PORT=80\nSERVER_HOST=localhost\n');
});
it('merge files and set from parameter', () => {
program.parse(['node', 'test', '-i', 'first.env', 'second.env', 'third.env', '--', 'SERVER_PASSWORD=updated value']);
expect(mockExit).toBeCalled();
@ -229,6 +241,14 @@ describe('Update command', () => {
);
});
it('merge files and set from parameter without update', () => {
program.parse(['node', 'test', '-a', '-i', 'first.env', 'second.env', 'third.env', '--', 'SERVER_PASSWORD=tried updated value', 'NEW_VALUE=append']);
expect(mockExit).toBeCalled();
expect(mockStdout).toHaveBeenCalledWith(
'SERVER_PORT=80\nSERVER_HOST=localhost\nSERVER_PASSWORD=secret\nCLIENT_HOST=192.168.4.42\nCLIENT_PORT=3000\nNEW_VALUE=append\n',
);
});
it('merge files and set from parameter and invalid parameter', () => {
program.parse(['node', 'test', '-i', 'first.env', 'second.env', 'third.env', '--', 'SERVER_PASSWORD=updated value', 'INVA LID', 'LAST_ARGUMENT=correct']);
expect(mockExit).toHaveBeenCalledWith(1);

@ -101,6 +101,7 @@ export function makeProgram() {
.option('-m, --modify', 'Modify first input file')
.option('-b, --beautify', 'Beautifies resulting env file')
.option('-u, --onlyUpdate', 'Only updates existing values, without appending new values')
.option('-a, --onlyAppend', 'Only append new values, without updating existing values')
.option('-p, --smartAppend', 'Smart appends variables depending on their names')
.option('-r, --resilient', 'Ignore files that cannot be read during update')
.option('-s, --silent', 'Mute all messages and errors')
@ -128,6 +129,7 @@ export function makeProgram() {
let sourceParsingError = '';
config.beautify = options.beautify || false;
config.noUpdate = options.onlyAppend || false;
config.modifyMode = options.onlyUpdate ? ModifyMode.NO_APPEND : options.smartAppend ? ModifyMode.SMART_APPEND : ModifyMode.APPEND;
const baseData = inputData.shift() || '';

@ -104,6 +104,64 @@ describe('Updating tokens', () => {
);
});
it('do not update in append only mode', () => {
expect(stringifyTokens(update([vtoken('ALA', 'ma kota')], [['ALA', 'ma psa']], { modifyMode: ModifyMode.APPEND, noUpdate: true }))).toEqual('ALA="ma kota"\n');
expect(
stringifyTokens(
update(
[vtoken('ALA', 'ma kota')],
[
['ALA', 'ma psa'],
['ALA', 'ma jednak kota'],
],
{ modifyMode: ModifyMode.APPEND, noUpdate: true },
),
),
).toEqual('ALA="ma kota"\n');
expect(
stringifyTokens(
update(
[vtoken('HOST', '127.0.0.1'), nltoken(), vtoken('PORT', '80'), nltoken(), vtoken('LOGIN', 'root')],
[['LOGIN', 'debian'], { name: 'PORT', value: '8080', comment: ' # debug only' }],
{ modifyMode: ModifyMode.APPEND, noUpdate: true },
),
),
).toEqual('HOST=127.0.0.1\nPORT=80\nLOGIN=root\n');
expect(
stringifyTokens(
update(
[
ctoken('###########'),
nltoken(),
ctoken('# Server'),
nltoken(),
ctoken('###########'),
nltoken('\n\n'),
vtoken('SERVER_HOST', '127.0.0.1'),
nltoken(),
vtoken('SERVER_PORT', '80'),
nltoken(),
vtoken('SERVER_LOGIN', 'root'),
nltoken('\n\n'),
ctoken('###########'),
nltoken(),
ctoken('# Client'),
nltoken(),
ctoken('###########'),
nltoken('\n\n'),
vtoken('CLIENT_LOGIN', 'john'),
],
[['SERVER_LOGIN', 'debian'], { name: 'SERVER_PORT', value: '8080', comment: ' # debug only' }, ['SERVER_PASSWORD', 'secret']],
{ modifyMode: ModifyMode.APPEND, noUpdate: true },
),
),
).toEqual(
'###########\n# Server\n###########\n\nSERVER_HOST=127.0.0.1\nSERVER_PORT=80\nSERVER_LOGIN=root\n\n###########\n# Client\n###########\n\nCLIENT_LOGIN=john\nSERVER_PASSWORD=secret\n',
);
});
it('delete value', () => {
expect(
stringifyTokens(
@ -227,6 +285,108 @@ describe('Updating tokens', () => {
'###########\n# Server\n###########\n\nSERVER_HOST=127.0.0.1\nSERVER_PASSWORD=secret\nSERVER_PORT=8080 # debug only\nSERVER_LOGIN=debian\n\n###########\n# Client\n###########\n\nCLIENT_LOGIN=john\n',
);
});
it('appends smart with no update config', () => {
expect(
stringifyTokens(
update(
[
vtoken('SERVER_HOST', '127.0.0.1'),
vtoken('SERVER_PORT', '80'),
vtoken('SERVER_LOGIN', 'root'),
ctoken('#-------------------------'),
vtoken('CLIENT_LOGIN', 'john'),
vtoken('CLIENT_X_AXIS', '12'),
ctoken('#-------------------------'),
vtoken('AUTO_RUN', 'true'),
vtoken('AUTO_CLEAN', 'false'),
],
[
['CLIENT_ACCESS', 'limited'],
['SERVER_OUTPUT', '/dev/null'],
['CLIENT_Z_AXIS', '100'],
['ZOOM', '100%'],
['AUTO_STOP', 'true'],
['QUALITY', '90%'],
['AUTO_APPEND', 'true'],
['AUTO_ZERO', '000'],
],
{ modifyMode: ModifyMode.SMART_APPEND, noUpdate: true },
),
),
).toEqual(
'SERVER_HOST=127.0.0.1\nSERVER_OUTPUT=/dev/null\nSERVER_PORT=80\nSERVER_LOGIN=root\n' +
'#-------------------------\n' +
'CLIENT_ACCESS=limited\nCLIENT_LOGIN=john\nCLIENT_X_AXIS=12\nCLIENT_Z_AXIS=100\n' +
'#-------------------------\n' +
'AUTO_APPEND=true\nAUTO_RUN=true\nAUTO_CLEAN=false\nAUTO_STOP=true\nAUTO_ZERO=000\n' +
'QUALITY=90%\nZOOM=100%\n',
);
expect(
stringifyTokens(
update(
[],
[
['SERVER_HOST', '127.0.0.1'],
['SERVER_PORT', '80'],
['SERVER_LOGIN', 'root'],
['CLIENT_LOGIN', 'john'],
['CLIENT_X_AXIS', '12'],
['AUTO_RUN', 'true'],
['AUTO_CLEAN', 'false'],
['CLIENT_ACCESS', 'limited'],
['SERVER_OUTPUT', '/dev/null'],
['CLIENT_Z_AXIS', '100'],
['ZOOM', '100%'],
['AUTO_STOP', 'true'],
['QUALITY', '90%'],
['AUTO_APPEND', 'true'],
['AUTO_ZERO', '000'],
],
{ modifyMode: ModifyMode.SMART_APPEND, noUpdate: true },
),
),
).toEqual(
'AUTO_APPEND=true\nAUTO_CLEAN=false\nAUTO_RUN=true\nAUTO_STOP=true\nAUTO_ZERO=000\n' +
'CLIENT_ACCESS=limited\nCLIENT_LOGIN=john\nCLIENT_X_AXIS=12\nCLIENT_Z_AXIS=100\n' +
'QUALITY=90%\n' +
'SERVER_HOST=127.0.0.1\nSERVER_LOGIN=root\nSERVER_OUTPUT=/dev/null\nSERVER_PORT=80\n' +
'ZOOM=100%\n',
);
expect(
stringifyTokens(
update(
[
ctoken('###########'),
nltoken(),
ctoken('# Server'),
nltoken(),
ctoken('###########'),
nltoken('\n\n'),
vtoken('SERVER_HOST', '127.0.0.1'),
nltoken(),
vtoken('SERVER_PORT', '80'),
nltoken(),
vtoken('SERVER_LOGIN', 'root'),
nltoken('\n\n'),
ctoken('###########'),
nltoken(),
ctoken('# Client'),
nltoken(),
ctoken('###########'),
nltoken('\n\n'),
vtoken('CLIENT_LOGIN', 'john'),
],
[['SERVER_LOGIN', 'debian'], { name: 'SERVER_PORT', value: '8080', comment: ' # debug only' }, ['SERVER_PASSWORD', 'secret']],
{ modifyMode: ModifyMode.SMART_APPEND, noUpdate: true },
),
),
).toEqual(
'###########\n# Server\n###########\n\nSERVER_HOST=127.0.0.1\nSERVER_PASSWORD=secret\nSERVER_PORT=80\nSERVER_LOGIN=root\n\n###########\n# Client\n###########\n\nCLIENT_LOGIN=john\n',
);
});
});
describe('Fixing token list', () => {

@ -106,6 +106,9 @@ export function update(tokens: Token[], updateWith: VariableToUpdate[], config?:
const updateVar: Variable | VariableToken = Array.isArray(u) ? { name: u[0], value: u[1] } : u;
const tokenToUpdate = tokens.findIndex((t) => t.token === TokenType.VARIABLE && (t as VariableToken).name === updateVar.name);
if (tokenToUpdate > -1) {
if (config?.noUpdate) {
return;
}
// delete
if (updateVar.value == null) {
if (tokenToUpdate < tokens.length - 1 && tokens[tokenToUpdate + 1].token === TokenType.NEWLINE) {

@ -35,6 +35,7 @@ export type Variable = {
export type Config = {
beautify?: boolean;
noUpdate?: boolean;
enforceNewLineEnd?: boolean;
modifyMode?: ModifyMode;
};

Loading…
Cancel
Save