@crowdin/app-project-module 0.108.0 → 1.0.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.
Files changed (202) hide show
  1. package/out/app-test/integration/get-integration-files.js +16 -4
  2. package/out/app-test/integration/types.d.ts +1 -1
  3. package/out/app-test/integration/update-crowdin.js +2 -2
  4. package/out/app-test/integration/update-integration.js +2 -2
  5. package/out/index.d.ts +2 -1
  6. package/out/index.js +73 -30
  7. package/out/middlewares/auto-credentials-masker.d.ts +4 -0
  8. package/out/middlewares/auto-credentials-masker.js +45 -0
  9. package/out/middlewares/crowdin-client.d.ts +1 -1
  10. package/out/middlewares/integration-credentials.d.ts +2 -2
  11. package/out/middlewares/integration-credentials.js +7 -4
  12. package/out/middlewares/render-ui-module.d.ts +3 -3
  13. package/out/middlewares/render-ui-module.js +10 -13
  14. package/out/middlewares/ui-module.d.ts +1 -1
  15. package/out/middlewares/ui-module.js +11 -1
  16. package/out/modules/about.d.ts +2 -1
  17. package/out/modules/about.js +10 -3
  18. package/out/modules/ai-prompt-provider/handlers/compile.d.ts +1 -1
  19. package/out/modules/ai-prompt-provider/handlers/compile.js +7 -1
  20. package/out/modules/ai-prompt-provider/index.js +2 -2
  21. package/out/modules/ai-prompt-provider/types.d.ts +7 -1
  22. package/out/modules/ai-provider/handlers/chat-completions.d.ts +1 -1
  23. package/out/modules/ai-provider/handlers/chat-completions.js +1 -1
  24. package/out/modules/ai-provider/handlers/get-model-list.d.ts +1 -1
  25. package/out/modules/ai-provider/index.js +2 -2
  26. package/out/modules/ai-provider/types.d.ts +4 -4
  27. package/out/modules/ai-request-processors/handler.d.ts +1 -1
  28. package/out/modules/ai-request-processors/handler.js +12 -2
  29. package/out/modules/ai-request-processors/types.d.ts +12 -2
  30. package/out/modules/ai-tools/handlers/tool-calls.d.ts +1 -1
  31. package/out/modules/ai-tools/handlers/tool-calls.js +1 -1
  32. package/out/modules/ai-tools/index.js +1 -1
  33. package/out/modules/ai-tools/types.d.ts +1 -1
  34. package/out/modules/auth-guard/handlers/verify.d.ts +1 -1
  35. package/out/modules/auth-guard/index.js +1 -1
  36. package/out/modules/automation-action/handlers/execute.d.ts +1 -1
  37. package/out/modules/automation-action/handlers/execute.js +1 -1
  38. package/out/modules/automation-action/handlers/input-schema.d.ts +1 -1
  39. package/out/modules/automation-action/handlers/output-schema.d.ts +1 -1
  40. package/out/modules/automation-action/handlers/validate-settings.d.ts +1 -1
  41. package/out/modules/automation-action/handlers/validate-settings.js +1 -1
  42. package/out/modules/automation-action/index.js +1 -1
  43. package/out/modules/automation-action/types.d.ts +4 -4
  44. package/out/modules/automation-action/util/index.js +2 -5
  45. package/out/modules/context-menu/index.js +2 -2
  46. package/out/modules/custom-mt/handlers/translate.d.ts +1 -1
  47. package/out/modules/custom-mt/handlers/translate.js +25 -9
  48. package/out/modules/custom-mt/index.js +3 -3
  49. package/out/modules/custom-mt/types.d.ts +10 -2
  50. package/out/modules/custom-spell-check/handlers/get-languages-list.d.ts +1 -1
  51. package/out/modules/custom-spell-check/handlers/spell-check.d.ts +1 -1
  52. package/out/modules/custom-spell-check/index.js +4 -4
  53. package/out/modules/editor-right-panel/index.js +1 -1
  54. package/out/modules/external-qa-check/handlers/validate.d.ts +1 -1
  55. package/out/modules/external-qa-check/index.js +2 -2
  56. package/out/modules/file-processing/handlers/custom-file-format.d.ts +7 -2
  57. package/out/modules/file-processing/handlers/custom-file-format.js +62 -22
  58. package/out/modules/file-processing/handlers/file-download.d.ts +1 -1
  59. package/out/modules/file-processing/handlers/file-download.js +5 -0
  60. package/out/modules/file-processing/handlers/pre-post-process.d.ts +1 -1
  61. package/out/modules/file-processing/handlers/pre-post-process.js +41 -15
  62. package/out/modules/file-processing/handlers/translations-alignment.d.ts +1 -1
  63. package/out/modules/file-processing/handlers/translations-alignment.js +10 -4
  64. package/out/modules/file-processing/index.js +12 -2
  65. package/out/modules/file-processing/types.d.ts +36 -5
  66. package/out/modules/file-processing/util/defaults.js +50 -6
  67. package/out/modules/file-processing/util/files.js +2 -1
  68. package/out/modules/form-data-display.d.ts +1 -1
  69. package/out/modules/form-data-save.d.ts +1 -1
  70. package/out/modules/install.d.ts +1 -1
  71. package/out/modules/integration/handlers/crowdin-file-progress.d.ts +1 -1
  72. package/out/modules/integration/handlers/crowdin-file-progress.js +5 -1
  73. package/out/modules/integration/handlers/crowdin-files-target-languages.d.ts +5 -0
  74. package/out/modules/integration/handlers/crowdin-files-target-languages.js +103 -0
  75. package/out/modules/integration/handlers/crowdin-files.d.ts +1 -1
  76. package/out/modules/integration/handlers/crowdin-files.js +7 -1
  77. package/out/modules/integration/handlers/crowdin-project.d.ts +1 -1
  78. package/out/modules/integration/handlers/crowdin-update.d.ts +1 -1
  79. package/out/modules/integration/handlers/crowdin-update.js +59 -18
  80. package/out/modules/integration/handlers/crowdin-webhook.d.ts +1 -1
  81. package/out/modules/integration/handlers/crowdin-webhook.js +15 -8
  82. package/out/modules/integration/handlers/integration-data.d.ts +1 -1
  83. package/out/modules/integration/handlers/integration-data.js +13 -6
  84. package/out/modules/integration/handlers/integration-login.d.ts +1 -1
  85. package/out/modules/integration/handlers/integration-logout.d.ts +1 -1
  86. package/out/modules/integration/handlers/integration-logout.js +8 -3
  87. package/out/modules/integration/handlers/integration-update.d.ts +1 -1
  88. package/out/modules/integration/handlers/integration-update.js +44 -6
  89. package/out/modules/integration/handlers/integration-webhook.d.ts +1 -1
  90. package/out/modules/integration/handlers/invite-users.d.ts +1 -1
  91. package/out/modules/integration/handlers/job-cancel.d.ts +1 -1
  92. package/out/modules/integration/handlers/job-info-deprecated.d.ts +1 -1
  93. package/out/modules/integration/handlers/job-info-deprecated.js +3 -2
  94. package/out/modules/integration/handlers/job-info.d.ts +1 -1
  95. package/out/modules/integration/handlers/job-list.d.ts +1 -1
  96. package/out/modules/integration/handlers/main.d.ts +1 -1
  97. package/out/modules/integration/handlers/main.js +32 -2
  98. package/out/modules/integration/handlers/oauth-login.d.ts +1 -1
  99. package/out/modules/integration/handlers/oauth-login.js +28 -6
  100. package/out/modules/integration/handlers/oauth-polling.d.ts +1 -1
  101. package/out/modules/integration/handlers/oauth-url.d.ts +1 -1
  102. package/out/modules/integration/handlers/settings-save.d.ts +1 -1
  103. package/out/modules/integration/handlers/settings-save.js +9 -9
  104. package/out/modules/integration/handlers/settings.d.ts +1 -1
  105. package/out/modules/integration/handlers/sync-settings-save.d.ts +1 -1
  106. package/out/modules/integration/handlers/sync-settings-save.js +5 -9
  107. package/out/modules/integration/handlers/sync-settings.d.ts +1 -1
  108. package/out/modules/integration/handlers/user-errors.d.ts +1 -1
  109. package/out/modules/integration/handlers/users.d.ts +1 -1
  110. package/out/modules/integration/index.js +19 -33
  111. package/out/modules/integration/types.d.ts +133 -29
  112. package/out/modules/integration/types.js +1 -0
  113. package/out/modules/integration/util/cron.d.ts +2 -2
  114. package/out/modules/integration/util/cron.js +40 -24
  115. package/out/modules/integration/util/defaults.d.ts +4 -0
  116. package/out/modules/integration/util/defaults.js +175 -15
  117. package/out/modules/integration/util/files.d.ts +2 -1
  118. package/out/modules/integration/util/files.js +19 -8
  119. package/out/modules/integration/util/job.js +4 -3
  120. package/out/modules/integration/util/snapshot.js +19 -3
  121. package/out/modules/integration/util/types.d.ts +1 -0
  122. package/out/modules/integration/util/types.js +1 -0
  123. package/out/modules/integration/util/webhooks.d.ts +8 -8
  124. package/out/modules/integration/util/webhooks.js +34 -17
  125. package/out/modules/manifest.js +12 -12
  126. package/out/modules/modal/index.js +2 -2
  127. package/out/modules/organization-menu/index.js +5 -4
  128. package/out/modules/organization-settings-menu/index.js +5 -4
  129. package/out/modules/profile-resources-menu/index.js +5 -4
  130. package/out/modules/profile-settings-menu/index.js +5 -4
  131. package/out/modules/project-menu/index.js +1 -1
  132. package/out/modules/project-menu-crowdsource/index.js +1 -1
  133. package/out/modules/project-reports/index.js +3 -2
  134. package/out/modules/project-tools/index.js +3 -2
  135. package/out/modules/status.d.ts +1 -1
  136. package/out/modules/status.js +12 -3
  137. package/out/modules/subscription-paid.d.ts +1 -1
  138. package/out/modules/uninstall.d.ts +1 -1
  139. package/out/modules/uninstall.js +1 -1
  140. package/out/modules/webhooks/handlers/webhook-handler.d.ts +2 -2
  141. package/out/modules/webhooks/handlers/webhook-handler.js +33 -22
  142. package/out/modules/webhooks/types.d.ts +7 -0
  143. package/out/modules/workflow-step-type/handlers/delete-step.d.ts +1 -1
  144. package/out/modules/workflow-step-type/handlers/step-settings-save.d.ts +1 -1
  145. package/out/modules/workflow-step-type/index.js +2 -2
  146. package/out/modules/workflow-step-type/util/index.js +3 -6
  147. package/out/static/js/dependent.js +16 -7
  148. package/out/static/ui/error.bundle.js +474 -0
  149. package/out/static/ui/error.bundle.js.map +1 -0
  150. package/out/static/ui/install.bundle.js +459 -0
  151. package/out/static/ui/install.bundle.js.map +1 -0
  152. package/out/static/ui/login.bundle.js +630 -0
  153. package/out/static/ui/login.bundle.js.map +1 -0
  154. package/out/static/ui/main.bundle.js +2109 -0
  155. package/out/static/ui/main.bundle.js.map +1 -0
  156. package/out/static/ui/oauth.bundle.js +467 -0
  157. package/out/static/ui/oauth.bundle.js.map +1 -0
  158. package/out/storage/d1.d.ts +107 -0
  159. package/out/storage/d1.js +831 -0
  160. package/out/storage/index.js +8 -1
  161. package/out/storage/mysql.js +22 -19
  162. package/out/storage/postgre.d.ts +0 -1
  163. package/out/storage/postgre.js +20 -30
  164. package/out/storage/sqlite.d.ts +2 -5
  165. package/out/storage/sqlite.js +29 -69
  166. package/out/types.d.ts +78 -18
  167. package/out/util/connection.js +1 -1
  168. package/out/util/credentials-masker.d.ts +3 -3
  169. package/out/util/credentials-masker.js +14 -20
  170. package/out/util/cron.d.ts +29 -0
  171. package/out/util/cron.js +87 -0
  172. package/out/util/index.d.ts +14 -1
  173. package/out/util/index.js +121 -10
  174. package/out/util/jsx-renderer.d.ts +14 -0
  175. package/out/util/jsx-renderer.js +35 -0
  176. package/out/util/logger.d.ts +1 -0
  177. package/out/util/logger.js +2 -2
  178. package/out/util/static-files.d.ts +19 -0
  179. package/out/util/static-files.js +87 -0
  180. package/out/util/subscription.js +1 -1
  181. package/out/views/AboutPage.d.ts +10 -0
  182. package/out/views/AboutPage.js +76 -0
  183. package/out/views/FormPage.d.ts +14 -0
  184. package/out/views/FormPage.js +28 -0
  185. package/out/views/SubscriptionPage.d.ts +7 -0
  186. package/out/views/SubscriptionPage.js +26 -0
  187. package/out/views/index.d.ts +8 -0
  188. package/out/views/index.js +15 -0
  189. package/out/views/layout/Head.d.ts +9 -0
  190. package/out/views/layout/Head.js +54 -0
  191. package/package.json +43 -41
  192. package/out/util/handlebars.d.ts +0 -1
  193. package/out/util/handlebars.js +0 -46
  194. package/out/views/about.handlebars +0 -102
  195. package/out/views/error.handlebars +0 -54
  196. package/out/views/form.handlebars +0 -31
  197. package/out/views/install.handlebars +0 -16
  198. package/out/views/login.handlebars +0 -332
  199. package/out/views/main.handlebars +0 -2042
  200. package/out/views/oauth.handlebars +0 -11
  201. package/out/views/partials/head.handlebars +0 -53
  202. package/out/views/subscription.handlebars +0 -26
@@ -0,0 +1,831 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.D1Storage = void 0;
13
+ const types_1 = require("../modules/integration/util/types");
14
+ const crypto_1 = require("crypto");
15
+ class D1Storage {
16
+ constructor(config) {
17
+ this.migrated = false;
18
+ this.tables = {
19
+ crowdin_credentials: `(
20
+ id varchar not null primary key,
21
+ app_secret varchar null,
22
+ domain varchar null,
23
+ user_id varchar null,
24
+ agent_id varchar null,
25
+ organization_id varchar null,
26
+ base_url varchar null,
27
+ access_token varchar not null,
28
+ refresh_token varchar not null,
29
+ expire varchar not null,
30
+ type varchar not null
31
+ )`,
32
+ integration_credentials: `(
33
+ id varchar not null primary key,
34
+ credentials varchar not null,
35
+ crowdin_id varchar not null,
36
+ managers varchar null
37
+ )`,
38
+ sync_settings: `(
39
+ id integer not null primary key autoincrement,
40
+ files varchar null,
41
+ integration_id varchar not null,
42
+ crowdin_id varchar not null,
43
+ type varchar not null,
44
+ provider varchar not null
45
+ )`,
46
+ app_metadata: `(
47
+ id varchar not null primary key,
48
+ data varchar null,
49
+ crowdin_id varchar null
50
+ )`,
51
+ files_snapshot: `(
52
+ id integer not null primary key autoincrement,
53
+ integration_id varchar not null,
54
+ crowdin_id varchar not null,
55
+ files varchar null,
56
+ provider varchar not null
57
+ )`,
58
+ webhooks: `(
59
+ id integer not null primary key autoincrement,
60
+ file_id varchar not null,
61
+ integration_id varchar not null,
62
+ crowdin_id varchar not null,
63
+ provider varchar not null
64
+ )`,
65
+ user_errors: `(
66
+ id integer not null primary key autoincrement,
67
+ action varchar not null,
68
+ message varchar not null,
69
+ data varchar null,
70
+ created_at varchar not null,
71
+ crowdin_id varchar not null,
72
+ integration_id varchar null
73
+ )`,
74
+ integration_settings: `(
75
+ id integer not null primary key autoincrement,
76
+ integration_id varchar not null,
77
+ crowdin_id varchar not null,
78
+ config varchar null
79
+ )`,
80
+ job: `(
81
+ id varchar not null primary key,
82
+ integration_id varchar not null,
83
+ crowdin_id varchar not null,
84
+ type varchar not null,
85
+ title varchar null,
86
+ progress integer DEFAULT 0,
87
+ status varchar DEFAULT '${types_1.JobStatus.CREATED}',
88
+ payload varchar null,
89
+ info varchar null,
90
+ data varchar null,
91
+ attempt varchar DEFAULT 0,
92
+ errors varchar null,
93
+ processed_entities varchar null,
94
+ created_at varchar not null,
95
+ updated_at varchar null,
96
+ finished_at varchar null
97
+ )`,
98
+ translation_file_cache: `(
99
+ id integer not null primary key autoincrement,
100
+ integration_id varchar not null,
101
+ crowdin_id varchar not null,
102
+ file_id integer not null,
103
+ language_id varchar not null,
104
+ etag varchar
105
+ )`,
106
+ unsynced_files: `(
107
+ id integer not null primary key autoincrement,
108
+ integration_id varchar not null,
109
+ crowdin_id varchar not null,
110
+ files varchar null
111
+ )`,
112
+ synced_data: `(
113
+ id integer not null primary key autoincrement,
114
+ files varchar null,
115
+ integration_id varchar not null,
116
+ crowdin_id varchar not null,
117
+ type varchar not null,
118
+ updated_at varchar null
119
+ )`,
120
+ };
121
+ this.db = config.database;
122
+ }
123
+ ensureMigrated() {
124
+ return __awaiter(this, void 0, void 0, function* () {
125
+ if (!this.migrated) {
126
+ yield this.migrate();
127
+ this.migrated = true;
128
+ }
129
+ });
130
+ }
131
+ addColumn(tableName, column, defaultValue) {
132
+ return __awaiter(this, void 0, void 0, function* () {
133
+ const tableInfo = yield this.db.prepare(`PRAGMA table_info(${tableName})`).all();
134
+ const columns = tableInfo.results || [];
135
+ const exists = columns.some((columnInfo) => columnInfo.name === column);
136
+ if (!exists) {
137
+ yield this.db.prepare(`ALTER TABLE ${tableName} ADD COLUMN ${column} varchar ${defaultValue}`).run();
138
+ }
139
+ });
140
+ }
141
+ updateTables() {
142
+ return __awaiter(this, void 0, void 0, function* () {
143
+ yield this.addColumn('job', 'processed_entities', 'null');
144
+ });
145
+ }
146
+ migrate() {
147
+ return __awaiter(this, void 0, void 0, function* () {
148
+ try {
149
+ // Create all tables
150
+ const statements = [];
151
+ const tableEntries = Object.keys(this.tables).map((key) => [
152
+ key,
153
+ this.tables[key],
154
+ ]);
155
+ for (const [tableName, tableSchema] of tableEntries) {
156
+ statements.push(this.db.prepare(`CREATE TABLE IF NOT EXISTS ${tableName} ${tableSchema}`));
157
+ }
158
+ // Execute all table creation in batch
159
+ yield this.db.batch(statements);
160
+ // Update tables with new columns if needed
161
+ yield this.updateTables();
162
+ }
163
+ catch (e) {
164
+ console.error(e);
165
+ }
166
+ });
167
+ }
168
+ saveCrowdinCredentials(credentials) {
169
+ var _a, _b, _c;
170
+ return __awaiter(this, void 0, void 0, function* () {
171
+ yield this.db
172
+ .prepare('INSERT INTO crowdin_credentials(id, app_secret, domain, user_id, agent_id, organization_id, base_url, access_token, refresh_token, expire, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)')
173
+ .bind(...this.sanitizeBindValues(credentials.id, credentials.appSecret, credentials.domain, (_a = credentials.userId) === null || _a === void 0 ? void 0 : _a.toString(), (_b = credentials.agentId) === null || _b === void 0 ? void 0 : _b.toString(), (_c = credentials.organizationId) === null || _c === void 0 ? void 0 : _c.toString(), credentials.baseUrl, credentials.accessToken, credentials.refreshToken, credentials.expire, credentials.type))
174
+ .run();
175
+ });
176
+ }
177
+ updateCrowdinCredentials(credentials) {
178
+ var _a, _b, _c;
179
+ return __awaiter(this, void 0, void 0, function* () {
180
+ yield this.db
181
+ .prepare('UPDATE crowdin_credentials SET app_secret = ?, domain = ?, user_id = ?, agent_id = ?, organization_id = ?, base_url = ?, access_token = ?, refresh_token = ?, expire = ? WHERE id = ?')
182
+ .bind(...this.sanitizeBindValues(credentials.appSecret, credentials.domain, (_a = credentials.userId) === null || _a === void 0 ? void 0 : _a.toString(), (_b = credentials.agentId) === null || _b === void 0 ? void 0 : _b.toString(), (_c = credentials.organizationId) === null || _c === void 0 ? void 0 : _c.toString(), credentials.baseUrl, credentials.accessToken, credentials.refreshToken, credentials.expire, credentials.id))
183
+ .run();
184
+ });
185
+ }
186
+ getCrowdinCredentials(id) {
187
+ return __awaiter(this, void 0, void 0, function* () {
188
+ const row = yield this.db
189
+ .prepare('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 = ?')
190
+ .bind(id)
191
+ .first();
192
+ if (row) {
193
+ return Object.assign(Object.assign({}, row), { userId: row.userId ? parseInt(row.userId, 10) : row.userId, agentId: row.agentId ? parseInt(row.agentId, 10) : row.agentId, organizationId: row.organizationId ? parseInt(row.organizationId, 10) : row.organizationId });
194
+ }
195
+ });
196
+ }
197
+ getAllCrowdinCredentials() {
198
+ return __awaiter(this, void 0, void 0, function* () {
199
+ const result = yield this.db
200
+ .prepare('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')
201
+ .all();
202
+ return (result.results || []).map((row) => (Object.assign(Object.assign({}, row), { userId: row.userId ? parseInt(row.userId, 10) : row.userId, agentId: row.agentId ? parseInt(row.agentId, 10) : row.agentId, organizationId: row.organizationId ? parseInt(row.organizationId, 10) : row.organizationId })));
203
+ });
204
+ }
205
+ deleteCrowdinCredentials(id) {
206
+ return __awaiter(this, void 0, void 0, function* () {
207
+ const statements = [
208
+ this.db.prepare('DELETE FROM crowdin_credentials WHERE id = ?').bind(id),
209
+ this.db.prepare('DELETE FROM integration_credentials WHERE crowdin_id = ?').bind(id),
210
+ this.db.prepare('DELETE FROM sync_settings WHERE crowdin_id = ?').bind(id),
211
+ this.db.prepare('DELETE FROM app_metadata WHERE crowdin_id = ?').bind(id),
212
+ this.db.prepare('DELETE FROM files_snapshot WHERE crowdin_id = ?').bind(id),
213
+ this.db.prepare('DELETE FROM webhooks WHERE crowdin_id = ?').bind(id),
214
+ this.db.prepare('DELETE FROM user_errors WHERE crowdin_id = ?').bind(id),
215
+ this.db.prepare('DELETE FROM integration_settings WHERE crowdin_id = ?').bind(id),
216
+ this.db.prepare('DELETE FROM job WHERE crowdin_id = ?').bind(id),
217
+ this.db.prepare('DELETE FROM translation_file_cache WHERE crowdin_id = ?').bind(id),
218
+ this.db.prepare('DELETE FROM unsynced_files WHERE crowdin_id = ?').bind(id),
219
+ this.db.prepare('DELETE FROM synced_data WHERE crowdin_id = ?').bind(id),
220
+ ];
221
+ yield this.db.batch(statements);
222
+ });
223
+ }
224
+ saveIntegrationCredentials(id, credentials, crowdinId) {
225
+ return __awaiter(this, void 0, void 0, function* () {
226
+ yield this.db
227
+ .prepare('INSERT INTO integration_credentials(id, credentials, crowdin_id) VALUES (?, ?, ?)')
228
+ .bind(id, credentials, crowdinId)
229
+ .run();
230
+ });
231
+ }
232
+ updateIntegrationCredentials(id, credentials) {
233
+ return __awaiter(this, void 0, void 0, function* () {
234
+ yield this.db
235
+ .prepare('UPDATE integration_credentials SET credentials = ? WHERE id = ?')
236
+ .bind(credentials, id)
237
+ .run();
238
+ });
239
+ }
240
+ updateIntegrationManagers(id, managers) {
241
+ return __awaiter(this, void 0, void 0, function* () {
242
+ yield this.db.prepare('UPDATE integration_credentials SET managers = ? WHERE id = ?').bind(managers, id).run();
243
+ });
244
+ }
245
+ getIntegrationCredentials(id) {
246
+ return __awaiter(this, void 0, void 0, function* () {
247
+ const row = yield this.db
248
+ .prepare('SELECT id, credentials, crowdin_id as crowdinId, managers FROM integration_credentials WHERE id = ?')
249
+ .bind(id)
250
+ .first();
251
+ if (row) {
252
+ return row;
253
+ }
254
+ });
255
+ }
256
+ getAllIntegrationCredentials(crowdinId) {
257
+ return __awaiter(this, void 0, void 0, function* () {
258
+ const result = yield this.db
259
+ .prepare('SELECT id, credentials, crowdin_id as crowdinId, managers FROM integration_credentials WHERE crowdin_id = ?')
260
+ .bind(crowdinId)
261
+ .all();
262
+ return result.results || [];
263
+ });
264
+ }
265
+ deleteIntegrationCredentials(id) {
266
+ return __awaiter(this, void 0, void 0, function* () {
267
+ const statements = [
268
+ this.db.prepare('DELETE FROM integration_credentials WHERE id = ?').bind(id),
269
+ this.db.prepare('DELETE FROM sync_settings WHERE integration_id = ?').bind(id),
270
+ this.db.prepare('DELETE FROM files_snapshot WHERE integration_id = ?').bind(id),
271
+ this.db.prepare('DELETE FROM webhooks WHERE integration_id = ?').bind(id),
272
+ this.db.prepare('DELETE FROM user_errors WHERE integration_id = ?').bind(id),
273
+ this.db.prepare('DELETE FROM integration_settings WHERE integration_id = ?').bind(id),
274
+ this.db.prepare('DELETE FROM job WHERE integration_id = ?').bind(id),
275
+ this.db.prepare('DELETE FROM translation_file_cache WHERE integration_id = ?').bind(id),
276
+ this.db.prepare('DELETE FROM unsynced_files WHERE integration_id = ?').bind(id),
277
+ this.db.prepare('DELETE FROM synced_data WHERE integration_id = ?').bind(id),
278
+ ];
279
+ yield this.db.batch(statements);
280
+ });
281
+ }
282
+ deleteAllIntegrationCredentials(crowdinId) {
283
+ return __awaiter(this, void 0, void 0, function* () {
284
+ const statements = [
285
+ this.db.prepare('DELETE FROM integration_credentials WHERE crowdin_id = ?').bind(crowdinId),
286
+ this.db.prepare('DELETE FROM sync_settings WHERE crowdin_id = ?').bind(crowdinId),
287
+ this.db.prepare('DELETE FROM files_snapshot WHERE crowdin_id = ?').bind(crowdinId),
288
+ this.db.prepare('DELETE FROM webhooks WHERE crowdin_id = ?').bind(crowdinId),
289
+ this.db.prepare('DELETE FROM user_errors WHERE crowdin_id = ?').bind(crowdinId),
290
+ this.db.prepare('DELETE FROM job WHERE crowdin_id = ?').bind(crowdinId),
291
+ this.db.prepare('DELETE FROM unsynced_files WHERE crowdin_id = ?').bind(crowdinId),
292
+ this.db.prepare('DELETE FROM synced_data WHERE crowdin_id = ?').bind(crowdinId),
293
+ ];
294
+ yield this.db.batch(statements);
295
+ });
296
+ }
297
+ saveMetadata(id, metadata, crowdinId) {
298
+ return __awaiter(this, void 0, void 0, function* () {
299
+ yield this.db
300
+ .prepare('INSERT INTO app_metadata(id, data, crowdin_id) VALUES (?, ?, ?)')
301
+ .bind(id, JSON.stringify(metadata), crowdinId)
302
+ .run();
303
+ });
304
+ }
305
+ updateMetadata(id, metadata, crowdinId) {
306
+ return __awaiter(this, void 0, void 0, function* () {
307
+ yield this.db
308
+ .prepare('UPDATE app_metadata SET data = ?, crowdin_id = ? WHERE id = ?')
309
+ .bind(JSON.stringify(metadata), crowdinId, id)
310
+ .run();
311
+ });
312
+ }
313
+ getMetadata(id) {
314
+ return __awaiter(this, void 0, void 0, function* () {
315
+ const result = yield this.db.prepare('SELECT data FROM app_metadata WHERE id = ?').bind(id).first();
316
+ return (result === null || result === void 0 ? void 0 : result.data) ? JSON.parse(result.data) : undefined;
317
+ });
318
+ }
319
+ getAllMetadata() {
320
+ return __awaiter(this, void 0, void 0, function* () {
321
+ const result = yield this.db.prepare('SELECT * FROM app_metadata').all();
322
+ return result.results || [];
323
+ });
324
+ }
325
+ deleteMetadata(id) {
326
+ return __awaiter(this, void 0, void 0, function* () {
327
+ yield this.db.prepare('DELETE FROM app_metadata WHERE id = ?').bind(id).run();
328
+ });
329
+ }
330
+ getSyncSettingsByProvider(integrationId, provider) {
331
+ return __awaiter(this, void 0, void 0, function* () {
332
+ const row = yield this.db
333
+ .prepare('SELECT id, files, integration_id as integrationId, crowdin_id as crowdinId, type, provider FROM sync_settings WHERE integration_id = ? AND provider = ?')
334
+ .bind(integrationId, provider)
335
+ .first();
336
+ if (row) {
337
+ return row;
338
+ }
339
+ });
340
+ }
341
+ getSyncSettingsBySchedule(type, schedule) {
342
+ return __awaiter(this, void 0, void 0, function* () {
343
+ const result = yield this.db
344
+ .prepare(`
345
+ SELECT s.id, s.files, s.integration_id as integrationId, s.crowdin_id as crowdinId, s.type, s.provider
346
+ FROM sync_settings s
347
+ INNER JOIN integration_settings i ON s.integration_id = i.integration_id
348
+ WHERE s.type = ?
349
+ AND CASE
350
+ WHEN i.config IS NULL THEN 0
351
+ ELSE json_extract(i.config, '$.schedule') = ?
352
+ END
353
+ `)
354
+ .bind(type, schedule)
355
+ .all();
356
+ return result.results || [];
357
+ });
358
+ }
359
+ saveSyncSettings(files, integrationId, crowdinId, type, provider) {
360
+ return __awaiter(this, void 0, void 0, function* () {
361
+ yield this.db
362
+ .prepare('INSERT INTO sync_settings(files, integration_id, crowdin_id, type, provider) VALUES (?, ?, ?, ?, ?)')
363
+ .bind(files, integrationId, crowdinId, type, provider)
364
+ .run();
365
+ });
366
+ }
367
+ updateSyncSettings(files, integrationId, crowdinId, type, provider) {
368
+ return __awaiter(this, void 0, void 0, function* () {
369
+ yield this.db
370
+ .prepare('UPDATE sync_settings SET files = ? WHERE integration_id = ? AND crowdin_id = ? AND type = ? AND provider = ?')
371
+ .bind(files, integrationId, crowdinId, type, provider)
372
+ .run();
373
+ });
374
+ }
375
+ getSyncSettings(integrationId, crowdinId, type, provider) {
376
+ return __awaiter(this, void 0, void 0, function* () {
377
+ const row = yield this.db
378
+ .prepare('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 = ?')
379
+ .bind(integrationId, crowdinId, type, provider)
380
+ .first();
381
+ if (row) {
382
+ return row;
383
+ }
384
+ });
385
+ }
386
+ saveFilesSnapshot(files, integrationId, crowdinId, provider) {
387
+ return __awaiter(this, void 0, void 0, function* () {
388
+ yield this.db
389
+ .prepare('INSERT INTO files_snapshot(files, integration_id, crowdin_id, provider) VALUES (?, ?, ?, ?)')
390
+ .bind(files, integrationId, crowdinId, provider)
391
+ .run();
392
+ });
393
+ }
394
+ updateFilesSnapshot(files, integrationId, crowdinId, provider) {
395
+ return __awaiter(this, void 0, void 0, function* () {
396
+ yield this.db
397
+ .prepare('UPDATE files_snapshot SET files = ? WHERE integration_id = ? AND crowdin_id = ? AND provider = ? ')
398
+ .bind(files, integrationId, crowdinId, provider)
399
+ .run();
400
+ });
401
+ }
402
+ getFilesSnapshot(integrationId, crowdinId, provider) {
403
+ return __awaiter(this, void 0, void 0, function* () {
404
+ const row = yield this.db
405
+ .prepare('SELECT id, files, integration_id as integrationId, crowdin_id as crowdinId, provider FROM files_snapshot WHERE integration_id = ? AND crowdin_id = ? AND provider = ?')
406
+ .bind(integrationId, crowdinId, provider)
407
+ .first();
408
+ if (row) {
409
+ return row;
410
+ }
411
+ });
412
+ }
413
+ getAllWebhooks(integrationId, crowdinId, provider) {
414
+ return __awaiter(this, void 0, void 0, function* () {
415
+ const result = yield this.db
416
+ .prepare('SELECT id, file_id as fileId, integration_id as integrationId, crowdin_id as crowdinId, provider FROM webhooks WHERE integration_id = ? AND crowdin_id = ? AND provider = ?')
417
+ .bind(integrationId, crowdinId, provider)
418
+ .all();
419
+ return result.results || [];
420
+ });
421
+ }
422
+ getWebhooks(fileId, integrationId, crowdinId, provider) {
423
+ return __awaiter(this, void 0, void 0, function* () {
424
+ const row = yield this.db
425
+ .prepare('SELECT id, file_id as fileId, integration_id as integrationId, crowdin_id as crowdinId, provider FROM webhooks WHERE file_id = ? AND integration_id = ? AND crowdin_id = ? AND provider = ?')
426
+ .bind(fileId, integrationId, crowdinId, provider)
427
+ .first();
428
+ if (row) {
429
+ return row;
430
+ }
431
+ });
432
+ }
433
+ saveWebhooks(fileId, integrationId, crowdinId, provider) {
434
+ return __awaiter(this, void 0, void 0, function* () {
435
+ yield this.db
436
+ .prepare('INSERT INTO webhooks(file_id, integration_id, crowdin_id, provider) VALUES (?, ?, ?, ?)')
437
+ .bind(fileId, integrationId, crowdinId, provider)
438
+ .run();
439
+ });
440
+ }
441
+ deleteWebhooks(fileIds, integrationId, crowdinId, provider) {
442
+ return __awaiter(this, void 0, void 0, function* () {
443
+ if (fileIds.length === 0) {
444
+ return;
445
+ }
446
+ const placeholders = fileIds.map(() => '?').join(',');
447
+ yield this.db
448
+ .prepare(`DELETE FROM webhooks WHERE file_id IN (${placeholders}) AND integration_id = ? AND crowdin_id = ? AND provider = ?`)
449
+ .bind(...fileIds, integrationId, crowdinId, provider)
450
+ .run();
451
+ });
452
+ }
453
+ getAllUserErrors(crowdinId, integrationId) {
454
+ return __awaiter(this, void 0, void 0, function* () {
455
+ let whereIntegrationCondition = 'integration_id is NULL';
456
+ const params = [crowdinId];
457
+ if (integrationId) {
458
+ whereIntegrationCondition = 'integration_id = ?';
459
+ params.push(integrationId);
460
+ }
461
+ const result = yield this.db
462
+ .prepare(`SELECT id, action, message, data, created_at as createdAt, integration_id as integrationId, crowdin_id as crowdinId FROM user_errors WHERE crowdin_id = ? AND ${whereIntegrationCondition}`)
463
+ .bind(...this.sanitizeBindValues(...params))
464
+ .all();
465
+ return result.results || [];
466
+ });
467
+ }
468
+ saveUserError(action, message, data, createdAt, crowdinId, integrationId) {
469
+ return __awaiter(this, void 0, void 0, function* () {
470
+ yield this.db
471
+ .prepare('INSERT INTO user_errors(action, message, data, created_at, integration_id, crowdin_id) VALUES (?, ?, ?, ?, ?, ?)')
472
+ .bind(...this.sanitizeBindValues(action, message, data, createdAt, integrationId, crowdinId))
473
+ .run();
474
+ });
475
+ }
476
+ deleteUserErrors(date, crowdinId, integrationId) {
477
+ return __awaiter(this, void 0, void 0, function* () {
478
+ let whereIntegrationCondition = 'integration_id is NULL';
479
+ const params = [date, crowdinId];
480
+ if (integrationId) {
481
+ whereIntegrationCondition = 'integration_id = ?';
482
+ params.push(integrationId);
483
+ }
484
+ yield this.db
485
+ .prepare(`DELETE FROM user_errors WHERE created_at < ? AND crowdin_id = ? AND ${whereIntegrationCondition}`)
486
+ .bind(...this.sanitizeBindValues(...params))
487
+ .run();
488
+ });
489
+ }
490
+ deleteAllUsersErrorsOlderThan(date) {
491
+ return __awaiter(this, void 0, void 0, function* () {
492
+ yield this.db.prepare('DELETE FROM user_errors WHERE created_at < ?').bind(date).run();
493
+ });
494
+ }
495
+ saveIntegrationConfig(integrationId, crowdinId, config) {
496
+ return __awaiter(this, void 0, void 0, function* () {
497
+ yield this.db
498
+ .prepare('INSERT INTO integration_settings(integration_id, crowdin_id, config) VALUES (?, ?, ?)')
499
+ .bind(integrationId, crowdinId, config)
500
+ .run();
501
+ });
502
+ }
503
+ getAllIntegrationConfigs(crowdinId) {
504
+ return __awaiter(this, void 0, void 0, function* () {
505
+ const result = yield this.db
506
+ .prepare('SELECT config, integration_id as integrationId FROM integration_settings WHERE crowdin_id = ?')
507
+ .bind(crowdinId)
508
+ .all();
509
+ return result.results || [];
510
+ });
511
+ }
512
+ getIntegrationConfig(integrationId) {
513
+ return __awaiter(this, void 0, void 0, function* () {
514
+ const row = yield this.db
515
+ .prepare('SELECT config FROM integration_settings WHERE integration_id = ?')
516
+ .bind(integrationId)
517
+ .first();
518
+ if (row) {
519
+ return row;
520
+ }
521
+ });
522
+ }
523
+ updateIntegrationConfig(integrationId, config) {
524
+ return __awaiter(this, void 0, void 0, function* () {
525
+ yield this.db
526
+ .prepare('UPDATE integration_settings SET config = ? WHERE integration_id = ?')
527
+ .bind(config, integrationId)
528
+ .run();
529
+ });
530
+ }
531
+ createJob(params) {
532
+ return __awaiter(this, void 0, void 0, function* () {
533
+ const id = (0, crypto_1.randomUUID)();
534
+ yield this.db
535
+ .prepare('INSERT INTO job(id, integration_id, crowdin_id, type, payload, title, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)')
536
+ .bind(id, params.integrationId, params.crowdinId, params.type, params.payload, params.title, Date.now().toString())
537
+ .run();
538
+ return id;
539
+ });
540
+ }
541
+ updateJob(params) {
542
+ return __awaiter(this, void 0, void 0, function* () {
543
+ const updateFields = ['updated_at = ?'];
544
+ const updateParams = [Date.now().toString()];
545
+ if (params.progress) {
546
+ updateFields.push('progress = ?');
547
+ updateParams.push(Math.round(params.progress));
548
+ if (params.progress >= 100) {
549
+ updateFields.push('finished_at = ?');
550
+ updateParams.push(Date.now().toString());
551
+ }
552
+ }
553
+ if (params.status) {
554
+ updateFields.push('status = ?');
555
+ updateParams.push(params.status);
556
+ if (!updateFields.includes('finished_at = ?') &&
557
+ [types_1.JobStatus.FAILED, types_1.JobStatus.CANCELED].includes(params.status)) {
558
+ updateFields.push('finished_at = ?');
559
+ updateParams.push(Date.now().toString());
560
+ }
561
+ }
562
+ if (params.data) {
563
+ updateFields.push('data = ?');
564
+ updateParams.push(params.data);
565
+ }
566
+ if (params.info) {
567
+ updateFields.push('info = ?');
568
+ updateParams.push(params.info);
569
+ }
570
+ if (params.attempt) {
571
+ updateFields.push('attempt = ?');
572
+ updateParams.push(params.attempt);
573
+ }
574
+ if (params.errors) {
575
+ updateFields.push('errors = ?');
576
+ updateParams.push(JSON.stringify(params.errors));
577
+ }
578
+ if (params.processedEntities) {
579
+ updateFields.push('processed_entities = ?');
580
+ updateParams.push(params.processedEntities);
581
+ }
582
+ updateParams.push(params.id);
583
+ const query = `UPDATE job SET ${updateFields.join(', ')} WHERE id = ?`;
584
+ yield this.db
585
+ .prepare(query)
586
+ .bind(...updateParams)
587
+ .run();
588
+ });
589
+ }
590
+ getJob(params) {
591
+ return __awaiter(this, void 0, void 0, function* () {
592
+ const row = yield this.db
593
+ .prepare(`
594
+ SELECT id, integration_id as integrationId, crowdin_id as crowdinId, type, payload, progress, status,
595
+ title, info, data, attempt, errors, processed_entities as processedEntities, created_at as createdAt, updated_at as updatedAt, finished_at as finishedAt
596
+ FROM job
597
+ WHERE id = ?
598
+ `)
599
+ .bind(params.id)
600
+ .first();
601
+ if (row) {
602
+ return row;
603
+ }
604
+ });
605
+ }
606
+ getActiveJobs(params) {
607
+ return __awaiter(this, void 0, void 0, function* () {
608
+ const result = yield this.db
609
+ .prepare(`
610
+ 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
611
+ FROM job
612
+ WHERE integration_id = ? AND crowdin_id = ? AND finished_at is NULL
613
+ `)
614
+ .bind(params.integrationId, params.crowdinId)
615
+ .all();
616
+ return result.results || [];
617
+ });
618
+ }
619
+ deleteFinishedJobs() {
620
+ return __awaiter(this, void 0, void 0, function* () {
621
+ yield this.db.prepare('DELETE FROM job WHERE finished_at IS NOT NULL').run();
622
+ });
623
+ }
624
+ getAllInProgressJobs() {
625
+ return __awaiter(this, void 0, void 0, function* () {
626
+ const result = yield this.db
627
+ .prepare(`
628
+ 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
629
+ FROM job
630
+ WHERE status IN (?,?) AND finished_at is NULL
631
+ `)
632
+ .bind(types_1.JobStatus.IN_PROGRESS, types_1.JobStatus.CREATED)
633
+ .all();
634
+ return result.results || [];
635
+ });
636
+ }
637
+ getAllJobs(params) {
638
+ return __awaiter(this, void 0, void 0, function* () {
639
+ const result = yield this.db
640
+ .prepare(`
641
+ SELECT
642
+ id,
643
+ integration_id as integrationId,
644
+ crowdin_id as crowdinId,
645
+ type,
646
+ payload,
647
+ progress,
648
+ status,
649
+ title,
650
+ info,
651
+ data,
652
+ attempt,
653
+ created_at as createdAt,
654
+ updated_at as updatedAt,
655
+ finished_at as finishedAt
656
+ FROM job
657
+ WHERE integration_id = ? AND crowdin_id = ?
658
+ ORDER BY created_at DESC
659
+ LIMIT ? OFFSET ?
660
+ `)
661
+ .bind(params.integrationId, params.crowdinId, params.limit, params.offset)
662
+ .all();
663
+ return result.results || [];
664
+ });
665
+ }
666
+ saveTranslationCache(params) {
667
+ return __awaiter(this, void 0, void 0, function* () {
668
+ yield this.db
669
+ .prepare('INSERT INTO translation_file_cache(integration_id, crowdin_id, file_id, language_id, etag) VALUES (?, ?, ?, ?, ?)')
670
+ .bind(params.integrationId, params.crowdinId, params.fileId, params.languageId, params.etag)
671
+ .run();
672
+ });
673
+ }
674
+ getFileTranslationCache(params) {
675
+ return __awaiter(this, void 0, void 0, function* () {
676
+ const result = yield this.db
677
+ .prepare(`
678
+ SELECT integration_id as integrationId, crowdin_id as crowdinId, file_id as fileId, language_id as languageId, etag
679
+ FROM translation_file_cache
680
+ WHERE integration_id = ? AND crowdin_id = ? AND file_id = ?
681
+ `)
682
+ .bind(params.integrationId, params.crowdinId, params.fileId)
683
+ .all();
684
+ return result.results || [];
685
+ });
686
+ }
687
+ getFileTranslationCacheByLanguage(params) {
688
+ return __awaiter(this, void 0, void 0, function* () {
689
+ const row = yield this.db
690
+ .prepare(`
691
+ SELECT integration_id as integrationId, crowdin_id as crowdinId, file_id as fileId, language_id as languageId, etag
692
+ FROM translation_file_cache
693
+ WHERE integration_id = ? AND crowdin_id = ? AND file_id = ? AND language_id = ?
694
+ `)
695
+ .bind(params.integrationId, params.crowdinId, params.fileId, params.languageId)
696
+ .first();
697
+ if (row) {
698
+ return row;
699
+ }
700
+ });
701
+ }
702
+ updateTranslationCache(params) {
703
+ return __awaiter(this, void 0, void 0, function* () {
704
+ yield this.db
705
+ .prepare('UPDATE translation_file_cache SET etag = ? WHERE integration_id = ? AND crowdin_id = ? AND file_id = ? AND language_id = ?')
706
+ .bind(params.etag, params.integrationId, params.crowdinId, params.fileId, params.languageId)
707
+ .run();
708
+ });
709
+ }
710
+ saveUnsyncedFiles(params) {
711
+ return __awaiter(this, void 0, void 0, function* () {
712
+ yield this.db
713
+ .prepare('INSERT INTO unsynced_files(integration_id, crowdin_id, files) VALUES (?, ?, ?)')
714
+ .bind(params.integrationId, params.crowdinId, params.files)
715
+ .run();
716
+ });
717
+ }
718
+ updateUnsyncedFiles(params) {
719
+ return __awaiter(this, void 0, void 0, function* () {
720
+ yield this.db
721
+ .prepare('UPDATE unsynced_files SET files = ? WHERE integration_id = ? AND crowdin_id = ?')
722
+ .bind(params.files, params.integrationId, params.crowdinId)
723
+ .run();
724
+ });
725
+ }
726
+ getUnsyncedFiles(params) {
727
+ return __awaiter(this, void 0, void 0, function* () {
728
+ const row = yield this.db
729
+ .prepare('SELECT files FROM unsynced_files WHERE integration_id = ? AND crowdin_id = ?')
730
+ .bind(params.integrationId, params.crowdinId)
731
+ .first();
732
+ if (row) {
733
+ return row;
734
+ }
735
+ });
736
+ }
737
+ registerCustomTable(tableName, schema) {
738
+ return __awaiter(this, void 0, void 0, function* () {
739
+ const schemaKeys = Object.keys(schema);
740
+ const columns = schemaKeys.map((name) => `${name} ${schema[name]}`).join(', ');
741
+ yield this.db.prepare(`CREATE TABLE IF NOT EXISTS ${tableName} (${columns})`).run();
742
+ });
743
+ }
744
+ insertRecord(tableName, data) {
745
+ return __awaiter(this, void 0, void 0, function* () {
746
+ const keys = Object.keys(data);
747
+ const columns = keys.join(', ');
748
+ const placeholders = keys.map(() => '?').join(', ');
749
+ const values = keys.map((key) => data[key]);
750
+ yield this.db
751
+ .prepare(`INSERT INTO ${tableName} (${columns}) VALUES (${placeholders})`)
752
+ .bind(...this.sanitizeBindValues(...values))
753
+ .run();
754
+ });
755
+ }
756
+ selectRecords(tableName, options = {}, params = []) {
757
+ var _a;
758
+ return __awaiter(this, void 0, void 0, function* () {
759
+ const columns = ((_a = options.columns) === null || _a === void 0 ? void 0 : _a.length) ? options.columns.join(', ') : '*';
760
+ const distinctKeyword = options.distinct ? 'DISTINCT ' : '';
761
+ const whereClause = options.whereClause ? ` ${options.whereClause}` : '';
762
+ const orderByClause = options.orderBy ? ` ORDER BY ${options.orderBy}` : '';
763
+ const limitClause = options.limit ? ` LIMIT ${options.limit}` : '';
764
+ const offsetClause = options.offset ? ` OFFSET ${options.offset}` : '';
765
+ const query = `SELECT ${distinctKeyword}${columns} FROM ${tableName}${whereClause}${orderByClause}${limitClause}${offsetClause};`;
766
+ const stmt = this.db.prepare(query);
767
+ const result = params.length > 0 ? yield stmt.bind(...this.sanitizeBindValues(...params)).all() : yield stmt.all();
768
+ return result.results || [];
769
+ });
770
+ }
771
+ updateRecord(tableName, data, whereClause, params = []) {
772
+ return __awaiter(this, void 0, void 0, function* () {
773
+ const setClause = Object.keys(data)
774
+ .map((key) => `${key} = ?`)
775
+ .join(', ');
776
+ const values = Object.values(data);
777
+ const query = `UPDATE ${tableName} SET ${setClause} ${whereClause};`;
778
+ yield this.db
779
+ .prepare(query)
780
+ .bind(...this.sanitizeBindValues(...values, ...params))
781
+ .run();
782
+ });
783
+ }
784
+ deleteRecord(tableName, whereClause, params = []) {
785
+ return __awaiter(this, void 0, void 0, function* () {
786
+ const query = `DELETE FROM ${tableName} ${whereClause};`;
787
+ const stmt = this.db.prepare(query);
788
+ if (params.length > 0) {
789
+ yield stmt.bind(...this.sanitizeBindValues(...params)).run();
790
+ }
791
+ else {
792
+ yield stmt.run();
793
+ }
794
+ });
795
+ }
796
+ saveSyncedData(files, integrationId, crowdinId, type) {
797
+ return __awaiter(this, void 0, void 0, function* () {
798
+ yield this.db
799
+ .prepare('INSERT INTO synced_data(files, integration_id, crowdin_id, type, updated_at) VALUES (?, ?, ?, ?, ?)')
800
+ .bind(files, integrationId, crowdinId, type, Date.now().toString())
801
+ .run();
802
+ });
803
+ }
804
+ updateSyncedData(files, integrationId, crowdinId, type) {
805
+ return __awaiter(this, void 0, void 0, function* () {
806
+ yield this.db
807
+ .prepare('UPDATE synced_data SET files = ?, updated_at = ? WHERE integration_id = ? AND crowdin_id = ? AND type = ?')
808
+ .bind(files, Date.now().toString(), integrationId, crowdinId, type)
809
+ .run();
810
+ });
811
+ }
812
+ getSyncedData(integrationId, crowdinId, type) {
813
+ return __awaiter(this, void 0, void 0, function* () {
814
+ const row = yield this.db
815
+ .prepare('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 = ?')
816
+ .bind(integrationId, crowdinId, type)
817
+ .first();
818
+ if (row) {
819
+ return row;
820
+ }
821
+ });
822
+ }
823
+ /**
824
+ * Converts undefined values to null for D1 compatibility
825
+ * D1 does not support undefined values, so we convert them to null
826
+ */
827
+ sanitizeBindValues(...values) {
828
+ return values.map((v) => (v === undefined ? null : v));
829
+ }
830
+ }
831
+ exports.D1Storage = D1Storage;