@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.
Files changed (62) hide show
  1. package/README.md +25 -44
  2. package/bin/lpm.js +2 -354
  3. package/bin/lpx.js +4 -0
  4. package/bin/native.js +154 -0
  5. package/package.json +42 -82
  6. package/scripts/install-binary.js +219 -550
  7. package/CHANGELOG.md +0 -197
  8. package/LICENSE +0 -15
  9. package/index.d.ts +0 -131
  10. package/index.js +0 -31
  11. package/lib/api.js +0 -398
  12. package/lib/commands/add.js +0 -1217
  13. package/lib/commands/audit.js +0 -283
  14. package/lib/commands/cache.js +0 -209
  15. package/lib/commands/check-name.js +0 -112
  16. package/lib/commands/config.js +0 -186
  17. package/lib/commands/doctor.js +0 -140
  18. package/lib/commands/info.js +0 -215
  19. package/lib/commands/init.js +0 -146
  20. package/lib/commands/install.js +0 -264
  21. package/lib/commands/login.js +0 -595
  22. package/lib/commands/logout.js +0 -94
  23. package/lib/commands/marketplace-compare.js +0 -164
  24. package/lib/commands/marketplace-earnings.js +0 -89
  25. package/lib/commands/mcp-setup.js +0 -363
  26. package/lib/commands/npmrc.js +0 -178
  27. package/lib/commands/open.js +0 -82
  28. package/lib/commands/outdated.js +0 -291
  29. package/lib/commands/pool-stats.js +0 -100
  30. package/lib/commands/publish.js +0 -949
  31. package/lib/commands/quality.js +0 -211
  32. package/lib/commands/remove.js +0 -82
  33. package/lib/commands/run.js +0 -14
  34. package/lib/commands/search.js +0 -143
  35. package/lib/commands/setup.js +0 -221
  36. package/lib/commands/skills.js +0 -898
  37. package/lib/commands/token-rotate.js +0 -25
  38. package/lib/commands/uninstall.js +0 -107
  39. package/lib/commands/whoami.js +0 -129
  40. package/lib/config.js +0 -328
  41. package/lib/constants.js +0 -190
  42. package/lib/ecosystem.js +0 -501
  43. package/lib/editor-skills.js +0 -321
  44. package/lib/editors.js +0 -215
  45. package/lib/import-rewriter.js +0 -364
  46. package/lib/install-targets/mcp-server.js +0 -245
  47. package/lib/install-targets/vscode-extension.js +0 -178
  48. package/lib/install-targets.js +0 -82
  49. package/lib/integrity.js +0 -179
  50. package/lib/lpm-config-prompts.js +0 -102
  51. package/lib/lpm-config.js +0 -408
  52. package/lib/oidc.js +0 -166
  53. package/lib/project-utils.js +0 -152
  54. package/lib/quality/checks.js +0 -687
  55. package/lib/quality/display.js +0 -155
  56. package/lib/quality/score.js +0 -118
  57. package/lib/quality/swift-checks.js +0 -447
  58. package/lib/safe-path.js +0 -180
  59. package/lib/secure-store.js +0 -321
  60. package/lib/swift-project.js +0 -637
  61. package/lib/ui.js +0 -40
  62. package/scripts/__tests__/install-binary.test.js +0 -346
@@ -1,186 +0,0 @@
1
- /**
2
- * Config Command
3
- *
4
- * Manage CLI configuration values.
5
- *
6
- * Usage:
7
- * lpm config list List all configuration values
8
- * lpm config get <key> Get a specific config value
9
- * lpm config set <key> <value> Set a config value
10
- * lpm config delete <key> Delete a config value (reset to default)
11
- *
12
- * Configurable Keys:
13
- * registry - Registry URL (default: https://lpm.dev)
14
- * timeout - Request timeout in milliseconds (default: 30000)
15
- * retries - Maximum retry attempts (default: 3)
16
- *
17
- * @module cli/lib/commands/config
18
- */
19
-
20
- import chalk from "chalk"
21
- import {
22
- deleteConfigValue,
23
- getAllConfig,
24
- getConfigValue,
25
- getToken,
26
- setConfigValue,
27
- } from "../config.js"
28
-
29
- /**
30
- * List all configuration values.
31
- */
32
- async function listConfig() {
33
- console.log(chalk.bold("\nLPM Configuration:\n"))
34
-
35
- const config = await getAllConfig()
36
-
37
- // Format and display each config value
38
- const entries = [
39
- ["Registry URL", config.registryUrl],
40
- ["Request Timeout", `${config.timeout}ms`],
41
- ["Max Retries", config.retries],
42
- ["Secure Storage", config.secureStorage],
43
- [
44
- "Authenticated",
45
- config.authenticated ? chalk.green("Yes") : chalk.dim("No"),
46
- ],
47
- ]
48
-
49
- const maxKeyLength = Math.max(...entries.map(([key]) => key.length))
50
-
51
- for (const [key, value] of entries) {
52
- const paddedKey = key.padEnd(maxKeyLength)
53
- console.log(` ${chalk.cyan(paddedKey)} ${value}`)
54
- }
55
-
56
- console.log("")
57
- }
58
-
59
- /**
60
- * Get a specific configuration value.
61
- * @param {string} key - The config key to get
62
- */
63
- async function getConfig(key) {
64
- // Token lives in secure storage, not the general config store
65
- if (key === "token") {
66
- const token = await getToken()
67
- if (!token) {
68
- console.log(chalk.yellow("No token found. Run `lpm login` first."))
69
- return
70
- }
71
- console.log(token)
72
- return
73
- }
74
-
75
- const value = getConfigValue(key)
76
-
77
- if (value === undefined) {
78
- console.log(chalk.yellow(`Configuration key '${key}' is not set.`))
79
- return
80
- }
81
-
82
- console.log(value)
83
- }
84
-
85
- /**
86
- * Set a configuration value.
87
- * @param {string} key - The config key to set
88
- * @param {string} value - The value to set
89
- */
90
- function setConfig(key, value) {
91
- // Validate known keys
92
- const numericKeys = ["timeout", "retries"]
93
- if (numericKeys.includes(key)) {
94
- const numValue = parseInt(value, 10)
95
- if (Number.isNaN(numValue) || numValue < 0) {
96
- console.error(chalk.red(`Error: '${key}' must be a positive number.`))
97
- process.exit(1)
98
- }
99
- }
100
-
101
- // Validate registry URL
102
- if (key === "registry" || key === "registryUrl") {
103
- try {
104
- new URL(value)
105
- } catch {
106
- console.error(chalk.red(`Error: '${value}' is not a valid URL.`))
107
- process.exit(1)
108
- }
109
- }
110
-
111
- const success = setConfigValue(key, value)
112
-
113
- if (success) {
114
- console.log(chalk.green(`Set ${key} = ${value}`))
115
- } else {
116
- console.error(chalk.red(`Failed to set '${key}'.`))
117
- process.exit(1)
118
- }
119
- }
120
-
121
- /**
122
- * Delete a configuration value (reset to default).
123
- * @param {string} key - The config key to delete
124
- */
125
- function deleteConfig(key) {
126
- const success = deleteConfigValue(key)
127
-
128
- if (success) {
129
- console.log(chalk.green(`Reset '${key}' to default value.`))
130
- } else {
131
- console.error(chalk.red(`Failed to delete '${key}'.`))
132
- process.exit(1)
133
- }
134
- }
135
-
136
- /**
137
- * Execute the config command.
138
- *
139
- * @param {string} action - The action to perform (list, get, set, delete)
140
- * @param {string} [key] - The config key
141
- * @param {string} [value] - The value to set
142
- */
143
- export async function config(action, key, value) {
144
- switch (action) {
145
- case "list":
146
- case undefined:
147
- await listConfig()
148
- break
149
-
150
- case "get":
151
- if (!key) {
152
- console.error(chalk.red("Error: Key required."))
153
- console.log(chalk.dim("Usage: lpm config get <key>"))
154
- process.exit(1)
155
- }
156
- await getConfig(key)
157
- break
158
-
159
- case "set":
160
- if (!key || value === undefined) {
161
- console.error(chalk.red("Error: Key and value required."))
162
- console.log(chalk.dim("Usage: lpm config set <key> <value>"))
163
- process.exit(1)
164
- }
165
- setConfig(key, value)
166
- break
167
-
168
- case "delete":
169
- case "rm":
170
- case "remove":
171
- if (!key) {
172
- console.error(chalk.red("Error: Key required."))
173
- console.log(chalk.dim("Usage: lpm config delete <key>"))
174
- process.exit(1)
175
- }
176
- deleteConfig(key)
177
- break
178
-
179
- default:
180
- console.error(chalk.red(`Unknown action: ${action}`))
181
- console.log(chalk.dim("Available actions: list, get, set, delete"))
182
- process.exit(1)
183
- }
184
- }
185
-
186
- export default config
@@ -1,140 +0,0 @@
1
- import fs from "node:fs"
2
- import path from "node:path"
3
- import chalk from "chalk"
4
- import { getRegistryUrl, getToken } from "../config.js"
5
- import { createSpinner, log, printHeader } from "../ui.js"
6
-
7
- export async function doctor() {
8
- printHeader()
9
- log.info("Running health checks...\n")
10
-
11
- const checks = []
12
-
13
- // 1. Check Auth
14
- const spinnerAuth = createSpinner("Checking authentication...").start()
15
- const token = await getToken()
16
- if (token) {
17
- spinnerAuth.succeed("Authentication token found.")
18
- checks.push({ name: "Auth Token", status: "ok" })
19
- } else {
20
- spinnerAuth.fail("No authentication token found. Run `lpm login`.")
21
- checks.push({ name: "Auth Token", status: "fail" })
22
- }
23
-
24
- // 2. Check Registry Reachability
25
- const spinnerApi = createSpinner("Checking registry connection...").start()
26
- try {
27
- const registryUrl = getRegistryUrl()
28
- // Use /-/whoami without a token — a 401 "Missing token" proves the registry is reachable.
29
- // Only network errors (ECONNREFUSED, timeout) indicate the registry is down.
30
- await fetch(`${registryUrl}/api/registry/-/whoami`, {
31
- signal: AbortSignal.timeout(10000),
32
- })
33
- spinnerApi.succeed(`Registry reachable at ${registryUrl}`)
34
- checks.push({ name: "Registry API", status: "ok" })
35
- } catch (err) {
36
- spinnerApi.fail(`Could not connect to registry: ${err.message}`)
37
- checks.push({ name: "Registry API", status: "fail" })
38
- }
39
-
40
- // 3. Check Quota (via whoami)
41
- if (token) {
42
- const spinnerQuota = createSpinner("Checking account quota...").start()
43
- try {
44
- // We can reuse the whoami logic or fetch directly
45
- // Since we are in doctor, let's fetch directly using the token
46
- const registryUrl = getRegistryUrl()
47
- const res = await fetch(`${registryUrl}/api/registry/-/whoami`, {
48
- headers: {
49
- Authorization: `Bearer ${token}`,
50
- },
51
- })
52
-
53
- if (res.ok) {
54
- const data = await res.json()
55
- if (data.plan_tier) {
56
- const limits = data.limits || {}
57
- let isOverLimit = false
58
- const statusMsg = `Plan: ${data.plan_tier.toUpperCase()}`
59
-
60
- if (limits.storageBytes) {
61
- if (data.usage.storage_bytes > limits.storageBytes)
62
- isOverLimit = true
63
- }
64
- if (
65
- limits.privatePackages &&
66
- limits.privatePackages !== Number.POSITIVE_INFINITY &&
67
- limits.privatePackages !== null
68
- ) {
69
- if (data.usage.private_packages > limits.privatePackages)
70
- isOverLimit = true
71
- }
72
-
73
- if (isOverLimit) {
74
- spinnerQuota.fail(`${statusMsg} | OVER LIMIT`)
75
- checks.push({ name: "Account Quota", status: "fail" })
76
- } else {
77
- spinnerQuota.succeed(
78
- `${statusMsg} | Storage: ${(data.usage.storage_bytes / 1024 / 1024).toFixed(0)}MB`,
79
- )
80
- checks.push({ name: "Account Quota", status: "ok" })
81
- }
82
- } else {
83
- spinnerQuota.info("Could not retrieve detailed quota info.")
84
- checks.push({ name: "Account Quota", status: "info" })
85
- }
86
- } else {
87
- spinnerQuota.warn("Could not fetch account details.")
88
- checks.push({ name: "Account Quota", status: "warn" })
89
- }
90
- } catch (err) {
91
- spinnerQuota.warn(`Quota check failed: ${err.message}`)
92
- checks.push({ name: "Account Quota", status: "warn" })
93
- }
94
- }
95
-
96
- // 4. Check .npmrc
97
- const spinnerNpmrc = createSpinner("Checking .npmrc configuration...").start()
98
- const npmrcPath = path.join(process.cwd(), ".npmrc")
99
- if (fs.existsSync(npmrcPath)) {
100
- const content = fs.readFileSync(npmrcPath, "utf-8")
101
- if (content.includes("registry=")) {
102
- spinnerNpmrc.succeed(".npmrc found and configured.")
103
- checks.push({ name: ".npmrc", status: "ok" })
104
- } else {
105
- spinnerNpmrc.warn(".npmrc found but might be missing registry config.")
106
- checks.push({ name: ".npmrc", status: "warn" })
107
- }
108
- } else {
109
- spinnerNpmrc.info("No local .npmrc found (global config might be used).")
110
- checks.push({ name: ".npmrc", status: "info" })
111
- }
112
-
113
- console.log("\nSummary:")
114
- checks.forEach(c => {
115
- const symbol =
116
- c.status === "ok"
117
- ? "✔"
118
- : c.status === "fail"
119
- ? "✖"
120
- : c.status === "warn"
121
- ? "⚠"
122
- : "ℹ"
123
- const color =
124
- c.status === "ok"
125
- ? chalk.green
126
- : c.status === "fail"
127
- ? chalk.red
128
- : c.status === "warn"
129
- ? chalk.yellow
130
- : chalk.blue
131
- console.log(color(`${symbol} ${c.name}`))
132
- })
133
-
134
- if (checks.some(c => c.status === "fail")) {
135
- console.log(chalk.red("\nSome checks failed. Please fix the issues above."))
136
- process.exit(1)
137
- } else {
138
- console.log(chalk.green("\nAll systems operational."))
139
- }
140
- }
@@ -1,215 +0,0 @@
1
- /**
2
- * Info Command
3
- *
4
- * Display detailed information about a package.
5
- *
6
- * Usage:
7
- * lpm info <package> [options]
8
- *
9
- * Options:
10
- * --json Output in JSON format
11
- * --versions Show all versions
12
- *
13
- * @module cli/lib/commands/info
14
- */
15
-
16
- import chalk from "chalk"
17
- import ora from "ora"
18
- import { get } from "../api.js"
19
-
20
- /**
21
- * Parse a package specifier.
22
- * @param {string} specifier - Package name (e.g., '@scope/name', 'name', 'name@1.0.0')
23
- * @returns {{ name: string, scope?: string, version?: string }}
24
- */
25
- function parsePackageSpecifier(specifier) {
26
- let name = specifier
27
- let scope
28
- let version
29
-
30
- // Handle version specifier
31
- const versionMatch = name.match(/^(.+)@(\d+\.\d+\.\d+.*)$/)
32
- if (versionMatch) {
33
- name = versionMatch[1]
34
- version = versionMatch[2]
35
- }
36
-
37
- // Handle scope
38
- if (name.startsWith("@")) {
39
- const scopeMatch = name.match(/^@([^/]+)\/(.+)$/)
40
- if (scopeMatch) {
41
- scope = scopeMatch[1]
42
- name = scopeMatch[2]
43
- }
44
- }
45
-
46
- return { name, scope, version }
47
- }
48
-
49
- /**
50
- * Format a date for display.
51
- * @param {string} dateStr
52
- * @returns {string}
53
- */
54
- function formatDate(dateStr) {
55
- const date = new Date(dateStr)
56
- return date.toLocaleDateString("en-US", {
57
- year: "numeric",
58
- month: "short",
59
- day: "numeric",
60
- })
61
- }
62
-
63
- /**
64
- * Execute the info command.
65
- *
66
- * @param {string} packageSpec - Package specifier
67
- * @param {Object} options - Command options
68
- * @param {boolean} [options.json] - Output as JSON
69
- * @param {boolean} [options.versions] - Show all versions
70
- */
71
- export async function info(packageSpec, options = {}) {
72
- if (!packageSpec || packageSpec.trim() === "") {
73
- console.error(chalk.red("Error: Package name required."))
74
- console.log(chalk.dim("Usage: lpm info <package>"))
75
- process.exit(1)
76
- }
77
-
78
- const { name, scope, version } = parsePackageSpecifier(packageSpec)
79
- const packagePath = scope ? `@${scope}/${name}` : name
80
-
81
- const spinner = ora(`Fetching info for ${packagePath}...`).start()
82
-
83
- try {
84
- // Registry uses NPM-compatible paths: /@scope/pkg or /@scope/pkg/version
85
- const url = version
86
- ? `/${encodeURIComponent(packagePath)}/${version}`
87
- : `/${encodeURIComponent(packagePath)}`
88
-
89
- const response = await get(url, {
90
- onRetry: (attempt, max) => {
91
- spinner.text = `Fetching (retry ${attempt}/${max})...`
92
- },
93
- })
94
-
95
- if (!response.ok) {
96
- if (response.status === 404) {
97
- throw new Error(`Package "${packagePath}" not found.`)
98
- }
99
- const data = await response.json().catch(() => ({}))
100
- throw new Error(data.error || `Failed to fetch package info.`)
101
- }
102
-
103
- const pkg = await response.json()
104
-
105
- spinner.stop()
106
-
107
- if (options.json) {
108
- console.log(JSON.stringify(pkg, null, 2))
109
- return
110
- }
111
-
112
- // Get latest version data from versions object
113
- const latestVersionTag = pkg["dist-tags"]?.latest
114
- const latestVersionData = latestVersionTag
115
- ? pkg.versions?.[latestVersionTag]
116
- : null
117
-
118
- // Display package info
119
- const fullName = pkg.name
120
-
121
- console.log("")
122
- console.log(
123
- chalk.bold.cyan(fullName) +
124
- chalk.dim(`@${pkg.latestVersion || latestVersionTag || "no versions"}`),
125
- )
126
- console.log("")
127
-
128
- if (pkg.description) {
129
- console.log(chalk.white(pkg.description))
130
- console.log("")
131
- }
132
-
133
- // Metadata table
134
- const metadata = [
135
- ["Latest Version", pkg.latestVersion || latestVersionTag || "N/A"],
136
- ["License", latestVersionData?.license || pkg.license || "N/A"],
137
- ["Author", latestVersionData?.author || pkg.author || "N/A"],
138
- ["Published", pkg.publishedAt ? formatDate(pkg.publishedAt) : "N/A"],
139
- ["Downloads", (pkg.downloads ?? 0).toLocaleString()],
140
- ]
141
-
142
- if (latestVersionData?.repository || pkg.repository) {
143
- metadata.push([
144
- "Repository",
145
- latestVersionData?.repository || pkg.repository,
146
- ])
147
- }
148
-
149
- if (latestVersionData?.homepage || pkg.homepage) {
150
- metadata.push(["Homepage", latestVersionData?.homepage || pkg.homepage])
151
- }
152
-
153
- const maxKeyLength = Math.max(...metadata.map(([key]) => key.length))
154
-
155
- for (const [key, value] of metadata) {
156
- const paddedKey = key.padEnd(maxKeyLength)
157
- console.log(` ${chalk.dim(paddedKey)} ${value}`)
158
- }
159
-
160
- console.log("")
161
-
162
- // Dependencies from latest version
163
- const deps = latestVersionData?.dependencies || pkg.dependencies
164
- if (deps && Object.keys(deps).length > 0) {
165
- console.log(chalk.bold("Dependencies:"))
166
- for (const [dep, ver] of Object.entries(deps)) {
167
- console.log(` ${chalk.cyan(dep)} ${chalk.dim(ver)}`)
168
- }
169
- console.log("")
170
- }
171
-
172
- // Show versions if requested (versions is an object, not array)
173
- if (
174
- options.allVersions &&
175
- pkg.versions &&
176
- Object.keys(pkg.versions).length > 0
177
- ) {
178
- console.log(chalk.bold("Versions:"))
179
- const versionList = Object.keys(pkg.versions).reverse().slice(0, 20)
180
- for (const v of versionList) {
181
- const date = pkg.time?.[v] ? formatDate(pkg.time[v]) : ""
182
- console.log(` ${chalk.green(v)} ${chalk.dim(date)}`)
183
- }
184
- if (Object.keys(pkg.versions).length > 20) {
185
- console.log(
186
- chalk.dim(
187
- ` ... and ${Object.keys(pkg.versions).length - 20} more versions`,
188
- ),
189
- )
190
- }
191
- console.log("")
192
- }
193
-
194
- // Keywords
195
- const keywords = latestVersionData?.keywords || pkg.keywords
196
- if (keywords && keywords.length > 0) {
197
- console.log(
198
- chalk.bold("Keywords:") +
199
- " " +
200
- keywords.map(k => chalk.dim(k)).join(", "),
201
- )
202
- console.log("")
203
- }
204
-
205
- // Install hint
206
- console.log(chalk.dim(`Install: lpm install ${fullName}`))
207
- console.log("")
208
- } catch (error) {
209
- spinner.fail(chalk.red("Failed to fetch package info."))
210
- console.error(chalk.red(` ${error.message}`))
211
- process.exit(1)
212
- }
213
- }
214
-
215
- export default info
@@ -1,146 +0,0 @@
1
- import fs from "node:fs"
2
- import path from "node:path"
3
- import * as p from "@clack/prompts"
4
- import chalk from "chalk"
5
- import { getRegistryUrl } from "../config.js"
6
- import { printHeader } from "../ui.js"
7
- import { setup } from "./setup.js"
8
-
9
- /**
10
- * Parse package name in the @lpm.dev/owner.package format
11
- */
12
- function parsePackageName(name) {
13
- if (!name.startsWith("@lpm.dev/")) {
14
- return { error: "Package name must start with @lpm.dev/" }
15
- }
16
-
17
- const nameWithOwner = name.replace("@lpm.dev/", "")
18
- const dotIndex = nameWithOwner.indexOf(".")
19
-
20
- if (dotIndex === -1) {
21
- return { error: "Format: @lpm.dev/owner.package-name" }
22
- }
23
-
24
- const owner = nameWithOwner.substring(0, dotIndex)
25
- const pkgName = nameWithOwner.substring(dotIndex + 1)
26
-
27
- // Validate owner format
28
- if (!/^[a-z][a-z0-9-]*$/.test(owner)) {
29
- return {
30
- error:
31
- "Owner must start with a letter and contain only lowercase letters, numbers, and hyphens",
32
- }
33
- }
34
-
35
- // Validate package name format
36
- if (!/^[a-z][a-z0-9-]*$/.test(pkgName)) {
37
- return {
38
- error:
39
- "Package name must start with a letter and contain only lowercase letters, numbers, and hyphens",
40
- }
41
- }
42
-
43
- return { owner, name: pkgName }
44
- }
45
-
46
- export async function init() {
47
- printHeader()
48
-
49
- p.intro(chalk.bgCyan(chalk.black(" lpm init ")))
50
-
51
- const project = await p.group(
52
- {
53
- name: () =>
54
- p.text({
55
- message: "What is the name of your package?",
56
- placeholder: "@lpm.dev/username.package-name",
57
- validate: value => {
58
- if (!value) return "Name is required"
59
- const parsed = parsePackageName(value)
60
- if (parsed.error) return parsed.error
61
- },
62
- }),
63
- version: () =>
64
- p.text({
65
- message: "Version",
66
- initialValue: "0.1.0",
67
- }),
68
- description: () =>
69
- p.text({
70
- message: "Description",
71
- placeholder: "A brief description of your package",
72
- }),
73
- entry: () =>
74
- p.text({
75
- message: "Entry point",
76
- initialValue: "index.js",
77
- }),
78
- license: () =>
79
- p.select({
80
- message: "License type",
81
- options: [
82
- { value: "ISC", label: "ISC" },
83
- { value: "MIT", label: "MIT" },
84
- { value: "UNLICENSED", label: "UNLICENSED (Private/Proprietary)" },
85
- ],
86
- }),
87
- confirm: () =>
88
- p.confirm({
89
- message: "Create package.json?",
90
- initialValue: true,
91
- }),
92
- },
93
- {
94
- onCancel: () => {
95
- p.cancel("Operation cancelled.")
96
- process.exit(0)
97
- },
98
- },
99
- )
100
-
101
- if (project.confirm) {
102
- const registryUrl = getRegistryUrl()
103
- const packageJson = {
104
- name: project.name,
105
- version: project.version,
106
- description: project.description,
107
- main: project.entry,
108
- scripts: {
109
- test: 'echo "Error: no test specified" && exit 1',
110
- },
111
- author: "",
112
- license: project.license,
113
- publishConfig: {
114
- registry: `${registryUrl}/api/registry/`,
115
- },
116
- }
117
-
118
- const filePath = path.join(process.cwd(), "package.json")
119
- fs.writeFileSync(filePath, JSON.stringify(packageJson, null, 2))
120
-
121
- p.note(JSON.stringify(packageJson, null, 2), "package.json")
122
-
123
- // Offer to setup .npmrc
124
- const npmrcPath = path.join(process.cwd(), ".npmrc")
125
- if (
126
- !fs.existsSync(npmrcPath) ||
127
- !fs.readFileSync(npmrcPath, "utf8").includes("@lpm.dev:registry")
128
- ) {
129
- const setupNpmrc = await p.confirm({
130
- message: "Create .npmrc for local development?",
131
- initialValue: true,
132
- })
133
-
134
- if (!p.isCancel(setupNpmrc) && setupNpmrc) {
135
- await setup({ registry: registryUrl })
136
- return
137
- }
138
- }
139
-
140
- p.outro(
141
- `Package initialized! Run ${chalk.cyan("lpm publish")} to push to the registry.`,
142
- )
143
- } else {
144
- p.outro("Cancelled.")
145
- }
146
- }