@@ -26,6 +26,69 @@ export interface Config {
2626 outputDir ?: string | undefined
2727 /** Export formats (csv,excel,json,map,pdf) */
2828 formats ?: string [ ] | undefined
29+
30+ // === Common export settings (apply to ALL formats) ===
31+ /** Filter ALL exports by categories */
32+ exportCategories ?: string [ ] | undefined
33+ /** Filter ALL exports by countries */
34+ exportCountries ?: string [ ] | undefined
35+ /** Filter ALL exports by sender names */
36+ exportFrom ?: string [ ] | undefined
37+ /** Filter ALL exports to on/after this date (YYYY-MM-DD) */
38+ exportStartDate ?: string | undefined
39+ /** Filter ALL exports to on/before this date (YYYY-MM-DD) */
40+ exportEndDate ?: string | undefined
41+ /** Min score threshold for ALL exports (0-3) */
42+ exportMinScore ?: number | undefined
43+ /** Only export activities with specific locations */
44+ exportOnlyLocations ?: boolean | undefined
45+ /** Only export generic activities without locations */
46+ exportOnlyGeneric ?: boolean | undefined
47+ /** Max activities in ALL exports (0 = all) */
48+ exportMaxActivities ?: number | undefined
49+ /** Sort order for ALL exports: score, oldest, newest */
50+ exportSort ?: string | undefined
51+
52+ // === PDF-specific settings (override export* for PDF only) ===
53+ /** Include thumbnails in PDF exports */
54+ pdfThumbnails ?: boolean | undefined
55+ /** Show score in PDF output */
56+ pdfIncludeScore ?: boolean | undefined
57+ /** Group by country in PDF (default: true) */
58+ pdfGroupByCountry ?: boolean | undefined
59+ /** Group by category in PDF (default: true) */
60+ pdfGroupByCategory ?: boolean | undefined
61+ /** PDF page size: A4 or Letter (default: based on home country) */
62+ pdfPageSize ?: string | undefined
63+ /** Custom PDF title */
64+ pdfTitle ?: string | undefined
65+ /** Custom PDF subtitle */
66+ pdfSubtitle ?: string | undefined
67+ /** Filter PDF by categories (overrides exportCategories) */
68+ pdfCategories ?: string [ ] | undefined
69+ /** Filter PDF by countries (overrides exportCountries) */
70+ pdfCountries ?: string [ ] | undefined
71+ /** Filter PDF by sender names (overrides exportFrom) */
72+ pdfFrom ?: string [ ] | undefined
73+ /** Filter PDF to on/after this date (overrides exportStartDate) */
74+ pdfStartDate ?: string | undefined
75+ /** Filter PDF to on/before this date (overrides exportEndDate) */
76+ pdfEndDate ?: string | undefined
77+ /** Min score for PDF (overrides exportMinScore) */
78+ pdfMinScore ?: number | undefined
79+ /** Only locations in PDF (overrides exportOnlyLocations) */
80+ pdfOnlyLocations ?: boolean | undefined
81+ /** Only generic in PDF (overrides exportOnlyGeneric) */
82+ pdfOnlyGeneric ?: boolean | undefined
83+ /** Max activities in PDF (overrides exportMaxActivities) */
84+ pdfMaxActivities ?: number | undefined
85+ /** Sort order for PDF (overrides exportSort) */
86+ pdfSort ?: string | undefined
87+
88+ // === Map-specific settings ===
89+ /** Default map tile style */
90+ mapDefaultStyle ?: string | undefined
91+
2992 /** When settings were last updated */
3093 updatedAt ?: string | undefined
3194}
@@ -34,20 +97,104 @@ export interface Config {
3497export type ConfigKey = keyof Omit < Config , 'updatedAt' >
3598
3699/** Config keys that accept string values */
37- const STRING_KEYS : ConfigKey [ ] = [ 'homeCountry' , 'timezone' , 'cacheDir' , 'outputDir' ]
100+ const STRING_KEYS : ConfigKey [ ] = [
101+ 'homeCountry' ,
102+ 'timezone' ,
103+ 'cacheDir' ,
104+ 'outputDir' ,
105+ // Common export
106+ 'exportStartDate' ,
107+ 'exportEndDate' ,
108+ 'exportSort' ,
109+ // PDF-specific
110+ 'pdfPageSize' ,
111+ 'pdfTitle' ,
112+ 'pdfSubtitle' ,
113+ 'pdfStartDate' ,
114+ 'pdfEndDate' ,
115+ 'pdfSort' ,
116+ // Map-specific
117+ 'mapDefaultStyle'
118+ ]
38119/** Config keys that accept boolean values */
39- const BOOLEAN_KEYS : ConfigKey [ ] = [ 'fetchImages' ]
120+ const BOOLEAN_KEYS : ConfigKey [ ] = [
121+ 'fetchImages' ,
122+ // Common export
123+ 'exportOnlyLocations' ,
124+ 'exportOnlyGeneric' ,
125+ // PDF-specific
126+ 'pdfThumbnails' ,
127+ 'pdfIncludeScore' ,
128+ 'pdfGroupByCountry' ,
129+ 'pdfGroupByCategory' ,
130+ 'pdfOnlyLocations' ,
131+ 'pdfOnlyGeneric'
132+ ]
133+ /** Config keys that accept number values */
134+ const NUMBER_KEYS : ConfigKey [ ] = [
135+ // Common export
136+ 'exportMinScore' ,
137+ 'exportMaxActivities' ,
138+ // PDF-specific
139+ 'pdfMinScore' ,
140+ 'pdfMaxActivities'
141+ ]
40142/** Config keys that accept array values */
41- const ARRAY_KEYS : ConfigKey [ ] = [ 'formats' ]
143+ const ARRAY_KEYS : ConfigKey [ ] = [
144+ 'formats' ,
145+ // Common export
146+ 'exportCategories' ,
147+ 'exportCountries' ,
148+ 'exportFrom' ,
149+ // PDF-specific
150+ 'pdfCategories' ,
151+ 'pdfCountries' ,
152+ 'pdfFrom'
153+ ]
42154
43155/** Descriptions for config keys (for help output) */
44156const CONFIG_DESCRIPTIONS : Record < ConfigKey , string > = {
45- homeCountry : 'Your home country for location context (default: detected from IP)' ,
46- timezone : 'Your timezone (e.g. Pacific/Auckland) (default: detected from system)' ,
47- fetchImages : 'Fetch images by default (default: false)' ,
157+ // General
48158 cacheDir : 'Cache directory path (default: ~/.cache/chat-to-map)' ,
159+ fetchImages : 'Fetch images by default (default: false)' ,
160+ formats : 'Export formats (default: csv,excel,json,map,pdf)' ,
161+ homeCountry : 'Your home country for location context (default: detected from IP)' ,
49162 outputDir : 'Output directory for exports (default: ./output)' ,
50- formats : 'Export formats (default: csv,excel,json,map,pdf)'
163+ timezone : 'Your timezone (e.g. Pacific/Auckland) (default: detected from system)' ,
164+
165+ // Common export settings
166+ exportCategories : 'Filter ALL exports by categories (comma-separated)' ,
167+ exportCountries : 'Filter ALL exports by countries (comma-separated)' ,
168+ exportFrom : 'Filter ALL exports by sender names (comma-separated)' ,
169+ exportStartDate : 'Filter ALL exports to on/after this date (YYYY-MM-DD)' ,
170+ exportEndDate : 'Filter ALL exports to on/before this date (YYYY-MM-DD)' ,
171+ exportMinScore : 'Min score for ALL exports (0-3)' ,
172+ exportOnlyLocations : 'Only export activities with specific locations' ,
173+ exportOnlyGeneric : 'Only export generic activities without locations' ,
174+ exportMaxActivities : 'Max activities in ALL exports, 0 for all (default: 0)' ,
175+ exportSort : 'Sort order for ALL exports: score, oldest, newest (default: score)' ,
176+
177+ // PDF-specific settings
178+ pdfThumbnails : 'Include thumbnails in PDF (default: false)' ,
179+ pdfIncludeScore : 'Show score in PDF output (default: false)' ,
180+ pdfGroupByCountry : 'Group by country in PDF (default: true)' ,
181+ pdfGroupByCategory : 'Group by category in PDF (default: true)' ,
182+ pdfPageSize : 'PDF page size: A4 or Letter (default: based on country)' ,
183+ pdfTitle : 'Custom PDF title' ,
184+ pdfSubtitle : 'Custom PDF subtitle' ,
185+ pdfCategories : 'Filter PDF by categories (overrides exportCategories)' ,
186+ pdfCountries : 'Filter PDF by countries (overrides exportCountries)' ,
187+ pdfFrom : 'Filter PDF by sender names (overrides exportFrom)' ,
188+ pdfStartDate : 'Filter PDF to on/after date (overrides exportStartDate)' ,
189+ pdfEndDate : 'Filter PDF to on/before date (overrides exportEndDate)' ,
190+ pdfMinScore : 'Min score for PDF (overrides exportMinScore)' ,
191+ pdfOnlyLocations : 'Only locations in PDF (overrides exportOnlyLocations)' ,
192+ pdfOnlyGeneric : 'Only generic in PDF (overrides exportOnlyGeneric)' ,
193+ pdfMaxActivities : 'Max activities in PDF (overrides exportMaxActivities)' ,
194+ pdfSort : 'Sort order for PDF (overrides exportSort)' ,
195+
196+ // Map-specific settings
197+ mapDefaultStyle : 'Default map tile style (e.g. osm, satellite, terrain)'
51198}
52199
53200/**
@@ -56,6 +203,7 @@ const CONFIG_DESCRIPTIONS: Record<ConfigKey, string> = {
56203 */
57204export function getConfigType ( key : ConfigKey ) : string {
58205 if ( BOOLEAN_KEYS . includes ( key ) ) return 'boolean'
206+ if ( NUMBER_KEYS . includes ( key ) ) return 'number'
59207 if ( ARRAY_KEYS . includes ( key ) ) return 'comma-separated'
60208 return 'string'
61209}
@@ -123,10 +271,16 @@ export async function saveConfig(config: Config, configFile?: string): Promise<v
123271/**
124272 * Parse a string value into the appropriate type for a config key.
125273 */
126- export function parseConfigValue ( key : ConfigKey , value : string ) : string | boolean | string [ ] {
274+ export function parseConfigValue (
275+ key : ConfigKey ,
276+ value : string
277+ ) : string | boolean | number | string [ ] {
127278 if ( BOOLEAN_KEYS . includes ( key ) ) {
128279 return value === 'true' || value === '1' || value === 'yes'
129280 }
281+ if ( NUMBER_KEYS . includes ( key ) ) {
282+ return Number . parseInt ( value , 10 )
283+ }
130284 if ( ARRAY_KEYS . includes ( key ) ) {
131285 return value . split ( ',' ) . map ( ( v ) => v . trim ( ) )
132286 }
@@ -153,23 +307,24 @@ export function isValidConfigKey(key: string): key is ConfigKey {
153307 return (
154308 STRING_KEYS . includes ( key as ConfigKey ) ||
155309 BOOLEAN_KEYS . includes ( key as ConfigKey ) ||
310+ NUMBER_KEYS . includes ( key as ConfigKey ) ||
156311 ARRAY_KEYS . includes ( key as ConfigKey )
157312 )
158313}
159314
160315/**
161- * Get all valid config keys.
316+ * Get all valid config keys (sorted alphabetically) .
162317 */
163318export function getValidConfigKeys ( ) : ConfigKey [ ] {
164- return [ ...STRING_KEYS , ...BOOLEAN_KEYS , ...ARRAY_KEYS ]
319+ return [ ...STRING_KEYS , ...BOOLEAN_KEYS , ...NUMBER_KEYS , ... ARRAY_KEYS ] . sort ( )
165320}
166321
167322/**
168323 * Set a single config value and save.
169324 */
170325export async function setConfigValue (
171326 key : ConfigKey ,
172- value : string | boolean | string [ ] ,
327+ value : string | boolean | number | string [ ] ,
173328 configFile ?: string
174329) : Promise < void > {
175330 const config = ( await loadConfig ( configFile ) ) ?? { }
0 commit comments