@crowdin/app-project-module 0.98.0-cf-12 → 0.98.0-cf-13
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 -4
- package/out/modules/integration/index.d.ts +1 -3
- package/out/modules/integration/index.js +23 -59
- package/out/types.d.ts +9 -2
- package/out/util/cron.d.ts +29 -0
- package/out/util/cron.js +87 -0
- package/package.json +1 -1
package/out/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import express from './util/terminus-express';
|
|
|
4
4
|
import { getRequestCredentialsMasker, postRequestCredentialsMasker, maskKey } from './util/credentials-masker';
|
|
5
5
|
export { getRequestCredentialsMasker, postRequestCredentialsMasker, maskKey };
|
|
6
6
|
export { ProjectPermissions, Scope, UserPermissions } from './types';
|
|
7
|
+
export { Cron } from './util/cron';
|
|
7
8
|
export { express };
|
|
8
9
|
export declare const metadataStore: CrowdinMetadataStore;
|
|
9
10
|
export declare function createApp(clientConfig: ClientConfig): void;
|
package/out/index.js
CHANGED
|
@@ -51,6 +51,7 @@ const uninstall_1 = __importDefault(require("./modules/uninstall"));
|
|
|
51
51
|
const status_1 = __importDefault(require("./modules/status"));
|
|
52
52
|
const storage = __importStar(require("./storage"));
|
|
53
53
|
const d1_1 = require("./storage/d1");
|
|
54
|
+
const cron = __importStar(require("./util/cron"));
|
|
54
55
|
const types_1 = require("./types");
|
|
55
56
|
const util_1 = require("./util");
|
|
56
57
|
const form_schema_1 = require("./util/form-schema");
|
|
@@ -139,6 +140,7 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
139
140
|
}
|
|
140
141
|
storage.initialize(config);
|
|
141
142
|
logger.initialize(config);
|
|
143
|
+
cron.initialize(config);
|
|
142
144
|
// Middleware to ensure D1 migration before handling requests
|
|
143
145
|
app.use((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
144
146
|
try {
|
|
@@ -208,7 +210,7 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
208
210
|
contextMenuApp.register({ config, app });
|
|
209
211
|
//other apps only work in authorized context
|
|
210
212
|
if (!(0, util_1.isAuthorizedConfig)(config)) {
|
|
211
|
-
return Object.assign({}, exports.metadataStore);
|
|
213
|
+
return Object.assign(Object.assign({}, exports.metadataStore), { cron: cron.getCron() });
|
|
212
214
|
}
|
|
213
215
|
app.post('/installed', (0, install_1.default)(config));
|
|
214
216
|
app.post('/uninstall', (0, uninstall_1.default)(config));
|
|
@@ -221,7 +223,7 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
221
223
|
* /util -> folder for utilities
|
|
222
224
|
* /handlers -> for http handlers
|
|
223
225
|
*/
|
|
224
|
-
|
|
226
|
+
integrationApp.register({ config, app });
|
|
225
227
|
customMTApp.register({ config, app });
|
|
226
228
|
fileProcessingApps.registerCustomFileFormat({ config, app });
|
|
227
229
|
fileProcessingApps.registerFilePreImport({ config, app });
|
|
@@ -238,8 +240,7 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
238
240
|
workflowStepType.register({ config, app });
|
|
239
241
|
aiRequestProcessors.register({ config, app });
|
|
240
242
|
addFormSchema({ config, app });
|
|
241
|
-
return Object.assign(Object.assign({}, exports.metadataStore), {
|
|
242
|
-
cronExecutions, storage: storage.getStorage(), establishCrowdinConnection: (authRequest, moduleKey) => {
|
|
243
|
+
return Object.assign(Object.assign({}, exports.metadataStore), { storage: storage.getStorage(), cron: cron.getCron(), establishCrowdinConnection: (authRequest, moduleKey) => {
|
|
243
244
|
let jwtToken = '';
|
|
244
245
|
if (typeof authRequest === 'string') {
|
|
245
246
|
jwtToken = authRequest;
|
|
@@ -1,27 +1,4 @@
|
|
|
1
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
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -41,6 +18,7 @@ const integration_credentials_1 = __importDefault(require("../../middlewares/int
|
|
|
41
18
|
const json_response_1 = __importDefault(require("../../middlewares/json-response"));
|
|
42
19
|
const util_1 = require("../../util");
|
|
43
20
|
const static_files_1 = require("../../util/static-files");
|
|
21
|
+
const cron_1 = require("../../util/cron");
|
|
44
22
|
const defaults_1 = require("./util/defaults");
|
|
45
23
|
const webhooks_1 = require("./util/webhooks");
|
|
46
24
|
const crowdin_file_progress_1 = __importDefault(require("./handlers/crowdin-file-progress"));
|
|
@@ -66,14 +44,13 @@ const sync_settings_save_1 = __importDefault(require("./handlers/sync-settings-s
|
|
|
66
44
|
const user_errors_1 = __importDefault(require("./handlers/user-errors"));
|
|
67
45
|
const users_1 = __importDefault(require("./handlers/users"));
|
|
68
46
|
const invite_users_1 = __importDefault(require("./handlers/invite-users"));
|
|
69
|
-
const
|
|
47
|
+
const cron_2 = require("./util/cron");
|
|
70
48
|
const storage_1 = require("../../storage");
|
|
71
49
|
function register({ config, app }) {
|
|
72
50
|
var _a, _b, _c;
|
|
73
|
-
let cronExecutions = {};
|
|
74
51
|
const integrationLogic = config.projectIntegration;
|
|
75
52
|
if (!integrationLogic) {
|
|
76
|
-
return
|
|
53
|
+
return;
|
|
77
54
|
}
|
|
78
55
|
(0, defaults_1.applyIntegrationModuleDefaults)(config, integrationLogic);
|
|
79
56
|
app.get((0, util_1.getLogoUrl)(integrationLogic, '/integration'), (0, static_files_1.serveFile)(config, integrationLogic.imagePath || config.imagePath));
|
|
@@ -184,39 +161,27 @@ function register({ config, app }) {
|
|
|
184
161
|
}), (0, oauth_polling_1.default)(integrationLogic));
|
|
185
162
|
}
|
|
186
163
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
164
|
+
const cron = (0, cron_1.getCron)();
|
|
165
|
+
if (integrationLogic.cronJobs) {
|
|
166
|
+
integrationLogic.cronJobs.forEach((job) => {
|
|
167
|
+
cron.schedule(job.expression, () => (0, cron_2.runJob)({ config, integration: integrationLogic, job }).catch(console.error));
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
if (integrationLogic.withCronSync) {
|
|
171
|
+
cron.schedule('0 * * * *', () => (0, cron_2.filesCron)({ config, integration: integrationLogic, period: '1' }).catch(console.error));
|
|
172
|
+
cron.schedule('0 */3 * * *', () => (0, cron_2.filesCron)({ config, integration: integrationLogic, period: '3' }).catch(console.error));
|
|
173
|
+
cron.schedule('0 */6 * * *', () => (0, cron_2.filesCron)({ config, integration: integrationLogic, period: '6' }).catch(console.error));
|
|
174
|
+
cron.schedule('0 */12 * * *', () => (0, cron_2.filesCron)({ config, integration: integrationLogic, period: '12' }).catch(console.error));
|
|
175
|
+
cron.schedule('0 0 * * *', () => (0, cron_2.filesCron)({ config, integration: integrationLogic, period: '24' }).catch(console.error));
|
|
176
|
+
}
|
|
177
|
+
// remove user errors
|
|
178
|
+
cron.schedule('0 0 * * *', () => __awaiter(this, void 0, void 0, function* () {
|
|
179
|
+
if (integrationLogic.userErrorLifetimeDays) {
|
|
180
|
+
const date = (0, util_1.getPreviousDate)(integrationLogic.userErrorLifetimeDays);
|
|
181
|
+
yield (0, storage_1.getStorage)().deleteAllUsersErrorsOlderThan(`${date.getTime()}`);
|
|
200
182
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
if (integrationLogic.userErrorLifetimeDays) {
|
|
204
|
-
const date = (0, util_1.getPreviousDate)(integrationLogic.userErrorLifetimeDays);
|
|
205
|
-
yield (0, storage_1.getStorage)().deleteAllUsersErrorsOlderThan(`${date.getTime()}`);
|
|
206
|
-
}
|
|
207
|
-
}));
|
|
208
|
-
cron.schedule('0 0 1 * *', () => (0, cron_1.removeFinishedJobs)());
|
|
209
|
-
})
|
|
210
|
-
.catch(() => {
|
|
211
|
-
// node-cron not available (e.g., Cloudflare Workers), delegating to external cron handler
|
|
212
|
-
cronExecutions = {
|
|
213
|
-
'0 * * * *': (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '1' }).catch(console.error),
|
|
214
|
-
'0 */3 * * *': (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '3' }).catch(console.error),
|
|
215
|
-
'0 */6 * * *': (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '6' }).catch(console.error),
|
|
216
|
-
'0 */12 * * *': (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '12' }).catch(console.error),
|
|
217
|
-
'0 0 * * *': (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '24' }).catch(console.error),
|
|
218
|
-
};
|
|
219
|
-
});
|
|
183
|
+
}));
|
|
184
|
+
cron.schedule('0 0 1 * *', () => (0, cron_2.removeFinishedJobs)());
|
|
220
185
|
if (integrationLogic.webhooks) {
|
|
221
186
|
app.post(`${integrationLogic.webhooks.crowdinWebhookUrl
|
|
222
187
|
? integrationLogic.webhooks.crowdinWebhookUrl
|
|
@@ -253,6 +218,5 @@ function register({ config, app }) {
|
|
|
253
218
|
checkSubscriptionExpiration: true,
|
|
254
219
|
moduleKey: integrationLogic.key,
|
|
255
220
|
}), (0, integration_credentials_1.default)(config, integrationLogic), (0, invite_users_1.default)());
|
|
256
|
-
return { cronExecutions };
|
|
257
221
|
}
|
|
258
222
|
exports.register = register;
|
package/out/types.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ import { ExternalQaCheckModule } from './modules/external-qa-check/types';
|
|
|
23
23
|
import { Webhook } from './modules/webhooks/types';
|
|
24
24
|
import { WorkflowStepTypeModule } from './modules/workflow-step-type/types';
|
|
25
25
|
import { AiRequestProcessorModule, AiStreamProcessorModule } from './modules/ai-request-processors/types';
|
|
26
|
+
import { Cron } from './util/cron';
|
|
27
|
+
export { Cron };
|
|
26
28
|
export interface ClientConfig extends ImagePath {
|
|
27
29
|
/**
|
|
28
30
|
* Authentication Crowdin App type: "authorization_code", "crowdin_app", "crowdin_agent". Default: "crowdin_app"
|
|
@@ -108,6 +110,12 @@ export interface ClientConfig extends ImagePath {
|
|
|
108
110
|
* config to configure Cloudflare D1 as a storage
|
|
109
111
|
*/
|
|
110
112
|
d1Config?: D1StorageConfig;
|
|
113
|
+
/**
|
|
114
|
+
* Custom cron for scheduling background jobs.
|
|
115
|
+
* If not provided, the default node-cron will be used.
|
|
116
|
+
* Useful for external cron systems like Cloudflare Workers Scheduled Events.
|
|
117
|
+
*/
|
|
118
|
+
cron?: Cron;
|
|
111
119
|
/**
|
|
112
120
|
* Cloudflare Workers Assets configuration
|
|
113
121
|
*/
|
|
@@ -414,7 +422,7 @@ export interface CrowdinAppUtilities extends CrowdinMetadataStore {
|
|
|
414
422
|
extra: Record<string, any>;
|
|
415
423
|
}>;
|
|
416
424
|
storage: Storage;
|
|
417
|
-
|
|
425
|
+
cron: Cron;
|
|
418
426
|
}
|
|
419
427
|
export interface CrowdinMetadataStore {
|
|
420
428
|
saveMetadata: (id: string, metadata: any, crowdinId: string) => Promise<void>;
|
|
@@ -529,4 +537,3 @@ export interface FileStore {
|
|
|
529
537
|
storeFile: (content: Buffer) => Promise<string>;
|
|
530
538
|
deleteFile: (fileRef: string) => Promise<void>;
|
|
531
539
|
}
|
|
532
|
-
export {};
|
|
@@ -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/package.json
CHANGED