hazo_config 1.3.0 → 1.4.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.
- package/.cursor/rules/general.mdc +26 -1
- package/.cursor/rules/package_development.mdc +34 -0
- package/LICENSE +21 -0
- package/dist/components/index.d.ts +5 -5
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/lib/config-loader.d.ts +10 -2
- package/dist/lib/config-loader.d.ts.map +1 -1
- package/dist/lib/config-loader.js +49 -2
- package/dist/lib/index.d.ts +4 -4
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +3 -3
- package/dist/lib/types.d.ts +12 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/components/index.ts +5 -5
- package/src/index.ts +3 -3
- package/src/lib/config-loader.ts +39 -2
- package/src/lib/index.ts +4 -4
- package/src/lib/types.ts +14 -0
- package/tsconfig.build.json +5 -1
|
@@ -48,4 +48,29 @@ alwaysApply: true
|
|
|
48
48
|
- When error messages are shown to the user, they should always be logged verbatem in the serverside log file as well
|
|
49
49
|
- pretty print the json output
|
|
50
50
|
- don't import the logger in the client side code
|
|
51
|
-
- whenever there's any actions on the database, or any API calls, please add details of the payload and update as well as the resulsts in the log file to help debug issues. For API calls, don't save any base64 data as it is too large.
|
|
51
|
+
- whenever there's any actions on the database, or any API calls, please add details of the payload and update as well as the resulsts in the log file to help debug issues. For API calls, don't save any base64 data as it is too large.
|
|
52
|
+
|
|
53
|
+
[For Packages ES Module Exports]
|
|
54
|
+
- When creating npm packages that will be consumed by ES module bundlers (Next.js, Vite, etc.), ALL export statements MUST use explicit file paths with .js extensions
|
|
55
|
+
- Directory imports like `export * from './components'` are INVALID in ES modules and will fail at runtime
|
|
56
|
+
- ALWAYS use explicit paths: `export * from './components/index.js'` instead of `export * from './components'`
|
|
57
|
+
- Even though source files are .ts, TypeScript requires .js extensions in import/export paths for ES module output
|
|
58
|
+
- This applies to all export statements in index.ts files and any barrel export files
|
|
59
|
+
|
|
60
|
+
[For packages: TypeScript Configuration]
|
|
61
|
+
- For package builds (tsconfig.build.json), set moduleResolution to "node16" or "node" (not "bundler") when shipping compiled output
|
|
62
|
+
- Ensure module is set to "ESNext" or "ES2020" for modern ES module output
|
|
63
|
+
- Add "type": "module" to package.json if shipping pure ESM packages
|
|
64
|
+
|
|
65
|
+
[For Packages: Export Path Rules]
|
|
66
|
+
- ✅ CORRECT: `export * from './lib/index.js'`
|
|
67
|
+
- ✅ CORRECT: `export * from './components/index.js'`
|
|
68
|
+
- ✅ CORRECT: `export { Something } from './utils.js'`
|
|
69
|
+
- ❌ WRONG: `export * from './lib'`
|
|
70
|
+
- ❌ WRONG: `export * from './components'`
|
|
71
|
+
- ❌ WRONG: `export { Something } from './utils'` (without extension)
|
|
72
|
+
|
|
73
|
+
[Verification]
|
|
74
|
+
- After building, check dist/index.js and ensure all export paths have .js extensions
|
|
75
|
+
- Test the built package in a consuming Next.js or ES module project to verify imports work
|
|
76
|
+
- If using TypeScript path aliases (@/...), ensure they are resolved to relative paths in the compiled output (not left as aliases)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Rules for package/library development to ensure ES module compatibility
|
|
3
|
+
globs:
|
|
4
|
+
- "src/**/*.ts"
|
|
5
|
+
- "src/**/*.tsx"
|
|
6
|
+
- "tsconfig*.json"
|
|
7
|
+
- "package.json"
|
|
8
|
+
alwaysApply: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
[Package Development - ES Module Exports]
|
|
12
|
+
- When creating npm packages that will be consumed by ES module bundlers (Next.js, Vite, etc.), ALL export statements MUST use explicit file paths with .js extensions
|
|
13
|
+
- Directory imports like `export * from './components'` are INVALID in ES modules and will fail at runtime
|
|
14
|
+
- ALWAYS use explicit paths: `export * from './components/index.js'` instead of `export * from './components'`
|
|
15
|
+
- Even though source files are .ts, TypeScript requires .js extensions in import/export paths for ES module output
|
|
16
|
+
- This applies to all export statements in index.ts files and any barrel export files
|
|
17
|
+
|
|
18
|
+
[TypeScript Configuration for Packages]
|
|
19
|
+
- For package builds (tsconfig.build.json), set moduleResolution to "node16" or "node" (not "bundler") when shipping compiled output
|
|
20
|
+
- Ensure module is set to "ESNext" or "ES2020" for modern ES module output
|
|
21
|
+
- Add "type": "module" to package.json if shipping pure ESM packages
|
|
22
|
+
|
|
23
|
+
[Export Path Rules]
|
|
24
|
+
- ✅ CORRECT: `export * from './lib/index.js'`
|
|
25
|
+
- ✅ CORRECT: `export * from './components/index.js'`
|
|
26
|
+
- ✅ CORRECT: `export { Something } from './utils.js'`
|
|
27
|
+
- ❌ WRONG: `export * from './lib'`
|
|
28
|
+
- ❌ WRONG: `export * from './components'`
|
|
29
|
+
- ❌ WRONG: `export { Something } from './utils'` (without extension)
|
|
30
|
+
|
|
31
|
+
[Verification]
|
|
32
|
+
- After building, check dist/index.js and ensure all export paths have .js extensions
|
|
33
|
+
- Test the built package in a consuming Next.js or ES module project to verify imports work
|
|
34
|
+
- If using TypeScript path aliases (@/...), ensure they are resolved to relative paths in the compiled output (not left as aliases)
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 pub12
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,6 +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';
|
|
1
|
+
export { ExampleComponent } from './example_component.js';
|
|
2
|
+
export { ConfigViewer } from './config_viewer.js';
|
|
3
|
+
export { ConfigEditor } from './config_editor.js';
|
|
4
|
+
export type { ConfigViewerProps } from './config_viewer.js';
|
|
5
|
+
export type { ConfigEditorProps } from './config_editor.js';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA"}
|
package/dist/components/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Component exports
|
|
2
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';
|
|
3
|
+
export { ExampleComponent } from './example_component.js';
|
|
4
|
+
export { ConfigViewer } from './config_viewer.js';
|
|
5
|
+
export { ConfigEditor } from './config_editor.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from './components';
|
|
2
|
-
export * from './lib/utils';
|
|
3
|
-
export * from './lib';
|
|
1
|
+
export * from './components/index.js';
|
|
2
|
+
export * from './lib/utils.js';
|
|
3
|
+
export * from './lib/index.js';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Main entry point for the component library
|
|
2
2
|
// Export all components and utilities from this file
|
|
3
|
-
export * from './components';
|
|
4
|
-
export * from './lib/utils';
|
|
5
|
-
export * from './lib';
|
|
3
|
+
export * from './components/index.js';
|
|
4
|
+
export * from './lib/utils.js';
|
|
5
|
+
export * from './lib/index.js';
|
|
@@ -11,18 +11,26 @@ import type { ConfigProvider, HazoConfigOptions } from './types';
|
|
|
11
11
|
* HazoConfig class
|
|
12
12
|
*
|
|
13
13
|
* Implements ConfigProvider interface for managing INI configuration files.
|
|
14
|
-
* Provides sync read/write operations with in-memory caching.
|
|
14
|
+
* Provides sync read/write operations with in-memory caching and automatic cache refresh.
|
|
15
15
|
*/
|
|
16
16
|
export declare class HazoConfig implements ConfigProvider {
|
|
17
17
|
private filePath;
|
|
18
18
|
private logger;
|
|
19
19
|
private config;
|
|
20
|
+
private cache_ttl_ms;
|
|
21
|
+
private disable_cache;
|
|
22
|
+
private last_cache_refresh;
|
|
20
23
|
/**
|
|
21
24
|
* Constructor
|
|
22
|
-
* @param options - Configuration options including filePath
|
|
25
|
+
* @param options - Configuration options including filePath, optional logger, cache settings
|
|
23
26
|
* @throws Error if file doesn't exist
|
|
24
27
|
*/
|
|
25
28
|
constructor(options: HazoConfigOptions);
|
|
29
|
+
/**
|
|
30
|
+
* Check if cache needs to be refreshed and refresh if needed
|
|
31
|
+
* This method is called before read operations to ensure cache is up to date
|
|
32
|
+
*/
|
|
33
|
+
private ensure_cache_fresh;
|
|
26
34
|
/**
|
|
27
35
|
* Get a configuration value by section and key
|
|
28
36
|
* @param section - The configuration section name
|
|
@@ -1 +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;
|
|
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;IAC3D,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,kBAAkB,CAAY;IAEtC;;;;OAIG;gBACS,OAAO,EAAE,iBAAiB;IAkBtC;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAsB1B;;;;;OAKG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAKrD;;;;OAIG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS;IAK/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;IA0Cf;;;OAGG;IACH,WAAW,IAAI,MAAM;IAIrB;;;OAGG;IACH,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CASzD"}
|
|
@@ -23,12 +23,12 @@ const no_op_logger = {
|
|
|
23
23
|
* HazoConfig class
|
|
24
24
|
*
|
|
25
25
|
* Implements ConfigProvider interface for managing INI configuration files.
|
|
26
|
-
* Provides sync read/write operations with in-memory caching.
|
|
26
|
+
* Provides sync read/write operations with in-memory caching and automatic cache refresh.
|
|
27
27
|
*/
|
|
28
28
|
export class HazoConfig {
|
|
29
29
|
/**
|
|
30
30
|
* Constructor
|
|
31
|
-
* @param options - Configuration options including filePath
|
|
31
|
+
* @param options - Configuration options including filePath, optional logger, cache settings
|
|
32
32
|
* @throws Error if file doesn't exist
|
|
33
33
|
*/
|
|
34
34
|
constructor(options) {
|
|
@@ -50,8 +50,28 @@ export class HazoConfig {
|
|
|
50
50
|
writable: true,
|
|
51
51
|
value: {}
|
|
52
52
|
});
|
|
53
|
+
Object.defineProperty(this, "cache_ttl_ms", {
|
|
54
|
+
enumerable: true,
|
|
55
|
+
configurable: true,
|
|
56
|
+
writable: true,
|
|
57
|
+
value: void 0
|
|
58
|
+
});
|
|
59
|
+
Object.defineProperty(this, "disable_cache", {
|
|
60
|
+
enumerable: true,
|
|
61
|
+
configurable: true,
|
|
62
|
+
writable: true,
|
|
63
|
+
value: void 0
|
|
64
|
+
});
|
|
65
|
+
Object.defineProperty(this, "last_cache_refresh", {
|
|
66
|
+
enumerable: true,
|
|
67
|
+
configurable: true,
|
|
68
|
+
writable: true,
|
|
69
|
+
value: 0
|
|
70
|
+
});
|
|
53
71
|
this.filePath = path.resolve(options.filePath);
|
|
54
72
|
this.logger = options.logger || no_op_logger;
|
|
73
|
+
this.cache_ttl_ms = options.cache_ttl_ms ?? 5000; // Default 5 seconds
|
|
74
|
+
this.disable_cache = options.disable_cache ?? false; // Default: caching enabled
|
|
55
75
|
// Validate file exists
|
|
56
76
|
if (!fs.existsSync(this.filePath)) {
|
|
57
77
|
const error = new Error(`Configuration file not found: ${this.filePath}`);
|
|
@@ -62,6 +82,28 @@ export class HazoConfig {
|
|
|
62
82
|
// Load initial configuration
|
|
63
83
|
this.refresh();
|
|
64
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Check if cache needs to be refreshed and refresh if needed
|
|
87
|
+
* This method is called before read operations to ensure cache is up to date
|
|
88
|
+
*/
|
|
89
|
+
ensure_cache_fresh() {
|
|
90
|
+
if (this.disable_cache) {
|
|
91
|
+
// If caching is disabled, always refresh from disk
|
|
92
|
+
this.refresh();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (this.cache_ttl_ms === 0) {
|
|
96
|
+
// If TTL is 0, cache never expires (only manual refresh)
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const now = Date.now();
|
|
100
|
+
const cache_age = now - this.last_cache_refresh;
|
|
101
|
+
if (cache_age >= this.cache_ttl_ms) {
|
|
102
|
+
// Cache has expired, refresh from disk
|
|
103
|
+
this.logger.debug(`[HazoConfig] Cache expired (age: ${cache_age}ms, ttl: ${this.cache_ttl_ms}ms), refreshing from disk`);
|
|
104
|
+
this.refresh();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
65
107
|
/**
|
|
66
108
|
* Get a configuration value by section and key
|
|
67
109
|
* @param section - The configuration section name
|
|
@@ -69,6 +111,7 @@ export class HazoConfig {
|
|
|
69
111
|
* @returns The configuration value, or undefined if not found
|
|
70
112
|
*/
|
|
71
113
|
get(section, key) {
|
|
114
|
+
this.ensure_cache_fresh();
|
|
72
115
|
return this.config[section]?.[key];
|
|
73
116
|
}
|
|
74
117
|
/**
|
|
@@ -77,6 +120,7 @@ export class HazoConfig {
|
|
|
77
120
|
* @returns A record of key-value pairs for the section, or undefined if section doesn't exist
|
|
78
121
|
*/
|
|
79
122
|
getSection(section) {
|
|
123
|
+
this.ensure_cache_fresh();
|
|
80
124
|
return this.config[section] ? { ...this.config[section] } : undefined;
|
|
81
125
|
}
|
|
82
126
|
/**
|
|
@@ -135,6 +179,8 @@ export class HazoConfig {
|
|
|
135
179
|
}
|
|
136
180
|
}
|
|
137
181
|
}
|
|
182
|
+
// Update cache timestamp
|
|
183
|
+
this.last_cache_refresh = Date.now();
|
|
138
184
|
this.logger.info(`[HazoConfig] Configuration refreshed from: ${this.filePath}`, {
|
|
139
185
|
sections: Object.keys(this.config)
|
|
140
186
|
});
|
|
@@ -167,6 +213,7 @@ export class HazoConfig {
|
|
|
167
213
|
* @returns A record of all sections and their key-value pairs
|
|
168
214
|
*/
|
|
169
215
|
getAllSections() {
|
|
216
|
+
this.ensure_cache_fresh();
|
|
170
217
|
// Return a deep copy to prevent external modification
|
|
171
218
|
const result = {};
|
|
172
219
|
for (const [section, values] of Object.entries(this.config)) {
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* configuration management utility. It serves as the primary entry point
|
|
6
6
|
* for consumers of the library.
|
|
7
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';
|
|
8
|
+
export { HazoConfig } from './config-loader.js';
|
|
9
|
+
export { MockConfigProvider } from './mock_config_provider.js';
|
|
10
|
+
export { ConfigErrorCode } from './types.js';
|
|
11
|
+
export type { ConfigProvider, HazoConfigOptions, Logger, HazoConfigError } from './types.js';
|
|
12
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,MAAM,EACN,eAAe,EAChB,MAAM,YAAY,CAAA"}
|
package/dist/lib/index.js
CHANGED
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
* configuration management utility. It serves as the primary entry point
|
|
6
6
|
* for consumers of the library.
|
|
7
7
|
*/
|
|
8
|
-
export { HazoConfig } from './config-loader';
|
|
9
|
-
export { MockConfigProvider } from './mock_config_provider';
|
|
10
|
-
export { ConfigErrorCode } from './types';
|
|
8
|
+
export { HazoConfig } from './config-loader.js';
|
|
9
|
+
export { MockConfigProvider } from './mock_config_provider.js';
|
|
10
|
+
export { ConfigErrorCode } from './types.js';
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -68,6 +68,18 @@ export interface HazoConfigOptions {
|
|
|
68
68
|
* Optional logger instance for logging operations
|
|
69
69
|
*/
|
|
70
70
|
logger?: Logger;
|
|
71
|
+
/**
|
|
72
|
+
* Cache time-to-live in milliseconds (default: 5000ms)
|
|
73
|
+
* When cache expires, configuration will be automatically refreshed from disk
|
|
74
|
+
* Set to 0 to disable automatic cache expiration (cache will only refresh on manual refresh() call)
|
|
75
|
+
*/
|
|
76
|
+
cache_ttl_ms?: number;
|
|
77
|
+
/**
|
|
78
|
+
* Disable caching entirely (default: false)
|
|
79
|
+
* When true, every get() and getSection() call will read from disk
|
|
80
|
+
* When false, values are cached in memory and refreshed based on cache_ttl_ms
|
|
81
|
+
*/
|
|
82
|
+
disable_cache?: boolean;
|
|
71
83
|
}
|
|
72
84
|
/**
|
|
73
85
|
* Error codes for configuration operations
|
package/dist/lib/types.d.ts.map
CHANGED
|
@@ -1 +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;
|
|
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;IAEf;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;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"}
|
package/package.json
CHANGED
package/src/components/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Component exports
|
|
2
2
|
// Export all components from this file for easy importing
|
|
3
3
|
|
|
4
|
-
export { ExampleComponent } from './example_component'
|
|
5
|
-
export { ConfigViewer } from './config_viewer'
|
|
6
|
-
export { ConfigEditor } from './config_editor'
|
|
7
|
-
export type { ConfigViewerProps } from './config_viewer'
|
|
8
|
-
export type { ConfigEditorProps } from './config_editor'
|
|
4
|
+
export { ExampleComponent } from './example_component.js'
|
|
5
|
+
export { ConfigViewer } from './config_viewer.js'
|
|
6
|
+
export { ConfigEditor } from './config_editor.js'
|
|
7
|
+
export type { ConfigViewerProps } from './config_viewer.js'
|
|
8
|
+
export type { ConfigEditorProps } from './config_editor.js'
|
|
9
9
|
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Main entry point for the component library
|
|
2
2
|
// Export all components and utilities from this file
|
|
3
3
|
|
|
4
|
-
export * from './components'
|
|
5
|
-
export * from './lib/utils'
|
|
6
|
-
export * from './lib'
|
|
4
|
+
export * from './components/index.js'
|
|
5
|
+
export * from './lib/utils.js'
|
|
6
|
+
export * from './lib/index.js'
|
|
7
7
|
|
package/src/lib/config-loader.ts
CHANGED
|
@@ -27,21 +27,26 @@ const no_op_logger: Logger = {
|
|
|
27
27
|
* HazoConfig class
|
|
28
28
|
*
|
|
29
29
|
* Implements ConfigProvider interface for managing INI configuration files.
|
|
30
|
-
* Provides sync read/write operations with in-memory caching.
|
|
30
|
+
* Provides sync read/write operations with in-memory caching and automatic cache refresh.
|
|
31
31
|
*/
|
|
32
32
|
export class HazoConfig implements ConfigProvider {
|
|
33
33
|
private filePath: string
|
|
34
34
|
private logger: Logger
|
|
35
35
|
private config: Record<string, Record<string, string>> = {}
|
|
36
|
+
private cache_ttl_ms: number
|
|
37
|
+
private disable_cache: boolean
|
|
38
|
+
private last_cache_refresh: number = 0
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
41
|
* Constructor
|
|
39
|
-
* @param options - Configuration options including filePath
|
|
42
|
+
* @param options - Configuration options including filePath, optional logger, cache settings
|
|
40
43
|
* @throws Error if file doesn't exist
|
|
41
44
|
*/
|
|
42
45
|
constructor(options: HazoConfigOptions) {
|
|
43
46
|
this.filePath = path.resolve(options.filePath)
|
|
44
47
|
this.logger = options.logger || no_op_logger
|
|
48
|
+
this.cache_ttl_ms = options.cache_ttl_ms ?? 5000 // Default 5 seconds
|
|
49
|
+
this.disable_cache = options.disable_cache ?? false // Default: caching enabled
|
|
45
50
|
|
|
46
51
|
// Validate file exists
|
|
47
52
|
if (!fs.existsSync(this.filePath)) {
|
|
@@ -55,6 +60,32 @@ export class HazoConfig implements ConfigProvider {
|
|
|
55
60
|
this.refresh()
|
|
56
61
|
}
|
|
57
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Check if cache needs to be refreshed and refresh if needed
|
|
65
|
+
* This method is called before read operations to ensure cache is up to date
|
|
66
|
+
*/
|
|
67
|
+
private ensure_cache_fresh(): void {
|
|
68
|
+
if (this.disable_cache) {
|
|
69
|
+
// If caching is disabled, always refresh from disk
|
|
70
|
+
this.refresh()
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (this.cache_ttl_ms === 0) {
|
|
75
|
+
// If TTL is 0, cache never expires (only manual refresh)
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const now = Date.now()
|
|
80
|
+
const cache_age = now - this.last_cache_refresh
|
|
81
|
+
|
|
82
|
+
if (cache_age >= this.cache_ttl_ms) {
|
|
83
|
+
// Cache has expired, refresh from disk
|
|
84
|
+
this.logger.debug(`[HazoConfig] Cache expired (age: ${cache_age}ms, ttl: ${this.cache_ttl_ms}ms), refreshing from disk`)
|
|
85
|
+
this.refresh()
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
58
89
|
/**
|
|
59
90
|
* Get a configuration value by section and key
|
|
60
91
|
* @param section - The configuration section name
|
|
@@ -62,6 +93,7 @@ export class HazoConfig implements ConfigProvider {
|
|
|
62
93
|
* @returns The configuration value, or undefined if not found
|
|
63
94
|
*/
|
|
64
95
|
get(section: string, key: string): string | undefined {
|
|
96
|
+
this.ensure_cache_fresh()
|
|
65
97
|
return this.config[section]?.[key]
|
|
66
98
|
}
|
|
67
99
|
|
|
@@ -71,6 +103,7 @@ export class HazoConfig implements ConfigProvider {
|
|
|
71
103
|
* @returns A record of key-value pairs for the section, or undefined if section doesn't exist
|
|
72
104
|
*/
|
|
73
105
|
getSection(section: string): Record<string, string> | undefined {
|
|
106
|
+
this.ensure_cache_fresh()
|
|
74
107
|
return this.config[section] ? { ...this.config[section] } : undefined
|
|
75
108
|
}
|
|
76
109
|
|
|
@@ -135,6 +168,9 @@ export class HazoConfig implements ConfigProvider {
|
|
|
135
168
|
}
|
|
136
169
|
}
|
|
137
170
|
|
|
171
|
+
// Update cache timestamp
|
|
172
|
+
this.last_cache_refresh = Date.now()
|
|
173
|
+
|
|
138
174
|
this.logger.info(`[HazoConfig] Configuration refreshed from: ${this.filePath}`, {
|
|
139
175
|
sections: Object.keys(this.config)
|
|
140
176
|
})
|
|
@@ -169,6 +205,7 @@ export class HazoConfig implements ConfigProvider {
|
|
|
169
205
|
* @returns A record of all sections and their key-value pairs
|
|
170
206
|
*/
|
|
171
207
|
getAllSections(): Record<string, Record<string, string>> {
|
|
208
|
+
this.ensure_cache_fresh()
|
|
172
209
|
// Return a deep copy to prevent external modification
|
|
173
210
|
const result: Record<string, Record<string, string>> = {}
|
|
174
211
|
for (const [section, values] of Object.entries(this.config)) {
|
package/src/lib/index.ts
CHANGED
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
* for consumers of the library.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
export { HazoConfig } from './config-loader'
|
|
10
|
-
export { MockConfigProvider } from './mock_config_provider'
|
|
11
|
-
export { ConfigErrorCode } from './types'
|
|
9
|
+
export { HazoConfig } from './config-loader.js'
|
|
10
|
+
export { MockConfigProvider } from './mock_config_provider.js'
|
|
11
|
+
export { ConfigErrorCode } from './types.js'
|
|
12
12
|
export type {
|
|
13
13
|
ConfigProvider,
|
|
14
14
|
HazoConfigOptions,
|
|
15
15
|
Logger,
|
|
16
16
|
HazoConfigError
|
|
17
|
-
} from './types'
|
|
17
|
+
} from './types.js'
|
|
18
18
|
|
package/src/lib/types.ts
CHANGED
|
@@ -76,6 +76,20 @@ export interface HazoConfigOptions {
|
|
|
76
76
|
* Optional logger instance for logging operations
|
|
77
77
|
*/
|
|
78
78
|
logger?: Logger
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Cache time-to-live in milliseconds (default: 5000ms)
|
|
82
|
+
* When cache expires, configuration will be automatically refreshed from disk
|
|
83
|
+
* Set to 0 to disable automatic cache expiration (cache will only refresh on manual refresh() call)
|
|
84
|
+
*/
|
|
85
|
+
cache_ttl_ms?: number
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Disable caching entirely (default: false)
|
|
89
|
+
* When true, every get() and getSection() call will read from disk
|
|
90
|
+
* When false, values are cached in memory and refreshed based on cache_ttl_ms
|
|
91
|
+
*/
|
|
92
|
+
disable_cache?: boolean
|
|
79
93
|
}
|
|
80
94
|
|
|
81
95
|
/**
|
package/tsconfig.build.json
CHANGED
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
"extends": "./tsconfig.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"noEmit": false,
|
|
5
|
+
"module": "ESNext",
|
|
5
6
|
"declaration": true,
|
|
6
7
|
"declarationMap": true,
|
|
7
8
|
"outDir": "./dist",
|
|
8
9
|
"rootDir": "./src",
|
|
9
|
-
"allowImportingTsExtensions": false
|
|
10
|
+
"allowImportingTsExtensions": false,
|
|
11
|
+
"moduleResolution": "node",
|
|
12
|
+
"allowSyntheticDefaultImports": true,
|
|
13
|
+
"esModuleInterop": true
|
|
10
14
|
},
|
|
11
15
|
"include": ["src"],
|
|
12
16
|
"exclude": ["**/*.stories.tsx", "**/*.test.tsx", "**/*.test.ts"]
|