@crowdin/app-project-module 0.74.0 → 0.76.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/update-crowdin.js +2 -0
- package/out/app-test/integration/update-integration.js +2 -0
- package/out/modules/api/api.js +75 -3
- package/out/modules/api/components.d.ts +58 -17
- package/out/modules/api/components.js +58 -17
- package/out/modules/integration/handlers/crowdin-files.js +11 -1
- package/out/modules/integration/handlers/job-cancel.d.ts +2 -1
- package/out/modules/integration/handlers/job-cancel.js +10 -2
- package/out/modules/integration/handlers/job-info.js +32 -1
- package/out/modules/integration/handlers/user-errors.js +2 -14
- package/out/modules/integration/index.js +1 -1
- package/out/modules/integration/types.d.ts +4 -2
- package/out/modules/integration/util/files.d.ts +7 -0
- package/out/modules/integration/util/files.js +44 -1
- package/out/modules/integration/util/job.js +33 -1
- package/out/modules/integration/util/types.d.ts +21 -0
- package/out/modules/integration/util/webhooks.js +18 -12
- package/out/storage/index.d.ts +19 -1
- package/out/storage/index.js +97 -1
- package/out/storage/mysql.d.ts +17 -1
- package/out/storage/mysql.js +134 -117
- package/out/storage/postgre.d.ts +20 -2
- package/out/storage/postgre.js +171 -120
- package/out/storage/sqlite.d.ts +17 -1
- package/out/storage/sqlite.js +131 -119
- package/out/types.d.ts +9 -0
- package/out/types.js +7 -1
- package/out/util/index.d.ts +5 -0
- package/out/util/index.js +22 -1
- package/out/views/main.handlebars +49 -50
- package/package.json +1 -1
|
@@ -3,6 +3,8 @@ import { Config } from '../../../types';
|
|
|
3
3
|
import { IntegrationLogic, IntegrationSyncSettings } from '../types';
|
|
4
4
|
import { ResponseObject } from '@crowdin/crowdin-api-client/out/core';
|
|
5
5
|
import { TranslationsModel } from '@crowdin/crowdin-api-client/out/translations';
|
|
6
|
+
import { AxiosError } from 'axios';
|
|
7
|
+
import { AppModuleError, AppUserModuleError } from '../../../util/logger';
|
|
6
8
|
export declare enum JobType {
|
|
7
9
|
UPDATE_TO_CROWDIN = "updateCrowdin",
|
|
8
10
|
UPDATE_TO_INTEGRATION = "updateIntegration",
|
|
@@ -56,6 +58,8 @@ export type JobClient = {
|
|
|
56
58
|
type: JobClientType;
|
|
57
59
|
translationUploaded: SaveUploadedFileTranslation;
|
|
58
60
|
fetchTranslation: FetchTranslation;
|
|
61
|
+
markFilesAsUnsynced: MarkUnsyncedFiles;
|
|
62
|
+
unmarkFilesAsUnsynced: UnmarkUnsyncedFiles;
|
|
59
63
|
};
|
|
60
64
|
export type UpdateJobProgress = ({ progress, status, info, data, attempt, }: Omit<UpdateJobParams, 'id'>) => Promise<{
|
|
61
65
|
isCanceled: boolean;
|
|
@@ -92,3 +96,20 @@ export interface TranslationCache {
|
|
|
92
96
|
export type GetFileTranslationCache = Pick<TranslationCache, 'integrationId' | 'crowdinId' | 'fileId'>;
|
|
93
97
|
export type GetFileTranslationCacheByLanguageParams = Pick<TranslationCache, 'integrationId' | 'crowdinId' | 'fileId' | 'languageId'>;
|
|
94
98
|
export type UpdateTranslationCacheParams = Pick<TranslationCache, 'integrationId' | 'crowdinId' | 'fileId' | 'languageId' | 'etag'>;
|
|
99
|
+
export type MarkUnsyncedFiles = ({ files, }: {
|
|
100
|
+
files: {
|
|
101
|
+
fileId: number;
|
|
102
|
+
error: AxiosError | AppModuleError | AppUserModuleError | Error | string;
|
|
103
|
+
}[];
|
|
104
|
+
}) => Promise<void>;
|
|
105
|
+
export type UnmarkUnsyncedFiles = ({ files }: {
|
|
106
|
+
files: {
|
|
107
|
+
fileId: number;
|
|
108
|
+
}[];
|
|
109
|
+
}) => Promise<void>;
|
|
110
|
+
export interface UnsyncedFiles {
|
|
111
|
+
integrationId: string;
|
|
112
|
+
crowdinId: string;
|
|
113
|
+
files: string;
|
|
114
|
+
}
|
|
115
|
+
export type GetUnsyncedFiles = Pick<UnsyncedFiles, 'integrationId' | 'crowdinId'>;
|
|
@@ -45,8 +45,8 @@ const connection_1 = require("../../../util/connection");
|
|
|
45
45
|
const defaults_1 = require("./defaults");
|
|
46
46
|
const index_1 = require("../../../util/index");
|
|
47
47
|
const logger_1 = require("../../../util/logger");
|
|
48
|
-
const prefetchCount =
|
|
49
|
-
const forceProcessDelay =
|
|
48
|
+
const prefetchCount = 10;
|
|
49
|
+
const forceProcessDelay = 10000;
|
|
50
50
|
exports.HookEvents = {
|
|
51
51
|
fileAdded: 'file.added',
|
|
52
52
|
fileDeleted: 'file.deleted',
|
|
@@ -407,7 +407,7 @@ function consumer({ channel, config, integration, }) {
|
|
|
407
407
|
webhooksInfo[clientId].data.push(data);
|
|
408
408
|
}
|
|
409
409
|
if (messagesCounter < prefetchCount) {
|
|
410
|
-
// if all messages are not received, wait
|
|
410
|
+
// if all messages are not received, wait 10 seconds to force process messages
|
|
411
411
|
timeoutId = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
412
412
|
yield processMessages({
|
|
413
413
|
webhooksData,
|
|
@@ -436,16 +436,22 @@ function consumer({ channel, config, integration, }) {
|
|
|
436
436
|
}
|
|
437
437
|
function processMessages({ channel, msg, webhooksData, webhooksInfo, }) {
|
|
438
438
|
return __awaiter(this, void 0, void 0, function* () {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
439
|
+
try {
|
|
440
|
+
yield Promise.all(webhooksData);
|
|
441
|
+
for (const { data, integration, webhookData } of Object.values(webhooksInfo)) {
|
|
442
|
+
if (webhookData && webhookData.crowdinClient) {
|
|
443
|
+
yield updateCrowdinFromWebhookRequest({
|
|
444
|
+
integration: integration,
|
|
445
|
+
webhookData: webhookData,
|
|
446
|
+
req: data,
|
|
447
|
+
});
|
|
448
|
+
}
|
|
447
449
|
}
|
|
450
|
+
channel.ack(msg, true);
|
|
451
|
+
}
|
|
452
|
+
catch (e) {
|
|
453
|
+
(0, logger_1.logError)(e);
|
|
454
|
+
channel.nack(msg, false, false);
|
|
448
455
|
}
|
|
449
|
-
channel.ack(msg, true);
|
|
450
456
|
});
|
|
451
457
|
}
|
package/out/storage/index.d.ts
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
import { IntegrationConfig, IntegrationCredentials, IntegrationFilesSnapshot, IntegrationSyncSettings, IntegrationWebhooks, Provider } from '../modules/integration/types';
|
|
2
2
|
import { Config, CrowdinCredentials, UnauthorizedConfig } from '../types';
|
|
3
|
-
import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache } from '../modules/integration/util/types';
|
|
3
|
+
import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache, UnsyncedFiles, GetUnsyncedFiles } from '../modules/integration/util/types';
|
|
4
4
|
import { UserErrors } from './types';
|
|
5
|
+
declare const TABLES: {
|
|
6
|
+
crowdin_credentials: string;
|
|
7
|
+
integration_credentials: string;
|
|
8
|
+
sync_settings: string;
|
|
9
|
+
app_metadata: string;
|
|
10
|
+
files_snapshot: string;
|
|
11
|
+
webhooks: string;
|
|
12
|
+
user_errors: string;
|
|
13
|
+
integration_settings: string;
|
|
14
|
+
job: string;
|
|
15
|
+
translation_file_cache: string;
|
|
16
|
+
unsynced_files: string;
|
|
17
|
+
};
|
|
5
18
|
export interface Storage {
|
|
19
|
+
tables: typeof TABLES;
|
|
6
20
|
migrate(): Promise<void>;
|
|
7
21
|
saveCrowdinCredentials(credentials: CrowdinCredentials): Promise<void>;
|
|
8
22
|
updateCrowdinCredentials(credentials: CrowdinCredentials): Promise<void>;
|
|
@@ -51,6 +65,10 @@ export interface Storage {
|
|
|
51
65
|
getFileTranslationCache(params: GetFileTranslationCache): Promise<TranslationCache[] | undefined>;
|
|
52
66
|
getFileTranslationCacheByLanguage(params: GetFileTranslationCacheByLanguageParams): Promise<TranslationCache | undefined>;
|
|
53
67
|
updateTranslationCache(params: UpdateTranslationCacheParams): Promise<void>;
|
|
68
|
+
saveUnsyncedFiles(params: UnsyncedFiles): Promise<void>;
|
|
69
|
+
getUnsyncedFiles(params: GetUnsyncedFiles): Promise<UnsyncedFiles | undefined>;
|
|
70
|
+
updateUnsyncedFiles(params: UnsyncedFiles): Promise<void>;
|
|
54
71
|
}
|
|
55
72
|
export declare function initialize(config: Config | UnauthorizedConfig): Promise<void>;
|
|
56
73
|
export declare function getStorage(): Storage;
|
|
74
|
+
export {};
|
package/out/storage/index.js
CHANGED
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/camelcase */
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
20
|
+
if (mod && mod.__esModule) return mod;
|
|
21
|
+
var result = {};
|
|
22
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
23
|
+
__setModuleDefault(result, mod);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
2
26
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
27
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
28
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,18 +32,44 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
32
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
33
|
});
|
|
10
34
|
};
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
11
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
39
|
exports.getStorage = exports.initialize = void 0;
|
|
40
|
+
const types_1 = require("../types");
|
|
13
41
|
const logger_1 = require("../util/logger");
|
|
14
42
|
const mysql_1 = require("./mysql");
|
|
15
43
|
const postgre_1 = require("./postgre");
|
|
16
44
|
const sqlite_1 = require("./sqlite");
|
|
45
|
+
const path_1 = __importStar(require("path"));
|
|
46
|
+
const fs_1 = __importDefault(require("fs"));
|
|
47
|
+
const child_process_1 = require("child_process");
|
|
48
|
+
const util = __importStar(require("node:util"));
|
|
49
|
+
const TABLES = {
|
|
50
|
+
crowdin_credentials: 'crowdin_credentials',
|
|
51
|
+
integration_credentials: 'integration_credentials',
|
|
52
|
+
sync_settings: 'sync_settings',
|
|
53
|
+
app_metadata: 'app_metadata',
|
|
54
|
+
files_snapshot: 'files_snapshot',
|
|
55
|
+
webhooks: 'webhooks',
|
|
56
|
+
user_errors: 'user_errors',
|
|
57
|
+
integration_settings: 'integration_settings',
|
|
58
|
+
job: 'job',
|
|
59
|
+
translation_file_cache: 'translation_file_cache',
|
|
60
|
+
unsynced_files: 'unsynced_files',
|
|
61
|
+
};
|
|
17
62
|
let storage;
|
|
18
63
|
function initialize(config) {
|
|
19
64
|
return __awaiter(this, void 0, void 0, function* () {
|
|
20
65
|
if (config.postgreConfig) {
|
|
21
66
|
(0, logger_1.log)('Using PostgreSQL database');
|
|
22
|
-
|
|
67
|
+
let dumpDirectory = null;
|
|
68
|
+
if (config.migrateToPostgreFromSQLite) {
|
|
69
|
+
dumpDirectory = config.dbFolder;
|
|
70
|
+
createDumpForMigration(config);
|
|
71
|
+
}
|
|
72
|
+
storage = new postgre_1.PostgreStorage(config.postgreConfig, dumpDirectory);
|
|
23
73
|
}
|
|
24
74
|
else if (config.mysqlConfig) {
|
|
25
75
|
(0, logger_1.log)('Using MySQL database');
|
|
@@ -27,6 +77,10 @@ function initialize(config) {
|
|
|
27
77
|
}
|
|
28
78
|
else {
|
|
29
79
|
(0, logger_1.log)('Using SQLite database');
|
|
80
|
+
if (config.migrateToPostgreFromSQLite === false) {
|
|
81
|
+
(0, logger_1.log)('Try to get SQLite file from backup');
|
|
82
|
+
getSqLiteFileFromBackup(config);
|
|
83
|
+
}
|
|
30
84
|
storage = new sqlite_1.SQLiteStorage({ dbFolder: config.dbFolder });
|
|
31
85
|
}
|
|
32
86
|
yield storage.migrate();
|
|
@@ -40,3 +94,45 @@ function getStorage() {
|
|
|
40
94
|
return storage;
|
|
41
95
|
}
|
|
42
96
|
exports.getStorage = getStorage;
|
|
97
|
+
function createDumpForMigration(config) {
|
|
98
|
+
const sqliteFilePath = (0, path_1.join)(config.dbFolder, types_1.storageFiles.SQLITE);
|
|
99
|
+
const backupFilePath = (0, path_1.join)(config.dbFolder, types_1.storageFiles.SQLITE_BACKUP);
|
|
100
|
+
if (!fs_1.default.existsSync(sqliteFilePath)) {
|
|
101
|
+
(0, logger_1.log)('SQLite database not found, skipping migration dump creation');
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
(0, logger_1.log)('Creating dump for migration from SQLite to PostgreSQL');
|
|
105
|
+
for (const tableName in TABLES) {
|
|
106
|
+
(0, logger_1.log)(`Creating dump for table ${tableName}`);
|
|
107
|
+
const dumpFileName = util.format(types_1.storageFiles.DUMP, tableName);
|
|
108
|
+
const dumpFilePath = path_1.default.join(config.dbFolder, dumpFileName);
|
|
109
|
+
(0, child_process_1.execSync)(`sqlite3 ${sqliteFilePath} ".output ${dumpFilePath}" ".dump ${tableName}" ".output stdout"`);
|
|
110
|
+
let modifiedContent = fs_1.default.readFileSync(dumpFilePath).toString();
|
|
111
|
+
// 1. Remove SQLite-specific PRAGMA statements
|
|
112
|
+
modifiedContent = modifiedContent.replace(/PRAGMA foreign_keys=OFF;\n/g, '');
|
|
113
|
+
// 2. Adjust transaction syntax for PostgreSQL
|
|
114
|
+
modifiedContent = modifiedContent.replace(/BEGIN TRANSACTION;\n/g, '');
|
|
115
|
+
modifiedContent = modifiedContent.replace(/COMMIT TRANSACTION;\n/g, '');
|
|
116
|
+
// 3. Ensure tables are only created if they don't already exist
|
|
117
|
+
modifiedContent = modifiedContent
|
|
118
|
+
.replace(/CREATE TABLE IF NOT EXISTS/g, 'CREATE TABLE') // Remove duplicate IF NOT EXISTS
|
|
119
|
+
.replace(/CREATE TABLE/g, 'CREATE TABLE IF NOT EXISTS'); // Add IF NOT EXISTS if missing
|
|
120
|
+
// 4. Add `ON CONFLICT DO NOTHING` to INSERT statements to handle conflicts gracefully
|
|
121
|
+
modifiedContent = modifiedContent.replace(/(INSERT INTO [^;]+)(;)/g, '$1 ON CONFLICT DO NOTHING;');
|
|
122
|
+
// 5. Convert SQLite-specific data types to PostgreSQL equivalents
|
|
123
|
+
modifiedContent = modifiedContent.replace(/integer not null primary key autoincrement/gi, 'serial primary key');
|
|
124
|
+
modifiedContent = modifiedContent.replace(/varchar not null primary key/gi, 'varchar primary key');
|
|
125
|
+
// 6. Remove SQLite-specific function replace()
|
|
126
|
+
modifiedContent = modifiedContent.replace(/replace\s*\('([^']+?)',\s*'?\\[rn]'?\s*,\s*char\s*\([0-9]+\)\s*\)/gi, "'$1'");
|
|
127
|
+
fs_1.default.writeFileSync(dumpFilePath, modifiedContent, { encoding: 'utf8', flag: 'w' });
|
|
128
|
+
}
|
|
129
|
+
fs_1.default.renameSync(sqliteFilePath, backupFilePath);
|
|
130
|
+
}
|
|
131
|
+
function getSqLiteFileFromBackup(config) {
|
|
132
|
+
const sqliteFilePath = (0, path_1.join)(config.dbFolder, types_1.storageFiles.SQLITE);
|
|
133
|
+
const backupFilePath = (0, path_1.join)(config.dbFolder, types_1.storageFiles.SQLITE_BACKUP);
|
|
134
|
+
if (fs_1.default.existsSync(backupFilePath) && !fs_1.default.existsSync(sqliteFilePath)) {
|
|
135
|
+
(0, logger_1.log)('Restoring SQLite database from backup');
|
|
136
|
+
fs_1.default.renameSync(backupFilePath, sqliteFilePath);
|
|
137
|
+
}
|
|
138
|
+
}
|
package/out/storage/mysql.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Storage } from '.';
|
|
2
2
|
import { CrowdinCredentials } from '../types';
|
|
3
|
-
import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache } from '../modules/integration/util/types';
|
|
3
|
+
import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache, UnsyncedFiles, GetUnsyncedFiles } from '../modules/integration/util/types';
|
|
4
4
|
import { IntegrationConfig, IntegrationCredentials, IntegrationFilesSnapshot, IntegrationSyncSettings, IntegrationWebhooks } from '../modules/integration/types';
|
|
5
5
|
import { UserErrors } from './types';
|
|
6
6
|
export interface MySQLStorageConfig {
|
|
@@ -17,6 +17,19 @@ export declare class MySQLStorage implements Storage {
|
|
|
17
17
|
private _rej?;
|
|
18
18
|
private dbPromise;
|
|
19
19
|
private config;
|
|
20
|
+
tables: {
|
|
21
|
+
crowdin_credentials: string;
|
|
22
|
+
integration_credentials: string;
|
|
23
|
+
sync_settings: string;
|
|
24
|
+
app_metadata: string;
|
|
25
|
+
files_snapshot: string;
|
|
26
|
+
webhooks: string;
|
|
27
|
+
user_errors: string;
|
|
28
|
+
integration_settings: string;
|
|
29
|
+
job: string;
|
|
30
|
+
translation_file_cache: string;
|
|
31
|
+
unsynced_files: string;
|
|
32
|
+
};
|
|
20
33
|
constructor(config: MySQLStorageConfig);
|
|
21
34
|
executeQuery<T>(command: (connection: any) => Promise<T>): Promise<T>;
|
|
22
35
|
migrate(): Promise<void>;
|
|
@@ -68,4 +81,7 @@ export declare class MySQLStorage implements Storage {
|
|
|
68
81
|
getFileTranslationCache({ integrationId, crowdinId, fileId, }: GetFileTranslationCache): Promise<TranslationCache[] | undefined>;
|
|
69
82
|
getFileTranslationCacheByLanguage({ integrationId, crowdinId, fileId, languageId, }: GetFileTranslationCacheByLanguageParams): Promise<TranslationCache | undefined>;
|
|
70
83
|
updateTranslationCache({ integrationId, crowdinId, fileId, languageId, etag, }: UpdateTranslationCacheParams): Promise<void>;
|
|
84
|
+
saveUnsyncedFiles({ integrationId, crowdinId, files }: UnsyncedFiles): Promise<void>;
|
|
85
|
+
updateUnsyncedFiles({ integrationId, crowdinId, files }: UnsyncedFiles): Promise<void>;
|
|
86
|
+
getUnsyncedFiles({ integrationId, crowdinId }: GetUnsyncedFiles): Promise<UnsyncedFiles | undefined>;
|
|
71
87
|
}
|
package/out/storage/mysql.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
/* eslint-disable no-unused-expressions */
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
4
4
|
/* eslint-disable @typescript-eslint/ban-ts-ignore */
|
|
5
|
+
/* eslint-disable @typescript-eslint/camelcase */
|
|
5
6
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
7
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
8
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -23,6 +24,100 @@ class MySQLStorage {
|
|
|
23
24
|
this._res = res;
|
|
24
25
|
this._rej = rej;
|
|
25
26
|
});
|
|
27
|
+
this.tables = {
|
|
28
|
+
crowdin_credentials: `(
|
|
29
|
+
id varchar(255) primary key,
|
|
30
|
+
app_secret text,
|
|
31
|
+
domain varchar(255),
|
|
32
|
+
user_id varchar(255),
|
|
33
|
+
agent_id varchar(255),
|
|
34
|
+
organization_id varchar(255),
|
|
35
|
+
base_url varchar(255),
|
|
36
|
+
access_token text not null,
|
|
37
|
+
refresh_token text not null,
|
|
38
|
+
expire varchar(255) not null,
|
|
39
|
+
type varchar(255) not null
|
|
40
|
+
)`,
|
|
41
|
+
integration_credentials: `(
|
|
42
|
+
id varchar(255) primary key,
|
|
43
|
+
credentials text,
|
|
44
|
+
crowdin_id varchar(255) not null,
|
|
45
|
+
managers text
|
|
46
|
+
)`,
|
|
47
|
+
sync_settings: `(
|
|
48
|
+
id int auto_increment primary key,
|
|
49
|
+
files text,
|
|
50
|
+
integration_id varchar(255) not null,
|
|
51
|
+
crowdin_id varchar(255) not null,
|
|
52
|
+
type varchar(255) not null,
|
|
53
|
+
provider varchar(255) not null
|
|
54
|
+
)`,
|
|
55
|
+
app_metadata: `(
|
|
56
|
+
id varchar(255) primary key,
|
|
57
|
+
data text,
|
|
58
|
+
crowdin_id text
|
|
59
|
+
)`,
|
|
60
|
+
files_snapshot: `(
|
|
61
|
+
id int auto_increment primary key,
|
|
62
|
+
files text,
|
|
63
|
+
integration_id varchar(255) not null,
|
|
64
|
+
crowdin_id varchar(255) not null,
|
|
65
|
+
provider varchar(255) not null
|
|
66
|
+
)`,
|
|
67
|
+
webhooks: `(
|
|
68
|
+
id int auto_increment primary key,
|
|
69
|
+
file_id varchar(255) not null,
|
|
70
|
+
integration_id varchar(255) not null,
|
|
71
|
+
crowdin_id varchar(255) not null,
|
|
72
|
+
provider varchar(255) not null
|
|
73
|
+
)`,
|
|
74
|
+
user_errors: `(
|
|
75
|
+
id int auto_increment primary key,
|
|
76
|
+
action varchar(255) not null,
|
|
77
|
+
message varchar(255) not null,
|
|
78
|
+
data text,
|
|
79
|
+
created_at varchar(255) not null,
|
|
80
|
+
crowdin_id varchar(255) not null,
|
|
81
|
+
integration_id varchar(255)
|
|
82
|
+
)`,
|
|
83
|
+
integration_settings: `(
|
|
84
|
+
id int auto_increment primary key,
|
|
85
|
+
integration_id varchar(255) not null,
|
|
86
|
+
crowdin_id varchar(255) not null,
|
|
87
|
+
config text
|
|
88
|
+
)`,
|
|
89
|
+
job: `(
|
|
90
|
+
id varchar(255) not null primary key,
|
|
91
|
+
integration_id varchar(255) not null,
|
|
92
|
+
crowdin_id varchar(255) not null,
|
|
93
|
+
type varchar(255) not null,
|
|
94
|
+
payload text,
|
|
95
|
+
title text,
|
|
96
|
+
progress int 0,
|
|
97
|
+
status varchar(255) '${types_1.JobStatus.CREATED}',
|
|
98
|
+
payload text,
|
|
99
|
+
info text,
|
|
100
|
+
data text,
|
|
101
|
+
attempt int 0,
|
|
102
|
+
created_at varchar(255) not null,
|
|
103
|
+
updated_at varchar(255),
|
|
104
|
+
finished_at varchar(255)
|
|
105
|
+
)`,
|
|
106
|
+
translation_file_cache: `(
|
|
107
|
+
id int auto_increment primary key,
|
|
108
|
+
integration_id varchar(255) not null,
|
|
109
|
+
crowdin_id varchar(255) not null,
|
|
110
|
+
file_id int not null,
|
|
111
|
+
language_id varchar(255) not null,
|
|
112
|
+
etag varchar(255)
|
|
113
|
+
)`,
|
|
114
|
+
unsynced_files: `(
|
|
115
|
+
id int auto_increment primary key,
|
|
116
|
+
integration_id varchar(255) not null,
|
|
117
|
+
crowdin_id varchar(255) not null,
|
|
118
|
+
files text
|
|
119
|
+
)`,
|
|
120
|
+
};
|
|
26
121
|
this.config = config;
|
|
27
122
|
}
|
|
28
123
|
executeQuery(command) {
|
|
@@ -52,7 +147,7 @@ class MySQLStorage {
|
|
|
52
147
|
migrate() {
|
|
53
148
|
return __awaiter(this, void 0, void 0, function* () {
|
|
54
149
|
try {
|
|
55
|
-
yield this.executeQuery(this.addTables);
|
|
150
|
+
yield this.executeQuery((connection) => this.addTables(connection));
|
|
56
151
|
this._res && this._res();
|
|
57
152
|
}
|
|
58
153
|
catch (e) {
|
|
@@ -63,122 +158,9 @@ class MySQLStorage {
|
|
|
63
158
|
}
|
|
64
159
|
addTables(connection) {
|
|
65
160
|
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
id varchar(255) primary key,
|
|
70
|
-
app_secret text,
|
|
71
|
-
domain varchar(255),
|
|
72
|
-
user_id varchar(255),
|
|
73
|
-
agent_id varchar(255),
|
|
74
|
-
organization_id varchar(255),
|
|
75
|
-
base_url varchar(255),
|
|
76
|
-
access_token text not null,
|
|
77
|
-
refresh_token text not null,
|
|
78
|
-
expire varchar(255) not null,
|
|
79
|
-
type varchar(255) not null
|
|
80
|
-
)
|
|
81
|
-
`);
|
|
82
|
-
yield connection.execute(`
|
|
83
|
-
create table if not exists integration_credentials
|
|
84
|
-
(
|
|
85
|
-
id varchar(255) primary key,
|
|
86
|
-
credentials text,
|
|
87
|
-
crowdin_id varchar(255) not null,
|
|
88
|
-
managers text
|
|
89
|
-
)
|
|
90
|
-
`);
|
|
91
|
-
yield connection.execute(`
|
|
92
|
-
create table if not exists sync_settings
|
|
93
|
-
(
|
|
94
|
-
id int auto_increment primary key,
|
|
95
|
-
files text,
|
|
96
|
-
integration_id varchar(255) not null,
|
|
97
|
-
crowdin_id varchar(255) not null,
|
|
98
|
-
type varchar(255) not null,
|
|
99
|
-
provider varchar(255) not null
|
|
100
|
-
)
|
|
101
|
-
`);
|
|
102
|
-
yield connection.execute(`
|
|
103
|
-
create table if not exists app_metadata
|
|
104
|
-
(
|
|
105
|
-
id varchar(255) primary key,
|
|
106
|
-
data text,
|
|
107
|
-
crowdin_id text
|
|
108
|
-
)
|
|
109
|
-
`);
|
|
110
|
-
yield connection.execute(`
|
|
111
|
-
create table if not exists files_snapshot
|
|
112
|
-
(
|
|
113
|
-
id int auto_increment primary key,
|
|
114
|
-
files text,
|
|
115
|
-
integration_id varchar(255) not null,
|
|
116
|
-
crowdin_id varchar(255) not null,
|
|
117
|
-
provider varchar(255) not null
|
|
118
|
-
)
|
|
119
|
-
`);
|
|
120
|
-
yield connection.execute(`
|
|
121
|
-
create table if not exists webhooks
|
|
122
|
-
(
|
|
123
|
-
id int auto_increment primary key,
|
|
124
|
-
file_id varchar(255) not null,
|
|
125
|
-
integration_id varchar(255) not null,
|
|
126
|
-
crowdin_id varchar(255) not null,
|
|
127
|
-
provider varchar(255) not null
|
|
128
|
-
)
|
|
129
|
-
`);
|
|
130
|
-
yield connection.execute(`
|
|
131
|
-
create table if not exists user_errors
|
|
132
|
-
(
|
|
133
|
-
id int auto_increment primary key,
|
|
134
|
-
action varchar(255) not null,
|
|
135
|
-
message varchar(255) not null,
|
|
136
|
-
data text,
|
|
137
|
-
created_at varchar(255) not null,
|
|
138
|
-
crowdin_id varchar(255) not null,
|
|
139
|
-
integration_id varchar(255)
|
|
140
|
-
)
|
|
141
|
-
`);
|
|
142
|
-
yield connection.execute(`
|
|
143
|
-
create table if not exists integration_settings
|
|
144
|
-
(
|
|
145
|
-
id int auto_increment primary key,
|
|
146
|
-
integration_id varchar(255) not null,
|
|
147
|
-
crowdin_id varchar(255) not null,
|
|
148
|
-
config text
|
|
149
|
-
)
|
|
150
|
-
`);
|
|
151
|
-
yield connection.execute(`
|
|
152
|
-
create table if not exists job
|
|
153
|
-
(
|
|
154
|
-
id varchar(255) not null primary key,
|
|
155
|
-
integration_id varchar(255) not null,
|
|
156
|
-
crowdin_id varchar(255) not null,
|
|
157
|
-
type varchar(255) not null,
|
|
158
|
-
payload text,
|
|
159
|
-
title text,
|
|
160
|
-
progress int 0,
|
|
161
|
-
status varchar(255) '${types_1.JobStatus.CREATED}',
|
|
162
|
-
payload text,
|
|
163
|
-
info text,
|
|
164
|
-
data text,
|
|
165
|
-
attempt int 0,
|
|
166
|
-
created_at varchar(255) not null,
|
|
167
|
-
updated_at varchar(255),
|
|
168
|
-
finished_at varchar(255)
|
|
169
|
-
)
|
|
170
|
-
`);
|
|
171
|
-
yield connection.execute(`
|
|
172
|
-
create table if not exists translation_file_cache
|
|
173
|
-
(
|
|
174
|
-
id int auto_increment primary key,
|
|
175
|
-
integration_id varchar(255) not null,
|
|
176
|
-
crowdin_id varchar(255) not null,
|
|
177
|
-
file_id int not null,
|
|
178
|
-
language_id varchar(255) not null,
|
|
179
|
-
etag varchar(255)
|
|
180
|
-
)
|
|
181
|
-
`);
|
|
161
|
+
for (const [tableName, tableSchema] of Object.entries(this.tables)) {
|
|
162
|
+
yield connection.execute(`create table if not exists ${tableName} ${tableSchema}`);
|
|
163
|
+
}
|
|
182
164
|
});
|
|
183
165
|
}
|
|
184
166
|
saveCrowdinCredentials(credentials) {
|
|
@@ -248,6 +230,7 @@ class MySQLStorage {
|
|
|
248
230
|
yield connection.execute('DELETE FROM integration_settings WHERE crowdin_id = ?', [id]);
|
|
249
231
|
yield connection.execute('DELETE FROM job WHERE crowdin_id = ?', [id]);
|
|
250
232
|
yield connection.execute('DELETE FROM translation_file_cache WHERE crowdin_id = ?', [id]);
|
|
233
|
+
yield connection.execute('DELETE FROM unsynced_files WHERE crowdin_id = ?', [id]);
|
|
251
234
|
}));
|
|
252
235
|
});
|
|
253
236
|
}
|
|
@@ -300,6 +283,7 @@ class MySQLStorage {
|
|
|
300
283
|
yield connection.execute('DELETE FROM files_snapshot where integration_id = ?', [id]);
|
|
301
284
|
yield connection.execute('DELETE FROM webhooks where integration_id = ?', [id]);
|
|
302
285
|
yield connection.execute('DELETE FROM job where integration_id = ?', [id]);
|
|
286
|
+
yield connection.execute('DELETE FROM unsynced_files where integration_id = ?', [id]);
|
|
303
287
|
}));
|
|
304
288
|
});
|
|
305
289
|
}
|
|
@@ -313,6 +297,7 @@ class MySQLStorage {
|
|
|
313
297
|
yield connection.execute('DELETE FROM webhooks where crowdin_id = ?', [crowdinId]);
|
|
314
298
|
yield connection.execute('DELETE FROM user_errors where crowdin_id = ?', [crowdinId]);
|
|
315
299
|
yield connection.execute('DELETE FROM job where crowdin_id = ?', [crowdinId]);
|
|
300
|
+
yield connection.execute('DELETE FROM unsynced_files where crowdin_id = ?', [crowdinId]);
|
|
316
301
|
}));
|
|
317
302
|
});
|
|
318
303
|
}
|
|
@@ -675,5 +660,37 @@ class MySQLStorage {
|
|
|
675
660
|
`, [etag, integrationId, crowdinId, fileId, languageId]));
|
|
676
661
|
});
|
|
677
662
|
}
|
|
663
|
+
saveUnsyncedFiles({ integrationId, crowdinId, files }) {
|
|
664
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
665
|
+
yield this.dbPromise;
|
|
666
|
+
yield this.executeQuery((connection) => connection.execute(`
|
|
667
|
+
INSERT INTO unsynced_files(integration_id, crowdin_id, files)
|
|
668
|
+
VALUES (?, ?, ?,)
|
|
669
|
+
`, [integrationId, crowdinId, files]));
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
updateUnsyncedFiles({ integrationId, crowdinId, files }) {
|
|
673
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
674
|
+
yield this.dbPromise;
|
|
675
|
+
yield this.executeQuery((connection) => connection.execute(`
|
|
676
|
+
UPDATE unsynced_files
|
|
677
|
+
SET files = ?
|
|
678
|
+
WHERE integration_id = ? AND crowdin_id = ?
|
|
679
|
+
`, [files, integrationId, crowdinId]));
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
getUnsyncedFiles({ integrationId, crowdinId }) {
|
|
683
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
684
|
+
yield this.dbPromise;
|
|
685
|
+
return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
|
|
686
|
+
const [rows] = yield connection.execute(`
|
|
687
|
+
SELECT fileIds
|
|
688
|
+
FROM unsynced_files
|
|
689
|
+
WHERE integration_id = ? AND crowdin_id = ?
|
|
690
|
+
`, [integrationId, crowdinId]);
|
|
691
|
+
return (rows || [])[0];
|
|
692
|
+
}));
|
|
693
|
+
});
|
|
694
|
+
}
|
|
678
695
|
}
|
|
679
696
|
exports.MySQLStorage = MySQLStorage;
|
package/out/storage/postgre.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Client } from 'pg';
|
|
|
2
2
|
import { Storage } from '.';
|
|
3
3
|
import { CrowdinCredentials } from '../types';
|
|
4
4
|
import { IntegrationConfig, IntegrationCredentials, IntegrationFilesSnapshot, IntegrationSyncSettings, IntegrationWebhooks } from '../modules/integration/types';
|
|
5
|
-
import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache } from '../modules/integration/util/types';
|
|
5
|
+
import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache, UnsyncedFiles, GetUnsyncedFiles } from '../modules/integration/util/types';
|
|
6
6
|
import { UserErrors } from './types';
|
|
7
7
|
export interface PostgreStorageConfig {
|
|
8
8
|
host?: string;
|
|
@@ -18,10 +18,24 @@ export interface PostgreStorageConfig {
|
|
|
18
18
|
}
|
|
19
19
|
export declare class PostgreStorage implements Storage {
|
|
20
20
|
private config;
|
|
21
|
+
private directoryPath;
|
|
21
22
|
private _res?;
|
|
22
23
|
private _rej?;
|
|
23
24
|
private dbPromise;
|
|
24
|
-
|
|
25
|
+
tables: {
|
|
26
|
+
crowdin_credentials: string;
|
|
27
|
+
integration_credentials: string;
|
|
28
|
+
sync_settings: string;
|
|
29
|
+
app_metadata: string;
|
|
30
|
+
files_snapshot: string;
|
|
31
|
+
webhooks: string;
|
|
32
|
+
user_errors: string;
|
|
33
|
+
integration_settings: string;
|
|
34
|
+
job: string;
|
|
35
|
+
translation_file_cache: string;
|
|
36
|
+
unsynced_files: string;
|
|
37
|
+
};
|
|
38
|
+
constructor(config: PostgreStorageConfig, directoryPath: string | null);
|
|
25
39
|
executeQuery<T>(command: (client: Client) => Promise<T>): Promise<T>;
|
|
26
40
|
migrate(): Promise<void>;
|
|
27
41
|
alterTables(client: Client): Promise<void>;
|
|
@@ -75,4 +89,8 @@ export declare class PostgreStorage implements Storage {
|
|
|
75
89
|
getFileTranslationCache({ integrationId, crowdinId, fileId, }: GetFileTranslationCache): Promise<TranslationCache[] | undefined>;
|
|
76
90
|
getFileTranslationCacheByLanguage({ integrationId, crowdinId, fileId, languageId, }: GetFileTranslationCacheByLanguageParams): Promise<TranslationCache | undefined>;
|
|
77
91
|
updateTranslationCache({ integrationId, crowdinId, fileId, languageId, etag, }: UpdateTranslationCacheParams): Promise<void>;
|
|
92
|
+
private migrateFromSqlite;
|
|
93
|
+
saveUnsyncedFiles({ integrationId, crowdinId, files }: UnsyncedFiles): Promise<void>;
|
|
94
|
+
updateUnsyncedFiles({ integrationId, crowdinId, files }: UnsyncedFiles): Promise<void>;
|
|
95
|
+
getUnsyncedFiles({ integrationId, crowdinId }: GetUnsyncedFiles): Promise<UnsyncedFiles | undefined>;
|
|
78
96
|
}
|