data-primals-engine 1.0.11 → 1.1.1

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 (167) hide show
  1. package/README.md +36 -0
  2. package/client/README.md +116 -0
  3. package/client/index.html +31 -0
  4. package/client/index.js +25 -0
  5. package/client/package-lock.json +11664 -0
  6. package/client/package.json +70 -0
  7. package/client/public/demo/26899917-d1ba-4df4-bb33-48d09a8778da.jpg +0 -0
  8. package/client/public/demo/4b9894c7-12cd-466d-8fd3-a2757b09ec96.jpg +0 -0
  9. package/client/public/demo/7ed369ac-a1a2-4b45-b0cd-4fd5bcf5a75a.jpg +0 -0
  10. package/client/public/doc/API.postman_collection.json +214 -0
  11. package/client/public/github.svg +1 -0
  12. package/client/public/profilCompany.jpg +0 -0
  13. package/client/public/profilDeveloper.jpg +0 -0
  14. package/client/public/profilEngineer.jpg +0 -0
  15. package/client/public/profilPersonal.jpg +0 -0
  16. package/client/public/profils .psd +0 -0
  17. package/client/public/react.svg +9 -0
  18. package/client/src/APIInfo.jsx +328 -0
  19. package/client/src/AddWidgetTypeModal.jsx +44 -0
  20. package/client/src/AddWidgetTypeModal.scss +87 -0
  21. package/client/src/App.css +42 -0
  22. package/client/src/App.jsx +588 -0
  23. package/client/src/App.scss +1466 -0
  24. package/client/src/AssistantChat.jsx +280 -0
  25. package/client/src/AssistantChat.scss +229 -0
  26. package/client/src/Button.jsx +12 -0
  27. package/client/src/Button.scss +197 -0
  28. package/client/src/CalculationBuilder.jsx +338 -0
  29. package/client/src/CalculationStepRow.jsx +199 -0
  30. package/client/src/CalendarConfigModal.jsx +49 -0
  31. package/client/src/ChartConfigModal.jsx +402 -0
  32. package/client/src/ConditionBuilder.jsx +622 -0
  33. package/client/src/ConditionBuilder.scss +672 -0
  34. package/client/src/ConditionBuilder2.jsx +757 -0
  35. package/client/src/ContentView.jsx +274 -0
  36. package/client/src/CronBuilder.jsx +126 -0
  37. package/client/src/CronBuilder.scss +128 -0
  38. package/client/src/CronPartBuilder.jsx +150 -0
  39. package/client/src/Dashboard.jsx +210 -0
  40. package/client/src/Dashboard.scss +445 -0
  41. package/client/src/DashboardChart.jsx +362 -0
  42. package/client/src/DashboardFlexViewItem.jsx +129 -0
  43. package/client/src/DashboardView.jsx +554 -0
  44. package/client/src/DataChart.jsx +349 -0
  45. package/client/src/DataEditor.jsx +556 -0
  46. package/client/src/DataLayout.jsx +709 -0
  47. package/client/src/DataTable.jsx +996 -0
  48. package/client/src/DataTable.scss +73 -0
  49. package/client/src/Dialog.jsx +90 -0
  50. package/client/src/Dialog.scss +117 -0
  51. package/client/src/DisplayFlexNodeRenderer.jsx +115 -0
  52. package/client/src/DocumentationPageLayout.jsx +93 -0
  53. package/client/src/DocumentationPageLayout.scss +262 -0
  54. package/client/src/Draggable.jsx +222 -0
  55. package/client/src/Draggable.scss +49 -0
  56. package/client/src/ExportDialog.jsx +172 -0
  57. package/client/src/Field.jsx +1558 -0
  58. package/client/src/FlexBuilder.jsx +269 -0
  59. package/client/src/FlexBuilder.scss +226 -0
  60. package/client/src/FlexBuilderControls.jsx +170 -0
  61. package/client/src/FlexBuilderModal.jsx +75 -0
  62. package/client/src/FlexBuilderModal.scss +109 -0
  63. package/client/src/FlexBuilderPreview.jsx +48 -0
  64. package/client/src/FlexBuilderUtils.js +84 -0
  65. package/client/src/FlexDataRenderer.jsx +170 -0
  66. package/client/src/FlexDataRenderer.scss +80 -0
  67. package/client/src/FlexNode.jsx +290 -0
  68. package/client/src/FlexTreeUtils.js +129 -0
  69. package/client/src/HiddenableCell.jsx +46 -0
  70. package/client/src/HiddenableCell.scss +36 -0
  71. package/client/src/KPIDialog.jsx +39 -0
  72. package/client/src/KPIWidget.jsx +139 -0
  73. package/client/src/KanbanCard.jsx +92 -0
  74. package/client/src/KanbanColumn.jsx +29 -0
  75. package/client/src/KanbanConfigModal.jsx +115 -0
  76. package/client/src/KanbanView.jsx +113 -0
  77. package/client/src/KanbanView.scss +107 -0
  78. package/client/src/MessageRotator.jsx +77 -0
  79. package/client/src/MessageRotator.scss +14 -0
  80. package/client/src/ModelCreator.jsx +640 -0
  81. package/client/src/ModelCreator.scss +154 -0
  82. package/client/src/ModelCreatorField.jsx +810 -0
  83. package/client/src/ModelImporter.jsx +120 -0
  84. package/client/src/ModelList.jsx +205 -0
  85. package/client/src/Notification.jsx +137 -0
  86. package/client/src/Notification.scss +126 -0
  87. package/client/src/NotificationProvider.jsx +73 -0
  88. package/client/src/PackGallery.jsx +211 -0
  89. package/client/src/PackGallery.scss +156 -0
  90. package/client/src/Pagination.jsx +141 -0
  91. package/client/src/RTE.jsx +415 -0
  92. package/client/src/RTETrans.jsx +103 -0
  93. package/client/src/RelationField.jsx +247 -0
  94. package/client/src/RelationValue.jsx +230 -0
  95. package/client/src/RestoreConfirmationModal.jsx +183 -0
  96. package/client/src/RestoreDialog.jsx +134 -0
  97. package/client/src/RestoreDialog.scss +67 -0
  98. package/client/src/RichTextEditorModal.jsx +34 -0
  99. package/client/src/RichTextEditorModal.scss +54 -0
  100. package/client/src/TourSpotlight.jsx +234 -0
  101. package/client/src/TourSpotlight.scss +100 -0
  102. package/client/src/TutorialsMenu.jsx +83 -0
  103. package/client/src/TutorialsMenu.scss +217 -0
  104. package/client/src/TutorialsRewardModal.jsx +65 -0
  105. package/client/src/Utils.jsx +78 -0
  106. package/client/src/ViewSwitcher.jsx +54 -0
  107. package/client/src/ViewSwitcher.scss +74 -0
  108. package/client/src/Webpage.jsx +69 -0
  109. package/client/src/_variables.scss +21 -0
  110. package/client/src/assets/react.svg +1 -0
  111. package/client/src/constants.js +68 -0
  112. package/client/src/contexts/AuthContext.jsx +28 -0
  113. package/client/src/contexts/ModelContext.jsx +328 -0
  114. package/client/src/contexts/UIContext.jsx +52 -0
  115. package/client/src/core/data.js +35 -0
  116. package/client/src/entry-client.jsx +15 -0
  117. package/client/src/entry-server.jsx +13 -0
  118. package/client/src/filter.js +222 -0
  119. package/client/src/hooks/data.js +101 -0
  120. package/client/src/hooks/useDebounce.js +20 -0
  121. package/client/src/hooks/useDragAndDrop.js +59 -0
  122. package/client/src/hooks/useLocalStorage.js +100 -0
  123. package/client/src/hooks/useMount.js +42 -0
  124. package/client/src/hooks/useTutorials.jsx +227 -0
  125. package/client/src/hooks/useWindowSize.js +24 -0
  126. package/client/src/i18n.js +47 -0
  127. package/client/src/index.css +90 -0
  128. package/client/src/index.js +10 -0
  129. package/client/src/main.jsx +11 -0
  130. package/client/src/translations.js +15940 -0
  131. package/client/src/tutorials.js +112 -0
  132. package/client/vite.config.js +30 -0
  133. package/eslint.config.js +50 -0
  134. package/package.json +51 -27
  135. package/server.js +9 -0
  136. package/src/constants.js +12 -23
  137. package/src/core.js +9 -8
  138. package/src/data.js +81 -80
  139. package/src/defaultModels.js +114 -115
  140. package/src/email.js +8 -9
  141. package/src/engine.js +5 -5
  142. package/src/events.js +1 -2
  143. package/src/i18n.js +212 -211
  144. package/src/middlewares/middleware-mongodb.js +94 -93
  145. package/src/migrate.js +24 -24
  146. package/src/modules/assistant.js +55 -55
  147. package/src/modules/bucket.js +10 -9
  148. package/src/modules/data.js +387 -357
  149. package/src/modules/file.js +3 -6
  150. package/src/modules/mongodb.js +6 -7
  151. package/src/modules/user.js +24 -47
  152. package/src/modules/workflow.js +139 -73
  153. package/src/openai.jobs.js +2 -2
  154. package/src/packs.js +30 -31
  155. package/src/providers.js +101 -3
  156. package/src/setenv.js +1 -1
  157. package/src/user.js +0 -17
  158. package/src/workers/crypto-worker.js +21 -20
  159. package/src/workers/import-export-worker.js +18 -18
  160. package/test/data.backup.integration.test.js +7 -12
  161. package/test/data.integration.test.js +27 -25
  162. package/test/globalSetup.js +2 -2
  163. package/test/import_export.integration.test.js +6 -6
  164. package/test/model.integration.test.js +21 -22
  165. package/test/workflow.integration.test.js +2 -5
  166. package/test/workflow.robustness.test.js +6 -13
  167. package/vitest.config.js +2 -2
@@ -4,7 +4,7 @@ import {getCollection} from "../src/modules/mongodb.js";
4
4
 
5
5
  export default async function () {
6
6
 
7
- // --- Configuration initiale ---
7
+ // --- Configuration initiale ---
8
8
  Config.Set("modules", ["mongodb", "data", "file", "bucket", "workflow","user", "assistant"]);
9
9
 
10
10
  console.log('\n--- Global Setup: Initializing engine and database for all tests ---');
@@ -12,4 +12,4 @@ export default async function () {
12
12
 
13
13
  // Initialisez et exportez les collections
14
14
  console.log('--- Global Setup: Complete. Engine is running. ---');
15
- }
15
+ }
@@ -10,7 +10,7 @@ import {
10
10
 
11
11
  import {
12
12
  modelsCollection as getAppModelsCollection,
13
- getCollectionForUser as getAppUserCollection,
13
+ getCollectionForUser as getAppUserCollection
14
14
  } from 'data-primals-engine/modules/mongodb';
15
15
  import {sleep} from "data-primals-engine/core";
16
16
  import fs from "node:fs";
@@ -33,8 +33,8 @@ const impexTestModel = {
33
33
  { name: 'name', type: 'string', required: true },
34
34
  { name: 'sku', type: 'string', unique: true },
35
35
  { name: 'price', type: 'number', required: true },
36
- { name: 'inStock', type: 'boolean', default: true },
37
- ],
36
+ { name: 'inStock', type: 'boolean', default: true }
37
+ ]
38
38
  };
39
39
 
40
40
  // --- Setup de l'environnement de test ---
@@ -62,7 +62,7 @@ describe('Intégration des fonctions d\'Import/Export', () => {
62
62
  // Préparation avant chaque test du bloc
63
63
  beforeEach(async () => {
64
64
  testModelsColInstance = getAppModelsCollection;
65
- testDatasColInstance = getAppUserCollection(mockUser);
65
+ testDatasColInstance = await getAppUserCollection(mockUser);
66
66
 
67
67
  // Nettoyage complet pour un état propre
68
68
  await testDatasColInstance.deleteMany({ _user: "testuserImpex"});
@@ -74,7 +74,7 @@ describe('Intégration des fonctions d\'Import/Export', () => {
74
74
  await insertData(impexTestModel.name, [
75
75
  { name: 'Produit A', sku: 'SKU-A', price: 10.50, inStock: true },
76
76
  { name: 'Produit B', sku: 'SKU-B', price: 25.00, inStock: false },
77
- { name: 'Produit C', sku: 'SKU-C', price: 99.99, inStock: true },
77
+ { name: 'Produit C', sku: 'SKU-C', price: 99.99, inStock: true }
78
78
  ], {}, mockUser, false);
79
79
  });
80
80
 
@@ -82,7 +82,7 @@ describe('Intégration des fonctions d\'Import/Export', () => {
82
82
  it('devrait exporter les données en format JSON', async () => {
83
83
  const res= await exportData({
84
84
  models: [impexTestModel.name],
85
- depth: 1,
85
+ depth: 1
86
86
  }, mockUser);
87
87
 
88
88
  expect(res.success).toBeTruthy();
@@ -38,7 +38,7 @@ async function setupTestContext() {
38
38
  {name: 'relatedName', type: 'string', required: true, unique: true},
39
39
  {name: 'relatedValue', type: 'number'}
40
40
  ],
41
- maxRequestData: 10,
41
+ maxRequestData: 10
42
42
  };
43
43
 
44
44
  const comprehensiveTestModelDefinition = {
@@ -90,9 +90,9 @@ async function setupTestContext() {
90
90
  {name: 'objectField', type: 'object'},
91
91
  // Model & ModelField (validation of string format, not existence)
92
92
  {name: 'modelNameField', type: 'model'},
93
- {name: 'modelFieldNameField', type: 'modelField'}, // Note: modelField type expects an object {model: 'modelName', field: 'fieldName'}
93
+ {name: 'modelFieldNameField', type: 'modelField'} // Note: modelField type expects an object {model: 'modelName', field: 'fieldName'}
94
94
  ],
95
- maxRequestData: 50,
95
+ maxRequestData: 50
96
96
  };
97
97
 
98
98
  // Insérer les modèles en base
@@ -108,7 +108,7 @@ async function setupTestContext() {
108
108
  return {
109
109
  currentTestUser,
110
110
  comprehensiveTestModelDefinition,
111
- relatedModelDefinition,
111
+ relatedModelDefinition
112
112
  };
113
113
  }
114
114
 
@@ -127,22 +127,21 @@ describe('CRUD on model definitions and integrity tests', () => {
127
127
  it('should create and drop index when field.index is toggled (premium user)', async () => {
128
128
  // --- SETUP ---
129
129
  const { currentTestUser, comprehensiveTestModelDefinition } = await setupTestContext();
130
- const premiumUser = { ...currentTestUser, userPlan: 'premium' };
131
- const dataCollection = getCollectionForUser(premiumUser);
130
+ const dataCollection = await getCollectionForUser(currentTestUser);
132
131
  const fieldToIndex = 'stringUnique'; // Utiliser un champ qui existe vraiment dans le modèle
133
132
 
133
+ // --- FIX: Ensure the collection exists before any operation ---
134
+ // By inserting and deleting a dummy document, we force MongoDB to create the
135
+ // collection and its default indexes. This prevents the "ns does not exist"
136
+ // error in asynchronous listeners (like workflow triggers).
137
+ const dummyDoc = await dataCollection.insertOne({ _model: 'dummy', _user: currentTestUser.username });
138
+ await dataCollection.deleteOne({ _id: dummyDoc.insertedId });
139
+
140
+
134
141
  // --- VERIFICATION INITIALE ---
135
142
  // S'assurer qu'aucun index n'existe au départ.
136
- // On enveloppe l'appel dans un try/catch pour gérer le cas où la collection n'existe pas.
137
- let initialIndexes = [];
138
- try {
139
- initialIndexes = await dataCollection.indexes();
140
- } catch (e) {
141
- // C'est normal si la collection n'existe pas encore. On considère qu'il n'y a pas d'index.
142
- if (e.codeName !== 'NamespaceNotFound') {
143
- throw e; // Relancer les autres erreurs inattendues
144
- }
145
- }
143
+ // Cet appel ne plantera plus car la collection est maintenant créée.
144
+ const initialIndexes = await dataCollection.indexes();
146
145
  expect(initialIndexes.some(i => i.key[fieldToIndex] === 1)).toBe(false);
147
146
 
148
147
  // --- ACTION 1 : AJOUTER UN INDEX ---
@@ -150,9 +149,9 @@ describe('CRUD on model definitions and integrity tests', () => {
150
149
  ...comprehensiveTestModelDefinition,
151
150
  fields: comprehensiveTestModelDefinition.fields.map(f =>
152
151
  f.name === fieldToIndex ? { ...f, index: true } : f
153
- ),
152
+ )
154
153
  };
155
- await editModel(premiumUser, testModelId, modelWithIndex);
154
+ await editModel(currentTestUser, testModelId, modelWithIndex);
156
155
 
157
156
  // --- VERIFICATION 1 ---
158
157
  // Maintenant, la collection et l'index doivent exister.
@@ -163,7 +162,7 @@ describe('CRUD on model definitions and integrity tests', () => {
163
162
  // Le filtre partiel est crucial pour que l'index ne s'applique qu'aux bonnes données
164
163
  expect(newIndex.partialFilterExpression).toEqual({
165
164
  _model: comprehensiveTestModelDefinition.name,
166
- _user: premiumUser.username,
165
+ _user: currentTestUser.username
167
166
  });
168
167
 
169
168
  // --- ACTION 2 : SUPPRIMER L'INDEX ---
@@ -171,14 +170,14 @@ describe('CRUD on model definitions and integrity tests', () => {
171
170
  ...comprehensiveTestModelDefinition,
172
171
  fields: comprehensiveTestModelDefinition.fields.map(f =>
173
172
  f.name === fieldToIndex ? { ...f, index: false } : f
174
- ),
173
+ )
175
174
  };
176
- await editModel(premiumUser, testModelId, modelWithoutIndex);
175
+ await editModel(currentTestUser, testModelId, modelWithoutIndex);
177
176
 
178
177
  // --- VERIFICATION 2 ---
179
178
  const indexesAfterDeletion = await dataCollection.indexes();
180
179
  expect(indexesAfterDeletion.some(i => i.key[fieldToIndex] === 1)).toBe(false);
181
- }, 20000); // Augmenter le timeout si nécessaire pour les opérations d'index
180
+ }, 20000);
182
181
 
183
182
  it('should not save extra, non-defined fields in the model definition', async () => {
184
183
  const { currentTestUser, comprehensiveTestModelDefinition, relatedModelDefinition } = await setupTestContext();
@@ -33,7 +33,7 @@ const targetDataModel = {
33
33
  { name: 'projectName', type: 'string', required: true },
34
34
  { name: 'status', type: 'string', required: true }, // ex: 'new', 'active', 'archived'
35
35
  { name: 'budget', type: 'number' }
36
- ],
36
+ ]
37
37
  };
38
38
 
39
39
  // Les modèles qui définissent le système de workflow lui-même.
@@ -130,9 +130,6 @@ const workflowMetaModels = [
130
130
 
131
131
  let testModelsColInstance;
132
132
  let testDatasColInstance;
133
- let engineInstance;
134
-
135
- const port = process.env.PORT || getUniquePort(); // Port différent
136
133
 
137
134
  // On "espionne" `c` pour vérifier qu'elle est appelée sans l'exécuter réellement.
138
135
  // Cela nous permet de tester uniquement la logique de déclenchement.
@@ -140,7 +137,7 @@ const processWorkflowRunSpy = vi.spyOn(workflowModule, 'processWorkflowRun');
140
137
 
141
138
  beforeEach(async () => {
142
139
  testModelsColInstance = getAppModelsCollection;
143
- testDatasColInstance = getCollectionForUser(mockUser);
140
+ testDatasColInstance = await getCollectionForUser(mockUser);
144
141
  // Nettoyer les données avant chaque test
145
142
  await testDatasColInstance.deleteMany({_user: "testuserWorkflow"});
146
143
 
@@ -1,18 +1,11 @@
1
1
  import { ObjectId } from 'mongodb';
2
- import { expect, describe, it, beforeEach, afterAll, beforeAll, vi } from 'vitest';
2
+ import { expect, describe, it, beforeEach, beforeAll, vi } from 'vitest';
3
3
  import { Config } from "data-primals-engine/config";
4
-
5
- // --- Configuration initiale (similaire à workflow.integration.test.js) ---
6
- let mongod;
7
- let testDbUri;
8
- const testDbName = 'testRobustnessDbHO_Workflow';
9
-
10
4
  // --- Importations des modules de l'application ---
11
- import { Engine } from "data-primals-engine/engine";
12
5
  import { insertData, editData } from 'data-primals-engine/modules/data';
13
6
  import { modelsCollection as getAppModelsCollection, getCollectionForUser, getCollection } from 'data-primals-engine/modules/mongodb';
14
7
  import * as workflowModule from 'data-primals-engine/modules/workflow';
15
- import {getUniquePort, initEngine} from "../src/setenv.js";
8
+ import {initEngine} from "../src/setenv.js";
16
9
  import {maxExecutionsByStep} from "data-primals-engine/constants";
17
10
 
18
11
  vi.mock('data-primals-engine/modules/workflow', { spy: true })
@@ -44,7 +37,7 @@ beforeAll(async () =>{
44
37
 
45
38
  beforeEach(async () => {
46
39
  testModelsColInstance = getAppModelsCollection;
47
- testDatasColInstance = getCollectionForUser(mockUser);
40
+ testDatasColInstance = await getCollectionForUser(mockUser);
48
41
  await testDatasColInstance.deleteMany({ _user: mockUser.username });
49
42
  await getCollection('job_locks').deleteMany({}); // Nettoyer les verrous
50
43
  const mods = await testModelsColInstance.find({ $and: [{_user: mockUser.username}, {$or: [{name: targetDataModel.name}, ...workflowMetaModels.map(m =>({name: m.name}))] }]}).toArray();
@@ -71,7 +64,7 @@ describe('Tests de robustesse et des cas limites du module Workflow', () => {
71
64
  const now = new Date();
72
65
  await jobsCollection.insertOne({
73
66
  jobId: jobId,
74
- lockedUntil: new Date(now.getTime() + 10 * 60 * 1000), // Verrouillé pour 10 min
67
+ lockedUntil: new Date(now.getTime() + 10 * 60 * 1000) // Verrouillé pour 10 min
75
68
  });
76
69
 
77
70
  // 2. Act: Tenter de lancer le job
@@ -89,7 +82,7 @@ describe('Tests de robustesse et des cas limites du module Workflow', () => {
89
82
  // 1. Arrange: Insérer un verrou qui a déjà expiré (simule un crash)
90
83
  await jobsCollection.insertOne({
91
84
  jobId: jobId,
92
- lockedUntil: new Date(Date.now() - 1000), // Expiré depuis 1 seconde
85
+ lockedUntil: new Date(Date.now() - 1000) // Expiré depuis 1 seconde
93
86
  });
94
87
 
95
88
  // 2. Act: Lancer le job
@@ -155,7 +148,7 @@ describe('Tests de robustesse et des cas limites du module Workflow', () => {
155
148
  // Cette condition est conçue pour échouer car la donnée n'existera pas
156
149
  conditions: { status: 'must-be-this-to-succeed' },
157
150
  onSuccessStep: successStep.toString(),
158
- onFailureStep: failureStep.toString(),
151
+ onFailureStep: failureStep.toString()
159
152
  };
160
153
  const startStep = (await insertData('workflowStep', startStepDef, {}, mockUser)).insertedIds[0];
161
154
  const workflow = (await insertData('workflow', { name: 'Failure Path Workflow', startStep: startStep.toString() }, {}, mockUser)).insertedIds[0];
package/vitest.config.js CHANGED
@@ -11,6 +11,6 @@ export default defineConfig({
11
11
  testTimeout: 25000, // 20 seconds
12
12
 
13
13
  // Tell Vitest where to find your global setup and teardown files
14
- globalTeardown: './test/globalTeardown.js',
15
- },
14
+ globalTeardown: './test/globalTeardown.js'
15
+ }
16
16
  });