git-sshripped 0.1.4
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/README.md +95 -0
- package/bin/git-sshripped +95 -0
- package/package.json +33 -0
- package/src/index.js +101 -0
package/README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# git-sshripped
|
|
2
|
+
|
|
3
|
+
Git-transparent encryption using SSH keys. No GPG, no Rust toolchain required.
|
|
4
|
+
|
|
5
|
+
This is the npm distribution of [git-sshripped](https://github.com/BSteffaniak/git-sshripped), a tool that keeps selected files encrypted at rest in Git repositories while letting developers work with plaintext when the repo is unlocked.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install git-sshripped
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This installs a prebuilt native binary for your platform. No Rust or Cargo needed.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### CLI
|
|
18
|
+
|
|
19
|
+
Once installed, `git-sshripped` is available as a command:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Initialize in a repo
|
|
23
|
+
git-sshripped init --pattern "secrets/**"
|
|
24
|
+
|
|
25
|
+
# Unlock (decrypt files for local development)
|
|
26
|
+
git-sshripped unlock
|
|
27
|
+
|
|
28
|
+
# Lock (scrub plaintext from working tree)
|
|
29
|
+
git-sshripped lock
|
|
30
|
+
|
|
31
|
+
# Check status
|
|
32
|
+
git-sshripped status
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Auto-unlock in postinstall
|
|
36
|
+
|
|
37
|
+
Add this to your project's `package.json` so that encrypted files are automatically decrypted after `npm install`:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"scripts": {
|
|
42
|
+
"postinstall": "git-sshripped unlock --soft"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The `--soft` flag ensures that `npm install` won't fail if the user doesn't have access to the encrypted files (e.g., they don't have the right SSH key, or they're a CI bot without credentials). A warning is printed instead.
|
|
48
|
+
|
|
49
|
+
For strict mode (fail if unlock fails):
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"scripts": {
|
|
54
|
+
"postinstall": "git-sshripped unlock"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Programmatic API
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
const { binaryPath, run } = require("git-sshripped");
|
|
63
|
+
|
|
64
|
+
// Get the path to the binary
|
|
65
|
+
console.log(binaryPath);
|
|
66
|
+
|
|
67
|
+
// Spawn git-sshripped with arguments
|
|
68
|
+
const child = run(["status", "--json"]);
|
|
69
|
+
child.on("exit", (code) => {
|
|
70
|
+
console.log("exit code:", code);
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Binary resolution
|
|
75
|
+
|
|
76
|
+
The binary is resolved in this order:
|
|
77
|
+
|
|
78
|
+
1. `GIT_SSHRIPPED_BINARY_PATH` environment variable
|
|
79
|
+
2. Platform-specific npm package (installed automatically via `optionalDependencies`)
|
|
80
|
+
3. System-installed `git-sshripped` found in `PATH`
|
|
81
|
+
|
|
82
|
+
## Supported platforms
|
|
83
|
+
|
|
84
|
+
| Platform | Architecture | npm package |
|
|
85
|
+
|----------|-------------|-------------|
|
|
86
|
+
| macOS | ARM64 (Apple Silicon) | `@git-sshripped/darwin-arm64` |
|
|
87
|
+
| macOS | x64 (Intel) | `@git-sshripped/darwin-x64` |
|
|
88
|
+
| Linux | x64 (glibc) | `@git-sshripped/linux-x64` |
|
|
89
|
+
| Linux | ARM64 (glibc) | `@git-sshripped/linux-arm64` |
|
|
90
|
+
| Linux | x64 (musl/Alpine) | `@git-sshripped/linux-x64-musl` |
|
|
91
|
+
| Windows | x64 | `@git-sshripped/win32-x64` |
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
MPL-2.0
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const { platform, arch, env, argv } = process;
|
|
5
|
+
const { execSync, spawnSync } = require("child_process");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
|
|
8
|
+
function isMusl() {
|
|
9
|
+
// On non-linux, musl detection is irrelevant
|
|
10
|
+
if (platform !== "linux") return false;
|
|
11
|
+
try {
|
|
12
|
+
const stderr = execSync("ldd --version 2>&1", {
|
|
13
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
14
|
+
}).toString();
|
|
15
|
+
if (stderr.indexOf("musl") > -1) return true;
|
|
16
|
+
} catch (err) {
|
|
17
|
+
// ldd --version exits non-zero on musl systems and prints to stderr
|
|
18
|
+
if (err.stderr && err.stderr.toString().indexOf("musl") > -1) return true;
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const PLATFORMS = {
|
|
24
|
+
win32: {
|
|
25
|
+
x64: "@git-sshripped/win32-x64/git-sshripped.exe",
|
|
26
|
+
},
|
|
27
|
+
darwin: {
|
|
28
|
+
x64: "@git-sshripped/darwin-x64/git-sshripped",
|
|
29
|
+
arm64: "@git-sshripped/darwin-arm64/git-sshripped",
|
|
30
|
+
},
|
|
31
|
+
linux: {
|
|
32
|
+
x64: "@git-sshripped/linux-x64/git-sshripped",
|
|
33
|
+
arm64: "@git-sshripped/linux-arm64/git-sshripped",
|
|
34
|
+
},
|
|
35
|
+
"linux-musl": {
|
|
36
|
+
x64: "@git-sshripped/linux-x64-musl/git-sshripped",
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
function getBinaryPath() {
|
|
41
|
+
// 1. Environment variable override
|
|
42
|
+
if (env.GIT_SSHRIPPED_BINARY_PATH) {
|
|
43
|
+
return env.GIT_SSHRIPPED_BINARY_PATH;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 2. Resolve from platform-specific package
|
|
47
|
+
const platformKey =
|
|
48
|
+
platform === "linux" && isMusl() ? "linux-musl" : platform;
|
|
49
|
+
const subpath = PLATFORMS?.[platformKey]?.[arch];
|
|
50
|
+
|
|
51
|
+
if (subpath) {
|
|
52
|
+
try {
|
|
53
|
+
return require.resolve(subpath);
|
|
54
|
+
} catch {
|
|
55
|
+
// Platform package not installed, fall through
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 3. Fallback: look for git-sshripped in PATH
|
|
60
|
+
try {
|
|
61
|
+
const which = platform === "win32" ? "where" : "which";
|
|
62
|
+
const resolved = execSync(`${which} git-sshripped`, {
|
|
63
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
64
|
+
})
|
|
65
|
+
.toString()
|
|
66
|
+
.trim()
|
|
67
|
+
.split("\n")[0];
|
|
68
|
+
if (resolved) return resolved;
|
|
69
|
+
} catch {
|
|
70
|
+
// Not found in PATH
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 4. Give up with a helpful error
|
|
74
|
+
console.error(
|
|
75
|
+
`Error: No prebuilt git-sshripped binary available for ${platform}/${arch}.
|
|
76
|
+
|
|
77
|
+
To fix this, either:
|
|
78
|
+
- Install git-sshripped via cargo: cargo install git_sshripped_cli
|
|
79
|
+
- Set GIT_SSHRIPPED_BINARY_PATH to point to a git-sshripped binary
|
|
80
|
+
- File an issue: https://github.com/BSteffaniak/git-sshripped/issues`
|
|
81
|
+
);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const binPath = getBinaryPath();
|
|
86
|
+
const result = spawnSync(binPath, argv.slice(2), {
|
|
87
|
+
shell: false,
|
|
88
|
+
stdio: "inherit",
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
if (result.error) {
|
|
92
|
+
throw result.error;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
process.exitCode = result.status;
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "git-sshripped",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Git-transparent encryption using SSH keys. No GPG, no Rust toolchain required.",
|
|
5
|
+
"license": "MPL-2.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/BSteffaniak/git-sshripped.git"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"git-sshripped": "bin/git-sshripped"
|
|
12
|
+
},
|
|
13
|
+
"main": "src/index.js",
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=18"
|
|
16
|
+
},
|
|
17
|
+
"optionalDependencies": {
|
|
18
|
+
"@git-sshripped/darwin-arm64": "0.1.4",
|
|
19
|
+
"@git-sshripped/darwin-x64": "0.1.4",
|
|
20
|
+
"@git-sshripped/linux-arm64": "0.1.4",
|
|
21
|
+
"@git-sshripped/linux-x64": "0.1.4",
|
|
22
|
+
"@git-sshripped/linux-x64-musl": "0.1.4",
|
|
23
|
+
"@git-sshripped/win32-x64": "0.1.4"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"bin/",
|
|
27
|
+
"src/"
|
|
28
|
+
],
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public",
|
|
31
|
+
"registry": "https://registry.npmjs.org"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { platform, arch } = process;
|
|
4
|
+
const { execSync, spawn } = require("child_process");
|
|
5
|
+
const { env } = process;
|
|
6
|
+
|
|
7
|
+
function isMusl() {
|
|
8
|
+
if (platform !== "linux") return false;
|
|
9
|
+
try {
|
|
10
|
+
const stderr = execSync("ldd --version 2>&1", {
|
|
11
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
12
|
+
}).toString();
|
|
13
|
+
if (stderr.indexOf("musl") > -1) return true;
|
|
14
|
+
} catch (err) {
|
|
15
|
+
if (err.stderr && err.stderr.toString().indexOf("musl") > -1) return true;
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const PLATFORMS = {
|
|
21
|
+
win32: {
|
|
22
|
+
x64: "@git-sshripped/win32-x64/git-sshripped.exe",
|
|
23
|
+
},
|
|
24
|
+
darwin: {
|
|
25
|
+
x64: "@git-sshripped/darwin-x64/git-sshripped",
|
|
26
|
+
arm64: "@git-sshripped/darwin-arm64/git-sshripped",
|
|
27
|
+
},
|
|
28
|
+
linux: {
|
|
29
|
+
x64: "@git-sshripped/linux-x64/git-sshripped",
|
|
30
|
+
arm64: "@git-sshripped/linux-arm64/git-sshripped",
|
|
31
|
+
},
|
|
32
|
+
"linux-musl": {
|
|
33
|
+
x64: "@git-sshripped/linux-x64-musl/git-sshripped",
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Resolves the path to the git-sshripped binary.
|
|
39
|
+
*
|
|
40
|
+
* Resolution order:
|
|
41
|
+
* 1. GIT_SSHRIPPED_BINARY_PATH environment variable
|
|
42
|
+
* 2. Platform-specific npm package
|
|
43
|
+
* 3. System-installed binary in PATH
|
|
44
|
+
*
|
|
45
|
+
* @returns {string} Absolute path to the binary
|
|
46
|
+
* @throws {Error} If no binary can be found
|
|
47
|
+
*/
|
|
48
|
+
function getBinaryPath() {
|
|
49
|
+
if (env.GIT_SSHRIPPED_BINARY_PATH) {
|
|
50
|
+
return env.GIT_SSHRIPPED_BINARY_PATH;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const platformKey =
|
|
54
|
+
platform === "linux" && isMusl() ? "linux-musl" : platform;
|
|
55
|
+
const subpath = PLATFORMS?.[platformKey]?.[arch];
|
|
56
|
+
|
|
57
|
+
if (subpath) {
|
|
58
|
+
try {
|
|
59
|
+
return require.resolve(subpath);
|
|
60
|
+
} catch {
|
|
61
|
+
// Platform package not installed
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const which = platform === "win32" ? "where" : "which";
|
|
67
|
+
const resolved = execSync(`${which} git-sshripped`, {
|
|
68
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
69
|
+
})
|
|
70
|
+
.toString()
|
|
71
|
+
.trim()
|
|
72
|
+
.split("\n")[0];
|
|
73
|
+
if (resolved) return resolved;
|
|
74
|
+
} catch {
|
|
75
|
+
// Not found in PATH
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
throw new Error(
|
|
79
|
+
`No prebuilt git-sshripped binary available for ${platform}/${arch}. ` +
|
|
80
|
+
`Install via cargo (cargo install git_sshripped_cli) or set GIT_SSHRIPPED_BINARY_PATH.`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The resolved path to the git-sshripped binary.
|
|
86
|
+
* @type {string}
|
|
87
|
+
*/
|
|
88
|
+
const binaryPath = getBinaryPath();
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Spawn git-sshripped with the given arguments.
|
|
92
|
+
*
|
|
93
|
+
* @param {string[]} args - Command-line arguments to pass
|
|
94
|
+
* @param {import("child_process").SpawnOptions} [options] - Options passed to child_process.spawn
|
|
95
|
+
* @returns {import("child_process").ChildProcess}
|
|
96
|
+
*/
|
|
97
|
+
function run(args, options) {
|
|
98
|
+
return spawn(binaryPath, args, { stdio: "inherit", ...options });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
module.exports = { binaryPath, run };
|