@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 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.
@@ -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