data-primals-engine 1.6.1 → 1.6.2-rc1
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 +968 -938
- package/client/package-lock.json +524 -5
- package/client/package.json +2 -1
- package/client/src/App.scss +14 -1
- package/client/src/Dashboard.jsx +4 -0
- package/client/src/DataLayout.jsx +85 -20
- package/client/src/DataLayout.scss +32 -6
- package/client/src/DataTable.jsx +18 -11
- package/client/src/ModelCreator.jsx +686 -683
- package/client/src/ModelImporter.jsx +1 -1
- package/client/src/ViewSwitcher.jsx +1 -1
- package/client/src/WorkflowEditor.jsx +317 -0
- package/client/src/WorkflowEditor.scss +16 -0
- package/package.json +142 -142
- package/src/defaultModels.js +5 -2
- package/src/i18n.js +35 -3
- package/src/modules/data/data.operations.js +3487 -3484
- package/src/modules/workflow.js +1 -4
- package/src/packs.js +239 -24
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, {useState, useEffect} from 'react';
|
|
2
2
|
import { useModelContext } from './contexts/ModelContext.jsx';
|
|
3
3
|
import { useAuthContext } from './contexts/AuthContext.jsx';
|
|
4
|
-
import {Trans, useTranslation} from '
|
|
4
|
+
import {Trans, useTranslation} from '../../src/i18n.js';
|
|
5
5
|
import {FaArrowDown, FaInfo} from 'react-icons/fa';
|
|
6
6
|
import { CheckboxField } from './Field.jsx';
|
|
7
7
|
import Button from './Button.jsx';
|
|
@@ -30,7 +30,7 @@ const ViewSwitcher = ({ currentView, onViewChange, configuredViews, onConfigureV
|
|
|
30
30
|
title={t(view.labelKey, view.defaultLabel)}
|
|
31
31
|
>
|
|
32
32
|
{view.icon}
|
|
33
|
-
|
|
33
|
+
{/*<span className="hidden md:inline-block ml-2">{t(view.labelKey, view.defaultLabel)}</span>*/}
|
|
34
34
|
</Button>
|
|
35
35
|
{/* AJOUT : Bouton de configuration pour la vue active */}
|
|
36
36
|
{isActive && view.id !== 'table' && (
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import React, { useState, useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
import ReactFlow, {
|
|
3
|
+
MiniMap,
|
|
4
|
+
Controls,
|
|
5
|
+
Background,
|
|
6
|
+
useNodesState,
|
|
7
|
+
useEdgesState,
|
|
8
|
+
addEdge
|
|
9
|
+
} from 'reactflow';
|
|
10
|
+
import 'reactflow/dist/style.css';
|
|
11
|
+
import { useModelContext } from './contexts/ModelContext';
|
|
12
|
+
import { useAuthContext } from './contexts/AuthContext';
|
|
13
|
+
import { Trans, useTranslation } from 'react-i18next';
|
|
14
|
+
import { CodeField } from "./Field.jsx";
|
|
15
|
+
import { useQuery } from 'react-query';
|
|
16
|
+
|
|
17
|
+
import "./WorkflowEditor.scss"
|
|
18
|
+
// --- Custom Node Types (à créer) ---
|
|
19
|
+
// import TriggerNode from './nodes/TriggerNode';
|
|
20
|
+
// import StepNode from './nodes/StepNode';
|
|
21
|
+
|
|
22
|
+
const nodeTypes = {
|
|
23
|
+
// trigger: TriggerNode,
|
|
24
|
+
// step: StepNode,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const WorkflowEditor = ({ workflowId }) => {
|
|
28
|
+
const { t } = useTranslation();
|
|
29
|
+
const { me } = useAuthContext();
|
|
30
|
+
const { models } = useModelContext();
|
|
31
|
+
|
|
32
|
+
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
|
33
|
+
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
|
34
|
+
const [selectedNode, setSelectedNode] = useState(null);
|
|
35
|
+
const [panelWidth, setPanelWidth] = useState(300);
|
|
36
|
+
const resizeData = useRef({ isResizing: false, initialX: 0, initialWidth: 0 });
|
|
37
|
+
|
|
38
|
+
const handleMouseDown = (e) => {
|
|
39
|
+
e.preventDefault();
|
|
40
|
+
resizeData.current = {
|
|
41
|
+
isResizing: true,
|
|
42
|
+
initialX: e.clientX,
|
|
43
|
+
initialWidth: panelWidth
|
|
44
|
+
};
|
|
45
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
46
|
+
document.addEventListener('mouseup', handleMouseUp);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const handleMouseMove = useCallback((e) => {
|
|
50
|
+
if (!resizeData.current.isResizing) return; // Utilise la référence qui ne change pas
|
|
51
|
+
const dx = e.clientX - resizeData.current.initialX; // Calcule le delta depuis le clic initial
|
|
52
|
+
const newWidth = resizeData.current.initialWidth - dx; // Applique le delta à la largeur initiale
|
|
53
|
+
setPanelWidth(Math.max(200, Math.min(newWidth, 800))); // Applique les limites
|
|
54
|
+
}, []); // Plus besoin de dépendances, la logique est entièrement contenue dans la ref
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
const handleMouseUp = () => {
|
|
58
|
+
resizeData.current.isResizing = false;
|
|
59
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
60
|
+
document.removeEventListener('mouseup', handleMouseUp);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
// Query 1: Fetch the main workflow document
|
|
65
|
+
const { data: mainWorkflowData, isLoading: isLoadingMainWorkflow, error: errorMainWorkflow } = useQuery(
|
|
66
|
+
['mainWorkflow', workflowId],
|
|
67
|
+
() => fetch('/api/data/search?_user='+me.username, {
|
|
68
|
+
method: 'POST',
|
|
69
|
+
headers: { 'Content-Type': 'application/json' },
|
|
70
|
+
body: JSON.stringify({
|
|
71
|
+
model: 'workflow',
|
|
72
|
+
filter: { $eq: [{$toString:'$_id'}, workflowId] },
|
|
73
|
+
// No pipelines, no depth here, as per user request
|
|
74
|
+
})
|
|
75
|
+
}).then(res => res.json()),
|
|
76
|
+
{
|
|
77
|
+
enabled: !!workflowId,
|
|
78
|
+
select: (data) => data?.data?.[0]
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// Query 2: Fetch all workflowStep documents related to this workflow
|
|
83
|
+
const { data: workflowStepsData, isLoading: isLoadingSteps, error: errorSteps } = useQuery(
|
|
84
|
+
['workflowSteps', workflowId],
|
|
85
|
+
() => fetch('/api/data/search?_user=' + me.username, {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
headers: { 'Content-Type': 'application/json' },
|
|
88
|
+
body: JSON.stringify({
|
|
89
|
+
model: 'workflowStep',
|
|
90
|
+
filter: { workflow: workflowId },
|
|
91
|
+
// Use a shallow depth to populate direct relations like 'actions'
|
|
92
|
+
// This avoids a deep recursive lookup for the entire graph, but makes step data usable
|
|
93
|
+
depth: 1
|
|
94
|
+
})
|
|
95
|
+
}).then(res => res.json()),
|
|
96
|
+
{
|
|
97
|
+
enabled: !!workflowId, // La requête ne s'exécute que si workflowId est défini
|
|
98
|
+
select: (data) => data?.data || []
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// Query 3: Fetch all workflowAction documents related to this workflow
|
|
103
|
+
const { data: workflowActionsData, isLoading: isLoadingActions, error: errorActions } = useQuery(
|
|
104
|
+
['workflowActions', workflowId],
|
|
105
|
+
() => fetch('/api/data/search?_user=' + me.username, {
|
|
106
|
+
method: 'POST',
|
|
107
|
+
headers: { 'Content-Type': 'application/json' },
|
|
108
|
+
body: JSON.stringify({
|
|
109
|
+
model: 'workflowAction',
|
|
110
|
+
filter: { workflow: workflowId },
|
|
111
|
+
// No depth needed here as actions are usually flat
|
|
112
|
+
})
|
|
113
|
+
}).then(res => res.json()),
|
|
114
|
+
{
|
|
115
|
+
enabled: !!workflowId,
|
|
116
|
+
select: (data) => data?.data || []
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
if (mainWorkflowData && workflowStepsData && workflowActionsData) {
|
|
122
|
+
const initialNodes = [];
|
|
123
|
+
const initialEdges = [];
|
|
124
|
+
const processedSteps = new Set();
|
|
125
|
+
|
|
126
|
+
// Create a map for quick lookup of steps
|
|
127
|
+
const stepsMap = new Map(workflowStepsData.map(step => [step._id, step]));
|
|
128
|
+
|
|
129
|
+
// 1. Nœud du déclencheur (Trigger)
|
|
130
|
+
initialNodes.push({
|
|
131
|
+
id: `workflow-start-${mainWorkflowData._id}`,
|
|
132
|
+
type: 'input',
|
|
133
|
+
position: { x: 250, y: 5 },
|
|
134
|
+
data: {
|
|
135
|
+
label: `Début: ${typeof mainWorkflowData.name === 'object' ? mainWorkflowData.name.value : mainWorkflowData.name}`,
|
|
136
|
+
// --- CORRECTION ---
|
|
137
|
+
// On inclut toutes les données du workflow pour la cohérence
|
|
138
|
+
...mainWorkflowData
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Create a map for quick lookup of actions
|
|
143
|
+
const actionsMap = new Map(workflowActionsData.map(action => [action._id, action]));
|
|
144
|
+
|
|
145
|
+
// 2. Traitement récursif des étapes
|
|
146
|
+
const processStep = (stepId, parentNodeId, parentPosition, isSuccessBranch = true) => {
|
|
147
|
+
if (!stepId || processedSteps.has(stepId)) return;
|
|
148
|
+
|
|
149
|
+
const step = stepsMap.get(stepId);
|
|
150
|
+
if (!step) {
|
|
151
|
+
console.warn(`WorkflowEditor: Step with ID ${stepId} not found in fetched steps.`);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
processedSteps.add(stepId);
|
|
156
|
+
|
|
157
|
+
const nodePosition = { x: parentPosition.x, y: parentPosition.y + 120 };
|
|
158
|
+
initialNodes.push({
|
|
159
|
+
id: step._id,
|
|
160
|
+
type: 'default',
|
|
161
|
+
className: 'workflow-step-node',
|
|
162
|
+
position: nodePosition,
|
|
163
|
+
data: {
|
|
164
|
+
label: (step?.name && typeof step.name === 'object' ? step.name.value : step.name) || `Étape ${step._id}`,
|
|
165
|
+
...step // --- CORRECTION --- On inclut l'objet step complet
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
initialEdges.push({ id: `e-${parentNodeId}-${step._id}`, source: parentNodeId, target: step._id, type: 'smoothstep' });
|
|
169
|
+
|
|
170
|
+
let lastActionId = step._id;
|
|
171
|
+
// The actions on the step are just IDs now, we need to look them up
|
|
172
|
+
const actionIds = Array.isArray(step.actions) ? step.actions : (step.actions ? [step.actions] : []);
|
|
173
|
+
const actions = actionIds.map(id => actionsMap.get(id)).filter(Boolean); // Get full action objects
|
|
174
|
+
|
|
175
|
+
if (actionIds.length !== actions.length) {
|
|
176
|
+
const missingIds = actionIds.filter(id => !actionsMap.has(id));
|
|
177
|
+
console.warn(`WorkflowEditor: Could not find the following actions: ${missingIds.join(', ')}`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
actions.forEach((action, index) => {
|
|
181
|
+
const actionNodePosition = { x: nodePosition.x, y: nodePosition.y + (index + 1) * 80 };
|
|
182
|
+
initialNodes.push({
|
|
183
|
+
id: action._id,
|
|
184
|
+
type: 'default',
|
|
185
|
+
className: 'workflow-action-node',
|
|
186
|
+
position: actionNodePosition,
|
|
187
|
+
data: {
|
|
188
|
+
label: action.name.value || `Action ${action._id}`,
|
|
189
|
+
...action // --- CORRECTION --- On inclut l'objet action complet
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
initialEdges.push({ id: `e-${lastActionId}-${action._id}`, source: lastActionId, target: action._id, type: 'smoothstep' });
|
|
193
|
+
lastActionId = action._id;
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Créer les liens (edges)
|
|
197
|
+
if (step.onSuccessStep && typeof step.onSuccessStep === 'string') { // onSuccessStep is an ID
|
|
198
|
+
processStep(step.onSuccessStep, lastActionId, { x: nodePosition.x - 200, y: nodePosition.y + (actions.length * 80) }, true);
|
|
199
|
+
initialEdges.push({ id: `e-${lastActionId}-success-${step.onSuccessStep}`, source: lastActionId, target: step.onSuccessStep, label: t('onSuccess', 'onSuccess'), type: 'smoothstep' });
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (step.onFailureStep && typeof step.onFailureStep === 'string') { // onFailureStep is an ID
|
|
203
|
+
processStep(step.onFailureStep, lastActionId, { x: nodePosition.x + 200, y: nodePosition.y + (actions.length * 80) }, false);
|
|
204
|
+
initialEdges.push({ id: `e-${lastActionId}-failure-${step.onFailureStep}`, source: lastActionId, target: step.onFailureStep, label: t('onFailure', 'onFailure'), type: 'smoothstep', animated: true, style: { stroke: '#ff4d4d' } });
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
if (mainWorkflowData.startStep) {
|
|
209
|
+
initialEdges.push({
|
|
210
|
+
id: `e-start-${mainWorkflowData.startStep}`, // startStep is an ID
|
|
211
|
+
source: `workflow-start-${mainWorkflowData._id}`,
|
|
212
|
+
target: mainWorkflowData.startStep,
|
|
213
|
+
type: 'smoothstep',
|
|
214
|
+
});
|
|
215
|
+
processStep(mainWorkflowData.startStep, `workflow-start-${mainWorkflowData._id}`, { x: 250, y: 5 });
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
setNodes(initialNodes);
|
|
219
|
+
setEdges(initialEdges);
|
|
220
|
+
}
|
|
221
|
+
}, [mainWorkflowData, workflowStepsData, workflowActionsData, setNodes, setEdges, t]);
|
|
222
|
+
|
|
223
|
+
const onConnect = useCallback(
|
|
224
|
+
(params) => setEdges((eds) => addEdge(params, eds)),
|
|
225
|
+
[setEdges],
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const onNodeClick = useCallback((event, node) => { // Keep this for potential future node editing
|
|
229
|
+
setSelectedNode(node);
|
|
230
|
+
console.log('Node clicked:', node);
|
|
231
|
+
}, []);
|
|
232
|
+
|
|
233
|
+
const onPaneClick = useCallback(() => { // Keep this for potential future node editing
|
|
234
|
+
setSelectedNode(null);
|
|
235
|
+
}, []);
|
|
236
|
+
|
|
237
|
+
if (isLoadingMainWorkflow || isLoadingSteps || isLoadingActions) { // Check all loading states
|
|
238
|
+
return <div>{t('loading', 'Chargement...')}</div>;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (errorMainWorkflow || errorSteps || errorActions) { // Check all error states
|
|
242
|
+
const errorMessage = errorMainWorkflow?.message || errorSteps?.message || errorActions?.message || 'Unknown error';
|
|
243
|
+
return <div><Trans i18nKey="error.generic" values={{ message: errorMessage }}>Erreur: {{ message: errorMessage }}</Trans></div>;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return (
|
|
247
|
+
<div className={"flex-1"} style={{ width: '100%', height: '80vh', display: 'flex' }}>
|
|
248
|
+
<ReactFlow
|
|
249
|
+
nodes={nodes}
|
|
250
|
+
edges={edges}
|
|
251
|
+
onNodesChange={onNodesChange}
|
|
252
|
+
onEdgesChange={onEdgesChange}
|
|
253
|
+
onConnect={onConnect}
|
|
254
|
+
onNodeClick={onNodeClick}
|
|
255
|
+
onPaneClick={onPaneClick}
|
|
256
|
+
nodeTypes={nodeTypes}
|
|
257
|
+
fitView
|
|
258
|
+
>
|
|
259
|
+
<Controls />
|
|
260
|
+
<MiniMap />
|
|
261
|
+
<Background variant="dots" gap={12} size={1} />
|
|
262
|
+
</ReactFlow>
|
|
263
|
+
|
|
264
|
+
{/* Panneau latéral pour l'édition des propriétés */}
|
|
265
|
+
{selectedNode && (
|
|
266
|
+
<div className="properties-panel" style={{ width: `${panelWidth}px`, padding: '10px', borderLeft: '1px solid #ccc' }}>
|
|
267
|
+
<div
|
|
268
|
+
className="resizer"
|
|
269
|
+
onMouseDown={handleMouseDown}
|
|
270
|
+
/>
|
|
271
|
+
<h3><Trans i18nKey="properties">Propriétés</Trans></h3>
|
|
272
|
+
<p><strong>ID:</strong> {selectedNode.id}</p>
|
|
273
|
+
|
|
274
|
+
{/* Affiche les conditions pour un workflowStep */}
|
|
275
|
+
{selectedNode.data.conditions && (
|
|
276
|
+
<div className="mt-2">
|
|
277
|
+
<strong><Trans i18nKey="conditions">Conditions:</Trans></strong>
|
|
278
|
+
<CodeField language="json" value={JSON.stringify(selectedNode.data.conditions, null, 2)} readOnly={true} />
|
|
279
|
+
</div>
|
|
280
|
+
)}
|
|
281
|
+
|
|
282
|
+
{/* Affiche le script pour une action ExecuteScript */}
|
|
283
|
+
{selectedNode.data.type && (
|
|
284
|
+
<div className="mt-2">
|
|
285
|
+
<strong><Trans i18nKey="action">Action :</Trans></strong> {selectedNode.data.type}
|
|
286
|
+
{selectedNode.data.targetModel&& (
|
|
287
|
+
<p>
|
|
288
|
+
<strong><Trans i18nKey="action">Modèle cible : </Trans></strong>{selectedNode.data.targetModel}
|
|
289
|
+
</p>
|
|
290
|
+
)}
|
|
291
|
+
{selectedNode.data.targetSelector&& (
|
|
292
|
+
<p>
|
|
293
|
+
<strong><Trans i18nKey="filter">Filtre sur :</Trans></strong>
|
|
294
|
+
<br/><CodeField language="javascript" value={JSON.stringify(selectedNode.data.targetSelector)} readOnly={true} />
|
|
295
|
+
</p>
|
|
296
|
+
)}
|
|
297
|
+
{(selectedNode.data.dataToCreate || selectedNode.data.fieldsToUpdate) && (
|
|
298
|
+
<p>
|
|
299
|
+
<strong><Trans i18nKey="filter">Code déclenché :</Trans></strong>
|
|
300
|
+
<br/><CodeField language="javascript" value={JSON.stringify(selectedNode.data.dataToCreate || selectedNode.data.fieldsToUpdate)} readOnly={true} />
|
|
301
|
+
</p>
|
|
302
|
+
)}
|
|
303
|
+
</div>
|
|
304
|
+
)}
|
|
305
|
+
{/* Affiche le script pour une action ExecuteScript */}
|
|
306
|
+
{selectedNode.data.type === 'ExecuteScript' && selectedNode.data.script && (
|
|
307
|
+
<div className="mt-2">
|
|
308
|
+
<CodeField language="javascript" value={selectedNode.data.script} readOnly={true} />
|
|
309
|
+
</div>
|
|
310
|
+
)}
|
|
311
|
+
</div>
|
|
312
|
+
)}
|
|
313
|
+
</div>
|
|
314
|
+
);
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
export default WorkflowEditor;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
.workflow-step-node {
|
|
3
|
+
background-color: #e0e7ff; /* Un bleu clair pour les étapes */
|
|
4
|
+
border-color: #a5b4fc;
|
|
5
|
+
border-width: 2px;
|
|
6
|
+
font-weight: bold;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.workflow-action-node {
|
|
10
|
+
background-color: #f0f9ff; /* Un bleu très clair pour les actions */
|
|
11
|
+
border-color: #bae6fd;
|
|
12
|
+
border-width: 1px;
|
|
13
|
+
border-style: dashed;
|
|
14
|
+
width: auto;
|
|
15
|
+
min-width: 150px;
|
|
16
|
+
}
|
package/package.json
CHANGED
|
@@ -1,142 +1,142 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "data-primals-engine",
|
|
3
|
-
"version": "1.6.
|
|
4
|
-
"description": "data-primals-engine is a package responsible from handling large amount of data using MongoDB in a practical and performant way. It can also get workflow models working (for automation), and fully supports internationalisation. It also has integrated AI assistant.",
|
|
5
|
-
"main": "src/engine.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"preinstall": "npx force-resolutions",
|
|
9
|
-
"dev": "concurrently \"npm:client\" \"npm:devserver\"",
|
|
10
|
-
"prod": "npm run build-server && npm run server",
|
|
11
|
-
"client": "cd client && npm run dev",
|
|
12
|
-
"build-server": "vite build client --config client/vite.config.js --outDir dist",
|
|
13
|
-
"build-client": "cd client && npm run build",
|
|
14
|
-
"server": "cross-env NODE_ENV=production node server.js",
|
|
15
|
-
"devserver": "npm run build-server && cross-env NODE_ENV=development PORT=7633 node server.js",
|
|
16
|
-
"lint": "eslint .",
|
|
17
|
-
"format": "prettier --write .",
|
|
18
|
-
"clean": "rm -rf node_modules package-lock.json",
|
|
19
|
-
"test": "cross-env MONGO_DB_URL=\"mongodb://localhost:27017\" PORT=7635 vitest --no-file-parallelism --no-watch",
|
|
20
|
-
"audit": "npm audit --audit-level=high",
|
|
21
|
-
"migrate:create": "node src/migrate.js create",
|
|
22
|
-
"migrate:up": "node src/migrate.js up",
|
|
23
|
-
"migrate:down": "node src/migrate.js down",
|
|
24
|
-
"migrate:revert": "node src/migrate.js revert",
|
|
25
|
-
"migrate:status": "node src/migrate.js status"
|
|
26
|
-
},
|
|
27
|
-
"optionalDependencies": {
|
|
28
|
-
"@rollup/rollup-linux-x64-gnu": "4.6.1"
|
|
29
|
-
},
|
|
30
|
-
"resolutions": {
|
|
31
|
-
"on-headers": "1.1.0",
|
|
32
|
-
"brace-expansion": "2.0.2",
|
|
33
|
-
"prismjs": "1.30.0",
|
|
34
|
-
"xml2js": ">=0.5.0",
|
|
35
|
-
"tar-fs": ">=3.1.1",
|
|
36
|
-
"vite": ">=7.0.8"
|
|
37
|
-
},
|
|
38
|
-
"overrides": {
|
|
39
|
-
"react-syntax-highlighter": {
|
|
40
|
-
"prismjs": "1.30.0"
|
|
41
|
-
},
|
|
42
|
-
"react-code-blocks": {
|
|
43
|
-
"prismjs": "1.30.0"
|
|
44
|
-
},
|
|
45
|
-
"refractor": {
|
|
46
|
-
"prismjs": "1.30.0"
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
"repository": {
|
|
50
|
-
"type": "git",
|
|
51
|
-
"url": "https://github.com/anonympins/data-primals-engine.git"
|
|
52
|
-
},
|
|
53
|
-
"exports": {
|
|
54
|
-
".": "./src/index.js",
|
|
55
|
-
"./modules/*.js": "./src/modules/*.js",
|
|
56
|
-
"./modules/*": "./src/modules/*/index.js",
|
|
57
|
-
"./client": "./client/index.js",
|
|
58
|
-
"./*": "./src/*.js"
|
|
59
|
-
},
|
|
60
|
-
"dependencies": {
|
|
61
|
-
"@langchain/core": "^0.3.
|
|
62
|
-
"archiver": "^7.0.1",
|
|
63
|
-
"aws-sdk": "^2.1692.0",
|
|
64
|
-
"bcrypt": "^6.0.0",
|
|
65
|
-
"body-parser": "^2.2.0",
|
|
66
|
-
"chalk": "^5.4.1",
|
|
67
|
-
"check-disk-space": "^3.4.0",
|
|
68
|
-
"compression": "^1.8.1",
|
|
69
|
-
"cookie-parser": "^1.4.7",
|
|
70
|
-
"cronstrue": "^3.2.0",
|
|
71
|
-
"csv-parse": "^6.1.0",
|
|
72
|
-
"date-fns": "^4.1.0",
|
|
73
|
-
"express-csrf-double-submit-cookie": "^2.0.0",
|
|
74
|
-
"express-formidable": "^1.2.0",
|
|
75
|
-
"express-mongo-sanitize": "^2.2.0",
|
|
76
|
-
"express-rate-limit": "^8.0.1",
|
|
77
|
-
"express-session": "^1.18.2",
|
|
78
|
-
"handlebars": "^4.7.8",
|
|
79
|
-
"i18next-browser-languagedetector": "^8.2.0",
|
|
80
|
-
"isolated-vm": "^5.0.0",
|
|
81
|
-
"juice": "^11.0.
|
|
82
|
-
"mathjs": "^
|
|
83
|
-
"mongodb": "^6.18.0",
|
|
84
|
-
"node-cache": "^5.1.2",
|
|
85
|
-
"node-schedule": "^2.1.1",
|
|
86
|
-
"nodemailer": "^7.0.
|
|
87
|
-
"openai": "^
|
|
88
|
-
"passport": "^0.7.0",
|
|
89
|
-
"passport-saml-encrypted": "^0.1.13",
|
|
90
|
-
"process": "^0.11.10",
|
|
91
|
-
"prop-types": "^15.8.1",
|
|
92
|
-
"randomcolor": "^0.6.2",
|
|
93
|
-
"react-markdown": "^10.1.0",
|
|
94
|
-
"read-excel-file": "^
|
|
95
|
-
"request-ip": "^3.3.0",
|
|
96
|
-
"safe-regex": "^2.1.1",
|
|
97
|
-
"sanitize-html": "^2.17.0",
|
|
98
|
-
"sirv": "^3.0.
|
|
99
|
-
"stripe": "^
|
|
100
|
-
"swagger-ui-express": "^5.0.1",
|
|
101
|
-
"tar": "^7.
|
|
102
|
-
"tinycolor2": "^1.6.0",
|
|
103
|
-
"uniqid": "^5.4.0",
|
|
104
|
-
"vitest": "^3.2.4",
|
|
105
|
-
"yaml": "^2.8.
|
|
106
|
-
},
|
|
107
|
-
"peerDependencies": {
|
|
108
|
-
"express": "^5.1.0",
|
|
109
|
-
"passport-azure-ad": "^4.3.5",
|
|
110
|
-
"passport-google-oauth20": "^2.0.0",
|
|
111
|
-
"react": "18.3.1",
|
|
112
|
-
"react-i18next": "^
|
|
113
|
-
"react-query": "
|
|
114
|
-
"@langchain/anthropic": "^0.3.
|
|
115
|
-
"@langchain/deepseek": "^0.1.0",
|
|
116
|
-
"@langchain/google-genai": "^0.2.
|
|
117
|
-
"@langchain/openai": "^0.6.
|
|
118
|
-
},
|
|
119
|
-
"devDependencies": {
|
|
120
|
-
"@eslint/js": "^9.32.0",
|
|
121
|
-
"concurrently": "^9.2.0",
|
|
122
|
-
"cross-env": "^10.0.0",
|
|
123
|
-
"eslint": "^9.32.0",
|
|
124
|
-
"globals": "^16.3.0"
|
|
125
|
-
},
|
|
126
|
-
"subPackages": [
|
|
127
|
-
"client"
|
|
128
|
-
],
|
|
129
|
-
"keywords": [
|
|
130
|
-
"data-driven engine",
|
|
131
|
-
"headless CMS",
|
|
132
|
-
"backend",
|
|
133
|
-
"automation",
|
|
134
|
-
"AWS S3",
|
|
135
|
-
"MongoDB"
|
|
136
|
-
],
|
|
137
|
-
"author": "anonympins",
|
|
138
|
-
"license": "MIT",
|
|
139
|
-
"engines": {
|
|
140
|
-
"node": ">=20.0.0"
|
|
141
|
-
}
|
|
142
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "data-primals-engine",
|
|
3
|
+
"version": "1.6.2-rc1",
|
|
4
|
+
"description": "data-primals-engine is a package responsible from handling large amount of data using MongoDB in a practical and performant way. It can also get workflow models working (for automation), and fully supports internationalisation. It also has integrated AI assistant.",
|
|
5
|
+
"main": "src/engine.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"preinstall": "npx force-resolutions",
|
|
9
|
+
"dev": "concurrently \"npm:client\" \"npm:devserver\"",
|
|
10
|
+
"prod": "npm run build-server && npm run server",
|
|
11
|
+
"client": "cd client && npm run dev",
|
|
12
|
+
"build-server": "vite build client --config client/vite.config.js --outDir dist",
|
|
13
|
+
"build-client": "cd client && npm run build",
|
|
14
|
+
"server": "cross-env NODE_ENV=production node server.js",
|
|
15
|
+
"devserver": "npm run build-server && cross-env NODE_ENV=development PORT=7633 node server.js",
|
|
16
|
+
"lint": "eslint .",
|
|
17
|
+
"format": "prettier --write .",
|
|
18
|
+
"clean": "rm -rf node_modules package-lock.json",
|
|
19
|
+
"test": "cross-env MONGO_DB_URL=\"mongodb://localhost:27017\" PORT=7635 vitest --no-file-parallelism --no-watch",
|
|
20
|
+
"audit": "npm audit --audit-level=high",
|
|
21
|
+
"migrate:create": "node src/migrate.js create",
|
|
22
|
+
"migrate:up": "node src/migrate.js up",
|
|
23
|
+
"migrate:down": "node src/migrate.js down",
|
|
24
|
+
"migrate:revert": "node src/migrate.js revert",
|
|
25
|
+
"migrate:status": "node src/migrate.js status"
|
|
26
|
+
},
|
|
27
|
+
"optionalDependencies": {
|
|
28
|
+
"@rollup/rollup-linux-x64-gnu": "4.6.1"
|
|
29
|
+
},
|
|
30
|
+
"resolutions": {
|
|
31
|
+
"on-headers": "1.1.0",
|
|
32
|
+
"brace-expansion": "2.0.2",
|
|
33
|
+
"prismjs": "1.30.0",
|
|
34
|
+
"xml2js": ">=0.5.0",
|
|
35
|
+
"tar-fs": ">=3.1.1",
|
|
36
|
+
"vite": ">=7.0.8"
|
|
37
|
+
},
|
|
38
|
+
"overrides": {
|
|
39
|
+
"react-syntax-highlighter": {
|
|
40
|
+
"prismjs": "1.30.0"
|
|
41
|
+
},
|
|
42
|
+
"react-code-blocks": {
|
|
43
|
+
"prismjs": "1.30.0"
|
|
44
|
+
},
|
|
45
|
+
"refractor": {
|
|
46
|
+
"prismjs": "1.30.0"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "https://github.com/anonympins/data-primals-engine.git"
|
|
52
|
+
},
|
|
53
|
+
"exports": {
|
|
54
|
+
".": "./src/index.js",
|
|
55
|
+
"./modules/*.js": "./src/modules/*.js",
|
|
56
|
+
"./modules/*": "./src/modules/*/index.js",
|
|
57
|
+
"./client": "./client/index.js",
|
|
58
|
+
"./*": "./src/*.js"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"@langchain/core": "^0.3.79",
|
|
62
|
+
"archiver": "^7.0.1",
|
|
63
|
+
"aws-sdk": "^2.1692.0",
|
|
64
|
+
"bcrypt": "^6.0.0",
|
|
65
|
+
"body-parser": "^2.2.0",
|
|
66
|
+
"chalk": "^5.4.1",
|
|
67
|
+
"check-disk-space": "^3.4.0",
|
|
68
|
+
"compression": "^1.8.1",
|
|
69
|
+
"cookie-parser": "^1.4.7",
|
|
70
|
+
"cronstrue": "^3.2.0",
|
|
71
|
+
"csv-parse": "^6.1.0",
|
|
72
|
+
"date-fns": "^4.1.0",
|
|
73
|
+
"express-csrf-double-submit-cookie": "^2.0.0",
|
|
74
|
+
"express-formidable": "^1.2.0",
|
|
75
|
+
"express-mongo-sanitize": "^2.2.0",
|
|
76
|
+
"express-rate-limit": "^8.0.1",
|
|
77
|
+
"express-session": "^1.18.2",
|
|
78
|
+
"handlebars": "^4.7.8",
|
|
79
|
+
"i18next-browser-languagedetector": "^8.2.0",
|
|
80
|
+
"isolated-vm": "^5.0.0",
|
|
81
|
+
"juice": "^11.0.3",
|
|
82
|
+
"mathjs": "^15.1.0",
|
|
83
|
+
"mongodb": "^6.18.0",
|
|
84
|
+
"node-cache": "^5.1.2",
|
|
85
|
+
"node-schedule": "^2.1.1",
|
|
86
|
+
"nodemailer": "^7.0.10",
|
|
87
|
+
"openai": "^6.9.1",
|
|
88
|
+
"passport": "^0.7.0",
|
|
89
|
+
"passport-saml-encrypted": "^0.1.13",
|
|
90
|
+
"process": "^0.11.10",
|
|
91
|
+
"prop-types": "^15.8.1",
|
|
92
|
+
"randomcolor": "^0.6.2",
|
|
93
|
+
"react-markdown": "^10.1.0",
|
|
94
|
+
"read-excel-file": "^6.0.1",
|
|
95
|
+
"request-ip": "^3.3.0",
|
|
96
|
+
"safe-regex": "^2.1.1",
|
|
97
|
+
"sanitize-html": "^2.17.0",
|
|
98
|
+
"sirv": "^3.0.2",
|
|
99
|
+
"stripe": "^20.0.0",
|
|
100
|
+
"swagger-ui-express": "^5.0.1",
|
|
101
|
+
"tar": "^7.5.2",
|
|
102
|
+
"tinycolor2": "^1.6.0",
|
|
103
|
+
"uniqid": "^5.4.0",
|
|
104
|
+
"vitest": "^3.2.4",
|
|
105
|
+
"yaml": "^2.8.1"
|
|
106
|
+
},
|
|
107
|
+
"peerDependencies": {
|
|
108
|
+
"express": "^5.1.0",
|
|
109
|
+
"passport-azure-ad": "^4.3.5",
|
|
110
|
+
"passport-google-oauth20": "^2.0.0",
|
|
111
|
+
"react": "18.3.1",
|
|
112
|
+
"react-i18next": "^16.3.4",
|
|
113
|
+
"react-query": "^3.39.3",
|
|
114
|
+
"@langchain/anthropic": "^0.3.33",
|
|
115
|
+
"@langchain/deepseek": "^0.1.0",
|
|
116
|
+
"@langchain/google-genai": "^0.2.18",
|
|
117
|
+
"@langchain/openai": "^0.6.16"
|
|
118
|
+
},
|
|
119
|
+
"devDependencies": {
|
|
120
|
+
"@eslint/js": "^9.32.0",
|
|
121
|
+
"concurrently": "^9.2.0",
|
|
122
|
+
"cross-env": "^10.0.0",
|
|
123
|
+
"eslint": "^9.32.0",
|
|
124
|
+
"globals": "^16.3.0"
|
|
125
|
+
},
|
|
126
|
+
"subPackages": [
|
|
127
|
+
"client"
|
|
128
|
+
],
|
|
129
|
+
"keywords": [
|
|
130
|
+
"data-driven engine",
|
|
131
|
+
"headless CMS",
|
|
132
|
+
"backend",
|
|
133
|
+
"automation",
|
|
134
|
+
"AWS S3",
|
|
135
|
+
"MongoDB"
|
|
136
|
+
],
|
|
137
|
+
"author": "anonympins",
|
|
138
|
+
"license": "MIT",
|
|
139
|
+
"engines": {
|
|
140
|
+
"node": ">=20.0.0"
|
|
141
|
+
}
|
|
142
|
+
}
|