@embedpdf/core 1.0.20 → 1.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/plugin/builder.d.ts +11 -0
- package/dist/lib/types/plugin.d.ts +19 -0
- package/dist/preact/adapter.d.ts +2 -1
- package/dist/preact/index.cjs +1 -1
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.js +41 -64
- package/dist/preact/index.js.map +1 -1
- package/dist/react/adapter.d.ts +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +41 -64
- package/dist/react/index.js.map +1 -1
- package/dist/shared-preact/components/auto-mount.d.ts +8 -0
- package/dist/shared-preact/components/embed-pdf.d.ts +21 -1
- package/dist/shared-preact/components/index.d.ts +0 -1
- package/dist/shared-react/components/auto-mount.d.ts +8 -0
- package/dist/shared-react/components/embed-pdf.d.ts +21 -1
- package/dist/shared-react/components/index.d.ts +0 -1
- package/dist/vue/components/auto-mount.vue.d.ts +18 -0
- package/dist/vue/components/embed-pdf.vue.d.ts +15 -6
- package/dist/vue/components/nested-wrapper.vue.d.ts +17 -0
- package/dist/vue/index.cjs +1 -1
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.js +88 -4
- package/dist/vue/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/shared-preact/components/counter-rotate-container.d.ts +0 -33
- package/dist/shared-react/components/counter-rotate-container.d.ts +0 -33
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@embedpdf/models");class e{constructor(){this.dependencyGraph=new Map}addNode(t,e=[]){this.dependencyGraph.set(t,new Set(e))}hasCircularDependencies(){const t=new Set,e=new Set,i=s=>{t.add(s),e.add(s);const r=this.dependencyGraph.get(s)||new Set;for(const n of r)if(t.has(n)){if(e.has(n))return!0}else if(i(n))return!0;return e.delete(s),!1};for(const s of this.dependencyGraph.keys())if(!t.has(s)&&i(s))return!0;return!1}resolveLoadOrder(){if(this.hasCircularDependencies())throw new Error("Circular dependencies detected");const t=[],e=new Set,i=new Set,s=r=>{if(i.has(r))throw new Error("Circular dependency");if(e.has(r))return;i.add(r);const n=this.dependencyGraph.get(r)||new Set;for(const t of n)s(t);i.delete(r),e.add(r),t.push(r)};for(const r of this.dependencyGraph.keys())e.has(r)||s(r);return t}}class i extends Error{constructor(t){super(t),this.name="PluginRegistrationError"}}class s extends Error{constructor(t){super(t),this.name="PluginNotFoundError"}}class r extends Error{constructor(t){super(t),this.name="CircularDependencyError"}}class n extends Error{constructor(t){super(t),this.name="CapabilityNotFoundError"}}class o extends Error{constructor(t){super(t),this.name="CapabilityConflictError"}}class a extends Error{constructor(t){super(t),this.name="PluginInitializationError"}}class l extends Error{constructor(t){super(t),this.name="PluginConfigurationError"}}class u{constructor(t,e){this.store=t,this.pluginId=e}getState(){return this.store.getState().plugins[this.pluginId]}dispatch(t){return this.store.dispatchToPlugin(this.pluginId,t)}subscribeToState(t){return this.store.subscribeToPlugin(this.pluginId,((e,i,s)=>{t(e,i,s)}))}onAction(t,e){return this.store.onAction(t,((t,i,s)=>{e(t,i.plugins[this.pluginId],s.plugins[this.pluginId])}))}}const h="LOAD_DOCUMENT",c="REFRESH_DOCUMENT",d="REFRESH_PAGES",g="SET_DOCUMENT",p="SET_DOCUMENT_ERROR",f="SET_SCALE",y="SET_ROTATION",w="SET_PAGES",m=[h,c,g,p,f,y,w];class S{constructor(t,e){this.initialCoreState=e,this.pluginReducers={},this.listeners=[],this.pluginListeners={},this.state={core:e,plugins:{}},this.coreReducer=t}addPluginReducer(t,e,i){this.state.plugins[t]=i,this.pluginReducers[t]=e}dispatchToCore(t){if(!this.coreReducer)return this.getState();const e=this.getState();this.state.core=this.coreReducer(this.state.core,t);const i=this.getState();return this.listeners.forEach((s=>s(t,i,e))),i}dispatchToPlugin(t,e,i=!0){const s=this.getState(),r=this.pluginReducers[t];if(!r)return s;const n=s.plugins[t],o=r(n,e);this.state.plugins[t]=o;const a=this.getState();return i&&this.listeners.forEach((t=>t(e,a,s))),this.pluginListeners[t]&&this.pluginListeners[t].forEach((t=>{t(e,o,n)})),o}dispatch(t){const e=this.getState();this.isCoreAction(t)&&(this.state.core=this.coreReducer(this.state.core,t));for(const s in this.pluginReducers){const i=this.pluginReducers[s],r=e.plugins[s];i&&(this.state.plugins[s]=i(r,t))}const i=this.getState();return this.listeners.forEach((s=>s(t,i,e))),i}getState(){return{core:{...this.state.core},plugins:{...this.state.plugins}}}subscribe(t){return this.listeners.push(t),()=>{this.listeners=this.listeners.filter((e=>e!==t))}}subscribeToPlugin(t,e){if(!(t in this.state.plugins))throw new Error(`Plugin state not found for plugin "${t}". Did you forget to call addPluginReducer?`);return this.pluginListeners[t]||(this.pluginListeners[t]=[]),this.pluginListeners[t].push(e),()=>{this.pluginListeners[t]=this.pluginListeners[t].filter((t=>t!==e)),0===this.pluginListeners[t].length&&delete this.pluginListeners[t]}}onAction(t,e){return this.subscribe(((i,s,r)=>{i.type===t&&e(i,s,r)}))}getPluginStore(t){if(!(t in this.state.plugins))throw new Error(`Plugin state not found for plugin "${t}". Did you forget to call addPluginReducer?`);return new u(this,t)}isCoreAction(t){return m.includes(t.type)}destroy(){var t,e;this.listeners.length=0;for(const i in this.pluginListeners)null==(e=null==(t=this.pluginListeners[i])?void 0:t.splice)||e.call(t,0);this.pluginListeners={},this.pluginReducers={},this.state.plugins={},this.state.core={...this.initialCoreState}}}const b=e=>({scale:(null==e?void 0:e.scale)??1,rotation:(null==e?void 0:e.rotation)??t.Rotation.Degree0,document:null,pages:[],loading:!1,error:null}),E=(t,e)=>{switch(e.type){case h:return{...t,loading:!0,error:null};case g:case c:return{...t,document:e.payload,pages:e.payload.pages.map((t=>[t])),loading:!1,error:null};case y:return{...t,rotation:e.payload};case w:return{...t,pages:e.payload};case p:return{...t,loading:!1,error:e.payload};case f:return{...t,scale:e.payload};default:return t}};class P{constructor(t,e){this.handler=t,this.options=e,this.lastRun=0,this.handle=t=>{"debounce"===this.options.mode?this.debounce(t):this.throttle(t)}}debounce(t){this.timeoutId&&window.clearTimeout(this.timeoutId),this.timeoutId=window.setTimeout((()=>{this.handler(t),this.timeoutId=void 0}),this.options.wait)}throttle(t){if("debounce"===this.options.mode)return;const e=Date.now(),i=this.options.throttleMode||"leading-trailing";e-this.lastRun>=this.options.wait&&("leading-trailing"===i&&this.handler(t),this.lastRun=e),this.timeoutId&&window.clearTimeout(this.timeoutId),this.timeoutId=window.setTimeout((()=>{this.handler(t),this.lastRun=Date.now(),this.timeoutId=void 0}),this.options.wait-(e-this.lastRun))}destroy(){this.timeoutId&&window.clearTimeout(this.timeoutId)}}function R(t,e,i){if(t===e)return!0;if(null==t||null==e)return t===e;const s=typeof t;if(s!==typeof e)return!1;if("object"===s){i||(i=new Set);const s=function(t,e){return`${x(t)}__${x(e)}`}(t,e);if(i.has(s))return!0;i.add(s);const r=Array.isArray(t),n=Array.isArray(e);return r&&n?function(t,e,i){if(t.length!==e.length)return!1;const s=new Array(e.length).fill(!1);t:for(let r=0;r<t.length;r++){const n=t[r];for(let t=0;t<e.length;t++)if(!s[t]&&R(n,e[t],i)){s[t]=!0;continue t}return!1}return!0}(t,e,i):!r&&!n&&function(t,e,i){const s=Object.keys(t).sort(),r=Object.keys(e).sort();if(s.length!==r.length)return!1;for(let n=0;n<s.length;n++)if(s[n]!==r[n])return!1;for(const n of s){if(!R(t[n],e[n],i))return!1}return!0}(t,e,i)}return!1}let v=0;const C=new WeakMap;function x(t){return C.has(t)||C.set(t,++v),C.get(t)}exports.BasePlugin=class{constructor(t,e){if(this.id=t,this.registry=e,this.debouncedActions={},this.unsubscribeFromState=null,this.unsubscribeFromCoreStore=null,t!==this.constructor.id)throw new Error(`Plugin ID mismatch: ${t} !== ${this.constructor.id}`);this.engine=this.registry.getEngine(),this.logger=this.registry.getLogger(),this.coreStore=this.registry.getStore(),this.pluginStore=this.coreStore.getPluginStore(this.id),this.unsubscribeFromState=this.pluginStore.subscribeToState(((t,e,i)=>{this.onStoreUpdated(i,e)})),this.unsubscribeFromCoreStore=this.coreStore.subscribe(((t,e,i)=>{this.onCoreStoreUpdated(i,e)})),this.readyPromise=new Promise((t=>{this.readyResolve=t})),this.readyResolve()}provides(){if(!this._capability){const t=this.buildCapability();this._capability=Object.freeze(t)}return this._capability}get state(){return this.pluginStore.getState()}get coreState(){return this.coreStore.getState()}getState(){return this.pluginStore.getState()}getCoreState(){return this.coreStore.getState()}dispatchCoreAction(t){return this.coreStore.dispatchToCore(t)}dispatchToAllPlugins(t){return this.coreStore.dispatch(t)}dispatch(t){return this.pluginStore.dispatch(t)}debouncedDispatch(t,e=100){const i=Date.now();return i-(this.debouncedActions[t.type]||0)>=e&&(this.debouncedActions[t.type]=i,this.dispatch(t),!0)}subscribe(t){return this.pluginStore.subscribeToState(t)}subscribeToCoreStore(t){return this.coreStore.subscribe(t)}onStoreUpdated(t,e){}onCoreStoreUpdated(t,e){}destroy(){this.unsubscribeFromState&&(this.unsubscribeFromState(),this.unsubscribeFromState=null),this.unsubscribeFromCoreStore&&(this.unsubscribeFromCoreStore(),this.unsubscribeFromCoreStore=null)}ready(){return this.readyPromise}markReady(){this.readyResolve()}resetReady(){this.readyPromise=new Promise((t=>{this.readyResolve=t}))}},exports.CORE_ACTION_TYPES=m,exports.CapabilityConflictError=o,exports.CapabilityNotFoundError=n,exports.CircularDependencyError=r,exports.DependencyResolver=e,exports.EventControl=P,exports.LOAD_DOCUMENT=h,exports.PluginConfigurationError=l,exports.PluginInitializationError=a,exports.PluginNotFoundError=s,exports.PluginRegistrationError=i,exports.PluginRegistry=class{constructor(i,s){this.plugins=new Map,this.manifests=new Map,this.capabilities=new Map,this.status=new Map,this.configurations=new Map,this.engineInitialized=!1,this.initPromise=null,this.pendingRegistrations=[],this.processingRegistrations=[],this.initialized=!1,this.isInitializing=!1,this.pluginsReadyPromise=null,this.destroyed=!1,this.resolver=new e,this.engine=i,this.initialCoreState=b(s),this.store=new S(E,this.initialCoreState),this.logger=(null==s?void 0:s.logger)??new t.NoopLogger}getLogger(){return this.logger}async ensureEngineInitialized(){if(!this.engineInitialized)if(this.engine.initialize){const t=this.engine.initialize();await t.toPromise(),this.engineInitialized=!0}else this.engineInitialized=!0}registerPlugin(t,e){if(this.initialized&&!this.isInitializing)throw new i("Cannot register plugins after initialization");this.validateManifest(t.manifest),this.store.addPluginReducer(t.manifest.id,t.reducer,"function"==typeof t.initialState?t.initialState(this.initialCoreState,{...t.manifest.defaultConfig,...e}):t.initialState),this.pendingRegistrations.push({package:t,config:e})}getStore(){return this.store}getEngine(){return this.engine}pluginsReady(){return this.pluginsReadyPromise||(this.pluginsReadyPromise=(async()=>{this.initialized||await this.initialize();const t=Array.from(this.plugins.values()).map((t=>"function"==typeof t.ready?t.ready():Promise.resolve()));await Promise.all(t)})()),this.pluginsReadyPromise}async initialize(){if(this.destroyed)throw new i("Registry has been destroyed");return this.initPromise||(this.initPromise=(async()=>{var t;if(this.initialized)throw new i("Registry is already initialized");this.isInitializing=!0;try{if(await this.ensureEngineInitialized(),this.destroyed)return;for(;this.pendingRegistrations.length>0;){if(this.destroyed)return;this.processingRegistrations=[...this.pendingRegistrations],this.pendingRegistrations=[];for(const e of this.processingRegistrations){const t=new Set,i=[...e.package.manifest.requires,...e.package.manifest.optional];for(const e of i){const i=this.processingRegistrations.find((t=>t.package.manifest.provides.includes(e)));i&&t.add(i.package.manifest.id)}this.resolver.addNode(e.package.manifest.id,[...t])}const t=this.resolver.resolveLoadOrder();for(const e of t){const t=this.processingRegistrations.find((t=>t.package.manifest.id===e));await this.initializePlugin(t.package.manifest,t.package.create,t.config)}this.processingRegistrations=[],this.resolver=new e}for(const e of this.plugins.values())await(null==(t=e.postInitialize)?void 0:t.call(e).catch((t=>{console.error(`Error in postInitialize for plugin ${e.id}`,t),this.status.set(e.id,"error")})));this.initialized=!0}catch(s){if(s instanceof Error)throw new r(`Failed to resolve plugin dependencies: ${s.message}`);throw s}finally{this.isInitializing=!1}})()),this.initPromise}async initializePlugin(t,e,s){const r={...t.defaultConfig,...s};this.validateConfig(t.id,r,t.defaultConfig);const n=e(this,r);this.validatePlugin(n);for(const a of t.requires)if(!this.capabilities.has(a))throw new i(`Missing required capability: ${a} for plugin ${t.id}`);for(const i of t.optional)this.capabilities.has(i)&&this.logger.debug("PluginRegistry","OptionalCapability",`Optional capability ${i} is available for plugin ${t.id}`);this.logger.debug("PluginRegistry","InitializePlugin",`Initializing plugin ${t.id}`,{provides:t.provides});for(const a of t.provides){if(this.capabilities.has(a))throw new i(`Capability ${a} is already provided by plugin ${this.capabilities.get(a)}`);this.capabilities.set(a,t.id)}this.plugins.set(t.id,n),this.manifests.set(t.id,t),this.status.set(t.id,"registered"),this.configurations.set(t.id,r);try{n.initialize&&await n.initialize(r),this.status.set(t.id,"active"),this.logger.info("PluginRegistry","PluginInitialized",`Plugin ${t.id} initialized successfully`)}catch(o){throw this.plugins.delete(t.id),this.manifests.delete(t.id),this.logger.error("PluginRegistry","InitializationFailed",`Plugin ${t.id} initialization failed`,{provides:t.provides,error:o}),t.provides.forEach((t=>this.capabilities.delete(t))),o}}getPluginConfig(t){const e=this.configurations.get(t);if(!e)throw new s(`Configuration for plugin ${t} not found`);return e}validateConfig(t,e,i){const s=Object.keys(i).filter((t=>!e.hasOwnProperty(t)));if(s.length>0)throw new l(`Missing required configuration keys for plugin ${t}: ${s.join(", ")}`)}async updatePluginConfig(t,e){const i=this.getPlugin(t);if(!i)throw new s(`Plugin ${t} not found`);const r=this.manifests.get(t),n=this.configurations.get(t);if(!r||!n)throw new s(`Plugin ${t} not found`);const o={...n,...e};this.validateConfig(t,o,r.defaultConfig),this.configurations.set(t,o),i.initialize&&await i.initialize(o)}registerPluginBatch(t){for(const e of t)this.registerPlugin(e.package,e.config)}async unregisterPlugin(t){const e=this.plugins.get(t);if(!e)throw new s(`Plugin ${t} is not registered`);const r=this.manifests.get(t);if(!r)throw new s(`Manifest for plugin ${t} not found`);for(const[s,o]of this.manifests.entries()){if(s===t)continue;if([...o.requires,...o.optional].some((t=>r.provides.includes(t))))throw new i(`Cannot unregister plugin ${t}: plugin ${s} depends on it`)}try{e.destroy&&await e.destroy();for(const t of r.provides)this.capabilities.delete(t);this.plugins.delete(t),this.manifests.delete(t),this.status.delete(t)}catch(n){if(n instanceof Error)throw new Error(`Failed to unregister plugin ${t}: ${n.message}`);throw n}}getPlugin(t){const e=this.plugins.get(t);return e||null}getCapabilityProvider(t){const e=this.capabilities.get(t);return e?this.getPlugin(e):null}hasCapability(t){return this.capabilities.has(t)}getAllPlugins(){return Array.from(this.plugins.values())}getPluginStatus(t){const e=this.status.get(t);if(!e)throw new s(`Plugin ${t} not found`);return e}validatePlugin(t){if(!t.id)throw new i("Plugin must have an id")}validateManifest(t){if(!t.id)throw new i("Manifest must have an id");if(!t.name)throw new i("Manifest must have a name");if(!t.version)throw new i("Manifest must have a version");if(!Array.isArray(t.provides))throw new i("Manifest must have a provides array");if(!Array.isArray(t.requires))throw new i("Manifest must have a requires array");if(!Array.isArray(t.optional))throw new i("Manifest must have an optional array")}isDestroyed(){return this.destroyed}async destroy(){var t;if(this.destroyed)throw new i("Registry has already been destroyed");this.destroyed=!0;try{await this.initPromise}catch{}for(const e of Array.from(this.plugins.values()).reverse())await(null==(t=e.destroy)?void 0:t.call(e));this.store.destroy(),this.plugins.clear(),this.manifests.clear(),this.capabilities.clear(),this.status.clear(),this.pendingRegistrations.length=0,this.processingRegistrations.length=0}},exports.REFRESH_DOCUMENT=c,exports.REFRESH_PAGES=d,exports.SET_DOCUMENT=g,exports.SET_DOCUMENT_ERROR=p,exports.SET_PAGES=w,exports.SET_ROTATION=y,exports.SET_SCALE=f,exports.arePropsEqual=R,exports.clamp=function(t,e,i){return t<e?e:t>i?i:t},exports.createBehaviorEmitter=function(t,e=R){const i=new Set,s=new Map;let r=t;const n=(t,e)=>{let n=t,o=()=>{};if(e){const i=new P(t,e);n=i.handle,o=()=>i.destroy(),s.set(t,{wrapped:n,destroy:o})}return void 0!==r&&n(r),i.add(n),()=>{i.delete(n),o(),s.delete(t)}};return{get value(){return r},emit(t=void 0){void 0!==r&&e(r,t)||(r=t,(t=>{i.forEach((e=>e(t)))})(t))},on:n,off(t){const e=s.get(t);e?(i.delete(e.wrapped),e.destroy(),s.delete(t)):i.delete(t)},clear(){i.clear(),s.forEach((t=>t.destroy())),s.clear()},select:(t,e=R)=>(i,s)=>{let o;if(void 0!==r){const e=t(r);o=e,i(e)}return n((s=>{const r=t(s);void 0!==o&&e(o,r)||(o=r,i(r))}),s)}}},exports.createEmitter=function(){const t=new Set;return{emit:(e=void 0)=>t.forEach((t=>t(e))),on:e=>(t.add(e),()=>t.delete(e)),off:e=>t.delete(e),clear:()=>t.clear()}},exports.createPluginRegistration=function(t,e){return{package:t,config:e}},exports.enumEntries=function(t){return Object.entries(t).map((([t,e])=>{const i=Number(t);return[Number.isFinite(i)&&""!==t.trim()?i:t,e]}))},exports.getPagesWithRotatedSize=e=>e.pages.map((i=>i.map((i=>({...i,rotatedSize:t.transformSize(i.size,e.rotation,1)}))))),exports.initialCoreState=b,exports.loadDocument=()=>({type:h}),exports.refreshDocument=t=>({type:c,payload:t}),exports.refreshPages=t=>({type:d,payload:t}),exports.setDocument=t=>({type:g,payload:t}),exports.setDocumentError=t=>({type:p,payload:t}),exports.setPages=t=>({type:w,payload:t}),exports.setRotation=t=>({type:y,payload:t}),exports.setScale=t=>({type:f,payload:t});
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@embedpdf/models");class e{constructor(){this.dependencyGraph=new Map}addNode(t,e=[]){this.dependencyGraph.set(t,new Set(e))}hasCircularDependencies(){const t=new Set,e=new Set,i=s=>{t.add(s),e.add(s);const r=this.dependencyGraph.get(s)||new Set;for(const n of r)if(t.has(n)){if(e.has(n))return!0}else if(i(n))return!0;return e.delete(s),!1};for(const s of this.dependencyGraph.keys())if(!t.has(s)&&i(s))return!0;return!1}resolveLoadOrder(){if(this.hasCircularDependencies())throw new Error("Circular dependencies detected");const t=[],e=new Set,i=new Set,s=r=>{if(i.has(r))throw new Error("Circular dependency");if(e.has(r))return;i.add(r);const n=this.dependencyGraph.get(r)||new Set;for(const t of n)s(t);i.delete(r),e.add(r),t.push(r)};for(const r of this.dependencyGraph.keys())e.has(r)||s(r);return t}}class i extends Error{constructor(t){super(t),this.name="PluginRegistrationError"}}class s extends Error{constructor(t){super(t),this.name="PluginNotFoundError"}}class r extends Error{constructor(t){super(t),this.name="CircularDependencyError"}}class n extends Error{constructor(t){super(t),this.name="CapabilityNotFoundError"}}class o extends Error{constructor(t){super(t),this.name="CapabilityConflictError"}}class a extends Error{constructor(t){super(t),this.name="PluginInitializationError"}}class l extends Error{constructor(t){super(t),this.name="PluginConfigurationError"}}class u{constructor(t,e){this.store=t,this.pluginId=e}getState(){return this.store.getState().plugins[this.pluginId]}dispatch(t){return this.store.dispatchToPlugin(this.pluginId,t)}subscribeToState(t){return this.store.subscribeToPlugin(this.pluginId,((e,i,s)=>{t(e,i,s)}))}onAction(t,e){return this.store.onAction(t,((t,i,s)=>{e(t,i.plugins[this.pluginId],s.plugins[this.pluginId])}))}}const h="LOAD_DOCUMENT",c="REFRESH_DOCUMENT",d="REFRESH_PAGES",g="SET_DOCUMENT",p="SET_DOCUMENT_ERROR",f="SET_SCALE",y="SET_ROTATION",m="SET_PAGES",w=[h,c,g,p,f,y,m];class S{constructor(t,e){this.initialCoreState=e,this.pluginReducers={},this.listeners=[],this.pluginListeners={},this.state={core:e,plugins:{}},this.coreReducer=t}addPluginReducer(t,e,i){this.state.plugins[t]=i,this.pluginReducers[t]=e}dispatchToCore(t){if(!this.coreReducer)return this.getState();const e=this.getState();this.state.core=this.coreReducer(this.state.core,t);const i=this.getState();return this.listeners.forEach((s=>s(t,i,e))),i}dispatchToPlugin(t,e,i=!0){const s=this.getState(),r=this.pluginReducers[t];if(!r)return s;const n=s.plugins[t],o=r(n,e);this.state.plugins[t]=o;const a=this.getState();return i&&this.listeners.forEach((t=>t(e,a,s))),this.pluginListeners[t]&&this.pluginListeners[t].forEach((t=>{t(e,o,n)})),o}dispatch(t){const e=this.getState();this.isCoreAction(t)&&(this.state.core=this.coreReducer(this.state.core,t));for(const s in this.pluginReducers){const i=this.pluginReducers[s],r=e.plugins[s];i&&(this.state.plugins[s]=i(r,t))}const i=this.getState();return this.listeners.forEach((s=>s(t,i,e))),i}getState(){return{core:{...this.state.core},plugins:{...this.state.plugins}}}subscribe(t){return this.listeners.push(t),()=>{this.listeners=this.listeners.filter((e=>e!==t))}}subscribeToPlugin(t,e){if(!(t in this.state.plugins))throw new Error(`Plugin state not found for plugin "${t}". Did you forget to call addPluginReducer?`);return this.pluginListeners[t]||(this.pluginListeners[t]=[]),this.pluginListeners[t].push(e),()=>{this.pluginListeners[t]=this.pluginListeners[t].filter((t=>t!==e)),0===this.pluginListeners[t].length&&delete this.pluginListeners[t]}}onAction(t,e){return this.subscribe(((i,s,r)=>{i.type===t&&e(i,s,r)}))}getPluginStore(t){if(!(t in this.state.plugins))throw new Error(`Plugin state not found for plugin "${t}". Did you forget to call addPluginReducer?`);return new u(this,t)}isCoreAction(t){return w.includes(t.type)}destroy(){var t,e;this.listeners.length=0;for(const i in this.pluginListeners)null==(e=null==(t=this.pluginListeners[i])?void 0:t.splice)||e.call(t,0);this.pluginListeners={},this.pluginReducers={},this.state.plugins={},this.state.core={...this.initialCoreState}}}const b=e=>({scale:(null==e?void 0:e.scale)??1,rotation:(null==e?void 0:e.rotation)??t.Rotation.Degree0,document:null,pages:[],loading:!1,error:null}),E=(t,e)=>{switch(e.type){case h:return{...t,loading:!0,error:null};case g:case c:return{...t,document:e.payload,pages:e.payload.pages.map((t=>[t])),loading:!1,error:null};case y:return{...t,rotation:e.payload};case m:return{...t,pages:e.payload};case p:return{...t,loading:!1,error:e.payload};case f:return{...t,scale:e.payload};default:return t}};class P{constructor(t,e){this.handler=t,this.options=e,this.lastRun=0,this.handle=t=>{"debounce"===this.options.mode?this.debounce(t):this.throttle(t)}}debounce(t){this.timeoutId&&window.clearTimeout(this.timeoutId),this.timeoutId=window.setTimeout((()=>{this.handler(t),this.timeoutId=void 0}),this.options.wait)}throttle(t){if("debounce"===this.options.mode)return;const e=Date.now(),i=this.options.throttleMode||"leading-trailing";e-this.lastRun>=this.options.wait&&("leading-trailing"===i&&this.handler(t),this.lastRun=e),this.timeoutId&&window.clearTimeout(this.timeoutId),this.timeoutId=window.setTimeout((()=>{this.handler(t),this.lastRun=Date.now(),this.timeoutId=void 0}),this.options.wait-(e-this.lastRun))}destroy(){this.timeoutId&&window.clearTimeout(this.timeoutId)}}function R(t,e,i){if(t===e)return!0;if(null==t||null==e)return t===e;const s=typeof t;if(s!==typeof e)return!1;if("object"===s){i||(i=new Set);const s=function(t,e){return`${x(t)}__${x(e)}`}(t,e);if(i.has(s))return!0;i.add(s);const r=Array.isArray(t),n=Array.isArray(e);return r&&n?function(t,e,i){if(t.length!==e.length)return!1;const s=new Array(e.length).fill(!1);t:for(let r=0;r<t.length;r++){const n=t[r];for(let t=0;t<e.length;t++)if(!s[t]&&R(n,e[t],i)){s[t]=!0;continue t}return!1}return!0}(t,e,i):!r&&!n&&function(t,e,i){const s=Object.keys(t).sort(),r=Object.keys(e).sort();if(s.length!==r.length)return!1;for(let n=0;n<s.length;n++)if(s[n]!==r[n])return!1;for(const n of s){if(!R(t[n],e[n],i))return!1}return!0}(t,e,i)}return!1}let v=0;const C=new WeakMap;function x(t){return C.has(t)||C.set(t,++v),C.get(t)}class z{constructor(t){this.autoMountElements=[],this.package=t}addUtility(t){return this.autoMountElements.push({component:t,type:"utility"}),this}addWrapper(t){return this.autoMountElements.push({component:t,type:"wrapper"}),this}build(){return{...this.package,autoMountElements:()=>this.autoMountElements}}}exports.BasePlugin=class{constructor(t,e){if(this.id=t,this.registry=e,this.debouncedActions={},this.unsubscribeFromState=null,this.unsubscribeFromCoreStore=null,t!==this.constructor.id)throw new Error(`Plugin ID mismatch: ${t} !== ${this.constructor.id}`);this.engine=this.registry.getEngine(),this.logger=this.registry.getLogger(),this.coreStore=this.registry.getStore(),this.pluginStore=this.coreStore.getPluginStore(this.id),this.unsubscribeFromState=this.pluginStore.subscribeToState(((t,e,i)=>{this.onStoreUpdated(i,e)})),this.unsubscribeFromCoreStore=this.coreStore.subscribe(((t,e,i)=>{this.onCoreStoreUpdated(i,e)})),this.readyPromise=new Promise((t=>{this.readyResolve=t})),this.readyResolve()}provides(){if(!this._capability){const t=this.buildCapability();this._capability=Object.freeze(t)}return this._capability}get state(){return this.pluginStore.getState()}get coreState(){return this.coreStore.getState()}getState(){return this.pluginStore.getState()}getCoreState(){return this.coreStore.getState()}dispatchCoreAction(t){return this.coreStore.dispatchToCore(t)}dispatchToAllPlugins(t){return this.coreStore.dispatch(t)}dispatch(t){return this.pluginStore.dispatch(t)}debouncedDispatch(t,e=100){const i=Date.now();return i-(this.debouncedActions[t.type]||0)>=e&&(this.debouncedActions[t.type]=i,this.dispatch(t),!0)}subscribe(t){return this.pluginStore.subscribeToState(t)}subscribeToCoreStore(t){return this.coreStore.subscribe(t)}onStoreUpdated(t,e){}onCoreStoreUpdated(t,e){}destroy(){this.unsubscribeFromState&&(this.unsubscribeFromState(),this.unsubscribeFromState=null),this.unsubscribeFromCoreStore&&(this.unsubscribeFromCoreStore(),this.unsubscribeFromCoreStore=null)}ready(){return this.readyPromise}markReady(){this.readyResolve()}resetReady(){this.readyPromise=new Promise((t=>{this.readyResolve=t}))}},exports.CORE_ACTION_TYPES=w,exports.CapabilityConflictError=o,exports.CapabilityNotFoundError=n,exports.CircularDependencyError=r,exports.DependencyResolver=e,exports.EventControl=P,exports.LOAD_DOCUMENT=h,exports.PluginConfigurationError=l,exports.PluginInitializationError=a,exports.PluginNotFoundError=s,exports.PluginPackageBuilder=z,exports.PluginRegistrationError=i,exports.PluginRegistry=class{constructor(i,s){this.plugins=new Map,this.manifests=new Map,this.capabilities=new Map,this.status=new Map,this.configurations=new Map,this.engineInitialized=!1,this.initPromise=null,this.pendingRegistrations=[],this.processingRegistrations=[],this.initialized=!1,this.isInitializing=!1,this.pluginsReadyPromise=null,this.destroyed=!1,this.resolver=new e,this.engine=i,this.initialCoreState=b(s),this.store=new S(E,this.initialCoreState),this.logger=(null==s?void 0:s.logger)??new t.NoopLogger}getLogger(){return this.logger}async ensureEngineInitialized(){if(!this.engineInitialized)if(this.engine.initialize){const t=this.engine.initialize();await t.toPromise(),this.engineInitialized=!0}else this.engineInitialized=!0}registerPlugin(t,e){if(this.initialized&&!this.isInitializing)throw new i("Cannot register plugins after initialization");this.validateManifest(t.manifest),this.store.addPluginReducer(t.manifest.id,t.reducer,"function"==typeof t.initialState?t.initialState(this.initialCoreState,{...t.manifest.defaultConfig,...e}):t.initialState),this.pendingRegistrations.push({package:t,config:e})}getStore(){return this.store}getEngine(){return this.engine}pluginsReady(){return this.pluginsReadyPromise||(this.pluginsReadyPromise=(async()=>{this.initialized||await this.initialize();const t=Array.from(this.plugins.values()).map((t=>"function"==typeof t.ready?t.ready():Promise.resolve()));await Promise.all(t)})()),this.pluginsReadyPromise}async initialize(){if(this.destroyed)throw new i("Registry has been destroyed");return this.initPromise||(this.initPromise=(async()=>{var t;if(this.initialized)throw new i("Registry is already initialized");this.isInitializing=!0;try{if(await this.ensureEngineInitialized(),this.destroyed)return;for(;this.pendingRegistrations.length>0;){if(this.destroyed)return;this.processingRegistrations=[...this.pendingRegistrations],this.pendingRegistrations=[];for(const e of this.processingRegistrations){const t=new Set,i=[...e.package.manifest.requires,...e.package.manifest.optional];for(const e of i){const i=this.processingRegistrations.find((t=>t.package.manifest.provides.includes(e)));i&&t.add(i.package.manifest.id)}this.resolver.addNode(e.package.manifest.id,[...t])}const t=this.resolver.resolveLoadOrder();for(const e of t){const t=this.processingRegistrations.find((t=>t.package.manifest.id===e));await this.initializePlugin(t.package.manifest,t.package.create,t.config)}this.processingRegistrations=[],this.resolver=new e}for(const e of this.plugins.values())await(null==(t=e.postInitialize)?void 0:t.call(e).catch((t=>{console.error(`Error in postInitialize for plugin ${e.id}`,t),this.status.set(e.id,"error")})));this.initialized=!0}catch(s){if(s instanceof Error)throw new r(`Failed to resolve plugin dependencies: ${s.message}`);throw s}finally{this.isInitializing=!1}})()),this.initPromise}async initializePlugin(t,e,s){const r={...t.defaultConfig,...s};this.validateConfig(t.id,r,t.defaultConfig);const n=e(this,r);this.validatePlugin(n);for(const a of t.requires)if(!this.capabilities.has(a))throw new i(`Missing required capability: ${a} for plugin ${t.id}`);for(const i of t.optional)this.capabilities.has(i)&&this.logger.debug("PluginRegistry","OptionalCapability",`Optional capability ${i} is available for plugin ${t.id}`);this.logger.debug("PluginRegistry","InitializePlugin",`Initializing plugin ${t.id}`,{provides:t.provides});for(const a of t.provides){if(this.capabilities.has(a))throw new i(`Capability ${a} is already provided by plugin ${this.capabilities.get(a)}`);this.capabilities.set(a,t.id)}this.plugins.set(t.id,n),this.manifests.set(t.id,t),this.status.set(t.id,"registered"),this.configurations.set(t.id,r);try{n.initialize&&await n.initialize(r),this.status.set(t.id,"active"),this.logger.info("PluginRegistry","PluginInitialized",`Plugin ${t.id} initialized successfully`)}catch(o){throw this.plugins.delete(t.id),this.manifests.delete(t.id),this.logger.error("PluginRegistry","InitializationFailed",`Plugin ${t.id} initialization failed`,{provides:t.provides,error:o}),t.provides.forEach((t=>this.capabilities.delete(t))),o}}getPluginConfig(t){const e=this.configurations.get(t);if(!e)throw new s(`Configuration for plugin ${t} not found`);return e}validateConfig(t,e,i){const s=Object.keys(i).filter((t=>!e.hasOwnProperty(t)));if(s.length>0)throw new l(`Missing required configuration keys for plugin ${t}: ${s.join(", ")}`)}async updatePluginConfig(t,e){const i=this.getPlugin(t);if(!i)throw new s(`Plugin ${t} not found`);const r=this.manifests.get(t),n=this.configurations.get(t);if(!r||!n)throw new s(`Plugin ${t} not found`);const o={...n,...e};this.validateConfig(t,o,r.defaultConfig),this.configurations.set(t,o),i.initialize&&await i.initialize(o)}registerPluginBatch(t){for(const e of t)this.registerPlugin(e.package,e.config)}async unregisterPlugin(t){const e=this.plugins.get(t);if(!e)throw new s(`Plugin ${t} is not registered`);const r=this.manifests.get(t);if(!r)throw new s(`Manifest for plugin ${t} not found`);for(const[s,o]of this.manifests.entries()){if(s===t)continue;if([...o.requires,...o.optional].some((t=>r.provides.includes(t))))throw new i(`Cannot unregister plugin ${t}: plugin ${s} depends on it`)}try{e.destroy&&await e.destroy();for(const t of r.provides)this.capabilities.delete(t);this.plugins.delete(t),this.manifests.delete(t),this.status.delete(t)}catch(n){if(n instanceof Error)throw new Error(`Failed to unregister plugin ${t}: ${n.message}`);throw n}}getPlugin(t){const e=this.plugins.get(t);return e||null}getCapabilityProvider(t){const e=this.capabilities.get(t);return e?this.getPlugin(e):null}hasCapability(t){return this.capabilities.has(t)}getAllPlugins(){return Array.from(this.plugins.values())}getPluginStatus(t){const e=this.status.get(t);if(!e)throw new s(`Plugin ${t} not found`);return e}validatePlugin(t){if(!t.id)throw new i("Plugin must have an id")}validateManifest(t){if(!t.id)throw new i("Manifest must have an id");if(!t.name)throw new i("Manifest must have a name");if(!t.version)throw new i("Manifest must have a version");if(!Array.isArray(t.provides))throw new i("Manifest must have a provides array");if(!Array.isArray(t.requires))throw new i("Manifest must have a requires array");if(!Array.isArray(t.optional))throw new i("Manifest must have an optional array")}isDestroyed(){return this.destroyed}async destroy(){var t;if(this.destroyed)throw new i("Registry has already been destroyed");this.destroyed=!0;try{await this.initPromise}catch{}for(const e of Array.from(this.plugins.values()).reverse())await(null==(t=e.destroy)?void 0:t.call(e));this.store.destroy(),this.plugins.clear(),this.manifests.clear(),this.capabilities.clear(),this.status.clear(),this.pendingRegistrations.length=0,this.processingRegistrations.length=0}},exports.REFRESH_DOCUMENT=c,exports.REFRESH_PAGES=d,exports.SET_DOCUMENT=g,exports.SET_DOCUMENT_ERROR=p,exports.SET_PAGES=m,exports.SET_ROTATION=y,exports.SET_SCALE=f,exports.arePropsEqual=R,exports.clamp=function(t,e,i){return t<e?e:t>i?i:t},exports.createBehaviorEmitter=function(t,e=R){const i=new Set,s=new Map;let r=t;const n=(t,e)=>{let n=t,o=()=>{};if(e){const i=new P(t,e);n=i.handle,o=()=>i.destroy(),s.set(t,{wrapped:n,destroy:o})}return void 0!==r&&n(r),i.add(n),()=>{i.delete(n),o(),s.delete(t)}};return{get value(){return r},emit(t=void 0){void 0!==r&&e(r,t)||(r=t,(t=>{i.forEach((e=>e(t)))})(t))},on:n,off(t){const e=s.get(t);e?(i.delete(e.wrapped),e.destroy(),s.delete(t)):i.delete(t)},clear(){i.clear(),s.forEach((t=>t.destroy())),s.clear()},select:(t,e=R)=>(i,s)=>{let o;if(void 0!==r){const e=t(r);o=e,i(e)}return n((s=>{const r=t(s);void 0!==o&&e(o,r)||(o=r,i(r))}),s)}}},exports.createEmitter=function(){const t=new Set;return{emit:(e=void 0)=>t.forEach((t=>t(e))),on:e=>(t.add(e),()=>t.delete(e)),off:e=>t.delete(e),clear:()=>t.clear()}},exports.createPluginPackage=function(t){return new z(t)},exports.createPluginRegistration=function(t,e){return{package:t,config:e}},exports.enumEntries=function(t){return Object.entries(t).map((([t,e])=>{const i=Number(t);return[Number.isFinite(i)&&""!==t.trim()?i:t,e]}))},exports.getPagesWithRotatedSize=e=>e.pages.map((i=>i.map((i=>({...i,rotatedSize:t.transformSize(i.size,e.rotation,1)}))))),exports.hasAutoMountElements=function(t){return"autoMountElements"in t&&"function"==typeof t.autoMountElements},exports.initialCoreState=b,exports.loadDocument=()=>({type:h}),exports.refreshDocument=t=>({type:c,payload:t}),exports.refreshPages=t=>({type:d,payload:t}),exports.setDocument=t=>({type:g,payload:t}),exports.setDocumentError=t=>({type:p,payload:t}),exports.setPages=t=>({type:m,payload:t}),exports.setRotation=t=>({type:y,payload:t}),exports.setScale=t=>({type:f,payload:t});
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/lib/utils/dependency-resolver.ts","../src/lib/types/errors.ts","../src/lib/store/plugin-store.ts","../src/lib/store/actions.ts","../src/lib/store/store.ts","../src/lib/store/initial-state.ts","../src/lib/store/reducer.ts","../src/lib/utils/event-control.ts","../src/lib/utils/math.ts","../src/lib/base/base-plugin.ts","../src/lib/registry/plugin-registry.ts","../src/lib/utils/eventing.ts","../src/lib/utils/plugin-helpers.ts","../src/lib/utils/typed-object.ts","../src/lib/store/selectors.ts"],"sourcesContent":["export class DependencyResolver {\n private dependencyGraph = new Map<string, Set<string>>();\n\n addNode(id: string, dependencies: string[] = []) {\n this.dependencyGraph.set(id, new Set(dependencies));\n }\n\n private hasCircularDependencies(): boolean {\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n\n const dfs = (id: string): boolean => {\n visited.add(id);\n recursionStack.add(id);\n\n const dependencies = this.dependencyGraph.get(id) || new Set();\n for (const dep of dependencies) {\n if (!visited.has(dep)) {\n if (dfs(dep)) return true;\n } else if (recursionStack.has(dep)) {\n return true; // Circular dependency found\n }\n }\n\n recursionStack.delete(id);\n return false;\n };\n\n for (const id of this.dependencyGraph.keys()) {\n if (!visited.has(id)) {\n if (dfs(id)) return true;\n }\n }\n\n return false;\n }\n\n resolveLoadOrder(): string[] {\n if (this.hasCircularDependencies()) {\n throw new Error('Circular dependencies detected');\n }\n\n const result: string[] = [];\n const visited = new Set<string>();\n const temp = new Set<string>();\n\n const visit = (id: string) => {\n if (temp.has(id)) throw new Error('Circular dependency');\n if (visited.has(id)) return;\n\n temp.add(id);\n\n const dependencies = this.dependencyGraph.get(id) || new Set();\n for (const dep of dependencies) {\n visit(dep);\n }\n\n temp.delete(id);\n visited.add(id);\n result.push(id);\n };\n\n for (const id of this.dependencyGraph.keys()) {\n if (!visited.has(id)) {\n visit(id);\n }\n }\n\n return result;\n }\n}\n","export class PluginRegistrationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PluginRegistrationError';\n }\n}\n\nexport class PluginNotFoundError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PluginNotFoundError';\n }\n}\n\nexport class CircularDependencyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CircularDependencyError';\n }\n}\n\nexport class CapabilityNotFoundError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CapabilityNotFoundError';\n }\n}\n\n// You might also want to add:\nexport class CapabilityConflictError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CapabilityConflictError';\n }\n}\n\nexport class PluginInitializationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PluginInitializationError';\n }\n}\n\nexport class PluginConfigurationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PluginConfigurationError';\n }\n}\n","import { Store } from './store';\nimport { Action } from './types';\n\n/**\n * A type-safe store handle for plugins, providing access to plugin-specific state and actions.\n */\nexport class PluginStore<PluginState, PluginAction extends Action> {\n private store: Store<any, any>;\n private pluginId: string;\n\n /**\n * Initializes the PluginStore with the main store and plugin ID.\n * @param store The main store instance.\n * @param pluginId The unique identifier for the plugin.\n */\n constructor(store: Store<any, any>, pluginId: string) {\n this.store = store;\n this.pluginId = pluginId;\n }\n\n /**\n * Gets the current state of the plugin.\n * @returns The plugin's state.\n */\n getState(): PluginState {\n return this.store.getState().plugins[this.pluginId] as PluginState;\n }\n\n /**\n * Dispatches an action for the plugin and returns the *new* global state.\n * If you only need the plugin’s updated state, call `getState()` afterward.\n * @param action The action to dispatch.\n * @returns The updated global store state (after plugin reducer).\n */\n dispatch(action: PluginAction): PluginState {\n return this.store.dispatchToPlugin(this.pluginId, action);\n }\n\n /**\n * Subscribes to state changes only for this specific plugin.\n * You now receive (action, newPluginState, oldPluginState) in the callback.\n *\n * @param listener The callback to invoke when plugin state changes.\n * @returns A function to unsubscribe the listener.\n */\n subscribeToState(\n listener: (action: PluginAction, newState: PluginState, oldState: PluginState) => void,\n ) {\n return this.store.subscribeToPlugin(this.pluginId, (action, newPluginState, oldPluginState) => {\n listener(\n action as PluginAction,\n newPluginState as PluginState,\n oldPluginState as PluginState,\n );\n });\n }\n\n /**\n * Subscribes to a specific action type for the plugin.\n * This still uses the main store's `onAction`, so you get the *global*\n * old/new store states there. If you specifically want old/new plugin state,\n * use `subscribeToState` instead.\n *\n * @param type The action type to listen for.\n * @param handler The callback to invoke when the action occurs.\n * @returns A function to unsubscribe the handler.\n */\n onAction<T extends PluginAction['type']>(\n type: T,\n handler: (\n action: Extract<PluginAction, { type: T }>,\n state: PluginState,\n oldState: PluginState,\n ) => void,\n ) {\n return this.store.onAction(type, (action, state, oldState) => {\n handler(\n action as Extract<PluginAction, { type: T }>,\n state.plugins[this.pluginId] as PluginState,\n oldState.plugins[this.pluginId] as PluginState,\n );\n });\n }\n}\n","import { PdfDocumentObject, PdfPageObject, Rotation } from '@embedpdf/models';\n\nexport const LOAD_DOCUMENT = 'LOAD_DOCUMENT';\nexport const REFRESH_DOCUMENT = 'REFRESH_DOCUMENT';\nexport const REFRESH_PAGES = 'REFRESH_PAGES';\nexport const SET_DOCUMENT = 'SET_DOCUMENT';\nexport const SET_DOCUMENT_ERROR = 'SET_DOCUMENT_ERROR';\nexport const SET_SCALE = 'SET_SCALE';\nexport const SET_ROTATION = 'SET_ROTATION';\nexport const SET_PAGES = 'SET_PAGES';\n\nexport const CORE_ACTION_TYPES = [\n LOAD_DOCUMENT,\n REFRESH_DOCUMENT,\n SET_DOCUMENT,\n SET_DOCUMENT_ERROR,\n SET_SCALE,\n SET_ROTATION,\n SET_PAGES,\n] as const;\n\n// Action Type Interfaces\nexport interface LoadDocumentAction {\n type: typeof LOAD_DOCUMENT;\n}\n\nexport interface RefreshDocumentAction {\n type: typeof REFRESH_DOCUMENT;\n payload: PdfDocumentObject;\n}\n\nexport interface RefreshPagesAction {\n type: typeof REFRESH_PAGES;\n payload: number[];\n}\n\nexport interface SetDocumentAction {\n type: typeof SET_DOCUMENT;\n payload: PdfDocumentObject;\n}\n\nexport interface SetDocumentErrorAction {\n type: typeof SET_DOCUMENT_ERROR;\n payload: string;\n}\n\nexport interface SetScaleAction {\n type: typeof SET_SCALE;\n payload: number;\n}\n\nexport interface SetRotationAction {\n type: typeof SET_ROTATION;\n payload: Rotation;\n}\n\nexport interface SetPagesAction {\n type: typeof SET_PAGES;\n payload: PdfPageObject[][];\n}\n\nexport type DocumentAction =\n | LoadDocumentAction\n | RefreshDocumentAction\n | RefreshPagesAction\n | SetDocumentAction\n | SetDocumentErrorAction\n | SetScaleAction\n | SetRotationAction\n | SetPagesAction;\n\n// Core actions\nexport type CoreAction = DocumentAction;\n\nexport const loadDocument = (): CoreAction => ({ type: LOAD_DOCUMENT });\nexport const refreshDocument = (document: PdfDocumentObject): CoreAction => ({\n type: REFRESH_DOCUMENT,\n payload: document,\n});\nexport const refreshPages = (pages: number[]): CoreAction => ({\n type: REFRESH_PAGES,\n payload: pages,\n});\nexport const setDocument = (document: PdfDocumentObject): CoreAction => ({\n type: SET_DOCUMENT,\n payload: document,\n});\nexport const setDocumentError = (error: string): CoreAction => ({\n type: SET_DOCUMENT_ERROR,\n payload: error,\n});\nexport const setScale = (scale: number): CoreAction => ({ type: SET_SCALE, payload: scale });\nexport const setRotation = (rotation: Rotation): CoreAction => ({\n type: SET_ROTATION,\n payload: rotation,\n});\nexport const setPages = (pages: PdfPageObject[][]): CoreAction => ({\n type: SET_PAGES,\n payload: pages,\n});\n","import { Reducer, Action, StoreState, StoreListener, PluginListener } from './types';\nimport { PluginStore } from './plugin-store';\nimport { CORE_ACTION_TYPES } from './actions';\n\n/**\n * A generic, type-safe store class managing core and plugin states, reducers, and subscriptions.\n * @template CoreState The type of the core state.\n * @template CoreAction The type of actions handled by core reducers (extends Action).\n */\nexport class Store<CoreState, CoreAction extends Action = Action> {\n private state: StoreState<CoreState>;\n private coreReducer: Reducer<CoreState, CoreAction>;\n private pluginReducers: Record<string, Reducer<any, Action>> = {};\n\n private listeners: StoreListener<CoreState>[] = [];\n private pluginListeners: Record<string, PluginListener[]> = {};\n\n /**\n * Initializes the store with the provided core state.\n * @param reducer The core reducer function\n * @param initialCoreState The initial core state\n */\n constructor(\n reducer: Reducer<CoreState, CoreAction>,\n public initialCoreState: CoreState,\n ) {\n this.state = { core: initialCoreState, plugins: {} };\n this.coreReducer = reducer;\n }\n\n /**\n * Adds a reducer for a plugin-specific state.\n * @param pluginId The unique identifier for the plugin.\n * @param reducer The reducer function for the plugin state.\n * @param initialState The initial state for the plugin.\n */\n addPluginReducer<PluginState>(\n pluginId: string,\n reducer: Reducer<PluginState, Action>,\n initialState: PluginState,\n ) {\n this.state.plugins[pluginId] = initialState;\n this.pluginReducers[pluginId] = reducer;\n }\n\n /**\n * Dispatches an action *only* to the core reducer.\n * Notifies the global store listeners with (action, newState, oldState).\n *\n * @param action The action to dispatch, typed as CoreAction\n * @returns The updated *global* store state\n */\n dispatchToCore(action: CoreAction): StoreState<CoreState> {\n if (!this.coreReducer) {\n return this.getState();\n }\n\n const oldState = this.getState();\n // Update core state via its reducer\n this.state.core = this.coreReducer(this.state.core, action);\n\n const newState = this.getState();\n // Notify all main-store subscribers\n this.listeners.forEach((listener) => listener(action, newState, oldState));\n\n return newState;\n }\n\n /**\n * Dispatches an action *only* to a specific plugin.\n * Optionally notifies global store listeners if `notifyGlobal` is true.\n * Always notifies plugin-specific listeners with (action, newPluginState, oldPluginState).\n *\n * @param pluginId The plugin identifier\n * @param action The plugin action to dispatch\n * @param notifyGlobal Whether to also notify global store listeners\n * @returns The updated *global* store state\n */\n dispatchToPlugin<PluginAction extends Action>(\n pluginId: string,\n action: PluginAction,\n notifyGlobal: boolean = true,\n ): any {\n const oldGlobalState = this.getState();\n\n const reducer = this.pluginReducers[pluginId];\n if (!reducer) {\n // No plugin found, just return the old state\n return oldGlobalState;\n }\n\n // Grab the old plugin state\n const oldPluginState = oldGlobalState.plugins[pluginId];\n // Reduce to new plugin state\n const newPluginState = reducer(oldPluginState, action);\n // Update the store's plugin slice\n this.state.plugins[pluginId] = newPluginState;\n\n const newGlobalState = this.getState();\n\n // If we are notifying the main store subscribers about plugin changes\n if (notifyGlobal) {\n this.listeners.forEach((listener) => listener(action, newGlobalState, oldGlobalState));\n }\n\n // Notify plugin-specific listeners\n if (this.pluginListeners[pluginId]) {\n this.pluginListeners[pluginId].forEach((listener) => {\n listener(action, newPluginState, oldPluginState);\n });\n }\n\n return newPluginState;\n }\n\n /**\n * Dispatches an action to update the state using:\n * - the core reducer (if it's a CoreAction)\n * - *all* plugin reducers (regardless of action type), with no global notify for each plugin\n *\n * Returns the new *global* store state after all reducers have processed the action.\n *\n * @param action The action to dispatch (can be CoreAction or any Action).\n */\n dispatch(action: CoreAction | Action): StoreState<CoreState> {\n // Keep old state to notify global listeners *once*, after all reducers run.\n const oldState = this.getState();\n // 1) Apply core reducer (only if action is a CoreAction)\n if (this.isCoreAction(action)) {\n this.state.core = this.coreReducer(this.state.core, action);\n }\n\n // 2) Apply plugin reducers (without globally notifying after each plugin)\n for (const pluginId in this.pluginReducers) {\n const reducer = this.pluginReducers[pluginId];\n const oldPluginState = oldState.plugins[pluginId];\n if (reducer) {\n this.state.plugins[pluginId] = reducer(oldPluginState, action);\n }\n // We do *not* notify global listeners or plugin listeners here,\n // as that might be undesired \"fan-out\". If you want per-plugin subscription\n // triggered on every dispatch, you can do so here, but that’s up to you.\n }\n\n // 3) Notify global listeners *once* with the final new state\n const newState = this.getState();\n this.listeners.forEach((listener) => listener(action, newState, oldState));\n\n // 4) Return the new global store state\n return newState;\n }\n\n /**\n * Returns a shallow copy of the current state.\n * @returns The current store state.\n */\n getState(): StoreState<CoreState> {\n return {\n core: { ...this.state.core },\n plugins: { ...this.state.plugins },\n };\n }\n\n /**\n * Subscribes a listener to *global* state changes.\n * The callback signature is now (action, newState, oldState).\n *\n * @param listener The callback to invoke on state changes\n * @returns A function to unsubscribe the listener\n */\n subscribe(listener: StoreListener<CoreState>) {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n /**\n * Subscribes a listener to *plugin-specific* state changes.\n * The callback signature is now (action, newPluginState, oldPluginState).\n *\n * @param pluginId The unique identifier for the plugin.\n * @param listener The callback to invoke on plugin state changes.\n * @returns A function to unsubscribe the listener.\n */\n subscribeToPlugin(pluginId: string, listener: PluginListener) {\n if (!(pluginId in this.state.plugins)) {\n throw new Error(\n `Plugin state not found for plugin \"${pluginId}\". Did you forget to call addPluginReducer?`,\n );\n }\n\n if (!this.pluginListeners[pluginId]) {\n this.pluginListeners[pluginId] = [];\n }\n this.pluginListeners[pluginId].push(listener);\n\n return () => {\n this.pluginListeners[pluginId] = this.pluginListeners[pluginId].filter((l) => l !== listener);\n if (this.pluginListeners[pluginId].length === 0) {\n delete this.pluginListeners[pluginId];\n }\n };\n }\n\n /**\n * Subscribes to a specific action type (only from the core's action union).\n * The callback signature is (action, newState, oldState).\n *\n * @param type The action type to listen for.\n * @param handler The callback to invoke when the action occurs.\n * @returns A function to unsubscribe the handler.\n */\n onAction<T extends CoreAction['type']>(\n type: T,\n handler: (\n action: Extract<CoreAction, { type: T }>,\n state: StoreState<CoreState>,\n oldState: StoreState<CoreState>,\n ) => void,\n ) {\n return this.subscribe((action, newState, oldState) => {\n if (action.type === type) {\n handler(action as Extract<CoreAction, { type: T }>, newState, oldState);\n }\n });\n }\n\n /**\n * Gets a PluginStore handle for a specific plugin.\n * @param pluginId The unique identifier for the plugin.\n * @returns A PluginStore instance for the plugin.\n */\n getPluginStore<PluginState, PluginAction extends Action>(\n pluginId: string,\n ): PluginStore<PluginState, PluginAction> {\n if (!(pluginId in this.state.plugins)) {\n throw new Error(\n `Plugin state not found for plugin \"${pluginId}\". Did you forget to call addPluginReducer?`,\n );\n }\n return new PluginStore<PluginState, PluginAction>(this, pluginId);\n }\n\n /**\n * Helper method to check if an action is a CoreAction.\n * Adjust if you have a more refined way to differentiate CoreAction vs. any other Action.\n */\n public isCoreAction(action: Action): action is CoreAction {\n // In many codebases you'd do something more robust here\n // or rely on TypeScript's narrowing logic if possible.\n return CORE_ACTION_TYPES.includes(action.type as (typeof CORE_ACTION_TYPES)[number]);\n }\n\n /**\n * Destroy the store: drop every listener and plugin reducer\n */\n public destroy(): void {\n // 1. empty listener collections\n this.listeners.length = 0;\n for (const id in this.pluginListeners) {\n this.pluginListeners[id]?.splice?.(0);\n }\n this.pluginListeners = {};\n\n // 2. wipe plugin reducers and states\n this.pluginReducers = {};\n this.state.plugins = {};\n\n // 3. reset core state to initial\n this.state.core = { ...this.initialCoreState };\n }\n}\n","import { PdfDocumentObject, PdfPageObject, Rotation } from '@embedpdf/models';\nimport { PluginRegistryConfig } from '../types/plugin';\n\nexport interface CoreState {\n scale: number;\n rotation: Rotation;\n document: PdfDocumentObject | null;\n pages: PdfPageObject[][];\n loading: boolean;\n error: string | null;\n}\n\nexport const initialCoreState: (config?: PluginRegistryConfig) => CoreState = (config) => ({\n scale: config?.scale ?? 1,\n rotation: config?.rotation ?? Rotation.Degree0,\n document: null,\n pages: [],\n loading: false,\n error: null,\n});\n","import { Reducer } from './types';\nimport { CoreState } from './initial-state';\nimport {\n CoreAction,\n LOAD_DOCUMENT,\n REFRESH_DOCUMENT,\n SET_DOCUMENT,\n SET_DOCUMENT_ERROR,\n SET_PAGES,\n SET_ROTATION,\n SET_SCALE,\n} from './actions';\n\nexport const coreReducer: Reducer<CoreState, CoreAction> = (state, action): CoreState => {\n switch (action.type) {\n case LOAD_DOCUMENT:\n return {\n ...state,\n loading: true,\n error: null,\n };\n\n case SET_DOCUMENT:\n return {\n ...state,\n document: action.payload,\n pages: action.payload.pages.map((page) => [page]),\n loading: false,\n error: null,\n };\n\n case REFRESH_DOCUMENT:\n return {\n ...state,\n document: action.payload,\n pages: action.payload.pages.map((page) => [page]),\n loading: false,\n error: null,\n };\n\n case SET_ROTATION:\n return {\n ...state,\n rotation: action.payload,\n };\n\n case SET_PAGES:\n return {\n ...state,\n pages: action.payload,\n };\n\n case SET_DOCUMENT_ERROR:\n return {\n ...state,\n loading: false,\n error: action.payload,\n };\n\n case SET_SCALE:\n return {\n ...state,\n scale: action.payload,\n };\n\n default:\n return state;\n }\n};\n","export type EventHandler<T> = (data: T) => void;\n\nexport interface BaseEventControlOptions {\n wait: number;\n}\n\nexport interface DebounceOptions extends BaseEventControlOptions {\n mode: 'debounce';\n}\n\nexport interface ThrottleOptions extends BaseEventControlOptions {\n mode: 'throttle';\n throttleMode?: 'leading-trailing' | 'trailing';\n}\n\nexport type EventControlOptions = DebounceOptions | ThrottleOptions;\n\nexport class EventControl<T> {\n private timeoutId?: number;\n private lastRun: number = 0;\n\n constructor(\n private handler: EventHandler<T>,\n private options: EventControlOptions,\n ) {}\n\n handle = (data: T): void => {\n if (this.options.mode === 'debounce') {\n this.debounce(data);\n } else {\n this.throttle(data);\n }\n };\n\n private debounce(data: T): void {\n if (this.timeoutId) {\n window.clearTimeout(this.timeoutId);\n }\n\n this.timeoutId = window.setTimeout(() => {\n this.handler(data);\n this.timeoutId = undefined;\n }, this.options.wait);\n }\n\n private throttle(data: T): void {\n if (this.options.mode === 'debounce') return;\n\n const now = Date.now();\n const throttleMode = this.options.throttleMode || 'leading-trailing';\n\n if (now - this.lastRun >= this.options.wait) {\n if (throttleMode === 'leading-trailing') {\n this.handler(data);\n }\n this.lastRun = now;\n }\n\n // Always schedule the trailing execution\n if (this.timeoutId) {\n window.clearTimeout(this.timeoutId);\n }\n\n this.timeoutId = window.setTimeout(\n () => {\n this.handler(data);\n this.lastRun = Date.now();\n this.timeoutId = undefined;\n },\n this.options.wait - (now - this.lastRun),\n );\n }\n\n destroy(): void {\n if (this.timeoutId) {\n window.clearTimeout(this.timeoutId);\n }\n }\n}\n","/**\n * Restrict a numeric value to the inclusive range [min, max].\n *\n * @example\n * clamp( 5, 0, 10) // 5\n * clamp(-3, 0, 10) // 0\n * clamp(17, 0, 10) // 10\n */\nexport function clamp(value: number, min: number, max: number): number {\n return value < min ? min : value > max ? max : value;\n}\n\n/**\n * Deeply compares two values (objects, arrays, primitives)\n * with the following rules:\n * - Objects are compared ignoring property order.\n * - Arrays are compared ignoring element order (multiset comparison).\n * - Primitives are compared by strict equality.\n * - null/undefined are treated as normal primitives.\n *\n * @param a First value\n * @param b Second value\n * @param visited Used internally to detect cycles\n */\nexport function arePropsEqual(a: any, b: any, visited?: Set<any>): boolean {\n // Quick path for reference equality or same primitive\n if (a === b) {\n return true;\n }\n\n // Handle null/undefined mismatch\n if (a == null || b == null) {\n // If one is null/undefined and the other isn't, no match\n return a === b;\n }\n\n // Check types\n const aType = typeof a;\n const bType = typeof b;\n if (aType !== bType) return false;\n\n // If they are both objects or arrays, handle recursively\n if (aType === 'object') {\n // Optionally handle cyclical references\n if (!visited) visited = new Set();\n const pairId = getPairId(a, b);\n if (visited.has(pairId)) {\n // Already compared these two objects => assume true to avoid infinite recursion\n // or return false if you want to treat cycles as inequality\n return true;\n }\n visited.add(pairId);\n\n const aIsArray = Array.isArray(a);\n const bIsArray = Array.isArray(b);\n if (aIsArray && bIsArray) {\n // Compare as arrays ignoring order\n return arraysEqualUnordered(a, b, visited);\n } else if (!aIsArray && !bIsArray) {\n // Compare as plain objects (order of properties doesn't matter)\n return objectsEqual(a, b, visited);\n } else {\n // One is array, the other is object => not equal\n return false;\n }\n }\n\n // If both are function, symbol, etc. - typically we might say false\n // But you can decide your own logic for function or symbol equality\n return false;\n}\n\nfunction getPairId(a: any, b: any) {\n // Could do something more advanced. This is a cheap approach:\n // e.g. use the memory reference or an object identity approach\n return `${objectId(a)}__${objectId(b)}`;\n}\n\n/**\n * If you want stable object IDs, you'd need a WeakMap to store them.\n * This simplistic approach just calls toString on the object.\n */\nlet objectIdCounter = 0;\nconst objectIds = new WeakMap<object, number>();\n\nfunction objectId(obj: object): number {\n if (!objectIds.has(obj)) {\n objectIds.set(obj, ++objectIdCounter);\n }\n return objectIds.get(obj)!;\n}\n\nfunction arraysEqualUnordered(a: any[], b: any[], visited?: Set<any>): boolean {\n if (a.length !== b.length) return false;\n\n const used = new Array<boolean>(b.length).fill(false);\n\n // For each element in a, find an unused matching element in b\n outer: for (let i = 0; i < a.length; i++) {\n const elemA = a[i];\n for (let j = 0; j < b.length; j++) {\n if (used[j]) continue; // already used that slot\n if (arePropsEqual(elemA, b[j], visited)) {\n used[j] = true;\n continue outer; // found match for a[i], proceed\n }\n }\n // If we never found a match\n return false;\n }\n\n return true;\n}\n\nfunction objectsEqual(a: object, b: object, visited?: Set<any>): boolean {\n // Get all prop keys\n const aKeys = Object.keys(a).sort();\n const bKeys = Object.keys(b).sort();\n if (aKeys.length !== bKeys.length) return false;\n\n // Compare each property name\n for (let i = 0; i < aKeys.length; i++) {\n if (aKeys[i] !== bKeys[i]) return false;\n }\n\n // Compare each property value\n for (const key of aKeys) {\n // @ts-ignore\n const valA = a[key];\n // @ts-ignore\n const valB = b[key];\n if (!arePropsEqual(valA, valB, visited)) {\n return false;\n }\n }\n return true;\n}\n","import { IPlugin } from '../types/plugin';\nimport { PluginRegistry } from '../registry/plugin-registry';\nimport { Action, CoreAction, CoreState, PluginStore, Store, StoreState } from '../store';\nimport { Logger, PdfEngine } from '@embedpdf/models';\n\nexport interface StateChangeHandler<TState> {\n (state: TState): void;\n}\n\nexport abstract class BasePlugin<\n TConfig = unknown,\n TCapability = unknown,\n TState = unknown,\n TAction extends Action = Action,\n> implements IPlugin<TConfig>\n{\n static readonly id: string;\n\n protected pluginStore: PluginStore<TState, TAction>;\n protected coreStore: Store<CoreState, CoreAction>;\n protected readonly logger: Logger;\n protected readonly engine: PdfEngine;\n\n // Track debounced actions\n private debouncedActions: Record<string, number> = {};\n private unsubscribeFromState: (() => void) | null = null;\n private unsubscribeFromCoreStore: (() => void) | null = null;\n\n private _capability?: Readonly<TCapability>;\n\n private readyPromise: Promise<void>;\n private readyResolve!: () => void;\n\n constructor(\n public readonly id: string,\n protected registry: PluginRegistry,\n ) {\n if (id !== (this.constructor as typeof BasePlugin).id) {\n throw new Error(\n `Plugin ID mismatch: ${id} !== ${(this.constructor as typeof BasePlugin).id}`,\n );\n }\n this.engine = this.registry.getEngine();\n this.logger = this.registry.getLogger();\n this.coreStore = this.registry.getStore();\n this.pluginStore = this.coreStore.getPluginStore<TState, TAction>(this.id);\n this.unsubscribeFromState = this.pluginStore.subscribeToState((action, newState, oldState) => {\n this.onStoreUpdated(oldState, newState);\n });\n this.unsubscribeFromCoreStore = this.coreStore.subscribe((action, newState, oldState) => {\n this.onCoreStoreUpdated(oldState, newState);\n });\n\n // Initialize ready state\n this.readyPromise = new Promise((resolve) => {\n this.readyResolve = resolve;\n });\n // By default, plugins are ready immediately\n this.readyResolve();\n }\n\n /** Construct the public capability (called once & cached). */\n protected abstract buildCapability(): TCapability;\n\n public provides(): Readonly<TCapability> {\n if (!this._capability) {\n const cap = this.buildCapability();\n\n this._capability = Object.freeze(cap);\n }\n return this._capability;\n }\n\n /**\n * Initialize plugin with config\n */\n abstract initialize(config: TConfig): Promise<void>;\n\n /**\n * Get a copy of the current state\n */\n protected get state(): Readonly<TState> {\n return this.pluginStore.getState();\n }\n\n /**\n * Get a copy of the current core state\n */\n protected get coreState(): Readonly<StoreState<CoreState>> {\n return this.coreStore.getState();\n }\n\n /**\n * @deprecated use `this.state` Get a copy of the current state\n */\n protected getState(): TState {\n return this.pluginStore.getState();\n }\n\n /**\n * @deprecated use `this.coreState` Get a copy of the current core state\n */\n protected getCoreState(): StoreState<CoreState> {\n return this.coreStore.getState();\n }\n\n /**\n * Core Dispatch\n */\n protected dispatchCoreAction(action: CoreAction): StoreState<CoreState> {\n return this.coreStore.dispatchToCore(action);\n }\n\n /**\n * Dispatch an action to all plugins\n */\n protected dispatchToAllPlugins(action: TAction): StoreState<CoreState> {\n return this.coreStore.dispatch(action);\n }\n\n /**\n * Dispatch an action\n */\n protected dispatch(action: TAction): TState {\n return this.pluginStore.dispatch(action);\n }\n\n /**\n * Dispatch an action with debouncing to prevent rapid repeated calls\n * @param action The action to dispatch\n * @param debounceTime Time in ms to debounce (default: 100ms)\n * @returns boolean indicating whether the action was dispatched or debounced\n */\n protected debouncedDispatch(action: TAction, debounceTime: number = 100): boolean {\n const now = Date.now();\n const lastActionTime = this.debouncedActions[action.type] || 0;\n\n if (now - lastActionTime >= debounceTime) {\n this.debouncedActions[action.type] = now;\n this.dispatch(action);\n return true;\n }\n\n return false;\n }\n\n /**\n * Subscribe to state changes\n */\n protected subscribe(listener: (action: TAction, state: TState) => void): () => void {\n return this.pluginStore.subscribeToState(listener);\n }\n\n /**\n * Subscribe to core store changes\n */\n protected subscribeToCoreStore(\n listener: (action: Action, state: StoreState<CoreState>) => void,\n ): () => void {\n return this.coreStore.subscribe(listener);\n }\n\n /**\n * Called when the plugin store state is updated\n * @param oldState Previous state\n * @param newState New state\n */\n protected onStoreUpdated(oldState: TState, newState: TState): void {\n // Default implementation does nothing - can be overridden by plugins\n }\n\n /**\n * Called when the core store state is updated\n * @param oldState Previous state\n * @param newState New state\n */\n protected onCoreStoreUpdated(\n oldState: StoreState<CoreState>,\n newState: StoreState<CoreState>,\n ): void {\n // Default implementation does nothing - can be overridden by plugins\n }\n\n /**\n * Cleanup method to be called when plugin is being destroyed\n */\n public destroy(): void {\n if (this.unsubscribeFromState) {\n this.unsubscribeFromState();\n this.unsubscribeFromState = null;\n }\n if (this.unsubscribeFromCoreStore) {\n this.unsubscribeFromCoreStore();\n this.unsubscribeFromCoreStore = null;\n }\n }\n\n /**\n * Returns a promise that resolves when the plugin is ready\n */\n public ready(): Promise<void> {\n return this.readyPromise;\n }\n\n /**\n * Mark the plugin as ready\n */\n protected markReady(): void {\n this.readyResolve();\n }\n\n /**\n * Reset the ready state (useful for plugins that need to reinitialize)\n */\n protected resetReady(): void {\n this.readyPromise = new Promise((resolve) => {\n this.readyResolve = resolve;\n });\n }\n}\n","import { DependencyResolver } from '../utils/dependency-resolver';\nimport {\n IPlugin,\n PluginBatchRegistration,\n PluginManifest,\n PluginStatus,\n PluginPackage,\n PluginRegistryConfig,\n} from '../types/plugin';\nimport {\n PluginRegistrationError,\n PluginNotFoundError,\n CircularDependencyError,\n PluginConfigurationError,\n} from '../types/errors';\nimport { Logger, NoopLogger, PdfEngine } from '@embedpdf/models';\nimport { Action, CoreState, Store, initialCoreState, Reducer } from '../store';\nimport { CoreAction } from '../store/actions';\nimport { coreReducer } from '../store/reducer';\n\n// Define a more flexible generic type for plugin registrations\ninterface PluginRegistration {\n // Use existential types for the plugin package to allow accepting any plugin type\n package: PluginPackage<any, any, any, any>;\n config?: any;\n}\n\nexport class PluginRegistry {\n private plugins: Map<string, IPlugin> = new Map();\n private manifests: Map<string, PluginManifest> = new Map();\n private capabilities: Map<string, string> = new Map(); // capability -> pluginId\n private status: Map<string, PluginStatus> = new Map();\n private resolver: DependencyResolver;\n private configurations: Map<string, unknown> = new Map();\n private engine: PdfEngine;\n private engineInitialized = false;\n private store: Store<CoreState, CoreAction>;\n private initPromise: Promise<void> | null = null;\n private logger: Logger;\n\n private pendingRegistrations: PluginRegistration[] = [];\n private processingRegistrations: PluginRegistration[] = [];\n private initialized = false;\n private isInitializing = false;\n private initialCoreState: CoreState;\n private pluginsReadyPromise: Promise<void> | null = null;\n private destroyed = false;\n\n constructor(engine: PdfEngine, config?: PluginRegistryConfig) {\n this.resolver = new DependencyResolver();\n this.engine = engine;\n this.initialCoreState = initialCoreState(config);\n this.store = new Store<CoreState, CoreAction>(coreReducer, this.initialCoreState);\n this.logger = config?.logger ?? new NoopLogger();\n }\n\n /**\n * Get the logger instance\n */\n getLogger(): Logger {\n return this.logger;\n }\n\n /**\n * Ensure engine is initialized before proceeding\n */\n private async ensureEngineInitialized(): Promise<void> {\n if (this.engineInitialized) {\n return;\n }\n\n if (this.engine.initialize) {\n const task = this.engine.initialize();\n await task.toPromise();\n this.engineInitialized = true;\n } else {\n this.engineInitialized = true;\n }\n }\n\n /**\n * Register a plugin without initializing it\n */\n registerPlugin<\n TPlugin extends IPlugin<TConfig>,\n TConfig = unknown,\n TState = unknown,\n TAction extends Action = Action,\n >(\n pluginPackage: PluginPackage<TPlugin, TConfig, TState, TAction>,\n config?: Partial<TConfig>,\n ): void {\n if (this.initialized && !this.isInitializing) {\n throw new PluginRegistrationError('Cannot register plugins after initialization');\n }\n\n this.validateManifest(pluginPackage.manifest);\n\n // Use appropriate typing for store methods\n this.store.addPluginReducer(\n pluginPackage.manifest.id,\n // We need one type assertion here since we can't fully reconcile TAction with Action\n // due to TypeScript's type system limitations with generic variance\n pluginPackage.reducer as Reducer<TState, Action>,\n 'function' === typeof pluginPackage.initialState\n ? (pluginPackage.initialState as (coreState: CoreState, config: TConfig) => TState)(\n this.initialCoreState,\n {\n ...pluginPackage.manifest.defaultConfig,\n ...config,\n },\n )\n : pluginPackage.initialState,\n );\n\n this.pendingRegistrations.push({\n package: pluginPackage,\n config,\n });\n }\n\n /**\n * Get the central store instance\n */\n getStore(): Store<CoreState, CoreAction> {\n return this.store;\n }\n\n /**\n * Get the engine instance\n */\n getEngine(): PdfEngine {\n return this.engine;\n }\n\n /**\n * Get a promise that resolves when all plugins are ready\n */\n public pluginsReady(): Promise<void> {\n // Re-use the same promise every time it’s asked for\n if (this.pluginsReadyPromise) {\n return this.pluginsReadyPromise;\n }\n\n // Build the promise the *first* time it’s requested\n this.pluginsReadyPromise = (async () => {\n // 1. Wait until the registry itself has finished initialising\n if (!this.initialized) {\n await this.initialize();\n }\n\n // 2. Wait for every plugin’s ready() promise (if it has one)\n const readyPromises = Array.from(this.plugins.values()).map((p) =>\n typeof p.ready === 'function' ? p.ready() : Promise.resolve(),\n );\n\n await Promise.all(readyPromises); // resolves when the slowest is done\n })();\n\n return this.pluginsReadyPromise;\n }\n\n /**\n * INITIALISE THE REGISTRY – runs once no-matter-how-many calls *\n */\n async initialize(): Promise<void> {\n if (this.destroyed) {\n throw new PluginRegistrationError('Registry has been destroyed');\n }\n\n // If an initialisation is already in-flight (or finished)\n // return the very same promise so callers can await it.\n if (this.initPromise) {\n return this.initPromise;\n }\n\n // Wrap your existing body in a single promise and cache it\n this.initPromise = (async () => {\n if (this.initialized) {\n throw new PluginRegistrationError('Registry is already initialized');\n }\n\n this.isInitializing = true;\n\n try {\n /* ---------------- original body starts ------------------ */\n await this.ensureEngineInitialized();\n // Check if destroyed after engine initialization\n if (this.destroyed) {\n return;\n }\n\n while (this.pendingRegistrations.length > 0) {\n // Check if destroyed before processing each batch\n if (this.destroyed) {\n return;\n }\n this.processingRegistrations = [...this.pendingRegistrations];\n this.pendingRegistrations = [];\n\n for (const reg of this.processingRegistrations) {\n const dependsOn = new Set<string>();\n const allDeps = [...reg.package.manifest.requires, ...reg.package.manifest.optional];\n for (const cap of allDeps) {\n const provider = this.processingRegistrations.find((r) =>\n r.package.manifest.provides.includes(cap),\n );\n if (provider) dependsOn.add(provider.package.manifest.id);\n }\n this.resolver.addNode(reg.package.manifest.id, [...dependsOn]);\n }\n\n const loadOrder = this.resolver.resolveLoadOrder();\n for (const id of loadOrder) {\n const reg = this.processingRegistrations.find((r) => r.package.manifest.id === id)!;\n await this.initializePlugin(reg.package.manifest, reg.package.create, reg.config);\n }\n\n this.processingRegistrations = [];\n this.resolver = new DependencyResolver();\n }\n\n for (const plugin of this.plugins.values()) {\n await plugin.postInitialize?.().catch((e) => {\n console.error(`Error in postInitialize for plugin ${plugin.id}`, e);\n this.status.set(plugin.id, 'error');\n });\n }\n\n this.initialized = true;\n /* ----------------- original body ends ------------------- */\n } catch (err) {\n if (err instanceof Error) {\n throw new CircularDependencyError(\n `Failed to resolve plugin dependencies: ${err.message}`,\n );\n }\n throw err;\n } finally {\n this.isInitializing = false;\n }\n })();\n\n return this.initPromise;\n }\n\n /**\n * Initialize a single plugin with all necessary checks\n */\n private async initializePlugin<TConfig>(\n manifest: PluginManifest<TConfig>,\n packageCreator: (registry: PluginRegistry, config?: TConfig) => IPlugin<TConfig>,\n config?: Partial<TConfig>,\n ): Promise<void> {\n const finalConfig = {\n ...manifest.defaultConfig,\n ...config,\n };\n\n this.validateConfig(manifest.id, finalConfig, manifest.defaultConfig);\n\n // Create plugin instance during initialization\n const plugin = packageCreator(this, finalConfig);\n this.validatePlugin(plugin);\n\n // Verify all required capabilities are available\n for (const capability of manifest.requires) {\n if (!this.capabilities.has(capability)) {\n throw new PluginRegistrationError(\n `Missing required capability: ${capability} for plugin ${manifest.id}`,\n );\n }\n }\n\n // Optional capabilities can be null, so we don't throw errors for them\n for (const capability of manifest.optional) {\n if (this.capabilities.has(capability)) {\n // Optional capability is available, but we don't require it\n this.logger.debug(\n 'PluginRegistry',\n 'OptionalCapability',\n `Optional capability ${capability} is available for plugin ${manifest.id}`,\n );\n }\n }\n\n this.logger.debug('PluginRegistry', 'InitializePlugin', `Initializing plugin ${manifest.id}`, {\n provides: manifest.provides,\n });\n\n // Register provided capabilities\n for (const capability of manifest.provides) {\n if (this.capabilities.has(capability)) {\n throw new PluginRegistrationError(\n `Capability ${capability} is already provided by plugin ${this.capabilities.get(capability)}`,\n );\n }\n this.capabilities.set(capability, manifest.id);\n }\n\n // Store plugin and manifest\n this.plugins.set(manifest.id, plugin);\n this.manifests.set(manifest.id, manifest);\n this.status.set(manifest.id, 'registered');\n this.configurations.set(manifest.id, finalConfig);\n\n try {\n if (plugin.initialize) {\n await plugin.initialize(finalConfig);\n }\n this.status.set(manifest.id, 'active');\n\n this.logger.info(\n 'PluginRegistry',\n 'PluginInitialized',\n `Plugin ${manifest.id} initialized successfully`,\n );\n } catch (error) {\n // Cleanup on initialization failure\n this.plugins.delete(manifest.id);\n this.manifests.delete(manifest.id);\n this.logger.error(\n 'PluginRegistry',\n 'InitializationFailed',\n `Plugin ${manifest.id} initialization failed`,\n { provides: manifest.provides, error },\n );\n manifest.provides.forEach((cap) => this.capabilities.delete(cap));\n throw error;\n }\n }\n\n getPluginConfig<TConfig>(pluginId: string): TConfig {\n const config = this.configurations.get(pluginId);\n if (!config) {\n throw new PluginNotFoundError(`Configuration for plugin ${pluginId} not found`);\n }\n return config as TConfig;\n }\n\n private validateConfig(pluginId: string, config: unknown, defaultConfig: unknown): void {\n // Check all required fields exist\n const requiredKeys = Object.keys(defaultConfig as object);\n const missingKeys = requiredKeys.filter((key) => !(config as object).hasOwnProperty(key));\n\n if (missingKeys.length > 0) {\n throw new PluginConfigurationError(\n `Missing required configuration keys for plugin ${pluginId}: ${missingKeys.join(', ')}`,\n );\n }\n\n // You could add more validation here:\n // - Type checking\n // - Value range validation\n // - Format validation\n // etc.\n }\n\n async updatePluginConfig<TConfig>(pluginId: string, config: Partial<TConfig>): Promise<void> {\n const plugin = this.getPlugin(pluginId);\n\n if (!plugin) {\n throw new PluginNotFoundError(`Plugin ${pluginId} not found`);\n }\n\n const manifest = this.manifests.get(pluginId);\n const currentConfig = this.configurations.get(pluginId);\n\n if (!manifest || !currentConfig) {\n throw new PluginNotFoundError(`Plugin ${pluginId} not found`);\n }\n\n // Merge new config with current\n const newConfig = {\n ...currentConfig,\n ...config,\n };\n\n // Validate new configuration\n this.validateConfig(pluginId, newConfig, manifest.defaultConfig);\n\n // Store new configuration\n this.configurations.set(pluginId, newConfig);\n\n // Reinitialize plugin if needed\n if (plugin.initialize) {\n await plugin.initialize(newConfig);\n }\n }\n\n /**\n * Register multiple plugins at once\n */\n registerPluginBatch(registrations: PluginBatchRegistration<IPlugin<any>, any, any, any>[]): void {\n for (const reg of registrations) {\n this.registerPlugin(reg.package, reg.config);\n }\n }\n\n /**\n * Unregister a plugin\n */\n async unregisterPlugin(pluginId: string): Promise<void> {\n const plugin = this.plugins.get(pluginId);\n if (!plugin) {\n throw new PluginNotFoundError(`Plugin ${pluginId} is not registered`);\n }\n\n const manifest = this.manifests.get(pluginId);\n if (!manifest) {\n throw new PluginNotFoundError(`Manifest for plugin ${pluginId} not found`);\n }\n\n // Check if any other plugins depend on this one\n for (const [otherId, otherManifest] of this.manifests.entries()) {\n if (otherId === pluginId) continue;\n\n const dependsOnThis = [...otherManifest.requires, ...otherManifest.optional].some((cap) =>\n manifest.provides.includes(cap),\n );\n\n if (dependsOnThis) {\n throw new PluginRegistrationError(\n `Cannot unregister plugin ${pluginId}: plugin ${otherId} depends on it`,\n );\n }\n }\n\n // Cleanup plugin\n try {\n if (plugin.destroy) {\n await plugin.destroy();\n }\n\n // Remove capabilities\n for (const capability of manifest.provides) {\n this.capabilities.delete(capability);\n }\n\n // Remove plugin and manifest\n this.plugins.delete(pluginId);\n this.manifests.delete(pluginId);\n this.status.delete(pluginId);\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to unregister plugin ${pluginId}: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * Get a plugin instance\n * @param pluginId The ID of the plugin to get\n * @returns The plugin instance or null if not found\n */\n getPlugin<T extends IPlugin>(pluginId: string): T | null {\n const plugin = this.plugins.get(pluginId);\n if (!plugin) {\n return null;\n }\n return plugin as T;\n }\n\n /**\n * Get a plugin that provides a specific capability\n * @param capability The capability to get a provider for\n * @returns The plugin providing the capability or null if not found\n */\n getCapabilityProvider(capability: string): IPlugin | null {\n const pluginId = this.capabilities.get(capability);\n if (!pluginId) {\n return null;\n }\n return this.getPlugin(pluginId);\n }\n\n /**\n * Check if a capability is available\n */\n hasCapability(capability: string): boolean {\n return this.capabilities.has(capability);\n }\n\n /**\n * Get all registered plugins\n */\n getAllPlugins(): IPlugin[] {\n return Array.from(this.plugins.values());\n }\n\n /**\n * Get plugin status\n */\n getPluginStatus(pluginId: string): PluginStatus {\n const status = this.status.get(pluginId);\n if (!status) {\n throw new PluginNotFoundError(`Plugin ${pluginId} not found`);\n }\n return status;\n }\n\n /**\n * Validate plugin object\n */\n private validatePlugin(plugin: IPlugin): void {\n if (!plugin.id) {\n throw new PluginRegistrationError('Plugin must have an id');\n }\n }\n\n /**\n * Validate plugin manifest\n */\n private validateManifest(manifest: PluginManifest): void {\n if (!manifest.id) {\n throw new PluginRegistrationError('Manifest must have an id');\n }\n if (!manifest.name) {\n throw new PluginRegistrationError('Manifest must have a name');\n }\n if (!manifest.version) {\n throw new PluginRegistrationError('Manifest must have a version');\n }\n if (!Array.isArray(manifest.provides)) {\n throw new PluginRegistrationError('Manifest must have a provides array');\n }\n if (!Array.isArray(manifest.requires)) {\n throw new PluginRegistrationError('Manifest must have a requires array');\n }\n if (!Array.isArray(manifest.optional)) {\n throw new PluginRegistrationError('Manifest must have an optional array');\n }\n }\n\n isDestroyed(): boolean {\n return this.destroyed;\n }\n\n /**\n * DESTROY EVERYTHING – waits for any ongoing initialise(), once *\n */\n async destroy(): Promise<void> {\n if (this.destroyed) throw new PluginRegistrationError('Registry has already been destroyed');\n this.destroyed = true;\n\n // If initialisation is still underway, wait (success OR failure)\n try {\n await this.initPromise;\n } catch {\n /* ignore – still need to clean up */\n }\n\n /* ------- original teardown, unchanged except the guard ------ */\n for (const plugin of Array.from(this.plugins.values()).reverse()) {\n await plugin.destroy?.();\n }\n\n this.store.destroy();\n\n this.plugins.clear();\n this.manifests.clear();\n this.capabilities.clear();\n this.status.clear();\n this.pendingRegistrations.length = 0;\n this.processingRegistrations.length = 0;\n }\n}\n","import { EventControl, EventControlOptions } from './event-control';\nimport { arePropsEqual } from './math';\n\n/* ------------------------------------------------------------------ */\n/* basic types */\n/* ------------------------------------------------------------------ */\nexport type Listener<T = any> = (value: T) => void;\nexport type Unsubscribe = () => void;\n\n/* ------------------------------------------------------------------ */\n/* EventListener */\n/* ------------------------------------------------------------------ */\nexport type EventListener<T> =\n | ((listener: Listener<T>) => Unsubscribe)\n | ((listener: Listener<T>, options?: EventControlOptions) => Unsubscribe);\n\n/* ------------------------------------------------------------ */\n/* helpers for typing `.on()` with an optional second argument */\n/* ------------------------------------------------------------ */\nexport type EventHook<T = any> = EventListener<T>;\n/* ------------------------------------------------------------------ */\n/* minimal “dumb” emitter (no value cache, no equality) */\n/* ------------------------------------------------------------------ */\nexport interface Emitter<T = any> {\n emit(value?: T): void;\n on(listener: Listener<T>): Unsubscribe;\n off(listener: Listener<T>): void;\n clear(): void;\n}\n\nexport function createEmitter<T = any>(): Emitter<T> {\n const listeners = new Set<Listener<T>>();\n\n const on: EventHook<T> = (l: Listener<T>) => {\n listeners.add(l);\n return () => listeners.delete(l);\n };\n\n return {\n emit: (v = undefined as T) => listeners.forEach((l) => l(v)),\n on,\n off: (l) => listeners.delete(l),\n clear: () => listeners.clear(),\n };\n}\n\n/* ------------------------------------------------------------ */\n/* public interface */\n/* ------------------------------------------------------------ */\nexport interface BehaviorEmitter<T = any> extends Omit<Emitter<T>, 'on' | 'off'> {\n readonly value?: T;\n on: EventHook<T>;\n off(listener: Listener<T>): void;\n select<U>(selector: (v: T) => U, equality?: (a: U, b: U) => boolean): EventHook<U>;\n}\n\n/* ------------------------------------------------------------ */\n/* implementation */\n/* ------------------------------------------------------------ */\nexport function createBehaviorEmitter<T = any>(\n initial?: T,\n equality: (a: T, b: T) => boolean = arePropsEqual,\n): BehaviorEmitter<T> {\n const listeners = new Set<Listener<T>>();\n const proxyMap = new Map<Listener<T>, { wrapped: Listener<T>; destroy: () => void }>();\n let _value = initial; // cached value\n\n /* -------------- helpers ----------------------------------- */\n const notify = (v: T) => listeners.forEach((l) => l(v));\n\n const baseOn: EventHook<T> = (listener: Listener<T>, options?: EventControlOptions) => {\n /* wrap & remember if we have control options ------------------ */\n let realListener = listener;\n let destroy = () => {};\n\n if (options) {\n const ctl = new EventControl(listener, options);\n realListener = ctl.handle as Listener<T>;\n destroy = () => ctl.destroy();\n proxyMap.set(listener, { wrapped: realListener, destroy });\n }\n\n /* immediate replay of last value ------------------------------ */\n if (_value !== undefined) realListener(_value);\n\n listeners.add(realListener);\n\n return () => {\n listeners.delete(realListener);\n destroy();\n proxyMap.delete(listener);\n };\n };\n\n /* -------------- public object ------------------------------ */\n return {\n /* emitter behaviour ---------------------------------------- */\n get value() {\n return _value;\n },\n\n emit(v = undefined as T) {\n if (_value === undefined || !equality(_value, v)) {\n _value = v;\n notify(v);\n }\n },\n\n on: baseOn,\n off(listener: Listener<T>) {\n /* did we wrap this listener? */\n const proxy = proxyMap.get(listener);\n if (proxy) {\n listeners.delete(proxy.wrapped);\n proxy.destroy();\n proxyMap.delete(listener);\n } else {\n listeners.delete(listener);\n }\n },\n\n clear() {\n listeners.clear();\n proxyMap.forEach((p) => p.destroy());\n proxyMap.clear();\n },\n\n /* derived hook --------------------------------------------- */\n select<U>(selector: (v: T) => U, eq: (a: U, b: U) => boolean = arePropsEqual): EventHook<U> {\n return (listener: Listener<U>, options?: EventControlOptions) => {\n let prev: U | undefined;\n\n /* replay */\n if (_value !== undefined) {\n const mapped = selector(_value);\n prev = mapped;\n listener(mapped);\n }\n\n /* subscribe to parent */\n return baseOn(\n (next) => {\n const mapped = selector(next);\n if (prev === undefined || !eq(prev, mapped)) {\n prev = mapped;\n listener(mapped);\n }\n },\n options as EventControlOptions | undefined,\n ); // pass control opts straight through\n };\n },\n };\n}\n","import { Action } from '../store';\nimport { IPlugin, PluginBatchRegistration, PluginPackage } from '../types/plugin';\n\n/**\n * Helper function to create a properly typed plugin registration\n */\nexport function createPluginRegistration<\n T extends IPlugin<TConfig>,\n TConfig,\n TState,\n TAction extends Action,\n>(\n pluginPackage: PluginPackage<T, TConfig, TState, TAction>,\n config?: Partial<TConfig>,\n): PluginBatchRegistration<T, TConfig, any, any> {\n return {\n package: pluginPackage,\n config,\n };\n}\n","/* ------------------------------------------------------------------ */\n/* enumEntries – iterate over enum-keyed Records with strong typing */\n/* ------------------------------------------------------------------ */\n\ntype EnumKey = string | number;\n\n/**\n * Iterate over a Record whose keys are enum members (numeric or string),\n * getting back a fully-typed `[key, value]` tuple array.\n *\n * Usage:\n * for (const [subtype, defaults] of enumEntries(this.state.toolDefaults)) {\n * // subtype is inferred as keyof ToolDefaultsBySubtype\n * }\n */\nexport function enumEntries<E extends EnumKey, V>(record: Record<E, V>): Array<[E, V]> {\n // Tell TS the values are V (not unknown) *before* we map.\n return (Object.entries(record) as [string, V][]).map(([k, v]) => {\n // Numeric enums come out of Object.entries as \"0\", \"1\", … → convert.\n const maybeNum = Number(k);\n const typedKey: E =\n Number.isFinite(maybeNum) && k.trim() !== '' // looks like a number?\n ? (maybeNum as unknown as E) // numeric enum key\n : (k as unknown as E); // string enum key\n\n return [typedKey, v]; // v is already typed as V\n });\n}\n","import { CoreState } from './initial-state';\nimport { transformSize, PdfPageObjectWithRotatedSize } from '@embedpdf/models';\n\nexport const getPagesWithRotatedSize = (state: CoreState): PdfPageObjectWithRotatedSize[][] => {\n return state.pages.map((page) =>\n page.map((p) => ({\n ...p,\n rotatedSize: transformSize(p.size, state.rotation, 1),\n })),\n );\n};\n"],"names":["DependencyResolver","constructor","this","dependencyGraph","Map","addNode","id","dependencies","set","Set","hasCircularDependencies","visited","recursionStack","dfs","add","get","dep","has","delete","keys","resolveLoadOrder","Error","result","temp","visit","push","PluginRegistrationError","message","super","name","PluginNotFoundError","CircularDependencyError","CapabilityNotFoundError","CapabilityConflictError","PluginInitializationError","PluginConfigurationError","PluginStore","store","pluginId","getState","plugins","dispatch","action","dispatchToPlugin","subscribeToState","listener","subscribeToPlugin","newPluginState","oldPluginState","onAction","type","handler","state","oldState","LOAD_DOCUMENT","REFRESH_DOCUMENT","REFRESH_PAGES","SET_DOCUMENT","SET_DOCUMENT_ERROR","SET_SCALE","SET_ROTATION","SET_PAGES","CORE_ACTION_TYPES","Store","reducer","initialCoreState","pluginReducers","listeners","pluginListeners","core","coreReducer","addPluginReducer","initialState","dispatchToCore","newState","forEach","notifyGlobal","oldGlobalState","newGlobalState","isCoreAction","subscribe","filter","l","length","getPluginStore","includes","destroy","_b","_a","splice","call","config","scale","rotation","Rotation","Degree0","document","pages","loading","error","payload","map","page","EventControl","options","lastRun","handle","data","mode","debounce","throttle","timeoutId","window","clearTimeout","setTimeout","wait","now","Date","throttleMode","arePropsEqual","a","b","aType","pairId","objectId","getPairId","aIsArray","Array","isArray","bIsArray","used","fill","outer","i","elemA","j","arraysEqualUnordered","aKeys","Object","sort","bKeys","key","objectsEqual","objectIdCounter","objectIds","WeakMap","obj","registry","debouncedActions","unsubscribeFromState","unsubscribeFromCoreStore","engine","getEngine","logger","getLogger","coreStore","getStore","pluginStore","onStoreUpdated","onCoreStoreUpdated","readyPromise","Promise","resolve","readyResolve","provides","_capability","cap","buildCapability","freeze","coreState","getCoreState","dispatchCoreAction","dispatchToAllPlugins","debouncedDispatch","debounceTime","subscribeToCoreStore","ready","markReady","resetReady","manifests","capabilities","status","configurations","engineInitialized","initPromise","pendingRegistrations","processingRegistrations","initialized","isInitializing","pluginsReadyPromise","destroyed","resolver","NoopLogger","ensureEngineInitialized","initialize","task","toPromise","registerPlugin","pluginPackage","validateManifest","manifest","defaultConfig","package","pluginsReady","readyPromises","from","values","p","all","reg","dependsOn","allDeps","requires","optional","provider","find","r","loadOrder","initializePlugin","create","plugin","postInitialize","catch","e","console","err","packageCreator","finalConfig","validateConfig","validatePlugin","capability","debug","info","getPluginConfig","missingKeys","hasOwnProperty","join","updatePluginConfig","getPlugin","currentConfig","newConfig","registerPluginBatch","registrations","unregisterPlugin","otherId","otherManifest","entries","some","getCapabilityProvider","hasCapability","getAllPlugins","getPluginStatus","version","isDestroyed","reverse","clear","value","min","max","initial","equality","proxyMap","_value","baseOn","realListener","ctl","wrapped","emit","v","notify","on","off","proxy","select","selector","eq","prev","mapped","next","record","k","maybeNum","Number","isFinite","trim","rotatedSize","transformSize","size"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/lib/utils/dependency-resolver.ts","../src/lib/types/errors.ts","../src/lib/store/plugin-store.ts","../src/lib/store/actions.ts","../src/lib/store/store.ts","../src/lib/store/initial-state.ts","../src/lib/store/reducer.ts","../src/lib/utils/event-control.ts","../src/lib/utils/math.ts","../src/lib/plugin/builder.ts","../src/lib/base/base-plugin.ts","../src/lib/registry/plugin-registry.ts","../src/lib/utils/eventing.ts","../src/lib/utils/plugin-helpers.ts","../src/lib/utils/typed-object.ts","../src/lib/store/selectors.ts","../src/lib/types/plugin.ts"],"sourcesContent":["export class DependencyResolver {\n private dependencyGraph = new Map<string, Set<string>>();\n\n addNode(id: string, dependencies: string[] = []) {\n this.dependencyGraph.set(id, new Set(dependencies));\n }\n\n private hasCircularDependencies(): boolean {\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n\n const dfs = (id: string): boolean => {\n visited.add(id);\n recursionStack.add(id);\n\n const dependencies = this.dependencyGraph.get(id) || new Set();\n for (const dep of dependencies) {\n if (!visited.has(dep)) {\n if (dfs(dep)) return true;\n } else if (recursionStack.has(dep)) {\n return true; // Circular dependency found\n }\n }\n\n recursionStack.delete(id);\n return false;\n };\n\n for (const id of this.dependencyGraph.keys()) {\n if (!visited.has(id)) {\n if (dfs(id)) return true;\n }\n }\n\n return false;\n }\n\n resolveLoadOrder(): string[] {\n if (this.hasCircularDependencies()) {\n throw new Error('Circular dependencies detected');\n }\n\n const result: string[] = [];\n const visited = new Set<string>();\n const temp = new Set<string>();\n\n const visit = (id: string) => {\n if (temp.has(id)) throw new Error('Circular dependency');\n if (visited.has(id)) return;\n\n temp.add(id);\n\n const dependencies = this.dependencyGraph.get(id) || new Set();\n for (const dep of dependencies) {\n visit(dep);\n }\n\n temp.delete(id);\n visited.add(id);\n result.push(id);\n };\n\n for (const id of this.dependencyGraph.keys()) {\n if (!visited.has(id)) {\n visit(id);\n }\n }\n\n return result;\n }\n}\n","export class PluginRegistrationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PluginRegistrationError';\n }\n}\n\nexport class PluginNotFoundError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PluginNotFoundError';\n }\n}\n\nexport class CircularDependencyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CircularDependencyError';\n }\n}\n\nexport class CapabilityNotFoundError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CapabilityNotFoundError';\n }\n}\n\n// You might also want to add:\nexport class CapabilityConflictError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CapabilityConflictError';\n }\n}\n\nexport class PluginInitializationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PluginInitializationError';\n }\n}\n\nexport class PluginConfigurationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PluginConfigurationError';\n }\n}\n","import { Store } from './store';\nimport { Action } from './types';\n\n/**\n * A type-safe store handle for plugins, providing access to plugin-specific state and actions.\n */\nexport class PluginStore<PluginState, PluginAction extends Action> {\n private store: Store<any, any>;\n private pluginId: string;\n\n /**\n * Initializes the PluginStore with the main store and plugin ID.\n * @param store The main store instance.\n * @param pluginId The unique identifier for the plugin.\n */\n constructor(store: Store<any, any>, pluginId: string) {\n this.store = store;\n this.pluginId = pluginId;\n }\n\n /**\n * Gets the current state of the plugin.\n * @returns The plugin's state.\n */\n getState(): PluginState {\n return this.store.getState().plugins[this.pluginId] as PluginState;\n }\n\n /**\n * Dispatches an action for the plugin and returns the *new* global state.\n * If you only need the plugin’s updated state, call `getState()` afterward.\n * @param action The action to dispatch.\n * @returns The updated global store state (after plugin reducer).\n */\n dispatch(action: PluginAction): PluginState {\n return this.store.dispatchToPlugin(this.pluginId, action);\n }\n\n /**\n * Subscribes to state changes only for this specific plugin.\n * You now receive (action, newPluginState, oldPluginState) in the callback.\n *\n * @param listener The callback to invoke when plugin state changes.\n * @returns A function to unsubscribe the listener.\n */\n subscribeToState(\n listener: (action: PluginAction, newState: PluginState, oldState: PluginState) => void,\n ) {\n return this.store.subscribeToPlugin(this.pluginId, (action, newPluginState, oldPluginState) => {\n listener(\n action as PluginAction,\n newPluginState as PluginState,\n oldPluginState as PluginState,\n );\n });\n }\n\n /**\n * Subscribes to a specific action type for the plugin.\n * This still uses the main store's `onAction`, so you get the *global*\n * old/new store states there. If you specifically want old/new plugin state,\n * use `subscribeToState` instead.\n *\n * @param type The action type to listen for.\n * @param handler The callback to invoke when the action occurs.\n * @returns A function to unsubscribe the handler.\n */\n onAction<T extends PluginAction['type']>(\n type: T,\n handler: (\n action: Extract<PluginAction, { type: T }>,\n state: PluginState,\n oldState: PluginState,\n ) => void,\n ) {\n return this.store.onAction(type, (action, state, oldState) => {\n handler(\n action as Extract<PluginAction, { type: T }>,\n state.plugins[this.pluginId] as PluginState,\n oldState.plugins[this.pluginId] as PluginState,\n );\n });\n }\n}\n","import { PdfDocumentObject, PdfPageObject, Rotation } from '@embedpdf/models';\n\nexport const LOAD_DOCUMENT = 'LOAD_DOCUMENT';\nexport const REFRESH_DOCUMENT = 'REFRESH_DOCUMENT';\nexport const REFRESH_PAGES = 'REFRESH_PAGES';\nexport const SET_DOCUMENT = 'SET_DOCUMENT';\nexport const SET_DOCUMENT_ERROR = 'SET_DOCUMENT_ERROR';\nexport const SET_SCALE = 'SET_SCALE';\nexport const SET_ROTATION = 'SET_ROTATION';\nexport const SET_PAGES = 'SET_PAGES';\n\nexport const CORE_ACTION_TYPES = [\n LOAD_DOCUMENT,\n REFRESH_DOCUMENT,\n SET_DOCUMENT,\n SET_DOCUMENT_ERROR,\n SET_SCALE,\n SET_ROTATION,\n SET_PAGES,\n] as const;\n\n// Action Type Interfaces\nexport interface LoadDocumentAction {\n type: typeof LOAD_DOCUMENT;\n}\n\nexport interface RefreshDocumentAction {\n type: typeof REFRESH_DOCUMENT;\n payload: PdfDocumentObject;\n}\n\nexport interface RefreshPagesAction {\n type: typeof REFRESH_PAGES;\n payload: number[];\n}\n\nexport interface SetDocumentAction {\n type: typeof SET_DOCUMENT;\n payload: PdfDocumentObject;\n}\n\nexport interface SetDocumentErrorAction {\n type: typeof SET_DOCUMENT_ERROR;\n payload: string;\n}\n\nexport interface SetScaleAction {\n type: typeof SET_SCALE;\n payload: number;\n}\n\nexport interface SetRotationAction {\n type: typeof SET_ROTATION;\n payload: Rotation;\n}\n\nexport interface SetPagesAction {\n type: typeof SET_PAGES;\n payload: PdfPageObject[][];\n}\n\nexport type DocumentAction =\n | LoadDocumentAction\n | RefreshDocumentAction\n | RefreshPagesAction\n | SetDocumentAction\n | SetDocumentErrorAction\n | SetScaleAction\n | SetRotationAction\n | SetPagesAction;\n\n// Core actions\nexport type CoreAction = DocumentAction;\n\nexport const loadDocument = (): CoreAction => ({ type: LOAD_DOCUMENT });\nexport const refreshDocument = (document: PdfDocumentObject): CoreAction => ({\n type: REFRESH_DOCUMENT,\n payload: document,\n});\nexport const refreshPages = (pages: number[]): CoreAction => ({\n type: REFRESH_PAGES,\n payload: pages,\n});\nexport const setDocument = (document: PdfDocumentObject): CoreAction => ({\n type: SET_DOCUMENT,\n payload: document,\n});\nexport const setDocumentError = (error: string): CoreAction => ({\n type: SET_DOCUMENT_ERROR,\n payload: error,\n});\nexport const setScale = (scale: number): CoreAction => ({ type: SET_SCALE, payload: scale });\nexport const setRotation = (rotation: Rotation): CoreAction => ({\n type: SET_ROTATION,\n payload: rotation,\n});\nexport const setPages = (pages: PdfPageObject[][]): CoreAction => ({\n type: SET_PAGES,\n payload: pages,\n});\n","import { Reducer, Action, StoreState, StoreListener, PluginListener } from './types';\nimport { PluginStore } from './plugin-store';\nimport { CORE_ACTION_TYPES } from './actions';\n\n/**\n * A generic, type-safe store class managing core and plugin states, reducers, and subscriptions.\n * @template CoreState The type of the core state.\n * @template CoreAction The type of actions handled by core reducers (extends Action).\n */\nexport class Store<CoreState, CoreAction extends Action = Action> {\n private state: StoreState<CoreState>;\n private coreReducer: Reducer<CoreState, CoreAction>;\n private pluginReducers: Record<string, Reducer<any, Action>> = {};\n\n private listeners: StoreListener<CoreState>[] = [];\n private pluginListeners: Record<string, PluginListener[]> = {};\n\n /**\n * Initializes the store with the provided core state.\n * @param reducer The core reducer function\n * @param initialCoreState The initial core state\n */\n constructor(\n reducer: Reducer<CoreState, CoreAction>,\n public initialCoreState: CoreState,\n ) {\n this.state = { core: initialCoreState, plugins: {} };\n this.coreReducer = reducer;\n }\n\n /**\n * Adds a reducer for a plugin-specific state.\n * @param pluginId The unique identifier for the plugin.\n * @param reducer The reducer function for the plugin state.\n * @param initialState The initial state for the plugin.\n */\n addPluginReducer<PluginState>(\n pluginId: string,\n reducer: Reducer<PluginState, Action>,\n initialState: PluginState,\n ) {\n this.state.plugins[pluginId] = initialState;\n this.pluginReducers[pluginId] = reducer;\n }\n\n /**\n * Dispatches an action *only* to the core reducer.\n * Notifies the global store listeners with (action, newState, oldState).\n *\n * @param action The action to dispatch, typed as CoreAction\n * @returns The updated *global* store state\n */\n dispatchToCore(action: CoreAction): StoreState<CoreState> {\n if (!this.coreReducer) {\n return this.getState();\n }\n\n const oldState = this.getState();\n // Update core state via its reducer\n this.state.core = this.coreReducer(this.state.core, action);\n\n const newState = this.getState();\n // Notify all main-store subscribers\n this.listeners.forEach((listener) => listener(action, newState, oldState));\n\n return newState;\n }\n\n /**\n * Dispatches an action *only* to a specific plugin.\n * Optionally notifies global store listeners if `notifyGlobal` is true.\n * Always notifies plugin-specific listeners with (action, newPluginState, oldPluginState).\n *\n * @param pluginId The plugin identifier\n * @param action The plugin action to dispatch\n * @param notifyGlobal Whether to also notify global store listeners\n * @returns The updated *global* store state\n */\n dispatchToPlugin<PluginAction extends Action>(\n pluginId: string,\n action: PluginAction,\n notifyGlobal: boolean = true,\n ): any {\n const oldGlobalState = this.getState();\n\n const reducer = this.pluginReducers[pluginId];\n if (!reducer) {\n // No plugin found, just return the old state\n return oldGlobalState;\n }\n\n // Grab the old plugin state\n const oldPluginState = oldGlobalState.plugins[pluginId];\n // Reduce to new plugin state\n const newPluginState = reducer(oldPluginState, action);\n // Update the store's plugin slice\n this.state.plugins[pluginId] = newPluginState;\n\n const newGlobalState = this.getState();\n\n // If we are notifying the main store subscribers about plugin changes\n if (notifyGlobal) {\n this.listeners.forEach((listener) => listener(action, newGlobalState, oldGlobalState));\n }\n\n // Notify plugin-specific listeners\n if (this.pluginListeners[pluginId]) {\n this.pluginListeners[pluginId].forEach((listener) => {\n listener(action, newPluginState, oldPluginState);\n });\n }\n\n return newPluginState;\n }\n\n /**\n * Dispatches an action to update the state using:\n * - the core reducer (if it's a CoreAction)\n * - *all* plugin reducers (regardless of action type), with no global notify for each plugin\n *\n * Returns the new *global* store state after all reducers have processed the action.\n *\n * @param action The action to dispatch (can be CoreAction or any Action).\n */\n dispatch(action: CoreAction | Action): StoreState<CoreState> {\n // Keep old state to notify global listeners *once*, after all reducers run.\n const oldState = this.getState();\n // 1) Apply core reducer (only if action is a CoreAction)\n if (this.isCoreAction(action)) {\n this.state.core = this.coreReducer(this.state.core, action);\n }\n\n // 2) Apply plugin reducers (without globally notifying after each plugin)\n for (const pluginId in this.pluginReducers) {\n const reducer = this.pluginReducers[pluginId];\n const oldPluginState = oldState.plugins[pluginId];\n if (reducer) {\n this.state.plugins[pluginId] = reducer(oldPluginState, action);\n }\n // We do *not* notify global listeners or plugin listeners here,\n // as that might be undesired \"fan-out\". If you want per-plugin subscription\n // triggered on every dispatch, you can do so here, but that’s up to you.\n }\n\n // 3) Notify global listeners *once* with the final new state\n const newState = this.getState();\n this.listeners.forEach((listener) => listener(action, newState, oldState));\n\n // 4) Return the new global store state\n return newState;\n }\n\n /**\n * Returns a shallow copy of the current state.\n * @returns The current store state.\n */\n getState(): StoreState<CoreState> {\n return {\n core: { ...this.state.core },\n plugins: { ...this.state.plugins },\n };\n }\n\n /**\n * Subscribes a listener to *global* state changes.\n * The callback signature is now (action, newState, oldState).\n *\n * @param listener The callback to invoke on state changes\n * @returns A function to unsubscribe the listener\n */\n subscribe(listener: StoreListener<CoreState>) {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n /**\n * Subscribes a listener to *plugin-specific* state changes.\n * The callback signature is now (action, newPluginState, oldPluginState).\n *\n * @param pluginId The unique identifier for the plugin.\n * @param listener The callback to invoke on plugin state changes.\n * @returns A function to unsubscribe the listener.\n */\n subscribeToPlugin(pluginId: string, listener: PluginListener) {\n if (!(pluginId in this.state.plugins)) {\n throw new Error(\n `Plugin state not found for plugin \"${pluginId}\". Did you forget to call addPluginReducer?`,\n );\n }\n\n if (!this.pluginListeners[pluginId]) {\n this.pluginListeners[pluginId] = [];\n }\n this.pluginListeners[pluginId].push(listener);\n\n return () => {\n this.pluginListeners[pluginId] = this.pluginListeners[pluginId].filter((l) => l !== listener);\n if (this.pluginListeners[pluginId].length === 0) {\n delete this.pluginListeners[pluginId];\n }\n };\n }\n\n /**\n * Subscribes to a specific action type (only from the core's action union).\n * The callback signature is (action, newState, oldState).\n *\n * @param type The action type to listen for.\n * @param handler The callback to invoke when the action occurs.\n * @returns A function to unsubscribe the handler.\n */\n onAction<T extends CoreAction['type']>(\n type: T,\n handler: (\n action: Extract<CoreAction, { type: T }>,\n state: StoreState<CoreState>,\n oldState: StoreState<CoreState>,\n ) => void,\n ) {\n return this.subscribe((action, newState, oldState) => {\n if (action.type === type) {\n handler(action as Extract<CoreAction, { type: T }>, newState, oldState);\n }\n });\n }\n\n /**\n * Gets a PluginStore handle for a specific plugin.\n * @param pluginId The unique identifier for the plugin.\n * @returns A PluginStore instance for the plugin.\n */\n getPluginStore<PluginState, PluginAction extends Action>(\n pluginId: string,\n ): PluginStore<PluginState, PluginAction> {\n if (!(pluginId in this.state.plugins)) {\n throw new Error(\n `Plugin state not found for plugin \"${pluginId}\". Did you forget to call addPluginReducer?`,\n );\n }\n return new PluginStore<PluginState, PluginAction>(this, pluginId);\n }\n\n /**\n * Helper method to check if an action is a CoreAction.\n * Adjust if you have a more refined way to differentiate CoreAction vs. any other Action.\n */\n public isCoreAction(action: Action): action is CoreAction {\n // In many codebases you'd do something more robust here\n // or rely on TypeScript's narrowing logic if possible.\n return CORE_ACTION_TYPES.includes(action.type as (typeof CORE_ACTION_TYPES)[number]);\n }\n\n /**\n * Destroy the store: drop every listener and plugin reducer\n */\n public destroy(): void {\n // 1. empty listener collections\n this.listeners.length = 0;\n for (const id in this.pluginListeners) {\n this.pluginListeners[id]?.splice?.(0);\n }\n this.pluginListeners = {};\n\n // 2. wipe plugin reducers and states\n this.pluginReducers = {};\n this.state.plugins = {};\n\n // 3. reset core state to initial\n this.state.core = { ...this.initialCoreState };\n }\n}\n","import { PdfDocumentObject, PdfPageObject, Rotation } from '@embedpdf/models';\nimport { PluginRegistryConfig } from '../types/plugin';\n\nexport interface CoreState {\n scale: number;\n rotation: Rotation;\n document: PdfDocumentObject | null;\n pages: PdfPageObject[][];\n loading: boolean;\n error: string | null;\n}\n\nexport const initialCoreState: (config?: PluginRegistryConfig) => CoreState = (config) => ({\n scale: config?.scale ?? 1,\n rotation: config?.rotation ?? Rotation.Degree0,\n document: null,\n pages: [],\n loading: false,\n error: null,\n});\n","import { Reducer } from './types';\nimport { CoreState } from './initial-state';\nimport {\n CoreAction,\n LOAD_DOCUMENT,\n REFRESH_DOCUMENT,\n SET_DOCUMENT,\n SET_DOCUMENT_ERROR,\n SET_PAGES,\n SET_ROTATION,\n SET_SCALE,\n} from './actions';\n\nexport const coreReducer: Reducer<CoreState, CoreAction> = (state, action): CoreState => {\n switch (action.type) {\n case LOAD_DOCUMENT:\n return {\n ...state,\n loading: true,\n error: null,\n };\n\n case SET_DOCUMENT:\n return {\n ...state,\n document: action.payload,\n pages: action.payload.pages.map((page) => [page]),\n loading: false,\n error: null,\n };\n\n case REFRESH_DOCUMENT:\n return {\n ...state,\n document: action.payload,\n pages: action.payload.pages.map((page) => [page]),\n loading: false,\n error: null,\n };\n\n case SET_ROTATION:\n return {\n ...state,\n rotation: action.payload,\n };\n\n case SET_PAGES:\n return {\n ...state,\n pages: action.payload,\n };\n\n case SET_DOCUMENT_ERROR:\n return {\n ...state,\n loading: false,\n error: action.payload,\n };\n\n case SET_SCALE:\n return {\n ...state,\n scale: action.payload,\n };\n\n default:\n return state;\n }\n};\n","export type EventHandler<T> = (data: T) => void;\n\nexport interface BaseEventControlOptions {\n wait: number;\n}\n\nexport interface DebounceOptions extends BaseEventControlOptions {\n mode: 'debounce';\n}\n\nexport interface ThrottleOptions extends BaseEventControlOptions {\n mode: 'throttle';\n throttleMode?: 'leading-trailing' | 'trailing';\n}\n\nexport type EventControlOptions = DebounceOptions | ThrottleOptions;\n\nexport class EventControl<T> {\n private timeoutId?: number;\n private lastRun: number = 0;\n\n constructor(\n private handler: EventHandler<T>,\n private options: EventControlOptions,\n ) {}\n\n handle = (data: T): void => {\n if (this.options.mode === 'debounce') {\n this.debounce(data);\n } else {\n this.throttle(data);\n }\n };\n\n private debounce(data: T): void {\n if (this.timeoutId) {\n window.clearTimeout(this.timeoutId);\n }\n\n this.timeoutId = window.setTimeout(() => {\n this.handler(data);\n this.timeoutId = undefined;\n }, this.options.wait);\n }\n\n private throttle(data: T): void {\n if (this.options.mode === 'debounce') return;\n\n const now = Date.now();\n const throttleMode = this.options.throttleMode || 'leading-trailing';\n\n if (now - this.lastRun >= this.options.wait) {\n if (throttleMode === 'leading-trailing') {\n this.handler(data);\n }\n this.lastRun = now;\n }\n\n // Always schedule the trailing execution\n if (this.timeoutId) {\n window.clearTimeout(this.timeoutId);\n }\n\n this.timeoutId = window.setTimeout(\n () => {\n this.handler(data);\n this.lastRun = Date.now();\n this.timeoutId = undefined;\n },\n this.options.wait - (now - this.lastRun),\n );\n }\n\n destroy(): void {\n if (this.timeoutId) {\n window.clearTimeout(this.timeoutId);\n }\n }\n}\n","/**\n * Restrict a numeric value to the inclusive range [min, max].\n *\n * @example\n * clamp( 5, 0, 10) // 5\n * clamp(-3, 0, 10) // 0\n * clamp(17, 0, 10) // 10\n */\nexport function clamp(value: number, min: number, max: number): number {\n return value < min ? min : value > max ? max : value;\n}\n\n/**\n * Deeply compares two values (objects, arrays, primitives)\n * with the following rules:\n * - Objects are compared ignoring property order.\n * - Arrays are compared ignoring element order (multiset comparison).\n * - Primitives are compared by strict equality.\n * - null/undefined are treated as normal primitives.\n *\n * @param a First value\n * @param b Second value\n * @param visited Used internally to detect cycles\n */\nexport function arePropsEqual(a: any, b: any, visited?: Set<any>): boolean {\n // Quick path for reference equality or same primitive\n if (a === b) {\n return true;\n }\n\n // Handle null/undefined mismatch\n if (a == null || b == null) {\n // If one is null/undefined and the other isn't, no match\n return a === b;\n }\n\n // Check types\n const aType = typeof a;\n const bType = typeof b;\n if (aType !== bType) return false;\n\n // If they are both objects or arrays, handle recursively\n if (aType === 'object') {\n // Optionally handle cyclical references\n if (!visited) visited = new Set();\n const pairId = getPairId(a, b);\n if (visited.has(pairId)) {\n // Already compared these two objects => assume true to avoid infinite recursion\n // or return false if you want to treat cycles as inequality\n return true;\n }\n visited.add(pairId);\n\n const aIsArray = Array.isArray(a);\n const bIsArray = Array.isArray(b);\n if (aIsArray && bIsArray) {\n // Compare as arrays ignoring order\n return arraysEqualUnordered(a, b, visited);\n } else if (!aIsArray && !bIsArray) {\n // Compare as plain objects (order of properties doesn't matter)\n return objectsEqual(a, b, visited);\n } else {\n // One is array, the other is object => not equal\n return false;\n }\n }\n\n // If both are function, symbol, etc. - typically we might say false\n // But you can decide your own logic for function or symbol equality\n return false;\n}\n\nfunction getPairId(a: any, b: any) {\n // Could do something more advanced. This is a cheap approach:\n // e.g. use the memory reference or an object identity approach\n return `${objectId(a)}__${objectId(b)}`;\n}\n\n/**\n * If you want stable object IDs, you'd need a WeakMap to store them.\n * This simplistic approach just calls toString on the object.\n */\nlet objectIdCounter = 0;\nconst objectIds = new WeakMap<object, number>();\n\nfunction objectId(obj: object): number {\n if (!objectIds.has(obj)) {\n objectIds.set(obj, ++objectIdCounter);\n }\n return objectIds.get(obj)!;\n}\n\nfunction arraysEqualUnordered(a: any[], b: any[], visited?: Set<any>): boolean {\n if (a.length !== b.length) return false;\n\n const used = new Array<boolean>(b.length).fill(false);\n\n // For each element in a, find an unused matching element in b\n outer: for (let i = 0; i < a.length; i++) {\n const elemA = a[i];\n for (let j = 0; j < b.length; j++) {\n if (used[j]) continue; // already used that slot\n if (arePropsEqual(elemA, b[j], visited)) {\n used[j] = true;\n continue outer; // found match for a[i], proceed\n }\n }\n // If we never found a match\n return false;\n }\n\n return true;\n}\n\nfunction objectsEqual(a: object, b: object, visited?: Set<any>): boolean {\n // Get all prop keys\n const aKeys = Object.keys(a).sort();\n const bKeys = Object.keys(b).sort();\n if (aKeys.length !== bKeys.length) return false;\n\n // Compare each property name\n for (let i = 0; i < aKeys.length; i++) {\n if (aKeys[i] !== bKeys[i]) return false;\n }\n\n // Compare each property value\n for (const key of aKeys) {\n // @ts-ignore\n const valA = a[key];\n // @ts-ignore\n const valB = b[key];\n if (!arePropsEqual(valA, valB, visited)) {\n return false;\n }\n }\n return true;\n}\n","import {\n PluginPackage,\n WithAutoMount,\n AutoMountElement,\n StandaloneComponent,\n ContainerComponent,\n IPlugin,\n} from '../types/plugin';\nimport { Action } from '../store/types';\n\nexport class PluginPackageBuilder<\n T extends IPlugin<TConfig>,\n TConfig = unknown,\n TState = unknown,\n TAction extends Action = Action,\n> {\n private package: PluginPackage<T, TConfig, TState, TAction>;\n private autoMountElements: AutoMountElement[] = [];\n\n constructor(basePackage: PluginPackage<T, TConfig, TState, TAction>) {\n this.package = basePackage;\n }\n\n addUtility(component: StandaloneComponent): this {\n this.autoMountElements.push({ component, type: 'utility' });\n return this;\n }\n\n addWrapper(component: ContainerComponent): this {\n this.autoMountElements.push({ component, type: 'wrapper' });\n return this;\n }\n\n build(): WithAutoMount<PluginPackage<T, TConfig, TState, TAction>> {\n return {\n ...this.package,\n autoMountElements: () => this.autoMountElements,\n };\n }\n}\n\n// Helper function for cleaner API\nexport function createPluginPackage<\n T extends IPlugin<TConfig>,\n TConfig = unknown,\n TState = unknown,\n TAction extends Action = Action,\n>(basePackage: PluginPackage<T, TConfig, TState, TAction>) {\n return new PluginPackageBuilder(basePackage);\n}\n","import { IPlugin } from '../types/plugin';\nimport { PluginRegistry } from '../registry/plugin-registry';\nimport { Action, CoreAction, CoreState, PluginStore, Store, StoreState } from '../store';\nimport { Logger, PdfEngine } from '@embedpdf/models';\n\nexport interface StateChangeHandler<TState> {\n (state: TState): void;\n}\n\nexport abstract class BasePlugin<\n TConfig = unknown,\n TCapability = unknown,\n TState = unknown,\n TAction extends Action = Action,\n> implements IPlugin<TConfig>\n{\n static readonly id: string;\n\n protected pluginStore: PluginStore<TState, TAction>;\n protected coreStore: Store<CoreState, CoreAction>;\n protected readonly logger: Logger;\n protected readonly engine: PdfEngine;\n\n // Track debounced actions\n private debouncedActions: Record<string, number> = {};\n private unsubscribeFromState: (() => void) | null = null;\n private unsubscribeFromCoreStore: (() => void) | null = null;\n\n private _capability?: Readonly<TCapability>;\n\n private readyPromise: Promise<void>;\n private readyResolve!: () => void;\n\n constructor(\n public readonly id: string,\n protected registry: PluginRegistry,\n ) {\n if (id !== (this.constructor as typeof BasePlugin).id) {\n throw new Error(\n `Plugin ID mismatch: ${id} !== ${(this.constructor as typeof BasePlugin).id}`,\n );\n }\n this.engine = this.registry.getEngine();\n this.logger = this.registry.getLogger();\n this.coreStore = this.registry.getStore();\n this.pluginStore = this.coreStore.getPluginStore<TState, TAction>(this.id);\n this.unsubscribeFromState = this.pluginStore.subscribeToState((action, newState, oldState) => {\n this.onStoreUpdated(oldState, newState);\n });\n this.unsubscribeFromCoreStore = this.coreStore.subscribe((action, newState, oldState) => {\n this.onCoreStoreUpdated(oldState, newState);\n });\n\n // Initialize ready state\n this.readyPromise = new Promise((resolve) => {\n this.readyResolve = resolve;\n });\n // By default, plugins are ready immediately\n this.readyResolve();\n }\n\n /** Construct the public capability (called once & cached). */\n protected abstract buildCapability(): TCapability;\n\n public provides(): Readonly<TCapability> {\n if (!this._capability) {\n const cap = this.buildCapability();\n\n this._capability = Object.freeze(cap);\n }\n return this._capability;\n }\n\n /**\n * Initialize plugin with config\n */\n abstract initialize(config: TConfig): Promise<void>;\n\n /**\n * Get a copy of the current state\n */\n protected get state(): Readonly<TState> {\n return this.pluginStore.getState();\n }\n\n /**\n * Get a copy of the current core state\n */\n protected get coreState(): Readonly<StoreState<CoreState>> {\n return this.coreStore.getState();\n }\n\n /**\n * @deprecated use `this.state` Get a copy of the current state\n */\n protected getState(): TState {\n return this.pluginStore.getState();\n }\n\n /**\n * @deprecated use `this.coreState` Get a copy of the current core state\n */\n protected getCoreState(): StoreState<CoreState> {\n return this.coreStore.getState();\n }\n\n /**\n * Core Dispatch\n */\n protected dispatchCoreAction(action: CoreAction): StoreState<CoreState> {\n return this.coreStore.dispatchToCore(action);\n }\n\n /**\n * Dispatch an action to all plugins\n */\n protected dispatchToAllPlugins(action: TAction): StoreState<CoreState> {\n return this.coreStore.dispatch(action);\n }\n\n /**\n * Dispatch an action\n */\n protected dispatch(action: TAction): TState {\n return this.pluginStore.dispatch(action);\n }\n\n /**\n * Dispatch an action with debouncing to prevent rapid repeated calls\n * @param action The action to dispatch\n * @param debounceTime Time in ms to debounce (default: 100ms)\n * @returns boolean indicating whether the action was dispatched or debounced\n */\n protected debouncedDispatch(action: TAction, debounceTime: number = 100): boolean {\n const now = Date.now();\n const lastActionTime = this.debouncedActions[action.type] || 0;\n\n if (now - lastActionTime >= debounceTime) {\n this.debouncedActions[action.type] = now;\n this.dispatch(action);\n return true;\n }\n\n return false;\n }\n\n /**\n * Subscribe to state changes\n */\n protected subscribe(listener: (action: TAction, state: TState) => void): () => void {\n return this.pluginStore.subscribeToState(listener);\n }\n\n /**\n * Subscribe to core store changes\n */\n protected subscribeToCoreStore(\n listener: (action: Action, state: StoreState<CoreState>) => void,\n ): () => void {\n return this.coreStore.subscribe(listener);\n }\n\n /**\n * Called when the plugin store state is updated\n * @param oldState Previous state\n * @param newState New state\n */\n protected onStoreUpdated(oldState: TState, newState: TState): void {\n // Default implementation does nothing - can be overridden by plugins\n }\n\n /**\n * Called when the core store state is updated\n * @param oldState Previous state\n * @param newState New state\n */\n protected onCoreStoreUpdated(\n oldState: StoreState<CoreState>,\n newState: StoreState<CoreState>,\n ): void {\n // Default implementation does nothing - can be overridden by plugins\n }\n\n /**\n * Cleanup method to be called when plugin is being destroyed\n */\n public destroy(): void {\n if (this.unsubscribeFromState) {\n this.unsubscribeFromState();\n this.unsubscribeFromState = null;\n }\n if (this.unsubscribeFromCoreStore) {\n this.unsubscribeFromCoreStore();\n this.unsubscribeFromCoreStore = null;\n }\n }\n\n /**\n * Returns a promise that resolves when the plugin is ready\n */\n public ready(): Promise<void> {\n return this.readyPromise;\n }\n\n /**\n * Mark the plugin as ready\n */\n protected markReady(): void {\n this.readyResolve();\n }\n\n /**\n * Reset the ready state (useful for plugins that need to reinitialize)\n */\n protected resetReady(): void {\n this.readyPromise = new Promise((resolve) => {\n this.readyResolve = resolve;\n });\n }\n}\n","import { DependencyResolver } from '../utils/dependency-resolver';\nimport {\n IPlugin,\n PluginBatchRegistration,\n PluginManifest,\n PluginStatus,\n PluginPackage,\n PluginRegistryConfig,\n} from '../types/plugin';\nimport {\n PluginRegistrationError,\n PluginNotFoundError,\n CircularDependencyError,\n PluginConfigurationError,\n} from '../types/errors';\nimport { Logger, NoopLogger, PdfEngine } from '@embedpdf/models';\nimport { Action, CoreState, Store, initialCoreState, Reducer } from '../store';\nimport { CoreAction } from '../store/actions';\nimport { coreReducer } from '../store/reducer';\n\n// Define a more flexible generic type for plugin registrations\ninterface PluginRegistration {\n // Use existential types for the plugin package to allow accepting any plugin type\n package: PluginPackage<any, any, any, any>;\n config?: any;\n}\n\nexport class PluginRegistry {\n private plugins: Map<string, IPlugin> = new Map();\n private manifests: Map<string, PluginManifest> = new Map();\n private capabilities: Map<string, string> = new Map(); // capability -> pluginId\n private status: Map<string, PluginStatus> = new Map();\n private resolver: DependencyResolver;\n private configurations: Map<string, unknown> = new Map();\n private engine: PdfEngine;\n private engineInitialized = false;\n private store: Store<CoreState, CoreAction>;\n private initPromise: Promise<void> | null = null;\n private logger: Logger;\n\n private pendingRegistrations: PluginRegistration[] = [];\n private processingRegistrations: PluginRegistration[] = [];\n private initialized = false;\n private isInitializing = false;\n private initialCoreState: CoreState;\n private pluginsReadyPromise: Promise<void> | null = null;\n private destroyed = false;\n\n constructor(engine: PdfEngine, config?: PluginRegistryConfig) {\n this.resolver = new DependencyResolver();\n this.engine = engine;\n this.initialCoreState = initialCoreState(config);\n this.store = new Store<CoreState, CoreAction>(coreReducer, this.initialCoreState);\n this.logger = config?.logger ?? new NoopLogger();\n }\n\n /**\n * Get the logger instance\n */\n getLogger(): Logger {\n return this.logger;\n }\n\n /**\n * Ensure engine is initialized before proceeding\n */\n private async ensureEngineInitialized(): Promise<void> {\n if (this.engineInitialized) {\n return;\n }\n\n if (this.engine.initialize) {\n const task = this.engine.initialize();\n await task.toPromise();\n this.engineInitialized = true;\n } else {\n this.engineInitialized = true;\n }\n }\n\n /**\n * Register a plugin without initializing it\n */\n registerPlugin<\n TPlugin extends IPlugin<TConfig>,\n TConfig = unknown,\n TState = unknown,\n TAction extends Action = Action,\n >(\n pluginPackage: PluginPackage<TPlugin, TConfig, TState, TAction>,\n config?: Partial<TConfig>,\n ): void {\n if (this.initialized && !this.isInitializing) {\n throw new PluginRegistrationError('Cannot register plugins after initialization');\n }\n\n this.validateManifest(pluginPackage.manifest);\n\n // Use appropriate typing for store methods\n this.store.addPluginReducer(\n pluginPackage.manifest.id,\n // We need one type assertion here since we can't fully reconcile TAction with Action\n // due to TypeScript's type system limitations with generic variance\n pluginPackage.reducer as Reducer<TState, Action>,\n 'function' === typeof pluginPackage.initialState\n ? (pluginPackage.initialState as (coreState: CoreState, config: TConfig) => TState)(\n this.initialCoreState,\n {\n ...pluginPackage.manifest.defaultConfig,\n ...config,\n },\n )\n : pluginPackage.initialState,\n );\n\n this.pendingRegistrations.push({\n package: pluginPackage,\n config,\n });\n }\n\n /**\n * Get the central store instance\n */\n getStore(): Store<CoreState, CoreAction> {\n return this.store;\n }\n\n /**\n * Get the engine instance\n */\n getEngine(): PdfEngine {\n return this.engine;\n }\n\n /**\n * Get a promise that resolves when all plugins are ready\n */\n public pluginsReady(): Promise<void> {\n // Re-use the same promise every time it’s asked for\n if (this.pluginsReadyPromise) {\n return this.pluginsReadyPromise;\n }\n\n // Build the promise the *first* time it’s requested\n this.pluginsReadyPromise = (async () => {\n // 1. Wait until the registry itself has finished initialising\n if (!this.initialized) {\n await this.initialize();\n }\n\n // 2. Wait for every plugin’s ready() promise (if it has one)\n const readyPromises = Array.from(this.plugins.values()).map((p) =>\n typeof p.ready === 'function' ? p.ready() : Promise.resolve(),\n );\n\n await Promise.all(readyPromises); // resolves when the slowest is done\n })();\n\n return this.pluginsReadyPromise;\n }\n\n /**\n * INITIALISE THE REGISTRY – runs once no-matter-how-many calls *\n */\n async initialize(): Promise<void> {\n if (this.destroyed) {\n throw new PluginRegistrationError('Registry has been destroyed');\n }\n\n // If an initialisation is already in-flight (or finished)\n // return the very same promise so callers can await it.\n if (this.initPromise) {\n return this.initPromise;\n }\n\n // Wrap your existing body in a single promise and cache it\n this.initPromise = (async () => {\n if (this.initialized) {\n throw new PluginRegistrationError('Registry is already initialized');\n }\n\n this.isInitializing = true;\n\n try {\n /* ---------------- original body starts ------------------ */\n await this.ensureEngineInitialized();\n // Check if destroyed after engine initialization\n if (this.destroyed) {\n return;\n }\n\n while (this.pendingRegistrations.length > 0) {\n // Check if destroyed before processing each batch\n if (this.destroyed) {\n return;\n }\n this.processingRegistrations = [...this.pendingRegistrations];\n this.pendingRegistrations = [];\n\n for (const reg of this.processingRegistrations) {\n const dependsOn = new Set<string>();\n const allDeps = [...reg.package.manifest.requires, ...reg.package.manifest.optional];\n for (const cap of allDeps) {\n const provider = this.processingRegistrations.find((r) =>\n r.package.manifest.provides.includes(cap),\n );\n if (provider) dependsOn.add(provider.package.manifest.id);\n }\n this.resolver.addNode(reg.package.manifest.id, [...dependsOn]);\n }\n\n const loadOrder = this.resolver.resolveLoadOrder();\n for (const id of loadOrder) {\n const reg = this.processingRegistrations.find((r) => r.package.manifest.id === id)!;\n await this.initializePlugin(reg.package.manifest, reg.package.create, reg.config);\n }\n\n this.processingRegistrations = [];\n this.resolver = new DependencyResolver();\n }\n\n for (const plugin of this.plugins.values()) {\n await plugin.postInitialize?.().catch((e) => {\n console.error(`Error in postInitialize for plugin ${plugin.id}`, e);\n this.status.set(plugin.id, 'error');\n });\n }\n\n this.initialized = true;\n /* ----------------- original body ends ------------------- */\n } catch (err) {\n if (err instanceof Error) {\n throw new CircularDependencyError(\n `Failed to resolve plugin dependencies: ${err.message}`,\n );\n }\n throw err;\n } finally {\n this.isInitializing = false;\n }\n })();\n\n return this.initPromise;\n }\n\n /**\n * Initialize a single plugin with all necessary checks\n */\n private async initializePlugin<TConfig>(\n manifest: PluginManifest<TConfig>,\n packageCreator: (registry: PluginRegistry, config?: TConfig) => IPlugin<TConfig>,\n config?: Partial<TConfig>,\n ): Promise<void> {\n const finalConfig = {\n ...manifest.defaultConfig,\n ...config,\n };\n\n this.validateConfig(manifest.id, finalConfig, manifest.defaultConfig);\n\n // Create plugin instance during initialization\n const plugin = packageCreator(this, finalConfig);\n this.validatePlugin(plugin);\n\n // Verify all required capabilities are available\n for (const capability of manifest.requires) {\n if (!this.capabilities.has(capability)) {\n throw new PluginRegistrationError(\n `Missing required capability: ${capability} for plugin ${manifest.id}`,\n );\n }\n }\n\n // Optional capabilities can be null, so we don't throw errors for them\n for (const capability of manifest.optional) {\n if (this.capabilities.has(capability)) {\n // Optional capability is available, but we don't require it\n this.logger.debug(\n 'PluginRegistry',\n 'OptionalCapability',\n `Optional capability ${capability} is available for plugin ${manifest.id}`,\n );\n }\n }\n\n this.logger.debug('PluginRegistry', 'InitializePlugin', `Initializing plugin ${manifest.id}`, {\n provides: manifest.provides,\n });\n\n // Register provided capabilities\n for (const capability of manifest.provides) {\n if (this.capabilities.has(capability)) {\n throw new PluginRegistrationError(\n `Capability ${capability} is already provided by plugin ${this.capabilities.get(capability)}`,\n );\n }\n this.capabilities.set(capability, manifest.id);\n }\n\n // Store plugin and manifest\n this.plugins.set(manifest.id, plugin);\n this.manifests.set(manifest.id, manifest);\n this.status.set(manifest.id, 'registered');\n this.configurations.set(manifest.id, finalConfig);\n\n try {\n if (plugin.initialize) {\n await plugin.initialize(finalConfig);\n }\n this.status.set(manifest.id, 'active');\n\n this.logger.info(\n 'PluginRegistry',\n 'PluginInitialized',\n `Plugin ${manifest.id} initialized successfully`,\n );\n } catch (error) {\n // Cleanup on initialization failure\n this.plugins.delete(manifest.id);\n this.manifests.delete(manifest.id);\n this.logger.error(\n 'PluginRegistry',\n 'InitializationFailed',\n `Plugin ${manifest.id} initialization failed`,\n { provides: manifest.provides, error },\n );\n manifest.provides.forEach((cap) => this.capabilities.delete(cap));\n throw error;\n }\n }\n\n getPluginConfig<TConfig>(pluginId: string): TConfig {\n const config = this.configurations.get(pluginId);\n if (!config) {\n throw new PluginNotFoundError(`Configuration for plugin ${pluginId} not found`);\n }\n return config as TConfig;\n }\n\n private validateConfig(pluginId: string, config: unknown, defaultConfig: unknown): void {\n // Check all required fields exist\n const requiredKeys = Object.keys(defaultConfig as object);\n const missingKeys = requiredKeys.filter((key) => !(config as object).hasOwnProperty(key));\n\n if (missingKeys.length > 0) {\n throw new PluginConfigurationError(\n `Missing required configuration keys for plugin ${pluginId}: ${missingKeys.join(', ')}`,\n );\n }\n\n // You could add more validation here:\n // - Type checking\n // - Value range validation\n // - Format validation\n // etc.\n }\n\n async updatePluginConfig<TConfig>(pluginId: string, config: Partial<TConfig>): Promise<void> {\n const plugin = this.getPlugin(pluginId);\n\n if (!plugin) {\n throw new PluginNotFoundError(`Plugin ${pluginId} not found`);\n }\n\n const manifest = this.manifests.get(pluginId);\n const currentConfig = this.configurations.get(pluginId);\n\n if (!manifest || !currentConfig) {\n throw new PluginNotFoundError(`Plugin ${pluginId} not found`);\n }\n\n // Merge new config with current\n const newConfig = {\n ...currentConfig,\n ...config,\n };\n\n // Validate new configuration\n this.validateConfig(pluginId, newConfig, manifest.defaultConfig);\n\n // Store new configuration\n this.configurations.set(pluginId, newConfig);\n\n // Reinitialize plugin if needed\n if (plugin.initialize) {\n await plugin.initialize(newConfig);\n }\n }\n\n /**\n * Register multiple plugins at once\n */\n registerPluginBatch(registrations: PluginBatchRegistration<IPlugin<any>, any, any, any>[]): void {\n for (const reg of registrations) {\n this.registerPlugin(reg.package, reg.config);\n }\n }\n\n /**\n * Unregister a plugin\n */\n async unregisterPlugin(pluginId: string): Promise<void> {\n const plugin = this.plugins.get(pluginId);\n if (!plugin) {\n throw new PluginNotFoundError(`Plugin ${pluginId} is not registered`);\n }\n\n const manifest = this.manifests.get(pluginId);\n if (!manifest) {\n throw new PluginNotFoundError(`Manifest for plugin ${pluginId} not found`);\n }\n\n // Check if any other plugins depend on this one\n for (const [otherId, otherManifest] of this.manifests.entries()) {\n if (otherId === pluginId) continue;\n\n const dependsOnThis = [...otherManifest.requires, ...otherManifest.optional].some((cap) =>\n manifest.provides.includes(cap),\n );\n\n if (dependsOnThis) {\n throw new PluginRegistrationError(\n `Cannot unregister plugin ${pluginId}: plugin ${otherId} depends on it`,\n );\n }\n }\n\n // Cleanup plugin\n try {\n if (plugin.destroy) {\n await plugin.destroy();\n }\n\n // Remove capabilities\n for (const capability of manifest.provides) {\n this.capabilities.delete(capability);\n }\n\n // Remove plugin and manifest\n this.plugins.delete(pluginId);\n this.manifests.delete(pluginId);\n this.status.delete(pluginId);\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to unregister plugin ${pluginId}: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * Get a plugin instance\n * @param pluginId The ID of the plugin to get\n * @returns The plugin instance or null if not found\n */\n getPlugin<T extends IPlugin>(pluginId: string): T | null {\n const plugin = this.plugins.get(pluginId);\n if (!plugin) {\n return null;\n }\n return plugin as T;\n }\n\n /**\n * Get a plugin that provides a specific capability\n * @param capability The capability to get a provider for\n * @returns The plugin providing the capability or null if not found\n */\n getCapabilityProvider(capability: string): IPlugin | null {\n const pluginId = this.capabilities.get(capability);\n if (!pluginId) {\n return null;\n }\n return this.getPlugin(pluginId);\n }\n\n /**\n * Check if a capability is available\n */\n hasCapability(capability: string): boolean {\n return this.capabilities.has(capability);\n }\n\n /**\n * Get all registered plugins\n */\n getAllPlugins(): IPlugin[] {\n return Array.from(this.plugins.values());\n }\n\n /**\n * Get plugin status\n */\n getPluginStatus(pluginId: string): PluginStatus {\n const status = this.status.get(pluginId);\n if (!status) {\n throw new PluginNotFoundError(`Plugin ${pluginId} not found`);\n }\n return status;\n }\n\n /**\n * Validate plugin object\n */\n private validatePlugin(plugin: IPlugin): void {\n if (!plugin.id) {\n throw new PluginRegistrationError('Plugin must have an id');\n }\n }\n\n /**\n * Validate plugin manifest\n */\n private validateManifest(manifest: PluginManifest): void {\n if (!manifest.id) {\n throw new PluginRegistrationError('Manifest must have an id');\n }\n if (!manifest.name) {\n throw new PluginRegistrationError('Manifest must have a name');\n }\n if (!manifest.version) {\n throw new PluginRegistrationError('Manifest must have a version');\n }\n if (!Array.isArray(manifest.provides)) {\n throw new PluginRegistrationError('Manifest must have a provides array');\n }\n if (!Array.isArray(manifest.requires)) {\n throw new PluginRegistrationError('Manifest must have a requires array');\n }\n if (!Array.isArray(manifest.optional)) {\n throw new PluginRegistrationError('Manifest must have an optional array');\n }\n }\n\n isDestroyed(): boolean {\n return this.destroyed;\n }\n\n /**\n * DESTROY EVERYTHING – waits for any ongoing initialise(), once *\n */\n async destroy(): Promise<void> {\n if (this.destroyed) throw new PluginRegistrationError('Registry has already been destroyed');\n this.destroyed = true;\n\n // If initialisation is still underway, wait (success OR failure)\n try {\n await this.initPromise;\n } catch {\n /* ignore – still need to clean up */\n }\n\n /* ------- original teardown, unchanged except the guard ------ */\n for (const plugin of Array.from(this.plugins.values()).reverse()) {\n await plugin.destroy?.();\n }\n\n this.store.destroy();\n\n this.plugins.clear();\n this.manifests.clear();\n this.capabilities.clear();\n this.status.clear();\n this.pendingRegistrations.length = 0;\n this.processingRegistrations.length = 0;\n }\n}\n","import { EventControl, EventControlOptions } from './event-control';\nimport { arePropsEqual } from './math';\n\n/* ------------------------------------------------------------------ */\n/* basic types */\n/* ------------------------------------------------------------------ */\nexport type Listener<T = any> = (value: T) => void;\nexport type Unsubscribe = () => void;\n\n/* ------------------------------------------------------------------ */\n/* EventListener */\n/* ------------------------------------------------------------------ */\nexport type EventListener<T> =\n | ((listener: Listener<T>) => Unsubscribe)\n | ((listener: Listener<T>, options?: EventControlOptions) => Unsubscribe);\n\n/* ------------------------------------------------------------ */\n/* helpers for typing `.on()` with an optional second argument */\n/* ------------------------------------------------------------ */\nexport type EventHook<T = any> = EventListener<T>;\n/* ------------------------------------------------------------------ */\n/* minimal “dumb” emitter (no value cache, no equality) */\n/* ------------------------------------------------------------------ */\nexport interface Emitter<T = any> {\n emit(value?: T): void;\n on(listener: Listener<T>): Unsubscribe;\n off(listener: Listener<T>): void;\n clear(): void;\n}\n\nexport function createEmitter<T = any>(): Emitter<T> {\n const listeners = new Set<Listener<T>>();\n\n const on: EventHook<T> = (l: Listener<T>) => {\n listeners.add(l);\n return () => listeners.delete(l);\n };\n\n return {\n emit: (v = undefined as T) => listeners.forEach((l) => l(v)),\n on,\n off: (l) => listeners.delete(l),\n clear: () => listeners.clear(),\n };\n}\n\n/* ------------------------------------------------------------ */\n/* public interface */\n/* ------------------------------------------------------------ */\nexport interface BehaviorEmitter<T = any> extends Omit<Emitter<T>, 'on' | 'off'> {\n readonly value?: T;\n on: EventHook<T>;\n off(listener: Listener<T>): void;\n select<U>(selector: (v: T) => U, equality?: (a: U, b: U) => boolean): EventHook<U>;\n}\n\n/* ------------------------------------------------------------ */\n/* implementation */\n/* ------------------------------------------------------------ */\nexport function createBehaviorEmitter<T = any>(\n initial?: T,\n equality: (a: T, b: T) => boolean = arePropsEqual,\n): BehaviorEmitter<T> {\n const listeners = new Set<Listener<T>>();\n const proxyMap = new Map<Listener<T>, { wrapped: Listener<T>; destroy: () => void }>();\n let _value = initial; // cached value\n\n /* -------------- helpers ----------------------------------- */\n const notify = (v: T) => listeners.forEach((l) => l(v));\n\n const baseOn: EventHook<T> = (listener: Listener<T>, options?: EventControlOptions) => {\n /* wrap & remember if we have control options ------------------ */\n let realListener = listener;\n let destroy = () => {};\n\n if (options) {\n const ctl = new EventControl(listener, options);\n realListener = ctl.handle as Listener<T>;\n destroy = () => ctl.destroy();\n proxyMap.set(listener, { wrapped: realListener, destroy });\n }\n\n /* immediate replay of last value ------------------------------ */\n if (_value !== undefined) realListener(_value);\n\n listeners.add(realListener);\n\n return () => {\n listeners.delete(realListener);\n destroy();\n proxyMap.delete(listener);\n };\n };\n\n /* -------------- public object ------------------------------ */\n return {\n /* emitter behaviour ---------------------------------------- */\n get value() {\n return _value;\n },\n\n emit(v = undefined as T) {\n if (_value === undefined || !equality(_value, v)) {\n _value = v;\n notify(v);\n }\n },\n\n on: baseOn,\n off(listener: Listener<T>) {\n /* did we wrap this listener? */\n const proxy = proxyMap.get(listener);\n if (proxy) {\n listeners.delete(proxy.wrapped);\n proxy.destroy();\n proxyMap.delete(listener);\n } else {\n listeners.delete(listener);\n }\n },\n\n clear() {\n listeners.clear();\n proxyMap.forEach((p) => p.destroy());\n proxyMap.clear();\n },\n\n /* derived hook --------------------------------------------- */\n select<U>(selector: (v: T) => U, eq: (a: U, b: U) => boolean = arePropsEqual): EventHook<U> {\n return (listener: Listener<U>, options?: EventControlOptions) => {\n let prev: U | undefined;\n\n /* replay */\n if (_value !== undefined) {\n const mapped = selector(_value);\n prev = mapped;\n listener(mapped);\n }\n\n /* subscribe to parent */\n return baseOn(\n (next) => {\n const mapped = selector(next);\n if (prev === undefined || !eq(prev, mapped)) {\n prev = mapped;\n listener(mapped);\n }\n },\n options as EventControlOptions | undefined,\n ); // pass control opts straight through\n };\n },\n };\n}\n","import { Action } from '../store';\nimport { IPlugin, PluginBatchRegistration, PluginPackage } from '../types/plugin';\n\n/**\n * Helper function to create a properly typed plugin registration\n */\nexport function createPluginRegistration<\n T extends IPlugin<TConfig>,\n TConfig,\n TState,\n TAction extends Action,\n>(\n pluginPackage: PluginPackage<T, TConfig, TState, TAction>,\n config?: Partial<TConfig>,\n): PluginBatchRegistration<T, TConfig, any, any> {\n return {\n package: pluginPackage,\n config,\n };\n}\n","/* ------------------------------------------------------------------ */\n/* enumEntries – iterate over enum-keyed Records with strong typing */\n/* ------------------------------------------------------------------ */\n\ntype EnumKey = string | number;\n\n/**\n * Iterate over a Record whose keys are enum members (numeric or string),\n * getting back a fully-typed `[key, value]` tuple array.\n *\n * Usage:\n * for (const [subtype, defaults] of enumEntries(this.state.toolDefaults)) {\n * // subtype is inferred as keyof ToolDefaultsBySubtype\n * }\n */\nexport function enumEntries<E extends EnumKey, V>(record: Record<E, V>): Array<[E, V]> {\n // Tell TS the values are V (not unknown) *before* we map.\n return (Object.entries(record) as [string, V][]).map(([k, v]) => {\n // Numeric enums come out of Object.entries as \"0\", \"1\", … → convert.\n const maybeNum = Number(k);\n const typedKey: E =\n Number.isFinite(maybeNum) && k.trim() !== '' // looks like a number?\n ? (maybeNum as unknown as E) // numeric enum key\n : (k as unknown as E); // string enum key\n\n return [typedKey, v]; // v is already typed as V\n });\n}\n","import { CoreState } from './initial-state';\nimport { transformSize, PdfPageObjectWithRotatedSize } from '@embedpdf/models';\n\nexport const getPagesWithRotatedSize = (state: CoreState): PdfPageObjectWithRotatedSize[][] => {\n return state.pages.map((page) =>\n page.map((p) => ({\n ...p,\n rotatedSize: transformSize(p.size, state.rotation, 1),\n })),\n );\n};\n","import { PluginRegistry } from '../registry/plugin-registry';\nimport { Logger, PdfEngine, Rotation } from '@embedpdf/models';\nimport { Action, Reducer } from '../store/types';\nimport { CoreState } from '../store';\n\nexport interface IPlugin<TConfig = unknown> {\n id: string;\n\n initialize?(config: TConfig): Promise<void>;\n destroy?(): Promise<void> | void;\n provides?(): any;\n postInitialize?(): Promise<void>;\n ready?(): Promise<void>;\n}\n\nexport interface BasePluginConfig {\n enabled?: boolean;\n}\n\nexport interface PluginRegistryConfig {\n rotation?: Rotation;\n scale?: number;\n logger?: Logger;\n}\n\nexport interface PluginManifest<TConfig = unknown> {\n id: string;\n name: string;\n version: string;\n provides: string[]; // Capabilities this plugin provides\n requires: string[]; // Mandatory capabilities\n optional: string[]; // Optional capabilities\n defaultConfig: TConfig; // Default configuration\n metadata?: {\n description?: string;\n author?: string;\n homepage?: string;\n [key: string]: unknown;\n };\n}\n\nexport interface PluginPackage<\n T extends IPlugin<TConfig>,\n TConfig = unknown,\n TState = unknown,\n TAction extends Action = Action,\n> {\n manifest: PluginManifest<TConfig>;\n create(registry: PluginRegistry, config: TConfig): T;\n reducer: Reducer<TState, TAction>;\n initialState: TState | ((coreState: CoreState, config: TConfig) => TState);\n}\n\nexport type Component = any;\n\n// Use semantic names that describe PURPOSE, not implementation\nexport type StandaloneComponent = Component; // Doesn't wrap content\nexport type ContainerComponent = Component; // Wraps/contains content\n\nexport type AutoMountElement =\n | {\n component: StandaloneComponent;\n type: 'utility';\n }\n | {\n component: ContainerComponent;\n type: 'wrapper';\n };\n\nexport type WithAutoMount<T extends PluginPackage<any, any, any, any>> = T & {\n /**\n * Returns an array of components/elements with their mount type.\n * - 'utility': Mounted as hidden DOM elements (file pickers, download anchors)\n * - 'wrapper': Wraps the viewer content (fullscreen providers, theme providers)\n */\n autoMountElements: () => AutoMountElement[];\n};\n\nexport function hasAutoMountElements<T extends PluginPackage<any, any, any, any>>(\n pkg: T,\n): pkg is WithAutoMount<T> {\n return 'autoMountElements' in pkg && typeof pkg.autoMountElements === 'function';\n}\n\nexport type PluginStatus =\n | 'registered' // Plugin is registered but not initialized\n | 'active' // Plugin is initialized and running\n | 'error' // Plugin encountered an error\n | 'disabled' // Plugin is temporarily disabled\n | 'unregistered'; // Plugin is being unregistered\n\nexport interface PluginBatchRegistration<\n T extends IPlugin<TConfig>,\n TConfig = unknown,\n TState = unknown,\n TAction extends Action = Action,\n> {\n package: PluginPackage<T, TConfig, TState, TAction>;\n config?: Partial<TConfig>;\n}\n\nexport interface GlobalStoreState<TPlugins extends Record<string, any> = {}> {\n core: CoreState;\n plugins: TPlugins;\n}\n"],"names":["DependencyResolver","constructor","this","dependencyGraph","Map","addNode","id","dependencies","set","Set","hasCircularDependencies","visited","recursionStack","dfs","add","get","dep","has","delete","keys","resolveLoadOrder","Error","result","temp","visit","push","PluginRegistrationError","message","super","name","PluginNotFoundError","CircularDependencyError","CapabilityNotFoundError","CapabilityConflictError","PluginInitializationError","PluginConfigurationError","PluginStore","store","pluginId","getState","plugins","dispatch","action","dispatchToPlugin","subscribeToState","listener","subscribeToPlugin","newPluginState","oldPluginState","onAction","type","handler","state","oldState","LOAD_DOCUMENT","REFRESH_DOCUMENT","REFRESH_PAGES","SET_DOCUMENT","SET_DOCUMENT_ERROR","SET_SCALE","SET_ROTATION","SET_PAGES","CORE_ACTION_TYPES","Store","reducer","initialCoreState","pluginReducers","listeners","pluginListeners","core","coreReducer","addPluginReducer","initialState","dispatchToCore","newState","forEach","notifyGlobal","oldGlobalState","newGlobalState","isCoreAction","subscribe","filter","l","length","getPluginStore","includes","destroy","_b","_a","splice","call","config","scale","rotation","Rotation","Degree0","document","pages","loading","error","payload","map","page","EventControl","options","lastRun","handle","data","mode","debounce","throttle","timeoutId","window","clearTimeout","setTimeout","wait","now","Date","throttleMode","arePropsEqual","a","b","aType","pairId","objectId","getPairId","aIsArray","Array","isArray","bIsArray","used","fill","outer","i","elemA","j","arraysEqualUnordered","aKeys","Object","sort","bKeys","key","objectsEqual","objectIdCounter","objectIds","WeakMap","obj","PluginPackageBuilder","basePackage","autoMountElements","package","addUtility","component","addWrapper","build","registry","debouncedActions","unsubscribeFromState","unsubscribeFromCoreStore","engine","getEngine","logger","getLogger","coreStore","getStore","pluginStore","onStoreUpdated","onCoreStoreUpdated","readyPromise","Promise","resolve","readyResolve","provides","_capability","cap","buildCapability","freeze","coreState","getCoreState","dispatchCoreAction","dispatchToAllPlugins","debouncedDispatch","debounceTime","subscribeToCoreStore","ready","markReady","resetReady","manifests","capabilities","status","configurations","engineInitialized","initPromise","pendingRegistrations","processingRegistrations","initialized","isInitializing","pluginsReadyPromise","destroyed","resolver","NoopLogger","ensureEngineInitialized","initialize","task","toPromise","registerPlugin","pluginPackage","validateManifest","manifest","defaultConfig","pluginsReady","readyPromises","from","values","p","all","reg","dependsOn","allDeps","requires","optional","provider","find","r","loadOrder","initializePlugin","create","plugin","postInitialize","catch","e","console","err","packageCreator","finalConfig","validateConfig","validatePlugin","capability","debug","info","getPluginConfig","missingKeys","hasOwnProperty","join","updatePluginConfig","getPlugin","currentConfig","newConfig","registerPluginBatch","registrations","unregisterPlugin","otherId","otherManifest","entries","some","getCapabilityProvider","hasCapability","getAllPlugins","getPluginStatus","version","isDestroyed","reverse","clear","value","min","max","initial","equality","proxyMap","_value","baseOn","realListener","ctl","wrapped","emit","v","notify","on","off","proxy","select","selector","eq","prev","mapped","next","record","k","maybeNum","Number","isFinite","trim","rotatedSize","transformSize","size","pkg"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -885,6 +885,9 @@ function createPluginRegistration(pluginPackage, config) {
|
|
|
885
885
|
config
|
|
886
886
|
};
|
|
887
887
|
}
|
|
888
|
+
function hasAutoMountElements(pkg) {
|
|
889
|
+
return "autoMountElements" in pkg && typeof pkg.autoMountElements === "function";
|
|
890
|
+
}
|
|
888
891
|
class BasePlugin {
|
|
889
892
|
constructor(id, registry) {
|
|
890
893
|
this.id = id;
|
|
@@ -1255,6 +1258,29 @@ function enumEntries(record) {
|
|
|
1255
1258
|
return [typedKey, v];
|
|
1256
1259
|
});
|
|
1257
1260
|
}
|
|
1261
|
+
class PluginPackageBuilder {
|
|
1262
|
+
constructor(basePackage) {
|
|
1263
|
+
this.autoMountElements = [];
|
|
1264
|
+
this.package = basePackage;
|
|
1265
|
+
}
|
|
1266
|
+
addUtility(component) {
|
|
1267
|
+
this.autoMountElements.push({ component, type: "utility" });
|
|
1268
|
+
return this;
|
|
1269
|
+
}
|
|
1270
|
+
addWrapper(component) {
|
|
1271
|
+
this.autoMountElements.push({ component, type: "wrapper" });
|
|
1272
|
+
return this;
|
|
1273
|
+
}
|
|
1274
|
+
build() {
|
|
1275
|
+
return {
|
|
1276
|
+
...this.package,
|
|
1277
|
+
autoMountElements: () => this.autoMountElements
|
|
1278
|
+
};
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
function createPluginPackage(basePackage) {
|
|
1282
|
+
return new PluginPackageBuilder(basePackage);
|
|
1283
|
+
}
|
|
1258
1284
|
export {
|
|
1259
1285
|
BasePlugin,
|
|
1260
1286
|
CORE_ACTION_TYPES,
|
|
@@ -1267,6 +1293,7 @@ export {
|
|
|
1267
1293
|
PluginConfigurationError,
|
|
1268
1294
|
PluginInitializationError,
|
|
1269
1295
|
PluginNotFoundError,
|
|
1296
|
+
PluginPackageBuilder,
|
|
1270
1297
|
PluginRegistrationError,
|
|
1271
1298
|
PluginRegistry,
|
|
1272
1299
|
REFRESH_DOCUMENT,
|
|
@@ -1280,9 +1307,11 @@ export {
|
|
|
1280
1307
|
clamp,
|
|
1281
1308
|
createBehaviorEmitter,
|
|
1282
1309
|
createEmitter,
|
|
1310
|
+
createPluginPackage,
|
|
1283
1311
|
createPluginRegistration,
|
|
1284
1312
|
enumEntries,
|
|
1285
1313
|
getPagesWithRotatedSize,
|
|
1314
|
+
hasAutoMountElements,
|
|
1286
1315
|
initialCoreState,
|
|
1287
1316
|
loadDocument,
|
|
1288
1317
|
refreshDocument,
|