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.
- package/.github/workflows/node.js.yml +2 -7
- package/client/package.json +70 -69
- package/client/src/APIInfo.jsx +2 -5
- package/client/src/App.jsx +3 -3
- package/client/src/CalculationBuilder.jsx +2 -2
- package/client/src/Dashboard.jsx +2 -2
- package/client/src/DashboardChart.jsx +1 -1
- package/client/src/DashboardFlexViewItem.jsx +1 -1
- package/client/src/DashboardView.jsx +1 -1
- package/client/src/DataEditor.jsx +2 -2
- package/client/src/DataLayout.jsx +3 -9
- package/client/src/DataTable.jsx +3 -3
- package/client/src/DisplayFlexNodeRenderer.jsx +3 -3
- package/client/src/Field.jsx +2 -2
- package/client/src/FlexBuilder.jsx +1 -1
- package/client/src/KPIWidget.jsx +1 -1
- package/client/src/KanbanCard.jsx +1 -1
- package/client/src/ModelCreator.jsx +3 -3
- package/client/src/ModelCreatorField.jsx +2 -2
- package/client/src/ModelImporter.jsx +1 -1
- package/client/src/PackGallery.jsx +1 -1
- package/client/src/RTETrans.jsx +1 -1
- package/client/src/RelationField.jsx +1 -1
- package/client/src/RelationValue.jsx +1 -1
- package/client/src/Webpage.jsx +2 -2
- package/client/src/constants.js +1 -0
- package/client/src/contexts/ModelContext.jsx +2 -3
- package/client/src/hooks/data.js +1 -1
- package/client/src/hooks/useTutorials.jsx +1 -1
- package/package.json +3 -4
- package/src/constants.js +1 -0
- package/src/i18n.js +2 -1
- package/src/modules/assistant.js +1 -1
- package/src/modules/bucket.js +1 -1
- package/src/modules/data.js +1 -1
- package/src/modules/file.js +1 -1
- package/src/modules/user.js +1 -1
- package/src/modules/workflow.js +53 -96
- package/src/setenv.js +1 -1
- package/test/data.integration.test.js +4 -10
- 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:
|
|
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: [
|
|
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
|
|
package/client/package.json
CHANGED
|
@@ -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
|
-
"
|
|
15
|
-
"@
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"@
|
|
30
|
-
"@
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"react-
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"react-
|
|
47
|
-
"react-
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"@
|
|
59
|
-
"@types/react
|
|
60
|
-
"@
|
|
61
|
-
"
|
|
62
|
-
"eslint
|
|
63
|
-
"eslint-plugin-react
|
|
64
|
-
"eslint-plugin-react-
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
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
|
}
|
package/client/src/APIInfo.jsx
CHANGED
|
@@ -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 "
|
|
6
|
+
import {getDefaultForType} from "../../src/data.js";
|
|
7
7
|
import { CodeBlock, tomorrowNightBright } from 'react-code-blocks';
|
|
8
|
-
import {
|
|
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= {}}) => {
|
package/client/src/App.jsx
CHANGED
|
@@ -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 "
|
|
56
|
-
import {getRandom} from "
|
|
57
|
-
import {getUserHash} from "
|
|
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 "
|
|
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 "
|
|
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)}`;
|
package/client/src/Dashboard.jsx
CHANGED
|
@@ -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 "
|
|
14
|
-
import {getUserHash, getUserId} from "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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";
|
package/client/src/DataTable.jsx
CHANGED
|
@@ -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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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
|
-
|
|
10
|
+
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Récupère une valeur imbriquée dans un objet (ex: 'user.address.city').
|
package/client/src/Field.jsx
CHANGED
|
@@ -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 "
|
|
15
|
-
import {mainFieldsTypes, maxFileSize} from "
|
|
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 "
|
|
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';
|
package/client/src/KPIWidget.jsx
CHANGED
|
@@ -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 "
|
|
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 "
|
|
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 "
|
|
17
|
+
} from "../../src/constants.js";
|
|
18
18
|
import {useAuthContext} from "./contexts/AuthContext.jsx";
|
|
19
|
-
import {getUserHash, getUserId, isLocalUser} from "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
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 "
|
|
10
|
+
import {elementsPerPage} from "../../src/constants.js";
|
|
11
11
|
|
|
12
12
|
// --- API Fetching Functions ---
|
|
13
13
|
const fetchPacks = async (sortBy, lang) => {
|
package/client/src/RTETrans.jsx
CHANGED
|
@@ -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 "
|
|
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 "
|
|
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 "
|
|
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();
|
package/client/src/Webpage.jsx
CHANGED
|
@@ -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 "
|
|
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 "
|
|
11
|
+
import {getUserHash, getUserId} from "../../src/data.js";
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
function Webpage({children}) {
|
package/client/src/constants.js
CHANGED
|
@@ -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 {
|
|
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 "
|
|
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
|
|
package/client/src/hooks/data.js
CHANGED
|
@@ -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 "
|
|
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 "
|
|
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.
|
|
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
|
-
"
|
|
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": ">=
|
|
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;
|
package/src/modules/assistant.js
CHANGED
|
@@ -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 "
|
|
10
|
+
import i18n from "../../src/i18n.js";
|
|
11
11
|
import {generateLimiter} from "./user.js";
|
|
12
12
|
import rateLimit from "express-rate-limit";
|
|
13
13
|
|
package/src/modules/bucket.js
CHANGED
|
@@ -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 "
|
|
12
|
+
import i18n from "../../src/i18n.js";
|
|
13
13
|
import {sendEmail} from "../email.js";
|
|
14
14
|
import {throttleMiddleware} from "../middlewares/throttle.js";
|
|
15
15
|
|
package/src/modules/data.js
CHANGED
|
@@ -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 "
|
|
67
|
+
import i18n from "../i18n.js";
|
|
68
68
|
import {
|
|
69
69
|
executeSafeJavascript,
|
|
70
70
|
runScheduledJobWithDbLock,
|
package/src/modules/file.js
CHANGED
|
@@ -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 "
|
|
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";
|
package/src/modules/user.js
CHANGED
package/src/modules/workflow.js
CHANGED
|
@@ -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
|
|
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 "
|
|
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
|
-
|
|
184
|
-
async function executeWithIsolatedVm(actionDef, context) {
|
|
184
|
+
export async function executeSafeJavascript(actionDef, context, user) {
|
|
185
185
|
const code = actionDef.script;
|
|
186
|
-
const
|
|
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
|
-
//
|
|
193
|
-
|
|
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
|
-
|
|
233
|
-
|
|
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
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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:
|
|
215
|
+
level: level,
|
|
272
216
|
message: finalMessage,
|
|
273
217
|
timestamp: new Date().toISOString()
|
|
274
218
|
});
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
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
|
-
|
|
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
|
-
|
|
296
|
-
|
|
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
|
-
|
|
304
|
-
|
|
305
|
-
const
|
|
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,14 +1,13 @@
|
|
|
1
1
|
// __tests__/data.integration.test.js
|
|
2
2
|
import { ObjectId } from 'mongodb';
|
|
3
|
-
import {expect, describe, it, beforeEach,
|
|
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
|
-
|
|
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 {
|
|
20
|
-
import
|
|
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 "
|
|
9
|
+
import {maxExecutionsByStep} from "../src/constants.js";
|
|
10
10
|
|
|
11
11
|
vi.mock('data-primals-engine/modules/workflow', { spy: true })
|
|
12
12
|
|