@regressionproof/cli 0.0.1 → 0.1.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.
- package/CHANGELOG.md +38 -0
- package/package.json +4 -3
- package/build/.spruce/settings.json +0 -10
- package/build/cli.d.ts +0 -2
- package/build/cli.js +0 -18
- package/build/cli.js.map +0 -1
- package/build/components/Init.d.ts +0 -4
- package/build/components/Init.js +0 -221
- package/build/components/Init.js.map +0 -1
- package/build/components/Init.tsx +0 -320
- package/build/config/ConfigManager.d.ts +0 -17
- package/build/config/ConfigManager.js +0 -36
- package/build/config/ConfigManager.js.map +0 -1
- package/build/index.d.ts +0 -1
- package/build/index.js +0 -3
- package/build/index.js.map +0 -1
- package/build/jest/JestConfigurator.d.ts +0 -12
- package/build/jest/JestConfigurator.js +0 -60
- package/build/jest/JestConfigurator.js.map +0 -1
- package/build/utilities/slug.d.ts +0 -2
- package/build/utilities/slug.js +0 -22
- package/build/utilities/slug.js.map +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
## [0.1.1](https://github.com/sprucelabsai-community/regressionproof/compare/v0.1.0...v0.1.1) (2026-01-12)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @regressionproof/cli
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# 0.1.0 (2026-01-12)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* configure package publishing ([fe9f0ca](https://github.com/sprucelabsai-community/regressionproof/commit/fe9f0ca))
|
|
20
|
+
* ESM/CJS interop for CLI importing client ([d66b208](https://github.com/sprucelabsai-community/regressionproof/commit/d66b208))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Documentation
|
|
24
|
+
|
|
25
|
+
* simplify README, add ARCHITECTURE.md ([8246e6e](https://github.com/sprucelabsai-community/regressionproof/commit/8246e6e))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Features
|
|
29
|
+
|
|
30
|
+
* add CircleCI config and e2e scripts ([049caa1](https://github.com/sprucelabsai-community/regressionproof/commit/049caa1))
|
|
31
|
+
* add parallel watch and fancy CLI banner ([e55a396](https://github.com/sprucelabsai-community/regressionproof/commit/e55a396))
|
|
32
|
+
* ESM support and CLI init component ([d60a534](https://github.com/sprucelabsai-community/regressionproof/commit/d60a534))
|
|
33
|
+
* lerna, CJS builds, slug validation, jest-reporter scaffold ([2516cac](https://github.com/sprucelabsai-community/regressionproof/commit/2516cac))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Refactoring
|
|
37
|
+
|
|
38
|
+
* extract CLI business logic into dedicated modules ([dadd01c](https://github.com/sprucelabsai-community/regressionproof/commit/dadd01c))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@regressionproof/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
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.
|
|
36
|
+
"@regressionproof/client": "^0.1.1",
|
|
37
37
|
"dotenv": "^17.2.3",
|
|
38
38
|
"ink": "^5.1.0",
|
|
39
39
|
"ink-big-text": "^2.0.0",
|
|
@@ -55,5 +55,6 @@
|
|
|
55
55
|
"description": "The cli to setup regression proof training locally",
|
|
56
56
|
"skill": {
|
|
57
57
|
"namespace": "regressionproof-cli"
|
|
58
|
-
}
|
|
58
|
+
},
|
|
59
|
+
"gitHead": "3d13b4ce3234f7a108cf5588836499f75196463f"
|
|
59
60
|
}
|
package/build/cli.d.ts
DELETED
package/build/cli.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import 'dotenv/config';
|
|
3
|
-
import { render } from 'ink';
|
|
4
|
-
import React from 'react';
|
|
5
|
-
import Init from './components/Init.js';
|
|
6
|
-
const command = process.argv[2];
|
|
7
|
-
const projectNameArg = process.argv[3];
|
|
8
|
-
if (command === 'init') {
|
|
9
|
-
render(React.createElement(Init, { projectName: projectNameArg }));
|
|
10
|
-
}
|
|
11
|
-
else {
|
|
12
|
-
console.log('Usage: regressionproof <command>');
|
|
13
|
-
console.log('');
|
|
14
|
-
console.log('Commands:');
|
|
15
|
-
console.log(' init [projectName] Initialize a new project');
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=cli.js.map
|
package/build/cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAA;AACtB,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,IAAI,MAAM,sBAAsB,CAAA;AAEvC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAC/B,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAEtC,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,CAAC,CAAA;AACtE,CAAC;KAAM,CAAC;IACJ,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAA;IAC/C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACxB,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAA;IAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACnB,CAAC"}
|
package/build/components/Init.js
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
import client from '@regressionproof/client';
|
|
2
|
-
const RegressionProofClient = client.default ?? client;
|
|
3
|
-
import { Box, Text, useApp } from 'ink';
|
|
4
|
-
import BigText from 'ink-big-text';
|
|
5
|
-
import TextInput from 'ink-text-input';
|
|
6
|
-
import React from 'react';
|
|
7
|
-
import ConfigManager from '../config/ConfigManager.js';
|
|
8
|
-
import JestConfigurator from '../jest/JestConfigurator.js';
|
|
9
|
-
import { getRepoNameFromGit, toSlug } from '../utilities/slug.js';
|
|
10
|
-
const API_URL = process.env.REGRESSIONPROOF_API_URL ?? 'https://api.regressionproof.ai';
|
|
11
|
-
class InitComponent extends React.Component {
|
|
12
|
-
checkTimeout = null;
|
|
13
|
-
apiClient;
|
|
14
|
-
configManager;
|
|
15
|
-
constructor(props) {
|
|
16
|
-
super(props);
|
|
17
|
-
const providedName = props.projectName;
|
|
18
|
-
const defaultName = providedName ?? getRepoNameFromGit();
|
|
19
|
-
this.configManager = new ConfigManager();
|
|
20
|
-
this.apiClient = new RegressionProofClient(API_URL);
|
|
21
|
-
// Check if already registered (idempotent)
|
|
22
|
-
const existingCreds = this.configManager.loadCredentials(defaultName);
|
|
23
|
-
if (existingCreds) {
|
|
24
|
-
this.state = {
|
|
25
|
-
name: defaultName,
|
|
26
|
-
step: 'success',
|
|
27
|
-
availability: 'available',
|
|
28
|
-
errorMessage: '',
|
|
29
|
-
credentials: existingCreds,
|
|
30
|
-
jestConfig: null,
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
this.state = {
|
|
35
|
-
name: defaultName,
|
|
36
|
-
step: providedName ? 'registering' : 'input',
|
|
37
|
-
availability: 'idle',
|
|
38
|
-
errorMessage: '',
|
|
39
|
-
credentials: null,
|
|
40
|
-
jestConfig: null,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
componentDidMount() {
|
|
45
|
-
// If we have a provided name and not already registered, start registration
|
|
46
|
-
if (this.props.projectName && this.state.step === 'registering') {
|
|
47
|
-
void this.register();
|
|
48
|
-
}
|
|
49
|
-
else if (this.state.step === 'success') {
|
|
50
|
-
// Already registered, configure Jest and exit
|
|
51
|
-
const jestConfigurator = new JestConfigurator();
|
|
52
|
-
const jestConfig = jestConfigurator.configure();
|
|
53
|
-
this.setState({ jestConfig });
|
|
54
|
-
setTimeout(() => this.props.exit(), 1000);
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
void this.checkAvailability();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
componentDidUpdate(_, prevState) {
|
|
61
|
-
if (prevState.name !== this.state.name && this.state.step === 'input') {
|
|
62
|
-
void this.checkAvailability();
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
componentWillUnmount() {
|
|
66
|
-
this.clearCheckTimeout();
|
|
67
|
-
}
|
|
68
|
-
clearCheckTimeout() {
|
|
69
|
-
if (this.checkTimeout) {
|
|
70
|
-
clearTimeout(this.checkTimeout);
|
|
71
|
-
this.checkTimeout = null;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
async checkAvailability() {
|
|
75
|
-
this.clearCheckTimeout();
|
|
76
|
-
const { name } = this.state;
|
|
77
|
-
if (name.length < 3) {
|
|
78
|
-
this.setState({ availability: 'idle', errorMessage: '' });
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
this.setState({ availability: 'checking' });
|
|
82
|
-
this.checkTimeout = setTimeout(async () => {
|
|
83
|
-
try {
|
|
84
|
-
const isAvailable = await this.apiClient.checkNameAvailability(name);
|
|
85
|
-
this.setState({
|
|
86
|
-
availability: isAvailable ? 'available' : 'taken',
|
|
87
|
-
errorMessage: '',
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
catch (err) {
|
|
91
|
-
this.setState({
|
|
92
|
-
availability: 'error',
|
|
93
|
-
errorMessage: this.formatError(err),
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}, 300);
|
|
97
|
-
}
|
|
98
|
-
formatError(err) {
|
|
99
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
100
|
-
const cause = err instanceof Error && 'cause' in err ? ` (${err.cause})` : '';
|
|
101
|
-
return `${message}${cause} - ${API_URL}`;
|
|
102
|
-
}
|
|
103
|
-
handleNameChange = (value) => {
|
|
104
|
-
this.setState({ name: toSlug(value) });
|
|
105
|
-
};
|
|
106
|
-
handleSubmit = async () => {
|
|
107
|
-
const { availability, name } = this.state;
|
|
108
|
-
if (availability !== 'available' || name.length < 3) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
this.setState({ step: 'registering' });
|
|
112
|
-
await this.register();
|
|
113
|
-
};
|
|
114
|
-
async register() {
|
|
115
|
-
const { name } = this.state;
|
|
116
|
-
try {
|
|
117
|
-
const credentials = await this.apiClient.registerProject({ name });
|
|
118
|
-
this.setState({ credentials });
|
|
119
|
-
this.configManager.saveCredentials(name, credentials);
|
|
120
|
-
this.setState({ step: 'configuring' });
|
|
121
|
-
const jestConfigurator = new JestConfigurator();
|
|
122
|
-
const jestConfig = jestConfigurator.configure();
|
|
123
|
-
this.setState({ jestConfig, step: 'success' });
|
|
124
|
-
setTimeout(() => this.props.exit(), 3000);
|
|
125
|
-
}
|
|
126
|
-
catch (err) {
|
|
127
|
-
this.setState({
|
|
128
|
-
step: 'error',
|
|
129
|
-
errorMessage: err instanceof Error ? err.message : String(err),
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
renderStatusIndicator() {
|
|
134
|
-
const { availability, errorMessage } = this.state;
|
|
135
|
-
switch (availability) {
|
|
136
|
-
case 'idle':
|
|
137
|
-
return null;
|
|
138
|
-
case 'checking':
|
|
139
|
-
return React.createElement(Text, { color: "yellow" }, "checking...");
|
|
140
|
-
case 'available':
|
|
141
|
-
return React.createElement(Text, { color: "green" }, "available (press Enter)");
|
|
142
|
-
case 'taken':
|
|
143
|
-
return React.createElement(Text, { color: "red" }, "already taken");
|
|
144
|
-
case 'error':
|
|
145
|
-
return React.createElement(Text, { color: "red" }, errorMessage);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
renderRegistering() {
|
|
149
|
-
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
150
|
-
React.createElement(Text, { color: "yellow" },
|
|
151
|
-
"Registering project \"",
|
|
152
|
-
this.state.name,
|
|
153
|
-
"\"...")));
|
|
154
|
-
}
|
|
155
|
-
renderConfiguring() {
|
|
156
|
-
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
157
|
-
React.createElement(Text, { color: "yellow" }, "Configuring Jest reporter...")));
|
|
158
|
-
}
|
|
159
|
-
renderSuccess() {
|
|
160
|
-
const { name, credentials, jestConfig } = this.state;
|
|
161
|
-
const configDir = this.configManager.getConfigDir(name);
|
|
162
|
-
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
163
|
-
React.createElement(Text, { color: "green", bold: true }, "Project registered successfully!"),
|
|
164
|
-
React.createElement(Box, { marginTop: 1, flexDirection: "column" },
|
|
165
|
-
React.createElement(Text, null,
|
|
166
|
-
"Config saved to:",
|
|
167
|
-
' ',
|
|
168
|
-
React.createElement(Text, { color: "cyan" },
|
|
169
|
-
configDir,
|
|
170
|
-
"/config.json")),
|
|
171
|
-
React.createElement(Text, null,
|
|
172
|
-
"Git remote: ",
|
|
173
|
-
React.createElement(Text, { color: "cyan" }, credentials?.url)),
|
|
174
|
-
jestConfig?.configured ? (React.createElement(Text, null,
|
|
175
|
-
"Jest reporter added to:",
|
|
176
|
-
' ',
|
|
177
|
-
React.createElement(Text, { color: "cyan" }, jestConfig.location))) : (React.createElement(Text, { color: "yellow" }, "Could not auto-configure Jest. Add manually:"))),
|
|
178
|
-
!jestConfig?.configured && (React.createElement(Box, { marginTop: 1, flexDirection: "column" },
|
|
179
|
-
React.createElement(Text, { color: "gray" }, "// jest.config.js"),
|
|
180
|
-
React.createElement(Text, { color: "gray" }, "reporters: ['default', '@regressionproof/jest-reporter']"))),
|
|
181
|
-
React.createElement(Box, { marginTop: 1 },
|
|
182
|
-
React.createElement(Text, { color: "green" }, "Run your tests and snapshots will be captured automatically!"))));
|
|
183
|
-
}
|
|
184
|
-
renderError() {
|
|
185
|
-
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
186
|
-
React.createElement(Text, { color: "red", bold: true }, "Registration failed"),
|
|
187
|
-
React.createElement(Text, { color: "red" }, this.state.errorMessage)));
|
|
188
|
-
}
|
|
189
|
-
renderInput() {
|
|
190
|
-
const { name } = this.state;
|
|
191
|
-
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
192
|
-
React.createElement(BigText, { text: "regressionproof.ai", font: "tiny", colors: ['magenta', 'cyan'] }),
|
|
193
|
-
React.createElement(Text, { color: "gray" }, "Teaching LLMs to write better code."),
|
|
194
|
-
React.createElement(Box, { marginTop: 1, flexDirection: "column" },
|
|
195
|
-
React.createElement(Text, { bold: true }, "Project name:"),
|
|
196
|
-
React.createElement(Box, null,
|
|
197
|
-
React.createElement(TextInput, { value: name, onChange: this.handleNameChange, onSubmit: this.handleSubmit, placeholder: "my-awesome-project" }),
|
|
198
|
-
React.createElement(Box, { marginLeft: 2 }, this.renderStatusIndicator())),
|
|
199
|
-
name.length > 0 && name.length < 3 && (React.createElement(Text, { color: "gray" }, "Name must be at least 3 characters")))));
|
|
200
|
-
}
|
|
201
|
-
render() {
|
|
202
|
-
const { step } = this.state;
|
|
203
|
-
switch (step) {
|
|
204
|
-
case 'registering':
|
|
205
|
-
return this.renderRegistering();
|
|
206
|
-
case 'configuring':
|
|
207
|
-
return this.renderConfiguring();
|
|
208
|
-
case 'success':
|
|
209
|
-
return this.renderSuccess();
|
|
210
|
-
case 'error':
|
|
211
|
-
return this.renderError();
|
|
212
|
-
default:
|
|
213
|
-
return this.renderInput();
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
export default function Init(props) {
|
|
218
|
-
const { exit } = useApp();
|
|
219
|
-
return React.createElement(InitComponent, { exit: exit, projectName: props.projectName });
|
|
220
|
-
}
|
|
221
|
-
//# sourceMappingURL=Init.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Init.js","sourceRoot":"","sources":["../../src/components/Init.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
import client from '@regressionproof/client'
|
|
2
|
-
const RegressionProofClient = client.default ?? client
|
|
3
|
-
import { Box, Text, useApp } from 'ink'
|
|
4
|
-
import BigText from 'ink-big-text'
|
|
5
|
-
import TextInput from 'ink-text-input'
|
|
6
|
-
import React from 'react'
|
|
7
|
-
import ConfigManager, { Credentials } from '../config/ConfigManager.js'
|
|
8
|
-
import JestConfigurator, { JestConfigResult } from '../jest/JestConfigurator.js'
|
|
9
|
-
import { getRepoNameFromGit, toSlug } from '../utilities/slug.js'
|
|
10
|
-
|
|
11
|
-
const API_URL =
|
|
12
|
-
process.env.REGRESSIONPROOF_API_URL ?? 'https://api.regressionproof.ai'
|
|
13
|
-
|
|
14
|
-
class InitComponent extends React.Component<Props, State> {
|
|
15
|
-
private checkTimeout: NodeJS.Timeout | null = null
|
|
16
|
-
private apiClient: InstanceType<typeof RegressionProofClient>
|
|
17
|
-
private configManager: ConfigManager
|
|
18
|
-
|
|
19
|
-
public constructor(props: Props) {
|
|
20
|
-
super(props)
|
|
21
|
-
|
|
22
|
-
const providedName = props.projectName
|
|
23
|
-
const defaultName = providedName ?? getRepoNameFromGit()
|
|
24
|
-
|
|
25
|
-
this.configManager = new ConfigManager()
|
|
26
|
-
this.apiClient = new RegressionProofClient(API_URL)
|
|
27
|
-
|
|
28
|
-
// Check if already registered (idempotent)
|
|
29
|
-
const existingCreds = this.configManager.loadCredentials(defaultName)
|
|
30
|
-
if (existingCreds) {
|
|
31
|
-
this.state = {
|
|
32
|
-
name: defaultName,
|
|
33
|
-
step: 'success',
|
|
34
|
-
availability: 'available',
|
|
35
|
-
errorMessage: '',
|
|
36
|
-
credentials: existingCreds,
|
|
37
|
-
jestConfig: null,
|
|
38
|
-
}
|
|
39
|
-
} else {
|
|
40
|
-
this.state = {
|
|
41
|
-
name: defaultName,
|
|
42
|
-
step: providedName ? 'registering' : 'input',
|
|
43
|
-
availability: 'idle',
|
|
44
|
-
errorMessage: '',
|
|
45
|
-
credentials: null,
|
|
46
|
-
jestConfig: null,
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
public componentDidMount(): void {
|
|
52
|
-
// If we have a provided name and not already registered, start registration
|
|
53
|
-
if (this.props.projectName && this.state.step === 'registering') {
|
|
54
|
-
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)
|
|
61
|
-
} else {
|
|
62
|
-
void this.checkAvailability()
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
public componentDidUpdate(_: Props, prevState: State): void {
|
|
67
|
-
if (prevState.name !== this.state.name && this.state.step === 'input') {
|
|
68
|
-
void this.checkAvailability()
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
public componentWillUnmount(): void {
|
|
73
|
-
this.clearCheckTimeout()
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
private clearCheckTimeout(): void {
|
|
77
|
-
if (this.checkTimeout) {
|
|
78
|
-
clearTimeout(this.checkTimeout)
|
|
79
|
-
this.checkTimeout = null
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
private async checkAvailability(): Promise<void> {
|
|
84
|
-
this.clearCheckTimeout()
|
|
85
|
-
|
|
86
|
-
const { name } = this.state
|
|
87
|
-
if (name.length < 3) {
|
|
88
|
-
this.setState({ availability: 'idle', errorMessage: '' })
|
|
89
|
-
return
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
this.setState({ availability: 'checking' })
|
|
93
|
-
|
|
94
|
-
this.checkTimeout = setTimeout(async () => {
|
|
95
|
-
try {
|
|
96
|
-
const isAvailable =
|
|
97
|
-
await this.apiClient.checkNameAvailability(name)
|
|
98
|
-
this.setState({
|
|
99
|
-
availability: isAvailable ? 'available' : 'taken',
|
|
100
|
-
errorMessage: '',
|
|
101
|
-
})
|
|
102
|
-
} catch (err) {
|
|
103
|
-
this.setState({
|
|
104
|
-
availability: 'error',
|
|
105
|
-
errorMessage: this.formatError(err),
|
|
106
|
-
})
|
|
107
|
-
}
|
|
108
|
-
}, 300)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
private formatError(err: unknown): string {
|
|
112
|
-
const message = err instanceof Error ? err.message : String(err)
|
|
113
|
-
const cause =
|
|
114
|
-
err instanceof Error && 'cause' in err ? ` (${err.cause})` : ''
|
|
115
|
-
return `${message}${cause} - ${API_URL}`
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
private handleNameChange = (value: string): void => {
|
|
119
|
-
this.setState({ name: toSlug(value) })
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
private handleSubmit = async (): Promise<void> => {
|
|
123
|
-
const { availability, name } = this.state
|
|
124
|
-
if (availability !== 'available' || name.length < 3) {
|
|
125
|
-
return
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
this.setState({ step: 'registering' })
|
|
129
|
-
await this.register()
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
private async register(): Promise<void> {
|
|
133
|
-
const { name } = this.state
|
|
134
|
-
|
|
135
|
-
try {
|
|
136
|
-
const credentials = await this.apiClient.registerProject({ name })
|
|
137
|
-
this.setState({ credentials })
|
|
138
|
-
|
|
139
|
-
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)
|
|
148
|
-
} catch (err) {
|
|
149
|
-
this.setState({
|
|
150
|
-
step: 'error',
|
|
151
|
-
errorMessage: err instanceof Error ? err.message : String(err),
|
|
152
|
-
})
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
private renderStatusIndicator(): React.ReactNode {
|
|
157
|
-
const { availability, errorMessage } = this.state
|
|
158
|
-
|
|
159
|
-
switch (availability) {
|
|
160
|
-
case 'idle':
|
|
161
|
-
return null
|
|
162
|
-
case 'checking':
|
|
163
|
-
return <Text color="yellow">checking...</Text>
|
|
164
|
-
case 'available':
|
|
165
|
-
return <Text color="green">available (press Enter)</Text>
|
|
166
|
-
case 'taken':
|
|
167
|
-
return <Text color="red">already taken</Text>
|
|
168
|
-
case 'error':
|
|
169
|
-
return <Text color="red">{errorMessage}</Text>
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
private renderRegistering(): React.ReactElement {
|
|
174
|
-
return (
|
|
175
|
-
<Box flexDirection="column" padding={1}>
|
|
176
|
-
<Text color="yellow">
|
|
177
|
-
Registering project "{this.state.name}"...
|
|
178
|
-
</Text>
|
|
179
|
-
</Box>
|
|
180
|
-
)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
private renderConfiguring(): React.ReactElement {
|
|
184
|
-
return (
|
|
185
|
-
<Box flexDirection="column" padding={1}>
|
|
186
|
-
<Text color="yellow">Configuring Jest reporter...</Text>
|
|
187
|
-
</Box>
|
|
188
|
-
)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
private renderSuccess(): React.ReactElement {
|
|
192
|
-
const { name, credentials, jestConfig } = this.state
|
|
193
|
-
const configDir = this.configManager.getConfigDir(name)
|
|
194
|
-
|
|
195
|
-
return (
|
|
196
|
-
<Box flexDirection="column" padding={1}>
|
|
197
|
-
<Text color="green" bold>
|
|
198
|
-
Project registered successfully!
|
|
199
|
-
</Text>
|
|
200
|
-
<Box marginTop={1} flexDirection="column">
|
|
201
|
-
<Text>
|
|
202
|
-
Config saved to:{' '}
|
|
203
|
-
<Text color="cyan">{configDir}/config.json</Text>
|
|
204
|
-
</Text>
|
|
205
|
-
<Text>
|
|
206
|
-
Git remote: <Text color="cyan">{credentials?.url}</Text>
|
|
207
|
-
</Text>
|
|
208
|
-
{jestConfig?.configured ? (
|
|
209
|
-
<Text>
|
|
210
|
-
Jest reporter added to:{' '}
|
|
211
|
-
<Text color="cyan">{jestConfig.location}</Text>
|
|
212
|
-
</Text>
|
|
213
|
-
) : (
|
|
214
|
-
<Text color="yellow">
|
|
215
|
-
Could not auto-configure Jest. Add manually:
|
|
216
|
-
</Text>
|
|
217
|
-
)}
|
|
218
|
-
</Box>
|
|
219
|
-
{!jestConfig?.configured && (
|
|
220
|
-
<Box marginTop={1} flexDirection="column">
|
|
221
|
-
<Text color="gray">// jest.config.js</Text>
|
|
222
|
-
<Text color="gray">
|
|
223
|
-
reporters: ['default',
|
|
224
|
-
'@regressionproof/jest-reporter']
|
|
225
|
-
</Text>
|
|
226
|
-
</Box>
|
|
227
|
-
)}
|
|
228
|
-
<Box marginTop={1}>
|
|
229
|
-
<Text color="green">
|
|
230
|
-
Run your tests and snapshots will be captured
|
|
231
|
-
automatically!
|
|
232
|
-
</Text>
|
|
233
|
-
</Box>
|
|
234
|
-
</Box>
|
|
235
|
-
)
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
private renderError(): React.ReactElement {
|
|
239
|
-
return (
|
|
240
|
-
<Box flexDirection="column" padding={1}>
|
|
241
|
-
<Text color="red" bold>
|
|
242
|
-
Registration failed
|
|
243
|
-
</Text>
|
|
244
|
-
<Text color="red">{this.state.errorMessage}</Text>
|
|
245
|
-
</Box>
|
|
246
|
-
)
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
private renderInput(): React.ReactElement {
|
|
250
|
-
const { name } = this.state
|
|
251
|
-
|
|
252
|
-
return (
|
|
253
|
-
<Box flexDirection="column" padding={1}>
|
|
254
|
-
<BigText
|
|
255
|
-
text="regressionproof.ai"
|
|
256
|
-
font="tiny"
|
|
257
|
-
colors={['magenta', 'cyan']}
|
|
258
|
-
/>
|
|
259
|
-
<Text color="gray">Teaching LLMs to write better code.</Text>
|
|
260
|
-
|
|
261
|
-
<Box marginTop={1} flexDirection="column">
|
|
262
|
-
<Text bold>Project name:</Text>
|
|
263
|
-
<Box>
|
|
264
|
-
<TextInput
|
|
265
|
-
value={name}
|
|
266
|
-
onChange={this.handleNameChange}
|
|
267
|
-
onSubmit={this.handleSubmit}
|
|
268
|
-
placeholder="my-awesome-project"
|
|
269
|
-
/>
|
|
270
|
-
<Box marginLeft={2}>{this.renderStatusIndicator()}</Box>
|
|
271
|
-
</Box>
|
|
272
|
-
{name.length > 0 && name.length < 3 && (
|
|
273
|
-
<Text color="gray">
|
|
274
|
-
Name must be at least 3 characters
|
|
275
|
-
</Text>
|
|
276
|
-
)}
|
|
277
|
-
</Box>
|
|
278
|
-
</Box>
|
|
279
|
-
)
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
public render(): React.ReactElement {
|
|
283
|
-
const { step } = this.state
|
|
284
|
-
|
|
285
|
-
switch (step) {
|
|
286
|
-
case 'registering':
|
|
287
|
-
return this.renderRegistering()
|
|
288
|
-
case 'configuring':
|
|
289
|
-
return this.renderConfiguring()
|
|
290
|
-
case 'success':
|
|
291
|
-
return this.renderSuccess()
|
|
292
|
-
case 'error':
|
|
293
|
-
return this.renderError()
|
|
294
|
-
default:
|
|
295
|
-
return this.renderInput()
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
export default function Init(props: { projectName?: string }): React.ReactElement {
|
|
301
|
-
const { exit } = useApp()
|
|
302
|
-
return <InitComponent exit={exit} projectName={props.projectName} />
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
type Step = 'input' | 'registering' | 'configuring' | 'success' | 'error'
|
|
306
|
-
type Availability = 'idle' | 'checking' | 'available' | 'taken' | 'error'
|
|
307
|
-
|
|
308
|
-
interface Props {
|
|
309
|
-
exit: () => void
|
|
310
|
-
projectName?: string
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
interface State {
|
|
314
|
-
name: string
|
|
315
|
-
step: Step
|
|
316
|
-
availability: Availability
|
|
317
|
-
errorMessage: string
|
|
318
|
-
credentials: Credentials | null
|
|
319
|
-
jestConfig: JestConfigResult | null
|
|
320
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export default class ConfigManager {
|
|
2
|
-
private baseDir;
|
|
3
|
-
constructor(baseDir?: string);
|
|
4
|
-
getConfigDir(projectName: string): string;
|
|
5
|
-
saveCredentials(projectName: string, credentials: Credentials): void;
|
|
6
|
-
loadCredentials(projectName: string): Credentials | null;
|
|
7
|
-
}
|
|
8
|
-
export interface Credentials {
|
|
9
|
-
url: string;
|
|
10
|
-
token: string;
|
|
11
|
-
}
|
|
12
|
-
export interface ProjectConfig {
|
|
13
|
-
remote: {
|
|
14
|
-
url: string;
|
|
15
|
-
token: string;
|
|
16
|
-
};
|
|
17
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import os from 'os';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
export default class ConfigManager {
|
|
5
|
-
baseDir;
|
|
6
|
-
constructor(baseDir = path.join(os.homedir(), '.regressionproof')) {
|
|
7
|
-
this.baseDir = baseDir;
|
|
8
|
-
}
|
|
9
|
-
getConfigDir(projectName) {
|
|
10
|
-
return path.join(this.baseDir, projectName);
|
|
11
|
-
}
|
|
12
|
-
saveCredentials(projectName, credentials) {
|
|
13
|
-
const configDir = this.getConfigDir(projectName);
|
|
14
|
-
fs.mkdirSync(configDir, { recursive: true });
|
|
15
|
-
const configPath = path.join(configDir, 'config.json');
|
|
16
|
-
const config = {
|
|
17
|
-
remote: {
|
|
18
|
-
url: credentials.url,
|
|
19
|
-
token: credentials.token,
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
23
|
-
}
|
|
24
|
-
loadCredentials(projectName) {
|
|
25
|
-
const configPath = path.join(this.getConfigDir(projectName), 'config.json');
|
|
26
|
-
if (!fs.existsSync(configPath)) {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
30
|
-
return {
|
|
31
|
-
url: config.remote.url,
|
|
32
|
-
token: config.remote.token,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=ConfigManager.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigManager.js","sourceRoot":"","sources":["../../src/config/ConfigManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,MAAM,CAAC,OAAO,OAAO,aAAa;IACtB,OAAO,CAAQ;IAEvB,YACI,UAAkB,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,kBAAkB,CAAC;QAE7D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IAC1B,CAAC;IAEM,YAAY,CAAC,WAAmB;QACnC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;IAC/C,CAAC;IAEM,eAAe,CAClB,WAAmB,EACnB,WAAwB;QAExB,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;QAChD,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAE5C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;QACtD,MAAM,MAAM,GAAkB;YAC1B,MAAM,EAAE;gBACJ,GAAG,EAAE,WAAW,CAAC,GAAG;gBACpB,KAAK,EAAE,WAAW,CAAC,KAAK;aAC3B;SACJ,CAAA;QACD,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IACjE,CAAC;IAEM,eAAe,CAAC,WAAmB;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CACxB,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,EAC9B,aAAa,CAChB,CAAA;QACD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAA;QACf,CAAC;QAED,MAAM,MAAM,GAAkB,IAAI,CAAC,KAAK,CACpC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CACvC,CAAA;QACD,OAAO;YACH,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG;YACtB,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK;SAC7B,CAAA;IACL,CAAC;CACJ"}
|
package/build/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/build/index.js
DELETED
package/build/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,iBAAiB"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export default class JestConfigurator {
|
|
2
|
-
private cwd;
|
|
3
|
-
private reporterPackage;
|
|
4
|
-
constructor(cwd?: string);
|
|
5
|
-
configure(): JestConfigResult;
|
|
6
|
-
private tryConfigurePackageJson;
|
|
7
|
-
private tryConfigureJestConfig;
|
|
8
|
-
}
|
|
9
|
-
export interface JestConfigResult {
|
|
10
|
-
configured: boolean;
|
|
11
|
-
location: string;
|
|
12
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
export default class JestConfigurator {
|
|
4
|
-
cwd;
|
|
5
|
-
reporterPackage = '@regressionproof/jest-reporter';
|
|
6
|
-
constructor(cwd = process.cwd()) {
|
|
7
|
-
this.cwd = cwd;
|
|
8
|
-
}
|
|
9
|
-
configure() {
|
|
10
|
-
return (this.tryConfigurePackageJson() ??
|
|
11
|
-
this.tryConfigureJestConfig('jest.config.ts') ??
|
|
12
|
-
this.tryConfigureJestConfig('jest.config.js') ?? {
|
|
13
|
-
configured: false,
|
|
14
|
-
location: '',
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
tryConfigurePackageJson() {
|
|
18
|
-
const packageJsonPath = path.join(this.cwd, 'package.json');
|
|
19
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
23
|
-
if (!packageJson.jest) {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
if (!packageJson.jest.reporters) {
|
|
27
|
-
packageJson.jest.reporters = ['default'];
|
|
28
|
-
}
|
|
29
|
-
if (!packageJson.jest.reporters.includes(this.reporterPackage)) {
|
|
30
|
-
packageJson.jest.reporters.push(this.reporterPackage);
|
|
31
|
-
}
|
|
32
|
-
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
|
|
33
|
-
return { configured: true, location: 'package.json' };
|
|
34
|
-
}
|
|
35
|
-
tryConfigureJestConfig(filename) {
|
|
36
|
-
const configPath = path.join(this.cwd, filename);
|
|
37
|
-
if (!fs.existsSync(configPath)) {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
let content = fs.readFileSync(configPath, 'utf-8');
|
|
41
|
-
if (content.includes(this.reporterPackage)) {
|
|
42
|
-
return {
|
|
43
|
-
configured: true,
|
|
44
|
-
location: `${filename} (already configured)`,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
if (content.includes('reporters:')) {
|
|
48
|
-
content = content.replace(/(reporters:\s*\[)/, `$1'${this.reporterPackage}', `);
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
const exportPattern = filename.endsWith('.ts')
|
|
52
|
-
? /(export\s+default\s*\{)/
|
|
53
|
-
: /(module\.exports\s*=\s*\{)/;
|
|
54
|
-
content = content.replace(exportPattern, `$1\n reporters: ['default', '${this.reporterPackage}'],`);
|
|
55
|
-
}
|
|
56
|
-
fs.writeFileSync(configPath, content);
|
|
57
|
-
return { configured: true, location: filename };
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
//# sourceMappingURL=JestConfigurator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"JestConfigurator.js","sourceRoot":"","sources":["../../src/jest/JestConfigurator.ts"],"names":[],"mappings":"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"}
|
package/build/utilities/slug.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
2
|
-
export function toSlug(input) {
|
|
3
|
-
return input
|
|
4
|
-
.toLowerCase()
|
|
5
|
-
.replace(/\s+/g, '-')
|
|
6
|
-
.replace(/[^a-z0-9-_]/g, '')
|
|
7
|
-
.replace(/-+/g, '-')
|
|
8
|
-
.replace(/^-|-$/g, '');
|
|
9
|
-
}
|
|
10
|
-
export function getRepoNameFromGit() {
|
|
11
|
-
try {
|
|
12
|
-
const remoteUrl = execSync('git remote get-url origin', {
|
|
13
|
-
encoding: 'utf-8',
|
|
14
|
-
}).trim();
|
|
15
|
-
const match = remoteUrl.match(/[/:]([^/:]+?)(\.git)?$/);
|
|
16
|
-
return toSlug(match?.[1] ?? '');
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
return '';
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
//# sourceMappingURL=slug.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"slug.js","sourceRoot":"","sources":["../../src/utilities/slug.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,MAAM,UAAU,MAAM,CAAC,KAAa;IAChC,OAAO,KAAK;SACP,WAAW,EAAE;SACb,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;SAC3B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,UAAU,kBAAkB;IAC9B,IAAI,CAAC;QACD,MAAM,SAAS,GAAG,QAAQ,CAAC,2BAA2B,EAAE;YACpD,QAAQ,EAAE,OAAO;SACpB,CAAC,CAAC,IAAI,EAAE,CAAA;QACT,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;QACvD,OAAO,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;IACnC,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAA;IACb,CAAC;AACL,CAAC"}
|