@crowdin/app-project-module
Version:
Module that generates for you all common endpoints for serving standalone Crowdin App
975 lines (974 loc) • 47.1 kB
JavaScript
"use strict";
/* eslint-disable no-unused-expressions */
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MySQLStorage = void 0;
const uuid_1 = require("uuid");
const types_1 = require("../modules/integration/util/types");
const util_1 = require("../util");
class MySQLStorage {
constructor(config) {
this.mysql = require('mysql2/promise');
this.dbPromise = new Promise((res, rej) => {
this._res = res;
this._rej = rej;
});
this.tableIndexes = {
integration_credentials: {
idx_crowdin: '(crowdin_id)',
},
sync_settings: {
idx_integration_provider: '(integration_id, provider)',
idx_crowdin: '(crowdin_id)',
idx_type: '(type)',
},
files_snapshot: {
idx_integration: '(integration_id)',
idx_crowdin: '(crowdin_id)',
},
webhooks: {
idx_integration_crowdin: '(integration_id, crowdin_id)',
idx_file_provider: '(file_id, provider)',
},
user_errors: {
idx_integration_crowdin: '(integration_id, crowdin_id)',
idx_crowdin: '(crowdin_id)',
idx_created_at: '(created_at)',
},
integration_settings: {
idx_integration: '(integration_id)',
idx_crowdin: '(crowdin_id)',
},
job: {
idx_integration_crowdin: '(integration_id, crowdin_id)',
idx_finished_at: '(finished_at)',
idx_status: '(status)',
},
translation_file_cache: {
idx_integration_crowdin_file_language: '(integration_id, crowdin_id, file_id, language_id)',
idx_crowdin: '(crowdin_id)',
},
unsynced_files: {
idx_integration_crowdin: '(integration_id, crowdin_id)',
idx_crowdin: '(crowdin_id)',
},
};
this.tables = {
crowdin_credentials: `(
id varchar(255) primary key,
app_secret text,
domain varchar(255),
user_id varchar(255),
agent_id varchar(255),
organization_id varchar(255),
base_url varchar(255),
access_token text not null,
refresh_token text not null,
expire varchar(255) not null,
type varchar(255) not null
)`,
integration_credentials: `(
id varchar(255) primary key,
credentials text,
crowdin_id varchar(255) not null,
managers text
)`,
sync_settings: `(
id int auto_increment primary key,
files text,
integration_id varchar(255) not null,
crowdin_id varchar(255) not null,
type varchar(255) not null,
provider varchar(255) not null
)`,
app_metadata: `(
id varchar(255) primary key,
data text,
crowdin_id text
)`,
files_snapshot: `(
id int auto_increment primary key,
files text,
integration_id varchar(255) not null,
crowdin_id varchar(255) not null,
provider varchar(255) not null
)`,
webhooks: `(
id int auto_increment primary key,
file_id varchar(255) not null,
integration_id varchar(255) not null,
crowdin_id varchar(255) not null,
provider varchar(255) not null
)`,
user_errors: `(
id int auto_increment primary key,
action varchar(255) not null,
message varchar(255) not null,
data text,
created_at varchar(255) not null,
crowdin_id varchar(255) not null,
integration_id varchar(255)
)`,
integration_settings: `(
id int auto_increment primary key,
integration_id varchar(255) not null,
crowdin_id varchar(255) not null,
config text
)`,
job: `(
id varchar(255) not null primary key,
integration_id varchar(255) not null,
crowdin_id varchar(255) not null,
type varchar(255) not null,
payload text,
title text,
progress int 0,
status varchar(255) '${types_1.JobStatus.CREATED}',
payload text,
info text,
data text,
attempt int 0,
errors text,
processed_entities text,
created_at varchar(255) not null,
updated_at varchar(255),
finished_at varchar(255)
)`,
translation_file_cache: `(
id int auto_increment primary key,
integration_id varchar(255) not null,
crowdin_id varchar(255) not null,
file_id int not null,
language_id varchar(255) not null,
etag varchar(255)
)`,
unsynced_files: `(
id int auto_increment primary key,
integration_id varchar(255) not null,
crowdin_id varchar(255) not null,
files text
)`,
synced_data: `(
id int auto_increment primary key,
files text,
integration_id varchar(255) not null,
crowdin_id varchar(255) not null,
type varchar(255) not null,
updated_at varchar(255) null,
)`,
};
this.config = config;
}
executeQuery(command) {
return __awaiter(this, void 0, void 0, function* () {
return (0, util_1.executeWithRetry)(() => __awaiter(this, void 0, void 0, function* () {
let connection;
try {
connection = yield this.mysql.createConnection(this.config);
const res = yield command(connection);
yield connection.end();
return res;
}
catch (error) {
if (connection) {
try {
yield connection.end();
}
catch (nestedError) {
throw nestedError;
}
}
throw error;
}
}));
});
}
migrate() {
return __awaiter(this, void 0, void 0, function* () {
try {
yield this.executeQuery((connection) => this.addTables(connection));
this._res && this._res();
}
catch (e) {
console.error(e);
this._rej && this._rej();
}
});
}
addTables(connection) {
return __awaiter(this, void 0, void 0, function* () {
for (const [tableName, tableSchema] of Object.entries(this.tables)) {
yield connection.execute(`create table if not exists ${tableName} ${tableSchema}`);
if (this.tableIndexes[tableName]) {
for (const [indexName, indexSchema] of Object.entries(this.tableIndexes[tableName])) {
// For MySQL, we need to handle partial indexes differently since MySQL doesn't support WHERE clauses in indexes
// We'll create the basic index without the WHERE clause
const indexColumns = indexSchema.replace(/WHERE.*$/, '').trim();
yield connection.execute(`create index if not exists ${indexName} on ${tableName}${indexColumns}`);
}
}
}
});
}
saveCrowdinCredentials(credentials) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('INSERT INTO crowdin_credentials(id, app_secret, domain, user_id, agent_id, organization_id, base_url, access_token, refresh_token, expire, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
credentials.id,
credentials.appSecret,
credentials.domain,
credentials.userId,
credentials.agentId,
credentials.organizationId,
credentials.baseUrl,
credentials.accessToken,
credentials.refreshToken,
credentials.expire,
credentials.type,
]));
});
}
updateCrowdinCredentials(credentials) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('UPDATE crowdin_credentials SET app_secret = ?, domain = ?, user_id = ?, agent_id = ?, organization_id = ?, base_url = ?, access_token = ?, refresh_token = ?, expire = ? WHERE id = ?', [
credentials.appSecret,
credentials.domain,
credentials.userId,
credentials.agentId,
credentials.organizationId,
credentials.baseUrl,
credentials.accessToken,
credentials.refreshToken,
credentials.expire,
credentials.id,
]));
});
}
getCrowdinCredentials(id) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT id, app_secret as "appSecret", domain, user_id as "userId", agent_id as "agentId", organization_id as "organizationId", base_url as "baseUrl", access_token as "accessToken", refresh_token as "refreshToken", expire, type FROM crowdin_credentials WHERE id = ?', [id]);
return (rows || [])[0];
}));
});
}
getAllCrowdinCredentials() {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT id, app_secret as "appSecret", domain, user_id as "userId", agent_id as "agentId", organization_id as "organizationId", base_url as "baseUrl", access_token as "accessToken", refresh_token as "refreshToken", expire, type FROM crowdin_credentials', []);
return rows || [];
}));
});
}
deleteCrowdinCredentials(id) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
yield connection.execute('DELETE FROM crowdin_credentials where id = ?', [id]);
yield connection.execute('DELETE FROM integration_credentials where crowdin_id = ?', [id]);
yield connection.execute('DELETE FROM sync_settings WHERE crowdin_id = ?', [id]);
yield connection.execute('DELETE FROM app_metadata WHERE crowdin_id = ?', [id]);
yield connection.execute('DELETE FROM files_snapshot WHERE crowdin_id = ?', [id]);
yield connection.execute('DELETE FROM webhooks WHERE crowdin_id = ?', [id]);
yield connection.execute('DELETE FROM user_errors WHERE crowdin_id = ?', [id]);
yield connection.execute('DELETE FROM integration_settings WHERE crowdin_id = ?', [id]);
yield connection.execute('DELETE FROM job WHERE crowdin_id = ?', [id]);
yield connection.execute('DELETE FROM translation_file_cache WHERE crowdin_id = ?', [id]);
yield connection.execute('DELETE FROM unsynced_files WHERE crowdin_id = ?', [id]);
yield connection.execute('DELETE FROM synced_data WHERE crowdin_id = ?', [id]);
}));
});
}
saveIntegrationCredentials(id, credentials, crowdinId) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('INSERT INTO integration_credentials(id, credentials, crowdin_id) VALUES (?, ?, ?)', [
id,
credentials,
crowdinId,
]));
});
}
updateIntegrationCredentials(id, credentials) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('UPDATE integration_credentials SET credentials = ? WHERE id = ?', [credentials, id]));
});
}
updateIntegrationManagers(id, managers) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('UPDATE integration_credentials SET managers = ? WHERE id = ?', [managers, id]));
});
}
getIntegrationCredentials(id) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT id, credentials, crowdin_id as "crowdinId", managers FROM integration_credentials WHERE id = ?', [id]);
return (rows || [])[0];
}));
});
}
getAllIntegrationCredentials(crowdinId) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT id, credentials, crowdin_id as "crowdinId", managers FROM integration_credentials WHERE crowdin_id = ?', [crowdinId]);
return rows || [];
}));
});
}
deleteIntegrationCredentials(id) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
yield connection.execute('DELETE FROM integration_credentials where id = ?', [id]);
yield connection.execute('DELETE FROM sync_settings where integration_id = ?', [id]);
yield connection.execute('DELETE FROM files_snapshot where integration_id = ?', [id]);
yield connection.execute('DELETE FROM webhooks where integration_id = ?', [id]);
yield connection.execute('DELETE FROM job where integration_id = ?', [id]);
yield connection.execute('DELETE FROM unsynced_files where integration_id = ?', [id]);
yield connection.execute('DELETE FROM synced_data where integration_id = ?', [id]);
}));
});
}
deleteAllIntegrationCredentials(crowdinId) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
yield connection.execute('DELETE FROM integration_credentials where crowdin_id = ?', [crowdinId]);
yield connection.execute('DELETE FROM sync_settings where crowdin_id = ?', [crowdinId]);
yield connection.execute('DELETE FROM files_snapshot where crowdin_id = ?', [crowdinId]);
yield connection.execute('DELETE FROM webhooks where crowdin_id = ?', [crowdinId]);
yield connection.execute('DELETE FROM user_errors where crowdin_id = ?', [crowdinId]);
yield connection.execute('DELETE FROM job where crowdin_id = ?', [crowdinId]);
yield connection.execute('DELETE FROM unsynced_files where crowdin_id = ?', [crowdinId]);
yield connection.execute('DELETE FROM synced_data where crowdin_id = ?', [crowdinId]);
}));
});
}
saveMetadata(id, metadata, crowdinId) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('INSERT INTO app_metadata(id, data, crowdin_id) VALUES (?, ?, ?)', [
id,
JSON.stringify(metadata),
crowdinId,
]));
});
}
updateMetadata(id, metadata, crowdinId) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('UPDATE app_metadata SET data = ?, crowdin_id = ? WHERE id = ?', [
JSON.stringify(metadata),
crowdinId,
id,
]));
});
}
getMetadata(id) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT data FROM app_metadata WHERE id = ?', [id]);
if (rows && rows[0]) {
return JSON.parse(rows[0].data);
}
}));
});
}
getAllMetadata() {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT * FROM app_metadata');
return rows || [];
}));
});
}
deleteMetadata(id) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('DELETE FROM app_metadata where id = ?', [id]));
});
}
getSyncSettingsByProvider(integrationId, provider) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT id, files, integration_id as "integrationId", crowdin_id as "crowdinId", type, provider FROM sync_settings WHERE integration_id = ? AND provider = ?', [integrationId, provider]);
return (rows || [])[0];
}));
});
}
getSyncSettingsBySchedule(type, schedule) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute(`
SELECT s.id, s.files, s.integration_id as "integrationId", s.crowdin_id as "crowdinId", s.type, s.provider
FROM sync_settings s
INNER JOIN integration_settings i ON s.integration_id = i.integration_id
WHERE s.type = ?
AND CASE
WHEN i.config IS NULL THEN false
ELSE JSON_EXTRACT(i.config, '$.schedule') = ?
END
`, [type, schedule]);
return rows || [];
}));
});
}
saveSyncSettings(files, integrationId, crowdinId, type, provider) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('INSERT INTO sync_settings(files, integration_id, crowdin_id, type, provider) VALUES (?, ?, ?, ?, ?)', [files, integrationId, crowdinId, type, provider]));
});
}
updateSyncSettings(files, integrationId, crowdinId, type, provider) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('UPDATE sync_settings SET files = ? WHERE integration_id = ? AND crowdin_id = ? AND type = ? AND provider = ?', [files, integrationId, crowdinId, type, provider]));
});
}
getSyncSettings(integrationId, crowdinId, type, provider) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT id, files, integration_id as "integrationId", crowdin_id as "crowdinId", type, provider FROM sync_settings WHERE integration_id = ? AND crowdin_id = ? AND type = ? AND provider = ?', [integrationId, crowdinId, type, provider]);
return (rows || [])[0];
}));
});
}
saveFilesSnapshot(files, integrationId, crowdinId, provider) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('INSERT INTO files_snapshot(files, integration_id, crowdin_id, provider) VALUES (?, ?, ?, ?)', [files, integrationId, crowdinId, provider]));
});
}
updateFilesSnapshot(files, integrationId, crowdinId, provider) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('UPDATE files_snapshot SET files = ? WHERE integration_id = ? AND crowdin_id = ? AND provider = ?', [files, integrationId, crowdinId, provider]));
});
}
getFilesSnapshot(integrationId, crowdinId, provider) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT id, files, integration_id as "integrationId", crowdin_id as "crowdinId" FROM files_snapshot WHERE integration_id = ? AND crowdin_id = ? AND provider = ?', [integrationId, crowdinId, provider]);
return (rows || [])[0];
}));
});
}
getAllWebhooks(integrationId, crowdinId, provider) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT id, file_id as "fileId", integration_id as "integrationId", crowdin_id as "crowdinId" FROM webhooks WHERE integration_id = ? AND crowdin_id = ? AND provider = ?', [integrationId, crowdinId, provider]);
return rows || [];
}));
});
}
getWebhooks(fileId, integrationId, crowdinId, provider) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT id, file_id as "fileId", integration_id as "integrationId", crowdin_id as "crowdinId" FROM webhooks WHERE file_id = ? AND integration_id = ? AND crowdin_id = ? AND provider = ?', [fileId, integrationId, crowdinId, provider]);
return (rows || [])[0];
}));
});
}
saveWebhooks(fileId, integrationId, crowdinId, provider) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('INSERT INTO webhooks(file_id, integration_id, crowdin_id, provider) VALUES (?, ?, ?, ?)', [fileId, integrationId, crowdinId, provider]));
});
}
deleteWebhooks(fileIds, integrationId, crowdinId, provider) {
return __awaiter(this, void 0, void 0, function* () {
if (!fileIds.length) {
return;
}
yield this.dbPromise;
const placeholders = fileIds.map(() => '?').join(',');
yield this.executeQuery((connection) => connection.execute(`DELETE
FROM webhooks
WHERE file_id IN (${placeholders})
AND integration_id = ?
AND crowdin_id = ?
AND provider = ?`, [...fileIds, integrationId, crowdinId, provider]));
});
}
getAllUserErrors(crowdinId, integrationId) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
let whereIntegrationCondition = 'integration_id is NULL';
const params = [crowdinId];
if (integrationId) {
whereIntegrationCondition = 'integration_id = ?';
params.push(integrationId);
}
const [rows] = yield connection.execute(`SELECT id, action, message, data, created_at as "createdAt"
FROM user_errors
WHERE crowdin_id = ? AND ${whereIntegrationCondition}`, params);
return rows || [];
}));
});
}
saveUserError(action, message, data, createdAt, crowdinId, integrationId) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('INSERT INTO user_errors(action, message, data, created_at, integration_id, crowdin_id) VALUES (?, ?, ?, ?, ?, ?)', [action, message, data, createdAt, integrationId, crowdinId]));
});
}
deleteUserErrors(createdAt, crowdinId, integrationId) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => {
let whereIntegrationCondition = 'integration_id is NULL';
const params = [createdAt, crowdinId];
if (integrationId) {
whereIntegrationCondition = 'integration_id = ?';
params.push(integrationId);
}
return connection.execute(`DELETE
FROM user_errors
WHERE created_at < ?
AND crowdin_id = ?
AND ${whereIntegrationCondition}`, params);
});
});
}
deleteAllUsersErrorsOlderThan(createdAt) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('DELETE FROM user_errors WHERE created_at < ?', [createdAt]));
});
}
saveIntegrationConfig(integrationId, crowdinId, config) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('INSERT INTO integration_settings(integrationId, crowdin_id, config) VALUES (?, ?, ?)', [
integrationId,
crowdinId,
config,
]));
});
}
getAllIntegrationConfigs(crowdinId) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT config FROM integration_settings WHERE crowdin_id = ?', [
crowdinId,
]);
return rows || [];
}));
});
}
getIntegrationConfig(integrationId) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT config FROM integration_settings WHERE integration_id = ?', [integrationId]);
return (rows || [])[0];
}));
});
}
updateIntegrationConfig(integrationId, config) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('UPDATE integration_settings SET config = ? WHERE id = ?', [config, integrationId]));
});
}
createJob({ integrationId, crowdinId, type, title, payload }) {
return __awaiter(this, void 0, void 0, function* () {
const id = (0, uuid_1.v4)();
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute(`
INSERT INTO job(id, integration_id, crowdin_id, type, payload, title, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?)
`, [id, integrationId, crowdinId, type, payload, title, Date.now().toString()]));
return id;
});
}
updateJob({ id, progress, status, info, data, attempt, errors, processedEntities, }) {
return __awaiter(this, void 0, void 0, function* () {
const updateFields = ['updated_at'];
const updateParams = [Date.now().toString()];
if (progress) {
updateFields.push('progress = ?');
updateParams.push(Math.round(progress));
if (progress >= 100) {
updateFields.push('finished_at = ?');
updateParams.push(Date.now().toString());
}
}
if (status) {
updateFields.push('status = ?');
updateParams.push(status);
if (!updateFields.includes('finished_at = ?') && [types_1.JobStatus.FAILED, types_1.JobStatus.CANCELED].includes(status)) {
updateFields.push('finished_at = ?');
updateParams.push(Date.now().toString());
}
}
if (data) {
updateFields.push('data = ?');
updateParams.push(data);
}
if (info) {
updateFields.push('info = ?');
updateParams.push(info);
}
if (attempt) {
updateFields.push('attempt = ?');
updateParams.push(attempt);
}
if (errors) {
updateFields.push('errors = ?');
updateParams.push(JSON.stringify(errors));
}
if (processedEntities) {
updateFields.push('processed_entities = ?');
updateParams.push(processedEntities);
}
updateParams.push(id);
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute(`
UPDATE job
SET ${updateFields.join(', ')}
WHERE id = ?
`, updateParams));
});
}
getJob({ id }) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute(`
SELECT id,
integration_id as "integrationId",
crowdin_id as "crowdinId",
type,
payload,
progress,
status,
title,
info,
data,
attempt,
errors,
processed_entities as "processedEntities",
created_at as "createdAt",
updated_at as "updatedAt",
finished_at as "finishedAt"
FROM job
WHERE id = ?
`, [id]);
return (rows || [])[0];
}));
});
}
getActiveJobs({ integrationId, crowdinId }) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute(`
SELECT id,
integration_id as "integrationId",
crowdin_id as "crowdinId",
type,
payload,
progress,
status,
title,
info,
data,
attempt,
errors,
processed_entities as "processedEntities",
created_at as "createdAt",
updated_at as "updatedAt",
finished_at as "finishedAt"
FROM job
WHERE integration_id = ?
AND crowdin_id = ?
AND finished_at is NULL
`, [integrationId, crowdinId]);
return rows || [];
}));
});
}
deleteFinishedJobs() {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('DELETE FROM job WHERE finished_at is not NULL', []));
});
}
getAllInProgressJobs() {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute(`
SELECT id,
integration_id as "integrationId",
crowdin_id as "crowdinId",
type,
payload,
progress,
status,
title,
info,
data,
attempt,
errors,
processed_entities as "processedEntities",
created_at as "createdAt",
updated_at as "updatedAt",
finished_at as "finishedAt"
FROM job
WHERE status IN (?, ?)
AND finished_at is NULL
`, [types_1.JobStatus.IN_PROGRESS, types_1.JobStatus.CREATED]);
return rows || [];
}));
});
}
getAllJobs({ integrationId, crowdinId, limit, offset }) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute(`
SELECT
id,
integration_id as "integrationId",
crowdin_id as "crowdinId",
type,
payload,
progress,
status,
title,
info,
data,
attempt,
created_at as "createdAt",
updated_at as "updatedAt",
finished_at as "finishedAt"
FROM job
WHERE integration_id = ?
AND crowdin_id = ?
ORDER BY created_at DESC
LIMIT ? OFFSET ?
`, [integrationId, crowdinId, limit, offset]);
return rows || [];
}));
});
}
saveTranslationCache({ integrationId, crowdinId, fileId, languageId, etag, }) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute(`
INSERT INTO translation_file_cache(integration_id, crowdin_id, file_id, language_id, etag)
VALUES (?, ?, ?, ?, ?)
`, [integrationId, crowdinId, fileId, languageId, etag]));
});
}
getFileTranslationCache({ integrationId, crowdinId, fileId, }) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute(`
SELECT integration_id as "integrationId",
crowdin_id as "crowdinId",
file_id as "fileId",
language_id as "languageId",
etag
FROM translation_file_cache
WHERE integration_id = ?
AND crowdin_id = ?
AND file_id = ?
`, [integrationId, crowdinId, fileId]);
return rows || [];
}));
});
}
getFileTranslationCacheByLanguage({ integrationId, crowdinId, fileId, languageId, }) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute(`
SELECT integration_id as "integrationId",
crowdin_id as "crowdinId",
file_id as "fileId",
language_id as "languageId",
etag
FROM translation_file_cache
WHERE integration_id = ?
AND crowdin_id = ?
AND file_id = ?
AND language_id = ?
`, [integrationId, crowdinId, fileId, languageId]);
return (rows || [])[0];
}));
});
}
updateTranslationCache({ integrationId, crowdinId, fileId, languageId, etag, }) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute(`
UPDATE translation_file_cache
SET etag = ?
WHERE integration_id = ?
AND crowdin_id = ?
AND file_id = ?
AND language_id = ?
`, [etag, integrationId, crowdinId, fileId, languageId]));
});
}
saveUnsyncedFiles({ integrationId, crowdinId, files }) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute(`
INSERT INTO unsynced_files(integration_id, crowdin_id, files)
VALUES (?, ?, ?,)
`, [integrationId, crowdinId, files]));
});
}
updateUnsyncedFiles({ integrationId, crowdinId, files }) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute(`
UPDATE unsynced_files
SET files = ?
WHERE integration_id = ?
AND crowdin_id = ?
`, [files, integrationId, crowdinId]));
});
}
getUnsyncedFiles({ integrationId, crowdinId }) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute(`
SELECT fileIds
FROM unsynced_files
WHERE integration_id = ?
AND crowdin_id = ?
`, [integrationId, crowdinId]);
return (rows || [])[0];
}));
});
}
registerCustomTable(tableName, schema) {
return __awaiter(this, void 0, void 0, function* () {
const columns = Object.entries(schema)
.map(([col, def]) => `${col} ${def}`)
.join(', ');
const query = `CREATE TABLE IF NOT EXISTS ${tableName}
(
${columns}
);`;
yield this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
yield connection.execute(query);
return;
}));
});
}
insertRecord(tableName, data) {
return __awaiter(this, void 0, void 0, function* () {
const columns = Object.keys(data).join(', ');
const placeholders = Object.keys(data)
.map(() => '?')
.join(', ');
const values = Object.values(data);
const query = `INSERT INTO ${tableName} (${columns})
VALUES (${placeholders});`;
yield this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
yield connection.execute(query, values);
return;
}));
});
}
selectRecords(tableName, options = {}, params = []) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const columns = ((_a = options.columns) === null || _a === void 0 ? void 0 : _a.length) ? options.columns.join(', ') : '*';
const distinctKeyword = options.distinct ? 'DISTINCT ' : '';
const whereClause = options.whereClause ? ` ${options.whereClause}` : '';
const orderByClause = options.orderBy ? ` ORDER BY ${options.orderBy}` : '';
let limitClause = options.limit ? ` LIMIT ${options.limit}` : '';
if (!options.limit && options.offset) {
throw new Error('[selectRecords] Limit is required for pagination with MySQL');
}
else if (options.limit && options.offset) {
limitClause += ` OFFSET ${options.offset}`;
}
const query = `SELECT ${distinctKeyword}${columns} FROM ${tableName}${whereClause}${orderByClause}${limitClause};`;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute(query, params);
return rows;
}));
});
}
updateRecord(tableName, data, whereClause, params = []) {
return __awaiter(this, void 0, void 0, function* () {
const setClause = Object.keys(data)
.map((key) => `${key} = ?`)
.join(', ');
const values = Object.values(data);
const query = `UPDATE ${tableName}
SET ${setClause} ${whereClause};`;
yield this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
yield connection.execute(query, [...values, ...params]);
return;
}));
});
}
deleteRecord(tableName, whereClause, params = []) {
return __awaiter(this, void 0, void 0, function* () {
const query = `DELETE
FROM ${tableName} ${whereClause};`;
yield this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
yield connection.execute(query, params);
return;
}));
});
}
saveSyncedData(files, integrationId, crowdinId, type) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('INSERT INTO synced_data(files, integration_id, crowdin_id, type, updated_at) VALUES (?, ?, ?, ?, ?)', [files, integrationId, crowdinId, type, Date.now().toString()]));
});
}
updateSyncedData(files, integrationId, crowdinId, type) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
yield this.executeQuery((connection) => connection.execute('UPDATE synced_data SET files = ?, updated_at = ? WHERE integration_id = ? AND crowdin_id = ? AND type = ?', [files, Date.now().toString(), integrationId, crowdinId, type]));
});
}
getSyncedData(integrationId, crowdinId, type) {
return __awaiter(this, void 0, void 0, function* () {
yield this.dbPromise;
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
const [rows] = yield connection.execute('SELECT id, files, integration_id as "integrationId", crowdin_id as "crowdinId", type, updated_at as "updatedAt" FROM synced_data WHERE integration_id = ? AND crowdin_id = ? AND type = ?', [integrationId, crowdinId, type]);
return (rows || [])[0];
}));
});
}
}
exports.MySQLStorage = MySQLStorage;