@crowdin/app-project-module 0.105.1 → 0.107.0-cf-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/app-test/integration/get-integration-files.js +0 -1
- package/out/app-test/integration/mocks/mock-axios.js +0 -1
- package/out/app-test/integration/update-crowdin.js +0 -1
- package/out/app-test/integration/update-integration.js +0 -1
- package/out/index.d.ts +1 -0
- package/out/index.js +30 -12
- package/out/middlewares/crowdin-client.d.ts +1 -1
- package/out/middlewares/integration-credentials.d.ts +1 -1
- package/out/middlewares/integration-credentials.js +4 -1
- package/out/middlewares/render-ui-module.d.ts +3 -3
- package/out/middlewares/render-ui-module.js +9 -13
- package/out/middlewares/ui-module.d.ts +1 -1
- package/out/middlewares/ui-module.js +10 -1
- package/out/modules/about.d.ts +2 -1
- package/out/modules/about.js +10 -3
- package/out/modules/ai-prompt-provider/handlers/compile.d.ts +1 -1
- package/out/modules/ai-prompt-provider/index.js +2 -2
- package/out/modules/ai-provider/handlers/chat-completions.d.ts +1 -1
- package/out/modules/ai-provider/handlers/chat-completions.js +0 -1
- package/out/modules/ai-provider/handlers/get-model-list.d.ts +1 -1
- package/out/modules/ai-provider/index.js +2 -2
- package/out/modules/ai-provider/types.d.ts +2 -2
- package/out/modules/ai-provider/util/index.js +0 -2
- package/out/modules/ai-request-processors/handler.d.ts +1 -1
- package/out/modules/ai-tools/handlers/tool-calls.d.ts +1 -1
- package/out/modules/ai-tools/index.js +1 -1
- package/out/modules/api/api.js +0 -1
- package/out/modules/auth-guard/handlers/verify.d.ts +1 -1
- package/out/modules/auth-guard/index.js +1 -1
- package/out/modules/automation-action/handlers/execute.d.ts +1 -1
- package/out/modules/automation-action/handlers/input-schema.d.ts +1 -1
- package/out/modules/automation-action/handlers/output-schema.d.ts +1 -1
- package/out/modules/automation-action/handlers/validate-settings.d.ts +1 -1
- package/out/modules/automation-action/index.js +1 -1
- package/out/modules/context-menu/index.js +2 -2
- package/out/modules/custom-mt/handlers/translate.d.ts +2 -2
- package/out/modules/custom-mt/handlers/translate.js +53 -4
- package/out/modules/custom-mt/index.js +6 -3
- package/out/modules/custom-mt/types.d.ts +14 -2
- package/out/modules/custom-spell-check/handlers/get-languages-list.d.ts +1 -1
- package/out/modules/custom-spell-check/handlers/spell-check.d.ts +1 -1
- package/out/modules/custom-spell-check/index.js +4 -4
- package/out/modules/editor-right-panel/index.js +1 -1
- package/out/modules/external-qa-check/handlers/validate.d.ts +1 -1
- package/out/modules/external-qa-check/index.js +2 -2
- package/out/modules/file-processing/handlers/custom-file-format.d.ts +7 -2
- package/out/modules/file-processing/handlers/custom-file-format.js +59 -19
- package/out/modules/file-processing/handlers/file-download.d.ts +1 -1
- package/out/modules/file-processing/handlers/file-download.js +5 -0
- package/out/modules/file-processing/handlers/pre-post-process.d.ts +1 -1
- package/out/modules/file-processing/handlers/pre-post-process.js +34 -14
- package/out/modules/file-processing/handlers/translations-alignment.d.ts +1 -1
- package/out/modules/file-processing/index.js +12 -2
- package/out/modules/file-processing/util/defaults.js +50 -6
- package/out/modules/file-processing/util/files.js +2 -1
- package/out/modules/form-data-display.d.ts +1 -1
- package/out/modules/form-data-save.d.ts +1 -1
- package/out/modules/install.d.ts +1 -1
- package/out/modules/integration/handlers/crowdin-file-progress.d.ts +1 -1
- package/out/modules/integration/handlers/crowdin-files.d.ts +1 -1
- package/out/modules/integration/handlers/crowdin-project.d.ts +1 -1
- package/out/modules/integration/handlers/crowdin-update.d.ts +1 -1
- package/out/modules/integration/handlers/crowdin-webhook.d.ts +1 -1
- package/out/modules/integration/handlers/integration-data.d.ts +1 -1
- package/out/modules/integration/handlers/integration-login.d.ts +1 -1
- package/out/modules/integration/handlers/integration-logout.d.ts +1 -1
- package/out/modules/integration/handlers/integration-update.d.ts +1 -1
- package/out/modules/integration/handlers/integration-webhook.d.ts +1 -1
- package/out/modules/integration/handlers/invite-users.d.ts +1 -1
- package/out/modules/integration/handlers/job-cancel.d.ts +1 -1
- package/out/modules/integration/handlers/job-info-deprecated.d.ts +1 -1
- package/out/modules/integration/handlers/job-info.d.ts +1 -1
- package/out/modules/integration/handlers/job-list.d.ts +1 -1
- package/out/modules/integration/handlers/main.d.ts +1 -1
- package/out/modules/integration/handlers/main.js +13 -1
- package/out/modules/integration/handlers/oauth-login.d.ts +1 -1
- package/out/modules/integration/handlers/oauth-login.js +12 -3
- package/out/modules/integration/handlers/oauth-polling.d.ts +2 -2
- package/out/modules/integration/handlers/oauth-polling.js +5 -3
- package/out/modules/integration/handlers/oauth-url.d.ts +1 -1
- package/out/modules/integration/handlers/settings-save.d.ts +1 -1
- package/out/modules/integration/handlers/settings.d.ts +1 -1
- package/out/modules/integration/handlers/sync-settings-save.d.ts +1 -1
- package/out/modules/integration/handlers/sync-settings-save.js +0 -2
- package/out/modules/integration/handlers/sync-settings.d.ts +1 -1
- package/out/modules/integration/handlers/user-errors.d.ts +1 -1
- package/out/modules/integration/handlers/users.d.ts +1 -1
- package/out/modules/integration/index.js +13 -34
- package/out/modules/integration/util/cron.js +1 -10
- package/out/modules/integration/util/defaults.js +31 -28
- package/out/modules/integration/util/files.js +18 -11
- package/out/modules/integration/util/job.js +0 -4
- package/out/modules/integration/util/snapshot.js +1 -5
- package/out/modules/integration/util/webhooks.js +1 -8
- package/out/modules/manifest.js +15 -13
- package/out/modules/modal/index.js +2 -2
- package/out/modules/organization-menu/index.js +5 -4
- package/out/modules/organization-settings-menu/index.js +5 -4
- package/out/modules/profile-resources-menu/index.js +5 -4
- package/out/modules/profile-settings-menu/index.js +5 -4
- package/out/modules/project-menu/index.js +1 -1
- package/out/modules/project-menu-crowdsource/index.js +1 -1
- package/out/modules/project-reports/index.js +3 -2
- package/out/modules/project-tools/index.js +3 -2
- package/out/modules/status.d.ts +1 -1
- package/out/modules/status.js +12 -3
- package/out/modules/subscription-paid.d.ts +1 -1
- package/out/modules/uninstall.d.ts +1 -1
- package/out/modules/webhooks/handlers/webhook-handler.d.ts +1 -1
- package/out/modules/webhooks/handlers/webhook-handler.js +30 -15
- package/out/modules/webhooks/types.d.ts +7 -0
- package/out/modules/workflow-step-type/handlers/delete-step.d.ts +1 -1
- package/out/modules/workflow-step-type/handlers/step-settings-save.d.ts +1 -1
- package/out/modules/workflow-step-type/index.js +2 -2
- package/out/storage/d1.d.ts +107 -0
- package/out/storage/d1.js +829 -0
- package/out/storage/index.js +8 -2
- package/out/storage/mysql.js +0 -3
- package/out/storage/postgre.js +0 -1
- package/out/storage/sqlite.js +0 -3
- package/out/types.d.ts +41 -2
- package/out/util/axios.js +0 -1
- package/out/util/credentials-masker.d.ts +1 -1
- package/out/util/cron.d.ts +29 -0
- package/out/util/cron.js +87 -0
- package/out/util/index.d.ts +12 -1
- package/out/util/index.js +54 -6
- package/out/util/jsx-renderer.d.ts +6 -0
- package/out/util/jsx-renderer.js +13 -0
- package/out/util/logger.js +0 -4
- package/out/util/static-files.d.ts +19 -0
- package/out/util/static-files.js +87 -0
- package/out/views/AboutPage.d.ts +10 -0
- package/out/views/AboutPage.js +76 -0
- package/out/views/ErrorPage.d.ts +18 -0
- package/out/views/ErrorPage.js +56 -0
- package/out/views/FormPage.d.ts +14 -0
- package/out/views/FormPage.js +28 -0
- package/out/views/InstallPage.d.ts +10 -0
- package/out/views/InstallPage.js +22 -0
- package/out/views/LoginPage.d.ts +33 -0
- package/out/views/LoginPage.js +200 -0
- package/out/views/MainPage.d.ts +81 -0
- package/out/views/MainPage.js +1784 -0
- package/out/views/OAuthPage.d.ts +7 -0
- package/out/views/OAuthPage.js +17 -0
- package/out/views/SubscriptionPage.d.ts +7 -0
- package/out/views/SubscriptionPage.js +26 -0
- package/out/views/index.d.ts +13 -0
- package/out/views/index.js +25 -0
- package/out/views/layout/Head.d.ts +9 -0
- package/out/views/layout/Head.js +54 -0
- package/package.json +33 -18
- package/out/util/handlebars.d.ts +0 -1
- package/out/util/handlebars.js +0 -46
- package/out/views/about.handlebars +0 -102
- package/out/views/error.handlebars +0 -54
- package/out/views/form.handlebars +0 -31
- package/out/views/install.handlebars +0 -16
- package/out/views/login.handlebars +0 -332
- package/out/views/main.handlebars +0 -2042
- package/out/views/oauth.handlebars +0 -11
- package/out/views/partials/head.handlebars +0 -53
- package/out/views/subscription.handlebars +0 -26
package/out/storage/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/* eslint-disable @typescript-eslint/camelcase */
|
|
3
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
3
|
if (k2 === undefined) k2 = k;
|
|
5
4
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -42,6 +41,7 @@ const logger_1 = require("../util/logger");
|
|
|
42
41
|
const mysql_1 = require("./mysql");
|
|
43
42
|
const postgre_1 = require("./postgre");
|
|
44
43
|
const sqlite_1 = require("./sqlite");
|
|
44
|
+
const d1_1 = require("./d1");
|
|
45
45
|
const path_1 = __importStar(require("path"));
|
|
46
46
|
const fs_1 = __importDefault(require("fs"));
|
|
47
47
|
const child_process_1 = require("child_process");
|
|
@@ -63,7 +63,13 @@ exports.TABLES = {
|
|
|
63
63
|
let storage;
|
|
64
64
|
function initialize(config) {
|
|
65
65
|
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
-
if (config.
|
|
66
|
+
if (config.d1Config) {
|
|
67
|
+
(0, logger_1.log)('Using Cloudflare D1 database');
|
|
68
|
+
storage = new d1_1.D1Storage(config.d1Config);
|
|
69
|
+
// Skip migration for D1 - it will be done lazily on first request
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
else if (config.postgreConfig) {
|
|
67
73
|
(0, logger_1.log)('Using PostgreSQL database');
|
|
68
74
|
let dumpDirectory = null;
|
|
69
75
|
if (config.migrateToPostgreFromSQLite) {
|
package/out/storage/mysql.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* eslint-disable no-unused-expressions */
|
|
3
|
-
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
4
|
-
/* eslint-disable @typescript-eslint/ban-ts-ignore */
|
|
5
|
-
/* eslint-disable @typescript-eslint/camelcase */
|
|
6
3
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
7
4
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
8
5
|
return new (P || (P = Promise))(function (resolve, reject) {
|
package/out/storage/postgre.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* eslint-disable no-unused-expressions */
|
|
3
|
-
/* eslint-disable @typescript-eslint/camelcase */
|
|
4
3
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
5
4
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
6
5
|
return new (P || (P = Promise))(function (resolve, reject) {
|
package/out/storage/sqlite.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/* eslint-disable @typescript-eslint/camelcase */
|
|
3
|
-
/* eslint-disable @typescript-eslint/ban-ts-ignore */
|
|
4
2
|
/* eslint-disable no-unused-expressions */
|
|
5
|
-
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
6
3
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
7
4
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
8
5
|
return new (P || (P = Promise))(function (resolve, reject) {
|
package/out/types.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
1
3
|
import Crowdin from '@crowdin/crowdin-api-client';
|
|
2
4
|
import { JwtPayload, VerifyOptions } from '@crowdin/crowdin-apps-functions';
|
|
3
5
|
import { Request } from 'express';
|
|
@@ -10,6 +12,8 @@ import { IntegrationLogic } from './modules/integration/types';
|
|
|
10
12
|
import { Storage } from './storage';
|
|
11
13
|
import { MySQLStorageConfig } from './storage/mysql';
|
|
12
14
|
import { PostgreStorageConfig } from './storage/postgre';
|
|
15
|
+
import { D1StorageConfig } from './storage/d1';
|
|
16
|
+
import type { Fetcher } from '@cloudflare/workers-types';
|
|
13
17
|
import { ApiModule } from './modules/api/types';
|
|
14
18
|
import { LogErrorFunction, LogFunction } from './util/logger';
|
|
15
19
|
import { AiProviderModule } from './modules/ai-provider/types';
|
|
@@ -21,6 +25,8 @@ import { WorkflowStepTypeModule } from './modules/workflow-step-type/types';
|
|
|
21
25
|
import { AiRequestProcessorModule, AiStreamProcessorModule } from './modules/ai-request-processors/types';
|
|
22
26
|
import { AutomationActionModule } from './modules/automation-action/types';
|
|
23
27
|
import { AuthGuardModule } from './modules/auth-guard/types';
|
|
28
|
+
import { Cron } from './util/cron';
|
|
29
|
+
export { Cron };
|
|
24
30
|
export interface ClientConfig extends ImagePath {
|
|
25
31
|
/**
|
|
26
32
|
* Authentication Crowdin App type: "authorization_code", "crowdin_app", "crowdin_agent". Default: "crowdin_app"
|
|
@@ -102,6 +108,20 @@ export interface ClientConfig extends ImagePath {
|
|
|
102
108
|
* config to configure MySQL as a storage
|
|
103
109
|
*/
|
|
104
110
|
mysqlConfig?: MySQLStorageConfig;
|
|
111
|
+
/**
|
|
112
|
+
* config to configure Cloudflare D1 as a storage
|
|
113
|
+
*/
|
|
114
|
+
d1Config?: D1StorageConfig;
|
|
115
|
+
/**
|
|
116
|
+
* Custom cron for scheduling background jobs.
|
|
117
|
+
* If not provided, the default node-cron will be used.
|
|
118
|
+
* Useful for external cron systems like Cloudflare Workers Scheduled Events.
|
|
119
|
+
*/
|
|
120
|
+
cron?: Cron;
|
|
121
|
+
/**
|
|
122
|
+
* Cloudflare Workers Assets configuration
|
|
123
|
+
*/
|
|
124
|
+
assetsConfig?: AssetsConfig;
|
|
105
125
|
/**
|
|
106
126
|
* integration module logic
|
|
107
127
|
*/
|
|
@@ -277,13 +297,27 @@ export interface ClientConfig extends ImagePath {
|
|
|
277
297
|
* Auth guard module for custom authentication/authorization checks
|
|
278
298
|
*/
|
|
279
299
|
authGuard?: AuthGuardModule | AuthGuardModule[];
|
|
300
|
+
/**
|
|
301
|
+
* custom file storage
|
|
302
|
+
*/
|
|
303
|
+
fileStore?: FileStore;
|
|
304
|
+
/**
|
|
305
|
+
* path to assets files directory (default: 'static')
|
|
306
|
+
*/
|
|
307
|
+
assetsPath?: string;
|
|
308
|
+
}
|
|
309
|
+
export interface AssetsConfig {
|
|
310
|
+
/**
|
|
311
|
+
* Cloudflare Workers Assets Fetcher
|
|
312
|
+
*/
|
|
313
|
+
fetcher: Fetcher;
|
|
280
314
|
}
|
|
281
315
|
export interface Environments {
|
|
282
316
|
environments?: Environment | Environment[];
|
|
283
317
|
}
|
|
284
318
|
type Environment = 'crowdin' | 'crowdin-enterprise';
|
|
285
319
|
export type Config = ClientConfig & {
|
|
286
|
-
baseUrl
|
|
320
|
+
baseUrl?: string;
|
|
287
321
|
clientId: string;
|
|
288
322
|
clientSecret: string;
|
|
289
323
|
port: number;
|
|
@@ -408,6 +442,7 @@ export interface CrowdinAppUtilities extends CrowdinMetadataStore {
|
|
|
408
442
|
extra: Record<string, any>;
|
|
409
443
|
}>;
|
|
410
444
|
storage: Storage;
|
|
445
|
+
cron: Cron;
|
|
411
446
|
}
|
|
412
447
|
export interface CrowdinMetadataStore {
|
|
413
448
|
saveMetadata: (id: string, metadata: any, crowdinId: string) => Promise<void>;
|
|
@@ -522,4 +557,8 @@ export interface ModalModule extends ModuleContent, UiModule, Environments {
|
|
|
522
557
|
}
|
|
523
558
|
export interface ContextModule extends ContextContent, UiModule, Environments {
|
|
524
559
|
}
|
|
525
|
-
export {
|
|
560
|
+
export interface FileStore {
|
|
561
|
+
getFile: (fileRef: string) => Promise<Buffer>;
|
|
562
|
+
storeFile: (content: Buffer) => Promise<string>;
|
|
563
|
+
deleteFile: (fileRef: string) => Promise<void>;
|
|
564
|
+
}
|
package/out/util/axios.js
CHANGED
|
@@ -19,7 +19,6 @@ class AxiosProvider {
|
|
|
19
19
|
}
|
|
20
20
|
configureRequest() {
|
|
21
21
|
this.axios.interceptors.request.use((config) => {
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
23
22
|
return new Promise((resolve) => {
|
|
24
23
|
const interval = setInterval(() => {
|
|
25
24
|
if (this.pendingRequests < AxiosProvider.CROWDIN_API_MAX_CONCURRENT_REQUESTS) {
|
|
@@ -6,5 +6,5 @@ declare function getRequestCredentialsMasker({ moduleConfig, dataPath, }: {
|
|
|
6
6
|
moduleConfig?: UiModule;
|
|
7
7
|
dataPath?: string;
|
|
8
8
|
}): (req: Request | CrowdinClientRequest, res: Response, next: Function) => any;
|
|
9
|
-
declare function postRequestCredentialsMasker(moduleConfig?: UiModule, credentialsExtractor?: Function): (req:
|
|
9
|
+
declare function postRequestCredentialsMasker(moduleConfig?: UiModule, credentialsExtractor?: Function): (req: Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
|
|
10
10
|
export { getRequestCredentialsMasker, postRequestCredentialsMasker, maskKey };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Config, UnauthorizedConfig } from '../types';
|
|
2
|
+
export interface Cron {
|
|
3
|
+
/**
|
|
4
|
+
* Schedule a task to run on a cron expression
|
|
5
|
+
* @param expression - Cron expression (e.g., '0 * * * *' for hourly)
|
|
6
|
+
* @param task - Async task to execute
|
|
7
|
+
*/
|
|
8
|
+
schedule(expression: string, task: () => Promise<void>): void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Default Node.js cron handler that uses node-cron
|
|
12
|
+
*/
|
|
13
|
+
export declare class NodeCron implements Cron {
|
|
14
|
+
private cron;
|
|
15
|
+
private pendingSchedules;
|
|
16
|
+
private initialized;
|
|
17
|
+
constructor();
|
|
18
|
+
schedule(expression: string, task: () => Promise<void>): void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Initialize the cron instance
|
|
22
|
+
* @param config - Client configuration
|
|
23
|
+
*/
|
|
24
|
+
export declare function initialize(config: Config | UnauthorizedConfig): void;
|
|
25
|
+
/**
|
|
26
|
+
* Get the initialized cron instance
|
|
27
|
+
* @returns The cron instance
|
|
28
|
+
*/
|
|
29
|
+
export declare function getCron(): Cron;
|
package/out/util/cron.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
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.getCron = exports.initialize = exports.NodeCron = void 0;
|
|
27
|
+
const logger_1 = require("./logger");
|
|
28
|
+
/**
|
|
29
|
+
* Default Node.js cron handler that uses node-cron
|
|
30
|
+
*/
|
|
31
|
+
class NodeCron {
|
|
32
|
+
constructor() {
|
|
33
|
+
this.pendingSchedules = [];
|
|
34
|
+
this.initialized = false;
|
|
35
|
+
// Dynamically import node-cron
|
|
36
|
+
Promise.resolve().then(() => __importStar(require('node-cron'))).then((nodeCron) => {
|
|
37
|
+
this.cron = nodeCron.default || nodeCron;
|
|
38
|
+
this.initialized = true;
|
|
39
|
+
// Schedule all pending tasks
|
|
40
|
+
this.pendingSchedules.forEach(({ expression, task }) => {
|
|
41
|
+
this.cron.schedule(expression, task);
|
|
42
|
+
});
|
|
43
|
+
this.pendingSchedules = [];
|
|
44
|
+
})
|
|
45
|
+
.catch((error) => {
|
|
46
|
+
console.error('Failed to load node-cron:', error);
|
|
47
|
+
throw new Error('node-cron is required for the default cron. Please install it or provide a custom cron in config.');
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
schedule(expression, task) {
|
|
51
|
+
if (this.initialized && this.cron) {
|
|
52
|
+
this.cron.schedule(expression, task);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// Queue the task until node-cron is loaded
|
|
56
|
+
this.pendingSchedules.push({ expression, task });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.NodeCron = NodeCron;
|
|
61
|
+
let cron;
|
|
62
|
+
/**
|
|
63
|
+
* Initialize the cron instance
|
|
64
|
+
* @param config - Client configuration
|
|
65
|
+
*/
|
|
66
|
+
function initialize(config) {
|
|
67
|
+
if (config.cron) {
|
|
68
|
+
(0, logger_1.log)('Using custom cron implementation');
|
|
69
|
+
cron = config.cron;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
(0, logger_1.log)('Using default NodeCron implementation');
|
|
73
|
+
cron = new NodeCron();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.initialize = initialize;
|
|
77
|
+
/**
|
|
78
|
+
* Get the initialized cron instance
|
|
79
|
+
* @returns The cron instance
|
|
80
|
+
*/
|
|
81
|
+
function getCron() {
|
|
82
|
+
if (!cron) {
|
|
83
|
+
throw new Error('Cron not initialized');
|
|
84
|
+
}
|
|
85
|
+
return cron;
|
|
86
|
+
}
|
|
87
|
+
exports.getCron = getCron;
|
package/out/util/index.d.ts
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
import { Request, Response } from 'express';
|
|
2
2
|
import { Config, CrowdinClientRequest, ImagePath, UnauthorizedConfig } from '../types';
|
|
3
|
+
export { renderJSX } from './jsx-renderer';
|
|
3
4
|
export declare class CodeError extends Error {
|
|
4
5
|
code: number | undefined;
|
|
5
6
|
constructor(message: string, code?: number);
|
|
6
7
|
}
|
|
8
|
+
export declare function extractBaseUrlFromRequest(req: Request): string;
|
|
7
9
|
export declare function runAsyncWrapper(callback: Function): (req: Request | CrowdinClientRequest, res: Response, next: Function) => void;
|
|
8
10
|
export declare function encryptData(config: Config, data: string): string;
|
|
9
11
|
export declare function decryptData(config: Config, data: string): string;
|
|
10
12
|
export declare function executeWithRetry<T>(func: () => Promise<T>, numOfRetries?: number): Promise<T>;
|
|
11
|
-
export declare function getLogoUrl(moduleConfig?: ImagePath, modulePath?: string): string;
|
|
13
|
+
export declare function getLogoUrl(config: Config | UnauthorizedConfig, moduleConfig?: ImagePath, modulePath?: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Logo middleware with backwards compatibility
|
|
16
|
+
* Serves both /logo.png (backwards-compatible) and actual file name
|
|
17
|
+
* @param config - App configuration (required for Cloudflare Workers Assets support)
|
|
18
|
+
* @param moduleConfig - Module configuration with imagePath (optional, falls back to config.imagePath)
|
|
19
|
+
* @returns Express middleware
|
|
20
|
+
*/
|
|
21
|
+
export declare function serveLogo(config: Config | UnauthorizedConfig, moduleConfig?: ImagePath): (req: Request, res: Response, next: Function) => Promise<void>;
|
|
12
22
|
export declare function isAuthorizedConfig(config: Config | UnauthorizedConfig): config is Config;
|
|
13
23
|
export declare function isJson(string: string): boolean;
|
|
24
|
+
export declare function isDefined(value: any): boolean;
|
|
14
25
|
export declare function getPreviousDate(days: number): Date;
|
|
15
26
|
export declare function prepareFormDataMetadataId(req: CrowdinClientRequest, config: Config): Promise<string>;
|
|
16
27
|
export declare function validateEmail(email: string | number): boolean;
|
package/out/util/index.js
CHANGED
|
@@ -32,12 +32,25 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
32
32
|
});
|
|
33
33
|
};
|
|
34
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
-
exports.getFormattedDate = exports.validateEmail = exports.prepareFormDataMetadataId = exports.getPreviousDate = exports.isJson = exports.isAuthorizedConfig = exports.getLogoUrl = exports.executeWithRetry = exports.decryptData = exports.encryptData = exports.runAsyncWrapper = exports.CodeError = void 0;
|
|
35
|
+
exports.getFormattedDate = exports.validateEmail = exports.prepareFormDataMetadataId = exports.getPreviousDate = exports.isDefined = exports.isJson = exports.isAuthorizedConfig = exports.serveLogo = exports.getLogoUrl = exports.executeWithRetry = exports.decryptData = exports.encryptData = exports.runAsyncWrapper = exports.extractBaseUrlFromRequest = exports.CodeError = exports.renderJSX = void 0;
|
|
36
36
|
const crypto = __importStar(require("crypto-js"));
|
|
37
37
|
const storage_1 = require("../storage");
|
|
38
38
|
const types_1 = require("../types");
|
|
39
39
|
const logger_1 = require("./logger");
|
|
40
40
|
const crowdin_apps_functions_1 = require("@crowdin/crowdin-apps-functions");
|
|
41
|
+
const jsx_renderer_1 = require("./jsx-renderer");
|
|
42
|
+
const views_1 = require("../views");
|
|
43
|
+
const static_files_1 = require("./static-files");
|
|
44
|
+
var jsx_renderer_2 = require("./jsx-renderer");
|
|
45
|
+
Object.defineProperty(exports, "renderJSX", { enumerable: true, get: function () { return jsx_renderer_2.renderJSX; } });
|
|
46
|
+
/**
|
|
47
|
+
* Extract file name from path (works in both Node.js and Cloudflare Workers)
|
|
48
|
+
* Supports both Unix (/) and Windows (\) path separators
|
|
49
|
+
*/
|
|
50
|
+
function basename(filePath) {
|
|
51
|
+
// Replace all backslashes with forward slashes, then get the last segment
|
|
52
|
+
return filePath.replace(/\\/g, '/').split('/').pop();
|
|
53
|
+
}
|
|
41
54
|
class CodeError extends Error {
|
|
42
55
|
constructor(message, code) {
|
|
43
56
|
super(message);
|
|
@@ -45,6 +58,12 @@ class CodeError extends Error {
|
|
|
45
58
|
}
|
|
46
59
|
}
|
|
47
60
|
exports.CodeError = CodeError;
|
|
61
|
+
function extractBaseUrlFromRequest(req) {
|
|
62
|
+
const protocol = req.protocol;
|
|
63
|
+
const host = req.get('host');
|
|
64
|
+
return `${protocol}://${host}`;
|
|
65
|
+
}
|
|
66
|
+
exports.extractBaseUrlFromRequest = extractBaseUrlFromRequest;
|
|
48
67
|
function isCrowdinClientRequest(req) {
|
|
49
68
|
return req.crowdinContext;
|
|
50
69
|
}
|
|
@@ -61,7 +80,9 @@ function handleError(err, req, res) {
|
|
|
61
80
|
if (!res.headersSent) {
|
|
62
81
|
const errorMessage = { message: (0, logger_1.getErrorMessage)(err), code };
|
|
63
82
|
if ('integrationCredentials' in req) {
|
|
64
|
-
|
|
83
|
+
const html = (0, jsx_renderer_1.renderJSX)(views_1.ErrorPage, errorMessage);
|
|
84
|
+
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
85
|
+
res.send(html);
|
|
65
86
|
}
|
|
66
87
|
else {
|
|
67
88
|
res.status(code).send({ error: errorMessage });
|
|
@@ -108,13 +129,36 @@ function executeWithRetry(func, numOfRetries = 2) {
|
|
|
108
129
|
});
|
|
109
130
|
}
|
|
110
131
|
exports.executeWithRetry = executeWithRetry;
|
|
111
|
-
function getLogoUrl(moduleConfig, modulePath) {
|
|
112
|
-
|
|
113
|
-
|
|
132
|
+
function getLogoUrl(config, moduleConfig, modulePath) {
|
|
133
|
+
// Extract file name from imagePath with fallback to config.imagePath
|
|
134
|
+
const imagePath = (moduleConfig === null || moduleConfig === void 0 ? void 0 : moduleConfig.imagePath) || config.imagePath;
|
|
135
|
+
const fileName = basename(imagePath);
|
|
136
|
+
if (!modulePath) {
|
|
137
|
+
return `/${fileName}`;
|
|
114
138
|
}
|
|
115
|
-
return `/logo${modulePath}
|
|
139
|
+
return `/logo${modulePath}/${fileName}`;
|
|
116
140
|
}
|
|
117
141
|
exports.getLogoUrl = getLogoUrl;
|
|
142
|
+
/**
|
|
143
|
+
* Logo middleware with backwards compatibility
|
|
144
|
+
* Serves both /logo.png (backwards-compatible) and actual file name
|
|
145
|
+
* @param config - App configuration (required for Cloudflare Workers Assets support)
|
|
146
|
+
* @param moduleConfig - Module configuration with imagePath (optional, falls back to config.imagePath)
|
|
147
|
+
* @returns Express middleware
|
|
148
|
+
*/
|
|
149
|
+
function serveLogo(config, moduleConfig) {
|
|
150
|
+
const imagePath = (moduleConfig === null || moduleConfig === void 0 ? void 0 : moduleConfig.imagePath) || config.imagePath;
|
|
151
|
+
const fileName = basename(imagePath);
|
|
152
|
+
const fileHandler = (0, static_files_1.serveFile)(config, imagePath);
|
|
153
|
+
return (req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
154
|
+
// Match exact paths: /logo.png (backwards-compatible) or /{actual-file-name}
|
|
155
|
+
if (req.path === '/logo.png' || req.path === `/${fileName}`) {
|
|
156
|
+
return fileHandler(req, res, next);
|
|
157
|
+
}
|
|
158
|
+
next();
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
exports.serveLogo = serveLogo;
|
|
118
162
|
function isAuthorizedConfig(config) {
|
|
119
163
|
return !!config.clientId && !!config.clientSecret && config.authenticationType !== types_1.AuthenticationType.NONE;
|
|
120
164
|
}
|
|
@@ -129,6 +173,10 @@ function isJson(string) {
|
|
|
129
173
|
return true;
|
|
130
174
|
}
|
|
131
175
|
exports.isJson = isJson;
|
|
176
|
+
function isDefined(value) {
|
|
177
|
+
return value !== undefined && value !== null;
|
|
178
|
+
}
|
|
179
|
+
exports.isDefined = isDefined;
|
|
132
180
|
function getPreviousDate(days) {
|
|
133
181
|
const date = new Date();
|
|
134
182
|
date.setDate(date.getDate() - days);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderJSX = void 0;
|
|
4
|
+
const server_1 = require("react-dom/server");
|
|
5
|
+
/**
|
|
6
|
+
* Renders a React component to HTML string
|
|
7
|
+
* Uses React Server-Side Rendering (renderToStaticMarkup)
|
|
8
|
+
*/
|
|
9
|
+
function renderJSX(Component, props) {
|
|
10
|
+
const element = Component(props);
|
|
11
|
+
return '<!DOCTYPE html>' + (0, server_1.renderToStaticMarkup)(element);
|
|
12
|
+
}
|
|
13
|
+
exports.renderJSX = renderJSX;
|
package/out/util/logger.js
CHANGED
|
@@ -73,9 +73,7 @@ function log(message, context) {
|
|
|
73
73
|
project: {
|
|
74
74
|
id: context.jwtPayload.context.project_id,
|
|
75
75
|
identifier: (_a = context.jwtPayload.context.project_identifier) !== null && _a !== void 0 ? _a : '',
|
|
76
|
-
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
77
76
|
organization_id: context.jwtPayload.context.organization_id,
|
|
78
|
-
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
79
77
|
user_id: context.jwtPayload.context.user_id,
|
|
80
78
|
},
|
|
81
79
|
user: {
|
|
@@ -108,9 +106,7 @@ function logError(e, context) {
|
|
|
108
106
|
project: {
|
|
109
107
|
id: context.jwtPayload.context.project_id,
|
|
110
108
|
identifier: (_a = context.jwtPayload.context.project_identifier) !== null && _a !== void 0 ? _a : '',
|
|
111
|
-
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
112
109
|
organization_id: context.jwtPayload.context.organization_id,
|
|
113
|
-
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
114
110
|
user_id: context.jwtPayload.context.user_id,
|
|
115
111
|
},
|
|
116
112
|
user: {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static Files Abstraction Layer
|
|
3
|
+
* Dual compatibility: Node.js (Express) + Cloudflare Workers (Assets Fetcher)
|
|
4
|
+
*/
|
|
5
|
+
/// <reference types="serve-static" />
|
|
6
|
+
import express, { Request, Response } from 'express';
|
|
7
|
+
import { Config, UnauthorizedConfig } from '../types';
|
|
8
|
+
/**
|
|
9
|
+
* Serve static directory with dual compatibility
|
|
10
|
+
* @param config - App configuration
|
|
11
|
+
* @param staticPath - Path to static directory
|
|
12
|
+
*/
|
|
13
|
+
export declare function serveStatic(config: Config | UnauthorizedConfig, staticPath: string): ((req: Request, res: Response, next: Function) => Promise<void>) | import("serve-static").RequestHandler<express.Response<any, Record<string, any>>>;
|
|
14
|
+
/**
|
|
15
|
+
* Serve single file (e.g., logo.png, icons/star.svg) with dual compatibility
|
|
16
|
+
* @param config - App configuration
|
|
17
|
+
* @param filePath - Path to file
|
|
18
|
+
*/
|
|
19
|
+
export declare function serveFile(config: Config | UnauthorizedConfig, filePath: string): (req: Request, res: Response, next: Function) => Promise<void>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Static Files Abstraction Layer
|
|
4
|
+
* Dual compatibility: Node.js (Express) + Cloudflare Workers (Assets Fetcher)
|
|
5
|
+
*/
|
|
6
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
7
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
8
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
9
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
10
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
11
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
12
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
16
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.serveFile = exports.serveStatic = void 0;
|
|
20
|
+
const express_1 = __importDefault(require("express"));
|
|
21
|
+
const path_1 = __importDefault(require("path"));
|
|
22
|
+
/**
|
|
23
|
+
* Proxy Workers Assets response to Express response
|
|
24
|
+
*/
|
|
25
|
+
function proxyAssetsResponse(fetcher, assetPath, baseUrl, req, res, next) {
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
try {
|
|
28
|
+
if (assetPath === '/') {
|
|
29
|
+
return next();
|
|
30
|
+
}
|
|
31
|
+
const assetUrl = new URL(assetPath, baseUrl);
|
|
32
|
+
const response = yield fetcher.fetch(assetUrl.toString());
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
return next();
|
|
35
|
+
}
|
|
36
|
+
const body = yield response.arrayBuffer();
|
|
37
|
+
const contentType = response.headers.get('content-type');
|
|
38
|
+
if (contentType) {
|
|
39
|
+
res.setHeader('Content-Type', contentType);
|
|
40
|
+
}
|
|
41
|
+
res.send(Buffer.from(body));
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
next(err);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Serve static directory with dual compatibility
|
|
50
|
+
* @param config - App configuration
|
|
51
|
+
* @param staticPath - Path to static directory
|
|
52
|
+
*/
|
|
53
|
+
function serveStatic(config, staticPath) {
|
|
54
|
+
var _a;
|
|
55
|
+
if ((_a = config.assetsConfig) === null || _a === void 0 ? void 0 : _a.fetcher) {
|
|
56
|
+
const assetsFetcher = config.assetsConfig.fetcher;
|
|
57
|
+
return (req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
const assetPath = `/${staticPath}/${req.path}`.replace(/\/+/g, '/');
|
|
59
|
+
yield proxyAssetsResponse(assetsFetcher, assetPath, config.baseUrl, req, res, next);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
const rootDir = path_1.default.dirname(__dirname);
|
|
63
|
+
const absolutePath = path_1.default.isAbsolute(staticPath) ? staticPath : path_1.default.join(rootDir, staticPath);
|
|
64
|
+
return express_1.default.static(absolutePath);
|
|
65
|
+
}
|
|
66
|
+
exports.serveStatic = serveStatic;
|
|
67
|
+
/**
|
|
68
|
+
* Serve single file (e.g., logo.png, icons/star.svg) with dual compatibility
|
|
69
|
+
* @param config - App configuration
|
|
70
|
+
* @param filePath - Path to file
|
|
71
|
+
*/
|
|
72
|
+
function serveFile(config, filePath) {
|
|
73
|
+
return (req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
var _a;
|
|
75
|
+
if ((_a = config.assetsConfig) === null || _a === void 0 ? void 0 : _a.fetcher) {
|
|
76
|
+
const assetsFetcher = config.assetsConfig.fetcher;
|
|
77
|
+
const assetPath = filePath.startsWith('/') ? filePath : `/${filePath}`;
|
|
78
|
+
yield proxyAssetsResponse(assetsFetcher, assetPath, config.baseUrl, req, res, next);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
const rootDir = path_1.default.dirname(__dirname);
|
|
82
|
+
const absolutePath = path_1.default.isAbsolute(filePath) ? filePath : path_1.default.join(rootDir, filePath);
|
|
83
|
+
res.sendFile(absolutePath);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
exports.serveFile = serveFile;
|