data-primals-engine 1.0.10 → 1.1.0

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 (166) hide show
  1. package/client/README.md +8 -0
  2. package/client/index.html +31 -0
  3. package/client/index.js +25 -0
  4. package/client/package-lock.json +11664 -0
  5. package/client/package.json +70 -0
  6. package/client/public/demo/26899917-d1ba-4df4-bb33-48d09a8778da.jpg +0 -0
  7. package/client/public/demo/4b9894c7-12cd-466d-8fd3-a2757b09ec96.jpg +0 -0
  8. package/client/public/demo/7ed369ac-a1a2-4b45-b0cd-4fd5bcf5a75a.jpg +0 -0
  9. package/client/public/doc/API.postman_collection.json +214 -0
  10. package/client/public/github.svg +1 -0
  11. package/client/public/profilCompany.jpg +0 -0
  12. package/client/public/profilDeveloper.jpg +0 -0
  13. package/client/public/profilEngineer.jpg +0 -0
  14. package/client/public/profilPersonal.jpg +0 -0
  15. package/client/public/profils .psd +0 -0
  16. package/client/public/react.svg +9 -0
  17. package/client/src/APIInfo.jsx +328 -0
  18. package/client/src/AddWidgetTypeModal.jsx +44 -0
  19. package/client/src/AddWidgetTypeModal.scss +87 -0
  20. package/client/src/App.css +42 -0
  21. package/client/src/App.jsx +586 -0
  22. package/client/src/App.scss +1466 -0
  23. package/client/src/AssistantChat.jsx +280 -0
  24. package/client/src/AssistantChat.scss +229 -0
  25. package/client/src/Button.jsx +12 -0
  26. package/client/src/Button.scss +197 -0
  27. package/client/src/CalculationBuilder.jsx +338 -0
  28. package/client/src/CalculationStepRow.jsx +199 -0
  29. package/client/src/CalendarConfigModal.jsx +49 -0
  30. package/client/src/ChartConfigModal.jsx +402 -0
  31. package/client/src/ConditionBuilder.jsx +622 -0
  32. package/client/src/ConditionBuilder.scss +672 -0
  33. package/client/src/ConditionBuilder2.jsx +757 -0
  34. package/client/src/ContentView.jsx +274 -0
  35. package/client/src/CronBuilder.jsx +126 -0
  36. package/client/src/CronBuilder.scss +128 -0
  37. package/client/src/CronPartBuilder.jsx +150 -0
  38. package/client/src/Dashboard.jsx +210 -0
  39. package/client/src/Dashboard.scss +445 -0
  40. package/client/src/DashboardChart.jsx +362 -0
  41. package/client/src/DashboardFlexViewItem.jsx +129 -0
  42. package/client/src/DashboardView.jsx +554 -0
  43. package/client/src/DataChart.jsx +349 -0
  44. package/client/src/DataEditor.jsx +556 -0
  45. package/client/src/DataLayout.jsx +709 -0
  46. package/client/src/DataTable.jsx +996 -0
  47. package/client/src/DataTable.scss +73 -0
  48. package/client/src/Dialog.jsx +90 -0
  49. package/client/src/Dialog.scss +117 -0
  50. package/client/src/DisplayFlexNodeRenderer.jsx +115 -0
  51. package/client/src/DocumentationPageLayout.jsx +93 -0
  52. package/client/src/DocumentationPageLayout.scss +262 -0
  53. package/client/src/Draggable.jsx +222 -0
  54. package/client/src/Draggable.scss +49 -0
  55. package/client/src/ExportDialog.jsx +172 -0
  56. package/client/src/Field.jsx +1558 -0
  57. package/client/src/FlexBuilder.jsx +269 -0
  58. package/client/src/FlexBuilder.scss +226 -0
  59. package/client/src/FlexBuilderControls.jsx +170 -0
  60. package/client/src/FlexBuilderModal.jsx +75 -0
  61. package/client/src/FlexBuilderModal.scss +109 -0
  62. package/client/src/FlexBuilderPreview.jsx +48 -0
  63. package/client/src/FlexBuilderUtils.js +84 -0
  64. package/client/src/FlexDataRenderer.jsx +170 -0
  65. package/client/src/FlexDataRenderer.scss +80 -0
  66. package/client/src/FlexNode.jsx +290 -0
  67. package/client/src/FlexTreeUtils.js +129 -0
  68. package/client/src/HiddenableCell.jsx +46 -0
  69. package/client/src/HiddenableCell.scss +36 -0
  70. package/client/src/KPIDialog.jsx +39 -0
  71. package/client/src/KPIWidget.jsx +139 -0
  72. package/client/src/KanbanCard.jsx +92 -0
  73. package/client/src/KanbanColumn.jsx +29 -0
  74. package/client/src/KanbanConfigModal.jsx +115 -0
  75. package/client/src/KanbanView.jsx +113 -0
  76. package/client/src/KanbanView.scss +107 -0
  77. package/client/src/MessageRotator.jsx +77 -0
  78. package/client/src/MessageRotator.scss +14 -0
  79. package/client/src/ModelCreator.jsx +640 -0
  80. package/client/src/ModelCreator.scss +154 -0
  81. package/client/src/ModelCreatorField.jsx +810 -0
  82. package/client/src/ModelImporter.jsx +120 -0
  83. package/client/src/ModelList.jsx +205 -0
  84. package/client/src/Notification.jsx +137 -0
  85. package/client/src/Notification.scss +126 -0
  86. package/client/src/NotificationProvider.jsx +73 -0
  87. package/client/src/PackGallery.jsx +211 -0
  88. package/client/src/PackGallery.scss +156 -0
  89. package/client/src/Pagination.jsx +141 -0
  90. package/client/src/RTE.jsx +415 -0
  91. package/client/src/RTETrans.jsx +103 -0
  92. package/client/src/RelationField.jsx +247 -0
  93. package/client/src/RelationValue.jsx +230 -0
  94. package/client/src/RestoreConfirmationModal.jsx +183 -0
  95. package/client/src/RestoreDialog.jsx +134 -0
  96. package/client/src/RestoreDialog.scss +67 -0
  97. package/client/src/RichTextEditorModal.jsx +34 -0
  98. package/client/src/RichTextEditorModal.scss +54 -0
  99. package/client/src/TourSpotlight.jsx +234 -0
  100. package/client/src/TourSpotlight.scss +100 -0
  101. package/client/src/TutorialsMenu.jsx +83 -0
  102. package/client/src/TutorialsMenu.scss +217 -0
  103. package/client/src/TutorialsRewardModal.jsx +65 -0
  104. package/client/src/Utils.jsx +78 -0
  105. package/client/src/ViewSwitcher.jsx +54 -0
  106. package/client/src/ViewSwitcher.scss +74 -0
  107. package/client/src/Webpage.jsx +69 -0
  108. package/client/src/_variables.scss +21 -0
  109. package/client/src/assets/react.svg +1 -0
  110. package/client/src/constants.js +68 -0
  111. package/client/src/contexts/AuthContext.jsx +28 -0
  112. package/client/src/contexts/ModelContext.jsx +328 -0
  113. package/client/src/contexts/UIContext.jsx +52 -0
  114. package/client/src/core/data.js +35 -0
  115. package/client/src/entry-client.jsx +15 -0
  116. package/client/src/entry-server.jsx +13 -0
  117. package/client/src/filter.js +222 -0
  118. package/client/src/hooks/data.js +101 -0
  119. package/client/src/hooks/useDebounce.js +20 -0
  120. package/client/src/hooks/useDragAndDrop.js +59 -0
  121. package/client/src/hooks/useLocalStorage.js +100 -0
  122. package/client/src/hooks/useMount.js +42 -0
  123. package/client/src/hooks/useTutorials.jsx +227 -0
  124. package/client/src/hooks/useWindowSize.js +24 -0
  125. package/client/src/i18n.js +47 -0
  126. package/client/src/index.css +90 -0
  127. package/client/src/index.js +10 -0
  128. package/client/src/main.jsx +11 -0
  129. package/client/src/translations.js +15940 -0
  130. package/client/src/tutorials.js +112 -0
  131. package/client/vite.config.js +30 -0
  132. package/eslint.config.js +50 -0
  133. package/package.json +48 -27
  134. package/server.js +9 -0
  135. package/src/constants.js +12 -23
  136. package/src/core.js +9 -8
  137. package/src/data.js +81 -80
  138. package/src/defaultModels.js +114 -115
  139. package/src/email.js +8 -9
  140. package/src/engine.js +5 -5
  141. package/src/events.js +1 -2
  142. package/src/i18n.js +5390 -211
  143. package/src/middlewares/middleware-mongodb.js +94 -93
  144. package/src/migrate.js +24 -24
  145. package/src/modules/assistant.js +55 -55
  146. package/src/modules/bucket.js +10 -9
  147. package/src/modules/data.js +387 -357
  148. package/src/modules/file.js +3 -6
  149. package/src/modules/mongodb.js +6 -7
  150. package/src/modules/user.js +24 -47
  151. package/src/modules/workflow.js +68 -67
  152. package/src/openai.jobs.js +2 -2
  153. package/src/packs.js +30 -31
  154. package/src/providers.js +101 -3
  155. package/src/setenv.js +1 -1
  156. package/src/user.js +0 -17
  157. package/src/workers/crypto-worker.js +21 -20
  158. package/src/workers/import-export-worker.js +18 -18
  159. package/test/data.backup.integration.test.js +7 -12
  160. package/test/data.integration.test.js +27 -25
  161. package/test/globalSetup.js +2 -2
  162. package/test/import_export.integration.test.js +6 -6
  163. package/test/model.integration.test.js +21 -22
  164. package/test/workflow.integration.test.js +2 -5
  165. package/test/workflow.robustness.test.js +6 -13
  166. package/vitest.config.js +2 -2
@@ -0,0 +1,112 @@
1
+ // Fichier : src/tutorials.js
2
+
3
+ export const tutorialsConfig = [
4
+ {
5
+ id: 'contact-management-basics',
6
+ name: 'Gestion des contacts : Les bases',
7
+ description: 'Apprenez les opérations fondamentales : créer et supprimer un contact.',
8
+ icon: 'FaUserPlus',
9
+ stages: [
10
+ {
11
+ stage: 1,
12
+ tourName: 'tour-create-contact', // Nom du tour guidé à lancer
13
+ name: 'Créez votre premier contact',
14
+ description: 'Ajoutez un nouveau contact avec le prénom "Richard".',
15
+ completionCondition: { model: 'contact', limit: 1, filter: { "firstName": "Richard" } }
16
+ },
17
+ {
18
+ stage: 2,
19
+ tourName: 'tour-delete-contact',
20
+ name: 'Effacez vos traces',
21
+ description: 'Maintenant, supprimez le contact "Richard" que vous venez de créer.',
22
+ // La condition pour valider une suppression est de vérifier que le nombre d'éléments correspondants est 0.
23
+ completionCondition: { model: 'contact', limit: 0, filter: { "firstName": "Richard" } }
24
+ }
25
+ ],
26
+ rewards: {
27
+ xpBonus: 150,
28
+ achievement: 'CONTACT_MANAGER_NOVICE',
29
+ notification: { title: 'Gestionnaire de contacts', message: 'Vous maîtrisez les bases de la gestion de contacts !' }
30
+ }
31
+ },
32
+ {
33
+ id: 'advanced-permissions',
34
+ name: 'Permissions & rôles',
35
+ description: 'Maîtrisez la gestion des droits du bout des doigts !',
36
+ icon: 'FaUserShield',
37
+ stages: [
38
+ {
39
+ stage: 1,
40
+ tourName: 'tour-set-permissions',
41
+ name: 'Gestion des droits utilisateurs',
42
+ description: 'Trouvez l\'utilisateur "userTuto" et donnez-lui le droit "visitor".',
43
+ completionCondition: {model: 'user', limit: 1, filter: {"username": "userTuto", "roles": { "$find": {"$eq":["$$this.name","visitor"]}}}}
44
+ },
45
+ {
46
+ stage: 2,
47
+ tourName: 'tour-create-role',
48
+ name: 'Créer un nouveau rôle',
49
+ description: 'Créez un rôle personnalisé nommé "Modérateur".',
50
+ // Condition : un document dans le modèle 'role' avec le nom 'Modérateur' doit exister.
51
+ // (On suppose ici l'existence d'un modèle 'role' pour gérer les rôles).
52
+ completionCondition: { model: 'role', limit: 1, filter: { "name": "moderator" } }
53
+ },
54
+ {
55
+ stage: 3,
56
+ tourName: 'tour-assign-permission-to-role',
57
+ name: 'Ajouter une permission au rôle',
58
+ description: 'Modifiez le rôle "moderator" pour lui ajouter la permission "API_EDIT_DATA_content".',
59
+ // Condition : le rôle 'Modérateur' doit avoir une permission nommée 'delete_contact'.
60
+ // (On suppose que le modèle 'role' a un champ 'permissions' qui est un tableau de relations).
61
+ completionCondition: { model: 'role', limit: 1, filter: { "name": "moderator", "permissions": { "$find": { "$eq": ["$$this.name", "API_EDIT_DATA_content"] } } } }
62
+ },
63
+ {
64
+ stage: 4,
65
+ tourName: 'tour-assign-role-to-user',
66
+ name: 'Promouvoir un utilisateur',
67
+ description: 'Maintenant, assignez votre rôle "moderator" à l\'utilisateur "userTuto".',
68
+ // Condition : l'utilisateur 'userTuto' doit maintenant aussi avoir le rôle 'Modérateur'.
69
+ completionCondition: { model: 'user', limit: 1, filter: { "username": "userTuto", "roles": { "$find": { "$eq": ["$$this.name", "moderator"] } } } }
70
+ }
71
+ ],
72
+ rewards: {
73
+ xpBonus: 500,
74
+ achievement: 'PERMISSION_ARCHITECT',
75
+ notification: { title: 'Architecte des Permissions', message: 'Vous savez maintenant comment finement gérer les accès !' }
76
+ }
77
+ },
78
+ {
79
+ id: 'requests',
80
+ name: 'Suivi d\'Activité',
81
+ description: 'Découvrez les succès liés à l\'activité.',
82
+ icon: 'FaUserShield',
83
+ stages: [
84
+ {
85
+ stage: 1,
86
+ tourName: null, // Pas de tour guidé, l'action peut se faire n'importe où
87
+ name: 'Première requête',
88
+ description: 'Effectuez des actions pour générer 50 requêtes système pour débloquer votre premier succès d\'activité.',
89
+ completionCondition: {model: 'request', limit: 50, filter: {}}
90
+ },
91
+ {
92
+ stage: 2,
93
+ tourName: null,
94
+ name: 'Activité soutenue',
95
+ description: 'Continuez votre activité et atteignez 250 requêtes pour le prochain palier.',
96
+ completionCondition: {model: 'request', limit: 250, filter: {}}
97
+ },
98
+ {
99
+ stage: 3,
100
+ tourName: null,
101
+ name: 'Expert en requêtes',
102
+ description: 'Impressionnant ! Atteignez 1000 requêtes pour prouver votre maîtrise.',
103
+ completionCondition: {model: 'request', limit: 1000, filter: {}}
104
+ }
105
+ ],
106
+ rewards: {
107
+ xpBonus: 1000,
108
+ achievement: 'REQUEST_MASTER',
109
+ notification: { title: 'Maître des Requêtes', message: 'Votre activité sur le réseau est remarquable !' }
110
+ }
111
+ }
112
+ ];
@@ -0,0 +1,30 @@
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react'
3
+
4
+ // https://vite.dev/config/
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ base: "/",
8
+ build: {
9
+ outDir: "dist"
10
+ },
11
+ server : {
12
+ proxy: {
13
+ '/api': {
14
+ target: 'http://localhost:7633',
15
+ secure: false,
16
+ changeOrigin: true,
17
+ // Optionnel mais utile pour le débogage :
18
+ // Affiche les requêtes proxy dans la console de Vite.
19
+ configure: (proxy, options) => {
20
+ proxy.on('proxyReq', (proxyReq, req, res) => {
21
+ console.log(`[Vite Proxy] Forwarding request: ${req.method} ${req.url} -> ${options.target}${proxyReq.path}`);
22
+ });
23
+ }
24
+ }
25
+ }
26
+ },
27
+ fs: {
28
+ allow: ["./src"]
29
+ }
30
+ })
@@ -0,0 +1,50 @@
1
+ // eslint.config.js
2
+ import globals from "globals";
3
+ import js from "@eslint/js";
4
+ // eslint.config.js
5
+ import { defineConfig } from "eslint/config";
6
+
7
+ export default defineConfig([
8
+ {
9
+ // Fichiers sur lesquels appliquer cette configuration
10
+ files: ["**/*.js"],
11
+
12
+ // Ignore les répertoires qui ne doivent pas être analysés
13
+ ignores: [
14
+ "node_modules/",
15
+ "dist/",
16
+ "coverage/",
17
+ "test-backups/"
18
+ ],
19
+
20
+ // Options liées au langage JavaScript
21
+ languageOptions: {
22
+ ecmaVersion: "latest", // Utilise la dernière version de JavaScript
23
+ sourceType: "module", // Votre projet utilise des modules ES
24
+ globals: {
25
+ ...globals.node, // Globaux pour l'environnement Node.js
26
+ ...globals.es2021, // Globaux pour ES2021
27
+ ...globals.vitest // Globaux pour Vitest (describe, it, expect, etc.)
28
+ }
29
+ },
30
+
31
+ // Utilise les règles recommandées par ESLint
32
+ ...js.configs.recommended,
33
+
34
+ // Vos règles personnalisées (à ajuster selon vos préférences)
35
+ rules: {
36
+ // Erreurs potentielles
37
+ "no-console": "off", // Avertit sur l'utilisation de console.log, mais ne bloque pas
38
+ "no-unused-vars": ["warn", { "args": "none" }], // Avertit sur les variables non utilisées
39
+
40
+ // Meilleures pratiques
41
+ "eqeqeq": ["error", "always"], // Impose l'utilisation de === et !==
42
+
43
+ // Style du code
44
+ "indent": ["error", 4], // Impose une indentation de 4 espaces
45
+ "quotes": ["off"], // Impose l'utilisation de guillemets simples
46
+ "semi": ["off"], // Impose l'utilisation de points-virgules à la fin des instructions
47
+ "comma-dangle": ["error"] // Impose une virgule finale sur les objets et tableaux multilignes
48
+ }
49
+ }
50
+ ]);
package/package.json CHANGED
@@ -1,20 +1,32 @@
1
1
  {
2
2
  "name": "data-primals-engine",
3
- "version": "1.0.10",
3
+ "version": "1.1.0",
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",
7
7
  "scripts": {
8
- "test": "cross-env MONGO_DB_URL=\"mongodb://localhost:27017\" PORT=7635 vitest --no-file-parallelism",
9
8
  "preinstall": "npx force-resolutions",
10
- "devserver": "cross-env NODE_ENV=development node server.js",
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",
11
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",
12
21
  "migrate:create": "node src/migrate.js create",
13
22
  "migrate:up": "node src/migrate.js up",
14
23
  "migrate:down": "node src/migrate.js down",
15
24
  "migrate:revert": "node src/migrate.js revert",
16
25
  "migrate:status": "node src/migrate.js status"
17
26
  },
27
+ "optionalDependencies": {
28
+ "@rollup/rollup-linux-x64-gnu": "4.6.1"
29
+ },
18
30
  "resolutions": {
19
31
  "tar-fs": "3.0.9",
20
32
  "on-headers": "1.1.0",
@@ -27,41 +39,49 @@
27
39
  "exports": {
28
40
  ".": "./src/index.js",
29
41
  "./modules/*": "./src/modules/*.js",
42
+ "./client": "./client/index.js",
30
43
  "./*": "./src/*.js"
31
44
  },
45
+ "peerDependencies": {
46
+ "react": ">=18.0.0",
47
+ "react-query": ">=3.0.0"
48
+ },
32
49
  "dependencies": {
33
- "@langchain/core": "^0.3.62",
34
- "@langchain/google-genai": "^0.2.14",
35
- "@langchain/openai": "^0.5.18",
50
+ "@langchain/core": "^0.3.66",
51
+ "@langchain/google-genai": "^0.2.16",
52
+ "@langchain/openai": "^0.6.3",
36
53
  "archiver": "^7.0.1",
37
54
  "aws-sdk": "^2.1692.0",
38
- "bcrypt": "^5.1.1",
39
- "body-parser": "^1.20.3",
55
+ "bcrypt": "^6.0.0",
56
+ "body-parser": "^2.2.0",
40
57
  "chalk": "^5.4.1",
41
58
  "check-disk-space": "^3.4.0",
42
- "compression": "^1.8.0",
59
+ "compression": "^1.8.1",
43
60
  "cookie-parser": "^1.4.7",
44
- "cronstrue": "^3.1.0",
45
- "csv-parse": "^5.6.0",
61
+ "cronstrue": "^3.2.0",
62
+ "csv-parse": "^6.1.0",
63
+ "data-primals-engine": "^1.0.11",
46
64
  "date-fns": "^4.1.0",
47
- "express": "^4.21.2",
48
- "express-csrf-double-submit-cookie": "^1.2.1",
65
+ "express": "^5.1.0",
66
+ "express-csrf-double-submit-cookie": "^2.0.0",
49
67
  "express-formidable": "^1.2.0",
50
68
  "express-mongo-sanitize": "^2.2.0",
51
69
  "express-rate-limit": "^8.0.1",
52
- "express-session": "^1.18.1",
53
- "i18next": "^24.2.2",
54
- "i18next-browser-languagedetector": "^8.0.4",
70
+ "express-session": "^1.18.2",
71
+ "i18next": "^25.3.2",
72
+ "i18next-browser-languagedetector": "^8.2.0",
55
73
  "juice": "^11.0.1",
56
- "mathjs": "^14.4.0",
57
- "mongodb": "^6.12.0",
74
+ "mathjs": "^14.6.0",
75
+ "mongodb": "^6.18.0",
58
76
  "node-cache": "^5.1.2",
59
77
  "node-schedule": "^2.1.1",
60
- "nodemailer": "^6.10.0",
61
- "openai": "^5.8.2",
78
+ "nodemailer": "^7.0.5",
79
+ "prop-types": "^15.8.1",
80
+ "openai": "^5.10.2",
81
+ "process": "^0.11.10",
62
82
  "randomcolor": "^0.6.2",
63
83
  "react-helmet": "^6.1.0",
64
- "react-i18next": "^15.4.1",
84
+ "react-i18next": "^15.6.1",
65
85
  "react-markdown": "^10.1.0",
66
86
  "request-ip": "^3.3.0",
67
87
  "sanitize-html": "^2.17.0",
@@ -69,16 +89,17 @@
69
89
  "swagger-ui-express": "^5.0.1",
70
90
  "tar": "^7.4.3",
71
91
  "uniqid": "^5.4.0",
72
- "vitest": "^3.2.3",
92
+ "vitest": "^3.2.4",
73
93
  "yaml": "^2.8.0"
74
94
  },
75
95
  "devDependencies": {
76
- "@eslint/js": "^9.17.0",
77
- "cross-env": "^7.0.3",
78
- "eslint": "^9.17.0",
79
- "globals": "^15.14.0",
80
- "process": "^0.11.10"
96
+ "@eslint/js": "^9.32.0",
97
+ "concurrently": "^9.2.0",
98
+ "cross-env": "^10.0.0",
99
+ "eslint": "^9.32.0",
100
+ "globals": "^16.3.0"
81
101
  },
102
+ "subPackages": ["client"],
82
103
  "keywords": [
83
104
  "mongodb",
84
105
  "data",
package/server.js CHANGED
@@ -5,6 +5,7 @@
5
5
  //set ES modules to be loaded by the script
6
6
  import process from "node:process";
7
7
  import {Config, Engine, BenchmarkTool, GameObject, Logger} from "./src/index.js";
8
+ import sirv from "sirv";
8
9
 
9
10
  Config.Set("modules", ["mongodb", "data", "file", "bucket", "workflow","user", "assistant", "swagger"])
10
11
  Config.Set("middlewares", []);
@@ -29,4 +30,12 @@ engine.start(port, async (r) => {
29
30
  const logger = engine.getComponent(Logger);
30
31
  console.log("Server started on port" + port);
31
32
  timer.stop();
33
+
34
+ // 2. Use sirv to serve static files from 'client/dist'
35
+ // The 'single: true' option is key for SPAs. It will serve 'index.html'
36
+ // for any route that doesn't match a file, enabling client-side routing.
37
+ engine.use(sirv('client/dist', {
38
+ single: true,
39
+ dev: process.env.NODE_ENV === 'development'
40
+ }));
32
41
  });
package/src/constants.js CHANGED
@@ -14,12 +14,13 @@ export const availableLangs = [
14
14
  "el",
15
15
  "ru",
16
16
  "cs",
17
- "sv",
17
+ "sv"
18
18
  ];
19
19
 
20
+
20
21
  export const awsDefaultConfig = {
21
22
  bucketName : 'bucket-primals',
22
- region: 'eu-north-1',
23
+ region: 'eu-north-1'
23
24
  }
24
25
 
25
26
  export const emailDefaultConfig = {
@@ -70,21 +71,8 @@ export const maxExecutionsByStep = 5;
70
71
  export const maxWorkflowSteps = 15;
71
72
 
72
73
  export const maxPrivateFileSize = 20 * megabytes; // Taille max par fichier privé (20 Mo)
73
- export const maxTotalPrivateFilesSizeFree = 125 * megabytes; // Stockage total pour les comptes gratuits (250 Mo)
74
- export const maxTotalPrivateFilesSizeStandard = 250 * megabytes; // Stockage total pour les comptes standard (250 Mo)
75
- export const maxTotalPrivateFilesSizePremium = 20000 * kilobytes * kilobytes; //
76
-
77
- export const plans = {
78
- free:{
79
- maxModelsPerUser,
80
- maxTotalDataPerUser,
81
- maxDataPerModelPerUser,
82
- requestLimitPerHour: 7200,
83
- },
84
- premium: {
85
- requestLimitPerHour: 250000,
86
- }
87
- }
74
+ export const maxTotalPrivateFilesSize = 250 * megabytes;
75
+
88
76
  //
89
77
  export const optionsSanitizer = {
90
78
  allowedTags: [
@@ -103,9 +91,9 @@ export const optionsSanitizer = {
103
91
  code: ['class'],
104
92
  img: [ 'src', "alt","width","height","style" ]
105
93
  },
106
- // Lots of these won't come up by default because we don't allow them
94
+ // Lots of these won't come up by default because we don't allow them
107
95
  selfClosing: [ 'img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta' ],
108
- // URL schemes we permit
96
+ // URL schemes we permit
109
97
  allowedSchemes: [ 'http', 'https', 'ftp', 'mailto', 'tel' ],
110
98
  allowedSchemesByTag: {},
111
99
  allowedSchemesAppliedToAttributes: [ 'href', 'src', 'cite' ],
@@ -123,14 +111,15 @@ metaModels['i18n'] = { load: ['translation','lang']};
123
111
  metaModels['website'] = { load: ['webpage', 'content', 'taxonomy', 'contact', 'event', 'resource'], 'require': ['i18n'] };
124
112
  metaModels['messaging'] = { load: ['alert','ticket', 'message', 'channel'], 'require': ['i18n'] };
125
113
  metaModels['eshopping'] = { load: [
126
- 'order', 'currency', 'product', 'productVariant', 'discount', 'cart', 'cartItem',
127
- 'brand', 'return', 'review', 'stock', 'returnItem', 'userSubscription',
128
- 'warehouse', 'shipment', 'campaign', 'stockAlert', 'invoice'],
129
- 'require': ['i18n', 'users', 'messaging'] };
114
+ 'order', 'currency', 'product', 'productVariant', 'discount', 'cart', 'cartItem',
115
+ 'brand', 'return', 'review', 'stock', 'returnItem', 'userSubscription',
116
+ 'warehouse', 'shipment', 'campaign', 'stockAlert', 'invoice'],
117
+ 'require': ['i18n', 'users', 'messaging'] };
130
118
  metaModels['workflow'] = { load: ['env', 'workflow', 'workflowRun', 'workflowAction', 'workflowStep', 'workflowTrigger']};
131
119
  metaModels['erp'] = { load: [ 'accountingExercise', 'accountingLineItem', 'accountingEntry', 'employee', 'dashboard', 'kpi'] };
132
120
 
133
121
 
122
+
134
123
  export const allowedFields = ['locked', 'hiddenable', 'anonymized', 'condition', 'color', 'index', 'type', 'required', 'hint', 'default', 'validate', 'unique', 'name', 'placeholder', 'asMain'];
135
124
 
136
125
 
package/src/core.js CHANGED
@@ -136,7 +136,7 @@ export function shuffle(array) {
136
136
  let currentIndex = array.length;
137
137
 
138
138
  // While there remain elements to shuffle...
139
- while (currentIndex != 0) {
139
+ while (currentIndex !== 0) {
140
140
 
141
141
  // Pick a remaining element...
142
142
  let randomIndex = Math.floor(Math.random() * currentIndex);
@@ -164,15 +164,16 @@ export const setSeed = (s)=>{
164
164
  seed = s;
165
165
  }
166
166
  function splitmix32(a) {
167
- a |= 0;
168
- a = a + 0x9e3779b9 | 0;
169
- let t = a ^ a >>> 16;
170
- t = Math.imul(t, 0x21f0aaad);
171
- t = t ^ t >>> 15;
172
- t = Math.imul(t, 0x735a2d97);
173
- return ((t = t ^ t >>> 15) >>> 0) / 4294967296;
167
+ a |= 0;
168
+ a = a + 0x9e3779b9 | 0;
169
+ let t = a ^ a >>> 16;
170
+ t = Math.imul(t, 0x21f0aaad);
171
+ t = t ^ t >>> 15;
172
+ t = Math.imul(t, 0x735a2d97);
173
+ return ((t = t ^ t >>> 15) >>> 0) / 4294967296;
174
174
  }
175
175
 
176
+
176
177
  export const getRand = () =>splitmix32(seed);
177
178
 
178
179
  export const getRandom = (minInclusive,maxInclusive) => {
package/src/data.js CHANGED
@@ -183,39 +183,40 @@ export function getDefaultForType(field) {
183
183
  if(field.default)
184
184
  return typeof(field.default) === 'function' ? field.default() : field.default;
185
185
  switch (field.type) {
186
- case 'string':
187
- case 'string_t':
188
- case 'richtext':
189
- case 'password':
190
- case 'email':
191
- case 'phone':
192
- case 'url':
193
- return '';
194
- case 'model':
195
- return '';
196
- case 'modelField':
197
- return { model: '', field: '' };
198
- case 'color':
199
- return null;
200
- case 'number':
201
- return 0;
202
- case 'date':
203
- case 'datetime':
204
- return null;
205
- case 'boolean':
206
- return false;
207
- case 'file':
208
- return null;
209
- case 'array':
210
- return [];
211
- case 'enum':
212
- return field.required && field.items && field.items.length > 0 ? field.items[0] : null;
213
- case 'object':
214
- return {};
215
- case 'relation':
216
- return field.multiple ? [] : null;
217
- default:
218
- return undefined;
186
+ case 'string':
187
+ case 'string_t':
188
+ case 'richtext':
189
+ case 'password':
190
+ case 'email':
191
+ case 'phone':
192
+ case 'url':
193
+ return '';
194
+ case 'model':
195
+ return '';
196
+ case 'modelField':
197
+ return { model: '', field: '' };
198
+ case 'color':
199
+ return null;
200
+ case 'number':
201
+ return 0;
202
+ case 'date':
203
+ case 'datetime':
204
+ return null;
205
+ case 'boolean':
206
+ return false;
207
+ case 'file':
208
+ return null;
209
+ case 'array':
210
+ return [];
211
+ case 'enum':
212
+ return field.required && field.items && field.items.length > 0 ? field.items[0] : null;
213
+ case 'object':
214
+ return {};
215
+ case 'relation':
216
+ return field.multiple ? [] : null;
217
+ default:
218
+
219
+ return undefined;
219
220
  }
220
221
  }
221
222
 
@@ -319,54 +320,54 @@ function buildApiConditionPayloadRecursive(conditionNode) {
319
320
 
320
321
  // --- Build the specific $expr based on the operator ---
321
322
  switch (exprOperator) {
322
- case '$nin':
323
- const ninValueArray = Array.isArray(value) ? value : String(value).split(',').map(s => s.trim()).filter(Boolean);
324
- // Note: $nin at the top level is often better handled *outside* $expr
325
- // but for consistency with $find, we keep it inside $expr here.
326
- // If segmentsForNesting.length === 0, a standard query { field: { $nin: [...] } } might be more efficient.
327
- exprPayload = { '$not': { '$in': [fieldPathForExpr, ninValueArray] } };
328
- break;
329
- case '$in':
330
- const inValueArray = Array.isArray(value) ? value : String(value).split(',').map(s => s.trim()).filter(Boolean);
331
- // Similar note as $nin regarding top-level efficiency.
332
- exprPayload = { '$in': [fieldPathForExpr, inValueArray] };
333
- break;
334
- case '$regexMatch':
335
- exprPayload = {
336
- '$regexMatch': {
337
- input: fieldPathForExpr,
338
- regex: String(value),
339
- options: 'i'
340
- }
341
- };
342
- break;
343
- case '$exists':
344
- const shouldExist = typeof value === 'boolean' ? value : String(value).toLowerCase() === 'true';
345
- // Using $ne/$eq with $type is a common way to check existence in $expr
346
- exprPayload = {
347
- [shouldExist ? '$ne' : '$eq']: [ { $type: fieldPathForExpr }, "undefined" ]
348
- };
349
- // Note: For top-level, { field: { $exists: true/false } } is standard.
350
- break;
351
- default:
352
- // Standard binary operators ($eq, $ne, $gt, $gte, $lt, $lte)
353
- let processedValue = value;
354
- // Basic type guessing for common string values
355
- if (operator === '$eq' || operator === '$ne') {
356
- if (value === 'true') processedValue = true;
357
- else if (value === 'false') processedValue = false;
358
- else if (value === 'null') processedValue = null;
359
- // Avoid automatic number conversion for eq/ne unless explicitly needed
360
- } else if (['$gt', '$gte', '$lt', '$lte'].includes(operator)) {
361
- // Attempt number conversion for comparison operators
362
- const num = Number(value);
363
- if (!isNaN(num) && String(value).trim() !== '') {
364
- processedValue = num;
365
- }
366
- // TODO: Consider adding date conversion if field type is known
323
+ case '$nin':
324
+ const ninValueArray = Array.isArray(value) ? value : String(value).split(',').map(s => s.trim()).filter(Boolean);
325
+ // Note: $nin at the top level is often better handled *outside* $expr
326
+ // but for consistency with $find, we keep it inside $expr here.
327
+ // If segmentsForNesting.length === 0, a standard query { field: { $nin: [...] } } might be more efficient.
328
+ exprPayload = { '$not': { '$in': [fieldPathForExpr, ninValueArray] } };
329
+ break;
330
+ case '$in':
331
+ const inValueArray = Array.isArray(value) ? value : String(value).split(',').map(s => s.trim()).filter(Boolean);
332
+ // Similar note as $nin regarding top-level efficiency.
333
+ exprPayload = { '$in': [fieldPathForExpr, inValueArray] };
334
+ break;
335
+ case '$regexMatch':
336
+ exprPayload = {
337
+ '$regexMatch': {
338
+ input: fieldPathForExpr,
339
+ regex: String(value),
340
+ options: 'i'
367
341
  }
368
- exprPayload = { [exprOperator]: [fieldPathForExpr, processedValue] };
369
- break;
342
+ };
343
+ break;
344
+ case '$exists':
345
+ const shouldExist = typeof value === 'boolean' ? value : String(value).toLowerCase() === 'true';
346
+ // Using $ne/$eq with $type is a common way to check existence in $expr
347
+ exprPayload = {
348
+ [shouldExist ? '$ne' : '$eq']: [ { $type: fieldPathForExpr }, "undefined" ]
349
+ };
350
+ // Note: For top-level, { field: { $exists: true/false } } is standard.
351
+ break;
352
+ default:
353
+ // Standard binary operators ($eq, $ne, $gt, $gte, $lt, $lte)
354
+ let processedValue = value;
355
+ // Basic type guessing for common string values
356
+ if (operator === '$eq' || operator === '$ne') {
357
+ if (value === 'true') processedValue = true;
358
+ else if (value === 'false') processedValue = false;
359
+ else if (value === 'null') processedValue = null;
360
+ // Avoid automatic number conversion for eq/ne unless explicitly needed
361
+ } else if (['$gt', '$gte', '$lt', '$lte'].includes(operator)) {
362
+ // Attempt number conversion for comparison operators
363
+ const num = Number(value);
364
+ if (!isNaN(num) && String(value).trim() !== '') {
365
+ processedValue = num;
366
+ }
367
+ // TODO: Consider adding date conversion if field type is known
368
+ }
369
+ exprPayload = { [exprOperator]: [fieldPathForExpr, processedValue] };
370
+ break;
370
371
  }
371
372
 
372
373
  // The final payload for the innermost level is the $expr object