11import {
2- getConfigTopLevelCategories ,
32 runConfigGet ,
43 runConfigList ,
54 runConfigSet ,
65 runConfigValidate ,
76} from '../../commands/config'
8- import { getByPath , loadMergedSettings } from '../../utils/config'
7+ import { getByPath , getTopLevelSettingCategories , loadMergedSettings , toCategoryLabel } from '../../../utils/settings-config'
8+ import {
9+ type GuidedSettingField ,
10+ guidedSettingCategories ,
11+ } from '../../../utils/settings-guided-schema'
912import { tuiPrompts } from '../prompts'
1013
11- const toCategoryLabel = ( key : string ) : string => {
12- return key
13- . split ( / [ _ \- . ] / )
14- . filter ( Boolean )
15- . map ( ( part ) => part . charAt ( 0 ) . toUpperCase ( ) + part . slice ( 1 ) )
16- . join ( ' ' )
17- }
18-
1914const getCategoryOptions = ( ) => {
20- const categories = getConfigTopLevelCategories ( ) . sort ( ( a , b ) => a . localeCompare ( b ) )
15+ const categories = getTopLevelSettingCategories ( ) . sort ( ( a , b ) => a . localeCompare ( b ) )
2116
2217 return [
2318 ...categories . map ( ( category ) => ( {
@@ -28,116 +23,6 @@ const getCategoryOptions = () => {
2823 ]
2924}
3025
31- type GuidedSetting = {
32- label : string
33- path : string
34- type : 'boolean' | 'number' | 'string' | 'select' | 'stringArray'
35- options ?: string [ ]
36- placeholder ?: string
37- validate ?: ( value : string ) => string | undefined
38- }
39-
40- type GuidedCategory = {
41- value : string
42- label : string
43- settings : GuidedSetting [ ]
44- }
45-
46- const requireNonEmpty = ( value : string ) : string | undefined => {
47- return value . trim ( ) ? undefined : 'Value is required'
48- }
49-
50- const requireSafeNonNegativeInteger = ( value : string ) : string | undefined => {
51- const trimmed = value . trim ( )
52- if ( ! / ^ \d + $ / . test ( trimmed ) ) {
53- return 'Value must be a non-negative integer'
54- }
55-
56- const parsed = Number ( trimmed )
57- if ( ! Number . isSafeInteger ( parsed ) ) {
58- return 'Value must be a safe integer'
59- }
60-
61- return undefined
62- }
63-
64- const guidedCategories : GuidedCategory [ ] = [
65- {
66- value : 'payments' ,
67- label : 'Payments' ,
68- settings : [
69- { label : 'Enable payments' , path : 'payments.enabled' , type : 'boolean' } ,
70- {
71- label : 'Payment processor' ,
72- path : 'payments.processor' ,
73- type : 'select' ,
74- options : [ 'zebedee' , 'lnbits' , 'lnurl' , 'nodeless' , 'opennode' ] ,
75- } ,
76- {
77- label : 'Admission fee enabled' ,
78- path : 'payments.feeSchedules.admission[0].enabled' ,
79- type : 'boolean' ,
80- } ,
81- {
82- label : 'Admission fee amount (msats)' ,
83- path : 'payments.feeSchedules.admission[0].amount' ,
84- type : 'number' ,
85- validate : requireSafeNonNegativeInteger ,
86- } ,
87- ] ,
88- } ,
89- {
90- value : 'network' ,
91- label : 'Network' ,
92- settings : [
93- {
94- label : 'Relay URL' ,
95- path : 'info.relay_url' ,
96- type : 'string' ,
97- placeholder : 'wss://relay.example.com' ,
98- validate : requireNonEmpty ,
99- } ,
100- {
101- label : 'Relay name' ,
102- path : 'info.name' ,
103- type : 'string' ,
104- placeholder : 'relay.example.com' ,
105- validate : requireNonEmpty ,
106- } ,
107- {
108- label : 'Max payload size' ,
109- path : 'network.maxPayloadSize' ,
110- type : 'number' ,
111- validate : requireSafeNonNegativeInteger ,
112- } ,
113- ] ,
114- } ,
115- {
116- value : 'limits' ,
117- label : 'Limits' ,
118- settings : [
119- {
120- label : 'Rate limiter strategy' ,
121- path : 'limits.rateLimiter.strategy' ,
122- type : 'select' ,
123- options : [ 'ewma' , 'sliding_window' ] ,
124- } ,
125- {
126- label : 'Primary event content max length' ,
127- path : 'limits.event.content[0].maxLength' ,
128- type : 'number' ,
129- validate : requireSafeNonNegativeInteger ,
130- } ,
131- {
132- label : 'Minimum pubkey balance' ,
133- path : 'limits.event.pubkey.minBalance' ,
134- type : 'number' ,
135- validate : requireSafeNonNegativeInteger ,
136- } ,
137- ] ,
138- } ,
139- ]
140-
14126const formatCurrentValue = ( value : unknown ) : string => {
14227 if ( Array . isArray ( value ) ) {
14328 return value . length === 0 ? '[]' : value . join ( ', ' )
@@ -162,7 +47,7 @@ const formatCurrentValue = (value: unknown): string => {
16247 return String ( value )
16348}
16449
165- const getGuidedSettingValue = async ( setting : GuidedSetting , currentValue : unknown ) => {
50+ const getGuidedSettingValue = async ( setting : GuidedSettingField , currentValue : unknown ) => {
16651 switch ( setting . type ) {
16752 case 'boolean' : {
16853 const answer = await tuiPrompts . confirm ( {
@@ -248,7 +133,7 @@ const getGuidedSettingValue = async (setting: GuidedSetting, currentValue: unkno
248133const runGuidedConfigureMenu = async ( ) : Promise < number > => {
249134 const category = await tuiPrompts . select ( {
250135 message : 'Configuration category' ,
251- options : [ ...guidedCategories . map ( ( { value, label } ) => ( { value, label } ) ) , { value : 'back' , label : 'Back' } ] ,
136+ options : [ ...guidedSettingCategories . map ( ( { value, label } ) => ( { value, label } ) ) , { value : 'back' , label : 'Back' } ] ,
252137 } )
253138
254139 if ( tuiPrompts . isCancel ( category ) ) {
@@ -259,7 +144,7 @@ const runGuidedConfigureMenu = async (): Promise<number> => {
259144 return 0
260145 }
261146
262- const selectedCategory = guidedCategories . find ( ( entry ) => entry . value === category )
147+ const selectedCategory = guidedSettingCategories . find ( ( entry ) => entry . value === category )
263148 if ( ! selectedCategory ) {
264149 tuiPrompts . cancel ( 'Unknown category' )
265150 return 1
0 commit comments