@crowdin/app-project-module 0.81.1 → 0.82.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/modules/ai-request-processors/handler.d.ts +5 -0
- package/out/modules/ai-request-processors/handler.js +63 -0
- package/out/modules/ai-request-processors/index.d.ts +16 -0
- package/out/modules/ai-request-processors/index.js +45 -0
- package/out/modules/ai-request-processors/types.d.ts +14 -0
- package/out/modules/ai-request-processors/types.js +2 -0
- package/out/modules/file-processing/handlers/pre-post-process.js +22 -2
- package/out/modules/file-processing/types.d.ts +1 -1
- package/out/modules/manifest.js +17 -0
- package/out/static/js/form.js +14 -12
- package/out/types.d.ts +17 -0
- package/out/views/main.handlebars +4 -0
- package/package.json +3 -3
package/out/index.js
CHANGED
|
@@ -83,6 +83,7 @@ const projectReportsApp = __importStar(require("./modules/project-reports"));
|
|
|
83
83
|
const projectToolsApp = __importStar(require("./modules/project-tools"));
|
|
84
84
|
const webhooks = __importStar(require("./modules/webhooks"));
|
|
85
85
|
const workflowStepType = __importStar(require("./modules/workflow-step-type"));
|
|
86
|
+
const aiRequestProcessors = __importStar(require("./modules/ai-request-processors"));
|
|
86
87
|
const subscription_1 = require("./util/subscription");
|
|
87
88
|
var types_2 = require("./types");
|
|
88
89
|
Object.defineProperty(exports, "ProjectPermissions", { enumerable: true, get: function () { return types_2.ProjectPermissions; } });
|
|
@@ -190,6 +191,7 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
190
191
|
externalQaCheck.register({ config, app });
|
|
191
192
|
webhooks.register({ config, app });
|
|
192
193
|
workflowStepType.register({ config, app });
|
|
194
|
+
aiRequestProcessors.register({ config, app });
|
|
193
195
|
addFormSchema({ config, app });
|
|
194
196
|
return Object.assign(Object.assign({}, exports.metadataStore), { storage: storage.getStorage(), establishCrowdinConnection: (authRequest, moduleKey) => {
|
|
195
197
|
let jwtToken = '';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/// <reference types="qs" />
|
|
2
|
+
import { Response } from 'express';
|
|
3
|
+
import { CrowdinClientRequest } from '../../types';
|
|
4
|
+
import { AiRequestProcessorModule, AiStreamProcessorModule } from './types';
|
|
5
|
+
export default function handle(module: AiRequestProcessorModule | AiStreamProcessorModule, canHandleStream?: boolean): (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,63 @@
|
|
|
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 BUFFERING_FLAG = '~buffering~';
|
|
15
|
+
function handle(module, canHandleStream = false) {
|
|
16
|
+
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
try {
|
|
18
|
+
if (canHandleStream && req.headers['transfer-encoding'] === 'chunked') {
|
|
19
|
+
if (!('processStream' in module)) {
|
|
20
|
+
res.writeHead(202, {}).end();
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
res.writeHead(200, {
|
|
24
|
+
Connection: 'keep-alive',
|
|
25
|
+
'Cache-Control': 'no-cache',
|
|
26
|
+
'Content-Type': 'text/event-stream',
|
|
27
|
+
'X-Accel-Buffering': 'no',
|
|
28
|
+
});
|
|
29
|
+
req.on('data', (chunk) => __awaiter(this, void 0, void 0, function* () {
|
|
30
|
+
let chunkStr = chunk.toString();
|
|
31
|
+
// actually we checked if processStream exists already, but need do to this again to calm down TS compiler
|
|
32
|
+
chunkStr = module.processStream
|
|
33
|
+
? yield module.processStream(chunkStr, req.query, req.crowdinApiClient, req.crowdinContext)
|
|
34
|
+
: chunkStr;
|
|
35
|
+
if (!chunkStr && typeof chunkStr !== 'string') {
|
|
36
|
+
res.write(BUFFERING_FLAG);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
res.write(chunkStr);
|
|
40
|
+
}));
|
|
41
|
+
req.on('end', () => {
|
|
42
|
+
res.end();
|
|
43
|
+
});
|
|
44
|
+
req.on('error', (e) => {
|
|
45
|
+
if (req.logError) {
|
|
46
|
+
req.logError(e);
|
|
47
|
+
}
|
|
48
|
+
res.end();
|
|
49
|
+
});
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const result = yield module.processRequest(req.body, req.query, req.crowdinApiClient, req.crowdinContext);
|
|
53
|
+
res.send(result);
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
if (req.logError) {
|
|
57
|
+
req.logError(e);
|
|
58
|
+
}
|
|
59
|
+
res.send({ error: { message: (0, logger_1.getErrorMessage)(e) } });
|
|
60
|
+
}
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
exports.default = handle;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Express } from 'express';
|
|
2
|
+
import { Config } from '../../types';
|
|
3
|
+
export declare enum AiRequestProcessorModuleWithStream {
|
|
4
|
+
aiRequestPreParse = "aiRequestPreParse"
|
|
5
|
+
}
|
|
6
|
+
export declare enum AiRequestProcessorModuleWithoutStream {
|
|
7
|
+
aiRequestPreCompile = "aiRequestPreCompile",
|
|
8
|
+
aiRequestPostCompile = "aiRequestPostCompile",
|
|
9
|
+
aiRequestPostParse = "aiRequestPostParse"
|
|
10
|
+
}
|
|
11
|
+
export type AiRequestProcessorModuleType = AiRequestProcessorModuleWithoutStream | AiRequestProcessorModuleWithStream;
|
|
12
|
+
export declare function generateModuleSlugFromType(moduleType: string): string;
|
|
13
|
+
export declare function register({ config, app }: {
|
|
14
|
+
config: Config;
|
|
15
|
+
app: Express;
|
|
16
|
+
}): void;
|
|
@@ -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 = exports.generateModuleSlugFromType = exports.AiRequestProcessorModuleWithoutStream = exports.AiRequestProcessorModuleWithStream = void 0;
|
|
7
|
+
const json_response_1 = __importDefault(require("../../middlewares/json-response"));
|
|
8
|
+
const crowdin_client_1 = __importDefault(require("../../middlewares/crowdin-client"));
|
|
9
|
+
const handler_1 = __importDefault(require("./handler"));
|
|
10
|
+
var AiRequestProcessorModuleWithStream;
|
|
11
|
+
(function (AiRequestProcessorModuleWithStream) {
|
|
12
|
+
AiRequestProcessorModuleWithStream["aiRequestPreParse"] = "aiRequestPreParse";
|
|
13
|
+
})(AiRequestProcessorModuleWithStream = exports.AiRequestProcessorModuleWithStream || (exports.AiRequestProcessorModuleWithStream = {}));
|
|
14
|
+
var AiRequestProcessorModuleWithoutStream;
|
|
15
|
+
(function (AiRequestProcessorModuleWithoutStream) {
|
|
16
|
+
AiRequestProcessorModuleWithoutStream["aiRequestPreCompile"] = "aiRequestPreCompile";
|
|
17
|
+
AiRequestProcessorModuleWithoutStream["aiRequestPostCompile"] = "aiRequestPostCompile";
|
|
18
|
+
AiRequestProcessorModuleWithoutStream["aiRequestPostParse"] = "aiRequestPostParse";
|
|
19
|
+
})(AiRequestProcessorModuleWithoutStream = exports.AiRequestProcessorModuleWithoutStream || (exports.AiRequestProcessorModuleWithoutStream = {}));
|
|
20
|
+
function generateModuleSlugFromType(moduleType) {
|
|
21
|
+
return moduleType
|
|
22
|
+
.split(/\.?(?=[A-Z])/)
|
|
23
|
+
.join('-')
|
|
24
|
+
.toLowerCase();
|
|
25
|
+
}
|
|
26
|
+
exports.generateModuleSlugFromType = generateModuleSlugFromType;
|
|
27
|
+
function registerProcessorModuleByTypeKey(moduleKey, { config, app }) {
|
|
28
|
+
const module = config[moduleKey];
|
|
29
|
+
if (!module) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
app.post('/ai-request-processor/' + generateModuleSlugFromType(moduleKey), json_response_1.default, (0, crowdin_client_1.default)({
|
|
33
|
+
config,
|
|
34
|
+
optional: false,
|
|
35
|
+
checkSubscriptionExpiration: true,
|
|
36
|
+
moduleKey: module.key,
|
|
37
|
+
}), (0, handler_1.default)(module, moduleKey in AiRequestProcessorModuleWithStream));
|
|
38
|
+
}
|
|
39
|
+
function register({ config, app }) {
|
|
40
|
+
[
|
|
41
|
+
...Object.values(AiRequestProcessorModuleWithoutStream),
|
|
42
|
+
...Object.values(AiRequestProcessorModuleWithStream),
|
|
43
|
+
].forEach((moduleTypeKey) => registerProcessorModuleByTypeKey(moduleTypeKey, { config, app }));
|
|
44
|
+
}
|
|
45
|
+
exports.register = register;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { CrowdinContextInfo, ModuleKey } from '../../types';
|
|
2
|
+
import Crowdin from '@crowdin/crowdin-api-client';
|
|
3
|
+
export interface AiRequestProcessorModule extends ModuleKey {
|
|
4
|
+
/**
|
|
5
|
+
* updates request data
|
|
6
|
+
*/
|
|
7
|
+
processRequest: (requestData: any, requestContext: any, client: Crowdin, context: CrowdinContextInfo) => Promise<never>;
|
|
8
|
+
}
|
|
9
|
+
export interface AiStreamProcessorModule extends AiRequestProcessorModule {
|
|
10
|
+
/**
|
|
11
|
+
* updates request data
|
|
12
|
+
*/
|
|
13
|
+
processStream?: (chunk: any, requestContext: any, client: Crowdin, context: CrowdinContextInfo) => Promise<string | null>;
|
|
14
|
+
}
|
|
@@ -92,11 +92,31 @@ function handle(baseConfig, config, folderName) {
|
|
|
92
92
|
break;
|
|
93
93
|
case types_1.ProcessFileJobType.POST_IMPORT:
|
|
94
94
|
case types_1.ProcessFileJobType.PRE_EXPORT:
|
|
95
|
-
const { strings, error: stringsFileError } = fileProcessResult;
|
|
95
|
+
const { strings, error: stringsFileError, previewFile } = fileProcessResult;
|
|
96
|
+
let maxSize = files_1.MAX_BODY_SIZE;
|
|
97
|
+
if (strings && previewFile && body.jobType === types_1.ProcessFileJobType.POST_IMPORT) {
|
|
98
|
+
maxSize = maxSize / 2;
|
|
99
|
+
}
|
|
100
|
+
if (previewFile && body.jobType === types_1.ProcessFileJobType.POST_IMPORT) {
|
|
101
|
+
if (Buffer.byteLength(previewFile) < maxSize) {
|
|
102
|
+
response.preview = previewFile.toString('base64');
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
let url;
|
|
106
|
+
if (config.storeFile) {
|
|
107
|
+
url = yield config.storeFile(previewFile);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const storedFile = yield (0, files_1.storeFile)(previewFile, path_1.default.join(folderPath, folderName));
|
|
111
|
+
url = `${baseFilesUrl}?file=${storedFile}`;
|
|
112
|
+
}
|
|
113
|
+
response.previewUrl = url;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
96
116
|
if (strings) {
|
|
97
117
|
const stringsNDJson = strings.map((s) => JSON.stringify(s)).join('\n\r');
|
|
98
118
|
const bufferData = Buffer.from(stringsNDJson, 'utf-8');
|
|
99
|
-
if (Buffer.byteLength(bufferData) <
|
|
119
|
+
if (Buffer.byteLength(bufferData) < maxSize) {
|
|
100
120
|
response.strings = strings;
|
|
101
121
|
}
|
|
102
122
|
else {
|
|
@@ -115,7 +115,7 @@ export interface BuildFileResponse {
|
|
|
115
115
|
fileName?: string;
|
|
116
116
|
fileType?: string;
|
|
117
117
|
}
|
|
118
|
-
export interface StringsFileResponse extends
|
|
118
|
+
export interface StringsFileResponse extends ParseFileResponse {
|
|
119
119
|
notModified?: boolean;
|
|
120
120
|
}
|
|
121
121
|
export interface ContentFileResponse extends BuildFileResponse {
|
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 ai_request_processors_1 = require("./ai-request-processors");
|
|
9
10
|
function normalizeEnvironments(environments) {
|
|
10
11
|
if (Array.isArray(environments)) {
|
|
11
12
|
return environments;
|
|
@@ -236,6 +237,22 @@ function handle(config) {
|
|
|
236
237
|
})), (uiModule ? { url: '/settings/' + (uiModule.fileName || 'index.html') } : {})),
|
|
237
238
|
];
|
|
238
239
|
}
|
|
240
|
+
[
|
|
241
|
+
...Object.values(ai_request_processors_1.AiRequestProcessorModuleWithoutStream),
|
|
242
|
+
...Object.values(ai_request_processors_1.AiRequestProcessorModuleWithStream),
|
|
243
|
+
].forEach((moduleType) => {
|
|
244
|
+
const module = config[moduleType];
|
|
245
|
+
if (!module) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const moduleSlug = (0, ai_request_processors_1.generateModuleSlugFromType)(moduleType);
|
|
249
|
+
modules[moduleSlug] = [
|
|
250
|
+
{
|
|
251
|
+
key: config.identifier + '-' + moduleSlug,
|
|
252
|
+
processorUrl: '/ai-request-processor/' + moduleSlug,
|
|
253
|
+
},
|
|
254
|
+
];
|
|
255
|
+
});
|
|
239
256
|
if (config.aiPromptProvider) {
|
|
240
257
|
// prevent possible overrides of the other modules
|
|
241
258
|
config.aiPromptProvider = Object.assign(Object.assign({}, config.aiPromptProvider), { key: config.identifier + '-ai-prompt-provider' });
|