kaelum 1.4.8 → 1.5.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/core/plugin.js ADDED
@@ -0,0 +1,82 @@
1
+ // core/plugin.js
2
+ // Kaelum plugin registration system.
3
+ // Plugins are functions that receive (app, options) and can add routes,
4
+ // middleware, and config to the Kaelum app instance.
5
+
6
+ /**
7
+ * Resolve the display name and dedup key for a plugin function.
8
+ * Checks fn.pluginName first, then fn.name, falls back to null (anonymous).
9
+ * @param {Function} fn
10
+ * @returns {string|null}
11
+ */
12
+ function resolvePluginName(fn) {
13
+ if (typeof fn.pluginName === "string" && fn.pluginName) {
14
+ return fn.pluginName;
15
+ }
16
+ if (typeof fn.name === "string" && fn.name) {
17
+ return fn.name;
18
+ }
19
+ return null;
20
+ }
21
+
22
+ /**
23
+ * Register a plugin on the Kaelum app.
24
+ *
25
+ * @param {Object} app - Kaelum/Express app instance
26
+ * @param {Function} fn - Plugin function with signature (app, options) => void
27
+ * @param {Object} [options={}] - Options passed to the plugin
28
+ * @returns {Object} app - for chaining
29
+ * @throws {Error} if fn is not a function
30
+ * @throws {Error} if a named plugin with the same name is already registered
31
+ */
32
+ function registerPlugin(app, fn, options = {}) {
33
+ if (typeof fn !== "function") {
34
+ throw new Error(
35
+ `Kaelum plugin: expected a function, got ${typeof fn}`
36
+ );
37
+ }
38
+
39
+ // ensure registry exists
40
+ if (!app.locals) app.locals = {};
41
+ if (!Array.isArray(app.locals._kaelum_plugins)) {
42
+ app.locals._kaelum_plugins = [];
43
+ }
44
+
45
+ const name = resolvePluginName(fn);
46
+
47
+ // duplicate guard for named plugins
48
+ if (name) {
49
+ const already = app.locals._kaelum_plugins.find((p) => p.name === name);
50
+ if (already) {
51
+ throw new Error(
52
+ `Kaelum plugin: "${name}" is already registered. ` +
53
+ `Each named plugin can only be registered once.`
54
+ );
55
+ }
56
+ }
57
+
58
+ // execute the plugin
59
+ fn(app, options);
60
+
61
+ // record in registry
62
+ app.locals._kaelum_plugins.push({
63
+ name: name || `anonymous_${app.locals._kaelum_plugins.length}`,
64
+ options,
65
+ });
66
+
67
+ return app;
68
+ }
69
+
70
+ /**
71
+ * Return the list of registered plugin names.
72
+ * @param {Object} app
73
+ * @returns {string[]}
74
+ */
75
+ function getPlugins(app) {
76
+ if (!app.locals || !Array.isArray(app.locals._kaelum_plugins)) {
77
+ return [];
78
+ }
79
+ return app.locals._kaelum_plugins.map((p) => p.name);
80
+ }
81
+
82
+ module.exports = { registerPlugin, getPlugins };
package/createApp.js CHANGED
@@ -19,6 +19,7 @@ const { errorHandler } = require("./core/errorHandler");
19
19
  const registerHealth = require("./core/healthCheck");
20
20
  const redirect = require("./core/redirect");
21
21
  const { removeMiddlewareByFn } = require("./core/utils");
22
+ const { registerPlugin, getPlugins } = require("./core/plugin");
22
23
 
23
24
  function createApp() {
24
25
  const app = express();
@@ -29,6 +30,7 @@ function createApp() {
29
30
  // ensure locals object and initial persisted config
30
31
  app.locals = app.locals || {};
31
32
  app.locals.kaelumConfig = app.locals.kaelumConfig || {};
33
+ app.locals._kaelum_plugins = [];
32
34
  // persist baseline config so app.get("kaelum:config") is always available
33
35
  app.set("kaelum:config", app.locals.kaelumConfig);
34
36
 
@@ -169,6 +171,17 @@ function createApp() {
169
171
  // alias for convenience
170
172
  app.errorHandler = app.useErrorHandler;
171
173
 
174
+ // ---------------------------
175
+ // Plugin system
176
+ // ---------------------------
177
+ app.plugin = function (fn, options) {
178
+ return registerPlugin(app, fn, options);
179
+ };
180
+
181
+ app.getPlugins = function () {
182
+ return getPlugins(app);
183
+ };
184
+
172
185
  return app;
173
186
  }
174
187
 
package/index.d.ts CHANGED
@@ -53,6 +53,9 @@ interface RouteHandlers {
53
53
  [subpath: string]: any;
54
54
  }
55
55
 
56
+ /** Plugin function signature */
57
+ type KaelumPlugin = (app: KaelumApp, options?: Record<string, any>) => void;
58
+
56
59
  interface KaelumApp extends Express {
57
60
  /** Configure Kaelum features (cors, helmet, static, logs, etc.) */
58
61
  setConfig(options: KaelumConfig): KaelumConfig;
@@ -93,6 +96,12 @@ interface KaelumApp extends Express {
93
96
 
94
97
  /** Remove static file serving */
95
98
  removeStatic(): KaelumConfig;
99
+
100
+ /** Register a plugin */
101
+ plugin(fn: KaelumPlugin, options?: Record<string, any>): KaelumApp;
102
+
103
+ /** List registered plugin names */
104
+ getPlugins(): string[];
96
105
  }
97
106
 
98
107
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kaelum",
3
- "version": "1.4.8",
3
+ "version": "1.5.0",
4
4
  "description": "A minimalist Node.js framework for building web pages and APIs with simplicity and speed.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",