@regressionproof/cli 0.1.0 → 0.1.2

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/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.1.2](https://github.com/sprucelabsai-community/regressionproof/compare/v0.1.1...v0.1.2) (2026-01-12)
7
+
8
+ **Note:** Version bump only for package @regressionproof/cli
9
+
10
+
11
+
12
+
13
+
14
+ ## [0.1.1](https://github.com/sprucelabsai-community/regressionproof/compare/v0.1.0...v0.1.1) (2026-01-12)
15
+
16
+ **Note:** Version bump only for package @regressionproof/cli
17
+
18
+
19
+
20
+
21
+
6
22
  # 0.1.0 (2026-01-12)
7
23
 
8
24
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@regressionproof/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -33,7 +33,7 @@
33
33
  "watch.tsc": "tsc -w"
34
34
  },
35
35
  "dependencies": {
36
- "@regressionproof/client": "^0.1.0",
36
+ "@regressionproof/client": "^0.1.2",
37
37
  "dotenv": "^17.2.3",
38
38
  "ink": "^5.1.0",
39
39
  "ink-big-text": "^2.0.0",
@@ -56,5 +56,5 @@
56
56
  "skill": {
57
57
  "namespace": "regressionproof-cli"
58
58
  },
59
- "gitHead": "664a65b45bf5e4608ed8f1f376eb8dc04341c2b2"
59
+ "gitHead": "0dc77840a646cb322901f05aa87eb3d2efa3e8d9"
60
60
  }
@@ -4,6 +4,8 @@ import { Box, Text, useApp } from 'ink'
4
4
  import BigText from 'ink-big-text'
5
5
  import TextInput from 'ink-text-input'
6
6
  import React from 'react'
7
+ import { spawnSync } from 'node:child_process'
8
+ import { existsSync, readFileSync } from 'node:fs'
7
9
  import ConfigManager, { Credentials } from '../config/ConfigManager.js'
8
10
  import JestConfigurator, { JestConfigResult } from '../jest/JestConfigurator.js'
9
11
  import { getRepoNameFromGit, toSlug } from '../utilities/slug.js'
@@ -30,7 +32,7 @@ class InitComponent extends React.Component<Props, State> {
30
32
  if (existingCreds) {
31
33
  this.state = {
32
34
  name: defaultName,
33
- step: 'success',
35
+ step: 'installing',
34
36
  availability: 'available',
35
37
  errorMessage: '',
36
38
  credentials: existingCreds,
@@ -52,12 +54,8 @@ class InitComponent extends React.Component<Props, State> {
52
54
  // If we have a provided name and not already registered, start registration
53
55
  if (this.props.projectName && this.state.step === 'registering') {
54
56
  void this.register()
55
- } else if (this.state.step === 'success') {
56
- // Already registered, configure Jest and exit
57
- const jestConfigurator = new JestConfigurator()
58
- const jestConfig = jestConfigurator.configure()
59
- this.setState({ jestConfig })
60
- setTimeout(() => this.props.exit(), 1000)
57
+ } else if (this.state.step === 'installing') {
58
+ void this.installAndConfigure()
61
59
  } else {
62
60
  void this.checkAvailability()
63
61
  }
@@ -137,14 +135,7 @@ class InitComponent extends React.Component<Props, State> {
137
135
  this.setState({ credentials })
138
136
 
139
137
  this.configManager.saveCredentials(name, credentials)
140
-
141
- this.setState({ step: 'configuring' })
142
-
143
- const jestConfigurator = new JestConfigurator()
144
- const jestConfig = jestConfigurator.configure()
145
- this.setState({ jestConfig, step: 'success' })
146
-
147
- setTimeout(() => this.props.exit(), 3000)
138
+ await this.installAndConfigure()
148
139
  } catch (err) {
149
140
  this.setState({
150
141
  step: 'error',
@@ -153,6 +144,108 @@ class InitComponent extends React.Component<Props, State> {
153
144
  }
154
145
  }
155
146
 
147
+ private async installAndConfigure(): Promise<void> {
148
+ this.setState({ step: 'installing' })
149
+ const installResult = this.installDependencies()
150
+ if (!installResult.success) {
151
+ this.setState({
152
+ step: 'error',
153
+ errorMessage:
154
+ installResult.message ??
155
+ 'Failed to install dependencies.',
156
+ })
157
+ return
158
+ }
159
+
160
+ this.setState({ step: 'configuring' })
161
+ const jestConfigurator = new JestConfigurator()
162
+ const jestConfig = jestConfigurator.configure()
163
+ this.setState({ jestConfig, step: 'success' })
164
+
165
+ setTimeout(() => this.props.exit(), 3000)
166
+ }
167
+
168
+ private installDependencies(): InstallResult {
169
+ if (!existsSync('package.json')) {
170
+ return {
171
+ success: false,
172
+ message:
173
+ 'No package.json found. regressionproof currently supports Node.js + Jest projects.',
174
+ }
175
+ }
176
+
177
+ let packageJson: {
178
+ dependencies?: Record<string, string>
179
+ devDependencies?: Record<string, string>
180
+ }
181
+
182
+ try {
183
+ packageJson = JSON.parse(
184
+ readFileSync('package.json', 'utf8')
185
+ ) as {
186
+ dependencies?: Record<string, string>
187
+ devDependencies?: Record<string, string>
188
+ }
189
+ } catch (err) {
190
+ const message = err instanceof Error ? err.message : String(err)
191
+ return {
192
+ success: false,
193
+ message: `Failed to read package.json: ${message}`,
194
+ }
195
+ }
196
+
197
+ const hasReporter = Boolean(
198
+ packageJson.dependencies?.['@regressionproof/jest-reporter'] ??
199
+ packageJson.devDependencies?.[
200
+ '@regressionproof/jest-reporter'
201
+ ]
202
+ )
203
+ if (hasReporter) {
204
+ return { success: true }
205
+ }
206
+
207
+ const packageManager = this.getPackageManager()
208
+ const result = spawnSync(
209
+ packageManager.command,
210
+ [...packageManager.args, '@regressionproof/jest-reporter'],
211
+ {
212
+ encoding: 'utf8',
213
+ shell: true,
214
+ }
215
+ )
216
+
217
+ if (result.error || result.status !== 0) {
218
+ const details =
219
+ result.stderr?.trim() ||
220
+ result.stdout?.trim() ||
221
+ result.error?.message
222
+ return {
223
+ success: false,
224
+ message: `Failed to install dependencies${
225
+ details ? `: ${details}` : ''
226
+ }`,
227
+ }
228
+ }
229
+
230
+ return { success: true }
231
+ }
232
+
233
+ private getPackageManager(): PackageManager {
234
+ if (existsSync('pnpm-lock.yaml')) {
235
+ return { command: 'pnpm', args: ['add', '-D'] }
236
+ }
237
+
238
+ if (existsSync('yarn.lock')) {
239
+ return { command: 'yarn', args: ['add', '-D'] }
240
+ }
241
+
242
+ if (existsSync('package-lock.json')) {
243
+ return { command: 'npm', args: ['install', '-D'] }
244
+ }
245
+
246
+ return { command: 'npm', args: ['install', '-D'] }
247
+ }
248
+
156
249
  private renderStatusIndicator(): React.ReactNode {
157
250
  const { availability, errorMessage } = this.state
158
251
 
@@ -188,6 +281,14 @@ class InitComponent extends React.Component<Props, State> {
188
281
  )
189
282
  }
190
283
 
284
+ private renderInstalling(): React.ReactElement {
285
+ return (
286
+ <Box flexDirection="column" padding={1}>
287
+ <Text color="yellow">Installing dependencies...</Text>
288
+ </Box>
289
+ )
290
+ }
291
+
191
292
  private renderSuccess(): React.ReactElement {
192
293
  const { name, credentials, jestConfig } = this.state
193
294
  const configDir = this.configManager.getConfigDir(name)
@@ -285,6 +386,8 @@ class InitComponent extends React.Component<Props, State> {
285
386
  switch (step) {
286
387
  case 'registering':
287
388
  return this.renderRegistering()
389
+ case 'installing':
390
+ return this.renderInstalling()
288
391
  case 'configuring':
289
392
  return this.renderConfiguring()
290
393
  case 'success':
@@ -302,7 +405,13 @@ export default function Init(props: { projectName?: string }): React.ReactElemen
302
405
  return <InitComponent exit={exit} projectName={props.projectName} />
303
406
  }
304
407
 
305
- type Step = 'input' | 'registering' | 'configuring' | 'success' | 'error'
408
+ type Step =
409
+ | 'input'
410
+ | 'registering'
411
+ | 'installing'
412
+ | 'configuring'
413
+ | 'success'
414
+ | 'error'
306
415
  type Availability = 'idle' | 'checking' | 'available' | 'taken' | 'error'
307
416
 
308
417
  interface Props {
@@ -318,3 +427,13 @@ interface State {
318
427
  credentials: Credentials | null
319
428
  jestConfig: JestConfigResult | null
320
429
  }
430
+
431
+ interface PackageManager {
432
+ command: string
433
+ args: string[]
434
+ }
435
+
436
+ interface InstallResult {
437
+ success: boolean
438
+ message?: string
439
+ }