@lpm-registry/cli 0.58.0 → 0.59.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/README.md +25 -44
- package/bin/lpm.js +2 -354
- package/bin/lpx.js +4 -0
- package/bin/native.js +154 -0
- package/package.json +42 -82
- package/scripts/install-binary.js +219 -550
- package/CHANGELOG.md +0 -197
- package/LICENSE +0 -15
- package/index.d.ts +0 -131
- package/index.js +0 -31
- package/lib/api.js +0 -398
- package/lib/commands/add.js +0 -1217
- package/lib/commands/audit.js +0 -283
- package/lib/commands/cache.js +0 -209
- package/lib/commands/check-name.js +0 -112
- package/lib/commands/config.js +0 -186
- package/lib/commands/doctor.js +0 -140
- package/lib/commands/info.js +0 -215
- package/lib/commands/init.js +0 -146
- package/lib/commands/install.js +0 -264
- package/lib/commands/login.js +0 -595
- package/lib/commands/logout.js +0 -94
- package/lib/commands/marketplace-compare.js +0 -164
- package/lib/commands/marketplace-earnings.js +0 -89
- package/lib/commands/mcp-setup.js +0 -363
- package/lib/commands/npmrc.js +0 -178
- package/lib/commands/open.js +0 -82
- package/lib/commands/outdated.js +0 -291
- package/lib/commands/pool-stats.js +0 -100
- package/lib/commands/publish.js +0 -949
- package/lib/commands/quality.js +0 -211
- package/lib/commands/remove.js +0 -82
- package/lib/commands/run.js +0 -14
- package/lib/commands/search.js +0 -143
- package/lib/commands/setup.js +0 -221
- package/lib/commands/skills.js +0 -898
- package/lib/commands/token-rotate.js +0 -25
- package/lib/commands/uninstall.js +0 -107
- package/lib/commands/whoami.js +0 -129
- package/lib/config.js +0 -328
- package/lib/constants.js +0 -190
- package/lib/ecosystem.js +0 -501
- package/lib/editor-skills.js +0 -321
- package/lib/editors.js +0 -215
- package/lib/import-rewriter.js +0 -364
- package/lib/install-targets/mcp-server.js +0 -245
- package/lib/install-targets/vscode-extension.js +0 -178
- package/lib/install-targets.js +0 -82
- package/lib/integrity.js +0 -179
- package/lib/lpm-config-prompts.js +0 -102
- package/lib/lpm-config.js +0 -408
- package/lib/oidc.js +0 -166
- package/lib/project-utils.js +0 -152
- package/lib/quality/checks.js +0 -687
- package/lib/quality/display.js +0 -155
- package/lib/quality/score.js +0 -118
- package/lib/quality/swift-checks.js +0 -447
- package/lib/safe-path.js +0 -180
- package/lib/secure-store.js +0 -321
- package/lib/swift-project.js +0 -637
- package/lib/ui.js +0 -40
- package/scripts/__tests__/install-binary.test.js +0 -346
package/README.md
CHANGED
|
@@ -1,64 +1,45 @@
|
|
|
1
|
-
# LPM
|
|
1
|
+
# LPM CLI
|
|
2
2
|
|
|
3
|
-
Fast, secure, all-in-one
|
|
3
|
+
Fast, secure, all-in-one package manager written in Rust.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npm install -g @lpm-registry/cli
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
This package is the npm gateway for the native LPM CLI. It installs a small
|
|
10
|
+
JavaScript launcher plus the matching platform package, such as
|
|
11
|
+
`@lpm-registry/cli-darwin-arm64` or `@lpm-registry/cli-linux-x64`. A tiny
|
|
12
|
+
`postinstall` verifier checks the native binary and wires the global command to
|
|
13
|
+
it where the platform allows that.
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
curl -fsSL https://lpm.dev/install.sh | sh # Standalone
|
|
15
|
-
cargo install --git https://github.com/lpm-dev/rust-client lpm-cli # Source
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
</details>
|
|
19
|
-
|
|
20
|
-
## About This Package
|
|
21
|
-
|
|
22
|
-
This npm package is a thin wrapper that downloads the native Rust binary on `postinstall`. All CLI functionality is provided by the Rust client — see [lpm-dev/rust-client](https://github.com/lpm-dev/rust-client) for full documentation, benchmarks, and the complete command reference.
|
|
15
|
+
The JavaScript launcher does not implement package-manager behavior. All CLI
|
|
16
|
+
commands run in the native Rust binary.
|
|
23
17
|
|
|
24
|
-
|
|
18
|
+
Source for this npm package lives in `lpm-dev/rust-client/npm/cli`.
|
|
25
19
|
|
|
26
|
-
##
|
|
20
|
+
## Updating
|
|
27
21
|
|
|
28
22
|
```bash
|
|
29
|
-
lpm
|
|
30
|
-
lpm install # Install deps (aliases: i)
|
|
31
|
-
lpm publish # Publish to lpm.dev (aliases: p)
|
|
32
|
-
lpm dev # Zero-config dev server + HTTPS + tunnel
|
|
23
|
+
lpm self-update
|
|
33
24
|
```
|
|
34
25
|
|
|
35
|
-
|
|
26
|
+
When LPM was installed through npm, self-update runs:
|
|
36
27
|
|
|
37
|
-
|
|
28
|
+
```bash
|
|
29
|
+
npm install -g @lpm-registry/cli@<version>
|
|
30
|
+
```
|
|
38
31
|
|
|
39
|
-
##
|
|
32
|
+
## Troubleshooting
|
|
40
33
|
|
|
41
|
-
|
|
34
|
+
If your package manager was configured to omit optional dependencies, reinstall
|
|
35
|
+
with optional dependencies enabled:
|
|
42
36
|
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
generateIntegrity,
|
|
46
|
-
verifyIntegrity,
|
|
47
|
-
runQualityChecks,
|
|
48
|
-
parseLpmPackageReference,
|
|
49
|
-
detectFramework,
|
|
50
|
-
} from "@lpm-registry/cli";
|
|
37
|
+
```bash
|
|
38
|
+
npm install -g @lpm-registry/cli
|
|
51
39
|
```
|
|
52
40
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
| `generateIntegrity(buffer, algorithm?)` | Generate an SRI integrity hash (default: `sha512`) |
|
|
56
|
-
| `verifyIntegrity(buffer, expected)` | Verify a buffer against an SRI integrity string |
|
|
57
|
-
| `runQualityChecks({ packageJson, readme, ... })` | Run all 28 quality checks and return score, tier, and checks |
|
|
58
|
-
| `parseLpmPackageReference(ref)` | Parse `@lpm.dev/owner.pkg@version?key=val` into components |
|
|
59
|
-
| `readLpmConfig(dir)` | Read and validate `lpm.config.json` from a directory |
|
|
60
|
-
| `detectFramework()` | Detect the project framework (nextjs, vite, remix, astro) |
|
|
61
|
-
|
|
62
|
-
## License
|
|
41
|
+
If install scripts were disabled, reinstall without `--ignore-scripts` so npm
|
|
42
|
+
can validate the native binary during installation.
|
|
63
43
|
|
|
64
|
-
|
|
44
|
+
Other install methods are documented at
|
|
45
|
+
[github.com/lpm-dev/rust-client](https://github.com/lpm-dev/rust-client).
|
package/bin/lpm.js
CHANGED
|
@@ -1,356 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { runNativeCommand } from "./native.js";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
* LPM CLI Entry Point — Minimal fallback wrapper.
|
|
5
|
-
*
|
|
6
|
-
* In most cases, this file has been replaced by a hard link to the native
|
|
7
|
-
* Rust binary during postinstall (zero Node.js overhead). This JS wrapper
|
|
8
|
-
* only runs when:
|
|
9
|
-
*
|
|
10
|
-
* 1. Hard-link failed (cross-device mount, permissions)
|
|
11
|
-
* 2. npm rebuild recreated the symlink
|
|
12
|
-
* 3. Binary download failed during postinstall
|
|
13
|
-
*
|
|
14
|
-
* Resolution order:
|
|
15
|
-
* 1. Try platform package binary (optionalDependencies)
|
|
16
|
-
* 2. Try lpm-bin in bin/ directory (GitHub Releases download)
|
|
17
|
-
* 3. Fall through to JS CLI implementation
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
import { execFileSync } from "node:child_process";
|
|
21
|
-
import fs from "node:fs";
|
|
22
|
-
import { createRequire } from "node:module";
|
|
23
|
-
import os from "node:os";
|
|
24
|
-
import path from "node:path";
|
|
25
|
-
import { fileURLToPath } from "node:url";
|
|
26
|
-
|
|
27
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
28
|
-
const require = createRequire(import.meta.url);
|
|
29
|
-
|
|
30
|
-
// ─── Try native binary (Tier 1: platform package) ──────────────────
|
|
31
|
-
|
|
32
|
-
const PLATFORMS = {
|
|
33
|
-
"darwin-arm64": { pkg: "@lpm-registry/cli-darwin-arm64", binary: "lpm" },
|
|
34
|
-
"darwin-x64": { pkg: "@lpm-registry/cli-darwin-x64", binary: "lpm" },
|
|
35
|
-
"linux-x64": { pkg: "@lpm-registry/cli-linux-x64", binary: "lpm" },
|
|
36
|
-
"linux-arm64": { pkg: "@lpm-registry/cli-linux-arm64", binary: "lpm" },
|
|
37
|
-
"win32-x64": { pkg: "@lpm-registry/cli-win32-x64", binary: "lpm.exe" },
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
// Allow override via environment variable (for debugging / custom builds)
|
|
41
|
-
const envBinary = process.env.LPM_BINARY_PATH;
|
|
42
|
-
if (envBinary && fs.existsSync(envBinary)) {
|
|
43
|
-
runBinary(envBinary);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Try platform package from optionalDependencies
|
|
47
|
-
const platform = `${process.platform}-${os.arch()}`;
|
|
48
|
-
const platformInfo = PLATFORMS[platform];
|
|
49
|
-
|
|
50
|
-
if (platformInfo) {
|
|
51
|
-
try {
|
|
52
|
-
const pkgJsonPath = require.resolve(`${platformInfo.pkg}/package.json`);
|
|
53
|
-
const binaryPath = path.join(
|
|
54
|
-
path.dirname(pkgJsonPath),
|
|
55
|
-
platformInfo.binary,
|
|
56
|
-
);
|
|
57
|
-
if (fs.existsSync(binaryPath)) {
|
|
58
|
-
runBinary(binaryPath);
|
|
59
|
-
}
|
|
60
|
-
} catch {
|
|
61
|
-
// Package not installed
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// ─── Try native binary (Tier 2: downloaded by postinstall) ─────────
|
|
66
|
-
|
|
67
|
-
const legacyBinaryName =
|
|
68
|
-
process.platform === "win32" ? "lpm-bin.exe" : "lpm-bin";
|
|
69
|
-
const legacyBinaryPath = path.join(__dirname, legacyBinaryName);
|
|
70
|
-
|
|
71
|
-
if (fs.existsSync(legacyBinaryPath)) {
|
|
72
|
-
runBinary(legacyBinaryPath);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// ─── JS CLI fallback (Tier 3) ──────────────────────────────────────
|
|
76
|
-
|
|
77
|
-
import { Command } from "commander";
|
|
78
|
-
import updateNotifier from "update-notifier";
|
|
79
|
-
import { add } from "../lib/commands/add.js";
|
|
80
|
-
import { audit } from "../lib/commands/audit.js";
|
|
81
|
-
import { cache } from "../lib/commands/cache.js";
|
|
82
|
-
import { checkName } from "../lib/commands/check-name.js";
|
|
83
|
-
import { config } from "../lib/commands/config.js";
|
|
84
|
-
import { doctor } from "../lib/commands/doctor.js";
|
|
85
|
-
import { info } from "../lib/commands/info.js";
|
|
86
|
-
import { init } from "../lib/commands/init.js";
|
|
87
|
-
import { install } from "../lib/commands/install.js";
|
|
88
|
-
import { login } from "../lib/commands/login.js";
|
|
89
|
-
import { logout } from "../lib/commands/logout.js";
|
|
90
|
-
import { marketplaceCompare } from "../lib/commands/marketplace-compare.js";
|
|
91
|
-
import { marketplaceEarnings } from "../lib/commands/marketplace-earnings.js";
|
|
92
|
-
import { mcpRemove, mcpSetup, mcpStatus } from "../lib/commands/mcp-setup.js";
|
|
93
|
-
import { npmrc } from "../lib/commands/npmrc.js";
|
|
94
|
-
import { openDashboard } from "../lib/commands/open.js";
|
|
95
|
-
import { outdated } from "../lib/commands/outdated.js";
|
|
96
|
-
import { poolStats } from "../lib/commands/pool-stats.js";
|
|
97
|
-
import { publish } from "../lib/commands/publish.js";
|
|
98
|
-
import { quality } from "../lib/commands/quality.js";
|
|
99
|
-
import { remove } from "../lib/commands/remove.js";
|
|
100
|
-
import { run } from "../lib/commands/run.js";
|
|
101
|
-
import { search } from "../lib/commands/search.js";
|
|
102
|
-
import { setup } from "../lib/commands/setup.js";
|
|
103
|
-
import {
|
|
104
|
-
skillsClean,
|
|
105
|
-
skillsInstall,
|
|
106
|
-
skillsList,
|
|
107
|
-
skillsValidate,
|
|
108
|
-
} from "../lib/commands/skills.js";
|
|
109
|
-
import { rotateToken } from "../lib/commands/token-rotate.js";
|
|
110
|
-
import { uninstall } from "../lib/commands/uninstall.js";
|
|
111
|
-
import { whoami } from "../lib/commands/whoami.js";
|
|
112
|
-
|
|
113
|
-
// Load package.json
|
|
114
|
-
const pkg = JSON.parse(
|
|
115
|
-
fs.readFileSync(path.join(__dirname, "../package.json"), "utf-8"),
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
// Check for updates
|
|
119
|
-
updateNotifier({ pkg }).notify();
|
|
120
|
-
|
|
121
|
-
const program = new Command();
|
|
122
|
-
|
|
123
|
-
program
|
|
124
|
-
.name("lpm")
|
|
125
|
-
.description("CLI for Licensed Package Manager")
|
|
126
|
-
.version(pkg.version);
|
|
127
|
-
|
|
128
|
-
// Authentication
|
|
129
|
-
program
|
|
130
|
-
.command("login")
|
|
131
|
-
.alias("l")
|
|
132
|
-
.description("Authenticate with the registry")
|
|
133
|
-
.action(login);
|
|
134
|
-
program
|
|
135
|
-
.command("logout")
|
|
136
|
-
.alias("lo")
|
|
137
|
-
.description("Clear stored authentication token")
|
|
138
|
-
.option("--revoke", "Also revoke the token on the server")
|
|
139
|
-
.option("--clear-cache", "Clear local package cache")
|
|
140
|
-
.action(logout);
|
|
141
|
-
program
|
|
142
|
-
.command("whoami")
|
|
143
|
-
.description("Check current authenticated user")
|
|
144
|
-
.option("--json", "Output in JSON format")
|
|
145
|
-
.action(whoami);
|
|
146
|
-
|
|
147
|
-
// Package Management
|
|
148
|
-
program
|
|
149
|
-
.command("init")
|
|
150
|
-
.description("Interactively create a package.json for LPM")
|
|
151
|
-
.action(init);
|
|
152
|
-
program
|
|
153
|
-
.command("install [packages...]")
|
|
154
|
-
.alias("i")
|
|
155
|
-
.description("Install packages")
|
|
156
|
-
.option("--json", "Machine-readable JSON output")
|
|
157
|
-
.option("--no-skills", "Skip fetching Agent Skills")
|
|
158
|
-
.option("--pm <manager>", "Package manager to use")
|
|
159
|
-
.action(install);
|
|
160
|
-
program
|
|
161
|
-
.command("uninstall <packages...>")
|
|
162
|
-
.aliases(["un", "unlink"])
|
|
163
|
-
.description("Uninstall packages")
|
|
164
|
-
.option("--pm <manager>", "Package manager to use")
|
|
165
|
-
.action(uninstall);
|
|
166
|
-
program
|
|
167
|
-
.command("publish")
|
|
168
|
-
.alias("p")
|
|
169
|
-
.description("Publish a package to the registry")
|
|
170
|
-
.option("--check", "Quality check only")
|
|
171
|
-
.option("--min-score <score>", "Minimum quality score")
|
|
172
|
-
.option("--provenance", "Force OIDC provenance")
|
|
173
|
-
.option("--dry-run", "Preview without publishing")
|
|
174
|
-
.action(publish);
|
|
175
|
-
program
|
|
176
|
-
.command("add <package>")
|
|
177
|
-
.description("Extract package source code")
|
|
178
|
-
.option("-p, --path <path>", "Target directory")
|
|
179
|
-
.option("-f, --force", "Overwrite existing files")
|
|
180
|
-
.option("-y, --yes", "Accept defaults")
|
|
181
|
-
.option("--alias <alias>", "Import alias prefix")
|
|
182
|
-
.option("--target <name>", "Swift SPM target")
|
|
183
|
-
.option("--json", "JSON output")
|
|
184
|
-
.option("--dry-run", "Preview only")
|
|
185
|
-
.action(add);
|
|
186
|
-
program
|
|
187
|
-
.command("remove <package>")
|
|
188
|
-
.alias("rm")
|
|
189
|
-
.description("Remove a previously added package")
|
|
190
|
-
.action(remove);
|
|
191
|
-
|
|
192
|
-
// Discovery
|
|
193
|
-
program
|
|
194
|
-
.command("search <query>")
|
|
195
|
-
.description("Search packages")
|
|
196
|
-
.option("--limit <n>", "Max results", "20")
|
|
197
|
-
.option("--json", "JSON output")
|
|
198
|
-
.action((q, o) => search(q, { ...o, limit: parseInt(o.limit, 10) }));
|
|
199
|
-
program
|
|
200
|
-
.command("info <package>")
|
|
201
|
-
.description("Package info")
|
|
202
|
-
.option("--json", "JSON output")
|
|
203
|
-
.option("-a, --all-versions", "Show all versions")
|
|
204
|
-
.action(info);
|
|
205
|
-
program
|
|
206
|
-
.command("check-name <name>")
|
|
207
|
-
.description("Check name availability")
|
|
208
|
-
.option("--json", "JSON output")
|
|
209
|
-
.action(checkName);
|
|
210
|
-
program
|
|
211
|
-
.command("quality <package>")
|
|
212
|
-
.description("Quality report")
|
|
213
|
-
.option("--json", "JSON output")
|
|
214
|
-
.action(quality);
|
|
215
|
-
|
|
216
|
-
// Maintenance
|
|
217
|
-
program
|
|
218
|
-
.command("audit [action]")
|
|
219
|
-
.description("Security audit")
|
|
220
|
-
.option("--json", "JSON output")
|
|
221
|
-
.option("--level <level>", "Minimum severity")
|
|
222
|
-
.action(audit);
|
|
223
|
-
program
|
|
224
|
-
.command("outdated")
|
|
225
|
-
.description("Check outdated deps")
|
|
226
|
-
.option("--json", "JSON output")
|
|
227
|
-
.option("--all", "Show all deps")
|
|
228
|
-
.action(outdated);
|
|
229
|
-
program.command("doctor").description("Health check").action(doctor);
|
|
230
|
-
|
|
231
|
-
// Configuration
|
|
232
|
-
const setupCommand = program
|
|
233
|
-
.command("setup")
|
|
234
|
-
.description("Configure .npmrc for CI or local development")
|
|
235
|
-
.action(() => setupCommand.help());
|
|
236
|
-
setupCommand
|
|
237
|
-
.command("ci")
|
|
238
|
-
.description("Generate .npmrc for CI/CD")
|
|
239
|
-
.option("-r, --registry <url>", "Custom registry URL")
|
|
240
|
-
.option("--oidc", "Exchange OIDC token")
|
|
241
|
-
.option("--proxy", "Route all npm traffic through lpm.dev")
|
|
242
|
-
.option("--scoped", "Scoped registry only")
|
|
243
|
-
.action(setup);
|
|
244
|
-
setupCommand
|
|
245
|
-
.command("local")
|
|
246
|
-
.description("Generate read-only .npmrc token for local development")
|
|
247
|
-
.option("-d, --days <number>", "Token expiry days")
|
|
248
|
-
.option("--proxy", "Route all npm traffic through lpm.dev")
|
|
249
|
-
.option("--scoped", "Scoped registry only")
|
|
250
|
-
.action(npmrc);
|
|
251
|
-
program
|
|
252
|
-
.command("config [action] [key] [value]")
|
|
253
|
-
.description("Manage CLI config")
|
|
254
|
-
.action(config);
|
|
255
|
-
program
|
|
256
|
-
.command("set <key> <value>")
|
|
257
|
-
.description('Shortcut for "lpm config set"')
|
|
258
|
-
.action((k, v) => config("set", k, v));
|
|
259
|
-
program
|
|
260
|
-
.command("cache <action>")
|
|
261
|
-
.description("Manage local cache")
|
|
262
|
-
.action(cache);
|
|
263
|
-
|
|
264
|
-
// Utility
|
|
265
|
-
program
|
|
266
|
-
.command("open")
|
|
267
|
-
.description("Open dashboard in browser")
|
|
268
|
-
.action(openDashboard);
|
|
269
|
-
program
|
|
270
|
-
.command("run <script>")
|
|
271
|
-
.description("Run npm scripts")
|
|
272
|
-
.allowUnknownOption()
|
|
273
|
-
.action(run);
|
|
274
|
-
|
|
275
|
-
// Subcommands
|
|
276
|
-
const token = program.command("token").description("Token management");
|
|
277
|
-
token.command("rotate").description("Rotate token").action(rotateToken);
|
|
278
|
-
|
|
279
|
-
const pool = program.command("pool").description("Pool revenue");
|
|
280
|
-
pool
|
|
281
|
-
.command("stats")
|
|
282
|
-
.description("Pool earnings")
|
|
283
|
-
.option("--json", "JSON output")
|
|
284
|
-
.action(poolStats);
|
|
285
|
-
|
|
286
|
-
const mcp = program.command("mcp").description("MCP server");
|
|
287
|
-
mcp
|
|
288
|
-
.command("setup")
|
|
289
|
-
.description("Configure MCP server")
|
|
290
|
-
.option("--project", "Project-level config")
|
|
291
|
-
.action(mcpSetup);
|
|
292
|
-
mcp
|
|
293
|
-
.command("remove")
|
|
294
|
-
.description("Remove MCP server")
|
|
295
|
-
.option("--project", "Project-level only")
|
|
296
|
-
.action(mcpRemove);
|
|
297
|
-
mcp
|
|
298
|
-
.command("status")
|
|
299
|
-
.description("MCP server status")
|
|
300
|
-
.option("--verbose", "Show diagnostics")
|
|
301
|
-
.action(mcpStatus);
|
|
302
|
-
|
|
303
|
-
const skills = program.command("skills").description("Agent Skills");
|
|
304
|
-
skills
|
|
305
|
-
.command("validate")
|
|
306
|
-
.description("Validate skills files")
|
|
307
|
-
.option("--json", "JSON output")
|
|
308
|
-
.action(skillsValidate);
|
|
309
|
-
skills
|
|
310
|
-
.command("install [package]")
|
|
311
|
-
.description("Install skills")
|
|
312
|
-
.option("--json", "JSON output")
|
|
313
|
-
.action(skillsInstall);
|
|
314
|
-
skills
|
|
315
|
-
.command("list")
|
|
316
|
-
.description("List available skills")
|
|
317
|
-
.option("--json", "JSON output")
|
|
318
|
-
.action(skillsList);
|
|
319
|
-
skills
|
|
320
|
-
.command("clean")
|
|
321
|
-
.description("Remove installed skills")
|
|
322
|
-
.option("--json", "JSON output")
|
|
323
|
-
.action(skillsClean);
|
|
324
|
-
|
|
325
|
-
const marketplace = program.command("marketplace").description("Marketplace");
|
|
326
|
-
marketplace
|
|
327
|
-
.command("compare <input>")
|
|
328
|
-
.description("Find comparable packages")
|
|
329
|
-
.option("--json", "JSON output")
|
|
330
|
-
.option("--category <category>", "Filter by category")
|
|
331
|
-
.option("--limit <n>", "Max results")
|
|
332
|
-
.action(marketplaceCompare);
|
|
333
|
-
marketplace
|
|
334
|
-
.command("earnings")
|
|
335
|
-
.description("Revenue summary")
|
|
336
|
-
.option("--json", "JSON output")
|
|
337
|
-
.action(marketplaceEarnings);
|
|
338
|
-
|
|
339
|
-
program.parse();
|
|
340
|
-
|
|
341
|
-
// ─── Helper ────────────────────────────────────────────────────────
|
|
342
|
-
|
|
343
|
-
function runBinary(binaryPath) {
|
|
344
|
-
try {
|
|
345
|
-
execFileSync(binaryPath, process.argv.slice(2), {
|
|
346
|
-
stdio: "inherit",
|
|
347
|
-
env: process.env,
|
|
348
|
-
});
|
|
349
|
-
process.exit(0);
|
|
350
|
-
} catch (err) {
|
|
351
|
-
if (err.status != null) {
|
|
352
|
-
process.exit(err.status);
|
|
353
|
-
}
|
|
354
|
-
// Binary failed to execute — fall through to JS CLI
|
|
355
|
-
}
|
|
356
|
-
}
|
|
4
|
+
runNativeCommand("lpm");
|
package/bin/lpx.js
ADDED
package/bin/native.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
|
|
9
|
+
export const PLATFORMS = Object.freeze({
|
|
10
|
+
"darwin-arm64": {
|
|
11
|
+
pkg: "@lpm-registry/cli-darwin-arm64",
|
|
12
|
+
lpm: "lpm",
|
|
13
|
+
lpx: "lpx",
|
|
14
|
+
},
|
|
15
|
+
"darwin-x64": {
|
|
16
|
+
pkg: "@lpm-registry/cli-darwin-x64",
|
|
17
|
+
lpm: "lpm",
|
|
18
|
+
lpx: "lpx",
|
|
19
|
+
},
|
|
20
|
+
"linux-arm64": {
|
|
21
|
+
pkg: "@lpm-registry/cli-linux-arm64",
|
|
22
|
+
lpm: "lpm",
|
|
23
|
+
lpx: "lpx",
|
|
24
|
+
},
|
|
25
|
+
"linux-x64": {
|
|
26
|
+
pkg: "@lpm-registry/cli-linux-x64",
|
|
27
|
+
lpm: "lpm",
|
|
28
|
+
lpx: "lpx",
|
|
29
|
+
},
|
|
30
|
+
"win32-x64": {
|
|
31
|
+
pkg: "@lpm-registry/cli-win32-x64",
|
|
32
|
+
lpm: "lpm.exe",
|
|
33
|
+
lpx: "lpx.exe",
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export function platformKey(platform = process.platform, arch = os.arch()) {
|
|
38
|
+
return `${platform}-${arch}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function resolveNativeBinary(options = {}) {
|
|
42
|
+
const command = options.command ?? "lpm";
|
|
43
|
+
const env = options.env ?? process.env;
|
|
44
|
+
const platform = options.platform ?? process.platform;
|
|
45
|
+
const arch = options.arch ?? os.arch();
|
|
46
|
+
const requireFn = options.requireFn ?? require;
|
|
47
|
+
|
|
48
|
+
const override = env.LPM_BINARY_PATH;
|
|
49
|
+
if (override) {
|
|
50
|
+
return {
|
|
51
|
+
path: override,
|
|
52
|
+
source: "env",
|
|
53
|
+
argsPrefix: command === "lpx" ? ["dlx"] : [],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const key = platformKey(platform, arch);
|
|
58
|
+
const spec = PLATFORMS[key];
|
|
59
|
+
if (!spec) {
|
|
60
|
+
throw new LpmWrapperError(
|
|
61
|
+
`Unsupported platform: ${key}`,
|
|
62
|
+
[
|
|
63
|
+
"LPM publishes native npm packages for macOS, Linux, and Windows on x64/arm64.",
|
|
64
|
+
"Use another install method from https://github.com/lpm-dev/rust-client.",
|
|
65
|
+
],
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let packageJsonPath;
|
|
70
|
+
try {
|
|
71
|
+
packageJsonPath = requireFn.resolve(`${spec.pkg}/package.json`);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
throw new LpmWrapperError(
|
|
74
|
+
`Native package ${spec.pkg} is not installed.`,
|
|
75
|
+
[
|
|
76
|
+
"Reinstall with optional dependencies enabled:",
|
|
77
|
+
" npm install -g @lpm-registry/cli",
|
|
78
|
+
"If you used --omit=optional, --no-optional, or a package-manager policy that blocks optional dependencies, remove that setting.",
|
|
79
|
+
],
|
|
80
|
+
error,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const binaryPath = path.join(path.dirname(packageJsonPath), spec[command]);
|
|
85
|
+
if (!fs.existsSync(binaryPath)) {
|
|
86
|
+
throw new LpmWrapperError(
|
|
87
|
+
`Native package ${spec.pkg} is installed, but ${spec[command]} is missing.`,
|
|
88
|
+
["Reinstall LPM with `npm install -g @lpm-registry/cli`."],
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
path: binaryPath,
|
|
94
|
+
source: spec.pkg,
|
|
95
|
+
argsPrefix: [],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function runNativeCommand(command) {
|
|
100
|
+
let native;
|
|
101
|
+
try {
|
|
102
|
+
native = resolveNativeBinary({ command });
|
|
103
|
+
} catch (error) {
|
|
104
|
+
printWrapperError(error);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const args = native.argsPrefix.concat(process.argv.slice(2));
|
|
109
|
+
const result = spawnSync(native.path, args, {
|
|
110
|
+
stdio: "inherit",
|
|
111
|
+
env: process.env,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
if (result.error) {
|
|
115
|
+
console.error(`[lpm] Failed to run native binary at ${native.path}`);
|
|
116
|
+
console.error(`[lpm] ${result.error.message}`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (result.signal) {
|
|
121
|
+
forwardSignalExit(result.signal);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
process.exit(result.status ?? 1);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export class LpmWrapperError extends Error {
|
|
128
|
+
constructor(message, hints = [], cause = undefined) {
|
|
129
|
+
super(message, cause ? { cause } : undefined);
|
|
130
|
+
this.name = "LpmWrapperError";
|
|
131
|
+
this.hints = hints;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function printWrapperError(error) {
|
|
136
|
+
if (error instanceof LpmWrapperError) {
|
|
137
|
+
console.error(`[lpm] ${error.message}`);
|
|
138
|
+
for (const hint of error.hints) {
|
|
139
|
+
console.error(`[lpm] ${hint}`);
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
console.error(`[lpm] ${error?.message ?? error}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function forwardSignalExit(signal) {
|
|
148
|
+
const signalNumber = os.constants.signals[signal];
|
|
149
|
+
if (signalNumber) {
|
|
150
|
+
process.kill(process.pid, signal);
|
|
151
|
+
process.exit(128 + signalNumber);
|
|
152
|
+
}
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|