@hexabot-ai/cli 3.1.4-alpha.0 → 3.2.0-alpha.0
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 +6 -4
- package/dist/commands/__tests__/create.test.js +4 -2
- package/dist/commands/create.js +31 -5
- package/eslint.config.cjs +1 -1
- package/package.json +1 -1
- package/src/commands/__tests__/create.test.ts +4 -2
- package/src/commands/create.ts +39 -5
- package/test/__mocks__/chalk.ts +7 -1
- package/tsconfig.eslint.json +5 -0
package/README.md
CHANGED
|
@@ -155,10 +155,12 @@ For detailed information on how to get started, as well as in-depth user and dev
|
|
|
155
155
|
|
|
156
156
|
You can also find specific documentation for different components of the project in the following locations:
|
|
157
157
|
|
|
158
|
-
- [API Documentation](api/README.md)
|
|
159
|
-
- [UI Documentation](frontend/README.md)
|
|
160
|
-
- [
|
|
161
|
-
- [
|
|
158
|
+
- [API Documentation](../api/README.md)
|
|
159
|
+
- [UI Documentation](../frontend/README.md)
|
|
160
|
+
- [Agentic Package Documentation](../agentic/README.md)
|
|
161
|
+
- [Types Package Documentation](../types/README.md)
|
|
162
|
+
- [Workflow Graph Documentation](../graph/README.md)
|
|
163
|
+
- [Live Chat Widget Documentation](../widget/README.md)
|
|
162
164
|
|
|
163
165
|
## Contributing
|
|
164
166
|
|
|
@@ -118,7 +118,9 @@ describe('registerCreateCommand', () => {
|
|
|
118
118
|
.mockResolvedValueOnce('Anis')
|
|
119
119
|
.mockResolvedValueOnce('Bot')
|
|
120
120
|
.mockResolvedValueOnce('anis@example.com');
|
|
121
|
-
password
|
|
121
|
+
password
|
|
122
|
+
.mockResolvedValueOnce('Admin#123')
|
|
123
|
+
.mockResolvedValueOnce('Admin#123');
|
|
122
124
|
const program = new Command();
|
|
123
125
|
registerCreateCommand(program);
|
|
124
126
|
await program.parseAsync([
|
|
@@ -142,7 +144,7 @@ describe('registerCreateCommand', () => {
|
|
|
142
144
|
});
|
|
143
145
|
expect(exitSpy).not.toHaveBeenCalled();
|
|
144
146
|
expect(input).toHaveBeenCalledTimes(3);
|
|
145
|
-
expect(password).toHaveBeenCalledTimes(
|
|
147
|
+
expect(password).toHaveBeenCalledTimes(2);
|
|
146
148
|
});
|
|
147
149
|
it('fails cleanly when create runs in a non-interactive terminal', async () => {
|
|
148
150
|
setTTY(false);
|
package/dist/commands/create.js
CHANGED
|
@@ -135,6 +135,18 @@ const validateEmail = (value) => {
|
|
|
135
135
|
}
|
|
136
136
|
return true;
|
|
137
137
|
};
|
|
138
|
+
const validateAdminPassword = (value) => {
|
|
139
|
+
const trimmed = value.trim();
|
|
140
|
+
if (!trimmed) {
|
|
141
|
+
return 'Password is required.';
|
|
142
|
+
}
|
|
143
|
+
// Keep the rule simple and explicit for CLI UX. Complexity policies vary by org.
|
|
144
|
+
const minLength = 12;
|
|
145
|
+
if (trimmed.length < minLength) {
|
|
146
|
+
return `Password must be at least ${minLength} characters.`;
|
|
147
|
+
}
|
|
148
|
+
return true;
|
|
149
|
+
};
|
|
138
150
|
const assertInteractiveTerminal = () => {
|
|
139
151
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
140
152
|
throw new Error('hexabot create requires an interactive terminal to capture admin credentials.');
|
|
@@ -142,22 +154,36 @@ const assertInteractiveTerminal = () => {
|
|
|
142
154
|
};
|
|
143
155
|
const promptSeedAdminCredentials = async () => {
|
|
144
156
|
assertInteractiveTerminal();
|
|
157
|
+
console.log('\n');
|
|
158
|
+
console.log(chalk.bold('Admin account (initial credentials)'));
|
|
159
|
+
console.log(chalk.gray('These details are used to seed the first admin user. You can change them later in your env file.'));
|
|
160
|
+
console.log('\n');
|
|
145
161
|
const firstName = (await input({
|
|
146
|
-
message: '
|
|
162
|
+
message: 'First name (e.g. Jhon)',
|
|
147
163
|
validate: requireValue('First name'),
|
|
148
164
|
})).trim();
|
|
149
165
|
const lastName = (await input({
|
|
150
|
-
message: '
|
|
166
|
+
message: 'Last name (e.g. Doe)',
|
|
151
167
|
validate: requireValue('Last name'),
|
|
152
168
|
})).trim();
|
|
153
169
|
const email = (await input({
|
|
154
|
-
message: '
|
|
170
|
+
message: 'Email (e.g. admin@company.com)',
|
|
155
171
|
validate: validateEmail,
|
|
156
172
|
})).trim();
|
|
157
173
|
const adminPassword = await password({
|
|
158
|
-
message: '
|
|
174
|
+
message: 'Password (min 12 chars)',
|
|
175
|
+
mask: '*',
|
|
176
|
+
validate: validateAdminPassword,
|
|
177
|
+
});
|
|
178
|
+
await password({
|
|
179
|
+
message: 'Confirm password',
|
|
159
180
|
mask: '*',
|
|
160
|
-
validate:
|
|
181
|
+
validate: (value) => {
|
|
182
|
+
if (value !== adminPassword) {
|
|
183
|
+
return 'Passwords do not match.';
|
|
184
|
+
}
|
|
185
|
+
return true;
|
|
186
|
+
},
|
|
161
187
|
});
|
|
162
188
|
return {
|
|
163
189
|
firstName,
|
package/eslint.config.cjs
CHANGED
|
@@ -42,7 +42,7 @@ const createConfig = ({ headerYear = '2025' } = {}) => {
|
|
|
42
42
|
languageOptions: {
|
|
43
43
|
parser: tsParser,
|
|
44
44
|
parserOptions: {
|
|
45
|
-
project: path.join(__dirname, 'tsconfig.json'),
|
|
45
|
+
project: path.join(__dirname, 'tsconfig.eslint.json'),
|
|
46
46
|
tsconfigRootDir: __dirname,
|
|
47
47
|
sourceType: 'module',
|
|
48
48
|
},
|
package/package.json
CHANGED
|
@@ -138,7 +138,9 @@ describe('registerCreateCommand', () => {
|
|
|
138
138
|
.mockResolvedValueOnce('Anis')
|
|
139
139
|
.mockResolvedValueOnce('Bot')
|
|
140
140
|
.mockResolvedValueOnce('anis@example.com');
|
|
141
|
-
(password as any)
|
|
141
|
+
(password as any)
|
|
142
|
+
.mockResolvedValueOnce('Admin#123')
|
|
143
|
+
.mockResolvedValueOnce('Admin#123');
|
|
142
144
|
|
|
143
145
|
const program = new Command();
|
|
144
146
|
registerCreateCommand(program);
|
|
@@ -172,7 +174,7 @@ describe('registerCreateCommand', () => {
|
|
|
172
174
|
});
|
|
173
175
|
expect(exitSpy).not.toHaveBeenCalled();
|
|
174
176
|
expect(input).toHaveBeenCalledTimes(3);
|
|
175
|
-
expect(password).toHaveBeenCalledTimes(
|
|
177
|
+
expect(password).toHaveBeenCalledTimes(2);
|
|
176
178
|
});
|
|
177
179
|
|
|
178
180
|
it('fails cleanly when create runs in a non-interactive terminal', async () => {
|
package/src/commands/create.ts
CHANGED
|
@@ -206,6 +206,20 @@ const validateEmail = (value: string) => {
|
|
|
206
206
|
|
|
207
207
|
return true;
|
|
208
208
|
};
|
|
209
|
+
const validateAdminPassword = (value: string) => {
|
|
210
|
+
const trimmed = value.trim();
|
|
211
|
+
if (!trimmed) {
|
|
212
|
+
return 'Password is required.';
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Keep the rule simple and explicit for CLI UX. Complexity policies vary by org.
|
|
216
|
+
const minLength = 12;
|
|
217
|
+
if (trimmed.length < minLength) {
|
|
218
|
+
return `Password must be at least ${minLength} characters.`;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return true;
|
|
222
|
+
};
|
|
209
223
|
const assertInteractiveTerminal = () => {
|
|
210
224
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
211
225
|
throw new Error(
|
|
@@ -216,28 +230,48 @@ const assertInteractiveTerminal = () => {
|
|
|
216
230
|
const promptSeedAdminCredentials = async (): Promise<AdminSeedCredentials> => {
|
|
217
231
|
assertInteractiveTerminal();
|
|
218
232
|
|
|
233
|
+
console.log('\n');
|
|
234
|
+
console.log(chalk.bold('Admin account (initial credentials)'));
|
|
235
|
+
console.log(
|
|
236
|
+
chalk.gray(
|
|
237
|
+
'These details are used to seed the first admin user. You can change them later in your env file.',
|
|
238
|
+
),
|
|
239
|
+
);
|
|
240
|
+
console.log('\n');
|
|
241
|
+
|
|
219
242
|
const firstName = (
|
|
220
243
|
await input({
|
|
221
|
-
message: '
|
|
244
|
+
message: 'First name (e.g. Jhon)',
|
|
222
245
|
validate: requireValue('First name'),
|
|
223
246
|
})
|
|
224
247
|
).trim();
|
|
225
248
|
const lastName = (
|
|
226
249
|
await input({
|
|
227
|
-
message: '
|
|
250
|
+
message: 'Last name (e.g. Doe)',
|
|
228
251
|
validate: requireValue('Last name'),
|
|
229
252
|
})
|
|
230
253
|
).trim();
|
|
231
254
|
const email = (
|
|
232
255
|
await input({
|
|
233
|
-
message: '
|
|
256
|
+
message: 'Email (e.g. admin@company.com)',
|
|
234
257
|
validate: validateEmail,
|
|
235
258
|
})
|
|
236
259
|
).trim();
|
|
237
260
|
const adminPassword = await password({
|
|
238
|
-
message: '
|
|
261
|
+
message: 'Password (min 12 chars)',
|
|
239
262
|
mask: '*',
|
|
240
|
-
validate:
|
|
263
|
+
validate: validateAdminPassword,
|
|
264
|
+
});
|
|
265
|
+
await password({
|
|
266
|
+
message: 'Confirm password',
|
|
267
|
+
mask: '*',
|
|
268
|
+
validate: (value: string) => {
|
|
269
|
+
if (value !== adminPassword) {
|
|
270
|
+
return 'Passwords do not match.';
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return true;
|
|
274
|
+
},
|
|
241
275
|
});
|
|
242
276
|
|
|
243
277
|
return {
|
package/test/__mocks__/chalk.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Hexabot — Fair Core License (FCL-1.0-ALv2)
|
|
3
|
+
* Copyright (c) 2026 Hexastack.
|
|
4
|
+
* Full terms: see LICENSE.md.
|
|
5
|
+
*/
|
|
2
6
|
|
|
7
|
+
const passthrough = (value: string) => value;
|
|
3
8
|
const chalkMock = {
|
|
4
9
|
blue: passthrough,
|
|
10
|
+
bold: passthrough,
|
|
5
11
|
yellow: passthrough,
|
|
6
12
|
cyan: passthrough,
|
|
7
13
|
red: passthrough,
|