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.
@@ -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 'react-i18next';
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
- <span className="hidden md:inline-block ml-2">{t(view.labelKey, view.defaultLabel)}</span>
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.1",
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.66",
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.1",
82
- "mathjs": "^14.6.0",
83
- "mongodb": "^6.18.0",
84
- "node-cache": "^5.1.2",
85
- "node-schedule": "^2.1.1",
86
- "nodemailer": "^7.0.7",
87
- "openai": "^5.10.2",
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": "^5.8.8",
95
- "request-ip": "^3.3.0",
96
- "safe-regex": "^2.1.1",
97
- "sanitize-html": "^2.17.0",
98
- "sirv": "^3.0.1",
99
- "stripe": "^18.4.0",
100
- "swagger-ui-express": "^5.0.1",
101
- "tar": "^7.4.3",
102
- "tinycolor2": "^1.6.0",
103
- "uniqid": "^5.4.0",
104
- "vitest": "^3.2.4",
105
- "yaml": "^2.8.0"
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": "^15.6.1",
113
- "react-query": ">=3.0.0",
114
- "@langchain/anthropic": "^0.3.26",
115
- "@langchain/deepseek": "^0.1.0",
116
- "@langchain/google-genai": "^0.2.16",
117
- "@langchain/openai": "^0.6.3"
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
+ }