@flink-app/management-actions-plugin 0.12.1-alpha.7 → 0.13.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.
@@ -0,0 +1,8 @@
1
+ // Generated Fri Jan 09 2026 11:18:15 GMT+0100 (Central European Standard Time)
2
+ import { autoRegisteredHandlers, HttpMethod } from "@flink-app/flink";
3
+ import * as Get_0 from "../src/handlers/Get";
4
+ import * as PostById_0 from "../src/handlers/PostById";
5
+
6
+ export const handlers = [];
7
+ autoRegisteredHandlers.push(...handlers);
8
+
@@ -0,0 +1,5 @@
1
+ // Generated Fri Jan 09 2026 11:18:15 GMT+0100 (Central European Standard Time)
2
+ import { autoRegisteredJobs } from "@flink-app/flink";
3
+ export const jobs = [];
4
+ autoRegisteredJobs.push(...jobs);
5
+
@@ -0,0 +1,5 @@
1
+ // Generated Fri Jan 09 2026 11:18:15 GMT+0100 (Central European Standard Time)
2
+ import { autoRegisteredRepos } from "@flink-app/flink";
3
+ export const repos = [];
4
+ autoRegisteredRepos.push(...repos);
5
+
@@ -0,0 +1,5 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$ref": "#/definitions/Schemas",
4
+ "definitions": {}
5
+ }
@@ -0,0 +1 @@
1
+ // Generated Fri Jan 09 2026 11:18:15 GMT+0100 (Central European Standard Time)
@@ -0,0 +1,6 @@
1
+ // Generated Fri Jan 09 2026 11:18:15 GMT+0100 (Central European Standard Time)
2
+ import "./generatedHandlers";
3
+ import "./generatedRepos";
4
+ import "./generatedJobs";
5
+ import "../src/index";
6
+ export default {}; // Export an empty object to make it a module
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # @flink-app/management-actions-plugin
2
+
3
+ ## 0.13.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Migrate to pnpm and streamlines build process.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+ - @flink-app/management-api-plugin@0.13.0
13
+ - @flink-app/flink@0.13.0
@@ -0,0 +1 @@
1
+ export declare const handlers: never[];
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handlers = void 0;
4
+ // Generated Fri Jan 09 2026 11:18:15 GMT+0100 (Central European Standard Time)
5
+ var flink_1 = require("@flink-app/flink");
6
+ exports.handlers = [];
7
+ flink_1.autoRegisteredHandlers.push.apply(flink_1.autoRegisteredHandlers, exports.handlers);
@@ -0,0 +1 @@
1
+ export declare const jobs: never[];
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.jobs = void 0;
4
+ // Generated Fri Jan 09 2026 11:18:15 GMT+0100 (Central European Standard Time)
5
+ var flink_1 = require("@flink-app/flink");
6
+ exports.jobs = [];
7
+ flink_1.autoRegisteredJobs.push.apply(flink_1.autoRegisteredJobs, exports.jobs);
@@ -0,0 +1 @@
1
+ export declare const repos: never[];
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.repos = void 0;
4
+ // Generated Fri Jan 09 2026 11:18:15 GMT+0100 (Central European Standard Time)
5
+ var flink_1 = require("@flink-app/flink");
6
+ exports.repos = [];
7
+ flink_1.autoRegisteredRepos.push.apply(flink_1.autoRegisteredRepos, exports.repos);
File without changes
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ // Generated Fri Jan 09 2026 11:18:15 GMT+0100 (Central European Standard Time)
@@ -0,0 +1,5 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$ref": "#/definitions/Schemas",
4
+ "definitions": {}
5
+ }
@@ -0,0 +1,6 @@
1
+ import "./generatedHandlers";
2
+ import "./generatedRepos";
3
+ import "./generatedJobs";
4
+ import "../src/index";
5
+ declare const _default: {};
6
+ export default _default;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // Generated Fri Jan 09 2026 11:18:15 GMT+0100 (Central European Standard Time)
4
+ require("./generatedHandlers");
5
+ require("./generatedRepos");
6
+ require("./generatedJobs");
7
+ require("../src/index");
8
+ exports.default = {}; // Export an empty object to make it a module
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
14
  function verb(n) { return function (v) { return step([n, v]); }; }
15
15
  function step(op) {
16
16
  if (f) throw new TypeError("Generator is already executing.");
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
14
  function verb(n) { return function (v) { return step([n, v]); }; }
15
15
  function step(op) {
16
16
  if (f) throw new TypeError("Generator is already executing.");
@@ -0,0 +1,5 @@
1
+ import { FlinkContext, Handler } from "@flink-app/flink";
2
+ import { ActionView } from "../schemas/Action";
3
+ declare const getHandler: Handler<FlinkContext, any, ActionView[]>;
4
+ export default getHandler;
5
+ export declare const __assumedHttpMethod = "get", __file = "Get.ts", __query: never[], __params: never[];
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.__params = exports.__query = exports.__file = exports.__assumedHttpMethod = void 0;
40
+ var getHandler = function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
41
+ var modules, module, actions, data;
42
+ var _c, _d;
43
+ var ctx = _b.ctx, req = _b.req, origin = _b.origin;
44
+ return __generator(this, function (_e) {
45
+ modules = ctx.plugins.managementApi.moduleList.modules;
46
+ module = modules.find(function (p) { return p.id == origin; });
47
+ if (((_c = module.data) === null || _c === void 0 ? void 0 : _c.actions) == null) {
48
+ return [2 /*return*/, {
49
+ data: [],
50
+ status: 200,
51
+ }];
52
+ }
53
+ actions = (_d = module.data) === null || _d === void 0 ? void 0 : _d.actions;
54
+ data = actions.map(function (a) {
55
+ var av = {
56
+ id: a.id,
57
+ description: a.description,
58
+ arguments: a.arguments,
59
+ };
60
+ return av;
61
+ });
62
+ return [2 /*return*/, {
63
+ data: data,
64
+ status: 200,
65
+ }];
66
+ });
67
+ }); };
68
+ exports.default = getHandler;
69
+ exports.__assumedHttpMethod = "get", exports.__file = "Get.ts", exports.__query = [], exports.__params = [];
@@ -0,0 +1,5 @@
1
+ import { FlinkContext, Handler } from "@flink-app/flink";
2
+ import { ActionArgumentsValues, ActionResponse } from "../schemas/Action";
3
+ declare const postHandler: Handler<FlinkContext, ActionArgumentsValues, ActionResponse>;
4
+ export default postHandler;
5
+ export declare const __assumedHttpMethod = "post", __file = "PostById.ts", __query: never[], __params: never[];
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.__params = exports.__query = exports.__file = exports.__assumedHttpMethod = void 0;
40
+ var flink_1 = require("@flink-app/flink");
41
+ var Action_1 = require("../schemas/Action");
42
+ var postHandler = function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
43
+ var modules, module, actions, action, i, arg, resp, ex_1;
44
+ var _c;
45
+ var ctx = _b.ctx, req = _b.req, origin = _b.origin;
46
+ return __generator(this, function (_d) {
47
+ switch (_d.label) {
48
+ case 0:
49
+ modules = ctx.plugins.managementApi.moduleList.modules;
50
+ module = modules.find(function (p) { return p.id == origin; });
51
+ if (((_c = module.data) === null || _c === void 0 ? void 0 : _c.actions) == null) {
52
+ return [2 /*return*/, (0, flink_1.notFound)("Action not found")];
53
+ }
54
+ actions = module.data.actions;
55
+ action = actions.find(function (a) { return a.id == req.params.actionId; });
56
+ if (action == null) {
57
+ return [2 /*return*/, (0, flink_1.notFound)("Action not found")];
58
+ }
59
+ for (i in action.arguments) {
60
+ arg = action.arguments[i];
61
+ if (arg.required) {
62
+ if (req.body[arg.id] == null) {
63
+ return [2 /*return*/, (0, flink_1.badRequest)("".concat(arg.id, " is missing "))];
64
+ }
65
+ }
66
+ }
67
+ _d.label = 1;
68
+ case 1:
69
+ _d.trys.push([1, 3, , 4]);
70
+ return [4 /*yield*/, action.handler(ctx, req.body)];
71
+ case 2:
72
+ resp = _d.sent();
73
+ if (resp.status == Action_1.ActionReturnStatus.success) {
74
+ return [2 /*return*/, {
75
+ data: resp,
76
+ status: 200,
77
+ }];
78
+ }
79
+ else {
80
+ return [2 /*return*/, (0, flink_1.internalServerError)(resp.error)];
81
+ }
82
+ return [3 /*break*/, 4];
83
+ case 3:
84
+ ex_1 = _d.sent();
85
+ console.log("EXCEPTIOIN managementActionsPlugin:");
86
+ console.log(ex_1);
87
+ return [2 /*return*/, (0, flink_1.internalServerError)()];
88
+ case 4: return [2 /*return*/];
89
+ }
90
+ });
91
+ }); };
92
+ exports.default = postHandler;
93
+ exports.__assumedHttpMethod = "post", exports.__file = "PostById.ts", exports.__query = [], exports.__params = [];
@@ -0,0 +1,11 @@
1
+ import { ManagementApiModule } from "@flink-app/management-api-plugin";
2
+ import { Action } from "./schemas/Action";
3
+ export interface GetManagementModuleConfig {
4
+ pluginId?: string;
5
+ ui: boolean;
6
+ uiSettings?: {
7
+ title: string;
8
+ };
9
+ actions: Action[];
10
+ }
11
+ export declare const GetManagementModule: (config: GetManagementModuleConfig) => ManagementApiModule;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.GetManagementModule = void 0;
27
+ var management_api_plugin_1 = require("@flink-app/management-api-plugin");
28
+ var flink_1 = require("@flink-app/flink");
29
+ var postHandler = __importStar(require("./handlers/PostById"));
30
+ var getHandler = __importStar(require("./handlers/Get"));
31
+ var GetManagementModule = function (config) {
32
+ var _a;
33
+ if (config.pluginId == null)
34
+ config.pluginId = "managementActionsApi";
35
+ var endpoints = [];
36
+ endpoints.push({
37
+ routeProps: {
38
+ path: "/:actionId",
39
+ method: flink_1.HttpMethod.post,
40
+ origin: config.pluginId,
41
+ },
42
+ handler: postHandler,
43
+ });
44
+ endpoints.push({
45
+ routeProps: {
46
+ path: "",
47
+ method: flink_1.HttpMethod.get,
48
+ origin: config.pluginId,
49
+ },
50
+ handler: getHandler,
51
+ });
52
+ var features = [];
53
+ var module = {
54
+ id: config.pluginId || "action",
55
+ uiSettings: {
56
+ title: ((_a = config.uiSettings) === null || _a === void 0 ? void 0 : _a.title) || "Actions",
57
+ icon: "",
58
+ features: features,
59
+ },
60
+ ui: config.ui,
61
+ type: management_api_plugin_1.ManagementApiType.action,
62
+ endpoints: endpoints,
63
+ data: {
64
+ actions: config.actions,
65
+ },
66
+ };
67
+ return module;
68
+ };
69
+ exports.GetManagementModule = GetManagementModule;
@@ -0,0 +1,35 @@
1
+ import { FlinkContext } from "@flink-app/flink";
2
+ export interface Action {
3
+ id: string;
4
+ description?: string;
5
+ arguments: ActionArguments[];
6
+ handler(ctx: FlinkContext<any>, args: ActionArgumentsValues): Promise<ActionResponse>;
7
+ }
8
+ export interface ActionArgumentsValues {
9
+ [key: string]: any;
10
+ }
11
+ export interface ActionResponse {
12
+ status: ActionReturnStatus;
13
+ error?: string;
14
+ data?: {
15
+ [key: string]: any;
16
+ };
17
+ }
18
+ export declare enum ActionReturnStatus {
19
+ success = "SUCCESS",
20
+ error = "ERROR"
21
+ }
22
+ export interface ActionArguments {
23
+ id: string;
24
+ required: boolean;
25
+ type: ActionArugmentType;
26
+ default?: string;
27
+ }
28
+ export declare enum ActionArugmentType {
29
+ text = "TEXT"
30
+ }
31
+ export interface ActionView {
32
+ id: string;
33
+ description?: string;
34
+ arguments: ActionArguments[];
35
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ActionArugmentType = exports.ActionReturnStatus = void 0;
4
+ var ActionReturnStatus;
5
+ (function (ActionReturnStatus) {
6
+ ActionReturnStatus["success"] = "SUCCESS";
7
+ ActionReturnStatus["error"] = "ERROR";
8
+ })(ActionReturnStatus || (exports.ActionReturnStatus = ActionReturnStatus = {}));
9
+ var ActionArugmentType;
10
+ (function (ActionArugmentType) {
11
+ ActionArugmentType["text"] = "TEXT";
12
+ })(ActionArugmentType || (exports.ActionArugmentType = ActionArugmentType = {}));
package/package.json CHANGED
@@ -1,30 +1,27 @@
1
1
  {
2
- "name": "@flink-app/management-actions-plugin",
3
- "version": "0.12.1-alpha.7",
4
- "description": "Flink plugin that makes it possible create actions that can be run trought the management-api",
5
- "scripts": {
6
- "test": "echo \"Error: no test specified\"",
7
- "build": "flink build",
8
- "prepublish": "tsc"
9
- },
10
- "author": "johan@frost.se",
11
- "publishConfig": {
12
- "access": "public"
13
- },
14
- "license": "MIT",
15
- "types": "dist/src/index.d.ts",
16
- "main": "dist/src/index.js",
17
- "dependencies": {
18
- "@flink-app/management-api-plugin": "^0.12.1-alpha.7",
19
- "express": "^4.17.1",
20
- "node-color-log": "^5.3.1"
21
- },
22
- "devDependencies": {
23
- "@flink-app/flink": "^0.12.1-alpha.7",
24
- "@types/express": "4.17.11",
25
- "@types/node": "22.13.10",
26
- "ts-node": "^9.1.1",
27
- "typescript": "5.4.5"
28
- },
29
- "gitHead": "cd86dec5f9b3bf23c01374a729bb02d8a48c2869"
30
- }
2
+ "name": "@flink-app/management-actions-plugin",
3
+ "version": "0.13.0",
4
+ "description": "Flink plugin that makes it possible create actions that can be run trought the management-api",
5
+ "author": "johan@frost.se",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "license": "MIT",
10
+ "types": "dist/src/index.d.ts",
11
+ "main": "dist/src/index.js",
12
+ "dependencies": {
13
+ "node-color-log": "^5.3.1",
14
+ "@flink-app/flink": "0.13.0",
15
+ "@flink-app/management-api-plugin": "0.13.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/node": "22.13.10",
19
+ "ts-node": "^10.9.2"
20
+ },
21
+ "gitHead": "4243e3b3cd6d4e1ca001a61baa8436bf2bbe4113",
22
+ "scripts": {
23
+ "test": "echo \"Error: no test specified\"",
24
+ "build": "flink build",
25
+ "clean": "rimraf dist .flink"
26
+ }
27
+ }
package/readme.md CHANGED
@@ -1,66 +1,385 @@
1
- # Flink API Docs
1
+ # @flink-app/management-actions-plugin
2
2
 
3
- A FLINK management-api module that makes it possible to expose actions that can be executed via the management-api, and thereby also via flink-admin.
3
+ A Flink management API module that enables you to create and execute custom actions through the management API. This plugin integrates with `@flink-app/management-api-plugin` to expose server-side actions that can be triggered via HTTP requests.
4
4
 
5
- ## Prerequisite
6
- Flink management-api-plugin must be installed and configured to your project.
5
+ ## Features
7
6
 
8
- ## Usage
7
+ - Define custom server-side actions with arguments
8
+ - Execute actions through the management API
9
+ - Type-safe argument handling
10
+ - Built-in UI support for management interfaces
11
+ - Flexible response handling with success/error states
12
+ - List all available actions via API
9
13
 
10
- Install plugin to your flink app project:
14
+ ## Prerequisites
11
15
 
12
- ```
13
- npm i -S @flink-app/management-actions-plugin
16
+ This plugin requires `@flink-app/management-api-plugin` to be installed and configured in your Flink application.
17
+
18
+ ```bash
19
+ npm install @flink-app/management-api-plugin
14
20
  ```
15
21
 
16
- Add and configure plugin in your app startup (probable the `index.ts` in root project):
22
+ ## Installation
17
23
 
24
+ ```bash
25
+ npm install @flink-app/management-actions-plugin
18
26
  ```
19
- import { GetManagementModule as GetActionsManagmenetModule } from '@flink-app/management-actions-plugin'
20
27
 
21
- const actionsManagementModule = GetActionsManagmenetModule({
22
- ui: true,
23
- uiSettings: {
24
- title: 'Actions',
25
- },
26
- actions : [
27
- {
28
- id: 'hello-world',
29
- description: 'Greets you',
30
- arguments: [
31
- {
32
- id: 'name',
33
- type: ActionArugmentType.text,
34
- required: true,
35
- },
36
- ],
37
- async handler(ctx: FlinkContext<any>, args: ActionArgumentsValues): Promise<ActionResponse> {
38
-
39
- return {
40
- data: {
41
- message: 'Hello ' + args.name,
42
- },
43
- status: ActionReturnStatus.success,
44
- }
28
+ ## Usage
29
+
30
+ ### Basic Setup
31
+
32
+ ```typescript
33
+ import { FlinkApp } from "@flink-app/flink";
34
+ import { managementApiPlugin } from "@flink-app/management-api-plugin";
35
+ import {
36
+ GetManagementModule,
37
+ ActionArugmentType,
38
+ ActionReturnStatus,
39
+ } from "@flink-app/management-actions-plugin";
40
+
41
+ const actionsModule = GetManagementModule({
42
+ ui: true,
43
+ uiSettings: {
44
+ title: "Actions",
45
+ },
46
+ actions: [
47
+ {
48
+ id: "hello-world",
49
+ description: "Greets you with a personalized message",
50
+ arguments: [
51
+ {
52
+ id: "name",
53
+ type: ActionArugmentType.text,
54
+ required: true,
45
55
  },
56
+ ],
57
+ async handler(ctx, args) {
58
+ return {
59
+ data: {
60
+ message: "Hello " + args.name,
61
+ },
62
+ status: ActionReturnStatus.success,
63
+ };
64
+ },
46
65
  },
47
-
48
- ]
49
- })
50
-
66
+ ],
67
+ });
51
68
 
52
69
  function start() {
53
70
  new FlinkApp<AppContext>({
54
71
  name: "My app",
55
72
  plugins: [
56
- // Register plugin
57
- managementApiPlugin({
58
- token : "SECRET_TOKEN_USED_TO_COMMUNICATE_WITH_THE_API",
59
- jwtSecret : "JWT_SECRET_USED_TO_GENERATE_LOGGED_IN_TOKENS",
60
- modules : [actionsManagementModule] // <-- Add the module
61
- })
73
+ managementApiPlugin({
74
+ token: "SECRET_TOKEN",
75
+ jwtSecret: "JWT_SECRET",
76
+ modules: [actionsModule],
77
+ }),
62
78
  ],
63
79
  }).start();
64
80
  }
81
+ ```
82
+
83
+ ## Action Definition
84
+
85
+ Each action requires the following properties:
86
+
87
+ ### Action Interface
88
+
89
+ ```typescript
90
+ interface Action {
91
+ id: string; // Unique identifier for the action
92
+ description?: string; // Human-readable description
93
+ arguments: ActionArguments[]; // Array of input arguments
94
+ handler: (ctx: FlinkContext<any>, args: ActionArgumentsValues) => Promise<ActionResponse>;
95
+ }
96
+ ```
97
+
98
+ ### Action Arguments
99
+
100
+ ```typescript
101
+ interface ActionArguments {
102
+ id: string; // Argument identifier
103
+ required: boolean; // Whether the argument is required
104
+ type: ActionArugmentType; // Argument type
105
+ default?: string; // Optional default value
106
+ }
107
+
108
+ enum ActionArugmentType {
109
+ text = "TEXT",
110
+ }
111
+ ```
112
+
113
+ ### Action Response
114
+
115
+ ```typescript
116
+ interface ActionResponse {
117
+ status: ActionReturnStatus; // SUCCESS or ERROR
118
+ error?: string; // Error message (if status is ERROR)
119
+ data?: {
120
+ [key: string]: any; // Response data (if status is SUCCESS)
121
+ };
122
+ }
123
+
124
+ enum ActionReturnStatus {
125
+ success = "SUCCESS",
126
+ error = "ERROR",
127
+ }
128
+ ```
129
+
130
+ ## API Endpoints
131
+
132
+ The plugin exposes two endpoints for each actions module:
133
+
134
+ ### List Actions
135
+
136
+ ```
137
+ GET /managementapi/{pluginId}
138
+ ```
139
+
140
+ Returns a list of all available actions with their configurations.
141
+
142
+ **Response:**
143
+ ```json
144
+ [
145
+ {
146
+ "id": "hello-world",
147
+ "description": "Greets you with a personalized message",
148
+ "arguments": [
149
+ {
150
+ "id": "name",
151
+ "type": "TEXT",
152
+ "required": true
153
+ }
154
+ ]
155
+ }
156
+ ]
157
+ ```
158
+
159
+ ### Execute Action
160
+
161
+ ```
162
+ POST /managementapi/{pluginId}/{actionId}
163
+ ```
164
+
165
+ Executes a specific action with provided arguments.
166
+
167
+ **Headers:**
168
+ ```
169
+ management-token: YOUR_TOKEN_OR_JWT
170
+ ```
171
+
172
+ **Request Body:**
173
+ ```json
174
+ {
175
+ "name": "World"
176
+ }
177
+ ```
178
+
179
+ **Response:**
180
+ ```json
181
+ {
182
+ "status": "SUCCESS",
183
+ "data": {
184
+ "message": "Hello World"
185
+ }
186
+ }
187
+ ```
188
+
189
+ ## Advanced Examples
190
+
191
+ ### Action with Multiple Arguments
192
+
193
+ ```typescript
194
+ {
195
+ id: "create-user",
196
+ description: "Creates a new user in the system",
197
+ arguments: [
198
+ {
199
+ id: "username",
200
+ type: ActionArugmentType.text,
201
+ required: true,
202
+ },
203
+ {
204
+ id: "email",
205
+ type: ActionArugmentType.text,
206
+ required: true,
207
+ },
208
+ {
209
+ id: "role",
210
+ type: ActionArugmentType.text,
211
+ required: false,
212
+ default: "user",
213
+ },
214
+ ],
215
+ async handler(ctx, args) {
216
+ try {
217
+ const user = await ctx.repos.userRepo.create({
218
+ username: args.username,
219
+ email: args.email,
220
+ role: args.role,
221
+ });
222
+
223
+ return {
224
+ status: ActionReturnStatus.success,
225
+ data: { userId: user._id },
226
+ };
227
+ } catch (error) {
228
+ return {
229
+ status: ActionReturnStatus.error,
230
+ error: error.message,
231
+ };
232
+ }
233
+ },
234
+ }
235
+ ```
65
236
 
237
+ ### Action with Database Access
238
+
239
+ ```typescript
240
+ {
241
+ id: "cleanup-old-records",
242
+ description: "Removes records older than 30 days",
243
+ arguments: [],
244
+ async handler(ctx, args) {
245
+ try {
246
+ const cutoffDate = new Date();
247
+ cutoffDate.setDate(cutoffDate.getDate() - 30);
248
+
249
+ const result = await ctx.repos.recordRepo.deleteMany({
250
+ createdAt: { $lt: cutoffDate },
251
+ });
252
+
253
+ return {
254
+ status: ActionReturnStatus.success,
255
+ data: {
256
+ deletedCount: result.deletedCount,
257
+ message: `Removed ${result.deletedCount} old records`,
258
+ },
259
+ };
260
+ } catch (error) {
261
+ return {
262
+ status: ActionReturnStatus.error,
263
+ error: `Failed to cleanup records: ${error.message}`,
264
+ };
265
+ }
266
+ },
267
+ }
268
+ ```
269
+
270
+ ### Action with External API Call
271
+
272
+ ```typescript
273
+ {
274
+ id: "sync-data",
275
+ description: "Syncs data from external service",
276
+ arguments: [
277
+ {
278
+ id: "service",
279
+ type: ActionArugmentType.text,
280
+ required: true,
281
+ },
282
+ ],
283
+ async handler(ctx, args) {
284
+ try {
285
+ const response = await fetch(`https://api.example.com/${args.service}`);
286
+ const data = await response.json();
287
+
288
+ // Process and store data
289
+ await ctx.repos.dataRepo.create(data);
290
+
291
+ return {
292
+ status: ActionReturnStatus.success,
293
+ data: {
294
+ recordsImported: data.length,
295
+ service: args.service,
296
+ },
297
+ };
298
+ } catch (error) {
299
+ return {
300
+ status: ActionReturnStatus.error,
301
+ error: `Sync failed: ${error.message}`,
302
+ };
303
+ }
304
+ },
305
+ }
66
306
  ```
307
+
308
+ ## Configuration Options
309
+
310
+ ### GetManagementModule Options
311
+
312
+ ```typescript
313
+ interface GetManagementModuleConfig {
314
+ pluginId?: string; // Custom plugin ID (defaults to "managementActionsApi")
315
+ ui: boolean; // Enable UI features
316
+ uiSettings?: {
317
+ title: string; // Display title in management UI
318
+ };
319
+ actions: Action[]; // Array of actions to register
320
+ }
321
+ ```
322
+
323
+ ## Context Access
324
+
325
+ Action handlers receive the full Flink context, providing access to:
326
+
327
+ - `ctx.repos` - All registered repositories
328
+ - `ctx.db` - MongoDB database connection
329
+ - `ctx.plugins` - All plugin contexts
330
+ - Any other context properties from your application
331
+
332
+ ## Security
333
+
334
+ All action endpoints are protected by the management API authentication system. Ensure you:
335
+
336
+ - Use the management token header for all requests
337
+ - Validate and sanitize action arguments
338
+ - Implement proper error handling
339
+ - Avoid exposing sensitive data in responses
340
+ - Log action executions for audit purposes
341
+
342
+ ## Testing Actions
343
+
344
+ You can test your actions using curl or any HTTP client:
345
+
346
+ ```bash
347
+ # Get list of actions
348
+ curl 'https://your-api.com/managementapi/managementActionsApi' \
349
+ -H 'management-token: YOUR_TOKEN'
350
+
351
+ # Execute an action
352
+ curl -X POST 'https://your-api.com/managementapi/managementActionsApi/hello-world' \
353
+ -H 'management-token: YOUR_TOKEN' \
354
+ -H 'Content-Type: application/json' \
355
+ -d '{"name":"World"}'
356
+ ```
357
+
358
+ ## TypeScript Support
359
+
360
+ The plugin is written in TypeScript and provides full type definitions for all interfaces and enums.
361
+
362
+ ## Error Handling
363
+
364
+ Always return proper error responses from action handlers:
365
+
366
+ ```typescript
367
+ async handler(ctx, args) {
368
+ try {
369
+ // Your action logic
370
+ return {
371
+ status: ActionReturnStatus.success,
372
+ data: { /* your data */ },
373
+ };
374
+ } catch (error) {
375
+ return {
376
+ status: ActionReturnStatus.error,
377
+ error: error instanceof Error ? error.message : "Unknown error",
378
+ };
379
+ }
380
+ }
381
+ ```
382
+
383
+ ## License
384
+
385
+ MIT
package/tsconfig.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "noEmit": false,
16
16
  "declaration": true,
17
17
  "experimentalDecorators": true,
18
- "checkJs": true,
18
+ "checkJs": false,
19
19
  "outDir": "dist"
20
20
  },
21
21
  "include": ["./src/*"],