@chriscode/hush 5.0.0 → 5.0.2

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.
Files changed (77) hide show
  1. package/dist/cli.js +39 -26
  2. package/dist/commands/check.d.ts +3 -3
  3. package/dist/commands/check.d.ts.map +1 -1
  4. package/dist/commands/check.js +27 -31
  5. package/dist/commands/decrypt.d.ts +2 -2
  6. package/dist/commands/decrypt.d.ts.map +1 -1
  7. package/dist/commands/decrypt.js +52 -55
  8. package/dist/commands/edit.d.ts +2 -2
  9. package/dist/commands/edit.d.ts.map +1 -1
  10. package/dist/commands/edit.js +10 -12
  11. package/dist/commands/encrypt.d.ts +2 -2
  12. package/dist/commands/encrypt.d.ts.map +1 -1
  13. package/dist/commands/encrypt.js +27 -29
  14. package/dist/commands/expansions.d.ts +2 -2
  15. package/dist/commands/expansions.d.ts.map +1 -1
  16. package/dist/commands/expansions.js +46 -44
  17. package/dist/commands/has.d.ts +2 -2
  18. package/dist/commands/has.d.ts.map +1 -1
  19. package/dist/commands/has.js +12 -15
  20. package/dist/commands/init.d.ts +2 -2
  21. package/dist/commands/init.d.ts.map +1 -1
  22. package/dist/commands/init.js +92 -100
  23. package/dist/commands/inspect.d.ts +2 -2
  24. package/dist/commands/inspect.d.ts.map +1 -1
  25. package/dist/commands/inspect.js +14 -16
  26. package/dist/commands/keys.d.ts +2 -1
  27. package/dist/commands/keys.d.ts.map +1 -1
  28. package/dist/commands/keys.js +47 -49
  29. package/dist/commands/list.d.ts +2 -2
  30. package/dist/commands/list.d.ts.map +1 -1
  31. package/dist/commands/list.js +11 -14
  32. package/dist/commands/migrate.d.ts +2 -1
  33. package/dist/commands/migrate.d.ts.map +1 -1
  34. package/dist/commands/migrate.js +38 -37
  35. package/dist/commands/push.d.ts +2 -2
  36. package/dist/commands/push.d.ts.map +1 -1
  37. package/dist/commands/push.js +41 -45
  38. package/dist/commands/resolve.d.ts +2 -2
  39. package/dist/commands/resolve.d.ts.map +1 -1
  40. package/dist/commands/resolve.js +25 -28
  41. package/dist/commands/run.d.ts +2 -2
  42. package/dist/commands/run.d.ts.map +1 -1
  43. package/dist/commands/run.js +35 -39
  44. package/dist/commands/set.d.ts +2 -2
  45. package/dist/commands/set.d.ts.map +1 -1
  46. package/dist/commands/set.js +61 -70
  47. package/dist/commands/skill.d.ts +2 -2
  48. package/dist/commands/skill.d.ts.map +1 -1
  49. package/dist/commands/skill.js +149 -459
  50. package/dist/commands/status.d.ts +2 -2
  51. package/dist/commands/status.d.ts.map +1 -1
  52. package/dist/commands/status.js +48 -52
  53. package/dist/commands/template.d.ts +2 -2
  54. package/dist/commands/template.d.ts.map +1 -1
  55. package/dist/commands/template.js +36 -39
  56. package/dist/commands/trace.d.ts +2 -2
  57. package/dist/commands/trace.d.ts.map +1 -1
  58. package/dist/commands/trace.js +16 -19
  59. package/dist/config/loader.js +3 -3
  60. package/dist/context.d.ts +3 -0
  61. package/dist/context.d.ts.map +1 -0
  62. package/dist/context.js +60 -0
  63. package/dist/core/parse.js +3 -3
  64. package/dist/core/sops.js +9 -9
  65. package/dist/core/template.d.ts +2 -2
  66. package/dist/core/template.d.ts.map +1 -1
  67. package/dist/core/template.js +11 -12
  68. package/dist/lib/age.js +9 -9
  69. package/dist/lib/fs.d.ts +25 -0
  70. package/dist/lib/fs.d.ts.map +1 -0
  71. package/dist/lib/fs.js +36 -0
  72. package/dist/lib/onepassword.d.ts.map +1 -1
  73. package/dist/lib/onepassword.js +41 -4
  74. package/dist/types.d.ts +92 -0
  75. package/dist/types.d.ts.map +1 -1
  76. package/dist/utils/version-check.js +5 -5
  77. package/package.json +3 -2
@@ -1 +1 @@
1
- {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/core/template.ts"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AASvD,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,WAAW,GACf,mBAAmB,CAqCrB;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EAAE,EACtB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,OAAO,GAAE,kBAAuB,GAC/B,MAAM,EAAE,CAQV"}
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/core/template.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AASpE,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,WAAW,EAChB,EAAE,EAAE,WAAW,CAAC,IAAI,CAAC,GACpB,mBAAmB,CAqCrB;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EAAE,EACtB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,OAAO,GAAE,kBAAuB,GAC/B,MAAM,EAAE,CAQV"}
@@ -1,31 +1,30 @@
1
- import { existsSync, readFileSync } from 'node:fs';
2
1
  import { join } from 'node:path';
3
2
  import { parseEnvContent } from './parse.js';
4
3
  import { mergeVars } from './merge.js';
5
4
  import { interpolateVars } from './interpolate.js';
6
5
  const TEMPLATE_FILES = {
7
- base: '.env',
8
- development: '.env.development',
9
- production: '.env.production',
10
- local: '.env.local',
6
+ base: '.hush',
7
+ development: '.hush.development',
8
+ production: '.hush.production',
9
+ local: '.hush.local',
11
10
  };
12
- export function loadLocalTemplates(contextDir, env) {
11
+ export function loadLocalTemplates(contextDir, env, fs) {
13
12
  const files = [];
14
13
  const varSources = [];
15
14
  const basePath = join(contextDir, TEMPLATE_FILES.base);
16
- if (existsSync(basePath)) {
15
+ if (fs.existsSync(basePath)) {
17
16
  files.push(TEMPLATE_FILES.base);
18
- varSources.push(parseEnvContent(readFileSync(basePath, 'utf-8')));
17
+ varSources.push(parseEnvContent(fs.readFileSync(basePath, 'utf-8')));
19
18
  }
20
19
  const envPath = join(contextDir, TEMPLATE_FILES[env]);
21
- if (existsSync(envPath)) {
20
+ if (fs.existsSync(envPath)) {
22
21
  files.push(TEMPLATE_FILES[env]);
23
- varSources.push(parseEnvContent(readFileSync(envPath, 'utf-8')));
22
+ varSources.push(parseEnvContent(fs.readFileSync(envPath, 'utf-8')));
24
23
  }
25
24
  const localPath = join(contextDir, TEMPLATE_FILES.local);
26
- if (existsSync(localPath)) {
25
+ if (fs.existsSync(localPath)) {
27
26
  files.push(TEMPLATE_FILES.local);
28
- varSources.push(parseEnvContent(readFileSync(localPath, 'utf-8')));
27
+ varSources.push(parseEnvContent(fs.readFileSync(localPath, 'utf-8')));
29
28
  }
30
29
  if (varSources.length === 0) {
31
30
  return {
package/dist/lib/age.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { execSync } from 'node:child_process';
2
- import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
2
+ import { fs } from './fs.js';
3
3
  import { join, dirname } from 'node:path';
4
4
  import { homedir } from 'node:os';
5
5
  const KEYS_DIR = join(homedir(), '.config', 'sops', 'age', 'keys');
@@ -30,29 +30,29 @@ export function keyPath(project) {
30
30
  return join(KEYS_DIR, `${project.replace(/\//g, '-')}.txt`);
31
31
  }
32
32
  export function keyExists(project) {
33
- return existsSync(keyPath(project));
33
+ return fs.existsSync(keyPath(project));
34
34
  }
35
35
  export function keySave(project, key) {
36
36
  const path = keyPath(project);
37
- mkdirSync(dirname(path), { recursive: true });
38
- writeFileSync(path, `# project: ${project}\n# public key: ${key.public}\n${key.private}\n`, { mode: 0o600 });
37
+ fs.mkdirSync(dirname(path), { recursive: true });
38
+ fs.writeFileSync(path, `# project: ${project}\n# public key: ${key.public}\n${key.private}\n`, { mode: 0o600 });
39
39
  }
40
40
  export function keyLoad(project) {
41
41
  const path = keyPath(project);
42
- if (!existsSync(path))
42
+ if (!fs.existsSync(path))
43
43
  return null;
44
- const content = readFileSync(path, 'utf-8');
44
+ const content = fs.readFileSync(path, 'utf-8');
45
45
  const pub = content.match(/# public key: (age1[a-z0-9]+)/)?.[1];
46
46
  const priv = content.match(/(AGE-SECRET-KEY-[A-Z0-9]+)/)?.[1];
47
47
  return pub && priv ? { private: priv, public: pub } : null;
48
48
  }
49
49
  export function keysList() {
50
- if (!existsSync(KEYS_DIR))
50
+ if (!fs.existsSync(KEYS_DIR))
51
51
  return [];
52
- return readdirSync(KEYS_DIR)
52
+ return fs.readdirSync(KEYS_DIR)
53
53
  .filter(f => f.endsWith('.txt'))
54
54
  .map(f => {
55
- const content = readFileSync(join(KEYS_DIR, f), 'utf-8');
55
+ const content = fs.readFileSync(join(KEYS_DIR, f), 'utf-8');
56
56
  const project = content.match(/# project: (.+)/)?.[1] ?? content.match(/# repo: (.+)/)?.[1];
57
57
  const pub = content.match(/# public key: (age1[a-z0-9]+)/)?.[1];
58
58
  return project && pub ? { project, public: pub } : null;
@@ -0,0 +1,25 @@
1
+ import { type PathLike, type WriteFileOptions } from 'node:fs';
2
+ /**
3
+ * Filesystem wrapper to allow for easier testing and isolation of side effects.
4
+ * All core logic and commands should use these instead of direct node:fs calls.
5
+ */
6
+ export declare const fs: {
7
+ existsSync: (path: PathLike) => boolean;
8
+ readFileSync: (path: PathLike, options?: {
9
+ encoding?: BufferEncoding;
10
+ flag?: string;
11
+ } | BufferEncoding) => string | Buffer;
12
+ writeFileSync: (path: PathLike, data: string | Uint8Array, options?: WriteFileOptions) => void;
13
+ mkdirSync: (path: PathLike, options?: {
14
+ recursive?: boolean;
15
+ mode?: number;
16
+ }) => string | undefined;
17
+ readdirSync: (path: PathLike, options?: {
18
+ recursive?: boolean;
19
+ }) => string[];
20
+ unlinkSync: (path: PathLike) => void;
21
+ statSync: (path: PathLike) => import("fs").Stats;
22
+ fstatSync: (fd: number) => import("fs").Stats;
23
+ renameSync: (oldPath: PathLike, newPath: PathLike) => void;
24
+ };
25
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/lib/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAUL,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACtB,MAAM,SAAS,CAAC;AAEjB;;;GAGG;AAEH,eAAO,MAAM,EAAE;uBACM,QAAQ,KAAG,OAAO;yBAIhB,QAAQ,YAAY;QAAE,QAAQ,CAAC,EAAE,cAAc,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,cAAc,KAAG,MAAM,GAAG,MAAM;0BAKlG,QAAQ,QAAQ,MAAM,GAAG,UAAU,YAAY,gBAAgB,KAAG,IAAI;sBAI1E,QAAQ,YAAY;QAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAG,MAAM,GAAG,SAAS;wBAI7E,QAAQ,YAAY;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,KAAG,MAAM,EAAE;uBAKvD,QAAQ,KAAG,IAAI;qBAIjB,QAAQ;oBAIT,MAAM;0BAIA,QAAQ,WAAW,QAAQ,KAAG,IAAI;CAGzD,CAAC"}
package/dist/lib/fs.js ADDED
@@ -0,0 +1,36 @@
1
+ import { existsSync as nodeExistsSync, readFileSync as nodeReadFileSync, writeFileSync as nodeWriteFileSync, mkdirSync as nodeMkdirSync, readdirSync as nodeReaddirSync, unlinkSync as nodeUnlinkSync, statSync as nodeStatSync, fstatSync as nodeFstatSync, renameSync as nodeRenameSync, } from 'node:fs';
2
+ /**
3
+ * Filesystem wrapper to allow for easier testing and isolation of side effects.
4
+ * All core logic and commands should use these instead of direct node:fs calls.
5
+ */
6
+ export const fs = {
7
+ existsSync: (path) => {
8
+ return nodeExistsSync(path);
9
+ },
10
+ readFileSync: (path, options) => {
11
+ // @ts-ignore - handled by overloads in node:fs
12
+ return nodeReadFileSync(path, options);
13
+ },
14
+ writeFileSync: (path, data, options) => {
15
+ nodeWriteFileSync(path, data, options);
16
+ },
17
+ mkdirSync: (path, options) => {
18
+ return nodeMkdirSync(path, options);
19
+ },
20
+ readdirSync: (path, options) => {
21
+ // @ts-ignore - handled by node:fs
22
+ return nodeReaddirSync(path, options);
23
+ },
24
+ unlinkSync: (path) => {
25
+ nodeUnlinkSync(path);
26
+ },
27
+ statSync: (path) => {
28
+ return nodeStatSync(path);
29
+ },
30
+ fstatSync: (fd) => {
31
+ return nodeFstatSync(fd);
32
+ },
33
+ renameSync: (oldPath, newPath) => {
34
+ nodeRenameSync(oldPath, newPath);
35
+ }
36
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"onepassword.d.ts","sourceRoot":"","sources":["../../src/lib/onepassword.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,qBAAqB,CAAC;AAUjD,wBAAgB,WAAW,IAAI,OAAO,CAOrC;AAED,wBAAgB,WAAW,IAAI,OAAO,CAOrC;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASvE;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAiBvG;AAED,wBAAgB,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAYnD"}
1
+ {"version":3,"file":"onepassword.d.ts","sourceRoot":"","sources":["../../src/lib/onepassword.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc,qBAAqB,CAAC;AA8CjD,wBAAgB,WAAW,IAAI,OAAO,CAOrC;AAED,wBAAgB,WAAW,IAAI,OAAO,CAOrC;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASvE;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAiBvG;AAED,wBAAgB,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAYnD"}
@@ -1,6 +1,43 @@
1
1
  import { execSync } from 'node:child_process';
2
+ import { platform } from 'node:os';
2
3
  export const OP_ITEM_PREFIX = 'SOPS Key - hush/';
3
- function opExec(command) {
4
+ function showBiometricNotification(reason) {
5
+ const title = 'Hush - 1Password';
6
+ const message = `${reason}\n\n1Password biometric prompt will appear next.`;
7
+ try {
8
+ switch (platform()) {
9
+ case 'darwin': {
10
+ const script = `display dialog "${message}" with title "${title}" buttons {"Continue"} default button "Continue" with icon note`;
11
+ execSync(`osascript -e '${script}'`, { stdio: 'pipe' });
12
+ break;
13
+ }
14
+ case 'win32': {
15
+ const psScript = `
16
+ Add-Type -AssemblyName System.Windows.Forms
17
+ [System.Windows.Forms.MessageBox]::Show("${message}", "${title}", "OK", "Information")
18
+ `;
19
+ execSync(`powershell -Command "${psScript}"`, { stdio: 'pipe' });
20
+ break;
21
+ }
22
+ case 'linux': {
23
+ try {
24
+ execSync(`zenity --info --title="${title}" --text="${message}"`, { stdio: 'pipe' });
25
+ }
26
+ catch {
27
+ execSync(`kdialog --msgbox "${message}" --title "${title}"`, { stdio: 'pipe' });
28
+ }
29
+ break;
30
+ }
31
+ }
32
+ }
33
+ catch {
34
+ // If GUI fails, fall through silently - better to continue than block
35
+ }
36
+ }
37
+ function opExec(command, reason) {
38
+ if (reason) {
39
+ showBiometricNotification(reason);
40
+ }
4
41
  return execSync(`op signin && ${command}`, {
5
42
  encoding: 'utf-8',
6
43
  stdio: 'pipe',
@@ -29,7 +66,7 @@ export function opGetKey(project, vault) {
29
66
  try {
30
67
  const vaultArgs = vault ? ['--vault', vault] : [];
31
68
  const command = ['op', 'item', 'get', `${OP_ITEM_PREFIX}${project}`, ...vaultArgs, '--fields', 'password', '--reveal'].join(' ');
32
- const result = opExec(command);
69
+ const result = opExec(command, `Retrieving encryption key for "${project}" from 1Password.`);
33
70
  return result.trim() || null;
34
71
  }
35
72
  catch {
@@ -47,7 +84,7 @@ export function opStoreKey(project, privateKey, publicKey, vault) {
47
84
  `"public_key[text]=${publicKey}"`,
48
85
  ].join(' ');
49
86
  try {
50
- opExec(command);
87
+ opExec(command, `Backing up encryption key for "${project}" to 1Password.`);
51
88
  }
52
89
  catch (err) {
53
90
  const message = err instanceof Error ? err.message : 'Failed to store in 1Password';
@@ -58,7 +95,7 @@ export function opListKeys(vault) {
58
95
  try {
59
96
  const vaultArgs = vault ? ['--vault', vault] : [];
60
97
  const command = ['op', 'item', 'list', '--categories', 'password', ...vaultArgs, '--format', 'json'].join(' ');
61
- const result = opExec(command);
98
+ const result = opExec(command, 'Listing Hush encryption keys stored in 1Password.');
62
99
  const items = JSON.parse(result);
63
100
  return items
64
101
  .filter(i => i.title.startsWith(OP_ITEM_PREFIX))
package/dist/types.d.ts CHANGED
@@ -50,6 +50,7 @@ export interface SetOptions {
50
50
  root: string;
51
51
  file?: 'shared' | 'development' | 'production' | 'local';
52
52
  key?: string;
53
+ value?: string;
53
54
  gui?: boolean;
54
55
  }
55
56
  export interface RunOptions {
@@ -119,4 +120,95 @@ export interface TraceOptions {
119
120
  }
120
121
  export declare const DEFAULT_SOURCES: SourceFiles;
121
122
  export declare const FORMAT_OUTPUT_FILES: Record<OutputFormat, Record<Environment, string>>;
123
+ export interface HushContext {
124
+ fs: {
125
+ existsSync(path: string): boolean;
126
+ readFileSync(path: string, options?: {
127
+ encoding?: BufferEncoding;
128
+ flag?: string;
129
+ } | BufferEncoding): string | Buffer;
130
+ writeFileSync(path: string, data: string | Uint8Array, options?: {
131
+ encoding?: BufferEncoding;
132
+ mode?: number;
133
+ flag?: string;
134
+ } | BufferEncoding | null): void;
135
+ mkdirSync(path: string, options?: {
136
+ recursive?: boolean;
137
+ mode?: number;
138
+ }): string | undefined;
139
+ readdirSync(path: string, options?: {
140
+ recursive?: boolean;
141
+ withFileTypes?: boolean;
142
+ }): (string | {
143
+ name: string;
144
+ isDirectory(): boolean;
145
+ })[];
146
+ unlinkSync(path: string): void;
147
+ statSync(path: string): {
148
+ isDirectory(): boolean;
149
+ mtime: Date;
150
+ };
151
+ renameSync(oldPath: string, newPath: string): void;
152
+ };
153
+ path: {
154
+ join(...paths: string[]): string;
155
+ };
156
+ exec: {
157
+ spawnSync(command: string, args: string[], options?: any): {
158
+ status: number | null;
159
+ stdout: string | Buffer;
160
+ stderr: string | Buffer;
161
+ error?: Error;
162
+ };
163
+ execSync(command: string, options?: any): string | Buffer;
164
+ };
165
+ logger: {
166
+ log(message: string): void;
167
+ error(message: string): void;
168
+ warn(message: string): void;
169
+ info(message: string): void;
170
+ };
171
+ process: {
172
+ cwd(): string;
173
+ exit(code: number): never;
174
+ env: NodeJS.ProcessEnv;
175
+ stdin: NodeJS.ReadStream;
176
+ stdout: NodeJS.WriteStream;
177
+ };
178
+ config: {
179
+ loadConfig(root: string): HushConfig;
180
+ findProjectRoot(startDir: string): {
181
+ configPath: string;
182
+ projectRoot: string;
183
+ } | null;
184
+ };
185
+ age: {
186
+ ageAvailable(): boolean;
187
+ ageGenerate(): {
188
+ private: string;
189
+ public: string;
190
+ };
191
+ keyExists(project: string): boolean;
192
+ keySave(project: string, key: {
193
+ private: string;
194
+ public: string;
195
+ }): void;
196
+ keyPath(project: string): string;
197
+ keyLoad(project: string): {
198
+ private: string;
199
+ public: string;
200
+ } | null;
201
+ agePublicFromPrivate(privateKey: string): string;
202
+ };
203
+ onepassword: {
204
+ opInstalled(): boolean;
205
+ opAvailable(): boolean;
206
+ opGetKey(project: string): string | null;
207
+ opStoreKey(project: string, privateKey: string, publicKey: string): void;
208
+ };
209
+ sops: {
210
+ decrypt(path: string): string;
211
+ isSopsInstalled(): boolean;
212
+ };
213
+ }
122
214
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { existsSync, mkdirSync, readFileSync } from 'node:fs';
1
+ import { fs } from '../lib/fs.js';
2
2
  import { join } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
4
  import { spawn } from 'node:child_process';
@@ -8,13 +8,13 @@ const CACHE_FILE = join(CONFIG_DIR, 'update-check.json');
8
8
  const CHECK_INTERVAL_MS = 1000 * 60 * 60 * 24;
9
9
  export function checkForUpdate(currentVersion) {
10
10
  try {
11
- if (!existsSync(CONFIG_DIR)) {
12
- mkdirSync(CONFIG_DIR, { recursive: true });
11
+ if (!fs.existsSync(CONFIG_DIR)) {
12
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
13
13
  }
14
14
  let cache = null;
15
- if (existsSync(CACHE_FILE)) {
15
+ if (fs.existsSync(CACHE_FILE)) {
16
16
  try {
17
- cache = JSON.parse(readFileSync(CACHE_FILE, 'utf-8'));
17
+ cache = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf-8'));
18
18
  }
19
19
  catch {
20
20
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chriscode/hush",
3
- "version": "5.0.0",
3
+ "version": "5.0.2",
4
4
  "description": "SOPS-based secrets management for monorepos. Encrypt once, decrypt everywhere.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -52,8 +52,9 @@
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/node": "^20.11.0",
55
+ "@vitest/coverage-v8": "^4.0.17",
55
56
  "typescript": "^5.8.3",
56
- "vitest": "^2.0.0"
57
+ "vitest": "^4.0.17"
57
58
  },
58
59
  "files": [
59
60
  "dist",