data-primals-engine 1.0.7 → 1.0.9

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.
@@ -0,0 +1,59 @@
1
+ # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
3
+
4
+ name: Node.js CI
5
+
6
+ on:
7
+ push:
8
+ branches: [ "develop", "main" ]
9
+ pull_request:
10
+ branches: [ "develop", "main" ]
11
+
12
+ jobs:
13
+ build:
14
+
15
+ runs-on: ubuntu-latest
16
+ container:
17
+ image: node:18 # Specify the Docker version you needx
18
+ env:
19
+ NODE_OPTIONS: "--max_old_space_size=4096"
20
+ NODE_ENV: development
21
+ ports:
22
+ - 7635
23
+ - 27017
24
+ strategy:
25
+ matrix:
26
+ node-version: [18.x]
27
+ # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
28
+ services:
29
+ mongodb:
30
+ image: mongo:5.0
31
+ ports:
32
+ - 27017:27017
33
+ options: >-
34
+ --health-cmd "mongo --eval 'db.serverStatus()'"
35
+ --health-interval 10s
36
+ --health-timeout 5s
37
+ --health-retries 5
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+
41
+ - name: Install MongoDB Tools
42
+ run: |
43
+ wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | apt-key add -
44
+ echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/5.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-5.0.list
45
+ apt-get update
46
+ apt-get install -y mongodb-org-tools
47
+
48
+ - name: Set up Node.js
49
+ uses: actions/setup-node@v2
50
+ with:
51
+ node-version: '18.18.2'
52
+
53
+ - name: Install dependencies
54
+ run: npm install
55
+
56
+ - name: Run tests
57
+ run: npm test
58
+
59
+
@@ -0,0 +1,23 @@
1
+ name: Publish package to GitHub Packages
2
+ on:
3
+ release:
4
+ types: [published]
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ permissions:
9
+ contents: read
10
+ packages: write
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ # Setup .npmrc file to publish to GitHub Packages
14
+ - uses: actions/setup-node@v4
15
+ with:
16
+ node-version: '20.x'
17
+ registry-url: 'https://npm.pkg.github.com'
18
+ # Defaults to the user or organization that owns the workflow file
19
+ scope: '@octocat'
20
+ - run: npm ci
21
+ - run: npm publish
22
+ env:
23
+ NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
package/Dockerfile ADDED
@@ -0,0 +1,15 @@
1
+ # Base image
2
+ FROM node:18.18.2
3
+
4
+ # Set working directory
5
+ WORKDIR /
6
+
7
+ # Copy package files and install dependencies
8
+ COPY package.json ./
9
+ RUN npm install
10
+
11
+ # Copy application code
12
+ COPY . .
13
+
14
+ # Expose the application port
15
+ EXPOSE 7633
package/DockerfileTest ADDED
@@ -0,0 +1,15 @@
1
+ # Base image
2
+ FROM node:18.18.2
3
+
4
+ # Set working directory
5
+ WORKDIR /
6
+
7
+ # Copy package files and install dependencies
8
+ COPY package.json ./
9
+ RUN npm install
10
+
11
+ # Copy application code
12
+ COPY . .
13
+
14
+ # Expose the application port
15
+ EXPOSE 7635
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "data-primals-engine",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
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",
8
9
  "preinstall": "npx force-resolutions",
9
10
  "devserver": "cross-env NODE_ENV=development node server.js",
10
11
  "server": "cross-env NODE_ENV=production node server.js",
@@ -39,11 +40,9 @@
39
40
  "chalk": "^5.4.1",
40
41
  "check-disk-space": "^3.4.0",
41
42
  "compression": "^1.8.0",
42
- "connect-mongo": "^5.1.0",
43
43
  "cookie-parser": "^1.4.7",
44
44
  "cronstrue": "^3.1.0",
45
45
  "csv-parse": "^5.6.0",
46
- "csv-parser": "^3.2.0",
47
46
  "date-fns": "^4.1.0",
48
47
  "express": "^4.21.2",
49
48
  "express-csrf-double-submit-cookie": "^1.2.1",
@@ -61,7 +60,6 @@
61
60
  "nodemailer": "^6.10.0",
62
61
  "openai": "^5.8.2",
63
62
  "randomcolor": "^0.6.2",
64
- "rate-limiter-flexible": "^5.0.5",
65
63
  "react-helmet": "^6.1.0",
66
64
  "react-i18next": "^15.4.1",
67
65
  "react-markdown": "^10.1.0",
@@ -70,10 +68,9 @@
70
68
  "sirv": "^3.0.1",
71
69
  "swagger-ui-express": "^5.0.1",
72
70
  "tar": "^7.4.3",
73
- "tar-fs": "^3.0.8",
74
71
  "uniqid": "^5.4.0",
75
- "yaml": "^2.8.0",
76
- "zlib": "^1.0.5"
72
+ "vitest": "^3.2.3",
73
+ "yaml": "^2.8.0"
77
74
  },
78
75
  "devDependencies": {
79
76
  "@eslint/js": "^9.17.0",
package/server.js CHANGED
@@ -13,11 +13,20 @@ const bench = GameObject.Create("Benchmark");
13
13
  const timer = bench.addComponent(BenchmarkTool);
14
14
  timer.start();
15
15
 
16
- const engine = Engine.Create();
16
+
17
+ const engine = await Engine.Create();
18
+
19
+ if (process.argv.length === 3) {
20
+ let arg = process.argv[2];
21
+ if( arg === 'reset-models'){
22
+ console.log("resetting models");
23
+ await engine.resetModels();
24
+ }
25
+ }
17
26
 
18
27
  const port = process.env.PORT || 7633;
19
28
  engine.start(port, async (r) => {
20
29
  const logger = engine.getComponent(Logger);
21
-
30
+ console.log("Server started on port" + port);
22
31
  timer.stop();
23
32
  });
package/src/data.js CHANGED
@@ -29,8 +29,12 @@ export const isLocalUser = (user) => {
29
29
  return user && user._model === 'user' && typeof(user._user) === 'string' && user._user.trim() !== '';
30
30
  };
31
31
 
32
+ export const isDemoUser = (user) => {
33
+ return /^demo[0-9]{1,2}$/.test(user?.username);
34
+ }
35
+
32
36
  export function getUserHash(user) {
33
- if( /^demo[0-9]{1,2}$/.test(user?.username) ){
37
+ if( isDemoUser(user) ){
34
38
  return user.username;
35
39
  }
36
40
  return user ? (
@@ -419,8 +423,9 @@ export const getFieldValueHash = (model, data) => {
419
423
  * @param {array} allModels - Un tableau contenant les définitions de TOUS les modèles du système.
420
424
  * @returns {string} - La chaîne de caractères représentant la donnée.
421
425
  */
422
- export const getDataAsString = (model, data, t, allModels, extended=false) => {
423
-
426
+ export const getDataAsString = (model, data, tr, allModels, extended=false) => {
427
+ const { t, i18n} = tr;
428
+ const lang = (i18n.resolvedLanguage || i18n.language).split(/[-_]/)?.[0];
424
429
  // Cas de base : si le modèle ou les données sont manquants, on ne peut rien faire.
425
430
  if (!model || !data) {
426
431
  return '';
@@ -464,7 +469,6 @@ export const getDataAsString = (model, data, t, allModels, extended=false) => {
464
469
  const relatedModel = allModels?.find(m => m.name === fieldDef.relation);
465
470
  if (!relatedModel) return `[${fieldDef.relation}]`; // Modnon trouvé
466
471
 
467
- console.log({relatedModel, value});
468
472
  // Si la relation est multiple (un tableau d'objets)
469
473
  if (Array.isArray(value)) {
470
474
  return value
@@ -474,10 +478,16 @@ export const getDataAsString = (model, data, t, allModels, extended=false) => {
474
478
  }
475
479
  // Si la relation est simple (un seul objet)
476
480
  else if (typeof value === 'object') {
477
- console.log({relatedModel, value});
478
481
  return getDataAsString(relatedModel, value, t, allModels); // Appel récursif
479
482
  }
480
483
  }
484
+
485
+ if(fieldDef.type === 'datetime'){
486
+ return new Date(value).toLocaleDateString(lang, {year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric'});
487
+ }
488
+ if(fieldDef.type === 'date'){
489
+ return new Date(value).toLocaleDateString(lang, {year: 'numeric', month: 'numeric', day: 'numeric'});
490
+ }
481
491
  // --- FIN DE LA NOUVELLE LOGIQUE ---
482
492
 
483
493
  // Logique existante pour les autres types de champs
package/src/email.js CHANGED
@@ -2,6 +2,8 @@ import { translations } from "data-primals-engine/i18n";
2
2
  import process from "node:process";
3
3
  import nodemailer from "nodemailer";
4
4
  import juice from "juice";
5
+ import {event_trigger} from "./core.js";
6
+ import {emailDefaultConfig} from "./constants.js";
5
7
 
6
8
  // Le transporteur par défaut, utilisé si aucune config spécifique n'est fournie.
7
9
  const defaultTransporter = nodemailer.createTransport({
package/src/engine.js CHANGED
@@ -8,7 +8,7 @@ import {cookiesSecret, dbName} from "./constants.js";
8
8
  import http from "http";
9
9
  import cookieParser from "cookie-parser";
10
10
  import requestIp from 'request-ip';
11
- import {createModel, getModels, validateModelStructure} from "./modules/data.js";
11
+ import {createModel, deleteModels, getModels, validateModelStructure} from "./modules/data.js";
12
12
  import {defaultModels} from "./defaultModels.js";
13
13
  import {DefaultUserProvider} from "./providers.js";
14
14
  import formidableMiddleware from 'express-formidable';
@@ -17,7 +17,7 @@ import formidableMiddleware from 'express-formidable';
17
17
  const isProduction = process.env.NODE_ENV === 'production'
18
18
 
19
19
  // Connection URL
20
- export const dbUrl = process.env.MONGO_DB_URL || 'mongodb://127.0.0.1:27017';
20
+ export const dbUrl = process.env.CI ? 'mongodb://mongodb:27017' : (process.env.MONGO_DB_URL || 'mongodb://127.0.0.1:27017');
21
21
  export const MongoClient = new InternalMongoClient(dbUrl, { maxPoolSize: 20 });
22
22
 
23
23
  // Database Name
@@ -25,9 +25,10 @@ export const MongoDatabase = MongoClient.db(dbName);
25
25
 
26
26
 
27
27
  export const Engine = {
28
- Create: (options) => {
28
+ Create: async (options) => {
29
29
  const engine = GameObject.Create("Engine");
30
30
  console.log("Creating engine", Config.Get('modules'));
31
+ engine.addComponent(Logger);
31
32
 
32
33
  engine.userProvider = new DefaultUserProvider(engine);
33
34
 
@@ -71,10 +72,38 @@ export const Engine = {
71
72
  return engine._modules.find(m => m.module === module);
72
73
  };
73
74
 
75
+
76
+ const logger = engine.getComponent(Logger);
77
+
78
+ const importModule = async (module) => {
79
+ const moduleA = await import(module);
80
+ if (moduleA.onInit){
81
+ await moduleA.onInit(engine);
82
+ return {...moduleA, module};
83
+ }else {
84
+ const mod = moduleA.default();
85
+ await mod?.onInit(engine);
86
+ return { ...mod, module};
87
+ }
88
+ };
89
+
90
+ await Promise.all(Config.Get('modules', []).map(async module => {
91
+ try {
92
+ if( fs.existsSync(module)){
93
+ return await importModule(module);
94
+ }else {
95
+ return await importModule('./modules/' + module + ".js");
96
+ }
97
+ } catch (e){
98
+ console.log('ERROR at loading module '+ module + ' in /modules dir.'+ e);
99
+ }
100
+ })).then(async e => {
101
+ engine._modules = e;
102
+ return Promise.resolve();
103
+ });
74
104
  let server;
75
105
  engine.start = async (port, cb) =>{
76
106
  // Use connect method to connect to the server
77
- await MongoClient.connect();
78
107
 
79
108
  // Start http server
80
109
  server = http.createServer(app);
@@ -87,37 +116,11 @@ export const Engine = {
87
116
 
88
117
  server.listen(port);
89
118
 
90
- const importModule = async (module) => {
91
- const moduleA = await import(module);
92
- if (moduleA.onInit){
93
- await moduleA.onInit(engine);
94
- return {...moduleA, module};
95
- }else {
96
- const mod = moduleA.default();
97
- await mod?.onInit(engine);
98
- return { ...mod, module};
99
- }
100
- };
101
-
102
- await Promise.all(Config.Get('modules').map(async module => {
103
- try {
104
- if( fs.existsSync(module)){
105
- return await importModule(module);
106
- }else {
107
- return await importModule('./modules/' + module + ".js");
108
- }
109
- } catch (e){
110
- console.log('ERROR at loading module '+ module + ' in /modules dir.'+ e);
111
- }
112
- })).then(async e => {
113
- engine._modules = e;
114
- if (cb)
115
- return await cb();
116
- return Promise.resolve();
117
- });
118
-
119
119
  await setupInitialModels();
120
120
 
121
+ if (cb)
122
+ await cb();
123
+
121
124
  process.on('uncaughtException', function (exception) {
122
125
  console.error(exception);
123
126
  fs.appendFile('issues.txt', JSON.stringify({ code: exception.code, message: exception.message, stack: exception.stack }), function (err) {
@@ -128,14 +131,11 @@ export const Engine = {
128
131
  process.exit(0);
129
132
  });
130
133
  }
131
- engine.addComponent(Logger);
132
134
 
133
135
  engine.stop = async () => {
134
136
  await server.close();
135
137
  };
136
138
 
137
- const logger = engine.getComponent(Logger);
138
-
139
139
  async function setupInitialModels() {
140
140
  logger.info("Validating structures of default models...");
141
141
  const ms = Object.values(Config.Get('defaultModels', defaultModels));
@@ -151,13 +151,15 @@ export const Engine = {
151
151
  model.locked = true;
152
152
  const r = await createModel(model);
153
153
  dbModels.push({...model, _id: r.insertedId });
154
- }
155
- else
156
- logger.info('Model loaded (' + model.name + ')', {});
154
+ logger.info('Model inserted (' + model.name + ')');
155
+ }else
156
+ logger.info('Model loaded (' + model.name + ')');
157
157
  }
158
158
  logger.info("All models loaded.");
159
159
  }
160
-
160
+ engine.resetModels = async () => {
161
+ await deleteModels();
162
+ };
161
163
  return engine;
162
164
  }
163
165
  }
package/src/gameObject.js CHANGED
@@ -70,23 +70,21 @@ export class UsableBehaviour extends Behaviour {
70
70
 
71
71
  use() {
72
72
  Event.Trigger("GameObject.UsableBehavior.use", "system", "calls", this);
73
- // Logique d'utilisation (exemple)
74
- console.log(this.gameObject.name + " a été utilisé !");
75
73
  }
76
74
  }
77
75
 
78
- const pilote = GameObject.Create("Pilote");
76
+ const mainDriver = GameObject.Create("MainDrivers");
79
77
 
80
78
  // Exemple d'attachement de comportements
81
- pilote.addComponent(MovableBehaviour, 10);
82
- pilote.addComponent(UsableBehaviour);
79
+ mainDriver.addComponent(MovableBehaviour, 10);
80
+ mainDriver.addComponent(UsableBehaviour);
83
81
 
84
82
  // Accéder et utiliser les composants
85
- const movable = pilote.getComponent(MovableBehaviour);
83
+ const movable = mainDriver.getComponent(MovableBehaviour);
86
84
  if (movable) {
87
85
  movable.update();
88
86
  }
89
- const usable = pilote.getComponent(UsableBehaviour);
87
+ const usable = mainDriver.getComponent(UsableBehaviour);
90
88
  if (usable) {
91
89
  usable.use();
92
90
  }
package/src/migrate.js CHANGED
@@ -15,7 +15,7 @@ Config.Set("modules", ["mongodb"]);
15
15
  const MIGRATIONS_DIR = path.resolve(process.cwd(), 'server', 'src', 'migrations');
16
16
  const MIGRATIONS_COLLECTION = 'migrations_log';
17
17
 
18
- const engine = Engine.Create();
18
+ const engine = await Engine.Create();
19
19
  const port = process.env.MIGRATE_PORT || 7640;
20
20
 
21
21
  engine.start(port, async () => {