adminizer 4.3.0-build.80 → 4.3.0-build.81
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/assets/add-ChaPnvFv.js +1 -0
- package/assets/{add-form-C04ZI5LT.js → add-form-DNqlORQQ.js} +1 -1
- package/assets/add-group-D6YsQVrC.js +1 -0
- package/assets/{add-group-form-CyRwxTs3.js → add-group-form-CDi1y4af.js} +1 -1
- package/assets/{add-user-form-yp020h4r.js → add-user-form-BzXHahSY.js} +1 -1
- package/assets/add-user-psdNyGx8.js +1 -0
- package/assets/{app-CpGtjhxF.css → app-PLVuwM-H.css} +1 -1
- package/assets/{app-layout-BmT5KQwc.js → app-layout-AWzEe1aH.js} +1 -1
- package/assets/{app-sidebar-4lm9f_CG.js → app-sidebar-Bd4nWVXq.js} +1 -1
- package/assets/app-sidebar-header-jBFp1qZb.js +1 -0
- package/assets/app.js +3 -3
- package/assets/{catalog-CG_EB2kz.js → catalog-XiWBZptC.js} +1 -1
- package/assets/{dashboard-CsmJfdLb.js → dashboard-DcRJErQB.js} +1 -1
- package/assets/date-picker-A6CYw4SC.js +1 -0
- package/assets/del-modal-0klf0PNC.js +1 -0
- package/assets/{field-renderer-Bp1lfm0v.js → field-renderer-CYB5W2He.js} +3 -3
- package/assets/form-B-he6_tT.js +1 -0
- package/assets/{form-CSTeMDf5.js → form-BGRpsR-M.js} +1 -1
- package/assets/{home-D00XjLjD.js → home-B7aZTHTv.js} +2 -2
- package/assets/icon-k6999vVE.js +1 -0
- package/assets/{init-user-L-oxFTOv.js → init-user-Btm16ElL.js} +1 -1
- package/assets/input-error-Dbp_lp61.js +1 -0
- package/assets/list-_tZumymo.js +1 -0
- package/assets/{list-table-vIvydJV2.js → list-table-OzVUH7i4.js} +4 -4
- package/assets/{login-DLMJ6l_r.js → login-DeqxLVx3.js} +1 -1
- package/assets/manifest.json +74 -74
- package/assets/material-icon-B9BY_7p9.js +1 -0
- package/assets/{media-manager-ASGJ4PcS.js → media-manager-DQ5CA_na.js} +1 -1
- package/assets/{module-mxngd2cA.js → module-Drcr0QjC.js} +1 -1
- package/assets/{nav-footer-DbGCtmmN.js → nav-footer-DWHxIgb7.js} +1 -1
- package/assets/{nav-main-BcWhl71g.js → nav-main-CRT9ezos.js} +1 -1
- package/assets/notification-C7K-zK4k.js +27 -0
- package/assets/{register-C_W_hOmq.js → register-CMhPasDj.js} +1 -1
- package/assets/tabs-GDFuClHU.js +1 -0
- package/assets/{theme-switcher-D1G6OSMc.js → theme-switcher-C35zBCil.js} +1 -1
- package/assets/{welcome-FHRCdke0.js → welcome-CbhDDQlg.js} +1 -1
- package/controllers/add.js +1 -1
- package/controllers/catalog/FrontentCatalogAdapter.d.ts +4 -4
- package/controllers/edit.js +1 -15
- package/controllers/list.js +2 -2
- package/controllers/login.js +2 -2
- package/controllers/navigation/edit.js +1 -1
- package/controllers/notifications/NotificationController.d.ts +5 -5
- package/controllers/notifications/NotificationController.js +77 -78
- package/controllers/remove.js +1 -11
- package/controllers/view.js +1 -1
- package/helpers/configHelper.d.ts +1 -1
- package/helpers/fieldsHelper.d.ts +1 -1
- package/helpers/fieldsHelper.js +1 -1
- package/helpers/inertiaAddHelper.d.ts +1 -1
- package/helpers/translationHelper.d.ts +1 -1
- package/helpers/translationHelper.js +1 -1
- package/index.d.ts +14 -13
- package/index.js +14 -13
- package/interfaces/adminpanelConfig.d.ts +1 -1
- package/interfaces/global.d.ts +3 -3
- package/interfaces/types.d.ts +10 -1
- package/lib/Adminizer.d.ts +7 -7
- package/lib/Adminizer.js +7 -7
- package/lib/{v4/DataAccessor.d.ts → DataAccessor.d.ts} +4 -4
- package/lib/{v4/DataAccessor.js → DataAccessor.js} +3 -3
- package/lib/{v4/I18n.js → I18n.js} +2 -2
- package/lib/{v4/PolicyManager.d.ts → PolicyManager.d.ts} +1 -1
- package/lib/{v4/PolicyManager.js → PolicyManager.js} +2 -2
- package/lib/{v4/catalog → catalog}/AbstractCatalog.d.ts +1 -1
- package/lib/{v4/catalog → catalog}/Navigation.d.ts +2 -2
- package/lib/{v4/catalog → catalog}/Navigation.js +1 -1
- package/lib/{v4/controls → controls}/AbstractControls.d.ts +1 -1
- package/lib/{v4/controls → controls}/codeEditor/MonacoEditor.d.ts +1 -1
- package/lib/{v4/controls → controls}/geojsoneditor/GeoEditor.d.ts +1 -1
- package/lib/{v4/controls → controls}/jsoneditor/JsonEditor.d.ts +1 -1
- package/lib/{v4/controls → controls}/markdown/ToastUiEditor.d.ts +1 -1
- package/lib/{v4/controls → controls}/table/Handsontable.d.ts +1 -1
- package/lib/{v4/controls → controls}/wysiwyg/CKeditor.d.ts +1 -1
- package/lib/{v4/datatable → datatable}/NodeTable.d.ts +1 -1
- package/lib/{v4/model → model}/AbstractModel.d.ts +12 -0
- package/lib/model/AbstractModel.js +178 -0
- package/lib/{v4/model → model}/ModelHandler.js +1 -1
- package/lib/{v4/model → model}/adapter/sequelize.d.ts +0 -1
- package/lib/{v4/model → model}/adapter/sequelize.js +6 -3
- package/lib/{v4/notifications → notifications}/AbstractNotificationService.d.ts +14 -7
- package/lib/notifications/AbstractNotificationService.js +233 -0
- package/lib/{v4/notifications → notifications}/GeneralNotificationService.d.ts +1 -1
- package/lib/{v4/notifications → notifications}/GeneralNotificationService.js +4 -2
- package/lib/notifications/NotificationHandler.d.ts +27 -0
- package/lib/notifications/NotificationHandler.js +41 -0
- package/lib/{v4/notifications → notifications}/SystemNotificationService.d.ts +5 -4
- package/lib/notifications/SystemNotificationService.js +173 -0
- package/lib/{v4/widgets → widgets}/abstractCustom.d.ts +1 -1
- package/lib/{v4/widgets → widgets}/abstractLink.d.ts +1 -1
- package/lib/{v4/widgets → widgets}/abstractWidgetBase.d.ts +1 -1
- package/lib/{v4/widgets → widgets}/widgetHandler.d.ts +2 -2
- package/migrations/index.d.ts +3 -0
- package/migrations/index.js +4 -0
- package/migrations/index.ts +5 -0
- package/migrations/umzug/0001.d.ts +7 -0
- package/migrations/umzug/0001.js +119 -0
- package/migrations/umzug/0001.ts +132 -0
- package/migrations/umzug.d.ts +2 -0
- package/migrations/umzug.js +8 -0
- package/migrations/umzug.ts +9 -0
- package/models/NotificationAP.d.ts +8 -0
- package/models/NotificationAP.js +8 -0
- package/models/UserAP.d.ts +1 -1
- package/package.json +5 -4
- package/system/Router.js +4 -8
- package/system/bindControls.js +6 -6
- package/system/bindInertia.js +4 -3
- package/system/bindNavigation.js +1 -1
- package/system/bindNotifications.js +3 -3
- package/system/bindReqFunctions.js +8 -25
- package/system/defaults.js +1 -1
- package/ui/components/ui/table.d.ts +1 -1
- package/ui/components/ui/table.js +2 -2
- package/assets/add-DSapOiv0.js +0 -1
- package/assets/add-group-DWR7SBTO.js +0 -1
- package/assets/add-user-acATGxUL.js +0 -1
- package/assets/app-sidebar-header-CxXmzszq.js +0 -1
- package/assets/date-picker-By3kj-Rx.js +0 -1
- package/assets/del-modal-DlcbcdR5.js +0 -1
- package/assets/form-CxHRGp7p.js +0 -1
- package/assets/icon-ButfCBrt.js +0 -1
- package/assets/input-error-CHsDLcK0.js +0 -1
- package/assets/list-4TOTsjqE.js +0 -1
- package/assets/material-icon-sXk4BK-N.js +0 -1
- package/assets/notification-BEfA5sT6.js +0 -1
- package/assets/tabs-CgZW_LLn.js +0 -1
- package/lib/v4/model/AbstractModel.js +0 -79
- package/lib/v4/notifications/AbstractNotificationService.js +0 -150
- package/lib/v4/notifications/NotificationHandler.d.ts +0 -69
- package/lib/v4/notifications/NotificationHandler.js +0 -127
- package/lib/v4/notifications/SystemNotificationService.js +0 -124
- /package/lib/{v4/I18n.d.ts → I18n.d.ts} +0 -0
- /package/lib/{v4/POWCaptcha.d.ts → POWCaptcha.d.ts} +0 -0
- /package/lib/{v4/POWCaptcha.js → POWCaptcha.js} +0 -0
- /package/lib/{v4/catalog → catalog}/AbstractCatalog.js +0 -0
- /package/lib/{v4/catalog → catalog}/CatalogHandler.d.ts +0 -0
- /package/lib/{v4/catalog → catalog}/CatalogHandler.js +0 -0
- /package/lib/{v4/controls → controls}/AbstractControls.js +0 -0
- /package/lib/{v4/controls → controls}/ControlsHandler.d.ts +0 -0
- /package/lib/{v4/controls → controls}/ControlsHandler.js +0 -0
- /package/lib/{v4/controls → controls}/codeEditor/MonacoEditor.js +0 -0
- /package/lib/{v4/controls → controls}/geojsoneditor/GeoEditor.js +0 -0
- /package/lib/{v4/controls → controls}/jsoneditor/JsonEditor.js +0 -0
- /package/lib/{v4/controls → controls}/markdown/ToastUiEditor.js +0 -0
- /package/lib/{v4/controls → controls}/table/Handsontable.js +0 -0
- /package/lib/{v4/controls → controls}/wysiwyg/CKeditor.js +0 -0
- /package/lib/{v4/datatable → datatable}/NodeTable.js +0 -0
- /package/lib/{v4/helper → helper}/jwt.d.ts +0 -0
- /package/lib/{v4/helper → helper}/jwt.js +0 -0
- /package/lib/{v4/inertia → inertia}/flash.d.ts +0 -0
- /package/lib/{v4/inertia → inertia}/flash.js +0 -0
- /package/lib/{v4/inertia → inertia}/inertiaAdapter.d.ts +0 -0
- /package/lib/{v4/inertia → inertia}/inertiaAdapter.js +0 -0
- /package/lib/{v4/model → model}/ModelHandler.d.ts +0 -0
- /package/lib/{v4/model → model}/adapter/waterline.d.ts +0 -0
- /package/lib/{v4/model → model}/adapter/waterline.js +0 -0
- /package/lib/{v4/widgets → widgets}/abstractAction.d.ts +0 -0
- /package/lib/{v4/widgets → widgets}/abstractAction.js +0 -0
- /package/lib/{v4/widgets → widgets}/abstractCustom.js +0 -0
- /package/lib/{v4/widgets → widgets}/abstractInfo.d.ts +0 -0
- /package/lib/{v4/widgets → widgets}/abstractInfo.js +0 -0
- /package/lib/{v4/widgets → widgets}/abstractLink.js +0 -0
- /package/lib/{v4/widgets → widgets}/abstractSwitch.d.ts +0 -0
- /package/lib/{v4/widgets → widgets}/abstractSwitch.js +0 -0
- /package/lib/{v4/widgets → widgets}/abstractWidgetBase.js +0 -0
- /package/lib/{v4/widgets → widgets}/widgetHandler.js +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { Adminizer } from '../Adminizer';
|
|
3
|
+
export class NotificationHandler extends EventEmitter {
|
|
4
|
+
services = new Map();
|
|
5
|
+
constructor() {
|
|
6
|
+
super();
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Register a new notification service
|
|
10
|
+
* @param service
|
|
11
|
+
*/
|
|
12
|
+
registerService(service) {
|
|
13
|
+
this.services.set(service.notificationClass, service);
|
|
14
|
+
Adminizer.log.info(`Notification service registered: ${service.notificationClass}`);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get a notification service by class
|
|
18
|
+
* @param notificationClass
|
|
19
|
+
*/
|
|
20
|
+
getService(notificationClass) {
|
|
21
|
+
return this.services.get(notificationClass);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get all registered services
|
|
25
|
+
*/
|
|
26
|
+
getAllServices() {
|
|
27
|
+
return Array.from(this.services.values());
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Dispatch a notification to a service
|
|
31
|
+
* @param notificationClass
|
|
32
|
+
* @param notification
|
|
33
|
+
*/
|
|
34
|
+
async dispatchNotification(notificationClass, notification) {
|
|
35
|
+
const service = this.getService(notificationClass);
|
|
36
|
+
if (!service) {
|
|
37
|
+
throw new Error(`Notification service not found: ${notificationClass}`);
|
|
38
|
+
}
|
|
39
|
+
return service.dispatchNotification(notification);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AbstractNotificationService } from './AbstractNotificationService';
|
|
2
|
-
import { INotification } from '
|
|
2
|
+
import { INotification } from '../../interfaces/types';
|
|
3
3
|
export declare class SystemNotificationService extends AbstractNotificationService {
|
|
4
4
|
readonly notificationClass = "system";
|
|
5
5
|
readonly icon: string;
|
|
@@ -7,12 +7,13 @@ export declare class SystemNotificationService extends AbstractNotificationServi
|
|
|
7
7
|
private crudChannels;
|
|
8
8
|
dispatchNotification(notification: Omit<INotification, 'id' | 'createdAt' | 'notificationClass' | 'icon'>): Promise<boolean>;
|
|
9
9
|
private broadcastToChannel;
|
|
10
|
-
addClientToChannel(clientId: string, channel: string): void;
|
|
11
|
-
removeClientFromChannel(clientId: string, channel: string): void;
|
|
12
|
-
removeClientFromAllChannels(clientId: string): void;
|
|
10
|
+
addClientToChannel(clientId: string, channel: string, userId: number): void;
|
|
11
|
+
removeClientFromChannel(clientId: string, channel: string, userId: number): void;
|
|
12
|
+
removeClientFromAllChannels(clientId: string, userId: number): void;
|
|
13
13
|
removeClient(clientId: string): void;
|
|
14
14
|
logSystemEvent(title: string, message: string, channel?: string, metadata?: Record<string | number, any>): Promise<boolean>;
|
|
15
15
|
logCreatedEvent(title: string, message: string, metadata?: Record<string | number, any>): Promise<boolean>;
|
|
16
16
|
logUpdatedEvent(title: string, message: string, metadata?: Record<string | number, any>): Promise<boolean>;
|
|
17
17
|
logDeletedEvent(title: string, message: string, metadata?: Record<string | number, any>): Promise<boolean>;
|
|
18
|
+
getUserChannels(userId: number): Map<string, Set<string>>;
|
|
18
19
|
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { AbstractNotificationService } from './AbstractNotificationService';
|
|
2
|
+
import { Adminizer } from '../Adminizer';
|
|
3
|
+
export class SystemNotificationService extends AbstractNotificationService {
|
|
4
|
+
notificationClass = 'system';
|
|
5
|
+
icon = 'settings';
|
|
6
|
+
iconColor = '#1eb707';
|
|
7
|
+
// Изменяем структуру каналов: храним по userId -> channel -> clientIds
|
|
8
|
+
crudChannels = new Map();
|
|
9
|
+
async dispatchNotification(notification) {
|
|
10
|
+
const fullNotification = {
|
|
11
|
+
...notification,
|
|
12
|
+
notificationClass: this.notificationClass,
|
|
13
|
+
channel: notification.channel ?? ''
|
|
14
|
+
};
|
|
15
|
+
let notificationDB;
|
|
16
|
+
// Сохраняем в базу
|
|
17
|
+
if (this.adminizer.modelHandler.model.has('notificationap')) {
|
|
18
|
+
try {
|
|
19
|
+
notificationDB = await this.adminizer.modelHandler.model.get('notificationap')["_create"](fullNotification);
|
|
20
|
+
const users = await this.adminizer.modelHandler.model.get('userap')["_find"]({});
|
|
21
|
+
for (const user of users) {
|
|
22
|
+
try {
|
|
23
|
+
if (this.adminizer.accessRightsHelper.hasPermission(`notification-${this.notificationClass}`, user)) {
|
|
24
|
+
await this.createUserNotification(notificationDB.id, user.id);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
Adminizer.log.error('Error creating UserNotificationAP:', error);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const event = {
|
|
32
|
+
type: 'notification',
|
|
33
|
+
data: {
|
|
34
|
+
...notificationDB,
|
|
35
|
+
icon: {
|
|
36
|
+
icon: this.icon,
|
|
37
|
+
iconColor: this.iconColor
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
notificationClass: this.notificationClass,
|
|
41
|
+
userId: notification.userId ?? null,
|
|
42
|
+
channel: notification.channel ?? 'system'
|
|
43
|
+
};
|
|
44
|
+
// Отправляем на все каналы или на конкретный канал
|
|
45
|
+
if (notification.channel) {
|
|
46
|
+
this.broadcastToChannel(notification.channel, event);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
this.broadcastToChannel('system', event);
|
|
50
|
+
}
|
|
51
|
+
Adminizer.log.info(`[System] Notification dispatched: ${fullNotification.title}`);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
Adminizer.log.error('Error saving system notification to database:', error);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
// Обновляем broadcastToChannel для работы с новой структурой
|
|
61
|
+
broadcastToChannel(channel, event) {
|
|
62
|
+
// Отправляем всем пользователям, подписанным на этот канал
|
|
63
|
+
this.crudChannels.forEach((userChannels, userId) => {
|
|
64
|
+
const channelClients = userChannels.get(channel);
|
|
65
|
+
if (channelClients) {
|
|
66
|
+
const userClients = this.clients.get(userId);
|
|
67
|
+
if (userClients) {
|
|
68
|
+
channelClients.forEach(clientId => {
|
|
69
|
+
const sendFn = userClients.get(clientId);
|
|
70
|
+
if (sendFn) {
|
|
71
|
+
try {
|
|
72
|
+
sendFn(event);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
Adminizer.log.error(`[${this.notificationClass}] Error sending to client ${clientId} on channel ${channel}:`, error);
|
|
76
|
+
this.removeClient(clientId);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
// Добавляем клиента к каналу с привязкой к пользователю
|
|
85
|
+
addClientToChannel(clientId, channel, userId) {
|
|
86
|
+
if (!this.crudChannels.has(userId)) {
|
|
87
|
+
this.crudChannels.set(userId, new Map());
|
|
88
|
+
}
|
|
89
|
+
const userChannels = this.crudChannels.get(userId);
|
|
90
|
+
if (!userChannels.has(channel)) {
|
|
91
|
+
userChannels.set(channel, new Set());
|
|
92
|
+
}
|
|
93
|
+
userChannels.get(channel).add(clientId);
|
|
94
|
+
Adminizer.log.info(`[${this.notificationClass}] Client ${clientId} (user ${userId}) added to channel ${channel}`);
|
|
95
|
+
}
|
|
96
|
+
// Удаляем клиента из канала конкретного пользователя
|
|
97
|
+
removeClientFromChannel(clientId, channel, userId) {
|
|
98
|
+
const userChannels = this.crudChannels.get(userId);
|
|
99
|
+
if (userChannels) {
|
|
100
|
+
const channelClients = userChannels.get(channel);
|
|
101
|
+
if (channelClients) {
|
|
102
|
+
channelClients.delete(clientId);
|
|
103
|
+
Adminizer.log.info(`[${this.notificationClass}] Client ${clientId} (user ${userId}) removed from channel ${channel}`);
|
|
104
|
+
// Если в канале больше нет клиентов - удаляем канал
|
|
105
|
+
if (channelClients.size === 0) {
|
|
106
|
+
userChannels.delete(channel);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Если у пользователя больше нет каналов - удаляем запись пользователя
|
|
110
|
+
if (userChannels.size === 0) {
|
|
111
|
+
this.crudChannels.delete(userId);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Удаляем клиента из всех каналов пользователя
|
|
116
|
+
removeClientFromAllChannels(clientId, userId) {
|
|
117
|
+
const userChannels = this.crudChannels.get(userId);
|
|
118
|
+
if (userChannels) {
|
|
119
|
+
userChannels.forEach((clients, channel) => {
|
|
120
|
+
clients.delete(clientId);
|
|
121
|
+
Adminizer.log.info(`[${this.notificationClass}] Client ${clientId} (user ${userId}) removed from channel ${channel}`);
|
|
122
|
+
// Если в канале больше нет клиентов - удаляем канал
|
|
123
|
+
if (clients.size === 0) {
|
|
124
|
+
userChannels.delete(channel);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
// Если у пользователя больше нет каналов - удаляем запись пользователя
|
|
128
|
+
if (userChannels.size === 0) {
|
|
129
|
+
this.crudChannels.delete(userId);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Переопределяем removeClient для очистки каналов
|
|
134
|
+
removeClient(clientId) {
|
|
135
|
+
// Находим userId по clientId
|
|
136
|
+
let foundUserId = null;
|
|
137
|
+
for (const [userId, userClients] of this.clients.entries()) {
|
|
138
|
+
if (userClients.has(clientId)) {
|
|
139
|
+
foundUserId = userId;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Удаляем клиента из основного хранилища
|
|
144
|
+
super.removeClient(clientId);
|
|
145
|
+
// Удаляем клиента из каналов
|
|
146
|
+
if (foundUserId !== null) {
|
|
147
|
+
this.removeClientFromAllChannels(clientId, foundUserId);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Специальный метод для системных событий с указанием канала
|
|
151
|
+
async logSystemEvent(title, message, channel, metadata) {
|
|
152
|
+
return this.dispatchNotification({
|
|
153
|
+
title: title,
|
|
154
|
+
message: message,
|
|
155
|
+
metadata: metadata,
|
|
156
|
+
channel: channel
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
// Методы для CRUD операций
|
|
160
|
+
async logCreatedEvent(title, message, metadata) {
|
|
161
|
+
return this.logSystemEvent(title, message, 'created', metadata);
|
|
162
|
+
}
|
|
163
|
+
async logUpdatedEvent(title, message, metadata) {
|
|
164
|
+
return this.logSystemEvent(title, message, 'updated', metadata);
|
|
165
|
+
}
|
|
166
|
+
async logDeletedEvent(title, message, metadata) {
|
|
167
|
+
return this.logSystemEvent(title, message, 'deleted', metadata);
|
|
168
|
+
}
|
|
169
|
+
// Новый метод для получения каналов пользователя
|
|
170
|
+
getUserChannels(userId) {
|
|
171
|
+
return this.crudChannels.get(userId) || new Map();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -3,8 +3,8 @@ import { InfoBase } from "./abstractInfo";
|
|
|
3
3
|
import { ActionBase } from "./abstractAction";
|
|
4
4
|
import { LinkBase } from "./abstractLink";
|
|
5
5
|
import { CustomBase } from "./abstractCustom";
|
|
6
|
-
import { AdminpanelIcon } from "
|
|
7
|
-
import { Adminizer } from "
|
|
6
|
+
import { AdminpanelIcon } from "../../interfaces/adminpanelConfig";
|
|
7
|
+
import { Adminizer } from "../Adminizer";
|
|
8
8
|
import { UserAP } from "models/UserAP";
|
|
9
9
|
import { I18n } from "../I18n";
|
|
10
10
|
export type WidgetType = (SwitchBase | InfoBase | ActionBase | LinkBase | CustomBase);
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { DataTypes } from "sequelize";
|
|
2
|
+
// Creates all system model tables according to src/models/* and
|
|
3
|
+
// SequelizeAdapter.generateSequelizeModel naming: tableName = modelName.toLowerCase()
|
|
4
|
+
// Associations:
|
|
5
|
+
// - UserAP <-> GroupAP: M:N via through table "groupapuserap" (UserAPId, GroupAPId)
|
|
6
|
+
// - MediaManagerAP.parent -> MediaManagerAP (parentId)
|
|
7
|
+
// - MediaManagerAP hasMany MediaManagerMetaAP via parent (MediaManagerMetaAP.parentId)
|
|
8
|
+
// - MediaManagerAP hasMany MediaManagerAssociationsAP via file (MediaManagerAssociationsAP.fileId)
|
|
9
|
+
// - UserNotificationAP belongsTo NotificationAP via alias "notificationId" -> FK column "notificationIdId"
|
|
10
|
+
export async function up({ context }) {
|
|
11
|
+
// userap
|
|
12
|
+
await context.createTable("userap", {
|
|
13
|
+
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
|
|
14
|
+
login: { type: DataTypes.STRING, unique: true },
|
|
15
|
+
fullName: { type: DataTypes.STRING },
|
|
16
|
+
email: { type: DataTypes.STRING },
|
|
17
|
+
avatar: { type: DataTypes.STRING },
|
|
18
|
+
passwordHashed: { type: DataTypes.STRING },
|
|
19
|
+
timezone: { type: DataTypes.STRING },
|
|
20
|
+
expires: { type: DataTypes.STRING },
|
|
21
|
+
locale: { type: DataTypes.STRING },
|
|
22
|
+
isDeleted: { type: DataTypes.BOOLEAN },
|
|
23
|
+
isActive: { type: DataTypes.BOOLEAN },
|
|
24
|
+
isAdministrator: { type: DataTypes.BOOLEAN },
|
|
25
|
+
widgets: { type: DataTypes.JSON },
|
|
26
|
+
isConfirmed: { type: DataTypes.BOOLEAN },
|
|
27
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
28
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
29
|
+
});
|
|
30
|
+
// groupap
|
|
31
|
+
await context.createTable("groupap", {
|
|
32
|
+
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
|
|
33
|
+
name: { type: DataTypes.STRING, unique: true },
|
|
34
|
+
description: { type: DataTypes.STRING },
|
|
35
|
+
tokens: { type: DataTypes.JSON },
|
|
36
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
37
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
38
|
+
});
|
|
39
|
+
// mediamanagerap (self-ref via parentId)
|
|
40
|
+
await context.createTable("mediamanagerap", {
|
|
41
|
+
id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true, allowNull: false },
|
|
42
|
+
parentId: { type: DataTypes.UUID, allowNull: true, references: { model: "mediamanagerap", key: "id" } },
|
|
43
|
+
mimeType: { type: DataTypes.STRING },
|
|
44
|
+
path: { type: DataTypes.STRING },
|
|
45
|
+
size: { type: DataTypes.INTEGER },
|
|
46
|
+
group: { type: DataTypes.STRING },
|
|
47
|
+
tag: { type: DataTypes.STRING },
|
|
48
|
+
url: { type: DataTypes.STRING },
|
|
49
|
+
filename: { type: DataTypes.STRING },
|
|
50
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
51
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
52
|
+
});
|
|
53
|
+
// mediamanagermetaap (belongsTo mediamanagerap via parentId)
|
|
54
|
+
await context.createTable("mediamanagermetaap", {
|
|
55
|
+
id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true, allowNull: false },
|
|
56
|
+
key: { type: DataTypes.STRING },
|
|
57
|
+
value: { type: DataTypes.JSON },
|
|
58
|
+
isPublic: { type: DataTypes.BOOLEAN },
|
|
59
|
+
parentId: { type: DataTypes.UUID, allowNull: true, references: { model: "mediamanagerap", key: "id" } },
|
|
60
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
61
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
62
|
+
});
|
|
63
|
+
// mediamanagerassociationsap (belongsTo mediamanagerap via fileId)
|
|
64
|
+
await context.createTable("mediamanagerassociationsap", {
|
|
65
|
+
id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true, allowNull: false },
|
|
66
|
+
mediaManagerId: { type: DataTypes.STRING },
|
|
67
|
+
model: { type: DataTypes.JSON },
|
|
68
|
+
modelId: { type: DataTypes.JSON },
|
|
69
|
+
widgetName: { type: DataTypes.STRING },
|
|
70
|
+
sortOrder: { type: DataTypes.INTEGER },
|
|
71
|
+
fileId: { type: DataTypes.UUID, allowNull: true, references: { model: "mediamanagerap", key: "id" } },
|
|
72
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
73
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
74
|
+
});
|
|
75
|
+
// notificationap
|
|
76
|
+
await context.createTable("notificationap", {
|
|
77
|
+
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
|
|
78
|
+
title: { type: DataTypes.STRING },
|
|
79
|
+
message: { type: DataTypes.STRING },
|
|
80
|
+
notificationClass: { type: DataTypes.STRING },
|
|
81
|
+
channel: { type: DataTypes.STRING },
|
|
82
|
+
metadata: { type: DataTypes.JSON },
|
|
83
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
84
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
85
|
+
});
|
|
86
|
+
// usernotificationap (FK to notificationap via column notificationIdId)
|
|
87
|
+
await context.createTable("usernotificationap", {
|
|
88
|
+
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
|
|
89
|
+
userId: { type: DataTypes.INTEGER },
|
|
90
|
+
notificationIdId: { type: DataTypes.INTEGER, allowNull: true, references: { model: "notificationap", key: "id" } },
|
|
91
|
+
read: { type: DataTypes.BOOLEAN },
|
|
92
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
93
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
94
|
+
});
|
|
95
|
+
// navigationap
|
|
96
|
+
await context.createTable("navigationap", {
|
|
97
|
+
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
|
|
98
|
+
label: { type: DataTypes.STRING, unique: true },
|
|
99
|
+
tree: { type: DataTypes.JSON },
|
|
100
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
101
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
102
|
+
});
|
|
103
|
+
// M:N join: GroupAP <-> UserAP via "groupapuserap"
|
|
104
|
+
await context.createTable("groupapuserap", {
|
|
105
|
+
UserAPId: { type: DataTypes.INTEGER, allowNull: false, references: { model: "userap", key: "id" } },
|
|
106
|
+
GroupAPId: { type: DataTypes.INTEGER, allowNull: false, references: { model: "groupap", key: "id" } },
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
export async function down({ context }) {
|
|
110
|
+
await context.dropTable("groupapuserap");
|
|
111
|
+
await context.dropTable("usernotificationap");
|
|
112
|
+
await context.dropTable("mediamanagermetaap");
|
|
113
|
+
await context.dropTable("mediamanagerassociationsap");
|
|
114
|
+
await context.dropTable("mediamanagerap");
|
|
115
|
+
await context.dropTable("navigationap");
|
|
116
|
+
await context.dropTable("notificationap");
|
|
117
|
+
await context.dropTable("groupap");
|
|
118
|
+
await context.dropTable("userap");
|
|
119
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { QueryInterface, DataTypes } from "sequelize";
|
|
2
|
+
|
|
3
|
+
type Ctx = { context: QueryInterface };
|
|
4
|
+
|
|
5
|
+
// Creates all system model tables according to src/models/* and
|
|
6
|
+
// SequelizeAdapter.generateSequelizeModel naming: tableName = modelName.toLowerCase()
|
|
7
|
+
// Associations:
|
|
8
|
+
// - UserAP <-> GroupAP: M:N via through table "groupapuserap" (UserAPId, GroupAPId)
|
|
9
|
+
// - MediaManagerAP.parent -> MediaManagerAP (parentId)
|
|
10
|
+
// - MediaManagerAP hasMany MediaManagerMetaAP via parent (MediaManagerMetaAP.parentId)
|
|
11
|
+
// - MediaManagerAP hasMany MediaManagerAssociationsAP via file (MediaManagerAssociationsAP.fileId)
|
|
12
|
+
// - UserNotificationAP belongsTo NotificationAP via alias "notificationId" -> FK column "notificationIdId"
|
|
13
|
+
|
|
14
|
+
export async function up({ context }: Ctx): Promise<void> {
|
|
15
|
+
// userap
|
|
16
|
+
await context.createTable("userap", {
|
|
17
|
+
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
|
|
18
|
+
login: { type: DataTypes.STRING, unique: true },
|
|
19
|
+
fullName: { type: DataTypes.STRING },
|
|
20
|
+
email: { type: DataTypes.STRING },
|
|
21
|
+
avatar: { type: DataTypes.STRING },
|
|
22
|
+
passwordHashed: { type: DataTypes.STRING },
|
|
23
|
+
timezone: { type: DataTypes.STRING },
|
|
24
|
+
expires: { type: DataTypes.STRING },
|
|
25
|
+
locale: { type: DataTypes.STRING },
|
|
26
|
+
isDeleted: { type: DataTypes.BOOLEAN },
|
|
27
|
+
isActive: { type: DataTypes.BOOLEAN },
|
|
28
|
+
isAdministrator: { type: DataTypes.BOOLEAN },
|
|
29
|
+
widgets: { type: DataTypes.JSON },
|
|
30
|
+
isConfirmed: { type: DataTypes.BOOLEAN },
|
|
31
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
32
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// groupap
|
|
36
|
+
await context.createTable("groupap", {
|
|
37
|
+
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
|
|
38
|
+
name: { type: DataTypes.STRING, unique: true },
|
|
39
|
+
description: { type: DataTypes.STRING },
|
|
40
|
+
tokens: { type: DataTypes.JSON },
|
|
41
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
42
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// mediamanagerap (self-ref via parentId)
|
|
46
|
+
await context.createTable("mediamanagerap", {
|
|
47
|
+
id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true, allowNull: false },
|
|
48
|
+
parentId: { type: DataTypes.UUID, allowNull: true, references: { model: "mediamanagerap", key: "id" } },
|
|
49
|
+
mimeType: { type: DataTypes.STRING },
|
|
50
|
+
path: { type: DataTypes.STRING },
|
|
51
|
+
size: { type: DataTypes.INTEGER },
|
|
52
|
+
group: { type: DataTypes.STRING },
|
|
53
|
+
tag: { type: DataTypes.STRING },
|
|
54
|
+
url: { type: DataTypes.STRING },
|
|
55
|
+
filename: { type: DataTypes.STRING },
|
|
56
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
57
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// mediamanagermetaap (belongsTo mediamanagerap via parentId)
|
|
61
|
+
await context.createTable("mediamanagermetaap", {
|
|
62
|
+
id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true, allowNull: false },
|
|
63
|
+
key: { type: DataTypes.STRING },
|
|
64
|
+
value: { type: DataTypes.JSON },
|
|
65
|
+
isPublic: { type: DataTypes.BOOLEAN },
|
|
66
|
+
parentId: { type: DataTypes.UUID, allowNull: true, references: { model: "mediamanagerap", key: "id" } },
|
|
67
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
68
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// mediamanagerassociationsap (belongsTo mediamanagerap via fileId)
|
|
72
|
+
await context.createTable("mediamanagerassociationsap", {
|
|
73
|
+
id: { type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4, primaryKey: true, allowNull: false },
|
|
74
|
+
mediaManagerId: { type: DataTypes.STRING },
|
|
75
|
+
model: { type: DataTypes.JSON },
|
|
76
|
+
modelId: { type: DataTypes.JSON },
|
|
77
|
+
widgetName: { type: DataTypes.STRING },
|
|
78
|
+
sortOrder: { type: DataTypes.INTEGER },
|
|
79
|
+
fileId: { type: DataTypes.UUID, allowNull: true, references: { model: "mediamanagerap", key: "id" } },
|
|
80
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
81
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// notificationap
|
|
85
|
+
await context.createTable("notificationap", {
|
|
86
|
+
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
|
|
87
|
+
title: { type: DataTypes.STRING },
|
|
88
|
+
message: { type: DataTypes.STRING },
|
|
89
|
+
notificationClass: { type: DataTypes.STRING },
|
|
90
|
+
channel: { type: DataTypes.STRING },
|
|
91
|
+
metadata: { type: DataTypes.JSON },
|
|
92
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
93
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// usernotificationap (FK to notificationap via column notificationIdId)
|
|
97
|
+
await context.createTable("usernotificationap", {
|
|
98
|
+
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
|
|
99
|
+
userId: { type: DataTypes.INTEGER },
|
|
100
|
+
notificationIdId: { type: DataTypes.INTEGER, allowNull: true, references: { model: "notificationap", key: "id" } },
|
|
101
|
+
read: { type: DataTypes.BOOLEAN },
|
|
102
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
103
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// navigationap
|
|
107
|
+
await context.createTable("navigationap", {
|
|
108
|
+
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
|
|
109
|
+
label: { type: DataTypes.STRING, unique: true },
|
|
110
|
+
tree: { type: DataTypes.JSON },
|
|
111
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
112
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// M:N join: GroupAP <-> UserAP via "groupapuserap"
|
|
116
|
+
await context.createTable("groupapuserap", {
|
|
117
|
+
UserAPId: { type: DataTypes.INTEGER, allowNull: false, references: { model: "userap", key: "id" } },
|
|
118
|
+
GroupAPId: { type: DataTypes.INTEGER, allowNull: false, references: { model: "groupap", key: "id" } },
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export async function down({ context }: Ctx): Promise<void> {
|
|
123
|
+
await context.dropTable("groupapuserap");
|
|
124
|
+
await context.dropTable("usernotificationap");
|
|
125
|
+
await context.dropTable("mediamanagermetaap");
|
|
126
|
+
await context.dropTable("mediamanagerassociationsap");
|
|
127
|
+
await context.dropTable("mediamanagerap");
|
|
128
|
+
await context.dropTable("navigationap");
|
|
129
|
+
await context.dropTable("notificationap");
|
|
130
|
+
await context.dropTable("groupap");
|
|
131
|
+
await context.dropTable("userap");
|
|
132
|
+
}
|
|
@@ -20,6 +20,14 @@ declare const _default: {
|
|
|
20
20
|
metadata: {
|
|
21
21
|
type: string;
|
|
22
22
|
};
|
|
23
|
+
createdAt: {
|
|
24
|
+
type: string;
|
|
25
|
+
autoCreatedAt: boolean;
|
|
26
|
+
};
|
|
27
|
+
updatedAt: {
|
|
28
|
+
type: string;
|
|
29
|
+
autoUpdatedAt: boolean;
|
|
30
|
+
};
|
|
23
31
|
};
|
|
24
32
|
export default _default;
|
|
25
33
|
export interface NotificationAP {
|
package/models/NotificationAP.js
CHANGED
package/models/UserAP.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adminizer",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.3.0-build.
|
|
4
|
+
"version": "4.3.0-build.81",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./index.js",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"dev:no-seed": "cross-env VITE_ENV=dev NO_SEED_DATA=true ORM=sequelize tsx watch --tsconfig ./fixture/tsconfig.json ./fixture/index.ts",
|
|
16
16
|
"dev:no-seed-clean": "cross-env VITE_ENV=dev NO_SEED_DATA=true CLEAN_TMP=true ORM=sequelize tsx watch --tsconfig ./fixture/tsconfig.json ./fixture/index.ts",
|
|
17
17
|
"dev:waterline": "cross-env VITE_ENV=dev ORM=waterline tsx watch --tsconfig ./fixture/tsconfig.json ./fixture/index.ts",
|
|
18
|
+
"dev:waterline:no-seed": "cross-env VITE_ENV=dev NO_SEED_DATA=true ORM=waterline tsx watch --tsconfig ./fixture/tsconfig.json ./fixture/index.ts",
|
|
18
19
|
"build:assets": "vite build",
|
|
19
20
|
"compile:backend": "tsc -p src/tsconfig.json",
|
|
20
21
|
"compile:ui": "tsc -p tsconfig.ui.json",
|
|
@@ -67,12 +68,11 @@
|
|
|
67
68
|
"react-dnd": "^16.0.1",
|
|
68
69
|
"reflect-metadata": "^0.2.2",
|
|
69
70
|
"sharp": "^0.33.5",
|
|
71
|
+
"sprintf-js": "^1.1.3",
|
|
70
72
|
"typeorm": "^0.3.20",
|
|
71
73
|
"uuid": "^11.0.5",
|
|
72
74
|
"waterline": "^0.15.2",
|
|
73
|
-
"winston": "^3.17.0"
|
|
74
|
-
"sprintf-js": "^1.1.3",
|
|
75
|
-
"sequelize": "^6.37.7"
|
|
75
|
+
"winston": "^3.17.0"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"@babel/plugin-proposal-decorators": "^7.27.1",
|
|
@@ -147,6 +147,7 @@
|
|
|
147
147
|
"sails-disk": "^2.1.2",
|
|
148
148
|
"sails-postgresql": "^5.0.1",
|
|
149
149
|
"sequelize-typescript": "^2.1.6",
|
|
150
|
+
"sequelize": "^6.37.7",
|
|
150
151
|
"shelljs": "^0.9.2",
|
|
151
152
|
"sonner": "^2.0.3",
|
|
152
153
|
"sqlite3": "^5.1.7",
|