@coopenomics/notifications 2026.5.30-3 → 2026.7.17-3
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/build.config.ts +1 -9
- package/dist/index.cjs +3248 -14
- package/dist/index.d.cts +479 -280
- package/dist/index.d.mts +479 -280
- package/dist/index.d.ts +479 -280
- package/dist/index.mjs +3239 -5
- package/package.json +3 -11
- package/src/workflows/approval-request/index.ts +1 -1
- package/src/workflows/expense-advance-report-reminder/index.ts +58 -0
- package/src/workflows/index.ts +9 -0
- package/src/workflows/membership-exit-confirmation/index.ts +38 -0
- package/src/workflows/new-agenda-item/index.ts +1 -1
- package/src/workflows/payment-refunded/index.ts +51 -0
- package/dist/shared/notifications.3e0dd08c.mjs +0 -3138
- package/dist/shared/notifications.8406132d.cjs +0 -3149
- package/dist/shared/notifications.d7ceb56f.d.cts +0 -98
- package/dist/shared/notifications.d7ceb56f.d.mts +0 -98
- package/dist/shared/notifications.d7ceb56f.d.ts +0 -98
- package/dist/sync/sync-runner.cjs +0 -7288
- package/dist/sync/sync-runner.d.cts +0 -48
- package/dist/sync/sync-runner.d.mts +0 -48
- package/dist/sync/sync-runner.d.ts +0 -48
- package/dist/sync/sync-runner.mjs +0 -7273
- package/src/sync/novu-sync.service.ts +0 -246
- package/src/sync/sync-runner.ts +0 -154
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
import axios, { AxiosInstance } from 'axios';
|
|
2
|
-
import {
|
|
3
|
-
Types,
|
|
4
|
-
Workflows
|
|
5
|
-
} from '../index';
|
|
6
|
-
|
|
7
|
-
export interface NovuSyncConfig {
|
|
8
|
-
apiKey: string;
|
|
9
|
-
apiUrl: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export class NovuSyncService {
|
|
13
|
-
private readonly client: AxiosInstance;
|
|
14
|
-
private readonly config: NovuSyncConfig;
|
|
15
|
-
|
|
16
|
-
constructor(config: NovuSyncConfig) {
|
|
17
|
-
this.config = config;
|
|
18
|
-
|
|
19
|
-
if (!this.config.apiKey) {
|
|
20
|
-
throw new Error('NOVU_API_KEY is required');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (!this.config.apiUrl) {
|
|
24
|
-
throw new Error('NOVU_API_URL is required');
|
|
25
|
-
}
|
|
26
|
-
this.client = axios.create({
|
|
27
|
-
baseURL: this.config.apiUrl,
|
|
28
|
-
headers: {
|
|
29
|
-
'Authorization': `ApiKey ${this.config.apiKey}`,
|
|
30
|
-
'Content-Type': 'application/json',
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Получить информацию о воркфлоу
|
|
37
|
-
*/
|
|
38
|
-
async getWorkflow(workflowId: string): Promise<any> {
|
|
39
|
-
try {
|
|
40
|
-
const response = await this.client.get(`/v2/workflows/${workflowId}`);
|
|
41
|
-
return response.data;
|
|
42
|
-
} catch (error: any) {
|
|
43
|
-
if (error.response?.status === 404) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
throw error;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Получить список всех воркфлоу
|
|
52
|
-
*/
|
|
53
|
-
async getAllWorkflows(): Promise<any[]> {
|
|
54
|
-
try {
|
|
55
|
-
const response = await this.client.get('/v2/workflows', {
|
|
56
|
-
params: {
|
|
57
|
-
limit: 10000
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
return response.data.data.workflows || [];
|
|
62
|
-
} catch (error: any) {
|
|
63
|
-
console.error('Ошибка получения списка воркфлоу:', console.dir(error.response?.data || error.message, {depth: null}));
|
|
64
|
-
throw error;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Создать новый воркфлоу
|
|
70
|
-
*/
|
|
71
|
-
async createWorkflow(data: Types.NovuWorkflowData): Promise<any> {
|
|
72
|
-
try {
|
|
73
|
-
// Для создания НЕ передаем origin (как в testFramework2.ts)
|
|
74
|
-
const createData = { ...data };
|
|
75
|
-
|
|
76
|
-
delete createData.origin;
|
|
77
|
-
|
|
78
|
-
const response = await this.client.post('/v2/workflows', createData);
|
|
79
|
-
return response.data;
|
|
80
|
-
} catch (error: any) {
|
|
81
|
-
console.error(`Ошибка создания воркфлоу ${data.workflowId}:`, error.response?.data || error.message);
|
|
82
|
-
throw error;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Обновить существующий воркфлоу
|
|
88
|
-
*/
|
|
89
|
-
async updateWorkflow(workflowId: string, data: Types.NovuWorkflowData): Promise<any> {
|
|
90
|
-
try {
|
|
91
|
-
// Для обновления ВСЕГДА передаем origin: "external" (как в testFramework2.ts)
|
|
92
|
-
const updateData = { ...data, origin: 'novu-cloud' as const };
|
|
93
|
-
const response = await this.client.put(`/v2/workflows/${workflowId}`, updateData);
|
|
94
|
-
// console.log('response', response.data);
|
|
95
|
-
return response.data;
|
|
96
|
-
} catch (error: any) {
|
|
97
|
-
console.error(`Ошибка обновления воркфлоу ${workflowId}:`, error.response?.data || error.message);
|
|
98
|
-
throw error;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Удалить воркфлоу по ID
|
|
104
|
-
*/
|
|
105
|
-
async deleteWorkflow(workflowId: string): Promise<void> {
|
|
106
|
-
try {
|
|
107
|
-
await this.client.delete(`/v2/workflows/${workflowId}`);
|
|
108
|
-
console.log(`Удален воркфлоу: ${workflowId}`);
|
|
109
|
-
} catch (error: any) {
|
|
110
|
-
if (error.response?.status === 404) {
|
|
111
|
-
console.log(`Воркфлоу ${workflowId} не найден (уже удален)`);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
console.error(`Ошибка удаления воркфлоу ${workflowId}:`, error.response?.data || error.message);
|
|
115
|
-
throw error;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Создать или обновить воркфлоу (upsert)
|
|
121
|
-
*/
|
|
122
|
-
async upsertWorkflow(workflow: Types.WorkflowDefinition): Promise<any> {
|
|
123
|
-
try {
|
|
124
|
-
console.log(`Проверяем воркфлоу: ${workflow.workflowId}`);
|
|
125
|
-
|
|
126
|
-
const existingWorkflow = await this.getWorkflow(workflow.workflowId);
|
|
127
|
-
|
|
128
|
-
const novuData: Types.NovuWorkflowData = {
|
|
129
|
-
name: workflow.name,
|
|
130
|
-
workflowId: workflow.workflowId,
|
|
131
|
-
description: workflow.description,
|
|
132
|
-
payloadSchema: workflow.payloadSchema,
|
|
133
|
-
steps: workflow.steps,
|
|
134
|
-
preferences: workflow.preferences,
|
|
135
|
-
tags: workflow.tags,
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
if (existingWorkflow) {
|
|
139
|
-
console.log(`Обновляем воркфлоу: ${workflow.workflowId}`);
|
|
140
|
-
return await this.updateWorkflow(workflow.workflowId, novuData);
|
|
141
|
-
} else {
|
|
142
|
-
console.log(`Создаём воркфлоу: ${workflow.workflowId}`);
|
|
143
|
-
return await this.createWorkflow(novuData);
|
|
144
|
-
}
|
|
145
|
-
} catch (error: any) {
|
|
146
|
-
console.error(`Ошибка upsert воркфлоу ${workflow.workflowId}:`, error.message);
|
|
147
|
-
throw error;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Удалить все существующие воркфлоу
|
|
153
|
-
*/
|
|
154
|
-
async deleteAllWorkflows(): Promise<void> {
|
|
155
|
-
console.log('Получаем список всех воркфлоу для удаления...');
|
|
156
|
-
|
|
157
|
-
try {
|
|
158
|
-
const workflows = await this.getAllWorkflows();
|
|
159
|
-
console.log(`Найдено ${workflows.length} воркфлоу для удаления`);
|
|
160
|
-
|
|
161
|
-
if (workflows.length === 0) {
|
|
162
|
-
console.log('Нет воркфлоу для удаления');
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const errors: string[] = [];
|
|
167
|
-
let deletedCount = 0;
|
|
168
|
-
|
|
169
|
-
for (const workflow of workflows) {
|
|
170
|
-
try {
|
|
171
|
-
await this.deleteWorkflow(workflow.workflowId || workflow._id);
|
|
172
|
-
deletedCount++;
|
|
173
|
-
} catch (error: any) {
|
|
174
|
-
const errorMessage = `Ошибка удаления воркфлоу ${workflow.workflowId || workflow._id}: ${error.message}`;
|
|
175
|
-
console.error(`✗ ${errorMessage}`);
|
|
176
|
-
errors.push(errorMessage);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
console.log(`\nРезультат удаления:`);
|
|
181
|
-
console.log(`✅ Удалено: ${deletedCount}`);
|
|
182
|
-
console.log(`❌ Ошибки: ${errors.length}`);
|
|
183
|
-
|
|
184
|
-
if (errors.length > 0) {
|
|
185
|
-
console.log(`\nСписок ошибок удаления:`);
|
|
186
|
-
errors.forEach((error, index) => {
|
|
187
|
-
console.log(`${index + 1}. ${error}`);
|
|
188
|
-
});
|
|
189
|
-
throw new Error(`Удаление завершилось с ошибками: ${errors.length} из ${workflows.length} воркфлоу`);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
console.log('✅ Все существующие воркфлоу удалены успешно');
|
|
193
|
-
} catch (error: any) {
|
|
194
|
-
console.error('❌ Критическая ошибка при удалении воркфлоу:', error.message);
|
|
195
|
-
throw error;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Создать или обновить все воркфлоу (с предварительным удалением существующих)
|
|
201
|
-
*/
|
|
202
|
-
async upsertAllWorkflows(): Promise<void> {
|
|
203
|
-
console.log('🚀 Начинаем полную синхронизацию воркфлоу...');
|
|
204
|
-
|
|
205
|
-
// Шаг 1: Удаляем все существующие воркфлоу
|
|
206
|
-
// try {
|
|
207
|
-
// await this.deleteAllWorkflows();
|
|
208
|
-
// } catch (error: any) {
|
|
209
|
-
// console.error('❌ Ошибка при удалении существующих воркфлоу:', error.message);
|
|
210
|
-
// throw error;
|
|
211
|
-
// }
|
|
212
|
-
|
|
213
|
-
// Шаг 2: Создаем новые воркфлоу
|
|
214
|
-
console.log(`\n📝 Начинаем создание ${Workflows.allWorkflows.length} новых воркфлоу...`);
|
|
215
|
-
|
|
216
|
-
const errors: string[] = [];
|
|
217
|
-
let successCount = 0;
|
|
218
|
-
|
|
219
|
-
for (const workflow of Workflows.allWorkflows) {
|
|
220
|
-
try {
|
|
221
|
-
await this.upsertWorkflow(workflow);
|
|
222
|
-
console.log(`✓ Воркфлоу ${workflow.workflowId} успешно создан`);
|
|
223
|
-
successCount++;
|
|
224
|
-
} catch (error: any) {
|
|
225
|
-
const errorMessage = `Ошибка создания воркфлоу ${workflow.workflowId}: ${error.message}`;
|
|
226
|
-
console.error(`✗ ${errorMessage}`);
|
|
227
|
-
errors.push(errorMessage);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
console.log(`\nРезультат синхронизации:`);
|
|
232
|
-
console.log(`✅ Успешно создано: ${successCount}`);
|
|
233
|
-
console.log(`❌ Ошибки: ${errors.length}`);
|
|
234
|
-
|
|
235
|
-
if (errors.length > 0) {
|
|
236
|
-
console.log(`\nСписок ошибок:`);
|
|
237
|
-
errors.forEach((error, index) => {
|
|
238
|
-
console.log(`${index + 1}. ${error}`);
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
throw new Error(`Синхронизация завершилась с ошибками: ${errors.length} из ${Workflows.allWorkflows.length} воркфлоу`);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
console.log('✅ Все воркфлоу синхронизированы успешно');
|
|
245
|
-
}
|
|
246
|
-
}
|
package/src/sync/sync-runner.ts
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { NovuSyncService } from './novu-sync.service';
|
|
4
|
-
import { existsSync } from 'fs';
|
|
5
|
-
import { join, dirname } from 'path';
|
|
6
|
-
import { watch } from 'chokidar';
|
|
7
|
-
import dotenv from 'dotenv';
|
|
8
|
-
import { fileURLToPath } from 'url';
|
|
9
|
-
|
|
10
|
-
dotenv.config();
|
|
11
|
-
|
|
12
|
-
// Конфигурация из переменных окружения
|
|
13
|
-
const config = {
|
|
14
|
-
apiKey: process.env.NOVU_API_KEY || '',
|
|
15
|
-
apiUrl: process.env.NOVU_API_URL || '',
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
async function runSync() {
|
|
19
|
-
console.log('🔄 Запуск синхронизации воркфлоу...');
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
// Проверяем конфигурацию
|
|
23
|
-
if (!config.apiKey) {
|
|
24
|
-
throw new Error('❌ NOVU_API_KEY не установлен в переменных окружения');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (!config.apiUrl) {
|
|
28
|
-
throw new Error('❌ NOVU_API_URL не установлен в переменных окружения');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const syncService = new NovuSyncService(config);
|
|
32
|
-
await syncService.upsertAllWorkflows();
|
|
33
|
-
console.log('✅ Синхронизация завершена успешно');
|
|
34
|
-
return true;
|
|
35
|
-
} catch (error: any) {
|
|
36
|
-
console.error('❌ Ошибка синхронизации:', error.message);
|
|
37
|
-
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async function main() {
|
|
43
|
-
const args = process.argv.slice(2);
|
|
44
|
-
const isDev = args.includes('--dev') || process.env.NODE_ENV === 'development';
|
|
45
|
-
|
|
46
|
-
if (isDev) {
|
|
47
|
-
console.log('📡 Режим разработки: отслеживаем изменения...');
|
|
48
|
-
|
|
49
|
-
// Запускаем синхронизацию сразу
|
|
50
|
-
const initialSyncSuccess = await runSync();
|
|
51
|
-
|
|
52
|
-
if (!initialSyncSuccess) {
|
|
53
|
-
console.error('❌ Первоначальная синхронизация не удалась');
|
|
54
|
-
process.exit(1);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Отслеживаем изменения в файлах воркфлоу и типов
|
|
58
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
59
|
-
const workflowsPath = join(__dirname, '../workflows');
|
|
60
|
-
const typesPath = join(__dirname, '../types');
|
|
61
|
-
|
|
62
|
-
const watchPaths = [];
|
|
63
|
-
if (existsSync(workflowsPath)) {
|
|
64
|
-
watchPaths.push(workflowsPath);
|
|
65
|
-
}
|
|
66
|
-
if (existsSync(typesPath)) {
|
|
67
|
-
watchPaths.push(typesPath);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (watchPaths.length > 0) {
|
|
71
|
-
console.log('👀 Отслеживаем изменения в:', watchPaths.join(', '));
|
|
72
|
-
|
|
73
|
-
let syncTimeout: NodeJS.Timeout | null = null;
|
|
74
|
-
|
|
75
|
-
const watcher = watch(watchPaths, {
|
|
76
|
-
ignored: /node_modules/,
|
|
77
|
-
persistent: true,
|
|
78
|
-
ignoreInitial: true,
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
watcher.on('change', (path: string) => {
|
|
82
|
-
console.log(`📝 Изменен файл: ${path}`);
|
|
83
|
-
|
|
84
|
-
// Дебаунс для избежания множественных запусков
|
|
85
|
-
if (syncTimeout) {
|
|
86
|
-
clearTimeout(syncTimeout);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
syncTimeout = setTimeout(async () => {
|
|
90
|
-
console.log('⏰ Запускаем синхронизацию...');
|
|
91
|
-
const success = await runSync();
|
|
92
|
-
if (!success) {
|
|
93
|
-
console.error('⚠️ Синхронизация не удалась, но продолжаем отслеживание...');
|
|
94
|
-
}
|
|
95
|
-
}, 1000);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
watcher.on('add', (path: string) => {
|
|
99
|
-
console.log(`➕ Добавлен файл: ${path}`);
|
|
100
|
-
if (syncTimeout) {
|
|
101
|
-
clearTimeout(syncTimeout);
|
|
102
|
-
}
|
|
103
|
-
syncTimeout = setTimeout(async () => {
|
|
104
|
-
console.log('⏰ Запускаем синхронизацию...');
|
|
105
|
-
const success = await runSync();
|
|
106
|
-
if (!success) {
|
|
107
|
-
console.error('⚠️ Синхронизация не удалась, но продолжаем отслеживание...');
|
|
108
|
-
}
|
|
109
|
-
}, 1000);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
watcher.on('unlink', (path: string) => {
|
|
113
|
-
console.log(`➖ Удален файл: ${path}`);
|
|
114
|
-
if (syncTimeout) {
|
|
115
|
-
clearTimeout(syncTimeout);
|
|
116
|
-
}
|
|
117
|
-
syncTimeout = setTimeout(async () => {
|
|
118
|
-
console.log('⏰ Запускаем синхронизацию...');
|
|
119
|
-
const success = await runSync();
|
|
120
|
-
if (!success) {
|
|
121
|
-
console.error('⚠️ Синхронизация не удалась, но продолжаем отслеживание...');
|
|
122
|
-
}
|
|
123
|
-
}, 1000);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
console.log('💡 Нажмите Ctrl+C для выхода');
|
|
127
|
-
|
|
128
|
-
// Держим процесс живым
|
|
129
|
-
process.on('SIGINT', () => {
|
|
130
|
-
console.log('\n👋 Выход из режима разработки');
|
|
131
|
-
watcher.close();
|
|
132
|
-
process.exit(0);
|
|
133
|
-
});
|
|
134
|
-
} else {
|
|
135
|
-
console.log('⚠️ Папки для отслеживания не найдены');
|
|
136
|
-
process.exit(1);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
} else {
|
|
140
|
-
// Production режим - запускаем один раз
|
|
141
|
-
const success = await runSync();
|
|
142
|
-
process.exit(success ? 0 : 1);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Проверяем, запущен ли файл как основной модуль
|
|
147
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
148
|
-
main().catch((error) => {
|
|
149
|
-
console.error('❌ Критическая ошибка:', error);
|
|
150
|
-
process.exit(1);
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export { runSync, NovuSyncService };
|