johankit-runtime 0.0.2 → 0.4.3

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.
Files changed (139) hide show
  1. package/README.md +93 -115
  2. package/dist/src/app.d.ts +7 -0
  3. package/dist/src/app.d.ts.map +1 -0
  4. package/dist/src/app.js +18 -0
  5. package/dist/src/app.js.map +1 -0
  6. package/dist/src/core/cache.d.ts +6 -0
  7. package/dist/src/core/cache.d.ts.map +1 -0
  8. package/dist/src/core/cache.js +18 -0
  9. package/dist/src/core/cache.js.map +1 -0
  10. package/dist/src/core/conditions/resolver.d.ts +2 -0
  11. package/dist/src/core/conditions/resolver.d.ts.map +1 -0
  12. package/dist/src/core/conditions/resolver.js +20 -0
  13. package/dist/src/core/conditions/resolver.js.map +1 -0
  14. package/dist/src/core/config-loader.d.ts +2 -0
  15. package/dist/src/core/config-loader.d.ts.map +1 -0
  16. package/dist/src/core/config-loader.js +18 -0
  17. package/dist/src/core/config-loader.js.map +1 -0
  18. package/dist/src/core/context.d.ts +2 -0
  19. package/dist/src/core/context.d.ts.map +1 -0
  20. package/dist/src/core/context.js +5 -0
  21. package/dist/src/core/context.js.map +1 -0
  22. package/dist/src/core/discovery.d.ts +4 -0
  23. package/dist/src/core/discovery.d.ts.map +1 -0
  24. package/dist/src/core/discovery.js +6 -0
  25. package/dist/src/core/discovery.js.map +1 -0
  26. package/dist/src/core/event/dispatch.d.ts +2 -0
  27. package/dist/src/core/event/dispatch.d.ts.map +1 -0
  28. package/dist/src/core/event/dispatch.js +30 -0
  29. package/dist/src/core/event/dispatch.js.map +1 -0
  30. package/dist/src/core/mcp/http-server.d.ts +11 -0
  31. package/dist/src/core/mcp/http-server.d.ts.map +1 -0
  32. package/dist/src/core/mcp/http-server.js +48 -0
  33. package/dist/src/core/mcp/http-server.js.map +1 -0
  34. package/dist/src/core/mcp/tools-mcp.d.ts +14 -0
  35. package/dist/src/core/mcp/tools-mcp.d.ts.map +1 -0
  36. package/dist/src/core/mcp/tools-mcp.js +55 -0
  37. package/dist/src/core/mcp/tools-mcp.js.map +1 -0
  38. package/dist/src/core/middleware/run.d.ts +3 -0
  39. package/dist/src/core/middleware/run.d.ts.map +1 -0
  40. package/dist/src/core/middleware/run.js +39 -0
  41. package/dist/src/core/middleware/run.js.map +1 -0
  42. package/dist/src/core/package.d.ts +8 -0
  43. package/dist/src/core/package.d.ts.map +1 -0
  44. package/dist/src/core/package.js +68 -0
  45. package/dist/src/core/package.js.map +1 -0
  46. package/dist/src/core/parse/cognites.d.ts +5 -0
  47. package/dist/src/core/parse/cognites.d.ts.map +1 -0
  48. package/{src → dist/src}/core/parse/cognites.js +7 -10
  49. package/dist/src/core/parse/cognites.js.map +1 -0
  50. package/dist/src/core/parse/hooks.d.ts +10 -0
  51. package/dist/src/core/parse/hooks.d.ts.map +1 -0
  52. package/dist/src/core/parse/hooks.js +31 -0
  53. package/dist/src/core/parse/hooks.js.map +1 -0
  54. package/dist/src/core/parse/middleware.d.ts +6 -0
  55. package/dist/src/core/parse/middleware.d.ts.map +1 -0
  56. package/{src → dist/src}/core/parse/middleware.js +9 -14
  57. package/dist/src/core/parse/middleware.js.map +1 -0
  58. package/dist/src/core/parse/predicates.d.ts +5 -0
  59. package/dist/src/core/parse/predicates.d.ts.map +1 -0
  60. package/{src → dist/src}/core/parse/predicates.js +9 -10
  61. package/dist/src/core/parse/predicates.js.map +1 -0
  62. package/dist/src/core/parse/routes.d.ts +6 -0
  63. package/dist/src/core/parse/routes.d.ts.map +1 -0
  64. package/{src → dist/src}/core/parse/routes.js +12 -17
  65. package/dist/src/core/parse/routes.js.map +1 -0
  66. package/dist/src/core/parse/tools.d.ts +12 -0
  67. package/dist/src/core/parse/tools.d.ts.map +1 -0
  68. package/dist/src/core/parse/tools.js +77 -0
  69. package/dist/src/core/parse/tools.js.map +1 -0
  70. package/dist/src/core/register/decorators.d.ts +7 -0
  71. package/dist/src/core/register/decorators.d.ts.map +1 -0
  72. package/dist/src/core/register/decorators.js +114 -0
  73. package/dist/src/core/register/decorators.js.map +1 -0
  74. package/dist/src/core/register/decorators.test.d.ts +2 -0
  75. package/dist/src/core/register/decorators.test.d.ts.map +1 -0
  76. package/dist/src/core/register/decorators.test.js +17 -0
  77. package/dist/src/core/register/decorators.test.js.map +1 -0
  78. package/dist/src/core/register.d.ts +2 -0
  79. package/dist/src/core/register.d.ts.map +1 -0
  80. package/dist/src/core/register.js +12 -0
  81. package/dist/src/core/register.js.map +1 -0
  82. package/dist/src/core/routes.d.ts +2 -0
  83. package/dist/src/core/routes.d.ts.map +1 -0
  84. package/dist/src/core/routes.js +65 -0
  85. package/dist/src/core/routes.js.map +1 -0
  86. package/dist/src/core/schema/export.d.ts +5 -0
  87. package/dist/src/core/schema/export.d.ts.map +1 -0
  88. package/dist/src/core/schema/export.js +15 -0
  89. package/dist/src/core/schema/export.js.map +1 -0
  90. package/dist/src/core/tools/capabilities.d.ts +2 -0
  91. package/dist/src/core/tools/capabilities.d.ts.map +1 -0
  92. package/dist/src/core/tools/capabilities.js +11 -0
  93. package/dist/src/core/tools/capabilities.js.map +1 -0
  94. package/dist/src/core/tools/lifecycle.d.ts +2 -0
  95. package/dist/src/core/tools/lifecycle.d.ts.map +1 -0
  96. package/dist/src/core/tools/lifecycle.js +6 -0
  97. package/dist/src/core/tools/lifecycle.js.map +1 -0
  98. package/dist/src/core/tools/middleware.d.ts +2 -0
  99. package/dist/src/core/tools/middleware.d.ts.map +1 -0
  100. package/dist/src/core/tools/middleware.js +7 -0
  101. package/dist/src/core/tools/middleware.js.map +1 -0
  102. package/dist/src/core/wiring.d.ts +2 -0
  103. package/dist/src/core/wiring.d.ts.map +1 -0
  104. package/dist/src/core/wiring.js +8 -0
  105. package/dist/src/core/wiring.js.map +1 -0
  106. package/dist/src/index.d.ts +5 -0
  107. package/dist/src/index.d.ts.map +1 -0
  108. package/dist/src/index.js +40 -0
  109. package/dist/src/index.js.map +1 -0
  110. package/dist/src/server.d.ts +2 -0
  111. package/dist/src/server.d.ts.map +1 -0
  112. package/dist/src/server.js +19 -0
  113. package/dist/src/server.js.map +1 -0
  114. package/dist/src/types.d.ts +87 -0
  115. package/dist/src/types.d.ts.map +1 -0
  116. package/dist/src/types.js +3 -0
  117. package/dist/src/types.js.map +1 -0
  118. package/dist/tests/cognites.test.js +21 -0
  119. package/dist/tests/dispatch.test.js +73 -0
  120. package/dist/tests/hooks.test.js +31 -0
  121. package/dist/tests/middleware.test.js +19 -0
  122. package/dist/tests/predicates.test.js +20 -0
  123. package/dist/tests/routes.test.js +26 -0
  124. package/dist/tests/tools.test.js +38 -0
  125. package/package.json +13 -12
  126. package/src/app.ts +0 -18
  127. package/src/core/event/dispatch.js +0 -31
  128. package/src/core/mcp/http-server.js +0 -52
  129. package/src/core/mcp/tools-mcp.js +0 -50
  130. package/src/core/package.js +0 -79
  131. package/src/core/parse/hooks.js +0 -37
  132. package/src/core/parse/tools.js +0 -82
  133. package/src/core/register/decorators.js +0 -150
  134. package/src/core/register/decorators.test.js +0 -13
  135. package/src/core/register.js +0 -37
  136. package/src/core/routes.js +0 -89
  137. package/src/index.ts +0 -42
  138. package/src/server.ts +0 -15
  139. package/src/types.ts +0 -104
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ (0, vitest_1.describe)('dispatchEvent', () => {
5
+ let dispatchEvent;
6
+ let packageModule;
7
+ let decoratorModule;
8
+ (0, vitest_1.beforeEach)(() => {
9
+ vitest_1.vi.resetModules();
10
+ vitest_1.vi.clearAllMocks();
11
+ packageModule = require('../src/core/package');
12
+ decoratorModule = require('../src/core/register/decorators');
13
+ vitest_1.vi.spyOn(packageModule, 'getPackages');
14
+ vitest_1.vi.spyOn(decoratorModule, 'registerHooks');
15
+ ({ dispatchEvent } = require('../src/core/event/dispatch'));
16
+ });
17
+ (0, vitest_1.it)('processa hooks de todos os packages e retorna o resultado final', async () => {
18
+ packageModule.getPackages.mockResolvedValue([
19
+ { folder: 'pkg1' },
20
+ { folder: 'pkg2' },
21
+ ]);
22
+ const hook1 = vitest_1.vi.fn(async (d) => ({ ...d, p1: true }));
23
+ const hook2 = vitest_1.vi.fn(async (d) => ({ ...d, p2: true }));
24
+ decoratorModule.registerHooks.mockImplementation(async (folder) => {
25
+ if (folder === 'pkg1')
26
+ return [{ event: 'test', call: hook1 }];
27
+ if (folder === 'pkg2')
28
+ return [{ event: 'test', call: hook2 }];
29
+ return [];
30
+ });
31
+ const result = await dispatchEvent('test', { base: true });
32
+ (0, vitest_1.expect)(result).toEqual({
33
+ base: true,
34
+ p1: true,
35
+ p2: true,
36
+ });
37
+ });
38
+ (0, vitest_1.it)('continua execução se um package falhar ao registrar hooks', async () => {
39
+ packageModule.getPackages.mockResolvedValue([
40
+ { folder: 'fail' },
41
+ { folder: 'ok' },
42
+ ]);
43
+ decoratorModule.registerHooks.mockImplementation(async (folder) => {
44
+ if (folder === 'fail')
45
+ throw new Error('Load error');
46
+ return [
47
+ {
48
+ event: 'test',
49
+ call: async (d) => ({ ...d, ok: true }),
50
+ },
51
+ ];
52
+ });
53
+ const result = await dispatchEvent('test', {});
54
+ (0, vitest_1.expect)(result).toEqual({ ok: true });
55
+ });
56
+ (0, vitest_1.it)('ignora hooks de outros eventos', async () => {
57
+ packageModule.getPackages.mockResolvedValue([{ folder: 'pkg' }]);
58
+ decoratorModule.registerHooks.mockResolvedValue([
59
+ { event: 'other', call: vitest_1.vi.fn() },
60
+ { event: 'test', call: async (d) => ({ ...d, hit: true }) },
61
+ ]);
62
+ const result = await dispatchEvent('test', {});
63
+ (0, vitest_1.expect)(result).toEqual({ hit: true });
64
+ });
65
+ (0, vitest_1.it)('ignora retorno null ou undefined do hook', async () => {
66
+ packageModule.getPackages.mockResolvedValue([{ folder: 'pkg' }]);
67
+ decoratorModule.registerHooks.mockResolvedValue([
68
+ { event: 'test', call: async () => null },
69
+ ]);
70
+ const result = await dispatchEvent('test', { base: true });
71
+ (0, vitest_1.expect)(result).toEqual({ base: true });
72
+ });
73
+ });
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const { parseHook } = require('../src/core/parse/hooks');
5
+ (0, vitest_1.describe)('parseHook', () => {
6
+ (0, vitest_1.it)('should return null if input is not a function', () => {
7
+ (0, vitest_1.expect)(parseHook('not a function')).toBeNull();
8
+ });
9
+ (0, vitest_1.it)('should parse a valid hook with conditions', () => {
10
+ const testHook = () => {
11
+ /**
12
+ * @register_hook user_login
13
+ * @only web
14
+ * @never mobile
15
+ * @when authenticated
16
+ */
17
+ return true;
18
+ };
19
+ const result = parseHook(testHook);
20
+ (0, vitest_1.expect)(result.event).toBe('user_login');
21
+ (0, vitest_1.expect)(result.condition.only).toContain('web');
22
+ (0, vitest_1.expect)(result.condition.never).toContain('mobile');
23
+ (0, vitest_1.expect)(result.condition.when).toContain('authenticated');
24
+ });
25
+ (0, vitest_1.it)('should return null if no register_hook decorator is found', () => {
26
+ const noHook = () => {
27
+ /** @description just a comment */
28
+ };
29
+ (0, vitest_1.expect)(parseHook(noHook)).toBeNull();
30
+ });
31
+ });
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const { parseMiddleware } = require('../src/core/parse/middleware');
5
+ (0, vitest_1.describe)('parseMiddleware', () => {
6
+ (0, vitest_1.it)('should parse middleware inside function body', () => {
7
+ const myMiddleware = () => {
8
+ /**
9
+ * @register_middleware checkLog
10
+ * @predicate is_admin
11
+ * @predicate is_owner
12
+ */
13
+ };
14
+ const result = parseMiddleware(myMiddleware);
15
+ (0, vitest_1.expect)(result.name).toBe('checkLog');
16
+ (0, vitest_1.expect)(result.predicates).toContain('is_admin');
17
+ (0, vitest_1.expect)(result.predicates).toContain('is_owner');
18
+ });
19
+ });
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const { parsePredicate } = require('../src/core/parse/predicates');
5
+ (0, vitest_1.describe)('parsePredicate', () => {
6
+ (0, vitest_1.it)('should parse predicate with custom name', () => {
7
+ const isAuth = () => {
8
+ /** @register_predicate auth_check */
9
+ };
10
+ const result = parsePredicate(isAuth);
11
+ (0, vitest_1.expect)(result.name).toBe('auth_check');
12
+ });
13
+ (0, vitest_1.it)('should use function name if decorator name is missing', () => {
14
+ function isAdmin() {
15
+ /** @register_predicate */
16
+ }
17
+ const result = parsePredicate(isAdmin);
18
+ (0, vitest_1.expect)(result.name).toBe('isAdmin');
19
+ });
20
+ });
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const { parseRouter } = require('../src/core/parse/routes');
5
+ (0, vitest_1.describe)('parseRouter', () => {
6
+ (0, vitest_1.it)('should parse valid route decorators', () => {
7
+ const handler = () => {
8
+ /**
9
+ * @register_router /test
10
+ * @method POST
11
+ */
12
+ };
13
+ const result = parseRouter(handler);
14
+ (0, vitest_1.expect)(result.path).toBe('/test');
15
+ (0, vitest_1.expect)(result.method).toBe('post');
16
+ });
17
+ (0, vitest_1.it)('should default method to get', () => {
18
+ const handler = () => {
19
+ /**
20
+ * @register_router /simple
21
+ */
22
+ };
23
+ const result = parseRouter(handler);
24
+ (0, vitest_1.expect)(result.method).toBe('get');
25
+ });
26
+ });
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const { parseTool } = require('../src/core/parse/tools');
5
+ (0, vitest_1.describe)('parseTool', () => {
6
+ (0, vitest_1.it)('should parse tool parameters and descriptions', () => {
7
+ function calculate(args) {
8
+ /**
9
+ * @register_tool calc
10
+ * @description useful tool
11
+ * @param {number} x - first number
12
+ * @param {number?} y - second optional number
13
+ */
14
+ }
15
+ const result = parseTool(calculate);
16
+ (0, vitest_1.expect)(result.name).toBe('calc');
17
+ (0, vitest_1.expect)(result.description).toBe('useful tool');
18
+ (0, vitest_1.expect)(result.parameters).toHaveLength(2);
19
+ (0, vitest_1.expect)(result.parameters[0].name).toBe('x');
20
+ (0, vitest_1.expect)(result.parameters[0].required).toBe(true);
21
+ (0, vitest_1.expect)(result.parameters[1].name).toBe('y');
22
+ (0, vitest_1.expect)(result.parameters[1].required).toBe(false);
23
+ });
24
+ (0, vitest_1.it)('should parse complex nested object parameters', () => {
25
+ const tool = () => {
26
+ /**
27
+ * @register_tool complex
28
+ * @param {string} user.name - name
29
+ * @param {number} user.age - age
30
+ */
31
+ };
32
+ const result = parseTool(tool);
33
+ const userParam = result.parameters.find(p => p.name === 'user');
34
+ (0, vitest_1.expect)(userParam).toBeDefined();
35
+ (0, vitest_1.expect)(userParam.type).toBe('object');
36
+ (0, vitest_1.expect)(result.parameters).toHaveLength(3);
37
+ });
38
+ });
package/package.json CHANGED
@@ -1,29 +1,30 @@
1
1
  {
2
2
  "name": "johankit-runtime",
3
- "version": "0.0.2",
3
+ "version": "0.4.3",
4
4
  "description": "A pluggable runtime for any back-end",
5
- "main": "src/index.js",
5
+ "main": "dist/src/index.js",
6
+ "types": "dist/src/index.d.ts",
6
7
  "scripts": {
7
8
  "build": "tsc",
9
+ "prepublishOnly": "npm run build",
8
10
  "test": "vitest run",
9
11
  "test:coverage": "vitest run --coverage"
10
12
  },
11
13
  "files": [
12
- "src",
14
+ "dist",
13
15
  "README.md"
14
16
  ],
15
17
  "dependencies": {
16
- "express": "^5.2.1",
17
- "js-yaml": "^4.1.0"
18
+ "@sveltejs/kit": "^2.49.4",
19
+ "express": "^4.22.1",
20
+ "js-yaml": "^4.1.0",
21
+ "mdsvex": "^0.12.6"
18
22
  },
19
23
  "devDependencies": {
20
- "vitest": "latest",
24
+ "@types/express": "^4.17.21",
25
+ "@types/node": "^20.0.0",
21
26
  "@vitest/coverage-v8": "latest",
22
27
  "typescript": "^5.4.0",
23
- "@types/node": "^20.0.0",
24
- "@types/express": "^4.17.21"
25
- },
26
- "peerDependencies": {
27
- "express": "^4.x"
28
+ "vitest": "latest"
28
29
  }
29
- }
30
+ }
package/src/app.ts DELETED
@@ -1,18 +0,0 @@
1
- import express, { Application } from 'express'
2
- import { registerPackages } from './core/register'
3
-
4
- type JohankitApp = Application & {
5
- setup: () => Promise<void>
6
- }
7
-
8
- const app = express() as Application
9
-
10
- ;(app as JohankitApp).setup = async () => {
11
- try {
12
- await registerPackages(app)
13
- } catch (error: any) {
14
- console.log(`Error registering packages: ${error.message}`, 'error')
15
- }
16
- }
17
-
18
- export default app as JohankitApp
@@ -1,31 +0,0 @@
1
- const { registerHooks } = require('../register/decorators');
2
- const { getPackages } = require('../package');
3
-
4
- async function dispatchEvent(eventName, payload) {
5
- const packages = await getPackages();
6
- let finalResult = payload;
7
-
8
- for (const pkg of packages) {
9
- try {
10
- const hooks = await registerHooks(pkg.folder);
11
- const relevant = hooks.filter(h => h.event === eventName);
12
-
13
- for (const hook of relevant) {
14
- try {
15
- const result = await hook.call(finalResult);
16
- if (result !== undefined && result !== null) {
17
- finalResult = result;
18
- }
19
- } catch (err) {
20
- console.warn(`[Hook Error] Package ${pkg.folder} failed on event ${eventName}:`, err.message);
21
- }
22
- }
23
- } catch (err) {
24
- continue;
25
- }
26
- }
27
-
28
- return finalResult;
29
- }
30
-
31
- module.exports = { dispatchEvent };
@@ -1,52 +0,0 @@
1
- const express = require('express');
2
- const bodyParser = require('body-parser');
3
- const { bootstrapMcp } = require('./tools-mcp');
4
-
5
- async function createMcpHttpServer(options = {}) {
6
- const app = express();
7
- const port = options.port || 3333;
8
- const workspace = options.workspace || process.env.PACKAGES_PATH;
9
-
10
- if (!workspace) {
11
- throw new Error('PACKAGES_PATH or workspace option is required');
12
- }
13
-
14
- const mcp = await bootstrapMcp(workspace);
15
-
16
- app.use(bodyParser.json());
17
-
18
- app.get('/mcp', (req, res) => {
19
- res.json({ protocol: mcp.protocol, version: mcp.version });
20
- });
21
-
22
- app.get('/mcp/tools', (req, res) => {
23
- try {
24
- res.json(mcp.listTools());
25
- } catch (err) {
26
- res.status(500).json({ error: err.message });
27
- }
28
- });
29
-
30
- app.post('/mcp/call', async (req, res) => {
31
- const { name, args } = req.body || {};
32
-
33
- if (!name) {
34
- return res.status(400).json({ error: 'Tool name is required' });
35
- }
36
-
37
- try {
38
- const result = await mcp.callTool(name, args || {});
39
- res.json({ result });
40
- } catch (err) {
41
- res.status(500).json({ error: err.message });
42
- }
43
- });
44
-
45
- const server = app.listen(port, () => {
46
- console.log(`MCP HTTP server running on port ${port}`);
47
- });
48
-
49
- return { app, server, mcp };
50
- }
51
-
52
- module.exports = { createMcpHttpServer };
@@ -1,50 +0,0 @@
1
- const { registerTools } = require('../register/decorators');
2
-
3
- function toolToMcp(tool) {
4
- return {
5
- name: tool.name,
6
- description: tool.description || '',
7
- inputSchema: tool.parameters || { type: 'object', properties: {} },
8
- handler: async (args) => {
9
- return await tool.call(args);
10
- },
11
- condition: tool.condition || null
12
- };
13
- }
14
-
15
- async function loadMcpTools(agentFolder) {
16
- const tools = await registerTools(agentFolder);
17
- return tools.map(toolToMcp);
18
- }
19
-
20
- function createMcpServer(tools) {
21
- return {
22
- protocol: 'mcp',
23
- version: '1.0.0',
24
- listTools() {
25
- return tools.map(t => ({
26
- name: t.name,
27
- description: t.description,
28
- inputSchema: t.inputSchema
29
- }));
30
- },
31
- async callTool(name, args) {
32
- const tool = tools.find(t => t.name === name);
33
- if (!tool) {
34
- throw new Error(`Tool not found: ${name}`);
35
- }
36
- return await tool.handler(args);
37
- }
38
- };
39
- }
40
-
41
- async function bootstrapMcp(agentFolder) {
42
- const tools = await loadMcpTools(agentFolder);
43
- return createMcpServer(tools);
44
- }
45
-
46
- module.exports = {
47
- loadMcpTools,
48
- createMcpServer,
49
- bootstrapMcp
50
- };
@@ -1,79 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- const { log } = console;
5
-
6
- async function getPackage(folderName) {
7
- try {
8
- const pluginsPath = process.env.PACKAGES_PATH || path.join(__dirname, '..', 'packages');
9
- const manifestPath = path.join(pluginsPath, folderName, 'package.json');
10
-
11
- let manifest = {};
12
-
13
- try {
14
- if (fs.existsSync(manifestPath)) {
15
- manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
16
- }
17
- } catch (error) {
18
- console.error(`Manifest not found in ${folderName}:`, error);
19
- throw new Error(`Manifest not found in folder ${folderName}`);
20
- }
21
-
22
- return {
23
- ...manifest,
24
- folder: folderName,
25
- };
26
- } catch (error) {
27
- throw error;
28
- }
29
- }
30
-
31
- async function getPackages() {
32
- try {
33
- const pluginsPath = process.env.PACKAGES_PATH || path.join(__dirname, '..', 'packages');
34
- const pluginFolders = fs.readdirSync(pluginsPath).filter(f => fs.statSync(path.join(pluginsPath, f)).isDirectory());
35
-
36
- const folderPackages = await Promise.all(pluginFolders.map(async folderName => {
37
- return await getPackage(folderName);
38
- }));
39
-
40
- return folderPackages;
41
- } catch (error) {
42
- throw error;
43
- }
44
- }
45
-
46
- const registerPackage = async (app, pkg) => {
47
- const basePackagesPath = process.env.PACKAGES_PATH || path.join(__dirname, '..', 'packages');
48
- const packageDir = path.join(basePackagesPath, pkg.folder);
49
- const manifestPath = path.join(packageDir, 'package.json');
50
- pkg.dir = packageDir;
51
-
52
- try {
53
- if (!fs.existsSync(manifestPath)) {
54
- return;
55
- }
56
-
57
- if (!fs.existsSync(path.join(packageDir, 'routes.js'))) {
58
- return;
59
- }
60
-
61
- const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
62
- const usePackage = manifest.entry ? require(path.join(packageDir, manifest.entry)) : () => { };
63
-
64
- if (typeof usePackage !== 'function') {
65
- log(`${pkg.name} invalid entry point. Expected a function.`, 'error');
66
- return;
67
- }
68
-
69
- const packg = usePackage(app) ?? usePackage;
70
- packg?.setup && packg.setup();
71
-
72
- log(`${pkg.name} ${pkg.version ? `version ${pkg.version}` : ''} is running.\n`);
73
- } catch (error) {
74
- log(`Error with package ${pkg.name}: ${error.message}`, 'error');
75
- log(`${pkg.name} ${pkg.version ? `version ${pkg.version}` : ''} isn't running.\n`);
76
- }
77
- };
78
-
79
- module.exports = { getPackage, getPackages, registerPackage };
@@ -1,37 +0,0 @@
1
- function parseHook(fn) {
2
- if (typeof fn !== 'function') return null;
3
-
4
- const fnStr = fn.toString();
5
- const docMatch = fnStr.match(/\/\*\*([\s\S]*?)\*\//);
6
- if (!docMatch) return null;
7
-
8
- const doc = docMatch[1];
9
-
10
- const hookMatch = doc.match(/@register_hook\s+([^\s]+)/);
11
- if (!hookMatch) return null;
12
-
13
- const event = hookMatch[1].trim();
14
-
15
- const condition = { only: [], never: [], when: [] };
16
-
17
- const onlyMatches = [...doc.matchAll(/@only\s+([^\s]+)/g)];
18
- onlyMatches.forEach(m => condition.only.push(m[1]));
19
-
20
- const neverMatches = [...doc.matchAll(/@never\s+([^\s]+)/g)];
21
- neverMatches.forEach(m => condition.never.push(m[1]));
22
-
23
- const whenMatches = [...doc.matchAll(/@when\s+([^\s]+)/g)];
24
- whenMatches.forEach(m => condition.when.push(m[1]));
25
-
26
- Object.keys(condition).forEach(k => {
27
- if (condition[k].length === 0) delete condition[k];
28
- });
29
-
30
- return {
31
- event,
32
- call: fn,
33
- condition
34
- };
35
- }
36
-
37
- module.exports = { parseHook };
@@ -1,82 +0,0 @@
1
- function parseTool(fn) {
2
- const meta = {
3
- name: fn.name || null,
4
- description: null,
5
- parameters: [],
6
- call: fn,
7
- condition: { only: [], never: [], when: [] }
8
- };
9
-
10
- const fnString = fn.toString();
11
- const jsdocMatch = fnString.match(/\/\*\*([\s\S]*?)\*\//);
12
- if (!jsdocMatch) return null;
13
-
14
- const lines = jsdocMatch[1].split('\n').map(l => l.trim().replace(/^\*\s?/, ''));
15
-
16
- const registerLine = lines.find(l => l.startsWith('@register_tool'));
17
- if (!registerLine) return null;
18
-
19
- const registerMatch = registerLine.match(/@register_tool\s*(\S+)?/);
20
- if (registerMatch && registerMatch[1]) {
21
- meta.name = registerMatch[1];
22
- } else if (!meta.name) {
23
- meta.name = 'anonymousTool';
24
- }
25
-
26
- const paramMap = {};
27
-
28
- const descriptionLine = lines.find(l => l.startsWith('@description'));
29
- if (descriptionLine) meta.description = descriptionLine.replace('@description', '').trim();
30
-
31
- lines.forEach(line => {
32
- if (line.startsWith('@param')) {
33
- const match = line.match(/@param {([\w\[\]\?]+)} (\S+) - (.+)/);
34
- if (!match) return;
35
-
36
- let [_, type, name, description] = match;
37
- let required = !type.endsWith('?');
38
- if (!required) type = type.slice(0, -1);
39
-
40
- const cleanName = name.replace(/\[\]/g, '');
41
- const isArray = name.includes('[]');
42
- const isNested = cleanName.includes('.');
43
-
44
- if (isNested) {
45
- const parentName = cleanName.split('.')[0];
46
- if (!paramMap[parentName]) {
47
- const parent = {
48
- name: parentName,
49
- type: isArray ? 'array' : 'object',
50
- description: `${parentName} object`,
51
- required
52
- };
53
- meta.parameters.push(parent);
54
- paramMap[parentName] = parent;
55
- } else if (required) {
56
- paramMap[parentName].required = true;
57
- }
58
- }
59
-
60
- const param = { name, type, description, required };
61
- meta.parameters.push(param);
62
- paramMap[name] = param;
63
- }
64
-
65
- const onlyMatch = line.match(/@only\s+([^\s]+)/);
66
- if (onlyMatch) meta.condition.only.push(onlyMatch[1]);
67
-
68
- const neverMatch = line.match(/@never\s+([^\s]+)/);
69
- if (neverMatch) meta.condition.never.push(neverMatch[1]);
70
-
71
- const whenMatch = line.match(/@when\s+([^\s]+)/);
72
- if (whenMatch) meta.condition.when.push(whenMatch[1]);
73
- });
74
-
75
- Object.keys(meta.condition).forEach(k => {
76
- if (meta.condition[k].length === 0) delete meta.condition[k];
77
- });
78
-
79
- return meta;
80
- }
81
-
82
- module.exports = { parseTool };