@chriscode/hush 4.2.0 → 5.0.1
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/cli.js +58 -29
- package/dist/commands/check.d.ts +3 -3
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +30 -33
- package/dist/commands/decrypt.d.ts +2 -2
- package/dist/commands/decrypt.d.ts.map +1 -1
- package/dist/commands/decrypt.js +52 -55
- package/dist/commands/edit.d.ts +2 -2
- package/dist/commands/edit.d.ts.map +1 -1
- package/dist/commands/edit.js +10 -12
- package/dist/commands/encrypt.d.ts +2 -2
- package/dist/commands/encrypt.d.ts.map +1 -1
- package/dist/commands/encrypt.js +27 -29
- package/dist/commands/expansions.d.ts +2 -2
- package/dist/commands/expansions.d.ts.map +1 -1
- package/dist/commands/expansions.js +46 -44
- package/dist/commands/has.d.ts +2 -2
- package/dist/commands/has.d.ts.map +1 -1
- package/dist/commands/has.js +12 -15
- package/dist/commands/init.d.ts +2 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +107 -87
- package/dist/commands/inspect.d.ts +2 -2
- package/dist/commands/inspect.d.ts.map +1 -1
- package/dist/commands/inspect.js +14 -16
- package/dist/commands/keys.d.ts +2 -1
- package/dist/commands/keys.d.ts.map +1 -1
- package/dist/commands/keys.js +47 -49
- package/dist/commands/list.d.ts +2 -2
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +11 -14
- package/dist/commands/migrate.d.ts +7 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +117 -0
- package/dist/commands/push.d.ts +2 -2
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +41 -45
- package/dist/commands/resolve.d.ts +2 -2
- package/dist/commands/resolve.d.ts.map +1 -1
- package/dist/commands/resolve.js +25 -28
- package/dist/commands/run.d.ts +2 -2
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +35 -39
- package/dist/commands/set.d.ts +2 -2
- package/dist/commands/set.d.ts.map +1 -1
- package/dist/commands/set.js +61 -70
- package/dist/commands/skill.d.ts +2 -2
- package/dist/commands/skill.d.ts.map +1 -1
- package/dist/commands/skill.js +186 -487
- package/dist/commands/status.d.ts +2 -2
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +52 -55
- package/dist/commands/template.d.ts +2 -2
- package/dist/commands/template.d.ts.map +1 -1
- package/dist/commands/template.js +36 -39
- package/dist/commands/trace.d.ts +2 -2
- package/dist/commands/trace.d.ts.map +1 -1
- package/dist/commands/trace.js +16 -19
- package/dist/config/loader.js +3 -3
- package/dist/context.d.ts +3 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +59 -0
- package/dist/core/parse.js +3 -3
- package/dist/core/sops.js +9 -9
- package/dist/core/template.d.ts +2 -2
- package/dist/core/template.d.ts.map +1 -1
- package/dist/core/template.js +11 -12
- package/dist/lib/age.js +9 -9
- package/dist/lib/fs.d.ts +25 -0
- package/dist/lib/fs.d.ts.map +1 -0
- package/dist/lib/fs.js +36 -0
- package/dist/lib/onepassword.d.ts.map +1 -1
- package/dist/lib/onepassword.js +41 -4
- package/dist/types.d.ts +91 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -4
- package/dist/utils/version-check.js +5 -5
- package/package.json +3 -2
package/dist/commands/set.js
CHANGED
|
@@ -1,74 +1,65 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process';
|
|
2
|
-
import { existsSync, fstatSync } from 'node:fs';
|
|
3
1
|
import { join } from 'node:path';
|
|
4
2
|
import { platform } from 'node:os';
|
|
5
3
|
import pc from 'picocolors';
|
|
6
|
-
import { loadConfig } from '../config/loader.js';
|
|
7
4
|
import { setKey } from '../core/sops.js';
|
|
8
|
-
|
|
9
|
-
function hasStdinPipe() {
|
|
5
|
+
function hasStdinPipe(ctx) {
|
|
10
6
|
try {
|
|
11
|
-
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
const stat = fstatSync(STDIN_FD);
|
|
15
|
-
return stat.isFIFO() || stat.isFile();
|
|
7
|
+
return !ctx.process.stdin.isTTY;
|
|
16
8
|
}
|
|
17
9
|
catch {
|
|
18
10
|
return false;
|
|
19
11
|
}
|
|
20
12
|
}
|
|
21
|
-
function readFromStdinPipe() {
|
|
13
|
+
function readFromStdinPipe(ctx) {
|
|
22
14
|
return new Promise((resolve, reject) => {
|
|
23
15
|
let data = '';
|
|
24
|
-
process.stdin.setEncoding('utf8');
|
|
25
|
-
process.stdin.on('data', (chunk) => {
|
|
16
|
+
ctx.process.stdin.setEncoding('utf8');
|
|
17
|
+
ctx.process.stdin.on('data', (chunk) => {
|
|
26
18
|
data += chunk;
|
|
27
19
|
});
|
|
28
|
-
process.stdin.on('end', () => {
|
|
20
|
+
ctx.process.stdin.on('end', () => {
|
|
29
21
|
const trimTrailingNewlines = /\n+$/;
|
|
30
22
|
resolve(data.replace(trimTrailingNewlines, ''));
|
|
31
23
|
});
|
|
32
|
-
process.stdin.on('error', reject);
|
|
33
|
-
process.stdin.resume();
|
|
24
|
+
ctx.process.stdin.on('error', reject);
|
|
25
|
+
ctx.process.stdin.resume();
|
|
34
26
|
});
|
|
35
27
|
}
|
|
36
|
-
function promptViaMacOSDialog(key) {
|
|
28
|
+
function promptViaMacOSDialog(ctx, key) {
|
|
37
29
|
try {
|
|
38
|
-
const script = `display dialog "Enter value for ${key}:" default answer "" with
|
|
39
|
-
const result = execSync(`osascript -e '${script}' -e 'text returned of result'`, {
|
|
30
|
+
const script = `display dialog "Enter value for ${key}:" default answer "" with title "Hush - Set Secret"`;
|
|
31
|
+
const result = ctx.exec.execSync(`osascript -e '${script}' -e 'text returned of result'`, {
|
|
40
32
|
encoding: 'utf-8',
|
|
41
33
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
42
34
|
});
|
|
43
|
-
return result.trim();
|
|
35
|
+
return result.toString().trim();
|
|
44
36
|
}
|
|
45
37
|
catch {
|
|
46
38
|
return null;
|
|
47
39
|
}
|
|
48
40
|
}
|
|
49
|
-
function promptViaWindowsDialog(key) {
|
|
41
|
+
function promptViaWindowsDialog(ctx, key) {
|
|
50
42
|
try {
|
|
51
43
|
const psScript = `
|
|
52
44
|
Add-Type -AssemblyName System.Windows.Forms
|
|
53
45
|
Add-Type -AssemblyName System.Drawing
|
|
54
|
-
|
|
46
|
+
|
|
55
47
|
$form = New-Object System.Windows.Forms.Form
|
|
56
48
|
$form.Text = 'Hush - Set Secret'
|
|
57
49
|
$form.Size = New-Object System.Drawing.Size(300,150)
|
|
58
50
|
$form.StartPosition = 'CenterScreen'
|
|
59
|
-
|
|
51
|
+
|
|
60
52
|
$label = New-Object System.Windows.Forms.Label
|
|
61
53
|
$label.Location = New-Object System.Drawing.Point(10,20)
|
|
62
54
|
$label.Size = New-Object System.Drawing.Size(280,20)
|
|
63
55
|
$label.Text = 'Enter value for ${key}:'
|
|
64
56
|
$form.Controls.Add($label)
|
|
65
|
-
|
|
57
|
+
|
|
66
58
|
$textBox = New-Object System.Windows.Forms.TextBox
|
|
67
59
|
$textBox.Location = New-Object System.Drawing.Point(10,50)
|
|
68
60
|
$textBox.Size = New-Object System.Drawing.Size(260,20)
|
|
69
|
-
$textBox.PasswordChar = '*'
|
|
70
61
|
$form.Controls.Add($textBox)
|
|
71
|
-
|
|
62
|
+
|
|
72
63
|
$okButton = New-Object System.Windows.Forms.Button
|
|
73
64
|
$okButton.Location = New-Object System.Drawing.Point(10,80)
|
|
74
65
|
$okButton.Size = New-Object System.Drawing.Size(75,23)
|
|
@@ -76,11 +67,11 @@ function promptViaWindowsDialog(key) {
|
|
|
76
67
|
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
|
|
77
68
|
$form.AcceptButton = $okButton
|
|
78
69
|
$form.Controls.Add($okButton)
|
|
79
|
-
|
|
70
|
+
|
|
80
71
|
$form.TopMost = $true
|
|
81
|
-
|
|
72
|
+
|
|
82
73
|
$result = $form.ShowDialog()
|
|
83
|
-
|
|
74
|
+
|
|
84
75
|
if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
|
|
85
76
|
Write-Output $textBox.Text
|
|
86
77
|
} else {
|
|
@@ -88,41 +79,41 @@ function promptViaWindowsDialog(key) {
|
|
|
88
79
|
}
|
|
89
80
|
`;
|
|
90
81
|
const encodedCommand = Buffer.from(psScript, 'utf16le').toString('base64');
|
|
91
|
-
const result = execSync(`powershell -EncodedCommand "${encodedCommand}"`, {
|
|
82
|
+
const result = ctx.exec.execSync(`powershell -EncodedCommand "${encodedCommand}"`, {
|
|
92
83
|
encoding: 'utf-8',
|
|
93
84
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
94
85
|
});
|
|
95
|
-
return result.trim();
|
|
86
|
+
return result.toString().trim();
|
|
96
87
|
}
|
|
97
88
|
catch {
|
|
98
89
|
return null;
|
|
99
90
|
}
|
|
100
91
|
}
|
|
101
|
-
function promptViaLinuxDialog(key) {
|
|
92
|
+
function promptViaLinuxDialog(ctx, key) {
|
|
102
93
|
try {
|
|
103
|
-
const result = execSync(`zenity --
|
|
94
|
+
const result = ctx.exec.execSync(`zenity --entry --title="Hush - Set Secret" --text="Enter value for ${key}:"`, {
|
|
104
95
|
encoding: 'utf-8',
|
|
105
96
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
106
97
|
});
|
|
107
|
-
return result.trim();
|
|
98
|
+
return result.toString().trim();
|
|
108
99
|
}
|
|
109
100
|
catch {
|
|
110
101
|
try {
|
|
111
|
-
const result = execSync(`kdialog --
|
|
102
|
+
const result = ctx.exec.execSync(`kdialog --inputbox "Enter value for ${key}:" --title "Hush - Set Secret"`, {
|
|
112
103
|
encoding: 'utf-8',
|
|
113
104
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
114
105
|
});
|
|
115
|
-
return result.trim();
|
|
106
|
+
return result.toString().trim();
|
|
116
107
|
}
|
|
117
108
|
catch {
|
|
118
109
|
return null;
|
|
119
110
|
}
|
|
120
111
|
}
|
|
121
112
|
}
|
|
122
|
-
function promptViaTTY(key) {
|
|
113
|
+
function promptViaTTY(ctx, key) {
|
|
123
114
|
return new Promise((resolve, reject) => {
|
|
124
|
-
process.stdout.write(`Enter value for ${pc.cyan(key)}: `);
|
|
125
|
-
const stdin = process.stdin;
|
|
115
|
+
ctx.process.stdout.write(`Enter value for ${pc.cyan(key)}: `);
|
|
116
|
+
const stdin = ctx.process.stdin;
|
|
126
117
|
stdin.setRawMode(true);
|
|
127
118
|
stdin.resume();
|
|
128
119
|
stdin.setEncoding('utf8');
|
|
@@ -135,49 +126,49 @@ function promptViaTTY(key) {
|
|
|
135
126
|
stdin.setRawMode(false);
|
|
136
127
|
stdin.pause();
|
|
137
128
|
stdin.removeListener('data', onData);
|
|
138
|
-
process.stdout.write('\n');
|
|
129
|
+
ctx.process.stdout.write('\n');
|
|
139
130
|
resolve(value);
|
|
140
131
|
break;
|
|
141
132
|
case '\u0003':
|
|
142
133
|
stdin.setRawMode(false);
|
|
143
134
|
stdin.pause();
|
|
144
135
|
stdin.removeListener('data', onData);
|
|
145
|
-
process.stdout.write('\n');
|
|
136
|
+
ctx.process.stdout.write('\n');
|
|
146
137
|
reject(new Error('Cancelled'));
|
|
147
138
|
break;
|
|
148
139
|
case '\u007F':
|
|
149
140
|
case '\b':
|
|
150
141
|
if (value.length > 0) {
|
|
151
142
|
value = value.slice(0, -1);
|
|
152
|
-
process.stdout.write('\b \b');
|
|
143
|
+
ctx.process.stdout.write('\b \b');
|
|
153
144
|
}
|
|
154
145
|
break;
|
|
155
146
|
default:
|
|
156
147
|
value += char;
|
|
157
|
-
process.stdout.write('\u2022');
|
|
148
|
+
ctx.process.stdout.write('\u2022');
|
|
158
149
|
}
|
|
159
150
|
};
|
|
160
151
|
stdin.on('data', onData);
|
|
161
152
|
});
|
|
162
153
|
}
|
|
163
|
-
async function promptForValue(key, forceGui) {
|
|
164
|
-
if (hasStdinPipe()) {
|
|
165
|
-
return readFromStdinPipe();
|
|
154
|
+
async function promptForValue(ctx, key, forceGui) {
|
|
155
|
+
if (hasStdinPipe(ctx)) {
|
|
156
|
+
return readFromStdinPipe(ctx);
|
|
166
157
|
}
|
|
167
|
-
if (process.stdin.isTTY && !forceGui) {
|
|
168
|
-
return promptViaTTY(key);
|
|
158
|
+
if (ctx.process.stdin.isTTY && !forceGui) {
|
|
159
|
+
return promptViaTTY(ctx, key);
|
|
169
160
|
}
|
|
170
|
-
|
|
161
|
+
ctx.logger.log(pc.dim('Opening dialog for secret input...'));
|
|
171
162
|
let value = null;
|
|
172
163
|
switch (platform()) {
|
|
173
164
|
case 'darwin':
|
|
174
|
-
value = promptViaMacOSDialog(key);
|
|
165
|
+
value = promptViaMacOSDialog(ctx, key);
|
|
175
166
|
break;
|
|
176
167
|
case 'win32':
|
|
177
|
-
value = promptViaWindowsDialog(key);
|
|
168
|
+
value = promptViaWindowsDialog(ctx, key);
|
|
178
169
|
break;
|
|
179
170
|
case 'linux':
|
|
180
|
-
value = promptViaLinuxDialog(key);
|
|
171
|
+
value = promptViaLinuxDialog(ctx, key);
|
|
181
172
|
break;
|
|
182
173
|
}
|
|
183
174
|
if (value !== null) {
|
|
@@ -188,39 +179,39 @@ async function promptForValue(key, forceGui) {
|
|
|
188
179
|
}
|
|
189
180
|
throw new Error('Dialog cancelled or failed. Interactive input requires a terminal (TTY) or a supported GUI environment.');
|
|
190
181
|
}
|
|
191
|
-
export async function setCommand(options) {
|
|
192
|
-
const { root, file, key, gui } = options;
|
|
193
|
-
const config = loadConfig(root);
|
|
182
|
+
export async function setCommand(ctx, options) {
|
|
183
|
+
const { root, file, key, value: inlineValue, gui } = options;
|
|
184
|
+
const config = ctx.config.loadConfig(root);
|
|
194
185
|
const fileKey = file ?? 'shared';
|
|
195
186
|
const sourcePath = config.sources[fileKey];
|
|
196
187
|
const encryptedPath = join(root, sourcePath + '.encrypted');
|
|
197
188
|
if (!key) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
process.exit(1);
|
|
189
|
+
ctx.logger.error(pc.red('Usage: hush set <KEY> [-e environment]'));
|
|
190
|
+
ctx.logger.error(pc.dim('Example: hush set DATABASE_URL'));
|
|
191
|
+
ctx.logger.error(pc.dim(' hush set API_KEY -e production'));
|
|
192
|
+
ctx.logger.error(pc.dim('\nTo edit all secrets in an editor, use: hush edit'));
|
|
193
|
+
ctx.process.exit(1);
|
|
203
194
|
}
|
|
204
|
-
if (!existsSync(encryptedPath) && !existsSync(join(root, '.sops.yaml'))) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
process.exit(1);
|
|
195
|
+
if (!ctx.fs.existsSync(encryptedPath) && !ctx.fs.existsSync(join(root, '.sops.yaml'))) {
|
|
196
|
+
ctx.logger.error(pc.red('Hush is not initialized in this directory'));
|
|
197
|
+
ctx.logger.error(pc.dim('Run "hush init" first, then "hush encrypt"'));
|
|
198
|
+
ctx.process.exit(1);
|
|
208
199
|
}
|
|
209
200
|
try {
|
|
210
|
-
const value = await promptForValue(key, gui ?? false);
|
|
201
|
+
const value = inlineValue ?? await promptForValue(ctx, key, gui ?? false);
|
|
211
202
|
if (!value) {
|
|
212
|
-
|
|
213
|
-
process.exit(1);
|
|
203
|
+
ctx.logger.error(pc.yellow('No value entered, aborting'));
|
|
204
|
+
ctx.process.exit(1);
|
|
214
205
|
}
|
|
215
206
|
setKey(encryptedPath, key, value);
|
|
216
207
|
const envLabel = fileKey === 'shared' ? '' : ` in ${fileKey}`;
|
|
217
|
-
|
|
208
|
+
ctx.logger.log(pc.green(`\n${key} set${envLabel} (${value.length} chars, encrypted)`));
|
|
218
209
|
}
|
|
219
210
|
catch (error) {
|
|
220
211
|
const err = error;
|
|
221
212
|
if (err.message === 'Cancelled') {
|
|
222
|
-
|
|
223
|
-
process.exit(1);
|
|
213
|
+
ctx.logger.log(pc.yellow('Cancelled'));
|
|
214
|
+
ctx.process.exit(1);
|
|
224
215
|
}
|
|
225
216
|
throw err;
|
|
226
217
|
}
|
package/dist/commands/skill.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { SkillOptions } from '../types.js';
|
|
2
|
-
export declare function skillCommand(options: SkillOptions): Promise<void>;
|
|
1
|
+
import type { HushContext, SkillOptions } from '../types.js';
|
|
2
|
+
export declare function skillCommand(ctx: HushContext, options: SkillOptions): Promise<void>;
|
|
3
3
|
//# sourceMappingURL=skill.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAkvC7D,wBAAsB,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CzF"}
|