@blac/adapter
Advanced tools
+35
-22
| let _blac_core = require("@blac/core"); | ||
| let _blac_core_tracking = require("@blac/core/tracking"); | ||
@@ -12,4 +11,17 @@ //#region src/index.ts | ||
| constructor() { | ||
| this.manager = new _blac_core_tracking.DependencyManager(); | ||
| this.manager = new _blac_core.DependencyManager(); | ||
| this.cachedDeps = null; | ||
| } | ||
| resolveCached(rawInstance) { | ||
| if (this.cachedDeps) { | ||
| let allValid = true; | ||
| for (const dep of this.cachedDeps) if (dep.isDisposed) { | ||
| allValid = false; | ||
| break; | ||
| } | ||
| if (allValid) return this.cachedDeps; | ||
| } | ||
| this.cachedDeps = (0, _blac_core.resolveDependencies)(rawInstance); | ||
| return this.cachedDeps; | ||
| } | ||
| /** | ||
@@ -24,7 +36,7 @@ * Update subscriptions to external bloc dependencies. | ||
| updateSubscriptions(getterState, rawInstance, onGetterChange) { | ||
| if (!getterState) return false; | ||
| const currentDeps = (0, _blac_core_tracking.resolveDependencies)(rawInstance); | ||
| if (!getterState || rawInstance.dependencies.size === 0) return false; | ||
| const currentDeps = this.resolveCached(rawInstance); | ||
| const onExternalChange = () => { | ||
| (0, _blac_core_tracking.invalidateRenderCache)(getterState); | ||
| if ((0, _blac_core_tracking.hasGetterChanges)(rawInstance, getterState)) onGetterChange(); | ||
| (0, _blac_core.invalidateRenderCache)(getterState); | ||
| if ((0, _blac_core.hasGetterChanges)(rawInstance, getterState)) onGetterChange(); | ||
| }; | ||
@@ -38,2 +50,3 @@ return this.manager.sync(currentDeps, onExternalChange, rawInstance); | ||
| this.manager.cleanup(); | ||
| this.cachedDeps = null; | ||
| } | ||
@@ -51,3 +64,3 @@ }; | ||
| return instance.subscribe(() => { | ||
| const depState = adapterState.dependencyState || (adapterState.dependencyState = (0, _blac_core_tracking.createDependencyState)()); | ||
| const depState = adapterState.dependencyState || (adapterState.dependencyState = (0, _blac_core.createDependencyState)()); | ||
| const hasStateDeps = depState.pathCache && depState.pathCache.size > 0; | ||
@@ -57,3 +70,3 @@ const hasGetterDeps = adapterState.getterState && adapterState.getterState.trackedGetters.size > 0; | ||
| if (!hasStateDeps && !hasGetterDeps && !isPrimitiveState) return; | ||
| let stateChanged = (0, _blac_core_tracking.hasDependencyChanges)(depState, instance.state); | ||
| let stateChanged = (0, _blac_core.hasDependencyChanges)(depState, instance.state); | ||
| if (!hasStateDeps && hasGetterDeps) stateChanged = false; | ||
@@ -64,3 +77,3 @@ if (stateChanged) { | ||
| } | ||
| if ((0, _blac_core_tracking.hasGetterChanges)(instance, adapterState.getterState)) callback(); | ||
| if ((0, _blac_core.hasGetterChanges)(instance, adapterState.getterState)) callback(); | ||
| }); | ||
@@ -81,3 +94,3 @@ }; | ||
| const newDeps = config.dependencies(instance.state, instance); | ||
| if (!adapterState.manualDepsCache || !(0, _blac_core_tracking.shallowEqual)(adapterState.manualDepsCache, newDeps)) { | ||
| if (!adapterState.manualDepsCache || !(0, _blac_core.shallowEqual)(adapterState.manualDepsCache, newDeps)) { | ||
| adapterState.manualDepsCache = newDeps; | ||
@@ -107,12 +120,12 @@ callback(); | ||
| return () => { | ||
| const depState = adapterState.dependencyState || (adapterState.dependencyState = (0, _blac_core_tracking.createDependencyState)()); | ||
| if ((0, _blac_core_tracking.hasTrackedData)(depState)) (0, _blac_core_tracking.capturePaths)(depState, instance.state); | ||
| const depState = adapterState.dependencyState || (adapterState.dependencyState = (0, _blac_core.createDependencyState)()); | ||
| if ((0, _blac_core.hasTrackedData)(depState)) (0, _blac_core.capturePaths)(depState, instance.state); | ||
| if (adapterState.getterState) { | ||
| (0, _blac_core_tracking.invalidateRenderCache)(adapterState.getterState); | ||
| (0, _blac_core_tracking.commitTrackedGetters)(adapterState.getterState); | ||
| (0, _blac_core.invalidateRenderCache)(adapterState.getterState); | ||
| (0, _blac_core.commitTrackedGetters)(adapterState.getterState); | ||
| adapterState.getterState.isTracking = true; | ||
| (0, _blac_core_tracking.setActiveTracker)(instance, adapterState.getterState); | ||
| (0, _blac_core.setActiveTracker)(instance, adapterState.getterState); | ||
| } | ||
| (0, _blac_core_tracking.startDependency)(depState); | ||
| return (0, _blac_core_tracking.createDependencyProxy)(depState, instance.state); | ||
| (0, _blac_core.startDependency)(depState); | ||
| return (0, _blac_core.createDependencyProxy)(depState, instance.state); | ||
| }; | ||
@@ -153,4 +166,4 @@ } | ||
| manualDepsCache: null, | ||
| getterState: (0, _blac_core_tracking.createGetterState)(), | ||
| proxiedBloc: (0, _blac_core_tracking.createBlocProxy)(instance) | ||
| getterState: (0, _blac_core.createGetterState)(), | ||
| proxiedBloc: (0, _blac_core.createBlocProxy)(instance) | ||
| }; | ||
@@ -195,4 +208,4 @@ } | ||
| adapterState.getterState.isTracking = false; | ||
| (0, _blac_core_tracking.clearActiveTracker)(rawInstance); | ||
| (0, _blac_core_tracking.commitTrackedGetters)(adapterState.getterState); | ||
| (0, _blac_core.clearActiveTracker)(rawInstance); | ||
| (0, _blac_core.commitTrackedGetters)(adapterState.getterState); | ||
| } | ||
@@ -202,3 +215,3 @@ } | ||
| //#endregion | ||
| exports.DependencyManager = _blac_core_tracking.DependencyManager; | ||
| exports.DependencyManager = _blac_core.DependencyManager; | ||
| exports.ExternalDepsManager = ExternalDepsManager; | ||
@@ -205,0 +218,0 @@ Object.defineProperty(exports, 'acquire', { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.cjs","names":["DependencyManager"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @blac/adapter - Framework Adapter\n *\n * Reusable utilities for integrating BlaC with any reactive framework.\n * Provides subscription and snapshot functions for different tracking modes.\n *\n * This package provides the building blocks for React, Preact, Vue, and other\n * framework integrations.\n */\nimport type {\n ExtractState,\n InstanceReadonlyState,\n InstanceState,\n StateContainerConstructor,\n StateContainerInstance,\n} from '@blac/core';\n\n// Re-export types needed by framework integrations\nexport type {\n ExtractState,\n InstanceReadonlyState,\n InstanceState,\n StateContainerConstructor,\n StateContainerInstance,\n} from '@blac/core';\n\n// Re-export registry functions needed by hooks\nexport {\n acquire,\n release,\n isIsolatedClass,\n generateIsolatedKey,\n} from '@blac/core';\n\n// Import tracking types and functions from @blac/core/tracking subpath\nimport type { DependencyState, GetterState } from '@blac/core/tracking';\n\nimport {\n createDependencyState,\n startDependency,\n createDependencyProxy,\n capturePaths,\n hasDependencyChanges,\n hasTrackedData,\n shallowEqual,\n createGetterState,\n createBlocProxy,\n hasGetterChanges,\n setActiveTracker,\n clearActiveTracker,\n commitTrackedGetters,\n invalidateRenderCache,\n resolveDependencies,\n DependencyManager,\n} from '@blac/core/tracking';\n\n/**\n * Internal state for framework adapters, holding tracking and caching data.\n * @template TBloc - The state container type\n */\nexport interface AdapterState<TBloc extends StateContainerConstructor> {\n /** Dependency tracker for state property access tracking */\n dependencyState: DependencyState<ExtractState<TBloc>> | null;\n /** Cached manual dependencies for comparison */\n manualDepsCache: unknown[] | null;\n /** Getter state for computed property tracking */\n getterState: GetterState | null;\n /** Proxied bloc instance for auto-tracking */\n proxiedBloc: InstanceState<TBloc> | null;\n}\n\n/**\n * Configuration for manual dependency tracking mode\n * @template TBloc - The state container type\n */\nexport interface ManualDepsConfig<TBloc extends StateContainerConstructor> {\n /** Function that returns dependency array from state and bloc */\n dependencies: (\n state: ExtractState<TBloc>,\n bloc: InstanceState<TBloc>,\n ) => any[];\n}\n\n/**\n * Callback function invoked when subscribed state changes\n */\nexport type SubscriptionCallback = () => void;\n\n/**\n * Function that subscribes to state changes and returns an unsubscribe function\n */\nexport type SubscribeFunction = (callback: SubscriptionCallback) => () => void;\n\n/**\n * Function that returns a snapshot of the current state\n * @template TState - The state type\n */\nexport type SnapshotFunction<TState> = () => TState;\n\n/**\n * Manages subscriptions to external bloc dependencies for getter tracking.\n * When a getter accesses another bloc's state, this manager ensures\n * re-renders occur when those external dependencies change.\n */\nexport class ExternalDepsManager {\n private manager = new DependencyManager();\n\n /**\n * Update subscriptions to external bloc dependencies.\n * Resolves transitive dependencies via depend() declarations.\n * @param getterState - The getter tracker state (needed for change detection)\n * @param rawInstance - The primary bloc instance (excluded from subscriptions)\n * @param onGetterChange - Callback to invoke when external dependency changes\n * @returns true if subscriptions were updated, false if unchanged\n */\n updateSubscriptions(\n getterState: GetterState | null,\n rawInstance: StateContainerInstance,\n onGetterChange: () => void,\n ): boolean {\n if (!getterState) {\n return false;\n }\n\n const currentDeps = resolveDependencies(rawInstance);\n\n const onExternalChange = () => {\n invalidateRenderCache(getterState);\n\n if (hasGetterChanges(rawInstance, getterState)) {\n onGetterChange();\n }\n };\n\n return this.manager.sync(currentDeps, onExternalChange, rawInstance);\n }\n\n /**\n * Clean up all active subscriptions\n */\n cleanup(): void {\n this.manager.cleanup();\n }\n}\n\nexport { DependencyManager };\n\n/**\n * Create a subscribe function for auto-tracking mode.\n * Only triggers callback when tracked properties change.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for tracking\n * @returns Subscribe function for use with useSyncExternalStore\n */\nexport function autoTrackSubscribe<TBloc extends StateContainerConstructor>(\n instance: InstanceReadonlyState<TBloc>,\n adapterState: AdapterState<TBloc>,\n): SubscribeFunction {\n return (callback: SubscriptionCallback) => {\n return instance.subscribe(() => {\n const depState =\n adapterState.dependencyState ||\n (adapterState.dependencyState = createDependencyState<any>());\n\n const hasStateDeps = depState.pathCache && depState.pathCache.size > 0;\n const hasGetterDeps =\n adapterState.getterState &&\n adapterState.getterState.trackedGetters.size > 0;\n\n const isPrimitiveState =\n instance.state !== null &&\n typeof instance.state !== 'object' &&\n typeof instance.state !== 'function';\n\n if (!hasStateDeps && !hasGetterDeps && !isPrimitiveState) {\n return;\n }\n\n let stateChanged = hasDependencyChanges(depState, instance.state);\n\n if (!hasStateDeps && hasGetterDeps) {\n stateChanged = false;\n }\n\n if (stateChanged) {\n callback();\n return;\n }\n\n const getterChanged = hasGetterChanges(\n instance,\n adapterState.getterState,\n );\n\n if (getterChanged) {\n callback();\n }\n });\n };\n}\n\n/**\n * Create a subscribe function for manual dependency tracking mode.\n * Only triggers callback when dependencies array changes.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for caching\n * @param config - Configuration with dependencies function\n * @returns Subscribe function for use with useSyncExternalStore\n */\nexport function manualDepsSubscribe<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n adapterState: AdapterState<TBloc>,\n config: ManualDepsConfig<TBloc>,\n): SubscribeFunction {\n return (callback: SubscriptionCallback) => {\n return instance.subscribe(() => {\n const newDeps = config.dependencies(instance.state, instance);\n if (\n !adapterState.manualDepsCache ||\n !shallowEqual(adapterState.manualDepsCache, newDeps)\n ) {\n adapterState.manualDepsCache = newDeps;\n callback();\n }\n });\n };\n}\n\n/**\n * Create a subscribe function for no-tracking mode.\n * Triggers callback on every state change.\n * @param instance - The state container instance\n * @returns Subscribe function for use with useSyncExternalStore\n */\nexport function noTrackSubscribe<TBloc extends StateContainerInstance>(\n instance: TBloc,\n): SubscribeFunction {\n return (callback: SubscriptionCallback) => instance.subscribe(callback);\n}\n\n/**\n * Create a snapshot function for auto-tracking mode.\n * Returns a proxied state that tracks property access.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for tracking\n * @returns Snapshot function for use with useSyncExternalStore\n */\nexport function autoTrackSnapshot<TBloc extends StateContainerConstructor>(\n instance: InstanceReadonlyState<TBloc>,\n adapterState: AdapterState<TBloc>,\n): SnapshotFunction<ExtractState<TBloc>> {\n return () => {\n const depState =\n adapterState.dependencyState ||\n (adapterState.dependencyState = createDependencyState<any>());\n\n if (hasTrackedData(depState)) {\n capturePaths(depState, instance.state);\n }\n\n if (adapterState.getterState) {\n invalidateRenderCache(adapterState.getterState);\n\n commitTrackedGetters(adapterState.getterState);\n\n adapterState.getterState.isTracking = true;\n\n setActiveTracker(instance, adapterState.getterState);\n }\n\n startDependency(depState);\n return createDependencyProxy(depState, instance.state);\n };\n}\n\n/**\n * Create a snapshot function for manual dependency tracking mode.\n * Caches dependencies for comparison on next render.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for caching\n * @param config - Configuration with dependencies function\n * @returns Snapshot function for use with useSyncExternalStore\n */\nexport function manualDepsSnapshot<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n adapterState: AdapterState<TBloc>,\n config: ManualDepsConfig<TBloc>,\n): SnapshotFunction<ExtractState<TBloc>> {\n return () => {\n adapterState.manualDepsCache = config.dependencies(\n instance.state,\n instance,\n );\n return instance.state;\n };\n}\n\n/**\n * Create a snapshot function for no-tracking mode.\n * Returns the raw state directly.\n * @param instance - The state container instance\n * @returns Snapshot function for use with useSyncExternalStore\n */\nexport function noTrackSnapshot<TBloc extends StateContainerConstructor>(\n instance: InstanceReadonlyState<TBloc>,\n): SnapshotFunction<ExtractState<TBloc>> {\n return () => instance.state;\n}\n\n/**\n * Initialize adapter state for auto-tracking mode.\n * Creates getter tracker and proxied bloc instance.\n * @param instance - The state container instance\n * @returns Initialized adapter state\n */\nexport function autoTrackInit<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n): AdapterState<TBloc> {\n return {\n dependencyState: null,\n manualDepsCache: null,\n getterState: createGetterState(),\n proxiedBloc: createBlocProxy(instance),\n };\n}\n\n/**\n * Initialize adapter state for manual dependency tracking mode.\n * No proxy is created; bloc is used directly.\n * @param instance - The state container instance\n * @returns Initialized adapter state\n */\nexport function manualDepsInit<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n): AdapterState<TBloc> {\n return {\n dependencyState: null,\n manualDepsCache: null,\n getterState: null,\n proxiedBloc: instance,\n };\n}\n\n/**\n * Initialize adapter state for no-tracking mode.\n * No tracking or proxy is created.\n * @param instance - The state container instance\n * @returns Initialized adapter state\n */\nexport function noTrackInit<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n): AdapterState<TBloc> {\n return {\n dependencyState: null,\n manualDepsCache: null,\n getterState: null,\n proxiedBloc: instance,\n };\n}\n\n/**\n * Disable getter tracking after render phase completes.\n * Clears the active tracker to prevent tracking outside of render.\n * @param adapterState - The adapter state\n * @param rawInstance - The raw bloc instance\n */\nexport function disableGetterTracking<TBloc extends StateContainerConstructor>(\n adapterState: AdapterState<TBloc>,\n rawInstance: InstanceState<TBloc>,\n): void {\n if (adapterState.getterState) {\n adapterState.getterState.isTracking = false;\n clearActiveTracker(rawInstance);\n commitTrackedGetters(adapterState.getterState);\n }\n}\n"],"mappings":";;;;;;;;;AAwGA,IAAa,sBAAb,MAAiC;;iBACb,IAAIA,uCAAmB;;;;;;;;;;CAUzC,oBACE,aACA,aACA,gBACS;AACT,MAAI,CAAC,YACH,QAAO;EAGT,MAAM,2DAAkC,YAAY;EAEpD,MAAM,yBAAyB;AAC7B,kDAAsB,YAAY;AAElC,iDAAqB,aAAa,YAAY,CAC5C,iBAAgB;;AAIpB,SAAO,KAAK,QAAQ,KAAK,aAAa,kBAAkB,YAAY;;;;;CAMtE,UAAgB;AACd,OAAK,QAAQ,SAAS;;;;;;;;;;AAa1B,SAAgB,mBACd,UACA,cACmB;AACnB,SAAQ,aAAmC;AACzC,SAAO,SAAS,gBAAgB;GAC9B,MAAM,WACJ,aAAa,oBACZ,aAAa,kEAA8C;GAE9D,MAAM,eAAe,SAAS,aAAa,SAAS,UAAU,OAAO;GACrE,MAAM,gBACJ,aAAa,eACb,aAAa,YAAY,eAAe,OAAO;GAEjD,MAAM,mBACJ,SAAS,UAAU,QACnB,OAAO,SAAS,UAAU,YAC1B,OAAO,SAAS,UAAU;AAE5B,OAAI,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,iBACtC;GAGF,IAAI,6DAAoC,UAAU,SAAS,MAAM;AAEjE,OAAI,CAAC,gBAAgB,cACnB,gBAAe;AAGjB,OAAI,cAAc;AAChB,cAAU;AACV;;AAQF,iDAJE,UACA,aAAa,YACd,CAGC,WAAU;IAEZ;;;;;;;;;;;AAYN,SAAgB,oBACd,UACA,cACA,QACmB;AACnB,SAAQ,aAAmC;AACzC,SAAO,SAAS,gBAAgB;GAC9B,MAAM,UAAU,OAAO,aAAa,SAAS,OAAO,SAAS;AAC7D,OACE,CAAC,aAAa,mBACd,uCAAc,aAAa,iBAAiB,QAAQ,EACpD;AACA,iBAAa,kBAAkB;AAC/B,cAAU;;IAEZ;;;;;;;;;AAUN,SAAgB,iBACd,UACmB;AACnB,SAAQ,aAAmC,SAAS,UAAU,SAAS;;;;;;;;;AAUzE,SAAgB,kBACd,UACA,cACuC;AACvC,cAAa;EACX,MAAM,WACJ,aAAa,oBACZ,aAAa,kEAA8C;AAE9D,8CAAmB,SAAS,CAC1B,uCAAa,UAAU,SAAS,MAAM;AAGxC,MAAI,aAAa,aAAa;AAC5B,kDAAsB,aAAa,YAAY;AAE/C,iDAAqB,aAAa,YAAY;AAE9C,gBAAa,YAAY,aAAa;AAEtC,6CAAiB,UAAU,aAAa,YAAY;;AAGtD,2CAAgB,SAAS;AACzB,wDAA6B,UAAU,SAAS,MAAM;;;;;;;;;;;AAY1D,SAAgB,mBACd,UACA,cACA,QACuC;AACvC,cAAa;AACX,eAAa,kBAAkB,OAAO,aACpC,SAAS,OACT,SACD;AACD,SAAO,SAAS;;;;;;;;;AAUpB,SAAgB,gBACd,UACuC;AACvC,cAAa,SAAS;;;;;;;;AASxB,SAAgB,cACd,UACqB;AACrB,QAAO;EACL,iBAAiB;EACjB,iBAAiB;EACjB,yDAAgC;EAChC,sDAA6B,SAAS;EACvC;;;;;;;;AASH,SAAgB,eACd,UACqB;AACrB,QAAO;EACL,iBAAiB;EACjB,iBAAiB;EACjB,aAAa;EACb,aAAa;EACd;;;;;;;;AASH,SAAgB,YACd,UACqB;AACrB,QAAO;EACL,iBAAiB;EACjB,iBAAiB;EACjB,aAAa;EACb,aAAa;EACd;;;;;;;;AASH,SAAgB,sBACd,cACA,aACM;AACN,KAAI,aAAa,aAAa;AAC5B,eAAa,YAAY,aAAa;AACtC,8CAAmB,YAAY;AAC/B,gDAAqB,aAAa,YAAY"} | ||
| {"version":3,"file":"index.cjs","names":["DependencyManager"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @blac/adapter - Framework Adapter\n *\n * Reusable utilities for integrating BlaC with any reactive framework.\n * Provides subscription and snapshot functions for different tracking modes.\n *\n * This package provides the building blocks for React, Preact, Vue, and other\n * framework integrations.\n */\nimport type {\n DependencyState,\n GetterState,\n ExtractState,\n InstanceReadonlyState,\n InstanceState,\n StateContainerConstructor,\n StateContainerInstance,\n} from '@blac/core';\n\nimport {\n acquire,\n release,\n isIsolatedClass,\n generateIsolatedKey,\n createDependencyState,\n startDependency,\n createDependencyProxy,\n capturePaths,\n hasDependencyChanges,\n hasTrackedData,\n shallowEqual,\n createGetterState,\n createBlocProxy,\n hasGetterChanges,\n setActiveTracker,\n clearActiveTracker,\n commitTrackedGetters,\n invalidateRenderCache,\n resolveDependencies,\n DependencyManager,\n} from '@blac/core';\n\nexport type {\n ExtractState,\n InstanceReadonlyState,\n InstanceState,\n StateContainerConstructor,\n StateContainerInstance,\n} from '@blac/core';\n\nexport {\n acquire,\n release,\n isIsolatedClass,\n generateIsolatedKey,\n} from '@blac/core';\n\n/**\n * Internal state for framework adapters, holding tracking and caching data.\n * @template TBloc - The state container type\n */\nexport interface AdapterState<TBloc extends StateContainerConstructor> {\n /** Dependency tracker for state property access tracking */\n dependencyState: DependencyState<ExtractState<TBloc>> | null;\n /** Cached manual dependencies for comparison */\n manualDepsCache: unknown[] | null;\n /** Getter state for computed property tracking */\n getterState: GetterState | null;\n /** Proxied bloc instance for auto-tracking */\n proxiedBloc: InstanceState<TBloc> | null;\n}\n\n/**\n * Configuration for manual dependency tracking mode\n * @template TBloc - The state container type\n */\nexport interface ManualDepsConfig<TBloc extends StateContainerConstructor> {\n /** Function that returns dependency array from state and bloc */\n dependencies: (\n state: ExtractState<TBloc>,\n bloc: InstanceState<TBloc>,\n ) => any[];\n}\n\n/**\n * Callback function invoked when subscribed state changes\n */\nexport type SubscriptionCallback = () => void;\n\n/**\n * Function that subscribes to state changes and returns an unsubscribe function\n */\nexport type SubscribeFunction = (callback: SubscriptionCallback) => () => void;\n\n/**\n * Function that returns a snapshot of the current state\n * @template TState - The state type\n */\nexport type SnapshotFunction<TState> = () => TState;\n\n/**\n * Manages subscriptions to external bloc dependencies for getter tracking.\n * When a getter accesses another bloc's state, this manager ensures\n * re-renders occur when those external dependencies change.\n */\nexport class ExternalDepsManager {\n private manager = new DependencyManager();\n private cachedDeps: Set<StateContainerInstance> | null = null;\n\n private resolveCached(\n rawInstance: StateContainerInstance,\n ): Set<StateContainerInstance> {\n if (this.cachedDeps) {\n let allValid = true;\n for (const dep of this.cachedDeps) {\n if (dep.isDisposed) {\n allValid = false;\n break;\n }\n }\n if (allValid) return this.cachedDeps;\n }\n this.cachedDeps = resolveDependencies(rawInstance);\n return this.cachedDeps;\n }\n\n /**\n * Update subscriptions to external bloc dependencies.\n * Resolves transitive dependencies via depend() declarations.\n * @param getterState - The getter tracker state (needed for change detection)\n * @param rawInstance - The primary bloc instance (excluded from subscriptions)\n * @param onGetterChange - Callback to invoke when external dependency changes\n * @returns true if subscriptions were updated, false if unchanged\n */\n updateSubscriptions(\n getterState: GetterState | null,\n rawInstance: StateContainerInstance,\n onGetterChange: () => void,\n ): boolean {\n if (!getterState || rawInstance.dependencies.size === 0) {\n return false;\n }\n\n const currentDeps = this.resolveCached(rawInstance);\n\n const onExternalChange = () => {\n invalidateRenderCache(getterState);\n\n if (hasGetterChanges(rawInstance, getterState)) {\n onGetterChange();\n }\n };\n\n return this.manager.sync(currentDeps, onExternalChange, rawInstance);\n }\n\n /**\n * Clean up all active subscriptions\n */\n cleanup(): void {\n this.manager.cleanup();\n this.cachedDeps = null;\n }\n}\n\nexport { DependencyManager };\n\n/**\n * Create a subscribe function for auto-tracking mode.\n * Only triggers callback when tracked properties change.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for tracking\n * @returns Subscribe function for use with useSyncExternalStore\n */\nexport function autoTrackSubscribe<TBloc extends StateContainerConstructor>(\n instance: InstanceReadonlyState<TBloc>,\n adapterState: AdapterState<TBloc>,\n): SubscribeFunction {\n return (callback: SubscriptionCallback) => {\n return instance.subscribe(() => {\n const depState =\n adapterState.dependencyState ||\n (adapterState.dependencyState = createDependencyState<any>());\n\n const hasStateDeps = depState.pathCache && depState.pathCache.size > 0;\n const hasGetterDeps =\n adapterState.getterState &&\n adapterState.getterState.trackedGetters.size > 0;\n\n const isPrimitiveState =\n instance.state !== null &&\n typeof instance.state !== 'object' &&\n typeof instance.state !== 'function';\n\n if (!hasStateDeps && !hasGetterDeps && !isPrimitiveState) {\n return;\n }\n\n let stateChanged = hasDependencyChanges(depState, instance.state);\n\n if (!hasStateDeps && hasGetterDeps) {\n stateChanged = false;\n }\n\n if (stateChanged) {\n callback();\n return;\n }\n\n const getterChanged = hasGetterChanges(\n instance,\n adapterState.getterState,\n );\n\n if (getterChanged) {\n callback();\n }\n });\n };\n}\n\n/**\n * Create a subscribe function for manual dependency tracking mode.\n * Only triggers callback when dependencies array changes.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for caching\n * @param config - Configuration with dependencies function\n * @returns Subscribe function for use with useSyncExternalStore\n */\nexport function manualDepsSubscribe<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n adapterState: AdapterState<TBloc>,\n config: ManualDepsConfig<TBloc>,\n): SubscribeFunction {\n return (callback: SubscriptionCallback) => {\n return instance.subscribe(() => {\n const newDeps = config.dependencies(instance.state, instance);\n if (\n !adapterState.manualDepsCache ||\n !shallowEqual(adapterState.manualDepsCache, newDeps)\n ) {\n adapterState.manualDepsCache = newDeps;\n callback();\n }\n });\n };\n}\n\n/**\n * Create a subscribe function for no-tracking mode.\n * Triggers callback on every state change.\n * @param instance - The state container instance\n * @returns Subscribe function for use with useSyncExternalStore\n */\nexport function noTrackSubscribe<TBloc extends StateContainerInstance>(\n instance: TBloc,\n): SubscribeFunction {\n return (callback: SubscriptionCallback) => instance.subscribe(callback);\n}\n\n/**\n * Create a snapshot function for auto-tracking mode.\n * Returns a proxied state that tracks property access.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for tracking\n * @returns Snapshot function for use with useSyncExternalStore\n */\nexport function autoTrackSnapshot<TBloc extends StateContainerConstructor>(\n instance: InstanceReadonlyState<TBloc>,\n adapterState: AdapterState<TBloc>,\n): SnapshotFunction<ExtractState<TBloc>> {\n return () => {\n const depState =\n adapterState.dependencyState ||\n (adapterState.dependencyState = createDependencyState<any>());\n\n if (hasTrackedData(depState)) {\n capturePaths(depState, instance.state);\n }\n\n if (adapterState.getterState) {\n invalidateRenderCache(adapterState.getterState);\n\n commitTrackedGetters(adapterState.getterState);\n\n adapterState.getterState.isTracking = true;\n\n setActiveTracker(instance, adapterState.getterState);\n }\n\n startDependency(depState);\n return createDependencyProxy(depState, instance.state);\n };\n}\n\n/**\n * Create a snapshot function for manual dependency tracking mode.\n * Caches dependencies for comparison on next render.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for caching\n * @param config - Configuration with dependencies function\n * @returns Snapshot function for use with useSyncExternalStore\n */\nexport function manualDepsSnapshot<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n adapterState: AdapterState<TBloc>,\n config: ManualDepsConfig<TBloc>,\n): SnapshotFunction<ExtractState<TBloc>> {\n return () => {\n adapterState.manualDepsCache = config.dependencies(\n instance.state,\n instance,\n );\n return instance.state;\n };\n}\n\n/**\n * Create a snapshot function for no-tracking mode.\n * Returns the raw state directly.\n * @param instance - The state container instance\n * @returns Snapshot function for use with useSyncExternalStore\n */\nexport function noTrackSnapshot<TBloc extends StateContainerConstructor>(\n instance: InstanceReadonlyState<TBloc>,\n): SnapshotFunction<ExtractState<TBloc>> {\n return () => instance.state;\n}\n\n/**\n * Initialize adapter state for auto-tracking mode.\n * Creates getter tracker and proxied bloc instance.\n * @param instance - The state container instance\n * @returns Initialized adapter state\n */\nexport function autoTrackInit<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n): AdapterState<TBloc> {\n return {\n dependencyState: null,\n manualDepsCache: null,\n getterState: createGetterState(),\n proxiedBloc: createBlocProxy(instance),\n };\n}\n\n/**\n * Initialize adapter state for manual dependency tracking mode.\n * No proxy is created; bloc is used directly.\n * @param instance - The state container instance\n * @returns Initialized adapter state\n */\nexport function manualDepsInit<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n): AdapterState<TBloc> {\n return {\n dependencyState: null,\n manualDepsCache: null,\n getterState: null,\n proxiedBloc: instance,\n };\n}\n\n/**\n * Initialize adapter state for no-tracking mode.\n * No tracking or proxy is created.\n * @param instance - The state container instance\n * @returns Initialized adapter state\n */\nexport function noTrackInit<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n): AdapterState<TBloc> {\n return {\n dependencyState: null,\n manualDepsCache: null,\n getterState: null,\n proxiedBloc: instance,\n };\n}\n\n/**\n * Disable getter tracking after render phase completes.\n * Clears the active tracker to prevent tracking outside of render.\n * @param adapterState - The adapter state\n * @param rawInstance - The raw bloc instance\n */\nexport function disableGetterTracking<TBloc extends StateContainerConstructor>(\n adapterState: AdapterState<TBloc>,\n rawInstance: InstanceState<TBloc>,\n): void {\n if (adapterState.getterState) {\n adapterState.getterState.isTracking = false;\n clearActiveTracker(rawInstance);\n commitTrackedGetters(adapterState.getterState);\n }\n}\n"],"mappings":"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"} |
+75
-109
@@ -1,21 +0,19 @@ | ||
| import { acquire } from '@blac/core'; | ||
| import { DependencyManager } from '@blac/core/tracking'; | ||
| import type { DependencyState } from '@blac/core/tracking'; | ||
| import { ExtractState } from '@blac/core'; | ||
| import { generateIsolatedKey } from '@blac/core'; | ||
| import type { GetterState } from '@blac/core/tracking'; | ||
| import { InstanceReadonlyState } from '@blac/core'; | ||
| import { InstanceState } from '@blac/core'; | ||
| import { isIsolatedClass } from '@blac/core'; | ||
| import { release } from '@blac/core'; | ||
| import { StateContainerConstructor } from '@blac/core'; | ||
| import { StateContainerInstance } from '@blac/core'; | ||
| export { acquire } | ||
| /** | ||
| * @blac/adapter - Framework Adapter | ||
| * | ||
| * Reusable utilities for integrating BlaC with any reactive framework. | ||
| * Provides subscription and snapshot functions for different tracking modes. | ||
| * | ||
| * This package provides the building blocks for React, Preact, Vue, and other | ||
| * framework integrations. | ||
| */ | ||
| import type { DependencyState, GetterState, ExtractState, InstanceReadonlyState, InstanceState, StateContainerConstructor, StateContainerInstance } from '@blac/core'; | ||
| import { DependencyManager } from '@blac/core'; | ||
| export type { ExtractState, InstanceReadonlyState, InstanceState, StateContainerConstructor, StateContainerInstance, } from '@blac/core'; | ||
| export { acquire, release, isIsolatedClass, generateIsolatedKey, } from '@blac/core'; | ||
| /** | ||
| * Internal state for framework adapters, holding tracking and caching data. | ||
| * @template TBloc - The state container type | ||
| */ | ||
| export declare interface AdapterState<TBloc extends StateContainerConstructor> { | ||
| export interface AdapterState<TBloc extends StateContainerConstructor> { | ||
| /** Dependency tracker for state property access tracking */ | ||
@@ -30,39 +28,23 @@ dependencyState: DependencyState<ExtractState<TBloc>> | null; | ||
| } | ||
| /** | ||
| * Initialize adapter state for auto-tracking mode. | ||
| * Creates getter tracker and proxied bloc instance. | ||
| * @param instance - The state container instance | ||
| * @returns Initialized adapter state | ||
| * Configuration for manual dependency tracking mode | ||
| * @template TBloc - The state container type | ||
| */ | ||
| export declare function autoTrackInit<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>): AdapterState<TBloc>; | ||
| export interface ManualDepsConfig<TBloc extends StateContainerConstructor> { | ||
| /** Function that returns dependency array from state and bloc */ | ||
| dependencies: (state: ExtractState<TBloc>, bloc: InstanceState<TBloc>) => any[]; | ||
| } | ||
| /** | ||
| * Create a snapshot function for auto-tracking mode. | ||
| * Returns a proxied state that tracks property access. | ||
| * @param instance - The state container instance | ||
| * @param adapterState - The adapter state for tracking | ||
| * @returns Snapshot function for use with useSyncExternalStore | ||
| * Callback function invoked when subscribed state changes | ||
| */ | ||
| export declare function autoTrackSnapshot<TBloc extends StateContainerConstructor>(instance: InstanceReadonlyState<TBloc>, adapterState: AdapterState<TBloc>): SnapshotFunction<ExtractState<TBloc>>; | ||
| export type SubscriptionCallback = () => void; | ||
| /** | ||
| * Create a subscribe function for auto-tracking mode. | ||
| * Only triggers callback when tracked properties change. | ||
| * @param instance - The state container instance | ||
| * @param adapterState - The adapter state for tracking | ||
| * @returns Subscribe function for use with useSyncExternalStore | ||
| * Function that subscribes to state changes and returns an unsubscribe function | ||
| */ | ||
| export declare function autoTrackSubscribe<TBloc extends StateContainerConstructor>(instance: InstanceReadonlyState<TBloc>, adapterState: AdapterState<TBloc>): SubscribeFunction; | ||
| export { DependencyManager } | ||
| export type SubscribeFunction = (callback: SubscriptionCallback) => () => void; | ||
| /** | ||
| * Disable getter tracking after render phase completes. | ||
| * Clears the active tracker to prevent tracking outside of render. | ||
| * @param adapterState - The adapter state | ||
| * @param rawInstance - The raw bloc instance | ||
| * Function that returns a snapshot of the current state | ||
| * @template TState - The state type | ||
| */ | ||
| export declare function disableGetterTracking<TBloc extends StateContainerConstructor>(adapterState: AdapterState<TBloc>, rawInstance: InstanceState<TBloc>): void; | ||
| export type SnapshotFunction<TState> = () => TState; | ||
| /** | ||
@@ -75,2 +57,4 @@ * Manages subscriptions to external bloc dependencies for getter tracking. | ||
| private manager; | ||
| private cachedDeps; | ||
| private resolveCached; | ||
| /** | ||
@@ -90,41 +74,12 @@ * Update subscriptions to external bloc dependencies. | ||
| } | ||
| export { ExtractState } | ||
| export { generateIsolatedKey } | ||
| export { InstanceReadonlyState } | ||
| export { InstanceState } | ||
| export { isIsolatedClass } | ||
| export { DependencyManager }; | ||
| /** | ||
| * Configuration for manual dependency tracking mode | ||
| * @template TBloc - The state container type | ||
| */ | ||
| export declare interface ManualDepsConfig<TBloc extends StateContainerConstructor> { | ||
| /** Function that returns dependency array from state and bloc */ | ||
| dependencies: (state: ExtractState<TBloc>, bloc: InstanceState<TBloc>) => any[]; | ||
| } | ||
| /** | ||
| * Initialize adapter state for manual dependency tracking mode. | ||
| * No proxy is created; bloc is used directly. | ||
| * Create a subscribe function for auto-tracking mode. | ||
| * Only triggers callback when tracked properties change. | ||
| * @param instance - The state container instance | ||
| * @returns Initialized adapter state | ||
| * @param adapterState - The adapter state for tracking | ||
| * @returns Subscribe function for use with useSyncExternalStore | ||
| */ | ||
| export declare function manualDepsInit<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>): AdapterState<TBloc>; | ||
| export declare function autoTrackSubscribe<TBloc extends StateContainerConstructor>(instance: InstanceReadonlyState<TBloc>, adapterState: AdapterState<TBloc>): SubscribeFunction; | ||
| /** | ||
| * Create a snapshot function for manual dependency tracking mode. | ||
| * Caches dependencies for comparison on next render. | ||
| * @param instance - The state container instance | ||
| * @param adapterState - The adapter state for caching | ||
| * @param config - Configuration with dependencies function | ||
| * @returns Snapshot function for use with useSyncExternalStore | ||
| */ | ||
| export declare function manualDepsSnapshot<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>, adapterState: AdapterState<TBloc>, config: ManualDepsConfig<TBloc>): SnapshotFunction<ExtractState<TBloc>>; | ||
| /** | ||
| * Create a subscribe function for manual dependency tracking mode. | ||
@@ -138,12 +93,27 @@ * Only triggers callback when dependencies array changes. | ||
| export declare function manualDepsSubscribe<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>, adapterState: AdapterState<TBloc>, config: ManualDepsConfig<TBloc>): SubscribeFunction; | ||
| /** | ||
| * Initialize adapter state for no-tracking mode. | ||
| * No tracking or proxy is created. | ||
| * Create a subscribe function for no-tracking mode. | ||
| * Triggers callback on every state change. | ||
| * @param instance - The state container instance | ||
| * @returns Initialized adapter state | ||
| * @returns Subscribe function for use with useSyncExternalStore | ||
| */ | ||
| export declare function noTrackInit<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>): AdapterState<TBloc>; | ||
| export declare function noTrackSubscribe<TBloc extends StateContainerInstance>(instance: TBloc): SubscribeFunction; | ||
| /** | ||
| * Create a snapshot function for auto-tracking mode. | ||
| * Returns a proxied state that tracks property access. | ||
| * @param instance - The state container instance | ||
| * @param adapterState - The adapter state for tracking | ||
| * @returns Snapshot function for use with useSyncExternalStore | ||
| */ | ||
| export declare function autoTrackSnapshot<TBloc extends StateContainerConstructor>(instance: InstanceReadonlyState<TBloc>, adapterState: AdapterState<TBloc>): SnapshotFunction<ExtractState<TBloc>>; | ||
| /** | ||
| * Create a snapshot function for manual dependency tracking mode. | ||
| * Caches dependencies for comparison on next render. | ||
| * @param instance - The state container instance | ||
| * @param adapterState - The adapter state for caching | ||
| * @param config - Configuration with dependencies function | ||
| * @returns Snapshot function for use with useSyncExternalStore | ||
| */ | ||
| export declare function manualDepsSnapshot<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>, adapterState: AdapterState<TBloc>, config: ManualDepsConfig<TBloc>): SnapshotFunction<ExtractState<TBloc>>; | ||
| /** | ||
| * Create a snapshot function for no-tracking mode. | ||
@@ -155,33 +125,29 @@ * Returns the raw state directly. | ||
| export declare function noTrackSnapshot<TBloc extends StateContainerConstructor>(instance: InstanceReadonlyState<TBloc>): SnapshotFunction<ExtractState<TBloc>>; | ||
| /** | ||
| * Create a subscribe function for no-tracking mode. | ||
| * Triggers callback on every state change. | ||
| * Initialize adapter state for auto-tracking mode. | ||
| * Creates getter tracker and proxied bloc instance. | ||
| * @param instance - The state container instance | ||
| * @returns Subscribe function for use with useSyncExternalStore | ||
| * @returns Initialized adapter state | ||
| */ | ||
| export declare function noTrackSubscribe<TBloc extends StateContainerInstance>(instance: TBloc): SubscribeFunction; | ||
| export { release } | ||
| export declare function autoTrackInit<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>): AdapterState<TBloc>; | ||
| /** | ||
| * Function that returns a snapshot of the current state | ||
| * @template TState - The state type | ||
| * Initialize adapter state for manual dependency tracking mode. | ||
| * No proxy is created; bloc is used directly. | ||
| * @param instance - The state container instance | ||
| * @returns Initialized adapter state | ||
| */ | ||
| export declare type SnapshotFunction<TState> = () => TState; | ||
| export { StateContainerConstructor } | ||
| export { StateContainerInstance } | ||
| export declare function manualDepsInit<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>): AdapterState<TBloc>; | ||
| /** | ||
| * Function that subscribes to state changes and returns an unsubscribe function | ||
| * Initialize adapter state for no-tracking mode. | ||
| * No tracking or proxy is created. | ||
| * @param instance - The state container instance | ||
| * @returns Initialized adapter state | ||
| */ | ||
| export declare type SubscribeFunction = (callback: SubscriptionCallback) => () => void; | ||
| export declare function noTrackInit<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>): AdapterState<TBloc>; | ||
| /** | ||
| * Callback function invoked when subscribed state changes | ||
| * Disable getter tracking after render phase completes. | ||
| * Clears the active tracker to prevent tracking outside of render. | ||
| * @param adapterState - The adapter state | ||
| * @param rawInstance - The raw bloc instance | ||
| */ | ||
| export declare type SubscriptionCallback = () => void; | ||
| export { } | ||
| export declare function disableGetterTracking<TBloc extends StateContainerConstructor>(adapterState: AdapterState<TBloc>, rawInstance: InstanceState<TBloc>): void; |
+75
-109
@@ -1,21 +0,19 @@ | ||
| import { acquire } from '@blac/core'; | ||
| import { DependencyManager } from '@blac/core/tracking'; | ||
| import type { DependencyState } from '@blac/core/tracking'; | ||
| import { ExtractState } from '@blac/core'; | ||
| import { generateIsolatedKey } from '@blac/core'; | ||
| import type { GetterState } from '@blac/core/tracking'; | ||
| import { InstanceReadonlyState } from '@blac/core'; | ||
| import { InstanceState } from '@blac/core'; | ||
| import { isIsolatedClass } from '@blac/core'; | ||
| import { release } from '@blac/core'; | ||
| import { StateContainerConstructor } from '@blac/core'; | ||
| import { StateContainerInstance } from '@blac/core'; | ||
| export { acquire } | ||
| /** | ||
| * @blac/adapter - Framework Adapter | ||
| * | ||
| * Reusable utilities for integrating BlaC with any reactive framework. | ||
| * Provides subscription and snapshot functions for different tracking modes. | ||
| * | ||
| * This package provides the building blocks for React, Preact, Vue, and other | ||
| * framework integrations. | ||
| */ | ||
| import type { DependencyState, GetterState, ExtractState, InstanceReadonlyState, InstanceState, StateContainerConstructor, StateContainerInstance } from '@blac/core'; | ||
| import { DependencyManager } from '@blac/core'; | ||
| export type { ExtractState, InstanceReadonlyState, InstanceState, StateContainerConstructor, StateContainerInstance, } from '@blac/core'; | ||
| export { acquire, release, isIsolatedClass, generateIsolatedKey, } from '@blac/core'; | ||
| /** | ||
| * Internal state for framework adapters, holding tracking and caching data. | ||
| * @template TBloc - The state container type | ||
| */ | ||
| export declare interface AdapterState<TBloc extends StateContainerConstructor> { | ||
| export interface AdapterState<TBloc extends StateContainerConstructor> { | ||
| /** Dependency tracker for state property access tracking */ | ||
@@ -30,39 +28,23 @@ dependencyState: DependencyState<ExtractState<TBloc>> | null; | ||
| } | ||
| /** | ||
| * Initialize adapter state for auto-tracking mode. | ||
| * Creates getter tracker and proxied bloc instance. | ||
| * @param instance - The state container instance | ||
| * @returns Initialized adapter state | ||
| * Configuration for manual dependency tracking mode | ||
| * @template TBloc - The state container type | ||
| */ | ||
| export declare function autoTrackInit<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>): AdapterState<TBloc>; | ||
| export interface ManualDepsConfig<TBloc extends StateContainerConstructor> { | ||
| /** Function that returns dependency array from state and bloc */ | ||
| dependencies: (state: ExtractState<TBloc>, bloc: InstanceState<TBloc>) => any[]; | ||
| } | ||
| /** | ||
| * Create a snapshot function for auto-tracking mode. | ||
| * Returns a proxied state that tracks property access. | ||
| * @param instance - The state container instance | ||
| * @param adapterState - The adapter state for tracking | ||
| * @returns Snapshot function for use with useSyncExternalStore | ||
| * Callback function invoked when subscribed state changes | ||
| */ | ||
| export declare function autoTrackSnapshot<TBloc extends StateContainerConstructor>(instance: InstanceReadonlyState<TBloc>, adapterState: AdapterState<TBloc>): SnapshotFunction<ExtractState<TBloc>>; | ||
| export type SubscriptionCallback = () => void; | ||
| /** | ||
| * Create a subscribe function for auto-tracking mode. | ||
| * Only triggers callback when tracked properties change. | ||
| * @param instance - The state container instance | ||
| * @param adapterState - The adapter state for tracking | ||
| * @returns Subscribe function for use with useSyncExternalStore | ||
| * Function that subscribes to state changes and returns an unsubscribe function | ||
| */ | ||
| export declare function autoTrackSubscribe<TBloc extends StateContainerConstructor>(instance: InstanceReadonlyState<TBloc>, adapterState: AdapterState<TBloc>): SubscribeFunction; | ||
| export { DependencyManager } | ||
| export type SubscribeFunction = (callback: SubscriptionCallback) => () => void; | ||
| /** | ||
| * Disable getter tracking after render phase completes. | ||
| * Clears the active tracker to prevent tracking outside of render. | ||
| * @param adapterState - The adapter state | ||
| * @param rawInstance - The raw bloc instance | ||
| * Function that returns a snapshot of the current state | ||
| * @template TState - The state type | ||
| */ | ||
| export declare function disableGetterTracking<TBloc extends StateContainerConstructor>(adapterState: AdapterState<TBloc>, rawInstance: InstanceState<TBloc>): void; | ||
| export type SnapshotFunction<TState> = () => TState; | ||
| /** | ||
@@ -75,2 +57,4 @@ * Manages subscriptions to external bloc dependencies for getter tracking. | ||
| private manager; | ||
| private cachedDeps; | ||
| private resolveCached; | ||
| /** | ||
@@ -90,41 +74,12 @@ * Update subscriptions to external bloc dependencies. | ||
| } | ||
| export { ExtractState } | ||
| export { generateIsolatedKey } | ||
| export { InstanceReadonlyState } | ||
| export { InstanceState } | ||
| export { isIsolatedClass } | ||
| export { DependencyManager }; | ||
| /** | ||
| * Configuration for manual dependency tracking mode | ||
| * @template TBloc - The state container type | ||
| */ | ||
| export declare interface ManualDepsConfig<TBloc extends StateContainerConstructor> { | ||
| /** Function that returns dependency array from state and bloc */ | ||
| dependencies: (state: ExtractState<TBloc>, bloc: InstanceState<TBloc>) => any[]; | ||
| } | ||
| /** | ||
| * Initialize adapter state for manual dependency tracking mode. | ||
| * No proxy is created; bloc is used directly. | ||
| * Create a subscribe function for auto-tracking mode. | ||
| * Only triggers callback when tracked properties change. | ||
| * @param instance - The state container instance | ||
| * @returns Initialized adapter state | ||
| * @param adapterState - The adapter state for tracking | ||
| * @returns Subscribe function for use with useSyncExternalStore | ||
| */ | ||
| export declare function manualDepsInit<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>): AdapterState<TBloc>; | ||
| export declare function autoTrackSubscribe<TBloc extends StateContainerConstructor>(instance: InstanceReadonlyState<TBloc>, adapterState: AdapterState<TBloc>): SubscribeFunction; | ||
| /** | ||
| * Create a snapshot function for manual dependency tracking mode. | ||
| * Caches dependencies for comparison on next render. | ||
| * @param instance - The state container instance | ||
| * @param adapterState - The adapter state for caching | ||
| * @param config - Configuration with dependencies function | ||
| * @returns Snapshot function for use with useSyncExternalStore | ||
| */ | ||
| export declare function manualDepsSnapshot<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>, adapterState: AdapterState<TBloc>, config: ManualDepsConfig<TBloc>): SnapshotFunction<ExtractState<TBloc>>; | ||
| /** | ||
| * Create a subscribe function for manual dependency tracking mode. | ||
@@ -138,12 +93,27 @@ * Only triggers callback when dependencies array changes. | ||
| export declare function manualDepsSubscribe<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>, adapterState: AdapterState<TBloc>, config: ManualDepsConfig<TBloc>): SubscribeFunction; | ||
| /** | ||
| * Initialize adapter state for no-tracking mode. | ||
| * No tracking or proxy is created. | ||
| * Create a subscribe function for no-tracking mode. | ||
| * Triggers callback on every state change. | ||
| * @param instance - The state container instance | ||
| * @returns Initialized adapter state | ||
| * @returns Subscribe function for use with useSyncExternalStore | ||
| */ | ||
| export declare function noTrackInit<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>): AdapterState<TBloc>; | ||
| export declare function noTrackSubscribe<TBloc extends StateContainerInstance>(instance: TBloc): SubscribeFunction; | ||
| /** | ||
| * Create a snapshot function for auto-tracking mode. | ||
| * Returns a proxied state that tracks property access. | ||
| * @param instance - The state container instance | ||
| * @param adapterState - The adapter state for tracking | ||
| * @returns Snapshot function for use with useSyncExternalStore | ||
| */ | ||
| export declare function autoTrackSnapshot<TBloc extends StateContainerConstructor>(instance: InstanceReadonlyState<TBloc>, adapterState: AdapterState<TBloc>): SnapshotFunction<ExtractState<TBloc>>; | ||
| /** | ||
| * Create a snapshot function for manual dependency tracking mode. | ||
| * Caches dependencies for comparison on next render. | ||
| * @param instance - The state container instance | ||
| * @param adapterState - The adapter state for caching | ||
| * @param config - Configuration with dependencies function | ||
| * @returns Snapshot function for use with useSyncExternalStore | ||
| */ | ||
| export declare function manualDepsSnapshot<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>, adapterState: AdapterState<TBloc>, config: ManualDepsConfig<TBloc>): SnapshotFunction<ExtractState<TBloc>>; | ||
| /** | ||
| * Create a snapshot function for no-tracking mode. | ||
@@ -155,33 +125,29 @@ * Returns the raw state directly. | ||
| export declare function noTrackSnapshot<TBloc extends StateContainerConstructor>(instance: InstanceReadonlyState<TBloc>): SnapshotFunction<ExtractState<TBloc>>; | ||
| /** | ||
| * Create a subscribe function for no-tracking mode. | ||
| * Triggers callback on every state change. | ||
| * Initialize adapter state for auto-tracking mode. | ||
| * Creates getter tracker and proxied bloc instance. | ||
| * @param instance - The state container instance | ||
| * @returns Subscribe function for use with useSyncExternalStore | ||
| * @returns Initialized adapter state | ||
| */ | ||
| export declare function noTrackSubscribe<TBloc extends StateContainerInstance>(instance: TBloc): SubscribeFunction; | ||
| export { release } | ||
| export declare function autoTrackInit<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>): AdapterState<TBloc>; | ||
| /** | ||
| * Function that returns a snapshot of the current state | ||
| * @template TState - The state type | ||
| * Initialize adapter state for manual dependency tracking mode. | ||
| * No proxy is created; bloc is used directly. | ||
| * @param instance - The state container instance | ||
| * @returns Initialized adapter state | ||
| */ | ||
| export declare type SnapshotFunction<TState> = () => TState; | ||
| export { StateContainerConstructor } | ||
| export { StateContainerInstance } | ||
| export declare function manualDepsInit<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>): AdapterState<TBloc>; | ||
| /** | ||
| * Function that subscribes to state changes and returns an unsubscribe function | ||
| * Initialize adapter state for no-tracking mode. | ||
| * No tracking or proxy is created. | ||
| * @param instance - The state container instance | ||
| * @returns Initialized adapter state | ||
| */ | ||
| export declare type SubscribeFunction = (callback: SubscriptionCallback) => () => void; | ||
| export declare function noTrackInit<TBloc extends StateContainerConstructor>(instance: InstanceState<TBloc>): AdapterState<TBloc>; | ||
| /** | ||
| * Callback function invoked when subscribed state changes | ||
| * Disable getter tracking after render phase completes. | ||
| * Clears the active tracker to prevent tracking outside of render. | ||
| * @param adapterState - The adapter state | ||
| * @param rawInstance - The raw bloc instance | ||
| */ | ||
| export declare type SubscriptionCallback = () => void; | ||
| export { } | ||
| export declare function disableGetterTracking<TBloc extends StateContainerConstructor>(adapterState: AdapterState<TBloc>, rawInstance: InstanceState<TBloc>): void; |
+17
-4
@@ -1,3 +0,2 @@ | ||
| import { acquire, generateIsolatedKey, isIsolatedClass, release } from "@blac/core"; | ||
| import { DependencyManager, capturePaths, clearActiveTracker, commitTrackedGetters, createBlocProxy, createDependencyProxy, createDependencyState, createGetterState, hasDependencyChanges, hasGetterChanges, hasTrackedData, invalidateRenderCache, resolveDependencies, setActiveTracker, shallowEqual, startDependency } from "@blac/core/tracking"; | ||
| import { DependencyManager, acquire, capturePaths, clearActiveTracker, commitTrackedGetters, createBlocProxy, createDependencyProxy, createDependencyState, createGetterState, generateIsolatedKey, hasDependencyChanges, hasGetterChanges, hasTrackedData, invalidateRenderCache, isIsolatedClass, release, resolveDependencies, setActiveTracker, shallowEqual, startDependency } from "@blac/core"; | ||
@@ -13,3 +12,16 @@ //#region src/index.ts | ||
| this.manager = new DependencyManager(); | ||
| this.cachedDeps = null; | ||
| } | ||
| resolveCached(rawInstance) { | ||
| if (this.cachedDeps) { | ||
| let allValid = true; | ||
| for (const dep of this.cachedDeps) if (dep.isDisposed) { | ||
| allValid = false; | ||
| break; | ||
| } | ||
| if (allValid) return this.cachedDeps; | ||
| } | ||
| this.cachedDeps = resolveDependencies(rawInstance); | ||
| return this.cachedDeps; | ||
| } | ||
| /** | ||
@@ -24,4 +36,4 @@ * Update subscriptions to external bloc dependencies. | ||
| updateSubscriptions(getterState, rawInstance, onGetterChange) { | ||
| if (!getterState) return false; | ||
| const currentDeps = resolveDependencies(rawInstance); | ||
| if (!getterState || rawInstance.dependencies.size === 0) return false; | ||
| const currentDeps = this.resolveCached(rawInstance); | ||
| const onExternalChange = () => { | ||
@@ -38,2 +50,3 @@ invalidateRenderCache(getterState); | ||
| this.manager.cleanup(); | ||
| this.cachedDeps = null; | ||
| } | ||
@@ -40,0 +53,0 @@ }; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @blac/adapter - Framework Adapter\n *\n * Reusable utilities for integrating BlaC with any reactive framework.\n * Provides subscription and snapshot functions for different tracking modes.\n *\n * This package provides the building blocks for React, Preact, Vue, and other\n * framework integrations.\n */\nimport type {\n ExtractState,\n InstanceReadonlyState,\n InstanceState,\n StateContainerConstructor,\n StateContainerInstance,\n} from '@blac/core';\n\n// Re-export types needed by framework integrations\nexport type {\n ExtractState,\n InstanceReadonlyState,\n InstanceState,\n StateContainerConstructor,\n StateContainerInstance,\n} from '@blac/core';\n\n// Re-export registry functions needed by hooks\nexport {\n acquire,\n release,\n isIsolatedClass,\n generateIsolatedKey,\n} from '@blac/core';\n\n// Import tracking types and functions from @blac/core/tracking subpath\nimport type { DependencyState, GetterState } from '@blac/core/tracking';\n\nimport {\n createDependencyState,\n startDependency,\n createDependencyProxy,\n capturePaths,\n hasDependencyChanges,\n hasTrackedData,\n shallowEqual,\n createGetterState,\n createBlocProxy,\n hasGetterChanges,\n setActiveTracker,\n clearActiveTracker,\n commitTrackedGetters,\n invalidateRenderCache,\n resolveDependencies,\n DependencyManager,\n} from '@blac/core/tracking';\n\n/**\n * Internal state for framework adapters, holding tracking and caching data.\n * @template TBloc - The state container type\n */\nexport interface AdapterState<TBloc extends StateContainerConstructor> {\n /** Dependency tracker for state property access tracking */\n dependencyState: DependencyState<ExtractState<TBloc>> | null;\n /** Cached manual dependencies for comparison */\n manualDepsCache: unknown[] | null;\n /** Getter state for computed property tracking */\n getterState: GetterState | null;\n /** Proxied bloc instance for auto-tracking */\n proxiedBloc: InstanceState<TBloc> | null;\n}\n\n/**\n * Configuration for manual dependency tracking mode\n * @template TBloc - The state container type\n */\nexport interface ManualDepsConfig<TBloc extends StateContainerConstructor> {\n /** Function that returns dependency array from state and bloc */\n dependencies: (\n state: ExtractState<TBloc>,\n bloc: InstanceState<TBloc>,\n ) => any[];\n}\n\n/**\n * Callback function invoked when subscribed state changes\n */\nexport type SubscriptionCallback = () => void;\n\n/**\n * Function that subscribes to state changes and returns an unsubscribe function\n */\nexport type SubscribeFunction = (callback: SubscriptionCallback) => () => void;\n\n/**\n * Function that returns a snapshot of the current state\n * @template TState - The state type\n */\nexport type SnapshotFunction<TState> = () => TState;\n\n/**\n * Manages subscriptions to external bloc dependencies for getter tracking.\n * When a getter accesses another bloc's state, this manager ensures\n * re-renders occur when those external dependencies change.\n */\nexport class ExternalDepsManager {\n private manager = new DependencyManager();\n\n /**\n * Update subscriptions to external bloc dependencies.\n * Resolves transitive dependencies via depend() declarations.\n * @param getterState - The getter tracker state (needed for change detection)\n * @param rawInstance - The primary bloc instance (excluded from subscriptions)\n * @param onGetterChange - Callback to invoke when external dependency changes\n * @returns true if subscriptions were updated, false if unchanged\n */\n updateSubscriptions(\n getterState: GetterState | null,\n rawInstance: StateContainerInstance,\n onGetterChange: () => void,\n ): boolean {\n if (!getterState) {\n return false;\n }\n\n const currentDeps = resolveDependencies(rawInstance);\n\n const onExternalChange = () => {\n invalidateRenderCache(getterState);\n\n if (hasGetterChanges(rawInstance, getterState)) {\n onGetterChange();\n }\n };\n\n return this.manager.sync(currentDeps, onExternalChange, rawInstance);\n }\n\n /**\n * Clean up all active subscriptions\n */\n cleanup(): void {\n this.manager.cleanup();\n }\n}\n\nexport { DependencyManager };\n\n/**\n * Create a subscribe function for auto-tracking mode.\n * Only triggers callback when tracked properties change.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for tracking\n * @returns Subscribe function for use with useSyncExternalStore\n */\nexport function autoTrackSubscribe<TBloc extends StateContainerConstructor>(\n instance: InstanceReadonlyState<TBloc>,\n adapterState: AdapterState<TBloc>,\n): SubscribeFunction {\n return (callback: SubscriptionCallback) => {\n return instance.subscribe(() => {\n const depState =\n adapterState.dependencyState ||\n (adapterState.dependencyState = createDependencyState<any>());\n\n const hasStateDeps = depState.pathCache && depState.pathCache.size > 0;\n const hasGetterDeps =\n adapterState.getterState &&\n adapterState.getterState.trackedGetters.size > 0;\n\n const isPrimitiveState =\n instance.state !== null &&\n typeof instance.state !== 'object' &&\n typeof instance.state !== 'function';\n\n if (!hasStateDeps && !hasGetterDeps && !isPrimitiveState) {\n return;\n }\n\n let stateChanged = hasDependencyChanges(depState, instance.state);\n\n if (!hasStateDeps && hasGetterDeps) {\n stateChanged = false;\n }\n\n if (stateChanged) {\n callback();\n return;\n }\n\n const getterChanged = hasGetterChanges(\n instance,\n adapterState.getterState,\n );\n\n if (getterChanged) {\n callback();\n }\n });\n };\n}\n\n/**\n * Create a subscribe function for manual dependency tracking mode.\n * Only triggers callback when dependencies array changes.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for caching\n * @param config - Configuration with dependencies function\n * @returns Subscribe function for use with useSyncExternalStore\n */\nexport function manualDepsSubscribe<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n adapterState: AdapterState<TBloc>,\n config: ManualDepsConfig<TBloc>,\n): SubscribeFunction {\n return (callback: SubscriptionCallback) => {\n return instance.subscribe(() => {\n const newDeps = config.dependencies(instance.state, instance);\n if (\n !adapterState.manualDepsCache ||\n !shallowEqual(adapterState.manualDepsCache, newDeps)\n ) {\n adapterState.manualDepsCache = newDeps;\n callback();\n }\n });\n };\n}\n\n/**\n * Create a subscribe function for no-tracking mode.\n * Triggers callback on every state change.\n * @param instance - The state container instance\n * @returns Subscribe function for use with useSyncExternalStore\n */\nexport function noTrackSubscribe<TBloc extends StateContainerInstance>(\n instance: TBloc,\n): SubscribeFunction {\n return (callback: SubscriptionCallback) => instance.subscribe(callback);\n}\n\n/**\n * Create a snapshot function for auto-tracking mode.\n * Returns a proxied state that tracks property access.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for tracking\n * @returns Snapshot function for use with useSyncExternalStore\n */\nexport function autoTrackSnapshot<TBloc extends StateContainerConstructor>(\n instance: InstanceReadonlyState<TBloc>,\n adapterState: AdapterState<TBloc>,\n): SnapshotFunction<ExtractState<TBloc>> {\n return () => {\n const depState =\n adapterState.dependencyState ||\n (adapterState.dependencyState = createDependencyState<any>());\n\n if (hasTrackedData(depState)) {\n capturePaths(depState, instance.state);\n }\n\n if (adapterState.getterState) {\n invalidateRenderCache(adapterState.getterState);\n\n commitTrackedGetters(adapterState.getterState);\n\n adapterState.getterState.isTracking = true;\n\n setActiveTracker(instance, adapterState.getterState);\n }\n\n startDependency(depState);\n return createDependencyProxy(depState, instance.state);\n };\n}\n\n/**\n * Create a snapshot function for manual dependency tracking mode.\n * Caches dependencies for comparison on next render.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for caching\n * @param config - Configuration with dependencies function\n * @returns Snapshot function for use with useSyncExternalStore\n */\nexport function manualDepsSnapshot<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n adapterState: AdapterState<TBloc>,\n config: ManualDepsConfig<TBloc>,\n): SnapshotFunction<ExtractState<TBloc>> {\n return () => {\n adapterState.manualDepsCache = config.dependencies(\n instance.state,\n instance,\n );\n return instance.state;\n };\n}\n\n/**\n * Create a snapshot function for no-tracking mode.\n * Returns the raw state directly.\n * @param instance - The state container instance\n * @returns Snapshot function for use with useSyncExternalStore\n */\nexport function noTrackSnapshot<TBloc extends StateContainerConstructor>(\n instance: InstanceReadonlyState<TBloc>,\n): SnapshotFunction<ExtractState<TBloc>> {\n return () => instance.state;\n}\n\n/**\n * Initialize adapter state for auto-tracking mode.\n * Creates getter tracker and proxied bloc instance.\n * @param instance - The state container instance\n * @returns Initialized adapter state\n */\nexport function autoTrackInit<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n): AdapterState<TBloc> {\n return {\n dependencyState: null,\n manualDepsCache: null,\n getterState: createGetterState(),\n proxiedBloc: createBlocProxy(instance),\n };\n}\n\n/**\n * Initialize adapter state for manual dependency tracking mode.\n * No proxy is created; bloc is used directly.\n * @param instance - The state container instance\n * @returns Initialized adapter state\n */\nexport function manualDepsInit<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n): AdapterState<TBloc> {\n return {\n dependencyState: null,\n manualDepsCache: null,\n getterState: null,\n proxiedBloc: instance,\n };\n}\n\n/**\n * Initialize adapter state for no-tracking mode.\n * No tracking or proxy is created.\n * @param instance - The state container instance\n * @returns Initialized adapter state\n */\nexport function noTrackInit<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n): AdapterState<TBloc> {\n return {\n dependencyState: null,\n manualDepsCache: null,\n getterState: null,\n proxiedBloc: instance,\n };\n}\n\n/**\n * Disable getter tracking after render phase completes.\n * Clears the active tracker to prevent tracking outside of render.\n * @param adapterState - The adapter state\n * @param rawInstance - The raw bloc instance\n */\nexport function disableGetterTracking<TBloc extends StateContainerConstructor>(\n adapterState: AdapterState<TBloc>,\n rawInstance: InstanceState<TBloc>,\n): void {\n if (adapterState.getterState) {\n adapterState.getterState.isTracking = false;\n clearActiveTracker(rawInstance);\n commitTrackedGetters(adapterState.getterState);\n }\n}\n"],"mappings":";;;;;;;;;AAwGA,IAAa,sBAAb,MAAiC;;iBACb,IAAI,mBAAmB;;;;;;;;;;CAUzC,oBACE,aACA,aACA,gBACS;AACT,MAAI,CAAC,YACH,QAAO;EAGT,MAAM,cAAc,oBAAoB,YAAY;EAEpD,MAAM,yBAAyB;AAC7B,yBAAsB,YAAY;AAElC,OAAI,iBAAiB,aAAa,YAAY,CAC5C,iBAAgB;;AAIpB,SAAO,KAAK,QAAQ,KAAK,aAAa,kBAAkB,YAAY;;;;;CAMtE,UAAgB;AACd,OAAK,QAAQ,SAAS;;;;;;;;;;AAa1B,SAAgB,mBACd,UACA,cACmB;AACnB,SAAQ,aAAmC;AACzC,SAAO,SAAS,gBAAgB;GAC9B,MAAM,WACJ,aAAa,oBACZ,aAAa,kBAAkB,uBAA4B;GAE9D,MAAM,eAAe,SAAS,aAAa,SAAS,UAAU,OAAO;GACrE,MAAM,gBACJ,aAAa,eACb,aAAa,YAAY,eAAe,OAAO;GAEjD,MAAM,mBACJ,SAAS,UAAU,QACnB,OAAO,SAAS,UAAU,YAC1B,OAAO,SAAS,UAAU;AAE5B,OAAI,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,iBACtC;GAGF,IAAI,eAAe,qBAAqB,UAAU,SAAS,MAAM;AAEjE,OAAI,CAAC,gBAAgB,cACnB,gBAAe;AAGjB,OAAI,cAAc;AAChB,cAAU;AACV;;AAQF,OALsB,iBACpB,UACA,aAAa,YACd,CAGC,WAAU;IAEZ;;;;;;;;;;;AAYN,SAAgB,oBACd,UACA,cACA,QACmB;AACnB,SAAQ,aAAmC;AACzC,SAAO,SAAS,gBAAgB;GAC9B,MAAM,UAAU,OAAO,aAAa,SAAS,OAAO,SAAS;AAC7D,OACE,CAAC,aAAa,mBACd,CAAC,aAAa,aAAa,iBAAiB,QAAQ,EACpD;AACA,iBAAa,kBAAkB;AAC/B,cAAU;;IAEZ;;;;;;;;;AAUN,SAAgB,iBACd,UACmB;AACnB,SAAQ,aAAmC,SAAS,UAAU,SAAS;;;;;;;;;AAUzE,SAAgB,kBACd,UACA,cACuC;AACvC,cAAa;EACX,MAAM,WACJ,aAAa,oBACZ,aAAa,kBAAkB,uBAA4B;AAE9D,MAAI,eAAe,SAAS,CAC1B,cAAa,UAAU,SAAS,MAAM;AAGxC,MAAI,aAAa,aAAa;AAC5B,yBAAsB,aAAa,YAAY;AAE/C,wBAAqB,aAAa,YAAY;AAE9C,gBAAa,YAAY,aAAa;AAEtC,oBAAiB,UAAU,aAAa,YAAY;;AAGtD,kBAAgB,SAAS;AACzB,SAAO,sBAAsB,UAAU,SAAS,MAAM;;;;;;;;;;;AAY1D,SAAgB,mBACd,UACA,cACA,QACuC;AACvC,cAAa;AACX,eAAa,kBAAkB,OAAO,aACpC,SAAS,OACT,SACD;AACD,SAAO,SAAS;;;;;;;;;AAUpB,SAAgB,gBACd,UACuC;AACvC,cAAa,SAAS;;;;;;;;AASxB,SAAgB,cACd,UACqB;AACrB,QAAO;EACL,iBAAiB;EACjB,iBAAiB;EACjB,aAAa,mBAAmB;EAChC,aAAa,gBAAgB,SAAS;EACvC;;;;;;;;AASH,SAAgB,eACd,UACqB;AACrB,QAAO;EACL,iBAAiB;EACjB,iBAAiB;EACjB,aAAa;EACb,aAAa;EACd;;;;;;;;AASH,SAAgB,YACd,UACqB;AACrB,QAAO;EACL,iBAAiB;EACjB,iBAAiB;EACjB,aAAa;EACb,aAAa;EACd;;;;;;;;AASH,SAAgB,sBACd,cACA,aACM;AACN,KAAI,aAAa,aAAa;AAC5B,eAAa,YAAY,aAAa;AACtC,qBAAmB,YAAY;AAC/B,uBAAqB,aAAa,YAAY"} | ||
| {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @blac/adapter - Framework Adapter\n *\n * Reusable utilities for integrating BlaC with any reactive framework.\n * Provides subscription and snapshot functions for different tracking modes.\n *\n * This package provides the building blocks for React, Preact, Vue, and other\n * framework integrations.\n */\nimport type {\n DependencyState,\n GetterState,\n ExtractState,\n InstanceReadonlyState,\n InstanceState,\n StateContainerConstructor,\n StateContainerInstance,\n} from '@blac/core';\n\nimport {\n acquire,\n release,\n isIsolatedClass,\n generateIsolatedKey,\n createDependencyState,\n startDependency,\n createDependencyProxy,\n capturePaths,\n hasDependencyChanges,\n hasTrackedData,\n shallowEqual,\n createGetterState,\n createBlocProxy,\n hasGetterChanges,\n setActiveTracker,\n clearActiveTracker,\n commitTrackedGetters,\n invalidateRenderCache,\n resolveDependencies,\n DependencyManager,\n} from '@blac/core';\n\nexport type {\n ExtractState,\n InstanceReadonlyState,\n InstanceState,\n StateContainerConstructor,\n StateContainerInstance,\n} from '@blac/core';\n\nexport {\n acquire,\n release,\n isIsolatedClass,\n generateIsolatedKey,\n} from '@blac/core';\n\n/**\n * Internal state for framework adapters, holding tracking and caching data.\n * @template TBloc - The state container type\n */\nexport interface AdapterState<TBloc extends StateContainerConstructor> {\n /** Dependency tracker for state property access tracking */\n dependencyState: DependencyState<ExtractState<TBloc>> | null;\n /** Cached manual dependencies for comparison */\n manualDepsCache: unknown[] | null;\n /** Getter state for computed property tracking */\n getterState: GetterState | null;\n /** Proxied bloc instance for auto-tracking */\n proxiedBloc: InstanceState<TBloc> | null;\n}\n\n/**\n * Configuration for manual dependency tracking mode\n * @template TBloc - The state container type\n */\nexport interface ManualDepsConfig<TBloc extends StateContainerConstructor> {\n /** Function that returns dependency array from state and bloc */\n dependencies: (\n state: ExtractState<TBloc>,\n bloc: InstanceState<TBloc>,\n ) => any[];\n}\n\n/**\n * Callback function invoked when subscribed state changes\n */\nexport type SubscriptionCallback = () => void;\n\n/**\n * Function that subscribes to state changes and returns an unsubscribe function\n */\nexport type SubscribeFunction = (callback: SubscriptionCallback) => () => void;\n\n/**\n * Function that returns a snapshot of the current state\n * @template TState - The state type\n */\nexport type SnapshotFunction<TState> = () => TState;\n\n/**\n * Manages subscriptions to external bloc dependencies for getter tracking.\n * When a getter accesses another bloc's state, this manager ensures\n * re-renders occur when those external dependencies change.\n */\nexport class ExternalDepsManager {\n private manager = new DependencyManager();\n private cachedDeps: Set<StateContainerInstance> | null = null;\n\n private resolveCached(\n rawInstance: StateContainerInstance,\n ): Set<StateContainerInstance> {\n if (this.cachedDeps) {\n let allValid = true;\n for (const dep of this.cachedDeps) {\n if (dep.isDisposed) {\n allValid = false;\n break;\n }\n }\n if (allValid) return this.cachedDeps;\n }\n this.cachedDeps = resolveDependencies(rawInstance);\n return this.cachedDeps;\n }\n\n /**\n * Update subscriptions to external bloc dependencies.\n * Resolves transitive dependencies via depend() declarations.\n * @param getterState - The getter tracker state (needed for change detection)\n * @param rawInstance - The primary bloc instance (excluded from subscriptions)\n * @param onGetterChange - Callback to invoke when external dependency changes\n * @returns true if subscriptions were updated, false if unchanged\n */\n updateSubscriptions(\n getterState: GetterState | null,\n rawInstance: StateContainerInstance,\n onGetterChange: () => void,\n ): boolean {\n if (!getterState || rawInstance.dependencies.size === 0) {\n return false;\n }\n\n const currentDeps = this.resolveCached(rawInstance);\n\n const onExternalChange = () => {\n invalidateRenderCache(getterState);\n\n if (hasGetterChanges(rawInstance, getterState)) {\n onGetterChange();\n }\n };\n\n return this.manager.sync(currentDeps, onExternalChange, rawInstance);\n }\n\n /**\n * Clean up all active subscriptions\n */\n cleanup(): void {\n this.manager.cleanup();\n this.cachedDeps = null;\n }\n}\n\nexport { DependencyManager };\n\n/**\n * Create a subscribe function for auto-tracking mode.\n * Only triggers callback when tracked properties change.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for tracking\n * @returns Subscribe function for use with useSyncExternalStore\n */\nexport function autoTrackSubscribe<TBloc extends StateContainerConstructor>(\n instance: InstanceReadonlyState<TBloc>,\n adapterState: AdapterState<TBloc>,\n): SubscribeFunction {\n return (callback: SubscriptionCallback) => {\n return instance.subscribe(() => {\n const depState =\n adapterState.dependencyState ||\n (adapterState.dependencyState = createDependencyState<any>());\n\n const hasStateDeps = depState.pathCache && depState.pathCache.size > 0;\n const hasGetterDeps =\n adapterState.getterState &&\n adapterState.getterState.trackedGetters.size > 0;\n\n const isPrimitiveState =\n instance.state !== null &&\n typeof instance.state !== 'object' &&\n typeof instance.state !== 'function';\n\n if (!hasStateDeps && !hasGetterDeps && !isPrimitiveState) {\n return;\n }\n\n let stateChanged = hasDependencyChanges(depState, instance.state);\n\n if (!hasStateDeps && hasGetterDeps) {\n stateChanged = false;\n }\n\n if (stateChanged) {\n callback();\n return;\n }\n\n const getterChanged = hasGetterChanges(\n instance,\n adapterState.getterState,\n );\n\n if (getterChanged) {\n callback();\n }\n });\n };\n}\n\n/**\n * Create a subscribe function for manual dependency tracking mode.\n * Only triggers callback when dependencies array changes.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for caching\n * @param config - Configuration with dependencies function\n * @returns Subscribe function for use with useSyncExternalStore\n */\nexport function manualDepsSubscribe<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n adapterState: AdapterState<TBloc>,\n config: ManualDepsConfig<TBloc>,\n): SubscribeFunction {\n return (callback: SubscriptionCallback) => {\n return instance.subscribe(() => {\n const newDeps = config.dependencies(instance.state, instance);\n if (\n !adapterState.manualDepsCache ||\n !shallowEqual(adapterState.manualDepsCache, newDeps)\n ) {\n adapterState.manualDepsCache = newDeps;\n callback();\n }\n });\n };\n}\n\n/**\n * Create a subscribe function for no-tracking mode.\n * Triggers callback on every state change.\n * @param instance - The state container instance\n * @returns Subscribe function for use with useSyncExternalStore\n */\nexport function noTrackSubscribe<TBloc extends StateContainerInstance>(\n instance: TBloc,\n): SubscribeFunction {\n return (callback: SubscriptionCallback) => instance.subscribe(callback);\n}\n\n/**\n * Create a snapshot function for auto-tracking mode.\n * Returns a proxied state that tracks property access.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for tracking\n * @returns Snapshot function for use with useSyncExternalStore\n */\nexport function autoTrackSnapshot<TBloc extends StateContainerConstructor>(\n instance: InstanceReadonlyState<TBloc>,\n adapterState: AdapterState<TBloc>,\n): SnapshotFunction<ExtractState<TBloc>> {\n return () => {\n const depState =\n adapterState.dependencyState ||\n (adapterState.dependencyState = createDependencyState<any>());\n\n if (hasTrackedData(depState)) {\n capturePaths(depState, instance.state);\n }\n\n if (adapterState.getterState) {\n invalidateRenderCache(adapterState.getterState);\n\n commitTrackedGetters(adapterState.getterState);\n\n adapterState.getterState.isTracking = true;\n\n setActiveTracker(instance, adapterState.getterState);\n }\n\n startDependency(depState);\n return createDependencyProxy(depState, instance.state);\n };\n}\n\n/**\n * Create a snapshot function for manual dependency tracking mode.\n * Caches dependencies for comparison on next render.\n * @param instance - The state container instance\n * @param adapterState - The adapter state for caching\n * @param config - Configuration with dependencies function\n * @returns Snapshot function for use with useSyncExternalStore\n */\nexport function manualDepsSnapshot<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n adapterState: AdapterState<TBloc>,\n config: ManualDepsConfig<TBloc>,\n): SnapshotFunction<ExtractState<TBloc>> {\n return () => {\n adapterState.manualDepsCache = config.dependencies(\n instance.state,\n instance,\n );\n return instance.state;\n };\n}\n\n/**\n * Create a snapshot function for no-tracking mode.\n * Returns the raw state directly.\n * @param instance - The state container instance\n * @returns Snapshot function for use with useSyncExternalStore\n */\nexport function noTrackSnapshot<TBloc extends StateContainerConstructor>(\n instance: InstanceReadonlyState<TBloc>,\n): SnapshotFunction<ExtractState<TBloc>> {\n return () => instance.state;\n}\n\n/**\n * Initialize adapter state for auto-tracking mode.\n * Creates getter tracker and proxied bloc instance.\n * @param instance - The state container instance\n * @returns Initialized adapter state\n */\nexport function autoTrackInit<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n): AdapterState<TBloc> {\n return {\n dependencyState: null,\n manualDepsCache: null,\n getterState: createGetterState(),\n proxiedBloc: createBlocProxy(instance),\n };\n}\n\n/**\n * Initialize adapter state for manual dependency tracking mode.\n * No proxy is created; bloc is used directly.\n * @param instance - The state container instance\n * @returns Initialized adapter state\n */\nexport function manualDepsInit<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n): AdapterState<TBloc> {\n return {\n dependencyState: null,\n manualDepsCache: null,\n getterState: null,\n proxiedBloc: instance,\n };\n}\n\n/**\n * Initialize adapter state for no-tracking mode.\n * No tracking or proxy is created.\n * @param instance - The state container instance\n * @returns Initialized adapter state\n */\nexport function noTrackInit<TBloc extends StateContainerConstructor>(\n instance: InstanceState<TBloc>,\n): AdapterState<TBloc> {\n return {\n dependencyState: null,\n manualDepsCache: null,\n getterState: null,\n proxiedBloc: instance,\n };\n}\n\n/**\n * Disable getter tracking after render phase completes.\n * Clears the active tracker to prevent tracking outside of render.\n * @param adapterState - The adapter state\n * @param rawInstance - The raw bloc instance\n */\nexport function disableGetterTracking<TBloc extends StateContainerConstructor>(\n adapterState: AdapterState<TBloc>,\n rawInstance: InstanceState<TBloc>,\n): void {\n if (adapterState.getterState) {\n adapterState.getterState.isTracking = false;\n clearActiveTracker(rawInstance);\n commitTrackedGetters(adapterState.getterState);\n }\n}\n"],"mappings":"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"} |
+6
-11
| { | ||
| "name": "@blac/adapter", | ||
| "version": "2.0.4", | ||
| "version": "2.0.5", | ||
| "license": "MIT", | ||
@@ -31,7 +31,3 @@ "author": "Brendan Mullins <jsnanigans@gmail.com>", | ||
| "files": [ | ||
| "dist/index.js", | ||
| "dist/index.cjs", | ||
| "dist/index.d.ts", | ||
| "dist/index.d.cts", | ||
| "dist/*.map", | ||
| "dist", | ||
| "README.md", | ||
@@ -48,3 +44,3 @@ "LICENSE" | ||
| "dependencies": { | ||
| "@blac/core": "2.0.4" | ||
| "@blac/core": "2.0.5" | ||
| }, | ||
@@ -56,2 +52,3 @@ "devDependencies": { | ||
| "typescript": "^5.9.2", | ||
| "publint": "^0.3.12", | ||
| "vitest": "3.2.4" | ||
@@ -61,6 +58,3 @@ }, | ||
| "dev": "tsdown --watch", | ||
| "build": "pnpm build:js && pnpm build:types && pnpm build:dts", | ||
| "build:js": "tsdown", | ||
| "build:types": "tsc -p tsconfig.build.json", | ||
| "build:dts": "api-extractor run --local && cp dist/index.d.ts dist/index.d.cts && rm -rf dist/.types", | ||
| "build": "tsdown && tsc -p tsconfig.build.json && cp dist/index.d.ts dist/index.d.cts", | ||
| "clean": "rm -rf dist", | ||
@@ -72,2 +66,3 @@ "format": "prettier --write \".\"", | ||
| "test:watch": "vitest --watch", | ||
| "verify": "publint", | ||
| "typecheck": "tsc --noEmit", | ||
@@ -74,0 +69,0 @@ "deploy": "pnpm publish --access public" |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
62136
1.67%591
3.32%6
20%+ Added
- Removed
Updated