@crowdin/app-project-module 2.1.0 → 2.3.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.d.ts +1 -0
- package/out/index.js +5 -1
- package/out/middlewares/ui-module.js +1 -2
- package/out/modules/about.d.ts +4 -0
- package/out/modules/about.js +25 -3
- package/out/modules/advisor-inspector/handlers/recheck.d.ts +4 -0
- package/out/modules/advisor-inspector/handlers/recheck.js +44 -0
- package/out/modules/advisor-inspector/index.d.ts +6 -0
- package/out/modules/advisor-inspector/index.js +35 -0
- package/out/modules/advisor-inspector/key.d.ts +4 -0
- package/out/modules/advisor-inspector/key.js +13 -0
- package/out/modules/advisor-inspector/report-insight.d.ts +3 -0
- package/out/modules/advisor-inspector/report-insight.js +61 -0
- package/out/modules/advisor-inspector/types.d.ts +59 -0
- package/out/modules/advisor-inspector/types.js +2 -0
- package/out/modules/manifest.js +15 -0
- package/out/static/css/styles.css +2 -342
- package/out/static/ui/about.bundle.js +542 -0
- package/out/static/ui/about.bundle.js.map +1 -0
- package/out/static/ui/error.bundle.js +120 -2
- package/out/static/ui/error.bundle.js.map +1 -1
- package/out/static/ui/form.bundle.js +164 -12
- package/out/static/ui/form.bundle.js.map +1 -1
- package/out/static/ui/install.bundle.js +8 -2
- package/out/static/ui/install.bundle.js.map +1 -1
- package/out/static/ui/login.bundle.js +425 -35
- package/out/static/ui/login.bundle.js.map +1 -1
- package/out/static/ui/main.bundle.js +718 -366
- package/out/static/ui/main.bundle.js.map +1 -1
- package/out/static/ui/oauth.bundle.js +8 -2
- package/out/static/ui/oauth.bundle.js.map +1 -1
- package/out/static/ui/subscription.bundle.js +542 -0
- package/out/static/ui/subscription.bundle.js.map +1 -0
- package/out/storage/drizzle/postgresql/migrations/0002_equal_skrulls.sql +3 -0
- package/out/storage/drizzle/postgresql/migrations/meta/0002_snapshot.json +646 -0
- package/out/storage/drizzle/postgresql/migrations/meta/_journal.json +7 -0
- package/out/storage/drizzle/postgresql/schema.js +2 -1
- package/out/storage/drizzle/sqlite/migrations/0001_new_rhodey.sql +26 -0
- package/out/storage/drizzle/sqlite/migrations/meta/0001_snapshot.json +687 -0
- package/out/storage/drizzle/sqlite/migrations/meta/_journal.json +7 -0
- package/out/storage/drizzle/sqlite/schema.js +2 -1
- package/out/types.d.ts +6 -0
- package/out/util/jsx-renderer.d.ts +2 -1
- package/out/util/jsx-renderer.js +8 -8
- package/out/views/FormPage.js +2 -2
- package/out/views/index.d.ts +0 -2
- package/out/views/index.js +1 -5
- package/out/views/layout/Head.js +0 -10
- package/package.json +5 -2
- package/out/static/css/about.css +0 -128
- package/out/static/css/crowdin-ui-colors.css +0 -115
- package/out/static/js/dependent.js +0 -315
- package/out/static/js/main.js +0 -96
- package/out/static/js/polyfills/fetch.js +0 -494
- package/out/static/js/polyfills/promise.js +0 -375
- package/out/views/AboutPage.d.ts +0 -10
- package/out/views/AboutPage.js +0 -88
- package/out/views/SubscriptionPage.d.ts +0 -7
- package/out/views/SubscriptionPage.js +0 -26
package/out/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { getRequestCredentialsMasker, postRequestCredentialsMasker, maskKey };
|
|
|
6
6
|
export * from './types';
|
|
7
7
|
export { Cron } from './util/cron';
|
|
8
8
|
export { express };
|
|
9
|
+
export { reportInsight as reportAdvisorInsight } from './modules/advisor-inspector/report-insight';
|
|
9
10
|
export declare const metadataStore: CrowdinMetadataStore;
|
|
10
11
|
export declare function createApp(clientConfig: ClientConfig): void;
|
|
11
12
|
export declare function addCrowdinEndpoints(app: Express, clientConfig: Config | ClientConfig): CrowdinAppUtilities;
|
package/out/index.js
CHANGED
|
@@ -48,7 +48,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
48
48
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
49
49
|
};
|
|
50
50
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
-
exports.metadataStore = exports.express = exports.maskKey = exports.postRequestCredentialsMasker = exports.getRequestCredentialsMasker = void 0;
|
|
51
|
+
exports.metadataStore = exports.reportAdvisorInsight = exports.express = exports.maskKey = exports.postRequestCredentialsMasker = exports.getRequestCredentialsMasker = void 0;
|
|
52
52
|
exports.createApp = createApp;
|
|
53
53
|
exports.addCrowdinEndpoints = addCrowdinEndpoints;
|
|
54
54
|
const logsFormatter = __importStar(require("@crowdin/logs-formatter"));
|
|
@@ -90,6 +90,7 @@ const spellCheckApp = __importStar(require("./modules/custom-spell-check"));
|
|
|
90
90
|
const aiProvider = __importStar(require("./modules/ai-provider"));
|
|
91
91
|
const aiPromptProvider = __importStar(require("./modules/ai-prompt-provider"));
|
|
92
92
|
const editorRightPanelApp = __importStar(require("./modules/editor-right-panel"));
|
|
93
|
+
const advisorInspector = __importStar(require("./modules/advisor-inspector"));
|
|
93
94
|
const externalQaCheck = __importStar(require("./modules/external-qa-check"));
|
|
94
95
|
const fileProcessingApps = __importStar(require("./modules/file-processing"));
|
|
95
96
|
const integrationApp = __importStar(require("./modules/integration"));
|
|
@@ -110,6 +111,8 @@ const automationAction = __importStar(require("./modules/automation-action"));
|
|
|
110
111
|
const authGuard = __importStar(require("./modules/auth-guard"));
|
|
111
112
|
const subscription_1 = require("./util/subscription");
|
|
112
113
|
__exportStar(require("./types"), exports);
|
|
114
|
+
var report_insight_1 = require("./modules/advisor-inspector/report-insight");
|
|
115
|
+
Object.defineProperty(exports, "reportAdvisorInsight", { enumerable: true, get: function () { return report_insight_1.reportInsight; } });
|
|
113
116
|
exports.metadataStore = {
|
|
114
117
|
getMetadata: (id) => {
|
|
115
118
|
return storage.getStorage().getMetadata(id);
|
|
@@ -257,6 +260,7 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
257
260
|
aiProvider.register({ config, app });
|
|
258
261
|
aiPromptProvider.register({ config, app });
|
|
259
262
|
externalQaCheck.register({ config, app });
|
|
263
|
+
advisorInspector.register({ config, app });
|
|
260
264
|
webhooks.register({ config, app });
|
|
261
265
|
workflowStepType.register({ config, app });
|
|
262
266
|
aiRequestProcessors.register({ config, app });
|
|
@@ -18,7 +18,6 @@ const connection_1 = require("../util/connection");
|
|
|
18
18
|
const jsx_renderer_1 = require("../util/jsx-renderer");
|
|
19
19
|
const logger_1 = require("../util/logger");
|
|
20
20
|
const subscription_1 = require("../util/subscription");
|
|
21
|
-
const views_1 = require("../views");
|
|
22
21
|
function handle({ config, allowUnauthorized = false, moduleType, }) {
|
|
23
22
|
return (0, util_1.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
24
23
|
// Allow access to non-HTML files
|
|
@@ -69,7 +68,7 @@ function handle({ config, allowUnauthorized = false, moduleType, }) {
|
|
|
69
68
|
accountType: credentials.type,
|
|
70
69
|
});
|
|
71
70
|
if (expired) {
|
|
72
|
-
const html = (0, jsx_renderer_1.
|
|
71
|
+
const html = (0, jsx_renderer_1.renderJSXOnClient)({ name: 'subscription', props: { subscribeLink } });
|
|
73
72
|
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
74
73
|
return res.send(html);
|
|
75
74
|
}
|
package/out/modules/about.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
2
|
import { Config, UnauthorizedConfig } from '../types';
|
|
3
|
+
export declare function getAboutPageHead({ name, storeLink }: {
|
|
4
|
+
name: string;
|
|
5
|
+
storeLink?: string;
|
|
6
|
+
}): string;
|
|
3
7
|
export declare function getAboutPageOptions(config: Config | UnauthorizedConfig): Promise<{
|
|
4
8
|
name: string;
|
|
5
9
|
logo: string;
|
package/out/modules/about.js
CHANGED
|
@@ -12,13 +12,35 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.getAboutPageHead = getAboutPageHead;
|
|
15
16
|
exports.getAboutPageOptions = getAboutPageOptions;
|
|
16
17
|
exports.default = handle;
|
|
17
18
|
const axios_1 = __importDefault(require("axios"));
|
|
18
19
|
const util_1 = require("../util");
|
|
19
20
|
const crowdin_client_1 = require("../middlewares/crowdin-client");
|
|
20
21
|
const jsx_renderer_1 = require("../util/jsx-renderer");
|
|
21
|
-
|
|
22
|
+
function escapeHtml(value) {
|
|
23
|
+
return value
|
|
24
|
+
.replace(/&/g, '&')
|
|
25
|
+
.replace(/</g, '<')
|
|
26
|
+
.replace(/>/g, '>')
|
|
27
|
+
.replace(/"/g, '"')
|
|
28
|
+
.replace(/'/g, ''');
|
|
29
|
+
}
|
|
30
|
+
function getAboutPageHead({ name, storeLink }) {
|
|
31
|
+
const escapedName = escapeHtml(name);
|
|
32
|
+
const escapedStoreLink = storeLink ? escapeHtml(storeLink) : '';
|
|
33
|
+
return `
|
|
34
|
+
<head>
|
|
35
|
+
<title>${escapedName}</title>
|
|
36
|
+
<meta charset="utf-8" />
|
|
37
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
|
38
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
39
|
+
${escapedStoreLink ? `<link rel="canonical" href="${escapedStoreLink}" />` : ''}
|
|
40
|
+
<link rel="stylesheet" href="/assets/css/styles.css" />
|
|
41
|
+
</head>
|
|
42
|
+
`;
|
|
43
|
+
}
|
|
22
44
|
function getAboutPageOptions(config) {
|
|
23
45
|
return __awaiter(this, void 0, void 0, function* () {
|
|
24
46
|
let detailPage = '';
|
|
@@ -46,7 +68,7 @@ function handle(config) {
|
|
|
46
68
|
const jwtToken = (0, crowdin_client_1.getToken)(req);
|
|
47
69
|
if (!jwtToken) {
|
|
48
70
|
const options = yield getAboutPageOptions(config);
|
|
49
|
-
const html = (0, jsx_renderer_1.
|
|
71
|
+
const html = (0, jsx_renderer_1.renderJSXOnClient)({ name: 'about', props: options, head: getAboutPageHead(options) });
|
|
50
72
|
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
51
73
|
return res.send(html);
|
|
52
74
|
}
|
|
@@ -56,7 +78,7 @@ function handle(config) {
|
|
|
56
78
|
}
|
|
57
79
|
}
|
|
58
80
|
const options = yield getAboutPageOptions(config);
|
|
59
|
-
const html = (0, jsx_renderer_1.
|
|
81
|
+
const html = (0, jsx_renderer_1.renderJSXOnClient)({ name: 'about', props: options, head: getAboutPageHead(options) });
|
|
60
82
|
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
61
83
|
return res.send(html);
|
|
62
84
|
});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Response } from 'express';
|
|
2
|
+
import { AdvisorInspectorModule } from '../types';
|
|
3
|
+
import { CrowdinClientRequest } from '../../../types';
|
|
4
|
+
export default function handle(inspector: AdvisorInspectorModule, moduleKey: string): (req: import("express").Request | CrowdinClientRequest, res: Response, next: Function) => void;
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
exports.default = handle;
|
|
13
|
+
const util_1 = require("../../../util");
|
|
14
|
+
const logger_1 = require("../../../util/logger");
|
|
15
|
+
function handle(inspector, moduleKey) {
|
|
16
|
+
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
const body = req.body;
|
|
18
|
+
(0, logger_1.log)(`Received advisor-inspector recheck nudge: ${JSON.stringify(body)}`);
|
|
19
|
+
// Ack first — BE expects a fast 2xx; the callback runs after the response flushes.
|
|
20
|
+
res.send({ data: { accepted: true } });
|
|
21
|
+
// Capture context locals BEFORE scheduling — Express may recycle `req` post-response.
|
|
22
|
+
const projectId = body.projectId;
|
|
23
|
+
const inspectorId = body.inspectorKey;
|
|
24
|
+
const crowdinId = req.crowdinContext.crowdinId;
|
|
25
|
+
const context = req.crowdinContext;
|
|
26
|
+
const client = req.crowdinApiClient;
|
|
27
|
+
// queueMicrotask is universal (works on Node AND Cloudflare Workers; setImmediate is Node-only).
|
|
28
|
+
queueMicrotask(() => __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
try {
|
|
30
|
+
yield inspector.onRecheck({
|
|
31
|
+
projectId,
|
|
32
|
+
moduleKey,
|
|
33
|
+
inspectorId,
|
|
34
|
+
crowdinId,
|
|
35
|
+
client,
|
|
36
|
+
context,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
(0, logger_1.log)(`advisor-inspector onRecheck error: ${(0, logger_1.getErrorMessage)(e)}`);
|
|
41
|
+
}
|
|
42
|
+
}));
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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 = register;
|
|
7
|
+
const crowdin_client_1 = require("../../middlewares/crowdin-client");
|
|
8
|
+
const json_response_1 = require("../../middlewares/json-response");
|
|
9
|
+
const render_ui_module_1 = __importDefault(require("../../middlewares/render-ui-module"));
|
|
10
|
+
const ui_module_1 = __importDefault(require("../../middlewares/ui-module"));
|
|
11
|
+
const recheck_1 = __importDefault(require("./handlers/recheck"));
|
|
12
|
+
const key_1 = require("./key");
|
|
13
|
+
function register({ config, app }) {
|
|
14
|
+
if (!config.advisorInspector) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const items = config.advisorInspector;
|
|
18
|
+
const isSingle = items.length === 1;
|
|
19
|
+
for (const [index, inspector] of items.entries()) {
|
|
20
|
+
const key = (0, key_1.resolveAdvisorInspectorKey)(config, inspector, index, isSingle);
|
|
21
|
+
const base = `/advisor-inspector/${key}`;
|
|
22
|
+
// Recheck nudge endpoint (BE → app, fire-and-forget).
|
|
23
|
+
// checkSubscriptionExpiration=false: nudges are platform traffic; 402-ing here
|
|
24
|
+
// would mask the async flow. App-paid features should gate inside onRecheck.
|
|
25
|
+
app.post(`${base}/recheck`, json_response_1.handle, (0, crowdin_client_1.handle)({
|
|
26
|
+
config,
|
|
27
|
+
optional: false,
|
|
28
|
+
checkSubscriptionExpiration: false,
|
|
29
|
+
moduleKey: key,
|
|
30
|
+
}), (0, recheck_1.default)(inspector, key));
|
|
31
|
+
if (inspector.uiPath || inspector.formSchema) {
|
|
32
|
+
app.use(`${base}/iframe`, (0, ui_module_1.default)({ config, moduleType: key }), (0, render_ui_module_1.default)(Object.assign(Object.assign({}, inspector), { key }), config));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveAdvisorInspectorKey = resolveAdvisorInspectorKey;
|
|
4
|
+
const normalize_module_1 = require("../../util/normalize-module");
|
|
5
|
+
function resolveAdvisorInspectorKey(config, item, index, isSingle) {
|
|
6
|
+
return (0, normalize_module_1.resolveInstanceKey)({
|
|
7
|
+
identifier: config.identifier,
|
|
8
|
+
suffix: 'advisor-inspector',
|
|
9
|
+
item,
|
|
10
|
+
index,
|
|
11
|
+
isSingle,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
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 __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.reportInsight = reportInsight;
|
|
16
|
+
const axios_1 = __importDefault(require("axios"));
|
|
17
|
+
const storage_1 = require("../../storage");
|
|
18
|
+
const connection_1 = require("../../util/connection");
|
|
19
|
+
const logger_1 = require("../../util/logger");
|
|
20
|
+
function buildBody(args) {
|
|
21
|
+
var _a, _b;
|
|
22
|
+
return Object.assign(Object.assign(Object.assign({ outcome: args.outcome }, (args.checkedAt !== undefined && { checkedAt: args.checkedAt })), { metrics: (_a = args.metrics) !== null && _a !== void 0 ? _a : [], recommendations: (_b = args.recommendations) !== null && _b !== void 0 ? _b : [] }), (args.payload !== undefined && { payload: args.payload }));
|
|
23
|
+
}
|
|
24
|
+
function put(url_1, body_1, token_1) {
|
|
25
|
+
return __awaiter(this, arguments, void 0, function* (url, body, token, timeoutMs = 300000) {
|
|
26
|
+
yield axios_1.default.put(url, body, {
|
|
27
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
28
|
+
timeout: timeoutMs,
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function isUnauthorized(e) {
|
|
33
|
+
const response = e === null || e === void 0 ? void 0 : e.response;
|
|
34
|
+
return !!response && response.status === 401;
|
|
35
|
+
}
|
|
36
|
+
function reportInsight(config, args) {
|
|
37
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
38
|
+
const credentials = yield (0, storage_1.getStorage)().getCrowdinCredentials(args.crowdinId);
|
|
39
|
+
if (!credentials) {
|
|
40
|
+
throw new Error(`reportInsight: no credentials for crowdinId=${args.crowdinId}`);
|
|
41
|
+
}
|
|
42
|
+
const body = buildBody(args);
|
|
43
|
+
const initial = yield (0, connection_1.prepareCrowdinClient)({ config, credentials, autoRenew: true });
|
|
44
|
+
let token = initial.token;
|
|
45
|
+
const url = `${initial.client.url}/projects/${args.projectId}` +
|
|
46
|
+
`/applications/${config.identifier}` +
|
|
47
|
+
`/modules/${args.moduleKey}/advisors/insights`;
|
|
48
|
+
try {
|
|
49
|
+
yield put(url, body, token, args.timeoutMs);
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
if (isUnauthorized(e)) {
|
|
53
|
+
({ token } = yield (0, connection_1.prepareCrowdinClient)({ config, credentials, autoRenew: true }));
|
|
54
|
+
yield put(url, body, token, args.timeoutMs);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
(0, logger_1.log)(`reportInsight PUT failed: ${(0, logger_1.getErrorMessage)(e)}`);
|
|
58
|
+
throw e;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import Crowdin from '@crowdin/crowdin-api-client';
|
|
2
|
+
import { CrowdinContextInfo, Environments, ModuleKey, UiModule } from '../../types';
|
|
3
|
+
export type AdvisorInspectorSeverity = 'high' | 'medium' | 'low';
|
|
4
|
+
export type AdvisorInspectorRefreshPolicy = 'hourly' | 'daily';
|
|
5
|
+
export type AdvisorInspectorCategory = 'context';
|
|
6
|
+
export type AdvisorInspectorOutcome = 'flagged' | 'clear' | 'not_applicable';
|
|
7
|
+
export interface AdvisorInspectorMetric {
|
|
8
|
+
key: string;
|
|
9
|
+
value: number;
|
|
10
|
+
unit?: 'percent' | 'count';
|
|
11
|
+
/** Comparison baseline shown in the UI */
|
|
12
|
+
threshold?: number;
|
|
13
|
+
tone?: 'default' | 'success' | 'danger';
|
|
14
|
+
checkedAt?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface AdvisorInspectorRecommendation {
|
|
17
|
+
id: string;
|
|
18
|
+
primary?: boolean;
|
|
19
|
+
params?: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
export interface AdvisorInspectorRecheckArgs {
|
|
22
|
+
projectId: number;
|
|
23
|
+
moduleKey: string;
|
|
24
|
+
/** prefixed, BE-supplied (e.g. 'app:my-app:daily-llm-check') */
|
|
25
|
+
inspectorId: string;
|
|
26
|
+
crowdinId: string;
|
|
27
|
+
client?: Crowdin;
|
|
28
|
+
context: CrowdinContextInfo;
|
|
29
|
+
}
|
|
30
|
+
export interface AdvisorInspectorRecheckRequest {
|
|
31
|
+
projectId: number;
|
|
32
|
+
inspectorKey: string;
|
|
33
|
+
}
|
|
34
|
+
export interface ReportInsightArgs {
|
|
35
|
+
crowdinId: string;
|
|
36
|
+
projectId: number;
|
|
37
|
+
moduleKey: string;
|
|
38
|
+
outcome: AdvisorInspectorOutcome;
|
|
39
|
+
metrics?: AdvisorInspectorMetric[];
|
|
40
|
+
recommendations?: AdvisorInspectorRecommendation[];
|
|
41
|
+
/**
|
|
42
|
+
* Free-form payload surfaced to the FE iframe via `formData`. BE requires an array
|
|
43
|
+
* (PHP-style — indexed or associative) and rejects raw scalars.
|
|
44
|
+
*/
|
|
45
|
+
payload?: unknown[] | Record<string, unknown>;
|
|
46
|
+
/** RFC3339; BE defaults to now() and clamps if >1h future / >7d past */
|
|
47
|
+
checkedAt?: string;
|
|
48
|
+
/** PUT request timeout in ms; default 300_000 (5 minutes) */
|
|
49
|
+
timeoutMs?: number;
|
|
50
|
+
}
|
|
51
|
+
export interface AdvisorInspectorModule extends Environments, ModuleKey, UiModule {
|
|
52
|
+
title: string;
|
|
53
|
+
/** Optional summary line; ≤70 chars */
|
|
54
|
+
summary?: string;
|
|
55
|
+
severity: AdvisorInspectorSeverity;
|
|
56
|
+
category: AdvisorInspectorCategory;
|
|
57
|
+
refreshPolicy: AdvisorInspectorRefreshPolicy;
|
|
58
|
+
onRecheck: (args: AdvisorInspectorRecheckArgs) => Promise<void>;
|
|
59
|
+
}
|
package/out/modules/manifest.js
CHANGED
|
@@ -9,6 +9,7 @@ const api_1 = require("./api/api");
|
|
|
9
9
|
const util_2 = require("./workflow-step-type/util");
|
|
10
10
|
const index_1 = require("./automation-action/util/index");
|
|
11
11
|
const ai_request_processors_1 = require("./ai-request-processors");
|
|
12
|
+
const key_1 = require("./advisor-inspector/key");
|
|
12
13
|
function normalizeEnvironments(environments) {
|
|
13
14
|
if (Array.isArray(environments)) {
|
|
14
15
|
return environments;
|
|
@@ -475,6 +476,20 @@ function handle(config) {
|
|
|
475
476
|
return Object.assign(Object.assign({ key, name: item.name || config.name, description: item.description || config.description, runQaCheckUrl: `${base}/validate` }, (item.batchSize ? { getBatchSizeUrl: `${base}/batch-size` } : {})), (uiModule ? { url: `${base}/settings/` + (uiModule.fileName || 'index.html') } : {}));
|
|
476
477
|
});
|
|
477
478
|
}
|
|
479
|
+
if (config.advisorInspector) {
|
|
480
|
+
config.advisorInspector = config.advisorInspector.map((item) => (Object.assign({}, item)));
|
|
481
|
+
const items = config.advisorInspector;
|
|
482
|
+
const isSingle = items.length === 1;
|
|
483
|
+
modules['advisor-inspector'] = items.map((item, index) => {
|
|
484
|
+
const key = (0, key_1.resolveAdvisorInspectorKey)(config, item, index, isSingle);
|
|
485
|
+
item.key = key;
|
|
486
|
+
const base = `/advisor-inspector/${key}`;
|
|
487
|
+
const hasIframe = !!(item.uiPath || item.formSchema);
|
|
488
|
+
return Object.assign(Object.assign(Object.assign(Object.assign({ key, name: item.name || config.name, title: item.title }, (item.summary && { summary: item.summary })), { severity: item.severity, category: item.category, refreshPolicy: item.refreshPolicy, recheckUrl: `${base}/recheck` }), (hasIframe && {
|
|
489
|
+
url: `${base}/iframe/${item.fileName || 'index.html'}`,
|
|
490
|
+
})), (item.environments && { environments: normalizeEnvironments(item.environments) }));
|
|
491
|
+
});
|
|
492
|
+
}
|
|
478
493
|
if (config.workflowStepType) {
|
|
479
494
|
// prevent possible overrides of the other modules
|
|
480
495
|
config.workflowStepType = config.workflowStepType.map((workflowStep) => (Object.assign({}, workflowStep)));
|