hazo_config 1.0.0 → 1.2.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.
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ import type { ConfigProvider } from '@/lib/types';
3
+ /**
4
+ * Config editor component props
5
+ */
6
+ export interface ConfigEditorProps {
7
+ /**
8
+ * The config provider instance
9
+ */
10
+ config_provider: ConfigProvider;
11
+ /**
12
+ * Additional CSS classes
13
+ */
14
+ className?: string;
15
+ /**
16
+ * Callback when config is updated
17
+ */
18
+ on_update?: () => void;
19
+ }
20
+ /**
21
+ * Config editor component
22
+ * Provides interface for viewing and editing configuration with refresh and save capabilities
23
+ * @param props - Component props
24
+ * @returns React component
25
+ */
26
+ export declare const ConfigEditor: React.FC<ConfigEditorProps>;
27
+ //# sourceMappingURL=config_editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config_editor.d.ts","sourceRoot":"","sources":["../../src/components/config_editor.tsx"],"names":[],"mappings":"AAGA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAElD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAGjD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,eAAe,EAAE,cAAc,CAAA;IAC/B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAmLpD,CAAA"}
@@ -0,0 +1,81 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // Config editor component for managing configuration
3
+ // Provides a more advanced interface for editing configuration values
4
+ import { useState, useEffect } from 'react';
5
+ import { cn } from '@/lib/utils';
6
+ import { RefreshCw, Save } from 'lucide-react';
7
+ /**
8
+ * Config editor component
9
+ * Provides interface for viewing and editing configuration with refresh and save capabilities
10
+ * @param props - Component props
11
+ * @returns React component
12
+ */
13
+ export const ConfigEditor = ({ config_provider, className, on_update, }) => {
14
+ const [sections, set_sections] = useState({});
15
+ const [selected_section, set_selected_section] = useState(null);
16
+ const [new_key, set_new_key] = useState('');
17
+ const [new_value, set_new_value] = useState('');
18
+ /**
19
+ * Load configuration from provider
20
+ */
21
+ const load_config = () => {
22
+ const all_sections = {};
23
+ if ('getAllSections' in config_provider && typeof config_provider.getAllSections === 'function') {
24
+ const all = config_provider.getAllSections();
25
+ Object.assign(all_sections, all);
26
+ }
27
+ set_sections(all_sections);
28
+ if (!selected_section && Object.keys(all_sections).length > 0) {
29
+ set_selected_section(Object.keys(all_sections)[0]);
30
+ }
31
+ };
32
+ useEffect(() => {
33
+ load_config();
34
+ }, [config_provider]);
35
+ /**
36
+ * Handle refresh button click
37
+ */
38
+ const handle_refresh = () => {
39
+ config_provider.refresh();
40
+ load_config();
41
+ if (on_update) {
42
+ on_update();
43
+ }
44
+ };
45
+ /**
46
+ * Handle save button click
47
+ */
48
+ const handle_save = () => {
49
+ config_provider.save();
50
+ load_config();
51
+ if (on_update) {
52
+ on_update();
53
+ }
54
+ };
55
+ /**
56
+ * Add a new key-value pair to selected section
57
+ */
58
+ const handle_add_key = () => {
59
+ if (selected_section && new_key && new_value) {
60
+ config_provider.set(selected_section, new_key, new_value);
61
+ set_new_key('');
62
+ set_new_value('');
63
+ load_config();
64
+ if (on_update) {
65
+ on_update();
66
+ }
67
+ }
68
+ };
69
+ /**
70
+ * Update a config value
71
+ */
72
+ const handle_update_value = (section, key, value) => {
73
+ config_provider.set(section, key, value);
74
+ load_config();
75
+ };
76
+ const current_section_data = selected_section ? sections[selected_section] : null;
77
+ return (_jsxs("div", { className: cn('cls_config_editor space-y-4', className), children: [_jsxs("div", { className: "cls_config_editor_header flex items-center justify-between border-b pb-2", children: [_jsx("h2", { className: "text-xl font-semibold", children: "Configuration Editor" }), _jsxs("div", { className: "flex gap-2", children: [_jsxs("button", { onClick: handle_refresh, className: "px-3 py-1 border rounded hover:bg-muted flex items-center gap-2", "aria-label": "Refresh", children: [_jsx(RefreshCw, { size: 16 }), "Refresh"] }), _jsxs("button", { onClick: handle_save, className: "px-3 py-1 bg-primary text-primary-foreground rounded hover:bg-primary/90 flex items-center gap-2", "aria-label": "Save", children: [_jsx(Save, { size: 16 }), "Save"] })] })] }), _jsxs("div", { className: "cls_config_editor_content grid grid-cols-1 md:grid-cols-3 gap-4", children: [_jsxs("div", { className: "cls_config_sections_list border rounded p-4", children: [_jsx("h3", { className: "font-semibold mb-2", children: "Sections" }), _jsx("div", { className: "space-y-1", children: Object.keys(sections).map((section_name) => (_jsx("button", { onClick: () => set_selected_section(section_name), className: cn('w-full text-left px-2 py-1 rounded text-sm', selected_section === section_name
78
+ ? 'bg-primary text-primary-foreground'
79
+ : 'hover:bg-muted'), children: section_name }, section_name))) })] }), _jsx("div", { className: "cls_config_section_content md:col-span-2 border rounded p-4", children: selected_section ? (_jsxs(_Fragment, { children: [_jsx("h3", { className: "font-semibold mb-4", children: selected_section }), _jsxs("div", { className: "space-y-3", children: [current_section_data &&
80
+ Object.entries(current_section_data).map(([key, value]) => (_jsxs("div", { className: "cls_config_item", children: [_jsx("label", { className: "block text-sm font-medium mb-1", children: key }), _jsx("input", { type: "text", value: value, onChange: (e) => handle_update_value(selected_section, key, e.target.value), className: "w-full px-2 py-1 border rounded" })] }, key))), _jsxs("div", { className: "cls_add_new_key border-t pt-3 mt-3", children: [_jsx("h4", { className: "text-sm font-medium mb-2", children: "Add New Key" }), _jsxs("div", { className: "space-y-2", children: [_jsx("input", { type: "text", placeholder: "Key name", value: new_key, onChange: (e) => set_new_key(e.target.value), className: "w-full px-2 py-1 border rounded text-sm" }), _jsx("input", { type: "text", placeholder: "Value", value: new_value, onChange: (e) => set_new_value(e.target.value), className: "w-full px-2 py-1 border rounded text-sm" }), _jsx("button", { onClick: handle_add_key, className: "px-3 py-1 bg-primary text-primary-foreground rounded hover:bg-primary/90 text-sm", children: "Add Key" })] })] })] })] })) : (_jsx("div", { className: "text-center text-muted-foreground py-8", children: "Select a section to view/edit" })) })] })] }));
81
+ };
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ import type { ConfigProvider } from '@/lib/types';
3
+ /**
4
+ * Config viewer component props
5
+ */
6
+ export interface ConfigViewerProps {
7
+ /**
8
+ * The config provider instance
9
+ */
10
+ config_provider: ConfigProvider;
11
+ /**
12
+ * Additional CSS classes
13
+ */
14
+ className?: string;
15
+ /**
16
+ * Callback when config is updated
17
+ */
18
+ on_update?: () => void;
19
+ }
20
+ /**
21
+ * Config viewer component
22
+ * Displays configuration sections and allows viewing/editing values
23
+ * @param props - Component props
24
+ * @returns React component
25
+ */
26
+ export declare const ConfigViewer: React.FC<ConfigViewerProps>;
27
+ //# sourceMappingURL=config_viewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config_viewer.d.ts","sourceRoot":"","sources":["../../src/components/config_viewer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAElD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAGjD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,eAAe,EAAE,cAAc,CAAA;IAC/B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAwIpD,CAAA"}
@@ -0,0 +1,76 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Config viewer component for displaying configuration data
3
+ // Displays configuration sections and values in a readable format
4
+ import { useState, useEffect } from 'react';
5
+ import { cn } from '@/lib/utils';
6
+ import { Pencil, CheckCircle2, XCircle } from 'lucide-react';
7
+ /**
8
+ * Config viewer component
9
+ * Displays configuration sections and allows viewing/editing values
10
+ * @param props - Component props
11
+ * @returns React component
12
+ */
13
+ export const ConfigViewer = ({ config_provider, className, on_update, }) => {
14
+ const [sections, set_sections] = useState({});
15
+ const [editing, set_editing] = useState(null);
16
+ const [edit_value, set_edit_value] = useState('');
17
+ /**
18
+ * Load configuration from provider
19
+ */
20
+ const load_config = () => {
21
+ const all_sections = {};
22
+ // Try to get all sections - if provider has getAllSections, use it
23
+ if ('getAllSections' in config_provider && typeof config_provider.getAllSections === 'function') {
24
+ const all = config_provider.getAllSections();
25
+ Object.assign(all_sections, all);
26
+ }
27
+ else {
28
+ // Fallback: try common section names
29
+ const common_sections = ['database', 'logging', 'api', 'server', 'app'];
30
+ for (const section of common_sections) {
31
+ const section_data = config_provider.getSection(section);
32
+ if (section_data) {
33
+ all_sections[section] = section_data;
34
+ }
35
+ }
36
+ }
37
+ set_sections(all_sections);
38
+ };
39
+ useEffect(() => {
40
+ load_config();
41
+ }, [config_provider]);
42
+ /**
43
+ * Start editing a config value
44
+ */
45
+ const start_edit = (section, key) => {
46
+ const value = config_provider.get(section, key) || '';
47
+ set_editing({ section, key });
48
+ set_edit_value(value);
49
+ };
50
+ /**
51
+ * Cancel editing
52
+ */
53
+ const cancel_edit = () => {
54
+ set_editing(null);
55
+ set_edit_value('');
56
+ };
57
+ /**
58
+ * Save edited value
59
+ */
60
+ const save_edit = () => {
61
+ if (editing) {
62
+ config_provider.set(editing.section, editing.key, edit_value);
63
+ config_provider.save();
64
+ load_config();
65
+ set_editing(null);
66
+ set_edit_value('');
67
+ if (on_update) {
68
+ on_update();
69
+ }
70
+ }
71
+ };
72
+ return (_jsx("div", { className: cn('cls_config_viewer space-y-4', className), children: Object.keys(sections).length === 0 ? (_jsx("div", { className: "p-4 text-center text-muted-foreground", children: "No configuration sections found" })) : (Object.entries(sections).map(([section_name, section_data]) => (_jsxs("div", { className: "cls_config_section border rounded-lg p-4", children: [_jsx("h3", { className: "text-lg font-semibold mb-3", children: section_name }), _jsx("div", { className: "space-y-2", children: Object.entries(section_data).map(([key, value]) => {
73
+ const is_editing = editing?.section === section_name && editing?.key === key;
74
+ return (_jsx("div", { className: "cls_config_item flex items-center gap-2", children: _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "text-sm font-medium text-muted-foreground", children: key }), is_editing ? (_jsxs("div", { className: "flex items-center gap-2 mt-1", children: [_jsx("input", { type: "text", value: edit_value, onChange: (e) => set_edit_value(e.target.value), className: "flex-1 px-2 py-1 border rounded text-sm", autoFocus: true }), _jsx("button", { onClick: save_edit, className: "text-green-600 hover:text-green-700", "aria-label": "Save", children: _jsx(CheckCircle2, { size: 20 }) }), _jsx("button", { onClick: cancel_edit, className: "text-red-600 hover:text-red-700", "aria-label": "Cancel", children: _jsx(XCircle, { size: 20 }) })] })) : (_jsxs("div", { className: "flex items-center gap-2 mt-1", children: [_jsx("div", { className: "flex-1 px-2 py-1 bg-muted rounded text-sm", children: value || '(empty)' }), _jsx("button", { onClick: () => start_edit(section_name, key), className: "text-blue-600 hover:text-blue-700", "aria-label": "Edit", children: _jsx(Pencil, { size: 18 }) })] }))] }) }, key));
75
+ }) })] }, section_name)))) }));
76
+ };
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ /**
3
+ * Example component props interface
4
+ */
5
+ export interface ExampleComponentProps {
6
+ /**
7
+ * The title to display
8
+ */
9
+ title?: string;
10
+ /**
11
+ * Additional CSS classes
12
+ */
13
+ className?: string;
14
+ }
15
+ /**
16
+ * Example component for demonstrating the component library setup
17
+ * @param props - Component props
18
+ * @returns React component
19
+ */
20
+ export declare const ExampleComponent: React.FC<ExampleComponentProps>;
21
+ //# sourceMappingURL=example_component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example_component.d.ts","sourceRoot":"","sources":["../../src/components/example_component.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAY5D,CAAA"}
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '@/lib/utils';
3
+ /**
4
+ * Example component for demonstrating the component library setup
5
+ * @param props - Component props
6
+ * @returns React component
7
+ */
8
+ export const ExampleComponent = ({ title = 'Example Component', className, }) => {
9
+ return (_jsxs("div", { className: cn('cls_example_component p-4 border rounded-lg', className), children: [_jsx("h2", { className: "text-xl font-semibold", children: title }), _jsx("p", { className: "text-muted-foreground mt-2", children: "This is an example component for the config management library." })] }));
10
+ };
@@ -0,0 +1,6 @@
1
+ export { ExampleComponent } from './example_component';
2
+ export { ConfigViewer } from './config_viewer';
3
+ export { ConfigEditor } from './config_editor';
4
+ export type { ConfigViewerProps } from './config_viewer';
5
+ export type { ConfigEditorProps } from './config_editor';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACxD,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,5 @@
1
+ // Component exports
2
+ // Export all components from this file for easy importing
3
+ export { ExampleComponent } from './example_component';
4
+ export { ConfigViewer } from './config_viewer';
5
+ export { ConfigEditor } from './config_editor';
@@ -0,0 +1,4 @@
1
+ export * from './components';
2
+ export * from './lib/utils';
3
+ export * from './lib';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,OAAO,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ // Main entry point for the component library
2
+ // Export all components and utilities from this file
3
+ export * from './components';
4
+ export * from './lib/utils';
5
+ export * from './lib';
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Purpose: Main implementation of HazoConfig
3
+ *
4
+ * This file provides the HazoConfig class that implements the ConfigProvider
5
+ * interface. It handles reading and writing INI configuration files with
6
+ * in-memory caching, sync operations, and preservation of file formatting.
7
+ * Zero dependencies - only Node.js built-ins and the 'ini' package.
8
+ */
9
+ import type { ConfigProvider, HazoConfigOptions } from './types';
10
+ /**
11
+ * HazoConfig class
12
+ *
13
+ * Implements ConfigProvider interface for managing INI configuration files.
14
+ * Provides sync read/write operations with in-memory caching.
15
+ */
16
+ export declare class HazoConfig implements ConfigProvider {
17
+ private filePath;
18
+ private logger;
19
+ private config;
20
+ /**
21
+ * Constructor
22
+ * @param options - Configuration options including filePath and optional logger
23
+ * @throws Error if file doesn't exist
24
+ */
25
+ constructor(options: HazoConfigOptions);
26
+ /**
27
+ * Get a configuration value by section and key
28
+ * @param section - The configuration section name
29
+ * @param key - The configuration key name
30
+ * @returns The configuration value, or undefined if not found
31
+ */
32
+ get(section: string, key: string): string | undefined;
33
+ /**
34
+ * Get an entire configuration section
35
+ * @param section - The configuration section name
36
+ * @returns A record of key-value pairs for the section, or undefined if section doesn't exist
37
+ */
38
+ getSection(section: string): Record<string, string> | undefined;
39
+ /**
40
+ * Set a configuration value
41
+ * @param section - The configuration section name
42
+ * @param key - The configuration key name
43
+ * @param value - The value to set
44
+ */
45
+ set(section: string, key: string, value: string): void;
46
+ /**
47
+ * Save the current configuration to disk
48
+ * Writes all changes immediately to the configuration file
49
+ */
50
+ save(): void;
51
+ /**
52
+ * Refresh the configuration from disk
53
+ * Reloads the configuration file and updates the in-memory cache
54
+ */
55
+ refresh(): void;
56
+ /**
57
+ * Get the file path being managed
58
+ * @returns The resolved file path
59
+ */
60
+ getFilePath(): string;
61
+ /**
62
+ * Get all configuration sections
63
+ * @returns A record of all sections and their key-value pairs
64
+ */
65
+ getAllSections(): Record<string, Record<string, string>>;
66
+ }
67
+ //# sourceMappingURL=config-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/lib/config-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAU,MAAM,SAAS,CAAA;AAaxE;;;;;GAKG;AACH,qBAAa,UAAW,YAAW,cAAc;IAC/C,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,MAAM,CAA6C;IAE3D;;;;OAIG;gBACS,OAAO,EAAE,iBAAiB;IAgBtC;;;;;OAKG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIrD;;;;OAIG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS;IAI/D;;;;;OAKG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAQtD;;;OAGG;IACH,IAAI,IAAI,IAAI;IAqBZ;;;OAGG;IACH,OAAO,IAAI,IAAI;IAuCf;;;OAGG;IACH,WAAW,IAAI,MAAM;IAIrB;;;OAGG;IACH,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAQzD"}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Purpose: Main implementation of HazoConfig
3
+ *
4
+ * This file provides the HazoConfig class that implements the ConfigProvider
5
+ * interface. It handles reading and writing INI configuration files with
6
+ * in-memory caching, sync operations, and preservation of file formatting.
7
+ * Zero dependencies - only Node.js built-ins and the 'ini' package.
8
+ */
9
+ import fs from 'fs';
10
+ import path from 'path';
11
+ import ini from 'ini';
12
+ import { ConfigErrorCode as EC } from './types';
13
+ /**
14
+ * No-op logger implementation (default when no logger provided)
15
+ */
16
+ const no_op_logger = {
17
+ debug: () => { },
18
+ info: () => { },
19
+ warn: () => { },
20
+ error: () => { }
21
+ };
22
+ /**
23
+ * HazoConfig class
24
+ *
25
+ * Implements ConfigProvider interface for managing INI configuration files.
26
+ * Provides sync read/write operations with in-memory caching.
27
+ */
28
+ export class HazoConfig {
29
+ /**
30
+ * Constructor
31
+ * @param options - Configuration options including filePath and optional logger
32
+ * @throws Error if file doesn't exist
33
+ */
34
+ constructor(options) {
35
+ Object.defineProperty(this, "filePath", {
36
+ enumerable: true,
37
+ configurable: true,
38
+ writable: true,
39
+ value: void 0
40
+ });
41
+ Object.defineProperty(this, "logger", {
42
+ enumerable: true,
43
+ configurable: true,
44
+ writable: true,
45
+ value: void 0
46
+ });
47
+ Object.defineProperty(this, "config", {
48
+ enumerable: true,
49
+ configurable: true,
50
+ writable: true,
51
+ value: {}
52
+ });
53
+ this.filePath = path.resolve(options.filePath);
54
+ this.logger = options.logger || no_op_logger;
55
+ // Validate file exists
56
+ if (!fs.existsSync(this.filePath)) {
57
+ const error = new Error(`Configuration file not found: ${this.filePath}`);
58
+ error.code = EC.FILE_NOT_FOUND;
59
+ this.logger.error(`[HazoConfig] Configuration file not found: ${this.filePath}`);
60
+ throw error;
61
+ }
62
+ // Load initial configuration
63
+ this.refresh();
64
+ }
65
+ /**
66
+ * Get a configuration value by section and key
67
+ * @param section - The configuration section name
68
+ * @param key - The configuration key name
69
+ * @returns The configuration value, or undefined if not found
70
+ */
71
+ get(section, key) {
72
+ return this.config[section]?.[key];
73
+ }
74
+ /**
75
+ * Get an entire configuration section
76
+ * @param section - The configuration section name
77
+ * @returns A record of key-value pairs for the section, or undefined if section doesn't exist
78
+ */
79
+ getSection(section) {
80
+ return this.config[section] ? { ...this.config[section] } : undefined;
81
+ }
82
+ /**
83
+ * Set a configuration value
84
+ * @param section - The configuration section name
85
+ * @param key - The configuration key name
86
+ * @param value - The value to set
87
+ */
88
+ set(section, key, value) {
89
+ if (!this.config[section]) {
90
+ this.config[section] = {};
91
+ }
92
+ this.config[section][key] = value;
93
+ this.logger.info(`[HazoConfig] Set config value: ${section}.${key}`, { value });
94
+ }
95
+ /**
96
+ * Save the current configuration to disk
97
+ * Writes all changes immediately to the configuration file
98
+ */
99
+ save() {
100
+ try {
101
+ // Convert config object back to INI format
102
+ const iniContent = ini.stringify(this.config, {
103
+ section: '[',
104
+ whitespace: true
105
+ });
106
+ // Write to file
107
+ fs.writeFileSync(this.filePath, iniContent, 'utf-8');
108
+ this.logger.info(`[HazoConfig] Configuration saved to: ${this.filePath}`);
109
+ }
110
+ catch (error) {
111
+ const configError = new Error(`Failed to save configuration: ${error.message || String(error)}`);
112
+ configError.code = EC.WRITE_ERROR;
113
+ configError.originalError = error;
114
+ this.logger.error(`[HazoConfig] Failed to save configuration: ${this.filePath}`, { error: String(error) });
115
+ throw configError;
116
+ }
117
+ }
118
+ /**
119
+ * Refresh the configuration from disk
120
+ * Reloads the configuration file and updates the in-memory cache
121
+ */
122
+ refresh() {
123
+ try {
124
+ // Read file content
125
+ const content = fs.readFileSync(this.filePath, 'utf-8');
126
+ // Parse INI content
127
+ const parsed = ini.parse(content);
128
+ // Convert to our internal format (ensure all values are strings)
129
+ this.config = {};
130
+ for (const [section, values] of Object.entries(parsed)) {
131
+ if (typeof values === 'object' && values !== null) {
132
+ this.config[section] = {};
133
+ for (const [key, value] of Object.entries(values)) {
134
+ this.config[section][key] = String(value);
135
+ }
136
+ }
137
+ }
138
+ this.logger.info(`[HazoConfig] Configuration refreshed from: ${this.filePath}`, {
139
+ sections: Object.keys(this.config)
140
+ });
141
+ }
142
+ catch (error) {
143
+ // Handle file read errors
144
+ if (error.code === 'ENOENT') {
145
+ const configError = new Error(`Configuration file not found: ${this.filePath}`);
146
+ configError.code = EC.FILE_NOT_FOUND;
147
+ this.logger.error(`[HazoConfig] Configuration file not found: ${this.filePath}`);
148
+ throw configError;
149
+ }
150
+ // Handle parse errors
151
+ const configError = new Error(`Failed to parse configuration: ${error.message || String(error)}`);
152
+ configError.code = EC.PARSE_ERROR;
153
+ configError.originalError = error;
154
+ this.logger.error(`[HazoConfig] Failed to parse configuration: ${this.filePath}`, { error: String(error) });
155
+ throw configError;
156
+ }
157
+ }
158
+ /**
159
+ * Get the file path being managed
160
+ * @returns The resolved file path
161
+ */
162
+ getFilePath() {
163
+ return this.filePath;
164
+ }
165
+ /**
166
+ * Get all configuration sections
167
+ * @returns A record of all sections and their key-value pairs
168
+ */
169
+ getAllSections() {
170
+ // Return a deep copy to prevent external modification
171
+ const result = {};
172
+ for (const [section, values] of Object.entries(this.config)) {
173
+ result[section] = { ...values };
174
+ }
175
+ return result;
176
+ }
177
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Purpose: Main export for the HazoConfig library.
3
+ *
4
+ * This file re-exports all public interfaces and classes for the HazoConfig
5
+ * configuration management utility. It serves as the primary entry point
6
+ * for consumers of the library.
7
+ */
8
+ export { HazoConfig } from './config-loader';
9
+ export { MockConfigProvider } from './mock_config_provider';
10
+ export { ConfigErrorCode } from './types';
11
+ export type { ConfigProvider, HazoConfigOptions, Logger, HazoConfigError } from './types';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AACzC,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,MAAM,EACN,eAAe,EAChB,MAAM,SAAS,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Purpose: Main export for the HazoConfig library.
3
+ *
4
+ * This file re-exports all public interfaces and classes for the HazoConfig
5
+ * configuration management utility. It serves as the primary entry point
6
+ * for consumers of the library.
7
+ */
8
+ export { HazoConfig } from './config-loader';
9
+ export { MockConfigProvider } from './mock_config_provider';
10
+ export { ConfigErrorCode } from './types';
@@ -0,0 +1,52 @@
1
+ import type { ConfigProvider } from './types';
2
+ /**
3
+ * Mock config provider that stores configuration in memory
4
+ * Useful for testing and Storybook demonstrations where file system is not available
5
+ */
6
+ export declare class MockConfigProvider implements ConfigProvider {
7
+ private config;
8
+ /**
9
+ * Constructor
10
+ * @param initial_config - Optional initial configuration data
11
+ */
12
+ constructor(initial_config?: Record<string, Record<string, string>>);
13
+ /**
14
+ * Get a configuration value by section and key
15
+ * @param section - The configuration section name
16
+ * @param key - The configuration key name
17
+ * @returns The configuration value, or undefined if not found
18
+ */
19
+ get(section: string, key: string): string | undefined;
20
+ /**
21
+ * Get an entire configuration section
22
+ * @param section - The configuration section name
23
+ * @returns A record of key-value pairs for the section, or undefined if section doesn't exist
24
+ */
25
+ getSection(section: string): Record<string, string> | undefined;
26
+ /**
27
+ * Set a configuration value
28
+ * @param section - The configuration section name
29
+ * @param key - The configuration key name
30
+ * @param value - The value to set
31
+ */
32
+ set(section: string, key: string, value: string): void;
33
+ /**
34
+ * Save the current configuration (no-op for mock, but maintains interface compatibility)
35
+ */
36
+ save(): void;
37
+ /**
38
+ * Refresh the configuration (no-op for mock, but maintains interface compatibility)
39
+ */
40
+ refresh(): void;
41
+ /**
42
+ * Get all configuration sections
43
+ * @returns A record of all sections and their key-value pairs
44
+ */
45
+ getAllSections(): Record<string, Record<string, string>>;
46
+ /**
47
+ * Reset the configuration to initial state or empty
48
+ * @param new_config - Optional new configuration to set
49
+ */
50
+ reset(new_config?: Record<string, Record<string, string>>): void;
51
+ }
52
+ //# sourceMappingURL=mock_config_provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock_config_provider.d.ts","sourceRoot":"","sources":["../../src/lib/mock_config_provider.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,cAAc;IACvD,OAAO,CAAC,MAAM,CAA6C;IAE3D;;;OAGG;gBACS,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAMnE;;;;;OAKG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIrD;;;;OAIG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS;IAI/D;;;;;OAKG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAOtD;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,OAAO,IAAI,IAAI;IAIf;;;OAGG;IACH,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAQxD;;;OAGG;IACH,KAAK,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI;CAOjE"}
@@ -0,0 +1,87 @@
1
+ // Mock config provider for browser/Storybook testing
2
+ // Implements ConfigProvider interface using in-memory storage instead of file system
3
+ /**
4
+ * Mock config provider that stores configuration in memory
5
+ * Useful for testing and Storybook demonstrations where file system is not available
6
+ */
7
+ export class MockConfigProvider {
8
+ /**
9
+ * Constructor
10
+ * @param initial_config - Optional initial configuration data
11
+ */
12
+ constructor(initial_config) {
13
+ Object.defineProperty(this, "config", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: {}
18
+ });
19
+ if (initial_config) {
20
+ this.config = JSON.parse(JSON.stringify(initial_config)); // Deep copy
21
+ }
22
+ }
23
+ /**
24
+ * Get a configuration value by section and key
25
+ * @param section - The configuration section name
26
+ * @param key - The configuration key name
27
+ * @returns The configuration value, or undefined if not found
28
+ */
29
+ get(section, key) {
30
+ return this.config[section]?.[key];
31
+ }
32
+ /**
33
+ * Get an entire configuration section
34
+ * @param section - The configuration section name
35
+ * @returns A record of key-value pairs for the section, or undefined if section doesn't exist
36
+ */
37
+ getSection(section) {
38
+ return this.config[section] ? { ...this.config[section] } : undefined;
39
+ }
40
+ /**
41
+ * Set a configuration value
42
+ * @param section - The configuration section name
43
+ * @param key - The configuration key name
44
+ * @param value - The value to set
45
+ */
46
+ set(section, key, value) {
47
+ if (!this.config[section]) {
48
+ this.config[section] = {};
49
+ }
50
+ this.config[section][key] = value;
51
+ }
52
+ /**
53
+ * Save the current configuration (no-op for mock, but maintains interface compatibility)
54
+ */
55
+ save() {
56
+ // No-op for mock provider
57
+ }
58
+ /**
59
+ * Refresh the configuration (no-op for mock, but maintains interface compatibility)
60
+ */
61
+ refresh() {
62
+ // No-op for mock provider
63
+ }
64
+ /**
65
+ * Get all configuration sections
66
+ * @returns A record of all sections and their key-value pairs
67
+ */
68
+ getAllSections() {
69
+ const result = {};
70
+ for (const [section, values] of Object.entries(this.config)) {
71
+ result[section] = { ...values };
72
+ }
73
+ return result;
74
+ }
75
+ /**
76
+ * Reset the configuration to initial state or empty
77
+ * @param new_config - Optional new configuration to set
78
+ */
79
+ reset(new_config) {
80
+ if (new_config) {
81
+ this.config = JSON.parse(JSON.stringify(new_config));
82
+ }
83
+ else {
84
+ this.config = {};
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Purpose: Core interfaces and types for the HazoConfig component.
3
+ *
4
+ * This file defines the fundamental building blocks for creating a flexible and
5
+ * extensible configuration management utility. It includes interfaces for the
6
+ * ConfigProvider pattern, configuration options, and error types, ensuring
7
+ * loose coupling and reusability across different projects.
8
+ */
9
+ /**
10
+ * Logger interface for dependency injection
11
+ * Matches the Logger interface from hazo_connect for consistency
12
+ */
13
+ export interface Logger {
14
+ debug(message: string, data?: any): void;
15
+ info(message: string, data?: any): void;
16
+ warn(message: string, data?: any): void;
17
+ error(message: string, data?: any): void;
18
+ }
19
+ /**
20
+ * ConfigProvider interface
21
+ *
22
+ * Defines the contract for configuration providers that can be used
23
+ * by other components (like hazo_connect) to access configuration values.
24
+ * This allows for dependency injection and makes components testable.
25
+ */
26
+ export interface ConfigProvider {
27
+ /**
28
+ * Get a configuration value by section and key
29
+ * @param section - The configuration section name
30
+ * @param key - The configuration key name
31
+ * @returns The configuration value, or undefined if not found
32
+ */
33
+ get(section: string, key: string): string | undefined;
34
+ /**
35
+ * Get an entire configuration section
36
+ * @param section - The configuration section name
37
+ * @returns A record of key-value pairs for the section, or undefined if section doesn't exist
38
+ */
39
+ getSection(section: string): Record<string, string> | undefined;
40
+ /**
41
+ * Set a configuration value
42
+ * @param section - The configuration section name
43
+ * @param key - The configuration key name
44
+ * @param value - The value to set
45
+ */
46
+ set(section: string, key: string, value: string): void;
47
+ /**
48
+ * Save the current configuration to disk
49
+ * Writes all changes immediately to the configuration file
50
+ */
51
+ save(): void;
52
+ /**
53
+ * Refresh the configuration from disk
54
+ * Reloads the configuration file and updates the in-memory cache
55
+ */
56
+ refresh(): void;
57
+ }
58
+ /**
59
+ * Options for initializing HazoConfig
60
+ */
61
+ export interface HazoConfigOptions {
62
+ /**
63
+ * Path to the configuration file (required)
64
+ * Can be absolute or relative to process.cwd()
65
+ */
66
+ filePath: string;
67
+ /**
68
+ * Optional logger instance for logging operations
69
+ */
70
+ logger?: Logger;
71
+ }
72
+ /**
73
+ * Error codes for configuration operations
74
+ */
75
+ export declare enum ConfigErrorCode {
76
+ FILE_NOT_FOUND = "HAZO_CONFIG_FILE_NOT_FOUND",
77
+ READ_ERROR = "HAZO_CONFIG_READ_ERROR",
78
+ WRITE_ERROR = "HAZO_CONFIG_WRITE_ERROR",
79
+ PARSE_ERROR = "HAZO_CONFIG_PARSE_ERROR",
80
+ VALIDATION_ERROR = "HAZO_CONFIG_VALIDATION_ERROR"
81
+ }
82
+ /**
83
+ * Standardized error response for configuration operations
84
+ */
85
+ export interface HazoConfigError {
86
+ code: string;
87
+ message: string;
88
+ filePath?: string;
89
+ originalError?: any;
90
+ }
91
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAAA;IACxC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAAA;IACvC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAAA;IACvC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAAA;CACzC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IAErD;;;;OAIG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;IAE/D;;;;;OAKG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAEtD;;;OAGG;IACH,IAAI,IAAI,IAAI,CAAA;IAEZ;;;OAGG;IACH,OAAO,IAAI,IAAI,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,oBAAY,eAAe;IACzB,cAAc,+BAA+B;IAC7C,UAAU,2BAA2B;IACrC,WAAW,4BAA4B;IACvC,WAAW,4BAA4B;IACvC,gBAAgB,iCAAiC;CAClD;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,GAAG,CAAA;CACpB"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Purpose: Core interfaces and types for the HazoConfig component.
3
+ *
4
+ * This file defines the fundamental building blocks for creating a flexible and
5
+ * extensible configuration management utility. It includes interfaces for the
6
+ * ConfigProvider pattern, configuration options, and error types, ensuring
7
+ * loose coupling and reusability across different projects.
8
+ */
9
+ /**
10
+ * Error codes for configuration operations
11
+ */
12
+ export var ConfigErrorCode;
13
+ (function (ConfigErrorCode) {
14
+ ConfigErrorCode["FILE_NOT_FOUND"] = "HAZO_CONFIG_FILE_NOT_FOUND";
15
+ ConfigErrorCode["READ_ERROR"] = "HAZO_CONFIG_READ_ERROR";
16
+ ConfigErrorCode["WRITE_ERROR"] = "HAZO_CONFIG_WRITE_ERROR";
17
+ ConfigErrorCode["PARSE_ERROR"] = "HAZO_CONFIG_PARSE_ERROR";
18
+ ConfigErrorCode["VALIDATION_ERROR"] = "HAZO_CONFIG_VALIDATION_ERROR";
19
+ })(ConfigErrorCode || (ConfigErrorCode = {}));
@@ -0,0 +1,8 @@
1
+ import { type ClassValue } from "clsx";
2
+ /**
3
+ * Merges class names using clsx and tailwind-merge
4
+ * @param inputs - Class values to merge
5
+ * @returns Merged class string
6
+ */
7
+ export declare function cn(...inputs: ClassValue[]): string;
8
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAA;AAG5C;;;;GAIG;AACH,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
@@ -0,0 +1,12 @@
1
+ // Utility functions for the component library
2
+ // Provides class name merging functionality using clsx and tailwind-merge
3
+ import { clsx } from "clsx";
4
+ import { twMerge } from "tailwind-merge";
5
+ /**
6
+ * Merges class names using clsx and tailwind-merge
7
+ * @param inputs - Class values to merge
8
+ * @returns Merged class string
9
+ */
10
+ export function cn(...inputs) {
11
+ return twMerge(clsx(inputs));
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_config",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Config wrapper with error handling",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -37,7 +37,6 @@ export const ConfigEditor: React.FC<ConfigEditorProps> = ({
37
37
  }) => {
38
38
  const [sections, set_sections] = useState<Record<string, Record<string, string>>>({})
39
39
  const [selected_section, set_selected_section] = useState<string | null>(null)
40
- const [new_section_name, set_new_section_name] = useState<string>('')
41
40
  const [new_key, set_new_key] = useState<string>('')
42
41
  const [new_value, set_new_value] = useState<string>('')
43
42
 
@@ -16,7 +16,8 @@ import { ConfigErrorCode as EC } from './types'
16
16
  /**
17
17
  * No-op logger implementation (default when no logger provided)
18
18
  */
19
- const noOpLogger: Logger = {
19
+ const no_op_logger: Logger = {
20
+ debug: () => {},
20
21
  info: () => {},
21
22
  warn: () => {},
22
23
  error: () => {}
@@ -32,7 +33,6 @@ export class HazoConfig implements ConfigProvider {
32
33
  private filePath: string
33
34
  private logger: Logger
34
35
  private config: Record<string, Record<string, string>> = {}
35
- private originalContent: string = ''
36
36
 
37
37
  /**
38
38
  * Constructor
@@ -41,7 +41,7 @@ export class HazoConfig implements ConfigProvider {
41
41
  */
42
42
  constructor(options: HazoConfigOptions) {
43
43
  this.filePath = path.resolve(options.filePath)
44
- this.logger = options.logger || noOpLogger
44
+ this.logger = options.logger || no_op_logger
45
45
 
46
46
  // Validate file exists
47
47
  if (!fs.existsSync(this.filePath)) {
@@ -97,16 +97,12 @@ export class HazoConfig implements ConfigProvider {
97
97
  // Convert config object back to INI format
98
98
  const iniContent = ini.stringify(this.config, {
99
99
  section: '[',
100
- whitespace: true,
101
- newline: '\n'
100
+ whitespace: true
102
101
  })
103
102
 
104
103
  // Write to file
105
104
  fs.writeFileSync(this.filePath, iniContent, 'utf-8')
106
105
 
107
- // Update original content for future reference
108
- this.originalContent = iniContent
109
-
110
106
  this.logger.info(`[HazoConfig] Configuration saved to: ${this.filePath}`)
111
107
  } catch (error: any) {
112
108
  const configError: any = new Error(`Failed to save configuration: ${error.message || String(error)}`)
@@ -125,8 +121,6 @@ export class HazoConfig implements ConfigProvider {
125
121
  try {
126
122
  // Read file content
127
123
  const content = fs.readFileSync(this.filePath, 'utf-8')
128
- this.originalContent = content
129
-
130
124
  // Parse INI content
131
125
  const parsed = ini.parse(content)
132
126
 
package/src/lib/types.ts CHANGED
@@ -12,6 +12,7 @@
12
12
  * Matches the Logger interface from hazo_connect for consistency
13
13
  */
14
14
  export interface Logger {
15
+ debug(message: string, data?: any): void
15
16
  info(message: string, data?: any): void
16
17
  warn(message: string, data?: any): void
17
18
  error(message: string, data?: any): void
@@ -5,7 +5,8 @@
5
5
  "declaration": true,
6
6
  "declarationMap": true,
7
7
  "outDir": "./dist",
8
- "rootDir": "./src"
8
+ "rootDir": "./src",
9
+ "allowImportingTsExtensions": false
9
10
  },
10
11
  "include": ["src"],
11
12
  "exclude": ["**/*.stories.tsx", "**/*.test.tsx", "**/*.test.ts"]