@lpm-registry/cli 0.2.0

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 (54) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/LICENSE +15 -0
  3. package/README.md +406 -0
  4. package/bin/lpm.js +334 -0
  5. package/index.d.ts +131 -0
  6. package/index.js +31 -0
  7. package/lib/api.js +324 -0
  8. package/lib/commands/add.js +1217 -0
  9. package/lib/commands/audit.js +283 -0
  10. package/lib/commands/cache.js +209 -0
  11. package/lib/commands/check-name.js +112 -0
  12. package/lib/commands/config.js +174 -0
  13. package/lib/commands/doctor.js +142 -0
  14. package/lib/commands/info.js +215 -0
  15. package/lib/commands/init.js +146 -0
  16. package/lib/commands/install.js +217 -0
  17. package/lib/commands/login.js +547 -0
  18. package/lib/commands/logout.js +94 -0
  19. package/lib/commands/marketplace-compare.js +164 -0
  20. package/lib/commands/marketplace-earnings.js +89 -0
  21. package/lib/commands/mcp-setup.js +363 -0
  22. package/lib/commands/open.js +82 -0
  23. package/lib/commands/outdated.js +291 -0
  24. package/lib/commands/pool-stats.js +100 -0
  25. package/lib/commands/publish.js +707 -0
  26. package/lib/commands/quality.js +211 -0
  27. package/lib/commands/remove.js +82 -0
  28. package/lib/commands/run.js +14 -0
  29. package/lib/commands/search.js +143 -0
  30. package/lib/commands/setup.js +92 -0
  31. package/lib/commands/skills.js +863 -0
  32. package/lib/commands/token-rotate.js +25 -0
  33. package/lib/commands/whoami.js +129 -0
  34. package/lib/config.js +240 -0
  35. package/lib/constants.js +190 -0
  36. package/lib/ecosystem.js +501 -0
  37. package/lib/editors.js +215 -0
  38. package/lib/import-rewriter.js +364 -0
  39. package/lib/install-targets/mcp-server.js +245 -0
  40. package/lib/install-targets/vscode-extension.js +178 -0
  41. package/lib/install-targets.js +82 -0
  42. package/lib/integrity.js +179 -0
  43. package/lib/lpm-config-prompts.js +102 -0
  44. package/lib/lpm-config.js +408 -0
  45. package/lib/project-utils.js +152 -0
  46. package/lib/quality/checks.js +654 -0
  47. package/lib/quality/display.js +139 -0
  48. package/lib/quality/score.js +115 -0
  49. package/lib/quality/swift-checks.js +447 -0
  50. package/lib/safe-path.js +180 -0
  51. package/lib/secure-store.js +288 -0
  52. package/lib/swift-project.js +637 -0
  53. package/lib/ui.js +40 -0
  54. package/package.json +74 -0
package/bin/lpm.js ADDED
@@ -0,0 +1,334 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs"
4
+ import path from "node:path"
5
+ import { fileURLToPath } from "node:url"
6
+ import { Command } from "commander"
7
+ import updateNotifier from "update-notifier"
8
+ import { add } from "../lib/commands/add.js"
9
+ import { audit } from "../lib/commands/audit.js"
10
+ import { cache } from "../lib/commands/cache.js"
11
+ import { checkName } from "../lib/commands/check-name.js"
12
+ import { config } from "../lib/commands/config.js"
13
+ import { doctor } from "../lib/commands/doctor.js"
14
+ import { info } from "../lib/commands/info.js"
15
+ import { init } from "../lib/commands/init.js"
16
+ import { install } from "../lib/commands/install.js"
17
+ import { login } from "../lib/commands/login.js"
18
+ import { logout } from "../lib/commands/logout.js"
19
+ import { marketplaceCompare } from "../lib/commands/marketplace-compare.js"
20
+ import { marketplaceEarnings } from "../lib/commands/marketplace-earnings.js"
21
+ import { mcpRemove, mcpSetup, mcpStatus } from "../lib/commands/mcp-setup.js"
22
+ import { openDashboard } from "../lib/commands/open.js"
23
+ import { outdated } from "../lib/commands/outdated.js"
24
+ import { poolStats } from "../lib/commands/pool-stats.js"
25
+ import { publish } from "../lib/commands/publish.js"
26
+ import { quality } from "../lib/commands/quality.js"
27
+ import { remove } from "../lib/commands/remove.js"
28
+ import { run } from "../lib/commands/run.js"
29
+ import { search } from "../lib/commands/search.js"
30
+ import { setup } from "../lib/commands/setup.js"
31
+ import {
32
+ skillsClean,
33
+ skillsInstall,
34
+ skillsList,
35
+ skillsValidate,
36
+ } from "../lib/commands/skills.js"
37
+ import { rotateToken } from "../lib/commands/token-rotate.js"
38
+ import { whoami } from "../lib/commands/whoami.js"
39
+
40
+ // Load package.json
41
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
42
+ const pkg = JSON.parse(
43
+ fs.readFileSync(path.join(__dirname, "../package.json"), "utf-8"),
44
+ )
45
+
46
+ // Check for updates
47
+ updateNotifier({ pkg }).notify()
48
+
49
+ const program = new Command()
50
+
51
+ program
52
+ .name("lpm")
53
+ .description("CLI for Licensed Package Manager")
54
+ .version(pkg.version)
55
+
56
+ // ============================================================================
57
+ // Authentication Commands
58
+ // ============================================================================
59
+
60
+ program
61
+ .command("login")
62
+ .alias("l")
63
+ .description("Authenticate with the registry")
64
+ .action(login)
65
+
66
+ program
67
+ .command("logout")
68
+ .alias("lo")
69
+ .description("Clear stored authentication token")
70
+ .option("--revoke", "Also revoke the token on the server")
71
+ .option("--clear-cache", "Clear local package cache")
72
+ .action(logout)
73
+
74
+ program
75
+ .command("whoami")
76
+ .description("Check current authenticated user")
77
+ .option("--json", "Output in JSON format")
78
+ .action(whoami)
79
+
80
+ // ============================================================================
81
+ // Package Management Commands
82
+ // ============================================================================
83
+
84
+ program
85
+ .command("init")
86
+ .description("Interactively create a package.json for LPM")
87
+ .action(init)
88
+
89
+ program
90
+ .command("install [packages...]")
91
+ .alias("i")
92
+ .description("Install packages with automatic registry authentication")
93
+ .option("--json", "Machine-readable JSON output")
94
+ .option("--no-skills", "Skip fetching Agent Skills after install")
95
+ .action(install)
96
+
97
+ program
98
+ .command("publish")
99
+ .alias("p")
100
+ .description("Publish a package to the registry")
101
+ .option("--check", "Run quality checks and display report without publishing")
102
+ .option(
103
+ "--min-score <score>",
104
+ "Minimum quality score required to publish (0-100)",
105
+ )
106
+ .action(publish)
107
+
108
+ program
109
+ .command("add <package>")
110
+ .description("Download and extract a package source code to your project")
111
+ .option("-p, --path <path>", "Target directory for the component")
112
+ .option("-f, --force", "Overwrite existing files without prompting")
113
+ .option("-y, --yes", "Accept defaults, skip interactive config prompts")
114
+ .option("--alias <alias>", "Import alias prefix (e.g., @/components/ui)")
115
+ .option("--target <name>", "Swift SPM target name")
116
+ .option("--install-deps", "Auto-install npm dependencies (default: true)")
117
+ .option("--no-install-deps", "Skip npm dependency installation")
118
+ .option("--json", "Machine-readable JSON output")
119
+ .option("--dry-run", "Preview what would happen without writing files")
120
+ .option("--no-skills", "Skip fetching Agent Skills after add")
121
+ .action(add)
122
+
123
+ program
124
+ .command("remove <package>")
125
+ .alias("rm")
126
+ .description(
127
+ "Remove a previously added package (e.g., MCP servers from editors)",
128
+ )
129
+ .action(remove)
130
+
131
+ // ============================================================================
132
+ // Package Discovery Commands
133
+ // ============================================================================
134
+
135
+ program
136
+ .command("search <query>")
137
+ .description("Search for packages in the marketplace")
138
+ .option("--limit <n>", "Maximum number of results", "20")
139
+ .option("--json", "Output in JSON format")
140
+ .action((query, options) =>
141
+ search(query, { ...options, limit: parseInt(options.limit, 10) }),
142
+ )
143
+
144
+ program
145
+ .command("info <package>")
146
+ .description("Show detailed information about a package")
147
+ .option("--json", "Output in JSON format")
148
+ .option("-a, --all-versions", "Show all versions")
149
+ .action(info)
150
+
151
+ program
152
+ .command("check-name <name>")
153
+ .description("Check if a package name is available on the registry")
154
+ .option("--json", "Output in JSON format")
155
+ .action(checkName)
156
+
157
+ program
158
+ .command("quality <package>")
159
+ .description("Show the server-side quality report for a package")
160
+ .option("--json", "Output in JSON format")
161
+ .action(quality)
162
+
163
+ // ============================================================================
164
+ // Security & Maintenance Commands
165
+ // ============================================================================
166
+
167
+ program
168
+ .command("audit [action]")
169
+ .description("Scan dependencies for known vulnerabilities")
170
+ .option("--json", "Output in JSON format")
171
+ .option(
172
+ "--level <level>",
173
+ "Minimum severity to report (low, moderate, high, critical)",
174
+ )
175
+ .action(audit)
176
+
177
+ program
178
+ .command("outdated")
179
+ .description("Check for outdated dependencies")
180
+ .option("--json", "Output in JSON format")
181
+ .option("--all", "Show all dependencies, not just outdated ones")
182
+ .action(outdated)
183
+
184
+ program
185
+ .command("doctor")
186
+ .description("Check the health of your LPM setup")
187
+ .action(doctor)
188
+
189
+ // ============================================================================
190
+ // Configuration Commands
191
+ // ============================================================================
192
+
193
+ program
194
+ .command("setup")
195
+ .description("Configure .npmrc for LPM packages (@lpm.dev scope)")
196
+ .option("-r, --registry <url>", "Custom registry URL")
197
+ .action(setup)
198
+
199
+ program
200
+ .command("config [action] [key] [value]")
201
+ .description("Manage CLI configuration (list, get, set, delete)")
202
+ .action(config)
203
+
204
+ program
205
+ .command("set <key> <value>")
206
+ .description('Shortcut for "lpm config set"')
207
+ .action((key, value) => config("set", key, value))
208
+
209
+ program
210
+ .command("cache <action>")
211
+ .description("Manage local package cache (clean, list, path)")
212
+ .action(cache)
213
+
214
+ // ============================================================================
215
+ // Utility Commands
216
+ // ============================================================================
217
+
218
+ program
219
+ .command("open")
220
+ .description("Open the dashboard or package page in your browser")
221
+ .action(openDashboard)
222
+
223
+ program
224
+ .command("run <script>")
225
+ .description("Run npm scripts (forwards to npm run)")
226
+ .allowUnknownOption()
227
+ .action(run)
228
+
229
+ // ============================================================================
230
+ // Token Management (Subcommand)
231
+ // ============================================================================
232
+
233
+ const token = program
234
+ .command("token")
235
+ .description("Manage authentication tokens")
236
+
237
+ token
238
+ .command("rotate")
239
+ .description("Rotate the current token")
240
+ .action(rotateToken)
241
+
242
+ // ============================================================================
243
+ // Pool Revenue (Subcommand)
244
+ // ============================================================================
245
+
246
+ const pool = program.command("pool").description("Pool revenue commands")
247
+
248
+ pool
249
+ .command("stats")
250
+ .description("Show your Pool earnings estimate for the current month")
251
+ .option("--json", "Output in JSON format")
252
+ .action(poolStats)
253
+
254
+ // ============================================================================
255
+ // MCP Server (Subcommand)
256
+ // ============================================================================
257
+
258
+ const mcp = program.command("mcp").description("MCP server commands")
259
+
260
+ mcp
261
+ .command("setup")
262
+ .description("Configure the LPM MCP server in your AI coding editors")
263
+ .option("--project", "Add to project-level config instead of global")
264
+ .action(mcpSetup)
265
+
266
+ mcp
267
+ .command("remove")
268
+ .description("Remove the LPM MCP server from all configured editors")
269
+ .option("--project", "Remove from project-level config only")
270
+ .action(mcpRemove)
271
+
272
+ mcp
273
+ .command("status")
274
+ .description("Show where the LPM MCP server is configured")
275
+ .option("--verbose", "Show command and args diagnostics for each editor")
276
+ .action(mcpStatus)
277
+
278
+ // ============================================================================
279
+ // Agent Skills (Subcommand)
280
+ // ============================================================================
281
+
282
+ const skills = program
283
+ .command("skills")
284
+ .description("Manage Agent Skills for AI coding assistants")
285
+
286
+ skills
287
+ .command("validate")
288
+ .description("Validate .lpm/skills/ files in the current directory")
289
+ .option("--json", "Output in JSON format")
290
+ .action(skillsValidate)
291
+
292
+ skills
293
+ .command("install [package]")
294
+ .description(
295
+ "Fetch and install skills from the registry (all deps or specific package)",
296
+ )
297
+ .option("--json", "Output in JSON format")
298
+ .action(skillsInstall)
299
+
300
+ skills
301
+ .command("list")
302
+ .description("List available skills for installed @lpm.dev/* packages")
303
+ .option("--json", "Output in JSON format")
304
+ .action(skillsList)
305
+
306
+ skills
307
+ .command("clean")
308
+ .description("Remove locally installed skills (.lpm/skills/ directory)")
309
+ .option("--json", "Output in JSON format")
310
+ .action(skillsClean)
311
+
312
+ // ============================================================================
313
+ // Marketplace (Subcommand)
314
+ // ============================================================================
315
+
316
+ const marketplace = program
317
+ .command("marketplace")
318
+ .description("Marketplace commands")
319
+
320
+ marketplace
321
+ .command("compare <input>")
322
+ .description("Find comparable packages by name or category")
323
+ .option("--json", "Output in JSON format")
324
+ .option("--category <category>", "Filter by category")
325
+ .option("--limit <n>", "Maximum number of results")
326
+ .action(marketplaceCompare)
327
+
328
+ marketplace
329
+ .command("earnings")
330
+ .description("Show your Marketplace revenue summary")
331
+ .option("--json", "Output in JSON format")
332
+ .action(marketplaceEarnings)
333
+
334
+ program.parse()
package/index.d.ts ADDED
@@ -0,0 +1,131 @@
1
+ /// <reference types="node" />
2
+
3
+ // Type declarations for @lpm-registry/cli
4
+
5
+ // --- integrity.js ---
6
+
7
+ export interface IntegrityHash {
8
+ algorithm: string
9
+ digest: string
10
+ }
11
+
12
+ export interface IntegrityResult {
13
+ valid: boolean
14
+ algorithm?: string
15
+ error?: string
16
+ actual?: string
17
+ }
18
+
19
+ export function generateIntegrity(buffer: Buffer, algorithm?: string): string
20
+ export function verifyIntegrity(
21
+ buffer: Buffer,
22
+ expectedIntegrity: string,
23
+ ): IntegrityResult
24
+ export function verifyIntegrityMultiple(
25
+ buffer: Buffer,
26
+ integrities: string[],
27
+ ): IntegrityResult
28
+ export function parseIntegrity(integrity: string): IntegrityHash
29
+
30
+ // --- safe-path.js ---
31
+
32
+ export interface PathValidation {
33
+ valid: boolean
34
+ resolvedPath?: string
35
+ error?: string
36
+ }
37
+
38
+ export interface TarballPathValidation {
39
+ valid: boolean
40
+ invalidPaths?: string[]
41
+ }
42
+
43
+ export function validateComponentPath(
44
+ projectRoot: string,
45
+ componentPath: string,
46
+ ): PathValidation
47
+ export function validateTarballPaths(
48
+ extractDir: string,
49
+ filePaths: string[],
50
+ ): TarballPathValidation
51
+ export function resolveSafePath(
52
+ basePath: string,
53
+ userPath: string,
54
+ ): PathValidation
55
+ export function sanitizeFilename(filename: string): string
56
+
57
+ // --- quality/score.js ---
58
+
59
+ export interface QualityCheck {
60
+ id: string
61
+ category: "documentation" | "code" | "testing" | "health"
62
+ label: string
63
+ passed: boolean
64
+ points: number
65
+ maxPoints: number
66
+ serverOnly?: boolean
67
+ }
68
+
69
+ export interface QualityMeta {
70
+ tier: "excellent" | "good" | "fair" | "needs-work"
71
+ score: number
72
+ maxScore: number
73
+ categories: Record<string, { score: number; max: number }>
74
+ }
75
+
76
+ export interface QualityResult {
77
+ score: number
78
+ checks: QualityCheck[]
79
+ meta: QualityMeta
80
+ }
81
+
82
+ export interface QualityInput {
83
+ packageJson: Record<string, unknown>
84
+ readme: string | null
85
+ lpmConfig: Record<string, unknown> | null
86
+ files: Array<{ path: string }>
87
+ unpackedSize: number
88
+ }
89
+
90
+ export function runQualityChecks(input: QualityInput): QualityResult
91
+
92
+ // --- lpm-config.js ---
93
+
94
+ export interface PackageReference {
95
+ name: string
96
+ version: string
97
+ inlineConfig: Record<string, string>
98
+ providedParams: Set<string>
99
+ }
100
+
101
+ export interface LpmConfig {
102
+ files?: Array<{
103
+ src: string
104
+ dest?: string
105
+ when?: string
106
+ }>
107
+ configSchema?: Record<string, unknown>
108
+ defaultConfig?: Record<string, string>
109
+ dependencies?: Record<string, unknown>
110
+ }
111
+
112
+ export interface LpmConfigValidation {
113
+ valid: boolean
114
+ errors?: string[]
115
+ }
116
+
117
+ export function parseLpmPackageReference(ref: string): PackageReference
118
+ export function readLpmConfig(extractDir: string): LpmConfig | null
119
+ export function validateLpmConfig(config: unknown): LpmConfigValidation
120
+ export function filterFiles(
121
+ files: LpmConfig["files"],
122
+ mergedConfig: Record<string, string>,
123
+ providedParams: Set<string>,
124
+ ): NonNullable<LpmConfig["files"]>
125
+ // --- project-utils.js ---
126
+
127
+ export type Framework = "nextjs" | "vite" | "remix" | "astro" | "unknown"
128
+
129
+ export function detectFramework(): Framework
130
+ export function getDefaultPath(framework: Framework): string
131
+ export function getUserImportPrefix(): string
package/index.js ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @lpm-registry/cli - CLI for Licensed Package Manager
3
+ *
4
+ * This module re-exports key utilities for programmatic use.
5
+ * For CLI usage, run `lpm` directly.
6
+ */
7
+
8
+ export {
9
+ generateIntegrity,
10
+ parseIntegrity,
11
+ verifyIntegrity,
12
+ verifyIntegrityMultiple,
13
+ } from "./lib/integrity.js"
14
+ export {
15
+ filterFiles,
16
+ parseLpmPackageReference,
17
+ readLpmConfig,
18
+ validateLpmConfig,
19
+ } from "./lib/lpm-config.js"
20
+ export {
21
+ detectFramework,
22
+ getDefaultPath,
23
+ getUserImportPrefix,
24
+ } from "./lib/project-utils.js"
25
+ export { runQualityChecks } from "./lib/quality/score.js"
26
+ export {
27
+ resolveSafePath,
28
+ sanitizeFilename,
29
+ validateComponentPath,
30
+ validateTarballPaths,
31
+ } from "./lib/safe-path.js"