@crowdin/app-project-module 0.100.3 → 0.101.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/out/index.js +2 -0
- package/out/middlewares/render-ui-module.js +1 -0
- package/out/middlewares/ui-module.js +14 -10
- package/out/modules/automation-action/handlers/execute.d.ts +5 -0
- package/out/modules/automation-action/handlers/execute.js +78 -0
- package/out/modules/automation-action/handlers/input-schema.d.ts +5 -0
- package/out/modules/automation-action/handlers/input-schema.js +29 -0
- package/out/modules/automation-action/handlers/output-schema.d.ts +5 -0
- package/out/modules/automation-action/handlers/output-schema.js +29 -0
- package/out/modules/automation-action/handlers/validate-settings.d.ts +5 -0
- package/out/modules/automation-action/handlers/validate-settings.js +35 -0
- package/out/modules/automation-action/index.d.ts +6 -0
- package/out/modules/automation-action/index.js +45 -0
- package/out/modules/automation-action/types.d.ts +49 -0
- package/out/modules/automation-action/types.js +2 -0
- package/out/modules/automation-action/util/index.d.ts +3 -0
- package/out/modules/automation-action/util/index.js +15 -0
- package/out/modules/automation-action/util/validate-input.d.ts +9 -0
- package/out/modules/automation-action/util/validate-input.js +60 -0
- package/out/modules/install.js +19 -2
- package/out/modules/manifest.js +25 -0
- package/out/static/js/form.js +12 -20
- package/out/types.d.ts +11 -0
- package/out/types.js +1 -0
- package/out/util/connection.js +24 -3
- package/out/views/form.handlebars +1 -0
- package/package.json +8 -3
package/out/index.js
CHANGED
|
@@ -87,6 +87,7 @@ const projectToolsApp = __importStar(require("./modules/project-tools"));
|
|
|
87
87
|
const webhooks = __importStar(require("./modules/webhooks"));
|
|
88
88
|
const workflowStepType = __importStar(require("./modules/workflow-step-type"));
|
|
89
89
|
const aiRequestProcessors = __importStar(require("./modules/ai-request-processors"));
|
|
90
|
+
const automationAction = __importStar(require("./modules/automation-action"));
|
|
90
91
|
const subscription_1 = require("./util/subscription");
|
|
91
92
|
var types_2 = require("./types");
|
|
92
93
|
Object.defineProperty(exports, "ProjectPermissions", { enumerable: true, get: function () { return types_2.ProjectPermissions; } });
|
|
@@ -220,6 +221,7 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
220
221
|
webhooks.register({ config, app });
|
|
221
222
|
workflowStepType.register({ config, app });
|
|
222
223
|
aiRequestProcessors.register({ config, app });
|
|
224
|
+
automationAction.register({ config, app });
|
|
223
225
|
addFormSchema({ config, app });
|
|
224
226
|
return Object.assign(Object.assign({}, exports.metadataStore), { storage: storage.getStorage(), establishCrowdinConnection: (authRequest, moduleKey) => {
|
|
225
227
|
let jwtToken = '';
|
|
@@ -26,6 +26,7 @@ function handle(moduleConfig) {
|
|
|
26
26
|
: `/api/${moduleConfig.key}/form-data`,
|
|
27
27
|
formSchema: JSON.stringify(moduleConfig.formSchema),
|
|
28
28
|
formUiSchema: moduleConfig.formUiSchema ? JSON.stringify(moduleConfig.formUiSchema) : '{}',
|
|
29
|
+
formPatchDataUrl: moduleConfig.formPatchDataUrl,
|
|
29
30
|
});
|
|
30
31
|
}
|
|
31
32
|
if (moduleConfig.uiPath) {
|
|
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const crowdin_apps_functions_1 = require("@crowdin/crowdin-apps-functions");
|
|
13
13
|
const storage_1 = require("../storage");
|
|
14
|
+
const types_1 = require("../types");
|
|
14
15
|
const util_1 = require("../util");
|
|
15
16
|
const connection_1 = require("../util/connection");
|
|
16
17
|
const logger_1 = require("../util/logger");
|
|
@@ -48,16 +49,19 @@ function handle({ config, allowUnauthorized = false, moduleType, }) {
|
|
|
48
49
|
if (!credentials) {
|
|
49
50
|
throw new Error("Can't find organization by id");
|
|
50
51
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
config,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
// TODO Skip subscription check here for APP_WITH_CODE
|
|
53
|
+
if (config.authenticationType !== types_1.AuthenticationType.APP_WITH_CODE) {
|
|
54
|
+
logInfo('Building crowdin client instance');
|
|
55
|
+
const { token } = yield (0, connection_1.prepareCrowdinClient)({ config, credentials, context });
|
|
56
|
+
const { expired, subscribeLink } = yield (0, subscription_1.checkSubscription)({
|
|
57
|
+
config,
|
|
58
|
+
token,
|
|
59
|
+
organization: credentials.id,
|
|
60
|
+
accountType: credentials.type,
|
|
61
|
+
});
|
|
62
|
+
if (expired) {
|
|
63
|
+
return res.render('subscription', { subscribeLink });
|
|
64
|
+
}
|
|
61
65
|
}
|
|
62
66
|
next();
|
|
63
67
|
}));
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/// <reference types="qs" />
|
|
2
|
+
import { Response } from 'express';
|
|
3
|
+
import { CrowdinClientRequest } from '../../../types';
|
|
4
|
+
import { AutomationActionModule } from '../types';
|
|
5
|
+
export default function getExecuteHandler(automationAction: AutomationActionModule): (req: CrowdinClientRequest | import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: Function) => void;
|
|
@@ -0,0 +1,78 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const util_1 = require("../../../util");
|
|
13
|
+
const logger_1 = require("../../../util/logger");
|
|
14
|
+
const validate_input_1 = require("../util/validate-input");
|
|
15
|
+
// Maximum response size: 250KB
|
|
16
|
+
const MAX_RESPONSE_SIZE = 250 * 1024;
|
|
17
|
+
function getExecuteHandler(automationAction) {
|
|
18
|
+
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
req.logInfo('Received automation action execute request');
|
|
20
|
+
const isTaskTokenMode = automationAction.invocationWaitMode === 'taskToken';
|
|
21
|
+
// In taskToken mode, respond immediately to prevent Crowdin retries
|
|
22
|
+
// Execution continues asynchronously, communicating via API calls
|
|
23
|
+
if (isTaskTokenMode) {
|
|
24
|
+
res.status(200).send();
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
let validationErrors;
|
|
28
|
+
let inputData = req.body.formData || req.body;
|
|
29
|
+
if (automationAction.inputSchema) {
|
|
30
|
+
req.logInfo('Validate automation input data');
|
|
31
|
+
const { errors, data } = (0, validate_input_1.validateAutomationData)({
|
|
32
|
+
data: req.body,
|
|
33
|
+
schema: automationAction.inputSchema,
|
|
34
|
+
});
|
|
35
|
+
validationErrors = errors;
|
|
36
|
+
inputData = data;
|
|
37
|
+
}
|
|
38
|
+
const result = yield automationAction.execute({
|
|
39
|
+
client: req.crowdinApiClient,
|
|
40
|
+
inputData,
|
|
41
|
+
validationErrors,
|
|
42
|
+
context: req.crowdinContext,
|
|
43
|
+
req: req.body,
|
|
44
|
+
});
|
|
45
|
+
if (result) {
|
|
46
|
+
const responseJson = JSON.stringify(result);
|
|
47
|
+
const responseSize = Buffer.byteLength(responseJson, 'utf8');
|
|
48
|
+
// Check response size before sending
|
|
49
|
+
if (responseSize > MAX_RESPONSE_SIZE) {
|
|
50
|
+
throw new Error(`Response size (${responseSize} bytes) exceeds the maximum allowed size of ${MAX_RESPONSE_SIZE} bytes (250KB)`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (automationAction.validateOutputData !== false && result && automationAction.outputSchema) {
|
|
54
|
+
req.logInfo('Validate automation output data');
|
|
55
|
+
const { errors } = (0, validate_input_1.validateAutomationData)({
|
|
56
|
+
data: result,
|
|
57
|
+
schema: automationAction.outputSchema,
|
|
58
|
+
preserveEmptyArrays: true,
|
|
59
|
+
});
|
|
60
|
+
if (errors) {
|
|
61
|
+
throw new Error(JSON.stringify(errors));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!isTaskTokenMode) {
|
|
65
|
+
res.json({
|
|
66
|
+
data: result,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
req.logError(error);
|
|
72
|
+
if (!isTaskTokenMode) {
|
|
73
|
+
res.status(500).send({ error: { message: (0, logger_1.getErrorMessage)(error) } });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
exports.default = getExecuteHandler;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/// <reference types="qs" />
|
|
2
|
+
import { Response } from 'express';
|
|
3
|
+
import { AutomationActionModule } from '../types';
|
|
4
|
+
import { CrowdinClientRequest } from '../../../types';
|
|
5
|
+
export default function getInputSchemaHandler(automationAction: AutomationActionModule): (req: CrowdinClientRequest | import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: Function) => void;
|
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const logger_1 = require("../../../util/logger");
|
|
13
|
+
const util_1 = require("../../../util");
|
|
14
|
+
function getInputSchemaHandler(automationAction) {
|
|
15
|
+
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
try {
|
|
17
|
+
let schema = {};
|
|
18
|
+
if (automationAction.inputSchema) {
|
|
19
|
+
schema = automationAction.inputSchema;
|
|
20
|
+
}
|
|
21
|
+
res.json(schema);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
req.logError(error);
|
|
25
|
+
res.status(500).send({ error: { message: (0, logger_1.getErrorMessage)(error) } });
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
exports.default = getInputSchemaHandler;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/// <reference types="qs" />
|
|
2
|
+
import { Response } from 'express';
|
|
3
|
+
import { AutomationActionModule } from '../types';
|
|
4
|
+
import { CrowdinClientRequest } from '../../../types';
|
|
5
|
+
export default function getOutputSchemaHandler(automationAction: AutomationActionModule): (req: CrowdinClientRequest | import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: Function) => void;
|
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const logger_1 = require("../../../util/logger");
|
|
13
|
+
const util_1 = require("../../../util");
|
|
14
|
+
function getOutputSchemaHandler(automationAction) {
|
|
15
|
+
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
try {
|
|
17
|
+
let schema = {};
|
|
18
|
+
if (automationAction.outputSchema) {
|
|
19
|
+
schema = automationAction.outputSchema;
|
|
20
|
+
}
|
|
21
|
+
res.json(schema);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
req.logError(error);
|
|
25
|
+
res.status(500).send({ error: { message: (0, logger_1.getErrorMessage)(error) } });
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
exports.default = getOutputSchemaHandler;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/// <reference types="qs" />
|
|
2
|
+
import { Response } from 'express';
|
|
3
|
+
import { AutomationActionModule } from '../types';
|
|
4
|
+
import { CrowdinClientRequest } from '../../../types';
|
|
5
|
+
export default function getInputSchemaHandler(automationAction: AutomationActionModule): (req: CrowdinClientRequest | import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: Function) => void;
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const logger_1 = require("../../../util/logger");
|
|
13
|
+
const util_1 = require("../../../util");
|
|
14
|
+
function getInputSchemaHandler(automationAction) {
|
|
15
|
+
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
var _a;
|
|
17
|
+
try {
|
|
18
|
+
let result = {};
|
|
19
|
+
if (automationAction.validateSettings) {
|
|
20
|
+
result = yield automationAction.validateSettings({
|
|
21
|
+
client: req.crowdinApiClient,
|
|
22
|
+
settings: ((_a = req === null || req === void 0 ? void 0 : req.body) === null || _a === void 0 ? void 0 : _a.settings) || [],
|
|
23
|
+
context: req.crowdinContext,
|
|
24
|
+
req: req.body,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
res.json(result);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
req.logError(error);
|
|
31
|
+
res.status(500).send({ error: { message: (0, logger_1.getErrorMessage)(error) } });
|
|
32
|
+
}
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
exports.default = getInputSchemaHandler;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.register = void 0;
|
|
7
|
+
const cors_1 = __importDefault(require("cors"));
|
|
8
|
+
const output_schema_1 = __importDefault(require("./handlers/output-schema"));
|
|
9
|
+
const input_schema_1 = __importDefault(require("./handlers/input-schema"));
|
|
10
|
+
const validate_settings_1 = __importDefault(require("./handlers/validate-settings"));
|
|
11
|
+
const execute_1 = __importDefault(require("./handlers/execute"));
|
|
12
|
+
const util_1 = require("./util");
|
|
13
|
+
const crowdin_client_1 = __importDefault(require("../../middlewares/crowdin-client"));
|
|
14
|
+
const ui_module_1 = __importDefault(require("../../middlewares/ui-module"));
|
|
15
|
+
const render_ui_module_1 = __importDefault(require("../../middlewares/render-ui-module"));
|
|
16
|
+
function register({ config, app }) {
|
|
17
|
+
if (!config.automationAction) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const automationActions = Array.isArray(config.automationAction)
|
|
21
|
+
? config.automationAction
|
|
22
|
+
: [config.automationAction];
|
|
23
|
+
for (const automationAction of automationActions) {
|
|
24
|
+
app.options((0, util_1.getAutomationActionUrl)('/automation-action/output-schema', automationAction), (0, cors_1.default)());
|
|
25
|
+
app.get((0, util_1.getAutomationActionUrl)('/automation-action/output-schema', automationAction), (0, cors_1.default)(), (0, output_schema_1.default)(automationAction));
|
|
26
|
+
app.options((0, util_1.getAutomationActionUrl)('/automation-action/input-schema', automationAction), (0, cors_1.default)());
|
|
27
|
+
app.get((0, util_1.getAutomationActionUrl)('/automation-action/input-schema', automationAction), (0, cors_1.default)(), (0, input_schema_1.default)(automationAction));
|
|
28
|
+
app.post((0, util_1.getAutomationActionUrl)('/automation-action/validate-settings', automationAction), (0, crowdin_client_1.default)({
|
|
29
|
+
config,
|
|
30
|
+
optional: true,
|
|
31
|
+
checkSubscriptionExpiration: false,
|
|
32
|
+
moduleKey: automationAction.key,
|
|
33
|
+
}), (0, validate_settings_1.default)(automationAction));
|
|
34
|
+
app.post((0, util_1.getAutomationActionUrl)('/automation-action/execute', automationAction), (0, cors_1.default)(), (0, crowdin_client_1.default)({
|
|
35
|
+
config,
|
|
36
|
+
optional: true,
|
|
37
|
+
checkSubscriptionExpiration: false,
|
|
38
|
+
moduleKey: automationAction.key,
|
|
39
|
+
}), (0, execute_1.default)(automationAction));
|
|
40
|
+
if (automationAction.settingsUiModule) {
|
|
41
|
+
app.use((0, util_1.getAutomationActionUrl)('/automation-action', automationAction), (0, ui_module_1.default)({ config, moduleType: automationAction.key }), (0, render_ui_module_1.default)(automationAction.settingsUiModule));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.register = register;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { CrowdinContextInfo, ImagePath, ModuleKey, UiModule } from '../../types';
|
|
2
|
+
import Crowdin from '@crowdin/crowdin-api-client';
|
|
3
|
+
export interface AutomationActionModule extends ModuleKey, ImagePath {
|
|
4
|
+
/**
|
|
5
|
+
* module name
|
|
6
|
+
*/
|
|
7
|
+
name: string;
|
|
8
|
+
/**
|
|
9
|
+
* module description
|
|
10
|
+
*/
|
|
11
|
+
description?: string;
|
|
12
|
+
/**
|
|
13
|
+
* invocation wait mode, default is sync
|
|
14
|
+
*/
|
|
15
|
+
invocationWaitMode?: 'sync' | 'taskToken';
|
|
16
|
+
/**
|
|
17
|
+
* JSON schema defining the structure of data returned by the automation action
|
|
18
|
+
*/
|
|
19
|
+
outputSchema?: any;
|
|
20
|
+
/**
|
|
21
|
+
* JSON schema defining the structure of input parameters expected by the automation action
|
|
22
|
+
*/
|
|
23
|
+
inputSchema?: any;
|
|
24
|
+
validateSettings?: ({ client, settings, context, req, }: {
|
|
25
|
+
client: Crowdin;
|
|
26
|
+
settings: any;
|
|
27
|
+
context: CrowdinContextInfo;
|
|
28
|
+
req: any;
|
|
29
|
+
}) => Promise<any>;
|
|
30
|
+
/**
|
|
31
|
+
* function to execute the automation action
|
|
32
|
+
*/
|
|
33
|
+
execute: ({ client, inputData, validationErrors, context, req, }: {
|
|
34
|
+
client: Crowdin;
|
|
35
|
+
inputData: any;
|
|
36
|
+
validationErrors?: Record<string, string> | undefined;
|
|
37
|
+
context: CrowdinContextInfo;
|
|
38
|
+
req: any;
|
|
39
|
+
}) => Promise<any>;
|
|
40
|
+
/**
|
|
41
|
+
* Settings UI module
|
|
42
|
+
*/
|
|
43
|
+
settingsUiModule?: UiModule;
|
|
44
|
+
/**
|
|
45
|
+
* validate output data, default: true
|
|
46
|
+
* set to false to skip output validation
|
|
47
|
+
*/
|
|
48
|
+
validateOutputData?: boolean;
|
|
49
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getAutomationActionUrl = exports.getAutomationActionKey = void 0;
|
|
7
|
+
const lodash_kebabcase_1 = __importDefault(require("lodash.kebabcase"));
|
|
8
|
+
function getAutomationActionKey(automationAction) {
|
|
9
|
+
return (0, lodash_kebabcase_1.default)(automationAction.name);
|
|
10
|
+
}
|
|
11
|
+
exports.getAutomationActionKey = getAutomationActionKey;
|
|
12
|
+
function getAutomationActionUrl(path, automationAction) {
|
|
13
|
+
return `${path}/${automationAction.key}`;
|
|
14
|
+
}
|
|
15
|
+
exports.getAutomationActionUrl = getAutomationActionUrl;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateAutomationData = void 0;
|
|
7
|
+
const ajv_1 = __importDefault(require("ajv"));
|
|
8
|
+
const ajv = new ajv_1.default({ allErrors: true, strict: false, coerceTypes: true });
|
|
9
|
+
function formatAjvErrors(errors = []) {
|
|
10
|
+
if (!errors.length) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
return errors.reduce((acc, err) => {
|
|
14
|
+
const path = err.instancePath || '/';
|
|
15
|
+
acc[path] = err.message || '';
|
|
16
|
+
return acc;
|
|
17
|
+
}, {});
|
|
18
|
+
}
|
|
19
|
+
function removeEmptyValues(obj, options = { preserveEmptyArrays: true }) {
|
|
20
|
+
const { preserveEmptyArrays = true } = options;
|
|
21
|
+
if (Array.isArray(obj)) {
|
|
22
|
+
return obj
|
|
23
|
+
.map((item) => removeEmptyValues(item, options))
|
|
24
|
+
.filter((v) => v !== undefined &&
|
|
25
|
+
v !== null &&
|
|
26
|
+
!(Array.isArray(v) && v.length === 0 && !preserveEmptyArrays) &&
|
|
27
|
+
!(typeof v === 'object' && Object.keys(v).length === 0));
|
|
28
|
+
}
|
|
29
|
+
if (typeof obj === 'object' && obj !== null) {
|
|
30
|
+
const newObj = {};
|
|
31
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
32
|
+
if (value === undefined) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const cleanedValue = removeEmptyValues(value, options);
|
|
36
|
+
if (cleanedValue !== '' &&
|
|
37
|
+
cleanedValue !== null &&
|
|
38
|
+
cleanedValue !== undefined &&
|
|
39
|
+
!(Array.isArray(cleanedValue) && cleanedValue.length === 0 && !preserveEmptyArrays) &&
|
|
40
|
+
!(typeof cleanedValue === 'object' &&
|
|
41
|
+
!Array.isArray(cleanedValue) &&
|
|
42
|
+
Object.keys(cleanedValue).length === 0)) {
|
|
43
|
+
newObj[key] = cleanedValue;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return newObj;
|
|
47
|
+
}
|
|
48
|
+
return obj;
|
|
49
|
+
}
|
|
50
|
+
function validateAutomationData({ data, schema, preserveEmptyArrays = false, }) {
|
|
51
|
+
const cleaned = removeEmptyValues(data, { preserveEmptyArrays });
|
|
52
|
+
const validate = ajv.compile(schema);
|
|
53
|
+
const valid = validate(cleaned);
|
|
54
|
+
return {
|
|
55
|
+
valid: Boolean(valid),
|
|
56
|
+
errors: formatAjvErrors((validate === null || validate === void 0 ? void 0 : validate.errors) || []),
|
|
57
|
+
data: cleaned,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
exports.validateAutomationData = validateAutomationData;
|
package/out/modules/install.js
CHANGED
|
@@ -54,7 +54,7 @@ function handle(config) {
|
|
|
54
54
|
}
|
|
55
55
|
exports.default = handle;
|
|
56
56
|
function fetchToken(config, event) {
|
|
57
|
-
var _a, _b, _c;
|
|
57
|
+
var _a, _b, _c, _d;
|
|
58
58
|
return __awaiter(this, void 0, void 0, function* () {
|
|
59
59
|
if (config.authenticationType === types_1.AuthenticationType.CODE) {
|
|
60
60
|
const token = yield (0, crowdin_apps_functions_1.generateOAuthToken)({
|
|
@@ -86,6 +86,23 @@ function fetchToken(config, event) {
|
|
|
86
86
|
refreshToken: '',
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
|
+
if (config.authenticationType === types_1.AuthenticationType.APP_WITH_CODE) {
|
|
90
|
+
const token = yield (0, crowdin_apps_functions_1.fetchAppWithCodeToken)({
|
|
91
|
+
appId: config.identifier,
|
|
92
|
+
appSecret: event.appSecret,
|
|
93
|
+
clientId: config.clientId,
|
|
94
|
+
clientSecret: config.clientSecret,
|
|
95
|
+
domain: event.domain || '',
|
|
96
|
+
userId: event.userId,
|
|
97
|
+
code: event.code,
|
|
98
|
+
url: (_c = config.crowdinUrls) === null || _c === void 0 ? void 0 : _c.accountUrl,
|
|
99
|
+
});
|
|
100
|
+
return {
|
|
101
|
+
accessToken: (0, util_1.encryptData)(config, token.accessToken),
|
|
102
|
+
expiresIn: token.expiresIn,
|
|
103
|
+
refreshToken: '',
|
|
104
|
+
};
|
|
105
|
+
}
|
|
89
106
|
const token = yield (0, crowdin_apps_functions_1.fetchAppToken)({
|
|
90
107
|
appId: config.identifier,
|
|
91
108
|
appSecret: event.appSecret,
|
|
@@ -93,7 +110,7 @@ function fetchToken(config, event) {
|
|
|
93
110
|
clientSecret: config.clientSecret,
|
|
94
111
|
domain: event.domain || '',
|
|
95
112
|
userId: event.userId,
|
|
96
|
-
url: (
|
|
113
|
+
url: (_d = config.crowdinUrls) === null || _d === void 0 ? void 0 : _d.accountUrl,
|
|
97
114
|
});
|
|
98
115
|
return {
|
|
99
116
|
accessToken: (0, util_1.encryptData)(config, token.accessToken),
|
package/out/modules/manifest.js
CHANGED
|
@@ -6,6 +6,7 @@ const subscription_1 = require("../util/subscription");
|
|
|
6
6
|
const api_1 = require("./api/api");
|
|
7
7
|
const util_2 = require("./ai-tools/util");
|
|
8
8
|
const util_3 = require("./workflow-step-type/util");
|
|
9
|
+
const index_1 = require("./automation-action/util/index");
|
|
9
10
|
const ai_request_processors_1 = require("./ai-request-processors");
|
|
10
11
|
function normalizeEnvironments(environments) {
|
|
11
12
|
if (Array.isArray(environments)) {
|
|
@@ -382,6 +383,30 @@ function handle(config) {
|
|
|
382
383
|
modules['workflow-step-type'].push(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ key: workflowStep.key, name: workflowStep.name || config.name }, ((workflowStep === null || workflowStep === void 0 ? void 0 : workflowStep.imagePath) ? { logo: (0, util_1.getLogoUrl)(workflowStep, `-${workflowStep.key}`) } : {})), { description: workflowStep.description || config.description, boundaries: workflowStep.boundaries }), (workflowStep.editorMode ? { editorMode: workflowStep.editorMode } : {})), { updateSettingsUrl: (0, util_3.getWorkflowStepUrl)('/workflow-step/settings', workflowStep), deleteSettingsUrl: (0, util_3.getWorkflowStepUrl)('/workflow-step/delete', workflowStep) }), (uiModule ? { url: (0, util_3.getWorkflowStepUrl)('/workflow-step', workflowStep) } : {})));
|
|
383
384
|
}
|
|
384
385
|
}
|
|
386
|
+
if (config.automationAction) {
|
|
387
|
+
// prevent possible overrides of the other modules
|
|
388
|
+
if (Array.isArray(config.automationAction)) {
|
|
389
|
+
config.automationAction = config.automationAction.map((automationAction) => (Object.assign({}, automationAction)));
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
config.automationAction = Object.assign({}, config.automationAction);
|
|
393
|
+
}
|
|
394
|
+
const automationActions = Array.isArray(config.automationAction)
|
|
395
|
+
? config.automationAction
|
|
396
|
+
: [config.automationAction];
|
|
397
|
+
modules['automation-action'] = [];
|
|
398
|
+
for (const automationAction of automationActions) {
|
|
399
|
+
if (!automationAction.key) {
|
|
400
|
+
automationAction.key = config.identifier + '-' + (0, index_1.getAutomationActionKey)(automationAction);
|
|
401
|
+
}
|
|
402
|
+
const uiModule = automationAction.settingsUiModule;
|
|
403
|
+
modules['automation-action'].push(Object.assign(Object.assign(Object.assign(Object.assign({ key: automationAction.key, name: automationAction.name || config.name, description: automationAction.description || config.description }, (automationAction.outputSchema
|
|
404
|
+
? { outputSchemaUrl: (0, index_1.getAutomationActionUrl)('/automation-action/output-schema', automationAction) }
|
|
405
|
+
: {})), (automationAction.inputSchema
|
|
406
|
+
? { inputSchemaUrl: (0, index_1.getAutomationActionUrl)('/automation-action/input-schema', automationAction) }
|
|
407
|
+
: {})), { validateSettingsUrl: (0, index_1.getAutomationActionUrl)('/automation-action/validate-settings', automationAction), executeUrl: (0, index_1.getAutomationActionUrl)('/automation-action/execute', automationAction), invocationWaitMode: automationAction.invocationWaitMode || 'sync' }), (uiModule ? { url: (0, index_1.getAutomationActionUrl)('/automation-action', automationAction) } : {})));
|
|
408
|
+
}
|
|
409
|
+
}
|
|
385
410
|
const events = {
|
|
386
411
|
installed: '/installed',
|
|
387
412
|
uninstall: '/uninstall',
|