@balancy/utils 1.0.34 → 1.0.35
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/README.md +89 -128
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,156 +1,148 @@
|
|
|
1
1
|
# @balancy/utils
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Utility functions and helpers for the Balancy ecosystem.
|
|
4
4
|
|
|
5
|
-
## ⭐
|
|
5
|
+
## ⭐ Main Features
|
|
6
6
|
|
|
7
|
-
- **IndexedDB FileHelper** -
|
|
8
|
-
-
|
|
7
|
+
- **IndexedDB FileHelper** - Complete file system integration with IndexedDB for browser environments
|
|
8
|
+
- **Utility Functions** - Collection of useful helper functions for development
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Installation
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
13
|
npm install @balancy/utils
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
## 🚀
|
|
16
|
+
## 🚀 Quick Start with IndexedDB FileHelper
|
|
17
17
|
|
|
18
18
|
```typescript
|
|
19
19
|
import { IndexedDBFileHelperAdapter } from '@balancy/utils';
|
|
20
|
-
import { Balancy
|
|
20
|
+
import { Balancy } from '@balancy/core';
|
|
21
21
|
|
|
22
|
-
//
|
|
22
|
+
// Create and initialize the file helper
|
|
23
23
|
const fileHelperAdapter = await IndexedDBFileHelperAdapter.create({
|
|
24
|
-
cachePath: '.balancy'
|
|
25
|
-
preloadStrategy: 'full' // полная предзагрузка для максимальной производительности
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// ❗ ВАЖНО: Настройка интеграции с DataObjectsManager (решает проблему дублирования)
|
|
29
|
-
fileHelperAdapter.setSpriteLoader((id, callback) => {
|
|
30
|
-
DataObjectsManager.loadSprite(id, callback);
|
|
24
|
+
cachePath: '.balancy'
|
|
31
25
|
});
|
|
32
26
|
|
|
33
|
-
//
|
|
27
|
+
// Get cache statistics
|
|
34
28
|
const stats = fileHelperAdapter.getCacheStats();
|
|
35
29
|
console.log(`📁 Files: ${stats.fileCount}, 💾 Memory: ${stats.memoryUsage}`);
|
|
36
30
|
|
|
37
|
-
//
|
|
31
|
+
// Initialize Balancy (DataObjectsManager integration is automatic)
|
|
38
32
|
await Balancy.Main.initializeFileHelper(fileHelperAdapter);
|
|
39
33
|
```
|
|
40
34
|
|
|
41
|
-
## 🛠️
|
|
35
|
+
## 🛠️ Using Utility Functions
|
|
42
36
|
|
|
43
37
|
```typescript
|
|
44
38
|
import { isEmpty, deepClone, formatNumber, generateId, delay, retry } from '@balancy/utils';
|
|
45
39
|
|
|
46
|
-
//
|
|
47
|
-
console.log(isEmpty(''));
|
|
48
|
-
console.log(isEmpty([]));
|
|
49
|
-
console.log(isEmpty({}));
|
|
40
|
+
// Check for empty values
|
|
41
|
+
console.log(isEmpty('')); // true
|
|
42
|
+
console.log(isEmpty([])); // true
|
|
43
|
+
console.log(isEmpty({})); // true
|
|
50
44
|
|
|
51
|
-
//
|
|
45
|
+
// Deep clone objects
|
|
52
46
|
const original = { a: 1, b: { c: 2 } };
|
|
53
47
|
const cloned = deepClone(original);
|
|
54
48
|
|
|
55
|
-
//
|
|
49
|
+
// Format numbers
|
|
56
50
|
console.log(formatNumber(1234567)); // "1,234,567"
|
|
57
51
|
|
|
58
|
-
//
|
|
59
|
-
console.log(generateId());
|
|
60
|
-
console.log(generateId(12));
|
|
52
|
+
// Generate random IDs
|
|
53
|
+
console.log(generateId()); // "AbC12xyz"
|
|
54
|
+
console.log(generateId(12)); // "AbC12xyzDeFg"
|
|
61
55
|
|
|
62
|
-
//
|
|
63
|
-
await delay(1000); //
|
|
56
|
+
// Delay execution
|
|
57
|
+
await delay(1000); // wait 1 second
|
|
64
58
|
|
|
65
|
-
// Retry
|
|
59
|
+
// Retry with exponential backoff
|
|
66
60
|
const result = await retry(async () => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}, 3, 1000); // 3
|
|
61
|
+
// some async operation
|
|
62
|
+
return await fetchData();
|
|
63
|
+
}, 3, 1000); // 3 attempts, 1s base delay
|
|
70
64
|
```
|
|
71
65
|
|
|
72
66
|
## 📁 IndexedDB FileHelper API
|
|
73
67
|
|
|
74
68
|
### `IndexedDBFileHelperAdapter.create(config)`
|
|
75
|
-
|
|
69
|
+
Main method to create a file system adapter.
|
|
76
70
|
|
|
77
71
|
```typescript
|
|
78
|
-
interface
|
|
79
|
-
cachePath: string; //
|
|
80
|
-
codePath?: string; //
|
|
81
|
-
resourcesPath?: string; //
|
|
82
|
-
preloadStrategy?: 'none' | 'partial' | 'full'; // Стратегия предзагрузки
|
|
83
|
-
enableLogging?: boolean; // Включить логирование
|
|
72
|
+
interface FileHelperPaths {
|
|
73
|
+
cachePath: string; // Cache path (required)
|
|
74
|
+
codePath?: string; // Generated code path
|
|
75
|
+
resourcesPath?: string; // Resources path
|
|
84
76
|
}
|
|
85
77
|
```
|
|
86
78
|
|
|
87
|
-
###
|
|
79
|
+
### Alternative creation methods:
|
|
88
80
|
|
|
89
81
|
```typescript
|
|
90
|
-
//
|
|
82
|
+
// Fast creation without preloading
|
|
91
83
|
const fastAdapter = await IndexedDBFileHelperAdapter.createFast({
|
|
92
84
|
cachePath: '.balancy'
|
|
93
85
|
});
|
|
94
86
|
|
|
95
|
-
//
|
|
87
|
+
// Creation with partial preloading
|
|
96
88
|
const partialAdapter = await IndexedDBFileHelperAdapter.createWithPartialPreload({
|
|
97
89
|
cachePath: '.balancy'
|
|
98
90
|
});
|
|
99
91
|
```
|
|
100
92
|
|
|
101
|
-
###
|
|
93
|
+
### Main methods:
|
|
102
94
|
|
|
103
95
|
#### `getBinaryFile(key: string): Promise<Uint8Array | null>`
|
|
104
|
-
|
|
96
|
+
Loads a binary file by key.
|
|
105
97
|
|
|
106
98
|
#### `saveBinaryFile(key: string, data: Uint8Array): Promise<boolean>`
|
|
107
|
-
|
|
99
|
+
Saves binary data.
|
|
108
100
|
|
|
109
101
|
#### `hasFile(key: string): Promise<boolean>`
|
|
110
|
-
|
|
102
|
+
Checks if file exists.
|
|
111
103
|
|
|
112
104
|
#### `deleteFile(key: string): Promise<boolean>`
|
|
113
|
-
|
|
105
|
+
Deletes file from cache.
|
|
114
106
|
|
|
115
107
|
#### `getCacheStats(): CacheStats`
|
|
116
|
-
|
|
108
|
+
Returns cache usage statistics.
|
|
117
109
|
|
|
118
110
|
```typescript
|
|
119
111
|
interface CacheStats {
|
|
120
|
-
fileCount: number; //
|
|
121
|
-
memoryUsage: string; //
|
|
122
|
-
hitRate?: number; //
|
|
123
|
-
totalRequests?: number; //
|
|
124
|
-
cacheHits?: number; //
|
|
112
|
+
fileCount: number; // Number of files in cache
|
|
113
|
+
memoryUsage: string; // Memory usage (human readable)
|
|
114
|
+
hitRate?: number; // Cache hit rate percentage
|
|
115
|
+
totalRequests?: number; // Total number of requests
|
|
116
|
+
cacheHits?: number; // Number of cache hits
|
|
125
117
|
}
|
|
126
118
|
```
|
|
127
119
|
|
|
128
|
-
## 🔧
|
|
120
|
+
## 🔧 Utility Functions
|
|
129
121
|
|
|
130
122
|
### `isEmpty(value: any): boolean`
|
|
131
|
-
|
|
123
|
+
Checks if value is empty (null, undefined, empty string, empty array, empty object).
|
|
132
124
|
|
|
133
125
|
### `deepClone<T>(obj: T): T`
|
|
134
|
-
|
|
126
|
+
Performs deep cloning of objects.
|
|
135
127
|
|
|
136
128
|
### `formatNumber(num: number, locale?: string): string`
|
|
137
|
-
|
|
129
|
+
Formats numbers with thousand separators. Uses 'en-US' locale by default.
|
|
138
130
|
|
|
139
131
|
### `generateId(length?: number): string`
|
|
140
|
-
|
|
132
|
+
Generates random ID of specified length (default 8 characters).
|
|
141
133
|
|
|
142
134
|
### `delay(ms: number): Promise<void>`
|
|
143
|
-
|
|
135
|
+
Creates a delay for specified milliseconds.
|
|
144
136
|
|
|
145
137
|
### `retry<T>(fn: () => Promise<T>, maxAttempts?: number, baseDelay?: number): Promise<T>`
|
|
146
|
-
|
|
138
|
+
Executes function with retry attempts on errors. Uses exponential backoff between attempts.
|
|
147
139
|
|
|
148
|
-
## 📖
|
|
140
|
+
## 📖 Usage Examples
|
|
149
141
|
|
|
150
|
-
###
|
|
142
|
+
### Game Data Integration
|
|
151
143
|
|
|
152
144
|
```typescript
|
|
153
|
-
//
|
|
145
|
+
// Save game data
|
|
154
146
|
const gameData = {
|
|
155
147
|
playerLevel: 42,
|
|
156
148
|
coins: 1500,
|
|
@@ -160,15 +152,15 @@ const gameData = {
|
|
|
160
152
|
const jsonData = JSON.stringify(gameData);
|
|
161
153
|
await adapter.saveBinaryFile('player_data.json', new TextEncoder().encode(jsonData));
|
|
162
154
|
|
|
163
|
-
//
|
|
155
|
+
// Load game data
|
|
164
156
|
const savedData = await adapter.getBinaryFile('player_data.json');
|
|
165
157
|
if (savedData) {
|
|
166
158
|
const parsedData = JSON.parse(new TextDecoder().decode(savedData));
|
|
167
|
-
console.log('
|
|
159
|
+
console.log('Game data:', parsedData);
|
|
168
160
|
}
|
|
169
161
|
```
|
|
170
162
|
|
|
171
|
-
###
|
|
163
|
+
### Performance Monitoring
|
|
172
164
|
|
|
173
165
|
```typescript
|
|
174
166
|
const stats = adapter.getCacheStats();
|
|
@@ -177,31 +169,25 @@ console.log(`Memory usage: ${stats.memoryUsage}`);
|
|
|
177
169
|
console.log(`Total files: ${stats.fileCount}`);
|
|
178
170
|
```
|
|
179
171
|
|
|
180
|
-
## 🏗️
|
|
172
|
+
## 🏗️ Preloading Strategies
|
|
173
|
+
|
|
174
|
+
The package supports different preloading strategies for optimal performance:
|
|
181
175
|
|
|
182
|
-
- **`'full'`** -
|
|
183
|
-
- **`'partial'`** -
|
|
184
|
-
- **`'none'`** -
|
|
176
|
+
- **`'full'`** - Loads ALL files into memory at initialization. Maximum performance, higher memory usage.
|
|
177
|
+
- **`'partial'`** - Loads only cache files. Balance between speed and memory.
|
|
178
|
+
- **`'none'`** - No preloading. Minimal memory usage, files loaded on demand.
|
|
185
179
|
|
|
186
|
-
## 📋 TypeScript
|
|
180
|
+
## 📋 TypeScript Interfaces
|
|
187
181
|
|
|
188
182
|
```typescript
|
|
189
|
-
//
|
|
183
|
+
// Main interfaces for FileHelper
|
|
190
184
|
interface FileHelperPaths {
|
|
191
185
|
cachePath: string;
|
|
192
186
|
codePath?: string;
|
|
193
187
|
resourcesPath?: string;
|
|
194
188
|
}
|
|
195
189
|
|
|
196
|
-
|
|
197
|
-
getBinaryFile(key: string): Promise<Uint8Array | null>;
|
|
198
|
-
saveBinaryFile(key: string, data: Uint8Array): Promise<boolean>;
|
|
199
|
-
hasFile(key: string): Promise<boolean>;
|
|
200
|
-
deleteFile(key: string): Promise<boolean>;
|
|
201
|
-
clearCache(): Promise<boolean>;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Утилитарные интерфейсы
|
|
190
|
+
// Utility interfaces
|
|
205
191
|
interface RetryOptions {
|
|
206
192
|
maxAttempts?: number;
|
|
207
193
|
baseDelay?: number;
|
|
@@ -213,71 +199,46 @@ interface UtilsConfig {
|
|
|
213
199
|
}
|
|
214
200
|
```
|
|
215
201
|
|
|
216
|
-
## 🚨
|
|
202
|
+
## 🚨 Important Notes
|
|
217
203
|
|
|
218
|
-
###
|
|
204
|
+
### Integration with Balancy Core
|
|
219
205
|
|
|
220
|
-
|
|
206
|
+
The `@balancy/utils` package is designed as an **optional dependency** of `@balancy/core`. This means:
|
|
221
207
|
|
|
222
|
-
✅
|
|
223
|
-
✅
|
|
224
|
-
✅ **TypeScript
|
|
208
|
+
✅ **Can be used** independently for IndexedDB functionality
|
|
209
|
+
✅ **Can be integrated** with Balancy Core for full functionality
|
|
210
|
+
✅ **TypeScript support** works fully in both cases
|
|
225
211
|
|
|
226
212
|
```typescript
|
|
227
|
-
//
|
|
213
|
+
// Independent usage
|
|
228
214
|
import { IndexedDBFileHelperAdapter } from '@balancy/utils';
|
|
229
215
|
const adapter = await IndexedDBFileHelperAdapter.create({ cachePath: '.balancy' });
|
|
230
216
|
|
|
231
|
-
//
|
|
217
|
+
// Integration with Balancy (requires @balancy/core)
|
|
232
218
|
import { Balancy } from '@balancy/core';
|
|
233
219
|
import { IndexedDBFileHelperAdapter } from '@balancy/utils';
|
|
234
220
|
|
|
235
221
|
const adapter = await IndexedDBFileHelperAdapter.create({ cachePath: '.balancy' });
|
|
236
|
-
await Balancy.Main.initializeFileHelper(adapter);
|
|
222
|
+
await Balancy.Main.initializeFileHelper(adapter); // Auto-configures DataObjectsManager
|
|
237
223
|
```
|
|
238
224
|
|
|
239
|
-
###
|
|
240
|
-
|
|
241
|
-
- **Стратегия `'full'`** рекомендуется для продакшн приложений
|
|
242
|
-
- **Стратегия `'partial'`** подходит для разработки
|
|
243
|
-
- **Стратегия `'none'`** для ограниченных ресурсов
|
|
244
|
-
|
|
245
|
-
### Совместимость
|
|
225
|
+
### Performance
|
|
246
226
|
|
|
247
|
-
-
|
|
248
|
-
-
|
|
249
|
-
-
|
|
250
|
-
- ❌ React Native (требуется полифилл)
|
|
227
|
+
- **Strategy `'full'`** recommended for production applications
|
|
228
|
+
- **Strategy `'partial'`** suitable for development
|
|
229
|
+
- **Strategy `'none'`** for resource-constrained environments
|
|
251
230
|
|
|
252
|
-
|
|
231
|
+
### Compatibility
|
|
253
232
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
**Симптомы:**
|
|
259
|
-
```javascript
|
|
260
|
-
console.log(DataObjectsManager.instance); // то undefined, то объект
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
**Решение:**
|
|
264
|
-
```typescript
|
|
265
|
-
// ❌ НЕПРАВИЛЬНО: Прямой импорт в utils может привести к дублированию
|
|
266
|
-
// import { DataObjectsManager } from '@balancy/core'; // в utils пакете
|
|
267
|
-
|
|
268
|
-
// ✅ ПРАВИЛЬНО: Передача через setSpriteLoader
|
|
269
|
-
import { DataObjectsManager } from '@balancy/core'; // в вашем приложении
|
|
270
|
-
|
|
271
|
-
const adapter = await IndexedDBFileHelperAdapter.create({cachePath: '.balancy'});
|
|
272
|
-
adapter.setSpriteLoader((id, callback) => {
|
|
273
|
-
DataObjectsManager.loadSprite(id, callback); // Использует правильный экземпляр
|
|
274
|
-
});
|
|
275
|
-
```
|
|
233
|
+
- ✅ Modern browsers with IndexedDB support
|
|
234
|
+
- ✅ Web Workers (with limitations)
|
|
235
|
+
- ❌ Node.js (IndexedDB not available)
|
|
236
|
+
- ❌ React Native (requires polyfill)
|
|
276
237
|
|
|
277
|
-
##
|
|
238
|
+
## License
|
|
278
239
|
|
|
279
240
|
MIT
|
|
280
241
|
|
|
281
|
-
##
|
|
242
|
+
## Support
|
|
282
243
|
|
|
283
|
-
|
|
244
|
+
For questions and support, contact the Balancy team.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@balancy/utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.35",
|
|
4
4
|
"homepage": "https://balancy.co",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@balancy/core": "~1.0.
|
|
41
|
+
"@balancy/core": "~1.0.35"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {}
|
|
44
44
|
}
|