@sschepis/magazine 0.1.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/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@sschepis/magazine",
3
+ "version": "0.1.0",
4
+ "description": "A decentralized library for Ethereum event logging, syncing, and querying using ethers.js and GunDB",
5
+ "type": "module",
6
+ "main": "./dist/magazine.umd.js",
7
+ "module": "./dist/magazine.es.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/magazine.es.js",
12
+ "require": "./dist/magazine.cjs.js",
13
+ "default": "./dist/magazine.umd.js",
14
+ "types": "./dist/index.d.ts"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "src",
20
+ "README.md",
21
+ "LICENSE"
22
+ ],
23
+ "keywords": [
24
+ "ethereum",
25
+ "events",
26
+ "blockchain",
27
+ "indexer",
28
+ "gun",
29
+ "gundb",
30
+ "decentralized",
31
+ "ethers",
32
+ "web3",
33
+ "event-log",
34
+ "smart-contract"
35
+ ],
36
+ "author": "Sebastian Schepis",
37
+ "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/sschepis/magazine.git"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/sschepis/magazine/issues"
44
+ },
45
+ "homepage": "https://github.com/sschepis/magazine#readme",
46
+ "engines": {
47
+ "node": ">=20.0.0"
48
+ },
49
+ "scripts": {
50
+ "dev": "vite",
51
+ "build": "vite build",
52
+ "preview": "vite preview",
53
+ "test": "kill $(lsof -t -i:8545) &> /dev/null; npx hardhat node & (sleep 5 && npx hardhat test && kill $!)",
54
+ "test:unit": "npx mocha test/unit.test.cjs --timeout 10000",
55
+ "prepublishOnly": "npm run build"
56
+ },
57
+ "devDependencies": {
58
+ "@nomicfoundation/hardhat-chai-matchers": "^2.1.0",
59
+ "@nomicfoundation/hardhat-ethers": "^3.1.0",
60
+ "@nomicfoundation/hardhat-network-helpers": "^1.1.0",
61
+ "@nomicfoundation/hardhat-toolbox": "^6.1.0",
62
+ "chai": "^4.3.7",
63
+ "chai-as-promised": "^8.0.1",
64
+ "hardhat": "^2.26.1",
65
+ "mocha": "^10.2.0",
66
+ "sinon": "^21.0.0",
67
+ "vite": "^4.1.0"
68
+ },
69
+ "dependencies": {
70
+ "ethers": "^6.0.8",
71
+ "gun": "^0.2020.1239",
72
+ "pako": "^2.1.0"
73
+ }
74
+ }
@@ -0,0 +1,202 @@
1
+ import Logger from './Logger.js';
2
+ import ConfigSchema from './ConfigSchema.js';
3
+
4
+ /**
5
+ * ConfigManager - Handles configuration validation and management using ConfigSchema
6
+ *
7
+ * @class ConfigManager
8
+ * @description Provides comprehensive configuration validation, management, and documentation
9
+ * using a formal schema-based approach for better error handling and developer experience.
10
+ */
11
+ export default class ConfigManager {
12
+ /**
13
+ * Create a ConfigManager instance
14
+ * @param {Object} config - Configuration object to validate and manage
15
+ * @throws {Error} If configuration validation fails
16
+ */
17
+ constructor(config) {
18
+ this.schema = new ConfigSchema();
19
+
20
+ // Initialize logger with basic config for validation logging
21
+ this.logger = new Logger({
22
+ context: 'ConfigManager',
23
+ level: config?.logLevel || 'info'
24
+ });
25
+
26
+ this.logger.debug('Initializing ConfigManager with schema validation', {
27
+ config: this._sanitizeConfig(config)
28
+ });
29
+
30
+ // Validate and process configuration using schema
31
+ const validationResult = this.validateConfig(config);
32
+
33
+ if (!validationResult.valid) {
34
+ const errorMessage = this._formatValidationErrors(validationResult.errors);
35
+ this.logger.error('Configuration validation failed', {
36
+ errors: validationResult.errors,
37
+ warnings: validationResult.warnings
38
+ });
39
+ throw new Error(`Configuration validation failed:\n${errorMessage}`);
40
+ }
41
+
42
+ // Log validation warnings if any
43
+ if (validationResult.warnings.length > 0) {
44
+ this.logger.warn('Configuration validation warnings', {
45
+ warnings: validationResult.warnings
46
+ });
47
+ }
48
+
49
+ // Use validated configuration
50
+ this.config = validationResult.validated;
51
+
52
+ this.logger.info('ConfigManager initialized successfully', {
53
+ name: this.config.name,
54
+ address: this.config.address,
55
+ networkId: this.config.networkId,
56
+ maxRetries: this.config.maxRetries,
57
+ retryDelay: this.config.retryDelay,
58
+ timeout: this.config.timeout,
59
+ warningsCount: validationResult.warnings.length
60
+ });
61
+ }
62
+
63
+ /**
64
+ * Sanitize config for logging (remove sensitive data)
65
+ * @private
66
+ * @param {Object} config - Configuration object to sanitize
67
+ * @returns {Object} Sanitized configuration object
68
+ */
69
+ _sanitizeConfig(config) {
70
+ if (!config) return config;
71
+ const sanitized = { ...config };
72
+ // Remove potentially sensitive information
73
+ if (sanitized.gun) {
74
+ sanitized.gun = { ...sanitized.gun };
75
+ delete sanitized.gun.peers; // May contain sensitive URLs
76
+ }
77
+ return sanitized;
78
+ }
79
+
80
+ /**
81
+ * Validate configuration using ConfigSchema
82
+ * @param {Object} config - Configuration object to validate
83
+ * @returns {Object} Validation result with validated config
84
+ */
85
+ validateConfig(config) {
86
+ if (!config || typeof config !== 'object') {
87
+ return {
88
+ valid: false,
89
+ errors: [{
90
+ field: 'config',
91
+ type: 'required',
92
+ message: 'Configuration must be a non-null object'
93
+ }],
94
+ warnings: [],
95
+ validated: {}
96
+ };
97
+ }
98
+
99
+ return this.schema.validate(config);
100
+ }
101
+
102
+ /**
103
+ * Format validation errors into a readable string
104
+ * @private
105
+ * @param {Array} errors - Array of validation errors
106
+ * @returns {string} Formatted error message
107
+ */
108
+ _formatValidationErrors(errors) {
109
+ return errors.map(error => ` - ${error.field}: ${error.message}`).join('\n');
110
+ }
111
+
112
+ /**
113
+ * Get schema documentation
114
+ * @returns {Object} Schema documentation object
115
+ */
116
+ getSchemaDocumentation() {
117
+ return this.schema.getDocumentation();
118
+ }
119
+
120
+ /**
121
+ * Generate example configuration
122
+ * @param {Object} options - Generation options
123
+ * @returns {Object} Example configuration object
124
+ */
125
+ generateExampleConfig(options = {}) {
126
+ return this.schema.generateExample(options);
127
+ }
128
+
129
+ /**
130
+ * Validate a configuration object without creating an instance
131
+ * @static
132
+ * @param {Object} config - Configuration to validate
133
+ * @returns {Object} Validation result
134
+ */
135
+ static validateConfiguration(config) {
136
+ const schema = new ConfigSchema();
137
+ return schema.validate(config);
138
+ }
139
+
140
+ /**
141
+ * Validate block number parameters
142
+ * @param {number} blockNumber - Block number to validate
143
+ * @param {string} paramName - Parameter name for error messages
144
+ * @throws {Error} If block number is invalid
145
+ */
146
+ validateBlockNumber(blockNumber, paramName = 'blockNumber') {
147
+ if (!Number.isInteger(blockNumber) || blockNumber < 0) {
148
+ throw new Error(`${paramName} must be a non-negative integer`);
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Validate options object for API methods
154
+ * @param {Object} options - Options object to validate
155
+ * @param {Array} allowedKeys - Array of allowed option keys
156
+ * @returns {Object} Validated options object
157
+ * @throws {Error} If options are invalid
158
+ */
159
+ validateOptions(options, allowedKeys = []) {
160
+ if (options !== undefined && (typeof options !== 'object' || options === null)) {
161
+ throw new Error('Options must be an object');
162
+ }
163
+
164
+ if (options && allowedKeys.length > 0) {
165
+ const invalidKeys = Object.keys(options).filter(key => !allowedKeys.includes(key));
166
+ if (invalidKeys.length > 0) {
167
+ throw new Error(`Invalid option keys: ${invalidKeys.join(', ')}. Allowed: ${allowedKeys.join(', ')}`);
168
+ }
169
+ }
170
+
171
+ return options || {};
172
+ }
173
+
174
+ /**
175
+ * Get configuration value by key
176
+ * @param {string} key - Configuration key
177
+ * @returns {*} Configuration value
178
+ */
179
+ get(key) {
180
+ return this.config[key];
181
+ }
182
+
183
+ /**
184
+ * Get all configuration
185
+ * @returns {Object} Complete configuration object
186
+ */
187
+ getAll() {
188
+ return { ...this.config };
189
+ }
190
+
191
+ /**
192
+ * Get retry options for network operations
193
+ * @returns {Object} Retry configuration object
194
+ */
195
+ getRetryOptions() {
196
+ return {
197
+ maxRetries: this.config.maxRetries,
198
+ retryDelay: this.config.retryDelay,
199
+ timeout: this.config.timeout
200
+ };
201
+ }
202
+ }