@majkapp/plugin-kit 1.0.7 → 1.0.8

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.
@@ -33,6 +33,18 @@ export interface FluentBuilder<Id extends string> {
33
33
  onReady(fn: (ctx: PluginContext, cleanup: (fn: CleanupFn) => void) => void | Promise<void>): this;
34
34
  /** Custom health check */
35
35
  health(fn: HealthCheckFn): this;
36
+ /**
37
+ * Set the plugin root directory explicitly (use __dirname from your plugin entry file).
38
+ * This ensures plugin-kit can find your files in both local development and npm installed scenarios.
39
+ * If not provided, falls back to the pluginRoot from MAJK's context.
40
+ *
41
+ * @example
42
+ * const plugin = definePlugin('my-plugin', 'My Plugin', '1.0.0')
43
+ * .pluginRoot(__dirname) // Use Node's __dirname
44
+ * .ui({ appDir: 'dist' }) // Now resolves relative to __dirname
45
+ * .build();
46
+ */
47
+ pluginRoot(dir: string): this;
36
48
  /** Build the plugin */
37
49
  build(): InProcessPlugin;
38
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-kit.d.ts","sourceRoot":"","sources":["../src/plugin-kit.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,aAAa,EAGb,eAAe,EACf,QAAQ,EACR,WAAW,EACX,WAAW,EACX,QAAQ,EACR,WAAW,EACX,UAAU,EACV,eAAe,EACf,WAAW,EACX,KAAK,EACL,UAAU,EACV,SAAS,EACT,aAAa,EAIb,eAAe,EACf,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAgqBjB;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,EAAE,SAAS,MAAM;IAC9C,mDAAmD;IACnD,MAAM,CAAC,KAAK,EAAE,mBAAmB,EAAE,IAAI,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAE7G,0CAA0C;IAC1C,EAAE,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAE5B,yBAAyB;IACzB,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IAE3C,yBAAyB;IACzB,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IAEzC,uBAAuB;IACvB,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAEnC,iBAAiB;IACjB,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAE/D,oEAAoE;IACpE,MAAM,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAEtD,8DAA8D;IAC9D,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;IAE5C,+DAA+D;IAC/D,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC;IAE9C,wBAAwB;IACxB,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,CAAC;IAEzC,0BAA0B;IAC1B,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAC;IAEjC,sCAAsC;IACtC,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAElG,0BAA0B;IAC1B,MAAM,CAAC,EAAE,EAAE,aAAa,GAAG,IAAI,CAAC;IAEhC,uBAAuB;IACvB,KAAK,IAAI,eAAe,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAClD,EAAE,EAAE,EAAE,EACN,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,aAAa,CAAC,EAAE,CAAC,CAoUnB"}
1
+ {"version":3,"file":"plugin-kit.d.ts","sourceRoot":"","sources":["../src/plugin-kit.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,aAAa,EAGb,eAAe,EACf,QAAQ,EACR,WAAW,EACX,WAAW,EACX,QAAQ,EACR,WAAW,EACX,UAAU,EACV,eAAe,EACf,WAAW,EACX,KAAK,EACL,UAAU,EACV,SAAS,EACT,aAAa,EAIb,eAAe,EACf,gBAAgB,EACjB,MAAM,SAAS,CAAC;AA8qBjB;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,EAAE,SAAS,MAAM;IAC9C,mDAAmD;IACnD,MAAM,CAAC,KAAK,EAAE,mBAAmB,EAAE,IAAI,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAE7G,0CAA0C;IAC1C,EAAE,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAE5B,yBAAyB;IACzB,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IAE3C,yBAAyB;IACzB,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IAEzC,uBAAuB;IACvB,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAEnC,iBAAiB;IACjB,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAE/D,oEAAoE;IACpE,MAAM,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAEtD,8DAA8D;IAC9D,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;IAE5C,+DAA+D;IAC/D,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC;IAE9C,wBAAwB;IACxB,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,CAAC;IAEzC,0BAA0B;IAC1B,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAC;IAEjC,sCAAsC;IACtC,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAElG,0BAA0B;IAC1B,MAAM,CAAC,EAAE,EAAE,aAAa,GAAG,IAAI,CAAC;IAEhC;;;;;;;;;;OAUG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B,uBAAuB;IACvB,KAAK,IAAI,eAAe,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAClD,EAAE,EAAE,EAAE,EACN,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,aAAa,CAAC,EAAE,CAAC,CAkVnB"}
@@ -286,7 +286,7 @@ function serveSpa(ui, req, res, ctx) {
286
286
  * Main plugin class built by the fluent API
287
287
  */
288
288
  class BuiltPlugin {
289
- constructor(id, name, version, capabilities, tools, apiRoutes, uiConfig, reactScreens, htmlScreens, wizard, onReadyFn, healthCheckFn) {
289
+ constructor(id, name, version, capabilities, tools, apiRoutes, uiConfig, reactScreens, htmlScreens, wizard, onReadyFn, healthCheckFn, userProvidedPluginRoot) {
290
290
  this.capabilities = capabilities;
291
291
  this.tools = tools;
292
292
  this.apiRoutes = apiRoutes;
@@ -296,6 +296,7 @@ class BuiltPlugin {
296
296
  this.wizard = wizard;
297
297
  this.onReadyFn = onReadyFn;
298
298
  this.healthCheckFn = healthCheckFn;
299
+ this.userProvidedPluginRoot = userProvidedPluginRoot;
299
300
  this.cleanups = [];
300
301
  this.router = [];
301
302
  this.id = id;
@@ -334,27 +335,40 @@ class BuiltPlugin {
334
335
  };
335
336
  }
336
337
  async onLoad(context) {
337
- this.context = context;
338
+ // Use user-provided pluginRoot (from __dirname) if available, otherwise fall back to context.pluginRoot
339
+ // The user-provided path comes from Node's __dirname which automatically resolves to the real directory
340
+ // (following symlinks), making it work correctly in both local development and npm installed scenarios
341
+ const effectivePluginRoot = this.userProvidedPluginRoot || context.pluginRoot;
342
+ this.context = {
343
+ ...context,
344
+ pluginRoot: effectivePluginRoot
345
+ };
338
346
  context.logger.info('═══════════════════════════════════════════════════════');
339
347
  context.logger.info(`🚀 Loading Plugin: ${this.name} (${this.id}) v${this.version}`);
340
- context.logger.info(`📍 Plugin Root: ${context.pluginRoot}`);
348
+ context.logger.info(`📍 Plugin Root: ${effectivePluginRoot}`);
349
+ if (this.userProvidedPluginRoot) {
350
+ context.logger.info(` (user-provided via .pluginRoot(__dirname))`);
351
+ }
352
+ else {
353
+ context.logger.info(` (from MAJK context - consider using .pluginRoot(__dirname) for better reliability)`);
354
+ }
341
355
  context.logger.info(`🌐 HTTP Port: ${context.http.port}`);
342
356
  context.logger.info(`🔗 Base URL: ${context.http.baseUrl}`);
343
357
  context.logger.info('═══════════════════════════════════════════════════════');
344
358
  // Validate file paths now that we have pluginRoot context
345
359
  if (this.reactScreens.length > 0 && this.uiConfig) {
346
- const indexPath = path_1.default.join(context.pluginRoot, this.uiConfig.appDir || '', 'index.html');
360
+ const indexPath = path_1.default.join(this.context.pluginRoot, this.uiConfig.appDir || '', 'index.html');
347
361
  if (!fs_1.default.existsSync(indexPath)) {
348
- throw new PluginRuntimeError(`React app not built: ${indexPath} does not exist. Run "npm run build" in your UI directory to build the React app.`, 'onLoad', { appDir: this.uiConfig.appDir, indexPath, pluginRoot: context.pluginRoot });
362
+ throw new PluginRuntimeError(`React app not built: ${indexPath} does not exist. Run "npm run build" in your UI directory to build the React app.`, 'onLoad', { appDir: this.uiConfig.appDir, indexPath, pluginRoot: this.context.pluginRoot });
349
363
  }
350
364
  context.logger.info(`✅ React UI found at: ${indexPath}`);
351
365
  }
352
366
  // Validate HTML screen files
353
367
  for (const screen of this.htmlScreens) {
354
368
  if ('htmlFile' in screen) {
355
- const filePath = path_1.default.join(context.pluginRoot, screen.htmlFile);
369
+ const filePath = path_1.default.join(this.context.pluginRoot, screen.htmlFile);
356
370
  if (!fs_1.default.existsSync(filePath)) {
357
- throw new PluginRuntimeError(`HTML screen file not found: ${screen.htmlFile}. Create the HTML file at ${filePath} or fix the path.`, 'onLoad', { screen: screen.id, file: screen.htmlFile, resolvedPath: filePath, pluginRoot: context.pluginRoot });
371
+ throw new PluginRuntimeError(`HTML screen file not found: ${screen.htmlFile}. Create the HTML file at ${filePath} or fix the path.`, 'onLoad', { screen: screen.id, file: screen.htmlFile, resolvedPath: filePath, pluginRoot: this.context.pluginRoot });
358
372
  }
359
373
  context.logger.info(`✅ HTML screen file found: ${screen.htmlFile}`);
360
374
  }
@@ -601,6 +615,7 @@ function definePlugin(id, name, version) {
601
615
  let _settings = null;
602
616
  let _onReady = null;
603
617
  let _healthCheck = null;
618
+ let _pluginRoot = undefined;
604
619
  const builder = {
605
620
  topbar(route, opts) {
606
621
  _topbars.push({
@@ -718,6 +733,13 @@ function definePlugin(id, name, version) {
718
733
  _healthCheck = fn;
719
734
  return this;
720
735
  },
736
+ pluginRoot(dir) {
737
+ if (!dir || typeof dir !== 'string') {
738
+ throw new PluginBuildError('pluginRoot must be a non-empty string', 'Pass __dirname from your plugin entry file: .pluginRoot(__dirname)', { provided: dir });
739
+ }
740
+ _pluginRoot = dir;
741
+ return this;
742
+ },
721
743
  build() {
722
744
  // ========== Build-Time Validation ==========
723
745
  // Validate React UI setup
@@ -811,7 +833,7 @@ function definePlugin(id, name, version) {
811
833
  // Return a class that instantiates BuiltPlugin
812
834
  return class extends BuiltPlugin {
813
835
  constructor() {
814
- super(id, name, version, _capabilities, _tools, _apiRoutes, _uiConfigured ? _ui : null, _reactScreens, _htmlScreens, _wizard, _onReady, _healthCheck);
836
+ super(id, name, version, _capabilities, _tools, _apiRoutes, _uiConfigured ? _ui : null, _reactScreens, _htmlScreens, _wizard, _onReady, _healthCheck, _pluginRoot);
815
837
  }
816
838
  };
817
839
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@majkapp/plugin-kit",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Fluent builder framework for creating robust MAJK plugins",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",