forked from npmx-dev/npmx.dev
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcli.ts
More file actions
114 lines (91 loc) · 3.03 KB
/
cli.ts
File metadata and controls
114 lines (91 loc) · 3.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env node
import process from 'node:process'
import { spawn } from 'node:child_process'
import { styleText } from 'node:util'
import * as p from '@clack/prompts'
import { defineCommand, runMain } from 'citty'
import { serve } from 'srvx'
import { createConnectorApp, generateToken, CONNECTOR_VERSION } from './server.ts'
import { getNpmUser, NPM_REGISTRY_URL } from './npm-client.ts'
import { initLogger, showToken, logInfo, logWarning, logError } from './logger.ts'
import { resolveNpmProcessCommand } from './npm-process.ts'
const DEFAULT_PORT = 31415
const DEFAULT_FRONTEND_URL = 'https://npmx.dev/'
const DEV_FRONTEND_URL = 'http://127.0.0.1:3000/'
async function runNpmLogin(): Promise<boolean> {
const { command, args } = resolveNpmProcessCommand(['login', `--registry=${NPM_REGISTRY_URL}`])
const child = spawn(command, args, { stdio: 'inherit' })
const { promise, resolve } = Promise.withResolvers<boolean>()
child.on('close', code => {
resolve(code === 0)
})
child.on('error', () => {
resolve(false)
})
return promise
}
const main = defineCommand({
meta: {
name: 'npmx-connector',
version: CONNECTOR_VERSION,
description: 'Local connector for npmx.dev',
},
args: {
port: {
type: 'string',
description: 'Port to listen on',
default: String(DEFAULT_PORT),
},
},
async run({ args }) {
const port = Number.parseInt(args.port as string, 10) || DEFAULT_PORT
const frontendUrl =
process.env.NPMX_CLI_DEV === 'true' ? DEV_FRONTEND_URL : DEFAULT_FRONTEND_URL
initLogger()
// Warning message and accept prompt
logWarning(
`This allows ${styleText('underline', 'npmx.dev')} to access your npm cli and any authenticated contexts.`,
)
const accept = await p.confirm({
message: 'Do you accept?',
initialValue: true,
})
if (!accept || p.isCancel(accept)) {
logError('Connector setup cancelled.')
process.exit(0)
}
// Check npm authentication before starting
logInfo('Checking npm authentication...')
let npmUser = await getNpmUser()
if (!npmUser) {
logWarning('Not logged in to npm. Starting npm login...')
// oxlint-disable-next-line no-console -- deliberate spacing
console.log()
const loginSuccess = await runNpmLogin()
// oxlint-disable-next-line no-console -- deliberate spacing
console.log()
if (!loginSuccess) {
logWarning('npm login failed or was cancelled.')
process.exit(1)
}
// Check again after login
npmUser = await getNpmUser()
if (!npmUser) {
logWarning('Still not authenticated after login attempt.')
process.exit(1)
}
}
logInfo(`Authenticated as: ${npmUser}`)
const token = generateToken()
showToken(token, port, frontendUrl)
const app = createConnectorApp(token)
const server = serve({
port,
hostname: '127.0.0.1',
fetch: app.fetch,
})
await server.ready()
logInfo('Waiting for connection... (Press Ctrl+C to stop)')
},
})
runMain(main)