@pravosleva/reactive-engine 2.6.4-alpha.8 → 2.6.5

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.
Files changed (79) hide show
  1. package/README.md +8 -8
  2. package/dist/core/core.d.ts +160 -0
  3. package/dist/core/core.d.ts.map +1 -1
  4. package/dist/core/core.method.computed.d.ts.map +1 -1
  5. package/dist/core.method.computed.mjs +2 -1
  6. package/dist/core.method.computed.mjs.map +1 -1
  7. package/dist/core.method.resource.mjs +3 -1
  8. package/dist/core.method.resource.mjs.map +1 -1
  9. package/dist/core.mjs.map +1 -1
  10. package/dist/decorators/withValidation/withValidation.d.ts +2 -2
  11. package/dist/decorators/withValidation/withValidation.d.ts.map +1 -1
  12. package/dist/decorators/withValidation/withValidation.mjs +1 -1
  13. package/dist/decorators/withValidation/withValidation.mjs.map +1 -1
  14. package/dist/decorators/withValidation/withValidation.test.d.ts +2 -0
  15. package/dist/decorators/withValidation/withValidation.test.d.ts.map +1 -0
  16. package/dist/index.mjs +2 -2
  17. package/dist/reactive-engine.umd.js +2 -2
  18. package/dist/reactive-engine.umd.js.map +1 -1
  19. package/package.json +8 -11
  20. package/dist/AbstractService.cjs +0 -2
  21. package/dist/AbstractService.cjs.map +0 -1
  22. package/dist/BaseREServiceEnhanced.cjs +0 -2
  23. package/dist/BaseREServiceEnhanced.cjs.map +0 -1
  24. package/dist/angular/core.angular-adapter.cjs +0 -2
  25. package/dist/angular/core.angular-adapter.cjs.map +0 -1
  26. package/dist/angular/index.cjs +0 -2
  27. package/dist/angular/index.cjs.map +0 -1
  28. package/dist/core.autolog.cjs +0 -2
  29. package/dist/core.autolog.cjs.map +0 -1
  30. package/dist/core.automatic.cjs +0 -2
  31. package/dist/core.automatic.cjs.map +0 -1
  32. package/dist/core.cjs +0 -2
  33. package/dist/core.cjs.map +0 -1
  34. package/dist/core.global.cjs +0 -2
  35. package/dist/core.global.cjs.map +0 -1
  36. package/dist/core.logger.cjs +0 -2
  37. package/dist/core.logger.cjs.map +0 -1
  38. package/dist/core.method.computed.cjs +0 -2
  39. package/dist/core.method.computed.cjs.map +0 -1
  40. package/dist/core.method.effect.cjs +0 -2
  41. package/dist/core.method.effect.cjs.map +0 -1
  42. package/dist/core.method.reactive.cjs +0 -2
  43. package/dist/core.method.reactive.cjs.map +0 -1
  44. package/dist/core.method.resource.cjs +0 -2
  45. package/dist/core.method.resource.cjs.map +0 -1
  46. package/dist/core.method.signal.cjs +0 -2
  47. package/dist/core.method.signal.cjs.map +0 -1
  48. package/dist/core.method.untrack.cjs +0 -2
  49. package/dist/core.method.untrack.cjs.map +0 -1
  50. package/dist/decorators/withCache/withCache.cjs +0 -2
  51. package/dist/decorators/withCache/withCache.cjs.map +0 -1
  52. package/dist/decorators/withDebounce/withDebounce.cjs +0 -2
  53. package/dist/decorators/withDebounce/withDebounce.cjs.map +0 -1
  54. package/dist/decorators/withLongPolling/withLongPolling.cjs +0 -2
  55. package/dist/decorators/withLongPolling/withLongPolling.cjs.map +0 -1
  56. package/dist/decorators/withStaleWhileRevalidate/withStaleWhileRevalidate.cjs +0 -2
  57. package/dist/decorators/withStaleWhileRevalidate/withStaleWhileRevalidate.cjs.map +0 -1
  58. package/dist/decorators/withThrottle/withThrottle.cjs +0 -2
  59. package/dist/decorators/withThrottle/withThrottle.cjs.map +0 -1
  60. package/dist/decorators/withThrottleAndCache/withThrottleAndCache.cjs +0 -2
  61. package/dist/decorators/withThrottleAndCache/withThrottleAndCache.cjs.map +0 -1
  62. package/dist/decorators/withThrottleComputed/withThrottleComputed.cjs +0 -2
  63. package/dist/decorators/withThrottleComputed/withThrottleComputed.cjs.map +0 -1
  64. package/dist/decorators/withValidation/withValidation.cjs +0 -2
  65. package/dist/decorators/withValidation/withValidation.cjs.map +0 -1
  66. package/dist/index.cjs +0 -1
  67. package/dist/index2.cjs +0 -1
  68. package/dist/react/hooks/useReactiveSubscription.cjs +0 -2
  69. package/dist/react/hooks/useReactiveSubscription.cjs.map +0 -1
  70. package/dist/react/hooks/useReactiveValue.cjs +0 -2
  71. package/dist/react/hooks/useReactiveValue.cjs.map +0 -1
  72. package/dist/react/index.cjs +0 -2
  73. package/dist/react/index.cjs.map +0 -1
  74. package/dist/utils/getExtractedValues.cjs +0 -2
  75. package/dist/utils/getExtractedValues.cjs.map +0 -1
  76. package/dist/vue/core.vue-adapter.cjs +0 -2
  77. package/dist/vue/core.vue-adapter.cjs.map +0 -1
  78. package/dist/vue/index.cjs +0 -2
  79. package/dist/vue/index.cjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"withThrottleAndCache.cjs","names":[],"sources":["../../../src/decorators/withThrottleAndCache/withThrottleAndCache.ts"],"sourcesContent":["interface ThrottleAndCacheOptions {\n /** Интервал троттлинга в миллисекундах. По умолчанию 300 мс */\n limit?: number;\n /** Время жизни кэша в миллисекундах. По умолчанию 5 минут (300000 мс) */\n ttl?: number;\n}\n\ninterface CacheEntry<T> {\n data: T;\n timestamp: number;\n}\n\n/**\n * Комбинированный декоратор высокой производительности: применяет ограничение частоты вызовов (Throttling)\n * с сохранением последнего вызова (Trailing edge) и проверяет валидность кэша в оперативной памяти\n * перед отправкой реального сетевого запроса.\n *\n * Нативно поддерживает отмену операций через стандартный `AbortSignal` на всех этапах жизненного цикла.\n *\n * ### 🧠 Алгоритм работы (Два контура защиты):\n * 1. **Контур Троттлинга:** Если функция вызывается чаще чем раз в `limit` миллисекунд,\n * вызовы группируются. Первый вызов выполняется мгновенно (Leading edge), а все последующие\n * внутри окна блокировки перезаписывают друг друга. Выполнится только самый последний вызов (Trailing edge)\n * по истечении таймера. Все промежуточные отброшенные вызовы отклоняются с ошибкой `AbortError`.\n * 2. **Контур Кэширования:** Когда таймер троттлинга истекает и наступает время реального выполнения,\n * функция генерирует строковый ключ на основе аргумента `source` (через `JSON.stringify` для объектов).\n * Если в кэше есть свежий результат, чей возраст меньше `ttl`, он возвращается мгновенно **без**\n * повторного вызова исходного `fetcher`-запроса.\n *\n * @template S Тип входных данных (аргументов) для запроса. Используется для генерации ключа кэша.\n * @template T Тип данных, возвращаемых асинхронным `fetcher`-ом (разрешенное значение промиса).\n *\n * @param {(source: S, signal: AbortSignal) => Promise<T>} fetcher Асинхронная функция-загрузчик, выполняющая реальный сетевой или дисковый запрос.\n * @param {ThrottleAndCacheOptions} [options={}] Параметры конфигурации декоратора.\n * @param {number} [options.limit=300] Окно троттлинга в миллисекундах (минимальный интервал между прямыми вызовами).\n * @param {number} [options.ttl=300000] Время жизни кэша (Time-To-Live) в миллисекундах (по умолчанию 5 минут).\n *\n * @returns {(source: S, signal: AbortSignal) => Promise<T>} Возвращает обернутую функцию, которая возвращает `Promise<T>`.\n *\n * @example\n * ```typescript\n * import { withThrottleAndCache } from '@pravosleva/reactive-engine';\n *\n * interface SearchQuery { query: string; page: number; }\n * interface SearchResult { items: string[]; total: number; }\n *\n * const fetchApi = async (search: SearchQuery, signal: AbortSignal): Promise<SearchResult> => {\n * const response = await fetch(`/api/search?q=${search.query}&p=${search.page}`, { signal });\n * return response.json();\n * };\n *\n * // Создаем оптимизированную функцию поиска\n * const optimizedSearch = withThrottleAndCache(fetchApi, { limit: 500, ttl: 60 * 1000 });\n *\n * // Пример вызова внутри реактивного эффекта\n * const controller = new AbortController();\n *\n * optimizedSearch({ query: 'react', page: 1 }, controller.signal)\n * .then(data => updateUi(data))\n * .catch(err => {\n * if (err.name === 'AbortError') console.log('Запрос отменен троттлером или пользователем');\n * });\n * ```\n *\n * @abstract\n * ### 🚨 Интеграция с AbortSignal и управление памятью\n * Декоратор имеет встроенный обработчик события `abort`. Если пользователь отменяет операцию\n * (например, уходит со страницы) во время ожидания в окне троттлинга:\n * - Активный таймер `setTimeout` сбрасывается и зануляется.\n * - Ожидающий промис немедленно переходит в состояние `rejected` с ошибкой `AbortError`.\n * - Все внутренние ссылки на `source` и методы разрешения промиса очищаются (`null`), предотвращая утечки памяти в замыканиях.\n */\nexport const withThrottleAndCache = <S, T>(\n fetcher: (source: S, signal: AbortSignal) => Promise<T>,\n options: ThrottleAndCacheOptions = {}\n) => {\n const limit = options.limit ?? 300\n const ttl = options.ttl ?? 5 * 60 * 1000\n\n // Инфраструктура троттлинга\n let lastExecutionTime = 0\n let throttleTimeoutId: ReturnType<typeof setTimeout> | null = null\n let lastSavedSource: S | null = null\n let lastSavedResolve: ((value: T | PromiseLike<T>) => void) | null = null\n let lastSavedReject: ((reason: any) => void) | null = null\n let lastSavedSignal: AbortSignal | null = null\n\n // Инфраструктура кэширования\n const cache = new Map<string, CacheEntry<T>>()\n\n // Внутренний хелпер для генерации ключа кэша\n const getCacheKey = (source: S): string => {\n return typeof source === 'object' && source !== null\n ? JSON.stringify(source)\n : String(source)\n }\n\n return (source: S, signal: AbortSignal): Promise<T> => {\n const now = Date.now()\n const remainingTime = limit - (now - lastExecutionTime)\n const cacheKey = getCacheKey(source)\n\n const onAbort = () => {\n if (throttleTimeoutId) {\n clearTimeout(throttleTimeoutId)\n throttleTimeoutId = null\n }\n if (lastSavedReject) {\n lastSavedReject(new DOMException('Aborted by resource signal during throttle', 'AbortError'))\n lastSavedResolve = null\n lastSavedReject = null\n }\n }\n\n // --- ФУНКЦИЯ ВЫПОЛНЕНИЯ ЗАПРОСА С УЧЕТОМ КЭША ---\n const executeWithCache = async (src: S, sig: AbortSignal): Promise<T> => {\n const currentNow = Date.now()\n const currentKey = getCacheKey(src)\n const cached = cache.get(currentKey)\n\n // Проверяем оперативную память на валидность кэша\n if (cached && currentNow - cached.timestamp < ttl) {\n return cached.data\n }\n\n // Если кэша нет — делаем реальный запрос\n const freshData = await fetcher(src, sig)\n\n // Сохраняем в кэш\n cache.set(currentKey, {\n data: freshData,\n timestamp: Date.now(),\n })\n\n return freshData\n }\n\n // --- ВЕТКА 1: Leading edge (Окно блокировки закрыто, выполняем сразу) ---\n if (remainingTime <= 0) {\n if (throttleTimeoutId) {\n clearTimeout(throttleTimeoutId)\n throttleTimeoutId = null\n }\n if (lastSavedReject) {\n lastSavedReject(new DOMException('Aborted due to newer direct execution', 'AbortError'))\n lastSavedResolve = null\n lastSavedReject = null\n }\n\n lastExecutionTime = now\n return executeWithCache(source, signal)\n }\n\n // --- ВЕТКА 2: Trailing edge (Внутри окна блокировки, перезаписываем хвост) ---\n if (lastSavedReject) {\n lastSavedReject(new DOMException('Aborted due to newer throttled value', 'AbortError'))\n }\n\n return new Promise<T>((resolve, reject) => {\n lastSavedSource = source\n lastSavedResolve = resolve\n lastSavedReject = reject\n lastSavedSignal = signal\n\n if (signal.aborted) {\n return onAbort()\n }\n signal.addEventListener('abort', onAbort)\n\n if (!throttleTimeoutId) {\n throttleTimeoutId = setTimeout(async () => {\n throttleTimeoutId = null\n\n const savedSource = lastSavedSource!\n const savedResolve = lastSavedResolve!\n const savedReject = lastSavedReject!\n const savedSignal = lastSavedSignal!\n\n lastSavedSource = null\n lastSavedResolve = null\n lastSavedReject = null\n lastSavedSignal = null\n savedSignal.removeEventListener('abort', onAbort)\n\n try {\n lastExecutionTime = Date.now()\n const data = await executeWithCache(savedSource, savedSignal)\n savedResolve(data)\n } catch (error) {\n savedReject(error)\n }\n }, remainingTime)\n }\n })\n }\n}\n"],"mappings":"AAwEA,IAAa,GACX,EACA,EAAmC,CAAC,IACjC,CACH,IAAM,EAAQ,EAAQ,OAAS,IACzB,EAAM,EAAQ,KAAO,IAAS,IAGhC,EAAoB,EACpB,EAA0D,KAC1D,EAA4B,KAC5B,EAAiE,KACjE,EAAkD,KAClD,EAAsC,KAGpC,EAAQ,IAAI,IAGZ,EAAe,GACZ,OAAO,GAAW,UAAY,EACjC,KAAK,UAAU,CAAM,EACrB,OAAO,CAAM,EAGnB,OAAQ,EAAW,IAAoC,CACrD,IAAM,EAAM,KAAK,IAAI,EACf,EAAgB,GAAS,EAAM,GACpB,EAAY,CAAM,EAEnC,IAAM,MAAgB,CACpB,AAEE,KADA,aAAa,CAAiB,EACV,MAEtB,AAGE,KAFA,EAAgB,IAAI,aAAa,6CAA8C,YAAY,CAAC,EAC5F,EAAmB,KACD,KAEtB,EAGM,EAAmB,MAAO,EAAQ,IAAiC,CACvE,IAAM,EAAa,KAAK,IAAI,EACtB,EAAa,EAAY,CAAG,EAC5B,EAAS,EAAM,IAAI,CAAU,EAGnC,GAAI,GAAU,EAAa,EAAO,UAAY,EAC5C,OAAO,EAAO,KAIhB,IAAM,EAAY,MAAM,EAAQ,EAAK,CAAG,EAQxC,OALA,EAAM,IAAI,EAAY,CACpB,KAAM,EACN,UAAW,KAAK,IAAI,CACtB,CAAC,EAEM,CACT,EAuBA,OApBI,GAAiB,GACnB,AAEE,KADA,aAAa,CAAiB,EACV,MAEtB,AAGE,KAFA,EAAgB,IAAI,aAAa,wCAAyC,YAAY,CAAC,EACvF,EAAmB,KACD,MAGpB,EAAoB,EACb,EAAiB,EAAQ,CAAM,IAIpC,GACF,EAAgB,IAAI,aAAa,uCAAwC,YAAY,CAAC,EAGjF,IAAI,SAAY,EAAS,IAAW,CAMzC,GALA,EAAkB,EAClB,EAAmB,EACnB,EAAkB,EAClB,EAAkB,EAEd,EAAO,QACT,OAAO,EAAQ,EAEjB,EAAO,iBAAiB,QAAS,CAAO,EAExC,AACE,IAAoB,WAAW,SAAY,CACzC,EAAoB,KAEpB,IAAM,EAAc,EACd,EAAe,EACf,EAAc,EACd,EAAc,EAEpB,EAAkB,KAClB,EAAmB,KACnB,EAAkB,KAClB,EAAkB,KAClB,EAAY,oBAAoB,QAAS,CAAO,EAEhD,GAAI,CACF,EAAoB,KAAK,IAAI,EAE7B,EAAa,MADM,EAAiB,EAAa,CAAW,CAC3C,CACnB,OAAS,EAAO,CACd,EAAY,CAAK,CACnB,CACF,EAAG,CAAa,CAEpB,CAAC,EACH,CACF"}
@@ -1,2 +0,0 @@
1
- var e=(e,t,n,r)=>{let i=r||`throttled_computed:unnamed`,a=n.limit,o=t(),s=e.signal(o,`signal:internal:${i}`),c=0,l=null,u=null,d=!1,f=!0,p=e=>{s.value=e,c=Date.now(),d=!1,l=null};return e.effect(()=>{let e=t();if(f){f=!1;return}let n=c===0?a:Date.now()-c;n>=a?(l&&=(clearTimeout(l),null),p(e)):(u=e,d=!0,l||=setTimeout(()=>{d&&p(u)},a-n))},`effect:throttle-scheduler:${i}`),{get value(){return s.value},subscribe:e=>s.subscribe(e),destroy:()=>{l&&clearTimeout(l)}}};exports.withThrottleComputed=e;
2
- //# sourceMappingURL=withThrottleComputed.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"withThrottleComputed.cjs","names":[],"sources":["../../../src/decorators/withThrottleComputed/withThrottleComputed.ts"],"sourcesContent":["import { ReactiveEngine } from '../../core/core'\n\ninterface ThrottleComputedOptions {\n limit: number;\n}\n\n/**\n * Обертка-декоратор для создания дросселируемых (throttled) вычисляемых значений.\n * Позволяет сгруппировать и ограничить частоту обновления тяжелых вычислений,\n * защищая граф зависимостей и UI от лавинообразных изменений (\"дребезга\" данных).\n *\n * ### 🧠 Как это работает под капотом:\n * 1. Функция синхронно считывает `getter()`, чтобы получить стартовое значение.\n * 2. Внутри создается скрытый сигнал `engine.signal<T>` для хранения задросселированного стейта.\n * 3. Регистрируется `engine.effect`, который автоматически собирает все реактивные зависимости\n * внутри вашего геттера. При изменении любой зависимости эффект запускает таймер на базе `setTimeout`.\n * 4. Значение выдается мгновенно на первом пассе, а последующие изменения зажимаются во временной интервал `options.limit`.\n *\n * @template T Тип вычисляемого значения.\n *\n * @param {ReactiveEngine} engine Экземпляр реактивного ядра, в контексте которого создаются примитивы.\n * @param {() => T} getter Функция-вычислитель, содержащая реактивные сигналы. Зависимости собираются автоматически.\n * @param {Object} options Конфигурация планировщика дросселирования.\n * @param {number} options.limit Временной интервал задержки в миллисекундах (минимальное время между обновлениями).\n * @param {string} [signalName] Необязательное имя для отладки. Будет впечено в системные маркеры логгера.\n *\n * @returns {Object} Возвращает объект интерфейса вычисляемого значения:\n * @returns {T} value Геттер для чтения текущего задросселированного значения (вызывает Pull-обновление).\n * @returns {(cb: (val: T) => void) => () => void} subscribe Метод подписки на изменения значения (для связи с UI слоем).\n * @returns {() => void} destroy Функция принудительной очистки активных таймеров. Обязательна к вызову при уничтожении контекста.\n *\n * @example\n * ```typescript\n * import { withThrottleComputed } from '@pravosleva/reactive-engine';\n *\n * const searchInput = engine.signal('reac', 'search');\n *\n * // Создаем задросселированный компут: будет обновляться не чаще чем раз в 300мс\n * const throttledSearch = withThrottleComputed(\n * engine,\n * () => executeHeavySearchFilter(searchInput.value),\n * { limit: 300 },\n * 'heavy-search'\n * );\n *\n * // Подписываемся на финальный результат\n * throttledSearch.subscribe((finalResult) => {\n * renderSearchResults(finalResult);\n * });\n *\n * // Не забываем вызвать destroy при анмаунте компонента/сервиса\n * onUnmounted(() => throttledSearch.destroy());\n * ```\n *\n * @abstract\n * ### 🧪 Тестирование с Fake Timers\n * Код функции переведен на нативный `Date.now()`, что обеспечивает 100% совместимость с ложными\n * таймерами в тестовых средах. При написании тестов используйте `vi.advanceTimersByTime(limit)`\n * для контролируемой перемотки времени планировщика.\n */\nexport const withThrottleComputed = <T>(\n engine: ReactiveEngine,\n getter: () => T,\n options: ThrottleComputedOptions,\n signalName?: string\n) => {\n const name = signalName || 'throttled_computed:unnamed'\n const limit = options.limit\n\n const initialValue = getter()\n const throttledSignal = engine.signal<T>(initialValue, `signal:internal:${name}`)\n\n // ИСПОЛЬЗУЕМ СТАНДАРТНЫЙ ТАЙМЕР ДЛЯ СИНХРOНИЗАЦИИ С ТЕСТАМИ\n let lastRunTime = 0\n let timeoutId: any = null\n let pendingValue: T | null = null\n let hasPending = false\n\n let isFirstEffectRun = true\n\n const updateSignal = (value: T) => {\n throttledSignal.value = value\n lastRunTime = Date.now() // Перешли на Date.now() для 100% поддержки FakeTimers\n hasPending = false\n timeoutId = null\n }\n\n engine.effect(() => {\n const freshValue = getter() // Собираем зависимости нативно\n\n if (isFirstEffectRun) {\n isFirstEffectRun = false\n return\n }\n\n const now = Date.now()\n\n // Если lastRunTime === 0 — это самое первое реальное изменение, пушим его сразу\n const timePassed = lastRunTime === 0 ? limit : (now - lastRunTime)\n\n if (timePassed >= limit) {\n if (timeoutId) {\n clearTimeout(timeoutId)\n timeoutId = null\n }\n updateSignal(freshValue)\n } else {\n pendingValue = freshValue\n hasPending = true\n\n if (!timeoutId) {\n timeoutId = setTimeout(() => {\n if (hasPending) {\n updateSignal(pendingValue as T)\n }\n }, limit - timePassed)\n }\n }\n }, `effect:throttle-scheduler:${name}`)\n\n const destroy = () => {\n if (timeoutId) {\n clearTimeout(timeoutId)\n }\n }\n\n return {\n get value(): T {\n return throttledSignal.value\n },\n subscribe: (cb: (val: T) => void) => throttledSignal.subscribe(cb),\n destroy\n }\n}\n"],"mappings":"AA4DA,IAAa,GACX,EACA,EACA,EACA,IACG,CACH,IAAM,EAAO,GAAc,6BACrB,EAAQ,EAAQ,MAEhB,EAAe,EAAO,EACtB,EAAkB,EAAO,OAAU,EAAc,mBAAmB,GAAM,EAG5E,EAAc,EACd,EAAiB,KACjB,EAAyB,KACzB,EAAa,GAEb,EAAmB,GAEjB,EAAgB,GAAa,CACjC,EAAgB,MAAQ,EACxB,EAAc,KAAK,IAAI,EACvB,EAAa,GACb,EAAY,IACd,EAyCA,OAvCA,EAAO,WAAa,CAClB,IAAM,EAAa,EAAO,EAE1B,GAAI,EAAkB,CACpB,EAAmB,GACnB,MACF,CAKA,IAAM,EAAa,IAAgB,EAAI,EAH3B,KAAK,IAG+B,EAAM,EAElD,GAAc,GAChB,AAEE,KADA,aAAa,CAAS,EACV,MAEd,EAAa,CAAU,IAEvB,EAAe,EACf,EAAa,GAEb,AACE,IAAY,eAAiB,CACvB,GACF,EAAa,CAAiB,CAElC,EAAG,EAAQ,CAAU,EAG3B,EAAG,6BAA6B,GAAM,EAQ/B,CACL,IAAI,OAAW,CACb,OAAO,EAAgB,KACzB,EACA,UAAY,GAAyB,EAAgB,UAAU,CAAE,EACjE,YAXoB,CAChB,GACF,aAAa,CAAS,CAE1B,CAQA,CACF"}
@@ -1,2 +0,0 @@
1
- var e=(e,t)=>(n,...r)=>{let{schema:i,errorsSignal:a}=t,o={},s=!1;for(let e in i){let t=i[e];if(typeof t==`function`){let r=t(n[e],n);typeof r==`string`&&(o[e]=r,s=!0)}}if(a.value=o,!s)return e(...r)},t=(e,t)=>async(n,r)=>{let{schema:i,errorsSignal:a}=t,o={},s=!1;for(let e in i){let t=i[e];if(typeof t==`function`){let r=t(n[e],n);typeof r==`string`&&(o[e]=r,s=!0)}}if(a.value=o,s)throw Error(`Core validation stopper`);return e(n,r)};exports.withResourceValidation=t,exports.withValidation=e;
2
- //# sourceMappingURL=withValidation.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"withValidation.cjs","names":[],"sources":["../../../src/decorators/withValidation/withValidation.ts"],"sourcesContent":["import { Signal } from '../../core/types'\n\nexport type ValidationSchema<T> = {\n [K in keyof T]?: (value: T[K], state: T) => string | true\n}\n\nexport interface ValidationOptions<T> {\n schema: ValidationSchema<T>\n errorsSignal: Signal<Record<string, string>>\n}\n\n/**\n * Декоратор для синхронных экшенов (например, переключение шагов)\n */\nexport const withValidation = <T, Args extends any[], R>(\n targetAction: (...args: Args) => R,\n options: ValidationOptions<T>\n) => {\n return (currentState: T, ...args: Args): R | void => {\n const { schema, errorsSignal } = options\n const nextErrors: Record<string, string> = {}\n let hasErrors = false\n\n for (const key in schema) {\n const validator = schema[key]\n if (typeof validator === 'function') {\n const result = validator(currentState[key], currentState)\n if (typeof result === 'string') {\n nextErrors[key] = result\n hasErrors = true\n }\n }\n }\n\n errorsSignal.value = nextErrors\n if (hasErrors) return\n\n return targetAction(...args)\n }\n}\n\n/**\n * Декоратор СТРОГО для асинхронных фетчеров engine.resource.\n * Прозрачно сохраняет типы входных и выходных данных оригинального fetcher.\n */\nexport const withResourceValidation = <S, T>(\n fetcher: (source: S, signal: AbortSignal) => Promise<T>,\n options: ValidationOptions<S>\n) => {\n // 🟢 ИСПРАВЛЕНО: Явно указываем Promise<T>, возвращая исходный тип ответа фетчера\n return async (sourceValue: S, abortSignal: AbortSignal): Promise<T> => {\n const { schema, errorsSignal } = options\n const nextErrors: Record<string, string> = {}\n let hasErrors = false\n\n for (const key in schema) {\n const validator = schema[key]\n if (typeof validator === 'function') {\n const result = validator(sourceValue[key], sourceValue)\n if (typeof result === 'string') {\n nextErrors[key] = result\n hasErrors = true\n }\n }\n }\n\n errorsSignal.value = nextErrors\n \n if (hasErrors) {\n throw new Error('Core validation stopper')\n }\n\n return fetcher(sourceValue, abortSignal)\n }\n}"],"mappings":"AAcA,IAAa,GACX,EACA,KAEQ,EAAiB,GAAG,IAAyB,CACnD,GAAM,CAAE,SAAQ,gBAAiB,EAC3B,EAAqC,CAAC,EACxC,EAAY,GAEhB,IAAK,IAAM,KAAO,EAAQ,CACxB,IAAM,EAAY,EAAO,GACzB,GAAI,OAAO,GAAc,WAAY,CACnC,IAAM,EAAS,EAAU,EAAa,GAAM,CAAY,EACpD,OAAO,GAAW,WACpB,EAAW,GAAO,EAClB,EAAY,GAEhB,CACF,CAEA,KAAa,MAAQ,EACjB,GAEJ,OAAO,EAAa,GAAG,CAAI,CAC7B,EAOW,GACX,EACA,IAGO,MAAO,EAAgB,IAAyC,CACrE,GAAM,CAAE,SAAQ,gBAAiB,EAC3B,EAAqC,CAAC,EACxC,EAAY,GAEhB,IAAK,IAAM,KAAO,EAAQ,CACxB,IAAM,EAAY,EAAO,GACzB,GAAI,OAAO,GAAc,WAAY,CACnC,IAAM,EAAS,EAAU,EAAY,GAAM,CAAW,EAClD,OAAO,GAAW,WACpB,EAAW,GAAO,EAClB,EAAY,GAEhB,CACF,CAIA,GAFA,EAAa,MAAQ,EAEjB,EACF,MAAU,MAAM,yBAAyB,EAG3C,OAAO,EAAQ,EAAa,CAAW,CACzC"}
package/dist/index.cjs DELETED
@@ -1 +0,0 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./core.cjs"),t=require("./core.automatic.cjs"),n=require("./core.autolog.cjs"),r=require("./core.global.cjs"),i=require("./AbstractService.cjs"),a=require("./BaseREServiceEnhanced.cjs"),o=require("./decorators/withCache/withCache.cjs"),s=require("./decorators/withDebounce/withDebounce.cjs"),c=require("./decorators/withLongPolling/withLongPolling.cjs"),l=require("./decorators/withThrottle/withThrottle.cjs"),u=require("./decorators/withThrottleComputed/withThrottleComputed.cjs"),d=require("./decorators/withThrottleAndCache/withThrottleAndCache.cjs"),f=require("./decorators/withStaleWhileRevalidate/withStaleWhileRevalidate.cjs"),p=require("./decorators/withValidation/withValidation.cjs");exports.AbstractService=i.AbstractService,exports.BaseREService=i.BaseREService,exports.BaseREServiceEnhanced=a.BaseREServiceEnhanced,exports.ReactiveEngine=t.ReactiveEngineAutomatic,exports.ReactiveEngineAutolog=n.ReactiveEngineAutolog,exports.ReactiveEngineAutomatic=t.ReactiveEngineAutomatic,exports.ReactiveEngineCore=e.ReactiveEngine,exports.batch=r.batch,exports.computed=r.computed,exports.effect=r.effect,exports.resetGlobalReactiveEngine=r.resetGlobalReactiveEngine,exports.signal=r.signal,exports.untrack=r.untrack,exports.withCache=o.withCache,exports.withDebounce=s.withDebounce,exports.withLongPolling=c.withLongPolling,exports.withResourceValidation=p.withResourceValidation,exports.withStaleWhileRevalidate=f.withStaleWhileRevalidate,exports.withThrottle=l.withThrottle,exports.withThrottleAndCache=d.withThrottleAndCache,exports.withThrottleComputed=u.withThrottleComputed,exports.withValidation=p.withValidation;
package/dist/index2.cjs DELETED
@@ -1 +0,0 @@
1
- const e=require("./core.cjs");require("./core.automatic.cjs"),require("./core.autolog.cjs");const t=require("./core.global.cjs"),n=require("./AbstractService.cjs"),r=require("./BaseREServiceEnhanced.cjs");exports.AbstractService=n.AbstractService,exports.BaseREService=n.BaseREService,exports.BaseREServiceEnhanced=r.BaseREServiceEnhanced,exports.ReactiveEngineAutomatic=e.ReactiveEngine,exports.batch=t.batch,exports.computed=t.computed,exports.effect=t.effect,exports.flushLogs=e.flushLogs,exports.queueLog=e.queueLog,exports.resetGlobalReactiveEngine=t.resetGlobalReactiveEngine,exports.signal=t.signal,exports.untrack=t.untrack;
@@ -1,2 +0,0 @@
1
- let e=require("react");function t(t,n){let r=(0,e.useRef)(n);(0,e.useEffect)(()=>{r.current=n},[n]),(0,e.useEffect)(()=>{if(!(!t||typeof t!=`object`)){if(`subscribe`in t&&typeof t.subscribe==`function`)return t.subscribe(e=>{r.current(e)});if(`__subscribe`in t&&typeof t.__subscribe==`function`)return t.__subscribe(()=>{r.current(t)})}},[t])}exports.useReactiveSubscription=t;
2
- //# sourceMappingURL=useReactiveSubscription.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useReactiveSubscription.cjs","names":[],"sources":["../../../src/react/hooks/useReactiveSubscription.ts"],"sourcesContent":["import { useEffect, useRef } from 'react'\nimport { ISignalLike } from '../../core/types'\n\ntype CleanupFn = () => void\n\n/**\n * 🔄 Универсальный хук подписки без принудительного рендеринга самого компонента.\n * Идеален для вызова аналитики, сайд-эффектов или логов при изменении коллекций.\n */\nexport function useReactiveSubscription<T>(\n item: T,\n callback: (val: T extends ISignalLike<infer V> ? V : T) => void\n): void {\n const callbackRef = useRef(callback)\n\n useEffect(() => {\n callbackRef.current = callback\n }, [callback])\n\n useEffect(() => {\n if (!item || typeof item !== 'object') return\n\n if ('subscribe' in item && typeof (item as Record<string, unknown>).subscribe === 'function') {\n const signalItem = (item as unknown) as ISignalLike<unknown>\n return signalItem.subscribe((newValue) => {\n callbackRef.current(newValue as any)\n })\n }\n\n if ('__subscribe' in item && typeof (item as Record<string, unknown>).__subscribe === 'function') {\n return ((item as Record<string, unknown>).__subscribe as (cb: () => void) => CleanupFn)(() => {\n callbackRef.current(item as any)\n })\n }\n }, [item])\n}\n"],"mappings":"uBASA,SAAgB,EACd,EACA,EACM,CACN,IAAM,GAAA,EAAA,EAAA,OAAA,CAAqB,CAAQ,GAEnC,EAAA,EAAA,UAAA,KAAgB,CACd,EAAY,QAAU,CACxB,EAAG,CAAC,CAAQ,CAAC,GAEb,EAAA,EAAA,UAAA,KAAgB,CACV,MAAC,GAAQ,OAAO,GAAS,UAE7B,IAAI,cAAe,GAAQ,OAAQ,EAAiC,WAAc,WAEhF,OAAO,EAAW,UAAW,GAAa,CACxC,EAAY,QAAQ,CAAe,CACrC,CAAC,EAGH,GAAI,gBAAiB,GAAQ,OAAQ,EAAiC,aAAgB,WACpF,OAAS,EAAiC,gBAAoD,CAC5F,EAAY,QAAQ,CAAW,CACjC,CAAC,CANA,CAQL,EAAG,CAAC,CAAI,CAAC,CACX"}
@@ -1,2 +0,0 @@
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
- //# sourceMappingURL=useReactiveValue.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useReactiveValue.cjs","names":[],"sources":["../../../src/react/hooks/useReactiveValue.ts"],"sourcesContent":["import { useSyncExternalStore, useDebugValue, useMemo, useState } from 'react'\nimport { ISignalLike } from '../../core/types'\n\n/**\n * ⚛️ УЛЬТИМАТИВНЫЙ ХУК ДЛЯ СТЯГИВАНИЯ ДАННЫХ ИЗ ГРАФА В СРЕДУ REACT\n * Автоматически выводит тип внутренней структуры данных (V) из любого сигнала или вычисляемого свойства.\n */\nexport function useReactiveValue<V>(signal: ISignalLike<V>): V;\nexport function useReactiveValue<T extends object>(proxy: T): T;\nexport function useReactiveValue<T>(primitive: T): T;\nexport function useReactiveValue(signal: any): any {\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._node || signal\n const engine = rawNode.engine || signal.engine\n\n // Локальный тикет рендеринга для useSyncExternalStore.\n const [ticket, setTicket] = useState(0)\n\n // 🟢 КАНОНИЧЕСКИЙ ВЕРСИОННЫЙ СНАПШOТ useSyncExternalStore С СИНХРOННЫМ ПOДТЯГИВАНИЕМ КЭША\n useSyncExternalStore(\n useMemo(() => (onStoreChange: () => void) => {\n const triggerStoreRerender = () => {\n setTicket((t) => t + 1)\n onStoreChange()\n }\n\n if (rawNode.type === 'computed' && typeof signal.__subscribe === 'function') {\n return signal.__subscribe(triggerStoreRerender)\n }\n\n if (rawNode.type !== 'computed' && '__subscribe' in signal && typeof signal.__subscribe === 'function') {\n return signal.__subscribe(triggerStoreRerender)\n }\n\n return signal.subscribe(triggerStoreRerender)\n }, [signal, rawNode]),\n\n () => ticket,\n () => 0\n )\n\n useDebugValue(ticket)\n\n // ⚛️ ТОПОЛОГИЧЕСКИЙ Pull: Стягиваем свежее значение в теле рендера под 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":"uBAUA,SAAgB,EAAiB,EAAkB,CACjD,IAAM,EAAU,GAAU,OAAO,GAAW,UAAY,gBAAiB,EAGzE,GAAI,EAFa,GAAU,OAAO,GAAW,UAAY,cAAe,IAEvD,CAAC,EAChB,OAAO,EAGT,IAAM,EAAU,EAAO,OAAS,EAC1B,EAAS,EAAQ,QAAU,EAAO,OAGlC,CAAC,EAAQ,IAAA,EAAA,EAAA,SAAA,CAAsB,CAAC,EAgCtC,OA7BA,EAAA,EAAA,qBAAA,EAAA,EAAA,EAAA,QAAA,KACiB,GAA8B,CAC3C,IAAM,MAA6B,CACjC,EAAW,GAAM,EAAI,CAAC,EACtB,EAAc,CAChB,EAUA,OARI,EAAQ,OAAS,YAAc,OAAO,EAAO,aAAgB,YAI7D,EAAQ,OAAS,YAAc,gBAAiB,GAAU,OAAO,EAAO,aAAgB,WACnF,EAAO,YAAY,CAAoB,EAGzC,EAAO,UAAU,CAAoB,CAC9C,EAAG,CAAC,EAAQ,CAAO,CAAC,MAEd,MACA,CACR,GAEA,EAAA,EAAA,cAAA,CAAc,CAAM,EAGhB,GAAU,YAAa,EAClB,EAAO,YAAe,EAAO,QAAU,IAAA,GAA2B,EAAf,EAAO,KAAe,EAG3E,EAAO,QAAU,IAAA,GAA2B,EAAf,EAAO,KAC7C"}
@@ -1,2 +0,0 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../core.cjs"),t=require("./hooks/useReactiveValue.cjs"),n=require("./hooks/useReactiveSubscription.cjs");var r=t.useReactiveValue,i=class extends e.ReactiveEngine{use(e){return t.useReactiveValue(e)}};exports.ReactiveEngine=i,exports.use=r,exports.useReactiveSubscription=n.useReactiveSubscription,exports.useReactiveValue=t.useReactiveValue;
2
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../src/react/index.ts"],"sourcesContent":["import { ReactiveEngineCore } from '../core/core'\nimport { useReactiveValue } from './hooks/useReactiveValue'\nimport { ISignalLike } from '../core/types'\n\nexport interface IUseReactiveHook {\n <V>(item: ISignalLike<V>): V;\n <T>(item: T): T;\n}\n\nexport const use: IUseReactiveHook = useReactiveValue as any\n\n/**\n * Расширенная версия движка ядра для ООП/DI паттернов в React-среде\n */\nexport class ReactiveEngine extends ReactiveEngineCore {\n public use<V>(item: ISignalLike<V>): V;\n public use<T>(item: T): T;\n public use(item: any): any {\n return useReactiveValue(item)\n }\n // Метод inject удален отсюда, так как он нативно наследуется из ReactiveEngineCore без хуков!\n}\n\nexport { useReactiveValue }\nexport { useReactiveSubscription } from './hooks/useReactiveSubscription'\n"],"mappings":"6LASA,IAAa,EAAwB,EAAA,iBAKxB,EAAb,cAAoC,EAAA,cAAmB,CAGrD,IAAW,EAAgB,CACzB,OAAO,EAAA,iBAAiB,CAAI,CAC9B,CAEF"}
@@ -1,2 +0,0 @@
1
- var e=({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};exports.getExtractedValues=e;
2
- //# sourceMappingURL=getExtractedValues.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"getExtractedValues.cjs","names":[],"sources":["../../src/utils/getExtractedValues.ts"],"sourcesContent":["export const getExtractedValues = ({\n tested, expectedKey, valueType\n}: {\n tested: string[];\n expectedKey: string;\n valueType: 'number' | 'string';\n}): string[] => {\n const results: string[] = []\n if (!tested || !Array.isArray(tested)) return results // Предохранитель от пустых массивов\n\n for (let i = 0, max = tested.length; i < max; i++) {\n const t = tested[i]\n if (typeof t !== 'string') continue // ЗАЩИТА: Пропускаем всё, что не является валидной строкой\n\n let regex\n switch (valueType) {\n case 'number':\n regex = new RegExp(`\\\\[${expectedKey}=(?<value>\\\\d+)\\\\]`, 'g')\n break\n case 'string':\n default:\n regex = new RegExp(`\\\\[${expectedKey}=(?<value>.*?)\\\\]`, 'g')\n break\n }\n\n for (const n of t.matchAll(regex)) {\n if (n?.groups) { results.push(n.groups.value) }\n }\n }\n return results\n}\n"],"mappings":"AAAA,IAAa,GAAsB,CACjC,SAAQ,cAAa,eAKP,CACd,IAAM,EAAoB,CAAC,EAC3B,GAAI,CAAC,GAAU,CAAC,MAAM,QAAQ,CAAM,EAAG,OAAO,EAE9C,IAAK,IAAI,EAAI,EAAG,EAAM,EAAO,OAAQ,EAAI,EAAK,IAAK,CACjD,IAAM,EAAI,EAAO,GACjB,GAAI,OAAO,GAAM,SAAU,SAE3B,IAAI,EACJ,OAAQ,EAAR,CACA,IAAK,SACH,EAAY,OAAO,MAAM,EAAY,oBAAqB,GAAG,EAC7D,MAEF,QACE,EAAY,OAAO,MAAM,EAAY,mBAAoB,GAAG,EAC5D,KACF,CAEA,IAAK,IAAM,KAAK,EAAE,SAAS,CAAK,EAC1B,GAAG,QAAU,EAAQ,KAAK,EAAE,OAAO,KAAK,CAEhD,CACA,OAAO,CACT"}
@@ -1,2 +0,0 @@
1
- let e=require("vue");function t(t){if(typeof t!=`object`||!t)return(0,e.shallowRef)(t);let n=`subscribe`in t&&typeof t.subscribe==`function`,r=(0,e.shallowRef)(n?t.value:t),i=null;if(n)i=t.subscribe(e=>{r.value=e});else if(`__subscribe`in t){let e=t;typeof e.__subscribe==`function`&&(i=e.__subscribe(()=>{r.value=Array.isArray(t)?[...t]:{...t}}))}return i&&(0,e.onScopeDispose)(()=>{i&&i()}),r}exports.useReactiveValue=t;
2
- //# sourceMappingURL=core.vue-adapter.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"core.vue-adapter.cjs","names":[],"sources":["../../src/vue/core.vue-adapter.ts"],"sourcesContent":["import { shallowRef, onScopeDispose, ShallowRef } from 'vue'\nimport { ISignalLike, CleanupFn } from '../core/types'\n\n/**\n * ⚛️ Расширенный интерфейс для поддержки внутренних методов подписки Proxy-объектов ядра\n */\ninterface IReactiveProxyExtension {\n __subscribe?: (cb: () => void) => CleanupFn;\n}\n\n/**\n * 🟢 REACTIVE ENGINE ADAPTER FOR VUE 3 (v2.6.1)\n *\n * Нативно интегрирует синхронные и асинхронные графы ядра с реактивной системой Vue 3.\n * Автоматически выводит тип внутренней структуры данных и возвращает строго типизированный ShallowRef.\n */\nexport function useReactiveValue<V>(signal: ISignalLike<V>): ShallowRef<V>;\nexport function useReactiveValue<T extends object>(proxy: T): ShallowRef<T>;\nexport function useReactiveValue<T>(primitive: T): ShallowRef<T>;\nexport function useReactiveValue(item: unknown): ShallowRef<unknown> {\n // Быстрый выход для примитивов или невалидных объектов, переданных по ошибке\n if (item === null || item === undefined || typeof item !== 'object') {\n return shallowRef(item)\n }\n\n const isSignal = 'subscribe' in item && typeof (item as Record<string, unknown>).subscribe === 'function'\n\n // Вычисляем стартовое значение без использования unsafe any\n const getInitialValue = (): unknown => {\n if (isSignal) {\n return (item as ISignalLike<unknown>).value\n }\n return item\n }\n\n // Инициализируем реактивный контейнер Vue 3 стартовым снимком из ядра\n const stateRef = shallowRef(getInitialValue())\n let unsubscribe: CleanupFn | null = null\n\n // =========================================================================\n // СЦЕНАРИЙ 1: Подписка на Сигналы и Вычисляемые свойства (Computed)\n // =========================================================================\n if (isSignal) {\n const signalItem = item as ISignalLike<unknown>\n unsubscribe = signalItem.subscribe((newValue) => {\n stateRef.value = newValue // Vue 3 автоматически триггерит обновление DOM\n })\n }\n // =========================================================================\n // СЦЕНАРИЙ 2: Подписка на глубокие Proxy-объекты и массивы (reactive)\n // =========================================================================\n else if ('__subscribe' in item) {\n const potentialProxy = item as IReactiveProxyExtension\n if (typeof potentialProxy.__subscribe === 'function') {\n unsubscribe = potentialProxy.__subscribe(() => {\n // Для Proxy-коллекций принудительно создаем shallow-копию ссылки,\n // заставляя ленивый движок Vue 3 безупречно перерисовывать шаблоны .push/.splice мутаций!\n stateRef.value = Array.isArray(item) ? [...item] : { ...item }\n })\n }\n }\n\n // Автоматически освобождаем оперативную память и гасим эффекты ядра\n // при размонтировании Vue-компонента или закрытии EffectScope\n if (unsubscribe) {\n onScopeDispose(() => {\n if (unsubscribe) unsubscribe()\n })\n }\n\n return stateRef\n}\n"],"mappings":"qBAmBA,SAAgB,EAAiB,EAAoC,CAEnE,GAA2C,OAAO,GAAS,WAAvD,EACF,OAAA,EAAA,EAAA,WAAA,CAAkB,CAAI,EAGxB,IAAM,EAAW,cAAe,GAAQ,OAAQ,EAAiC,WAAc,WAWzF,GAAA,EAAA,EAAA,WAAA,CAPA,EACM,EAA8B,MAEjC,CAIoC,EACzC,EAAgC,KAKpC,GAAI,EAEF,EAAc,EAAW,UAAW,GAAa,CAC/C,EAAS,MAAQ,CACnB,CAAC,OAKE,GAAI,gBAAiB,EAAM,CAC9B,IAAM,EAAiB,EACnB,OAAO,EAAe,aAAgB,aACxC,EAAc,EAAe,gBAAkB,CAG7C,EAAS,MAAQ,MAAM,QAAQ,CAAI,EAAI,CAAC,GAAG,CAAI,EAAI,CAAE,GAAG,CAAK,CAC/D,CAAC,EAEL,CAUA,OANI,IACF,EAAA,EAAA,eAAA,KAAqB,CACf,GAAa,EAAY,CAC/B,CAAC,EAGI,CACT"}
@@ -1,2 +0,0 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../core.cjs"),t=require("./core.vue-adapter.cjs");let n=require("vue");var r=class extends e.ReactiveEngine{frameworkPrefix=`vue-auto`;reactive(e,t){let n,r=e=>{if(!e||typeof e!=`object`||Symbol.iterator in e)return;let t=e;Reflect.has(t,`__subscribe`)||Object.defineProperty(t,"__subscribe",{get:()=>e=>this.effect(()=>{try{JSON.stringify(n)}catch{Object.values(n)}e()},`vue-proxy-internal-subscription`),configurable:!0,enumerable:!1}),Reflect.has(t,`__v_skip`)||Object.defineProperty(t,"__v_skip",{get:()=>!0,configurable:!0,enumerable:!1});for(let e in t)if(Object.prototype.hasOwnProperty.call(t,e)){let n=t[e];typeof n==`object`&&n&&r(n)}};return r(e),n=super.reactive(e,t),n}use(e){if(typeof e!=`object`||!e)return(0,n.shallowRef)(e);if(`subscribe`in e&&typeof e.subscribe==`function`){let t=e,r=(0,n.shallowRef)(this.untrack(()=>t.value)),i=`__subscribe`in t&&typeof t.__subscribe==`function`&&t.__subscribe?t.__subscribe(()=>{r.value=t.value,(0,n.triggerRef)(r)}):t.subscribe(e=>{r.value=e,(0,n.triggerRef)(r)});return(0,n.getCurrentInstance)()?(0,n.onUnmounted)(()=>i()):(0,n.getCurrentScope)()&&(0,n.onScopeDispose)(()=>i()),r}let t=(0,n.shallowRef)(e),r=e;if(`__subscribe`in r&&typeof r.__subscribe==`function`){let e=r.__subscribe(()=>{(0,n.triggerRef)(t)});(0,n.getCurrentInstance)()?(0,n.onUnmounted)(()=>e()):(0,n.getCurrentScope)()&&(0,n.onScopeDispose)(()=>e())}return t}};exports.ReactiveEngine=r,exports.useReactiveValue=t.useReactiveValue;
2
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../src/vue/index.ts"],"sourcesContent":["import { CleanupFn, ISignalLike } from '../core/types'\nimport { ReactiveEngineAutomatic } from '../core/core'\nimport { getCurrentInstance, getCurrentScope, onScopeDispose, onUnmounted, shallowRef, ShallowRef, triggerRef } from 'vue'\n\nexport { useReactiveValue } from './core.vue-adapter'\n\n/**\n * ⚛️ Расширенный интерфейс для поддержки внутренних маркеров Vue и Ядра на прокси-объектах\n */\ninterface IVueProxyExtensions {\n __subscribe?: (cb: () => void) => CleanupFn;\n __v_skip?: boolean;\n}\n\nclass ExtendedReactiveEngine extends ReactiveEngineAutomatic {\n protected override frameworkPrefix = 'vue-auto'\n\n public override reactive<T extends object>(target: T, name?: string): T {\n // Внутренний кэш оригинального прокси, который будет доступен в замыкании макрозадачи подписки\n let originalProxy: T\n\n const injectVueMarkers = (obj: unknown): void => {\n if (!obj || typeof obj !== 'object' || Symbol.iterator in (obj as object)) return\n\n const targetObj = obj as Record<string, unknown> & IVueProxyExtensions\n\n if (!Reflect.has(targetObj, '__subscribe')) {\n Object.defineProperty(targetObj, '__subscribe', {\n get: () => {\n return (cb: () => void) => {\n return this.effect(() => {\n try {\n JSON.stringify(originalProxy)\n } catch (e) {\n Object.values(originalProxy as Record<string, unknown>)\n }\n cb()\n }, 'vue-proxy-internal-subscription')\n }\n },\n configurable: true,\n enumerable: false\n })\n }\n\n if (!Reflect.has(targetObj, '__v_skip')) {\n Object.defineProperty(targetObj, '__v_skip', {\n get: () => true,\n configurable: true,\n enumerable: false\n })\n }\n\n for (const key in targetObj) {\n if (Object.prototype.hasOwnProperty.call(targetObj, key)) {\n const value = targetObj[key]\n if (value !== null && typeof value === 'object') {\n injectVueMarkers(value)\n }\n }\n }\n }\n\n injectVueMarkers(target)\n originalProxy = super.reactive(target, name)\n return originalProxy\n }\n\n /**\n * Адаптирует примитивы реактивного ядра во Vue ShallowRef объекты.\n * Полностью изолирует начальное чтение от реактивного контекста ядра (Topological Isolation).\n */\n public use<T>(item: T): T extends ISignalLike<infer V> ? ShallowRef<V> : ShallowRef<T> {\n type ReturnType = T extends ISignalLike<infer V> ? ShallowRef<V> : ShallowRef<T>\n\n if (item === null || item === undefined || typeof item !== 'object') {\n return shallowRef(item) as ReturnType\n }\n\n const isSignal = 'subscribe' in item && typeof (item as Record<string, unknown>).subscribe === 'function'\n\n if (isSignal) {\n const signalItem = item as unknown as ISignalLike<unknown>\n\n // ⚛️ КЛЮЧЕВОЙ ФИКС: Чтение стартового значения оборачиваем в untrack(),\n // предотвращая ложные каскадные вызовы Pull-валидатора при инициализации!\n const initialValue = this.untrack(() => signalItem.value)\n const state = shallowRef(initialValue)\n\n // Используем пассивный системный хук __subscribe, если он доступен (для computed-нод),\n // чтобы избежать спама множественных push-уведомлений посреди транзакции\n const hasHook = '__subscribe' in signalItem && typeof signalItem.__subscribe === 'function'\n\n const unsubscribe = hasHook && signalItem.__subscribe\n ? signalItem.__subscribe(() => {\n state.value = signalItem.value\n triggerRef(state)\n })\n : signalItem.subscribe((newValue) => {\n state.value = newValue\n triggerRef(state)\n })\n\n if (getCurrentInstance()) {\n onUnmounted(() => unsubscribe())\n } else if (getCurrentScope()) {\n onScopeDispose(() => unsubscribe())\n }\n\n return state as ReturnType\n }\n\n const state = shallowRef(item)\n const potentialProxy = item as Record<string, unknown> & IVueProxyExtensions\n\n if ('__subscribe' in potentialProxy && typeof potentialProxy.__subscribe === 'function') {\n const unsubscribe = potentialProxy.__subscribe(() => {\n triggerRef(state)\n })\n\n if (getCurrentInstance()) {\n onUnmounted(() => unsubscribe())\n } else if (getCurrentScope()) {\n onScopeDispose(() => unsubscribe())\n }\n }\n\n return state as ReturnType\n }\n}\n\nexport { ExtendedReactiveEngine as ReactiveEngine }\n"],"mappings":"2JAcA,IAAM,EAAN,cAAqC,EAAA,cAAwB,CAC3D,gBAAqC,WAErC,SAA2C,EAAW,EAAkB,CAEtE,IAAI,EAEE,EAAoB,GAAuB,CAC/C,GAAI,CAAC,GAAO,OAAO,GAAQ,UAAY,OAAO,YAAa,EAAgB,OAE3E,IAAM,EAAY,EAEb,QAAQ,IAAI,EAAW,aAAa,GACvC,OAAO,eAAe,EAAW,cAAe,CAC9C,QACU,GACC,KAAK,WAAa,CACvB,GAAI,CACF,KAAK,UAAU,CAAa,CAC9B,MAAY,CACV,OAAO,OAAO,CAAwC,CACxD,CACA,EAAG,CACL,EAAG,iCAAiC,EAGxC,aAAc,GACd,WAAY,EACd,CAAC,EAGE,QAAQ,IAAI,EAAW,UAAU,GACpC,OAAO,eAAe,EAAW,WAAY,CAC3C,QAAW,GACX,aAAc,GACd,WAAY,EACd,CAAC,EAGH,IAAK,IAAM,KAAO,EAChB,GAAI,OAAO,UAAU,eAAe,KAAK,EAAW,CAAG,EAAG,CACxD,IAAM,EAAQ,EAAU,GACF,OAAO,GAAU,UAAnC,GACF,EAAiB,CAAK,CAE1B,CAEJ,EAIA,OAFA,EAAiB,CAAM,EACvB,EAAgB,MAAM,SAAS,EAAQ,CAAI,EACpC,CACT,CAMA,IAAc,EAAyE,CAGrF,GAA2C,OAAO,GAAS,WAAvD,EACF,OAAA,EAAA,EAAA,WAAA,CAAkB,CAAI,EAKxB,GAFiB,cAAe,GAAQ,OAAQ,EAAiC,WAAc,WAEjF,CACZ,IAAM,EAAa,EAKb,GAAA,EAAA,EAAA,WAAA,CADe,KAAK,YAAc,EAAW,KAC1B,CAAY,EAM/B,EAFU,gBAAiB,GAAc,OAAO,EAAW,aAAgB,YAElD,EAAW,YACtC,EAAW,gBAAkB,CAC7B,EAAM,MAAQ,EAAW,OACzB,EAAA,EAAA,WAAA,CAAW,CAAK,CAClB,CAAC,EACC,EAAW,UAAW,GAAa,CACnC,EAAM,MAAQ,GACd,EAAA,EAAA,WAAA,CAAW,CAAK,CAClB,CAAC,EAQH,OANA,EAAA,EAAA,mBAAA,CAAuB,GACrB,EAAA,EAAA,YAAA,KAAkB,EAAY,CAAC,GAC1B,EAAA,EAAA,gBAAA,CAAoB,IACzB,EAAA,EAAA,eAAA,KAAqB,EAAY,CAAC,EAG7B,CACT,CAEA,IAAM,GAAA,EAAA,EAAA,WAAA,CAAmB,CAAI,EACvB,EAAiB,EAEvB,GAAI,gBAAiB,GAAkB,OAAO,EAAe,aAAgB,WAAY,CACvF,IAAM,EAAc,EAAe,gBAAkB,EACnD,EAAA,EAAA,WAAA,CAAW,CAAK,CAClB,CAAC,GAED,EAAA,EAAA,mBAAA,CAAuB,GACrB,EAAA,EAAA,YAAA,KAAkB,EAAY,CAAC,GAC1B,EAAA,EAAA,gBAAA,CAAoB,IACzB,EAAA,EAAA,eAAA,KAAqB,EAAY,CAAC,CAEtC,CAEA,OAAO,CACT,CACF"}