@reclaimprotocol/attestor-core 4.0.2 → 4.0.3

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,24 @@
1
+ /**
2
+ * Atomic operations utility for preventing race conditions.
3
+ * Provides mutex-like locks using Promise-based mutual exclusion.
4
+ */
5
+ export declare class AtomicOperations {
6
+ private static locks;
7
+ /**
8
+ * Execute a function with a named lock to prevent concurrent execution.
9
+ * @param lockName Unique identifier for the lock
10
+ * @param fn Function to execute atomically
11
+ * @returns Promise that resolves with the function's return value
12
+ */
13
+ static withLock<T>(lockName: string, fn: () => Promise<T>): Promise<T>;
14
+ /**
15
+ * Check if a lock is currently held.
16
+ * @param lockName Name of the lock to check
17
+ * @returns True if the lock is currently held
18
+ */
19
+ static isLocked(lockName: string): boolean;
20
+ /**
21
+ * Clear all locks (for testing/cleanup).
22
+ */
23
+ static clearAllLocks(): void;
24
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ /**
3
+ * Atomic operations utility for preventing race conditions.
4
+ * Provides mutex-like locks using Promise-based mutual exclusion.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.AtomicOperations = void 0;
8
+ class AtomicOperations {
9
+ /**
10
+ * Execute a function with a named lock to prevent concurrent execution.
11
+ * @param lockName Unique identifier for the lock
12
+ * @param fn Function to execute atomically
13
+ * @returns Promise that resolves with the function's return value
14
+ */
15
+ static async withLock(lockName, fn) {
16
+ // Wait for any existing lock to complete
17
+ const existingLock = this.locks.get(lockName);
18
+ if (existingLock) {
19
+ await existingLock.catch(() => {
20
+ // Ignore errors from previous lock holders
21
+ });
22
+ }
23
+ // Create a new lock
24
+ let resolve;
25
+ let reject;
26
+ const lockPromise = new Promise((res, rej) => {
27
+ resolve = res;
28
+ reject = rej;
29
+ });
30
+ this.locks.set(lockName, lockPromise);
31
+ try {
32
+ // Execute the function
33
+ const result = await fn();
34
+ resolve();
35
+ return result;
36
+ }
37
+ catch (error) {
38
+ reject(error);
39
+ throw error;
40
+ }
41
+ finally {
42
+ // Clean up the lock if we're still the current holder
43
+ if (this.locks.get(lockName) === lockPromise) {
44
+ this.locks.delete(lockName);
45
+ }
46
+ }
47
+ }
48
+ /**
49
+ * Check if a lock is currently held.
50
+ * @param lockName Name of the lock to check
51
+ * @returns True if the lock is currently held
52
+ */
53
+ static isLocked(lockName) {
54
+ return this.locks.has(lockName);
55
+ }
56
+ /**
57
+ * Clear all locks (for testing/cleanup).
58
+ */
59
+ static clearAllLocks() {
60
+ this.locks.clear();
61
+ }
62
+ }
63
+ exports.AtomicOperations = AtomicOperations;
64
+ AtomicOperations.locks = new Map();
65
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRvbWljLW9wZXJhdGlvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvYXRvbWljLW9wZXJhdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7O0FBRUgsTUFBYSxnQkFBZ0I7SUFHNUI7Ozs7O09BS0c7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBSSxRQUFnQixFQUFFLEVBQW9CO1FBQzlELHlDQUF5QztRQUN6QyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUM3QyxJQUFJLFlBQVksRUFBRSxDQUFDO1lBQ2xCLE1BQU0sWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUU7Z0JBQzdCLDJDQUEyQztZQUM1QyxDQUFDLENBQUMsQ0FBQTtRQUNILENBQUM7UUFFRCxvQkFBb0I7UUFDcEIsSUFBSSxPQUFtQixDQUFBO1FBQ3ZCLElBQUksTUFBNEIsQ0FBQTtRQUNoQyxNQUFNLFdBQVcsR0FBRyxJQUFJLE9BQU8sQ0FBTyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRTtZQUNsRCxPQUFPLEdBQUcsR0FBRyxDQUFBO1lBQ2IsTUFBTSxHQUFHLEdBQUcsQ0FBQTtRQUNiLENBQUMsQ0FBQyxDQUFBO1FBRUYsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLFdBQVcsQ0FBQyxDQUFBO1FBRXJDLElBQUksQ0FBQztZQUNKLHVCQUF1QjtZQUN2QixNQUFNLE1BQU0sR0FBRyxNQUFNLEVBQUUsRUFBRSxDQUFBO1lBQ3pCLE9BQVEsRUFBRSxDQUFBO1lBQ1YsT0FBTyxNQUFNLENBQUE7UUFDZCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNoQixNQUFPLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDZCxNQUFNLEtBQUssQ0FBQTtRQUNaLENBQUM7Z0JBQVMsQ0FBQztZQUNWLHNEQUFzRDtZQUN0RCxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxLQUFLLFdBQVcsRUFBRSxDQUFDO2dCQUM5QyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQTtZQUM1QixDQUFDO1FBQ0YsQ0FBQztJQUNGLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFnQjtRQUMvQixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBQ2hDLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxhQUFhO1FBQ25CLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUE7SUFDbkIsQ0FBQzs7QUExREYsNENBMkRDO0FBMURlLHNCQUFLLEdBQUcsSUFBSSxHQUFHLEVBQXlCLENBQUEifQ==
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Connection state machine for managing atomic state transitions.
3
+ * Prevents race conditions in connection state management.
4
+ */
5
+ export declare enum ConnectionState {
6
+ CONNECTING = "connecting",
7
+ CONNECTED = "connected",
8
+ CLOSING = "closing",
9
+ CLOSED = "closed"
10
+ }
11
+ type StateChangeListener = (oldState: ConnectionState, newState: ConnectionState) => void;
12
+ export declare class ConnectionStateMachine {
13
+ private currentState;
14
+ private listeners;
15
+ private transitionLock;
16
+ constructor(initialState?: ConnectionState);
17
+ /**
18
+ * Get current state.
19
+ */
20
+ getState(): ConnectionState;
21
+ /**
22
+ * Check if the connection is in any of the specified states.
23
+ */
24
+ isInState(...states: ConnectionState[]): boolean;
25
+ /**
26
+ * Register a state change listener.
27
+ */
28
+ onStateChange(listener: StateChangeListener): () => void;
29
+ /**
30
+ * Attempt to transition from allowed states to a new state.
31
+ * @param fromStates Allowed states to transition from
32
+ * @param toState Target state
33
+ * @param action Optional action to execute during transition
34
+ * @returns Promise that resolves to true if transition succeeded
35
+ */
36
+ transition(fromStates: ConnectionState | ConnectionState[], toState: ConnectionState, action?: () => Promise<void>): Promise<boolean>;
37
+ /**
38
+ * Force a state change without checking allowed transitions.
39
+ * Use with caution - mainly for error recovery.
40
+ */
41
+ forceState(newState: ConnectionState): Promise<void>;
42
+ }
43
+ export {};
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ /**
3
+ * Connection state machine for managing atomic state transitions.
4
+ * Prevents race conditions in connection state management.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ConnectionStateMachine = exports.ConnectionState = void 0;
8
+ var ConnectionState;
9
+ (function (ConnectionState) {
10
+ ConnectionState["CONNECTING"] = "connecting";
11
+ ConnectionState["CONNECTED"] = "connected";
12
+ ConnectionState["CLOSING"] = "closing";
13
+ ConnectionState["CLOSED"] = "closed";
14
+ })(ConnectionState || (exports.ConnectionState = ConnectionState = {}));
15
+ class ConnectionStateMachine {
16
+ constructor(initialState = ConnectionState.CONNECTING) {
17
+ this.listeners = [];
18
+ this.transitionLock = null;
19
+ this.currentState = initialState;
20
+ }
21
+ /**
22
+ * Get current state.
23
+ */
24
+ getState() {
25
+ return this.currentState;
26
+ }
27
+ /**
28
+ * Check if the connection is in any of the specified states.
29
+ */
30
+ isInState(...states) {
31
+ return states.includes(this.currentState);
32
+ }
33
+ /**
34
+ * Register a state change listener.
35
+ */
36
+ onStateChange(listener) {
37
+ this.listeners.push(listener);
38
+ return () => {
39
+ const index = this.listeners.indexOf(listener);
40
+ if (index >= 0) {
41
+ this.listeners.splice(index, 1);
42
+ }
43
+ };
44
+ }
45
+ /**
46
+ * Attempt to transition from allowed states to a new state.
47
+ * @param fromStates Allowed states to transition from
48
+ * @param toState Target state
49
+ * @param action Optional action to execute during transition
50
+ * @returns Promise that resolves to true if transition succeeded
51
+ */
52
+ async transition(fromStates, toState, action) {
53
+ // Wait for any existing transition to complete
54
+ if (this.transitionLock) {
55
+ await this.transitionLock.catch(() => {
56
+ // Ignore errors from previous transitions
57
+ });
58
+ }
59
+ // Create a new transition lock
60
+ let resolve;
61
+ let reject;
62
+ this.transitionLock = new Promise((res, rej) => {
63
+ resolve = res;
64
+ reject = rej;
65
+ });
66
+ try {
67
+ const allowedStates = Array.isArray(fromStates) ? fromStates : [fromStates];
68
+ // Check if transition is allowed
69
+ if (!allowedStates.includes(this.currentState)) {
70
+ resolve();
71
+ return false;
72
+ }
73
+ // If already in target state, no need to transition
74
+ if (this.currentState === toState) {
75
+ resolve();
76
+ return true;
77
+ }
78
+ const oldState = this.currentState;
79
+ // Execute action if provided
80
+ if (action) {
81
+ await action();
82
+ }
83
+ // Update state
84
+ this.currentState = toState;
85
+ // Notify listeners
86
+ for (const listener of this.listeners) {
87
+ try {
88
+ listener(oldState, toState);
89
+ }
90
+ catch (error) {
91
+ // Don't let listener errors break the state machine
92
+ console.error('Error in state change listener:', error);
93
+ }
94
+ }
95
+ resolve();
96
+ return true;
97
+ }
98
+ catch (error) {
99
+ reject(error);
100
+ throw error;
101
+ }
102
+ finally {
103
+ // Clear the transition lock
104
+ this.transitionLock = null;
105
+ }
106
+ }
107
+ /**
108
+ * Force a state change without checking allowed transitions.
109
+ * Use with caution - mainly for error recovery.
110
+ */
111
+ async forceState(newState) {
112
+ if (this.transitionLock) {
113
+ await this.transitionLock.catch(() => { });
114
+ }
115
+ const oldState = this.currentState;
116
+ this.currentState = newState;
117
+ // Notify listeners
118
+ for (const listener of this.listeners) {
119
+ try {
120
+ listener(oldState, newState);
121
+ }
122
+ catch (error) {
123
+ console.error('Error in state change listener:', error);
124
+ }
125
+ }
126
+ }
127
+ }
128
+ exports.ConnectionStateMachine = ConnectionStateMachine;
129
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdGlvbi1zdGF0ZS1tYWNoaW5lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL2Nvbm5lY3Rpb24tc3RhdGUtbWFjaGluZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztHQUdHOzs7QUFFSCxJQUFZLGVBS1g7QUFMRCxXQUFZLGVBQWU7SUFDMUIsNENBQXlCLENBQUE7SUFDekIsMENBQXVCLENBQUE7SUFDdkIsc0NBQW1CLENBQUE7SUFDbkIsb0NBQWlCLENBQUE7QUFDbEIsQ0FBQyxFQUxXLGVBQWUsK0JBQWYsZUFBZSxRQUsxQjtBQUlELE1BQWEsc0JBQXNCO0lBS2xDLFlBQVksZUFBZ0MsZUFBZSxDQUFDLFVBQVU7UUFIOUQsY0FBUyxHQUEwQixFQUFFLENBQUE7UUFDckMsbUJBQWMsR0FBeUIsSUFBSSxDQUFBO1FBR2xELElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFBO0lBQ2pDLENBQUM7SUFFRDs7T0FFRztJQUNILFFBQVE7UUFDUCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUE7SUFDekIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUyxDQUFDLEdBQUcsTUFBeUI7UUFDckMsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUMxQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxhQUFhLENBQUMsUUFBNkI7UUFDMUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDN0IsT0FBTyxHQUFHLEVBQUU7WUFDWCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtZQUM5QyxJQUFJLEtBQUssSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDaEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFBO1lBQ2hDLENBQUM7UUFD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
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Resource monitor for tracking resources and preventing leaks.
3
+ * Provides debugging capabilities and resource management.
4
+ */
5
+ import type { Logger } from '../types';
6
+ export interface ResourceInfo {
7
+ id: string;
8
+ type: string;
9
+ createdAt: Date;
10
+ metadata?: any;
11
+ }
12
+ export declare class ResourceMonitor {
13
+ private static instance;
14
+ private resources;
15
+ private logger;
16
+ private constructor();
17
+ /**
18
+ * Get or create the singleton ResourceMonitor instance.
19
+ */
20
+ static getInstance(logger: Logger): ResourceMonitor;
21
+ /**
22
+ * Track a new resource.
23
+ */
24
+ trackResource(id: string, type: string, metadata?: any): void;
25
+ /**
26
+ * Untrack a resource.
27
+ */
28
+ untrackResource(id: string): boolean;
29
+ /**
30
+ * Check if a resource is tracked.
31
+ */
32
+ isTracked(id: string): boolean;
33
+ /**
34
+ * Get information about a specific resource.
35
+ */
36
+ getResource(id: string): ResourceInfo | undefined;
37
+ /**
38
+ * Get all tracked resources.
39
+ */
40
+ getAllResources(): ResourceInfo[];
41
+ /**
42
+ * Get resources by type.
43
+ */
44
+ getResourcesByType(type: string): ResourceInfo[];
45
+ /**
46
+ * Get resources older than a specific age.
47
+ */
48
+ getResourcesOlderThan(ageMs: number): ResourceInfo[];
49
+ /**
50
+ * Log resource statistics.
51
+ */
52
+ logStats(): void;
53
+ /**
54
+ * Clear all tracked resources (for testing/cleanup).
55
+ */
56
+ clear(): void;
57
+ /**
58
+ * Reset the singleton instance (for testing).
59
+ */
60
+ static reset(): void;
61
+ }
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ /**
3
+ * Resource monitor for tracking resources and preventing leaks.
4
+ * Provides debugging capabilities and resource management.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ResourceMonitor = void 0;
8
+ class ResourceMonitor {
9
+ constructor(logger) {
10
+ this.resources = new Map();
11
+ this.logger = logger;
12
+ }
13
+ /**
14
+ * Get or create the singleton ResourceMonitor instance.
15
+ */
16
+ static getInstance(logger) {
17
+ if (!ResourceMonitor.instance) {
18
+ ResourceMonitor.instance = new ResourceMonitor(logger);
19
+ }
20
+ return ResourceMonitor.instance;
21
+ }
22
+ /**
23
+ * Track a new resource.
24
+ */
25
+ trackResource(id, type, metadata) {
26
+ const resource = {
27
+ id,
28
+ type,
29
+ createdAt: new Date(),
30
+ metadata
31
+ };
32
+ this.resources.set(id, resource);
33
+ this.logger.trace({ id, type, metadata }, 'Resource tracked');
34
+ }
35
+ /**
36
+ * Untrack a resource.
37
+ */
38
+ untrackResource(id) {
39
+ const resource = this.resources.get(id);
40
+ if (resource) {
41
+ this.resources.delete(id);
42
+ this.logger.trace({ id, type: resource.type }, 'Resource untracked');
43
+ return true;
44
+ }
45
+ return false;
46
+ }
47
+ /**
48
+ * Check if a resource is tracked.
49
+ */
50
+ isTracked(id) {
51
+ return this.resources.has(id);
52
+ }
53
+ /**
54
+ * Get information about a specific resource.
55
+ */
56
+ getResource(id) {
57
+ return this.resources.get(id);
58
+ }
59
+ /**
60
+ * Get all tracked resources.
61
+ */
62
+ getAllResources() {
63
+ return Array.from(this.resources.values());
64
+ }
65
+ /**
66
+ * Get resources by type.
67
+ */
68
+ getResourcesByType(type) {
69
+ return Array.from(this.resources.values()).filter(r => r.type === type);
70
+ }
71
+ /**
72
+ * Get resources older than a specific age.
73
+ */
74
+ getResourcesOlderThan(ageMs) {
75
+ const cutoff = new Date(Date.now() - ageMs);
76
+ return Array.from(this.resources.values()).filter(r => r.createdAt < cutoff);
77
+ }
78
+ /**
79
+ * Log resource statistics.
80
+ */
81
+ logStats() {
82
+ const byType = new Map();
83
+ for (const resource of this.resources.values()) {
84
+ byType.set(resource.type, (byType.get(resource.type) || 0) + 1);
85
+ }
86
+ const stats = Object.fromEntries(byType);
87
+ this.logger.info({
88
+ totalResources: this.resources.size,
89
+ byType: stats
90
+ }, 'Resource statistics');
91
+ }
92
+ /**
93
+ * Clear all tracked resources (for testing/cleanup).
94
+ */
95
+ clear() {
96
+ this.resources.clear();
97
+ }
98
+ /**
99
+ * Reset the singleton instance (for testing).
100
+ */
101
+ static reset() {
102
+ ResourceMonitor.instance = null;
103
+ }
104
+ }
105
+ exports.ResourceMonitor = ResourceMonitor;
106
+ ResourceMonitor.instance = null;
107
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UtbW9uaXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9yZXNvdXJjZS1tb25pdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7OztBQVdILE1BQWEsZUFBZTtJQUszQixZQUFvQixNQUFjO1FBSDFCLGNBQVMsR0FBRyxJQUFJLEdBQUcsRUFBd0IsQ0FBQTtRQUlsRCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQTtJQUNyQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQWM7UUFDaEMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUMvQixlQUFlLENBQUMsUUFBUSxHQUFHLElBQUksZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQ3ZELENBQUM7UUFDRCxPQUFPLGVBQWUsQ0FBQyxRQUFRLENBQUE7SUFDaEMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsYUFBYSxDQUFDLEVBQVUsRUFBRSxJQUFZLEVBQUUsUUFBYztRQUNyRCxNQUFNLFFBQVEsR0FBaUI7WUFDOUIsRUFBRTtZQUNGLElBQUk7WUFDSixTQUFTLEVBQUUsSUFBSSxJQUFJLEVBQUU7WUFDckIsUUFBUTtTQUNSLENBQUE7UUFFRCxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUE7UUFDaEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFFLGtCQUFrQixDQUFDLENBQUE7SUFDOUQsQ0FBQztJQUVEOztPQUVHO0lBQ0gsZUFBZSxDQUFDLEVBQVU7UUFDekIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDdkMsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNkLElBQUksQ0FBQyxT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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reclaimprotocol/attestor-core",
3
- "version": "4.0.2",
3
+ "version": "4.0.3",
4
4
  "description": "",
5
5
  "main": "lib/index",
6
6
  "scripts": {