@orchid-labs/pluxx 0.1.1 → 0.1.3
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 -8
- package/bin/pluxx.js +19 -28
- package/dist/agents.d.ts +16 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/cli/agent.d.ts +62 -0
- package/dist/cli/agent.d.ts.map +1 -1
- package/dist/cli/doctor.d.ts +2 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/entry.d.ts +2 -0
- package/dist/cli/entry.d.ts.map +1 -0
- package/dist/cli/index.d.ts +7 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +21810 -0
- package/dist/cli/init-from-mcp.d.ts +17 -1
- package/dist/cli/init-from-mcp.d.ts.map +1 -1
- package/dist/cli/install.d.ts +1 -0
- package/dist/cli/install.d.ts.map +1 -1
- package/dist/cli/lint.d.ts +3 -1
- package/dist/cli/lint.d.ts.map +1 -1
- package/dist/cli/mcp-proxy.d.ts.map +1 -1
- package/dist/cli/migrate.d.ts.map +1 -1
- package/dist/cli/primitive-summary.d.ts +14 -0
- package/dist/cli/primitive-summary.d.ts.map +1 -0
- package/dist/cli/prompt.d.ts +1 -1
- package/dist/cli/publish.d.ts +6 -1
- package/dist/cli/publish.d.ts.map +1 -1
- package/dist/cli/sync-from-mcp.d.ts.map +1 -1
- package/dist/cli/verify-install.d.ts +25 -0
- package/dist/cli/verify-install.d.ts.map +1 -0
- package/dist/commands.d.ts +10 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/compiler-intent.d.ts +165 -0
- package/dist/compiler-intent.d.ts.map +1 -0
- package/dist/config/load.d.ts.map +1 -1
- package/dist/delegation.d.ts +11 -0
- package/dist/delegation.d.ts.map +1 -0
- package/dist/generators/amp/index.d.ts.map +1 -1
- package/dist/generators/base.d.ts +5 -0
- package/dist/generators/base.d.ts.map +1 -1
- package/dist/generators/claude-code/index.d.ts.map +1 -1
- package/dist/generators/cline/index.d.ts.map +1 -1
- package/dist/generators/codex/index.d.ts +4 -0
- package/dist/generators/codex/index.d.ts.map +1 -1
- package/dist/generators/cursor/index.d.ts +1 -0
- package/dist/generators/cursor/index.d.ts.map +1 -1
- package/dist/generators/gemini-cli/index.d.ts.map +1 -1
- package/dist/generators/github-copilot/index.d.ts.map +1 -1
- package/dist/generators/opencode/index.d.ts +1 -0
- package/dist/generators/opencode/index.d.ts.map +1 -1
- package/dist/generators/openhands/index.d.ts.map +1 -1
- package/dist/generators/roo-code/index.d.ts.map +1 -1
- package/dist/generators/shared/claude-family.d.ts.map +1 -1
- package/dist/generators/warp/index.d.ts.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5371 -553
- package/dist/schema.d.ts +91 -42
- package/dist/schema.d.ts.map +1 -1
- package/dist/text-files.d.ts +5 -0
- package/dist/text-files.d.ts.map +1 -0
- package/dist/validation/platform-rules.d.ts +15 -1
- package/dist/validation/platform-rules.d.ts.map +1 -1
- package/package.json +15 -13
- package/src/cli/agent.ts +0 -1455
- package/src/cli/dev.ts +0 -112
- package/src/cli/doctor.ts +0 -987
- package/src/cli/eval.ts +0 -470
- package/src/cli/index.ts +0 -2933
- package/src/cli/init-from-mcp.ts +0 -2115
- package/src/cli/install.ts +0 -860
- package/src/cli/lint.ts +0 -1249
- package/src/cli/mcp-proxy.ts +0 -322
- package/src/cli/migrate.ts +0 -867
- package/src/cli/prompt.ts +0 -82
- package/src/cli/publish.ts +0 -401
- package/src/cli/runtime.ts +0 -86
- package/src/cli/sync-from-mcp.ts +0 -586
- package/src/cli/test.ts +0 -142
- package/src/compatibility/matrix.ts +0 -149
- package/src/config/define.ts +0 -20
- package/src/config/load.ts +0 -74
- package/src/generators/amp/index.ts +0 -63
- package/src/generators/base.ts +0 -188
- package/src/generators/claude-code/index.ts +0 -172
- package/src/generators/cline/index.ts +0 -35
- package/src/generators/codex/index.ts +0 -143
- package/src/generators/cursor/index.ts +0 -158
- package/src/generators/gemini-cli/index.ts +0 -83
- package/src/generators/github-copilot/index.ts +0 -32
- package/src/generators/hooks-warning.ts +0 -51
- package/src/generators/index.ts +0 -71
- package/src/generators/opencode/index.ts +0 -526
- package/src/generators/openhands/index.ts +0 -32
- package/src/generators/roo-code/index.ts +0 -35
- package/src/generators/shared/claude-family.ts +0 -215
- package/src/generators/warp/index.ts +0 -32
- package/src/hook-events.ts +0 -33
- package/src/index.ts +0 -34
- package/src/mcp/introspect.ts +0 -1107
- package/src/permissions.ts +0 -260
- package/src/schema.ts +0 -312
- package/src/user-config.ts +0 -177
- package/src/validation/platform-rules.ts +0 -686
package/src/cli/prompt.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Simple interactive prompt utilities using Bun's built-in readline.
|
|
3
|
-
* Zero external dependencies.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import * as readline from 'readline'
|
|
7
|
-
|
|
8
|
-
export class PromptCancelledError extends Error {
|
|
9
|
-
constructor() {
|
|
10
|
-
super('Init cancelled')
|
|
11
|
-
this.name = 'PromptCancelledError'
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function ask(question: string): Promise<string> {
|
|
16
|
-
return new Promise((resolve, reject) => {
|
|
17
|
-
const rl = readline.createInterface({
|
|
18
|
-
input: process.stdin,
|
|
19
|
-
output: process.stdout,
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
let settled = false
|
|
23
|
-
|
|
24
|
-
const settle = (fn: () => void) => {
|
|
25
|
-
if (settled) return
|
|
26
|
-
settled = true
|
|
27
|
-
rl.removeListener('SIGINT', onCancel)
|
|
28
|
-
rl.removeListener('close', onClose)
|
|
29
|
-
fn()
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const onCancel = () => {
|
|
33
|
-
settle(() => {
|
|
34
|
-
rl.close()
|
|
35
|
-
reject(new PromptCancelledError())
|
|
36
|
-
})
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const onClose = () => {
|
|
40
|
-
settle(() => {
|
|
41
|
-
reject(new PromptCancelledError())
|
|
42
|
-
})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
rl.once('SIGINT', onCancel)
|
|
46
|
-
rl.once('close', onClose)
|
|
47
|
-
|
|
48
|
-
rl.question(question, (answer) => {
|
|
49
|
-
settle(() => {
|
|
50
|
-
resolve(answer)
|
|
51
|
-
rl.close()
|
|
52
|
-
})
|
|
53
|
-
})
|
|
54
|
-
})
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Prompt for text input with an optional default value.
|
|
59
|
-
*/
|
|
60
|
-
export async function promptText(label: string, defaultValue?: string): Promise<string> {
|
|
61
|
-
const suffix = defaultValue ? ` (${defaultValue})` : ''
|
|
62
|
-
const answer = await ask(` ${label}${suffix}: `)
|
|
63
|
-
return answer.trim() || defaultValue || ''
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Prompt for a yes/no answer. Returns true for yes.
|
|
68
|
-
*/
|
|
69
|
-
export async function promptYesNo(label: string, defaultYes = false): Promise<boolean> {
|
|
70
|
-
const hint = defaultYes ? '(Y/n)' : '(y/N)'
|
|
71
|
-
const answer = await ask(` ${label} ${hint}: `)
|
|
72
|
-
const normalized = answer.trim().toLowerCase()
|
|
73
|
-
if (normalized === '') return defaultYes
|
|
74
|
-
return normalized === 'y' || normalized === 'yes'
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Close the readline interface. Must be called when done prompting.
|
|
79
|
-
*/
|
|
80
|
-
export function closePrompts(): void {
|
|
81
|
-
// Prompts are created per-question, so there is nothing to close here.
|
|
82
|
-
}
|
package/src/cli/publish.ts
DELETED
|
@@ -1,401 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, rmSync } from 'fs'
|
|
2
|
-
import { mkdtempSync } from 'fs'
|
|
3
|
-
import { resolve } from 'path'
|
|
4
|
-
import { spawnSync } from 'child_process'
|
|
5
|
-
import { tmpdir } from 'os'
|
|
6
|
-
import type { PluginConfig, TargetPlatform } from '../schema'
|
|
7
|
-
|
|
8
|
-
type PublishChannel = 'npm' | 'github-release'
|
|
9
|
-
|
|
10
|
-
interface CommandResult {
|
|
11
|
-
status: number | null
|
|
12
|
-
stdout: string
|
|
13
|
-
stderr: string
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
type CommandRunner = (
|
|
17
|
-
command: string,
|
|
18
|
-
args: string[],
|
|
19
|
-
options?: { cwd?: string },
|
|
20
|
-
) => CommandResult
|
|
21
|
-
|
|
22
|
-
export interface PublishPlanOptions {
|
|
23
|
-
requestedChannels?: PublishChannel[]
|
|
24
|
-
version?: string
|
|
25
|
-
tag?: string
|
|
26
|
-
dryRun?: boolean
|
|
27
|
-
rootDir?: string
|
|
28
|
-
runCommand?: CommandRunner
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface PublishAssetPlan {
|
|
32
|
-
platform: TargetPlatform
|
|
33
|
-
name: string
|
|
34
|
-
path: string
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface PublishCheck {
|
|
38
|
-
name: string
|
|
39
|
-
ok: boolean
|
|
40
|
-
code: string
|
|
41
|
-
detail?: string
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface PublishPlan {
|
|
45
|
-
command: 'publish'
|
|
46
|
-
dryRun: boolean
|
|
47
|
-
version: string
|
|
48
|
-
tag: string
|
|
49
|
-
channels: {
|
|
50
|
-
npm: {
|
|
51
|
-
enabled: boolean
|
|
52
|
-
explicit: boolean
|
|
53
|
-
packageName?: string
|
|
54
|
-
packageDir?: string
|
|
55
|
-
wouldPublish: boolean
|
|
56
|
-
}
|
|
57
|
-
githubRelease: {
|
|
58
|
-
enabled: boolean
|
|
59
|
-
explicit: boolean
|
|
60
|
-
releaseTag?: string
|
|
61
|
-
wouldCreateRelease: boolean
|
|
62
|
-
assets: PublishAssetPlan[]
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
checks: PublishCheck[]
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export interface PublishRunResult extends PublishPlan {
|
|
69
|
-
ok: boolean
|
|
70
|
-
execution?: {
|
|
71
|
-
npm?: { ok: boolean; detail?: string }
|
|
72
|
-
githubRelease?: { ok: boolean; detail?: string }
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function runCommandDefault(command: string, args: string[], options?: { cwd?: string }): CommandResult {
|
|
77
|
-
const result = spawnSync(command, args, {
|
|
78
|
-
cwd: options?.cwd,
|
|
79
|
-
encoding: 'utf-8',
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
status: result.status,
|
|
84
|
-
stdout: result.stdout ?? '',
|
|
85
|
-
stderr: result.stderr ?? '',
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function isTargetNpmBacked(platform: TargetPlatform): boolean {
|
|
90
|
-
return platform === 'opencode'
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function resolveRequestedChannels(options: PublishPlanOptions): {
|
|
94
|
-
requested: Set<PublishChannel>
|
|
95
|
-
explicit: { npm: boolean; githubRelease: boolean }
|
|
96
|
-
} {
|
|
97
|
-
const requested = new Set<PublishChannel>(options.requestedChannels ?? [])
|
|
98
|
-
return {
|
|
99
|
-
requested,
|
|
100
|
-
explicit: {
|
|
101
|
-
npm: requested.has('npm'),
|
|
102
|
-
githubRelease: requested.has('github-release'),
|
|
103
|
-
},
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function getBuiltTargets(rootDir: string, config: PluginConfig): TargetPlatform[] {
|
|
108
|
-
return config.targets.filter((platform) =>
|
|
109
|
-
existsSync(resolve(rootDir, config.outDir, platform)),
|
|
110
|
-
)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function buildReleaseAssets(rootDir: string, config: PluginConfig, version: string, targets: TargetPlatform[]): PublishAssetPlan[] {
|
|
114
|
-
return targets.map((platform) => ({
|
|
115
|
-
platform,
|
|
116
|
-
name: `${platform}-v${version}.tgz`,
|
|
117
|
-
path: resolve(rootDir, config.outDir, platform),
|
|
118
|
-
}))
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function readNpmPackageName(rootDir: string, config: PluginConfig): { packageName?: string; packageDir?: string } {
|
|
122
|
-
const packageDir = resolve(rootDir, config.outDir, 'opencode')
|
|
123
|
-
const packageJsonPath = resolve(packageDir, 'package.json')
|
|
124
|
-
if (!existsSync(packageJsonPath)) {
|
|
125
|
-
return {}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
try {
|
|
129
|
-
const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as { name?: string }
|
|
130
|
-
return {
|
|
131
|
-
packageName: pkg.name,
|
|
132
|
-
packageDir,
|
|
133
|
-
}
|
|
134
|
-
} catch {
|
|
135
|
-
return {
|
|
136
|
-
packageDir,
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function collectChecks(args: {
|
|
142
|
-
rootDir: string
|
|
143
|
-
config: PluginConfig
|
|
144
|
-
npmEnabled: boolean
|
|
145
|
-
githubReleaseEnabled: boolean
|
|
146
|
-
packageDir?: string
|
|
147
|
-
packageName?: string
|
|
148
|
-
runCommand: CommandRunner
|
|
149
|
-
}): PublishCheck[] {
|
|
150
|
-
const builtTargets = getBuiltTargets(args.rootDir, args.config)
|
|
151
|
-
const checks: PublishCheck[] = [
|
|
152
|
-
{
|
|
153
|
-
name: 'artifacts-exist',
|
|
154
|
-
ok: builtTargets.length > 0,
|
|
155
|
-
code: 'artifacts-exist',
|
|
156
|
-
detail: builtTargets.length > 0
|
|
157
|
-
? `Built targets: ${builtTargets.join(', ')}`
|
|
158
|
-
: `No built platform outputs found in ${args.config.outDir}/`,
|
|
159
|
-
},
|
|
160
|
-
]
|
|
161
|
-
|
|
162
|
-
const gitStatus = args.runCommand('git', ['status', '--porcelain'], { cwd: args.rootDir })
|
|
163
|
-
checks.push({
|
|
164
|
-
name: 'git-clean',
|
|
165
|
-
ok: gitStatus.status === 0 && gitStatus.stdout.trim() === '',
|
|
166
|
-
code: 'git-clean',
|
|
167
|
-
detail: gitStatus.status !== 0
|
|
168
|
-
? (gitStatus.stderr || gitStatus.stdout || 'Unable to read git status')
|
|
169
|
-
: gitStatus.stdout.trim() === ''
|
|
170
|
-
? 'Working tree is clean.'
|
|
171
|
-
: 'Working tree has uncommitted changes.',
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
if (args.npmEnabled) {
|
|
175
|
-
checks.push({
|
|
176
|
-
name: 'npm-package-ready',
|
|
177
|
-
ok: Boolean(args.packageDir && existsSync(resolve(args.packageDir, 'package.json')) && args.packageName),
|
|
178
|
-
code: 'npm-package-ready',
|
|
179
|
-
detail: args.packageDir
|
|
180
|
-
? `OpenCode package dir: ${args.packageDir}`
|
|
181
|
-
: 'No npm-backed target package found.',
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
const npmAuth = args.runCommand('npm', ['whoami'], { cwd: args.rootDir })
|
|
185
|
-
checks.push({
|
|
186
|
-
name: 'npm-auth',
|
|
187
|
-
ok: npmAuth.status === 0,
|
|
188
|
-
code: 'npm-auth',
|
|
189
|
-
detail: npmAuth.status === 0
|
|
190
|
-
? (npmAuth.stdout.trim() || 'npm auth OK')
|
|
191
|
-
: (npmAuth.stderr || npmAuth.stdout || 'npm auth unavailable'),
|
|
192
|
-
})
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (args.githubReleaseEnabled) {
|
|
196
|
-
const ghAuth = args.runCommand('gh', ['auth', 'status'], { cwd: args.rootDir })
|
|
197
|
-
checks.push({
|
|
198
|
-
name: 'github-release-auth',
|
|
199
|
-
ok: ghAuth.status === 0,
|
|
200
|
-
code: 'github-release-auth',
|
|
201
|
-
detail: ghAuth.status === 0
|
|
202
|
-
? 'gh auth OK'
|
|
203
|
-
: (ghAuth.stderr || ghAuth.stdout || 'gh auth unavailable'),
|
|
204
|
-
})
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
return checks
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
export function planPublish(config: PluginConfig, options: PublishPlanOptions = {}): PublishPlan {
|
|
211
|
-
const rootDir = options.rootDir ?? process.cwd()
|
|
212
|
-
const runCommand = options.runCommand ?? runCommandDefault
|
|
213
|
-
const builtTargets = getBuiltTargets(rootDir, config)
|
|
214
|
-
const { requested, explicit } = resolveRequestedChannels(options)
|
|
215
|
-
const defaultNpm = builtTargets.some(isTargetNpmBacked)
|
|
216
|
-
const defaultGithubRelease = builtTargets.length > 0
|
|
217
|
-
const npmEnabled = explicit.npm ? true : (requested.size === 0 ? defaultNpm : false)
|
|
218
|
-
const githubReleaseEnabled = explicit.githubRelease ? true : (requested.size === 0 ? defaultGithubRelease : false)
|
|
219
|
-
const version = options.version ?? config.version
|
|
220
|
-
const tag = options.tag ?? 'latest'
|
|
221
|
-
const { packageDir, packageName } = readNpmPackageName(rootDir, config)
|
|
222
|
-
const checks = collectChecks({
|
|
223
|
-
rootDir,
|
|
224
|
-
config,
|
|
225
|
-
npmEnabled,
|
|
226
|
-
githubReleaseEnabled,
|
|
227
|
-
packageDir,
|
|
228
|
-
packageName,
|
|
229
|
-
runCommand,
|
|
230
|
-
})
|
|
231
|
-
|
|
232
|
-
return {
|
|
233
|
-
command: 'publish',
|
|
234
|
-
dryRun: options.dryRun ?? false,
|
|
235
|
-
version,
|
|
236
|
-
tag,
|
|
237
|
-
channels: {
|
|
238
|
-
npm: {
|
|
239
|
-
enabled: npmEnabled,
|
|
240
|
-
explicit: explicit.npm,
|
|
241
|
-
packageName,
|
|
242
|
-
packageDir,
|
|
243
|
-
wouldPublish: npmEnabled,
|
|
244
|
-
},
|
|
245
|
-
githubRelease: {
|
|
246
|
-
enabled: githubReleaseEnabled,
|
|
247
|
-
explicit: explicit.githubRelease,
|
|
248
|
-
releaseTag: githubReleaseEnabled ? `v${version}` : undefined,
|
|
249
|
-
wouldCreateRelease: githubReleaseEnabled,
|
|
250
|
-
assets: githubReleaseEnabled ? buildReleaseAssets(rootDir, config, version, builtTargets) : [],
|
|
251
|
-
},
|
|
252
|
-
},
|
|
253
|
-
checks,
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
function createReleaseArchives(
|
|
258
|
-
rootDir: string,
|
|
259
|
-
config: PluginConfig,
|
|
260
|
-
assets: PublishAssetPlan[],
|
|
261
|
-
runCommand: CommandRunner,
|
|
262
|
-
): { tempRoot: string; archives: string[] } {
|
|
263
|
-
const tempRoot = mkdtempSync(resolve(tmpdir(), 'pluxx-publish-'))
|
|
264
|
-
const created: string[] = []
|
|
265
|
-
|
|
266
|
-
try {
|
|
267
|
-
for (const asset of assets) {
|
|
268
|
-
const archivePath = resolve(tempRoot, asset.name)
|
|
269
|
-
const result = runCommand(
|
|
270
|
-
'tar',
|
|
271
|
-
['-czf', archivePath, '-C', resolve(rootDir, config.outDir), asset.platform],
|
|
272
|
-
{ cwd: rootDir },
|
|
273
|
-
)
|
|
274
|
-
if (result.status !== 0) {
|
|
275
|
-
throw new Error(result.stderr || result.stdout || `Failed to create archive for ${asset.platform}`)
|
|
276
|
-
}
|
|
277
|
-
created.push(archivePath)
|
|
278
|
-
}
|
|
279
|
-
return { tempRoot, archives: created }
|
|
280
|
-
} catch (error) {
|
|
281
|
-
rmSync(tempRoot, { recursive: true, force: true })
|
|
282
|
-
throw error
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
export function formatPublishPlan(plan: PublishPlan): string[] {
|
|
287
|
-
const lines: string[] = [
|
|
288
|
-
`Resolved version: ${plan.version}`,
|
|
289
|
-
`Resolved tag: ${plan.tag}`,
|
|
290
|
-
`Channels: ${[
|
|
291
|
-
plan.channels.npm.enabled ? `npm${plan.channels.npm.explicit ? ' (explicit)' : ' (auto)'}` : null,
|
|
292
|
-
plan.channels.githubRelease.enabled ? `github-release${plan.channels.githubRelease.explicit ? ' (explicit)' : ' (auto)'}` : null,
|
|
293
|
-
].filter(Boolean).join(', ') || 'none'}`,
|
|
294
|
-
'',
|
|
295
|
-
'Checks:',
|
|
296
|
-
]
|
|
297
|
-
|
|
298
|
-
for (const check of plan.checks) {
|
|
299
|
-
lines.push(` - ${check.name}: ${check.ok ? 'ok' : 'fail'}${check.detail ? ` — ${check.detail}` : ''}`)
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
lines.push('')
|
|
303
|
-
if (plan.channels.npm.enabled) {
|
|
304
|
-
lines.push(`npm package: ${plan.channels.npm.packageName ?? 'unknown'} (${plan.channels.npm.packageDir ?? 'missing'})`)
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
if (plan.channels.githubRelease.enabled) {
|
|
308
|
-
lines.push(`GitHub release tag: ${plan.channels.githubRelease.releaseTag}`)
|
|
309
|
-
lines.push('Assets:')
|
|
310
|
-
for (const asset of plan.channels.githubRelease.assets) {
|
|
311
|
-
lines.push(` - ${asset.name} <- ${asset.path}`)
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
if (plan.dryRun) {
|
|
316
|
-
lines.push('')
|
|
317
|
-
lines.push('No remote changes were made.')
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
return lines
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
export function runPublish(config: PluginConfig, options: PublishPlanOptions = {}): PublishRunResult {
|
|
324
|
-
const rootDir = options.rootDir ?? process.cwd()
|
|
325
|
-
const runCommand = options.runCommand ?? runCommandDefault
|
|
326
|
-
const plan = planPublish(config, options)
|
|
327
|
-
|
|
328
|
-
const failedChecks = plan.checks.filter((check) => !check.ok)
|
|
329
|
-
if (failedChecks.length > 0) {
|
|
330
|
-
return {
|
|
331
|
-
...plan,
|
|
332
|
-
ok: false,
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
if (options.dryRun) {
|
|
337
|
-
return {
|
|
338
|
-
...plan,
|
|
339
|
-
ok: true,
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
const execution: NonNullable<PublishRunResult['execution']> = {}
|
|
344
|
-
|
|
345
|
-
if (plan.channels.npm.enabled) {
|
|
346
|
-
const npmChannel = plan.channels.npm
|
|
347
|
-
const result = runCommand(
|
|
348
|
-
'npm',
|
|
349
|
-
['publish', '--tag', plan.tag, '--access', 'public'],
|
|
350
|
-
{ cwd: npmChannel.packageDir },
|
|
351
|
-
)
|
|
352
|
-
execution.npm = {
|
|
353
|
-
ok: result.status === 0,
|
|
354
|
-
detail: result.status === 0
|
|
355
|
-
? (result.stdout.trim() || 'npm publish complete')
|
|
356
|
-
: (result.stderr || result.stdout || 'npm publish failed'),
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
if (plan.channels.githubRelease.enabled) {
|
|
361
|
-
const releaseTag = plan.channels.githubRelease.releaseTag!
|
|
362
|
-
const { tempRoot, archives } = createReleaseArchives(rootDir, config, plan.channels.githubRelease.assets, runCommand)
|
|
363
|
-
|
|
364
|
-
try {
|
|
365
|
-
const existing = runCommand('gh', ['release', 'view', releaseTag], { cwd: rootDir })
|
|
366
|
-
|
|
367
|
-
const result = existing.status === 0
|
|
368
|
-
? runCommand('gh', ['release', 'upload', releaseTag, '--clobber', ...archives], { cwd: rootDir })
|
|
369
|
-
: runCommand(
|
|
370
|
-
'gh',
|
|
371
|
-
[
|
|
372
|
-
'release',
|
|
373
|
-
'create',
|
|
374
|
-
releaseTag,
|
|
375
|
-
...archives,
|
|
376
|
-
'--title',
|
|
377
|
-
`${config.name} ${plan.version}`,
|
|
378
|
-
'--notes',
|
|
379
|
-
`Release generated by pluxx publish for ${config.name}@${plan.version}.`,
|
|
380
|
-
],
|
|
381
|
-
{ cwd: rootDir },
|
|
382
|
-
)
|
|
383
|
-
|
|
384
|
-
execution.githubRelease = {
|
|
385
|
-
ok: result.status === 0,
|
|
386
|
-
detail: result.status === 0
|
|
387
|
-
? (result.stdout.trim() || `GitHub release ${releaseTag} updated`)
|
|
388
|
-
: (result.stderr || result.stdout || 'GitHub release publish failed'),
|
|
389
|
-
}
|
|
390
|
-
} finally {
|
|
391
|
-
rmSync(tempRoot, { recursive: true, force: true })
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
const ok = Object.values(execution).every((channel) => channel.ok)
|
|
396
|
-
return {
|
|
397
|
-
...plan,
|
|
398
|
-
ok,
|
|
399
|
-
execution,
|
|
400
|
-
}
|
|
401
|
-
}
|
package/src/cli/runtime.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import * as clack from '@clack/prompts'
|
|
2
|
-
|
|
3
|
-
export interface CliRuntime {
|
|
4
|
-
dryRun: boolean
|
|
5
|
-
jsonOutput: boolean
|
|
6
|
-
quiet: boolean
|
|
7
|
-
isCI: boolean
|
|
8
|
-
isTTY: boolean
|
|
9
|
-
isInteractive: boolean
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function createCliRuntime(rawArgs: string[]): CliRuntime {
|
|
13
|
-
const isCI = process.env.CI === '1' || process.env.CI === 'true'
|
|
14
|
-
const isTTY = process.stdin.isTTY === true && process.stdout.isTTY === true
|
|
15
|
-
|
|
16
|
-
return {
|
|
17
|
-
dryRun: rawArgs.includes('--dry-run'),
|
|
18
|
-
jsonOutput: rawArgs.includes('--json'),
|
|
19
|
-
quiet: rawArgs.includes('--quiet'),
|
|
20
|
-
isCI,
|
|
21
|
-
isTTY,
|
|
22
|
-
isInteractive: isTTY && !isCI,
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function readFlag(rawArgs: string[], flag: string): boolean {
|
|
27
|
-
return rawArgs.includes(flag)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function readOption(rawArgs: string[], flag: string): string | undefined {
|
|
31
|
-
const index = rawArgs.indexOf(flag)
|
|
32
|
-
if (index === -1) return undefined
|
|
33
|
-
|
|
34
|
-
const value = rawArgs[index + 1]
|
|
35
|
-
if (!value || value.startsWith('-')) {
|
|
36
|
-
return undefined
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return value
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function readMultiValueOption(rawArgs: string[], flag: string): string[] | undefined {
|
|
43
|
-
const index = rawArgs.indexOf(flag)
|
|
44
|
-
if (index === -1) return undefined
|
|
45
|
-
|
|
46
|
-
const values: string[] = []
|
|
47
|
-
for (let i = index + 1; i < rawArgs.length; i += 1) {
|
|
48
|
-
const value = rawArgs[i]
|
|
49
|
-
if (value.startsWith('-')) break
|
|
50
|
-
values.push(value)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return values.length > 0 ? values : undefined
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function createSpinner(runtime: CliRuntime): ReturnType<typeof clack.spinner> | undefined {
|
|
57
|
-
if (runtime.jsonOutput || runtime.quiet || !runtime.isInteractive) {
|
|
58
|
-
return undefined
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return clack.spinner()
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function printJson(value: unknown): void {
|
|
65
|
-
console.log(JSON.stringify(value, null, 2))
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function logInfo(runtime: CliRuntime, message: string): void {
|
|
69
|
-
if (!runtime.jsonOutput && !runtime.quiet) {
|
|
70
|
-
console.log(message)
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function logWarn(runtime: CliRuntime, message: string): void {
|
|
75
|
-
if (!runtime.jsonOutput && !runtime.quiet) {
|
|
76
|
-
console.warn(message)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function logError(message: string): void {
|
|
81
|
-
console.error(message)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function formatPathList(paths: string[]): string {
|
|
85
|
-
return paths.length > 0 ? paths.join(', ') : 'none'
|
|
86
|
-
}
|