data-primals-engine 1.2.3 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CONTRIBUTING.md +91 -0
  2. package/README.md +33 -17
  3. package/client/src/App.jsx +0 -5
  4. package/client/src/ConditionBuilder.scss +34 -1
  5. package/client/src/ConditionBuilder2.jsx +179 -53
  6. package/client/src/ContentView.jsx +0 -3
  7. package/client/src/CronBuilder.jsx +0 -1
  8. package/client/src/CronPartBuilder.jsx +0 -2
  9. package/client/src/DashboardView.jsx +0 -5
  10. package/client/src/DataEditor.jsx +8 -10
  11. package/client/src/DataLayout.jsx +0 -1
  12. package/client/src/DataTable.jsx +1 -3
  13. package/client/src/Field.jsx +0 -5
  14. package/client/src/FlexBuilder.jsx +1 -1
  15. package/client/src/ModelCreatorField.jsx +1 -5
  16. package/client/src/RTE.jsx +1 -6
  17. package/client/src/RTETrans.jsx +0 -2
  18. package/client/src/RelationField.jsx +1 -1
  19. package/client/src/RelationValue.jsx +1 -2
  20. package/client/src/TourSpotlight.jsx +0 -2
  21. package/client/src/filter.js +87 -0
  22. package/client/src/hooks/data.js +1 -3
  23. package/client/src/hooks/useTutorials.jsx +0 -1
  24. package/package.json +3 -3
  25. package/server.js +2 -2
  26. package/src/email.js +2 -2
  27. package/src/engine.js +59 -20
  28. package/src/index.js +1 -1
  29. package/src/middlewares/middleware-mongodb.js +0 -1
  30. package/src/modules/assistant.js +1 -3
  31. package/src/modules/bucket.js +3 -4
  32. package/src/modules/{data.js → data/data.js} +34 -51
  33. package/src/modules/data/index.js +1 -0
  34. package/src/modules/file.js +1 -1
  35. package/src/modules/mongodb.js +0 -1
  36. package/src/modules/user.js +1 -1
  37. package/src/modules/workflow.js +38 -38
  38. package/src/packs.js +4 -1
  39. package/test/data.backup.integration.test.js +4 -5
  40. package/test/data.integration.test.js +2 -6
  41. package/test/events.test.js +1 -1
  42. package/test/file.test.js +1 -4
  43. package/test/import_export.integration.test.js +20 -13
  44. package/test/model.integration.test.js +8 -10
  45. package/test/user.test.js +2 -2
  46. package/test/vm.test.js +1 -1
  47. package/test/workflow.integration.test.js +17 -14
  48. package/test/workflow.robustness.test.js +15 -10
  49. package/src/modules/test +0 -147
@@ -1,4 +1,4 @@
1
- import {Logger} from "../gameObject.js";
1
+ import {Logger} from "../../gameObject.js";
2
2
  import {BSON, ObjectId} from "mongodb";
3
3
  import * as util from 'node:util';
4
4
  import {promisify} from 'node:util';
@@ -9,9 +9,9 @@ import * as tar from "tar";
9
9
  import process from "node:process";
10
10
  import {randomColor} from "randomcolor";
11
11
  import cronstrue from 'cronstrue/i18n.js';
12
- import {setTimeoutMiddleware} from '../middlewares/timeout.js';
12
+ import {setTimeoutMiddleware} from '../../middlewares/timeout.js';
13
13
  import {mkdir} from 'node:fs/promises';
14
- import {anonymizeText, getDefaultForType, getFieldValueHash, getUserId, isDemoUser, isLocalUser} from "../data.js";
14
+ import {anonymizeText, getDefaultForType, getFieldValueHash, getUserId, isDemoUser, isLocalUser} from "../../data.js";
15
15
  import {
16
16
  allowedFields,
17
17
  dbName,
@@ -36,7 +36,7 @@ import {
36
36
  optionsSanitizer,
37
37
  searchRequestTimeout,
38
38
  storageSafetyMargin
39
- } from "../constants.js";
39
+ } from "../../constants.js";
40
40
  import {
41
41
  getCollection,
42
42
  getCollectionForUser,
@@ -44,43 +44,43 @@ import {
44
44
  isObjectId,
45
45
  modelsCollection,
46
46
  packsCollection
47
- } from "./mongodb.js";
48
- import {dbUrl, MongoClient, MongoDatabase} from "../engine.js";
47
+ } from "../mongodb.js";
48
+ import {dbUrl, MongoClient, MongoDatabase} from "../../engine.js";
49
49
  import path from "node:path";
50
- import {getFileExtension, getObjectHash, getRandom, isGUID, isPlainObject, randomDate, sleep, uuidv4} from "../core.js";
51
- import {Event} from "../events.js";
50
+ import {getFileExtension, getObjectHash, getRandom, isGUID, isPlainObject, randomDate, sleep, uuidv4} from "../../core.js";
51
+ import {Event} from "../../events.js";
52
52
  import fs from "node:fs";
53
53
  import schedule from "node-schedule";
54
- import {middleware} from "../middlewares/middleware-mongodb.js";
55
- import i18n from "../i18n.js";
54
+ import {middleware} from "../../middlewares/middleware-mongodb.js";
55
+ import i18n from "../../i18n.js";
56
56
  import {
57
57
  executeSafeJavascript, processWorkflowRun,
58
58
  runScheduledJobWithDbLock,
59
59
  scheduleWorkflowTriggers,
60
60
  triggerWorkflows
61
- } from "./workflow.js";
61
+ } from "../workflow.js";
62
62
  import NodeCache from "node-cache";
63
63
  import AWS from 'aws-sdk';
64
- import {openaiJobModel} from "../openai.jobs.js";
64
+ import {openaiJobModel} from "../../openai.jobs.js";
65
65
  import checkDiskSpace from "check-disk-space";
66
66
  import {fileURLToPath} from 'url';
67
67
  import {Worker} from 'worker_threads';
68
- import {addFile, encryptFile, removeFile} from "./file.js";
69
- import {downloadFromS3, getS3Stream, getUserS3Config, listS3Backups, uploadToS3} from "./bucket.js";
68
+ import {addFile, encryptFile, removeFile} from "../file.js";
69
+ import {downloadFromS3, getS3Stream, getUserS3Config, listS3Backups, uploadToS3} from "../bucket.js";
70
70
  import {
71
71
  calculateTotalUserStorageUsage,
72
72
  generateLimiter,
73
73
  hasPermission,
74
74
  middlewareAuthenticator,
75
75
  userInitiator
76
- } from "./user.js";
77
- import {assistantGlobalLimiter} from "./assistant.js";
78
- import {getAllPacks} from "../packs.js";
79
- import {throttleMiddleware} from "../middlewares/throttle.js";
80
- import {Config} from "../config.js";
81
- import {profiles} from "../../client/src/constants.js";
82
- import {processFilterPlaceholders} from "../../client/src/filter.js";
83
- import {tutorialsConfig} from "../../client/src/tutorials.js";
76
+ } from "../user.js";
77
+ import {assistantGlobalLimiter} from "../assistant.js";
78
+ import {getAllPacks} from "../../packs.js";
79
+ import {throttleMiddleware} from "../../middlewares/throttle.js";
80
+ import {Config} from "../../config.js";
81
+ import {profiles} from "../../../client/src/constants.js";
82
+ import {processFilterPlaceholders} from "../../../client/src/filter.js";
83
+ import {tutorialsConfig} from "../../../client/src/tutorials.js";
84
84
 
85
85
  // Obtenir le chemin du répertoire courant de manière fiable avec ES Modules
86
86
  const __filename = fileURLToPath(import.meta.url);
@@ -202,7 +202,6 @@ export const dataTypes = {
202
202
  },
203
203
  code: {
204
204
  validate: (value, field) => {
205
- console.log(field,typeof(value));
206
205
  return value === null || (field.language === 'json' && typeof(value) === 'object') || (typeof value === 'string' && (field.maxlength === undefined || field.maxlength <= 0 || value.length <= field.maxlength));
207
206
  },
208
207
  filter: async (value, field) => {
@@ -536,7 +535,7 @@ export const getAPILang = (langs) => {
536
535
  */
537
536
  function runImportExportWorker(action, payload) {
538
537
  return new Promise((resolve, reject) => {
539
- const workerPath = path.resolve(__dirname, '../workers/import-export-worker.js');
538
+ const workerPath = path.resolve(process.cwd(), './src/workers/import-export-worker.js');
540
539
  const worker = new Worker(workerPath);
541
540
 
542
541
  worker.postMessage({ action, payload });
@@ -571,7 +570,7 @@ function runImportExportWorker(action, payload) {
571
570
  */
572
571
  function runCryptoWorkerTask(action, payload) {
573
572
  return new Promise((resolve, reject) => {
574
- const workerPath = path.resolve(__dirname, '../workers/crypto-worker.js');
573
+ const workerPath = path.resolve(process.cwd(), './src/workers/crypto-worker.js');
575
574
  const worker = new Worker(workerPath);
576
575
 
577
576
  worker.postMessage({ action, payload });
@@ -1296,7 +1295,7 @@ export async function onInit(defaultEngine) {
1296
1295
  "$rand",
1297
1296
  "$abs", '$sin', '$cos', '$tan', '$asin', '$acos', '$atan',
1298
1297
  "$toDate", "$toBool", "$toString", "$toInt", "$toDouble",
1299
- "$dateSubtract", "$dateAdd", "$dateToString",
1298
+ "$dateDiff", "$dateSubtract", "$dateAdd", "$dateToString",
1300
1299
  '$year', '$month', '$week', '$dayOfMonth', '$dayOfWeek', '$dayOfYear', '$hour', '$minute', '$second', '$millisecond'
1301
1300
  ]}));
1302
1301
 
@@ -2014,7 +2013,6 @@ export async function onInit(defaultEngine) {
2014
2013
  .limit(maxModelsPerUser).toArray());
2015
2014
  res.json(models);
2016
2015
  } catch (error) {
2017
- console.log(error);
2018
2016
  logger.error(error);
2019
2017
  res.status(500).json({ success: false, error: error.message });
2020
2018
  }
@@ -2340,15 +2338,6 @@ export async function onInit(defaultEngine) {
2340
2338
  res.json({ success: true, value: resultValue, totalCount: totalCount });
2341
2339
 
2342
2340
  } catch (error) { // <--- CATCH PRINCIPAL
2343
- // --- Log de l'erreur BRUTE interceptée ---
2344
- console.log('--- CATCH PRINCIPAL - RAW ERROR OBJECT ---');
2345
- console.log('Type:', typeof error);
2346
- console.log('Instance of Error:', error instanceof Error);
2347
- console.log('Error Object:', error); // Affiche la structure brute
2348
- console.log('Error Message:', error?.message);
2349
- console.log('Error Stack:', error?.stack);
2350
- console.log('--- END CATCH PRINCIPAL ---');
2351
- // --- Fin Log ---
2352
2341
 
2353
2342
  // Tentative de log via le logger standard (qui peut encore échouer si l'erreur est vraiment étrange)
2354
2343
  try {
@@ -3244,7 +3233,8 @@ async function processDocuments(datas, model, collection, me) {
3244
3233
  const idMap = new Map();
3245
3234
  const allInsertedIds = [];
3246
3235
 
3247
- for (const doc of datas) {
3236
+ const realData = Event.Trigger("OnDataInsert", "event", "system", datas) || datas;
3237
+ for (const doc of realData) {
3248
3238
  try {
3249
3239
  const newDocId = await insertAndResolveRelations(doc, model, collection, me, idMap);
3250
3240
  if (newDocId) {
@@ -3445,10 +3435,12 @@ async function applyFieldFilters(docToProcess, model) {
3445
3435
  for (const field of model.fields) {
3446
3436
  docToProcess[field.name] = typeof(docToProcess[field.name]) === 'undefined' || docToProcess[field.name] === null ? field.default:docToProcess[field.name];
3447
3437
  if (dataTypes[field.type]?.filter) {
3448
- docToProcess[field.name] = await dataTypes[field.type].filter(
3438
+ const filter = await dataTypes[field.type].filter(
3449
3439
  docToProcess[field.name],
3450
3440
  field
3451
3441
  );
3442
+ const realFilter = Event.Trigger('OnDataFilter', "event", "system",filter, field, docToProcess );
3443
+ docToProcess[field.name] = realFilter || filter;
3452
3444
  }
3453
3445
  }
3454
3446
  }
@@ -3478,7 +3470,9 @@ function validateModelData(doc, model, isPatch = false) {
3478
3470
  if (!fieldDef) continue; // On ignore les champs supplémentaires
3479
3471
 
3480
3472
  const validator = dataTypes[fieldDef.type]?.validate;
3481
- if (validator && !validator(value, fieldDef)) {
3473
+ const valid = validator && validator(value, fieldDef);
3474
+ const realValidation = Event.Trigger('OnDataValidate', "event", "system", value, fieldDef,doc );
3475
+ if (!(valid || realValidation)) {
3482
3476
  throw new Error(i18n.t('api.field.validationFailed', { field: fieldName, value }));
3483
3477
  }
3484
3478
  }
@@ -3694,8 +3688,6 @@ export const editData = async (modelName, filter, data, files, user, triggerWork
3694
3688
  return await internalEditOrPatchData(modelName, filter, data, files, user, false, triggerWorkflow, waitForWorkflow);
3695
3689
  };
3696
3690
 
3697
- // Dans src/modules/data.js
3698
-
3699
3691
  const internalEditOrPatchData = async (modelName, filter, data, files, user, isPatch, triggerWorkflow = true, waitForWorkflow = false) => {
3700
3692
  try {
3701
3693
  // 1. Vérification des permissions
@@ -3949,7 +3941,6 @@ export const deleteData = async (modelName, filter, user ={}, triggerWorkflow, w
3949
3941
 
3950
3942
  }
3951
3943
 
3952
- console.log(util.inspect(findFilter, false, 8, true));
3953
3944
  // 2. Récupérer les documents à supprimer pour vérifier leur type et annuler les schedules
3954
3945
  const documentsToDelete = await collection.aggregate([{ $match: { $expr: { "$and": findFilter } } }]).toArray();
3955
3946
 
@@ -4130,8 +4121,6 @@ export const deleteData = async (modelName, filter, user ={}, triggerWorkflow, w
4130
4121
  }
4131
4122
  }
4132
4123
 
4133
- // ... (le reste du fichier data.js)
4134
-
4135
4124
  export const searchData = async (query, user) => {
4136
4125
  const { page, limit, sort, model, ids, timeout, pack } = query; // Les filtres de la requête (attention aux injections MongoDB !)
4137
4126
 
@@ -4555,7 +4544,6 @@ export const searchData = async (query, user) => {
4555
4544
  } else if (fi.type === 'array') {
4556
4545
  // Handle array filtering here
4557
4546
  if (data[fi.name]) {
4558
- console.log('array filtering', data[fi.name]);
4559
4547
  pipelines.push({
4560
4548
  $match: {
4561
4549
  $expr: {
@@ -4591,7 +4579,6 @@ export const searchData = async (query, user) => {
4591
4579
 
4592
4580
  let pipelines = [];
4593
4581
  if( allIds.length ){
4594
- console.log({allIds});
4595
4582
  const id = {$in: ["$_id", allIds.map(m => new ObjectId(m))]};
4596
4583
  pipelines.push({
4597
4584
  $match: { $expr: id }
@@ -4617,7 +4604,7 @@ export const searchData = async (query, user) => {
4617
4604
  pipelines.push({$project: {_model: 0}});
4618
4605
  }
4619
4606
 
4620
- console.log(util.inspect(pipelines, false, 29, true));
4607
+ //console.log(util.inspect(pipelines, false, 29, true));
4621
4608
 
4622
4609
  // 4. Exécuter la pipeline
4623
4610
  const ts = parseInt(timeout, 10)/2.0 || searchRequestTimeout;
@@ -5787,7 +5774,6 @@ export async function installPack(packId, user, lang) {
5787
5774
  if (documents.length === 0) continue;
5788
5775
 
5789
5776
  const docsToInsert = [];
5790
- console.log(modelName, user);
5791
5777
 
5792
5778
  const modelDefForHash = await getModel(modelName, user);
5793
5779
 
@@ -5921,10 +5907,7 @@ export async function installPack(packId, user, lang) {
5921
5907
 
5922
5908
 
5923
5909
  export const installAllPacks = async () => {
5924
-
5925
5910
  const packs = await getAllPacks();
5926
-
5927
- console.log(util.inspect(packs, false, 20, true));
5928
5911
  await packsCollection.deleteMany({ _user: { $exists : false }});
5929
5912
  await packsCollection.insertMany(packs);
5930
5913
  }
@@ -0,0 +1 @@
1
+ export * from './data.js';
@@ -8,7 +8,7 @@ import {getFileExtension, isGUID, uuidv4} from "../core.js";
8
8
  import path from "node:path";
9
9
  import process from "node:process";
10
10
  import fs from "node:fs";
11
- import { checkServerCapacity} from "./data.js";
11
+ import { checkServerCapacity} from "./data/index.js";
12
12
  import crypto from "node:crypto";
13
13
  import * as tar from "tar";
14
14
  import {promisify} from "node:util";
@@ -2,7 +2,6 @@
2
2
  import process from "process";
3
3
  import {Logger} from "../gameObject.js";
4
4
  import {MongoDatabase} from "../engine.js";
5
- import fs from "node:fs";
6
5
 
7
6
  export let modelsCollection, datasCollection, filesCollection, packsCollection;
8
7
 
@@ -3,7 +3,7 @@ import {MongoDatabase} from "../engine.js";
3
3
  import {getCollection, getCollectionForUser, getUserCollectionName} from "./mongodb.js";
4
4
  import {isLocalUser} from "../data.js";
5
5
  import {ObjectId} from "mongodb";
6
- import {getAPILang} from "./data.js";
6
+ import {getAPILang} from "./data/index.js";
7
7
  import {Logger} from "../gameObject.js";
8
8
  import rateLimit from "express-rate-limit";
9
9
 
@@ -1,4 +1,3 @@
1
- // Exemple conceptuel dans la fonction de planification
2
1
  import {getCollection, getCollectionForUser, isObjectId} from "./mongodb.js";
3
2
  import schedule from "node-schedule";
4
3
  import {ObjectId} from "mongodb";
@@ -7,16 +6,16 @@ import crypto from "node:crypto";
7
6
  import ivm from 'isolated-vm';
8
7
 
9
8
  import {Logger} from "../gameObject.js";
10
- import {deleteData, insertData, patchData, searchData} from "./data.js";
11
- import {emailDefaultConfig, maxExecutionsByStep, maxWorkflowSteps, timeoutVM} from "../constants.js";
9
+ import {deleteData, insertData, patchData, searchData} from "./data/index.js";
10
+ import {emailDefaultConfig, maxExecutionsByStep, maxWorkflowSteps} from "../constants.js";
12
11
  import {ChatOpenAI} from "@langchain/openai";
13
12
  import {ChatGoogleGenerativeAI} from "@langchain/google-genai";
14
13
  import {ChatPromptTemplate} from "@langchain/core/prompts";
14
+ import { ChatDeepSeek } from "@langchain/deepseek";
15
15
  import i18n from "../../src/i18n.js";
16
16
  import {sendEmail} from "../email.js";
17
17
 
18
18
  import * as workflowModule from './workflow.js';
19
- import {isConditionMet} from "../filter.js";
20
19
  import util from "node:util";
21
20
 
22
21
  let logger = null;
@@ -1174,7 +1173,6 @@ export async function triggerWorkflows(triggerData, user, eventType) {
1174
1173
 
1175
1174
 
1176
1175
  console.debug(`[Workflow Trigger] Vérification dataFilter pour trigger ${trigger._id} avec filtre combiné:`, JSON.stringify(finalFilter));
1177
- console.log({triggerData, finalFilter});
1178
1176
  const match = await searchData({ model: triggerData._model, filter: finalFilter, limit: 1 }, user);
1179
1177
  if (!match.count) {
1180
1178
  console.debug(`[Workflow Trigger] Trigger ${trigger._id}: dataFilter non satisfait par la donnée ${dataId}. WorkflowRun non créé.`);
@@ -1358,7 +1356,6 @@ export async function processWorkflowRun(workflowRunId, user) {
1358
1356
  if (!isObjectId(actionId)) continue;
1359
1357
  const actionDef = await dbCollection.findOne({ _id: new ObjectId(actionId), _model: 'workflowAction' });
1360
1358
  if (!actionDef) return await logError(`Action definition ${actionId} not found.`);
1361
- console.log({actionDef});
1362
1359
  const actionResult = await workflowModule.executeStepAction(actionDef, contextData, user, dbCollection);
1363
1360
 
1364
1361
  if (actionResult.status === 'paused') {
@@ -1403,7 +1400,7 @@ export async function processWorkflowRun(workflowRunId, user) {
1403
1400
  if (actionResult.updatedContext) {
1404
1401
  contextData = { ...contextData, ...actionResult.updatedContext };
1405
1402
  }
1406
- console.log("action", util.inspect(actionResult, false, 8, true));
1403
+ //console.log("action", util.inspect(actionResult, false, 8, true));
1407
1404
  logger.info(`[processWorkflowRun] Run ID: ${runId}, Step ID: ${currentStepId}, Action ID: ${actionId}: Executed successfully.`);
1408
1405
  }
1409
1406
  }
@@ -1468,104 +1465,107 @@ export async function processWorkflowRun(workflowRunId, user) {
1468
1465
  }
1469
1466
  }
1470
1467
  /**
1471
- * Exécute une action de génération de contenu par IA ('GenerateAIContent').
1472
- * Récupère la clé API (priorité à l'environnement de l'utilisateur), initialise un client LangChain,
1473
- * formate un prompt avec les données du contexte, appelle le LLM, et retourne le résultat
1474
- * pour l'ajouter au contexte du workflow.
1468
+ * Executes an AI content generation action ('GenerateAIContent').
1469
+ * Retrieves the API key (prioritizing the user's environment), initializes a LangChain client,
1470
+ * formats a prompt with context data, calls the LLM, and returns the result
1471
+ * to be added to the workflow context.
1475
1472
  *
1476
- * @param {object} action - La définition de l'action depuis le workflow.
1477
- * @param {object} context - Le contexte d'exécution actuel du workflow.
1478
- * @param {object} user - L'utilisateur qui exécute le workflow.
1473
+ * @param {object} action - The action definition from the workflow.
1474
+ * @param {object} context - The current workflow execution context.
1475
+ * @param {object} user - The user executing the workflow.
1479
1476
  * @returns {Promise<{success: boolean, updatedContext?: object, message?: string}>}
1480
1477
  */
1481
1478
  async function executeGenerateAIContentAction(action, context, user) {
1482
1479
  const { aiProvider, aiModel, prompt } = action;
1483
1480
 
1484
- // 1. Récupérer la clé API (Environnement de l'utilisateur > Environnement de la machine)
1481
+ // 1. Retrieve the API key (User Environment > Machine Environment)
1485
1482
  let apiKey;
1486
1483
 
1487
1484
  const providers = {
1488
1485
  "OpenAI" : "OPENAI_API_KEY",
1489
- "Google": "GOOGLE_API_KEY"
1486
+ "Google": "GOOGLE_API_KEY",
1487
+ "DeepSeek": "DEEPSEEK_API_KEY"
1490
1488
  }
1491
1489
  const envKeyName = providers[aiProvider];
1492
1490
  if( !envKeyName ) {
1493
- return {success: false, message: i18n.t('aiContent.env', `Clé API pour ${aiProvider} (${envKeyName}) non trouvée dans l'environnement de l'utilisateur.`)};
1491
+ return {success: false, message: i18n.t('aiContent.env', `API key for provider ${aiProvider} (${envKeyName}) not found in user environment.`)};
1494
1492
  }
1495
1493
 
1496
- // Cherche d'abord dans les variables d'environnement de l'utilisateur
1494
+ // First look in the user's environment variables
1497
1495
  const envCollection = await getCollectionForUser(user);
1498
1496
  const userEnvVar = await envCollection.findOne({ _model: 'env', name: envKeyName, _user: user.username });
1499
1497
 
1500
1498
  if (userEnvVar && userEnvVar.value) {
1501
1499
  apiKey = userEnvVar.value;
1502
- logger.debug(`[AI Action] Utilisation de la clé API de l'environnement de l'utilisateur pour ${aiProvider}.`);
1500
+ logger.debug(`[AI Action] Using user environment API key for ${aiProvider}.`);
1503
1501
  } else {
1504
1502
  apiKey = process.env[envKeyName];
1505
- logger.debug(`[AI Action] Utilisation de la clé API de l'environnement de la machine pour ${aiProvider}.`);
1503
+ logger.debug(`[AI Action] Using machine environment API key for ${aiProvider}.`);
1506
1504
  }
1507
1505
 
1508
1506
  if (!apiKey) {
1509
- const message = `Clé API pour ${aiProvider} (${envKeyName}) non trouvée dans l'environnement de l'utilisateur ou de la machine.`;
1507
+ const message = `API key for ${aiProvider} (${envKeyName}) not found in user or machine environment.`;
1510
1508
  logger.error(`[AI Action] ${message}`);
1511
1509
  return { success: false, message };
1512
1510
  }
1513
1511
 
1514
- // 2. Initialiser le client LLM avec LangChain
1512
+ // 2. Initialize the LLM client with LangChain
1515
1513
  let llm;
1516
1514
  try {
1517
1515
  switch (aiProvider) {
1518
1516
  case 'OpenAI':
1519
- llm = new ChatOpenAI({ apiKey, modelName: aiModel, temperature: 0.7 });
1517
+ llm = new ChatOpenAI({ apiKey, model: aiModel, temperature: 0.7 });
1520
1518
  break;
1521
- case 'GoogleGemini':
1522
- llm = new ChatGoogleGenerativeAI({ apiKey, modelName: aiModel, temperature: 0.7 });
1519
+ case 'Google':
1520
+ llm = new ChatGoogleGenerativeAI({ apiKey, model: aiModel, temperature: 0.7 });
1521
+ break;
1522
+ case 'DeepSeek':
1523
+ llm = new ChatDeepSeek({ apiKey, model: aiModel, temperature: 0.7 });
1523
1524
  break;
1524
1525
  default:
1525
- throw new Error(`Fournisseur IA non supporté : ${aiProvider}`);
1526
+ throw new Error(`Unsupported AI provider: ${aiProvider}`);
1526
1527
  }
1527
1528
  } catch (initError) {
1528
- const message = `Échec de l'initialisation du client IA pour ${aiProvider}: ${initError.message}`;
1529
+ const message = `Failed to initialize AI client for ${aiProvider}: ${initError.message}`;
1529
1530
  logger.error(`[AI Action] ${message}`);
1530
1531
  return { success: false, message };
1531
1532
  }
1532
1533
 
1533
1534
  try {
1534
1535
  const substitutedPrompt = await substituteVariables(prompt, context, user);
1535
- // 3. Créer le "Prompt Template"
1536
- // LangChain gère la substitution des variables comme {triggerData.name}
1536
+ // 3. Create the "Prompt Template"
1537
+ // LangChain handles variable substitution like {triggerData.name}
1537
1538
  const realPrompt = ChatPromptTemplate.fromTemplate(substitutedPrompt);
1538
1539
 
1539
- // 4. Créer la chaîne de traitement (Prompt + Modèle)
1540
+ // 4. Create the processing chain (Prompt + Model)
1540
1541
  const chain = realPrompt.pipe(llm);
1541
1542
 
1542
- // 5. Invoquer la chaîne avec le contexte complet
1543
- // LangChain remplacera automatiquement les placeholders dans le prompt.
1544
- logger.debug(`[AI Action] Invocation de l'IA avec le modèle ${aiModel}.`);
1543
+ // 5. Invoke the chain with the complete context
1544
+ // LangChain will automatically replace placeholders in the prompt.
1545
+ logger.debug(`[AI Action] Invoking AI with model ${aiModel}.`);
1545
1546
  const response = await chain.invoke(context);
1546
1547
 
1547
- // 6. Préparer le résultat pour le fusionner dans le contexte du workflow
1548
+ // 6. Prepare the result to be merged into the workflow context
1548
1549
  const llmOutput = response.content;
1549
1550
  const outputVariable = 'aiContent';
1550
1551
  const updatedContext = {
1551
1552
  [outputVariable]: llmOutput
1552
1553
  };
1553
1554
 
1554
- logger.info(`[AI Action] Contenu généré avec succès et stocké dans la variable de contexte '${outputVariable}'.`);
1555
+ logger.info(`[AI Action] Content generated successfully and stored in context variable '${outputVariable}'.`);
1555
1556
 
1556
1557
  return {
1557
1558
  success: true,
1558
- updatedContext // Cet objet sera fusionné au contexte principal par le moteur de workflow
1559
+ updatedContext // This object will be merged into the main context by the workflow engine
1559
1560
  };
1560
1561
 
1561
1562
  } catch (llmError) {
1562
- const message = `Erreur durant la génération de contenu IA avec ${aiProvider}: ${llmError.message}`;
1563
+ const message = `Error during AI content generation with ${aiProvider}: ${llmError.message}`;
1563
1564
  logger.error(`[AI Action] ${message}`, llmError.stack);
1564
1565
  return { success: false, message };
1565
1566
  }
1566
1567
  }
1567
1568
 
1568
-
1569
1569
  /**
1570
1570
  * Gère l'action d'envoi d'e-mail d'un workflow.
1571
1571
  * Cette version améliorée peut traiter une liste de destinataires, en envoyant un e-mail
package/src/packs.js CHANGED
@@ -1,4 +1,4 @@
1
- import {getModels} from "./modules/data.js";
1
+ import {getModels} from "./modules/data/index.js";
2
2
 
3
3
 
4
4
  /*
@@ -1360,6 +1360,9 @@ return { processedChunk: context.result.chunk };
1360
1360
  },{
1361
1361
  name: "GOOGLE_API_KEY",
1362
1362
  value: "demo"
1363
+ },{
1364
+ name: "DEEPSEEK_API_KEY",
1365
+ value: "demo"
1363
1366
  }]
1364
1367
  }
1365
1368
  }
@@ -10,20 +10,19 @@ import { vi } from 'vitest'
10
10
  import {
11
11
  createModel,
12
12
  insertData
13
- } from 'data-primals-engine/modules/data';
13
+ } from '../src/index.js';
14
14
 
15
15
  import {
16
16
  modelsCollection as getAppModelsCollection,
17
17
  getCollectionForUser as getAppUserCollection, getCollectionForUser
18
- } from 'data-primals-engine/modules/mongodb';
18
+ } from '../src/modules/mongodb.js';
19
19
  import process from "node:process";
20
20
 
21
- import { dumpUserData, loadFromDump } from 'data-primals-engine/modules/data';
21
+ import { dumpUserData, loadFromDump } from '../src/index.js';
22
22
  import fs from "node:fs";
23
23
  import {initEngine} from "../src/setenv.js";
24
- import {getUserCollectionName} from "../src/modules/mongodb.js";
25
24
 
26
- vi.mock('data-primals-engine/engine', async(importOriginal) => {
25
+ vi.mock('../src/engine', async(importOriginal) => {
27
26
  const mod = await importOriginal() // type is inferred
28
27
  return {
29
28
  ...mod
@@ -7,19 +7,15 @@ import {
7
7
  editData,
8
8
  deleteData,
9
9
  searchData, installPack, deleteModels, createModel, patchData
10
- } from 'data-primals-engine/modules/data';
10
+ } from '../src/index.js';
11
11
 
12
12
  import {
13
13
  modelsCollection as getAppModelsCollection,
14
14
  getCollection,
15
15
  getCollectionForUser as getAppUserCollection, getCollectionForUser
16
- } from 'data-primals-engine/modules/mongodb';
16
+ } from '../src/modules/mongodb.js';
17
17
  import {getRandom} from "../src/core.js";
18
18
  import {generateUniqueName, initEngine} from "../src/setenv.js";
19
- import {processWorkflowRun} from "data-primals-engine/modules/workflow";
20
- import {sendEmail} from "../src/email.js";
21
- import {MongoDatabase} from "../src/engine.js";
22
- import {getUserCollectionName} from "../src/modules/mongodb.js";
23
19
 
24
20
  let testModelsColInstance;
25
21
  let testDatasColInstance;
@@ -1,7 +1,7 @@
1
1
  // events.test.js
2
2
  import { Event } from '../src/events.js';
3
3
  import {vitest} from "vitest";
4
- import {expect, describe, it, beforeEach, beforeAll, afterAll} from 'vitest';
4
+ import {expect, describe, it, beforeEach} from 'vitest';
5
5
 
6
6
  describe('Event System', () => {
7
7
  beforeEach(() => {
package/test/file.test.js CHANGED
@@ -1,16 +1,13 @@
1
- // __tests__/file.integration.test.js
2
- import { expect, describe, it, beforeEach, afterEach, beforeAll, afterAll, vi } from 'vitest';
1
+ import { expect, describe, it, beforeEach, beforeAll, afterAll, vi } from 'vitest';
3
2
  import { Config } from '../src/config.js';
4
3
  import fs from 'node:fs';
5
4
  import path from 'node:path';
6
5
  import { fileURLToPath } from 'node:url';
7
- import { ObjectId } from 'mongodb';
8
6
  import { initEngine, generateUniqueName } from "../src/setenv.js";
9
7
  import { addFile, removeFile, getFile, onInit } from "../src/modules/file.js";
10
8
  import {getCollection, getUserCollectionName} from "../src/modules/mongodb.js";
11
9
  import { Logger } from "../src/gameObject.js";
12
10
  import {maxPrivateFileSize} from "../src/constants.js";
13
- import {getCollectionForUser} from "data-primals-engine/modules/mongodb";
14
11
 
15
12
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
16
13