@@ -14,45 +14,21 @@ const { join } = require('node:path');
1414/**
1515 * @typedef {import('../src/config/types.ts').CodiffConfig } CodiffConfig
1616 * @typedef {import('../src/config/types.ts').CodiffDiffStyle } CodiffDiffStyle
17- * @typedef {import('../src/config/types.ts').CodiffKeymap } CodiffKeymap
18- * @typedef {import('../src/config/types.ts').CodiffSettings } CodiffSettings
1917 * @typedef {import('../src/config/types.ts').CodiffTheme } CodiffTheme
2018 * @typedef {import('../src/types.ts').CodiffPreferences } CodiffPreferences
2119 */
2220
21+ /** @type {CodiffConfig } */
22+ const defaultConfigTemplate = require ( '../config/defaults.json' ) ;
23+
2324const SCHEMA_URL =
2425 'https://raw.githubusercontent.com/nkzw-tech/codiff/main/src/config/codiff-config.schema.json' ;
2526
26- /** @type {CodiffSettings } */
27- const defaultSettings = {
28- copyCommentsOnClose : false ,
29- diffStyle : 'split' ,
30- lastRepositoryPath : '' ,
31- openAIModel : 'gpt-5.3-codex-spark' ,
32- showOutdated : false ,
33- showWhitespace : false ,
34- theme : 'system' ,
35- wordWrap : false ,
36- } ;
37-
38- /** @type {CodiffKeymap } */
39- const defaultKeymap = {
40- closeSearch : 'Escape' ,
41- commandBar : 'Mod+Shift+p' ,
42- diffSearch : 'Mod+f' ,
43- discardComment : 'Escape' ,
44- fileFilter : 'Mod+p' ,
45- nextSearchMatch : 'Enter' ,
46- prevSearchMatch : 'Shift+Enter' ,
47- submitComment : 'Mod+Enter' ,
48- toggleSidebar : 'Mod+b' ,
49- } ;
50-
51- /** @type {CodiffConfig } */
52- const defaultConfig = {
53- keymap : defaultKeymap ,
54- settings : defaultSettings ,
55- } ;
27+ /** @returns {CodiffConfig } */
28+ const createDefaultConfig = ( ) => ( {
29+ keymap : { ...defaultConfigTemplate . keymap } ,
30+ settings : { ...defaultConfigTemplate . settings } ,
31+ } ) ;
5632
5733const getConfigDir = ( ) => join ( homedir ( ) , '.codiff' ) ;
5834
@@ -147,8 +123,10 @@ const normalizeLastRepositoryPath = (path) =>
147123 * @returns {CodiffConfig }
148124 */
149125const mergeConfig = ( raw ) => {
126+ const defaults = createDefaultConfig ( ) ;
127+
150128 if ( typeof raw !== 'object' || raw === null ) {
151- return defaultConfig ;
129+ return defaults ;
152130 }
153131
154132 const obj = /** @type {Record<string, unknown> } */ ( raw ) ;
@@ -166,56 +144,70 @@ const mergeConfig = (raw) => {
166144 closeSearch :
167145 typeof rawKeymap . closeSearch === 'string'
168146 ? rawKeymap . closeSearch
169- : defaultKeymap . closeSearch ,
147+ : defaults . keymap . closeSearch ,
170148 commandBar :
171- typeof rawKeymap . commandBar === 'string' ? rawKeymap . commandBar : defaultKeymap . commandBar ,
149+ typeof rawKeymap . commandBar === 'string'
150+ ? rawKeymap . commandBar
151+ : defaults . keymap . commandBar ,
172152 diffSearch :
173- typeof rawKeymap . diffSearch === 'string' ? rawKeymap . diffSearch : defaultKeymap . diffSearch ,
153+ typeof rawKeymap . diffSearch === 'string'
154+ ? rawKeymap . diffSearch
155+ : defaults . keymap . diffSearch ,
174156 discardComment :
175157 typeof rawKeymap . discardComment === 'string'
176158 ? rawKeymap . discardComment
177- : defaultKeymap . discardComment ,
159+ : defaults . keymap . discardComment ,
178160 fileFilter :
179- typeof rawKeymap . fileFilter === 'string' ? rawKeymap . fileFilter : defaultKeymap . fileFilter ,
161+ typeof rawKeymap . fileFilter === 'string'
162+ ? rawKeymap . fileFilter
163+ : defaults . keymap . fileFilter ,
180164 nextSearchMatch :
181165 typeof rawKeymap . nextSearchMatch === 'string'
182166 ? rawKeymap . nextSearchMatch
183- : defaultKeymap . nextSearchMatch ,
167+ : defaults . keymap . nextSearchMatch ,
168+ openFile :
169+ typeof rawKeymap . openFile === 'string' ? rawKeymap . openFile : defaults . keymap . openFile ,
184170 prevSearchMatch :
185171 typeof rawKeymap . prevSearchMatch === 'string'
186172 ? rawKeymap . prevSearchMatch
187- : defaultKeymap . prevSearchMatch ,
173+ : defaults . keymap . prevSearchMatch ,
188174 submitComment :
189175 typeof rawKeymap . submitComment === 'string'
190176 ? rawKeymap . submitComment
191- : defaultKeymap . submitComment ,
177+ : defaults . keymap . submitComment ,
192178 toggleSidebar :
193179 typeof rawKeymap . toggleSidebar === 'string'
194180 ? rawKeymap . toggleSidebar
195- : defaultKeymap . toggleSidebar ,
181+ : defaults . keymap . toggleSidebar ,
196182 } ,
197183 settings : {
198184 copyCommentsOnClose :
199185 typeof rawSettings . copyCommentsOnClose === 'boolean'
200186 ? rawSettings . copyCommentsOnClose
201- : defaultSettings . copyCommentsOnClose ,
187+ : defaults . settings . copyCommentsOnClose ,
202188 diffStyle : normalizeDiffStyle ( rawSettings . diffStyle ) ,
189+ editorCommand :
190+ typeof rawSettings . editorCommand === 'string'
191+ ? rawSettings . editorCommand
192+ : defaults . settings . editorCommand ,
203193 lastRepositoryPath : normalizeLastRepositoryPath ( rawSettings . lastRepositoryPath ) ,
204194 openAIModel :
205195 typeof rawSettings . openAIModel === 'string'
206196 ? rawSettings . openAIModel
207- : defaultSettings . openAIModel ,
197+ : defaults . settings . openAIModel ,
208198 showOutdated :
209199 typeof rawSettings . showOutdated === 'boolean'
210200 ? rawSettings . showOutdated
211- : defaultSettings . showOutdated ,
201+ : defaults . settings . showOutdated ,
212202 showWhitespace :
213203 typeof rawSettings . showWhitespace === 'boolean'
214204 ? rawSettings . showWhitespace
215- : defaultSettings . showWhitespace ,
205+ : defaults . settings . showWhitespace ,
216206 theme : normalizeTheme ( rawSettings . theme ) ,
217207 wordWrap :
218- typeof rawSettings . wordWrap === 'boolean' ? rawSettings . wordWrap : defaultSettings . wordWrap ,
208+ typeof rawSettings . wordWrap === 'boolean'
209+ ? rawSettings . wordWrap
210+ : defaults . settings . wordWrap ,
219211 } ,
220212 } ;
221213} ;
@@ -228,15 +220,15 @@ const readConfig = () => {
228220 const configPath = getConfigPath ( ) ;
229221
230222 if ( ! existsSync ( configPath ) ) {
231- return defaultConfig ;
223+ return createDefaultConfig ( ) ;
232224 }
233225
234226 try {
235227 const text = readFileSync ( configPath , 'utf8' ) ;
236228 const raw = parseJsonc ( text ) ;
237229 return mergeConfig ( raw ) ;
238230 } catch {
239- return defaultConfig ;
231+ return createDefaultConfig ( ) ;
240232 }
241233} ;
242234
@@ -268,7 +260,7 @@ const initConfig = () => {
268260 return false ;
269261 }
270262
271- writeConfig ( defaultConfig ) ;
263+ writeConfig ( createDefaultConfig ( ) ) ;
272264 return true ;
273265} ;
274266
@@ -297,11 +289,12 @@ const migrateFromPreferences = (userDataPath, normalizeOpenAIModel) => {
297289
298290 try {
299291 const oldPrefs = JSON . parse ( readFileSync ( oldPath , 'utf8' ) ) ;
292+ const defaults = createDefaultConfig ( ) ;
300293 const config = mergeConfig ( {
301294 settings : {
302295 ...oldPrefs ,
303296 lastRepositoryPath : normalizeLastRepositoryPath ( oldPrefs ?. lastRepositoryPath ) ,
304- openAIModel : normalizeOpenAIModel ( oldPrefs ?. openAIModel ?? defaultSettings . openAIModel ) ,
297+ openAIModel : normalizeOpenAIModel ( oldPrefs ?. openAIModel ?? defaults . settings . openAIModel ) ,
305298 theme : normalizeTheme ( oldPrefs ?. theme ) ,
306299 } ,
307300 } ) ;
@@ -364,7 +357,7 @@ const configToPreferences = (config) => ({
364357
365358module . exports = {
366359 configToPreferences,
367- defaultConfig ,
360+ createDefaultConfig ,
368361 getConfigPath,
369362 initConfig,
370363 mergeConfig,
0 commit comments