@jucie.io/engine 1.1.39
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 +545 -0
- package/dist/Engine.d.ts +30 -0
- package/dist/ServiceProvider.d.ts +23 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +7 -0
- package/dist/lib/logger/src/Logger.d.ts +290 -0
- package/dist/services/command-manager.js +2 -0
- package/dist/services/command-manager.js.map +7 -0
- package/dist/services/database.js +11 -0
- package/dist/services/database.js.map +7 -0
- package/dist/services/local-storage.js +2 -0
- package/dist/services/local-storage.js.map +7 -0
- package/dist/services/message.js +9 -0
- package/dist/services/message.js.map +7 -0
- package/dist/services/painter.js +2 -0
- package/dist/services/painter.js.map +7 -0
- package/dist/services/server.js +4 -0
- package/dist/services/server.js.map +7 -0
- package/dist/services/signal.js +2 -0
- package/dist/services/signal.js.map +7 -0
- package/dist/services/socket.js +2 -0
- package/dist/services/socket.js.map +7 -0
- package/dist/services/state-machine.js +2 -0
- package/dist/services/state-machine.js.map +7 -0
- package/dist/services/storage.js +5 -0
- package/dist/services/storage.js.map +7 -0
- package/dist/services/worker.js +2 -0
- package/dist/services/worker.js.map +7 -0
- package/dist/types.d.ts +130 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
# @jucie.io/engine
|
|
2
|
+
|
|
3
|
+
A powerful, extensible service engine for JavaScript applications with middleware support, async operations, and comprehensive lifecycle management.
|
|
4
|
+
|
|
5
|
+
## Important Notice
|
|
6
|
+
|
|
7
|
+
This package is made publicly available for use but comes with no support, maintenance commitments, or warranty of any kind. It is provided strictly "as-is" under the MIT license.
|
|
8
|
+
|
|
9
|
+
- Issues and feature requests may not be addressed
|
|
10
|
+
- No timeline or commitment for updates
|
|
11
|
+
- Not actively seeking contributions
|
|
12
|
+
- Use at your own risk
|
|
13
|
+
|
|
14
|
+
If you choose to use this package, please ensure it meets your needs through your own testing and evaluation.
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
- ๐ **Service Architecture**: Clean, modular service system with lifecycle management
|
|
19
|
+
- ๐ง **Middleware Support**: Composable middleware with sync/async support
|
|
20
|
+
- โก **Async Operations**: Full async/await support for actions and middleware
|
|
21
|
+
- ๐ก๏ธ **Security**: Built-in protection against prototype pollution and namespace conflicts
|
|
22
|
+
- ๐ **Dependency Management**: Automatic service dependency resolution
|
|
23
|
+
- โ๏ธ **Configuration**: Flexible service configuration with defaults merging
|
|
24
|
+
- ๐งช **Well Tested**: Comprehensive test suite with 33+ test cases
|
|
25
|
+
- ๐ฆ **TypeScript Ready**: Full TypeScript definitions included
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @jucie.io/engine
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
### Method Pattern
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
import { Engine, ServiceProvider } from '@jucie.io/engine';
|
|
39
|
+
|
|
40
|
+
// Create an engine instance
|
|
41
|
+
const engine = Engine.create();
|
|
42
|
+
|
|
43
|
+
// Define a service using method pattern
|
|
44
|
+
class MyService extends ServiceProvider {
|
|
45
|
+
static manifest = {
|
|
46
|
+
name: 'My Service',
|
|
47
|
+
namespace: 'myService',
|
|
48
|
+
version: '1.0.0'
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
actions(useContext, config) {
|
|
52
|
+
return {
|
|
53
|
+
greet: (name) => `Hello, ${name}!`,
|
|
54
|
+
fetchData: async () => {
|
|
55
|
+
// Async operations supported
|
|
56
|
+
return await fetch('/api/data').then(r => r.json());
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
middleware(useContext, config) {
|
|
62
|
+
return (action, ctx, next) => {
|
|
63
|
+
console.log(`Executing action: ${action}`);
|
|
64
|
+
return next();
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Install the service
|
|
70
|
+
await engine.install(MyService);
|
|
71
|
+
|
|
72
|
+
// Use the service
|
|
73
|
+
const greeting = engine.myService.greet('World');
|
|
74
|
+
console.log(greeting); // "Hello, World!"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Setup Pattern
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
import { Engine, ServiceProvider } from '@jucie.io/engine';
|
|
81
|
+
|
|
82
|
+
// Create an engine instance
|
|
83
|
+
const engine = Engine.create();
|
|
84
|
+
|
|
85
|
+
// Define a service using setup pattern
|
|
86
|
+
class MyService extends ServiceProvider {
|
|
87
|
+
static manifest = {
|
|
88
|
+
name: 'My Service',
|
|
89
|
+
namespace: 'myService',
|
|
90
|
+
version: '1.0.0'
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
setup({ defineActions, defineMiddleware }) {
|
|
94
|
+
defineActions((useContext, config) => {
|
|
95
|
+
return {
|
|
96
|
+
greet: (name) => `Hello, ${name}!`,
|
|
97
|
+
fetchData: async () => {
|
|
98
|
+
return await fetch('/api/data').then(r => r.json());
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
defineMiddleware((useContext, config) => {
|
|
104
|
+
return (action, ctx, next) => {
|
|
105
|
+
console.log(`Executing action: ${action}`);
|
|
106
|
+
return next();
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Install the service
|
|
113
|
+
await engine.install(MyService);
|
|
114
|
+
|
|
115
|
+
// Use the service
|
|
116
|
+
const greeting = engine.myService.greet('World');
|
|
117
|
+
console.log(greeting); // "Hello, World!"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Service Architecture
|
|
121
|
+
|
|
122
|
+
### ServiceProvider Base Class
|
|
123
|
+
|
|
124
|
+
All services extend the `ServiceProvider` base class and implement the following lifecycle methods:
|
|
125
|
+
|
|
126
|
+
#### Required Properties
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
static manifest = {
|
|
130
|
+
name: 'Service Name',
|
|
131
|
+
namespace: 'serviceName', // Must be valid JS identifier
|
|
132
|
+
version: '1.0.0'
|
|
133
|
+
};
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Service Definition Patterns
|
|
137
|
+
|
|
138
|
+
The ServiceProvider supports two patterns for defining service functionality:
|
|
139
|
+
|
|
140
|
+
**Method Pattern** (Traditional approach):
|
|
141
|
+
- **`actions(useContext, config)`** - Define service actions (required)
|
|
142
|
+
- **`middleware(useContext, config)`** - Define middleware functions (optional)
|
|
143
|
+
- **`getters(useContext, config)`** - Define read-only properties (optional)
|
|
144
|
+
- **`initialize(useContext, config)`** - Setup logic called directly (optional)
|
|
145
|
+
- **`uninstall(useContext, config)`** - Cleanup logic called directly (optional)
|
|
146
|
+
|
|
147
|
+
**Setup Pattern** (Declarative approach):
|
|
148
|
+
- **`setup({ defineActions, defineMiddleware, defineGetters, defineInitialize, defineUninstall })`** - Declarative service definition
|
|
149
|
+
|
|
150
|
+
### Method Pattern Example
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
class DatabaseService extends ServiceProvider {
|
|
154
|
+
static manifest = {
|
|
155
|
+
name: 'Database Service',
|
|
156
|
+
namespace: 'db',
|
|
157
|
+
version: '1.0.0',
|
|
158
|
+
defaults: { connectionString: 'sqlite:memory:' }
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
#connection = null;
|
|
162
|
+
|
|
163
|
+
initialize(useContext, config) {
|
|
164
|
+
this.#connection = createConnection(this.config.connectionString);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
getters(useContext, config) {
|
|
168
|
+
return {
|
|
169
|
+
isConnected: () => this.#connection !== null
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
middleware(useContext, config) {
|
|
174
|
+
return (action, ctx, next) => {
|
|
175
|
+
console.log(`Database action: ${action}`);
|
|
176
|
+
return next();
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
actions(useContext, config) {
|
|
181
|
+
return {
|
|
182
|
+
async query: (sql, params = []) => {
|
|
183
|
+
return await this.#connection.query(sql, params);
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
async transaction: async (callback) => {
|
|
187
|
+
const tx = await this.#connection.beginTransaction();
|
|
188
|
+
try {
|
|
189
|
+
const result = await callback(tx);
|
|
190
|
+
await tx.commit();
|
|
191
|
+
return result;
|
|
192
|
+
} catch (error) {
|
|
193
|
+
await tx.rollback();
|
|
194
|
+
throw error;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
uninstall(useContext, config) {
|
|
201
|
+
if (this.#connection) {
|
|
202
|
+
this.#connection.close();
|
|
203
|
+
this.#connection = null;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Setup Pattern Example
|
|
210
|
+
|
|
211
|
+
```javascript
|
|
212
|
+
class CacheService extends ServiceProvider {
|
|
213
|
+
static manifest = {
|
|
214
|
+
name: 'Cache Service',
|
|
215
|
+
namespace: 'cache',
|
|
216
|
+
version: '1.0.0',
|
|
217
|
+
defaults: { ttl: 300000, maxSize: 1000 }
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
#cache = new Map();
|
|
221
|
+
|
|
222
|
+
setup({ defineMiddleware, defineGetters, defineActions, defineInitialize, defineUninstall }) {
|
|
223
|
+
// Define middleware
|
|
224
|
+
defineMiddleware((useContext, config) => {
|
|
225
|
+
return (action, ctx, next) => {
|
|
226
|
+
console.log(`Cache action: ${action}`);
|
|
227
|
+
return next();
|
|
228
|
+
};
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Define getters
|
|
232
|
+
defineGetters((useContext, config) => {
|
|
233
|
+
return {
|
|
234
|
+
size: () => this.#cache.size,
|
|
235
|
+
isEnabled: () => this.config.maxSize > 0
|
|
236
|
+
};
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Define actions
|
|
240
|
+
defineActions((useContext, config) => {
|
|
241
|
+
return {
|
|
242
|
+
get: (key) => {
|
|
243
|
+
const item = this.#cache.get(key);
|
|
244
|
+
if (!item) return null;
|
|
245
|
+
|
|
246
|
+
if (Date.now() > item.expires) {
|
|
247
|
+
this.#cache.delete(key);
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return item.value;
|
|
252
|
+
},
|
|
253
|
+
|
|
254
|
+
set: (key, value, ttl = this.config.ttl) => {
|
|
255
|
+
if (this.#cache.size >= this.config.maxSize) {
|
|
256
|
+
// Remove oldest entry
|
|
257
|
+
const firstKey = this.#cache.keys().next().value;
|
|
258
|
+
this.#cache.delete(firstKey);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
this.#cache.set(key, {
|
|
262
|
+
value,
|
|
263
|
+
expires: Date.now() + ttl
|
|
264
|
+
});
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
clear: () => {
|
|
268
|
+
this.#cache.clear();
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// Define initialize
|
|
274
|
+
defineInitialize((useContext, config) => {
|
|
275
|
+
console.log('Cache service initialized');
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// Define uninstall
|
|
279
|
+
defineUninstall((useContext, config) => {
|
|
280
|
+
this.#cache.clear();
|
|
281
|
+
console.log('Cache service cleaned up');
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Pattern Comparison
|
|
288
|
+
|
|
289
|
+
| Feature | Method Pattern | Setup Pattern |
|
|
290
|
+
|---------|---------------|---------------|
|
|
291
|
+
| **Syntax** | Class methods | Single setup function |
|
|
292
|
+
| **Organization** | Separate methods | Centralized definition |
|
|
293
|
+
| **Flexibility** | High - conditional methods | Medium - declarative |
|
|
294
|
+
| **Readability** | Good for simple services | Excellent for complex services |
|
|
295
|
+
| **Type Safety** | Standard class methods | Requires proper typing |
|
|
296
|
+
| **Use Case** | Simple to medium services | Complex services with many definitions |
|
|
297
|
+
|
|
298
|
+
## Middleware System
|
|
299
|
+
|
|
300
|
+
The engine supports powerful middleware composition for intercepting and processing action calls:
|
|
301
|
+
|
|
302
|
+
```javascript
|
|
303
|
+
class LoggingService extends ServiceProvider {
|
|
304
|
+
static manifest = {
|
|
305
|
+
name: 'Logging Service',
|
|
306
|
+
namespace: 'logging',
|
|
307
|
+
version: '1.0.0'
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
middleware(useContext, config) {
|
|
311
|
+
return [
|
|
312
|
+
// Sync middleware
|
|
313
|
+
(action, ctx, next) => {
|
|
314
|
+
console.log(`[${new Date().toISOString()}] Starting ${action}`);
|
|
315
|
+
const start = Date.now();
|
|
316
|
+
|
|
317
|
+
const result = next();
|
|
318
|
+
|
|
319
|
+
console.log(`[${new Date().toISOString()}] Completed ${action} in ${Date.now() - start}ms`);
|
|
320
|
+
return result;
|
|
321
|
+
},
|
|
322
|
+
|
|
323
|
+
// Async middleware
|
|
324
|
+
async (action, ctx, next) => {
|
|
325
|
+
// Authentication check
|
|
326
|
+
const user = await authenticateUser();
|
|
327
|
+
if (!user) {
|
|
328
|
+
throw new Error('Unauthorized');
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
ctx.user = user;
|
|
332
|
+
return next();
|
|
333
|
+
}
|
|
334
|
+
];
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
actions(useContext, config) {
|
|
338
|
+
return {
|
|
339
|
+
log: (message) => console.log(message)
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Service Dependencies
|
|
346
|
+
|
|
347
|
+
Services can declare dependencies that are automatically installed:
|
|
348
|
+
|
|
349
|
+
```javascript
|
|
350
|
+
class AuthService extends ServiceProvider {
|
|
351
|
+
static manifest = {
|
|
352
|
+
name: 'Auth Service',
|
|
353
|
+
namespace: 'auth',
|
|
354
|
+
version: '1.0.0'
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
actions(useContext, config) {
|
|
358
|
+
const { engine } = useContext();
|
|
359
|
+
return {
|
|
360
|
+
login: (credentials) => {
|
|
361
|
+
// Use dependency
|
|
362
|
+
return engine.db.query('SELECT * FROM users WHERE email = ?', [credentials.email]);
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
class ApiService extends ServiceProvider {
|
|
369
|
+
static manifest = {
|
|
370
|
+
name: 'API Service',
|
|
371
|
+
namespace: 'api',
|
|
372
|
+
version: '1.0.0',
|
|
373
|
+
dependencies: [AuthService, DatabaseService] // Auto-install dependencies
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
actions(useContext, config) {
|
|
377
|
+
const { engine } = useContext();
|
|
378
|
+
return {
|
|
379
|
+
handleRequest: (req, res) => {
|
|
380
|
+
// Dependencies are available
|
|
381
|
+
const user = engine.auth.getCurrentUser();
|
|
382
|
+
return engine.db.query('SELECT * FROM posts WHERE userId = ?', [user.id]);
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## Configuration
|
|
390
|
+
|
|
391
|
+
Services support configuration with defaults:
|
|
392
|
+
|
|
393
|
+
```javascript
|
|
394
|
+
class ConfigurableService extends ServiceProvider {
|
|
395
|
+
static manifest = {
|
|
396
|
+
name: 'Configurable Service',
|
|
397
|
+
namespace: 'configurable',
|
|
398
|
+
version: '1.0.0',
|
|
399
|
+
defaults: {
|
|
400
|
+
timeout: 5000,
|
|
401
|
+
retries: 3,
|
|
402
|
+
debug: false
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
actions(useContext, config) {
|
|
407
|
+
return {
|
|
408
|
+
getConfig: () => this.config,
|
|
409
|
+
getTimeout: () => this.config.timeout
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Install with custom configuration
|
|
415
|
+
const configuredService = ConfigurableService.configure({
|
|
416
|
+
timeout: 10000,
|
|
417
|
+
debug: true
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
await engine.install(configuredService);
|
|
421
|
+
console.log(engine.configurable.getTimeout()); // 10000
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## Global Engine Context
|
|
425
|
+
|
|
426
|
+
The engine provides global context management:
|
|
427
|
+
|
|
428
|
+
```javascript
|
|
429
|
+
import { provideEngine, useEngine, hasEngine } from '@jucie.io/engine';
|
|
430
|
+
|
|
431
|
+
// Provide engine globally
|
|
432
|
+
provideEngine(engine);
|
|
433
|
+
|
|
434
|
+
// Use engine from anywhere
|
|
435
|
+
const globalEngine = useEngine();
|
|
436
|
+
const hasGlobalEngine = hasEngine();
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
## Error Handling
|
|
440
|
+
|
|
441
|
+
The engine provides comprehensive error handling with context:
|
|
442
|
+
|
|
443
|
+
```javascript
|
|
444
|
+
class ErrorProneService extends ServiceProvider {
|
|
445
|
+
static manifest = {
|
|
446
|
+
name: 'Error Service',
|
|
447
|
+
namespace: 'error',
|
|
448
|
+
version: '1.0.0'
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
actions(useContext, config) {
|
|
452
|
+
return {
|
|
453
|
+
riskyOperation: () => {
|
|
454
|
+
throw new Error('Something went wrong');
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
try {
|
|
461
|
+
await engine.install(ErrorProneService);
|
|
462
|
+
engine.error.riskyOperation();
|
|
463
|
+
} catch (error) {
|
|
464
|
+
console.log(error.action); // 'riskyOperation'
|
|
465
|
+
console.log(error.namespace); // 'error'
|
|
466
|
+
console.log(error.message); // 'Something went wrong'
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
## Security Features
|
|
471
|
+
|
|
472
|
+
The engine includes built-in security protections:
|
|
473
|
+
|
|
474
|
+
- **Prototype Pollution Prevention**: Blocks `__proto__` and `constructor` namespace usage
|
|
475
|
+
- **Namespace Validation**: Ensures valid JavaScript identifiers
|
|
476
|
+
- **Reserved Namespace Protection**: Prevents conflicts with engine methods
|
|
477
|
+
- **Input Sanitization**: Validates service manifests and configurations
|
|
478
|
+
|
|
479
|
+
## API Reference
|
|
480
|
+
|
|
481
|
+
### Engine
|
|
482
|
+
|
|
483
|
+
#### `Engine.create(config?)`
|
|
484
|
+
Creates a new engine instance.
|
|
485
|
+
|
|
486
|
+
#### `engine.install(...services)`
|
|
487
|
+
Installs one or more services.
|
|
488
|
+
|
|
489
|
+
#### `engine.uninstall(...namespaces)`
|
|
490
|
+
Uninstalls services by namespace.
|
|
491
|
+
|
|
492
|
+
#### `engine.use(...definitions)`
|
|
493
|
+
Adds middleware or other definitions directly.
|
|
494
|
+
|
|
495
|
+
### ServiceProvider
|
|
496
|
+
|
|
497
|
+
#### `ServiceProvider.configure(options)`
|
|
498
|
+
Creates a configured service instance.
|
|
499
|
+
|
|
500
|
+
#### Static Properties
|
|
501
|
+
- `manifest` - Service metadata and configuration
|
|
502
|
+
|
|
503
|
+
#### Lifecycle Methods
|
|
504
|
+
- `actions(useContext, config)` - Define service actions
|
|
505
|
+
- `middleware(useContext, config)` - Define middleware functions
|
|
506
|
+
- `getters(useContext, config)` - Define read-only properties
|
|
507
|
+
- `initialize(useContext, config)` - Setup logic called directly
|
|
508
|
+
- `uninstall(useContext, config)` - Cleanup logic called directly
|
|
509
|
+
|
|
510
|
+
## Testing
|
|
511
|
+
|
|
512
|
+
The engine includes a comprehensive test suite:
|
|
513
|
+
|
|
514
|
+
```bash
|
|
515
|
+
# Run all tests
|
|
516
|
+
npm test
|
|
517
|
+
|
|
518
|
+
# Run tests in watch mode
|
|
519
|
+
npm run test:watch
|
|
520
|
+
|
|
521
|
+
# Run tests with coverage
|
|
522
|
+
npm run test:coverage
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
## Development
|
|
526
|
+
|
|
527
|
+
```bash
|
|
528
|
+
# Install dependencies
|
|
529
|
+
npm install
|
|
530
|
+
|
|
531
|
+
# Build the project
|
|
532
|
+
npm run build
|
|
533
|
+
|
|
534
|
+
# Watch for changes
|
|
535
|
+
npm run watch
|
|
536
|
+
|
|
537
|
+
# Run benchmarks
|
|
538
|
+
npm run bench
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
## License
|
|
542
|
+
|
|
543
|
+
MIT License with Commons Clause - See [LICENSE](LICENSE) file for details.
|
|
544
|
+
|
|
545
|
+
**TL;DR**: Free to use in your projects, but you cannot sell this software as a competing product or service.
|
package/dist/Engine.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export class Engine {
|
|
2
|
+
state: {
|
|
3
|
+
get(path: string[]): any;
|
|
4
|
+
set(path: string[], value: any): void;
|
|
5
|
+
update(path: string[], fn: (value: any) => any): void;
|
|
6
|
+
apply(path: string[], change: { to: any }): any;
|
|
7
|
+
keys(path?: string[]): string[];
|
|
8
|
+
loadState(path: string[], initialState: any): void;
|
|
9
|
+
};
|
|
10
|
+
reactors: {
|
|
11
|
+
create(id: string, fn: () => any, config?: any): any;
|
|
12
|
+
destroy(id: string): void;
|
|
13
|
+
};
|
|
14
|
+
subscribers: {
|
|
15
|
+
subscribe(path: string[], callback: (value: any) => void): void;
|
|
16
|
+
unsubscribe(path: string[], callback: (value: any) => void): void;
|
|
17
|
+
};
|
|
18
|
+
core: {
|
|
19
|
+
path: {
|
|
20
|
+
validate(path: string[]): string[];
|
|
21
|
+
resolve(path: string[]): string[];
|
|
22
|
+
};
|
|
23
|
+
dispatcher: {
|
|
24
|
+
notify(tag: string, type: string, previous: any, current: any): void;
|
|
25
|
+
};
|
|
26
|
+
tagger: {
|
|
27
|
+
register(path: string[]): string;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export class ServiceProvider {
|
|
2
|
+
static manifest: {
|
|
3
|
+
name: string;
|
|
4
|
+
dependencies: string[];
|
|
5
|
+
version: string;
|
|
6
|
+
description: string;
|
|
7
|
+
author: string;
|
|
8
|
+
license: string;
|
|
9
|
+
homepage: string;
|
|
10
|
+
repository: {
|
|
11
|
+
type: string;
|
|
12
|
+
url: string;
|
|
13
|
+
};
|
|
14
|
+
defaults: Record<string, any>;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
static markAsCore(token: symbol): void;
|
|
18
|
+
|
|
19
|
+
$services: any;
|
|
20
|
+
defineActions(engine: any, config: any): any;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const __INTERNAL_CORE_TOKEN: unique symbol;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var u={PRIMITIVE:0,OBJECT:1,ARRAY:2,RESERVED:3},A=class s{constructor(e){this.flags=0,e!==void 0&&(typeof e=="function"?this.flags|=1:typeof e=="object"&&e!==null&&!Array.isArray(e)?(this._children=new Map(Object.entries(e).map(([t,r])=>[t,new s(r)])),this.flags|=16,this.originalType=u.OBJECT):Array.isArray(e)?(this._children=new Map(e.map((t,r)=>[r,new s(t)])),this.flags|=16,this.originalType=u.ARRAY):(this.value=e,this.originalType=u.PRIMITIVE))}get isFunction(){return(this.flags&1)!==0}set isFunction(e){this.flags=e?this.flags|1:this.flags&-2}get isSetOnce(){return(this.flags&2)!==0}set isSetOnce(e){this.flags=e?this.flags|2:this.flags&-3}get cached(){return(this.flags&4)!==0}set cached(e){this.flags=e?this.flags|4:this.flags&-5}get executed(){return(this.flags&8)!==0}set executed(e){this.flags=e?this.flags|8:this.flags&-9}get hasChildrenFlag(){return(this.flags&16)!==0}set hasChildrenFlag(e){this.flags=e?this.flags|16:this.flags&-17}get isFixed(){return(this.flags&32)!==0}set isFixed(e){this.flags=e?this.flags|32:this.flags&-33}get originalType(){return this.flags>>6&3}set originalType(e){this.flags=this.flags&-193|(e&3)<<6}get children(){return this._children||(this._children=new Map,this.hasChildrenFlag=!0),this._children}hasChildren(){return this.hasChildrenFlag&&this._children&&this._children.size>0}get cachedResult(){return this._cachedResult}set cachedResult(e){this._cachedResult=e}get cachedAt(){return this._cachedAt}set cachedAt(e){this._cachedAt=e}get(e){let t=e.shift();if(t===void 0){if(this.flags&1){if((this.flags&6)===6)return this.cachedResult;let r=this.value();return this.flags&2&&(this.flags|=4,this.cachedResult=r,this.cachedAt=Date.now()),this.flags|=8,r}return this.value!==void 0?this.value:this.hasChildren()?this._reconstructFromChildren():void 0}if(this._children?.has(t))return this._children.get(t).get(e)}set(e,t){let r=e.shift();if(r===void 0){if(this.isFixed)throw new Error("Cannot overwrite fixed value at path. Use clearFixed() first if you need to modify it.");return typeof t=="object"&&t!==null&&!Array.isArray(t)&&typeof t!="function"?this._syncObjectChildren(t):Array.isArray(t)?this._syncArrayChildren(t):(this.value=t,this.flags=typeof t=="function"?1:0,this.originalType=u.PRIMITIVE),this}let n=this.children;return n.has(r)||n.set(r,new s),n.get(r).set(e,t),this}setOnce(e,t){let r=e.shift();if(r===void 0){if(this.isFixed)throw new Error("Cannot overwrite fixed value at path. Use clearFixed() first if you need to modify it.");return typeof t=="object"&&t!==null&&!Array.isArray(t)&&typeof t!="function"?(this._syncObjectChildren(t),this.flags=this.flags|2):Array.isArray(t)?(this._syncArrayChildren(t),this.flags=this.flags|2):(this.value=t,this.flags=typeof t=="function"?3:2,this.originalType=u.PRIMITIVE),this}let n=this.children;return n.has(r)||n.set(r,new s),n.get(r).setOnce(e,t),this}has(e){let t=e.shift();return t===void 0?this.value!==void 0:this._children?.has(t)?this._children.get(t).has(e):!1}remove(e){let t=e.shift();return t===void 0?(this.value=void 0,this.flags=this.flags&-16,this):(this._children?.has(t)&&this._children.get(t).remove(e),this)}clearCache(e){let t=e.shift();return t===void 0?(this.flags=this.flags&-5,this.cachedResult=null,this.cachedAt=null,this):(this._children?.has(t)&&this._children.get(t).clearCache(e),this)}fixed(e,t){let r=e.shift();if(r===void 0){if(this.value!==void 0&&this.isFixed)throw new Error("Value at path is already fixed and cannot be changed. Use clearFixed() first if needed.");return this.value=t,this.flags=(typeof t=="function"?1:0)|32,this}let n=this.children;return n.has(r)||n.set(r,new s),n.get(r).fixed(e,t),this}clearFixed(e){let t=e.shift();return t===void 0?this.isFixed?(this.flags=this.flags&-33,this):(console.warn("Attempted to clear fixed flag on non-fixed value"),this):(this._children?.has(t)&&this._children.get(t).clearFixed(e),this)}isFixedValue(e){let t=e.shift();return t===void 0?this.isFixed:this._children?.has(t)?this._children.get(t).isFixedValue(e):!1}_syncObjectChildren(e){let t=new Set(Object.keys(e)),r=new Set(this.children.keys());for(let n of r)t.has(n)||this.children.delete(n);for(let[n,i]of Object.entries(e))if(this.children.has(n)||this.children.set(n,new s),typeof i=="object"&&i!==null&&!Array.isArray(i)&&typeof i!="function")this.children.get(n)._syncObjectChildren(i);else if(Array.isArray(i))this.children.get(n)._syncArrayChildren(i);else{let o=this.children.get(n);o.value=i,o.flags=typeof i=="function"?1:0}this.value=void 0,this.flags=this.flags&-2,this.originalType=u.OBJECT}_syncArrayChildren(e){let t=new Set(e.map((n,i)=>i)),r=new Set(this.children.keys());for(let n of r)typeof n=="number"&&!t.has(n)&&this.children.delete(n);for(let n=0;n<e.length;n++){let i=e[n];if(this.children.has(n)||this.children.set(n,new s),typeof i=="object"&&i!==null&&!Array.isArray(i)&&typeof i!="function")this.children.get(n)._syncObjectChildren(i);else if(Array.isArray(i))this.children.get(n)._syncArrayChildren(i);else{let o=this.children.get(n);o.value=i,o.flags=typeof i=="function"?1:0}}this.value=void 0,this.flags=this.flags&-2,this.originalType=u.ARRAY}_reconstructFromChildren(){if(!this._children||this._children.size===0)return;if(this.originalType===u.ARRAY){let t=[];for(let[r,n]of this._children)typeof r=="number"&&(t[r]=n.get([]));return t}else{let t={};for(let[r,n]of this._children)t[r]=n.get([]);return t}}},x=class s{static create(e){return new s(e)}constructor(e={}){return this.load(e)}load(e){return this.root=new A(e),this}get(e){let t=Array.isArray(e)?[...e]:[e];return this.root.get(t)}update(e,t){let r=Array.isArray(e)?[...e]:[e],n=this.root.get([...r]),i=t(n);return this.root.set([...r],i),this}set(e,t){let r=Array.isArray(e)?[...e]:[e];return this.root.set(r,t),this}setOnce(e,t){let r=Array.isArray(e)?[...e]:[e];return this.root.setOnce(r,t),this}fixed(e,t){let r=Array.isArray(e)?[...e]:[e];return this.root.fixed(r,t),this}has(e){let t=Array.isArray(e)?[...e]:[e];return this.root.has(t)}remove(e){let t=Array.isArray(e)?[...e]:[e];return this.root.remove(t),this}clearCache(e){let t=Array.isArray(e)?[...e]:[e];return this.root.clearCache(t),this}clearFixed(e){let t=Array.isArray(e)?[...e]:[e];return this.root.clearFixed(t),this}isFixed(e){let t=Array.isArray(e)?[...e]:[e];return this.root.isFixedValue(t)}export(){return this._exportNode(this.root)}static import(e){let t=new s;return t.root=t._importNode(e),t}_exportNode(e){let t={flags:e.flags};if(e.isFunction)t.type="function",t.skipped=!0;else if(e.hasChildren()){t.type="map",t.value=[];for(let[r,n]of e._children)t.value.push([r,this._exportNode(n)]);e.value!==void 0&&(t.nodeValue=e.value)}else e.value!==void 0?(t.type="primitive",t.value=e.value):t.type="empty";return t}_importNode(e){let t=new A;switch(t.flags=e.flags||0,e.type){case"function":t.value=void 0,t.flags=t.flags&-16;break;case"primitive":t.value=e.value;break;case"map":if(e.value&&e.value.length>0){t._children=new Map;for(let[r,n]of e.value){let i=typeof r=="string"&&/^\d+$/.test(r)?parseInt(r,10):r;t._children.set(i,this._importNode(n))}t.hasChildrenFlag=!0}e.nodeValue!==void 0&&(t.value=e.nodeValue);break;case"empty":default:break}return t}};var d=Object.freeze(Object.create(null));function V(s){if(globalThis.queueMicrotask&&typeof globalThis.queueMicrotask=="function"){globalThis.queueMicrotask(s);return}setTimeout(s,0)}var _=class{#t;#e;constructor(e,t){this.#t=e,this.#e=t}on(e,t){return this.#e.subscribe(e,d,this.#t,t)}once(e,t){return this.#e.once(e,d,this.#t,t)}broadcast(e,...t){this.#e.publish(e,this.#t,d,t)}from(e){return{subscribe:(t,r)=>this.#e.subscribe(t,e,this.#t,r),once:(t,r)=>this.#e.once(t,e,this.#t,r)}}to(e){return{publish:(t,...r)=>this.#e.publish(t,this.#t,e,r),publishAsync:(t,...r)=>this.#e.publishAsync(t,this.#t,e,r)}}},b=class s{#t=new WeakMap;#e=new Map;#r=null;static create(e={}){return new s(e)}constructor({onError:e=null}={}){this.#r=e,this.createChannel(d)}channel(e){return this.createChannel(e)}createChannel(e){if(this.#t.has(e))return this.#t.get(e);let t=new _(e,this);return this.#t.set(e,t),t}#n(e){let t=this.#e.get(e);return t||(t=new Set,this.#e.set(e,t)),t}static#s(e,t){return e===d||t===d||e===t}static#i(e,t,r,n){return s.#s(e,r)&&s.#s(t,n)}subscribe(e,t,r,n){let i={from:t,to:r,handler:n};return this.#n(e).add(i),()=>{let o=this.#e.get(e);o&&o.delete(i)}}once(e,t,r,n){let i=null,o=c=>{try{n(c)}finally{i&&i()}};return i=this.subscribe(e,t,r,o),i}offAllFor(e){for(let t of this.#e.values())for(let r of Array.from(t))(r.from===e||r.to===e)&&t.delete(r)}listenerCount(e){let t=this.#e.get(e);return t?t.size:0}#o(e,t,r,n){let i=this.#e.get(e);if(!(!i||i.size===0)){for(let o of i)if(o.to!==t&&s.#i(t,r,o.from,o.to))try{o.handler(...n)}catch(c){this.#r&&this.#r(c,{event:e,from:t,to:r,listener:o})}}}publish(e,t,r,n){this.#o(e,t,r,n)}publishAsync(e,t,r,n){V(()=>this.#o(e,t,r,n))}broadcast(e,t,r){this.publish(e,t,d,r)}};var y={trace:10,debug:20,info:30,warn:40,error:50,silent:90},E=class s{static create(e={}){return new s(e)}#t;#e;#r;constructor({level:e="info",sinks:t=[],base:r={}}={}){this.#t=y[e]??y.info,this.#e=t,this.#r=r}setLevel(e){this.#t=y[e]??this.#t}child(e={},t=[]){return new s({level:this.level,sinks:[...this.#e,...t],base:{...this.#r,...e}})}get level(){return Object.entries(y).find(([e,t])=>t===this.#t)?.[0]??"info"}log(e,t,r={}){if((y[e]??y.info)<this.#t)return;let i={t:Date.now(),level:e,msg:t,...this.#r,...r};for(let o of this.#e)o(i)}trace(e,t){this.log("trace",e,t)}debug(e,t){this.log("debug",e,t)}info(e,t){this.log("info",e,t)}warn(e,t){this.log("warn",e,t)}error(e,t){this.log("error",e,t)}progress(e,t,r="",n={}){let i={t:Date.now(),type:"progress",level:"info",msg:r,current:e,total:t,message:r,percentage:Math.round(e/t*100),...this.#r,...n};for(let o of this.#e)o(i)}metric(e,t,r="ms",n={}){let i={t:Date.now(),type:"metric",level:"info",msg:`${e}: ${t}${r}`,name:e,value:t,unit:r,...this.#r,...n};for(let o of this.#e)o(i)}},j=s=>{let{t:e,level:t,msg:r,ns:n,...i}=s,o=new Date(e).toISOString(),c=t==="error"?console.error:t==="warn"?console.warn:console.log,a=`${n?`[${n}] `:""}${r}`;Object.keys(i).length>0?c(`[${o}] ${t.toUpperCase()} ${a}`,i):c(`[${o}] ${t.toUpperCase()} ${a}`)},N=(s=1e3)=>{let e=[];return{sink:t=>{e.push(t),e.length>s&&e.shift()},read:()=>e.slice(),clear:()=>{e.length=0}}};var I=new WeakMap,k=s=>{if(I.has(s))return I.get(s)};var w=s=>s&&s.constructor&&s.constructor.name==="AsyncFunction",M=(s,e)=>w(e)||s.some(w);var C=(s,e)=>e.length===0?s:e.length===1&&Array.isArray(e[0])?e[0]:e;var p=s=>s?Array.isArray(s)?s:[s]:[];var v=new Set(["__proto__","prototype","constructor"]),L=new Set(["use","install","uninstall","relay","state","debug"]),O=64,F=/^[a-zA-Z_$][a-zA-Z_$0-9]*$/;function R(s,e="key"){if(v.has(s))throw new Error(`Illegal key "${s}" in ${e}`)}function g(s){if(R(s,"namespace"),typeof s!="string")throw new Error(`Namespace must be a string, got ${typeof s}`);if(!F.test(s))throw new Error(`Invalid namespace "${s}". Must be a valid JS identifier`);if(s.length>O)throw new Error(`Namespace "${s}" too long (max ${O} chars)`);if(L.has(s))throw new Error(`Namespace "${s}" is reserved`);return s}function S(s,e,t="member"){if(R(s,`${t}:${e}`),typeof s!="string")throw new Error(`${t} name in ${e} must be a string`);if(!F.test(s))throw new Error(`Invalid ${t} name "${s}" in ${e}`);if(s.length>O)throw new Error(`${t} name "${s}" in ${e} too long (max ${O})`);return s}function T(s,e){if(!e||typeof e!="object")return e||s;if(!s||typeof s!="object")return e;let t={...s};for(let r in e)e.hasOwnProperty(r)&&(e[r]&&typeof e[r]=="object"&&!Array.isArray(e[r])&&s[r]&&typeof s[r]=="object"&&!Array.isArray(s[r])?t[r]=T(s[r],e[r]):t[r]=e[r]);return t}var D=()=>{let s=["DEVELOPMENT","TEST","DEV"];return typeof process<"u"&&process?.env?.NODE_ENV?s.includes(process.env.NODE_ENV.toUpperCase()):typeof globalThis<"u"&&globalThis.__ENV__?.NODE_ENV?s.includes(globalThis.__ENV__.NODE_ENV.toUpperCase()):!1};var P=class s{static options={};static create(e={}){return new s(e,s.options)}#t=new WeakMap;#e=new WeakMap;#r=new WeakMap;#n=new WeakMap;#s=new WeakMap;#i=void 0;#o={};#a=void 0;#l=void 0;#f=void 0;static configure(e){return e={...s.options,...e},{create:(t={})=>new s(t,e)}}constructor(e={},t=s.options){this.#i={...s.options,...t},this.#o={...e};for(let[r,n]of Object.entries(this.#o))Object.defineProperty(this,r,{value:n,enumerable:!0,configurable:!1,writable:!1});this.#f=x.create(),this.#a=b.create(),this.#l=E.create({level:D()?"debug":"info",sinks:[j,N(2e3).sink]})}get cache(){return this.#f}get relay(){return this.#a}get log(){return this.#l}use(...e){return this.#y(e,this)}install(...e){return this.#u(this,e)}#u(e,t){try{for(let n of t){if(!n.manifest?.namespace||!n.install)throw new Error(`${n.manifest?.name??"<unknown service>"} must have a namespace and install method`);if(Object.prototype.hasOwnProperty.call(e,n.manifest.namespace))throw new Error(`${n.manifest.namespace} already exists`);let i=T(this.#i||{},n.config||n.manifest.defaults||{}),o=this.#c(e,n.manifest.namespace),c=this.#m(e,n.manifest.namespace,o,i,n.manifest);if(n.manifest.dependencies?.length){let a=n.manifest.dependencies.filter(f=>f.unique),l=n.manifest.dependencies.filter(f=>!f.unique&&!Object.prototype.hasOwnProperty.call(e,f.manifest.namespace));a.length>0&&this.#u(c,a),l.length>0&&this.#u(e,l)}let h=this.#h(e,n.manifest.namespace,o,i,n.manifest);this.#y(n.install(h,i),e)}let r=this.#n.get(e);if(r?.size){for(let[n,i]of r)try{i()}finally{r.delete(n)}this.#n.delete(e)}return e}catch(r){throw r}}uninstall(...e){return this.#b(this,e)}#b(e,t){let r=this.#s.get(e),n=this.#t.get(e),i=this.#e.get(e),o=this.#d(e);for(let c of t)if(r?.get(c)?.(),r?.delete(c),o?.delete(c),this.#n.get(e)?.delete(c),Object.prototype.hasOwnProperty.call(e,c)&&delete e[c],n?.delete(c),i)for(let h of i.values())Object.prototype.hasOwnProperty.call(h,c)&&delete h[c];return r&&r.size===0&&this.#s.delete(e),this}#y(e,t=this){for(let r of e)if(r)switch(k(r)){case"MIDDLEWARE":this.#x(r,t);break;case"GETTERS":this.#A(r,t);break;case"ACTIONS":this.#w(r,t);break;case"INITIALIZE":this.#E(r,t);break;case"UNINSTALL":this.#C(r,t);break;default:throw new Error(`Unknown definition type: ${k(r)}`)}return this}#w(e,t=this){let r=g(e._name),n=this.#c(t,r),i=this.#h(t,r,n),o=e(i),c=this.#d(t).get(r)||[];for(let[h,a]of Object.entries(o)){if(h=S(h,r,"action"),Object.prototype.hasOwnProperty.call(n,h))throw new Error(`Action "${r}.${h}" already exists on this target`);let l=this.#O(r,h,a,n);if(c.length===0){n[h]=l;continue}let f=this.#$(c,l);n[h]=(...m)=>f(h,{namespace:r,action:h,args:m})}return this.#p(t,r,n)}#A(e,t=this){let r=g(e._name),n=this.#c(t,r),i=this.#h(t,r,n),o=e(i);for(let[c,h]of Object.entries(o)){S(c,r,"getter");let a=h.bind(n);Object.defineProperty(n,c,{get:()=>a(),enumerable:!0,configurable:!1})}return this.#p(t,r,n)}#x(e,t=this){let r=g(e._name),n=this.#c(t,r),i=this.#h(t,r,n),o=e(i),c=this.#d(t),h=c.get(r)||[],a=p(o).map(l=>{if(typeof l!="function")throw new Error("Middleware must be a function");return l});return c.set(r,h.concat(a)),this}#E(e,t=this){let r=g(e._name),n=this.#c(t,r),i=this.#h(t,r,n),o=()=>e(i),c=this.#n.get(t);return c||(c=new Map,this.#n.set(t,c)),c.set(r,o),this}#C(e,t=this){let r=g(e._name),n=this.#c(t,r),i=this.#h(t,r,n),o=()=>e(i),c=this.#s.get(t);return c||(c=new Map,this.#s.set(t,c)),c.set(r,o),this}#p(e,t,r){return Object.prototype.hasOwnProperty.call(e,t)?r=e[t]:Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!1}),this.#t.get(e)?.set(t,r),e}#O(e,t,r,n){let i=r.bind(n);return w(i)?async(...o)=>{try{return await i(...o)}catch(c){throw c.action=t,c.namespace=e,console.error(`Error in action "${e}.${t}":`,c),c}}:(...o)=>{try{return i(...o)}catch(c){throw c.action=t,c.namespace=e,console.error(`Error in action "${e}.${t}":`,c),c}}}#$(e,t){return M(p(e),t)?this.#k(e,t):this.#_(e,t)}#_(e,t){let r=p(e);return(n,i)=>{let o=-1,c=(h,a)=>{if(h<=o)throw new Error("next() called multiple times");o=h;let l=r[h];if(!l)return t(...a);let f={...i,args:a};return this.#g(l,n,f,(...m)=>{let $=C(a,m);return c(h+1,$)})};return c(0,i.args)}}#k(e,t){let r=p(e);return async(n,i)=>{let o=-1,c=async(h,a)=>{if(h<=o)throw new Error("next() called multiple times");o=h;let l=r[h];if(!l)return await t(...a);let f={...i,args:a};return await this.#g(l,n,f,(...m)=>{let $=C(a,m);return c(h+1,$)})};return c(0,i.args)}}#g(e,t,r,n){try{return e(t,r,n)}catch(i){throw i.middleware=e.name||"<anon>",i.action=t,i}}#d(e){let t=this.#r.get(e);return t||(t=new Map,this.#r.set(e,t)),t}#c(e,t){let r=this.#t.get(e);if(r||(r=new Map,this.#t.set(e,r)),r.has(t))return r.get(t);let n=Object.create(null);return r.set(t,n),n}#m(e,t,r,n=this.#i||{},i={}){let o=this.#e.get(e);if(o||(o=new Map,this.#e.set(e,o)),o.has(t))return o.get(t);let c={...this.#o,log:this.#l.child({ns:t},i.log?.sinks||[]),relay:this.#a.createChannel(r),cache:this.#f,config:n},h=new Proxy(c,{get(a,l,f){return l in a?Reflect.get(a,l,f):Reflect.get(e,l,f)},has(a,l){return l in a||l in e}});return o.set(t,h),h}#h(e,t,r,n=this.#i||{},i={}){return(...o)=>{let c=this.#m(e,t,r,n,i);if(!o||o.length===0)return c;if(o.length===1)return c[o[0]];let h=new Array(o.length);for(let a=0;a<o.length;a++)h[a]=c[o[a]];return h}}};export{P as Engine};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|