data-primals-engine 1.2.6-rc2 → 1.2.6

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.
@@ -13,17 +13,17 @@
13
13
  },
14
14
  "peerDependencies": {
15
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
16
  "react-chartjs-2": "^5.3.0",
25
17
  "react-code-blocks": "^0.1.6",
26
- "react-ga": "^3.3.1"
18
+ "react-cookie": "^8.0.0",
19
+ "react-ga": "^3.3.1",
20
+ "react-helmet": "^6.1.0",
21
+ "react-icons": "^5.0.1",
22
+ "react-international-phone": "^4.5.0",
23
+ "react-query": "^3.39.3",
24
+ "react-router-dom": "^7.1.5",
25
+ "react-syntax-highlighter": "^15.6.1",
26
+ "react-tooltip": "^5.28.1"
27
27
  },
28
28
  "dependencies": {
29
29
  "@babel/runtime": "^7.24.7",
@@ -43,15 +43,16 @@
43
43
  "@uiw/react-codemirror": "^4.23.10",
44
44
  "chart.js": "^4.4.9",
45
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
46
  "classnames": "^2.5.1",
51
47
  "date-fns": "^4.1.0",
52
48
  "express-rate-limit": "^7.5.1",
53
49
  "lowlight": "^3.3.0",
54
- "uniqid": "^5.4.0"
50
+ "react": ">=18.0.0",
51
+ "react-dom": "^18.3.1",
52
+ "react-router": "^7.2.0",
53
+ "react-switch": "^7.1.0",
54
+ "uniqid": "^5.4.0",
55
+ "yet-another-react-lightbox": "^3.22.0"
55
56
  },
56
57
  "devDependencies": {
57
58
  "@eslint/js": "^9.17.0",
@@ -67,4 +68,4 @@
67
68
  "sass-embedded": "^1.83.4",
68
69
  "vite": "^6.1.1"
69
70
  }
70
- }
71
+ }
@@ -421,6 +421,7 @@ input[type=number]::-webkit-outer-spin-button {
421
421
  form .field {
422
422
  width: 100%;
423
423
  .help {
424
+ width: 100%;
424
425
  color: #575757;
425
426
  padding: 4px;
426
427
  }
@@ -239,7 +239,7 @@ export const DataEditor = forwardRef(function MyDataEditor({
239
239
  onChange={(e) => handleChange({name: field.name, value: e})}/>
240
240
  case 'boolean':
241
241
  return <CheckboxField
242
- help={value && t('field_' + model.name + '_' + field.name + '_hint', field.hint || '')}
242
+ help={t('field_' + model.name + '_' + field.name + '_hint', field.hint || '')}
243
243
  key={field.name} {...inputProps} checked={value}
244
244
  onChange={(e) => handleChange({name: field.name, value: e.target.checked})}/>
245
245
  case 'string':
@@ -34,7 +34,7 @@ import { docco } from 'react-syntax-highlighter/dist/esm/styles/hljs';
34
34
  import { PhoneInput } from 'react-international-phone';
35
35
  import 'react-international-phone/style.css';
36
36
  import {useAuthContext} from "./contexts/AuthContext.jsx";
37
-
37
+ import Switch from "react-switch";
38
38
  export const Form = ({
39
39
  name,
40
40
  onValidate,
@@ -492,20 +492,6 @@ const CheckboxField = forwardRef(
492
492
  return (
493
493
  <>
494
494
  <div className={cn({field: true, "field-checkbox": true,"field-bg": true})}>
495
- <div className="inline"><input
496
- aria-required={required}
497
- aria-readonly={readOnly}
498
- readOnly={readOnly}
499
- type="checkbox"
500
- checked={value}
501
- placeholder={placeholder}
502
- id={id}
503
- name={name}
504
- onChange={handleChange}
505
- minLength={minlength}
506
- maxLength={maxlength}
507
- {...rest}
508
- />
509
495
  {label && (
510
496
  <label
511
497
  contentEditable={editable}
@@ -522,7 +508,9 @@ const CheckboxField = forwardRef(
522
508
  )}
523
509
  </label>
524
510
  )}
525
- </div>
511
+ <Switch
512
+ onChange={handleChange}
513
+ checked={value} />
526
514
  {help && <div className="flex help">{help}</div>}
527
515
  </div>
528
516
  {errors.length > 0 && (
@@ -2,6 +2,9 @@
2
2
  export const websiteTranslations = {
3
3
  fr: {
4
4
  translation: {
5
+
6
+ "api.data.relationFilterFailed": "La valeur {{value}} pour le champ {{field}} ne respecte pas le filtre de relation défini.",
7
+
5
8
  "dataimporter.excelPreview":"Aperçu des données Excel",
6
9
  "dataimporter.previewNote": "Note: Ceci est un aperçu des premières lignes. Les cellules vides sont affichées comme \"(vide)\".",
7
10
  "dataimporter.nullValue": "(vide)",
@@ -567,6 +570,8 @@ export const websiteTranslations = {
567
570
  "suggested_prompt.recipes.title": "Cooking Recipes",
568
571
  "suggested_prompt.recipes.prompt": "A collection of cooking recipes, with ingredients, instructions, and preparation time.",
569
572
 
573
+ "api.data.relationFilterFailed": "The value {{value}} for field {{field}} does not match the defined relationship filter.",
574
+
570
575
  "api.data.duplicateValue": "The value '{{value}}' already exists for the unique field '{{field}}'.",
571
576
  "api.model.invalidStructure": "The model is invalid. Some fields are incorrect.",
572
577
  "api.validate.fieldArray": "Field '{{0}}' must be an array.",
@@ -1975,6 +1980,7 @@ export const websiteTranslations = {
1975
1980
  "suggested_prompt.recipes.prompt": "Una colección de recetas de cocina, con ingredientes, instrucciones y tiempo de preparación.",
1976
1981
 
1977
1982
  "api.data.duplicateValue": "El valor '{{value}}' ya existe para el campo único '{{field}}'.",
1983
+ "api.data.relationFilterFailed": "El valor {{value}} del campo {{field}} no coincide con el filtro de relación definido.",
1978
1984
  "api.model.invalidStructure": "El modelo no es válido. Algunos campos son incorrectos.",
1979
1985
  "api.validate.fieldArray": "El campo '{{0}}' debe ser un array.",
1980
1986
  "api.validate.invalidMimeType": "Tipo de archivo '{{type}}' no válido. Los tipos permitidos son: {{authorized}}.",
@@ -3388,6 +3394,7 @@ export const websiteTranslations = {
3388
3394
  "suggested_prompt.recipes.prompt": "Uma coleção de receitas culinárias, com ingredientes, instruções e tempo de preparação.",
3389
3395
 
3390
3396
  "api.data.duplicateValue": "O valor '{{value}}' já existe para o campo exclusivo '{{field}}'.",
3397
+ "api.data.relationFilterFailed": "O valor {{value}} para o campo {{field}} não corresponde ao filtro de relacionamento definido.",
3391
3398
  "api.model.invalidStructure": "O modelo é inválido. Alguns campos estão incorretos.",
3392
3399
  "api.validate.fieldArray": "O campo '{{0}}' deve ser um array.",
3393
3400
  "api.validate.invalidMimeType": "Tipo de ficheiro inválido '{{type}}'. Os tipos permitidos são: {{authorized}}.",
@@ -4782,6 +4789,7 @@ export const websiteTranslations = {
4782
4789
  "suggested_prompt.recipes.prompt": "Eine Sammlung von Kochrezepten mit Zutaten, Anweisungen und Vorbereitungszeit.",
4783
4790
 
4784
4791
  "api.data.duplicateValue": "Der Wert '{{value}}' ist für das eindeutige Feld '{{field}}' bereits vorhanden.",
4792
+ "api.data.relationFilterFailed": "Der Wert {{value}} für das Feld {{field}} entspricht nicht dem definierten Beziehungsfilter.",
4785
4793
  "api.model.invalidStructure": "Das Modell ist ungültig. Einige Felder sind fehlerhaft.",
4786
4794
  "api.validate.fieldArray": "Feld '{{0}}' muss ein Array sein.",
4787
4795
  "api.validate.invalidMimeType": "Ungültiger Dateityp '{{type}}'. Zulässige Typen sind: {{authorized}}.",
@@ -6185,6 +6193,7 @@ export const websiteTranslations = {
6185
6193
  "suggested_prompt.recipes.prompt": "Una raccolta di ricette di cucina, con ingredienti, istruzioni e tempi di preparazione.",
6186
6194
 
6187
6195
  "api.data.duplicateValue": "Il valore '{{value}}' esiste già per il campo univoco '{{field}}'.",
6196
+ "api.data.relationFilterFailed": "Il valore {{value}} per il campo {{field}} non corrisponde al filtro di relazione definito.",
6188
6197
  "api.model.invalidStructure": "Il modello non è valido. Alcuni campi sono errati.",
6189
6198
  "api.validate.fieldArray": "Il campo '{{0}}' deve essere un array.",
6190
6199
  "api.validate.invalidMimeType": "Tipo di file '{{type}}' non valido. I tipi consentiti sono: {{authorized}}.",
@@ -7589,6 +7598,7 @@ export const websiteTranslations = {
7589
7598
  "suggested_prompt.recipes.prompt": "Sbírka receptů na vaření s ingrediencemi, návodem a přípravou čas.",
7590
7599
 
7591
7600
  "api.data.duplicateValue": "Hodnota '{{value}}' pro jedinečné pole '{{field}}' již existuje.",
7601
+ "api.data.relationFilterFailed": "Hodnota {{value}} pro pole {{field}} neodpovídá definovanému filtru vztahů.",
7592
7602
  "api.model.invalidStructure": "Model je neplatný. Některá pole jsou nesprávná.",
7593
7603
  "api.validate.fieldArray": "Pole '{{0}}' musí být pole.",
7594
7604
  "api.validate.invalidMimeType": "Neplatný typ souboru '{{type}}'. Povolené typy jsou: {{authorized}}.",
@@ -8988,6 +8998,7 @@ export const websiteTranslations = {
8988
8998
  "suggested_prompt.recipes.prompt": "Коллекция кулинарных рецептов с ингредиентами, инструкциями и описанием приготовления. время.",
8989
8999
 
8990
9000
  "api.data.duplicateValue": "Значение '{{value}}' уже существует для уникального поля '{{field}}'.",
9001
+ "api.data.relationFilterFailed": "Значение {{value}} для поля {{field}} не соответствует заданному фильтру связи.",
8991
9002
  "api.model.invalidStructure": "Модель недействительна. Некоторые поля неверны.",
8992
9003
  "api.validate.fieldArray": "Поле '{{0}}' должно быть массивом.",
8993
9004
  "api.validate.invalidMimeType": "Недопустимый тип файла '{{type}}'. Допустимые типы: {{authorized}}.",
@@ -10396,6 +10407,7 @@ export const websiteTranslations = {
10396
10407
  "suggested_prompt.recipes.prompt": "مجموعة من وصفات الطبخ، مع المكونات، والتعليمات، ومدة التحضير.",
10397
10408
 
10398
10409
  "api.data.duplicateValue": "القيمة '{{value}}' موجودة بالفعل للحقل الفريد '{{field}}'.",
10410
+ "api.data.relationFilterFailed": "القيمة {{value}} للحقل {{field}} لا تتطابق مع مرشح العلاقة المحدد.",
10399
10411
  "api.model.invalidStructure": "النموذج غير صالح. بعض الحقول غير صحيحة.",
10400
10412
  "api.validate.fieldArray": "يجب أن يكون الحقل '{{0}}' مصفوفة.",
10401
10413
  "api.validate.invalidMimeType": "نوع الملف '{{type}}' غير صالح. الأنواع المسموح بها هي: {{authorized}}.",
@@ -11823,6 +11835,7 @@ export const websiteTranslations = {
11823
11835
  "suggested_prompt.recipes.prompt": "En samling matlagningsrecept, med ingredienser, instruktioner, och förberedelsetid.",
11824
11836
 
11825
11837
  "api.data.duplicateValue": "Värdet '{{value}}' finns redan för det unika fältet '{{field}}'.",
11838
+ "api.data.relationFilterFailed": "Värdet {{value}} för fältet {{field}} matchar inte det definierade relationsfiltret.",
11826
11839
  "api.model.invalidStructure": "Modellen är ogiltig. Vissa fält är felaktiga.",
11827
11840
  "api.validate.fieldArray": "Fältet '{{0}}' måste vara en array.",
11828
11841
  "api.validate.invalidMimeType": "Ogiltig filtyp '{{type}}'. Tillåtna typer är: {{authorized}}.",
@@ -13222,6 +13235,8 @@ export const websiteTranslations = {
13222
13235
  "suggested_prompt.recipes.prompt": "Μια συλλογή συνταγών μαγειρικής, με υλικά, οδηγίες και χρόνο προετοιμασίας.",
13223
13236
 
13224
13237
  "api.data.duplicateValue": "Η τιμή '{{value}}' υπάρχει ήδη για το μοναδικό πεδίο '{{field}}'.",
13238
+ "api.data.relationFilterFailed": "Η τιμή {{value}} για το πεδίο {{field}} δεν ταιριάζει με το καθορισμένο φίλτρο σχέσης.",
13239
+
13225
13240
  "api.model.invalidStructure": "Το μοντέλο δεν είναι έγκυρο. Ορισμένα πεδία είναι λανθασμένα.",
13226
13241
  "api.validate.fieldArray": "Το πεδίο '{{0}}' πρέπει να είναι ένας πίνακας.",
13227
13242
  "api.validate.invalidMimeType": "Μη έγκυρος τύπος αρχείου '{{type}}'. Οι επιτρεπόμενοι τύποι είναι: {{authorized}}.",
@@ -14629,6 +14644,8 @@ export const websiteTranslations = {
14629
14644
  "suggested_prompt.recipes.prompt": "مجموعه‌ای از دستور پخت غذا، با مواد لازم، دستورالعمل و زمان آماده‌سازی.",
14630
14645
 
14631
14646
  "api.data.duplicateValue": "مقدار '{{value}}' از قبل برای فیلد منحصر به فرد '{{field}}' وجود دارد.",
14647
+ "api.data.relationFilterFailed": "مقدار {{value}} برای فیلد {{field}} با فیلتر رابطه تعریف شده مطابقت ندارد.",
14648
+
14632
14649
  "api.model.invalidStructure": "مدل نامعتبر است. برخی از فیلدها نادرست هستند.",
14633
14650
  "api.validate.fieldArray": "فیلد '{{0}}' باید یک آرایه باشد.",
14634
14651
  "api.validate.invalidMimeType": "نوع فایل '{{type}}' نامعتبر است. انواع مجاز عبارتند از: {{authorized}}.",
package/package.json CHANGED
@@ -1,120 +1,120 @@
1
- {
2
- "name": "data-primals-engine",
3
- "version": "1.2.6-rc2",
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",
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
- "tar-fs": "3.0.9",
32
- "on-headers": "1.1.0",
33
- "brace-expansion": "2.0.2",
34
- "prismjs": "1.30.0"
35
- },
36
- "repository": {
37
- "type": "git",
38
- "url": "https://github.com/anonympins/data-primals-engine.git"
39
- },
40
- "exports": {
41
- ".": "./src/index.js",
42
- "./modules/*.js": "./src/modules/*.js",
43
- "./modules/*": "./src/modules/*/index.js",
44
- "./client": "./client/index.js",
45
- "./*": "./src/*.js"
46
- },
47
- "peerDependencies": {
48
- "express": "^5.1.0",
49
- "react": ">=18.0.0",
50
- "react-query": ">=3.0.0"
51
- },
52
- "dependencies": {
53
- "@langchain/core": "^0.3.66",
54
- "@langchain/deepseek": "^0.1.0",
55
- "@langchain/google-genai": "^0.2.16",
56
- "@langchain/openai": "^0.6.3",
57
- "archiver": "^7.0.1",
58
- "aws-sdk": "^2.1692.0",
59
- "bcrypt": "^6.0.0",
60
- "body-parser": "^2.2.0",
61
- "chalk": "^5.4.1",
62
- "check-disk-space": "^3.4.0",
63
- "compression": "^1.8.1",
64
- "cookie-parser": "^1.4.7",
65
- "cronstrue": "^3.2.0",
66
- "csv-parse": "^6.1.0",
67
- "date-fns": "^4.1.0",
68
- "express-csrf-double-submit-cookie": "^2.0.0",
69
- "express-formidable": "^1.2.0",
70
- "express-mongo-sanitize": "^2.2.0",
71
- "express-rate-limit": "^8.0.1",
72
- "express-session": "^1.18.2",
73
- "i18next-browser-languagedetector": "^8.2.0",
74
- "isolated-vm": "^4.7.2",
75
- "juice": "^11.0.1",
76
- "mathjs": "^14.6.0",
77
- "mongodb": "^6.18.0",
78
- "node-cache": "^5.1.2",
79
- "node-schedule": "^2.1.1",
80
- "nodemailer": "^7.0.5",
81
- "openai": "^5.10.2",
82
- "process": "^0.11.10",
83
- "prop-types": "^15.8.1",
84
- "randomcolor": "^0.6.2",
85
- "react-i18next": "^15.6.1",
86
- "react-markdown": "^10.1.0",
87
- "read-excel-file": "^5.8.8",
88
- "request-ip": "^3.3.0",
89
- "sanitize-html": "^2.17.0",
90
- "sirv": "^3.0.1",
91
- "swagger-ui-express": "^5.0.1",
92
- "tar": "^7.4.3",
93
- "uniqid": "^5.4.0",
94
- "vitest": "^3.2.4",
95
- "yaml": "^2.8.0"
96
- },
97
- "devDependencies": {
98
- "@eslint/js": "^9.32.0",
99
- "concurrently": "^9.2.0",
100
- "cross-env": "^10.0.0",
101
- "eslint": "^9.32.0",
102
- "globals": "^16.3.0"
103
- },
104
- "subPackages": [
105
- "client"
106
- ],
107
- "keywords": [
108
- "data-driven engine",
109
- "headless CMS",
110
- "backend",
111
- "automation",
112
- "AWS S3",
113
- "MongoDB"
114
- ],
115
- "author": "anonympins",
116
- "license": "MIT",
117
- "engines": {
118
- "node": ">=20.0.0"
119
- }
120
- }
1
+ {
2
+ "name": "data-primals-engine",
3
+ "version": "1.2.6",
4
+ "description": "data-primals-engine is a package responsible from handling large amount of data using MongoDB in a practical and performant way. It can also get workflow models working (for automation), and fully supports internationalisation. It also has integrated AI assistant.",
5
+ "main": "src/engine.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "preinstall": "npx force-resolutions",
9
+ "dev": "concurrently \"npm:client\" \"npm:devserver\"",
10
+ "prod": "npm run build-server && npm run server",
11
+ "client": "cd client && npm run dev",
12
+ "build-server": "vite build client --config client/vite.config.js --outDir dist",
13
+ "build-client": "cd client && npm run build",
14
+ "server": "cross-env NODE_ENV=production node server.js",
15
+ "devserver": "npm run build-server && cross-env NODE_ENV=development PORT=7633 node server.js",
16
+ "lint": "eslint .",
17
+ "format": "prettier --write .",
18
+ "clean": "rm -rf node_modules package-lock.json",
19
+ "test": "cross-env MONGO_DB_URL=\"mongodb://localhost:27017\" PORT=7635 vitest --no-file-parallelism",
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
+ "tar-fs": "3.0.9",
32
+ "on-headers": "1.1.0",
33
+ "brace-expansion": "2.0.2",
34
+ "prismjs": "1.30.0"
35
+ },
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/anonympins/data-primals-engine.git"
39
+ },
40
+ "exports": {
41
+ ".": "./src/index.js",
42
+ "./modules/*.js": "./src/modules/*.js",
43
+ "./modules/*": "./src/modules/*/index.js",
44
+ "./client": "./client/index.js",
45
+ "./*": "./src/*.js"
46
+ },
47
+ "peerDependencies": {
48
+ "express": "^5.1.0",
49
+ "react": ">=18.0.0",
50
+ "react-query": ">=3.0.0"
51
+ },
52
+ "dependencies": {
53
+ "@langchain/core": "^0.3.66",
54
+ "@langchain/deepseek": "^0.1.0",
55
+ "@langchain/google-genai": "^0.2.16",
56
+ "@langchain/openai": "^0.6.3",
57
+ "archiver": "^7.0.1",
58
+ "aws-sdk": "^2.1692.0",
59
+ "bcrypt": "^6.0.0",
60
+ "body-parser": "^2.2.0",
61
+ "chalk": "^5.4.1",
62
+ "check-disk-space": "^3.4.0",
63
+ "compression": "^1.8.1",
64
+ "cookie-parser": "^1.4.7",
65
+ "cronstrue": "^3.2.0",
66
+ "csv-parse": "^6.1.0",
67
+ "date-fns": "^4.1.0",
68
+ "express-csrf-double-submit-cookie": "^2.0.0",
69
+ "express-formidable": "^1.2.0",
70
+ "express-mongo-sanitize": "^2.2.0",
71
+ "express-rate-limit": "^8.0.1",
72
+ "express-session": "^1.18.2",
73
+ "i18next-browser-languagedetector": "^8.2.0",
74
+ "isolated-vm": "^4.7.2",
75
+ "juice": "^11.0.1",
76
+ "mathjs": "^14.6.0",
77
+ "mongodb": "^6.18.0",
78
+ "node-cache": "^5.1.2",
79
+ "node-schedule": "^2.1.1",
80
+ "nodemailer": "^7.0.5",
81
+ "openai": "^5.10.2",
82
+ "process": "^0.11.10",
83
+ "prop-types": "^15.8.1",
84
+ "randomcolor": "^0.6.2",
85
+ "react-i18next": "^15.6.1",
86
+ "react-markdown": "^10.1.0",
87
+ "read-excel-file": "^5.8.8",
88
+ "request-ip": "^3.3.0",
89
+ "sanitize-html": "^2.17.0",
90
+ "sirv": "^3.0.1",
91
+ "swagger-ui-express": "^5.0.1",
92
+ "tar": "^7.4.3",
93
+ "uniqid": "^5.4.0",
94
+ "vitest": "^3.2.4",
95
+ "yaml": "^2.8.0"
96
+ },
97
+ "devDependencies": {
98
+ "@eslint/js": "^9.32.0",
99
+ "concurrently": "^9.2.0",
100
+ "cross-env": "^10.0.0",
101
+ "eslint": "^9.32.0",
102
+ "globals": "^16.3.0"
103
+ },
104
+ "subPackages": [
105
+ "client"
106
+ ],
107
+ "keywords": [
108
+ "data-driven engine",
109
+ "headless CMS",
110
+ "backend",
111
+ "automation",
112
+ "AWS S3",
113
+ "MongoDB"
114
+ ],
115
+ "author": "anonympins",
116
+ "license": "MIT",
117
+ "engines": {
118
+ "node": ">=20.0.0"
119
+ }
120
+ }
package/src/engine.js CHANGED
@@ -199,7 +199,6 @@ export const Engine = {
199
199
  }
200
200
  } catch (e) {
201
201
  logger.error(`Échec du chargement du module '${moduleIdentifier}':`, e.stack);
202
- return null;
203
202
  }
204
203
  }
205
204
 
package/src/filter.js CHANGED
@@ -175,15 +175,45 @@ export const isConditionMet = (model, cond, formData, allModels, user) => {
175
175
 
176
176
  if (!condition) return true;
177
177
 
178
+ // Cas 0: Condition est une valeur primitive (string, number, boolean)
179
+ // On la considère comme toujours vraie (comportement de searchData)
180
+ if (typeof condition !== 'object' || condition === null) {
181
+ return true;
182
+ }
183
+
178
184
  // Cas 1: Condition simple {field: value} → transformée en {field: {$eq: value}}
179
185
  if (typeof condition === 'object' && !Array.isArray(condition)) {
180
186
  const keys = Object.keys(condition);
187
+
188
+ // Cas spécial pour les conditions de type {field: value} (pas d'opérateur $)
181
189
  if (keys.length === 1 && !keys[0].startsWith('$') &&
182
190
  typeof condition[keys[0]] !== 'object') {
183
- const simpleCondition = {
184
- [keys[0]]: {$eq: condition[keys[0]]}
185
- };
186
- return evaluateSingleCondition(model, simpleCondition, formData, allModels, user);
191
+ const fieldName = keys[0];
192
+ const value = condition[fieldName];
193
+
194
+ // Si la valeur est null/undefined, on vérifie simplement l'existence
195
+ if (value === null || value === undefined) {
196
+ return formData[fieldName] === value;
197
+ }
198
+
199
+ // Sinon on fait une comparaison d'égalité simple
200
+ return formData[fieldName] == value;
201
+ }
202
+
203
+ // Cas spécial pour les tableaux - vérifie si la valeur est incluse
204
+ if (keys.length === 1 && !keys[0].startsWith('$') &&
205
+ Array.isArray(condition[keys[0]])) {
206
+ const fieldName = keys[0];
207
+ const values = condition[fieldName];
208
+ const fieldValue = formData[fieldName];
209
+
210
+ // Si le champ est aussi un tableau, vérifie l'intersection
211
+ if (Array.isArray(fieldValue)) {
212
+ return fieldValue.some(v => values.includes(v));
213
+ }
214
+
215
+ // Sinon vérifie si la valeur est dans le tableau
216
+ return values.includes(fieldValue);
187
217
  }
188
218
  }
189
219
 
@@ -218,4 +248,4 @@ export const isConditionMet = (model, cond, formData, allModels, user) => {
218
248
 
219
249
  // Cas 4: Tous les autres cas (conditions normales avec opérateurs)
220
250
  return evaluateSingleCondition(model, condition, formData, allModels, user);
221
- };
251
+ };
@@ -1,5 +1,6 @@
1
1
  import NodeCache from "node-cache";
2
-
2
+ import path from "node:path";
3
+ import {Worker} from 'worker_threads';
3
4
  export const modelsCache = new NodeCache( { stdTTL: 100, checkperiod: 120 } );
4
5
 
5
6
  export const mongoDBWhitelist = [
@@ -15,3 +16,73 @@ export const mongoDBWhitelist = [
15
16
  ];
16
17
  export let importJobs = {};
17
18
 
19
+
20
+ /**
21
+ * Exécute une tâche d'import/export (parsing, stringify) dans un worker thread.
22
+ * @param {('parse-json'|'parse-csv'|'stringify-json')} action - L'action à effectuer.
23
+ * @param {object} payload - Les données nécessaires pour l'action.
24
+ * @returns {Promise<any>} - Une promesse qui se résout avec les données traitées.
25
+ */
26
+ export function runImportExportWorker(action, payload) {
27
+ return new Promise((resolve, reject) => {
28
+ const workerPath = path.resolve(process.cwd(), './src/workers/import-export-worker.js');
29
+ const worker = new Worker(workerPath);
30
+
31
+ worker.postMessage({ action, payload });
32
+
33
+ worker.on('message', (result) => {
34
+ if (result.success) {
35
+ resolve(result.data);
36
+ } else {
37
+ // Correction : On s'assure de toujours passer une chaîne de caractères à new Error()
38
+ const errorMessage = result.error || `Import/Export Worker failed with an unknown error. Action: ${action}.`;
39
+ reject(new Error(errorMessage));
40
+ }
41
+ worker.terminate();
42
+ });
43
+
44
+ worker.on('error', (err) => {
45
+ reject(err);
46
+ worker.terminate();
47
+ });
48
+
49
+ worker.on('exit', (code) => {
50
+ if (code !== 0) {
51
+ reject(new Error(`Import/Export Worker stopped with exit code ${code}`));
52
+ }
53
+ });
54
+ });
55
+ }
56
+ /** Exécute une tâche de cryptographie dans un worker thread.
57
+ * @param {('encrypt'|'decrypt'|'hash')} action - L'action à effectuer.
58
+ * @param {object} payload - Les données nécessaires pour l'action.
59
+ * @returns {Promise<any>} - Une promesse qui se résout avec le résultat (si pertinent).
60
+ */
61
+ export function runCryptoWorkerTask(action, payload) {
62
+ return new Promise((resolve, reject) => {
63
+ const workerPath = path.resolve(process.cwd(), './src/workers/crypto-worker.js');
64
+ const worker = new Worker(workerPath);
65
+
66
+ worker.postMessage({ action, payload });
67
+
68
+ worker.on('message', (result) => {
69
+ if (result.success) {
70
+ resolve(result.data); // Résout avec les données (ex: le hash) ou undefined si pas de retour
71
+ } else {
72
+ reject(new Error(result.error));
73
+ }
74
+ worker.terminate();
75
+ });
76
+
77
+ worker.on('error', (err) => {
78
+ reject(err);
79
+ worker.terminate();
80
+ });
81
+
82
+ worker.on('exit', (code) => {
83
+ if (code !== 0) {
84
+ reject(new Error(`Crypto Worker stopped with exit code ${code}`));
85
+ }
86
+ });
87
+ });
88
+ }