Skip to content

Commit 074595b

Browse files
committed
feat: added option to preserve newlines
1 parent 2396734 commit 074595b

File tree

3 files changed

+44
-12
lines changed

3 files changed

+44
-12
lines changed

src/secrets/CommandEdit.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ class CommandEdit extends CommandPolykey {
2222
this.addOption(binOptions.nodeId);
2323
this.addOption(binOptions.clientHost);
2424
this.addOption(binOptions.clientPort);
25-
this.action(async (secretPath, options) => {
25+
this.action(async (fullSecretPath, options) => {
26+
const vaultName = fullSecretPath[0];
27+
const secretPath = fullSecretPath[1] ?? '/';
2628
const os = await import('os');
2729
const { spawn } = await import('child_process');
2830
const vaultsErrors = await import('polykey/dist/vaults/errors');
@@ -60,13 +62,13 @@ class CommandEdit extends CommandPolykey {
6062
},
6163
logger: this.logger.getChild(PolykeyClient.name),
6264
});
63-
const tmpFile = path.join(tmpDir, path.basename(secretPath[1]));
65+
const tmpFile = path.join(tmpDir, path.basename(secretPath));
6466
const secretExists = await binUtils.retryAuthentication(
6567
async (auth) => {
6668
let exists = true;
6769
const response = await pkClient.rpcClient.methods.vaultsSecretsGet({
68-
nameOrId: secretPath[0],
69-
secretName: secretPath[1] ?? '/',
70+
nameOrId: vaultName,
71+
secretName: secretPath,
7072
metadata: auth,
7173
});
7274
try {
@@ -86,7 +88,7 @@ class CommandEdit extends CommandPolykey {
8688
// First, write the inline error to standard error like other
8789
// secrets commands do.
8890
process.stderr.write(
89-
`edit: ${secretPath[1] ?? '/'}: No such file or directory\n`,
91+
`edit: ${secretPath}: No such file or directory\n`,
9092
);
9193
// Then, throw an error to get the non-zero exit code. As this
9294
// command is Polykey-specific, the code doesn't really matter
@@ -160,8 +162,8 @@ class CommandEdit extends CommandPolykey {
160162
async (auth) =>
161163
await pkClient.rpcClient.methods.vaultsSecretsWriteFile({
162164
metadata: auth,
163-
nameOrId: secretPath[0],
164-
secretName: secretPath[1],
165+
nameOrId: vaultName,
166+
secretName: secretPath,
165167
secretContent: content,
166168
}),
167169
meta,

src/secrets/CommandEnv.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class CommandEnv extends CommandPolykey {
2424
this.addOption(binOptions.envDuplicate);
2525
this.addOption(binOptions.preserveNewline);
2626
this.argument(
27-
'<args...>',
27+
'[args...]',
2828
'command and arguments formatted as [envPaths...][-- cmd [cmdArgs...]]',
2929
binParsers.parseEnvArgs,
3030
);
@@ -34,7 +34,17 @@ class CommandEnv extends CommandPolykey {
3434
args: [Array<[string, string?, string?]>, Array<string>],
3535
options,
3636
) => {
37-
args[1].shift();
37+
// The parser sets the default value for args. If no arguments are
38+
// provided, then args is an empty array []. This is different from the
39+
// expected structure. This block ensure that the structure is preserved.
40+
args = args[0] == null && args[1] == null ? [[], []] : args;
41+
42+
// There needs to be at least one argument or preserved argument provided
43+
if (args[0].length === 0 && options.preserveNewline.length === 0) {
44+
this.help();
45+
}
46+
// Remove the -- from the command arguments
47+
args[1]?.shift();
3848
const { default: PolykeyClient } = await import(
3949
'polykey/dist/PolykeyClient'
4050
);
@@ -55,6 +65,10 @@ class CommandEnv extends CommandPolykey {
5565
// b. output the env variables in the desired format
5666

5767
const [envVariables, [cmd, ...argv]] = args;
68+
// Append the secret paths which we want to preserve the newlines of
69+
if (options.preserveNewline) {
70+
envVariables.push(...options.preserveNewline);
71+
}
5872
const clientOptions = await binProcessors.processClientOptions(
5973
options.nodePath,
6074
options.nodeId,
@@ -161,8 +175,20 @@ class CommandEnv extends CommandPolykey {
161175
utils.never();
162176
}
163177
}
178+
179+
// Find if we need to preserve the newline for this secret
180+
let preserveNewline = false;
181+
if (options.preserveNewline) {
182+
for (const pair of options.preserveNewline) {
183+
if (pair[1] === secretName) {
184+
preserveNewline = true;
185+
break;
186+
}
187+
}
188+
}
189+
164190
// Trim the single trailing newline if it exists
165-
if (secretContent.endsWith('\n')) {
191+
if (!preserveNewline && secretContent.endsWith('\n')) {
166192
envp[newName] = secretContent.slice(0, -1);
167193
} else {
168194
envp[newName] = secretContent;

src/utils/options.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,10 +319,14 @@ const parents = new commander.Option(
319319
).default(false);
320320

321321
const preserveNewline = new commander.Option(
322-
'--preserve-newline <path>',
322+
'-pn --preserve-newline <path>',
323323
'Preserve the last trailing newline for the secret content',
324324
)
325-
.argParser(binParsers.parseSecretPathEnv)
325+
.argParser((value: string, previous: Array<[string, string?, string?]>) => {
326+
const out = previous ?? [];
327+
out.push(binParsers.parseSecretPathEnv(value));
328+
return out;
329+
})
326330
.default(undefined);
327331

328332
export {

0 commit comments

Comments
 (0)