@lpm-registry/cli 0.5.0 → 0.6.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.
@@ -18,7 +18,7 @@ const hasReadme = {
18
18
  id: "has-readme",
19
19
  category: "documentation",
20
20
  label: "Has README",
21
- maxPoints: 8,
21
+ max_points: 8,
22
22
  run: ({ readme }) => ({
23
23
  passed: !!readme && readme.length > 100,
24
24
  detail: readme
@@ -31,7 +31,7 @@ const readmeHasInstall = {
31
31
  id: "readme-install",
32
32
  category: "documentation",
33
33
  label: "README has install section",
34
- maxPoints: 3,
34
+ max_points: 3,
35
35
  run: ({ readme }) => {
36
36
  if (!readme) return { passed: false, detail: "No README" }
37
37
  const lower = readme.toLowerCase()
@@ -55,7 +55,7 @@ const readmeHasUsage = {
55
55
  id: "readme-usage",
56
56
  category: "documentation",
57
57
  label: "README has usage examples",
58
- maxPoints: 3,
58
+ max_points: 3,
59
59
  run: ({ readme }) => {
60
60
  if (!readme) return { passed: false, detail: "No README" }
61
61
  const lower = readme.toLowerCase()
@@ -77,7 +77,7 @@ const readmeHasApi = {
77
77
  id: "readme-api",
78
78
  category: "documentation",
79
79
  label: "README has API docs",
80
- maxPoints: 2,
80
+ max_points: 2,
81
81
  run: ({ readme }) => {
82
82
  if (!readme) return { passed: false, detail: "No README" }
83
83
  const lower = readme.toLowerCase()
@@ -100,7 +100,7 @@ const hasChangelog = {
100
100
  id: "has-changelog",
101
101
  category: "documentation",
102
102
  label: "Has CHANGELOG",
103
- maxPoints: 3,
103
+ max_points: 3,
104
104
  run: ({ files }) => {
105
105
  const changelogFiles = files.filter(f => {
106
106
  const name = (f.path || f).toLowerCase()
@@ -120,7 +120,7 @@ const hasLicense = {
120
120
  id: "has-license",
121
121
  category: "documentation",
122
122
  label: "Has LICENSE file",
123
- maxPoints: 3,
123
+ max_points: 3,
124
124
  run: ({ files, packageJson }) => {
125
125
  const licenseFiles = files.filter(f => {
126
126
  const name = (f.path || f).toLowerCase()
@@ -146,7 +146,7 @@ const hasTypes = {
146
146
  id: "has-types",
147
147
  category: "code",
148
148
  label: "Has TypeScript types",
149
- maxPoints: 8,
149
+ max_points: 8,
150
150
  run: ({ packageJson, files }) => {
151
151
  const hasTypesField = !!(packageJson.types || packageJson.typings)
152
152
  const hasDtsFiles = files.some(f => {
@@ -169,7 +169,7 @@ const intellisenseCoverage = {
169
169
  id: "intellisense-coverage",
170
170
  category: "code",
171
171
  label: "Intellisense coverage",
172
- maxPoints: 4,
172
+ max_points: 4,
173
173
  run: ({ packageJson, files }) => {
174
174
  // Full points if .d.ts files exist (complete intellisense)
175
175
  const hasTypesField = !!(packageJson.types || packageJson.typings)
@@ -188,7 +188,7 @@ const intellisenseCoverage = {
188
188
  return {
189
189
  passed: false,
190
190
  detail: "No .d.ts files or JSDoc detected for intellisense",
191
- serverOnly: true,
191
+ server_only: true,
192
192
  }
193
193
  },
194
194
  }
@@ -197,7 +197,7 @@ const hasEsm = {
197
197
  id: "esm-exports",
198
198
  category: "code",
199
199
  label: "ESM exports",
200
- maxPoints: 3,
200
+ max_points: 3,
201
201
  run: ({ packageJson }) => {
202
202
  const isModule = packageJson.type === "module"
203
203
  const hasModuleField = !!packageJson.module
@@ -220,7 +220,7 @@ const treeShakable = {
220
220
  id: "tree-shakable",
221
221
  category: "code",
222
222
  label: "Tree-shakable",
223
- maxPoints: 3,
223
+ max_points: 3,
224
224
  run: ({ packageJson }) => {
225
225
  const hasSideEffects = packageJson.sideEffects === false
226
226
  const hasExportsField = !!packageJson.exports
@@ -242,14 +242,14 @@ const noEval = {
242
242
  id: "no-eval",
243
243
  category: "code",
244
244
  label: "No eval/Function() patterns",
245
- maxPoints: 3,
245
+ max_points: 3,
246
246
  run: () => {
247
247
  // This check runs server-side from tarball contents.
248
248
  // CLI assumes pass; server overrides if eval detected.
249
249
  return {
250
250
  passed: true,
251
251
  detail: "Full check runs server-side",
252
- serverOnly: true,
252
+ server_only: true,
253
253
  }
254
254
  },
255
255
  }
@@ -258,7 +258,7 @@ const noLifecycleScripts = {
258
258
  id: "no-lifecycle-scripts",
259
259
  category: "health",
260
260
  label: "No lifecycle scripts",
261
- maxPoints: 2,
261
+ max_points: 2,
262
262
  run: ({ packageJson }) => {
263
263
  const lifecycleNames = [
264
264
  "preinstall",
@@ -287,7 +287,7 @@ const hasEngines = {
287
287
  id: "has-engines",
288
288
  category: "code",
289
289
  label: 'Has "engines" field',
290
- maxPoints: 1,
290
+ max_points: 1,
291
291
  run: ({ packageJson }) => {
292
292
  const hasField = !!packageJson.engines?.node
293
293
  return {
@@ -303,7 +303,7 @@ const hasExportsMap = {
303
303
  id: "has-exports-map",
304
304
  category: "code",
305
305
  label: 'Has "exports" map',
306
- maxPoints: 3,
306
+ max_points: 3,
307
307
  run: ({ packageJson }) => {
308
308
  const hasField = !!packageJson.exports
309
309
  return {
@@ -319,7 +319,7 @@ const smallDeps = {
319
319
  id: "small-deps",
320
320
  category: "code",
321
321
  label: "Small dependency footprint",
322
- maxPoints: 3,
322
+ max_points: 3,
323
323
  run: ({ packageJson }) => {
324
324
  const deps = packageJson.dependencies
325
325
  ? Object.keys(packageJson.dependencies).length
@@ -341,7 +341,7 @@ const sourceMaps = {
341
341
  id: "source-maps",
342
342
  category: "code",
343
343
  label: "Source maps included",
344
- maxPoints: 1,
344
+ max_points: 1,
345
345
  run: ({ files }) => {
346
346
  const mapFiles = files.filter(f => {
347
347
  const name = f.path || f
@@ -363,7 +363,7 @@ const hasTestFiles = {
363
363
  id: "has-test-files",
364
364
  category: "testing",
365
365
  label: "Has test files",
366
- maxPoints: 7,
366
+ max_points: 7,
367
367
  run: ({ projectFiles, files }) => {
368
368
  // Prefer projectFiles (local project scan) over files (tarball)
369
369
  // so authors don't need to ship test files in the package
@@ -392,7 +392,7 @@ const hasTestScript = {
392
392
  id: "has-test-script",
393
393
  category: "testing",
394
394
  label: "Has test script",
395
- maxPoints: 4,
395
+ max_points: 4,
396
396
  run: ({ packageJson }) => {
397
397
  const testScript = packageJson.scripts?.test
398
398
  const hasScript = !!testScript && !testScript.includes(DEFAULT_TEST_SCRIPT)
@@ -411,7 +411,7 @@ const hasDescription = {
411
411
  id: "has-description",
412
412
  category: "health",
413
413
  label: "Has description",
414
- maxPoints: 3,
414
+ max_points: 3,
415
415
  run: ({ packageJson }) => {
416
416
  const desc = packageJson.description
417
417
  const passed = !!desc && desc.length > 10
@@ -428,7 +428,7 @@ const hasKeywords = {
428
428
  id: "has-keywords",
429
429
  category: "health",
430
430
  label: "Has keywords",
431
- maxPoints: 1,
431
+ max_points: 1,
432
432
  run: ({ packageJson }) => {
433
433
  const keywords = packageJson.keywords
434
434
  const passed = Array.isArray(keywords) && keywords.length > 0
@@ -445,7 +445,7 @@ const hasRepository = {
445
445
  id: "has-repository",
446
446
  category: "health",
447
447
  label: "Has repository URL",
448
- maxPoints: 2,
448
+ max_points: 2,
449
449
  run: ({ packageJson }) => {
450
450
  const repo = packageJson.repository
451
451
  const hasRepo = !!(
@@ -465,7 +465,7 @@ const hasHomepage = {
465
465
  id: "has-homepage",
466
466
  category: "health",
467
467
  label: "Has homepage",
468
- maxPoints: 1,
468
+ max_points: 1,
469
469
  run: ({ packageJson }) => {
470
470
  const passed = !!packageJson.homepage
471
471
  return {
@@ -481,7 +481,7 @@ const reasonableSize = {
481
481
  id: "reasonable-size",
482
482
  category: "health",
483
483
  label: "Reasonable bundle size",
484
- maxPoints: 3,
484
+ max_points: 3,
485
485
  run: ({ unpackedSize }) => {
486
486
  if (!unpackedSize)
487
487
  return { passed: true, points: 3, detail: "Size unknown" }
@@ -506,14 +506,14 @@ const noVulnerabilities = {
506
506
  id: "no-vulnerabilities",
507
507
  category: "health",
508
508
  label: "No known vulnerabilities",
509
- maxPoints: 5,
509
+ max_points: 5,
510
510
  run: () => {
511
511
  // This check runs server-side with OSV scan results.
512
512
  // CLI assumes pass; server overrides with actual results.
513
513
  return {
514
514
  passed: true,
515
515
  detail: "Full check runs server-side",
516
- serverOnly: true,
516
+ server_only: true,
517
517
  }
518
518
  },
519
519
  }
@@ -522,14 +522,14 @@ const maintenanceHealth = {
522
522
  id: "maintenance-health",
523
523
  category: "health",
524
524
  label: "Active maintenance",
525
- maxPoints: 4,
525
+ max_points: 4,
526
526
  run: () => {
527
527
  // Server-only: checks if last version was published within 90 days.
528
528
  // CLI cannot know this — assumes pass.
529
529
  return {
530
530
  passed: true,
531
531
  detail: "Full check runs server-side",
532
- serverOnly: true,
532
+ server_only: true,
533
533
  }
534
534
  },
535
535
  }
@@ -538,7 +538,7 @@ const semverConsistency = {
538
538
  id: "semver-consistency",
539
539
  category: "health",
540
540
  label: "SemVer consistency",
541
- maxPoints: 4,
541
+ max_points: 4,
542
542
  run: ({ packageJson }) => {
543
543
  // CLI can check if the current version is valid semver
544
544
  const version = packageJson.version
@@ -552,7 +552,7 @@ const semverConsistency = {
552
552
  detail: isValid
553
553
  ? `Valid semver: ${version}`
554
554
  : `Invalid semver format: ${version}`,
555
- serverOnly: !isValid ? undefined : true,
555
+ server_only: !isValid ? undefined : true,
556
556
  }
557
557
  },
558
558
  }
@@ -561,14 +561,14 @@ const authorVerified = {
561
561
  id: "author-verified",
562
562
  category: "health",
563
563
  label: "Verified author",
564
- maxPoints: 3,
564
+ max_points: 3,
565
565
  run: () => {
566
566
  // Server-only: checks if the author has linked social accounts.
567
567
  // CLI cannot know this — assumes pass.
568
568
  return {
569
569
  passed: true,
570
570
  detail: "Full check runs server-side",
571
- serverOnly: true,
571
+ server_only: true,
572
572
  }
573
573
  },
574
574
  }
@@ -579,14 +579,14 @@ const hasSkills = {
579
579
  id: "has-skills",
580
580
  category: "health",
581
581
  label: "Has Agent Skills",
582
- maxPoints: 7,
582
+ max_points: 7,
583
583
  run: () => {
584
584
  // Server-only: checks if package has approved skills.
585
585
  // CLI cannot determine this — assumes fail.
586
586
  return {
587
587
  passed: false,
588
588
  detail: "Full check runs server-side",
589
- serverOnly: true,
589
+ server_only: true,
590
590
  }
591
591
  },
592
592
  }
@@ -595,14 +595,14 @@ const skillsComprehensive = {
595
595
  id: "skills-comprehensive",
596
596
  category: "health",
597
597
  label: "Comprehensive Agent Skills",
598
- maxPoints: 3,
598
+ max_points: 3,
599
599
  run: () => {
600
600
  // Server-only: checks if package has 3+ approved skills.
601
601
  // CLI cannot determine this — assumes fail.
602
602
  return {
603
603
  passed: false,
604
604
  detail: "Full check runs server-side",
605
- serverOnly: true,
605
+ server_only: true,
606
606
  }
607
607
  },
608
608
  }
@@ -44,13 +44,13 @@ export function displayQualityReport({ score, checks, meta, warnings }) {
44
44
  const tierColor = TIER_COLORS[meta.tier] || chalk.white
45
45
  const tierLabel = TIER_LABELS[meta.tier] || meta.tier
46
46
 
47
- const hasServerOnly = checks.some(c => c.serverOnly)
47
+ const hasServerOnly = checks.some(c => c.server_only)
48
48
 
49
49
  console.log("")
50
50
 
51
51
  // Individual checks first
52
52
  for (const check of checks) {
53
- if (check.serverOnly) {
53
+ if (check.server_only) {
54
54
  // Show server-only checks dimmed with ~ icon
55
55
  const icon = chalk.dim("~")
56
56
  const label = chalk.dim(check.label)
@@ -65,13 +65,13 @@ export function displayQualityReport({ score, checks, meta, warnings }) {
65
65
  }
66
66
 
67
67
  // Tips for failed checks (exclude server-only)
68
- const failed = checks.filter(c => !c.passed && !c.serverOnly)
68
+ const failed = checks.filter(c => !c.passed && !c.server_only)
69
69
  if (failed.length > 0) {
70
70
  console.log("")
71
71
  const tips = failed.slice(0, 3)
72
72
  for (const check of tips) {
73
73
  console.log(
74
- chalk.dim(` Tip: ${getTip(check.id)} (+${check.maxPoints} points)`),
74
+ chalk.dim(` Tip: ${getTip(check.id)} (+${check.max_points} points)`),
75
75
  )
76
76
  }
77
77
  }
@@ -72,7 +72,7 @@ export function runQualityChecks({
72
72
  const points = result.passed
73
73
  ? result.points !== undefined
74
74
  ? result.points
75
- : check.maxPoints
75
+ : check.max_points
76
76
  : 0
77
77
  return {
78
78
  id: check.id,
@@ -80,20 +80,20 @@ export function runQualityChecks({
80
80
  label: check.label,
81
81
  passed: result.passed,
82
82
  points,
83
- maxPoints: check.maxPoints,
83
+ max_points: check.max_points,
84
84
  detail: result.detail,
85
- ...(result.serverOnly && { serverOnly: true }),
85
+ ...(result.server_only && { server_only: true }),
86
86
  }
87
87
  })
88
88
 
89
- // Compute category scores dynamically from actual check maxPoints
89
+ // Compute category scores dynamically from actual check max_points
90
90
  const categories = {}
91
91
  for (const result of results) {
92
92
  if (!categories[result.category]) {
93
93
  categories[result.category] = { score: 0, max: 0 }
94
94
  }
95
95
  categories[result.category].score += result.points
96
- categories[result.category].max += result.maxPoints
96
+ categories[result.category].max += result.max_points
97
97
  }
98
98
 
99
99
  const totalScore = Object.values(categories).reduce(
@@ -18,7 +18,7 @@ export const swiftReadmeHasInstall = {
18
18
  id: "readme-install",
19
19
  category: "documentation",
20
20
  label: "README has install section",
21
- maxPoints: 3,
21
+ max_points: 3,
22
22
  run: ({ readme }) => {
23
23
  if (!readme) return { passed: false, detail: "No README" }
24
24
  const lower = readme.toLowerCase()
@@ -47,7 +47,7 @@ export const hasPlatformDeclarations = {
47
47
  id: "has-platforms",
48
48
  category: "code",
49
49
  label: "Has platform declarations",
50
- maxPoints: 6,
50
+ max_points: 6,
51
51
  run: ({ swiftManifest }) => {
52
52
  if (!swiftManifest)
53
53
  return { passed: false, detail: "No Swift manifest data" }
@@ -71,7 +71,7 @@ export const recentToolsVersion = {
71
71
  id: "recent-tools-version",
72
72
  category: "code",
73
73
  label: "Uses recent swift-tools-version",
74
- maxPoints: 5,
74
+ max_points: 5,
75
75
  run: ({ swiftManifest }) => {
76
76
  if (!swiftManifest)
77
77
  return { passed: false, detail: "No Swift manifest data" }
@@ -101,7 +101,7 @@ export const supportsMultiplePlatforms = {
101
101
  id: "multi-platform",
102
102
  category: "code",
103
103
  label: "Supports multiple platforms",
104
- maxPoints: 4,
104
+ max_points: 4,
105
105
  run: ({ swiftManifest }) => {
106
106
  if (!swiftManifest)
107
107
  return { passed: false, detail: "No Swift manifest data" }
@@ -127,7 +127,7 @@ export const hasPublicAPI = {
127
127
  id: "has-public-api",
128
128
  category: "code",
129
129
  label: "Has public API surface",
130
- maxPoints: 5,
130
+ max_points: 5,
131
131
  run: ({ files }) => {
132
132
  // Check if any .swift source files exist (exclude manifest and tests)
133
133
  const swiftFiles = files.filter(f => {
@@ -146,7 +146,7 @@ export const hasPublicAPI = {
146
146
  return {
147
147
  passed: true,
148
148
  detail: `${swiftFiles.length} Swift source file${swiftFiles.length !== 1 ? "s" : ""} found`,
149
- serverOnly: true,
149
+ server_only: true,
150
150
  }
151
151
  },
152
152
  }
@@ -155,14 +155,14 @@ export const hasDocComments = {
155
155
  id: "has-doc-comments",
156
156
  category: "code",
157
157
  label: "Has DocC documentation",
158
- maxPoints: 7,
158
+ max_points: 7,
159
159
  run: () => {
160
160
  // Full check runs server-side from tarball contents.
161
161
  // CLI assumes pass; server overrides if no documentation found.
162
162
  return {
163
163
  passed: true,
164
164
  detail: "Full check runs server-side",
165
- serverOnly: true,
165
+ server_only: true,
166
166
  }
167
167
  },
168
168
  }
@@ -171,7 +171,7 @@ export const smallDepsSwift = {
171
171
  id: "small-deps",
172
172
  category: "code",
173
173
  label: "Small dependency footprint",
174
- maxPoints: 4,
174
+ max_points: 4,
175
175
  run: ({ swiftManifest }) => {
176
176
  if (!swiftManifest)
177
177
  return { passed: true, points: 4, detail: "No manifest data" }
@@ -196,7 +196,7 @@ export const swiftHasTestTargets = {
196
196
  id: "has-test-files",
197
197
  category: "testing",
198
198
  label: "Has test targets",
199
- maxPoints: 7,
199
+ max_points: 7,
200
200
  run: ({ swiftManifest, files }) => {
201
201
  // Check Swift manifest for test targets
202
202
  const testTargets = (swiftManifest?.targets || []).filter(
@@ -227,7 +227,7 @@ export const swiftHasTestScript = {
227
227
  id: "has-test-script",
228
228
  category: "testing",
229
229
  label: "Has test configuration",
230
- maxPoints: 4,
230
+ max_points: 4,
231
231
  run: ({ swiftManifest }) => {
232
232
  // For Swift, having test targets in the manifest is the equivalent
233
233
  const testTargets = (swiftManifest?.targets || []).filter(
@@ -249,7 +249,7 @@ export const xcfHasValidPlist = {
249
249
  id: "xcf-valid-plist",
250
250
  category: "code",
251
251
  label: "Valid Info.plist",
252
- maxPoints: 10,
252
+ max_points: 10,
253
253
  run: ({ xcframeworkMeta }) => {
254
254
  if (!xcframeworkMeta)
255
255
  return { passed: false, detail: "No XCFramework metadata" }
@@ -270,7 +270,7 @@ export const xcfMultipleSlices = {
270
270
  id: "xcf-multi-slice",
271
271
  category: "code",
272
272
  label: "Supports multiple platform slices",
273
- maxPoints: 15,
273
+ max_points: 15,
274
274
  run: ({ xcframeworkMeta }) => {
275
275
  if (!xcframeworkMeta)
276
276
  return { passed: false, detail: "No XCFramework metadata" }
@@ -301,7 +301,7 @@ export const xcfReasonableSize = {
301
301
  id: "xcf-size",
302
302
  category: "code",
303
303
  label: "Reasonable framework size",
304
- maxPoints: 5,
304
+ max_points: 5,
305
305
  run: ({ unpackedSize }) => {
306
306
  if (!unpackedSize)
307
307
  return { passed: true, points: 5, detail: "No size data" }
@@ -324,7 +324,7 @@ export const xcfHasArchitectures = {
324
324
  id: "xcf-architectures",
325
325
  category: "code",
326
326
  label: "Supports arm64 architecture",
327
- maxPoints: 10,
327
+ max_points: 10,
328
328
  run: ({ xcframeworkMeta }) => {
329
329
  if (!xcframeworkMeta)
330
330
  return { passed: false, detail: "No XCFramework metadata" }
@@ -347,7 +347,7 @@ export const xcfHealthReasonableSize = {
347
347
  id: "reasonable-size",
348
348
  category: "health",
349
349
  label: "Reasonable framework size",
350
- maxPoints: 3,
350
+ max_points: 3,
351
351
  run: ({ unpackedSize }) => {
352
352
  if (!unpackedSize)
353
353
  return { passed: true, points: 3, detail: "Size unknown" }
@@ -439,9 +439,9 @@ export const xcframeworkChecks = [
439
439
  hasHomepage,
440
440
  xcfHealthReasonableSize,
441
441
  noVulnerabilities,
442
- { ...maintenanceHealth, maxPoints: 5 },
442
+ { ...maintenanceHealth, max_points: 5 },
443
443
  semverConsistency,
444
- { ...authorVerified, maxPoints: 4 },
444
+ { ...authorVerified, max_points: 4 },
445
445
  hasSkills,
446
446
  skillsComprehensive,
447
447
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lpm-registry/cli",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "CLI for Licensed Package Manager",
5
5
  "author": "LPM <hello@lpm.dev> (https://lpm.dev)",
6
6
  "repository": {
@@ -61,6 +61,11 @@
61
61
  "xcode": "^3.0.1"
62
62
  },
63
63
  "optionalDependencies": {
64
+ "@lpm-registry/cli-darwin-arm64": "0.6.0",
65
+ "@lpm-registry/cli-darwin-x64": "0.6.0",
66
+ "@lpm-registry/cli-linux-x64": "0.6.0",
67
+ "@lpm-registry/cli-linux-arm64": "0.6.0",
68
+ "@lpm-registry/cli-win32-x64": "0.6.0",
64
69
  "keytar": "^7.9.0"
65
70
  },
66
71
  "type": "module",