@pravosleva/reactive-engine 2.1.8-beta → 2.1.10-beta

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.
@@ -1 +1 @@
1
- {"version":3,"file":"core.method.effect.cjs","names":[],"sources":["../src/core/core.method.effect.ts"],"sourcesContent":["import { CleanupFn } from './types'\n\nexport function createEffect(\n engine: any,\n fn: () => void | CleanupFn,\n effectName?: string\n): () => void {\n const cleanups = new Set<CleanupFn>()\n const dependencies = new Set<any>()\n const depVersions = new Map<any, number>()\n\n // Список дочерних вложенных эффектов, созданных этим эффектом\n const ownedEffects = new Set<any>()\n\n const effectNode: any = {\n id: engine.subscriberId++,\n isDirty: true,\n depth: 1000,\n dependencies,\n depVersions,\n cleanups,\n ownedEffects,\n type: 'effect',\n isDisposed: false,\n run: () => {\n // Если эффект был принудительно уничтожен ДО старта фазы — выходим сразу\n if (effectNode.isDisposed) return\n if (effectNode === engine.activeConsumer) return\n\n const prevConsumer = engine.activeConsumer\n const prevOwner = engine.activeOwner\n\n // Переключаем глобальные контексты ядра на текущий эффект\n engine.activeConsumer = effectNode\n engine.activeOwner = effectNode\n\n const prevDeps = new Set(dependencies)\n dependencies.clear()\n\n try {\n // 🌳 Каскадно уничтожаем старых детей перед новым запуском\n ownedEffects.forEach(child => { if (child.dispose) child.dispose() })\n ownedEffects.clear()\n\n // Выполняем функции очистки (cleanups)\n engine.untrack(() => {\n cleanups.forEach(cb => { try { cb() } catch (err) { console.error(err) } })\n cleanups.clear()\n })\n\n // 🎯 ФИКС КЕЙСА #111 С УЧЕТОМ КОНТЕКСТА ВЛАДЕНИЯ:\n // Если во время вызова cleanups эффект уничтожил сам себя —\n // мы ОБЯЗАНЫ дать его телу выполниться в последний раз (чтобы инкрементировать счетчик),\n // но переводим сбор зависимостей в режим untracked, обнуляя активного консьюмера.\n if (effectNode.isDisposed) {\n engine.activeConsumer = null\n }\n\n // Выполнение тела эффекта\n const cleanup = fn()\n\n // Если эффект остался живым — сохраняем новые рёбра графа\n if (!effectNode.isDisposed) {\n if (typeof cleanup === 'function') cleanups.add(cleanup)\n effectNode.isDirty = false\n\n prevDeps.forEach(dep => {\n if (!dependencies.has(dep)) {\n dep.subscribers.delete(effectNode)\n depVersions.delete(dep)\n }\n })\n\n dependencies.forEach(dep => {\n const rawNode = dep._node || dep\n depVersions.set(dep, rawNode.version)\n })\n } else {\n // Если эффект умер на лету — тотально зачищаем все входящие связи\n prevDeps.forEach(dep => { dep.subscribers.delete(effectNode) })\n depVersions.clear()\n }\n\n engine.log({ type: 'effect', label: effectName || 'unnamed_effect' })\n } finally {\n engine.activeConsumer = prevConsumer\n engine.activeOwner = prevOwner\n }\n }\n }\n\n // Автоматическая регистрация в родительском контексте владения\n if (engine.activeOwner && engine.activeOwner.ownedEffects) {\n engine.activeOwner.ownedEffects.add(effectNode)\n }\n\n effectNode.run()\n\n const disposeFn = () => {\n // Позволяем вызывать метод даже если эффект в процессе выполнения,\n // но защищаем от повторного входа в базовую очистку\n const alreadyDisposed = effectNode.isDisposed\n effectNode.isDisposed = true\n\n // Каскадно уничтожаем всех вложенных детей\n ownedEffects.forEach(child => { if (child.dispose) child.dispose() })\n ownedEffects.clear()\n\n // Вызываем колбэки отписки только если это был первичный внешний вызов dispose\n if (!alreadyDisposed) {\n engine.untrack(() => {\n cleanups.forEach(cb => { try { cb() } catch (err) { console.error(err) } })\n cleanups.clear()\n })\n\n dependencies.forEach(dep => dep.subscribers.delete(effectNode))\n dependencies.clear()\n depVersions.clear()\n\n engine.pendingEffects.delete(effectNode)\n }\n }\n\n effectNode.dispose = disposeFn\n return disposeFn\n}\n"],"mappings":"AAEA,SAAgB,EACd,EACA,EACA,EACY,CACZ,IAAM,EAAW,IAAI,IACf,EAAe,IAAI,IACnB,EAAc,IAAI,IAGlB,EAAe,IAAI,IAEnB,EAAkB,CACtB,GAAI,EAAO,eACX,QAAS,GACT,MAAO,IACP,eACA,cACA,WACA,eACA,KAAM,SACN,WAAY,GACZ,QAAW,CAGT,GADI,EAAW,YACX,IAAe,EAAO,eAAgB,OAE1C,IAAM,EAAe,EAAO,eACtB,EAAY,EAAO,YAGzB,EAAO,eAAiB,EACxB,EAAO,YAAc,EAErB,IAAM,EAAW,IAAI,IAAI,CAAY,EACrC,EAAa,MAAM,EAEnB,GAAI,CAEF,EAAa,QAAQ,GAAS,CAAM,EAAM,SAAS,EAAM,QAAQ,CAAE,CAAC,EACpE,EAAa,MAAM,EAGnB,EAAO,YAAc,CACnB,EAAS,QAAQ,GAAM,CAAE,GAAI,CAAE,EAAG,CAAE,OAAS,EAAK,CAAE,QAAQ,MAAM,CAAG,CAAE,CAAE,CAAC,EAC1E,EAAS,MAAM,CACjB,CAAC,EAMG,EAAW,aACb,EAAO,eAAiB,MAI1B,IAAM,EAAU,EAAG,EAGd,EAAW,YAiBd,EAAS,QAAQ,GAAO,CAAE,EAAI,YAAY,OAAO,CAAU,CAAE,CAAC,EAC9D,EAAY,MAAM,IAjBd,OAAO,GAAY,YAAY,EAAS,IAAI,CAAO,EACvD,EAAW,QAAU,GAErB,EAAS,QAAQ,GAAO,CACjB,EAAa,IAAI,CAAG,IACvB,EAAI,YAAY,OAAO,CAAU,EACjC,EAAY,OAAO,CAAG,EAE1B,CAAC,EAED,EAAa,QAAQ,GAAO,CAC1B,IAAM,EAAU,EAAI,OAAS,EAC7B,EAAY,IAAI,EAAK,EAAQ,OAAO,CACtC,CAAC,GAOH,EAAO,IAAI,CAAE,KAAM,SAAU,MAAO,GAAc,gBAAiB,CAAC,CACtE,QAAU,CACR,EAAO,eAAiB,EACxB,EAAO,YAAc,CACvB,CACF,CACF,EAGI,EAAO,aAAe,EAAO,YAAY,cAC3C,EAAO,YAAY,aAAa,IAAI,CAAU,EAGhD,EAAW,IAAI,EAEf,IAAM,MAAkB,CAGtB,IAAM,EAAkB,EAAW,WACnC,EAAW,WAAa,GAGxB,EAAa,QAAQ,GAAS,CAAM,EAAM,SAAS,EAAM,QAAQ,CAAE,CAAC,EACpE,EAAa,MAAM,EAGd,IACH,EAAO,YAAc,CACnB,EAAS,QAAQ,GAAM,CAAE,GAAI,CAAE,EAAG,CAAE,OAAS,EAAK,CAAE,QAAQ,MAAM,CAAG,CAAE,CAAE,CAAC,EAC1E,EAAS,MAAM,CACjB,CAAC,EAED,EAAa,QAAQ,GAAO,EAAI,YAAY,OAAO,CAAU,CAAC,EAC9D,EAAa,MAAM,EACnB,EAAY,MAAM,EAElB,EAAO,eAAe,OAAO,CAAU,EAE3C,EAGA,MADA,GAAW,QAAU,EACd,CACT"}
1
+ {"version":3,"file":"core.method.effect.cjs","names":[],"sources":["../src/core/core.method.effect.ts"],"sourcesContent":["import { CleanupFn } from './types'\n\nexport function createEffect(\n engine: any,\n fn: () => void | CleanupFn,\n effectName?: string\n): () => void {\n const cleanups = new Set<CleanupFn>()\n const dependencies = new Set<any>()\n const depVersions = new Map<any, number>()\n\n // Список дочерних вложенных эффектов, созданных этим эффектом\n const ownedEffects = new Set<any>()\n\n const effectNode: any = {\n id: engine.subscriberId++,\n isDirty: true,\n depth: 1000,\n dependencies,\n depVersions,\n cleanups,\n ownedEffects,\n type: 'effect',\n isDisposed: false,\n run: () => {\n // Если эффект был принудительно уничтожен ДО старта фазы — выходим сразу\n if (effectNode.isDisposed) return\n if (effectNode === engine.activeConsumer) return\n\n const prevConsumer = engine.activeConsumer\n const prevOwner = engine.activeOwner\n\n // Переключаем глобальные контексты ядра на текущий эффект\n engine.activeConsumer = effectNode\n engine.activeOwner = effectNode\n\n const prevDeps = new Set(dependencies)\n dependencies.clear()\n\n try {\n // 🌳 Каскадно уничтожаем старых детей перед новым запуском\n ownedEffects.forEach(child => { if (child.dispose) child.dispose() })\n ownedEffects.clear()\n\n // Выполняем функции очистки (cleanups)\n engine.untrack(() => {\n cleanups.forEach(cb => { try { cb() } catch (err) { console.error(err) } })\n cleanups.clear()\n })\n\n // 🎯 ФИКС КЕЙСА #111 С УЧЕТОМ КОНТЕКСТА ВЛАДЕНИЯ:\n // Если во время вызова cleanups эффект уничтожил сам себя —\n // мы ОБЯЗАНЫ дать его телу выполниться в последний раз (чтобы инкрементировать счетчик),\n // но переводим сбор зависимостей в режим untracked, обнуляя активного консьюмера.\n if (effectNode.isDisposed) {\n engine.activeConsumer = null\n }\n\n // Выполнение тела эффекта\n const cleanup = fn()\n\n // Если эффект остался живым — сохраняем новые рёбра графа\n if (!effectNode.isDisposed) {\n if (typeof cleanup === 'function') cleanups.add(cleanup)\n effectNode.isDirty = false\n\n prevDeps.forEach(dep => {\n if (!dependencies.has(dep)) {\n dep.subscribers.delete(effectNode)\n depVersions.delete(dep)\n }\n })\n\n dependencies.forEach(dep => {\n const rawNode = dep._node || dep\n depVersions.set(dep, rawNode.version)\n })\n } else {\n // Если эффект умер на лету — тотально зачищаем все входящие связи\n prevDeps.forEach(dep => { dep.subscribers.delete(effectNode) })\n depVersions.clear()\n }\n\n engine.log({ type: 'effect', label: effectName || 'unnamed_effect' })\n } finally {\n engine.activeConsumer = prevConsumer\n engine.activeOwner = prevOwner\n }\n }\n }\n\n // Автоматическая регистрация в родительском контексте владения (Effect или Computed)\n if (engine.activeOwner && engine.activeOwner.ownedEffects) {\n engine.activeOwner.ownedEffects.add(effectNode)\n }\n\n\n effectNode.run()\n\n const disposeFn = () => {\n // Позволяем вызывать метод даже если эффект в процессе выполнения,\n // но защищаем от повторного входа в базовую очистку\n const alreadyDisposed = effectNode.isDisposed\n effectNode.isDisposed = true\n\n // Каскадно уничтожаем всех вложенных детей\n ownedEffects.forEach(child => { if (child.dispose) child.dispose() })\n ownedEffects.clear()\n\n // Вызываем колбэки отписки только если это был первичный внешний вызов dispose\n if (!alreadyDisposed) {\n engine.untrack(() => {\n cleanups.forEach(cb => { try { cb() } catch (err) { console.error(err) } })\n cleanups.clear()\n })\n\n dependencies.forEach(dep => dep.subscribers.delete(effectNode))\n dependencies.clear()\n depVersions.clear()\n\n engine.pendingEffects.delete(effectNode)\n }\n }\n\n effectNode.dispose = disposeFn\n return disposeFn\n}\n"],"mappings":"AAEA,SAAgB,EACd,EACA,EACA,EACY,CACZ,IAAM,EAAW,IAAI,IACf,EAAe,IAAI,IACnB,EAAc,IAAI,IAGlB,EAAe,IAAI,IAEnB,EAAkB,CACtB,GAAI,EAAO,eACX,QAAS,GACT,MAAO,IACP,eACA,cACA,WACA,eACA,KAAM,SACN,WAAY,GACZ,QAAW,CAGT,GADI,EAAW,YACX,IAAe,EAAO,eAAgB,OAE1C,IAAM,EAAe,EAAO,eACtB,EAAY,EAAO,YAGzB,EAAO,eAAiB,EACxB,EAAO,YAAc,EAErB,IAAM,EAAW,IAAI,IAAI,CAAY,EACrC,EAAa,MAAM,EAEnB,GAAI,CAEF,EAAa,QAAQ,GAAS,CAAM,EAAM,SAAS,EAAM,QAAQ,CAAE,CAAC,EACpE,EAAa,MAAM,EAGnB,EAAO,YAAc,CACnB,EAAS,QAAQ,GAAM,CAAE,GAAI,CAAE,EAAG,CAAE,OAAS,EAAK,CAAE,QAAQ,MAAM,CAAG,CAAE,CAAE,CAAC,EAC1E,EAAS,MAAM,CACjB,CAAC,EAMG,EAAW,aACb,EAAO,eAAiB,MAI1B,IAAM,EAAU,EAAG,EAGd,EAAW,YAiBd,EAAS,QAAQ,GAAO,CAAE,EAAI,YAAY,OAAO,CAAU,CAAE,CAAC,EAC9D,EAAY,MAAM,IAjBd,OAAO,GAAY,YAAY,EAAS,IAAI,CAAO,EACvD,EAAW,QAAU,GAErB,EAAS,QAAQ,GAAO,CACjB,EAAa,IAAI,CAAG,IACvB,EAAI,YAAY,OAAO,CAAU,EACjC,EAAY,OAAO,CAAG,EAE1B,CAAC,EAED,EAAa,QAAQ,GAAO,CAC1B,IAAM,EAAU,EAAI,OAAS,EAC7B,EAAY,IAAI,EAAK,EAAQ,OAAO,CACtC,CAAC,GAOH,EAAO,IAAI,CAAE,KAAM,SAAU,MAAO,GAAc,gBAAiB,CAAC,CACtE,QAAU,CACR,EAAO,eAAiB,EACxB,EAAO,YAAc,CACvB,CACF,CACF,EAGI,EAAO,aAAe,EAAO,YAAY,cAC3C,EAAO,YAAY,aAAa,IAAI,CAAU,EAIhD,EAAW,IAAI,EAEf,IAAM,MAAkB,CAGtB,IAAM,EAAkB,EAAW,WACnC,EAAW,WAAa,GAGxB,EAAa,QAAQ,GAAS,CAAM,EAAM,SAAS,EAAM,QAAQ,CAAE,CAAC,EACpE,EAAa,MAAM,EAGd,IACH,EAAO,YAAc,CACnB,EAAS,QAAQ,GAAM,CAAE,GAAI,CAAE,EAAG,CAAE,OAAS,EAAK,CAAE,QAAQ,MAAM,CAAG,CAAE,CAAE,CAAC,EAC1E,EAAS,MAAM,CACjB,CAAC,EAED,EAAa,QAAQ,GAAO,EAAI,YAAY,OAAO,CAAU,CAAC,EAC9D,EAAa,MAAM,EACnB,EAAY,MAAM,EAElB,EAAO,eAAe,OAAO,CAAU,EAE3C,EAGA,MADA,GAAW,QAAU,EACd,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"core.method.effect.mjs","names":[],"sources":["../src/core/core.method.effect.ts"],"sourcesContent":["import { CleanupFn } from './types'\n\nexport function createEffect(\n engine: any,\n fn: () => void | CleanupFn,\n effectName?: string\n): () => void {\n const cleanups = new Set<CleanupFn>()\n const dependencies = new Set<any>()\n const depVersions = new Map<any, number>()\n\n // Список дочерних вложенных эффектов, созданных этим эффектом\n const ownedEffects = new Set<any>()\n\n const effectNode: any = {\n id: engine.subscriberId++,\n isDirty: true,\n depth: 1000,\n dependencies,\n depVersions,\n cleanups,\n ownedEffects,\n type: 'effect',\n isDisposed: false,\n run: () => {\n // Если эффект был принудительно уничтожен ДО старта фазы — выходим сразу\n if (effectNode.isDisposed) return\n if (effectNode === engine.activeConsumer) return\n\n const prevConsumer = engine.activeConsumer\n const prevOwner = engine.activeOwner\n\n // Переключаем глобальные контексты ядра на текущий эффект\n engine.activeConsumer = effectNode\n engine.activeOwner = effectNode\n\n const prevDeps = new Set(dependencies)\n dependencies.clear()\n\n try {\n // 🌳 Каскадно уничтожаем старых детей перед новым запуском\n ownedEffects.forEach(child => { if (child.dispose) child.dispose() })\n ownedEffects.clear()\n\n // Выполняем функции очистки (cleanups)\n engine.untrack(() => {\n cleanups.forEach(cb => { try { cb() } catch (err) { console.error(err) } })\n cleanups.clear()\n })\n\n // 🎯 ФИКС КЕЙСА #111 С УЧЕТОМ КОНТЕКСТА ВЛАДЕНИЯ:\n // Если во время вызова cleanups эффект уничтожил сам себя —\n // мы ОБЯЗАНЫ дать его телу выполниться в последний раз (чтобы инкрементировать счетчик),\n // но переводим сбор зависимостей в режим untracked, обнуляя активного консьюмера.\n if (effectNode.isDisposed) {\n engine.activeConsumer = null\n }\n\n // Выполнение тела эффекта\n const cleanup = fn()\n\n // Если эффект остался живым — сохраняем новые рёбра графа\n if (!effectNode.isDisposed) {\n if (typeof cleanup === 'function') cleanups.add(cleanup)\n effectNode.isDirty = false\n\n prevDeps.forEach(dep => {\n if (!dependencies.has(dep)) {\n dep.subscribers.delete(effectNode)\n depVersions.delete(dep)\n }\n })\n\n dependencies.forEach(dep => {\n const rawNode = dep._node || dep\n depVersions.set(dep, rawNode.version)\n })\n } else {\n // Если эффект умер на лету — тотально зачищаем все входящие связи\n prevDeps.forEach(dep => { dep.subscribers.delete(effectNode) })\n depVersions.clear()\n }\n\n engine.log({ type: 'effect', label: effectName || 'unnamed_effect' })\n } finally {\n engine.activeConsumer = prevConsumer\n engine.activeOwner = prevOwner\n }\n }\n }\n\n // Автоматическая регистрация в родительском контексте владения\n if (engine.activeOwner && engine.activeOwner.ownedEffects) {\n engine.activeOwner.ownedEffects.add(effectNode)\n }\n\n effectNode.run()\n\n const disposeFn = () => {\n // Позволяем вызывать метод даже если эффект в процессе выполнения,\n // но защищаем от повторного входа в базовую очистку\n const alreadyDisposed = effectNode.isDisposed\n effectNode.isDisposed = true\n\n // Каскадно уничтожаем всех вложенных детей\n ownedEffects.forEach(child => { if (child.dispose) child.dispose() })\n ownedEffects.clear()\n\n // Вызываем колбэки отписки только если это был первичный внешний вызов dispose\n if (!alreadyDisposed) {\n engine.untrack(() => {\n cleanups.forEach(cb => { try { cb() } catch (err) { console.error(err) } })\n cleanups.clear()\n })\n\n dependencies.forEach(dep => dep.subscribers.delete(effectNode))\n dependencies.clear()\n depVersions.clear()\n\n engine.pendingEffects.delete(effectNode)\n }\n }\n\n effectNode.dispose = disposeFn\n return disposeFn\n}\n"],"mappings":";AAEA,SAAgB,EACd,GACA,GACA,GACY;CACZ,IAAM,oBAAW,IAAI,IAAe,GAC9B,oBAAe,IAAI,IAAS,GAC5B,oBAAc,IAAI,IAAiB,GAGnC,oBAAe,IAAI,IAAS,GAE5B,IAAkB;EACtB,IAAI,EAAO;EACX,SAAS;EACT,OAAO;EACP;EACA;EACA;EACA;EACA,MAAM;EACN,YAAY;EACZ,WAAW;GAGT,IADI,EAAW,cACX,MAAe,EAAO,gBAAgB;GAE1C,IAAM,IAAe,EAAO,gBACtB,IAAY,EAAO;GAIzB,AADA,EAAO,iBAAiB,GACxB,EAAO,cAAc;GAErB,IAAM,IAAW,IAAI,IAAI,CAAY;GACrC,EAAa,MAAM;GAEnB,IAAI;IAeF,AAbA,EAAa,SAAQ,MAAS;KAAE,AAAI,EAAM,WAAS,EAAM,QAAQ;IAAE,CAAC,GACpE,EAAa,MAAM,GAGnB,EAAO,cAAc;KAEnB,AADA,EAAS,SAAQ,MAAM;MAAE,IAAI;OAAE,EAAG;MAAE,SAAS,GAAK;OAAE,QAAQ,MAAM,CAAG;MAAE;KAAE,CAAC,GAC1E,EAAS,MAAM;IACjB,CAAC,GAMG,EAAW,eACb,EAAO,iBAAiB;IAI1B,IAAM,IAAU,EAAG;IAwBnB,AArBK,EAAW,cAiBd,EAAS,SAAQ,MAAO;KAAE,EAAI,YAAY,OAAO,CAAU;IAAE,CAAC,GAC9D,EAAY,MAAM,MAjBd,OAAO,KAAY,cAAY,EAAS,IAAI,CAAO,GACvD,EAAW,UAAU,IAErB,EAAS,SAAQ,MAAO;KACtB,AAAK,EAAa,IAAI,CAAG,MACvB,EAAI,YAAY,OAAO,CAAU,GACjC,EAAY,OAAO,CAAG;IAE1B,CAAC,GAED,EAAa,SAAQ,MAAO;KAC1B,IAAM,IAAU,EAAI,SAAS;KAC7B,EAAY,IAAI,GAAK,EAAQ,OAAO;IACtC,CAAC,IAOH,EAAO,IAAI;KAAE,MAAM;KAAU,OAAO,KAAc;IAAiB,CAAC;GACtE,UAAU;IAER,AADA,EAAO,iBAAiB,GACxB,EAAO,cAAc;GACvB;EACF;CACF;CAOA,AAJI,EAAO,eAAe,EAAO,YAAY,gBAC3C,EAAO,YAAY,aAAa,IAAI,CAAU,GAGhD,EAAW,IAAI;CAEf,IAAM,UAAkB;EAGtB,IAAM,IAAkB,EAAW;EAQnC,AAPA,EAAW,aAAa,IAGxB,EAAa,SAAQ,MAAS;GAAE,AAAI,EAAM,WAAS,EAAM,QAAQ;EAAE,CAAC,GACpE,EAAa,MAAM,GAGd,MACH,EAAO,cAAc;GAEnB,AADA,EAAS,SAAQ,MAAM;IAAE,IAAI;KAAE,EAAG;IAAE,SAAS,GAAK;KAAE,QAAQ,MAAM,CAAG;IAAE;GAAE,CAAC,GAC1E,EAAS,MAAM;EACjB,CAAC,GAED,EAAa,SAAQ,MAAO,EAAI,YAAY,OAAO,CAAU,CAAC,GAC9D,EAAa,MAAM,GACnB,EAAY,MAAM,GAElB,EAAO,eAAe,OAAO,CAAU;CAE3C;CAGA,OADA,EAAW,UAAU,GACd;AACT"}
1
+ {"version":3,"file":"core.method.effect.mjs","names":[],"sources":["../src/core/core.method.effect.ts"],"sourcesContent":["import { CleanupFn } from './types'\n\nexport function createEffect(\n engine: any,\n fn: () => void | CleanupFn,\n effectName?: string\n): () => void {\n const cleanups = new Set<CleanupFn>()\n const dependencies = new Set<any>()\n const depVersions = new Map<any, number>()\n\n // Список дочерних вложенных эффектов, созданных этим эффектом\n const ownedEffects = new Set<any>()\n\n const effectNode: any = {\n id: engine.subscriberId++,\n isDirty: true,\n depth: 1000,\n dependencies,\n depVersions,\n cleanups,\n ownedEffects,\n type: 'effect',\n isDisposed: false,\n run: () => {\n // Если эффект был принудительно уничтожен ДО старта фазы — выходим сразу\n if (effectNode.isDisposed) return\n if (effectNode === engine.activeConsumer) return\n\n const prevConsumer = engine.activeConsumer\n const prevOwner = engine.activeOwner\n\n // Переключаем глобальные контексты ядра на текущий эффект\n engine.activeConsumer = effectNode\n engine.activeOwner = effectNode\n\n const prevDeps = new Set(dependencies)\n dependencies.clear()\n\n try {\n // 🌳 Каскадно уничтожаем старых детей перед новым запуском\n ownedEffects.forEach(child => { if (child.dispose) child.dispose() })\n ownedEffects.clear()\n\n // Выполняем функции очистки (cleanups)\n engine.untrack(() => {\n cleanups.forEach(cb => { try { cb() } catch (err) { console.error(err) } })\n cleanups.clear()\n })\n\n // 🎯 ФИКС КЕЙСА #111 С УЧЕТОМ КОНТЕКСТА ВЛАДЕНИЯ:\n // Если во время вызова cleanups эффект уничтожил сам себя —\n // мы ОБЯЗАНЫ дать его телу выполниться в последний раз (чтобы инкрементировать счетчик),\n // но переводим сбор зависимостей в режим untracked, обнуляя активного консьюмера.\n if (effectNode.isDisposed) {\n engine.activeConsumer = null\n }\n\n // Выполнение тела эффекта\n const cleanup = fn()\n\n // Если эффект остался живым — сохраняем новые рёбра графа\n if (!effectNode.isDisposed) {\n if (typeof cleanup === 'function') cleanups.add(cleanup)\n effectNode.isDirty = false\n\n prevDeps.forEach(dep => {\n if (!dependencies.has(dep)) {\n dep.subscribers.delete(effectNode)\n depVersions.delete(dep)\n }\n })\n\n dependencies.forEach(dep => {\n const rawNode = dep._node || dep\n depVersions.set(dep, rawNode.version)\n })\n } else {\n // Если эффект умер на лету — тотально зачищаем все входящие связи\n prevDeps.forEach(dep => { dep.subscribers.delete(effectNode) })\n depVersions.clear()\n }\n\n engine.log({ type: 'effect', label: effectName || 'unnamed_effect' })\n } finally {\n engine.activeConsumer = prevConsumer\n engine.activeOwner = prevOwner\n }\n }\n }\n\n // Автоматическая регистрация в родительском контексте владения (Effect или Computed)\n if (engine.activeOwner && engine.activeOwner.ownedEffects) {\n engine.activeOwner.ownedEffects.add(effectNode)\n }\n\n\n effectNode.run()\n\n const disposeFn = () => {\n // Позволяем вызывать метод даже если эффект в процессе выполнения,\n // но защищаем от повторного входа в базовую очистку\n const alreadyDisposed = effectNode.isDisposed\n effectNode.isDisposed = true\n\n // Каскадно уничтожаем всех вложенных детей\n ownedEffects.forEach(child => { if (child.dispose) child.dispose() })\n ownedEffects.clear()\n\n // Вызываем колбэки отписки только если это был первичный внешний вызов dispose\n if (!alreadyDisposed) {\n engine.untrack(() => {\n cleanups.forEach(cb => { try { cb() } catch (err) { console.error(err) } })\n cleanups.clear()\n })\n\n dependencies.forEach(dep => dep.subscribers.delete(effectNode))\n dependencies.clear()\n depVersions.clear()\n\n engine.pendingEffects.delete(effectNode)\n }\n }\n\n effectNode.dispose = disposeFn\n return disposeFn\n}\n"],"mappings":";AAEA,SAAgB,EACd,GACA,GACA,GACY;CACZ,IAAM,oBAAW,IAAI,IAAe,GAC9B,oBAAe,IAAI,IAAS,GAC5B,oBAAc,IAAI,IAAiB,GAGnC,oBAAe,IAAI,IAAS,GAE5B,IAAkB;EACtB,IAAI,EAAO;EACX,SAAS;EACT,OAAO;EACP;EACA;EACA;EACA;EACA,MAAM;EACN,YAAY;EACZ,WAAW;GAGT,IADI,EAAW,cACX,MAAe,EAAO,gBAAgB;GAE1C,IAAM,IAAe,EAAO,gBACtB,IAAY,EAAO;GAIzB,AADA,EAAO,iBAAiB,GACxB,EAAO,cAAc;GAErB,IAAM,IAAW,IAAI,IAAI,CAAY;GACrC,EAAa,MAAM;GAEnB,IAAI;IAeF,AAbA,EAAa,SAAQ,MAAS;KAAE,AAAI,EAAM,WAAS,EAAM,QAAQ;IAAE,CAAC,GACpE,EAAa,MAAM,GAGnB,EAAO,cAAc;KAEnB,AADA,EAAS,SAAQ,MAAM;MAAE,IAAI;OAAE,EAAG;MAAE,SAAS,GAAK;OAAE,QAAQ,MAAM,CAAG;MAAE;KAAE,CAAC,GAC1E,EAAS,MAAM;IACjB,CAAC,GAMG,EAAW,eACb,EAAO,iBAAiB;IAI1B,IAAM,IAAU,EAAG;IAwBnB,AArBK,EAAW,cAiBd,EAAS,SAAQ,MAAO;KAAE,EAAI,YAAY,OAAO,CAAU;IAAE,CAAC,GAC9D,EAAY,MAAM,MAjBd,OAAO,KAAY,cAAY,EAAS,IAAI,CAAO,GACvD,EAAW,UAAU,IAErB,EAAS,SAAQ,MAAO;KACtB,AAAK,EAAa,IAAI,CAAG,MACvB,EAAI,YAAY,OAAO,CAAU,GACjC,EAAY,OAAO,CAAG;IAE1B,CAAC,GAED,EAAa,SAAQ,MAAO;KAC1B,IAAM,IAAU,EAAI,SAAS;KAC7B,EAAY,IAAI,GAAK,EAAQ,OAAO;IACtC,CAAC,IAOH,EAAO,IAAI;KAAE,MAAM;KAAU,OAAO,KAAc;IAAiB,CAAC;GACtE,UAAU;IAER,AADA,EAAO,iBAAiB,GACxB,EAAO,cAAc;GACvB;EACF;CACF;CAQA,AALI,EAAO,eAAe,EAAO,YAAY,gBAC3C,EAAO,YAAY,aAAa,IAAI,CAAU,GAIhD,EAAW,IAAI;CAEf,IAAM,UAAkB;EAGtB,IAAM,IAAkB,EAAW;EAQnC,AAPA,EAAW,aAAa,IAGxB,EAAa,SAAQ,MAAS;GAAE,AAAI,EAAM,WAAS,EAAM,QAAQ;EAAE,CAAC,GACpE,EAAa,MAAM,GAGd,MACH,EAAO,cAAc;GAEnB,AADA,EAAS,SAAQ,MAAM;IAAE,IAAI;KAAE,EAAG;IAAE,SAAS,GAAK;KAAE,QAAQ,MAAM,CAAG;IAAE;GAAE,CAAC,GAC1E,EAAS,MAAM;EACjB,CAAC,GAED,EAAa,SAAQ,MAAO,EAAI,YAAY,OAAO,CAAU,CAAC,GAC9D,EAAa,MAAM,GACnB,EAAY,MAAM,GAElB,EAAO,eAAe,OAAO,CAAU;CAE3C;CAGA,OADA,EAAW,UAAU,GACd;AACT"}
package/dist/core.mjs CHANGED
@@ -110,7 +110,7 @@ var f = class {
110
110
  if (t.isDirty) try {
111
111
  t.run();
112
112
  } catch (e) {
113
- if (this.batchDepth === 0) throw e;
113
+ throw e;
114
114
  }
115
115
  }
116
116
  } finally {
package/dist/core.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.mjs","names":[],"sources":["../src/core/core.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Signal, Computed, IEffect, EngineLoggerOptions, LogEventType, CleanupFn, TransactionContext, LogRecord, SignalOptions, ResourceOptions, ResourceState, Resource } from './types'\nimport { createComputed } from './core.method.computed'\nimport { createSignal } from './core.method.signal'\nimport { executeBatch } from './core.method.batch'\nimport { executeUntrack } from './core.method.untrack'\nimport { createReactive } from './core.method.reactive'\nimport { createEffect } from './core.method.effect'\nimport { ReactiveDebounceLogger } from './core.logger'\n\n// Тип для конструктора класса\ntype Constructor<T> = new (...args: any[]) => T\n// Тип для фабричной функции зависимостей\ntype Factory<T> = (engine: any) => T\n// Универсальный тип токена DI\ntype InjectionToken<T> = Constructor<T> | Factory<T> | symbol | string\n\nconst badgeColors: Record<LogEventType, string> = {\n signal: 'background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n computed: 'background: #42b883; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n effect: 'background: #e01e5a; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n batch: 'background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n resource: 'background: #d97706; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n reactive: 'background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;'\n}\nlet currentTransaction: TransactionContext | null = null\nfunction safeValueToString(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value)\n } catch (e) {\n return '[Cyclic Object or Layer]'\n }\n }\n return String(value)\n}\nexport function queueLog(type: LogEventType, label: string, details?: { from?: unknown; to?: unknown; payload?: unknown }): void {\n if (!currentTransaction) {\n currentTransaction = { id: Math.random().toString(36).substring(2, 9), pendingLogQueue: [], isFlushing: false }\n queueMicrotask(() => flushLogs())\n }\n currentTransaction.pendingLogQueue.push({ type, label, from: details?.from, to: details?.to, payload: details?.payload, timestamp: Date.now() })\n}\nexport function flushLogs(): void {\n if (!currentTransaction || currentTransaction.isFlushing) return\n currentTransaction.isFlushing = true\n const queue = currentTransaction.pendingLogQueue\n if (queue.length === 0) {\n currentTransaction = null\n return\n }\n console.groupCollapsed(`%cREACTIVE TRANSACTION%c [id: ${currentTransaction.id}] (${queue.length} operations)`, 'background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;', 'color: #888; font-weight: normal;')\n for (const record of queue) {\n const colorStyle = badgeColors[record.type]\n const hasTransition = record.from !== undefined || record.to !== undefined\n let logMessage = `%c${record.type.toUpperCase()}%c ${record.label}`\n\n if (hasTransition) {\n if (!!record.from)\n logMessage += ` ${safeValueToString(record.from)} → ${safeValueToString(record.to)}`\n else logMessage += ` (${safeValueToString(record.to)})`\n }\n\n if (record.payload !== undefined) {\n console.groupCollapsed(logMessage, colorStyle, 'color: inherit;')\n console.log('Payload:', record.payload)\n console.groupEnd()\n } else {\n console.log(logMessage, colorStyle, 'color: inherit;')\n }\n }\n console.groupEnd()\n currentTransaction = null\n}\nexport class ReactiveEngineCore {\n protected frameworkPrefix = 'core'\n private logger: EngineLoggerOptions\n public epoch = 0\n public activeConsumer: any = null\n public batchDepth = 0\n public subscriberId = 0\n public pendingEffects = new Set<any>()\n public computedCache = new Map<Function, WeakRef<Computed<unknown>>>()\n private diRegistry = new Map<unknown, unknown>()\n private diCache = new Map<unknown, unknown>()\n private proxyCache = new WeakMap<object, any>()\n private proxyTargets = new WeakSet<object>()\n private reactiveSignals = new WeakMap<object, Map<string | symbol, any>>()\n private cycleDetectionStack = new Set<unknown>()\n public batchedSignals = new Set<any>()\n public activeOwner: any = null\n\n constructor(options?: { logger?: EngineLoggerOptions }) {\n this.logger = options?.logger || { isEnabled: false }\n }\n\n public queueLog(type: LogEventType, label: string, details?: { from?: unknown; to?: unknown; payload?: unknown }): void {\n queueLog(type, label, details)\n }\n\n public batch<T>(fn: () => T): T {\n this.batchDepth++\n try {\n return fn()\n } finally {\n this.batchDepth--\n if (this.batchDepth === 0) {\n // 🚀 АТOМАРНЫЙ КOММИТ ТРАНЗАКЦИИ\n const signalsToFlush = Array.from(this.batchedSignals)\n this.batchedSignals.clear()\n\n // Сначала фиксируем финальные версии всех изменившихся сигналов\n signalsToFlush.forEach(sig => {\n if (sig._flushBatch) sig._flushBatch()\n })\n\n // Затем одной топологической волной запускаем эффекты\n this.flushEffects()\n }\n }\n }\n\n public flushEffects(): void {\n if (this.batchDepth > 0) return\n\n const effects = Array.from(this.pendingEffects)\n this.pendingEffects.clear()\n\n // Гарантируем строгий топологический порядок выполнения эффектов\n effects.sort((a, b) => (a.depth || 0) - (b.depth || 0) || a.id - b.id)\n\n const prevConsumer = this.activeConsumer\n\n try {\n for (const effect of effects) {\n if (effect.isDisposed) continue\n\n // Рекурсивный pull-анализ версий родителей перед запуском эффекта\n if (effect.dependencies && effect.dependencies.size > 0) {\n let parentChanged = false\n for (const dep of effect.dependencies) {\n const rawNode = dep._node || dep\n if (rawNode.type === 'computed' && rawNode.state > 0) {\n if (rawNode.update) rawNode.update()\n }\n if (effect.depVersions && effect.depVersions.get(dep) !== rawNode.version) {\n parentChanged = true\n }\n }\n // Value Equality Cut: Если предки стабильны, гасим эффект\n if (!parentChanged && effect.dependencies.size > 0) {\n effect.isDirty = false\n continue\n }\n }\n\n if (!effect.isDirty) continue\n\n try {\n effect.run()\n } catch (err) {\n if (this.batchDepth === 0) throw err\n }\n }\n } finally {\n this.activeConsumer = prevConsumer\n }\n }\n\n // public batch<T>(fn: () => T): T {\n // return executeBatch<T>(this, fn)\n // }\n\n private log ({ type, label, details, isInternalCoreSignal = false }: { type: LogEventType, label: string, details?: { from?: unknown; to?: unknown; payload?: unknown }, isInternalCoreSignal?: boolean }) {\n ReactiveDebounceLogger.processLog(this.logger, queueLog, {\n type,\n label,\n details,\n isInternalCoreSignal\n })\n }\n\n public signal<T>(initialValue: T, optionsOrName?: string | SignalOptions<T>): Signal<T> {\n return createSignal<T>(this, initialValue, optionsOrName)\n }\n\n public computed<T>(fn: () => T, signalName?: string): Computed<T> {\n // Просто делегируем вызов строго изолированной чистой функции\n return createComputed<T>(this, fn, signalName)\n }\n\n public effect(fn: () => void | CleanupFn, effectName?: string): () => void {\n return createEffect(this, fn, effectName)\n }\n\n public untrack<T>(fn: () => T): T {\n return executeUntrack<T>(this, fn)\n }\n\n public reactive<T extends object>(target: T, name?: string): T {\n return createReactive<T>(this, target, name)\n }\n\n public provide<T>(token: InjectionToken<T>, valueOrFactory: T | Factory<T>): void {\n this.diRegistry.set(token, valueOrFactory)\n this.diCache.delete(token)\n }\n\n public inject<T>(token: InjectionToken<T>): T {\n if (token === undefined || token === null) throw new Error('[DI Error] Token is empty')\n if (this.diCache.has(token)) return this.diCache.get(token) as T\n if (this.cycleDetectionStack.has(token)) throw new Error('[DI Error] Cyclic dependency detected')\n this.cycleDetectionStack.add(token)\n try {\n if (this.diRegistry.has(token)) {\n const entry = this.diRegistry.get(token)\n if (typeof entry === 'function') {\n if ((entry as any)._isMockFunction) {\n const mockRes = (entry as Function)(this)\n if (mockRes !== undefined) {\n this.diCache.set(token, mockRes)\n return mockRes as T\n }\n return entry as unknown as T\n }\n const str = entry.toString()\n const isClass = str.startsWith('class ') || str.startsWith('class{') || (entry.prototype && entry.prototype.constructor === entry && !str.startsWith('function') && !str.includes('=>'))\n if (!isClass) {\n const resolved = (entry as Factory<T>)(this)\n this.diCache.set(token, resolved)\n return resolved\n }\n return entry as unknown as T\n }\n return entry as T\n }\n if (typeof token === 'function') {\n const resolved = new (token as Constructor<T>)(this)\n this.diCache.set(token, resolved)\n return resolved\n }\n throw new Error('[DI Error] Token not found')\n } finally {\n this.cycleDetectionStack.delete(token)\n }\n }\n\n private delay(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal.aborted) {\n return reject(new DOMException('Aborted', 'AbortError'))\n }\n\n const timeoutId = setTimeout(() => {\n signal.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n\n const onAbort = () => {\n clearTimeout(timeoutId)\n reject(new DOMException('Aborted', 'AbortError'))\n }\n\n signal.addEventListener('abort', onAbort, { once: true })\n })\n }\n\n public resource<T, S = void>(\n fetcher: (source: S, signal: AbortSignal) => Promise<T>,\n source?: { value: S },\n optionsOrName?: string | ResourceOptions<T, S>,\n ): Resource<T> {\n const isOptionsObject = optionsOrName && typeof optionsOrName === 'object'\n const resourceSignalName = isOptionsObject\n ? ((optionsOrName as ResourceOptions<T, S>).name || 'unnamed_resource')\n : (optionsOrName as string) || 'unnamed_resource'\n\n const options: Partial<ResourceOptions<T, S>> = isOptionsObject\n ? (optionsOrName as ResourceOptions<T, S>)\n : {}\n\n const resetDataOnSourceChange = options.resetDataOnSourceChange ?? true\n const responseValidate = options.responseValidate\n const validateBeforeFetch = options.validateBeforeFetch\n const retryCount = 0\n const baseDelay = 1000\n const useExponential = true\n const maxRetryDelay = 1000 * 60 * 5\n const timeoutMs = 1000\n const state = this.signal<ResourceState<T>>(\n { data: null, loading: true, error: null, isRetrying: false },\n `[CORE_INTERNAL_SIGNAL=1]:resource:state:${resourceSignalName}`\n )\n\n const updateResourceState = (nextState: ResourceState<T>) => {\n this.log({ type: 'resource', label: resourceSignalName, details: { to: nextState, from: state.value } })\n state.value = nextState\n }\n\n const load = async (sValue: S, effectSignal: AbortSignal, isSourceChange = false) => {\n if (effectSignal.aborted) return\n const isValid = options.validateBeforeFetch ? options.validateBeforeFetch(sValue) : true\n\n /**\n * 🧐 WIP_CORE: Есть два пути, ни один не будет ошибкой, если разкомментировать код ниже. Чуть бозже добавлю опци для более тонкой отладки ядра.\n *\n * - АКТИВНО: Разделяем мирную блокировку (false) и боевую ошибку (string): работать будет идеально, но без логов, связанных с пре-валидацией\n * - НЕАКТИВНО: Более очевидное логирование процессов пре-валидации (выставление ошибок и мониторинг разработчиком)\n */\n // --\n // if (isValid === false) {\n // // Если валидатор вернул строго false — мы тихо блокируем старт фетчера,\n // // переводя ресурс в состояние ПОКОЯ (loading: false, error: null).\n // // Это полностью ликвидирует генерацию ложных ошибок при монтировании!\n // state.value = {\n // loading: false,\n // data: null,\n // error: null, // Ошибки нет! Стейт стабилен.\n // isRetrying: false\n // }\n // return\n // }\n // if (typeof isValid === 'string') {\n // // Если валидатор вернул строку — это боевая декларативная ошибка валидации формы.\n // // Здесь мы честно переводим ресурс в стейт ошибки, как и требовалось ранее.\n // state.value = {\n // loading: false,\n // data: null,\n // error: 'Core internal stopper',\n // isRetrying: false\n // }\n // return\n // }\n // --\n if (validateBeforeFetch) {\n const preValidationResult = validateBeforeFetch(sValue)\n if (preValidationResult === false || typeof preValidationResult === 'string') {\n if (effectSignal.aborted) return\n const errorMsg = typeof preValidationResult === 'string'\n ? preValidationResult\n : 'Pre-fetch validation failed for resource'\n\n const currentData = isSourceChange ? null : this.untrack(() => state.value.data)\n updateResourceState({ data: currentData, loading: false, error: errorMsg, isRetrying: false })\n return\n }\n }\n const shouldClear = isSourceChange && resetDataOnSourceChange\n const currentData = shouldClear ? null : this.untrack(() => state.value.data)\n updateResourceState({ data: currentData, loading: true, error: null, isRetrying: false })\n for (let attempt = 0; attempt <= retryCount; attempt++) {\n if (effectSignal.aborted) return\n let combinedSignal = effectSignal\n try {\n const data = await fetcher(sValue, combinedSignal)\n if (effectSignal.aborted) return\n if (combinedSignal.aborted) {\n throw new DOMException('The operation timed out.', 'TimeoutError')\n }\n if (responseValidate) {\n const validationResult = responseValidate(data)\n if (validationResult === false || typeof validationResult === 'string') {\n if (effectSignal.aborted) return\n const errorMsg = typeof validationResult === 'string' ? validationResult : 'Validation failed'\n updateResourceState({ data: null, loading: false, error: errorMsg, isRetrying: false })\n return\n }\n }\n if (effectSignal.aborted) return\n updateResourceState({ data, loading: false, error: null, isRetrying: false })\n return\n } catch (e: unknown) {\n if (effectSignal.aborted || ((e as Error).name === 'AbortError' && effectSignal.aborted)) return\n const isTimeout = (e as Error).name === 'TimeoutError' || (e as Error).name === 'AbortError' || (e as Error).message?.includes('timeout')\n const isCustomValidationError = getExtractedValues({\n tested: [(e as Error).message], expectedKey: 'THROW_CUSTOM_VALIDATION_ERROR_NO_RETRY', valueType: 'number',\n })?.[0] === '1' || false\n const __defaultCustomValidationErrorMessage = 'Custom validation error'\n let customValidationErrorMessage: string = isCustomValidationError\n ? (getExtractedValues({\n tested: [(e as Error).message], expectedKey: 'MESSAGE', valueType: 'string',\n })?.[0] || __defaultCustomValidationErrorMessage)\n : __defaultCustomValidationErrorMessage\n const isFetchBodyValidationError = isCustomValidationError || (e as Error).name === 'ValidationError'\n if (attempt === retryCount || isFetchBodyValidationError) {\n if (effectSignal.aborted) return\n const finalError = isTimeout\n ? new Error(`Request timed out after ${timeoutMs}ms`, { cause: e })\n : isCustomValidationError\n ? new Error(customValidationErrorMessage, { cause: e })\n : e\n\n updateResourceState({\n data: null, loading: false,\n error: finalError instanceof Error ? finalError.message : typeof finalError === 'string' ? finalError : `typeof finalError is ${typeof finalError}`,\n isRetrying: false,\n })\n return\n } else {\n if (effectSignal.aborted) return\n let currentDelay = useExponential ? baseDelay * Math.pow(2, attempt) : baseDelay\n currentDelay = Math.min(currentDelay, maxRetryDelay)\n const jitter = Math.random() * 200\n currentDelay = currentDelay + jitter\n updateResourceState({ data: state.value.data, loading: true, error: null, isRetrying: true })\n const logReason = isTimeout ? 'таймауту' : 'ошибке сети'\n console.warn(`[Resource Retry] \"${resourceSignalName}\" сбой по ${logReason}. Попытка ${attempt + 1}/${retryCount > 0 ? retryCount + 1 : attempt + 1}...`)\n\n try {\n await this.delay(currentDelay, effectSignal)\n if (effectSignal.aborted) return\n } catch (delayError) {\n return\n }\n }\n }\n }\n }\n\n let activeEffectController: AbortController | null = null\n\n this.effect(() => {\n const sValue = source ? source.value : undefined as S\n const effectController = new AbortController()\n activeEffectController = effectController\n\n this.untrack(() => {\n load(sValue as S, effectController.signal, true)\n })\n\n return () => effectController.abort()\n }, '[CORE_INTERNAL_SIGNAL=1]:effect')\n\n return {\n get data() { return state.value.data },\n get loading() { return state.value.loading },\n get error() { return state.value.error },\n get isRetrying() { return state.value.isRetrying },\n get value() { return state.value },\n refetch: () => {\n activeEffectController?.abort()\n activeEffectController = new AbortController()\n load(source ? source.value : undefined as S, activeEffectController.signal, false)\n },\n subscribe: (cb: (val: ResourceState<T>) => void) => state.subscribe(cb)\n }\n }\n}\n\nexport { ReactiveEngineCore as ReactiveEngine, ReactiveEngineCore as ReactiveEngineAutomatic }\n"],"mappings":"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"}
1
+ {"version":3,"file":"core.mjs","names":[],"sources":["../src/core/core.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Signal, Computed, IEffect, EngineLoggerOptions, LogEventType, CleanupFn, TransactionContext, LogRecord, SignalOptions, ResourceOptions, ResourceState, Resource } from './types'\nimport { createComputed } from './core.method.computed'\nimport { createSignal } from './core.method.signal'\nimport { executeBatch } from './core.method.batch'\nimport { executeUntrack } from './core.method.untrack'\nimport { createReactive } from './core.method.reactive'\nimport { createEffect } from './core.method.effect'\nimport { ReactiveDebounceLogger } from './core.logger'\n\n// Тип для конструктора класса\ntype Constructor<T> = new (...args: any[]) => T\n// Тип для фабричной функции зависимостей\ntype Factory<T> = (engine: any) => T\n// Универсальный тип токена DI\ntype InjectionToken<T> = Constructor<T> | Factory<T> | symbol | string\n\nconst badgeColors: Record<LogEventType, string> = {\n signal: 'background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n computed: 'background: #42b883; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n effect: 'background: #e01e5a; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n batch: 'background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n resource: 'background: #d97706; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;',\n reactive: 'background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;'\n}\nlet currentTransaction: TransactionContext | null = null\nfunction safeValueToString(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value)\n } catch (e) {\n return '[Cyclic Object or Layer]'\n }\n }\n return String(value)\n}\nexport function queueLog(type: LogEventType, label: string, details?: { from?: unknown; to?: unknown; payload?: unknown }): void {\n if (!currentTransaction) {\n currentTransaction = { id: Math.random().toString(36).substring(2, 9), pendingLogQueue: [], isFlushing: false }\n queueMicrotask(() => flushLogs())\n }\n currentTransaction.pendingLogQueue.push({ type, label, from: details?.from, to: details?.to, payload: details?.payload, timestamp: Date.now() })\n}\nexport function flushLogs(): void {\n if (!currentTransaction || currentTransaction.isFlushing) return\n currentTransaction.isFlushing = true\n const queue = currentTransaction.pendingLogQueue\n if (queue.length === 0) {\n currentTransaction = null\n return\n }\n console.groupCollapsed(`%cREACTIVE TRANSACTION%c [id: ${currentTransaction.id}] (${queue.length} operations)`, 'background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;', 'color: #888; font-weight: normal;')\n for (const record of queue) {\n const colorStyle = badgeColors[record.type]\n const hasTransition = record.from !== undefined || record.to !== undefined\n let logMessage = `%c${record.type.toUpperCase()}%c ${record.label}`\n\n if (hasTransition) {\n if (!!record.from)\n logMessage += ` ${safeValueToString(record.from)} → ${safeValueToString(record.to)}`\n else logMessage += ` (${safeValueToString(record.to)})`\n }\n\n if (record.payload !== undefined) {\n console.groupCollapsed(logMessage, colorStyle, 'color: inherit;')\n console.log('Payload:', record.payload)\n console.groupEnd()\n } else {\n console.log(logMessage, colorStyle, 'color: inherit;')\n }\n }\n console.groupEnd()\n currentTransaction = null\n}\nexport class ReactiveEngineCore {\n protected frameworkPrefix = 'core'\n private logger: EngineLoggerOptions\n public epoch = 0\n public activeConsumer: any = null\n public batchDepth = 0\n public subscriberId = 0\n public pendingEffects = new Set<any>()\n public computedCache = new Map<Function, WeakRef<Computed<unknown>>>()\n private diRegistry = new Map<unknown, unknown>()\n private diCache = new Map<unknown, unknown>()\n private proxyCache = new WeakMap<object, any>()\n private proxyTargets = new WeakSet<object>()\n private reactiveSignals = new WeakMap<object, Map<string | symbol, any>>()\n private cycleDetectionStack = new Set<unknown>()\n public batchedSignals = new Set<any>()\n public activeOwner: any = null\n\n constructor(options?: { logger?: EngineLoggerOptions }) {\n this.logger = options?.logger || { isEnabled: false }\n }\n\n public queueLog(type: LogEventType, label: string, details?: { from?: unknown; to?: unknown; payload?: unknown }): void {\n queueLog(type, label, details)\n }\n\n public batch<T>(fn: () => T): T {\n this.batchDepth++\n try {\n return fn()\n } finally {\n this.batchDepth--\n if (this.batchDepth === 0) {\n const signalsToFlush = Array.from(this.batchedSignals)\n this.batchedSignals.clear()\n\n signalsToFlush.forEach(sig => {\n if (sig._flushBatch) sig._flushBatch()\n })\n\n this.flushEffects()\n }\n }\n }\n\n public flushEffects(): void {\n if (this.batchDepth > 0) return\n\n const effects = Array.from(this.pendingEffects)\n this.pendingEffects.clear()\n\n // Строгая топологическая сортировка\n effects.sort((a, b) => (a.depth || 0) - (b.depth || 0) || a.id - b.id)\n\n const prevConsumer = this.activeConsumer\n\n try {\n for (const effect of effects) {\n if (effect.isDisposed) continue\n\n // Pull-валидация версий родителей перед запуском эффекта\n if (effect.dependencies && effect.dependencies.size > 0) {\n let parentChanged = false\n for (const dep of effect.dependencies) {\n const rawNode = dep._node || dep\n if (rawNode.type === 'computed' && rawNode.state > 0) {\n if (rawNode.update) rawNode.update()\n }\n if (effect.depVersions && effect.depVersions.get(dep) !== rawNode.version) {\n parentChanged = true\n }\n }\n if (!parentChanged && effect.dependencies.size > 0) {\n effect.isDirty = false\n continue\n }\n }\n\n if (!effect.isDirty) continue\n\n try {\n effect.run()\n } catch (err) {\n throw err\n }\n }\n } finally {\n this.activeConsumer = prevConsumer\n }\n }\n\n // public batch<T>(fn: () => T): T {\n // return executeBatch<T>(this, fn)\n // }\n\n private log ({ type, label, details, isInternalCoreSignal = false }: { type: LogEventType, label: string, details?: { from?: unknown; to?: unknown; payload?: unknown }, isInternalCoreSignal?: boolean }) {\n ReactiveDebounceLogger.processLog(this.logger, queueLog, {\n type,\n label,\n details,\n isInternalCoreSignal\n })\n }\n\n public signal<T>(initialValue: T, optionsOrName?: string | SignalOptions<T>): Signal<T> {\n return createSignal<T>(this, initialValue, optionsOrName)\n }\n\n public computed<T>(fn: () => T, signalName?: string): Computed<T> {\n // Просто делегируем вызов строго изолированной чистой функции\n return createComputed<T>(this, fn, signalName)\n }\n\n public effect(fn: () => void | CleanupFn, effectName?: string): () => void {\n return createEffect(this, fn, effectName)\n }\n\n public untrack<T>(fn: () => T): T {\n return executeUntrack<T>(this, fn)\n }\n\n public reactive<T extends object>(target: T, name?: string): T {\n return createReactive<T>(this, target, name)\n }\n\n public provide<T>(token: InjectionToken<T>, valueOrFactory: T | Factory<T>): void {\n this.diRegistry.set(token, valueOrFactory)\n this.diCache.delete(token)\n }\n\n public inject<T>(token: InjectionToken<T>): T {\n if (token === undefined || token === null) throw new Error('[DI Error] Token is empty')\n if (this.diCache.has(token)) return this.diCache.get(token) as T\n if (this.cycleDetectionStack.has(token)) throw new Error('[DI Error] Cyclic dependency detected')\n this.cycleDetectionStack.add(token)\n try {\n if (this.diRegistry.has(token)) {\n const entry = this.diRegistry.get(token)\n if (typeof entry === 'function') {\n if ((entry as any)._isMockFunction) {\n const mockRes = (entry as Function)(this)\n if (mockRes !== undefined) {\n this.diCache.set(token, mockRes)\n return mockRes as T\n }\n return entry as unknown as T\n }\n const str = entry.toString()\n const isClass = str.startsWith('class ') || str.startsWith('class{') || (entry.prototype && entry.prototype.constructor === entry && !str.startsWith('function') && !str.includes('=>'))\n if (!isClass) {\n const resolved = (entry as Factory<T>)(this)\n this.diCache.set(token, resolved)\n return resolved\n }\n return entry as unknown as T\n }\n return entry as T\n }\n if (typeof token === 'function') {\n const resolved = new (token as Constructor<T>)(this)\n this.diCache.set(token, resolved)\n return resolved\n }\n throw new Error('[DI Error] Token not found')\n } finally {\n this.cycleDetectionStack.delete(token)\n }\n }\n\n private delay(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal.aborted) {\n return reject(new DOMException('Aborted', 'AbortError'))\n }\n\n const timeoutId = setTimeout(() => {\n signal.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n\n const onAbort = () => {\n clearTimeout(timeoutId)\n reject(new DOMException('Aborted', 'AbortError'))\n }\n\n signal.addEventListener('abort', onAbort, { once: true })\n })\n }\n\n public resource<T, S = void>(\n fetcher: (source: S, signal: AbortSignal) => Promise<T>,\n source?: { value: S },\n optionsOrName?: string | ResourceOptions<T, S>,\n ): Resource<T> {\n const isOptionsObject = optionsOrName && typeof optionsOrName === 'object'\n const resourceSignalName = isOptionsObject\n ? ((optionsOrName as ResourceOptions<T, S>).name || 'unnamed_resource')\n : (optionsOrName as string) || 'unnamed_resource'\n\n const options: Partial<ResourceOptions<T, S>> = isOptionsObject\n ? (optionsOrName as ResourceOptions<T, S>)\n : {}\n\n const resetDataOnSourceChange = options.resetDataOnSourceChange ?? true\n const responseValidate = options.responseValidate\n const validateBeforeFetch = options.validateBeforeFetch\n const retryCount = 0\n const baseDelay = 1000\n const useExponential = true\n const maxRetryDelay = 1000 * 60 * 5\n const timeoutMs = 1000\n const state = this.signal<ResourceState<T>>(\n { data: null, loading: true, error: null, isRetrying: false },\n `[CORE_INTERNAL_SIGNAL=1]:resource:state:${resourceSignalName}`\n )\n\n const updateResourceState = (nextState: ResourceState<T>) => {\n this.log({ type: 'resource', label: resourceSignalName, details: { to: nextState, from: state.value } })\n state.value = nextState\n }\n\n const load = async (sValue: S, effectSignal: AbortSignal, isSourceChange = false) => {\n if (effectSignal.aborted) return\n const isValid = options.validateBeforeFetch ? options.validateBeforeFetch(sValue) : true\n\n /**\n * 🧐 WIP_CORE: Есть два пути, ни один не будет ошибкой, если разкомментировать код ниже. Чуть бозже добавлю опци для более тонкой отладки ядра.\n *\n * - АКТИВНО: Разделяем мирную блокировку (false) и боевую ошибку (string): работать будет идеально, но без логов, связанных с пре-валидацией\n * - НЕАКТИВНО: Более очевидное логирование процессов пре-валидации (выставление ошибок и мониторинг разработчиком)\n */\n // --\n // if (isValid === false) {\n // // Если валидатор вернул строго false — мы тихо блокируем старт фетчера,\n // // переводя ресурс в состояние ПОКОЯ (loading: false, error: null).\n // // Это полностью ликвидирует генерацию ложных ошибок при монтировании!\n // state.value = {\n // loading: false,\n // data: null,\n // error: null, // Ошибки нет! Стейт стабилен.\n // isRetrying: false\n // }\n // return\n // }\n // if (typeof isValid === 'string') {\n // // Если валидатор вернул строку — это боевая декларативная ошибка валидации формы.\n // // Здесь мы честно переводим ресурс в стейт ошибки, как и требовалось ранее.\n // state.value = {\n // loading: false,\n // data: null,\n // error: 'Core internal stopper',\n // isRetrying: false\n // }\n // return\n // }\n // --\n if (validateBeforeFetch) {\n const preValidationResult = validateBeforeFetch(sValue)\n if (preValidationResult === false || typeof preValidationResult === 'string') {\n if (effectSignal.aborted) return\n const errorMsg = typeof preValidationResult === 'string'\n ? preValidationResult\n : 'Pre-fetch validation failed for resource'\n\n const currentData = isSourceChange ? null : this.untrack(() => state.value.data)\n updateResourceState({ data: currentData, loading: false, error: errorMsg, isRetrying: false })\n return\n }\n }\n const shouldClear = isSourceChange && resetDataOnSourceChange\n const currentData = shouldClear ? null : this.untrack(() => state.value.data)\n updateResourceState({ data: currentData, loading: true, error: null, isRetrying: false })\n for (let attempt = 0; attempt <= retryCount; attempt++) {\n if (effectSignal.aborted) return\n let combinedSignal = effectSignal\n try {\n const data = await fetcher(sValue, combinedSignal)\n if (effectSignal.aborted) return\n if (combinedSignal.aborted) {\n throw new DOMException('The operation timed out.', 'TimeoutError')\n }\n if (responseValidate) {\n const validationResult = responseValidate(data)\n if (validationResult === false || typeof validationResult === 'string') {\n if (effectSignal.aborted) return\n const errorMsg = typeof validationResult === 'string' ? validationResult : 'Validation failed'\n updateResourceState({ data: null, loading: false, error: errorMsg, isRetrying: false })\n return\n }\n }\n if (effectSignal.aborted) return\n updateResourceState({ data, loading: false, error: null, isRetrying: false })\n return\n } catch (e: unknown) {\n if (effectSignal.aborted || ((e as Error).name === 'AbortError' && effectSignal.aborted)) return\n const isTimeout = (e as Error).name === 'TimeoutError' || (e as Error).name === 'AbortError' || (e as Error).message?.includes('timeout')\n const isCustomValidationError = getExtractedValues({\n tested: [(e as Error).message], expectedKey: 'THROW_CUSTOM_VALIDATION_ERROR_NO_RETRY', valueType: 'number',\n })?.[0] === '1' || false\n const __defaultCustomValidationErrorMessage = 'Custom validation error'\n let customValidationErrorMessage: string = isCustomValidationError\n ? (getExtractedValues({\n tested: [(e as Error).message], expectedKey: 'MESSAGE', valueType: 'string',\n })?.[0] || __defaultCustomValidationErrorMessage)\n : __defaultCustomValidationErrorMessage\n const isFetchBodyValidationError = isCustomValidationError || (e as Error).name === 'ValidationError'\n if (attempt === retryCount || isFetchBodyValidationError) {\n if (effectSignal.aborted) return\n const finalError = isTimeout\n ? new Error(`Request timed out after ${timeoutMs}ms`, { cause: e })\n : isCustomValidationError\n ? new Error(customValidationErrorMessage, { cause: e })\n : e\n\n updateResourceState({\n data: null, loading: false,\n error: finalError instanceof Error ? finalError.message : typeof finalError === 'string' ? finalError : `typeof finalError is ${typeof finalError}`,\n isRetrying: false,\n })\n return\n } else {\n if (effectSignal.aborted) return\n let currentDelay = useExponential ? baseDelay * Math.pow(2, attempt) : baseDelay\n currentDelay = Math.min(currentDelay, maxRetryDelay)\n const jitter = Math.random() * 200\n currentDelay = currentDelay + jitter\n updateResourceState({ data: state.value.data, loading: true, error: null, isRetrying: true })\n const logReason = isTimeout ? 'таймауту' : 'ошибке сети'\n console.warn(`[Resource Retry] \"${resourceSignalName}\" сбой по ${logReason}. Попытка ${attempt + 1}/${retryCount > 0 ? retryCount + 1 : attempt + 1}...`)\n\n try {\n await this.delay(currentDelay, effectSignal)\n if (effectSignal.aborted) return\n } catch (delayError) {\n return\n }\n }\n }\n }\n }\n\n let activeEffectController: AbortController | null = null\n\n this.effect(() => {\n const sValue = source ? source.value : undefined as S\n const effectController = new AbortController()\n activeEffectController = effectController\n\n this.untrack(() => {\n load(sValue as S, effectController.signal, true)\n })\n\n return () => effectController.abort()\n }, '[CORE_INTERNAL_SIGNAL=1]:effect')\n\n return {\n get data() { return state.value.data },\n get loading() { return state.value.loading },\n get error() { return state.value.error },\n get isRetrying() { return state.value.isRetrying },\n get value() { return state.value },\n refetch: () => {\n activeEffectController?.abort()\n activeEffectController = new AbortController()\n load(source ? source.value : undefined as S, activeEffectController.signal, false)\n },\n subscribe: (cb: (val: ResourceState<T>) => void) => state.subscribe(cb)\n }\n }\n}\n\nexport { ReactiveEngineCore as ReactiveEngine, ReactiveEngineCore as ReactiveEngineAutomatic }\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- let e=require("react");function t(t){let n=t&&typeof t==`object`&&`__subscribe`in t;if(!(t&&typeof t==`object`&&`subscribe`in t)&&!n)return t;let r=t._node||t,i=r.engine||t.engine,a=(0,e.useRef)(``),o=(0,e.useRef)(null);return(0,e.useDebugValue)((0,e.useSyncExternalStore)((0,e.useMemo)(()=>e=>r.type!==`computed`&&`__subscribe`in t&&typeof t.__subscribe==`function`||r.type===`computed`&&typeof t.__subscribe==`function`?t.__subscribe(e):t.subscribe(e),[t,r]),(0,e.useMemo)(()=>()=>{let e;if(e=i&&`untrack`in i?i.untrack(()=>t.value===void 0?t:t.value):t.value===void 0?t:t.value,typeof e!=`object`||!e)return e;let n=r?.version??t?.version??i?.epoch??0,s=`${r?.type||`node`}:${n}`;return e===o.current&&s===a.current?a.current:(o.current=e,a.current=s,s)},[t,r,i]),()=>0)),i&&`untrack`in i?i.untrack(()=>t.value===void 0?t:t.value):t.value===void 0?t:t.value}exports.useReactiveValue=t;
1
+ let e=require("react");function t(t){let n=t&&typeof t==`object`&&`__subscribe`in t;if(!(t&&typeof t==`object`&&`subscribe`in t)&&!n)return t;let r=t._node||t,i=r.engine||t.engine,[a,o]=(0,e.useState)(0);return(0,e.useSyncExternalStore)((0,e.useMemo)(()=>e=>{let n=()=>{o(e=>e+1),e()};return r.type===`computed`&&typeof t.__subscribe==`function`||r.type!==`computed`&&`__subscribe`in t&&typeof t.__subscribe==`function`?t.__subscribe(n):t.subscribe(n)},[t,r]),()=>a,()=>0),(0,e.useDebugValue)(a),i&&`untrack`in i?i.untrack(()=>t.value===void 0?t:t.value):t.value===void 0?t:t.value}exports.useReactiveValue=t;
2
2
  //# sourceMappingURL=useReactiveValue.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"useReactiveValue.cjs","names":[],"sources":["../../../src/react/hooks/useReactiveValue.ts"],"sourcesContent":["import { useSyncExternalStore, useDebugValue, useMemo, useRef } from 'react'\nimport { ISignalLike } from '../../core/types'\n\nexport function useReactiveValue<V>(signal: ISignalLike<V> | any): V {\n const isProxy = signal && typeof signal === 'object' && '__subscribe' in signal\n const isSignal = signal && typeof signal === 'object' && 'subscribe' in signal\n\n if (!isSignal && !isProxy) {\n return signal\n }\n\n const rawNode = (signal as any)._node || signal\n const engine = rawNode.engine || (signal as any).engine\n\n // Иммутабельные контейнеры кэширования для предотвращения бесконечных ререндеров в renderHook\n const lastSnapshotRef = useRef<string>('')\n const lastValueRef = useRef<any>(null)\n\n // 🟢 КАНОНИЧЕСКИЙ СНАПШOТ useSyncExternalStore С СЫРОЙ И ССЫЛОЧНОЙ СТАБИЛИЗАЦИЕЙ\n const nodeSnapshot = useSyncExternalStore(\n // 1. Фаза подписки: Доверяем push-уведомлениям Ятра для запуска ререндера React\n useMemo(() => (onStoreChange: () => void) => {\n if (rawNode.type !== 'computed' && '__subscribe' in signal && typeof (signal as any).__subscribe === 'function') {\n return (signal as any).__subscribe(onStoreChange)\n }\n\n if (rawNode.type === 'computed' && typeof (signal as any).__subscribe === 'function') {\n return (signal as any).__subscribe(onStoreChange)\n }\n\n return signal.subscribe(onStoreChange)\n }, [signal, rawNode]),\n\n // 2. getSnapshot: Принудительно вычисляем ленивый узел прямо на шаге снапшота в untrack.\n // Это гарантирует, что узел актуализирует свою версию ядра ДО сверки Concurrent Mode.\n useMemo(() => () => {\n let currentVal: any\n if (engine && 'untrack' in engine) {\n currentVal = engine.untrack(() => (signal.value !== undefined ? signal.value : signal))\n } else {\n currentVal = signal.value !== undefined ? signal.value : signal\n }\n\n // Если вычисленное значение — примитив (число, строка, булево, null),\n // мы возвращаем САМО значение напрямую! Это намертво закрывает теги примитивов и Пример 100.\n if (currentVal === null || typeof currentVal !== 'object') {\n return currentVal\n }\n\n // Защита для ссылочных типов (массивов из Примера 201 и фильтрации):\n // Если ссылка на вычисленный объект/массив осталась неизменной И числовая версия ядра\n // стабильна — мы возвращаем старый строковый токен-снапшот.\n // Это полностью исключает бесконечные ререндеры в StrictMode тестах!\n const currentVersion = rawNode?.version ?? (signal?.version ?? engine?.epoch ?? 0)\n const cachedToken = `${rawNode?.type || 'node'}:${currentVersion}`\n\n if (currentVal === lastValueRef.current && cachedToken === lastSnapshotRef.current) {\n return lastSnapshotRef.current\n }\n\n lastValueRef.current = currentVal\n lastSnapshotRef.current = cachedToken\n return cachedToken\n }, [signal, rawNode, engine]),\n\n // SSR Снапшот\n () => 0 as any\n )\n\n useDebugValue(nodeSnapshot)\n\n // ⚛️ ТОПОЛОГИЧЕСКИЙ Pull (Безопасный Рендеринг из кэша O(1)):\n // Так как граф гарантированно сошелся на шаге getSnapshot микросекунду назад,\n // мы просто возвращаем вычисленный результат из стабильного кэша ядра в untrack-режиме.\n if (engine && 'untrack' in engine) {\n return engine.untrack(() => (signal.value !== undefined ? signal.value : signal))\n }\n\n return signal.value !== undefined ? signal.value : signal\n}\n"],"mappings":"uBAGA,SAAgB,EAAoB,EAAiC,CACnE,IAAM,EAAU,GAAU,OAAO,GAAW,UAAY,gBAAiB,EAGzE,GAAI,EAFa,GAAU,OAAO,GAAW,UAAY,cAAe,IAEvD,CAAC,EAChB,OAAO,EAGT,IAAM,EAAW,EAAe,OAAS,EACnC,EAAS,EAAQ,QAAW,EAAe,OAG3C,GAAA,EAAA,EAAA,OAAA,CAAiC,EAAE,EACnC,GAAA,EAAA,EAAA,OAAA,CAA2B,IAAI,EA8DrC,OATA,EAAA,EAAA,cAAA,EAAA,EAAA,EAAA,qBAAA,EAAA,EAAA,EAAA,QAAA,KAhDiB,GACT,EAAQ,OAAS,YAAc,gBAAiB,GAAU,OAAQ,EAAe,aAAgB,YAIjG,EAAQ,OAAS,YAAc,OAAQ,EAAe,aAAgB,WAChE,EAAe,YAAY,CAAa,EAG3C,EAAO,UAAU,CAAa,EACpC,CAAC,EAAQ,CAAO,CAAC,GAAA,EAAA,EAAA,QAAA,SAIA,CAClB,IAAI,EASJ,GARA,AAGE,EAHE,GAAU,YAAa,EACZ,EAAO,YAAe,EAAO,QAAU,IAAA,GAA2B,EAAf,EAAO,KAAe,EAEzE,EAAO,QAAU,IAAA,GAA2B,EAAf,EAAO,MAKxB,OAAO,GAAe,WAA7C,EACF,OAAO,EAOT,IAAM,EAAiB,GAAS,SAAY,GAAQ,SAAW,GAAQ,OAAS,EAC1E,EAAc,GAAG,GAAS,MAAQ,OAAO,GAAG,IAQlD,OANI,IAAe,EAAa,SAAW,IAAgB,EAAgB,QAClE,EAAgB,SAGzB,EAAa,QAAU,EACvB,EAAgB,QAAU,EACnB,EACT,EAAG,CAAC,EAAQ,EAAS,CAAM,CAAC,MAGtB,CAGM,CAAY,EAKtB,GAAU,YAAa,EAClB,EAAO,YAAe,EAAO,QAAU,IAAA,GAA2B,EAAf,EAAO,KAAe,EAG3E,EAAO,QAAU,IAAA,GAA2B,EAAf,EAAO,KAC7C"}
1
+ {"version":3,"file":"useReactiveValue.cjs","names":[],"sources":["../../../src/react/hooks/useReactiveValue.ts"],"sourcesContent":["import { useSyncExternalStore, useDebugValue, useMemo, useRef, useState } from 'react'\nimport { ISignalLike } from '../../core/types'\n\nexport function useReactiveValue<V>(signal: ISignalLike<V> | any): V {\n const isProxy = signal && typeof signal === 'object' && '__subscribe' in signal\n const isSignal = signal && typeof signal === 'object' && 'subscribe' in signal\n\n if (!isSignal && !isProxy) {\n return signal\n }\n\n const rawNode = (signal as any)._node || signal\n const engine = rawNode.engine || (signal as any).engine\n\n // Локальный тикет рендеринга для useSyncExternalStore.\n // Это ЕДИНСТВЕННЫЙ детерминированный источник истины для React Concurrent Mode.\n const [ticket, setTicket] = useState(0)\n\n // 🟢 КАНОНИЧЕСКИЙ ВЕРСИОННЫЙ СНАПШOТ useSyncExternalStore С СИНХРOННЫМ ПOДТЯГИВАНИЕМ КЭША\n useSyncExternalStore(\n // 1. Фаза подписки: Доверяем push-уведомлениям Ядра для запуска ререндера React\n useMemo(() => (onStoreChange: () => void) => {\n const triggerStoreRerender = () => {\n setTicket((t) => t + 1)\n onStoreChange()\n }\n\n // Для вычисляемых свойств используем скрытый __subscribe, который ловит markDirty(1)\n if (rawNode.type === 'computed' && typeof (signal as any).__subscribe === 'function') {\n return (signal as any).__subscribe(triggerStoreRerender)\n }\n\n if (rawNode.type !== 'computed' && '__subscribe' in signal && typeof (signal as any).__subscribe === 'function') {\n return (signal as any).__subscribe(triggerStoreRerender)\n }\n\n return signal.subscribe(triggerStoreRerender)\n }, [signal, rawNode]),\n\n // 2. getSnapshot: Чистая, snapshot-безопасная O(1) операция!\n // Мы СТРОГО возвращаем локальный ticket, изолируя React от бесконечного инкремента engine.epoch.\n // Это намертво защищает от краша \"Maximum update depth exceeded\"!\n () => ticket,\n\n // SSR Снапшот\n () => 0\n )\n\n useDebugValue(ticket)\n\n // ⚛️ ТОПОЛОГИЧЕСКИЙ Pull (Безопасный Рендеринг из O(1) кэша ядра):\n // Вычисляем граф и стягиваем свежее значение непосредственно в теле рендера.\n // Оборачиваем в untrack, чтобы сам рендеринг React не создавал паразитных связей.\n if (engine && 'untrack' in engine) {\n return engine.untrack(() => (signal.value !== undefined ? signal.value : signal))\n }\n\n return signal.value !== undefined ? signal.value : signal\n}\n"],"mappings":"uBAGA,SAAgB,EAAoB,EAAiC,CACnE,IAAM,EAAU,GAAU,OAAO,GAAW,UAAY,gBAAiB,EAGzE,GAAI,EAFa,GAAU,OAAO,GAAW,UAAY,cAAe,IAEvD,CAAC,EAChB,OAAO,EAGT,IAAM,EAAW,EAAe,OAAS,EACnC,EAAS,EAAQ,QAAW,EAAe,OAI3C,CAAC,EAAQ,IAAA,EAAA,EAAA,SAAA,CAAsB,CAAC,EAyCtC,OAtCA,EAAA,EAAA,qBAAA,EAAA,EAAA,EAAA,QAAA,KAEiB,GAA8B,CAC3C,IAAM,MAA6B,CACjC,EAAW,GAAM,EAAI,CAAC,EACtB,EAAc,CAChB,EAWA,OARI,EAAQ,OAAS,YAAc,OAAQ,EAAe,aAAgB,YAItE,EAAQ,OAAS,YAAc,gBAAiB,GAAU,OAAQ,EAAe,aAAgB,WAC3F,EAAe,YAAY,CAAoB,EAGlD,EAAO,UAAU,CAAoB,CAC9C,EAAG,CAAC,EAAQ,CAAO,CAAC,MAKd,MAGA,CACR,GAEA,EAAA,EAAA,cAAA,CAAc,CAAM,EAKhB,GAAU,YAAa,EAClB,EAAO,YAAe,EAAO,QAAU,IAAA,GAA2B,EAAf,EAAO,KAAe,EAG3E,EAAO,QAAU,IAAA,GAA2B,EAAf,EAAO,KAC7C"}
@@ -1 +1 @@
1
- {"version":3,"file":"useReactiveValue.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useReactiveValue.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CA4EnE"}
1
+ {"version":3,"file":"useReactiveValue.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useReactiveValue.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CAuDnE"}
@@ -1,19 +1,15 @@
1
- import { useDebugValue as e, useMemo as t, useRef as n, useSyncExternalStore as r } from "react";
1
+ import { useDebugValue as e, useMemo as t, useState as n, useSyncExternalStore as r } from "react";
2
2
  //#region src/react/hooks/useReactiveValue.ts
3
3
  function i(i) {
4
4
  let a = i && typeof i == "object" && "__subscribe" in i;
5
5
  if (!(i && typeof i == "object" && "subscribe" in i) && !a) return i;
6
- let o = i._node || i, s = o.engine || i.engine, c = n(""), l = n(null);
7
- return e(r(t(() => (e) => o.type !== "computed" && "__subscribe" in i && typeof i.__subscribe == "function" || o.type === "computed" && typeof i.__subscribe == "function" ? i.__subscribe(e) : i.subscribe(e), [i, o]), t(() => () => {
8
- let e;
9
- if (e = s && "untrack" in s ? s.untrack(() => i.value === void 0 ? i : i.value) : i.value === void 0 ? i : i.value, typeof e != "object" || !e) return e;
10
- let t = o?.version ?? i?.version ?? s?.epoch ?? 0, n = `${o?.type || "node"}:${t}`;
11
- return e === l.current && n === c.current ? c.current : (l.current = e, c.current = n, n);
12
- }, [
13
- i,
14
- o,
15
- s
16
- ]), () => 0)), s && "untrack" in s ? s.untrack(() => i.value === void 0 ? i : i.value) : i.value === void 0 ? i : i.value;
6
+ let o = i._node || i, s = o.engine || i.engine, [c, l] = n(0);
7
+ return r(t(() => (e) => {
8
+ let t = () => {
9
+ l((e) => e + 1), e();
10
+ };
11
+ return o.type === "computed" && typeof i.__subscribe == "function" || o.type !== "computed" && "__subscribe" in i && typeof i.__subscribe == "function" ? i.__subscribe(t) : i.subscribe(t);
12
+ }, [i, o]), () => c, () => 0), e(c), s && "untrack" in s ? s.untrack(() => i.value === void 0 ? i : i.value) : i.value === void 0 ? i : i.value;
17
13
  }
18
14
  //#endregion
19
15
  export { i as useReactiveValue };
@@ -1 +1 @@
1
- {"version":3,"file":"useReactiveValue.mjs","names":[],"sources":["../../../src/react/hooks/useReactiveValue.ts"],"sourcesContent":["import { useSyncExternalStore, useDebugValue, useMemo, useRef } from 'react'\nimport { ISignalLike } from '../../core/types'\n\nexport function useReactiveValue<V>(signal: ISignalLike<V> | any): V {\n const isProxy = signal && typeof signal === 'object' && '__subscribe' in signal\n const isSignal = signal && typeof signal === 'object' && 'subscribe' in signal\n\n if (!isSignal && !isProxy) {\n return signal\n }\n\n const rawNode = (signal as any)._node || signal\n const engine = rawNode.engine || (signal as any).engine\n\n // Иммутабельные контейнеры кэширования для предотвращения бесконечных ререндеров в renderHook\n const lastSnapshotRef = useRef<string>('')\n const lastValueRef = useRef<any>(null)\n\n // 🟢 КАНОНИЧЕСКИЙ СНАПШOТ useSyncExternalStore С СЫРОЙ И ССЫЛОЧНОЙ СТАБИЛИЗАЦИЕЙ\n const nodeSnapshot = useSyncExternalStore(\n // 1. Фаза подписки: Доверяем push-уведомлениям Ятра для запуска ререндера React\n useMemo(() => (onStoreChange: () => void) => {\n if (rawNode.type !== 'computed' && '__subscribe' in signal && typeof (signal as any).__subscribe === 'function') {\n return (signal as any).__subscribe(onStoreChange)\n }\n\n if (rawNode.type === 'computed' && typeof (signal as any).__subscribe === 'function') {\n return (signal as any).__subscribe(onStoreChange)\n }\n\n return signal.subscribe(onStoreChange)\n }, [signal, rawNode]),\n\n // 2. getSnapshot: Принудительно вычисляем ленивый узел прямо на шаге снапшота в untrack.\n // Это гарантирует, что узел актуализирует свою версию ядра ДО сверки Concurrent Mode.\n useMemo(() => () => {\n let currentVal: any\n if (engine && 'untrack' in engine) {\n currentVal = engine.untrack(() => (signal.value !== undefined ? signal.value : signal))\n } else {\n currentVal = signal.value !== undefined ? signal.value : signal\n }\n\n // Если вычисленное значение — примитив (число, строка, булево, null),\n // мы возвращаем САМО значение напрямую! Это намертво закрывает теги примитивов и Пример 100.\n if (currentVal === null || typeof currentVal !== 'object') {\n return currentVal\n }\n\n // Защита для ссылочных типов (массивов из Примера 201 и фильтрации):\n // Если ссылка на вычисленный объект/массив осталась неизменной И числовая версия ядра\n // стабильна — мы возвращаем старый строковый токен-снапшот.\n // Это полностью исключает бесконечные ререндеры в StrictMode тестах!\n const currentVersion = rawNode?.version ?? (signal?.version ?? engine?.epoch ?? 0)\n const cachedToken = `${rawNode?.type || 'node'}:${currentVersion}`\n\n if (currentVal === lastValueRef.current && cachedToken === lastSnapshotRef.current) {\n return lastSnapshotRef.current\n }\n\n lastValueRef.current = currentVal\n lastSnapshotRef.current = cachedToken\n return cachedToken\n }, [signal, rawNode, engine]),\n\n // SSR Снапшот\n () => 0 as any\n )\n\n useDebugValue(nodeSnapshot)\n\n // ⚛️ ТОПОЛОГИЧЕСКИЙ Pull (Безопасный Рендеринг из кэша O(1)):\n // Так как граф гарантированно сошелся на шаге getSnapshot микросекунду назад,\n // мы просто возвращаем вычисленный результат из стабильного кэша ядра в untrack-режиме.\n if (engine && 'untrack' in engine) {\n return engine.untrack(() => (signal.value !== undefined ? signal.value : signal))\n }\n\n return signal.value !== undefined ? signal.value : signal\n}\n"],"mappings":";;AAGA,SAAgB,EAAoB,GAAiC;CACnE,IAAM,IAAU,KAAU,OAAO,KAAW,YAAY,iBAAiB;CAGzE,IAAI,EAFa,KAAU,OAAO,KAAW,YAAY,eAAe,MAEvD,CAAC,GAChB,OAAO;CAGT,IAAM,IAAW,EAAe,SAAS,GACnC,IAAS,EAAQ,UAAW,EAAe,QAG3C,IAAkB,EAAe,EAAE,GACnC,IAAe,EAAY,IAAI;CA8DrC,OATA,EAlDqB,EAEnB,SAAe,MACT,EAAQ,SAAS,cAAc,iBAAiB,KAAU,OAAQ,EAAe,eAAgB,cAIjG,EAAQ,SAAS,cAAc,OAAQ,EAAe,eAAgB,aAChE,EAAe,YAAY,CAAa,IAG3C,EAAO,UAAU,CAAa,GACpC,CAAC,GAAQ,CAAO,CAAC,GAIpB,cAAoB;EAClB,IAAI;EASJ,IARA,AAGE,IAHE,KAAU,aAAa,IACZ,EAAO,cAAe,EAAO,UAAU,KAAA,IAA2B,IAAf,EAAO,KAAe,IAEzE,EAAO,UAAU,KAAA,IAA2B,IAAf,EAAO,OAKxB,OAAO,KAAe,aAA7C,GACF,OAAO;EAOT,IAAM,IAAiB,GAAS,WAAY,GAAQ,WAAW,GAAQ,SAAS,GAC1E,IAAc,GAAG,GAAS,QAAQ,OAAO,GAAG;EAQlD,OANI,MAAe,EAAa,WAAW,MAAgB,EAAgB,UAClE,EAAgB,WAGzB,EAAa,UAAU,GACvB,EAAgB,UAAU,GACnB;CACT,GAAG;EAAC;EAAQ;EAAS;CAAM,CAAC,SAGtB,CAGM,CAAY,GAKtB,KAAU,aAAa,IAClB,EAAO,cAAe,EAAO,UAAU,KAAA,IAA2B,IAAf,EAAO,KAAe,IAG3E,EAAO,UAAU,KAAA,IAA2B,IAAf,EAAO;AAC7C"}
1
+ {"version":3,"file":"useReactiveValue.mjs","names":[],"sources":["../../../src/react/hooks/useReactiveValue.ts"],"sourcesContent":["import { useSyncExternalStore, useDebugValue, useMemo, useRef, useState } from 'react'\nimport { ISignalLike } from '../../core/types'\n\nexport function useReactiveValue<V>(signal: ISignalLike<V> | any): V {\n const isProxy = signal && typeof signal === 'object' && '__subscribe' in signal\n const isSignal = signal && typeof signal === 'object' && 'subscribe' in signal\n\n if (!isSignal && !isProxy) {\n return signal\n }\n\n const rawNode = (signal as any)._node || signal\n const engine = rawNode.engine || (signal as any).engine\n\n // Локальный тикет рендеринга для useSyncExternalStore.\n // Это ЕДИНСТВЕННЫЙ детерминированный источник истины для React Concurrent Mode.\n const [ticket, setTicket] = useState(0)\n\n // 🟢 КАНОНИЧЕСКИЙ ВЕРСИОННЫЙ СНАПШOТ useSyncExternalStore С СИНХРOННЫМ ПOДТЯГИВАНИЕМ КЭША\n useSyncExternalStore(\n // 1. Фаза подписки: Доверяем push-уведомлениям Ядра для запуска ререндера React\n useMemo(() => (onStoreChange: () => void) => {\n const triggerStoreRerender = () => {\n setTicket((t) => t + 1)\n onStoreChange()\n }\n\n // Для вычисляемых свойств используем скрытый __subscribe, который ловит markDirty(1)\n if (rawNode.type === 'computed' && typeof (signal as any).__subscribe === 'function') {\n return (signal as any).__subscribe(triggerStoreRerender)\n }\n\n if (rawNode.type !== 'computed' && '__subscribe' in signal && typeof (signal as any).__subscribe === 'function') {\n return (signal as any).__subscribe(triggerStoreRerender)\n }\n\n return signal.subscribe(triggerStoreRerender)\n }, [signal, rawNode]),\n\n // 2. getSnapshot: Чистая, snapshot-безопасная O(1) операция!\n // Мы СТРОГО возвращаем локальный ticket, изолируя React от бесконечного инкремента engine.epoch.\n // Это намертво защищает от краша \"Maximum update depth exceeded\"!\n () => ticket,\n\n // SSR Снапшот\n () => 0\n )\n\n useDebugValue(ticket)\n\n // ⚛️ ТОПОЛОГИЧЕСКИЙ Pull (Безопасный Рендеринг из O(1) кэша ядра):\n // Вычисляем граф и стягиваем свежее значение непосредственно в теле рендера.\n // Оборачиваем в untrack, чтобы сам рендеринг React не создавал паразитных связей.\n if (engine && 'untrack' in engine) {\n return engine.untrack(() => (signal.value !== undefined ? signal.value : signal))\n }\n\n return signal.value !== undefined ? signal.value : signal\n}\n"],"mappings":";;AAGA,SAAgB,EAAoB,GAAiC;CACnE,IAAM,IAAU,KAAU,OAAO,KAAW,YAAY,iBAAiB;CAGzE,IAAI,EAFa,KAAU,OAAO,KAAW,YAAY,eAAe,MAEvD,CAAC,GAChB,OAAO;CAGT,IAAM,IAAW,EAAe,SAAS,GACnC,IAAS,EAAQ,UAAW,EAAe,QAI3C,CAAC,GAAQ,KAAa,EAAS,CAAC;CAyCtC,OAtCA,EAEE,SAAe,MAA8B;EAC3C,IAAM,UAA6B;GAEjC,AADA,GAAW,MAAM,IAAI,CAAC,GACtB,EAAc;EAChB;EAWA,OARI,EAAQ,SAAS,cAAc,OAAQ,EAAe,eAAgB,cAItE,EAAQ,SAAS,cAAc,iBAAiB,KAAU,OAAQ,EAAe,eAAgB,aAC3F,EAAe,YAAY,CAAoB,IAGlD,EAAO,UAAU,CAAoB;CAC9C,GAAG,CAAC,GAAQ,CAAO,CAAC,SAKd,SAGA,CACR,GAEA,EAAc,CAAM,GAKhB,KAAU,aAAa,IAClB,EAAO,cAAe,EAAO,UAAU,KAAA,IAA2B,IAAf,EAAO,KAAe,IAG3E,EAAO,UAAU,KAAA,IAA2B,IAAf,EAAO;AAC7C"}
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pravosleva/reactive-engine v2.1.8-beta
2
+ * @pravosleva/reactive-engine v2.1.10-beta
3
3
  * High-performance transactional reactive engine with microtask batching.
4
4
  *
5
5
  * @license MIT
@@ -9,5 +9,5 @@
9
9
  * @contact Telegram Channel: https://t.me/bash_exp_ru/3393
10
10
  * @contact Developer Telegram: https://t.me/pravosleva
11
11
  */
12
- (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ReactiveEngineLib={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=({tested:e,expectedKey:t,valueType:n})=>{let r=[];if(!e||!Array.isArray(e))return r;for(let i=0,a=e.length;i<a;i++){let a=e[i];if(typeof a!=`string`)continue;let o;switch(n){case`number`:o=RegExp(`\\[${t}=(?<value>\\d+)\\]`,`g`);break;default:o=RegExp(`\\[${t}=(?<value>.*?)\\]`,`g`);break}for(let e of a.matchAll(o))e?.groups&&r.push(e.groups.value)}return r};function n(e,t,n){let r=e.computedCache.get(t)?.deref();if(r)return r;let i,a=!0,o=0,s=!1,c=2,l=new Set,u=new Map,d=e=>{if(!e)return;let t=e._node||e;if(t.dependencies&&t.dependencies.size>0){let n=Array.from(t.dependencies);t.dependencies.clear(),t.depVersions&&t.depVersions.clear(),n.forEach(n=>{let r=n._node||n;r.subscribers&&(r.subscribers.delete(t),r.subscribers.delete(e),r.subscribers.delete(m),r.type===`computed`&&r.subscribers.size===0&&d(r))})}},f=new class extends Set{delete(n){let r=super.delete(n);return this.size===0&&(c=2,a=!0,e.computedCache.delete(t)),r}},p=e=>{if(!s||e.state===2)return e.run();if(e.state===1){let t=!1;for(let n of Array.from(e.dependencies)){let r=n._node||n;if(r.type===`computed`&&r.state>0&&p(r),e.depVersions.get(n)!==r.version){t=!0;break}}return e.state=0,t||a?e.run():!1}return!1},m={id:e.subscriberId++,dependencies:l,subscribers:f,depth:1,type:`computed`,fn:t,get version(){return o},get state(){return c},set state(e){c=e},get depVersions(){return u},update:()=>p(m),run:()=>{if(e.cycleDetectionStack.has(m))throw Error(`[Graph Error] Cyclic dependency detected`);e.cycleDetectionStack.add(m);let r=e.activeConsumer;e.activeConsumer=m;let d=new Set(l);l.clear();try{let r=t();d.forEach(e=>{if(!l.has(e)){let t=e._node||e;t.subscribers&&t.subscribers.delete(m),u.delete(e)}});let p=a||!Object.is(i,r);if(p){let s=a?void 0:typeof i==`object`&&i?JSON.parse(JSON.stringify(i)):i;i=r,o++,e.log&&e.log({type:`computed`,label:n||`computed:[${t.name||m.id}]`,details:{from:s,to:r}}),f.forEach(t=>{let n=t._node||t;n.type===`effect`?(n.state=2,n.isDirty=!0,e.pendingEffects.add(t)):n.markDirty&&n.markDirty(1)})}a=!1,c=0,s=!0;let g=0;return l.forEach(e=>{let t=e._node||e;u.set(e,t.version),t.depth!==void 0&&t.depth>g&&(g=t.depth)}),f.forEach(e=>{let t=e._node||e;t.depVersions&&t.depVersions.set(h,o)}),m.depth=g+1,p}finally{e.activeConsumer=r,e.cycleDetectionStack.delete(m)}},markDirty:t=>{c>=t||(c=t,f.forEach(t=>{let n=t._node||t;n.type===`effect`&&(n.isDirty=!0,e.pendingEffects.add(t)),n.markDirty&&n.markDirty(1)}))}},h={get value(){return e.activeConsumer&&e.activeConsumer!==m&&(m.subscribers.add(e.activeConsumer),e.activeConsumer.dependencies.add(m)),p(m),e.activeConsumer&&e.activeConsumer.depVersions&&e.activeConsumer.depVersions.set(h,o),i},get valueWithoutTracking(){return i},get version(){return o},subscribe(t){let n={id:e.subscriberId++,isDirty:!0,depth:9999,dependencies:new Set,type:`effect`,run:()=>{if(!n.isDisposed)try{t(h.value)}catch(e){console.error(e)}}};return m.subscribers.add(n),t(h.value),()=>{n.isDisposed=!0,m.subscribers.delete(n)}},subscribeState(e){return h.subscribe(e)},destroy:()=>{m.subscribers.clear(),d(m),e.computedCache.delete(t),a=!0,c=2,s=!1},__subscribe(t){let n={id:e.subscriberId++,type:`effect`,run:t,isDirty:!1};return m.subscribers.add(n),()=>{f.delete(n)}}};return h._node=m,h.subscribers=f,h.dependencies=l,h._isDirty=()=>c>0,h.type=`computed`,h.run=()=>m.run(),e.computedCache.set(t,new WeakRef(h)),h}function r(e,n,r){let i=n,a=0,o=typeof r==`string`?r:r?.name,s=!!o&&t({tested:[o],expectedKey:`CORE_INTERNAL_SIGNAL`,valueType:`number`})?.[0]===`1`||!1,c=new Set,l=!1,u=n,d={type:`signal`,get version(){return a},subscribers:c},f=()=>{Array.from(c).forEach(t=>{let n=t._node||t;if(n.type===`effect`)n.isDirty=!0,e.pendingEffects.add(t);else if(n.type===`computed`)n.markDirty&&n.markDirty(2);else if(typeof t==`function`)try{t(i)}catch(e){console.error(e)}else if(t&&typeof t.run==`function`)try{t.run()}catch(e){console.error(e)}})},p={get value(){return e.activeConsumer&&(c.add(e.activeConsumer),e.activeConsumer.dependencies.add(p)),i},set value(t){if(Object.is(i,t)&&!(i===t&&typeof i==`object`&&i))return;if(r&&typeof r==`object`&&r.validate){let e=r.validate(t);if(e!==!0){console.error(typeof e==`string`?e:`[Validation Error]`);return}}if(e.batchDepth>0){l||(l=!0,u=i),i=t,e.batchedSignals.add(p);return}let n=i;i=t,a++,e.epoch++,e.log({type:`signal`,label:o||`signal`,details:{from:n,to:t},isInternalCoreSignal:s}),f(),e.batchDepth===0&&e.flushEffects()},get version(){return a},type:`signal`,subscribe(e){return c.add(e),e(i),()=>{c.delete(e)}},_flushBatch:()=>{l&&((!Object.is(u,i)||typeof i==`object`&&i)&&(a++,e.epoch++,e.log({type:`signal`,label:o||`signal_batched`,details:{from:u,to:i},isInternalCoreSignal:s}),f()),l=!1,u=i)}};return p._node=d,p.subscribers=c,p}function i(e,t){let n=e.activeConsumer;e.activeConsumer=null;try{return t()}finally{e.activeConsumer=n}}function a(e,t,n){if(e.proxyTargets.has(t))return t;if(e.proxyCache.has(t))return e.proxyCache.get(t);e.reactiveSignals.has(t)||e.reactiveSignals.set(t,new Map);let r=e.reactiveSignals.get(t),i=new Proxy(t,{get(t,i,a){if(i===`__subscribe`&&Array.isArray(t))return n=>{let i=r.get(`length`);return i||(i=e.signal(t.length),r.set(`length`,i)),i.subscribe(n)};if(Array.isArray(t)&&typeof i==`string`&&[`push`,`pop`,`shift`,`unshift`,`splice`,`sort`,`reverse`].includes(i))return(...n)=>{let o;return e.batch(()=>{o=Reflect.get(t,i).apply(a,n);let e=r.get(`length`);e&&(e.value=t.length),r.forEach((e,n)=>{n!==`length`&&(e.value=Reflect.get(t,n))})}),o};if(typeof i==`symbol`||i===`constructor`||i===`toJSON`)return Reflect.get(t,i,a);let o=r.get(i);o||(o=e.signal(Reflect.get(t,i)),r.set(i,o));let s=o.value;return e.activeConsumer&&e.log({type:`reactive`,label:`Read ${n||``}.${String(i)}`,details:{to:s}}),typeof s==`object`&&s?e.reactive(s,n?`${n}.${String(i)}`:String(i)):s},set(t,n,i,a){let o=(e.proxyTargets.has(i),i),s=Reflect.get(t,n);if(s===o&&n!==`length`)return!0;Reflect.set(t,n,o);let c=r.get(n);if(c||(c=e.signal(s),r.set(n,c)),c.value=o,Array.isArray(t)&&n!==`length`){let e=r.get(`length`);e&&(e.value=t.length)}return!0}});return e.proxyCache.set(t,i),e.proxyTargets.add(i),i}function o(e,t,n){let r=new Set,i=new Set,a=new Map,o=new Set,s={id:e.subscriberId++,isDirty:!0,depth:1e3,dependencies:i,depVersions:a,cleanups:r,ownedEffects:o,type:`effect`,isDisposed:!1,run:()=>{if(s.isDisposed||s===e.activeConsumer)return;let c=e.activeConsumer,l=e.activeOwner;e.activeConsumer=s,e.activeOwner=s;let u=new Set(i);i.clear();try{o.forEach(e=>{e.dispose&&e.dispose()}),o.clear(),e.untrack(()=>{r.forEach(e=>{try{e()}catch(e){console.error(e)}}),r.clear()}),s.isDisposed&&(e.activeConsumer=null);let c=t();s.isDisposed?(u.forEach(e=>{e.subscribers.delete(s)}),a.clear()):(typeof c==`function`&&r.add(c),s.isDirty=!1,u.forEach(e=>{i.has(e)||(e.subscribers.delete(s),a.delete(e))}),i.forEach(e=>{let t=e._node||e;a.set(e,t.version)})),e.log({type:`effect`,label:n||`unnamed_effect`})}finally{e.activeConsumer=c,e.activeOwner=l}}};e.activeOwner&&e.activeOwner.ownedEffects&&e.activeOwner.ownedEffects.add(s),s.run();let c=()=>{let t=s.isDisposed;s.isDisposed=!0,o.forEach(e=>{e.dispose&&e.dispose()}),o.clear(),t||(e.untrack(()=>{r.forEach(e=>{try{e()}catch(e){console.error(e)}}),r.clear()}),i.forEach(e=>e.subscribers.delete(s)),i.clear(),a.clear(),e.pendingEffects.delete(s))};return s.dispose=c,c}var s=class{static churnTracker=new Map;static TIME_WINDOW_MS=1e3;static CHURN_WARNING_THRESHOLD=3;static CHURN_CRITICAL_THRESHOLD=6;static isDeepEqual(e,t){return e===t?!0:typeof e!=`object`||typeof t!=`object`||e===null||t===null?!1:JSON.stringify(e)===JSON.stringify(t)}static analyzeSignalChurn(e){let t=Date.now();this.churnTracker.has(e)||this.churnTracker.set(e,[]);let n=this.churnTracker.get(e),r=t-this.TIME_WINDOW_MS,i=n.filter(e=>e>r);i.push(t),this.churnTracker.set(e,i);let a=i.length,o=(this.TIME_WINDOW_MS/1e3).toFixed(1);return a>=this.CHURN_CRITICAL_THRESHOLD?{marker:`🔴`,info:`[CRITICAL CHURN] (${a} изм./${o}s) — Нужен debounce!`}:a>=this.CHURN_WARNING_THRESHOLD?{marker:`🟡`,info:`[WARNING CHURN] (${a} изм./${o}s)`}:{marker:`🟢`,info:`[STABLE] (${a} изм./${o}s)`}}static processLog(e,t,n){let{type:r,label:i,details:a,isInternalCoreSignal:o=!1}=n;if(!e.isEnabled||o&&!e.isCoreOptimizationDebugEnabled)return;if(a&&`from`in a&&`to`in a&&this.isDeepEqual(a.from,a.to)){if(r===`computed`){t(r,`🔵 [IDLE PULL] ${i} (Значение кэша не изменилось)`,a);return}return}let s=``;if(r===`signal`||r===`resource`||r===`computed`){let e=this.analyzeSignalChurn(i);s=e.marker===`🟢`?` ${e.marker}`:` ${e.marker} ${e.info}`}t(r,`${i}${s}`,a)}},c={signal:`background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`,computed:`background: #42b883; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`,effect:`background: #e01e5a; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`,batch:`background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`,resource:`background: #d97706; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`,reactive:`background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`},l=null;function u(e){if(e===null)return`null`;if(e===void 0)return`undefined`;if(typeof e==`object`)try{return JSON.stringify(e)}catch{return`[Cyclic Object or Layer]`}return String(e)}function d(e,t,n){l||(l={id:Math.random().toString(36).substring(2,9),pendingLogQueue:[],isFlushing:!1},queueMicrotask(()=>f())),l.pendingLogQueue.push({type:e,label:t,from:n?.from,to:n?.to,payload:n?.payload,timestamp:Date.now()})}function f(){if(!l||l.isFlushing)return;l.isFlushing=!0;let e=l.pendingLogQueue;if(e.length===0){l=null;return}console.groupCollapsed(`%cREACTIVE TRANSACTION%c [id: ${l.id}] (${e.length} operations)`,`background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`,`color: #888; font-weight: normal;`);for(let t of e){let e=c[t.type],n=t.from!==void 0||t.to!==void 0,r=`%c${t.type.toUpperCase()}%c ${t.label}`;n&&(t.from?r+=` ${u(t.from)} → ${u(t.to)}`:r+=` (${u(t.to)})`),t.payload===void 0?console.log(r,e,`color: inherit;`):(console.groupCollapsed(r,e,`color: inherit;`),console.log(`Payload:`,t.payload),console.groupEnd())}console.groupEnd(),l=null}var p=class{frameworkPrefix=`core`;logger;epoch=0;activeConsumer=null;batchDepth=0;subscriberId=0;pendingEffects=new Set;computedCache=new Map;diRegistry=new Map;diCache=new Map;proxyCache=new WeakMap;proxyTargets=new WeakSet;reactiveSignals=new WeakMap;cycleDetectionStack=new Set;batchedSignals=new Set;activeOwner=null;constructor(e){this.logger=e?.logger||{isEnabled:!1}}queueLog(e,t,n){d(e,t,n)}batch(e){this.batchDepth++;try{return e()}finally{if(this.batchDepth--,this.batchDepth===0){let e=Array.from(this.batchedSignals);this.batchedSignals.clear(),e.forEach(e=>{e._flushBatch&&e._flushBatch()}),this.flushEffects()}}}flushEffects(){if(this.batchDepth>0)return;let e=Array.from(this.pendingEffects);this.pendingEffects.clear(),e.sort((e,t)=>(e.depth||0)-(t.depth||0)||e.id-t.id);let t=this.activeConsumer;try{for(let t of e)if(!t.isDisposed){if(t.dependencies&&t.dependencies.size>0){let e=!1;for(let n of t.dependencies){let r=n._node||n;r.type===`computed`&&r.state>0&&r.update&&r.update(),t.depVersions&&t.depVersions.get(n)!==r.version&&(e=!0)}if(!e&&t.dependencies.size>0){t.isDirty=!1;continue}}if(t.isDirty)try{t.run()}catch(e){if(this.batchDepth===0)throw e}}}finally{this.activeConsumer=t}}log({type:e,label:t,details:n,isInternalCoreSignal:r=!1}){s.processLog(this.logger,d,{type:e,label:t,details:n,isInternalCoreSignal:r})}signal(e,t){return r(this,e,t)}computed(e,t){return n(this,e,t)}effect(e,t){return o(this,e,t)}untrack(e){return i(this,e)}reactive(e,t){return a(this,e,t)}provide(e,t){this.diRegistry.set(e,t),this.diCache.delete(e)}inject(e){if(e==null)throw Error(`[DI Error] Token is empty`);if(this.diCache.has(e))return this.diCache.get(e);if(this.cycleDetectionStack.has(e))throw Error(`[DI Error] Cyclic dependency detected`);this.cycleDetectionStack.add(e);try{if(this.diRegistry.has(e)){let t=this.diRegistry.get(e);if(typeof t==`function`){if(t._isMockFunction){let n=t(this);return n===void 0?t:(this.diCache.set(e,n),n)}let n=t.toString();if(!(n.startsWith(`class `)||n.startsWith(`class{`)||t.prototype&&t.prototype.constructor===t&&!n.startsWith(`function`)&&!n.includes(`=>`))){let n=t(this);return this.diCache.set(e,n),n}return t}return t}if(typeof e==`function`){let t=new e(this);return this.diCache.set(e,t),t}throw Error(`[DI Error] Token not found`)}finally{this.cycleDetectionStack.delete(e)}}delay(e,t){return new Promise((n,r)=>{if(t.aborted)return r(new DOMException(`Aborted`,`AbortError`));let i=setTimeout(()=>{t.removeEventListener(`abort`,a),n()},e),a=()=>{clearTimeout(i),r(new DOMException(`Aborted`,`AbortError`))};t.addEventListener(`abort`,a,{once:!0})})}resource(e,n,r){let i=r&&typeof r==`object`,a=i?r.name||`unnamed_resource`:r||`unnamed_resource`,o=i?r:{},s=o.resetDataOnSourceChange??!0,c=o.responseValidate,l=o.validateBeforeFetch,u=this.signal({data:null,loading:!0,error:null,isRetrying:!1},`[CORE_INTERNAL_SIGNAL=1]:resource:state:${a}`),d=e=>{this.log({type:`resource`,label:a,details:{to:e,from:u.value}}),u.value=e},f=async(n,r,i=!1)=>{if(r.aborted)return;if(o.validateBeforeFetch&&o.validateBeforeFetch(n),l){let e=l(n);if(e===!1||typeof e==`string`){if(r.aborted)return;let t=typeof e==`string`?e:`Pre-fetch validation failed for resource`,n=i?null:this.untrack(()=>u.value.data);d({data:n,loading:!1,error:t,isRetrying:!1});return}}let f=i&&s?null:this.untrack(()=>u.value.data);d({data:f,loading:!0,error:null,isRetrying:!1});for(let i=0;i<=0;i++){if(r.aborted)return;let o=r;try{let t=await e(n,o);if(r.aborted)return;if(o.aborted)throw new DOMException(`The operation timed out.`,`TimeoutError`);if(c){let e=c(t);if(e===!1||typeof e==`string`){if(r.aborted)return;d({data:null,loading:!1,error:typeof e==`string`?e:`Validation failed`,isRetrying:!1});return}}if(r.aborted)return;d({data:t,loading:!1,error:null,isRetrying:!1});return}catch(e){if(r.aborted||e.name===`AbortError`&&r.aborted)return;let n=e.name===`TimeoutError`||e.name===`AbortError`||e.message?.includes(`timeout`),o=t({tested:[e.message],expectedKey:`THROW_CUSTOM_VALIDATION_ERROR_NO_RETRY`,valueType:`number`})?.[0]===`1`||!1,s=o&&t({tested:[e.message],expectedKey:`MESSAGE`,valueType:`string`})?.[0]||`Custom validation error`,c=o||e.name===`ValidationError`;if(i===0||c){if(r.aborted)return;let t=n?Error(`Request timed out after 1000ms`,{cause:e}):o?Error(s,{cause:e}):e;d({data:null,loading:!1,error:t instanceof Error?t.message:typeof t==`string`?t:`typeof finalError is ${typeof t}`,isRetrying:!1});return}else{if(r.aborted)return;let e=1e3*2**i;e=Math.min(e,3e5);let t=Math.random()*200;e+=t,d({data:u.value.data,loading:!0,error:null,isRetrying:!0}),console.warn(`[Resource Retry] "${a}" сбой по ${n?`таймауту`:`ошибке сети`}. Попытка ${i+1}/${i+1}...`);try{if(await this.delay(e,r),r.aborted)return}catch{return}}}}},p=null;return this.effect(()=>{let e=n?n.value:void 0,t=new AbortController;return p=t,this.untrack(()=>{f(e,t.signal,!0)}),()=>t.abort()},`[CORE_INTERNAL_SIGNAL=1]:effect`),{get data(){return u.value.data},get loading(){return u.value.loading},get error(){return u.value.error},get isRetrying(){return u.value.isRetrying},get value(){return u.value},refetch:()=>{p?.abort(),p=new AbortController,f(n?n.value:void 0,p.signal,!1)},subscribe:e=>u.subscribe(e)}}},m=class extends p{},h=class extends m{autoLogQueue=[];isHardFlushScheduled=!1;queueLog(e,t,n){this.autoLogQueue.push({type:e,name:t,meta:n,timestamp:Date.now()}),this.isHardFlushScheduled||(this.isHardFlushScheduled=!0,queueMicrotask(()=>this.flushLogs()))}flushLogs(){this.isHardFlushScheduled=!1,this.autoLogQueue.length!==0&&(typeof process<`u`&&process.env.NODE_ENV!==`test`&&(console.group(`📊 [Autolog] Срез транзакций: ${this.autoLogQueue.length} операций`),this.autoLogQueue.forEach(e=>console.log(`[${e.type.toUpperCase()}] ${e.name}`,e.meta||``)),console.groupEnd()),this.autoLogQueue=[])}computed(e,t){let n=this,r=t||`unnamed_computed`,i=super.computed(e,t),a=!1,o={get value(){if(a)return i.value;let e=typeof performance<`u`?performance.now():0,t=i.value;return e&&n.queueLog(`computed`,r,{value:t,duration:`${(performance.now()-e).toFixed(3)}ms`}),t},subscribe:e=>i.subscribe(e),destroy(){a=!0,i.destroy()}};return`_node`in i&&Object.defineProperty(o,"_node",{value:i._node,enumerable:!1}),o}},g=class{engine;constructor(e){this.engine=e,this.onInit()}createNumericSignal(e,t){return this.engine.signal(e,{name:t,validate:e=>typeof e==`number`&&!isNaN(e)})}createComputed(e){return this.engine.computed(e)}createSignal(e,t){return this.engine.signal(e,t)}onInit(){}},_=g,v=class{engine;constructor(e){this.engine=e,setTimeout(()=>this.onInit(),0)}onInit(){}};e.AbstractService=g,e.BaseREService=_,e.BaseREServiceEnhanced=v,e.ReactiveEngine=m,e.ReactiveEngineAutolog=h,e.ReactiveEngineAutomatic=p,e.ReactiveEngineCore=p,e.flushLogs=f,e.queueLog=d});
12
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ReactiveEngineLib={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=({tested:e,expectedKey:t,valueType:n})=>{let r=[];if(!e||!Array.isArray(e))return r;for(let i=0,a=e.length;i<a;i++){let a=e[i];if(typeof a!=`string`)continue;let o;switch(n){case`number`:o=RegExp(`\\[${t}=(?<value>\\d+)\\]`,`g`);break;default:o=RegExp(`\\[${t}=(?<value>.*?)\\]`,`g`);break}for(let e of a.matchAll(o))e?.groups&&r.push(e.groups.value)}return r};function n(e,t,n){let r=e.computedCache.get(t)?.deref();if(r)return r;let i,a=!0,o=0,s=!1,c=-1,l=2,u=new Set,d=new Map,f=new Set,p=e=>{if(!e)return;let t=e._node||e;if(t.dependencies&&t.dependencies.size>0){let n=Array.from(t.dependencies);t.dependencies.clear(),t.depVersions&&t.depVersions.clear(),n.forEach(n=>{let r=n._node||n;r.subscribers&&(r.subscribers.delete(t),r.subscribers.delete(e),r.subscribers.delete(g),r.type===`computed`&&r.subscribers.size===0&&p(r))})}},m=new class extends Set{delete(n){let r=super.delete(n);return this.size===0&&(l=2,a=!0,s=!1,p(g),e.computedCache.delete(t)),r}},h=e=>{if(!s||e.state===2)return e.run();if(e.state===1){let t=!1,n=-1,r=Array.from(e.dependencies||[]);for(let i=0;i<r.length;i++){let a=r[i],o=a._node||a;if(o.type===`computed`&&o.state>0&&h(o),e.depVersions.get(a)!==o.version){t=!0,n=i;break}}if(n!==-1)for(let e=n+1;e<r.length;e++){let t=r[e],n=t._node||t;n.type===`computed`&&n.state===1&&(n.state=0)}return e.state=0,t||a?e.run():!1}return!1},g={id:e.subscriberId++,dependencies:u,subscribers:m,ownedEffects:f,depth:1,type:`computed`,fn:t,get version(){return o},get state(){return l},set state(e){l=e},get depVersions(){return d},update:()=>h(g),run:()=>{if(c===e.epoch&&s)return!1;if(c=e.epoch,e.cycleDetectionStack.has(g))throw Error(`[Graph Error] Cyclic dependency detected`);e.cycleDetectionStack.add(g);let r=e.activeConsumer,p=e.activeOwner;e.activeConsumer=g,e.activeOwner=g;let h=new Set(u);u.clear();try{f.forEach(e=>{e.dispose&&e.dispose()}),f.clear();let r=t();h.forEach(e=>{if(!u.has(e)){let t=e._node||e;t.subscribers&&t.subscribers.delete(g),d.delete(e)}});let c=a||!Object.is(i,r);if(c){let t=a?void 0:typeof i==`object`&&i?JSON.parse(JSON.stringify(i)):i;i=r,o++,e.log&&n&&e.log({type:`computed`,label:n,details:{from:t,to:r}}),m.forEach(t=>{let n=t._node||t;n.type===`effect`?(n.state=2,n.isDirty=!0,e.pendingEffects.add(t)):n.markDirty&&n.markDirty(1)})}a=!1,l=0,s=!0;let p=0;return u.forEach(e=>{let t=e._node||e;d.set(e,t.version),t.subscribers&&t.subscribers.add(g),t.depth!==void 0&&t.depth>p&&(p=t.depth)}),m.forEach(e=>{let t=e._node||e;t.depVersions&&t.depVersions.set(_,o)}),g.depth=p+1,c}finally{e.activeConsumer=r,e.activeOwner=p,e.cycleDetectionStack.delete(g)}},markDirty:t=>{l>=t||(l=t,m.forEach(t=>{let n=t._node||t;n.type===`effect`?(n.isDirty=!0,e.pendingEffects.add(t)):n.markDirty&&n.markDirty(1)}))}},_={get value(){return e.activeConsumer&&e.activeConsumer!==g&&(g.subscribers.add(e.activeConsumer),e.activeConsumer.dependencies.add(g)),h(g),e.activeConsumer&&e.activeConsumer.depVersions&&e.activeConsumer.depVersions.set(_,o),i},get valueWithoutTracking(){return i},get version(){return o},subscribe(t){let n={id:e.subscriberId++,isDirty:!0,depth:9999,dependencies:new Set,type:`effect`,run:()=>{if(!n.isDisposed)try{t(_.value)}catch(e){console.error(e)}}};return g.subscribers.add(n),t(_.value),()=>{n.isDisposed=!0,g.subscribers.delete(n)}},subscribeState(e){return _.subscribe(e)},destroy:()=>{g.subscribers.clear(),p(g),e.computedCache.delete(t),a=!0,l=2,s=!1},__subscribe(t){let n={id:e.subscriberId++,type:`effect`,run:t,isDirty:!1};return g.subscribers.add(n),()=>{m.delete(n)}}};return _._node=g,_.subscribers=m,_.dependencies=u,_._isDirty=()=>l>0,_.type=`computed`,_.run=()=>g.run(),e.computedCache.set(t,new WeakRef(_)),_}function r(e,n,r){let i=n,a=0,o=typeof r==`string`?r:r?.name,s=!!o&&t({tested:[o],expectedKey:`CORE_INTERNAL_SIGNAL`,valueType:`number`})?.[0]===`1`||!1,c=new Set,l=!1,u=n,d={type:`signal`,get version(){return a},subscribers:c},f=()=>{Array.from(c).forEach(t=>{let n=t._node||t;if(n.type===`effect`)n.isDirty=!0,e.pendingEffects.add(t);else if(n.type===`computed`)n.markDirty&&n.markDirty(2);else if(typeof t==`function`)try{t(i)}catch(e){console.error(e)}else if(t&&typeof t.run==`function`)try{t.run()}catch(e){console.error(e)}})},p={get value(){return e.activeConsumer&&(c.add(e.activeConsumer),e.activeConsumer.dependencies.add(p)),i},set value(t){if(Object.is(i,t)&&!(i===t&&typeof i==`object`&&i))return;if(r&&typeof r==`object`&&r.validate){let e=r.validate(t);if(e!==!0){console.error(typeof e==`string`?e:`[Validation Error]`);return}}if(e.batchDepth>0){l||(l=!0,u=i),i=t,e.batchedSignals.add(p);return}let n=i;i=t,a++,e.epoch++,e.log({type:`signal`,label:o||`signal`,details:{from:n,to:t},isInternalCoreSignal:s}),f(),e.batchDepth===0&&e.flushEffects()},get version(){return a},type:`signal`,subscribe(e){return c.add(e),e(i),()=>{c.delete(e)}},_flushBatch:()=>{l&&((!Object.is(u,i)||typeof i==`object`&&i)&&(a++,e.epoch++,e.log({type:`signal`,label:o||`signal_batched`,details:{from:u,to:i},isInternalCoreSignal:s}),f()),l=!1,u=i)}};return p._node=d,p.subscribers=c,p}function i(e,t){let n=e.activeConsumer;e.activeConsumer=null;try{return t()}finally{e.activeConsumer=n}}function a(e,t,n){if(e.proxyTargets.has(t))return t;if(e.proxyCache.has(t))return e.proxyCache.get(t);e.reactiveSignals.has(t)||e.reactiveSignals.set(t,new Map);let r=e.reactiveSignals.get(t),i=new Proxy(t,{get(t,i,a){if(i===`__subscribe`&&Array.isArray(t))return n=>{let i=r.get(`length`);return i||(i=e.signal(t.length),r.set(`length`,i)),i.subscribe(n)};if(Array.isArray(t)&&typeof i==`string`&&[`push`,`pop`,`shift`,`unshift`,`splice`,`sort`,`reverse`].includes(i))return(...n)=>{let o;return e.batch(()=>{o=Reflect.get(t,i).apply(a,n);let e=r.get(`length`);e&&(e.value=t.length),r.forEach((e,n)=>{n!==`length`&&(e.value=Reflect.get(t,n))})}),o};if(typeof i==`symbol`||i===`constructor`||i===`toJSON`)return Reflect.get(t,i,a);let o=r.get(i);o||(o=e.signal(Reflect.get(t,i)),r.set(i,o));let s=o.value;return e.activeConsumer&&e.log({type:`reactive`,label:`Read ${n||``}.${String(i)}`,details:{to:s}}),typeof s==`object`&&s?e.reactive(s,n?`${n}.${String(i)}`:String(i)):s},set(t,n,i,a){let o=(e.proxyTargets.has(i),i),s=Reflect.get(t,n);if(s===o&&n!==`length`)return!0;Reflect.set(t,n,o);let c=r.get(n);if(c||(c=e.signal(s),r.set(n,c)),c.value=o,Array.isArray(t)&&n!==`length`){let e=r.get(`length`);e&&(e.value=t.length)}return!0}});return e.proxyCache.set(t,i),e.proxyTargets.add(i),i}function o(e,t,n){let r=new Set,i=new Set,a=new Map,o=new Set,s={id:e.subscriberId++,isDirty:!0,depth:1e3,dependencies:i,depVersions:a,cleanups:r,ownedEffects:o,type:`effect`,isDisposed:!1,run:()=>{if(s.isDisposed||s===e.activeConsumer)return;let c=e.activeConsumer,l=e.activeOwner;e.activeConsumer=s,e.activeOwner=s;let u=new Set(i);i.clear();try{o.forEach(e=>{e.dispose&&e.dispose()}),o.clear(),e.untrack(()=>{r.forEach(e=>{try{e()}catch(e){console.error(e)}}),r.clear()}),s.isDisposed&&(e.activeConsumer=null);let c=t();s.isDisposed?(u.forEach(e=>{e.subscribers.delete(s)}),a.clear()):(typeof c==`function`&&r.add(c),s.isDirty=!1,u.forEach(e=>{i.has(e)||(e.subscribers.delete(s),a.delete(e))}),i.forEach(e=>{let t=e._node||e;a.set(e,t.version)})),e.log({type:`effect`,label:n||`unnamed_effect`})}finally{e.activeConsumer=c,e.activeOwner=l}}};e.activeOwner&&e.activeOwner.ownedEffects&&e.activeOwner.ownedEffects.add(s),s.run();let c=()=>{let t=s.isDisposed;s.isDisposed=!0,o.forEach(e=>{e.dispose&&e.dispose()}),o.clear(),t||(e.untrack(()=>{r.forEach(e=>{try{e()}catch(e){console.error(e)}}),r.clear()}),i.forEach(e=>e.subscribers.delete(s)),i.clear(),a.clear(),e.pendingEffects.delete(s))};return s.dispose=c,c}var s=class{static churnTracker=new Map;static TIME_WINDOW_MS=1e3;static CHURN_WARNING_THRESHOLD=3;static CHURN_CRITICAL_THRESHOLD=6;static isDeepEqual(e,t){return e===t?!0:typeof e!=`object`||typeof t!=`object`||e===null||t===null?!1:JSON.stringify(e)===JSON.stringify(t)}static analyzeSignalChurn(e){let t=Date.now();this.churnTracker.has(e)||this.churnTracker.set(e,[]);let n=this.churnTracker.get(e),r=t-this.TIME_WINDOW_MS,i=n.filter(e=>e>r);i.push(t),this.churnTracker.set(e,i);let a=i.length,o=(this.TIME_WINDOW_MS/1e3).toFixed(1);return a>=this.CHURN_CRITICAL_THRESHOLD?{marker:`🔴`,info:`[CRITICAL CHURN] (${a} изм./${o}s) — Нужен debounce!`}:a>=this.CHURN_WARNING_THRESHOLD?{marker:`🟡`,info:`[WARNING CHURN] (${a} изм./${o}s)`}:{marker:`🟢`,info:`[STABLE] (${a} изм./${o}s)`}}static processLog(e,t,n){let{type:r,label:i,details:a,isInternalCoreSignal:o=!1}=n;if(!e.isEnabled||o&&!e.isCoreOptimizationDebugEnabled)return;if(a&&`from`in a&&`to`in a&&this.isDeepEqual(a.from,a.to)){if(r===`computed`){t(r,`🔵 [IDLE PULL] ${i} (Значение кэша не изменилось)`,a);return}return}let s=``;if(r===`signal`||r===`resource`||r===`computed`){let e=this.analyzeSignalChurn(i);s=e.marker===`🟢`?` ${e.marker}`:` ${e.marker} ${e.info}`}t(r,`${i}${s}`,a)}},c={signal:`background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`,computed:`background: #42b883; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`,effect:`background: #e01e5a; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`,batch:`background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`,resource:`background: #d97706; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`,reactive:`background: #007acc; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`},l=null;function u(e){if(e===null)return`null`;if(e===void 0)return`undefined`;if(typeof e==`object`)try{return JSON.stringify(e)}catch{return`[Cyclic Object or Layer]`}return String(e)}function d(e,t,n){l||(l={id:Math.random().toString(36).substring(2,9),pendingLogQueue:[],isFlushing:!1},queueMicrotask(()=>f())),l.pendingLogQueue.push({type:e,label:t,from:n?.from,to:n?.to,payload:n?.payload,timestamp:Date.now()})}function f(){if(!l||l.isFlushing)return;l.isFlushing=!0;let e=l.pendingLogQueue;if(e.length===0){l=null;return}console.groupCollapsed(`%cREACTIVE TRANSACTION%c [id: ${l.id}] (${e.length} operations)`,`background: #7952b3; color: #fff; padding: 2px 6px; border-radius: 4px; font-weight: bold;`,`color: #888; font-weight: normal;`);for(let t of e){let e=c[t.type],n=t.from!==void 0||t.to!==void 0,r=`%c${t.type.toUpperCase()}%c ${t.label}`;n&&(t.from?r+=` ${u(t.from)} → ${u(t.to)}`:r+=` (${u(t.to)})`),t.payload===void 0?console.log(r,e,`color: inherit;`):(console.groupCollapsed(r,e,`color: inherit;`),console.log(`Payload:`,t.payload),console.groupEnd())}console.groupEnd(),l=null}var p=class{frameworkPrefix=`core`;logger;epoch=0;activeConsumer=null;batchDepth=0;subscriberId=0;pendingEffects=new Set;computedCache=new Map;diRegistry=new Map;diCache=new Map;proxyCache=new WeakMap;proxyTargets=new WeakSet;reactiveSignals=new WeakMap;cycleDetectionStack=new Set;batchedSignals=new Set;activeOwner=null;constructor(e){this.logger=e?.logger||{isEnabled:!1}}queueLog(e,t,n){d(e,t,n)}batch(e){this.batchDepth++;try{return e()}finally{if(this.batchDepth--,this.batchDepth===0){let e=Array.from(this.batchedSignals);this.batchedSignals.clear(),e.forEach(e=>{e._flushBatch&&e._flushBatch()}),this.flushEffects()}}}flushEffects(){if(this.batchDepth>0)return;let e=Array.from(this.pendingEffects);this.pendingEffects.clear(),e.sort((e,t)=>(e.depth||0)-(t.depth||0)||e.id-t.id);let t=this.activeConsumer;try{for(let t of e)if(!t.isDisposed){if(t.dependencies&&t.dependencies.size>0){let e=!1;for(let n of t.dependencies){let r=n._node||n;r.type===`computed`&&r.state>0&&r.update&&r.update(),t.depVersions&&t.depVersions.get(n)!==r.version&&(e=!0)}if(!e&&t.dependencies.size>0){t.isDirty=!1;continue}}if(t.isDirty)try{t.run()}catch(e){throw e}}}finally{this.activeConsumer=t}}log({type:e,label:t,details:n,isInternalCoreSignal:r=!1}){s.processLog(this.logger,d,{type:e,label:t,details:n,isInternalCoreSignal:r})}signal(e,t){return r(this,e,t)}computed(e,t){return n(this,e,t)}effect(e,t){return o(this,e,t)}untrack(e){return i(this,e)}reactive(e,t){return a(this,e,t)}provide(e,t){this.diRegistry.set(e,t),this.diCache.delete(e)}inject(e){if(e==null)throw Error(`[DI Error] Token is empty`);if(this.diCache.has(e))return this.diCache.get(e);if(this.cycleDetectionStack.has(e))throw Error(`[DI Error] Cyclic dependency detected`);this.cycleDetectionStack.add(e);try{if(this.diRegistry.has(e)){let t=this.diRegistry.get(e);if(typeof t==`function`){if(t._isMockFunction){let n=t(this);return n===void 0?t:(this.diCache.set(e,n),n)}let n=t.toString();if(!(n.startsWith(`class `)||n.startsWith(`class{`)||t.prototype&&t.prototype.constructor===t&&!n.startsWith(`function`)&&!n.includes(`=>`))){let n=t(this);return this.diCache.set(e,n),n}return t}return t}if(typeof e==`function`){let t=new e(this);return this.diCache.set(e,t),t}throw Error(`[DI Error] Token not found`)}finally{this.cycleDetectionStack.delete(e)}}delay(e,t){return new Promise((n,r)=>{if(t.aborted)return r(new DOMException(`Aborted`,`AbortError`));let i=setTimeout(()=>{t.removeEventListener(`abort`,a),n()},e),a=()=>{clearTimeout(i),r(new DOMException(`Aborted`,`AbortError`))};t.addEventListener(`abort`,a,{once:!0})})}resource(e,n,r){let i=r&&typeof r==`object`,a=i?r.name||`unnamed_resource`:r||`unnamed_resource`,o=i?r:{},s=o.resetDataOnSourceChange??!0,c=o.responseValidate,l=o.validateBeforeFetch,u=this.signal({data:null,loading:!0,error:null,isRetrying:!1},`[CORE_INTERNAL_SIGNAL=1]:resource:state:${a}`),d=e=>{this.log({type:`resource`,label:a,details:{to:e,from:u.value}}),u.value=e},f=async(n,r,i=!1)=>{if(r.aborted)return;if(o.validateBeforeFetch&&o.validateBeforeFetch(n),l){let e=l(n);if(e===!1||typeof e==`string`){if(r.aborted)return;let t=typeof e==`string`?e:`Pre-fetch validation failed for resource`,n=i?null:this.untrack(()=>u.value.data);d({data:n,loading:!1,error:t,isRetrying:!1});return}}let f=i&&s?null:this.untrack(()=>u.value.data);d({data:f,loading:!0,error:null,isRetrying:!1});for(let i=0;i<=0;i++){if(r.aborted)return;let o=r;try{let t=await e(n,o);if(r.aborted)return;if(o.aborted)throw new DOMException(`The operation timed out.`,`TimeoutError`);if(c){let e=c(t);if(e===!1||typeof e==`string`){if(r.aborted)return;d({data:null,loading:!1,error:typeof e==`string`?e:`Validation failed`,isRetrying:!1});return}}if(r.aborted)return;d({data:t,loading:!1,error:null,isRetrying:!1});return}catch(e){if(r.aborted||e.name===`AbortError`&&r.aborted)return;let n=e.name===`TimeoutError`||e.name===`AbortError`||e.message?.includes(`timeout`),o=t({tested:[e.message],expectedKey:`THROW_CUSTOM_VALIDATION_ERROR_NO_RETRY`,valueType:`number`})?.[0]===`1`||!1,s=o&&t({tested:[e.message],expectedKey:`MESSAGE`,valueType:`string`})?.[0]||`Custom validation error`,c=o||e.name===`ValidationError`;if(i===0||c){if(r.aborted)return;let t=n?Error(`Request timed out after 1000ms`,{cause:e}):o?Error(s,{cause:e}):e;d({data:null,loading:!1,error:t instanceof Error?t.message:typeof t==`string`?t:`typeof finalError is ${typeof t}`,isRetrying:!1});return}else{if(r.aborted)return;let e=1e3*2**i;e=Math.min(e,3e5);let t=Math.random()*200;e+=t,d({data:u.value.data,loading:!0,error:null,isRetrying:!0}),console.warn(`[Resource Retry] "${a}" сбой по ${n?`таймауту`:`ошибке сети`}. Попытка ${i+1}/${i+1}...`);try{if(await this.delay(e,r),r.aborted)return}catch{return}}}}},p=null;return this.effect(()=>{let e=n?n.value:void 0,t=new AbortController;return p=t,this.untrack(()=>{f(e,t.signal,!0)}),()=>t.abort()},`[CORE_INTERNAL_SIGNAL=1]:effect`),{get data(){return u.value.data},get loading(){return u.value.loading},get error(){return u.value.error},get isRetrying(){return u.value.isRetrying},get value(){return u.value},refetch:()=>{p?.abort(),p=new AbortController,f(n?n.value:void 0,p.signal,!1)},subscribe:e=>u.subscribe(e)}}},m=class extends p{},h=class extends m{autoLogQueue=[];isHardFlushScheduled=!1;queueLog(e,t,n){this.autoLogQueue.push({type:e,name:t,meta:n,timestamp:Date.now()}),this.isHardFlushScheduled||(this.isHardFlushScheduled=!0,queueMicrotask(()=>this.flushLogs()))}flushLogs(){this.isHardFlushScheduled=!1,this.autoLogQueue.length!==0&&(typeof process<`u`&&process.env.NODE_ENV!==`test`&&(console.group(`📊 [Autolog] Срез транзакций: ${this.autoLogQueue.length} операций`),this.autoLogQueue.forEach(e=>console.log(`[${e.type.toUpperCase()}] ${e.name}`,e.meta||``)),console.groupEnd()),this.autoLogQueue=[])}computed(e,t){let n=this,r=t||`unnamed_computed`,i=super.computed(e,t),a=!1,o={get value(){if(a)return i.value;let e=typeof performance<`u`?performance.now():0,t=i.value;return e&&n.queueLog(`computed`,r,{value:t,duration:`${(performance.now()-e).toFixed(3)}ms`}),t},subscribe:e=>i.subscribe(e),destroy(){a=!0,i.destroy()}};return`_node`in i&&Object.defineProperty(o,"_node",{value:i._node,enumerable:!1}),o}},g=class{engine;constructor(e){this.engine=e,this.onInit()}createNumericSignal(e,t){return this.engine.signal(e,{name:t,validate:e=>typeof e==`number`&&!isNaN(e)})}createComputed(e){return this.engine.computed(e)}createSignal(e,t){return this.engine.signal(e,t)}onInit(){}},_=g,v=class{engine;constructor(e){this.engine=e,setTimeout(()=>this.onInit(),0)}onInit(){}};e.AbstractService=g,e.BaseREService=_,e.BaseREServiceEnhanced=v,e.ReactiveEngine=m,e.ReactiveEngineAutolog=h,e.ReactiveEngineAutomatic=p,e.ReactiveEngineCore=p,e.flushLogs=f,e.queueLog=d});
13
13
  //# sourceMappingURL=reactive-engine.umd.js.map