@momentumcms/plugins-core 0.0.1 → 0.1.2
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 +12 -0
- package/index.js +499 -0
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## 0.1.2 (2026-02-16)
|
|
2
|
+
|
|
3
|
+
### 🩹 Fixes
|
|
4
|
+
|
|
5
|
+
- **release:** centralize manifestRootsToUpdate to update both source and dist ([2b8f832](https://github.com/DonaldMurillo/momentum-cms/commit/2b8f832))
|
|
6
|
+
- **create-app:** fix Angular SSR, Analog builds, and CJS/ESM compatibility ([28d4d0a](https://github.com/DonaldMurillo/momentum-cms/commit/28d4d0a))
|
|
7
|
+
|
|
8
|
+
### ❤️ Thank You
|
|
9
|
+
|
|
10
|
+
- Claude Opus 4.6
|
|
11
|
+
- Donald Murillo @DonaldMurillo
|
|
12
|
+
|
|
1
13
|
## 0.1.1 (2026-02-16)
|
|
2
14
|
|
|
3
15
|
This was a version bump only for plugins-core to align it with other projects, there were no code changes.
|
package/index.js
ADDED
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
// libs/logger/src/lib/log-level.ts
|
|
2
|
+
var LOG_LEVEL_VALUES = {
|
|
3
|
+
debug: 0,
|
|
4
|
+
info: 1,
|
|
5
|
+
warn: 2,
|
|
6
|
+
error: 3,
|
|
7
|
+
fatal: 4,
|
|
8
|
+
silent: 5
|
|
9
|
+
};
|
|
10
|
+
function shouldLog(messageLevel, configuredLevel) {
|
|
11
|
+
return LOG_LEVEL_VALUES[messageLevel] >= LOG_LEVEL_VALUES[configuredLevel];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// libs/logger/src/lib/ansi-colors.ts
|
|
15
|
+
var ANSI = {
|
|
16
|
+
reset: "\x1B[0m",
|
|
17
|
+
bold: "\x1B[1m",
|
|
18
|
+
dim: "\x1B[2m",
|
|
19
|
+
// Foreground colors
|
|
20
|
+
red: "\x1B[31m",
|
|
21
|
+
green: "\x1B[32m",
|
|
22
|
+
yellow: "\x1B[33m",
|
|
23
|
+
blue: "\x1B[34m",
|
|
24
|
+
magenta: "\x1B[35m",
|
|
25
|
+
cyan: "\x1B[36m",
|
|
26
|
+
white: "\x1B[37m",
|
|
27
|
+
gray: "\x1B[90m",
|
|
28
|
+
// Background colors
|
|
29
|
+
bgRed: "\x1B[41m",
|
|
30
|
+
bgYellow: "\x1B[43m"
|
|
31
|
+
};
|
|
32
|
+
function colorize(text, ...codes) {
|
|
33
|
+
if (codes.length === 0)
|
|
34
|
+
return text;
|
|
35
|
+
return `${codes.join("")}${text}${ANSI.reset}`;
|
|
36
|
+
}
|
|
37
|
+
function supportsColor() {
|
|
38
|
+
if (process.env["FORCE_COLOR"] === "1")
|
|
39
|
+
return true;
|
|
40
|
+
if (process.env["NO_COLOR"] !== void 0)
|
|
41
|
+
return false;
|
|
42
|
+
if (process.env["TERM"] === "dumb")
|
|
43
|
+
return false;
|
|
44
|
+
return process.stdout.isTTY === true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// libs/logger/src/lib/formatters.ts
|
|
48
|
+
var LEVEL_COLORS = {
|
|
49
|
+
debug: [ANSI.dim, ANSI.gray],
|
|
50
|
+
info: [ANSI.cyan],
|
|
51
|
+
warn: [ANSI.yellow],
|
|
52
|
+
error: [ANSI.red],
|
|
53
|
+
fatal: [ANSI.bold, ANSI.white, ANSI.bgRed]
|
|
54
|
+
};
|
|
55
|
+
function padLevel(level) {
|
|
56
|
+
return level.toUpperCase().padEnd(5);
|
|
57
|
+
}
|
|
58
|
+
function formatTimestamp(date) {
|
|
59
|
+
const y = date.getFullYear();
|
|
60
|
+
const mo = String(date.getMonth() + 1).padStart(2, "0");
|
|
61
|
+
const d = String(date.getDate()).padStart(2, "0");
|
|
62
|
+
const h = String(date.getHours()).padStart(2, "0");
|
|
63
|
+
const mi = String(date.getMinutes()).padStart(2, "0");
|
|
64
|
+
const s = String(date.getSeconds()).padStart(2, "0");
|
|
65
|
+
const ms = String(date.getMilliseconds()).padStart(3, "0");
|
|
66
|
+
return `${y}-${mo}-${d} ${h}:${mi}:${s}.${ms}`;
|
|
67
|
+
}
|
|
68
|
+
function formatData(data) {
|
|
69
|
+
const entries = Object.entries(data);
|
|
70
|
+
if (entries.length === 0)
|
|
71
|
+
return "";
|
|
72
|
+
return " " + entries.map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`).join(" ");
|
|
73
|
+
}
|
|
74
|
+
function prettyFormatter(entry) {
|
|
75
|
+
const useColor = supportsColor();
|
|
76
|
+
const level = entry.level;
|
|
77
|
+
const ts = formatTimestamp(entry.timestamp);
|
|
78
|
+
const levelStr = padLevel(entry.level);
|
|
79
|
+
const ctx = `[${entry.context}]`;
|
|
80
|
+
const msg = entry.message;
|
|
81
|
+
const enrichmentStr = entry.enrichments ? formatData(entry.enrichments) : "";
|
|
82
|
+
const dataStr = entry.data ? formatData(entry.data) : "";
|
|
83
|
+
const extra = `${enrichmentStr}${dataStr}`;
|
|
84
|
+
if (useColor) {
|
|
85
|
+
const colors = LEVEL_COLORS[level];
|
|
86
|
+
const coloredLevel = colorize(levelStr, ...colors);
|
|
87
|
+
const coloredCtx = colorize(ctx, ANSI.magenta);
|
|
88
|
+
const coloredTs = colorize(ts, ANSI.gray);
|
|
89
|
+
return `${coloredTs} ${coloredLevel} ${coloredCtx} ${msg}${extra}
|
|
90
|
+
`;
|
|
91
|
+
}
|
|
92
|
+
return `${ts} ${levelStr} ${ctx} ${msg}${extra}
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
function jsonFormatter(entry) {
|
|
96
|
+
const output = {
|
|
97
|
+
timestamp: entry.timestamp.toISOString(),
|
|
98
|
+
level: entry.level,
|
|
99
|
+
context: entry.context,
|
|
100
|
+
message: entry.message
|
|
101
|
+
};
|
|
102
|
+
if (entry.enrichments && Object.keys(entry.enrichments).length > 0) {
|
|
103
|
+
Object.assign(output, entry.enrichments);
|
|
104
|
+
}
|
|
105
|
+
if (entry.data && Object.keys(entry.data).length > 0) {
|
|
106
|
+
output["data"] = entry.data;
|
|
107
|
+
}
|
|
108
|
+
return JSON.stringify(output) + "\n";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// libs/logger/src/lib/logger-config.types.ts
|
|
112
|
+
function resolveLoggingConfig(config) {
|
|
113
|
+
return {
|
|
114
|
+
level: config?.level ?? "info",
|
|
115
|
+
format: config?.format ?? "pretty",
|
|
116
|
+
timestamps: config?.timestamps ?? true,
|
|
117
|
+
output: config?.output ?? ((msg) => {
|
|
118
|
+
process.stdout.write(msg);
|
|
119
|
+
}),
|
|
120
|
+
errorOutput: config?.errorOutput ?? ((msg) => {
|
|
121
|
+
process.stderr.write(msg);
|
|
122
|
+
})
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// libs/logger/src/lib/logger.ts
|
|
127
|
+
var ERROR_LEVELS = /* @__PURE__ */ new Set(["warn", "error", "fatal"]);
|
|
128
|
+
var MomentumLogger = class _MomentumLogger {
|
|
129
|
+
static {
|
|
130
|
+
this.enrichers = [];
|
|
131
|
+
}
|
|
132
|
+
constructor(context, config) {
|
|
133
|
+
this.context = context;
|
|
134
|
+
this.config = isResolvedConfig(config) ? config : resolveLoggingConfig(config);
|
|
135
|
+
this.formatter = this.config.format === "json" ? jsonFormatter : prettyFormatter;
|
|
136
|
+
}
|
|
137
|
+
debug(message, data) {
|
|
138
|
+
this.log("debug", message, data);
|
|
139
|
+
}
|
|
140
|
+
info(message, data) {
|
|
141
|
+
this.log("info", message, data);
|
|
142
|
+
}
|
|
143
|
+
warn(message, data) {
|
|
144
|
+
this.log("warn", message, data);
|
|
145
|
+
}
|
|
146
|
+
error(message, data) {
|
|
147
|
+
this.log("error", message, data);
|
|
148
|
+
}
|
|
149
|
+
fatal(message, data) {
|
|
150
|
+
this.log("fatal", message, data);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Creates a child logger with a sub-context.
|
|
154
|
+
* e.g., `Momentum:DB` → `Momentum:DB:Migrate`
|
|
155
|
+
*/
|
|
156
|
+
child(subContext) {
|
|
157
|
+
return new _MomentumLogger(`${this.context}:${subContext}`, this.config);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Registers a global enricher that adds extra fields to all log entries.
|
|
161
|
+
*/
|
|
162
|
+
static registerEnricher(enricher) {
|
|
163
|
+
_MomentumLogger.enrichers.push(enricher);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Removes a previously registered enricher.
|
|
167
|
+
*/
|
|
168
|
+
static removeEnricher(enricher) {
|
|
169
|
+
const index = _MomentumLogger.enrichers.indexOf(enricher);
|
|
170
|
+
if (index >= 0) {
|
|
171
|
+
_MomentumLogger.enrichers.splice(index, 1);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Clears all registered enrichers. Primarily for testing.
|
|
176
|
+
*/
|
|
177
|
+
static clearEnrichers() {
|
|
178
|
+
_MomentumLogger.enrichers.length = 0;
|
|
179
|
+
}
|
|
180
|
+
log(level, message, data) {
|
|
181
|
+
if (!shouldLog(level, this.config.level))
|
|
182
|
+
return;
|
|
183
|
+
const enrichments = this.collectEnrichments();
|
|
184
|
+
const entry = {
|
|
185
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
186
|
+
level,
|
|
187
|
+
context: this.context,
|
|
188
|
+
message,
|
|
189
|
+
data,
|
|
190
|
+
enrichments: Object.keys(enrichments).length > 0 ? enrichments : void 0
|
|
191
|
+
};
|
|
192
|
+
const formatted = this.formatter(entry);
|
|
193
|
+
if (ERROR_LEVELS.has(level)) {
|
|
194
|
+
this.config.errorOutput(formatted);
|
|
195
|
+
} else {
|
|
196
|
+
this.config.output(formatted);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
collectEnrichments() {
|
|
200
|
+
const result = {};
|
|
201
|
+
for (const enricher of _MomentumLogger.enrichers) {
|
|
202
|
+
Object.assign(result, enricher.enrich());
|
|
203
|
+
}
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
function isResolvedConfig(config) {
|
|
208
|
+
if (!config)
|
|
209
|
+
return false;
|
|
210
|
+
return typeof config.level === "string" && typeof config.format === "string" && typeof config.timestamps === "boolean" && // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- type guard narrows union
|
|
211
|
+
typeof config.output === "function" && // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- type guard narrows union
|
|
212
|
+
typeof config.errorOutput === "function";
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// libs/logger/src/lib/logger-singleton.ts
|
|
216
|
+
var loggerInstance = null;
|
|
217
|
+
var ROOT_CONTEXT = "Momentum";
|
|
218
|
+
function getMomentumLogger() {
|
|
219
|
+
if (!loggerInstance) {
|
|
220
|
+
loggerInstance = new MomentumLogger(ROOT_CONTEXT);
|
|
221
|
+
}
|
|
222
|
+
return loggerInstance;
|
|
223
|
+
}
|
|
224
|
+
function createLogger(context) {
|
|
225
|
+
return getMomentumLogger().child(context);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// libs/plugins/core/src/lib/plugin-fatal-error.ts
|
|
229
|
+
var PluginFatalError = class extends Error {
|
|
230
|
+
constructor(pluginName, message) {
|
|
231
|
+
super(`[Plugin:${pluginName}] Fatal: ${message}`);
|
|
232
|
+
this.name = "PluginFatalError";
|
|
233
|
+
this.pluginName = pluginName;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// libs/plugins/core/src/lib/plugin-runner.ts
|
|
238
|
+
var PluginRunner = class {
|
|
239
|
+
constructor(options) {
|
|
240
|
+
this.middlewareDescriptors = [];
|
|
241
|
+
this.providerDescriptors = [];
|
|
242
|
+
this.initialized = false;
|
|
243
|
+
this.ready = false;
|
|
244
|
+
this.plugins = options.plugins;
|
|
245
|
+
this.config = options.config;
|
|
246
|
+
this.collections = options.collections;
|
|
247
|
+
this.logger = createLogger("Plugins");
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Create a plugin-scoped context.
|
|
251
|
+
*/
|
|
252
|
+
createContext(plugin) {
|
|
253
|
+
return {
|
|
254
|
+
config: this.config,
|
|
255
|
+
collections: this.collections,
|
|
256
|
+
logger: this.logger.child(plugin.name),
|
|
257
|
+
registerMiddleware: (descriptor) => {
|
|
258
|
+
this.middlewareDescriptors.push(descriptor);
|
|
259
|
+
},
|
|
260
|
+
registerProvider: (descriptor) => {
|
|
261
|
+
this.providerDescriptors.push(descriptor);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Run onInit for all plugins (in order).
|
|
267
|
+
* Call this before API initialization.
|
|
268
|
+
*/
|
|
269
|
+
async runInit() {
|
|
270
|
+
if (this.initialized) {
|
|
271
|
+
this.logger.warn("Plugins already initialized");
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
for (const plugin of this.plugins) {
|
|
275
|
+
try {
|
|
276
|
+
if (plugin.onInit) {
|
|
277
|
+
this.logger.debug(`Initializing plugin: ${plugin.name}`);
|
|
278
|
+
await plugin.onInit(this.createContext(plugin));
|
|
279
|
+
}
|
|
280
|
+
} catch (error) {
|
|
281
|
+
if (error instanceof PluginFatalError) {
|
|
282
|
+
throw error;
|
|
283
|
+
}
|
|
284
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
285
|
+
this.logger.error(`Plugin "${plugin.name}" failed during onInit: ${message}`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
this.initialized = true;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Run onReady for all plugins (in order).
|
|
292
|
+
* Call this after API + seeding complete.
|
|
293
|
+
*/
|
|
294
|
+
async runReady(api) {
|
|
295
|
+
if (this.ready) {
|
|
296
|
+
this.logger.warn("Plugins already marked ready");
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
for (const plugin of this.plugins) {
|
|
300
|
+
try {
|
|
301
|
+
if (plugin.onReady) {
|
|
302
|
+
this.logger.debug(`Plugin ready: ${plugin.name}`);
|
|
303
|
+
const context = {
|
|
304
|
+
...this.createContext(plugin),
|
|
305
|
+
api
|
|
306
|
+
};
|
|
307
|
+
await plugin.onReady(context);
|
|
308
|
+
}
|
|
309
|
+
} catch (error) {
|
|
310
|
+
if (error instanceof PluginFatalError) {
|
|
311
|
+
throw error;
|
|
312
|
+
}
|
|
313
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
314
|
+
this.logger.error(`Plugin "${plugin.name}" failed during onReady: ${message}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
this.ready = true;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Run onShutdown for all plugins (in reverse order).
|
|
321
|
+
* Call this during graceful shutdown.
|
|
322
|
+
*/
|
|
323
|
+
async runShutdown() {
|
|
324
|
+
const reversed = [...this.plugins].reverse();
|
|
325
|
+
for (const plugin of reversed) {
|
|
326
|
+
try {
|
|
327
|
+
if (plugin.onShutdown) {
|
|
328
|
+
this.logger.debug(`Shutting down plugin: ${plugin.name}`);
|
|
329
|
+
await plugin.onShutdown(this.createContext(plugin));
|
|
330
|
+
}
|
|
331
|
+
} catch (error) {
|
|
332
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
333
|
+
this.logger.error(`Plugin "${plugin.name}" failed during onShutdown: ${message}`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Get the list of registered plugin names.
|
|
339
|
+
*/
|
|
340
|
+
getPluginNames() {
|
|
341
|
+
return this.plugins.map((p) => p.name);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Get middleware descriptors registered by plugins during onInit.
|
|
345
|
+
* Returns descriptors in the order they were registered.
|
|
346
|
+
*/
|
|
347
|
+
getMiddleware() {
|
|
348
|
+
return [...this.middlewareDescriptors];
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Get provider descriptors registered by plugins during onInit.
|
|
352
|
+
* Returns descriptors in the order they were registered.
|
|
353
|
+
*/
|
|
354
|
+
getProviders() {
|
|
355
|
+
return [...this.providerDescriptors];
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
// libs/plugins/core/src/lib/hook-injector.ts
|
|
360
|
+
function injectCollectionEventHooks(collections, listener) {
|
|
361
|
+
for (const collection of collections) {
|
|
362
|
+
collection.hooks = collection.hooks ?? {};
|
|
363
|
+
const afterChangeHook = (args) => {
|
|
364
|
+
const operation = args.operation ?? "create";
|
|
365
|
+
const eventType = operation === "create" ? "afterChange" : "afterChange";
|
|
366
|
+
const event = {
|
|
367
|
+
collection: collection.slug,
|
|
368
|
+
event: eventType,
|
|
369
|
+
operation,
|
|
370
|
+
doc: args.doc ?? args.data,
|
|
371
|
+
previousDoc: args.originalDoc,
|
|
372
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
373
|
+
};
|
|
374
|
+
listener(event);
|
|
375
|
+
};
|
|
376
|
+
const existingAfterChange = collection.hooks.afterChange ?? [];
|
|
377
|
+
collection.hooks.afterChange = [...existingAfterChange, afterChangeHook];
|
|
378
|
+
const afterDeleteHook = (args) => {
|
|
379
|
+
const event = {
|
|
380
|
+
collection: collection.slug,
|
|
381
|
+
event: "afterDelete",
|
|
382
|
+
operation: "delete",
|
|
383
|
+
doc: args.doc,
|
|
384
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
385
|
+
};
|
|
386
|
+
listener(event);
|
|
387
|
+
};
|
|
388
|
+
const existingAfterDelete = collection.hooks.afterDelete ?? [];
|
|
389
|
+
collection.hooks.afterDelete = [...existingAfterDelete, afterDeleteHook];
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// libs/plugins/core/src/lib/event-bus/event-bus.ts
|
|
394
|
+
var MomentumEventBus = class {
|
|
395
|
+
constructor() {
|
|
396
|
+
this.subscriptions = [];
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Subscribe to events matching a pattern.
|
|
400
|
+
*
|
|
401
|
+
* @param pattern - Pattern string: "collection:event", "*:event", "collection:*", or "*"
|
|
402
|
+
* @param handler - Callback invoked when a matching event occurs
|
|
403
|
+
* @returns Unsubscribe function
|
|
404
|
+
*
|
|
405
|
+
* @example
|
|
406
|
+
* ```typescript
|
|
407
|
+
* bus.on('posts:afterChange', (event) => { ... });
|
|
408
|
+
* bus.on('*:afterDelete', (event) => { ... });
|
|
409
|
+
* const unsub = bus.on('*', (event) => { ... });
|
|
410
|
+
* unsub(); // remove subscription
|
|
411
|
+
* ```
|
|
412
|
+
*/
|
|
413
|
+
on(pattern, handler) {
|
|
414
|
+
const subscription = { pattern, handler };
|
|
415
|
+
this.subscriptions.push(subscription);
|
|
416
|
+
return () => {
|
|
417
|
+
const index = this.subscriptions.indexOf(subscription);
|
|
418
|
+
if (index !== -1) {
|
|
419
|
+
this.subscriptions.splice(index, 1);
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Subscribe to all events for a specific collection.
|
|
425
|
+
* Shorthand for `on("collection:*", handler)`.
|
|
426
|
+
*/
|
|
427
|
+
onCollection(collection, handler) {
|
|
428
|
+
return this.on(`${collection}:*`, handler);
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Subscribe to a specific event type across all collections.
|
|
432
|
+
* Shorthand for `on("*:event", handler)`.
|
|
433
|
+
*/
|
|
434
|
+
onEvent(event, handler) {
|
|
435
|
+
return this.on(`*:${event}`, handler);
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Emit a collection event to all matching subscribers.
|
|
439
|
+
*/
|
|
440
|
+
emit(event) {
|
|
441
|
+
for (const sub of this.subscriptions) {
|
|
442
|
+
if (matchesPattern(sub.pattern, event.collection, event.event)) {
|
|
443
|
+
sub.handler(event);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Remove all subscriptions.
|
|
449
|
+
*/
|
|
450
|
+
clear() {
|
|
451
|
+
this.subscriptions = [];
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Get the current number of subscriptions.
|
|
455
|
+
*/
|
|
456
|
+
get size() {
|
|
457
|
+
return this.subscriptions.length;
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
function matchesPattern(pattern, collection, event) {
|
|
461
|
+
if (pattern === "*") {
|
|
462
|
+
return true;
|
|
463
|
+
}
|
|
464
|
+
const parts = pattern.split(":");
|
|
465
|
+
if (parts.length !== 2) {
|
|
466
|
+
return false;
|
|
467
|
+
}
|
|
468
|
+
const [patternCollection, patternEvent] = parts;
|
|
469
|
+
const collectionMatch = patternCollection === "*" || patternCollection === collection;
|
|
470
|
+
const eventMatch = patternEvent === "*" || patternEvent === event;
|
|
471
|
+
return collectionMatch && eventMatch;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// libs/plugins/core/src/lib/event-bus/event-bus-plugin.ts
|
|
475
|
+
function eventBusPlugin() {
|
|
476
|
+
const bus = new MomentumEventBus();
|
|
477
|
+
return {
|
|
478
|
+
name: "event-bus",
|
|
479
|
+
bus,
|
|
480
|
+
onInit({ collections, logger }) {
|
|
481
|
+
logger.info("Injecting event hooks into collections");
|
|
482
|
+
injectCollectionEventHooks(collections, (event) => {
|
|
483
|
+
bus.emit(event);
|
|
484
|
+
});
|
|
485
|
+
logger.info(`Event hooks injected into ${collections.length} collections`);
|
|
486
|
+
},
|
|
487
|
+
onShutdown({ logger }) {
|
|
488
|
+
logger.info("Clearing event bus subscriptions");
|
|
489
|
+
bus.clear();
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
export {
|
|
494
|
+
MomentumEventBus,
|
|
495
|
+
PluginFatalError,
|
|
496
|
+
PluginRunner,
|
|
497
|
+
eventBusPlugin,
|
|
498
|
+
injectCollectionEventHooks
|
|
499
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@momentumcms/plugins-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Plugin system core and event bus for Momentum CMS",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Momentum CMS Contributors",
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"engines": {
|
|
23
23
|
"node": ">=18"
|
|
24
24
|
},
|
|
25
|
-
"type": "commonjs",
|
|
26
25
|
"main": "./index.cjs",
|
|
27
26
|
"types": "./src/index.d.ts",
|
|
28
27
|
"dependencies": {
|
|
29
|
-
"@momentumcms/core": "0.
|
|
30
|
-
"@momentumcms/logger": "0.
|
|
31
|
-
}
|
|
28
|
+
"@momentumcms/core": "0.1.2",
|
|
29
|
+
"@momentumcms/logger": "0.1.2"
|
|
30
|
+
},
|
|
31
|
+
"module": "./index.js"
|
|
32
32
|
}
|