@pravosleva/reactive-engine 2.6.2 → 2.6.3

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.
@@ -10,7 +10,7 @@ export declare function queueLog(type: LogEventType, label: string, details?: {
10
10
  export declare function flushLogs(): void;
11
11
  export declare class ReactiveEngineCore {
12
12
  protected frameworkPrefix: string;
13
- private logger;
13
+ logger: EngineLoggerOptions;
14
14
  epoch: number;
15
15
  activeConsumer: any;
16
16
  batchDepth: number;
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/core/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/core/core.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"core.logger.d.ts","sourceRoot":"","sources":["../../src/core/core.logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,UAAU,UAAU;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,qBAAa,sBAAsB;IACjC,OAAO,CAAC,MAAM,CAAC,YAAY,CAA8B;IAEzD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAO;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAI;IACnD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAI;IAEpD,OAAO,CAAC,MAAM,CAAC,WAAW;IAM1B,OAAO,CAAC,MAAM,CAAC,kBAAkB;WA4CnB,UAAU,CACtB,YAAY,EAAE,GAAG,EACjB,UAAU,EAAE,QAAQ,EACpB,MAAM,EAAE;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,UAAU,CAAC;QAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;KAAE;CAyBtG"}
1
+ {"version":3,"file":"core.logger.d.ts","sourceRoot":"","sources":["../../src/core/core.logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,UAAU,UAAU;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,qBAAa,sBAAsB;IACjC,OAAO,CAAC,MAAM,CAAC,YAAY,CAA8B;IAEzD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAO;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAI;IACnD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAI;IAEpD,OAAO,CAAC,MAAM,CAAC,WAAW;IAM1B,OAAO,CAAC,MAAM,CAAC,kBAAkB;WA4CnB,UAAU,CACtB,YAAY,EAAE,GAAG,EACjB,UAAU,EAAE,QAAQ,EACpB,MAAM,EAAE;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,UAAU,CAAC;QAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;KAAE;CAqCtG"}
@@ -1,10 +1,11 @@
1
- import { Resource, ResourceOptions, Signal } from './types';
1
+ import { EngineLoggerOptions, Resource, ResourceOptions, Signal } from './types';
2
2
  interface IReactiveEngine {
3
3
  signal<V>(initialValue: V, optionsOrName?: any): Signal<V>;
4
4
  effect(fn: () => any, name?: string): () => void;
5
5
  untrack<V>(fn: () => V): V;
6
6
  log(params: any): void;
7
7
  delay(ms: number, signal: AbortSignal): Promise<void>;
8
+ logger: EngineLoggerOptions;
8
9
  }
9
10
  export declare function createResource<T, S = void>(engine: IReactiveEngine, fetcher: (source: S, signal: AbortSignal) => Promise<T>, source?: {
10
11
  value: S;
@@ -1 +1 @@
1
- {"version":3,"file":"core.method.resource.d.ts","sourceRoot":"","sources":["../../src/core/core.method.resource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAiB,MAAM,EAAE,MAAM,SAAS,CAAA;AAG1E,UAAU,eAAe;IACvB,MAAM,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IACjD,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,GAAG,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAAC;IACvB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,EACxC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EACvD,MAAM,CAAC,EAAE;IAAE,KAAK,EAAE,CAAC,CAAA;CAAE,EACrB,aAAa,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,GAC7C,QAAQ,CAAC,CAAC,CAAC,CA4Jb"}
1
+ {"version":3,"file":"core.method.resource.d.ts","sourceRoot":"","sources":["../../src/core/core.method.resource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,eAAe,EAAiB,MAAM,EAAE,MAAM,SAAS,CAAA;AAG/F,UAAU,eAAe;IACvB,MAAM,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,aAAa,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IACjD,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,GAAG,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAAC;IACvB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,MAAM,EAAE,mBAAmB,CAAA;CAC5B;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,EACxC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EACvD,MAAM,CAAC,EAAE;IAAE,KAAK,EAAE,CAAC,CAAA;CAAE,EACrB,aAAa,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,GAC7C,QAAQ,CAAC,CAAC,CAAC,CAuQb"}
@@ -81,6 +81,9 @@ export interface ResourceState<T> {
81
81
  loading: boolean;
82
82
  error: string | null;
83
83
  isRetrying?: boolean;
84
+ attemptIndex: number;
85
+ retryCount: number;
86
+ totalElapsedMs?: number;
84
87
  }
85
88
  export interface Resource<T> extends ResourceState<T> {
86
89
  refetch: () => void;
@@ -93,6 +96,8 @@ export interface ResourceOptions<T, S = void> {
93
96
  resetDataOnSourceChange?: boolean;
94
97
  validateBeforeFetch?: (source: S) => boolean | string;
95
98
  responseValidate?: (data: T) => boolean | string;
99
+ timeout?: number;
100
+ retryCount?: number;
96
101
  }
97
102
  export interface EngineLoggerOptions {
98
103
  instanceName?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAA;AAEhD,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC;AAEhG,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,SAAS,EAAE,CAAC;IAC7B,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC;AACnC,MAAM,MAAM,QAAQ,GAAG,MAAM,SAAS,GAAG,IAAI,CAAC;AAC9C,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,MAAM,GAAG,MAAM,GAAG;IAAE,KAAI,MAAM,EAAE,kBAAkB,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;CAAE,CAAC;AAChG,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,kBAAkB,KAAK,CAAC,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAElB;;OAEG;IACH,oBAAoB,CAAC,EAAE,CAAC,CAAC;IAEzB;;OAEG;IACH,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,KAAK,SAAS,CAAC;IAE7C;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,SAAS,CAAC;CAC7C;AAED;;;GAGG;AACH,MAAM,WAAW,MAAM,CAAC,CAAC,CAAE,SAAQ,WAAW,CAAC,CAAC,CAAC;IAC/C,KAAK,EAAE,CAAC,CAAC;IACT,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,CAAE,SAAQ,WAAW,CAAC,CAAC,CAAC;IACjD,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,EAAE,CAAC,EAAE,MAAM,IAAI,CAAC;IAChB,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,MAAM,CAAC;CAC3C;AAED,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ,CAAC,CAAC,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;IACnD,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,SAAS,CAAC;IAC9D,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,mBAAmB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,GAAG,MAAM,CAAC;IACtD,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,GAAG,MAAM,CAAC;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,8BAA8B,CAAC,EAAE,OAAO,CAAC;CAC1C;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,EAAE,OAAO,CAAC;IACZ,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,QAAQ,EAAE,cAAc,CAAC;CAC1B"}
package/dist/core.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.cjs","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'\n// import { 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'\nimport { createResource } from './core.method.resource'\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: Array<Set<any> | undefined> = []\n public maxPendingDepth = 0\n public computedCache = new WeakMap<Function, any>()\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 public pendingCleanups = new Set<() => void>()\n\n // Метод для регистрации отложенной очистки\n public queueCleanup(cleanup: () => void): void {\n this.pendingCleanups.add(cleanup)\n }\n\n constructor(options?: { logger?: EngineLoggerOptions }) {\n this.logger = options?.logger || { isEnabled: false }\n }\n\n public scheduleEffect(effect: any): void {\n const depth = effect.depth || 0\n if (!this.pendingEffects[depth]) {\n this.pendingEffects[depth] = new Set()\n }\n this.pendingEffects[depth]!.add(effect)\n if (depth > this.maxPendingDepth) {\n this.maxPendingDepth = depth\n }\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 if (this.batchedSignals.size > 0) {\n for (const sig of this.batchedSignals) {\n if (sig._flushBatch) sig._flushBatch()\n }\n this.batchedSignals.clear()\n }\n\n this.flushEffects()\n }\n }\n }\n\n public flushEffects(): void {\n if (this.batchDepth > 0) return\n\n const prevConsumer = this.activeConsumer\n\n try {\n for (let depth = 0; depth <= this.maxPendingDepth; depth++) {\n const bucket = this.pendingEffects[depth]\n\n if (!bucket || bucket.size === 0) continue\n\n const effects = Array.from(bucket)\n bucket.clear()\n\n for (const effect of effects) {\n if (effect.isDisposed) continue\n\n // ⚡ ЗOЛОТOЙ СТАНДАРТ ОПТИМИЗАЦИИ (Early Dirty Check Bypass):\n // Переносим проверку грязи в самое начало цикла. Если эффект не был промаркирован\n // как DIRTY волной push-уведомлений, мы мгновенно пропускаем его, полностью\n // избавляя V8 от холостого обхода родителей и тяжелых хэш-поисков depVersions.get(dep).\n if (!effect.isDirty) continue\n\n if (effect.dependencies && effect.dependencies.size > 0) {\n let parentChanged = false\n\n for (const dep of effect.dependencies) {\n const rawNode = dep._node || dep\n\n if (rawNode.type === 'computed' && rawNode.state > 0) {\n if (rawNode.update) rawNode.update()\n }\n\n if (effect.depVersions && effect.depVersions.get(dep) !== rawNode.version) {\n parentChanged = true\n }\n }\n\n if (!parentChanged && effect.dependencies.size > 0) {\n effect.isDirty = false\n continue\n }\n }\n\n try {\n effect.run()\n } catch (err) {\n // ⚡ ФИКС ТЕСТА #177: Если один из эффектов выбросил исключение,\n // принудительно очищаем и гасим флаги грязи (isDirty) у всех оставшихся\n // в очереди эффектов текущего и последующих уровней глубины.\n for (let d = depth; d <= this.maxPendingDepth; d++) {\n const remainingBucket = this.pendingEffects[d]\n if (remainingBucket) {\n for (const remEffect of remainingBucket) {\n remEffect.isDirty = false\n }\n remainingBucket.clear()\n }\n }\n this.maxPendingDepth = 0\n throw err // Прокидываем ошибку дальше по спецификации\n }\n\n }\n\n if (depth > 0) {\n let hasEarlierEffects = false\n for (let i = 0; i < depth; i++) {\n if (this.pendingEffects[i] && this.pendingEffects[i]!.size > 0) {\n hasEarlierEffects = true\n break\n }\n }\n if (hasEarlierEffects) depth = -1\n }\n }\n this.maxPendingDepth = 0\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 // ⚛️ ФИКС ДЛЯ РЕЛИЗА 2.5.0: Меняем private на public,\n // чтобы изолированные функции-методы имели легальный доступ к регистратору логов\n public log(params: any) {\n if (!this.logger || !this.logger.isEnabled) return\n ReactiveDebounceLogger.processLog(this.logger, queueLog, params)\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 public 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 /**\n * Создает умную реактивную декларативную обертку над асинхронными операциями\n * с автоматическим подавлением Race Conditions и встроенным методом .destroy().\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 // Передаем инстанс движка (this) как IReactiveEngine для соблюдения строгой типизации\n return createResource<T, S>(this, fetcher, source, optionsOrName)\n }\n}\n\nexport { ReactiveEngineCore as ReactiveEngine, ReactiveEngineCore as ReactiveEngineAutomatic }\n"],"mappings":"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"}
1
+ {"version":3,"file":"core.cjs","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'\n// import { 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'\nimport { createResource } from './core.method.resource'\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 public logger: EngineLoggerOptions\n public epoch = 0\n public activeConsumer: any = null\n public batchDepth = 0\n public subscriberId = 0\n public pendingEffects: Array<Set<any> | undefined> = []\n public maxPendingDepth = 0\n public computedCache = new WeakMap<Function, any>()\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 public pendingCleanups = new Set<() => void>()\n\n // Метод для регистрации отложенной очистки\n public queueCleanup(cleanup: () => void): void {\n this.pendingCleanups.add(cleanup)\n }\n\n constructor(options?: { logger?: EngineLoggerOptions }) {\n this.logger = options?.logger || { isEnabled: false }\n }\n\n public scheduleEffect(effect: any): void {\n const depth = effect.depth || 0\n if (!this.pendingEffects[depth]) {\n this.pendingEffects[depth] = new Set()\n }\n this.pendingEffects[depth]!.add(effect)\n if (depth > this.maxPendingDepth) {\n this.maxPendingDepth = depth\n }\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 if (this.batchedSignals.size > 0) {\n for (const sig of this.batchedSignals) {\n if (sig._flushBatch) sig._flushBatch()\n }\n this.batchedSignals.clear()\n }\n\n this.flushEffects()\n }\n }\n }\n\n public flushEffects(): void {\n if (this.batchDepth > 0) return\n\n const prevConsumer = this.activeConsumer\n\n try {\n for (let depth = 0; depth <= this.maxPendingDepth; depth++) {\n const bucket = this.pendingEffects[depth]\n\n if (!bucket || bucket.size === 0) continue\n\n const effects = Array.from(bucket)\n bucket.clear()\n\n for (const effect of effects) {\n if (effect.isDisposed) continue\n\n // ⚡ ЗOЛОТOЙ СТАНДАРТ ОПТИМИЗАЦИИ (Early Dirty Check Bypass):\n // Переносим проверку грязи в самое начало цикла. Если эффект не был промаркирован\n // как DIRTY волной push-уведомлений, мы мгновенно пропускаем его, полностью\n // избавляя V8 от холостого обхода родителей и тяжелых хэш-поисков depVersions.get(dep).\n if (!effect.isDirty) continue\n\n if (effect.dependencies && effect.dependencies.size > 0) {\n let parentChanged = false\n\n for (const dep of effect.dependencies) {\n const rawNode = dep._node || dep\n\n if (rawNode.type === 'computed' && rawNode.state > 0) {\n if (rawNode.update) rawNode.update()\n }\n\n if (effect.depVersions && effect.depVersions.get(dep) !== rawNode.version) {\n parentChanged = true\n }\n }\n\n if (!parentChanged && effect.dependencies.size > 0) {\n effect.isDirty = false\n continue\n }\n }\n\n try {\n effect.run()\n } catch (err) {\n // ⚡ ФИКС ТЕСТА #177: Если один из эффектов выбросил исключение,\n // принудительно очищаем и гасим флаги грязи (isDirty) у всех оставшихся\n // в очереди эффектов текущего и последующих уровней глубины.\n for (let d = depth; d <= this.maxPendingDepth; d++) {\n const remainingBucket = this.pendingEffects[d]\n if (remainingBucket) {\n for (const remEffect of remainingBucket) {\n remEffect.isDirty = false\n }\n remainingBucket.clear()\n }\n }\n this.maxPendingDepth = 0\n throw err // Прокидываем ошибку дальше по спецификации\n }\n\n }\n\n if (depth > 0) {\n let hasEarlierEffects = false\n for (let i = 0; i < depth; i++) {\n if (this.pendingEffects[i] && this.pendingEffects[i]!.size > 0) {\n hasEarlierEffects = true\n break\n }\n }\n if (hasEarlierEffects) depth = -1\n }\n }\n this.maxPendingDepth = 0\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 // ⚛️ ФИКС ДЛЯ РЕЛИЗА 2.5.0: Меняем private на public,\n // чтобы изолированные функции-методы имели легальный доступ к регистратору логов\n public log(params: any) {\n if (!this.logger || !this.logger.isEnabled) return\n ReactiveDebounceLogger.processLog(this.logger, queueLog, params)\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 public 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 /**\n * Создает умную реактивную декларативную обертку над асинхронными операциями\n * с автоматическим подавлением Race Conditions и встроенным методом .destroy().\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 // Передаем инстанс движка (this) как IReactiveEngine для соблюдения строгой типизации\n return createResource<T, S>(this, fetcher, source, optionsOrName)\n }\n}\n\nexport { ReactiveEngineCore as ReactiveEngine, ReactiveEngineCore as ReactiveEngineAutomatic }\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- var e=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);let a=i.length,o=(this.TIME_WINDOW_MS/1e3).toFixed(1);return i.length<=1?(this.churnTracker.delete(e),{marker:`🟢`,info:`[STABLE] (1 изм./${o}s)`}):(this.churnTracker.set(e,i),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)}};exports.ReactiveDebounceLogger=e;
1
+ var e=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);let a=i.length,o=(this.TIME_WINDOW_MS/1e3).toFixed(1);return i.length<=1?(this.churnTracker.delete(e),{marker:`🟢`,info:`[STABLE] (1 изм./${o}s)`}):(this.churnTracker.set(e,i),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||e.filter&&!(e.filter instanceof RegExp?e.filter.test(i):i.includes(e.filter))||o&&!e.isCoreOptimizationDebugEnabled)return;if(a&&`from`in a&&`to`in a&&this.isDeepEqual(a.from,a.to)){if((r===`computed`||r===`resource`)&&e.isCoreOptimizationDebugEnabled){t(r,`🔵 [IDLE] ${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)}};exports.ReactiveDebounceLogger=e;
2
2
  //# sourceMappingURL=core.logger.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.logger.cjs","names":[],"sources":["../src/core/core.logger.ts"],"sourcesContent":["// core.logger.ts\nimport { LogEventType } from \"./types\"\n\ninterface LogDetails {\n from?: unknown;\n to?: unknown;\n payload?: unknown;\n}\n\nexport class ReactiveDebounceLogger {\n private static churnTracker = new Map<string, number[]>()\n\n private static readonly TIME_WINDOW_MS = 1000\n private static readonly CHURN_WARNING_THRESHOLD = 3\n private static readonly CHURN_CRITICAL_THRESHOLD = 6\n\n private static isDeepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false\n return JSON.stringify(a) === JSON.stringify(b)\n }\n\n private static analyzeSignalChurn(label: string): { marker: string; info: string } {\n const now = Date.now()\n if (!this.churnTracker.has(label)) {\n this.churnTracker.set(label, [])\n }\n\n const history = this.churnTracker.get(label)!\n const cutoff = now - this.TIME_WINDOW_MS\n // Фильтруем историю\n const activeHistory = history.filter(ts => ts > cutoff)\n activeHistory.push(now)\n\n const updateCount = activeHistory.length\n const intervalSec = (this.TIME_WINDOW_MS / 1000).toFixed(1)\n\n // ⚛️ ФИКС УТЕЧКИ ПАМЯТИ: Если узел стабилен и старых логов нет,\n // удаляем ключ из Map целиком, чтобы не копить мусор\n if (activeHistory.length <= 1) {\n this.churnTracker.delete(label)\n return { marker: '🟢', info: `[STABLE] (1 изм./${intervalSec}s)` }\n } else {\n this.churnTracker.set(label, activeHistory)\n }\n\n if (updateCount >= this.CHURN_CRITICAL_THRESHOLD) {\n return {\n marker: '🔴',\n info: `[CRITICAL CHURN] (${updateCount} изм./${intervalSec}s) — Нужен debounce!`\n }\n }\n\n if (updateCount >= this.CHURN_WARNING_THRESHOLD) {\n return {\n marker: '🟡',\n info: `[WARNING CHURN] (${updateCount} изм./${intervalSec}s)`\n }\n }\n\n return {\n marker: '🟢',\n info: `[STABLE] (${updateCount} изм./${intervalSec}s)`\n }\n }\n\n public static processLog(\n engineLogger: any,\n queueLogFn: Function,\n params: { type: LogEventType; label: string; details?: LogDetails; isInternalCoreSignal?: boolean }\n ) {\n const { type, label, details, isInternalCoreSignal = false } = params\n\n if (!engineLogger.isEnabled) return\n if (isInternalCoreSignal && !engineLogger.isCoreOptimizationDebugEnabled) return\n\n if (details && 'from' in details && 'to' in details) {\n if (this.isDeepEqual(details.from, details.to)) {\n if (type === 'computed') {\n queueLogFn(type, `🔵 [IDLE PULL] ${label} (Значение кэша не изменилось)`, details)\n return\n }\n return\n }\n }\n\n let churnInfo = ''\n if (type === 'signal' || type === 'resource' || type === 'computed') {\n const churn = this.analyzeSignalChurn(label)\n churnInfo = churn.marker === '🟢' ? ` ${churn.marker}` : ` ${churn.marker} ${churn.info}`\n }\n\n queueLogFn(type, `${label}${churnInfo}`, details)\n }\n}\n"],"mappings":"AASA,IAAa,EAAb,KAAoC,CAClC,OAAe,aAAe,IAAI,IAElC,OAAwB,eAAiB,IACzC,OAAwB,wBAA0B,EAClD,OAAwB,yBAA2B,EAEnD,OAAe,YAAY,EAAY,EAAqB,CAG1D,OAFI,IAAM,EAAU,GAChB,OAAO,GAAM,UAAY,OAAO,GAAM,UAAY,IAAM,MAAQ,IAAM,KAAa,GAChF,KAAK,UAAU,CAAC,IAAM,KAAK,UAAU,CAAC,CAC/C,CAEA,OAAe,mBAAmB,EAAiD,CACjF,IAAM,EAAM,KAAK,IAAI,EAChB,KAAK,aAAa,IAAI,CAAK,GAC9B,KAAK,aAAa,IAAI,EAAO,CAAC,CAAC,EAGjC,IAAM,EAAU,KAAK,aAAa,IAAI,CAAK,EACrC,EAAS,EAAM,KAAK,eAEpB,EAAgB,EAAQ,OAAO,GAAM,EAAK,CAAM,EACtD,EAAc,KAAK,CAAG,EAEtB,IAAM,EAAc,EAAc,OAC5B,GAAe,KAAK,eAAiB,IAAA,CAAM,QAAQ,CAAC,EAyB1D,OArBI,EAAc,QAAU,GAC1B,KAAK,aAAa,OAAO,CAAK,EACvB,CAAE,OAAQ,KAAM,KAAM,oBAAoB,EAAY,GAAI,IAEjE,KAAK,aAAa,IAAI,EAAO,CAAa,EAGxC,GAAe,KAAK,yBACf,CACL,OAAQ,KACR,KAAM,qBAAqB,EAAY,QAAQ,EAAY,qBAC7D,EAGE,GAAe,KAAK,wBACf,CACL,OAAQ,KACR,KAAM,oBAAoB,EAAY,QAAQ,EAAY,GAC5D,EAGK,CACL,OAAQ,KACR,KAAM,aAAa,EAAY,QAAQ,EAAY,GACrD,EACF,CAEA,OAAc,WACZ,EACA,EACA,EACA,CACA,GAAM,CAAE,OAAM,QAAO,UAAS,uBAAuB,IAAU,EAG/D,GADI,CAAC,EAAa,WACd,GAAwB,CAAC,EAAa,+BAAgC,OAE1E,GAAI,GAAW,SAAU,GAAW,OAAQ,GACtC,KAAK,YAAY,EAAQ,KAAM,EAAQ,EAAE,EAAG,CAC9C,GAAI,IAAS,WAAY,CACvB,EAAW,EAAM,kBAAkB,EAAM,gCAAiC,CAAO,EACjF,MACF,CACA,MACF,CAGF,IAAI,EAAY,GAChB,GAAI,IAAS,UAAY,IAAS,YAAc,IAAS,WAAY,CACnE,IAAM,EAAQ,KAAK,mBAAmB,CAAK,EAC3C,EAAY,EAAM,SAAW,KAAO,IAAI,EAAM,SAAW,IAAI,EAAM,OAAO,GAAG,EAAM,MACrF,CAEA,EAAW,EAAM,GAAG,IAAQ,IAAa,CAAO,CAClD,CACF"}
1
+ {"version":3,"file":"core.logger.cjs","names":[],"sources":["../src/core/core.logger.ts"],"sourcesContent":["// core.logger.ts\nimport { LogEventType } from \"./types\"\n\ninterface LogDetails {\n from?: unknown;\n to?: unknown;\n payload?: unknown;\n}\n\nexport class ReactiveDebounceLogger {\n private static churnTracker = new Map<string, number[]>()\n\n private static readonly TIME_WINDOW_MS = 1000\n private static readonly CHURN_WARNING_THRESHOLD = 3\n private static readonly CHURN_CRITICAL_THRESHOLD = 6\n\n private static isDeepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false\n return JSON.stringify(a) === JSON.stringify(b)\n }\n\n private static analyzeSignalChurn(label: string): { marker: string; info: string } {\n const now = Date.now()\n if (!this.churnTracker.has(label)) {\n this.churnTracker.set(label, [])\n }\n\n const history = this.churnTracker.get(label)!\n const cutoff = now - this.TIME_WINDOW_MS\n // Фильтруем историю\n const activeHistory = history.filter(ts => ts > cutoff)\n activeHistory.push(now)\n\n const updateCount = activeHistory.length\n const intervalSec = (this.TIME_WINDOW_MS / 1000).toFixed(1)\n\n // ⚛️ ФИКС УТЕЧКИ ПАМЯТИ: Если узел стабилен и старых логов нет,\n // удаляем ключ из Map целиком, чтобы не копить мусор\n if (activeHistory.length <= 1) {\n this.churnTracker.delete(label)\n return { marker: '🟢', info: `[STABLE] (1 изм./${intervalSec}s)` }\n } else {\n this.churnTracker.set(label, activeHistory)\n }\n\n if (updateCount >= this.CHURN_CRITICAL_THRESHOLD) {\n return {\n marker: '🔴',\n info: `[CRITICAL CHURN] (${updateCount} изм./${intervalSec}s) — Нужен debounce!`\n }\n }\n\n if (updateCount >= this.CHURN_WARNING_THRESHOLD) {\n return {\n marker: '🟡',\n info: `[WARNING CHURN] (${updateCount} изм./${intervalSec}s)`\n }\n }\n\n return {\n marker: '🟢',\n info: `[STABLE] (${updateCount} изм./${intervalSec}s)`\n }\n }\n\n public static processLog(\n engineLogger: any,\n queueLogFn: Function,\n params: { type: LogEventType; label: string; details?: LogDetails; isInternalCoreSignal?: boolean }\n ) {\n const { type, label, details, isInternalCoreSignal = false } = params\n\n if (!engineLogger.isEnabled) return\n\n // ⚛️ ФИКС #1: Включаем валидацию RegExp фильтра из настроек\n if (engineLogger.filter) {\n const isMatch = engineLogger.filter instanceof RegExp\n ? engineLogger.filter.test(label)\n : label.includes(engineLogger.filter)\n if (!isMatch) return\n }\n\n if (isInternalCoreSignal && !engineLogger.isCoreOptimizationDebugEnabled) return\n\n if (details && 'from' in details && 'to' in details) {\n if (this.isDeepEqual(details.from, details.to)) {\n // ⚛️ ФИКС #2: Разрешаем логам типов 'resource' выводить IDLE транзакции,\n // иначе глубокое равенство объектов состояния блокирует их вывод\n if ((type === 'computed' || type === 'resource') && engineLogger.isCoreOptimizationDebugEnabled) {\n queueLogFn(type, `🔵 [IDLE] ${label}`, details)\n return\n }\n return\n }\n }\n\n let churnInfo = ''\n if (type === 'signal' || type === 'resource' || type === 'computed') {\n const churn = this.analyzeSignalChurn(label)\n churnInfo = churn.marker === '🟢' ? ` ${churn.marker}` : ` ${churn.marker} ${churn.info}`\n }\n\n queueLogFn(type, `${label}${churnInfo}`, details)\n }\n\n}\n"],"mappings":"AASA,IAAa,EAAb,KAAoC,CAClC,OAAe,aAAe,IAAI,IAElC,OAAwB,eAAiB,IACzC,OAAwB,wBAA0B,EAClD,OAAwB,yBAA2B,EAEnD,OAAe,YAAY,EAAY,EAAqB,CAG1D,OAFI,IAAM,EAAU,GAChB,OAAO,GAAM,UAAY,OAAO,GAAM,UAAY,IAAM,MAAQ,IAAM,KAAa,GAChF,KAAK,UAAU,CAAC,IAAM,KAAK,UAAU,CAAC,CAC/C,CAEA,OAAe,mBAAmB,EAAiD,CACjF,IAAM,EAAM,KAAK,IAAI,EAChB,KAAK,aAAa,IAAI,CAAK,GAC9B,KAAK,aAAa,IAAI,EAAO,CAAC,CAAC,EAGjC,IAAM,EAAU,KAAK,aAAa,IAAI,CAAK,EACrC,EAAS,EAAM,KAAK,eAEpB,EAAgB,EAAQ,OAAO,GAAM,EAAK,CAAM,EACtD,EAAc,KAAK,CAAG,EAEtB,IAAM,EAAc,EAAc,OAC5B,GAAe,KAAK,eAAiB,IAAA,CAAM,QAAQ,CAAC,EAyB1D,OArBI,EAAc,QAAU,GAC1B,KAAK,aAAa,OAAO,CAAK,EACvB,CAAE,OAAQ,KAAM,KAAM,oBAAoB,EAAY,GAAI,IAEjE,KAAK,aAAa,IAAI,EAAO,CAAa,EAGxC,GAAe,KAAK,yBACf,CACL,OAAQ,KACR,KAAM,qBAAqB,EAAY,QAAQ,EAAY,qBAC7D,EAGE,GAAe,KAAK,wBACf,CACL,OAAQ,KACR,KAAM,oBAAoB,EAAY,QAAQ,EAAY,GAC5D,EAGK,CACL,OAAQ,KACR,KAAM,aAAa,EAAY,QAAQ,EAAY,GACrD,EACF,CAEA,OAAc,WACZ,EACA,EACA,EACA,CACA,GAAM,CAAE,OAAM,QAAO,UAAS,uBAAuB,IAAU,EAY/D,GAVI,CAAC,EAAa,WAGd,EAAa,QAIX,EAHY,EAAa,kBAAkB,OAC3C,EAAa,OAAO,KAAK,CAAK,EAC9B,EAAM,SAAS,EAAa,MAAM,IAIpC,GAAwB,CAAC,EAAa,+BAAgC,OAE1E,GAAI,GAAW,SAAU,GAAW,OAAQ,GACtC,KAAK,YAAY,EAAQ,KAAM,EAAQ,EAAE,EAAG,CAG9C,IAAK,IAAS,YAAc,IAAS,aAAe,EAAa,+BAAgC,CAC/F,EAAW,EAAM,aAAa,IAAS,CAAO,EAC9C,MACF,CACA,MACF,CAGF,IAAI,EAAY,GAChB,GAAI,IAAS,UAAY,IAAS,YAAc,IAAS,WAAY,CACnE,IAAM,EAAQ,KAAK,mBAAmB,CAAK,EAC3C,EAAY,EAAM,SAAW,KAAO,IAAI,EAAM,SAAW,IAAI,EAAM,OAAO,GAAG,EAAM,MACrF,CAEA,EAAW,EAAM,GAAG,IAAQ,IAAa,CAAO,CAClD,CAEF"}
@@ -29,10 +29,10 @@ var e = class {
29
29
  }
30
30
  static processLog(e, t, n) {
31
31
  let { type: r, label: i, details: a, isInternalCoreSignal: o = !1 } = n;
32
- if (!e.isEnabled || o && !e.isCoreOptimizationDebugEnabled) return;
32
+ if (!e.isEnabled || e.filter && !(e.filter instanceof RegExp ? e.filter.test(i) : i.includes(e.filter)) || o && !e.isCoreOptimizationDebugEnabled) return;
33
33
  if (a && "from" in a && "to" in a && this.isDeepEqual(a.from, a.to)) {
34
- if (r === "computed") {
35
- t(r, `🔵 [IDLE PULL] ${i} (Значение кэша не изменилось)`, a);
34
+ if ((r === "computed" || r === "resource") && e.isCoreOptimizationDebugEnabled) {
35
+ t(r, `🔵 [IDLE] ${i}`, a);
36
36
  return;
37
37
  }
38
38
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"core.logger.mjs","names":[],"sources":["../src/core/core.logger.ts"],"sourcesContent":["// core.logger.ts\nimport { LogEventType } from \"./types\"\n\ninterface LogDetails {\n from?: unknown;\n to?: unknown;\n payload?: unknown;\n}\n\nexport class ReactiveDebounceLogger {\n private static churnTracker = new Map<string, number[]>()\n\n private static readonly TIME_WINDOW_MS = 1000\n private static readonly CHURN_WARNING_THRESHOLD = 3\n private static readonly CHURN_CRITICAL_THRESHOLD = 6\n\n private static isDeepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false\n return JSON.stringify(a) === JSON.stringify(b)\n }\n\n private static analyzeSignalChurn(label: string): { marker: string; info: string } {\n const now = Date.now()\n if (!this.churnTracker.has(label)) {\n this.churnTracker.set(label, [])\n }\n\n const history = this.churnTracker.get(label)!\n const cutoff = now - this.TIME_WINDOW_MS\n // Фильтруем историю\n const activeHistory = history.filter(ts => ts > cutoff)\n activeHistory.push(now)\n\n const updateCount = activeHistory.length\n const intervalSec = (this.TIME_WINDOW_MS / 1000).toFixed(1)\n\n // ⚛️ ФИКС УТЕЧКИ ПАМЯТИ: Если узел стабилен и старых логов нет,\n // удаляем ключ из Map целиком, чтобы не копить мусор\n if (activeHistory.length <= 1) {\n this.churnTracker.delete(label)\n return { marker: '🟢', info: `[STABLE] (1 изм./${intervalSec}s)` }\n } else {\n this.churnTracker.set(label, activeHistory)\n }\n\n if (updateCount >= this.CHURN_CRITICAL_THRESHOLD) {\n return {\n marker: '🔴',\n info: `[CRITICAL CHURN] (${updateCount} изм./${intervalSec}s) — Нужен debounce!`\n }\n }\n\n if (updateCount >= this.CHURN_WARNING_THRESHOLD) {\n return {\n marker: '🟡',\n info: `[WARNING CHURN] (${updateCount} изм./${intervalSec}s)`\n }\n }\n\n return {\n marker: '🟢',\n info: `[STABLE] (${updateCount} изм./${intervalSec}s)`\n }\n }\n\n public static processLog(\n engineLogger: any,\n queueLogFn: Function,\n params: { type: LogEventType; label: string; details?: LogDetails; isInternalCoreSignal?: boolean }\n ) {\n const { type, label, details, isInternalCoreSignal = false } = params\n\n if (!engineLogger.isEnabled) return\n if (isInternalCoreSignal && !engineLogger.isCoreOptimizationDebugEnabled) return\n\n if (details && 'from' in details && 'to' in details) {\n if (this.isDeepEqual(details.from, details.to)) {\n if (type === 'computed') {\n queueLogFn(type, `🔵 [IDLE PULL] ${label} (Значение кэша не изменилось)`, details)\n return\n }\n return\n }\n }\n\n let churnInfo = ''\n if (type === 'signal' || type === 'resource' || type === 'computed') {\n const churn = this.analyzeSignalChurn(label)\n churnInfo = churn.marker === '🟢' ? ` ${churn.marker}` : ` ${churn.marker} ${churn.info}`\n }\n\n queueLogFn(type, `${label}${churnInfo}`, details)\n }\n}\n"],"mappings":";AASA,IAAa,IAAb,MAAoC;CAClC,OAAe,+BAAe,IAAI,IAAsB;CAExD,OAAwB,iBAAiB;CACzC,OAAwB,0BAA0B;CAClD,OAAwB,2BAA2B;CAEnD,OAAe,YAAY,GAAY,GAAqB;EAG1D,OAFI,MAAM,IAAU,KAChB,OAAO,KAAM,YAAY,OAAO,KAAM,YAAY,MAAM,QAAQ,MAAM,OAAa,KAChF,KAAK,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC;CAC/C;CAEA,OAAe,mBAAmB,GAAiD;EACjF,IAAM,IAAM,KAAK,IAAI;EACrB,AAAK,KAAK,aAAa,IAAI,CAAK,KAC9B,KAAK,aAAa,IAAI,GAAO,CAAC,CAAC;EAGjC,IAAM,IAAU,KAAK,aAAa,IAAI,CAAK,GACrC,IAAS,IAAM,KAAK,gBAEpB,IAAgB,EAAQ,QAAO,MAAM,IAAK,CAAM;EACtD,EAAc,KAAK,CAAG;EAEtB,IAAM,IAAc,EAAc,QAC5B,KAAe,KAAK,iBAAiB,IAAA,CAAM,QAAQ,CAAC;EAyB1D,OArBI,EAAc,UAAU,KAC1B,KAAK,aAAa,OAAO,CAAK,GACvB;GAAE,QAAQ;GAAM,MAAM,oBAAoB,EAAY;EAAI,MAEjE,KAAK,aAAa,IAAI,GAAO,CAAa,GAGxC,KAAe,KAAK,2BACf;GACL,QAAQ;GACR,MAAM,qBAAqB,EAAY,QAAQ,EAAY;EAC7D,IAGE,KAAe,KAAK,0BACf;GACL,QAAQ;GACR,MAAM,oBAAoB,EAAY,QAAQ,EAAY;EAC5D,IAGK;GACL,QAAQ;GACR,MAAM,aAAa,EAAY,QAAQ,EAAY;EACrD;CACF;CAEA,OAAc,WACZ,GACA,GACA,GACA;EACA,IAAM,EAAE,SAAM,UAAO,YAAS,0BAAuB,OAAU;EAG/D,IADI,CAAC,EAAa,aACd,KAAwB,CAAC,EAAa,gCAAgC;EAE1E,IAAI,KAAW,UAAU,KAAW,QAAQ,KACtC,KAAK,YAAY,EAAQ,MAAM,EAAQ,EAAE,GAAG;GAC9C,IAAI,MAAS,YAAY;IACvB,EAAW,GAAM,kBAAkB,EAAM,iCAAiC,CAAO;IACjF;GACF;GACA;EACF;EAGF,IAAI,IAAY;EAChB,IAAI,MAAS,YAAY,MAAS,cAAc,MAAS,YAAY;GACnE,IAAM,IAAQ,KAAK,mBAAmB,CAAK;GAC3C,IAAY,EAAM,WAAW,OAAO,IAAI,EAAM,WAAW,IAAI,EAAM,OAAO,GAAG,EAAM;EACrF;EAEA,EAAW,GAAM,GAAG,IAAQ,KAAa,CAAO;CAClD;AACF"}
1
+ {"version":3,"file":"core.logger.mjs","names":[],"sources":["../src/core/core.logger.ts"],"sourcesContent":["// core.logger.ts\nimport { LogEventType } from \"./types\"\n\ninterface LogDetails {\n from?: unknown;\n to?: unknown;\n payload?: unknown;\n}\n\nexport class ReactiveDebounceLogger {\n private static churnTracker = new Map<string, number[]>()\n\n private static readonly TIME_WINDOW_MS = 1000\n private static readonly CHURN_WARNING_THRESHOLD = 3\n private static readonly CHURN_CRITICAL_THRESHOLD = 6\n\n private static isDeepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false\n return JSON.stringify(a) === JSON.stringify(b)\n }\n\n private static analyzeSignalChurn(label: string): { marker: string; info: string } {\n const now = Date.now()\n if (!this.churnTracker.has(label)) {\n this.churnTracker.set(label, [])\n }\n\n const history = this.churnTracker.get(label)!\n const cutoff = now - this.TIME_WINDOW_MS\n // Фильтруем историю\n const activeHistory = history.filter(ts => ts > cutoff)\n activeHistory.push(now)\n\n const updateCount = activeHistory.length\n const intervalSec = (this.TIME_WINDOW_MS / 1000).toFixed(1)\n\n // ⚛️ ФИКС УТЕЧКИ ПАМЯТИ: Если узел стабилен и старых логов нет,\n // удаляем ключ из Map целиком, чтобы не копить мусор\n if (activeHistory.length <= 1) {\n this.churnTracker.delete(label)\n return { marker: '🟢', info: `[STABLE] (1 изм./${intervalSec}s)` }\n } else {\n this.churnTracker.set(label, activeHistory)\n }\n\n if (updateCount >= this.CHURN_CRITICAL_THRESHOLD) {\n return {\n marker: '🔴',\n info: `[CRITICAL CHURN] (${updateCount} изм./${intervalSec}s) — Нужен debounce!`\n }\n }\n\n if (updateCount >= this.CHURN_WARNING_THRESHOLD) {\n return {\n marker: '🟡',\n info: `[WARNING CHURN] (${updateCount} изм./${intervalSec}s)`\n }\n }\n\n return {\n marker: '🟢',\n info: `[STABLE] (${updateCount} изм./${intervalSec}s)`\n }\n }\n\n public static processLog(\n engineLogger: any,\n queueLogFn: Function,\n params: { type: LogEventType; label: string; details?: LogDetails; isInternalCoreSignal?: boolean }\n ) {\n const { type, label, details, isInternalCoreSignal = false } = params\n\n if (!engineLogger.isEnabled) return\n\n // ⚛️ ФИКС #1: Включаем валидацию RegExp фильтра из настроек\n if (engineLogger.filter) {\n const isMatch = engineLogger.filter instanceof RegExp\n ? engineLogger.filter.test(label)\n : label.includes(engineLogger.filter)\n if (!isMatch) return\n }\n\n if (isInternalCoreSignal && !engineLogger.isCoreOptimizationDebugEnabled) return\n\n if (details && 'from' in details && 'to' in details) {\n if (this.isDeepEqual(details.from, details.to)) {\n // ⚛️ ФИКС #2: Разрешаем логам типов 'resource' выводить IDLE транзакции,\n // иначе глубокое равенство объектов состояния блокирует их вывод\n if ((type === 'computed' || type === 'resource') && engineLogger.isCoreOptimizationDebugEnabled) {\n queueLogFn(type, `🔵 [IDLE] ${label}`, details)\n return\n }\n return\n }\n }\n\n let churnInfo = ''\n if (type === 'signal' || type === 'resource' || type === 'computed') {\n const churn = this.analyzeSignalChurn(label)\n churnInfo = churn.marker === '🟢' ? ` ${churn.marker}` : ` ${churn.marker} ${churn.info}`\n }\n\n queueLogFn(type, `${label}${churnInfo}`, details)\n }\n\n}\n"],"mappings":";AASA,IAAa,IAAb,MAAoC;CAClC,OAAe,+BAAe,IAAI,IAAsB;CAExD,OAAwB,iBAAiB;CACzC,OAAwB,0BAA0B;CAClD,OAAwB,2BAA2B;CAEnD,OAAe,YAAY,GAAY,GAAqB;EAG1D,OAFI,MAAM,IAAU,KAChB,OAAO,KAAM,YAAY,OAAO,KAAM,YAAY,MAAM,QAAQ,MAAM,OAAa,KAChF,KAAK,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC;CAC/C;CAEA,OAAe,mBAAmB,GAAiD;EACjF,IAAM,IAAM,KAAK,IAAI;EACrB,AAAK,KAAK,aAAa,IAAI,CAAK,KAC9B,KAAK,aAAa,IAAI,GAAO,CAAC,CAAC;EAGjC,IAAM,IAAU,KAAK,aAAa,IAAI,CAAK,GACrC,IAAS,IAAM,KAAK,gBAEpB,IAAgB,EAAQ,QAAO,MAAM,IAAK,CAAM;EACtD,EAAc,KAAK,CAAG;EAEtB,IAAM,IAAc,EAAc,QAC5B,KAAe,KAAK,iBAAiB,IAAA,CAAM,QAAQ,CAAC;EAyB1D,OArBI,EAAc,UAAU,KAC1B,KAAK,aAAa,OAAO,CAAK,GACvB;GAAE,QAAQ;GAAM,MAAM,oBAAoB,EAAY;EAAI,MAEjE,KAAK,aAAa,IAAI,GAAO,CAAa,GAGxC,KAAe,KAAK,2BACf;GACL,QAAQ;GACR,MAAM,qBAAqB,EAAY,QAAQ,EAAY;EAC7D,IAGE,KAAe,KAAK,0BACf;GACL,QAAQ;GACR,MAAM,oBAAoB,EAAY,QAAQ,EAAY;EAC5D,IAGK;GACL,QAAQ;GACR,MAAM,aAAa,EAAY,QAAQ,EAAY;EACrD;CACF;CAEA,OAAc,WACZ,GACA,GACA,GACA;EACA,IAAM,EAAE,SAAM,UAAO,YAAS,0BAAuB,OAAU;EAY/D,IAVI,CAAC,EAAa,aAGd,EAAa,UAIX,EAHY,EAAa,kBAAkB,SAC3C,EAAa,OAAO,KAAK,CAAK,IAC9B,EAAM,SAAS,EAAa,MAAM,MAIpC,KAAwB,CAAC,EAAa,gCAAgC;EAE1E,IAAI,KAAW,UAAU,KAAW,QAAQ,KACtC,KAAK,YAAY,EAAQ,MAAM,EAAQ,EAAE,GAAG;GAG9C,KAAK,MAAS,cAAc,MAAS,eAAe,EAAa,gCAAgC;IAC/F,EAAW,GAAM,aAAa,KAAS,CAAO;IAC9C;GACF;GACA;EACF;EAGF,IAAI,IAAY;EAChB,IAAI,MAAS,YAAY,MAAS,cAAc,MAAS,YAAY;GACnE,IAAM,IAAQ,KAAK,mBAAmB,CAAK;GAC3C,IAAY,EAAM,WAAW,OAAO,IAAI,EAAM,WAAW,IAAI,EAAM,OAAO,GAAG,EAAM;EACrF;EAEA,EAAW,GAAM,GAAG,IAAQ,KAAa,CAAO;CAClD;AAEF"}
@@ -1,2 +1,2 @@
1
- const e=require("./utils/getExtractedValues.cjs");function t(t,n,r,i){let a=i&&typeof i==`object`,o=a?i.name||`unnamed_resource`:i||`unnamed_resource`,s=a?i:{},c=s.resetDataOnSourceChange??!0,l=s.responseValidate,u=s.validateBeforeFetch,d=t.signal({data:null,loading:!0,error:null,isRetrying:!1},`[CORE_INTERNAL_SIGNAL=1]:resource:state:${o}`),f=e=>{t.log({type:`resource`,label:o,details:{to:e,from:d.value}}),d.value=e},p=async(r,i,a=!1)=>{if(i.aborted)return;if(s.validateBeforeFetch&&s.validateBeforeFetch(r),u){let e=u(r);if(e===!1||typeof e==`string`){if(i.aborted)return;let n=typeof e==`string`?e:`Pre-fetch validation failed for resource`,r=a?null:t.untrack(()=>d.value.data);f({data:r,loading:!1,error:n,isRetrying:!1});return}}let p=a&&c?null:t.untrack(()=>d.value.data);f({data:p,loading:!0,error:null,isRetrying:!1});for(let a=0;a<=0;a++){if(i.aborted)return;let s=i;try{let e=await n(r,s);if(i.aborted)return;if(s.aborted)throw new DOMException(`The operation timed out.`,`TimeoutError`);if(l){let t=l(e);if(t===!1||typeof t==`string`){if(i.aborted)return;f({data:null,loading:!1,error:typeof t==`string`?t:`Validation failed`,isRetrying:!1});return}}if(i.aborted)return;f({data:e,loading:!1,error:null,isRetrying:!1});return}catch(n){if(i.aborted||n.name===`AbortError`&&i.aborted)return;let r=n.name===`TimeoutError`||n.name===`AbortError`||n.message?.includes(`timeout`),s=e.getExtractedValues({tested:[n.message],expectedKey:`THROW_CUSTOM_VALIDATION_ERROR_NO_RETRY`,valueType:`number`})?.[0]===`1`||!1,c=s&&e.getExtractedValues({tested:[n.message],expectedKey:`MESSAGE`,valueType:`string`})?.[0]||`Custom validation error`,l=s||n.name===`ValidationError`;if(a===0||l){if(i.aborted)return;let e=r?Error(`Request timed out after 1000ms`,{cause:n}):s?Error(c,{cause:n}):n;f({data:null,loading:!1,error:e instanceof Error?e.message:typeof e==`string`?e:`typeof finalError is ${typeof e}`,isRetrying:!1});return}else{if(i.aborted)return;let e=1e3*2**a;e=Math.min(e,3e5);let n=Math.random()*200;e+=n,f({data:d.value.data,loading:!0,error:null,isRetrying:!0}),console.warn(`[Resource Retry] "${o}" сбой по ${r?`таймауту`:`ошибке сети`}. Попытка ${a+1}/${a+1}...`);try{if(await t.delay(e,i),i.aborted)return}catch{return}}}}},m=null,h=t.effect(()=>{let e=r?r.value:void 0,n=new AbortController;return m=n,t.untrack(()=>{p(e,n.signal,!0)}),()=>n.abort()},`[CORE_INTERNAL_SIGNAL=1]:effect`);return{get data(){return d.value.data},get loading(){return d.value.loading},get error(){return d.value.error},get isRetrying(){return d.value.isRetrying},get value(){return d.value},refetch:()=>{m?.abort(),m=new AbortController,p(r?r.value:void 0,m.signal,!1)},subscribe:e=>d.subscribe(e),destroy:()=>{m?.abort(),m=null,typeof h==`function`&&h(),d.destroy&&d.destroy()}}}exports.createResource=t;
1
+ const e=require("./utils/getExtractedValues.cjs");function t(t,n,r,i){let a=i&&typeof i==`object`,o=a?i.name||`unnamed_resource`:i||`unnamed_resource`,s=a?i:{},c=s.resetDataOnSourceChange??!0,l=s.responseValidate,u=s.validateBeforeFetch,d=s.retryCount??0,f=s.timeout??5e3,p=Date.now(),m=t.signal({data:null,loading:!0,error:null,isRetrying:!1,attemptIndex:0,retryCount:d,totalElapsedMs:void 0},`[CORE_INTERNAL_SIGNAL=1]:resource:state:${o}`),h=e=>{t.log({type:`resource`,label:o,details:{to:e,from:m.value}}),m.value=e},g=async(r,i,a=!1)=>{if(i.aborted)return;if(p=Date.now(),u){let e=u(r);if(e===!1||typeof e==`string`){if(i.aborted)return;let n=typeof e==`string`?e:`Pre-fetch validation failed for resource`,r=a?null:t.untrack(()=>m.value.data);h({data:r,loading:!1,error:n,isRetrying:!1,attemptIndex:0,retryCount:d,totalElapsedMs:void 0});return}}let s=a&&c?null:t.untrack(()=>m.value.data);h({data:s,loading:!0,error:null,isRetrying:!1,attemptIndex:0,retryCount:d,totalElapsedMs:void 0});for(let a=0;a<=d;a++){if(i.aborted)return;let s=AbortSignal.timeout(f),c=AbortSignal.any([i,s]);try{let e=await n(r,c);if(i.aborted)return;if(s.aborted)throw new DOMException(`The operation timed out.`,`TimeoutError`);if(l){let t=l(e);if(t===!1||typeof t==`string`){if(i.aborted)return;h({data:null,loading:!1,error:typeof t==`string`?t:`Validation failed`,isRetrying:!1,attemptIndex:0,retryCount:d,totalElapsedMs:void 0});return}}if(i.aborted)return;h({data:e,loading:!1,error:null,isRetrying:!1,attemptIndex:0,retryCount:d,totalElapsedMs:void 0});return}catch(n){let r=s.aborted||n.name===`TimeoutError`||n.message?.includes(`timeout`);if(i.aborted&&!r)return;let c=e.getExtractedValues({tested:[n.message],expectedKey:`THROW_CUSTOM_VALIDATION_ERROR_NO_RETRY`,valueType:`number`})?.[0]===`1`||!1,l=c&&e.getExtractedValues({tested:[n.message],expectedKey:`MESSAGE`,valueType:`string`})?.[0]||`Custom validation error`,u=c||n.name===`ValidationError`;if(a===d||u){if(i.aborted)return;let e=Date.now()-p,o=`${r?`Request timed out after ${f}ms (attempt ${a+1}/${d+1})`:c?l:n instanceof Error?n.message:String(n)}.${t.logger.isCoreOptimizationDebugEnabled?` Всего безуспешных попыток с момента изменения исходного сигнала: ${d+1}.`:``}`;h({data:null,loading:!1,error:o,isRetrying:!1,attemptIndex:a+1,retryCount:d,totalElapsedMs:e});return}else{if(i.aborted)return;let e=1e3*2**a;e=Math.min(e,3e5)+Math.random()*200,h({data:m.value.data,loading:!0,error:null,isRetrying:!0,attemptIndex:a+1,retryCount:d}),t.log({type:`resource`,label:`${o}:retry_scheduled`,details:{payload:{attempt:a+1,total:d,nextDelayMs:Math.round(e)}}}),console.warn(`[Resource Retry] "${o}" сбой по ${r?`таймауту`:`ошибке сети`}. Запрос ${a+1} из ${d+1} не удался. Ожидание повтора: ${Math.round(e)}ms`);try{if(await t.delay(e,i),i.aborted)return}catch{return}}}}},_=null,v=t.effect(()=>{let e=r?r.value:void 0,n=new AbortController;return _=n,t.untrack(()=>{g(e,n.signal,!0)}),()=>n.abort()},`[CORE_INTERNAL_SIGNAL=1]:effect`);return{get data(){return m.value.data},get loading(){return m.value.loading},get error(){return m.value.error},get isRetrying(){return m.value.isRetrying},get value(){return m.value},refetch:()=>{_?.abort(),_=new AbortController,g(r?r.value:void 0,_.signal,!1)},subscribe:e=>m.subscribe(e),destroy:()=>{_?.abort(),_=null,typeof v==`function`&&v(),m.destroy&&m.destroy()}}}exports.createResource=t;
2
2
  //# sourceMappingURL=core.method.resource.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.method.resource.cjs","names":[],"sources":["../src/core/core.method.resource.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { Resource, ResourceOptions, ResourceState, Signal } from './types'\n\n// Контракт ядра движка для безопасных вызовов методов с дженериками\ninterface IReactiveEngine {\n signal<V>(initialValue: V, optionsOrName?: any): Signal<V>;\n effect(fn: () => any, name?: string): () => void;\n untrack<V>(fn: () => V): V;\n log(params: any): void;\n delay(ms: number, signal: AbortSignal): Promise<void>;\n}\n\nexport function createResource<T, S = void>(\n engine: IReactiveEngine,\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\n // Вызов скомпилируется успешно, так как метод signal теперь строго описан в интерфейсе\n const state = engine.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 engine.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 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 : engine.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 : engine.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 engine.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 const disposeInternalEffect = engine.effect(() => {\n const sValue = source ? source.value : undefined as S\n const effectController = new AbortController()\n activeEffectController = effectController\n\n engine.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 destroy: () => {\n activeEffectController?.abort()\n activeEffectController = null\n if (typeof disposeInternalEffect === 'function') {\n disposeInternalEffect()\n }\n if ((state as any).destroy) {\n (state as any).destroy()\n }\n }\n } as any\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"core.method.resource.cjs","names":[],"sources":["../src/core/core.method.resource.ts"],"sourcesContent":["import { getExtractedValues } from '../utils/getExtractedValues'\nimport { EngineLoggerOptions, Resource, ResourceOptions, ResourceState, Signal } from './types'\n\n// Контракт ядра движка для безопасных вызовов методов с дженериками\ninterface IReactiveEngine {\n signal<V>(initialValue: V, optionsOrName?: any): Signal<V>;\n effect(fn: () => any, name?: string): () => void;\n untrack<V>(fn: () => V): V;\n log(params: any): void;\n delay(ms: number, signal: AbortSignal): Promise<void>;\n logger: EngineLoggerOptions\n}\n\nexport function createResource<T, S = void>(\n engine: IReactiveEngine,\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 baseDelay = 1000\n const useExponential = true\n const maxRetryDelay = 1000 * 60 * 5\n\n const retryCount = options.retryCount ?? 0\n const timeoutMs = options.timeout ?? 5000\n // Запоминаем точное время старта ВСЕЙ цепочки (включая ретраи и паузы)\n let startTime = Date.now()\n\n const state = engine.signal<ResourceState<T>>(\n {\n data: null,\n loading: true,\n error: null,\n isRetrying: false,\n attemptIndex: 0,\n retryCount,\n totalElapsedMs: undefined // Сбрасываем старый таймер\n },\n `[CORE_INTERNAL_SIGNAL=1]:resource:state:${resourceSignalName}`\n )\n\n const updateResourceState = (nextState: ResourceState<T>) => {\n engine.log({\n type: 'resource',\n label: resourceSignalName,\n details: { to: nextState, from: state.value },\n })\n state.value = nextState\n }\n\n const load = async (sValue: S, effectSignal: AbortSignal, isSourceChange = false) => {\n if (effectSignal.aborted) return\n\n // Фиксируем время старта бизнес-процесса в самом начале метода load\n startTime = Date.now()\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 : engine.untrack(() => state.value.data)\n // Явно зачищаем следы старого таймера при ошибке валидации аргументов\n updateResourceState({\n data: currentData,\n loading: false,\n error: errorMsg,\n isRetrying: false,\n attemptIndex: 0,\n retryCount,\n totalElapsedMs: undefined\n })\n return\n }\n }\n\n const shouldClear = isSourceChange && resetDataOnSourceChange\n const currentData = shouldClear ? null : engine.untrack(() => state.value.data)\n\n // Принудительно сбрасываем таймер в undefined перед входом в цикл ретраев\n updateResourceState({\n data: currentData,\n loading: true,\n error: null,\n isRetrying: false,\n attemptIndex: 0,\n retryCount,\n totalElapsedMs: undefined\n })\n\n // 🔄 Контур циклического выполнения попыток (от 0 до retryCount)\n for (let attempt = 0; attempt <= retryCount; attempt++) {\n if (effectSignal.aborted) return\n\n // Создаем персональный сигнал таймаута на эту конкретную попытку\n const timeoutSignal = AbortSignal.timeout(timeoutMs)\n\n // Объединяем управляющий сигнал графа и наш таймаут\n const combinedSignal = AbortSignal.any([effectSignal, timeoutSignal])\n\n try {\n const data = await fetcher(sValue, combinedSignal)\n\n if (effectSignal.aborted) return\n\n // Если фетчер вернул управление, но таймаут успел отработать раньше\n if (timeoutSignal.aborted) {\n throw new DOMException('The operation timed out.', 'TimeoutError')\n }\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({\n data: null,\n loading: false,\n error: errorMsg,\n isRetrying: false,\n attemptIndex: 0,\n retryCount,\n totalElapsedMs: undefined\n })\n return\n }\n }\n\n if (effectSignal.aborted) return\n // Успех: сохраняем данные, полностью очищаем ошибки и сквозной таймер\n updateResourceState({\n data,\n loading: false,\n error: null,\n isRetrying: false,\n attemptIndex: 0,\n retryCount,\n totalElapsedMs: undefined\n })\n return\n\n } catch (e: unknown) {\n // 1. Выявляем, произошел ли сбой по таймауту\n const isTimeout = timeoutSignal.aborted ||\n (e as Error).name === 'TimeoutError' ||\n (e as Error).message?.includes('timeout')\n\n // Если это обычная отмена дебаунсом из внешнего контура, мгновенно прекращаем работу\n if (effectSignal.aborted && !isTimeout) return\n\n // 2. Безопасно извлекаем валидационные маркеры до их использования в условиях\n const isCustomValidationError = getExtractedValues({\n tested: [(e as Error).message], expectedKey: 'THROW_CUSTOM_VALIDATION_ERROR_NO_RETRY', valueType: 'number',\n })?.[0] === '1' || false\n\n const __defaultCustomValidationErrorMessage = 'Custom validation error'\n const customValidationErrorMessage: string = isCustomValidationError\n ? (getExtractedValues({\n tested: [(e as Error).message], expectedKey: 'MESSAGE', valueType: 'string',\n })?.[0] || __defaultCustomValidationErrorMessage)\n : __defaultCustomValidationErrorMessage\n\n const isFetchBodyValidationError = isCustomValidationError || (e as Error).name === 'ValidationError'\n\n // Если попытки исчерпаны ИЛИ это валидационная ошибка тела, которая не подлежит повтору\n if (attempt === retryCount || isFetchBodyValidationError) {\n if (effectSignal.aborted) return\n\n // Считаем суммарное время от первого клика/сдвига карты до текущего момента\n const totalElapsedMs = Date.now() - startTime\n\n // Переменная customValidationErrorMessage теперь гарантированно определена выше!\n const baseErrorMsg = isTimeout\n ? `Request timed out after ${timeoutMs}ms (attempt ${attempt + 1}/${retryCount + 1})`\n : isCustomValidationError\n ? customValidationErrorMessage\n : e instanceof Error ? e.message : String(e)\n\n // Формируем детальное сообщение для вывода в UI\n const finalErrorMessage = `${baseErrorMsg}.${engine.logger.isCoreOptimizationDebugEnabled ? ` Всего безуспешных попыток с момента изменения исходного сигнала: ${retryCount + 1}.` : ''}`\n\n updateResourceState({\n data: null,\n loading: false,\n error: finalErrorMessage,\n isRetrying: false,\n attemptIndex: attempt + 1, // Выводим финальное число сделанных попыток\n retryCount,\n totalElapsedMs,\n })\n return\n } else {\n // Инициализируем планирование следующей попытки (Retry Backoff Phase)\n if (effectSignal.aborted) return\n\n let currentDelay = useExponential ? baseDelay * Math.pow(2, attempt) : baseDelay\n currentDelay = Math.min(currentDelay, maxRetryDelay) + Math.random() * 200\n\n updateResourceState({\n data: state.value.data,\n loading: true,\n error: null,\n isRetrying: true,\n attemptIndex: attempt + 1, // Индекс следующей накатываемой попытки для UI (1, 2, 3...)\n retryCount\n })\n\n engine.log({\n type: 'resource',\n label: `${resourceSignalName}:retry_scheduled`,\n details: { payload: { attempt: attempt + 1, total: retryCount, nextDelayMs: Math.round(currentDelay) } }\n })\n\n const logReason = isTimeout ? 'таймауту' : 'ошибке сети'\n // Исправлен счетчик: пишем честный индекс текущего упавшего запроса из общего пула\n console.warn(`[Resource Retry] \"${resourceSignalName}\" сбой по ${logReason}. Запрос ${attempt + 1} из ${retryCount + 1} не удался. Ожидание повтора: ${Math.round(currentDelay)}ms`)\n\n try {\n // Спим перед следующим циклом, уважая отмену внешнего графа\n await engine.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 const disposeInternalEffect = engine.effect(() => {\n const sValue = source ? source.value : undefined as S\n const effectController = new AbortController()\n activeEffectController = effectController\n\n engine.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 destroy: () => {\n activeEffectController?.abort()\n activeEffectController = null\n if (typeof disposeInternalEffect === 'function') {\n disposeInternalEffect()\n }\n if ((state as any).destroy) {\n (state as any).destroy()\n }\n }\n } as any\n}\n"],"mappings":"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"}
@@ -1,103 +1,130 @@
1
1
  import { getExtractedValues as e } from "./utils/getExtractedValues.mjs";
2
2
  //#region src/core/core.method.resource.ts
3
3
  function t(t, n, r, i) {
4
- let a = i && typeof i == "object", o = a ? i.name || "unnamed_resource" : i || "unnamed_resource", s = a ? i : {}, c = s.resetDataOnSourceChange ?? !0, l = s.responseValidate, u = s.validateBeforeFetch, d = t.signal({
4
+ let a = i && typeof i == "object", o = a ? i.name || "unnamed_resource" : i || "unnamed_resource", s = a ? i : {}, c = s.resetDataOnSourceChange ?? !0, l = s.responseValidate, u = s.validateBeforeFetch, d = s.retryCount ?? 0, f = s.timeout ?? 5e3, p = Date.now(), m = t.signal({
5
5
  data: null,
6
6
  loading: !0,
7
7
  error: null,
8
- isRetrying: !1
9
- }, `[CORE_INTERNAL_SIGNAL=1]:resource:state:${o}`), f = (e) => {
8
+ isRetrying: !1,
9
+ attemptIndex: 0,
10
+ retryCount: d,
11
+ totalElapsedMs: void 0
12
+ }, `[CORE_INTERNAL_SIGNAL=1]:resource:state:${o}`), h = (e) => {
10
13
  t.log({
11
14
  type: "resource",
12
15
  label: o,
13
16
  details: {
14
17
  to: e,
15
- from: d.value
18
+ from: m.value
16
19
  }
17
- }), d.value = e;
18
- }, p = async (r, i, a = !1) => {
20
+ }), m.value = e;
21
+ }, g = async (r, i, a = !1) => {
19
22
  if (i.aborted) return;
20
- if (s.validateBeforeFetch && s.validateBeforeFetch(r), u) {
23
+ if (p = Date.now(), u) {
21
24
  let e = u(r);
22
25
  if (e === !1 || typeof e == "string") {
23
26
  if (i.aborted) return;
24
- let n = typeof e == "string" ? e : "Pre-fetch validation failed for resource", r = a ? null : t.untrack(() => d.value.data);
25
- f({
27
+ let n = typeof e == "string" ? e : "Pre-fetch validation failed for resource", r = a ? null : t.untrack(() => m.value.data);
28
+ h({
26
29
  data: r,
27
30
  loading: !1,
28
31
  error: n,
29
- isRetrying: !1
32
+ isRetrying: !1,
33
+ attemptIndex: 0,
34
+ retryCount: d,
35
+ totalElapsedMs: void 0
30
36
  });
31
37
  return;
32
38
  }
33
39
  }
34
- let p = a && c ? null : t.untrack(() => d.value.data);
35
- f({
36
- data: p,
40
+ let s = a && c ? null : t.untrack(() => m.value.data);
41
+ h({
42
+ data: s,
37
43
  loading: !0,
38
44
  error: null,
39
- isRetrying: !1
45
+ isRetrying: !1,
46
+ attemptIndex: 0,
47
+ retryCount: d,
48
+ totalElapsedMs: void 0
40
49
  });
41
- for (let a = 0; a <= 0; a++) {
50
+ for (let a = 0; a <= d; a++) {
42
51
  if (i.aborted) return;
43
- let s = i;
52
+ let s = AbortSignal.timeout(f), c = AbortSignal.any([i, s]);
44
53
  try {
45
- let e = await n(r, s);
54
+ let e = await n(r, c);
46
55
  if (i.aborted) return;
47
56
  if (s.aborted) throw new DOMException("The operation timed out.", "TimeoutError");
48
57
  if (l) {
49
58
  let t = l(e);
50
59
  if (t === !1 || typeof t == "string") {
51
60
  if (i.aborted) return;
52
- f({
61
+ h({
53
62
  data: null,
54
63
  loading: !1,
55
64
  error: typeof t == "string" ? t : "Validation failed",
56
- isRetrying: !1
65
+ isRetrying: !1,
66
+ attemptIndex: 0,
67
+ retryCount: d,
68
+ totalElapsedMs: void 0
57
69
  });
58
70
  return;
59
71
  }
60
72
  }
61
73
  if (i.aborted) return;
62
- f({
74
+ h({
63
75
  data: e,
64
76
  loading: !1,
65
77
  error: null,
66
- isRetrying: !1
78
+ isRetrying: !1,
79
+ attemptIndex: 0,
80
+ retryCount: d,
81
+ totalElapsedMs: void 0
67
82
  });
68
83
  return;
69
84
  } catch (n) {
70
- if (i.aborted || n.name === "AbortError" && i.aborted) return;
71
- let r = n.name === "TimeoutError" || n.name === "AbortError" || n.message?.includes("timeout"), s = e({
85
+ let r = s.aborted || n.name === "TimeoutError" || n.message?.includes("timeout");
86
+ if (i.aborted && !r) return;
87
+ let c = e({
72
88
  tested: [n.message],
73
89
  expectedKey: "THROW_CUSTOM_VALIDATION_ERROR_NO_RETRY",
74
90
  valueType: "number"
75
- })?.[0] === "1" || !1, c = s && e({
91
+ })?.[0] === "1" || !1, l = c && e({
76
92
  tested: [n.message],
77
93
  expectedKey: "MESSAGE",
78
94
  valueType: "string"
79
- })?.[0] || "Custom validation error", l = s || n.name === "ValidationError";
80
- if (a === 0 || l) {
95
+ })?.[0] || "Custom validation error", u = c || n.name === "ValidationError";
96
+ if (a === d || u) {
81
97
  if (i.aborted) return;
82
- let e = r ? Error("Request timed out after 1000ms", { cause: n }) : s ? Error(c, { cause: n }) : n;
83
- f({
98
+ let e = Date.now() - p, o = `${r ? `Request timed out after ${f}ms (attempt ${a + 1}/${d + 1})` : c ? l : n instanceof Error ? n.message : String(n)}.${t.logger.isCoreOptimizationDebugEnabled ? ` Всего безуспешных попыток с момента изменения исходного сигнала: ${d + 1}.` : ""}`;
99
+ h({
84
100
  data: null,
85
101
  loading: !1,
86
- error: e instanceof Error ? e.message : typeof e == "string" ? e : `typeof finalError is ${typeof e}`,
87
- isRetrying: !1
102
+ error: o,
103
+ isRetrying: !1,
104
+ attemptIndex: a + 1,
105
+ retryCount: d,
106
+ totalElapsedMs: e
88
107
  });
89
108
  return;
90
109
  } else {
91
110
  if (i.aborted) return;
92
111
  let e = 1e3 * 2 ** a;
93
- e = Math.min(e, 3e5);
94
- let n = Math.random() * 200;
95
- e += n, f({
96
- data: d.value.data,
112
+ e = Math.min(e, 3e5) + Math.random() * 200, h({
113
+ data: m.value.data,
97
114
  loading: !0,
98
115
  error: null,
99
- isRetrying: !0
100
- }), console.warn(`[Resource Retry] "${o}" сбой по ${r ? "таймауту" : "ошибке сети"}. Попытка ${a + 1}/${a + 1}...`);
116
+ isRetrying: !0,
117
+ attemptIndex: a + 1,
118
+ retryCount: d
119
+ }), t.log({
120
+ type: "resource",
121
+ label: `${o}:retry_scheduled`,
122
+ details: { payload: {
123
+ attempt: a + 1,
124
+ total: d,
125
+ nextDelayMs: Math.round(e)
126
+ } }
127
+ }), console.warn(`[Resource Retry] "${o}" сбой по ${r ? "таймауту" : "ошибке сети"}. Запрос ${a + 1} из ${d + 1} не удался. Ожидание повтора: ${Math.round(e)}ms`);
101
128
  try {
102
129
  if (await t.delay(e, i), i.aborted) return;
103
130
  } catch {
@@ -106,34 +133,34 @@ function t(t, n, r, i) {
106
133
  }
107
134
  }
108
135
  }
109
- }, m = null, h = t.effect(() => {
136
+ }, _ = null, v = t.effect(() => {
110
137
  let e = r ? r.value : void 0, n = new AbortController();
111
- return m = n, t.untrack(() => {
112
- p(e, n.signal, !0);
138
+ return _ = n, t.untrack(() => {
139
+ g(e, n.signal, !0);
113
140
  }), () => n.abort();
114
141
  }, "[CORE_INTERNAL_SIGNAL=1]:effect");
115
142
  return {
116
143
  get data() {
117
- return d.value.data;
144
+ return m.value.data;
118
145
  },
119
146
  get loading() {
120
- return d.value.loading;
147
+ return m.value.loading;
121
148
  },
122
149
  get error() {
123
- return d.value.error;
150
+ return m.value.error;
124
151
  },
125
152
  get isRetrying() {
126
- return d.value.isRetrying;
153
+ return m.value.isRetrying;
127
154
  },
128
155
  get value() {
129
- return d.value;
156
+ return m.value;
130
157
  },
131
158
  refetch: () => {
132
- m?.abort(), m = new AbortController(), p(r ? r.value : void 0, m.signal, !1);
159
+ _?.abort(), _ = new AbortController(), g(r ? r.value : void 0, _.signal, !1);
133
160
  },
134
- subscribe: (e) => d.subscribe(e),
161
+ subscribe: (e) => m.subscribe(e),
135
162
  destroy: () => {
136
- m?.abort(), m = null, typeof h == "function" && h(), d.destroy && d.destroy();
163
+ _?.abort(), _ = null, typeof v == "function" && v(), m.destroy && m.destroy();
137
164
  }
138
165
  };
139
166
  }