data-primals-engine 1.5.2 → 1.6.1
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/README.md +938 -915
- package/client/README.md +136 -136
- package/client/index.js +0 -1
- package/client/public/doc/API.postman_collection.json +213 -213
- package/client/public/react.svg +9 -9
- package/client/src/AddWidgetTypeModal.jsx +47 -47
- package/client/src/App.css +42 -42
- package/client/src/App.jsx +92 -150
- package/client/src/App.scss +6 -0
- package/client/src/AssistantChat.jsx +362 -363
- package/client/src/Button.jsx +12 -12
- package/client/src/Dashboard.jsx +480 -480
- package/client/src/DashboardHtmlViewItem.jsx +146 -146
- package/client/src/DashboardView.jsx +654 -654
- package/client/src/DataEditor.jsx +383 -383
- package/client/src/DataLayout.jsx +779 -808
- package/client/src/DataTable.jsx +782 -822
- package/client/src/DataTable.scss +186 -186
- package/client/src/GeolocationField.jsx +93 -93
- package/client/src/HistoryDialog.jsx +307 -307
- package/client/src/HistoryDialog.scss +319 -319
- package/client/src/HtmlViewBuilderModal.jsx +90 -90
- package/client/src/HtmlViewBuilderModal.scss +17 -17
- package/client/src/HtmlViewCard.jsx +43 -43
- package/client/src/ModelCreator.jsx +683 -686
- package/client/src/ModelCreator.scss +1 -1
- package/client/src/ModelCreatorField.jsx +950 -950
- package/client/src/ModelImporter.jsx +3 -0
- package/client/src/ModelList.jsx +280 -280
- package/client/src/Notification.jsx +136 -136
- package/client/src/PackGallery.jsx +391 -391
- package/client/src/PackGallery.scss +231 -231
- package/client/src/Pagination.jsx +143 -143
- package/client/src/RelationField.jsx +354 -354
- package/client/src/RelationSelectorWidget.jsx +172 -172
- package/client/src/RelationValue.jsx +2 -1
- package/client/src/contexts/CommandContext.jsx +260 -0
- package/client/src/contexts/ModelContext.jsx +4 -1
- package/client/src/contexts/UIContext.jsx +72 -72
- package/client/src/filter.js +263 -263
- package/client/src/index.css +90 -90
- package/package.json +6 -5
- package/perf/artillery-hooks.js +37 -37
- package/perf/setup.yml +25 -25
- package/src/constants.js +4 -0
- package/src/defaultModels.js +7 -0
- package/src/engine.js +335 -335
- package/src/events.js +232 -137
- package/src/filter.js +274 -274
- package/src/index.js +1 -0
- package/src/modules/assistant/assistant.js +225 -83
- package/src/modules/auth-google/index.js +50 -50
- package/src/modules/auth-microsoft/index.js +81 -81
- package/src/modules/data/data.core.js +118 -118
- package/src/modules/data/data.history.js +555 -555
- package/src/modules/data/data.operations.js +112 -9
- package/src/modules/data/data.relations.js +686 -686
- package/src/modules/data/data.routes.js +1879 -1879
- package/src/modules/data/data.validation.js +2 -2
- package/src/modules/file.js +247 -247
- package/src/modules/user.js +14 -9
- package/src/packs.js +2 -2
- package/src/providers.js +2 -2
- package/src/services/stripe.js +196 -196
- package/src/sso.js +193 -193
- package/test/data.history.integration.test.js +264 -264
- package/test/data.integration.test.js +1281 -1206
- package/test/events.test.js +108 -10
- package/test/model.integration.test.js +377 -377
- package/test/user.test.js +106 -1
package/src/events.js
CHANGED
|
@@ -1,137 +1,232 @@
|
|
|
1
|
-
import {safeAssignObject} from "./core.js";
|
|
2
|
-
|
|
3
|
-
const events = {};
|
|
4
|
-
|
|
5
|
-
const eventLayerSystems = {
|
|
6
|
-
"priority": ["high", "medium", "low"],
|
|
7
|
-
"log": ["info", "debug", "warn", "error", "critical"],
|
|
8
|
-
"system": ["calls", "users"],
|
|
9
|
-
"event": ["system","user"],
|
|
10
|
-
"custom": ["data"]
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
1
|
+
import {safeAssignObject} from "./core.js";
|
|
2
|
+
|
|
3
|
+
const events = {};
|
|
4
|
+
|
|
5
|
+
const eventLayerSystems = {
|
|
6
|
+
"priority": ["high", "medium", "low"],
|
|
7
|
+
"log": ["info", "debug", "warn", "error", "critical"],
|
|
8
|
+
"system": ["calls", "users"],
|
|
9
|
+
"event": ["system","user"],
|
|
10
|
+
"custom": ["data"]
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Parses a priority string/number into a structured object for sorting.
|
|
15
|
+
* @param {string|number} [priority='identity'] - The priority value.
|
|
16
|
+
* - 'beforeAll': Executes before all others in the same layer.
|
|
17
|
+
* - 'afterAll': Executes after all others in the same layer.
|
|
18
|
+
* - A number (e.g., 50): A numeric weight (lower is higher priority).
|
|
19
|
+
* - 'identity' or undefined: Default, executes in registration order after weighted listeners.
|
|
20
|
+
* @returns {{type: string, weight: number}}
|
|
21
|
+
* @private
|
|
22
|
+
*/
|
|
23
|
+
function _parsePriority(priority = 'identity') {
|
|
24
|
+
if (priority === 'beforeAll') {
|
|
25
|
+
return { type: 'special', weight: -Infinity };
|
|
26
|
+
}
|
|
27
|
+
if (priority === 'afterAll') {
|
|
28
|
+
return { type: 'special', weight: Infinity };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const numericWeight = parseInt(priority, 10);
|
|
32
|
+
if (!isNaN(numericWeight)) {
|
|
33
|
+
return {
|
|
34
|
+
type: 'weighted',
|
|
35
|
+
weight: numericWeight
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Default for 'identity' or any unrecognized format
|
|
40
|
+
return { type: 'identity', weight: Number.MAX_SAFE_INTEGER };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
export const Event = {
|
|
48
|
+
Trigger: async (name, system = "priority", layer = "medium", ...args) => { // Ajout des arguments system et layer
|
|
49
|
+
if (!name || typeof name !== 'string') {
|
|
50
|
+
throw new Error('Event name must be a non-empty string');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!events[system] || !events[system][name] || (layer && !events[system][name][layer])) {
|
|
54
|
+
//console.warn(`No trigger found for ${name} in system ${system} layer ${layer}`);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const systemsToProcess = system ? [system] : Object.keys(events); // Si system est spécifié, on cible ce système uniquement, sinon tous les systèmes
|
|
59
|
+
console.log(`[Event] Triggering ${system}.${layer}.${name}`, {
|
|
60
|
+
callbacks: events[system]?.[name]?.[layer]?.length || 0
|
|
61
|
+
});
|
|
62
|
+
let ret = null;
|
|
63
|
+
for (const currentSystem of systemsToProcess) {
|
|
64
|
+
if (events[currentSystem] && events[currentSystem][name]) {
|
|
65
|
+
const layersToProcess = layer ? [layer] : eventLayerSystems[currentSystem] || Object.keys(events[currentSystem][name]); // Si layer est spécifié, on cible cette couche, sinon toutes les couches ou celles définies dans eventLayerSystems
|
|
66
|
+
|
|
67
|
+
if (layersToProcess) {
|
|
68
|
+
for (const currentLayer of layersToProcess) {
|
|
69
|
+
if (events[currentSystem][name][currentLayer]) {
|
|
70
|
+
// Create a copy and sort listeners based on priority before execution
|
|
71
|
+
const sortedListeners = [...events[currentSystem][name][currentLayer]].sort((a, b) => {
|
|
72
|
+
const weightDifference = a.priority.weight - b.priority.weight;
|
|
73
|
+
if (weightDifference !== 0) {
|
|
74
|
+
return weightDifference;
|
|
75
|
+
}
|
|
76
|
+
// For listeners with the same weight (especially 'identity'), maintain registration order
|
|
77
|
+
return a.originalIndex - b.originalIndex;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
for (const listener of sortedListeners) {
|
|
81
|
+
try {
|
|
82
|
+
const res = await listener.callback(...args);
|
|
83
|
+
if (typeof res === "object" && !Array.isArray(res)) {
|
|
84
|
+
if (typeof ret !== "object") ret = {};
|
|
85
|
+
ret = {...ret, ...res};
|
|
86
|
+
} else if (Array.isArray(res)) {
|
|
87
|
+
if (!ret || !Array.isArray(ret)) ret = [];
|
|
88
|
+
ret = ret.concat(res);
|
|
89
|
+
} else if (res !== undefined && res !== null) {
|
|
90
|
+
// Simplified aggregation for primitive types
|
|
91
|
+
if (typeof res === "string") {
|
|
92
|
+
ret = (ret || "") + res;
|
|
93
|
+
} else if (typeof res === "number") {
|
|
94
|
+
ret = (ret || 0) + res;
|
|
95
|
+
} else if (typeof res === "boolean") {
|
|
96
|
+
ret = res && (ret === null ? true : ret);
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
ret = res || ret;
|
|
100
|
+
}
|
|
101
|
+
} catch (error) {
|
|
102
|
+
const errorMsg = `Error in callback for event ${name} in system ${currentSystem} layer ${currentLayer}: ${error.message}`;
|
|
103
|
+
const newError = new Error(errorMsg);
|
|
104
|
+
newError.originalError = error; // Conserve l'erreur originale
|
|
105
|
+
newError.eventDetails = { name, system: currentSystem, layer: currentLayer };
|
|
106
|
+
throw newError;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return ret;
|
|
115
|
+
},
|
|
116
|
+
Listen: function(name = "", callback, ...args) {
|
|
117
|
+
let system = "priority";
|
|
118
|
+
let layer = "medium";
|
|
119
|
+
let priority = 'identity';
|
|
120
|
+
|
|
121
|
+
// Détecte si la nouvelle signature (avec objet) ou l'ancienne (avec arguments multiples) est utilisée.
|
|
122
|
+
if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null && !Array.isArray(args[0])) {
|
|
123
|
+
// Nouvelle signature: Listen(name, cb, { system, layer, priority })
|
|
124
|
+
({ system = "priority", layer = "medium", priority = 'identity' } = args[0]);
|
|
125
|
+
} else if (args.length > 0) {
|
|
126
|
+
// Ancienne signature: Listen(name, cb, system, layer, priority)
|
|
127
|
+
[system = "priority", layer = "medium", priority = 'identity'] = args;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const validSystems = Object.keys(eventLayerSystems);
|
|
131
|
+
if (!validSystems.includes(system)) {
|
|
132
|
+
throw new Error(`System '${system}' does not exist. Valid systems are: ${validSystems.join(', ')}`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const validLayers = eventLayerSystems[system];
|
|
136
|
+
if (!validLayers.includes(layer)) {
|
|
137
|
+
throw new Error(`Layer '${layer}' does not exist in system '${system}'. Valid layers are: ${validLayers.join(', ')}`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
safeAssignObject(events, system, events[system] || {});
|
|
141
|
+
safeAssignObject(events[system], name, events[system][name] || {});
|
|
142
|
+
safeAssignObject(events[system][name], layer, events[system][name][layer] || []);
|
|
143
|
+
|
|
144
|
+
const listener = {
|
|
145
|
+
callback,
|
|
146
|
+
priority: _parsePriority(priority),
|
|
147
|
+
originalIndex: events[system][name][layer].length
|
|
148
|
+
};
|
|
149
|
+
events[system][name][layer].push(listener);
|
|
150
|
+
},
|
|
151
|
+
addSystem: (system) => {
|
|
152
|
+
if (typeof system !== 'string' || system.trim() === '') {
|
|
153
|
+
throw new Error('Le nom du système doit être une chaîne de caractères non vide.');
|
|
154
|
+
}
|
|
155
|
+
if (!eventLayerSystems.hasOwnProperty(system)) {
|
|
156
|
+
eventLayerSystems[system] = [];
|
|
157
|
+
} else {
|
|
158
|
+
console.warn(`[Event] Le système '${system}' existe déjà.`);
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
addLayer: (system, layer) => {
|
|
162
|
+
if (typeof system !== 'string' || system.trim() === '') {
|
|
163
|
+
throw new Error('Le nom du système doit être une chaîne de caractères non vide.');
|
|
164
|
+
}
|
|
165
|
+
if (typeof layer !== 'string' || layer.trim() === '') {
|
|
166
|
+
throw new Error('Le nom de la couche doit être une chaîne de caractères non vide.');
|
|
167
|
+
}
|
|
168
|
+
if (!eventLayerSystems.hasOwnProperty(system)) {
|
|
169
|
+
throw new Error(`Le système '${system}' n'existe pas. Veuillez l'ajouter avec addSystem('${system}').`);
|
|
170
|
+
}
|
|
171
|
+
if (!eventLayerSystems[system].includes(layer)) {
|
|
172
|
+
eventLayerSystems[system].push(layer);
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
RemoveCallback: function(name, callback, ...args) {
|
|
176
|
+
let system = "priority";
|
|
177
|
+
let layer = "medium";
|
|
178
|
+
|
|
179
|
+
if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null && !Array.isArray(args[0])) {
|
|
180
|
+
// Nouvelle signature: Unlisten(name, cb, { system, layer })
|
|
181
|
+
({ system = "priority", layer = "medium" } = args[0]);
|
|
182
|
+
} else if (args.length > 0) {
|
|
183
|
+
// Ancienne signature: Unlisten(name, cb, system, layer)
|
|
184
|
+
[system = "priority", layer = "medium"] = args;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (!events[system] || !events[system][name] || !events[system][name][layer]) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const index = events[system][name][layer].findIndex(listener => listener.callback === callback);
|
|
192
|
+
if (index > -1) {
|
|
193
|
+
events[system][name][layer].splice(index, 1);
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Removes all listeners from a specific event layer that match a given priority.
|
|
199
|
+
* @param {string} name - The name of the event.
|
|
200
|
+
* @param {string|number} priority - The priority to remove ('beforeAll', 'afterAll', a number, or 'identity').
|
|
201
|
+
* @param {object} [options={}] - Options to specify the system and layer.
|
|
202
|
+
* @param {string} [options.system='priority'] - The system of the event.
|
|
203
|
+
* @param {string} [options.layer='medium'] - The layer of the event.
|
|
204
|
+
*/
|
|
205
|
+
RemoveCallbacksByPriority: function(name, priority, options = {}) {
|
|
206
|
+
const { system = "priority", layer = "medium" } = options;
|
|
207
|
+
|
|
208
|
+
if (!events[system] || !events[system][name] || !events[system][name][layer]) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const parsedPriorityToRemove = _parsePriority(priority);
|
|
213
|
+
events[system][name][layer] = events[system][name][layer].filter(listener => {
|
|
214
|
+
// Keep the listener if its priority does NOT match the one to remove
|
|
215
|
+
return listener.priority.type !== parsedPriorityToRemove.type || listener.priority.weight !== parsedPriorityToRemove.weight;
|
|
216
|
+
});
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
// Ajout d'une méthode pour supprimer tous les callbacks d'un événement (optionnel)
|
|
220
|
+
RemoveAllCallbacks: (name, system = 'priority') => {
|
|
221
|
+
if (events[system] && events[system][name]) {
|
|
222
|
+
delete events[system][name]; // Supprime l'objet contenant les couches et les callbacks
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
// Ajout d'une méthode pour supprimer tous les callbacks d'un système (optionnel)
|
|
227
|
+
RemoveSystemCallbacks: (system) => {
|
|
228
|
+
if (events[system]) {
|
|
229
|
+
delete events[system];
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|