@pooder/core 0.1.0 → 1.0.0
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/CHANGELOG.md +6 -0
- package/dist/index.d.mts +243 -134
- package/dist/index.d.ts +243 -134
- package/dist/index.js +442 -370
- package/dist/index.mjs +434 -367
- package/package.json +2 -4
- package/src/command.ts +9 -60
- package/src/context.ts +17 -0
- package/src/contribution/index.ts +12 -0
- package/src/contribution/points.ts +63 -0
- package/src/contribution/registry.ts +118 -0
- package/src/disposable.ts +3 -0
- package/src/event.ts +9 -4
- package/src/extension.ts +108 -171
- package/src/index.ts +140 -31
- package/src/run-test-full.ts +98 -0
- package/src/service.ts +25 -0
- package/src/services/CommandService.ts +79 -0
- package/src/services/ConfigurationService.ts +107 -0
- package/src/services/index.ts +4 -0
- package/src/test-extension-full.ts +79 -0
- package/tsconfig.test.json +7 -0
- package/src/canvas.ts +0 -3
- package/src/editor.ts +0 -226
- package/src/layer.ts +0 -13
- package/src/obj.ts +0 -7
- package/src/types.ts +0 -105
package/dist/index.js
CHANGED
|
@@ -20,25 +20,37 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
PooderCanvas: () => import_fabric.Canvas,
|
|
32
|
-
PooderEditor: () => PooderEditor,
|
|
33
|
-
PooderLayer: () => import_fabric2.Group,
|
|
34
|
-
PooderObject: () => import_fabric3.FabricObject,
|
|
35
|
-
Rect: () => import_fabric4.Rect,
|
|
36
|
-
Text: () => import_fabric4.Text,
|
|
37
|
-
filters: () => import_fabric4.filters,
|
|
38
|
-
util: () => import_fabric4.util
|
|
23
|
+
CommandService: () => CommandService,
|
|
24
|
+
ConfigurationService: () => ConfigurationService,
|
|
25
|
+
ContributionPointIds: () => ContributionPointIds,
|
|
26
|
+
ContributionRegistry: () => ContributionRegistry,
|
|
27
|
+
ExtensionManager: () => ExtensionManager,
|
|
28
|
+
ExtensionRegistry: () => ExtensionRegistry,
|
|
29
|
+
Pooder: () => Pooder,
|
|
30
|
+
ServiceRegistry: () => ServiceRegistry
|
|
39
31
|
});
|
|
40
32
|
module.exports = __toCommonJS(index_exports);
|
|
41
33
|
|
|
34
|
+
// src/service.ts
|
|
35
|
+
var ServiceRegistry = class {
|
|
36
|
+
constructor() {
|
|
37
|
+
this.services = /* @__PURE__ */ new Map();
|
|
38
|
+
}
|
|
39
|
+
register(name, service) {
|
|
40
|
+
this.services.set(name, service);
|
|
41
|
+
return service;
|
|
42
|
+
}
|
|
43
|
+
get(serviceName) {
|
|
44
|
+
return this.services.get(serviceName);
|
|
45
|
+
}
|
|
46
|
+
has(serviceName) {
|
|
47
|
+
return this.services.has(serviceName);
|
|
48
|
+
}
|
|
49
|
+
delete(serviceName) {
|
|
50
|
+
this.services.delete(serviceName);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
42
54
|
// src/event.ts
|
|
43
55
|
var EventBus = class {
|
|
44
56
|
constructor() {
|
|
@@ -75,440 +87,500 @@ var EventBus = class {
|
|
|
75
87
|
return (_b = (_a = this.events.get(event)) == null ? void 0 : _a.length) != null ? _b : 0;
|
|
76
88
|
}
|
|
77
89
|
};
|
|
90
|
+
var event_default = EventBus;
|
|
78
91
|
|
|
79
|
-
// src/
|
|
80
|
-
var
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
this.
|
|
92
|
+
// src/contribution/points.ts
|
|
93
|
+
var ContributionPointIds = {
|
|
94
|
+
CONTRIBUTIONS: "contribution.point.contributions",
|
|
95
|
+
COMMANDS: "contribution.point.commands",
|
|
96
|
+
TOOLS: "contribution.point.tools",
|
|
97
|
+
VIEWS: "contribution.point.views",
|
|
98
|
+
CONFIGURATIONS: "contribution.point.configurations"
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// src/contribution/registry.ts
|
|
102
|
+
var ContributionRegistry = class {
|
|
103
|
+
constructor() {
|
|
104
|
+
this.points = /* @__PURE__ */ new Map();
|
|
105
|
+
this.contributions = {
|
|
106
|
+
byId: /* @__PURE__ */ new Map(),
|
|
107
|
+
byPointId: /* @__PURE__ */ new Map()
|
|
108
|
+
};
|
|
92
109
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Register a new contribution point
|
|
112
|
+
*/
|
|
113
|
+
registerPoint(point) {
|
|
114
|
+
if (this.points.has(point.id)) {
|
|
115
|
+
console.warn(
|
|
116
|
+
`Contribution point ${point.id} already exists. Overwriting definitions may cause issues.`
|
|
117
|
+
);
|
|
98
118
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
console.error(`Error executing command "${name}":`, e);
|
|
103
|
-
return false;
|
|
119
|
+
this.points.set(point.id, point);
|
|
120
|
+
if (!this.contributions.byPointId.has(point.id)) {
|
|
121
|
+
this.contributions.byPointId.set(point.id, []);
|
|
104
122
|
}
|
|
105
123
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
124
|
+
/**
|
|
125
|
+
* Register a contribution to a specific point
|
|
126
|
+
* @returns Disposable to unregister the contribution
|
|
127
|
+
*/
|
|
128
|
+
register(pointId, contribution) {
|
|
129
|
+
if (this.contributions.byId.has(contribution.id)) {
|
|
130
|
+
console.warn(
|
|
131
|
+
`Contribution with ID "${contribution.id}" is already registered. Overwriting.`
|
|
132
|
+
);
|
|
133
|
+
this.unregister(pointId, contribution.id);
|
|
134
|
+
}
|
|
135
|
+
if (!this.points.has(pointId)) {
|
|
136
|
+
console.warn(
|
|
137
|
+
`Contribution point ${pointId} does not exist. The contribution ${contribution.id} will be queued but may not be valid.`
|
|
138
|
+
);
|
|
139
|
+
if (!this.contributions.byPointId.has(pointId)) {
|
|
140
|
+
this.contributions.byPointId.set(pointId, []);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const point = this.points.get(pointId);
|
|
144
|
+
if (point == null ? void 0 : point.validate) {
|
|
145
|
+
try {
|
|
146
|
+
if (!point.validate(contribution.data)) {
|
|
147
|
+
console.error(
|
|
148
|
+
`Contribution ${contribution.id} failed validation for point ${pointId}.`
|
|
149
|
+
);
|
|
150
|
+
return { dispose: () => {
|
|
151
|
+
} };
|
|
152
|
+
}
|
|
153
|
+
} catch (e) {
|
|
154
|
+
console.error(
|
|
155
|
+
`Validation error for contribution ${contribution.id}:`,
|
|
156
|
+
e
|
|
157
|
+
);
|
|
158
|
+
return { dispose: () => {
|
|
159
|
+
} };
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const arr = this.contributions.byPointId.get(pointId);
|
|
163
|
+
arr.push(contribution);
|
|
164
|
+
this.contributions.byId.set(contribution.id, contribution);
|
|
165
|
+
if (pointId === ContributionPointIds.CONTRIBUTIONS) {
|
|
166
|
+
this.registerPoint(contribution.data);
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
dispose: () => {
|
|
170
|
+
this.unregister(pointId, contribution.id);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
114
173
|
}
|
|
115
|
-
|
|
116
|
-
|
|
174
|
+
/**
|
|
175
|
+
* Get all contributions for a given point
|
|
176
|
+
*/
|
|
177
|
+
get(pointId) {
|
|
178
|
+
var _a;
|
|
179
|
+
return Array.from(
|
|
180
|
+
((_a = this.contributions.byPointId.get(pointId)) == null ? void 0 : _a.values()) || []
|
|
181
|
+
);
|
|
117
182
|
}
|
|
118
|
-
|
|
119
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Get a specific contribution by ID
|
|
185
|
+
*/
|
|
186
|
+
getById(id) {
|
|
187
|
+
return this.contributions.byId.get(id);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Get the contribution point definition
|
|
191
|
+
*/
|
|
192
|
+
getPoint(pointId) {
|
|
193
|
+
return this.points.get(pointId);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Unregister a contribution
|
|
197
|
+
*/
|
|
198
|
+
unregister(pointId, contributionId) {
|
|
199
|
+
const arr = this.contributions.byPointId.get(pointId);
|
|
200
|
+
arr == null ? void 0 : arr.splice(
|
|
201
|
+
arr.findIndex((c) => c.id === contributionId),
|
|
202
|
+
1
|
|
203
|
+
);
|
|
204
|
+
this.contributions.byId.delete(contributionId);
|
|
120
205
|
}
|
|
121
206
|
};
|
|
122
207
|
|
|
123
208
|
// src/extension.ts
|
|
124
|
-
var
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
Object.entries(extension.commands).forEach(([name, command]) => {
|
|
132
|
-
const commandName = `${extension.name}.${name}`;
|
|
133
|
-
this.editor.registerCommand(commandName, command);
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
_unregisterCommands(extension) {
|
|
138
|
-
if (extension.commands) {
|
|
139
|
-
Object.keys(extension.commands).forEach((name) => {
|
|
140
|
-
const commandName = `${extension.name}.${name}`;
|
|
141
|
-
this.editor.unregisterCommand(commandName);
|
|
142
|
-
});
|
|
143
|
-
}
|
|
209
|
+
var ExtensionRegistry = class extends Map {
|
|
210
|
+
};
|
|
211
|
+
var ExtensionManager = class {
|
|
212
|
+
constructor(context) {
|
|
213
|
+
this.extensionRegistry = new ExtensionRegistry();
|
|
214
|
+
this.extensionDisposables = /* @__PURE__ */ new Map();
|
|
215
|
+
this.context = context;
|
|
144
216
|
}
|
|
145
217
|
register(extension) {
|
|
146
|
-
|
|
147
|
-
if (this.editor.extensions.has(extension.name)) {
|
|
218
|
+
if (this.extensionRegistry.has(extension.id)) {
|
|
148
219
|
console.warn(
|
|
149
|
-
`Plugin "${extension.
|
|
220
|
+
`Plugin "${extension.id}" already registered. It will be overwritten.`
|
|
150
221
|
);
|
|
151
222
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
223
|
+
this.extensionDisposables.set(extension.id, []);
|
|
224
|
+
const disposables = this.extensionDisposables.get(extension.id);
|
|
225
|
+
if (extension.contribute) {
|
|
226
|
+
for (const [pointId, items] of Object.entries(extension.contribute())) {
|
|
227
|
+
if (Array.isArray(items)) {
|
|
228
|
+
items.forEach((item, index) => {
|
|
229
|
+
const contributionId = item.id || (item.command ? item.command : `${extension.id}.${pointId}.${index}`);
|
|
230
|
+
const contribution = {
|
|
231
|
+
id: contributionId,
|
|
232
|
+
metadata: {
|
|
233
|
+
extensionId: extension.id,
|
|
234
|
+
...item == null ? void 0 : item.metadata
|
|
235
|
+
},
|
|
236
|
+
data: item
|
|
237
|
+
};
|
|
238
|
+
const disposable = this.context.contributions.register(
|
|
239
|
+
pointId,
|
|
240
|
+
contribution
|
|
241
|
+
);
|
|
242
|
+
disposables.push(disposable);
|
|
243
|
+
const dispose = this.collectContribution(pointId, contribution);
|
|
244
|
+
if (dispose) {
|
|
245
|
+
disposables.push(dispose);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}
|
|
155
249
|
}
|
|
156
|
-
|
|
157
|
-
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
this.extensionRegistry.set(extension.id, extension);
|
|
253
|
+
this.context.eventBus.emit("extension:register", extension);
|
|
158
254
|
} catch (error) {
|
|
159
255
|
console.error(
|
|
160
|
-
`Error in onCreate hook for plugin "${extension.
|
|
256
|
+
`Error in onCreate hook for plugin "${extension.id}":`,
|
|
161
257
|
error
|
|
162
258
|
);
|
|
163
259
|
}
|
|
164
|
-
|
|
165
|
-
this.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
260
|
+
try {
|
|
261
|
+
extension.activate(this.context);
|
|
262
|
+
} catch (error) {
|
|
263
|
+
console.error(
|
|
264
|
+
`Error in onActivate hook for plugin "${extension.id}":`,
|
|
265
|
+
error
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
console.log(`Plugin "${extension.id}" registered successfully`);
|
|
269
|
+
}
|
|
270
|
+
collectContribution(pointId, item) {
|
|
271
|
+
if (pointId === ContributionPointIds.CONFIGURATIONS) {
|
|
272
|
+
const configService = this.context.services.get(
|
|
273
|
+
"ConfigurationService"
|
|
274
|
+
);
|
|
275
|
+
configService == null ? void 0 : configService.initializeDefaults([item.data]);
|
|
276
|
+
}
|
|
277
|
+
if (pointId === ContributionPointIds.COMMANDS && item.data.handler) {
|
|
278
|
+
const commandService = this.context.services.get("CommandService");
|
|
279
|
+
return commandService.registerCommand(item.id, item.data.handler);
|
|
176
280
|
}
|
|
177
|
-
console.log(`Plugin "${extension.name}" registered successfully`);
|
|
178
281
|
}
|
|
179
282
|
unregister(name) {
|
|
180
|
-
|
|
181
|
-
const extension = this.editor.extensions.get(name);
|
|
283
|
+
const extension = this.extensionRegistry.get(name);
|
|
182
284
|
if (!extension) {
|
|
183
285
|
console.warn(`Plugin "${name}" not found.`);
|
|
184
286
|
return;
|
|
185
287
|
}
|
|
186
|
-
if (this.mounted && extension.enabled) {
|
|
187
|
-
try {
|
|
188
|
-
(_a = extension.onUnmount) == null ? void 0 : _a.call(extension, this.editor);
|
|
189
|
-
} catch (error) {
|
|
190
|
-
console.error(`Error in onUnmount hook for plugin "${name}":`, error);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
288
|
try {
|
|
194
|
-
|
|
289
|
+
extension.deactivate(this.context);
|
|
195
290
|
} catch (error) {
|
|
196
|
-
console.error(`Error in
|
|
291
|
+
console.error(`Error in deactivate for plugin "${name}":`, error);
|
|
292
|
+
}
|
|
293
|
+
const disposables = this.extensionDisposables.get(name);
|
|
294
|
+
if (disposables) {
|
|
295
|
+
disposables.forEach((d) => d.dispose());
|
|
296
|
+
this.extensionDisposables.delete(name);
|
|
197
297
|
}
|
|
198
|
-
this.
|
|
199
|
-
this.editor.extensions.delete(name);
|
|
298
|
+
this.extensionRegistry.delete(name);
|
|
200
299
|
console.log(`Plugin "${name}" unregistered`);
|
|
201
300
|
return true;
|
|
202
301
|
}
|
|
203
302
|
enable(name) {
|
|
204
|
-
|
|
205
|
-
const extension = this.get(name);
|
|
303
|
+
const extension = this.extensionRegistry.get(name);
|
|
206
304
|
if (!extension) {
|
|
207
305
|
console.warn(`Plugin "${name}" not found.`);
|
|
208
306
|
return;
|
|
209
307
|
}
|
|
210
|
-
if (extension.enabled) return;
|
|
211
|
-
extension.enabled = true;
|
|
212
|
-
this._registerCommands(extension);
|
|
213
|
-
if (this.mounted) {
|
|
214
|
-
try {
|
|
215
|
-
(_a = extension.onMount) == null ? void 0 : _a.call(extension, this.editor);
|
|
216
|
-
} catch (error) {
|
|
217
|
-
console.error(`Error in onMount hook for plugin "${name}":`, error);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
308
|
}
|
|
221
309
|
disable(name) {
|
|
222
|
-
|
|
223
|
-
const extension = this.get(name);
|
|
310
|
+
const extension = this.extensionRegistry.get(name);
|
|
224
311
|
if (!extension) {
|
|
225
312
|
console.warn(`Plugin "${name}" not found.`);
|
|
226
313
|
return;
|
|
227
314
|
}
|
|
228
|
-
if (!extension.enabled) return;
|
|
229
|
-
extension.enabled = false;
|
|
230
|
-
this._unregisterCommands(extension);
|
|
231
|
-
if (this.mounted) {
|
|
232
|
-
try {
|
|
233
|
-
(_a = extension.onUnmount) == null ? void 0 : _a.call(extension, this.editor);
|
|
234
|
-
} catch (error) {
|
|
235
|
-
console.error(`Error in onUnmount hook for plugin "${name}":`, error);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
get(name) {
|
|
240
|
-
return this.editor.extensions.get(name);
|
|
241
|
-
}
|
|
242
|
-
has(name) {
|
|
243
|
-
return this.editor.extensions.has(name);
|
|
244
|
-
}
|
|
245
|
-
count() {
|
|
246
|
-
return this.editor.extensions.size;
|
|
247
|
-
}
|
|
248
|
-
list() {
|
|
249
|
-
return Array.from(this.editor.extensions.values());
|
|
250
|
-
}
|
|
251
|
-
mount() {
|
|
252
|
-
if (this.mounted) return;
|
|
253
|
-
this.editor.extensions.forEach((extension) => {
|
|
254
|
-
var _a;
|
|
255
|
-
if (extension.enabled) {
|
|
256
|
-
try {
|
|
257
|
-
console.log(`Mounting plugin "${extension.name}"`);
|
|
258
|
-
(_a = extension.onMount) == null ? void 0 : _a.call(extension, this.editor);
|
|
259
|
-
} catch (e) {
|
|
260
|
-
console.error(
|
|
261
|
-
`Error in onMount hook for plugin "${extension.name}":`,
|
|
262
|
-
e
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
console.log(`Plugins mounted`);
|
|
268
|
-
this.mounted = true;
|
|
269
|
-
}
|
|
270
|
-
unmount() {
|
|
271
|
-
if (!this.mounted) return;
|
|
272
|
-
this.editor.extensions.forEach((extension) => {
|
|
273
|
-
var _a;
|
|
274
|
-
if (extension.enabled) {
|
|
275
|
-
try {
|
|
276
|
-
(_a = extension.onUnmount) == null ? void 0 : _a.call(extension, this.editor);
|
|
277
|
-
} catch (e) {
|
|
278
|
-
console.error(
|
|
279
|
-
`Error in onUnmount hook for plugin "${extension.name}":`,
|
|
280
|
-
e
|
|
281
|
-
);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
console.log(`Plugins unmounted`);
|
|
286
|
-
this.mounted = false;
|
|
287
315
|
}
|
|
288
316
|
update() {
|
|
289
|
-
const state = this.editor.getState();
|
|
290
|
-
this.editor.extensions.forEach((extension) => {
|
|
291
|
-
var _a;
|
|
292
|
-
if (extension.enabled) {
|
|
293
|
-
try {
|
|
294
|
-
(_a = extension.onUpdate) == null ? void 0 : _a.call(extension, this.editor, state);
|
|
295
|
-
} catch (e) {
|
|
296
|
-
console.error(
|
|
297
|
-
`Error in onUpdate hook for plugin "${extension.name}":`,
|
|
298
|
-
e
|
|
299
|
-
);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
317
|
}
|
|
304
318
|
destroy() {
|
|
305
|
-
const extensionNames = Array.from(this.
|
|
319
|
+
const extensionNames = Array.from(this.extensionRegistry.keys());
|
|
306
320
|
extensionNames.forEach((name) => this.unregister(name));
|
|
307
|
-
this.mounted = false;
|
|
308
321
|
}
|
|
309
322
|
};
|
|
310
323
|
|
|
311
|
-
// src/
|
|
312
|
-
var
|
|
313
|
-
|
|
314
|
-
// src/editor.ts
|
|
315
|
-
var PooderEditor = class {
|
|
316
|
-
constructor(el, options = {}) {
|
|
317
|
-
this.extensions = /* @__PURE__ */ new Map();
|
|
324
|
+
// src/services/CommandService.ts
|
|
325
|
+
var CommandService = class {
|
|
326
|
+
constructor() {
|
|
318
327
|
this.commands = /* @__PURE__ */ new Map();
|
|
319
|
-
this.destroyed = false;
|
|
320
|
-
this.state = {
|
|
321
|
-
width: options.width || 800,
|
|
322
|
-
height: options.height || 600
|
|
323
|
-
};
|
|
324
|
-
this.canvas = new import_fabric.Canvas(el, {
|
|
325
|
-
width: this.state.width,
|
|
326
|
-
height: this.state.height,
|
|
327
|
-
preserveObjectStacking: true
|
|
328
|
-
});
|
|
329
|
-
this.eventBus = new EventBus();
|
|
330
|
-
this.commandManager = new DefaultCommandManager(this);
|
|
331
|
-
this.extensionManager = new DefaultExtensionManager(this);
|
|
332
|
-
if (options.extensions && options.extensions.length > 0) {
|
|
333
|
-
options.extensions.forEach(this.extensionManager.register);
|
|
334
|
-
}
|
|
335
|
-
this.extensionManager.mount();
|
|
336
|
-
console.log(
|
|
337
|
-
"Editor initialized with",
|
|
338
|
-
this.extensionManager.count(),
|
|
339
|
-
"plugins"
|
|
340
|
-
);
|
|
341
328
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
329
|
+
/**
|
|
330
|
+
* Register a command
|
|
331
|
+
* @param commandId Command Name (ID)
|
|
332
|
+
* @param handler Command handler function
|
|
333
|
+
* @param thisArg The `this` context for the handler
|
|
334
|
+
* @returns Disposable to unregister the command
|
|
335
|
+
*/
|
|
336
|
+
registerCommand(commandId, handler, thisArg) {
|
|
337
|
+
if (this.commands.has(commandId)) {
|
|
338
|
+
console.warn(
|
|
339
|
+
`Command "${commandId}" is already registered. Overwriting.`
|
|
340
|
+
);
|
|
345
341
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
342
|
+
const command = {
|
|
343
|
+
id: commandId,
|
|
344
|
+
handler: thisArg ? handler.bind(thisArg) : handler
|
|
345
|
+
};
|
|
346
|
+
this.commands.set(commandId, command);
|
|
347
|
+
return {
|
|
348
|
+
dispose: () => {
|
|
349
|
+
if (this.commands.get(commandId) === command) {
|
|
350
|
+
this.commands.delete(commandId);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
};
|
|
357
354
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
355
|
+
/**
|
|
356
|
+
* Execute a command
|
|
357
|
+
* @param commandId Command Name (ID)
|
|
358
|
+
* @param args Arguments to pass to the handler
|
|
359
|
+
* @returns The result of the command handler
|
|
360
|
+
*/
|
|
361
|
+
async executeCommand(commandId, ...args) {
|
|
362
|
+
const command = this.commands.get(commandId);
|
|
363
|
+
if (!command) {
|
|
364
|
+
throw new Error(`Command "${commandId}" not found.`);
|
|
365
|
+
}
|
|
366
|
+
try {
|
|
367
|
+
return await command.handler(...args);
|
|
368
|
+
} catch (error) {
|
|
369
|
+
console.error(`Error executing command "${commandId}":`, error);
|
|
370
|
+
throw error;
|
|
371
|
+
}
|
|
361
372
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
373
|
+
/**
|
|
374
|
+
* Get all registered commands
|
|
375
|
+
*/
|
|
376
|
+
getCommands() {
|
|
377
|
+
return this.commands;
|
|
365
378
|
}
|
|
366
|
-
|
|
367
|
-
|
|
379
|
+
/**
|
|
380
|
+
* Get a specific command
|
|
381
|
+
*/
|
|
382
|
+
getCommand(commandId) {
|
|
383
|
+
return this.commands.get(commandId);
|
|
368
384
|
}
|
|
369
|
-
|
|
370
|
-
this.
|
|
385
|
+
dispose() {
|
|
386
|
+
this.commands.clear();
|
|
371
387
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
// src/services/ConfigurationService.ts
|
|
391
|
+
var ConfigurationService = class {
|
|
392
|
+
constructor() {
|
|
393
|
+
this.configValues = /* @__PURE__ */ new Map();
|
|
394
|
+
this.eventBus = new event_default();
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Get a configuration value.
|
|
398
|
+
*/
|
|
399
|
+
get(key, defaultValue) {
|
|
400
|
+
if (this.configValues.has(key)) {
|
|
401
|
+
return this.configValues.get(key);
|
|
402
|
+
}
|
|
403
|
+
return defaultValue;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Update a configuration value.
|
|
407
|
+
* Emits 'change' event.
|
|
408
|
+
*/
|
|
409
|
+
update(key, value) {
|
|
410
|
+
const oldValue = this.configValues.get(key);
|
|
411
|
+
if (oldValue !== value) {
|
|
412
|
+
this.configValues.set(key, value);
|
|
413
|
+
this.eventBus.emit(`change:${key}`, { key, value, oldValue });
|
|
414
|
+
this.eventBus.emit("change", { key, value, oldValue });
|
|
376
415
|
}
|
|
377
|
-
this.emit("beforeCommand", name, ...args);
|
|
378
|
-
const result = this.commandManager.execute(name, ...args);
|
|
379
|
-
this.emit("afterCommand", name, args, result);
|
|
380
|
-
return result;
|
|
381
|
-
}
|
|
382
|
-
on(event, handler, priority) {
|
|
383
|
-
this.eventBus.on(event, handler, priority);
|
|
384
416
|
}
|
|
385
|
-
|
|
386
|
-
|
|
417
|
+
/**
|
|
418
|
+
* Listen for changes to a specific configuration key.
|
|
419
|
+
*/
|
|
420
|
+
onDidChange(key, callback) {
|
|
421
|
+
this.eventBus.on(`change:${key}`, callback);
|
|
422
|
+
return {
|
|
423
|
+
dispose: () => this.eventBus.off(`change:${key}`, callback)
|
|
424
|
+
};
|
|
387
425
|
}
|
|
388
|
-
|
|
389
|
-
|
|
426
|
+
/**
|
|
427
|
+
* Listen for any configuration change.
|
|
428
|
+
*/
|
|
429
|
+
onAnyChange(callback) {
|
|
430
|
+
this.eventBus.on("change", callback);
|
|
431
|
+
return {
|
|
432
|
+
dispose: () => this.eventBus.off("change", callback)
|
|
433
|
+
};
|
|
390
434
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
435
|
+
/**
|
|
436
|
+
* Export current configuration state as a JSON-serializable object.
|
|
437
|
+
* Useful for saving configuration templates.
|
|
438
|
+
*/
|
|
439
|
+
export() {
|
|
440
|
+
const exportData = {};
|
|
441
|
+
for (const [key, value] of this.configValues) {
|
|
442
|
+
exportData[key] = value;
|
|
394
443
|
}
|
|
395
|
-
return
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
444
|
+
return exportData;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Import configuration from a JSON object.
|
|
448
|
+
* This will merge the provided configuration with the current state,
|
|
449
|
+
* overwriting existing keys and triggering change events.
|
|
450
|
+
*/
|
|
451
|
+
import(data) {
|
|
452
|
+
if (!data || typeof data !== "object") {
|
|
453
|
+
console.warn("ConfigurationService: Import data must be an object.");
|
|
454
|
+
return;
|
|
404
455
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.id) === id;
|
|
456
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
457
|
+
this.update(key, value);
|
|
408
458
|
});
|
|
409
459
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
460
|
+
/**
|
|
461
|
+
* Initialize configuration with defaults from contributions.
|
|
462
|
+
* This should be called when a contribution is registered.
|
|
463
|
+
*/
|
|
464
|
+
initializeDefaults(contributions) {
|
|
465
|
+
contributions.forEach((contrib) => {
|
|
466
|
+
if (!contrib.id) {
|
|
467
|
+
console.warn(
|
|
468
|
+
"Configuration contribution missing 'id'. Skipping default initialization.",
|
|
469
|
+
contrib
|
|
470
|
+
);
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
if (!this.configValues.has(contrib.id) && contrib.default !== void 0) {
|
|
474
|
+
this.configValues.set(contrib.id, contrib.default);
|
|
475
|
+
}
|
|
419
476
|
});
|
|
420
477
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
this.
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
478
|
+
dispose() {
|
|
479
|
+
this.configValues.clear();
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
// src/index.ts
|
|
484
|
+
var Pooder = class {
|
|
485
|
+
constructor() {
|
|
486
|
+
this.eventBus = new event_default();
|
|
487
|
+
this.services = new ServiceRegistry();
|
|
488
|
+
this.contributions = new ContributionRegistry();
|
|
489
|
+
this.initDefaultContributionPoints();
|
|
490
|
+
const commandService = new CommandService();
|
|
491
|
+
this.registerService(commandService);
|
|
492
|
+
const configurationService = new ConfigurationService();
|
|
493
|
+
this.registerService(configurationService);
|
|
494
|
+
const context = {
|
|
495
|
+
eventBus: this.eventBus,
|
|
496
|
+
services: {
|
|
497
|
+
get: (serviceName) => this.services.get(serviceName)
|
|
498
|
+
},
|
|
499
|
+
contributions: {
|
|
500
|
+
get: (pointId) => this.getContributions(pointId),
|
|
501
|
+
register: (pointId, contribution) => this.registerContribution(pointId, contribution)
|
|
437
502
|
}
|
|
438
|
-
});
|
|
439
|
-
return {
|
|
440
|
-
width: this.state.width,
|
|
441
|
-
height: this.state.height,
|
|
442
|
-
metadata: this.state.metadata,
|
|
443
|
-
extensions
|
|
444
503
|
};
|
|
504
|
+
this.extensionManager = new ExtensionManager(context);
|
|
445
505
|
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
506
|
+
initDefaultContributionPoints() {
|
|
507
|
+
this.registerContributionPoint({
|
|
508
|
+
id: ContributionPointIds.CONTRIBUTIONS,
|
|
509
|
+
description: "Contribution point for contribution points"
|
|
510
|
+
});
|
|
511
|
+
this.registerContributionPoint({
|
|
512
|
+
id: ContributionPointIds.COMMANDS,
|
|
513
|
+
description: "Contribution point for commands"
|
|
514
|
+
});
|
|
515
|
+
this.registerContributionPoint({
|
|
516
|
+
id: ContributionPointIds.TOOLS,
|
|
517
|
+
description: "Contribution point for tools"
|
|
518
|
+
});
|
|
519
|
+
this.registerContributionPoint({
|
|
520
|
+
id: ContributionPointIds.VIEWS,
|
|
521
|
+
description: "Contribution point for UI views"
|
|
522
|
+
});
|
|
523
|
+
this.registerContributionPoint({
|
|
524
|
+
id: ContributionPointIds.CONFIGURATIONS,
|
|
525
|
+
description: "Contribution point for configurations"
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
// --- Service Management ---
|
|
529
|
+
registerService(service) {
|
|
530
|
+
var _a;
|
|
531
|
+
const serviceId = service.constructor.name;
|
|
532
|
+
try {
|
|
533
|
+
(_a = service == null ? void 0 : service.init) == null ? void 0 : _a.call(service);
|
|
534
|
+
} catch (e) {
|
|
535
|
+
console.error(`Error initializing service ${serviceId}:`, e);
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
this.services.register(serviceId, service);
|
|
539
|
+
this.eventBus.emit("service:register", service);
|
|
540
|
+
return true;
|
|
541
|
+
}
|
|
542
|
+
unregisterService(service) {
|
|
543
|
+
var _a;
|
|
544
|
+
const serviceId = service.constructor.name;
|
|
545
|
+
if (!this.services.has(serviceId)) {
|
|
546
|
+
console.warn(`Service ${serviceId} is not registered.`);
|
|
547
|
+
return true;
|
|
548
|
+
}
|
|
549
|
+
try {
|
|
550
|
+
(_a = service == null ? void 0 : service.dispose) == null ? void 0 : _a.call(service);
|
|
551
|
+
} catch (e) {
|
|
552
|
+
console.error(`Error disposing service ${serviceId}:`, e);
|
|
553
|
+
return false;
|
|
462
554
|
}
|
|
463
|
-
this.
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
height: json.height,
|
|
467
|
-
metadata: json.metadata
|
|
468
|
-
}));
|
|
555
|
+
this.services.delete(serviceId);
|
|
556
|
+
this.eventBus.emit("service:unregister", service);
|
|
557
|
+
return true;
|
|
469
558
|
}
|
|
470
|
-
|
|
471
|
-
return
|
|
559
|
+
getService(id) {
|
|
560
|
+
return this.services.get(id);
|
|
472
561
|
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
this.
|
|
476
|
-
this.
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
this.
|
|
480
|
-
this.
|
|
481
|
-
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
return this.
|
|
562
|
+
// --- Contribution Management ---
|
|
563
|
+
registerContributionPoint(point) {
|
|
564
|
+
this.contributions.registerPoint(point);
|
|
565
|
+
this.eventBus.emit("contribution:point:register", point);
|
|
566
|
+
}
|
|
567
|
+
registerContribution(pointId, contribution) {
|
|
568
|
+
const disposable = this.contributions.register(pointId, contribution);
|
|
569
|
+
this.eventBus.emit("contribution:register", { ...contribution, pointId });
|
|
570
|
+
return disposable;
|
|
571
|
+
}
|
|
572
|
+
getContributions(pointId) {
|
|
573
|
+
return this.contributions.get(pointId);
|
|
485
574
|
}
|
|
486
575
|
};
|
|
487
|
-
|
|
488
|
-
// src/layer.ts
|
|
489
|
-
var import_fabric2 = require("fabric");
|
|
490
|
-
|
|
491
|
-
// src/obj.ts
|
|
492
|
-
var import_fabric3 = require("fabric");
|
|
493
|
-
|
|
494
|
-
// src/index.ts
|
|
495
|
-
var import_fabric4 = require("fabric");
|
|
496
576
|
// Annotate the CommonJS export names for ESM import in node:
|
|
497
577
|
0 && (module.exports = {
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
PooderCanvas,
|
|
507
|
-
PooderEditor,
|
|
508
|
-
PooderLayer,
|
|
509
|
-
PooderObject,
|
|
510
|
-
Rect,
|
|
511
|
-
Text,
|
|
512
|
-
filters,
|
|
513
|
-
util
|
|
578
|
+
CommandService,
|
|
579
|
+
ConfigurationService,
|
|
580
|
+
ContributionPointIds,
|
|
581
|
+
ContributionRegistry,
|
|
582
|
+
ExtensionManager,
|
|
583
|
+
ExtensionRegistry,
|
|
584
|
+
Pooder,
|
|
585
|
+
ServiceRegistry
|
|
514
586
|
});
|