@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/LICENSE +21 -0
- package/README.md +167 -0
- package/dist/magazine.cjs.js +5 -0
- package/dist/magazine.cjs.js.map +1 -0
- package/dist/magazine.es.js +4149 -0
- package/dist/magazine.es.js.map +1 -0
- package/dist/magazine.umd.js +5 -0
- package/dist/magazine.umd.js.map +1 -0
- package/package.json +74 -0
- package/src/components/ConfigManager.js +202 -0
- package/src/components/ConfigSchema.js +506 -0
- package/src/components/DataCompressor.js +378 -0
- package/src/components/DataTransformer.js +1172 -0
- package/src/components/DebugUtils.js +657 -0
- package/src/components/EventFilter.js +474 -0
- package/src/components/EventMetadata.js +273 -0
- package/src/components/EventStore.js +443 -0
- package/src/components/EventSyncer.js +353 -0
- package/src/components/Logger.js +299 -0
- package/src/components/NetworkManager.js +461 -0
- package/src/components/Paginator.js +343 -0
- package/src/index.js +571 -0
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
|
+
}
|