data-primals-engine 1.1.2 → 1.1.4

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.
Files changed (41) hide show
  1. package/.github/workflows/node.js.yml +2 -7
  2. package/client/package.json +70 -69
  3. package/client/src/APIInfo.jsx +2 -5
  4. package/client/src/App.jsx +3 -3
  5. package/client/src/CalculationBuilder.jsx +2 -2
  6. package/client/src/Dashboard.jsx +2 -2
  7. package/client/src/DashboardChart.jsx +1 -1
  8. package/client/src/DashboardFlexViewItem.jsx +1 -1
  9. package/client/src/DashboardView.jsx +1 -1
  10. package/client/src/DataEditor.jsx +2 -2
  11. package/client/src/DataLayout.jsx +3 -9
  12. package/client/src/DataTable.jsx +3 -3
  13. package/client/src/DisplayFlexNodeRenderer.jsx +3 -3
  14. package/client/src/Field.jsx +2 -2
  15. package/client/src/FlexBuilder.jsx +1 -1
  16. package/client/src/KPIWidget.jsx +1 -1
  17. package/client/src/KanbanCard.jsx +1 -1
  18. package/client/src/ModelCreator.jsx +3 -3
  19. package/client/src/ModelCreatorField.jsx +2 -2
  20. package/client/src/ModelImporter.jsx +1 -1
  21. package/client/src/PackGallery.jsx +1 -1
  22. package/client/src/RTETrans.jsx +1 -1
  23. package/client/src/RelationField.jsx +1 -1
  24. package/client/src/RelationValue.jsx +1 -1
  25. package/client/src/Webpage.jsx +2 -2
  26. package/client/src/constants.js +1 -0
  27. package/client/src/contexts/ModelContext.jsx +2 -3
  28. package/client/src/hooks/data.js +1 -1
  29. package/client/src/hooks/useTutorials.jsx +1 -1
  30. package/package.json +3 -4
  31. package/src/constants.js +1 -0
  32. package/src/i18n.js +2 -1
  33. package/src/modules/assistant.js +1 -1
  34. package/src/modules/bucket.js +1 -1
  35. package/src/modules/data.js +1 -1
  36. package/src/modules/file.js +1 -1
  37. package/src/modules/user.js +1 -1
  38. package/src/modules/workflow.js +53 -96
  39. package/src/setenv.js +1 -1
  40. package/test/data.integration.test.js +4 -10
  41. package/test/workflow.robustness.test.js +1 -1
@@ -14,7 +14,7 @@ jobs:
14
14
 
15
15
  runs-on: ubuntu-latest
16
16
  container:
17
- image: node:18 # Specify the Docker version you needx
17
+ image: node:20 # Specify the Docker version you needx
18
18
  env:
19
19
  NODE_OPTIONS: "--max_old_space_size=4096"
20
20
  NODE_ENV: development
@@ -23,7 +23,7 @@ jobs:
23
23
  - 27017
24
24
  strategy:
25
25
  matrix:
26
- node-version: [18.x]
26
+ node-version: [20.x]
27
27
  # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
28
28
  services:
29
29
  mongodb:
@@ -45,11 +45,6 @@ jobs:
45
45
  apt-get update
46
46
  apt-get install -y mongodb-org-tools
47
47
 
48
- - name: Set up Node.js
49
- uses: actions/setup-node@v2
50
- with:
51
- node-version: '18.18.2'
52
-
53
48
  - name: Install dependencies
54
49
  run: npm install
55
50
 
@@ -1,70 +1,71 @@
1
- {
2
- "name": "client",
3
- "private": true,
4
- "version": "0.0.0",
5
- "type": "module",
6
- "scripts": {
7
- "dev": "vite",
8
- "build": "vite build --mode development",
9
- "build:ssr-client": "vite build --ssrManifest --outDir dist/client --mode development",
10
- "build:ssr-server": "vite build --ssr src/entry-server.jsx --outDir dist/server --mode development",
11
- "lint": "eslint .",
12
- "preview": "vite preview"
13
- },
14
- "dependencies": {
15
- "@babel/runtime": "^7.24.7",
16
- "@codeium/react-code-editor": "^1.0.12",
17
- "@codemirror/lang-javascript": "^6.2.3",
18
- "@tiptap/extension-code": "^2.12.0",
19
- "@tiptap/extension-code-block": "^2.12.0",
20
- "@tiptap/extension-code-block-lowlight": "^2.12.0",
21
- "@tiptap/extension-color": "^2.11.5",
22
- "@tiptap/extension-hard-break": "^2.12.0",
23
- "@tiptap/extension-image": "^2.12.0",
24
- "@tiptap/extension-link": "^2.12.0",
25
- "@tiptap/extension-list-item": "^2.11.5",
26
- "@tiptap/extension-text-style": "^2.11.5",
27
- "@tiptap/pm": "^2.11.5",
28
- "@tiptap/react": "^2.11.5",
29
- "@tiptap/starter-kit": "^2.11.5",
30
- "@uiw/react-codemirror": "^4.23.10",
31
- "chart.js": "^4.4.9",
32
- "chartjs-adapter-date-fns": "^3.0.0",
33
- "classnames": "^2.5.1",
34
- "date-fns": "^4.1.0",
35
- "express-rate-limit": "^7.5.1",
36
- "lowlight": "^3.3.0",
37
- "react-chartjs-2": "^5.3.0",
38
- "react-code-blocks": "^0.1.6",
39
- "react-cookie": "^8.0.0",
40
- "react-dom": "^18.3.1",
41
- "react-ga": "^3.3.1",
42
- "react-icons": "^5.0.1",
43
- "react-international-phone": "^4.5.0",
44
- "react-router": "^7.2.0",
45
- "react-router-dom": "^7.1.5",
46
- "react-syntax-highlighter": "^15.6.1",
47
- "react-tooltip": "^5.28.1",
48
- "uniqid": "^5.4.0",
49
- "yet-another-react-lightbox": "^3.22.0",
50
- "data-primals-engine": "^1.0.11",
51
- "react-query": "^3.39.3"
52
- },
53
- "peerDependencies": {
54
- "react": ">=18.0.0"
55
- },
56
- "devDependencies": {
57
- "@eslint/js": "^9.17.0",
58
- "@types/react": "^18.3.18",
59
- "@types/react-dom": "^18.3.5",
60
- "@vitejs/plugin-react": "^4.3.4",
61
- "eslint": "^9.17.0",
62
- "eslint-plugin-react": "^7.37.2",
63
- "eslint-plugin-react-hooks": "^5.0.0",
64
- "eslint-plugin-react-refresh": "^0.4.16",
65
- "globals": "^15.14.0",
66
- "process": "^0.11.10",
67
- "sass-embedded": "^1.83.4",
68
- "vite": "^6.1.1"
69
- }
1
+ {
2
+ "name": "client",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build --mode development",
9
+ "build:ssr-client": "vite build --ssrManifest --outDir dist/client --mode development",
10
+ "build:ssr-server": "vite build --ssr src/entry-server.jsx --outDir dist/server --mode development",
11
+ "lint": "eslint .",
12
+ "preview": "vite preview"
13
+ },
14
+ "peerDependencies": {
15
+ "@tiptap/react": "^2.11.5",
16
+ "react-router-dom": "^7.1.5",
17
+ "react-query": "^3.39.3",
18
+ "react-icons": "^5.0.1",
19
+ "react-tooltip": "^5.28.1",
20
+ "react-helmet": "^6.1.0",
21
+ "react-cookie": "^8.0.0",
22
+ "react-syntax-highlighter": "^15.6.1",
23
+ "react-international-phone": "^4.5.0",
24
+ "react-chartjs-2": "^5.3.0",
25
+ "react-code-blocks": "^0.1.6",
26
+ "react-ga": "^3.3.1"
27
+ },
28
+ "dependencies": {
29
+ "@babel/runtime": "^7.24.7",
30
+ "@codeium/react-code-editor": "^1.0.12",
31
+ "@codemirror/lang-javascript": "^6.2.3",
32
+ "@tiptap/extension-code": "^2.12.0",
33
+ "@tiptap/extension-code-block": "^2.12.0",
34
+ "@tiptap/extension-code-block-lowlight": "^2.12.0",
35
+ "@tiptap/extension-color": "^2.11.5",
36
+ "@tiptap/extension-hard-break": "^2.12.0",
37
+ "@tiptap/extension-image": "^2.12.0",
38
+ "@tiptap/extension-link": "^2.12.0",
39
+ "@tiptap/extension-list-item": "^2.11.5",
40
+ "@tiptap/extension-text-style": "^2.11.5",
41
+ "@tiptap/pm": "^2.11.5",
42
+ "@tiptap/starter-kit": "^2.11.5",
43
+ "@uiw/react-codemirror": "^4.23.10",
44
+ "chart.js": "^4.4.9",
45
+ "chartjs-adapter-date-fns": "^3.0.0",
46
+ "react-dom": "^18.3.1",
47
+ "react-router": "^7.2.0",
48
+ "yet-another-react-lightbox": "^3.22.0",
49
+ "react": ">=18.0.0",
50
+ "classnames": "^2.5.1",
51
+ "date-fns": "^4.1.0",
52
+ "express-rate-limit": "^7.5.1",
53
+ "lowlight": "^3.3.0",
54
+ "uniqid": "^5.4.0",
55
+ "data-primals-engine": "^1.0.11"
56
+ },
57
+ "devDependencies": {
58
+ "@eslint/js": "^9.17.0",
59
+ "@types/react": "^18.3.18",
60
+ "@types/react-dom": "^18.3.5",
61
+ "@vitejs/plugin-react": "^4.3.4",
62
+ "eslint": "^9.17.0",
63
+ "eslint-plugin-react": "^7.37.2",
64
+ "eslint-plugin-react-hooks": "^5.0.0",
65
+ "eslint-plugin-react-refresh": "^0.4.16",
66
+ "globals": "^15.14.0",
67
+ "process": "^0.11.10",
68
+ "sass-embedded": "^1.83.4",
69
+ "vite": "^6.1.1"
70
+ }
70
71
  }
@@ -3,16 +3,13 @@ import {useModelContext} from './contexts/ModelContext';
3
3
  import {useAuthContext} from "./contexts/AuthContext.jsx";
4
4
  import Button from "./Button.jsx";
5
5
  import {Trans, useTranslation} from "react-i18next";
6
- import {getDefaultForType} from "data-primals-engine/data";
6
+ import {getDefaultForType} from "../../src/data.js";
7
7
  import { CodeBlock, tomorrowNightBright } from 'react-code-blocks';
8
- import {getObjectHash, shuffle} from "data-primals-engine/core";
9
- import {mainFieldsTypes} from "data-primals-engine/constants";
10
- import {end} from "express-mongo-sanitize";
8
+ import {mainFieldsTypes} from "../../src/constants.js";
11
9
  import {FaFile, FaPlay, FaRunning} from "react-icons/fa";
12
10
  import {Tooltip} from "react-tooltip";
13
11
  import {CodeField} from "./Field.jsx";
14
12
  import {useMutation} from "react-query";
15
- import {FaF} from "react-icons/fa6";
16
13
  import {getHost} from "./constants.js";
17
14
 
18
15
  const Test= ({endpoint, lang, index, headers= {}}) => {
@@ -52,9 +52,9 @@ import {
52
52
  import {Helmet} from "react-helmet";
53
53
  import {useCookies, CookiesProvider} from "react-cookie";
54
54
 
55
- import { translations as allTranslations} from "data-primals-engine/i18n";
56
- import {getRandom} from "data-primals-engine/core";
57
- import {getUserHash} from "data-primals-engine/data";
55
+ import { translations as allTranslations} from "../../src/i18n.js";
56
+ import {getRandom} from "../../src/core.js";
57
+ import {getUserHash} from "../../src/data.js";
58
58
  import {seoTitle} from "./constants.js";
59
59
  import {host} from "../../src/constants.js";
60
60
  import i18next from "i18next";
@@ -1,9 +1,9 @@
1
1
  import React, {useState, useEffect, useCallback, useRef} from 'react';
2
2
  import { FaPlus, FaTrash, FaEquals } from 'react-icons/fa';
3
- import {object_equals} from "data-primals-engine/core"; // Assuming this is a deep equality check
3
+ import {object_equals} from "../../src/core.js"; // Assuming this is a deep equality check
4
4
  import CalculationStepRow from "./CalculationStepRow.jsx";
5
5
  import {getFieldDefinitionFromPath, isAtomicDateOperator} from "./core/data.js";
6
- import {MONGO_OPERATORS, OPERAND_TYPES} from "../src/constants.js";
6
+ import {MONGO_OPERATORS, OPERAND_TYPES} from "./constants.js";
7
7
 
8
8
  // --- Helper Functions & Constants ---
9
9
  const generateId = () => `step_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
@@ -10,8 +10,8 @@ import { SelectField } from "./Field.jsx";
10
10
  import {DashboardView} from "./DashboardView.jsx";
11
11
  import {useModelContext} from "./contexts/ModelContext.jsx";
12
12
  import {useParams, useSearchParams} from "react-router-dom";
13
- import {getObjectHash} from "data-primals-engine/core";
14
- import {getUserHash, getUserId} from "data-primals-engine/data";
13
+ import {getObjectHash} from "../../src/core.js";
14
+ import {getUserHash, getUserId} from "../../src/data.js";
15
15
 
16
16
  // --- DashboardsPage (Reste inchangé) ---
17
17
  export function DashboardsPage() {
@@ -14,7 +14,7 @@ import i18n from 'i18next';
14
14
 
15
15
  import 'chartjs-adapter-date-fns';
16
16
  import {useModelContext} from "./contexts/ModelContext.jsx";
17
- import {isDate} from "data-primals-engine/core";
17
+ import {isDate} from "../../src/core.js";
18
18
  import useWindowSize from "./hooks/useWindowSize.js";
19
19
  import useDebounce from "./hooks/useDebounce.js";
20
20
 
@@ -4,7 +4,7 @@ import {useTranslation} from "react-i18next";
4
4
  import {useAuthContext} from "./contexts/AuthContext.jsx";
5
5
  import React, {useEffect, useMemo, useRef} from "react";
6
6
  import {useQuery} from "react-query";
7
- import {conditionToApiSearchFilter} from "data-primals-engine/data";
7
+ import {conditionToApiSearchFilter} from "../../src/data.js";
8
8
  import {FaSpinner} from "react-icons/fa";
9
9
  import {DisplayFlexNodeRenderer} from "./DisplayFlexNodeRenderer.jsx";
10
10
 
@@ -15,7 +15,7 @@ import { useAuthContext } from "./contexts/AuthContext.jsx";
15
15
  import { DialogProvider } from "./Dialog.jsx";
16
16
  import {useModelContext} from "./contexts/ModelContext.jsx";
17
17
  import FlexDataRenderer from "./FlexDataRenderer.jsx";
18
- import {conditionToApiSearchFilter} from "data-primals-engine/data";
18
+ import {conditionToApiSearchFilter} from "../../src/data.js";
19
19
  // --- MODIFICATION : Import de la fonction cssProps ---
20
20
  import { cssProps } from 'data-primals-engine/core';
21
21
  import {DashboardFlexViewItem} from "./DashboardFlexViewItem.jsx";
@@ -1,5 +1,5 @@
1
1
  import React, {forwardRef, useEffect, useState} from "react"; // Ajout de useEffect
2
- import {conditionToApiSearchFilter, getDefaultForType} from "data-primals-engine/data";
2
+ import {conditionToApiSearchFilter, getDefaultForType} from "../../src/data.js";
3
3
  import { Trans, useTranslation } from "react-i18next";
4
4
  import {FaCode, FaLanguage, FaMinus, FaPlus, FaSitemap} from "react-icons/fa";
5
5
  import Button from "./Button.jsx";
@@ -15,7 +15,7 @@ import {
15
15
  SelectField,
16
16
  TextField
17
17
  } from "./Field.jsx";
18
- import i18n from "data-primals-engine/i18n";
18
+ import i18n from "../../src/i18n.js";
19
19
  import ConditionBuilder from "./ConditionBuilder.jsx";
20
20
  import {useModelContext} from "./contexts/ModelContext.jsx";
21
21
  import {useAuthContext} from "./contexts/AuthContext.jsx";
@@ -14,7 +14,7 @@ import {
14
14
  maxBytesPerSecondThrottleData,
15
15
  maxFileSize,
16
16
  maxRequestData, metaModels
17
- } from "data-primals-engine/constants";
17
+ } from "../../src/constants.js";
18
18
  import {
19
19
  FaArrowDown,
20
20
  FaArrowUp, FaBell,
@@ -27,20 +27,14 @@ import {
27
27
  FaPlus,
28
28
  FaTrash
29
29
  } from "react-icons/fa";
30
- import {getDefaultForType, getUserId} from "data-primals-engine/data";
30
+ import {getDefaultForType, getUserId} from "../../src/data.js";
31
31
  import {Trans, useTranslation} from "react-i18next";
32
32
 
33
- import {debounce, escapeRegExp, event_trigger, getObjectHash, isGUID} from "data-primals-engine/core";
33
+ import {debounce, escapeRegExp, event_trigger, getObjectHash, isGUID} from "../../src/core.js";
34
34
  import Button from "./Button.jsx";
35
35
  import {useAuthContext} from "./contexts/AuthContext.jsx";
36
- import {RTE} from "./RTE.jsx";
37
36
  import APIInfo from "./APIInfo.jsx";
38
- import {xt256} from "react-code-blocks";
39
- import {isList} from "@tiptap/react";
40
37
  import {useNotificationContext} from "./NotificationProvider.jsx";
41
- import modelCreator from "./ModelCreator.jsx";
42
- import RelationField from "./RelationField.jsx";
43
- import RelationValue from "./RelationValue.jsx";
44
38
  import {ModelImporter} from "./ModelImporter.jsx";
45
39
  import {DataTable} from "./DataTable.jsx";
46
40
  import {ModelList} from "./ModelList.jsx";
@@ -4,7 +4,7 @@ import {Trans, useTranslation} from "react-i18next";
4
4
  import {useMutation, useQuery, useQueryClient} from "react-query";
5
5
  import {useAuthContext} from "./contexts/AuthContext.jsx";
6
6
  import React, {useEffect, useMemo, useRef, useState} from "react";
7
- import {getUserId} from "data-primals-engine/data";
7
+ import {getUserId} from "../../src/data.js";
8
8
  import cronstrue from 'cronstrue/i18n';
9
9
  import {
10
10
  FaBook,
@@ -24,7 +24,7 @@ import {
24
24
  maxBytesPerSecondThrottleData,
25
25
  maxFileSize,
26
26
  maxRequestData
27
- } from "data-primals-engine/constants";
27
+ } from "../../src/constants.js";
28
28
  import Button from "./Button.jsx";
29
29
  import {Dialog, DialogProvider} from "./Dialog.jsx";
30
30
  import {
@@ -40,7 +40,7 @@ import {
40
40
  import RelationValue from "./RelationValue.jsx";
41
41
  import {FaPencil, FaTriangleExclamation} from "react-icons/fa6";
42
42
  import RestoreConfirmationModal from "./RestoreConfirmationModal.jsx";
43
- import {event_trigger, isLightColor} from "data-primals-engine/core";
43
+ import {event_trigger, isLightColor} from "../../src/core.js";
44
44
  import {isConditionMet} from "./DataEditor.jsx";
45
45
  import {Tooltip} from "react-tooltip";
46
46
  import ExportDialog from "./ExportDialog.jsx";
@@ -1,13 +1,13 @@
1
1
  // C:/Dev/hackersonline-engine/client/src/DisplayFlexNodeRenderer.jsx
2
2
  import {useTranslation} from "react-i18next";
3
- import {cssProps} from "data-primals-engine/core";
3
+ import {cssProps} from "../../src/core.js";
4
4
  import FlexDataRenderer from "./FlexDataRenderer.jsx";
5
5
  import React, {useState} from "react";
6
- import {getFieldPathValue} from "data-primals-engine/data";
6
+ import {getFieldPathValue} from "../../src/data.js";
7
7
  import {getFieldDefinitionFromPath} from "./core/data.js";
8
8
  import {Dialog, DialogProvider} from "./Dialog.jsx";
9
9
  import {FaPlay} from "react-icons/fa";
10
- import {substituteVariables} from "data-primals-engine/modules/workflow";
10
+
11
11
 
12
12
  /**
13
13
  * Récupère une valeur imbriquée dans un objet (ex: 'user.address.city').
@@ -11,8 +11,8 @@ import { recursiveMap, useRefs } from "./Utils.jsx";
11
11
  import {useTranslation} from "react-i18next";
12
12
  import { CodeiumEditor } from "@codeium/react-code-editor";
13
13
 
14
- import {debounce, escapeRegExp, isGUID, isLightColor} from "data-primals-engine/core";
15
- import {mainFieldsTypes, maxFileSize} from "data-primals-engine/constants";
14
+ import {debounce, escapeRegExp, isGUID, isLightColor} from "../../src/core.js";
15
+ import {mainFieldsTypes, maxFileSize} from "../../src/constants.js";
16
16
  import {useModelContext} from "./contexts/ModelContext.jsx";
17
17
  import {useQueryClient} from "react-query";
18
18
  import {
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
3
3
  import './FlexBuilder.scss';
4
4
  import { useAuthContext } from "./contexts/AuthContext.jsx";
5
5
  import { useTranslation } from "react-i18next";
6
- import { applyFilter } from "data-primals-engine/data";
6
+ import { applyFilter } from "../../src/data.js";
7
7
  import { FieldSelectorModal } from "./FlexNode.jsx";
8
8
  import { deepInsertNode, deepRemoveNode } from "./FlexBuilderUtils.js";
9
9
  import useDragAndDrop from './hooks/useDragAndDrop.js';
@@ -3,7 +3,7 @@ import { useQuery } from 'react-query';
3
3
  import * as FaIcons from 'react-icons/fa'; // Importer toutes les icônes Fa
4
4
  import * as Fa6Icons from 'react-icons/fa6'; // Importer Fa6
5
5
  import { FaInfo, FaTimes } from 'react-icons/fa';
6
- import { isLightColor } from "data-primals-engine/core"; // Pour le bouton supprimer
6
+ import { isLightColor } from "../../src/core.js"; // Pour le bouton supprimer
7
7
  import { Tooltip } from 'react-tooltip';
8
8
 
9
9
  // Fonction pour récupérer la valeur calculée d'un KPI (MODIFIÉE)
@@ -3,7 +3,7 @@
3
3
  import React from 'react';
4
4
  import {useTranslation} from "react-i18next";
5
5
  import {useModelContext} from "./contexts/ModelContext.jsx";
6
- import {getDataAsString} from "data-primals-engine/data";
6
+ import {getDataAsString} from "../../src/data.js";
7
7
 
8
8
 
9
9
  const KanbanCard = ({ card, model, subItemsField }) => {
@@ -14,15 +14,15 @@ import {
14
14
  mainFieldsTypes, maxFileSize,
15
15
  maxModelNameLength,
16
16
  maxRequestData
17
- } from "data-primals-engine/constants";
17
+ } from "../../src/constants.js";
18
18
  import {useAuthContext} from "./contexts/AuthContext.jsx";
19
- import {getUserHash, getUserId, isLocalUser} from "data-primals-engine/data";
19
+ import {getUserHash, getUserId, isLocalUser} from "../../src/data.js";
20
20
  import {useNotificationContext} from "./NotificationProvider.jsx";
21
21
  import ConditionBuilder from './ConditionBuilder.jsx';
22
22
  import './ConditionBuilder.scss';
23
23
  import {Tooltip} from "react-tooltip";
24
24
  import {FaCircleInfo} from "react-icons/fa6";
25
- import i18n from "data-primals-engine/i18n";
25
+ import i18n from "../../src/i18n.js";
26
26
  import Draggable from "./Draggable.jsx";
27
27
  import FlexBuilder from "./FlexBuilder.jsx";
28
28
  import {NavLink} from "react-router";
@@ -1,7 +1,7 @@
1
1
  import React, {useState} from "react";
2
2
  import {useModelContext} from "./contexts/ModelContext.jsx";
3
3
  import {useAuthContext} from "./contexts/AuthContext.jsx";
4
- import {isLocalUser} from "data-primals-engine/data";
4
+ import {isLocalUser} from "../../src/data.js";
5
5
  import {Trans, useTranslation} from "react-i18next";
6
6
  import {FaCircleInfo} from "react-icons/fa6";
7
7
  import {CheckboxField, CodeField, ColorField, NumberField, SelectField, TextField} from "./Field.jsx";
@@ -10,7 +10,7 @@ import {FaArrowDown, FaArrowUp, FaEdit, FaMinus, FaPlus, FaTrash} from "react-ic
10
10
  import CalculationBuilder from "./CalculationBuilder.jsx";
11
11
  import ConditionBuilder from "./ConditionBuilder.jsx";
12
12
  import Draggable from "./Draggable.jsx";
13
- import {mainFieldsTypes} from "data-primals-engine/constants";
13
+ import {mainFieldsTypes} from "../../src/constants.js";
14
14
 
15
15
  function RelationModelSelector({relation, onChange, ...rest}) {
16
16
  const {models} = useModelContext()
@@ -7,7 +7,7 @@ import { CheckboxField } from './Field.jsx';
7
7
  import Button from './Button.jsx';
8
8
  import { useQueryClient } from 'react-query';
9
9
  import { useNotificationContext } from './NotificationProvider.jsx';
10
- import {metaModels} from "data-primals-engine/constants";
10
+ import {metaModels} from "../../src/constants.js";
11
11
 
12
12
 
13
13
  const ModelImporter = ({ onImport }) => {
@@ -7,7 +7,7 @@ import { useNotificationContext } from './NotificationProvider.jsx';
7
7
  import { useModelContext } from './contexts/ModelContext.jsx';
8
8
 
9
9
  import './PackGallery.scss';
10
- import {elementsPerPage} from "data-primals-engine/constants";
10
+ import {elementsPerPage} from "../../src/constants.js";
11
11
 
12
12
  // --- API Fetching Functions ---
13
13
  const fetchPacks = async (sortBy, lang) => {
@@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
4
4
  import { RTE } from './RTE.jsx';
5
5
  import {useModelContext} from "./contexts/ModelContext.jsx";
6
6
  import {useQuery} from "react-query";
7
- import {getUserId} from "data-primals-engine/data";
7
+ import {getUserId} from "../../src/data.js";
8
8
  import {useAuthContext} from "./contexts/AuthContext.jsx";
9
9
 
10
10
  const RTETrans = ({ value, onChange, field }) => {
@@ -6,7 +6,7 @@ import { useAuthContext } from './contexts/AuthContext.jsx';
6
6
  import {conditionToApiSearchFilter, getDataAsString, getUserId} from 'data-primals-engine/data';
7
7
  import { FaEdit, FaTrash } from 'react-icons/fa';
8
8
  import Button from './Button.jsx';
9
- import {mainFieldsTypes} from "data-primals-engine/constants";
9
+ import {mainFieldsTypes} from "../../src/constants.js";
10
10
  import Draggable from "./Draggable.jsx";
11
11
  import {useTranslation} from "react-i18next";
12
12
 
@@ -8,7 +8,7 @@ import {FaMagnifyingGlass} from "react-icons/fa6";
8
8
  import {useAuthContext} from "./contexts/AuthContext.jsx";
9
9
  import {CodeField, ColorField} from "./Field.jsx";
10
10
  import { randomColor } from "randomcolor";
11
- import {getObjectHash, getRand, isLightColor, setSeed} from "data-primals-engine/core";
11
+ import {getObjectHash, getRand, isLightColor, setSeed} from "../../src/core.js";
12
12
 
13
13
  const RelationValue = ({ field, data, align }) => {
14
14
  const { models, relations, setRelations, dataByModel, relationIds, setRelationIds, setDatasToLoad, datasToLoad } = useModelContext();
@@ -5,10 +5,10 @@ import {useQuery} from "react-query";
5
5
  import {useLocation} from "react-router-dom";
6
6
  import {Helmet} from "react-helmet";
7
7
  import {useTranslation} from "react-i18next";
8
- import {getObjectHash} from "data-primals-engine/core";
8
+ import {getObjectHash} from "../../src/core.js";
9
9
  import {useData} from "./hooks/data.js";
10
10
  import {useAuthContext} from "./contexts/AuthContext.jsx";
11
- import {getUserHash, getUserId} from "data-primals-engine/data";
11
+ import {getUserHash, getUserId} from "../../src/data.js";
12
12
 
13
13
 
14
14
  function Webpage({children}) {
@@ -1,3 +1,4 @@
1
+ import {host} from "../../src/constants.js";
1
2
 
2
3
  export const seoTitle = 'Self Data Hosting';
3
4
 
@@ -1,10 +1,9 @@
1
1
  // ModelContext.jsx
2
2
  import React, {createContext, useCallback, useContext, useEffect, useMemo, useState} from 'react';
3
3
  import { useQueries, useQuery } from 'react-query';
4
- import {elementsPerPage} from "data-primals-engine/constants";
5
- import {getObjectHash} from "data-primals-engine/core";
4
+ import {getObjectHash} from "../../../src/core.js";
6
5
  import {useAuthContext} from "./AuthContext.jsx";
7
- import {getUserHash, getUserId} from "data-primals-engine/data";
6
+ import {getUserHash, getUserId} from "../../../src/data.js";
8
7
  import {useTranslation} from "react-i18next";
9
8
  import useLocalStorage from "../hooks/useLocalStorage.js";
10
9
 
@@ -1,7 +1,7 @@
1
1
  import {useQuery} from "react-query";
2
2
  import {getObjectHash} from "data-primals-engine/core";
3
3
  import {useAuthContext} from "../contexts/AuthContext.jsx";
4
- import {getUserHash, getUserId} from "data-primals-engine/data";
4
+ import {getUserHash, getUserId} from "../../../src/data";
5
5
  import {useTranslation} from "react-i18next";
6
6
  import {useEffect, useState} from "react";
7
7
  import {useUI} from "../contexts/UIContext.jsx";
@@ -6,7 +6,7 @@ import { tutorialsConfig } from '../tutorials.js';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { useCallback, useEffect, useMemo, useRef } from 'react';
8
8
  import useLocalStorage from "./useLocalStorage.js";
9
- import { event_off, event_on } from "data-primals-engine/core";
9
+ import { event_off, event_on } from "../../../src/core.js";
10
10
 
11
11
  /**
12
12
  * Hook pour gérer la logique des tutoriels multi-étapes.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "data-primals-engine",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "data-primals-engine is the package responsible from handling large amount of data in a practical and performant way. It can handle large amount of data in a practical and performant way. It can also get workflow models working (for automation), and fully supports internationalisation.",
5
5
  "main": "src/engine.js",
6
6
  "type": "module",
@@ -80,7 +80,6 @@
80
80
  "process": "^0.11.10",
81
81
  "prop-types": "^15.8.1",
82
82
  "randomcolor": "^0.6.2",
83
- "react-helmet": "^6.1.0",
84
83
  "react-i18next": "^15.6.1",
85
84
  "react-markdown": "^10.1.0",
86
85
  "request-ip": "^3.3.0",
@@ -90,7 +89,7 @@
90
89
  "tar": "^7.4.3",
91
90
  "uniqid": "^5.4.0",
92
91
  "vitest": "^3.2.4",
93
- "vm2": "^3.9.19",
92
+ "isolated-vm": "^4.7.2",
94
93
  "yaml": "^2.8.0"
95
94
  },
96
95
  "devDependencies": {
@@ -115,6 +114,6 @@
115
114
  "author": "anonympins",
116
115
  "license": "MIT",
117
116
  "engines": {
118
- "node": ">=18.0.0"
117
+ "node": ">=20.0.0"
119
118
  }
120
119
  }
package/src/constants.js CHANGED
@@ -212,6 +212,7 @@ export const maxTotalPrivateFilesSize = 250 * megabytes;
212
212
  */
213
213
  export const timeoutVM = 5000;
214
214
 
215
+ export const defaultMaxRequestData = 50000;
215
216
  /**
216
217
  * Options for the HTML sanitizer
217
218
  * @type {{allowedSchemesByTag: {}, selfClosing: string[], allowedSchemes: string[], enforceHtmlBoundary: boolean, disallowedTagsMode: string, allowProtocolRelative: boolean, allowedAttributes: {a: string[], img: string[], code: string[]}, allowedTags: string[], allowedSchemesAppliedToAttributes: string[]}}
package/src/i18n.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import i18n from "i18next";
2
- import {initReactI18next} from "react-i18next";
2
+ import {Trans, useTranslation, initReactI18next} from "react-i18next";
3
3
  import LanguageDetector from "i18next-browser-languagedetector";
4
4
 
5
5
  export const translations = {
@@ -12368,4 +12368,5 @@ i18n
12368
12368
  }
12369
12369
  });
12370
12370
 
12371
+ export {Trans, useTranslation};
12371
12372
  export default i18n;
@@ -7,7 +7,7 @@ import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
7
7
  import { HumanMessage, SystemMessage } from "@langchain/core/messages";
8
8
  import {searchData, patchData, deleteData, insertData} from "./data.js";
9
9
  import { getDataAsString } from "../data.js";
10
- import i18n from "data-primals-engine/i18n";
10
+ import i18n from "../../src/i18n.js";
11
11
  import {generateLimiter} from "./user.js";
12
12
  import rateLimit from "express-rate-limit";
13
13
 
@@ -9,7 +9,7 @@ import {Logger} from "../gameObject.js";
9
9
  import {middlewareAuthenticator, userInitiator} from "./user.js";
10
10
  import {awsDefaultConfig, maxBytesPerSecondThrottleData} from "../constants.js";
11
11
  import crypto from "node:crypto";
12
- import i18n from "data-primals-engine/i18n";
12
+ import i18n from "../../src/i18n.js";
13
13
  import {sendEmail} from "../email.js";
14
14
  import {throttleMiddleware} from "../middlewares/throttle.js";
15
15
 
@@ -64,7 +64,7 @@ import {
64
64
  import fs from "node:fs";
65
65
  import schedule from "node-schedule";
66
66
  import {middleware} from "../middlewares/middleware-mongodb.js";
67
- import i18n from "data-primals-engine/i18n";
67
+ import i18n from "../i18n.js";
68
68
  import {
69
69
  executeSafeJavascript,
70
70
  runScheduledJobWithDbLock,
@@ -2,7 +2,7 @@
2
2
  // Nouvelle fonction pour ajouter un fichier privé
3
3
  import {maxPrivateFileSize, megabytes} from "../constants.js";
4
4
  import {isLocalUser} from "../data.js";
5
- import i18n from "data-primals-engine/i18n";
5
+ import i18n from "../../src/i18n.js";
6
6
  import {getCollection} from "./mongodb.js";
7
7
  import {getFileExtension, isGUID, uuidv4} from "../core.js";
8
8
  import path from "node:path";
@@ -1,4 +1,4 @@
1
- import i18n from "data-primals-engine/i18n";
1
+ import i18n from "../i18n.js";
2
2
  import {MongoDatabase} from "../engine.js";
3
3
  import {getCollection, getCollectionForUser, getUserCollectionName} from "./mongodb.js";
4
4
  import {isLocalUser} from "../data.js";
@@ -4,14 +4,15 @@ import schedule from "node-schedule";
4
4
  import {ObjectId} from "mongodb";
5
5
  import crypto from "node:crypto";
6
6
 
7
- import {NodeVM, VM, VMScript} from 'vm2';
7
+ import ivm from 'isolated-vm';
8
+
8
9
  import {Logger} from "../gameObject.js";
9
10
  import {deleteData, insertData, patchData, searchData} from "./data.js";
10
11
  import {maxExecutionsByStep, maxWorkflowSteps, timeoutVM} from "../constants.js";
11
12
  import {ChatOpenAI} from "@langchain/openai";
12
13
  import {ChatGoogleGenerativeAI} from "@langchain/google-genai";
13
14
  import {ChatPromptTemplate} from "@langchain/core/prompts";
14
- import i18n from "data-primals-engine/i18n";
15
+ import i18n from "../../src/i18n.js";
15
16
  import {sendEmail} from "../email.js";
16
17
 
17
18
  import * as workflowModule from './workflow.js';
@@ -180,144 +181,100 @@ export async function scheduleWorkflowTriggers() {
180
181
  }
181
182
 
182
183
 
183
- /* Remplacement de la fonction executeSafeJavascript
184
- async function executeWithIsolatedVm(actionDef, context) {
184
+ export async function executeSafeJavascript(actionDef, context, user) {
185
185
  const code = actionDef.script;
186
- const isolate = new ivm.Isolate({ memoryLimit: 128 }); // Limite de 128MB de mémoire
186
+ const collectedLogs = [];
187
+ const isolate = new ivm.Isolate({ memoryLimit: 128 }); // 128MB memory limit
187
188
 
188
189
  try {
189
190
  const vmContext = await isolate.createContext();
190
191
  const jail = vmContext.global;
191
192
 
192
- // On expose une fonction 'log' sécurisée à l'intérieur de la VM.
193
- // C'est une référence, pas la fonction elle-même.
194
- await jail.set('log', new ivm.Reference(function(...args) {
195
- // On peut préfixer les logs pour savoir qu'ils viennent de la VM
196
- logger.info('[VM Script Log]', ...args);
197
- }));
198
-
199
- // On injecte les données du contexte. Elles sont COPIÉES, pas référencées.
200
- // C'est une caractéristique de sécurité clé.
201
- await jail.set('contextData', new ivm.ExternalCopy(context).copyInto());
202
- // On peut aussi exposer des fonctions spécifiques de votre application
203
- // await jail.set('myApiFunction', new ivm.Reference(async (params) => { ... }));
204
-
205
- // On compile le script
206
- const script = await isolate.compileScript(code);
207
-
208
- // On exécute le script avec un timeout
209
- const result = await script.run(vmContext, { timeout: 1000 });
210
-
211
- // Le résultat est une référence, on le copie pour l'utiliser dans notre contexte principal.
212
- return result;
213
-
214
- } catch (error) {
215
- logger.error("Error executing script with isolated-vm:", error.stack);
216
- // On propage une erreur propre
217
- throw new Error(`Script execution failed: ${error.message}`);
218
- } finally {
219
- // TRÈS IMPORTANT : Toujours libérer l'isolate pour éviter les fuites de mémoire.
220
- if (isolate && !isolate.isDisposed) {
221
- isolate.dispose();
222
- }
223
- }
224
- }
225
- REQUIRES NODE >=20
226
- */
227
-
228
- export async function executeSafeJavascript(actionDef, context, user) {
229
- const code = actionDef.script;
230
- const collectedLogs = []; // Tableau pour capturer les logs de cette exécution
193
+ // Helper to create a secure reference for our API functions
194
+ const createJailFunction = (fn) => new ivm.Reference(fn);
231
195
 
232
- // 1. Construire l'API qui sera exposée au script
233
- const scriptApi = {
234
- db: {
196
+ // 1. Build the sandboxed API
197
+ await jail.set('db', createJailFunction({
235
198
  create: (modelName, dataObject) => insertData(modelName, dataObject, {}, user),
236
199
  find: async (modelName, filter) => {
237
200
  const result = await searchData({ user, query: { model: modelName, filter } });
238
- return result.data;
201
+ return new ivm.ExternalCopy(result.data).copyInto();
239
202
  },
240
203
  findOne: async (modelName, filter) => {
241
204
  const result = await searchData({ user, query: { model: modelName, filter, limit: 1 } });
242
- return result.data?.[0] || null;
205
+ return new ivm.ExternalCopy(result.data?.[0] || null).copyInto();
243
206
  },
244
207
  update: (modelName, filter, updateObject) => patchData(modelName, filter, updateObject, {}, user),
245
208
  delete: (modelName, filter) => deleteData(modelName, null, filter, user)
246
- },
247
- logger: {
248
- // Chaque fonction de log utilise maintenant logger.trace() pour générer le message final
249
- info: (...args) => {
250
- // On génère le message final formaté une seule fois avec trace()
251
- const finalMessage = logger.trace('info', '[VM Script]', ...args);
252
- // On l'affiche en couleur dans la console du serveur
253
- // On stocke ce même message final dans les logs collectés
254
- collectedLogs.push({
255
- level: 'info',
256
- message: finalMessage, // Le message complet est stocké
257
- timestamp: new Date().toISOString()
258
- });
259
- },
260
- warn: (...args) => {
261
- const finalMessage = logger.trace('warn', '[VM Script]', ...args);
262
- collectedLogs.push({
263
- level: 'warn',
264
- message: finalMessage,
265
- timestamp: new Date().toISOString()
266
- });
267
- },
268
- error: (...args) => {
269
- const finalMessage = logger.trace('error', '[VM Script]', ...args);
209
+ }));
210
+
211
+ const createLoggerFunction = (level) => {
212
+ return (...args) => {
213
+ const finalMessage = logger.trace(level, '[VM Script]', ...args);
270
214
  collectedLogs.push({
271
- level: 'error',
215
+ level: level,
272
216
  message: finalMessage,
273
217
  timestamp: new Date().toISOString()
274
218
  });
275
- }
276
- },
277
- env: {
219
+ };
220
+ };
221
+
222
+ await jail.set('logger', createJailFunction({
223
+ info: createLoggerFunction('info'),
224
+ warn: createLoggerFunction('warn'),
225
+ error: createLoggerFunction('error')
226
+ }));
227
+
228
+ await jail.set('env', createJailFunction({
278
229
  get: async (variableName) => {
279
230
  if (!variableName) return null;
280
231
  const result = await searchData({ user, query: { model: 'env', filter: { name: variableName }, limit: 1 } });
281
- return result.data?.[0]?.value || null;
232
+ return new ivm.ExternalCopy(result.data?.[0]?.value || null).copyInto();
282
233
  },
283
234
  getAll: async () => {
284
235
  const result = await searchData({ user, query: { model: 'env' } });
285
- // Retourne un objet { NOM: valeur, ... } plus pratique
286
- return result.data.reduce((acc, v) => {
236
+ const envObject = result.data.reduce((acc, v) => {
287
237
  acc[v.name] = v.value;
288
238
  return acc;
289
239
  }, {});
240
+ return new ivm.ExternalCopy(envObject).copyInto();
290
241
  }
291
- },
292
- ...context
293
- };
242
+ }));
294
243
 
295
- const vm = new NodeVM({
296
- timeout: timeoutVM,
297
- sandbox: scriptApi,
298
- console: 'off',
299
- require: false,
300
- wasm: false
301
- });
244
+ // Inject the context data securely
245
+ await jail.set('context', new ivm.ExternalCopy(context).copyInto());
302
246
 
303
- try {
304
- const script = new VMScript(`const script = () => {${code}}; module.exports = script();`);
305
- const result= vm.run(script);
247
+ // 2. Prepare and run the script
248
+ // The script is wrapped in an async IIFE to handle promises correctly
249
+ const fullScript = `
250
+ (async () => {
251
+ ${code}
252
+ })();
253
+ `;
254
+
255
+ const script = await isolate.compileScript(fullScript);
256
+ const result = await script.run(vmContext, { timeout: timeoutVM, promise: true });
257
+
258
+ // The result is returned as an ExternalCopy, we need to copy it out
306
259
  return { success: true, data: result, logs: collectedLogs };
260
+
307
261
  } catch (error) {
308
262
  const errorMessage = `Script execution failed: ${error.message}`;
309
-
310
- // On utilise aussi trace() pour l'erreur critique
311
263
  const finalErrorMessage = logger.trace('critical', `[VM Script] ${errorMessage}\n${error.stack}`);
312
264
  collectedLogs.push({
313
265
  level: 'critical',
314
266
  message: finalErrorMessage,
315
267
  timestamp: new Date().toISOString()
316
268
  });
317
-
318
269
  return { success: false, message: errorMessage, logs: collectedLogs };
270
+ } finally {
271
+ // 3. CRUCIAL: Dispose of the isolate to prevent memory leaks
272
+ if (isolate && !isolate.isDisposed) {
273
+ isolate.dispose();
274
+ }
319
275
  }
320
276
  }
277
+
321
278
  /**
322
279
  * Handles the 'Webhook' workflow action.
323
280
  * Sends an HTTP request to a specified URL with substituted data using native fetch.
package/src/setenv.js CHANGED
@@ -1,4 +1,4 @@
1
- import {getRandom} from "data-primals-engine/core";
1
+ import {getRandom} from "./core.js";
2
2
  import process from "node:process";
3
3
  import {Engine} from "./index.js";
4
4
 
@@ -1,14 +1,13 @@
1
1
  // __tests__/data.integration.test.js
2
2
  import { ObjectId } from 'mongodb';
3
- import {expect, describe, it, beforeEach, afterEach, beforeAll, afterAll, vi} from 'vitest';
3
+ import {expect, describe, it, beforeEach, beforeAll} from 'vitest';
4
4
  import { Config } from '../src/config.js';
5
5
 
6
- // --- Importations des modules de votre application ---
7
6
  import {
8
7
  insertData,
9
8
  editData,
10
9
  deleteData,
11
- getModel, searchData, installPack
10
+ searchData, installPack
12
11
  } from 'data-primals-engine/modules/data';
13
12
 
14
13
  import {
@@ -16,13 +15,8 @@ import {
16
15
  getCollection,
17
16
  getCollectionForUser as getAppUserCollection
18
17
  } from 'data-primals-engine/modules/mongodb';
19
- import { Engine } from "data-primals-engine/engine";
20
- import process from "node:process";
21
- import fs from "node:fs";
22
- import util from "node:util";
23
- import {getRandom} from "data-primals-engine/core";
24
- import {generateUniqueName, getUniquePort, initEngine} from "../src/setenv.js";
25
- import {MongoDatabase} from "../src/engine.js";
18
+ import {getRandom} from "../src/core.js";
19
+ import {generateUniqueName, initEngine} from "../src/setenv.js";
26
20
 
27
21
  let testModelsColInstance;
28
22
  let testDatasColInstance;
@@ -6,7 +6,7 @@ import { insertData, editData } from 'data-primals-engine/modules/data';
6
6
  import { modelsCollection as getAppModelsCollection, getCollectionForUser, getCollection } from 'data-primals-engine/modules/mongodb';
7
7
  import * as workflowModule from 'data-primals-engine/modules/workflow';
8
8
  import {initEngine} from "../src/setenv.js";
9
- import {maxExecutionsByStep} from "data-primals-engine/constants";
9
+ import {maxExecutionsByStep} from "../src/constants.js";
10
10
 
11
11
  vi.mock('data-primals-engine/modules/workflow', { spy: true })
12
12