data-primals-engine 1.7.0 → 1.7.2

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 (39) hide show
  1. package/README.md +160 -160
  2. package/client/package-lock.json +1080 -212
  3. package/client/package.json +12 -6
  4. package/client/src/AssistantChat.jsx +1 -3
  5. package/client/src/DataLayout.jsx +19 -20
  6. package/client/src/DataTable.jsx +2 -2
  7. package/client/src/DocumentationPageLayout.scss +1 -1
  8. package/client/src/ViewSwitcher.jsx +1 -1
  9. package/client/vite.config.js +31 -30
  10. package/package.json +39 -23
  11. package/src/ai.jobs.js +135 -0
  12. package/src/constants.js +561 -545
  13. package/src/core.js +487 -477
  14. package/src/data.js +2 -0
  15. package/src/email.js +0 -2
  16. package/src/engine.js +50 -42
  17. package/src/filter.js +348 -343
  18. package/src/modules/assistant/assistant.js +782 -763
  19. package/src/modules/assistant/constants.js +23 -16
  20. package/src/modules/assistant/providers.js +77 -37
  21. package/src/modules/bucket.js +4 -0
  22. package/src/modules/data/data.cluster.js +191 -0
  23. package/src/modules/data/data.core.js +11 -8
  24. package/src/modules/data/data.js +13 -4
  25. package/src/modules/data/data.operations.js +186 -106
  26. package/src/modules/data/data.relations.js +1 -0
  27. package/src/modules/data/data.replication.js +83 -0
  28. package/src/modules/data/data.routes.js +2183 -1879
  29. package/src/modules/mongodb.js +76 -73
  30. package/src/modules/user.js +7 -1
  31. package/src/modules/worker-script-runner.js +97 -0
  32. package/src/modules/workflow.js +1953 -1815
  33. package/src/packs.js +5701 -5697
  34. package/src/providers.js +298 -297
  35. package/test/assistant.test.js +207 -206
  36. package/test/data.integration.test.js +1425 -1416
  37. package/test/import_export.integration.test.js +210 -210
  38. package/test/workflow.actions.integration.test.js +487 -475
  39. package/test/workflow.integration.test.js +332 -329
@@ -1,73 +1,76 @@
1
-
2
- import {Logger} from "../gameObject.js";
3
- import {MongoDatabase} from "../engine.js";
4
- import {ObjectId} from "mongodb";
5
- import {isLocalUser} from "../data.js";
6
- import {Event} from "../events.js";
7
- import {Config} from "../config.js";
8
-
9
- export let modelsCollection, datasCollection, filesCollection, packsCollection;
10
-
11
- export {ObjectId};
12
-
13
- let engine, logger, currentDb
14
-
15
- let colls= [];
16
- export async function onInit(defaultEngine) {
17
- engine = defaultEngine;
18
- logger = engine.getComponent(Logger);
19
-
20
- currentDb = MongoDatabase();
21
- modelsCollection = getCollection("models");
22
- datasCollection = getCollection(Config.Get('dataCollection', 'datas'));
23
- filesCollection = getCollection("files");
24
- packsCollection = getCollection("packs");
25
-
26
- colls = await currentDb.listCollections().toArray();
27
-
28
- await Event.Trigger("OnDatabaseLoaded", "system", "calls", engine)
29
- logger.info("MongoDB collections loaded.");
30
- }
31
-
32
- export const getCollections= async (forceRefresh)=>{
33
- if( !forceRefresh )
34
- return colls;
35
- colls = await currentDb.listCollections().toArray();
36
- }
37
-
38
- export const createCollection = async (coll)=>{
39
- const found =colls.find(f => f.name === coll);
40
- if( found){
41
- return getCollection(coll);
42
- }
43
- return await currentDb.createCollection(coll);
44
- }
45
-
46
- export const isObjectId = (id) => {
47
- return (typeof(id) === 'string' && id.match(/^[0-9a-fA-F]{24}$/));
48
- };
49
-
50
-
51
- export const getCollection = (str) => {
52
- return currentDb.collection(str);
53
- }
54
-
55
- export const getDatabase = () => {
56
- return currentDb;
57
- }
58
-
59
- // New function to determine the collection name for a user
60
- export const getUserCollectionName = async (user) => {
61
- const feat = await engine.userProvider.hasFeature(user, 'indexes');
62
- const dataCollectionName = Config.Get('dataCollection', 'datas');
63
- return feat ? (isLocalUser(user) ? `${dataCollectionName}_${user._user}` :`${dataCollectionName}_${user.username}` ) : dataCollectionName;
64
- };
65
-
66
-
67
- // Modify existing functions to use the correct collection
68
- export const getCollectionForUser = async (user) => {
69
- const collectionName = await getUserCollectionName(user);
70
- return getCollection(collectionName);
71
- };
72
-
73
-
1
+
2
+ import {Logger} from "../gameObject.js";
3
+ import {MongoDatabase} from "../engine.js";
4
+ import {ObjectId} from "mongodb";
5
+ import {isLocalUser} from "../data.js";
6
+ import {Event} from "../events.js";
7
+ import {Config} from "../config.js";
8
+
9
+ export let modelsCollection, datasCollection, filesCollection, packsCollection;
10
+
11
+ export {ObjectId};
12
+
13
+ let engine, logger, currentDb
14
+
15
+ let colls= [];
16
+ export async function onInit(defaultEngine) {
17
+ engine = defaultEngine;
18
+ logger = engine.getComponent(Logger);
19
+
20
+ currentDb = MongoDatabase();
21
+ modelsCollection = getCollection("models");
22
+ datasCollection = getCollection(Config.Get('dataCollection', 'datas'));
23
+ filesCollection = getCollection("files");
24
+ packsCollection = getCollection("packs");
25
+
26
+
27
+ colls = await (currentDb.listCollections()).toArray();
28
+
29
+ await Event.Trigger("OnDatabaseLoaded", "system", "calls", engine)
30
+ logger.info("MongoDB collections loaded.");
31
+ }
32
+
33
+ export const getCollections= async (forceRefresh)=>{
34
+ if( !forceRefresh )
35
+ return colls;
36
+ colls = await currentDb.listCollections().toArray();
37
+ }
38
+
39
+ export const createCollection = async (coll)=>{
40
+ const found =colls.find(f => f.name === coll);
41
+ if( found){
42
+ return getCollection(coll);
43
+ }
44
+ return await currentDb.createCollection(coll);
45
+ }
46
+
47
+ export const isObjectId = (id) => {
48
+ return (typeof(id) === 'string' && id.match(/^[0-9a-fA-F]{24}$/));
49
+ };
50
+
51
+
52
+ export const getCollection = (str) => {
53
+ if (typeof str !== 'string') {
54
+ logger?.error(`[MongoDB] Tentative d'accès à une collection avec un type invalide: ${typeof str}`);
55
+ throw new Error("Le nom de la collection doit être une chaîne de caractères.");
56
+ }
57
+ return currentDb.collection(str);
58
+ }
59
+
60
+ export const getDatabase = () => {
61
+ return currentDb;
62
+ }
63
+
64
+ // New function to determine the collection name for a user
65
+ export const getUserCollectionName = async (user) => {
66
+ const feat = await engine.userProvider.hasFeature(user, 'indexes');
67
+ const dataCollectionName = Config.Get('dataCollection', 'datas');
68
+ return feat ? (isLocalUser(user) ? `${dataCollectionName}_${user._user}` :`${dataCollectionName}_${user.username}` ) : dataCollectionName;
69
+ };
70
+
71
+
72
+ // Modify existing functions to use the correct collection
73
+ export const getCollectionForUser = async (user) => {
74
+ const collectionName = await getUserCollectionName(user);
75
+ return getCollection(collectionName);
76
+ };
@@ -358,8 +358,14 @@ export async function getSmtpConfig(user) {
358
358
  acc[variable.name.replace('SMTP_', '').toLowerCase()] = variable.value;
359
359
  return acc;
360
360
  }, {});
361
+
361
362
  if( !smtpConfig.port )
362
363
  smtpConfig.port = cfg.port;
363
-
364
+ if( !smtpConfig.host )
365
+ smtpConfig.host = cfg.host;
366
+ if( !smtpConfig.user )
367
+ smtpConfig.user = cfg.user;
368
+ if( !smtpConfig.pass )
369
+ smtpConfig.pass = cfg.pass;
364
370
  return smtpConfig;
365
371
  }
@@ -0,0 +1,97 @@
1
+ import { parentPort } from 'worker_threads';
2
+
3
+ let callIdCounter = 0;
4
+ const pendingCalls = new Map();
5
+
6
+ /**
7
+ * Appelle une fonction sur le thread principal et attend la réponse.
8
+ * @param {string} service - Le nom du service (ex: 'db').
9
+ * @param {string} method - Le nom de la méthode (ex: 'find').
10
+ * @param {...any} args - Les arguments de la méthode.
11
+ * @returns {Promise<any>}
12
+ */
13
+ function callHost(service, method, ...args) {
14
+ return new Promise((resolve, reject) => {
15
+ const callId = callIdCounter++;
16
+ pendingCalls.set(callId, { resolve, reject });
17
+ parentPort.postMessage({ type: 'call', callId, service, method, args });
18
+ });
19
+ }
20
+
21
+ // API exposée au script de l'utilisateur
22
+ const db = {
23
+ create: (model, data) => callHost('db', 'create', model, data),
24
+ find: (model, filter, options) => callHost('db', 'find', model, filter, options),
25
+ findOne: (model, filter) => callHost('db', 'findOne', model, filter),
26
+ update: (model, filter, update) => callHost('db', 'update', model, filter, update),
27
+ delete: (model, filter) => callHost('db', 'delete', model, filter),
28
+ };
29
+
30
+ const workflow = {
31
+ run: (name, context) => callHost('workflow', 'run', name, context),
32
+ };
33
+
34
+ const logger = {
35
+ info: (...args) => callHost('log', 'info', ...args),
36
+ warn: (...args) => callHost('log', 'warn', ...args),
37
+ error: (...args) => callHost('log', 'error', ...args),
38
+ };
39
+
40
+ const env = {
41
+ get: (name) => callHost('env', 'get', name),
42
+ getAll: () => callHost('env', 'getAll'),
43
+ };
44
+
45
+ const http = {
46
+ request: (method, url, options) => callHost('http', 'request', method, url, options),
47
+ };
48
+
49
+ /**
50
+ * Exécute le code utilisateur dans un scope sécurisé.
51
+ * @param {string} code - Le code à exécuter.
52
+ * @param {object} context - Le contexte du workflow.
53
+ */
54
+ async function runUserCode(code, context) {
55
+ // Crée une fonction asynchrone avec le code utilisateur.
56
+ // Les variables `db`, `logger`, `context`, etc., sont disponibles dans son scope.
57
+ const userFunction = new Function('db', 'workflow', 'logger', 'env', 'http', 'context', `return (async () => { ${code} })();`);
58
+
59
+ // Appelle la fonction avec l'API sandboxed.
60
+ return userFunction(db, workflow, logger, env, http, context);
61
+ }
62
+
63
+ // Gestionnaire de messages unique pour le worker
64
+ parentPort.on('message', (msg) => {
65
+ // Message initial pour démarrer l'exécution
66
+ if (msg.code) {
67
+ // Le worker ne doit pas se terminer tant que le code n'est pas fini.
68
+ parentPort.ref();
69
+ runUserCode(msg.code, msg.context)
70
+ .then(result => {
71
+ parentPort.postMessage({ type: 'done', result });
72
+ })
73
+ .catch(e => {
74
+ parentPort.postMessage({ type: 'error', error: e.message });
75
+ })
76
+ .finally(() => {
77
+ // Une fois terminé, le worker peut se fermer.
78
+ parentPort.unref();
79
+ });
80
+ }
81
+ // Message de réponse à un appel `callHost`
82
+ else if (msg.type === 'response') {
83
+ const { callId, result, error } = msg;
84
+ if (pendingCalls.has(callId)) {
85
+ const { resolve, reject } = pendingCalls.get(callId);
86
+ if (error) {
87
+ reject(new Error(error));
88
+ } else {
89
+ resolve(result);
90
+ }
91
+ pendingCalls.delete(callId);
92
+ }
93
+ } else if (msg.type === 'call') {
94
+ // Ce cas ne devrait pas arriver (le worker envoie 'call', il ne le reçoit pas),
95
+ // mais on le laisse pour la robustesse.
96
+ }
97
+ });