Skip to content

Commit 236d6cc

Browse files
authored
feat(1938): change config set options (#1947)
Signed-off-by: mmyslblocky <michal.myslinski@blockydevs.com>
1 parent 901efd9 commit 236d6cc

25 files changed

Lines changed: 217 additions & 198 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,10 @@ Configure the default key storage method using the config command:
342342

343343
```bash
344344
# Set to plain text storage (development/testing)
345-
hcli config set -o default_key_manager -V local
345+
hcli config set --default_key_manager local
346346

347347
# Set to encrypted storage (production)
348-
hcli config set -o default_key_manager -V local_encrypted
348+
hcli config set --default_key_manager local_encrypted
349349
```
350350

351351
### Per-Operation Override

docs/adr/ADR-004-key-protection-mechanism.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ Users can disable encryption entirely for development and testing scenarios:
118118
**Configuration Method:**
119119

120120
- First-run wizard will prompt: "Enable key encryption? (Recommended for production, can be disabled for local development)"
121-
- Key storage mode is configurable via: `hcli config set -o default_key_manager -V local|local_encrypted`
121+
- Key storage mode is configurable via: `hcli config set --default_key_manager local` or `hcli config set --default_key_manager local_encrypted`
122122

123123
**When Encryption is Disabled:**
124124

docs/architecture.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ Core API
614614
- Keys are stored in the KMS (Key Management Service) with two storage options:
615615
- **`local`**: Plain text storage (development/testing environments)
616616
- **`local_encrypted`**: AES-256-GCM encrypted storage (production environments)
617-
- Default key manager configurable via `hcli config set -o default_key_manager -V local|local_encrypted`
617+
- Default key manager configurable via `hcli config set --default_key_manager local` or `hcli config set --default_key_manager local_encrypted`
618618
- Per-operation override available using `--key-manager` flag on commands that store keys
619619
- No hardcoded credentials in code
620620

docs/core-api.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -583,9 +583,9 @@ The global log level is controlled by the config option `log_level`:
583583
- configure via CLI, for example:
584584

585585
```bash
586-
hcli config set -o log_level -V silent
587-
hcli config set -o log_level -V error
588-
hcli config set -o log_level -V debug
586+
hcli config set --log_level silent
587+
hcli config set --log_level error
588+
hcli config set --log_level debug
589589
```
590590

591591
All logger output is written to **stderr** so that structured command output on stdout
@@ -611,7 +611,7 @@ The KMS supports two storage modes for private keys:
611611
- **`local`** - Keys stored as plain text (suitable for development and testing)
612612
- **`local_encrypted`** - Keys encrypted using AES-256-GCM (recommended for production)
613613

614-
The default storage mode is configured via `hcli config set -o default_key_manager -V local|local_encrypted`. Individual operations can override this using the `--key-manager` flag when available.
614+
The default storage mode is configured via `hcli config set --default_key_manager local` or `hcli config set --default_key_manager local_encrypted`. Individual operations can override this using the `--key-manager` flag when available.
615615

616616
```typescript
617617
interface KmsService {

skills/hiero-cli/references/config.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,22 @@ hcli config get --option default_key_manager
4747

4848
### `hcli config set`
4949

50-
Set the value of a configuration option.
50+
Set the value of a configuration option. Pass exactly one named option flag per invocation.
5151

52-
| Option | Short | Type | Required | Description |
53-
| ---------- | ----- | ------ | -------- | ------------------------------------------------------------------ |
54-
| `--option` | `-o` | string | **yes** | Option name to set. Use `config list` to see available options |
55-
| `--value` | `-V` | string | **yes** | Value to set. Booleans: `true`/`false`. Numbers as strings: `"10"` |
52+
| Option | Type | Required | Allowed values |
53+
| --------------------------- | ------ | -------- | ------------------------------------------ |
54+
| `--default_key_manager` | string | one of | `local`, `local_encrypted` |
55+
| `--ed25519_support_enabled` | string | one of | `true`, `false` |
56+
| `--log_level` | string | one of | `silent`, `error`, `warn`, `info`, `debug` |
57+
| `--skip_confirmations` | string | one of | `true`, `false` |
5658

5759
**Example:**
5860

5961
```
60-
hcli config set --option default_key_manager --value local_encrypted
61-
hcli config set --option skip_confirmations --value true
62+
hcli config set --default_key_manager local_encrypted
63+
hcli config set --skip_confirmations true
64+
hcli config set --log_level debug
65+
hcli config set --ed25519_support_enabled false
6266
```
6367

6468
**Output:** `{ name, previousValue, newValue }`

src/__tests__/integration/config/config.integration.test.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describe('Config Integration Tests', () => {
3232
const optionNames = listConfigOutput.options.map((option) => option.name);
3333
expect(optionNames).toEqual(
3434
expect.arrayContaining([
35-
ConfigOptionKey.ed25519_support_enabled,
35+
ConfigOptionKey.ed25519_support,
3636
ConfigOptionKey.log_level,
3737
ConfigOptionKey.default_key_manager,
3838
]),
@@ -41,8 +41,7 @@ describe('Config Integration Tests', () => {
4141

4242
it('should set config option and then verify it with with get method', async () => {
4343
const setConfigArgs: Record<string, unknown> = {
44-
option: ConfigOptionKey.ed25519_support_enabled,
45-
value: 'true',
44+
[ConfigOptionKey.ed25519_support]: 'true',
4645
};
4746
const setConfigResult = await configSet({
4847
args: setConfigArgs,
@@ -53,14 +52,14 @@ describe('Config Integration Tests', () => {
5352
expect(setConfigOutput.newValue).toBe(true);
5453

5554
const getConfigArgs: Record<string, unknown> = {
56-
option: ConfigOptionKey.ed25519_support_enabled,
55+
option: ConfigOptionKey.ed25519_support,
5756
};
5857
const getConfigResult = await configGet({
5958
args: getConfigArgs,
6059
api: coreApi,
6160
});
6261
const getConfigOutput = getConfigResult.result as ConfigGetOutput;
63-
expect(getConfigOutput.name).toBe(ConfigOptionKey.ed25519_support_enabled);
62+
expect(getConfigOutput.name).toBe(ConfigOptionKey.ed25519_support);
6463
expect(getConfigOutput.value).toBe(true);
6564
expect(getConfigOutput.type).toBe('boolean');
6665
});

src/core/core-api/core-api.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@ import type { ContractVerifierService } from '@/core/services/contract-verifier/
1515
import type { IdentityResolutionService } from '@/core/services/identity-resolution/identity-resolution-service.interface';
1616
import type { KeyResolverService } from '@/core/services/key-resolver/key-resolver-service.interface';
1717
import type { KmsService } from '@/core/services/kms/kms-service.interface';
18-
import type {
19-
Logger,
20-
LogLevel,
21-
} from '@/core/services/logger/logger-service.interface';
18+
import type { Logger } from '@/core/services/logger/logger-service.interface';
2219
import type { HederaMirrornodeService } from '@/core/services/mirrornode/hedera-mirrornode-service.interface';
2320
import type { NetworkService } from '@/core/services/network/network-service.interface';
2421
import type { OutputService } from '@/core/services/output/output-service.interface';
@@ -31,6 +28,7 @@ import type { TopicService } from '@/core/services/topic/topic-transaction-servi
3128
import type { TransferService } from '@/core/services/transfer/transfer-service.interface';
3229
import type { TxExecuteService } from '@/core/services/tx-execute/tx-execute-service.interface';
3330
import type { TxSignService } from '@/core/services/tx-sign/tx-sign-service.interface';
31+
import type { LogLevel } from '@/core/types/shared.types';
3432

3533
import { AccountServiceImpl } from '@/core/services/account/account-transaction-service';
3634
import { AliasServiceImpl } from '@/core/services/alias/alias-service';

src/core/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export type * from './services/contract-verifier/contract-verifier-service.inter
3636
export type * from './services/identity-resolution/identity-resolution-service.interface';
3737
export type * from './services/key-resolver/key-resolver-service.interface';
3838
export type * from './services/kms/kms-service.interface';
39-
export * from './services/logger/logger-service.interface';
39+
export type * from './services/logger/logger-service.interface';
4040
export type * from './services/mirrornode/hedera-mirrornode-service.interface';
4141
export type { NetworkService } from './services/network/network-service.interface';
4242
export type * from './services/output/output-service.interface';

src/core/schemas/common-schemas.ts

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -739,29 +739,6 @@ export const ConfigOptionNameSchema = z
739739
)
740740
.describe('Configuration option name');
741741

742-
/**
743-
* Configuration Option Value
744-
* Value for configuration option (can be string, number, or boolean as string)
745-
* Handler will parse it to appropriate type
746-
*/
747-
export const ConfigOptionValueSchema = z
748-
.preprocess(
749-
(value) => {
750-
if (typeof value !== 'string') return value;
751-
const s = value.trim().toLowerCase();
752-
753-
if (s === 'true') return true;
754-
if (s === 'false') return false;
755-
756-
const n = Number(value);
757-
if (!Number.isNaN(n) && Number.isFinite(n)) return n;
758-
759-
return value;
760-
},
761-
z.union([z.boolean(), z.number(), z.string()]),
762-
)
763-
.describe('Configuration option value (boolean, number, or string)');
764-
765742
/**
766743
* Key Reference ID
767744
* Identifier for a key stored in KMS (Key Management System)
@@ -1242,3 +1219,8 @@ export const ScheduledTransactionDataSchema = z.object({
12421219
),
12431220
createdAt: z.string().optional(),
12441221
});
1222+
1223+
export const BooleanStringSchema = z.preprocess(
1224+
(v) => (v === 'true' ? true : v === 'false' ? false : v),
1225+
z.boolean({ error: 'Value must be true or false' }),
1226+
);

src/core/services/config/__tests__/unit/config-service.test.ts

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ describe('ConfigServiceImpl', () => {
2929
expect(options).toEqual(
3030
expect.arrayContaining([
3131
expect.objectContaining({
32-
name: ConfigOptionKey.ed25519_support_enabled,
32+
name: ConfigOptionKey.ed25519_support,
3333
type: 'boolean',
3434
value: false,
3535
}),
@@ -51,15 +51,14 @@ describe('ConfigServiceImpl', () => {
5151

5252
it('should return stored values when available', () => {
5353
stateMock.get.mockImplementation((_: string, key: string) => {
54-
if (key === (ConfigOptionKey.ed25519_support_enabled as string))
55-
return true;
54+
if (key === (ConfigOptionKey.ed25519_support as string)) return true;
5655
if (key === (ConfigOptionKey.log_level as string)) return 'debug';
5756
return undefined;
5857
});
5958

6059
const options = configService.listOptions();
6160
const ed25519Option = options.find(
62-
(o) => o.name === (ConfigOptionKey.ed25519_support_enabled as string),
61+
(o) => o.name === (ConfigOptionKey.ed25519_support as string),
6362
);
6463
const logLevelOption = options.find(
6564
(o) => o.name === (ConfigOptionKey.log_level as string),
@@ -89,33 +88,27 @@ describe('ConfigServiceImpl', () => {
8988
it('should return stored value for boolean option', () => {
9089
stateMock.get.mockReturnValue(true);
9190

92-
const result = configService.getOption(
93-
ConfigOptionKey.ed25519_support_enabled,
94-
);
91+
const result = configService.getOption(ConfigOptionKey.ed25519_support);
9592

9693
expect(stateMock.get).toHaveBeenCalledWith(
9794
'config',
98-
ConfigOptionKey.ed25519_support_enabled,
95+
ConfigOptionKey.ed25519_support,
9996
);
10097
expect(result).toBe(true);
10198
});
10299

103100
it('should return default value when not set', () => {
104101
stateMock.get.mockReturnValue(undefined);
105102

106-
const result = configService.getOption(
107-
ConfigOptionKey.ed25519_support_enabled,
108-
);
103+
const result = configService.getOption(ConfigOptionKey.ed25519_support);
109104

110105
expect(result).toBe(false);
111106
});
112107

113108
it('should return default value when null', () => {
114109
stateMock.get.mockReturnValue(null);
115110

116-
const result = configService.getOption(
117-
ConfigOptionKey.ed25519_support_enabled,
118-
);
111+
const result = configService.getOption(ConfigOptionKey.ed25519_support);
119112

120113
expect(result).toBe(false);
121114
});
@@ -129,9 +122,7 @@ describe('ConfigServiceImpl', () => {
129122
it('should convert value to boolean for boolean type', () => {
130123
stateMock.get.mockReturnValue('truthy_string');
131124

132-
const result = configService.getOption(
133-
ConfigOptionKey.ed25519_support_enabled,
134-
);
125+
const result = configService.getOption(ConfigOptionKey.ed25519_support);
135126

136127
expect(result).toBe(true);
137128
});
@@ -155,11 +146,11 @@ describe('ConfigServiceImpl', () => {
155146

156147
describe('setOption', () => {
157148
it('should set boolean option', () => {
158-
configService.setOption(ConfigOptionKey.ed25519_support_enabled, true);
149+
configService.setOption(ConfigOptionKey.ed25519_support, true);
159150

160151
expect(stateMock.set).toHaveBeenCalledWith(
161152
'config',
162-
ConfigOptionKey.ed25519_support_enabled,
153+
ConfigOptionKey.ed25519_support,
163154
true,
164155
);
165156
});
@@ -172,10 +163,7 @@ describe('ConfigServiceImpl', () => {
172163

173164
it('should throw error when setting non-boolean for boolean option', () => {
174165
expect(() =>
175-
configService.setOption(
176-
ConfigOptionKey.ed25519_support_enabled,
177-
'not_boolean',
178-
),
166+
configService.setOption(ConfigOptionKey.ed25519_support, 'not_boolean'),
179167
).toThrow(ValidationError);
180168
});
181169

0 commit comments

Comments
 (0)