@embedpdf/core 1.0.11 → 1.0.12
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 +2 -1335
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -585
- package/dist/index.js +55 -84
- package/dist/index.js.map +1 -1
- package/dist/lib/base/base-plugin.d.ts +98 -0
- package/dist/lib/index.d.ts +14 -0
- package/dist/lib/registry/plugin-registry.d.ts +100 -0
- package/dist/lib/store/actions.d.ts +39 -0
- package/dist/lib/store/index.d.ts +6 -0
- package/dist/lib/store/initial-state.d.ts +11 -0
- package/dist/lib/store/plugin-store.d.ts +48 -0
- package/dist/lib/store/reducer.d.ts +4 -0
- package/dist/lib/store/selectors.d.ts +3 -0
- package/dist/lib/store/store.d.ts +105 -0
- package/dist/lib/store/types.d.ts +28 -0
- package/dist/lib/types/errors.d.ts +21 -0
- package/dist/lib/types/plugin.d.ts +49 -0
- package/dist/lib/utils/dependency-resolver.d.ts +6 -0
- package/dist/lib/utils/event-control.d.ts +23 -0
- package/dist/lib/utils/eventing.d.ts +19 -0
- package/dist/lib/utils/math.d.ts +22 -0
- package/dist/lib/utils/plugin-helpers.d.ts +6 -0
- package/dist/lib/utils/typed-object.d.ts +12 -0
- package/dist/preact/adapter.d.ts +4 -0
- package/dist/preact/index.cjs +2 -188
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.d.ts +1 -71
- package/dist/preact/index.js +11 -27
- package/dist/preact/index.js.map +1 -1
- package/dist/react/adapter.d.ts +2 -0
- package/dist/react/index.cjs +2 -188
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.ts +1 -70
- package/dist/react/index.js +11 -28
- package/dist/react/index.js.map +1 -1
- package/dist/shared-preact/components/embed-pdf.d.ts +12 -0
- package/dist/shared-preact/components/index.d.ts +1 -0
- package/dist/shared-preact/context.d.ts +7 -0
- package/dist/shared-preact/hooks/index.d.ts +5 -0
- package/dist/shared-preact/hooks/use-capability.d.ts +16 -0
- package/dist/shared-preact/hooks/use-core-state.d.ts +6 -0
- package/dist/shared-preact/hooks/use-plugin.d.ts +16 -0
- package/dist/shared-preact/hooks/use-registry.d.ts +6 -0
- package/dist/shared-preact/hooks/use-store-state.d.ts +6 -0
- package/dist/shared-preact/index.d.ts +3 -0
- package/dist/shared-react/components/embed-pdf.d.ts +12 -0
- package/dist/shared-react/components/index.d.ts +1 -0
- package/dist/shared-react/context.d.ts +7 -0
- package/dist/shared-react/hooks/index.d.ts +5 -0
- package/dist/shared-react/hooks/use-capability.d.ts +16 -0
- package/dist/shared-react/hooks/use-core-state.d.ts +6 -0
- package/dist/shared-react/hooks/use-plugin.d.ts +16 -0
- package/dist/shared-react/hooks/use-registry.d.ts +6 -0
- package/dist/shared-react/hooks/use-store-state.d.ts +6 -0
- package/dist/shared-react/index.d.ts +3 -0
- package/dist/vue/components/embed-pdf.vue.d.ts +23 -0
- package/dist/vue/components/index.d.ts +1 -0
- package/dist/vue/composables/index.d.ts +5 -0
- package/dist/vue/composables/use-capability.d.ts +15 -0
- package/dist/vue/composables/use-core-state.d.ts +2 -0
- package/dist/vue/composables/use-plugin.d.ts +8 -0
- package/dist/vue/composables/use-registry.d.ts +1 -0
- package/dist/vue/composables/use-store-state.d.ts +10 -0
- package/dist/vue/context.d.ts +8 -0
- package/dist/vue/index.cjs +2 -0
- package/dist/vue/index.cjs.map +1 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +115 -0
- package/dist/vue/index.js.map +1 -0
- package/package.json +20 -12
- package/dist/index.d.cts +0 -585
- package/dist/preact/index.d.cts +0 -71
- package/dist/react/index.d.cts +0 -70
package/dist/index.cjs
CHANGED
|
@@ -1,1335 +1,2 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/index.ts
|
|
21
|
-
var index_exports = {};
|
|
22
|
-
__export(index_exports, {
|
|
23
|
-
BasePlugin: () => BasePlugin,
|
|
24
|
-
CORE_ACTION_TYPES: () => CORE_ACTION_TYPES,
|
|
25
|
-
CapabilityConflictError: () => CapabilityConflictError,
|
|
26
|
-
CapabilityNotFoundError: () => CapabilityNotFoundError,
|
|
27
|
-
CircularDependencyError: () => CircularDependencyError,
|
|
28
|
-
DependencyResolver: () => DependencyResolver,
|
|
29
|
-
EventControl: () => EventControl,
|
|
30
|
-
LOAD_DOCUMENT: () => LOAD_DOCUMENT,
|
|
31
|
-
PluginConfigurationError: () => PluginConfigurationError,
|
|
32
|
-
PluginInitializationError: () => PluginInitializationError,
|
|
33
|
-
PluginNotFoundError: () => PluginNotFoundError,
|
|
34
|
-
PluginRegistrationError: () => PluginRegistrationError,
|
|
35
|
-
PluginRegistry: () => PluginRegistry,
|
|
36
|
-
SET_DOCUMENT: () => SET_DOCUMENT,
|
|
37
|
-
SET_DOCUMENT_ERROR: () => SET_DOCUMENT_ERROR,
|
|
38
|
-
SET_PAGES: () => SET_PAGES,
|
|
39
|
-
SET_ROTATION: () => SET_ROTATION,
|
|
40
|
-
SET_SCALE: () => SET_SCALE,
|
|
41
|
-
arePropsEqual: () => arePropsEqual,
|
|
42
|
-
clamp: () => clamp,
|
|
43
|
-
createBehaviorEmitter: () => createBehaviorEmitter,
|
|
44
|
-
createEmitter: () => createEmitter,
|
|
45
|
-
createPluginRegistration: () => createPluginRegistration,
|
|
46
|
-
enumEntries: () => enumEntries,
|
|
47
|
-
getPagesWithRotatedSize: () => getPagesWithRotatedSize,
|
|
48
|
-
initialCoreState: () => initialCoreState,
|
|
49
|
-
loadDocument: () => loadDocument,
|
|
50
|
-
setDocument: () => setDocument,
|
|
51
|
-
setDocumentError: () => setDocumentError,
|
|
52
|
-
setPages: () => setPages,
|
|
53
|
-
setRotation: () => setRotation,
|
|
54
|
-
setScale: () => setScale
|
|
55
|
-
});
|
|
56
|
-
module.exports = __toCommonJS(index_exports);
|
|
57
|
-
|
|
58
|
-
// src/lib/utils/dependency-resolver.ts
|
|
59
|
-
var DependencyResolver = class {
|
|
60
|
-
constructor() {
|
|
61
|
-
this.dependencyGraph = /* @__PURE__ */ new Map();
|
|
62
|
-
}
|
|
63
|
-
addNode(id, dependencies = []) {
|
|
64
|
-
this.dependencyGraph.set(id, new Set(dependencies));
|
|
65
|
-
}
|
|
66
|
-
hasCircularDependencies() {
|
|
67
|
-
const visited = /* @__PURE__ */ new Set();
|
|
68
|
-
const recursionStack = /* @__PURE__ */ new Set();
|
|
69
|
-
const dfs = (id) => {
|
|
70
|
-
visited.add(id);
|
|
71
|
-
recursionStack.add(id);
|
|
72
|
-
const dependencies = this.dependencyGraph.get(id) || /* @__PURE__ */ new Set();
|
|
73
|
-
for (const dep of dependencies) {
|
|
74
|
-
if (!visited.has(dep)) {
|
|
75
|
-
if (dfs(dep)) return true;
|
|
76
|
-
} else if (recursionStack.has(dep)) {
|
|
77
|
-
return true;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
recursionStack.delete(id);
|
|
81
|
-
return false;
|
|
82
|
-
};
|
|
83
|
-
for (const id of this.dependencyGraph.keys()) {
|
|
84
|
-
if (!visited.has(id)) {
|
|
85
|
-
if (dfs(id)) return true;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
resolveLoadOrder() {
|
|
91
|
-
if (this.hasCircularDependencies()) {
|
|
92
|
-
throw new Error("Circular dependencies detected");
|
|
93
|
-
}
|
|
94
|
-
const result = [];
|
|
95
|
-
const visited = /* @__PURE__ */ new Set();
|
|
96
|
-
const temp = /* @__PURE__ */ new Set();
|
|
97
|
-
const visit = (id) => {
|
|
98
|
-
if (temp.has(id)) throw new Error("Circular dependency");
|
|
99
|
-
if (visited.has(id)) return;
|
|
100
|
-
temp.add(id);
|
|
101
|
-
const dependencies = this.dependencyGraph.get(id) || /* @__PURE__ */ new Set();
|
|
102
|
-
for (const dep of dependencies) {
|
|
103
|
-
visit(dep);
|
|
104
|
-
}
|
|
105
|
-
temp.delete(id);
|
|
106
|
-
visited.add(id);
|
|
107
|
-
result.push(id);
|
|
108
|
-
};
|
|
109
|
-
for (const id of this.dependencyGraph.keys()) {
|
|
110
|
-
if (!visited.has(id)) {
|
|
111
|
-
visit(id);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return result;
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
// src/lib/types/errors.ts
|
|
119
|
-
var PluginRegistrationError = class extends Error {
|
|
120
|
-
constructor(message) {
|
|
121
|
-
super(message);
|
|
122
|
-
this.name = "PluginRegistrationError";
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
var PluginNotFoundError = class extends Error {
|
|
126
|
-
constructor(message) {
|
|
127
|
-
super(message);
|
|
128
|
-
this.name = "PluginNotFoundError";
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
var CircularDependencyError = class extends Error {
|
|
132
|
-
constructor(message) {
|
|
133
|
-
super(message);
|
|
134
|
-
this.name = "CircularDependencyError";
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
var CapabilityNotFoundError = class extends Error {
|
|
138
|
-
constructor(message) {
|
|
139
|
-
super(message);
|
|
140
|
-
this.name = "CapabilityNotFoundError";
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
var CapabilityConflictError = class extends Error {
|
|
144
|
-
constructor(message) {
|
|
145
|
-
super(message);
|
|
146
|
-
this.name = "CapabilityConflictError";
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
var PluginInitializationError = class extends Error {
|
|
150
|
-
constructor(message) {
|
|
151
|
-
super(message);
|
|
152
|
-
this.name = "PluginInitializationError";
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
var PluginConfigurationError = class extends Error {
|
|
156
|
-
constructor(message) {
|
|
157
|
-
super(message);
|
|
158
|
-
this.name = "PluginConfigurationError";
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
// src/lib/store/plugin-store.ts
|
|
163
|
-
var PluginStore = class {
|
|
164
|
-
/**
|
|
165
|
-
* Initializes the PluginStore with the main store and plugin ID.
|
|
166
|
-
* @param store The main store instance.
|
|
167
|
-
* @param pluginId The unique identifier for the plugin.
|
|
168
|
-
*/
|
|
169
|
-
constructor(store, pluginId) {
|
|
170
|
-
this.store = store;
|
|
171
|
-
this.pluginId = pluginId;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Gets the current state of the plugin.
|
|
175
|
-
* @returns The plugin's state.
|
|
176
|
-
*/
|
|
177
|
-
getState() {
|
|
178
|
-
return this.store.getState().plugins[this.pluginId];
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Dispatches an action for the plugin and returns the *new* global state.
|
|
182
|
-
* If you only need the plugin’s updated state, call `getState()` afterward.
|
|
183
|
-
* @param action The action to dispatch.
|
|
184
|
-
* @returns The updated global store state (after plugin reducer).
|
|
185
|
-
*/
|
|
186
|
-
dispatch(action) {
|
|
187
|
-
return this.store.dispatchToPlugin(this.pluginId, action);
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Subscribes to state changes only for this specific plugin.
|
|
191
|
-
* You now receive (action, newPluginState, oldPluginState) in the callback.
|
|
192
|
-
*
|
|
193
|
-
* @param listener The callback to invoke when plugin state changes.
|
|
194
|
-
* @returns A function to unsubscribe the listener.
|
|
195
|
-
*/
|
|
196
|
-
subscribeToState(listener) {
|
|
197
|
-
return this.store.subscribeToPlugin(this.pluginId, (action, newPluginState, oldPluginState) => {
|
|
198
|
-
listener(
|
|
199
|
-
action,
|
|
200
|
-
newPluginState,
|
|
201
|
-
oldPluginState
|
|
202
|
-
);
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Subscribes to a specific action type for the plugin.
|
|
207
|
-
* This still uses the main store's `onAction`, so you get the *global*
|
|
208
|
-
* old/new store states there. If you specifically want old/new plugin state,
|
|
209
|
-
* use `subscribeToState` instead.
|
|
210
|
-
*
|
|
211
|
-
* @param type The action type to listen for.
|
|
212
|
-
* @param handler The callback to invoke when the action occurs.
|
|
213
|
-
* @returns A function to unsubscribe the handler.
|
|
214
|
-
*/
|
|
215
|
-
onAction(type, handler) {
|
|
216
|
-
return this.store.onAction(type, (action, state, oldState) => {
|
|
217
|
-
handler(
|
|
218
|
-
action,
|
|
219
|
-
state.plugins[this.pluginId],
|
|
220
|
-
oldState.plugins[this.pluginId]
|
|
221
|
-
);
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
// src/lib/store/actions.ts
|
|
227
|
-
var LOAD_DOCUMENT = "LOAD_DOCUMENT";
|
|
228
|
-
var SET_DOCUMENT = "SET_DOCUMENT";
|
|
229
|
-
var SET_DOCUMENT_ERROR = "SET_DOCUMENT_ERROR";
|
|
230
|
-
var SET_SCALE = "SET_SCALE";
|
|
231
|
-
var SET_ROTATION = "SET_ROTATION";
|
|
232
|
-
var SET_PAGES = "SET_PAGES";
|
|
233
|
-
var CORE_ACTION_TYPES = [
|
|
234
|
-
LOAD_DOCUMENT,
|
|
235
|
-
SET_DOCUMENT,
|
|
236
|
-
SET_DOCUMENT_ERROR,
|
|
237
|
-
SET_SCALE,
|
|
238
|
-
SET_ROTATION,
|
|
239
|
-
SET_PAGES
|
|
240
|
-
];
|
|
241
|
-
var loadDocument = () => ({ type: LOAD_DOCUMENT });
|
|
242
|
-
var setDocument = (document) => ({
|
|
243
|
-
type: SET_DOCUMENT,
|
|
244
|
-
payload: document
|
|
245
|
-
});
|
|
246
|
-
var setDocumentError = (error) => ({
|
|
247
|
-
type: SET_DOCUMENT_ERROR,
|
|
248
|
-
payload: error
|
|
249
|
-
});
|
|
250
|
-
var setScale = (scale) => ({ type: SET_SCALE, payload: scale });
|
|
251
|
-
var setRotation = (rotation) => ({
|
|
252
|
-
type: SET_ROTATION,
|
|
253
|
-
payload: rotation
|
|
254
|
-
});
|
|
255
|
-
var setPages = (pages) => ({
|
|
256
|
-
type: SET_PAGES,
|
|
257
|
-
payload: pages
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
// src/lib/store/store.ts
|
|
261
|
-
var Store = class {
|
|
262
|
-
/**
|
|
263
|
-
* Initializes the store with the provided core state.
|
|
264
|
-
* @param reducer The core reducer function
|
|
265
|
-
* @param initialCoreState The initial core state
|
|
266
|
-
*/
|
|
267
|
-
constructor(reducer, initialCoreState2) {
|
|
268
|
-
this.initialCoreState = initialCoreState2;
|
|
269
|
-
this.pluginReducers = {};
|
|
270
|
-
this.listeners = [];
|
|
271
|
-
this.pluginListeners = {};
|
|
272
|
-
this.state = { core: initialCoreState2, plugins: {} };
|
|
273
|
-
this.coreReducer = reducer;
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Adds a reducer for a plugin-specific state.
|
|
277
|
-
* @param pluginId The unique identifier for the plugin.
|
|
278
|
-
* @param reducer The reducer function for the plugin state.
|
|
279
|
-
* @param initialState The initial state for the plugin.
|
|
280
|
-
*/
|
|
281
|
-
addPluginReducer(pluginId, reducer, initialState) {
|
|
282
|
-
this.state.plugins[pluginId] = initialState;
|
|
283
|
-
this.pluginReducers[pluginId] = reducer;
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Dispatches an action *only* to the core reducer.
|
|
287
|
-
* Notifies the global store listeners with (action, newState, oldState).
|
|
288
|
-
*
|
|
289
|
-
* @param action The action to dispatch, typed as CoreAction
|
|
290
|
-
* @returns The updated *global* store state
|
|
291
|
-
*/
|
|
292
|
-
dispatchToCore(action) {
|
|
293
|
-
if (!this.coreReducer) {
|
|
294
|
-
return this.getState();
|
|
295
|
-
}
|
|
296
|
-
const oldState = this.getState();
|
|
297
|
-
this.state.core = this.coreReducer(this.state.core, action);
|
|
298
|
-
const newState = this.getState();
|
|
299
|
-
this.listeners.forEach((listener) => listener(action, newState, oldState));
|
|
300
|
-
return newState;
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Dispatches an action *only* to a specific plugin.
|
|
304
|
-
* Optionally notifies global store listeners if `notifyGlobal` is true.
|
|
305
|
-
* Always notifies plugin-specific listeners with (action, newPluginState, oldPluginState).
|
|
306
|
-
*
|
|
307
|
-
* @param pluginId The plugin identifier
|
|
308
|
-
* @param action The plugin action to dispatch
|
|
309
|
-
* @param notifyGlobal Whether to also notify global store listeners
|
|
310
|
-
* @returns The updated *global* store state
|
|
311
|
-
*/
|
|
312
|
-
dispatchToPlugin(pluginId, action, notifyGlobal = true) {
|
|
313
|
-
const oldGlobalState = this.getState();
|
|
314
|
-
const reducer = this.pluginReducers[pluginId];
|
|
315
|
-
if (!reducer) {
|
|
316
|
-
return oldGlobalState;
|
|
317
|
-
}
|
|
318
|
-
const oldPluginState = oldGlobalState.plugins[pluginId];
|
|
319
|
-
const newPluginState = reducer(oldPluginState, action);
|
|
320
|
-
this.state.plugins[pluginId] = newPluginState;
|
|
321
|
-
const newGlobalState = this.getState();
|
|
322
|
-
if (notifyGlobal) {
|
|
323
|
-
this.listeners.forEach((listener) => listener(action, newGlobalState, oldGlobalState));
|
|
324
|
-
}
|
|
325
|
-
if (this.pluginListeners[pluginId]) {
|
|
326
|
-
this.pluginListeners[pluginId].forEach((listener) => {
|
|
327
|
-
listener(action, newPluginState, oldPluginState);
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
return newPluginState;
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Dispatches an action to update the state using:
|
|
334
|
-
* - the core reducer (if it's a CoreAction)
|
|
335
|
-
* - *all* plugin reducers (regardless of action type), with no global notify for each plugin
|
|
336
|
-
*
|
|
337
|
-
* Returns the new *global* store state after all reducers have processed the action.
|
|
338
|
-
*
|
|
339
|
-
* @param action The action to dispatch (can be CoreAction or any Action).
|
|
340
|
-
*/
|
|
341
|
-
dispatch(action) {
|
|
342
|
-
const oldState = this.getState();
|
|
343
|
-
if (this.isCoreAction(action)) {
|
|
344
|
-
this.state.core = this.coreReducer(this.state.core, action);
|
|
345
|
-
}
|
|
346
|
-
for (const pluginId in this.pluginReducers) {
|
|
347
|
-
const reducer = this.pluginReducers[pluginId];
|
|
348
|
-
const oldPluginState = oldState.plugins[pluginId];
|
|
349
|
-
if (reducer) {
|
|
350
|
-
this.state.plugins[pluginId] = reducer(oldPluginState, action);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
const newState = this.getState();
|
|
354
|
-
this.listeners.forEach((listener) => listener(action, newState, oldState));
|
|
355
|
-
return newState;
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* Returns a shallow copy of the current state.
|
|
359
|
-
* @returns The current store state.
|
|
360
|
-
*/
|
|
361
|
-
getState() {
|
|
362
|
-
return {
|
|
363
|
-
core: { ...this.state.core },
|
|
364
|
-
plugins: { ...this.state.plugins }
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
/**
|
|
368
|
-
* Subscribes a listener to *global* state changes.
|
|
369
|
-
* The callback signature is now (action, newState, oldState).
|
|
370
|
-
*
|
|
371
|
-
* @param listener The callback to invoke on state changes
|
|
372
|
-
* @returns A function to unsubscribe the listener
|
|
373
|
-
*/
|
|
374
|
-
subscribe(listener) {
|
|
375
|
-
this.listeners.push(listener);
|
|
376
|
-
return () => {
|
|
377
|
-
this.listeners = this.listeners.filter((l) => l !== listener);
|
|
378
|
-
};
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* Subscribes a listener to *plugin-specific* state changes.
|
|
382
|
-
* The callback signature is now (action, newPluginState, oldPluginState).
|
|
383
|
-
*
|
|
384
|
-
* @param pluginId The unique identifier for the plugin.
|
|
385
|
-
* @param listener The callback to invoke on plugin state changes.
|
|
386
|
-
* @returns A function to unsubscribe the listener.
|
|
387
|
-
*/
|
|
388
|
-
subscribeToPlugin(pluginId, listener) {
|
|
389
|
-
if (!(pluginId in this.state.plugins)) {
|
|
390
|
-
throw new Error(
|
|
391
|
-
`Plugin state not found for plugin "${pluginId}". Did you forget to call addPluginReducer?`
|
|
392
|
-
);
|
|
393
|
-
}
|
|
394
|
-
if (!this.pluginListeners[pluginId]) {
|
|
395
|
-
this.pluginListeners[pluginId] = [];
|
|
396
|
-
}
|
|
397
|
-
this.pluginListeners[pluginId].push(listener);
|
|
398
|
-
return () => {
|
|
399
|
-
this.pluginListeners[pluginId] = this.pluginListeners[pluginId].filter((l) => l !== listener);
|
|
400
|
-
if (this.pluginListeners[pluginId].length === 0) {
|
|
401
|
-
delete this.pluginListeners[pluginId];
|
|
402
|
-
}
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
/**
|
|
406
|
-
* Subscribes to a specific action type (only from the core's action union).
|
|
407
|
-
* The callback signature is (action, newState, oldState).
|
|
408
|
-
*
|
|
409
|
-
* @param type The action type to listen for.
|
|
410
|
-
* @param handler The callback to invoke when the action occurs.
|
|
411
|
-
* @returns A function to unsubscribe the handler.
|
|
412
|
-
*/
|
|
413
|
-
onAction(type, handler) {
|
|
414
|
-
return this.subscribe((action, newState, oldState) => {
|
|
415
|
-
if (action.type === type) {
|
|
416
|
-
handler(action, newState, oldState);
|
|
417
|
-
}
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
/**
|
|
421
|
-
* Gets a PluginStore handle for a specific plugin.
|
|
422
|
-
* @param pluginId The unique identifier for the plugin.
|
|
423
|
-
* @returns A PluginStore instance for the plugin.
|
|
424
|
-
*/
|
|
425
|
-
getPluginStore(pluginId) {
|
|
426
|
-
if (!(pluginId in this.state.plugins)) {
|
|
427
|
-
throw new Error(
|
|
428
|
-
`Plugin state not found for plugin "${pluginId}". Did you forget to call addPluginReducer?`
|
|
429
|
-
);
|
|
430
|
-
}
|
|
431
|
-
return new PluginStore(this, pluginId);
|
|
432
|
-
}
|
|
433
|
-
/**
|
|
434
|
-
* Helper method to check if an action is a CoreAction.
|
|
435
|
-
* Adjust if you have a more refined way to differentiate CoreAction vs. any other Action.
|
|
436
|
-
*/
|
|
437
|
-
isCoreAction(action) {
|
|
438
|
-
return CORE_ACTION_TYPES.includes(action.type);
|
|
439
|
-
}
|
|
440
|
-
/**
|
|
441
|
-
* Destroy the store: drop every listener and plugin reducer
|
|
442
|
-
*/
|
|
443
|
-
destroy() {
|
|
444
|
-
this.listeners.length = 0;
|
|
445
|
-
for (const id in this.pluginListeners) {
|
|
446
|
-
this.pluginListeners[id]?.splice?.(0);
|
|
447
|
-
}
|
|
448
|
-
this.pluginListeners = {};
|
|
449
|
-
this.pluginReducers = {};
|
|
450
|
-
this.state.plugins = {};
|
|
451
|
-
this.state.core = { ...this.initialCoreState };
|
|
452
|
-
}
|
|
453
|
-
};
|
|
454
|
-
|
|
455
|
-
// src/lib/store/initial-state.ts
|
|
456
|
-
var import_models = require("@embedpdf/models");
|
|
457
|
-
var initialCoreState = (config) => ({
|
|
458
|
-
scale: config?.scale ?? 1,
|
|
459
|
-
rotation: config?.rotation ?? import_models.Rotation.Degree0,
|
|
460
|
-
document: null,
|
|
461
|
-
pages: [],
|
|
462
|
-
loading: false,
|
|
463
|
-
error: null
|
|
464
|
-
});
|
|
465
|
-
|
|
466
|
-
// src/lib/store/selectors.ts
|
|
467
|
-
var import_models2 = require("@embedpdf/models");
|
|
468
|
-
var getPagesWithRotatedSize = (state) => {
|
|
469
|
-
return state.pages.map(
|
|
470
|
-
(page) => page.map((p) => ({
|
|
471
|
-
...p,
|
|
472
|
-
rotatedSize: (0, import_models2.transformSize)(p.size, state.rotation, 1)
|
|
473
|
-
}))
|
|
474
|
-
);
|
|
475
|
-
};
|
|
476
|
-
|
|
477
|
-
// src/lib/store/reducer.ts
|
|
478
|
-
var coreReducer = (state, action) => {
|
|
479
|
-
switch (action.type) {
|
|
480
|
-
case LOAD_DOCUMENT:
|
|
481
|
-
return {
|
|
482
|
-
...state,
|
|
483
|
-
loading: true,
|
|
484
|
-
error: null
|
|
485
|
-
};
|
|
486
|
-
case SET_DOCUMENT:
|
|
487
|
-
return {
|
|
488
|
-
...state,
|
|
489
|
-
document: action.payload,
|
|
490
|
-
pages: action.payload.pages.map((page) => [page]),
|
|
491
|
-
loading: false,
|
|
492
|
-
error: null
|
|
493
|
-
};
|
|
494
|
-
case SET_ROTATION:
|
|
495
|
-
return {
|
|
496
|
-
...state,
|
|
497
|
-
rotation: action.payload
|
|
498
|
-
};
|
|
499
|
-
case SET_PAGES:
|
|
500
|
-
return {
|
|
501
|
-
...state,
|
|
502
|
-
pages: action.payload
|
|
503
|
-
};
|
|
504
|
-
case SET_DOCUMENT_ERROR:
|
|
505
|
-
return {
|
|
506
|
-
...state,
|
|
507
|
-
loading: false,
|
|
508
|
-
error: action.payload
|
|
509
|
-
};
|
|
510
|
-
case SET_SCALE:
|
|
511
|
-
return {
|
|
512
|
-
...state,
|
|
513
|
-
scale: action.payload
|
|
514
|
-
};
|
|
515
|
-
default:
|
|
516
|
-
return state;
|
|
517
|
-
}
|
|
518
|
-
};
|
|
519
|
-
|
|
520
|
-
// src/lib/registry/plugin-registry.ts
|
|
521
|
-
var PluginRegistry = class {
|
|
522
|
-
constructor(engine, config) {
|
|
523
|
-
this.plugins = /* @__PURE__ */ new Map();
|
|
524
|
-
this.manifests = /* @__PURE__ */ new Map();
|
|
525
|
-
this.capabilities = /* @__PURE__ */ new Map();
|
|
526
|
-
// capability -> pluginId
|
|
527
|
-
this.status = /* @__PURE__ */ new Map();
|
|
528
|
-
this.configurations = /* @__PURE__ */ new Map();
|
|
529
|
-
this.engineInitialized = false;
|
|
530
|
-
this.initPromise = null;
|
|
531
|
-
this.pendingRegistrations = [];
|
|
532
|
-
this.processingRegistrations = [];
|
|
533
|
-
this.initialized = false;
|
|
534
|
-
this.isInitializing = false;
|
|
535
|
-
this.pluginsReadyPromise = null;
|
|
536
|
-
this.destroyed = false;
|
|
537
|
-
this.resolver = new DependencyResolver();
|
|
538
|
-
this.engine = engine;
|
|
539
|
-
this.initialCoreState = initialCoreState(config);
|
|
540
|
-
this.store = new Store(coreReducer, this.initialCoreState);
|
|
541
|
-
}
|
|
542
|
-
/**
|
|
543
|
-
* Ensure engine is initialized before proceeding
|
|
544
|
-
*/
|
|
545
|
-
async ensureEngineInitialized() {
|
|
546
|
-
if (this.engineInitialized) {
|
|
547
|
-
return;
|
|
548
|
-
}
|
|
549
|
-
if (this.engine.initialize) {
|
|
550
|
-
const task = this.engine.initialize();
|
|
551
|
-
await task.toPromise();
|
|
552
|
-
this.engineInitialized = true;
|
|
553
|
-
} else {
|
|
554
|
-
this.engineInitialized = true;
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
/**
|
|
558
|
-
* Register a plugin without initializing it
|
|
559
|
-
*/
|
|
560
|
-
registerPlugin(pluginPackage, config) {
|
|
561
|
-
if (this.initialized && !this.isInitializing) {
|
|
562
|
-
throw new PluginRegistrationError("Cannot register plugins after initialization");
|
|
563
|
-
}
|
|
564
|
-
this.validateManifest(pluginPackage.manifest);
|
|
565
|
-
this.store.addPluginReducer(
|
|
566
|
-
pluginPackage.manifest.id,
|
|
567
|
-
// We need one type assertion here since we can't fully reconcile TAction with Action
|
|
568
|
-
// due to TypeScript's type system limitations with generic variance
|
|
569
|
-
pluginPackage.reducer,
|
|
570
|
-
"function" === typeof pluginPackage.initialState ? pluginPackage.initialState(
|
|
571
|
-
this.initialCoreState,
|
|
572
|
-
{
|
|
573
|
-
...pluginPackage.manifest.defaultConfig,
|
|
574
|
-
...config
|
|
575
|
-
}
|
|
576
|
-
) : pluginPackage.initialState
|
|
577
|
-
);
|
|
578
|
-
this.pendingRegistrations.push({
|
|
579
|
-
package: pluginPackage,
|
|
580
|
-
config
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
/**
|
|
584
|
-
* Get the central store instance
|
|
585
|
-
*/
|
|
586
|
-
getStore() {
|
|
587
|
-
return this.store;
|
|
588
|
-
}
|
|
589
|
-
/**
|
|
590
|
-
* Get the engine instance
|
|
591
|
-
*/
|
|
592
|
-
getEngine() {
|
|
593
|
-
return this.engine;
|
|
594
|
-
}
|
|
595
|
-
/**
|
|
596
|
-
* Get a promise that resolves when all plugins are ready
|
|
597
|
-
*/
|
|
598
|
-
pluginsReady() {
|
|
599
|
-
if (this.pluginsReadyPromise) {
|
|
600
|
-
return this.pluginsReadyPromise;
|
|
601
|
-
}
|
|
602
|
-
this.pluginsReadyPromise = (async () => {
|
|
603
|
-
if (!this.initialized) {
|
|
604
|
-
await this.initialize();
|
|
605
|
-
}
|
|
606
|
-
const readyPromises = Array.from(this.plugins.values()).map(
|
|
607
|
-
(p) => typeof p.ready === "function" ? p.ready() : Promise.resolve()
|
|
608
|
-
);
|
|
609
|
-
await Promise.all(readyPromises);
|
|
610
|
-
})();
|
|
611
|
-
return this.pluginsReadyPromise;
|
|
612
|
-
}
|
|
613
|
-
/**
|
|
614
|
-
* INITIALISE THE REGISTRY – runs once no-matter-how-many calls *
|
|
615
|
-
*/
|
|
616
|
-
async initialize() {
|
|
617
|
-
if (this.destroyed) {
|
|
618
|
-
throw new PluginRegistrationError("Registry has been destroyed");
|
|
619
|
-
}
|
|
620
|
-
if (this.initPromise) {
|
|
621
|
-
return this.initPromise;
|
|
622
|
-
}
|
|
623
|
-
this.initPromise = (async () => {
|
|
624
|
-
if (this.initialized) {
|
|
625
|
-
throw new PluginRegistrationError("Registry is already initialized");
|
|
626
|
-
}
|
|
627
|
-
this.isInitializing = true;
|
|
628
|
-
try {
|
|
629
|
-
await this.ensureEngineInitialized();
|
|
630
|
-
if (this.destroyed) {
|
|
631
|
-
return;
|
|
632
|
-
}
|
|
633
|
-
while (this.pendingRegistrations.length > 0) {
|
|
634
|
-
if (this.destroyed) {
|
|
635
|
-
return;
|
|
636
|
-
}
|
|
637
|
-
this.processingRegistrations = [...this.pendingRegistrations];
|
|
638
|
-
this.pendingRegistrations = [];
|
|
639
|
-
for (const reg of this.processingRegistrations) {
|
|
640
|
-
const dependsOn = /* @__PURE__ */ new Set();
|
|
641
|
-
const allDeps = [...reg.package.manifest.requires, ...reg.package.manifest.optional];
|
|
642
|
-
for (const cap of allDeps) {
|
|
643
|
-
const provider = this.processingRegistrations.find(
|
|
644
|
-
(r) => r.package.manifest.provides.includes(cap)
|
|
645
|
-
);
|
|
646
|
-
if (provider) dependsOn.add(provider.package.manifest.id);
|
|
647
|
-
}
|
|
648
|
-
this.resolver.addNode(reg.package.manifest.id, [...dependsOn]);
|
|
649
|
-
}
|
|
650
|
-
const loadOrder = this.resolver.resolveLoadOrder();
|
|
651
|
-
for (const id of loadOrder) {
|
|
652
|
-
const reg = this.processingRegistrations.find((r) => r.package.manifest.id === id);
|
|
653
|
-
await this.initializePlugin(reg.package.manifest, reg.package.create, reg.config);
|
|
654
|
-
}
|
|
655
|
-
this.processingRegistrations = [];
|
|
656
|
-
this.resolver = new DependencyResolver();
|
|
657
|
-
}
|
|
658
|
-
for (const plugin of this.plugins.values()) {
|
|
659
|
-
await plugin.postInitialize?.().catch((e) => {
|
|
660
|
-
console.error(`Error in postInitialize for plugin ${plugin.id}`, e);
|
|
661
|
-
this.status.set(plugin.id, "error");
|
|
662
|
-
});
|
|
663
|
-
}
|
|
664
|
-
this.initialized = true;
|
|
665
|
-
} catch (err) {
|
|
666
|
-
if (err instanceof Error) {
|
|
667
|
-
throw new CircularDependencyError(
|
|
668
|
-
`Failed to resolve plugin dependencies: ${err.message}`
|
|
669
|
-
);
|
|
670
|
-
}
|
|
671
|
-
throw err;
|
|
672
|
-
} finally {
|
|
673
|
-
this.isInitializing = false;
|
|
674
|
-
}
|
|
675
|
-
})();
|
|
676
|
-
return this.initPromise;
|
|
677
|
-
}
|
|
678
|
-
/**
|
|
679
|
-
* Initialize a single plugin with all necessary checks
|
|
680
|
-
*/
|
|
681
|
-
async initializePlugin(manifest, packageCreator, config) {
|
|
682
|
-
const finalConfig = {
|
|
683
|
-
...manifest.defaultConfig,
|
|
684
|
-
...config
|
|
685
|
-
};
|
|
686
|
-
this.validateConfig(manifest.id, finalConfig, manifest.defaultConfig);
|
|
687
|
-
const plugin = packageCreator(this, this.engine, finalConfig);
|
|
688
|
-
this.validatePlugin(plugin);
|
|
689
|
-
for (const capability of manifest.requires) {
|
|
690
|
-
if (!this.capabilities.has(capability)) {
|
|
691
|
-
throw new PluginRegistrationError(
|
|
692
|
-
`Missing required capability: ${capability} for plugin ${manifest.id}`
|
|
693
|
-
);
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
for (const capability of manifest.optional) {
|
|
697
|
-
if (this.capabilities.has(capability)) {
|
|
698
|
-
console.debug(`Optional capability ${capability} is available for plugin ${manifest.id}`);
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
console.log("initializePlugin", manifest.id, manifest.provides);
|
|
702
|
-
for (const capability of manifest.provides) {
|
|
703
|
-
if (this.capabilities.has(capability)) {
|
|
704
|
-
throw new PluginRegistrationError(
|
|
705
|
-
`Capability ${capability} is already provided by plugin ${this.capabilities.get(capability)}`
|
|
706
|
-
);
|
|
707
|
-
}
|
|
708
|
-
this.capabilities.set(capability, manifest.id);
|
|
709
|
-
}
|
|
710
|
-
this.plugins.set(manifest.id, plugin);
|
|
711
|
-
this.manifests.set(manifest.id, manifest);
|
|
712
|
-
this.status.set(manifest.id, "registered");
|
|
713
|
-
this.configurations.set(manifest.id, finalConfig);
|
|
714
|
-
try {
|
|
715
|
-
if (plugin.initialize) {
|
|
716
|
-
await plugin.initialize(finalConfig);
|
|
717
|
-
}
|
|
718
|
-
this.status.set(manifest.id, "active");
|
|
719
|
-
} catch (error) {
|
|
720
|
-
this.plugins.delete(manifest.id);
|
|
721
|
-
this.manifests.delete(manifest.id);
|
|
722
|
-
console.log("initializePlugin failed", manifest.id, manifest.provides);
|
|
723
|
-
manifest.provides.forEach((cap) => this.capabilities.delete(cap));
|
|
724
|
-
throw error;
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
getPluginConfig(pluginId) {
|
|
728
|
-
const config = this.configurations.get(pluginId);
|
|
729
|
-
if (!config) {
|
|
730
|
-
throw new PluginNotFoundError(`Configuration for plugin ${pluginId} not found`);
|
|
731
|
-
}
|
|
732
|
-
return config;
|
|
733
|
-
}
|
|
734
|
-
validateConfig(pluginId, config, defaultConfig) {
|
|
735
|
-
const requiredKeys = Object.keys(defaultConfig);
|
|
736
|
-
const missingKeys = requiredKeys.filter((key) => !config.hasOwnProperty(key));
|
|
737
|
-
if (missingKeys.length > 0) {
|
|
738
|
-
throw new PluginConfigurationError(
|
|
739
|
-
`Missing required configuration keys for plugin ${pluginId}: ${missingKeys.join(", ")}`
|
|
740
|
-
);
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
async updatePluginConfig(pluginId, config) {
|
|
744
|
-
const plugin = this.getPlugin(pluginId);
|
|
745
|
-
if (!plugin) {
|
|
746
|
-
throw new PluginNotFoundError(`Plugin ${pluginId} not found`);
|
|
747
|
-
}
|
|
748
|
-
const manifest = this.manifests.get(pluginId);
|
|
749
|
-
const currentConfig = this.configurations.get(pluginId);
|
|
750
|
-
if (!manifest || !currentConfig) {
|
|
751
|
-
throw new PluginNotFoundError(`Plugin ${pluginId} not found`);
|
|
752
|
-
}
|
|
753
|
-
const newConfig = {
|
|
754
|
-
...currentConfig,
|
|
755
|
-
...config
|
|
756
|
-
};
|
|
757
|
-
this.validateConfig(pluginId, newConfig, manifest.defaultConfig);
|
|
758
|
-
this.configurations.set(pluginId, newConfig);
|
|
759
|
-
if (plugin.initialize) {
|
|
760
|
-
await plugin.initialize(newConfig);
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
/**
|
|
764
|
-
* Register multiple plugins at once
|
|
765
|
-
*/
|
|
766
|
-
registerPluginBatch(registrations) {
|
|
767
|
-
for (const reg of registrations) {
|
|
768
|
-
this.registerPlugin(reg.package, reg.config);
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
/**
|
|
772
|
-
* Unregister a plugin
|
|
773
|
-
*/
|
|
774
|
-
async unregisterPlugin(pluginId) {
|
|
775
|
-
const plugin = this.plugins.get(pluginId);
|
|
776
|
-
if (!plugin) {
|
|
777
|
-
throw new PluginNotFoundError(`Plugin ${pluginId} is not registered`);
|
|
778
|
-
}
|
|
779
|
-
const manifest = this.manifests.get(pluginId);
|
|
780
|
-
if (!manifest) {
|
|
781
|
-
throw new PluginNotFoundError(`Manifest for plugin ${pluginId} not found`);
|
|
782
|
-
}
|
|
783
|
-
for (const [otherId, otherManifest] of this.manifests.entries()) {
|
|
784
|
-
if (otherId === pluginId) continue;
|
|
785
|
-
const dependsOnThis = [...otherManifest.requires, ...otherManifest.optional].some(
|
|
786
|
-
(cap) => manifest.provides.includes(cap)
|
|
787
|
-
);
|
|
788
|
-
if (dependsOnThis) {
|
|
789
|
-
throw new PluginRegistrationError(
|
|
790
|
-
`Cannot unregister plugin ${pluginId}: plugin ${otherId} depends on it`
|
|
791
|
-
);
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
try {
|
|
795
|
-
if (plugin.destroy) {
|
|
796
|
-
await plugin.destroy();
|
|
797
|
-
}
|
|
798
|
-
for (const capability of manifest.provides) {
|
|
799
|
-
this.capabilities.delete(capability);
|
|
800
|
-
}
|
|
801
|
-
this.plugins.delete(pluginId);
|
|
802
|
-
this.manifests.delete(pluginId);
|
|
803
|
-
this.status.delete(pluginId);
|
|
804
|
-
} catch (error) {
|
|
805
|
-
if (error instanceof Error) {
|
|
806
|
-
throw new Error(`Failed to unregister plugin ${pluginId}: ${error.message}`);
|
|
807
|
-
}
|
|
808
|
-
throw error;
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
/**
|
|
812
|
-
* Get a plugin instance
|
|
813
|
-
* @param pluginId The ID of the plugin to get
|
|
814
|
-
* @returns The plugin instance or null if not found
|
|
815
|
-
*/
|
|
816
|
-
getPlugin(pluginId) {
|
|
817
|
-
const plugin = this.plugins.get(pluginId);
|
|
818
|
-
if (!plugin) {
|
|
819
|
-
return null;
|
|
820
|
-
}
|
|
821
|
-
return plugin;
|
|
822
|
-
}
|
|
823
|
-
/**
|
|
824
|
-
* Get a plugin that provides a specific capability
|
|
825
|
-
* @param capability The capability to get a provider for
|
|
826
|
-
* @returns The plugin providing the capability or null if not found
|
|
827
|
-
*/
|
|
828
|
-
getCapabilityProvider(capability) {
|
|
829
|
-
const pluginId = this.capabilities.get(capability);
|
|
830
|
-
if (!pluginId) {
|
|
831
|
-
return null;
|
|
832
|
-
}
|
|
833
|
-
return this.getPlugin(pluginId);
|
|
834
|
-
}
|
|
835
|
-
/**
|
|
836
|
-
* Check if a capability is available
|
|
837
|
-
*/
|
|
838
|
-
hasCapability(capability) {
|
|
839
|
-
return this.capabilities.has(capability);
|
|
840
|
-
}
|
|
841
|
-
/**
|
|
842
|
-
* Get all registered plugins
|
|
843
|
-
*/
|
|
844
|
-
getAllPlugins() {
|
|
845
|
-
return Array.from(this.plugins.values());
|
|
846
|
-
}
|
|
847
|
-
/**
|
|
848
|
-
* Get plugin status
|
|
849
|
-
*/
|
|
850
|
-
getPluginStatus(pluginId) {
|
|
851
|
-
const status = this.status.get(pluginId);
|
|
852
|
-
if (!status) {
|
|
853
|
-
throw new PluginNotFoundError(`Plugin ${pluginId} not found`);
|
|
854
|
-
}
|
|
855
|
-
return status;
|
|
856
|
-
}
|
|
857
|
-
/**
|
|
858
|
-
* Validate plugin object
|
|
859
|
-
*/
|
|
860
|
-
validatePlugin(plugin) {
|
|
861
|
-
if (!plugin.id) {
|
|
862
|
-
throw new PluginRegistrationError("Plugin must have an id");
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
/**
|
|
866
|
-
* Validate plugin manifest
|
|
867
|
-
*/
|
|
868
|
-
validateManifest(manifest) {
|
|
869
|
-
if (!manifest.id) {
|
|
870
|
-
throw new PluginRegistrationError("Manifest must have an id");
|
|
871
|
-
}
|
|
872
|
-
if (!manifest.name) {
|
|
873
|
-
throw new PluginRegistrationError("Manifest must have a name");
|
|
874
|
-
}
|
|
875
|
-
if (!manifest.version) {
|
|
876
|
-
throw new PluginRegistrationError("Manifest must have a version");
|
|
877
|
-
}
|
|
878
|
-
if (!Array.isArray(manifest.provides)) {
|
|
879
|
-
throw new PluginRegistrationError("Manifest must have a provides array");
|
|
880
|
-
}
|
|
881
|
-
if (!Array.isArray(manifest.requires)) {
|
|
882
|
-
throw new PluginRegistrationError("Manifest must have a requires array");
|
|
883
|
-
}
|
|
884
|
-
if (!Array.isArray(manifest.optional)) {
|
|
885
|
-
throw new PluginRegistrationError("Manifest must have an optional array");
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
isDestroyed() {
|
|
889
|
-
return this.destroyed;
|
|
890
|
-
}
|
|
891
|
-
/**
|
|
892
|
-
* DESTROY EVERYTHING – waits for any ongoing initialise(), once *
|
|
893
|
-
*/
|
|
894
|
-
async destroy() {
|
|
895
|
-
if (this.destroyed) throw new PluginRegistrationError("Registry has already been destroyed");
|
|
896
|
-
this.destroyed = true;
|
|
897
|
-
try {
|
|
898
|
-
await this.initPromise;
|
|
899
|
-
} catch {
|
|
900
|
-
}
|
|
901
|
-
for (const plugin of Array.from(this.plugins.values()).reverse()) {
|
|
902
|
-
await plugin.destroy?.();
|
|
903
|
-
}
|
|
904
|
-
this.store.destroy();
|
|
905
|
-
this.plugins.clear();
|
|
906
|
-
this.manifests.clear();
|
|
907
|
-
this.capabilities.clear();
|
|
908
|
-
this.status.clear();
|
|
909
|
-
this.pendingRegistrations.length = 0;
|
|
910
|
-
this.processingRegistrations.length = 0;
|
|
911
|
-
}
|
|
912
|
-
};
|
|
913
|
-
|
|
914
|
-
// src/lib/utils/plugin-helpers.ts
|
|
915
|
-
function createPluginRegistration(pluginPackage, config) {
|
|
916
|
-
return {
|
|
917
|
-
package: pluginPackage,
|
|
918
|
-
config
|
|
919
|
-
};
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
// src/lib/base/base-plugin.ts
|
|
923
|
-
var BasePlugin = class {
|
|
924
|
-
constructor(id, registry) {
|
|
925
|
-
this.id = id;
|
|
926
|
-
this.registry = registry;
|
|
927
|
-
// Track debounced actions
|
|
928
|
-
this.debouncedActions = {};
|
|
929
|
-
this.unsubscribeFromState = null;
|
|
930
|
-
this.unsubscribeFromCoreStore = null;
|
|
931
|
-
if (id !== this.constructor.id) {
|
|
932
|
-
throw new Error(
|
|
933
|
-
`Plugin ID mismatch: ${id} !== ${this.constructor.id}`
|
|
934
|
-
);
|
|
935
|
-
}
|
|
936
|
-
this.coreStore = this.registry.getStore();
|
|
937
|
-
this.pluginStore = this.coreStore.getPluginStore(this.id);
|
|
938
|
-
this.unsubscribeFromState = this.pluginStore.subscribeToState((action, newState, oldState) => {
|
|
939
|
-
this.onStoreUpdated(oldState, newState);
|
|
940
|
-
});
|
|
941
|
-
this.unsubscribeFromCoreStore = this.coreStore.subscribe((action, newState, oldState) => {
|
|
942
|
-
this.onCoreStoreUpdated(oldState, newState);
|
|
943
|
-
});
|
|
944
|
-
this.readyPromise = new Promise((resolve) => {
|
|
945
|
-
this.readyResolve = resolve;
|
|
946
|
-
});
|
|
947
|
-
this.readyResolve();
|
|
948
|
-
}
|
|
949
|
-
provides() {
|
|
950
|
-
if (!this._capability) {
|
|
951
|
-
const cap = this.buildCapability();
|
|
952
|
-
this._capability = Object.freeze(cap);
|
|
953
|
-
}
|
|
954
|
-
return this._capability;
|
|
955
|
-
}
|
|
956
|
-
/**
|
|
957
|
-
* Get a copy of the current state
|
|
958
|
-
*/
|
|
959
|
-
get state() {
|
|
960
|
-
return this.pluginStore.getState();
|
|
961
|
-
}
|
|
962
|
-
/**
|
|
963
|
-
* Get a copy of the current core state
|
|
964
|
-
*/
|
|
965
|
-
get coreState() {
|
|
966
|
-
return this.coreStore.getState();
|
|
967
|
-
}
|
|
968
|
-
/**
|
|
969
|
-
* @deprecated use `this.state` Get a copy of the current state
|
|
970
|
-
*/
|
|
971
|
-
getState() {
|
|
972
|
-
return this.pluginStore.getState();
|
|
973
|
-
}
|
|
974
|
-
/**
|
|
975
|
-
* @deprecated use `this.coreState` Get a copy of the current core state
|
|
976
|
-
*/
|
|
977
|
-
getCoreState() {
|
|
978
|
-
return this.coreStore.getState();
|
|
979
|
-
}
|
|
980
|
-
/**
|
|
981
|
-
* Core Dispatch
|
|
982
|
-
*/
|
|
983
|
-
dispatchCoreAction(action) {
|
|
984
|
-
return this.coreStore.dispatchToCore(action);
|
|
985
|
-
}
|
|
986
|
-
/**
|
|
987
|
-
* Dispatch an action to all plugins
|
|
988
|
-
*/
|
|
989
|
-
dispatchToAllPlugins(action) {
|
|
990
|
-
return this.coreStore.dispatch(action);
|
|
991
|
-
}
|
|
992
|
-
/**
|
|
993
|
-
* Dispatch an action
|
|
994
|
-
*/
|
|
995
|
-
dispatch(action) {
|
|
996
|
-
return this.pluginStore.dispatch(action);
|
|
997
|
-
}
|
|
998
|
-
/**
|
|
999
|
-
* Dispatch an action with debouncing to prevent rapid repeated calls
|
|
1000
|
-
* @param action The action to dispatch
|
|
1001
|
-
* @param debounceTime Time in ms to debounce (default: 100ms)
|
|
1002
|
-
* @returns boolean indicating whether the action was dispatched or debounced
|
|
1003
|
-
*/
|
|
1004
|
-
debouncedDispatch(action, debounceTime = 100) {
|
|
1005
|
-
const now = Date.now();
|
|
1006
|
-
const lastActionTime = this.debouncedActions[action.type] || 0;
|
|
1007
|
-
if (now - lastActionTime >= debounceTime) {
|
|
1008
|
-
this.debouncedActions[action.type] = now;
|
|
1009
|
-
this.dispatch(action);
|
|
1010
|
-
return true;
|
|
1011
|
-
}
|
|
1012
|
-
return false;
|
|
1013
|
-
}
|
|
1014
|
-
/**
|
|
1015
|
-
* Subscribe to state changes
|
|
1016
|
-
*/
|
|
1017
|
-
subscribe(listener) {
|
|
1018
|
-
return this.pluginStore.subscribeToState(listener);
|
|
1019
|
-
}
|
|
1020
|
-
/**
|
|
1021
|
-
* Subscribe to core store changes
|
|
1022
|
-
*/
|
|
1023
|
-
subscribeToCoreStore(listener) {
|
|
1024
|
-
return this.coreStore.subscribe(listener);
|
|
1025
|
-
}
|
|
1026
|
-
/**
|
|
1027
|
-
* Called when the plugin store state is updated
|
|
1028
|
-
* @param oldState Previous state
|
|
1029
|
-
* @param newState New state
|
|
1030
|
-
*/
|
|
1031
|
-
onStoreUpdated(oldState, newState) {
|
|
1032
|
-
}
|
|
1033
|
-
/**
|
|
1034
|
-
* Called when the core store state is updated
|
|
1035
|
-
* @param oldState Previous state
|
|
1036
|
-
* @param newState New state
|
|
1037
|
-
*/
|
|
1038
|
-
onCoreStoreUpdated(oldState, newState) {
|
|
1039
|
-
}
|
|
1040
|
-
/**
|
|
1041
|
-
* Cleanup method to be called when plugin is being destroyed
|
|
1042
|
-
*/
|
|
1043
|
-
destroy() {
|
|
1044
|
-
if (this.unsubscribeFromState) {
|
|
1045
|
-
this.unsubscribeFromState();
|
|
1046
|
-
this.unsubscribeFromState = null;
|
|
1047
|
-
}
|
|
1048
|
-
if (this.unsubscribeFromCoreStore) {
|
|
1049
|
-
this.unsubscribeFromCoreStore();
|
|
1050
|
-
this.unsubscribeFromCoreStore = null;
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
/**
|
|
1054
|
-
* Returns a promise that resolves when the plugin is ready
|
|
1055
|
-
*/
|
|
1056
|
-
ready() {
|
|
1057
|
-
return this.readyPromise;
|
|
1058
|
-
}
|
|
1059
|
-
/**
|
|
1060
|
-
* Mark the plugin as ready
|
|
1061
|
-
*/
|
|
1062
|
-
markReady() {
|
|
1063
|
-
this.readyResolve();
|
|
1064
|
-
}
|
|
1065
|
-
/**
|
|
1066
|
-
* Reset the ready state (useful for plugins that need to reinitialize)
|
|
1067
|
-
*/
|
|
1068
|
-
resetReady() {
|
|
1069
|
-
this.readyPromise = new Promise((resolve) => {
|
|
1070
|
-
this.readyResolve = resolve;
|
|
1071
|
-
});
|
|
1072
|
-
}
|
|
1073
|
-
};
|
|
1074
|
-
|
|
1075
|
-
// src/lib/utils/event-control.ts
|
|
1076
|
-
var EventControl = class {
|
|
1077
|
-
constructor(handler, options) {
|
|
1078
|
-
this.handler = handler;
|
|
1079
|
-
this.options = options;
|
|
1080
|
-
this.lastRun = 0;
|
|
1081
|
-
this.handle = (data) => {
|
|
1082
|
-
if (this.options.mode === "debounce") {
|
|
1083
|
-
this.debounce(data);
|
|
1084
|
-
} else {
|
|
1085
|
-
this.throttle(data);
|
|
1086
|
-
}
|
|
1087
|
-
};
|
|
1088
|
-
}
|
|
1089
|
-
debounce(data) {
|
|
1090
|
-
if (this.timeoutId) {
|
|
1091
|
-
window.clearTimeout(this.timeoutId);
|
|
1092
|
-
}
|
|
1093
|
-
this.timeoutId = window.setTimeout(() => {
|
|
1094
|
-
this.handler(data);
|
|
1095
|
-
this.timeoutId = void 0;
|
|
1096
|
-
}, this.options.wait);
|
|
1097
|
-
}
|
|
1098
|
-
throttle(data) {
|
|
1099
|
-
if (this.options.mode === "debounce") return;
|
|
1100
|
-
const now = Date.now();
|
|
1101
|
-
const throttleMode = this.options.throttleMode || "leading-trailing";
|
|
1102
|
-
if (now - this.lastRun >= this.options.wait) {
|
|
1103
|
-
if (throttleMode === "leading-trailing") {
|
|
1104
|
-
this.handler(data);
|
|
1105
|
-
}
|
|
1106
|
-
this.lastRun = now;
|
|
1107
|
-
}
|
|
1108
|
-
if (this.timeoutId) {
|
|
1109
|
-
window.clearTimeout(this.timeoutId);
|
|
1110
|
-
}
|
|
1111
|
-
this.timeoutId = window.setTimeout(
|
|
1112
|
-
() => {
|
|
1113
|
-
this.handler(data);
|
|
1114
|
-
this.lastRun = Date.now();
|
|
1115
|
-
this.timeoutId = void 0;
|
|
1116
|
-
},
|
|
1117
|
-
this.options.wait - (now - this.lastRun)
|
|
1118
|
-
);
|
|
1119
|
-
}
|
|
1120
|
-
destroy() {
|
|
1121
|
-
if (this.timeoutId) {
|
|
1122
|
-
window.clearTimeout(this.timeoutId);
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
};
|
|
1126
|
-
|
|
1127
|
-
// src/lib/utils/math.ts
|
|
1128
|
-
function clamp(value, min, max) {
|
|
1129
|
-
return value < min ? min : value > max ? max : value;
|
|
1130
|
-
}
|
|
1131
|
-
function arePropsEqual(a, b, visited) {
|
|
1132
|
-
if (a === b) {
|
|
1133
|
-
return true;
|
|
1134
|
-
}
|
|
1135
|
-
if (a == null || b == null) {
|
|
1136
|
-
return a === b;
|
|
1137
|
-
}
|
|
1138
|
-
const aType = typeof a;
|
|
1139
|
-
const bType = typeof b;
|
|
1140
|
-
if (aType !== bType) return false;
|
|
1141
|
-
if (aType === "object") {
|
|
1142
|
-
if (!visited) visited = /* @__PURE__ */ new Set();
|
|
1143
|
-
const pairId = getPairId(a, b);
|
|
1144
|
-
if (visited.has(pairId)) {
|
|
1145
|
-
return true;
|
|
1146
|
-
}
|
|
1147
|
-
visited.add(pairId);
|
|
1148
|
-
const aIsArray = Array.isArray(a);
|
|
1149
|
-
const bIsArray = Array.isArray(b);
|
|
1150
|
-
if (aIsArray && bIsArray) {
|
|
1151
|
-
return arraysEqualUnordered(a, b, visited);
|
|
1152
|
-
} else if (!aIsArray && !bIsArray) {
|
|
1153
|
-
return objectsEqual(a, b, visited);
|
|
1154
|
-
} else {
|
|
1155
|
-
return false;
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
return false;
|
|
1159
|
-
}
|
|
1160
|
-
function getPairId(a, b) {
|
|
1161
|
-
return `${objectId(a)}__${objectId(b)}`;
|
|
1162
|
-
}
|
|
1163
|
-
var objectIdCounter = 0;
|
|
1164
|
-
var objectIds = /* @__PURE__ */ new WeakMap();
|
|
1165
|
-
function objectId(obj) {
|
|
1166
|
-
if (!objectIds.has(obj)) {
|
|
1167
|
-
objectIds.set(obj, ++objectIdCounter);
|
|
1168
|
-
}
|
|
1169
|
-
return objectIds.get(obj);
|
|
1170
|
-
}
|
|
1171
|
-
function arraysEqualUnordered(a, b, visited) {
|
|
1172
|
-
if (a.length !== b.length) return false;
|
|
1173
|
-
const used = new Array(b.length).fill(false);
|
|
1174
|
-
outer: for (let i = 0; i < a.length; i++) {
|
|
1175
|
-
const elemA = a[i];
|
|
1176
|
-
for (let j = 0; j < b.length; j++) {
|
|
1177
|
-
if (used[j]) continue;
|
|
1178
|
-
if (arePropsEqual(elemA, b[j], visited)) {
|
|
1179
|
-
used[j] = true;
|
|
1180
|
-
continue outer;
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
return false;
|
|
1184
|
-
}
|
|
1185
|
-
return true;
|
|
1186
|
-
}
|
|
1187
|
-
function objectsEqual(a, b, visited) {
|
|
1188
|
-
const aKeys = Object.keys(a).sort();
|
|
1189
|
-
const bKeys = Object.keys(b).sort();
|
|
1190
|
-
if (aKeys.length !== bKeys.length) return false;
|
|
1191
|
-
for (let i = 0; i < aKeys.length; i++) {
|
|
1192
|
-
if (aKeys[i] !== bKeys[i]) return false;
|
|
1193
|
-
}
|
|
1194
|
-
for (const key of aKeys) {
|
|
1195
|
-
const valA = a[key];
|
|
1196
|
-
const valB = b[key];
|
|
1197
|
-
if (!arePropsEqual(valA, valB, visited)) {
|
|
1198
|
-
return false;
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
return true;
|
|
1202
|
-
}
|
|
1203
|
-
|
|
1204
|
-
// src/lib/utils/eventing.ts
|
|
1205
|
-
function createEmitter() {
|
|
1206
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
1207
|
-
const on = (l) => {
|
|
1208
|
-
listeners.add(l);
|
|
1209
|
-
return () => listeners.delete(l);
|
|
1210
|
-
};
|
|
1211
|
-
return {
|
|
1212
|
-
emit: (v = void 0) => listeners.forEach((l) => l(v)),
|
|
1213
|
-
on,
|
|
1214
|
-
off: (l) => listeners.delete(l),
|
|
1215
|
-
clear: () => listeners.clear()
|
|
1216
|
-
};
|
|
1217
|
-
}
|
|
1218
|
-
function createBehaviorEmitter(initial, equality = arePropsEqual) {
|
|
1219
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
1220
|
-
const proxyMap = /* @__PURE__ */ new Map();
|
|
1221
|
-
let _value = initial;
|
|
1222
|
-
const notify = (v) => listeners.forEach((l) => l(v));
|
|
1223
|
-
const baseOn = (listener, options) => {
|
|
1224
|
-
let realListener = listener;
|
|
1225
|
-
let destroy = () => {
|
|
1226
|
-
};
|
|
1227
|
-
if (options) {
|
|
1228
|
-
const ctl = new EventControl(listener, options);
|
|
1229
|
-
realListener = ctl.handle;
|
|
1230
|
-
destroy = () => ctl.destroy();
|
|
1231
|
-
proxyMap.set(listener, { wrapped: realListener, destroy });
|
|
1232
|
-
}
|
|
1233
|
-
if (_value !== void 0) realListener(_value);
|
|
1234
|
-
listeners.add(realListener);
|
|
1235
|
-
return () => {
|
|
1236
|
-
listeners.delete(realListener);
|
|
1237
|
-
destroy();
|
|
1238
|
-
proxyMap.delete(listener);
|
|
1239
|
-
};
|
|
1240
|
-
};
|
|
1241
|
-
return {
|
|
1242
|
-
/* emitter behaviour ---------------------------------------- */
|
|
1243
|
-
get value() {
|
|
1244
|
-
return _value;
|
|
1245
|
-
},
|
|
1246
|
-
emit(v = void 0) {
|
|
1247
|
-
if (_value === void 0 || !equality(_value, v)) {
|
|
1248
|
-
_value = v;
|
|
1249
|
-
notify(v);
|
|
1250
|
-
}
|
|
1251
|
-
},
|
|
1252
|
-
on: baseOn,
|
|
1253
|
-
off(listener) {
|
|
1254
|
-
const proxy = proxyMap.get(listener);
|
|
1255
|
-
if (proxy) {
|
|
1256
|
-
listeners.delete(proxy.wrapped);
|
|
1257
|
-
proxy.destroy();
|
|
1258
|
-
proxyMap.delete(listener);
|
|
1259
|
-
} else {
|
|
1260
|
-
listeners.delete(listener);
|
|
1261
|
-
}
|
|
1262
|
-
},
|
|
1263
|
-
clear() {
|
|
1264
|
-
listeners.clear();
|
|
1265
|
-
proxyMap.forEach((p) => p.destroy());
|
|
1266
|
-
proxyMap.clear();
|
|
1267
|
-
},
|
|
1268
|
-
/* derived hook --------------------------------------------- */
|
|
1269
|
-
select(selector, eq = arePropsEqual) {
|
|
1270
|
-
return (listener, options) => {
|
|
1271
|
-
let prev;
|
|
1272
|
-
if (_value !== void 0) {
|
|
1273
|
-
const mapped = selector(_value);
|
|
1274
|
-
prev = mapped;
|
|
1275
|
-
listener(mapped);
|
|
1276
|
-
}
|
|
1277
|
-
return baseOn(
|
|
1278
|
-
(next) => {
|
|
1279
|
-
const mapped = selector(next);
|
|
1280
|
-
if (prev === void 0 || !eq(prev, mapped)) {
|
|
1281
|
-
prev = mapped;
|
|
1282
|
-
listener(mapped);
|
|
1283
|
-
}
|
|
1284
|
-
},
|
|
1285
|
-
options
|
|
1286
|
-
);
|
|
1287
|
-
};
|
|
1288
|
-
}
|
|
1289
|
-
};
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
// src/lib/utils/typed-object.ts
|
|
1293
|
-
function enumEntries(record) {
|
|
1294
|
-
return Object.entries(record).map(([k, v]) => {
|
|
1295
|
-
const maybeNum = Number(k);
|
|
1296
|
-
const typedKey = Number.isFinite(maybeNum) && k.trim() !== "" ? maybeNum : k;
|
|
1297
|
-
return [typedKey, v];
|
|
1298
|
-
});
|
|
1299
|
-
}
|
|
1300
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
1301
|
-
0 && (module.exports = {
|
|
1302
|
-
BasePlugin,
|
|
1303
|
-
CORE_ACTION_TYPES,
|
|
1304
|
-
CapabilityConflictError,
|
|
1305
|
-
CapabilityNotFoundError,
|
|
1306
|
-
CircularDependencyError,
|
|
1307
|
-
DependencyResolver,
|
|
1308
|
-
EventControl,
|
|
1309
|
-
LOAD_DOCUMENT,
|
|
1310
|
-
PluginConfigurationError,
|
|
1311
|
-
PluginInitializationError,
|
|
1312
|
-
PluginNotFoundError,
|
|
1313
|
-
PluginRegistrationError,
|
|
1314
|
-
PluginRegistry,
|
|
1315
|
-
SET_DOCUMENT,
|
|
1316
|
-
SET_DOCUMENT_ERROR,
|
|
1317
|
-
SET_PAGES,
|
|
1318
|
-
SET_ROTATION,
|
|
1319
|
-
SET_SCALE,
|
|
1320
|
-
arePropsEqual,
|
|
1321
|
-
clamp,
|
|
1322
|
-
createBehaviorEmitter,
|
|
1323
|
-
createEmitter,
|
|
1324
|
-
createPluginRegistration,
|
|
1325
|
-
enumEntries,
|
|
1326
|
-
getPagesWithRotatedSize,
|
|
1327
|
-
initialCoreState,
|
|
1328
|
-
loadDocument,
|
|
1329
|
-
setDocument,
|
|
1330
|
-
setDocumentError,
|
|
1331
|
-
setPages,
|
|
1332
|
-
setRotation,
|
|
1333
|
-
setScale
|
|
1334
|
-
});
|
|
1335
|
-
//# sourceMappingURL=index.cjs.map
|
|
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="SET_DOCUMENT",d="SET_DOCUMENT_ERROR",g="SET_SCALE",p="SET_ROTATION",f="SET_PAGES",y=[h,c,d,g,p,f];class w{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 y.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 m=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}),S=(t,e)=>{switch(e.type){case h:return{...t,loading:!0,error:null};case c:return{...t,document:e.payload,pages:e.payload.pages.map((t=>[t])),loading:!1,error:null};case p:return{...t,rotation:e.payload};case f:return{...t,pages:e.payload};case d:return{...t,loading:!1,error:e.payload};case g:return{...t,scale:e.payload};default:return t}};class b{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 P(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`${R(t)}__${R(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]&&P(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(!P(t[n],e[n],i))return!1}return!0}(t,e,i)}return!1}let E=0;const v=new WeakMap;function R(t){return v.has(t)||v.set(t,++E),v.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.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=y,exports.CapabilityConflictError=o,exports.CapabilityNotFoundError=n,exports.CircularDependencyError=r,exports.DependencyResolver=e,exports.EventControl=b,exports.LOAD_DOCUMENT=h,exports.PluginConfigurationError=l,exports.PluginInitializationError=a,exports.PluginNotFoundError=s,exports.PluginRegistrationError=i,exports.PluginRegistry=class{constructor(t,i){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=t,this.initialCoreState=m(i),this.store=new w(S,this.initialCoreState)}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,this.engine,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)&&console.debug(`Optional capability ${i} is available for plugin ${t.id}`);console.log("initializePlugin",t.id,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")}catch(o){throw this.plugins.delete(t.id),this.manifests.delete(t.id),console.log("initializePlugin failed",t.id,t.provides),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.SET_DOCUMENT=c,exports.SET_DOCUMENT_ERROR=d,exports.SET_PAGES=f,exports.SET_ROTATION=p,exports.SET_SCALE=g,exports.arePropsEqual=P,exports.clamp=function(t,e,i){return t<e?e:t>i?i:t},exports.createBehaviorEmitter=function(t,e=P){const i=new Set,s=new Map;let r=t;const n=(t,e)=>{let n=t,o=()=>{};if(e){const i=new b(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=P)=>(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=m,exports.loadDocument=()=>({type:h}),exports.setDocument=t=>({type:c,payload:t}),exports.setDocumentError=t=>({type:d,payload:t}),exports.setPages=t=>({type:f,payload:t}),exports.setRotation=t=>({type:p,payload:t}),exports.setScale=t=>({type:g,payload:t});
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|